diff --git a/local/alpha/config/vufind/config.ini b/local/alpha/config/vufind/config.ini
index addf3822b06c8398a29794c4a5a6caf486292d0b..95cac8f698a50008cd05f538af8ac80de1fb5bbe 100644
--- a/local/alpha/config/vufind/config.ini
+++ b/local/alpha/config/vufind/config.ini
@@ -2,21 +2,21 @@
 ;##################### DO NOT DELETE THIS HEADER ####################
 ;################### Leipzig University Library © 2015 ##############
 ;
-; This is the ISIL-instance-specific default INI-file and inherits
+; This is the default ALPHA-INI-file and inherits
 ; all the settings from the INI-file defined in [Parent_Config] which
 ; points to the default INI-file located in the folder vufind2/local
 ;
 
 [Parent_Config]
-relative_path = ../../../local/config/vufind/export.ini
+relative_path = ../../../config/vufind/config.ini
 
 ; A comma-separated list of config sections from the parent which should be
 ; completely overwritten by the equivalent sections in this configuration;
 ; any sections not listed here will be merged on a section-by-section basis.
-;override_full_sections = "EndNote"
+;override_full_sections = "Languages,AlphaBrowse_Types"
 
 ;
-;       Add instance-specific customization after this header.
+;       Add ALPHA-specific customization after this header.
 ;
 ;##################### DO NOT DELETE THIS HEADER ####################
 ;####################################################################
diff --git a/local/config/vufind/FincILS.ini b/local/config/vufind/FincILS.ini
index f288a15ef6a89018c6e24217a42ae9db35309f06..d255b92b531bdf33863c64144edbdbd21e2ce8a3 100644
--- a/local/config/vufind/FincILS.ini
+++ b/local/config/vufind/FincILS.ini
@@ -95,4 +95,11 @@ queryIls[] = 'getFacetAvail:Local'
 ; through user input. E.g. to select an email profile according to the selected
 ; pickUpLocation you have to set the value to "pickUpLocation".
 ; By default it is left empty using the default profile "EmailHold".
-;emailProfileSelector = 
+;emailProfileSelector =
+
+; the ILLRequests section contains regex patterns for inter library loan item detection
+; itemPattern matches the item ID, labelPattern matches the item's label
+; as used in a PAIA regex filter
+;[ILLRequests]
+;itemPattern = "/^(?:(?!DE-15)).*$/"
+;labelPattern = "/^ILL Status String$"
\ No newline at end of file
diff --git a/local/config/vufind/FincLibero.ini b/local/config/vufind/FincLibero.ini
new file mode 100644
index 0000000000000000000000000000000000000000..3b73011fd7f88f3a4f2e1cf71a1d30fe1aea2eac
--- /dev/null
+++ b/local/config/vufind/FincLibero.ini
@@ -0,0 +1,57 @@
+; General Settings for all FincLibero instances
+[Parent_Config]
+;inherits FincILS settings from same directory
+relative_path=FincILS.ini
+
+; entries in [RequiredConfig] denote settings that are tested during initialization
+; of FincLibero. Syntax is
+; <INI Section>[<key within section>] = true for required, false for not required
+; e.g. General[departmentLocationBase] = true makes FincLibero::init()
+; throw an InitException in case [General]->departmentLocationBase is not set
+; in any of FincLibero.ini or FincILS.ini
+;[RequiredConfig]
+;General[departmentLocationBase] = true
+;General[titleHoldLimitations] = true
+;General[pickUpLocationPatterns] = true
+;General[requestableLimitations] = true
+;General[holdableLimitations] = true
+;General[recallableLimitations] = true
+;General[awlLimitations] = true
+;General[stackURIs] = true
+;General[readingRoomURIs] = true
+
+; the following section is here to list info and examples for the settings
+; that may be defined as required in [RequiredConfig]
+; examples collected in DE-15 and DE-Zwi2
+;[General]
+; Pattern that will extend uris for department
+;departmentLocationBase = "http://data.ub.uni-leipzig.de/resource/DE-Zwi2/department/zw"
+
+; Limitations that will trigger an action.
+;titleHoldLimitations[] = "DE-Zwi2:OrderTitle:[0-9]+X?"
+
+; Patterns that will identify limitations as pickUpLocations
+;pickUpLocationPatterns[] = "/^http:\/\/data\.ub\.uni-leipzig\.de\/resource\//"
+
+; Limitations that will trigger the placeStorageRetrievalRequest action
+;requestableLimitations[] = DE-15:OrderRequired
+
+; Limitations that will trigger the placeHold action
+;holdableLimitations[] = DE-15:URI
+
+; Limitations that will trigger a recall action (currently not used).
+;recallableLimitations[] = DE-15:ReservationPossible
+
+; Limitations that will identify the item for being bound to another item.
+;awlLimitations[] = DE-15:OrderViaBoundItem
+
+; URIs that will be used for stack views
+;stackURIs[] = "http://data.ub.uni-leipzig.de/resource/DE-15/pickup/zw01thek"
+
+; URIs that will be used for reading room views
+;readingRoomURIs[] = "http://data.ub.uni-leipzig.de/resource/DE-15/pickup/zw01thekfo"
+
+; use Wachtl service for departments instead of DAIA details
+;useWachtlPickupLocations = false
+; use locationid and not customData
+;useDaiaLocationId = true
diff --git a/local/config/vufind/config.ini b/local/config/vufind/config.ini
index c4f84f2d911ca450e130da97c843e02fba6688f0..a7c4da375e38acf6bfa3d1957aaddb39f36e5164 100644
--- a/local/config/vufind/config.ini
+++ b/local/config/vufind/config.ini
@@ -26,6 +26,8 @@ autoConfigure = true
 url             = http://localhost/vufind_generic
 email           = dummy@vufind.org
 title           = "Generic Katalog (devel)"
+; The separator used between page name and site name in the <title> tag of pages.
+titleSeparator = "::"
 ; 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
diff --git a/local/languages/LiberoAccount/de.ini b/local/languages/LiberoAccount/de.ini
new file mode 100644
index 0000000000000000000000000000000000000000..2607d8ef6eec11a949cfb834357dfb934c5174d5
--- /dev/null
+++ b/local/languages/LiberoAccount/de.ini
@@ -0,0 +1,8 @@
+# Change pin account action
+change_user_pin = "PIN für Selbstverbuchung ändern"
+new_pin = "Neue PIN"
+confirm_new_pin = "Neue PIN bestätigen"
+new_pin_missmatch = "PIN Eingaben stimmen nicht überein"
+set_pin_success = "Die PIN wurde erfolgreich geändert"
+set_pin_error = "Änderung der PIN gescheitert. Wenden Sie sich bitte an das Bibliothekspersonal."
+set_pin_note = "Hinweis: Die PIN muss vierstellig sein und darf nur aus Ziffern bestehen."
diff --git a/local/languages/LiberoAccount/en.ini b/local/languages/LiberoAccount/en.ini
new file mode 100644
index 0000000000000000000000000000000000000000..7c3213fad165f2815bb9aa2d8c1f84b09cf9ed37
--- /dev/null
+++ b/local/languages/LiberoAccount/en.ini
@@ -0,0 +1,8 @@
+# Change pin account action
+change_user_pin = "Change PIN"
+new_pin = "New PIN"
+confirm_new_pin = "Confirm new PIN"
+new_pin_missmatch = "Confirmation of PIN is not valid. Please try it again"
+set_pin_success = "New PIN was set successfully"
+set_pin_error = "Errors occurred while changing PIN. Please ask on the service desk."
+set_pin_note = "Please note that the PIN must consist of four digits only (no letters, no symbols ...)."
diff --git a/local/languages/de.ini b/local/languages/de.ini
index 144a30c70ca1deeb25f86906093ba7b143947f42..6428ea9568274ecf180264ac9f35778dece09cc1 100644
--- a/local/languages/de.ini
+++ b/local/languages/de.ini
@@ -2054,7 +2054,6 @@ DE-Kn38 = "Hochschule für Musik und Tanz Köln"
 Range-from-to = "Bereich von/bis"
 
 ; #17833
-form-legend = "Bitte füllen Sie alle Felder aus"
 form-button-submit = "Ausgefülltes Formular abschicken"
 
 ; #17601
@@ -2077,3 +2076,8 @@ missing_record_exception = "Der aufgerufene Titel (%%id%%) ist nicht vorhanden."
 
 ; #18611 unknown resolver state 10
 Unknown Electronic = "Titel ist beim Resolver-Service nicht bekannt"
+
+; #20826
+title_wrapper = "%%pageTitle%% %%titleSeparator%% %%siteTitle%%"
+
+load_tab_content_hint = "Klicken Sie hier, um den Inhalt der Registerkarte zu laden."
diff --git a/local/languages/en.ini b/local/languages/en.ini
index 807e7d4350ab48baab9f48c06ec2fa6891b7f24f..f1aa7b7cf478120dce8ec464464eec64899cca2b 100644
--- a/local/languages/en.ini
+++ b/local/languages/en.ini
@@ -975,7 +975,7 @@ DE-15-292 = "Leipzig University Library, Central Library Medicine"
 DE-105 = "Technische Universität Bergakademie Freiberg"
 DE-197 = "City Library Leipzig"
 DE-520 = "Dresden University of Applied Sciences"
-DE-540 = "Dresden Academy of Fine Arts"
+DE-540 = "Dresden University of Fine Arts"
 DE-1156 = "Folkwang University of Arts"
 DE-1972 = "Robert Schumann Academy Düsseldorf"
 DE-Ch1 = "Technische Universität Chemnitz"
@@ -1949,7 +1949,6 @@ resolver_link_access_unknown = "Record unknown to resolver"
 ; message to be shown upon empty resolver response
 no_resolver_links = "No online links available."
 
-
 ; reset password
 reset_password_text = "Please complete the form below to reset your password. You will receive an email after we have completed resetting your password."
 Reset Password = "Reset Password"
@@ -2136,7 +2135,6 @@ DE-Kn38 = "Hochschule für Musik und Tanz Köln"
 Range-from-to = "Range from/to"
 
 ; #17833
-form-legend = "Please fill in all fields to create an account"
 form-button-submit = "Submit the completed form"
 
 ; #17601
@@ -2165,3 +2163,8 @@ missing_record_exception = "Record %%id%% is unavailable."
 
 ; #18611 unknown resolver state 10
 Unknown Electronic = "Record is unknown to the resolver service"
+
+; #20826
+title_wrapper = "%%pageTitle%% %%titleSeparator%% %%siteTitle%%"
+
+load_tab_content_hint = "Click to load tab content."
diff --git a/module/fid/src/Controller/CustomTraits/FidAcquisitionTrait.php b/module/fid/src/Controller/CustomTraits/FidAcquisitionTrait.php
index 85832745a15ac0db4f92d909f70cee892920a21f..072fa5649344ea7de972bdb342833e93ed81e29c 100644
--- a/module/fid/src/Controller/CustomTraits/FidAcquisitionTrait.php
+++ b/module/fid/src/Controller/CustomTraits/FidAcquisitionTrait.php
@@ -281,7 +281,8 @@ trait FidAcquisitionTrait
                 if ($form->isValid()) {
                     $label = $form->getData()['title'];
                     $type = $this->type;
-                    $hydratorData = compact('type', 'user', 'label');
+                    $status = $this->getDefaultStatus();
+                    $hydratorData = compact('type', 'user', 'label', 'status');
                     $hydratorData += $this->addTypeSpecificOrderInformation($form);
                     $form->getHydrator()->hydrate($hydratorData, $order = new Order());
                     $this->client->requestOrderCreation($order);
diff --git a/module/fid/src/Hydrator/OrderMissingRecordHydrator.php b/module/fid/src/Hydrator/OrderMissingRecordHydrator.php
index 5a53dbe855379fe2937e79ad43a3ace92fa4c9dc..de31875fc123b7b1776952d239cd9ed729df10a6 100644
--- a/module/fid/src/Hydrator/OrderMissingRecordHydrator.php
+++ b/module/fid/src/Hydrator/OrderMissingRecordHydrator.php
@@ -29,6 +29,7 @@ class OrderMissingRecordHydrator extends AbstractHydrator {
         $record = null;
 
         $object->setData(compact('record','partialCopy','digitization','pda'));
+        $object->setStatus($data['status']);
         $object->setLabel($data['label']);
         return;
     }
diff --git a/module/fid/src/View/Helper/Root/GetIt.php b/module/fid/src/View/Helper/Root/GetIt.php
index f12571cd82d20455ef0ab824bcd1c3dc48a94b5c..3e581db500dce409566682c914deecb1392b7622 100644
--- a/module/fid/src/View/Helper/Root/GetIt.php
+++ b/module/fid/src/View/Helper/Root/GetIt.php
@@ -209,7 +209,7 @@ class GetIt extends AbstractHelper
      *
      * @return array
      */
-    private function _getSourceIds($value)
+    protected function _getSourceIds($value)
     {
         $sids = $this->config->SourceIds;
         return isset($sids->$value) ? explode(',', $sids->$value) : [];
@@ -222,7 +222,7 @@ class GetIt extends AbstractHelper
      *
      * @return string
      */
-    private function _getNonSourceIds($value)
+    protected function _getNonSourceIds($value)
     {
         $sids = $this->config->NonSourceIds;
         return $sids->$value ?? '';
@@ -253,7 +253,8 @@ class GetIt extends AbstractHelper
 
         // let specific functions override defaults where necessary
         foreach ($this->sids as $sid_config) {
-            if (in_array($this->sid, $sid = $this->_getSourceIds($sid_config))) {
+            $sid = $this->_getSourceIds($sid_config);
+            if (current($sid) === 'ALL' || in_array($this->sid, $sid)) {
                 $foo = 'get_config_' . $sid_config;
                 $this->$foo(
                     $accordeonColor,
diff --git a/module/finc/src/finc/Cover/Loader.php b/module/finc/src/finc/Cover/Loader.php
index fe853e9f2e70b56c78ce7c19e6c80b9da8f3e06b..191c033eedfb322a6705907c526131a7157a544e 100644
--- a/module/finc/src/finc/Cover/Loader.php
+++ b/module/finc/src/finc/Cover/Loader.php
@@ -59,7 +59,7 @@ class Loader extends \VuFind\Cover\Loader
     public function loadUnavailable()
     {
         $this->hasLoadedUnavailable = true;
-        if ($this->config->Content->useCoverFallbacksOnFail) {
+        if ($this->config->Content->useCoverFallbacksOnFail && !empty($this->localFile)) {
             file_put_contents($this->localFile, self::EMPTY_IMAGE_CONTENT);
         }
         return parent::loadUnavailable();
diff --git a/module/finc/src/finc/ILS/Connection.php b/module/finc/src/finc/ILS/Connection.php
index 4ddbdddb7def752e7bd4613feefb22c14e280a71..a7f05faf35fdc579c430ccbc362c746858fe0187 100644
--- a/module/finc/src/finc/ILS/Connection.php
+++ b/module/finc/src/finc/ILS/Connection.php
@@ -91,4 +91,87 @@ class Connection extends \VuFind\ILS\Connection implements TranslatorAwareInterf
         }
         return $response;
     }
+
+    /**
+     * Check ILLRequests
+     *
+     * A support method for checkFunction(). This is responsible for checking
+     * the driver configuration to determine if the system supports ILL requests.
+     *
+     * @param array $functionConfig The ILL request configuration values
+     * @param array $params         An array of function-specific params (or null)
+     *
+     * @return mixed On success, an associative array with specific function keys
+     * and values either for placing requests via a form; on failure, false.
+     */
+    protected function checkMethodILLRequests($functionConfig, $params)
+    {
+        if (
+            method_exists($this, 'getMyILLRequests')
+            &&
+            isset($functionConfig['daiaILLpattern'])
+        ) {
+            return ['daiaILLpattern' => $functionConfig['daiaILLpattern']];
+        }
+
+        return false;
+    }
+
+
+    /**
+     * Get access to the driver object.
+     * Extends parent function with a bypass of failover on InitException
+     *
+     * @param bool $init Should we initialize the driver (if necessary), or load it
+     * "as-is"?
+     *
+     * @throws \Exception
+     * @throws InitException
+     * @return object
+     */
+    public function getDriver($init = true)
+    {
+        if (null === $this->driver) {
+            $this->setDriver($this->driverManager->get($this->config->driver));
+        }
+        if (!$this->driverInitialized && $init) {
+            try {
+                $this->initializeDriver();
+            } catch (InitException $e) {
+                throw $e;
+            } catch (\Exception $e) {
+                if (!$this->failOverToNoILS()) {
+                    throw $e;
+                }
+            }
+        }
+        return $this->driver;
+    }
+
+    /**
+     * Get Hidden Login Mode
+     *
+     * This is responsible for indicating whether login should be hidden.
+     *
+     * Extends parent function with a bypass of failover on InitException
+     *
+     * @throws \Exception
+     * @throws InitException
+     * @return bool true if the login should be hidden, false if not
+     */
+    public function loginIsHidden()
+    {
+        // Graceful degradation -- return false if no method supported.
+        try {
+            return $this->checkCapability('loginIsHidden')
+                ? $this->getDriver()->loginIsHidden() : false;
+        } catch (InitException $e) {
+            throw $e;
+        } catch (\Exception $e) {
+            if ($this->failOverToNoILS()) {
+                return call_user_func_array([$this, __METHOD__], func_get_args());
+            }
+            throw $e;
+        }
+    }
 }
diff --git a/module/finc/src/finc/ILS/Driver/FincILS.php b/module/finc/src/finc/ILS/Driver/FincILS.php
index 4dbb8c94e4b9546cae0e9e32304a6b741760f398..7f8f971642d890cfab5d37eb0ae675cc449a01a1 100644
--- a/module/finc/src/finc/ILS/Driver/FincILS.php
+++ b/module/finc/src/finc/ILS/Driver/FincILS.php
@@ -108,6 +108,22 @@ class FincILS extends PAIA implements LoggerAwareInterface
      */
     protected $isil;
 
+    /**
+     * Regex to be used in getMyILLRequests,
+     * finds item IDs denoting inter library loan requests
+     *
+     * @var string
+     */
+    protected $illItemPattern;
+
+    /**
+     * Regex to be used in getMyILLRequests,
+     * finds item labels denoting inter library loan requests
+     *
+     * @var string
+     */
+    protected $illLabelPattern;
+
     /**
      * Connection timeout in seconds used for _testILSConnection()
      *
@@ -223,6 +239,16 @@ class FincILS extends PAIA implements LoggerAwareInterface
         $this->ilsTestTimeout = isset($this->config['General'])
             && isset($this->config['General']['ilsTestTimeout'])
                 ? $this->config['General']['ilsTestTimeout'] : 90;
+
+        // set filter for reserved item IDs at ILL request
+        $this->illItemPattern =
+            (isset($this->config['ILLRequests']['itemPattern']))
+                ? $this->config['ILLRequests']['itemPattern'] : null;
+
+        // set filter for reserved item labels at ILL request
+        $this->illLabelPattern =
+            (isset($this->config['ILLRequests']['labelPattern']))
+                ? $this->config['ILLRequests']['labelPattern'] : null;
     }
 
     /**
@@ -421,7 +447,7 @@ class FincILS extends PAIA implements LoggerAwareInterface
                 $retval = array_fill(0, count($ids), false);
                 foreach ($new['first_results'] as $record) {
                     /** @var \finc\RecordDriver\SolrDefault $record */
-                    $callNumbers = $record->getField($idType);
+                    $callNumbers = (array)$record->getField($idType);
                     $matches = array_intersect($ids, $callNumbers);
                     foreach ($matches as $number => $match) {
                         /* map identifier to solr id */
@@ -1704,4 +1730,34 @@ class FincILS extends PAIA implements LoggerAwareInterface
         // overriden in FincLibero
         return $limitations;
     }
+
+    /**
+     * Customized getMyILLRequests, relies on PAIA-URI pattern
+     * @param array $patron
+     * @return array
+     */
+    public function getMyILLRequests($patron)
+    {
+        // filters for getMyILLRequests are:
+        // document.item = URI has to match config pattern
+
+        if (!empty($this->illItemPattern)) {
+            $filter['regex']['item'] = $this->illItemPattern;
+        }
+
+        if (!empty($this->illLabelPattern)) {
+            // filter out some item according their status label
+            // cf. #15214
+            $filter['regex']['label'] = $this->illLabelPattern;
+        }
+
+        if (!empty($filter)) {
+            // get items-docs for given filters
+            $items = $this->paiaGetItems($patron, $filter);
+
+            return $this->mapPaiaItems($items, 'myHoldsMapping');
+        }
+
+        return [];
+    }
 }
diff --git a/module/finc/src/finc/ILS/Driver/FincLibero.php b/module/finc/src/finc/ILS/Driver/FincLibero.php
index 85a3a419e41bc0758579e7d6e4fe9a37502d986e..ec2aed3e4ee37fa7011f3bfe07e13c2163d9e5f0 100644
--- a/module/finc/src/finc/ILS/Driver/FincLibero.php
+++ b/module/finc/src/finc/ILS/Driver/FincLibero.php
@@ -27,6 +27,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace finc\ILS\Driver;
+use finc\ILS\InitException;
 use VuFind\I18n\Translator\TranslatorAwareTrait;
 use VuFind\I18n\Translator\TranslatorAwareInterface,
     VuFind\Exception\ILS as ILSException;
@@ -122,8 +123,136 @@ class FincLibero extends FincILS implements TranslatorAwareInterface
     public function init()
     {
         parent::init();
-        $this->boundItemIdPattern = $this->config['General']['bound_item_id_pattern'] ?? null;
-        $this->boundItemLabelPattern = $this->config['General']['bound_item_label_pattern'] ?? null;
+
+        $this->setMemberFromConfig('boundItemPattern', 'General', 'bound_item_id_pattern');
+        $this->setMemberFromConfig('boundItemLabelPattern', 'General',
+            'bound_item_label_pattern');
+
+        // Get the base URI to extend departments.
+        $this->setMemberFromConfig(
+            'departmentLocationBase', 'General', 'departmentLocationBase',
+            "No departmentLocationBase defined in FincLibero.ini."
+        );
+
+        // get the URIs for the limitations that are marking an item that a hold can
+        // be placed on
+        $this->setMemberFromConfig(
+            'titleHoldLimitations',
+            'General',
+            'titleHoldLimitations',
+            "No Limitations defined for action titleHold.",
+            'titleHoldLimitations'
+        );
+
+        // get the pickUpLocationPatterns configured in ILS ini and being used for
+        // filtering limitations used for pickuplocations
+        $this->setMemberFromConfig(
+            'pickUpLocationPatterns',
+            'General',
+            'pickUpLocationPatterns',
+            "No pickUpLocationPatterns defined in FincLibero.ini."
+        );
+
+        // get the URIs for the limitations that are marking an item that a storage
+        // retrieval request can be placed on
+        $this->setMemberFromConfig(
+            'requestableLimitations',
+            'General',
+            'requestableLimitations',
+            "No Limitations defined for action Storage Retrieval Request.",
+            'requestableLimitations'
+        );
+
+        // get the URIs for the limitations that are marking an item that a hold can
+        // be placed on
+        $this->setMemberFromConfig(
+            'holdableLimitations',
+            'General',
+            'holdableLimitations',
+            "No Limitations defined for action Hold.",
+            'holdableLimitations'
+        );
+
+        // get the URIs for the limitations that are marking an item that a recall can
+        // be placed on
+        $this->setMemberFromConfig(
+            'recallableLimitations',
+            'General',
+            'recallableLimitations',
+            "No Limitations defined for action Recall.",
+            'recallableLimitations'
+        );
+
+        // get URIs of limitations that will identify the item for being bound to
+        // another item
+        $this->setMemberFromConfig(
+            'awlLimitations',
+            'General',
+            'awlLimitations',
+            "No awlLimitations defined.",
+            'awlLimitations'
+        );
+
+        // get the URIs identifying records for stack views
+        $this->setMemberFromConfig(
+            'stackURIs',
+            'General',
+            'stackURIs',
+            "No stack URIs defined."
+        );
+
+        // get the URIs identifying records for reading room views
+        $this->setMemberFromConfig(
+            'readingRoomURIs',
+            'General',
+            'readingRoomURIs',
+            "No reading room URIs defined."
+        );
+    }
+
+    /**
+     * Helper function for @see FincLibero::init()
+     * Set some member variables based on Config entries from FincILS.ini or
+     * FincLibero.ini.
+     * If the given config key (in given section) is set, the member variable will be
+     * initialized with the value(s) from that key.
+     * Otherwise (not set):
+     * When the setting is required via the [RequiredConfig] section AND a debug message is
+     * given, this message will be added to the debug log.
+     * With the last parameter $configuredLimitationName, the config entry will be added
+     * to the set of configured limitations under the given name
+     *
+     * @param string $memberName               name of class member to be set
+     * @param string $configSection            section from INI file to look up (e.g. 'General' for section [General])
+     * @param string $configKey                config key within that section
+     * @param string $debugMessage             message to add to debug log on fail if the config is set required
+     * @param string $configuredLimitationName name of limitation type to be used in setConfiguredLimitation()
+     */
+    protected function setMemberFromConfig(
+        $memberName,
+        $configSection,
+        $configKey,
+        $debugMessage = '',
+        $configuredLimitationName = ''
+    ) {
+        if (
+            !isset($this->config[$configSection])
+            ||
+            !isset($this->config[$configSection][$configKey])
+        ) {
+            if (
+                !empty($debugMessage)
+                &&
+                ($this->config['RequiredConfig'][$configSection][$configKey] ?? false)
+            ) {
+                throw new InitException($debugMessage);
+            }
+        } else {
+            $this->{$memberName} = $this->config[$configSection][$configKey];
+            if (!empty($configuredLimitationName)) {
+                $this->setConfiguredLimitation($configuredLimitationName);
+            }
+        }
     }
 
     /**
@@ -136,6 +265,121 @@ class FincLibero extends FincILS implements TranslatorAwareInterface
         return preg_quote(substr($this->daiaIdPrefix, 0, strpos($this->daiaIdPrefix, ':')+1));
     }
 
+    /**
+     * Parse an array with DAIA status information.
+     * Copies \VuFind\ILS\Driver\DAIA::parseDaiaArray to enable finc-specific
+     * titleHoldLogic
+     *
+     * @param string $id        Record id for the DAIA array.
+     * @param array  $daiaArray Array with raw DAIA status information.
+     *
+     * @return array            Array with VuFind compatible status information.
+     */
+    protected function parseDaiaArray($id, $daiaArray)
+    {
+        $doc_id = null;
+        $doc_href = null;
+
+        if (isset($daiaArray['id'])) {
+            $doc_id = $daiaArray['id'];
+        }
+
+        if (isset($daiaArray['href'])) {
+            // url of the document (not needed for VuFind)
+            $doc_href = $daiaArray['href'];
+        }
+
+        if (isset($daiaArray['message'])) {
+            // log messages for debugging
+            $this->logMessages($daiaArray['message'], 'document');
+        }
+
+        // if one or more items exist, iterate and build result-item
+        if (isset($daiaArray['item']) && is_array($daiaArray['item'])) {
+            $isTitleHold = null;
+            $isTitleHoldable = $this->hasTitleHolds();
+            $number = 0;
+            foreach ($daiaArray['item'] as $item) {
+                // if it is a title-holdable record, the first item is a dummy
+                // that delivers the title hold information and MUST NOT be
+                // forwarded as an actual piece of availability information
+                // instead, all following items MUST be marked as title-holdable,
+                // to enable the frontend to display an adequate link
+                if ($isTitleHoldable && !$isTitleHold) {
+                    if ($isTitleHold = $this->isTitleHold($item)) {
+                        $titleHoldId = $item['id'];
+                        continue;
+                    }
+                }
+                $result_item = [];
+                $result_item['id'] = $id;
+
+                // custom DAIA field
+                $result_item['doc_id'] = $doc_id;
+                if (
+                    $isTitleHold
+                    &&
+                    (
+                        !isset($this->noTitleHoldStatuses)
+                        ||
+                        empty($this->noTitleHoldStatuses)
+                        ||
+                        !in_array($item['localIlsStatus'],$this->noTitleHoldStatuses)
+                    )
+                ) {
+                    $result_item['item_id'] = $titleHoldId;
+                } else {
+                    $result_item['item_id'] = $item['id'];
+                }
+
+                // custom DAIA field used in getHoldLink()
+                $result_item['ilslink']
+                    = (isset($item['href']) ? $item['href'] : $doc_href);
+                if ($isTitleHold) {
+                    $result_item['addTitleHoldLink'] = TRUE;
+                }
+
+                // count items
+                $number++;
+                $result_item['number'] = $this->getItemNumber($item, $number);
+
+                // set default value for barcode
+                $result_item['barcode'] = $this->getItemBarcode($item);
+
+                // set default value for reserve
+                $result_item['reserve'] = $this->getItemReserveStatus($item);
+
+                // get callnumber
+                $result_item['callnumber'] = $this->getItemCallnumber($item);
+
+                // get location
+                $result_item['location'] = $this->getItemDepartment($item);
+
+                // custom DAIA field
+                $result_item['locationid'] = $this->getItemDepartmentId($item);
+
+                // get location link
+                $result_item['locationhref'] = $this->getItemDepartmentLink($item);
+
+                // custom DAIA field
+                $result_item['storage'] = $this->getItemStorage($item);
+
+                // custom DAIA field
+                $result_item['storageid'] = $this->getItemStorageId($item);
+
+                // custom DAIA field
+                $result_item['storagehref'] = $this->getItemStorageLink($item);
+
+                // status and availability will be calculated in own function
+                $result_item = $this->getItemStatus($item) + $result_item;
+
+                // add result_item to the result array
+                $result[] = $result_item;
+            } // end iteration on item
+        }
+        return $result;
+    }
+
     /**
      * FincLibero specific overrides of PAIA methods
      */
@@ -295,6 +539,28 @@ class FincLibero extends FincILS implements TranslatorAwareInterface
         }
     }
 
+    /**
+     * FincLibero specific override: we need to manually update the cat_password in
+     * the session as we do not save passwords in the database and therefore the
+     * ILSAuthenticator will use the session data instead.
+     *
+     * @param array $details Array with patron information, newPassword and
+     *                       oldPassword.
+     *
+     * @return array An array with patron information.
+     */
+    public function changePassword($details)
+    {
+        $retval = parent::changePassword($details);
+
+        if ($retval == ['success' => true, 'status' => 'Successfully changed']) {
+            $session = $this->getSession();
+            $session->cat_password = $details['newPassword'];
+        }
+
+        return $retval;
+    }
+
     /**
      * PAIA helper function to map session data to return value of patronLogin()
      *
@@ -341,6 +607,20 @@ class FincLibero extends FincILS implements TranslatorAwareInterface
         return $details;
     }
 
+    /**
+     * Returns the value for "callnumber" in VuFind getStatus/getHolding array
+     *
+     * @param array $item Array with DAIA item data
+     *
+     * @return string
+     */
+    protected function getItemCallnumber($item)
+    {
+        return isset($item['label']) && !empty($item['label'])
+            ? $item['label']
+            : '';
+    }
+
     /**
      * FincLibero specific overrides of DAIA methods
      */
@@ -356,17 +636,7 @@ class FincLibero extends FincILS implements TranslatorAwareInterface
     {
         $return = parent::getItemStatus($item);
 
-        // add all item specific information from DAIA field about to item_notes
-        // (https://intern.finc.info/issues/7863)
-        $about = (isset($item['about'])) ? [$item['about']] : [];
-
-        $return['item_notes'] = array_unique(
-            array_merge(
-                (array) $return['status'],
-                $return['item_notes'],
-                $about
-            )
-        );
+        $return['item_notes'] = $this->getItemNotes($return, $item);
 
         $return['awlRecordId'] = $this->getBoundItemId($item);
         // is this item bound with another item?
@@ -389,9 +659,49 @@ class FincLibero extends FincILS implements TranslatorAwareInterface
             }
         }
 
+        $return['service_type'] = $this->_reduceServices($return['services']);
+
         return $return;
     }
 
+    /**
+     * Helper function for getItemStatus().
+     * Gather all item notes from current (parent) result and DAIA item
+     *
+     * @param array $return intermediate result from parent::getItemStatus()
+     * @param array $item   DAIA item
+     * @return array 'item_notes' part for result
+     */
+    protected function getItemNotes($return, $item)
+    {
+        // add all item specific information from DAIA field about to item_notes
+        // (https://intern.finc.info/issues/7863)
+        return array_unique(
+            array_merge(
+                (array)$return['status'],
+                $return['item_notes'],
+                $item['about'] ?? []
+            )
+        );
+    }
+
+    /**
+     * Helper function for 'service_type' entry in getItemStatus
+     *
+     * @param array $services actually present services in DAIA item
+     * @return false|int|mixed preferred service if present or 0
+     */
+    protected function _reduceServices($services)
+    {
+        $prio = [
+            'loan',
+            'presentation',
+        ];
+        $res = array_intersect($prio, $services);
+        if (empty($res)) return 0;
+        else return current($res);
+    }
+
     /**
      * Helper function to return an appropriate status string for current item
      *
@@ -604,6 +914,31 @@ class FincLibero extends FincILS implements TranslatorAwareInterface
         return $this->mapPaiaItems($items, 'myHoldsMapping');
     }
 
+    /**
+     * This method queries the ILS for a patron's current storage retrieval requests.
+     * Returns items with properties:
+     *      - document.status = 2 (ordered)
+     *      - document.storage and document.storageid do have a certain location (Magazin, but not Lesesaal)
+     *
+     * note: stackURIs musst be configured in FincLibero.ini as required
+     *
+     * @param array $patron Array returned from patronLogin()
+     *
+     * @return array
+     */
+    public function getMyStorageRetrievalRequests($patron)
+    {
+        $filter = [
+            'status'  => [2],
+            'storageid' => $this->stackURIs,
+            'regex'   => ['item' => "/^(" . $this->getDaiaIdPrefixNamespace() . ").*$/"]
+        ];
+        // get items-docs for given filters
+        $items = $this->paiaGetItems($patron, $filter);
+
+        return $this->mapPaiaItems($items, 'myStorageRetrievalRequestsMapping');
+    }
+
     /**
      * Customized getMyTransactions for FincLibero to return items with properties:
      *      - document.status = 3 (held)
@@ -826,6 +1161,17 @@ class FincLibero extends FincILS implements TranslatorAwareInterface
         return null;
     }
 
+    /**
+     * May there be Title holdable items in this instance?
+     * Inherited FincLibero drivers should set see $titleHoldLimitations
+     * to achieve this
+     *
+     * @return bool
+     */
+    public function hasTitleHolds() {
+        return isset($this->titleHoldLimitations);
+    }
+
     /**
      * Place Title Hold
      *
@@ -925,4 +1271,47 @@ class FincLibero extends FincILS implements TranslatorAwareInterface
     {
         return '';
     }
+
+    /**
+     * This method returns a list of locations where a user may collect a hold.
+     *
+     * @param array $patron  Patron array returned by patronLogin method
+     * @param array $details Hold information array similar to placeHold's input
+     * @return array Array of associative arrays containing these keys:
+     *      locationID - A pick up location id or code (string)
+     *      locationDisplay – The text to display for the location (string)
+     *
+     * @link https://vufind.org/wiki/development:plugins:ils_drivers#getpickuplocations
+     */
+    public function getPickUpLocations($patron = [], $details = [])
+    {
+        // use departments of Wachtl, not DAIA
+        if ($this->config['General']['useWachtlPickupLocations'] ?? false) {
+            return $this->getWachtlPickUpLocations($details);
+        }
+
+        // use location and locationid, not customData of DAIA
+        if ($this->config['General']['useDaiaLocationId'] ?? false) {
+            return parent::getPickUpLocations($patron, $details);
+        }
+
+        // use DAIA customData
+        if ($details != [] && isset($details['id'])) {
+            $statusItems = $this->getStatus($details['id']);
+            foreach ($statusItems as $statusItem) {
+                if ($statusItem['item_id'] == $details['item_id']) {
+                    // our pickUpLocations are stored in the customData array upon
+                    // processing the DAIA availability information
+                    if (isset($statusItem['customData'])
+                        && isset($statusItem['customData']['pickUpLocations'])
+                    ) {
+                        return $statusItem['customData']['pickUpLocations'];
+                    } else {
+                        return $this->stackURIs ?? [];
+                    }
+                }
+            }
+        }
+        return [];
+    }
 }
diff --git a/module/finc/src/finc/ILS/Driver/LiberoWachtlTrait.php b/module/finc/src/finc/ILS/Driver/LiberoWachtlTrait.php
index 6135ea641d59fa38bd564fea19572276f6edb3af..21fcdc09c3ff203ea58b8ae0d49c39ecd2a36d2d 100644
--- a/module/finc/src/finc/ILS/Driver/LiberoWachtlTrait.php
+++ b/module/finc/src/finc/ILS/Driver/LiberoWachtlTrait.php
@@ -344,67 +344,6 @@ trait LiberoWachtlTrait
         return $bool;
     }
 
-    /**
-     * Change values of users profile.
-     *
-     * @param array $inval Associative array of key => value. Keys are:
-     *     - memberCode   : User ID returned by patronLogin
-     *     - street       : street and number
-     *     - additional   : optional address value
-     *     - city         : city/village
-     *     - zipCode      : location zip code
-     *     - emailAddress : email address
-     *     - reason       : reason of change
-     * @param array $patron Patron data
-     *
-     * @return boolean true OK, false FAIL
-     * @access public
-     * @throws \Exception Throws ILSException
-     */
-    public function setMyProfile($inval, $patron)
-    {
-        $map = self::profileDataMapper(true);
-
-        $params                 = $this->getLiberoWachtlRequestParams();
-        $params['memberCode']   = $patron['cat_username'];
-        $params['password']     = $patron['cat_password'];
-
-        $data = [];
-        if (is_array($inval) && (count($inval) > 0)) {
-            foreach ($inval as $k => $v) {
-                if (isset($map[$k])) {
-                    $data[$map[$k]] = $v;
-                } else {
-                    $data[$k] = $v;
-                }
-            }
-        }
-
-        $params = array_merge($params, $data);
-
-        try {
-            $result = $this->httpService->get(
-                $this->getLiberoWachtlUrl() .'setMyProfile.jsp',
-                $params,
-                null,
-                $this->getLiberoWachtlRequestHeaders()
-            );
-        } catch (\Exception $e) {
-            throw new ILSException($e->getMessage());
-        }
-
-        if (!$result->isSuccess()) {
-            // log error for debugging
-            $this->debug(
-                'HTTP status ' . $result->getStatusCode() .
-                ' received'
-            );
-            return false;
-        }
-
-        return $this->getLiberoWachtlResultBool($result);
-    }
-
     /**
      * Returns Array with profile fields that are never allowed to be edited
      *
@@ -503,6 +442,49 @@ trait LiberoWachtlTrait
         return $this->getLiberoWachtlResult($result, 'getMyProfile');
     }
 
+    /**
+     * This method returns a list of locations where a user may collect a hold.
+     *
+     * @param array $details Hold information array similar to placeHold's input - needed for overriden method in de_zi4
+     *
+     * @return array $locations Array of associative arrays containing these keys:
+     *      locationID - A pick up location id or code (string)
+     *      locationDisplay – The text to display for the location (string)
+     * @throws \Exception
+     * @throws \ILSException
+     *
+     * @link https://vufind.org/wiki/development:plugins:ils_drivers#getpickuplocations
+     */
+    public function getWachtlPickUpLocations($details = [])
+    {
+        $locations = [];
+
+        try {
+            $client = $this->httpService->createClient(
+                $this->baseUrl .
+                $this->config['General']['liberoDbName'] .
+                '/departments'
+            );
+            $result = $client->send();
+        } catch (\Exception $e) {
+            throw new ILSException($e->getMessage());
+        }
+
+        if ($result->isSuccess()) {
+            $arr = json_decode($result->getBody(), true);
+            $i = 0;
+            foreach ($arr as $code => $name) {
+                $locations[]
+                    = ['locationID' => $code, 'locationDisplay' => $name]
+                ;
+            }
+        } else {
+            $this->debug(
+                "No list of pickup locations found."
+            );
+        }
+        return $locations;
+    }
 
     /**
      * This method sends a PIN changing request to the LiberoWachtl.
@@ -677,6 +659,9 @@ trait LiberoWachtlTrait
                 $this->getLiberoWachtlRequestHeaders()
             );
         } catch (\Exception $e) {
+            $this->debug(
+                'Error loading loan history from LiberoWachtl: ' . $e->getMessage()
+            );
             throw new ILSException($e->getMessage());
         }
         if (!$result->isSuccess()) {
diff --git a/module/finc/src/finc/View/Helper/Root/HeadTitle.php b/module/finc/src/finc/ILS/InitException.php
similarity index 56%
rename from module/finc/src/finc/View/Helper/Root/HeadTitle.php
rename to module/finc/src/finc/ILS/InitException.php
index c4036a17429c5da292fb5e574bf9f40d53de3588..7e7a692cc70717ea3e4b107c33806966381ced22 100644
--- a/module/finc/src/finc/View/Helper/Root/HeadTitle.php
+++ b/module/finc/src/finc/ILS/InitException.php
@@ -1,10 +1,9 @@
 <?php
 /**
- * Head Title view helper
- *
+ * Exception thrown in FincLibero::init()
  * PHP version 7
  *
- * Copyright (C) Leipzig University Library 2020.
+ * Copyright (C) Leipzig University Library 2021.
  *
  * 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 +19,22 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  * @category VuFind
- * @package  View_Helpers
+ * @package  ILS_Drivers
  * @author   Dorian Merz <merz@ub.uni-leipzig.de>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development Wiki
+ * @link     https://vufind.org/wiki/development:plugins:ils_drivers Wiki
  */
-namespace finc\View\Helper\Root;
-
-use Zend\View\Helper\HeadTitle as BaseHelper;
+namespace finc\ILS;
 
 /**
- * Head Title view helper
+ * Exception thrown in FincLibero::init()
  *
  * @category VuFind
- * @package  View_Helpers
+ * @package  ILS_Drivers
  * @author   Dorian Merz <merz@ub.uni-leipzig.de>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development Wiki
+ * @link     https://vufind.org/wiki/development:plugins:ils_drivers Wiki
  */
-class HeadTitle extends BaseHelper
+class InitException extends \Exception
 {
-    protected $headerSuffix;
-
-    public function __construct($headerSuffix = '')
-    {
-        parent::__construct();
-        if (!empty($headerSuffix)) {
-            $this->headerSuffix = ' - '.$headerSuffix;
-        }
-    }
-
-    public function __invoke($title = null, $setType = null)
-    {
-        $title = $title ? : $this->headerSuffix;
-        return parent::__invoke($title, $setType);
-    }
 }
diff --git a/module/finc/src/finc/RecordTab/HierarchyTree.php b/module/finc/src/finc/RecordTab/HierarchyTree.php
index 315b773894fe50aa0da87b36fdf6c63318eb1ae9..56133533858816cab39174a1e310b1cf762716c5 100644
--- a/module/finc/src/finc/RecordTab/HierarchyTree.php
+++ b/module/finc/src/finc/RecordTab/HierarchyTree.php
@@ -67,4 +67,15 @@ class HierarchyTree extends \VuFind\RecordTab\HierarchyTree
         }
         return false;
     }
+
+    /**
+     * Can this tab be loaded via AJAX?
+     *
+     * @return bool
+     */
+    public function supportsAjax()
+    {
+        // No, special width adjustment needed.
+        return true;
+    }
 }
diff --git a/module/finc/src/finc/View/Helper/Root/ExternalLink.php b/module/finc/src/finc/View/Helper/Root/ExternalLink.php
index 91b1df9feaadbd1b7b2d51291c99fbd5a88d46d9..6bfbb6de3ccd846cfaef56c46476b148458683ec 100644
--- a/module/finc/src/finc/View/Helper/Root/ExternalLink.php
+++ b/module/finc/src/finc/View/Helper/Root/ExternalLink.php
@@ -27,6 +27,9 @@
  */
 namespace finc\View\Helper\Root;
 
+use Zend\View\Helper\EscapeHtml;
+use Zend\View\Helper\EscapeHtmlAttr;
+
 /**
  * External link view helper
  *
@@ -38,13 +41,6 @@ namespace finc\View\Helper\Root;
  */
 class ExternalLink extends \Zend\View\Helper\AbstractHelper
 {
-    /**
-     * Context view helper
-     *
-     * @var \VuFind\View\Helper\Root\Translate
-     */
-    protected $translator;
-
     /**
      * Default html attributes for external links
      *
@@ -55,6 +51,13 @@ class ExternalLink extends \Zend\View\Helper\AbstractHelper
         'rel' => 'noopener'
     ];
 
+    /**
+     * Escape manuelly flag
+     *
+     * @var bool
+     */
+    protected $manualEscape;
+
     /**
      * Renders an anchor element (hyperlink) to an external website
      *
@@ -62,7 +65,8 @@ class ExternalLink extends \Zend\View\Helper\AbstractHelper
      * @param string $label          desired label or translation token
      * @param array  $attributes     more attributes to apply to the a element,
      *                               key-value-pairs
-     * @param bool   $translateLabel true if label shall be translated
+     * @param bool   $manualEscape   true if $label conatins html to display and
+     *                               $attributes are escped before calling method
      *
      * @return string
      */
@@ -70,36 +74,55 @@ class ExternalLink extends \Zend\View\Helper\AbstractHelper
         $href,
         $label = '',
         $attributes = [],
-        $translateLabel = false
+        $manualEscape = false
     ) {
+        $this->manualEscape = $manualEscape;
+
         $link = '<a href="' . $href . '"';
         $attributes = array_merge($this->defaultAttributes, $attributes);
         foreach ($attributes as $key => $value) {
-            $link .= ' ' . $key . '="' . $value . '"';
+            $link .= ' ' . $key . '="' . $this->escapeHtmlAttr($value) . '"';
         }
         $link .= '>';
         if (empty($label)) {
             $label = $href;
-        } elseif ($translateLabel) {
-            $label = $this->translate($label);
         }
-        $link .= $label . '</a>';
+        $link .= $this->escapeHtml($label) . '</a>';
 
         return $link;
     }
 
     /**
-     * Helper function to provide access to Translate ViewHelper
+     * Helper function to provide access to EscapeHTML ViewHelper
+     * and esacpe lable if not disabled
+     *
+     * @param string $html html to escape
+     *
+     * @return string
+     */
+    protected function escapeHtml($html)
+    {
+        if ($this->manualEscape) {
+            return $html;
+        }
+        $htmlEscaper = $this->getView()->plugin('escapeHtml');
+        return $htmlEscaper($html);
+    }
+
+    /**
+     * Helper function to provide access to EscaperHTML Attribute ViewHelper
+     * and esacpe HTML attributes if not disabled
      *
      * @param string $label translation token
      *
      * @return string
      */
-    protected function translate($label)
+    protected function escapeHtmlAttr($htmlAttr)
     {
-        if (!isset($this->translator)) {
-            $this->translator = $this->getView()->plugin('translate');
+        if ($this->manualEscape) {
+            return $htmlAttr;
         }
-        return $this->translator->translate($label);
+        $htmlAttrEscaper = $this->getView()->plugin('escapeHtmlAttr');
+        return $htmlAttrEscaper($htmlAttr);
     }
 }
diff --git a/module/finc/src/finc/View/Helper/Root/Factory.php b/module/finc/src/finc/View/Helper/Root/Factory.php
index 4e44d5bae6a6e2bf0f8fa2a1aac7ae8a438cfb84..82c343ba186660ec99e903001f73c65ed609594d 100644
--- a/module/finc/src/finc/View/Helper/Root/Factory.php
+++ b/module/finc/src/finc/View/Helper/Root/Factory.php
@@ -211,19 +211,6 @@ class Factory
         );
     }
 
-    /**
-     * Construct Head Title Helper
-     *
-     * @param ContainerInterface $container Service manager
-     *
-     * @return HeadTitle
-     */
-    public static function getHeadTitle(ContainerInterface $container)
-    {
-        $config = $container->get('VuFind\Config')->get('config')->Site;
-        return new HeadTitle($config->title ?? '');
-    }
-
     /**
      * Construct ExternalLink
      *
diff --git a/themes/bootstrap3/templates/myresearch/bulk-action-buttons.phtml b/themes/bootstrap3/templates/myresearch/bulk-action-buttons.phtml
index 5faab89bab08a6b54ab8b691dba047df130846cc..c45b65be814f752315ead128e55978daa25fcac0 100644
--- a/themes/bootstrap3/templates/myresearch/bulk-action-buttons.phtml
+++ b/themes/bootstrap3/templates/myresearch/bulk-action-buttons.phtml
@@ -1,6 +1,6 @@
-<?php if (isset($locations)): ?>
-  <input type="hidden" name="listID" value="<?=$this->escapeHtmlAttr($locations->id)?>" />
-  <input type="hidden" name="listName" value="<?=$this->escapeHtmlAttr($locations->title)?>" />
+<?php if (isset($list)): ?>
+  <input type="hidden" name="listID" value="<?=$this->escapeHtmlAttr($list->id)?>" />
+  <input type="hidden" name="listName" value="<?=$this->escapeHtmlAttr($list->title)?>" />
 <?php endif; ?>
 <?php $user = $this->auth()->isLoggedIn(); ?>
 <div class="bulkActionButtons">
diff --git a/themes/fid/templates/fid/order/order-edit-missing-record.phtml b/themes/fid/templates/fid/order/order-edit-missing-record.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..144a2c896f6f649d06e093a465b4ec93724a719e
--- /dev/null
+++ b/themes/fid/templates/fid/order/order-edit-missing-record.phtml
@@ -0,0 +1,31 @@
+<!-- fid: fid - order - edit-order-missing-record -->
+<h2><?= $this->translate("fid::acquisition_info_requested_item") ?></h2>
+<table class="table table-striped">
+  <tr>
+    <th><?=$this->transEsc('Title')?>:</th>
+    <td>
+<?php
+$externalUrl = $this->order->getData()['digitization']['external_url'] ?? null;
+$recordLabel = $this->order->getLabel();
+if($externalUrl) : ?>
+    <?= $this->externalLink($externalUrl, $recordLabel, ['data-lightbox-ignore' => '']) ?>
+<?php else: ?>
+    <?=$recordLabel?>
+<?php endif; ?>
+    </td>
+  </tr>
+    <?php // Template for use by the renderArray helper:
+    $arrTemplate = '<tr></tr><th>%%LABEL%%:</th><td> %%VALUE%%</td></tr>';
+    ?>
+    <?= $this->renderArray(
+        $arrTemplate, $this->order->getData()['digitization'],
+        [
+            $this->transEsc('fid::acquisition_label_responsible') => 'responsible',
+            $this->transEsc('fid::acquisition_label_year') => 'year',
+            $this->transEsc('fid::acquisition_label_language') => 'language',
+            $this->transEsc('fid::acquisition_label_library') => 'library',
+            $this->transEsc('fid::acquisition_label_signature') => 'signature'
+        ]
+    ) ?>
+</table>
+<!-- fid: fid - order - edit-order-missing-record - END -->
diff --git a/themes/fid/templates/fid/order/order-edit.phtml b/themes/fid/templates/fid/order/order-edit.phtml
index 4b48b8ee68a0cb23d810342f33452436b840ed13..b8d4170b82fd599ca3bde1c9ee7e4b2f93fe2a20 100644
--- a/themes/fid/templates/fid/order/order-edit.phtml
+++ b/themes/fid/templates/fid/order/order-edit.phtml
@@ -38,12 +38,17 @@ $this->headTitle($title = $this->translate("fid::acquisition_{$order->getType()}
 
 <?=$this->render('fid/record/acquisition-contact-details'); ?>
 
+<?php if ($driver != null ): ?>
 <?php
-  $driver = $this->driver;
   $formatter = $this->recordDataFormatter();
   $this->coreFields = $formatter->getData($driver, $formatter->getDefaults('fid-acquisition-general'));
 ?>
 <?=$this->render('fid/record/acquisition-record-details'); ?>
+<?php else: ?>
+    <?=$this->render('fid/order/order-edit-missing-record', [
+        'order' => $this->order
+    ]) ?>
+<?php endif; ?>
 
 <h2><?=$this->translate("Status")?></h2>
 
diff --git a/themes/finc-accessibility/js/cart.js b/themes/finc-accessibility/js/cart.js
new file mode 100644
index 0000000000000000000000000000000000000000..9fc90e6810a59fd411c5861d382083f1672054af
--- /dev/null
+++ b/themes/finc-accessibility/js/cart.js
@@ -0,0 +1,287 @@
+/*global Cookies, VuFind */
+/*exported cartFormHandler */
+
+VuFind.register('cart', function Cart() {
+  var _COOKIE = 'vufind_cart';
+  var _COOKIE_SOURCES = 'vufind_cart_src';
+  var _COOKIE_DELIM = "\t";
+  var _COOKIE_DOMAIN = false;
+  var _COOKIE_PATH = '/';
+
+  function setDomain(domain) {
+    _COOKIE_DOMAIN = domain;
+  }
+
+  function setCookiePath(path) {
+    _COOKIE_PATH = path;
+  }
+
+  function _uniqueArray(op) {
+    var ret = [];
+    for (var i = 0; i < op.length; i++) {
+      if (ret.indexOf(op[i]) < 0) {
+        ret.push(op[i]);
+      }
+    }
+    return ret;
+  }
+
+  function _getItems() {
+    var items = Cookies.getItem(_COOKIE);
+    if (items) {
+      return items.split(_COOKIE_DELIM);
+    }
+    return [];
+  }
+  function _getSources() {
+    var items = Cookies.getItem(_COOKIE_SOURCES);
+    if (items) {
+      return items.split(_COOKIE_DELIM);
+    }
+    return [];
+  }
+  function getFullItems() {
+    var items = _getItems();
+    var sources = _getSources();
+    var full = [];
+    if (items.length === 0) {
+      return [];
+    }
+    for (var i = items.length; i--;) {
+      full[full.length] = sources[items[i].charCodeAt(0) - 65] + '|' + items[i].substr(1);
+    }
+    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);
+    if (items.length === parseInt(VuFind.translate('bookbagMax'), 10)) {
+      $('#cartItems .full').removeClass('hidden');
+    } else {
+      $('#cartItems .full').addClass('hidden');
+    }
+    _refreshToggles();
+  }
+
+  function addItem(id, _source) {
+    var source = _source || VuFind.defaultSearchBackend;
+    var cartItems = _getItems();
+    var cartSources = _getSources();
+    if (cartItems.length >= parseInt(VuFind.translate('bookbagMax'), 10)) {
+      return false;
+    }
+    var sIndex = cartSources.indexOf(source);
+    if (sIndex < 0) {
+      // Add source to source cookie
+      cartItems[cartItems.length] = String.fromCharCode(65 + cartSources.length) + id;
+      cartSources[cartSources.length] = source;
+      Cookies.setItem(_COOKIE_SOURCES, cartSources.join(_COOKIE_DELIM), false, _COOKIE_PATH, _COOKIE_DOMAIN);
+    } else {
+      cartItems[cartItems.length] = String.fromCharCode(65 + sIndex) + id;
+    }
+    Cookies.setItem(_COOKIE, _uniqueArray(cartItems).join(_COOKIE_DELIM), false, _COOKIE_PATH, _COOKIE_DOMAIN);
+    updateCount();
+    return true;
+  }
+  function removeItem(id, source) {
+    var cartItems = _getItems();
+    var cartSources = _getSources();
+    // Find
+    var cartIndex = cartItems.indexOf(String.fromCharCode(65 + cartSources.indexOf(source)) + id);
+    if (cartIndex > -1) {
+      var sourceIndex = cartItems[cartIndex].charCodeAt(0) - 65;
+      var saveSource = false;
+      for (var i = cartItems.length; i--;) {
+        if (i === cartIndex) {
+          continue;
+        }
+        // If this source is shared by another, keep it
+        if (cartItems[i].charCodeAt(0) - 65 === sourceIndex) {
+          saveSource = true;
+          break;
+        }
+      }
+      cartItems.splice(cartIndex, 1);
+      // Remove unused sources
+      if (!saveSource) {
+        var oldSources = cartSources.slice(0);
+        cartSources.splice(sourceIndex, 1);
+        // Adjust source index characters
+        for (var j = cartItems.length; j--;) {
+          var si = cartItems[j].charCodeAt(0) - 65;
+          var ni = cartSources.indexOf(oldSources[si]);
+          cartItems[j] = String.fromCharCode(65 + ni) + cartItems[j].substring(1);
+        }
+      }
+      if (cartItems.length > 0) {
+        Cookies.setItem(_COOKIE, _uniqueArray(cartItems).join(_COOKIE_DELIM), false, _COOKIE_PATH, _COOKIE_DOMAIN);
+        Cookies.setItem(_COOKIE_SOURCES, _uniqueArray(cartSources).join(_COOKIE_DELIM), false, _COOKIE_PATH, _COOKIE_DOMAIN);
+      } else {
+        Cookies.removeItem(_COOKIE, _COOKIE_PATH, _COOKIE_DOMAIN);
+        Cookies.removeItem(_COOKIE_SOURCES, _COOKIE_PATH, _COOKIE_DOMAIN);
+      }
+      updateCount();
+      return true;
+    }
+    return false;
+  }
+
+  var _cartNotificationTimeout = false;
+  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 addToSelected = function processCartFormValues() {
+        if (-1 === selected.indexOf(this.value)) {
+          selected.push(this.value);
+        }
+      };
+      var selectedInForm = $form.find('input[name="ids[]"]:checked');
+      var selectedFormAttr = $('input[form="' + $form.attr('id') + '"][name="ids[]"]:checked');
+      $(selectedInForm).each(addToSelected);
+      $(selectedFormAttr).each(addToSelected);
+      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 += VuFind.translate('itemsAddBag', {'%%count%%': added});
+        if (updated.length >= parseInt(VuFind.translate('bookbagMax'), 10)) {
+          msg += "<br/>" + VuFind.translate('bookbagFull');
+        }
+        if (inCart > 0 && orig.length > 0) {
+          msg += "<br/>" + VuFind.translate('itemsInBag', {'%%count%%': inCart});
+        }
+        $('#' + 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 _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(e) {
+          e.preventDefault();
+          if (addItem(currentId, currentSource)) {
+            $this.find('.cart-add').addClass('hidden');
+            /* #20374 set focus */
+            $this.find('.cart-remove').removeClass('hidden').focus();
+            /* #20374 set focus - END*/
+          } else {
+            $this.popover({content: VuFind.translate('bookbagFull')});
+            setTimeout(function recordCartFullHide() {
+              $this.popover('hide');
+            }, 5000);
+          }
+        });
+        $this.find('.cart-remove').click(function cartRemoveClick(e) {
+          e.preventDefault();
+          removeItem(currentId, currentSource);
+          /* #20374 set focus */
+          $this.find('.cart-add').removeClass('hidden').focus();
+          /* #20374 set focus - END */
+          $this.find('.cart-remove').addClass('hidden');
+        });
+      });
+    }
+  }
+
+  function init() {
+    // Record buttons
+    _registerToggles();
+    // Search results
+    _registerUpdate();
+    $("#updateCart, #bottom_updateCart").popover({
+      content: '',
+      html: true,
+      trigger: 'manual',
+      placement: $(document.body).hasClass('rtl') ? 'left' : 'right'
+    });
+    /* #18034 accessibility: inform screen reader about changes, eventually intregrate by PR into bootstrap - RL */
+    var cart = document.getElementById("cartSummary");
+    if (cart !== null && cart !== undefined) {
+      cart.setAttribute("aria-live", "polite");
+      cart.setAttribute("aria-atomic", "true");
+    }
+    /* #18034 - END */
+    updateCount();
+  }
+
+  // Reveal
+  return {
+    // Methods
+    addItem: addItem,
+    getFullItems: getFullItems,
+    hasItem: hasItem,
+    removeItem: removeItem,
+    setCookiePath: setCookiePath,
+    setDomain: setDomain,
+    updateCount: updateCount,
+    // Init
+    init: init
+  };
+});
+
+// Building an array and checking indexes prevents a race situation
+// We want to prioritize empty over printing
+function cartFormHandler(event, data) {
+  var keys = [];
+  for (var i in data) {
+    if (Object.prototype.hasOwnProperty.call(data, i)) {
+      keys.push(data[i].name);
+    }
+  }
+  if (keys.indexOf('ids[]') === -1) {
+    return null;
+  }
+  if (keys.indexOf('print') > -1) {
+    return true;
+  }
+}
+
+document.addEventListener('VuFind.lightbox.closed', VuFind.cart.updateCount, false);
diff --git a/themes/finc-accessibility/js/record.js b/themes/finc-accessibility/js/record.js
new file mode 100644
index 0000000000000000000000000000000000000000..26da27f6f5f484bf429a4eab12162fc12bf15de8
--- /dev/null
+++ b/themes/finc-accessibility/js/record.js
@@ -0,0 +1,325 @@
+/*global deparam, getUrlRoot, grecaptcha, recaptchaOnLoad, resetCaptcha, syn_get_widget, userIsLoggedIn, VuFind, setupJumpMenus */
+/*exported ajaxTagUpdate, recordDocReady, refreshTagListCallback */
+
+/**
+ * Functions and event handlers specific to record pages.
+ */
+function checkRequestIsValid(element, requestType) {
+  var recordId = element.href.match(/\/Record\/([^/]+)\//)[1];
+  var vars = deparam(element.href);
+  vars.id = recordId;
+
+  var url = VuFind.path + '/AJAX/JSON?' + $.param({
+    method: 'checkRequestIsValid',
+    id: recordId,
+    requestType: requestType,
+    data: vars
+  });
+  $.ajax({
+    dataType: 'json',
+    cache: false,
+    url: url
+  })
+    .done(function checkValidDone(response) {
+      if (response.data.status) {
+        $(element).removeClass('disabled')
+          .attr('title', response.data.msg)
+          .html('<i class="fa fa-flag" aria-hidden="true"></i>&nbsp;' + response.data.msg);
+      } else {
+        $(element).remove();
+      }
+    })
+    .fail(function checkValidFail(/*response*/) {
+      $(element).remove();
+    });
+}
+
+function setUpCheckRequest() {
+  $('.checkRequest').each(function checkRequest() {
+    checkRequestIsValid(this, 'Hold');
+  });
+  $('.checkStorageRetrievalRequest').each(function checkStorageRetrievalRequest() {
+    checkRequestIsValid(this, 'StorageRetrievalRequest');
+  });
+  $('.checkILLRequest').each(function checkILLRequest() {
+    checkRequestIsValid(this, 'ILLRequest');
+  });
+}
+
+function deleteRecordComment(element, recordId, recordSource, commentId) {
+  var url = VuFind.path + '/AJAX/JSON?' + $.param({ method: 'deleteRecordComment', id: commentId });
+  $.ajax({
+    dataType: 'json',
+    url: url
+  })
+    .done(function deleteCommentDone(/*response*/) {
+      $($(element).closest('.comment')[0]).remove();
+    });
+}
+
+function refreshCommentList($target, recordId, recordSource) {
+  var url = VuFind.path + '/AJAX/JSON?' + $.param({
+    method: 'getRecordCommentsAsHTML',
+    id: recordId,
+    source: recordSource
+  });
+  $.ajax({
+    dataType: 'json',
+    url: url
+  })
+    .done(function refreshCommentListDone(response) {
+      // Update HTML
+      var $commentList = $target.find('.comment-list');
+      $commentList.empty();
+      $commentList.append(response.data.html);
+      $commentList.find('.delete').unbind('click').click(function commentRefreshDeleteClick() {
+        var commentId = $(this).attr('id').substr('recordComment'.length);
+        deleteRecordComment(this, recordId, recordSource, commentId);
+        return false;
+      });
+      $target.find('.comment-form input[type="submit"]').button('reset');
+      resetCaptcha($target);
+    });
+}
+
+function registerAjaxCommentRecord(_context) {
+  var context = typeof _context === "undefined" ? document : _context;
+  // Form submission
+  $(context).find('form.comment-form').unbind('submit').submit(function commentFormSubmit() {
+    var form = this;
+    var id = form.id.value;
+    var recordSource = form.source.value;
+    var url = VuFind.path + '/AJAX/JSON?' + $.param({ method: 'commentRecord' });
+    var data = {
+      comment: form.comment.value,
+      id: id,
+      source: recordSource
+    };
+    if (typeof grecaptcha !== 'undefined') {
+      var recaptcha = $(form).find('.g-recaptcha');
+      if (recaptcha.length > 0) {
+        data['g-recaptcha-response'] = grecaptcha.getResponse(recaptcha.data('captchaId'));
+      }
+    }
+    $.ajax({
+      type: 'POST',
+      url: url,
+      data: data,
+      dataType: 'json'
+    })
+      .done(function addCommentDone(/*response, textStatus*/) {
+        var $form = $(form);
+        var $tab = $form.closest('.list-tab-content');
+        if (!$tab.length) {
+          $tab = $form.closest('.tab-pane');
+        }
+        refreshCommentList($tab, id, recordSource);
+        $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; }
+        VuFind.lightbox.alert(response.responseJSON.data, 'danger');
+      });
+    return false;
+  });
+  // Delete links
+  $('.delete').click(function commentDeleteClick() {
+    var commentId = this.id.substr('recordComment'.length);
+    deleteRecordComment(this, $('.hiddenId').val(), $('.hiddenSource').val(), commentId);
+    return false;
+  });
+  // Prevent form submit
+  return false;
+}
+
+function registerTabEvents() {
+  // Logged in AJAX
+  registerAjaxCommentRecord();
+  // Render recaptcha
+  recaptchaOnLoad();
+
+  setUpCheckRequest();
+
+  VuFind.lightbox.bind('.tab-pane.active');
+}
+
+function removeHashFromLocation() {
+  if (window.history.replaceState) {
+    var href = window.location.href.split('#');
+    window.history.replaceState({}, document.title, href[0]);
+  } else {
+    window.location.hash = '#';
+  }
+}
+
+function ajaxLoadTab($newTab, tabid, setHash) {
+  // Request the tab via AJAX:
+  $.ajax({
+    url: VuFind.path + getUrlRoot(document.URL) + '/AjaxTab',
+    type: 'POST',
+    data: {tab: tabid}
+  })
+    .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();
+      }
+      if (typeof setHash == 'undefined' || setHash) {
+        window.location.hash = tabid;
+      } else {
+        removeHashFromLocation();
+      }
+      setupJumpMenus($newTab);
+    });
+  return false;
+}
+
+function refreshTagList(_target, _loggedin) {
+  var loggedin = !!_loggedin || userIsLoggedIn;
+  var target = _target || document;
+  var recordId = $(target).find('.hiddenId').val();
+  var recordSource = $(target).find('.hiddenSource').val();
+  var $tagList = $(target).find('.tagList');
+  if ($tagList.length > 0) {
+    var url = VuFind.path + '/AJAX/JSON?' + $.param({
+      method: 'getRecordTags',
+      id: recordId,
+      source: recordSource
+    });
+    $.ajax({
+      dataType: 'json',
+      url: url
+    })
+      .done(function getRecordTagsDone(response) {
+        $tagList.empty();
+        $tagList.replaceWith(response.data.html);
+        if (loggedin) {
+          $tagList.addClass('loggedin');
+        } else {
+          $tagList.removeClass('loggedin');
+        }
+      });
+  }
+}
+function refreshTagListCallback() {
+  refreshTagList(false, true);
+}
+
+function ajaxTagUpdate(_link, tag, _remove) {
+  var link = _link || document;
+  var remove = _remove || false;
+  var $target = $(link).closest('.record');
+  var recordId = $target.find('.hiddenId').val();
+  var recordSource = $target.find('.hiddenSource').val();
+  $.ajax({
+    url: VuFind.path + '/AJAX/JSON?method=tagRecord',
+    method: 'POST',
+    data: {
+      tag: '"' + tag.replace(/\+/g, ' ') + '"',
+      id: recordId,
+      source: recordSource,
+      remove: remove
+    }
+  })
+    .always(function tagRecordAlways() {
+      refreshTagList($target, false);
+    });
+}
+
+function getNewRecordTab(tabid) {
+  return $('<div class="tab-pane ' + tabid + '-tab" id="' + tabid + '" role="tabpanel" tabindex="-1" aria-labelledby="' + tabid + '-tabselector"><i class="fa fa-spinner fa-spin" aria-hidden="true"></i> ' + VuFind.translate('loading') + '...</div>');
+}
+
+function backgroundLoadTab(tabid) {
+  if ($('.' + tabid + '-tab').length > 0) {
+    return;
+  }
+  var newTab = getNewRecordTab(tabid);
+  $('.nav-tabs a.' + tabid).closest('.result,.record').find('.tab-content').append(newTab);
+  return ajaxLoadTab(newTab, tabid, false);
+}
+
+function applyRecordTabHash() {
+  var activeTab = $('.record-tabs li.active').attr('data-tab');
+  var $initiallyActiveTab = $('.record-tabs li.initiallyActive a');
+  var newTab = typeof window.location.hash !== 'undefined'
+    ? window.location.hash.toLowerCase() : '';
+
+  // Open tab in url hash
+  if (newTab.length <= 1 || newTab === '#tabnav') {
+    $initiallyActiveTab.click();
+  } else if (newTab.length > 1 && '#' + activeTab !== newTab) {
+    $('.' + newTab.substr(1) + ' a').click();
+  }
+}
+
+$(window).on('hashchange', applyRecordTabHash);
+
+function recordDocReady() {
+  $('.record-tabs .nav-tabs a').click(function recordTabsClick() {
+    var $li = $(this).parent();
+    // If it's an active tab, click again to follow to a shareable link.
+    if ($li.hasClass('active')) {
+      return true;
+    }
+    var tabid = $li.attr('data-tab');
+    var $top = $(this).closest('.record-tabs');
+
+    // accessibility: mark tab controls as selected
+    $top.find('.record-tab.active').find('a').attr('aria-selected', 'false');
+    // accessibility: set information about connection between tab control and tab content
+    $(this).attr('aria-controls', tabid);
+    $('#' + tabid + '-tabselector').attr('aria-selected', 'true').attr('aria-controls', tabid);
+
+    // accessibility: set aria-hidden for content panes
+    $top.find('.tab-pane.active').removeClass('active').attr('aria-hidden', 'true');
+    $top.find('.' + tabid + '-tab').addClass('active').attr('aria-hidden', 'false');
+
+    // if we're flagged to skip AJAX for this tab, we need special behavior:
+    if ($li.hasClass('noajax')) {
+      // if this was the initially active tab, we have moved away from it and
+      // now need to return -- just switch it back on.
+      if ($li.hasClass('initiallyActive')) {
+        $(this).tab('show');
+        window.location.hash = 'tabnav';
+        return false;
+      }
+      // otherwise, we need to let the browser follow the link:
+      return true;
+    }
+    $(this).tab('show');
+    if ($top.find('.' + tabid + '-tab').length > 0) {
+      $top.find('.' + tabid + '-tab').addClass('active');
+      if ($top.find('#' + tabid ).length) {
+        $top.find('#' + tabid ).parent().focus();
+      }
+      if ($(this).parent().hasClass('initiallyActive')) {
+        removeHashFromLocation();
+      } else {
+        window.location.hash = tabid;
+      }
+      return false;
+    } else {
+      var newTab = getNewRecordTab(tabid).addClass('active');
+      $top.find('.tab-content').append(newTab);
+      if ($top.find('#' + tabid ).length) {
+        $top.find('#' + tabid ).parent().focus();
+      }
+      return ajaxLoadTab(newTab, tabid, !$(this).parent().hasClass('initiallyActive'));
+    }
+  });
+
+  $('[data-background]').each(function setupBackgroundTabs(index, el) {
+    backgroundLoadTab(el.className);
+  });
+
+  registerTabEvents();
+  applyRecordTabHash();
+}
diff --git a/themes/finc-accessibility/js/vendor/bootstrap-accessibility-de.min.js b/themes/finc-accessibility/js/vendor/bootstrap-accessibility-de.min.js
index 43f5fe0175e2f59b7456f6ae7d5439be1dc7a39e..9462f550c7f0d71ac6de52ed7987fe5831e5d3fe 100644
--- a/themes/finc-accessibility/js/vendor/bootstrap-accessibility-de.min.js
+++ b/themes/finc-accessibility/js/vendor/bootstrap-accessibility-de.min.js
@@ -310,4 +310,26 @@
             k = e.which || e.keyCode;
         /(37|38|39|40)/.test(k) && (index = $tabs.index($tabs.filter(".active")), (37 == k || 38 == k) && (index--, selectTab(index)), (39 == k || 40 == k) && (index++, selectTab(index)), e.preventDefault(), e.stopPropagation())
     }, $(document).on("keydown.carousel.data-api", "li[role=tab]", $.fn.carousel.Constructor.prototype.keydown)
-}(jQuery);
\ No newline at end of file
+}(jQuery);
+
+$(document).on('keydown', '.dropdown-abort', function(e) {
+    if(e.which == 13) {
+        let toggle = $(this).parent().parent().parent().find('.dropdown-toggle');
+        if(toggle.not(this).length){
+            toggle.focus();
+        }
+    }
+});
+$(document).on('keyup', '.dropdown-abort', function(e) {
+    if(e.which == 13) {
+        let toggle = $(this).parent().parent().parent().find('.dropdown-toggle');
+        if(toggle.not(this).length){
+            toggle.dropdown("toggle");
+        }
+    }
+});
+
+/* restore focus after closing of lightbox */
+$(document).on('click', '.bulkActionButtons input', function(e) {
+    VuFind.lightbox.setOrigin(e.target);
+});
\ No newline at end of file
diff --git a/themes/finc-accessibility/js/vendor/bootstrap-accessibility-en.min.js b/themes/finc-accessibility/js/vendor/bootstrap-accessibility-en.min.js
index 630f112aed7e6a0149687a95215c623908bf0404..7717b77ecd987717df53a4ae4de3c44e81629e1d 100644
--- a/themes/finc-accessibility/js/vendor/bootstrap-accessibility-en.min.js
+++ b/themes/finc-accessibility/js/vendor/bootstrap-accessibility-en.min.js
@@ -3,7 +3,6 @@
 * Copyright (c) 2020 PayPal Accessibility Team; Licensed BSD */
 !function ($) {
     "use strict";
-    console.log('en');
     var uniqueId = function (prefix) {
         return (prefix || "ui-id") + "-" + Math.floor(1e3 * Math.random() + 1)
     }, focusable = function (element, isTabIndexNotNaN) {
@@ -311,4 +310,26 @@
             k = e.which || e.keyCode;
         /(37|38|39|40)/.test(k) && (index = $tabs.index($tabs.filter(".active")), (37 == k || 38 == k) && (index--, selectTab(index)), (39 == k || 40 == k) && (index++, selectTab(index)), e.preventDefault(), e.stopPropagation())
     }, $(document).on("keydown.carousel.data-api", "li[role=tab]", $.fn.carousel.Constructor.prototype.keydown)
-}(jQuery);
\ No newline at end of file
+}(jQuery);
+
+$(document).on('keydown', '.dropdown-abort', function(e) {
+    if(e.which == 13) {
+        let toggle = $(this).parent().parent().parent().find('.dropdown-toggle');
+        if(toggle.not(this).length){
+            toggle.focus();
+        }
+    }
+});
+$(document).on('keyup', '.dropdown-abort', function(e) {
+    if(e.which == 13) {
+        let toggle = $(this).parent().parent().parent().find('.dropdown-toggle');
+        if(toggle.not(this).length){
+            toggle.dropdown("toggle");
+        }
+    }
+});
+
+/* restore focus after closing of lightbox */
+$(document).on('click', '.bulkActionButtons input', function(e) {
+    VuFind.lightbox.setOrigin(e.target);
+});
\ No newline at end of file
diff --git a/themes/finc-accessibility/scss/compiled.scss b/themes/finc-accessibility/scss/compiled.scss
index 766002b57789f053a07aea5a5099e79b2f515732..db481aca78be66dffc9e30ba18c9a77e01996dbd 100644
--- a/themes/finc-accessibility/scss/compiled.scss
+++ b/themes/finc-accessibility/scss/compiled.scss
@@ -54,4 +54,10 @@
 a.remove-filter {
   display: flex;
   width: 100%;
+}
+
+.record-tab.active{
+  .load-tab-content {
+    display: none;
+  }
 }
\ No newline at end of file
diff --git a/themes/finc-accessibility/templates/Recommend/SideFacets/cluster-list.phtml b/themes/finc-accessibility/templates/Recommend/SideFacets/cluster-list.phtml
index 293af05732827251527ee22b281cc69fe25b3cae..1b1f8adcbba51d11ecdae3e1785993b1e8cfff98 100644
--- a/themes/finc-accessibility/templates/Recommend/SideFacets/cluster-list.phtml
+++ b/themes/finc-accessibility/templates/Recommend/SideFacets/cluster-list.phtml
@@ -30,7 +30,7 @@
   ]) ?>
 <?php endforeach; ?>
 <?php if (empty($this->cluster['list'])): ?>
-  <div class="facet"><?=$this->transEsc('facet_list_empty')?></div>
+  <span class="facet"><?=$this->transEsc('facet_list_empty')?></span>
 <?php endif; ?>
 
 <?php /* LESS and SEE MORE links */ ?>
diff --git a/themes/finc-accessibility/templates/Recommend/SideFacets/filter-list.phtml b/themes/finc-accessibility/templates/Recommend/SideFacets/filter-list.phtml
index 3957f6ba12e6ac722e65ea77266a15df592e7e73..3d2c763fce3e185c1e9f000fd9d06f4856a12c75 100644
--- a/themes/finc-accessibility/templates/Recommend/SideFacets/filter-list.phtml
+++ b/themes/finc-accessibility/templates/Recommend/SideFacets/filter-list.phtml
@@ -1,7 +1,7 @@
 <!-- finc-accessibility - Recommend - SideFacets - filter-list.phtml -->
 <?php /* #18509 copied from bootstrap for adding language tags to displayText */ ?>
 <div class="facet-group active-filters">
-  <div class="title"><?=$this->transEsc('Remove Filters')?> <span class="sr-only"><?=$this->transEsc('facet_deselect_hint') ?></div>
+  <div class="title"><?=$this->transEsc('Remove Filters')?> <span class="sr-only"><?=$this->transEsc('facet_deselect_hint') ?></span></div>
   <ul>
   <?php foreach ($filterList as $field => $filters): ?>
     <?php foreach ($filters as $i => $filter): ?>
diff --git a/themes/finc/js/cart-finc.js b/themes/finc/js/cart-finc.js
deleted file mode 100644
index 0fbaf1015f44cd429d87a2f1db9a0f5745c5c320..0000000000000000000000000000000000000000
--- a/themes/finc/js/cart-finc.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* #18034 - inform screen reader about changes, eventually intregrate by PR into bootstrap cart.js - RL */
-$(document).ready(function() {
-  var cart = document.getElementById("cartSummary");
-  if (cart != null) {
-    cart.setAttribute("aria-live", "polite");
-    cart.setAttribute("aria-atomic", "true");
-  }
-});
diff --git a/themes/finc/js/lightbox.js b/themes/finc/js/lightbox.js
index 4d183e226b88d770ccea6bb32f1779abf431f7cd..8cdfbe87fe9d0cec2d198dd47dc4231c84df65ca 100644
--- a/themes/finc/js/lightbox.js
+++ b/themes/finc/js/lightbox.js
@@ -114,6 +114,16 @@ VuFind.register('lightbox', function Lightbox() {
     $('#modal').find('.checkbox-select-item').change(function lbSelectAllDisable() {
       $(this).closest('.modal-body').find('.checkbox-select-all').prop('checked', false);
     });
+
+    // #19695 accessibility: set id for aria-label
+    if (_modalBody.find('h1').length) {
+      _modalBody.find('h1:first').attr('id', 'modal-title');
+      $('#modal').attr('aria-labelledby', 'modal-title');
+    } else if (_modalBody.find('h2').length) {
+      _modalBody.find('h2:first').attr('id', 'modal-title');
+      $('#modal').attr('aria-labelledby', 'modal-title');
+    }
+
     // Recaptcha
     recaptchaOnLoad();
   }
@@ -426,6 +436,9 @@ VuFind.register('lightbox', function Lightbox() {
       }
     }
   }
+  function setOrigin(origin) {
+    _origin = origin;
+  }
   function onKeydown(e) {
     if (event.keyCode === 27) { // esc
       close();
@@ -483,7 +496,6 @@ VuFind.register('lightbox', function Lightbox() {
       });
     });
   }
-
   function reset() {
     _html(VuFind.translate('loading') + '...');
     _originalUrl = false;
@@ -540,6 +552,7 @@ VuFind.register('lightbox', function Lightbox() {
     render: render,
     // Reset
     reset: reset,
+    setOrigin: setOrigin,
     // Init
     init: init
   };
diff --git a/themes/finc/templates/Auth/AbstractBase/resetpassword.phtml b/themes/finc/templates/Auth/AbstractBase/resetpassword.phtml
index 379fd2fbdd2e9e13bd500a6dce199b62698a619d..ed63456d5f7021511cfd29ab0f268c7175593362 100644
--- a/themes/finc/templates/Auth/AbstractBase/resetpassword.phtml
+++ b/themes/finc/templates/Auth/AbstractBase/resetpassword.phtml
@@ -2,7 +2,7 @@
 <?php /* compare with BS login templates in Auth during updates */ ?>
 <?php
 // Set page title.
-$this->headTitle($this->translate('Reset Password') . ' | ' . $this->translate("LibraryName"));
+$this->headTitle($this->translate('Reset Password'));
 ?>
 <h1><?=$this->transEsc('Reset Password')?></h1>
 <form method="post" name="resetPasswordForm" action="<?=$this->url('myresearch-resetpassword')?>">
diff --git a/themes/finc/templates/Recommend/EbscoResults.phtml b/themes/finc/templates/Recommend/EbscoResults.phtml
index 2801644566d2ab48ed2af231dea8c7941f3daf61..253b18944ffacebbbb4811444c50dd5308a4b9f8 100644
--- a/themes/finc/templates/Recommend/EbscoResults.phtml
+++ b/themes/finc/templates/Recommend/EbscoResults.phtml
@@ -13,15 +13,17 @@ if (is_array($data['results']) && count($data['results']) > 0): ?>
         <span class="badge">
                 <?= $this->escapeHtml($result['hits']) ?>
             </span>
-            <a href="<?= $this->escapeHtmlAttr($result['url']) ?>" target="_blank">
-                <?= $this->escapeHtml($this->truncate($this->transEsc('Ebsco::'.$result['database']), 90)) ?>
-            </a>
+        <?= $this->externalLink(
+              $this->escapeHtmlAttr($result['url']),
+              $this->truncate($this->translate('Ebsco::'.$result['database']), 90)
+            ) ?>
       </div>
         <?php endforeach; ?>
-        <a class="facet narrow-toggle" href="<?=$this->escapeHtmlAttr($data['hits_total_url'])?>" target="_blank" rel="nofollow">
-          <?=$this->transEsc('more')?>&nbsp;...
-            </a>
-
+      <?= $this->externalLink(
+            $data['hits_total_url'],
+            $this->translate('more'),
+            ['class' => 'facet narrow-toggle']
+          ) ?>
       </div>
   </div>
 <?php endif; ?>
diff --git a/themes/finc/templates/Recommend/SideFacets.phtml b/themes/finc/templates/Recommend/SideFacets.phtml
index 8c7fff5acfa902339f2eaf28c3f5376178d00a96..3e524b476825eedf817ba8fa2c8b110c3aadf186 100644
--- a/themes/finc/templates/Recommend/SideFacets.phtml
+++ b/themes/finc/templates/Recommend/SideFacets.phtml
@@ -55,9 +55,9 @@ if ($hierarchicalFacets) {
 <?php if (!empty($sideFacetSet) && $results->getResultTotal() > 0): ?>
   <?php foreach ($sideFacetSet as $title => $cluster): ?>
     <div class="facet-group" id="side-panel-<?=$this->escapeHtmlAttr($title)?>">
-      <button <?php if(in_array($title, $collapsedFacets)): ?>class="title collapsed" aria-expanded="false"<?php else: ?>class="title" aria-expanded="true"<?php endif ?> data-toggle="collapse" href="#side-collapse-<?=$this->escapeHtmlAttr($title) ?>" >
+      <a <?php if(in_array($title, $collapsedFacets)): ?>class="title collapsed" aria-expanded="false"<?php else: ?>class="title" aria-expanded="true"<?php endif ?> data-toggle="collapse" href="#side-collapse-<?=$this->escapeHtmlAttr($title) ?>" >
         <?=$this->transEsc($cluster['label'])?> <span class="sr-only"><?=$this->transEsc('facet_select_hint') ?></span>
-      </button>
+      </a>
       <ul id="side-collapse-<?=$this->escapeHtmlAttr($title)?>" class="collapse<?php if (!in_array($title, $collapsedFacets)): ?> in<?php endif ?>">
         <?=$this->context($this)->renderInContext(
           'Recommend/SideFacets/facet.phtml',
diff --git a/themes/finc/templates/Recommend/SideFacets/range-slider.phtml b/themes/finc/templates/Recommend/SideFacets/range-slider.phtml
index 430be23580f50ce2ba0fccf96c7bb22bdf494db6..31a94bfef9261342ea71876881dca013bad5985f 100644
--- a/themes/finc/templates/Recommend/SideFacets/range-slider.phtml
+++ b/themes/finc/templates/Recommend/SideFacets/range-slider.phtml
@@ -4,7 +4,7 @@
      * slider-container element
      */
 ?>
-<div class="facet">
+<li class="facet">
   <?php if (!empty($this->facet['values'][0])): ?>
     <?php $this->sideFacet()->setAppliedFacet($this->transEsc('Skip to facet', ['%%filter_name%%' => $this->transEsc('Year of Publication')]), $this->escapeHtmlAttr($this->title) . 'from')?>
   <?php elseif (!empty($this->facet['values'][1])): ?>
@@ -34,7 +34,6 @@
     <?php endif; ?>
     <input class="btn btn-default" type="submit" value="<?=$this->transEsc('Set')?>"/>
   </form>
-</div>
 <?php if ($this->facet['type'] == 'date'): ?>
   <?php $this->headScript()->appendFile('vendor/bootstrap-slider.min.js'); ?>
   <?php $this->headLink()->appendStylesheet('vendor/bootstrap-slider.min.css'); ?>
@@ -83,4 +82,5 @@ JS;
   ?>
   <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET'); ?>
 <?php endif; ?>
+</li>
 <!-- finc - recommend - sidefacets - rangeslider - END -->
diff --git a/themes/finc/templates/RecordDriver/DefaultRecord/link-isn.phtml b/themes/finc/templates/RecordDriver/DefaultRecord/link-isn.phtml
index 77bed61f58f3b6a7a2cfc3113ec6a2fbb194be64..30507b95f9bba7a18fa8cdd5d980856dfd166994 100644
--- a/themes/finc/templates/RecordDriver/DefaultRecord/link-isn.phtml
+++ b/themes/finc/templates/RecordDriver/DefaultRecord/link-isn.phtml
@@ -1,9 +1,9 @@
 <?php
 /* use advanced search if we have multiple issns */
 if (is_array($this->lookfor) && count($this->lookfor) > 1) {
-  $query = '?join=AND&amp;bool0[]=OR';
+  $query = '?join=AND&amp;bool0%5B%5D=OR';
   foreach ($this->lookfor as $issn) {
-    $query .= '&amp;lookfor0[]=' . urlencode($issn) . '&amp;type0[]=ISN';
+    $query .= '&amp;lookfor0%5B%5D=' . urlencode($issn) . '&amp;type0%5B%5D=ISN';
   }
 } elseif (count($this->lookfor) == 1) {
   $query = '?lookfor=%22' . urlencode($this->lookfor[0]) . '%22&amp;type=ISN';
diff --git a/themes/finc/templates/RecordDriver/DefaultRecord/list-entry.phtml b/themes/finc/templates/RecordDriver/DefaultRecord/list-entry.phtml
index 377e7ddf6a32d81a0bc92b694099ffb1713e1234..39a333fa0798a25e2e271410e11ff8cfedbbd218 100644
--- a/themes/finc/templates/RecordDriver/DefaultRecord/list-entry.phtml
+++ b/themes/finc/templates/RecordDriver/DefaultRecord/list-entry.phtml
@@ -181,8 +181,13 @@ $thumbnailAlignment = $this->record($this->driver)->getThumbnailAlignment('list'
             }
             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>
+                  <?= $this->externalLink(
+                        $this->escapeHtmlAttr($this->proxyUrl($current['url'])),
+                        '<i class="fa fa-external-link" aria-hidden="true"></i>'
+                          . ($current['url'] == $current['desc'] ? $this->transEsc('Get full text') : $this->escapeHtml($current['desc'])),
+                        ['class' => 'fulltext'],
+                        true
+                  ) ?>
               <?php endforeach; ?>
             <?php endif; ?>
           <?php endif; ?>
@@ -224,7 +229,13 @@ $thumbnailAlignment = $this->record($this->driver)->getThumbnailAlignment('list'
             <ul class="dropdown-menu" role="menu" aria-labelledby="<?= $dLabel ?>">
               <li>
                 <?php /* #17711 give user feedback and dont reload page after deleting */ ?>
-                <a href="javascript:document.getElementById('<?=$dLabel?>').focus();" title="<?= $this->transEsc('confirm_delete_brief') ?>" onClick="$.post(
+                <a href="javascript:document.getElementById('<?=$dLabel?>').focus();" title="<?= $this->transEsc('confirm_delete_brief') ?>" onClick="
+                  let next = $(this).closest('.result.ajaxItem').next('.result.ajaxItem').find('.del-button');
+                  if (next.length === 0) {
+                    next = $('[id^=delete_list_items_]').first();
+                  }
+                  VuFind.lightbox.setOrigin(next);
+                  $.post(
                   '<?= $deleteUrl ?>',
                   {
                     'delete':'<?= $this->escapeJs($id) ?>',
diff --git a/themes/finc/templates/RecordDriver/DefaultRecord/result-list.phtml b/themes/finc/templates/RecordDriver/DefaultRecord/result-list.phtml
index 2d1425fa86e9d4d2a6bb2662c27d0722ce36cc4d..b6284f06c352176e5578d77c6f9921858ea8f2f3 100644
--- a/themes/finc/templates/RecordDriver/DefaultRecord/result-list.phtml
+++ b/themes/finc/templates/RecordDriver/DefaultRecord/result-list.phtml
@@ -94,30 +94,6 @@ if ($cover):
         <?php endif; ?>
       <?php endif; ?>
 
-      <?php
-/* Display information on duplicate records if available */
-      if ($dedupData = $this->driver->getDedupData()): ?>
-        <div class="dedupInformation">
-          <?php
-$i = 0;
-          foreach ($dedupData as $source => $current) {
-          if (++$i == 1) {
-              ?><span class="currentSource"><a href="<?=$this->recordLink()->getUrl($this->driver)?>"><?=$this->transEsc("source_$source", [], $source)?></a></span><?php
-          } else {
-          if ($i == 2) {
-          ?> <span class="otherSources">(<?=$this->transEsc('Other Sources')?>: <?php
-            } else {
-              ?>, <?php
-            }
-              ?><a href="<?=$this->recordLink()->getUrl($current['id'])?>"><?=$this->transEsc("source_$source", [], $source)?></a><?php
-            }
-            }
-            if ($i > 1) {
-            ?>)</span><?php
-        } ?>
-        </div>
-      <?php endif; ?>
-
       <div class="callnumAndLocation ajax-availability hidden">
         <?php if ($this->driver->supportsAjaxStatus()): ?>
           <strong class="hideIfDetailed"><?=$this->transEsc('Call Number')?>:</strong>
@@ -160,10 +136,13 @@ $i = 0;
         <?php if (!is_array($urls)) $urls = [];
         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>
+              <?= $this->externalLink(
+                    $this->escapeHtmlAttr($this->proxyUrl($current['url'])),
+                    '<i class="fa fa-external-link" aria-hidden="true"></i>'
+                      . ($current['url'] == $current['desc'] ? $this->transEsc('Get full text') : $this->escapeHtml($current['desc'])),
+                    ['class' => 'fulltext'],
+                    true
+              ) ?>
             <br/>
           <?php endforeach; ?>
         <?php endif; ?>
diff --git a/themes/finc/templates/RecordDriver/SolrAI/result-list.phtml b/themes/finc/templates/RecordDriver/SolrAI/result-list.phtml
index e21b80019c88987fa4b300e1455720c988b77584..5ca3d5c4e020227aaf00fd7f0b220944ae389778 100644
--- a/themes/finc/templates/RecordDriver/SolrAI/result-list.phtml
+++ b/themes/finc/templates/RecordDriver/SolrAI/result-list.phtml
@@ -4,6 +4,7 @@ $coverDetails = $this->record($this->driver)->getCoverDetails('result-list', 'me
 $cover = $coverDetails['html'];
 $thumbnail = false;
 $thumbnailAlignment = $this->record($this->driver)->getThumbnailAlignment('result');
+$describedById = $driver->getSourceIdentifier() . '|' . $driver->getUniqueId();
 if ($cover):
   ob_start(); ?>
   <div class="media-<?=$thumbnailAlignment?> <?=$this->escapeHtmlAttr($coverDetails['size'])?>" aria-hidden="true">
@@ -31,7 +32,7 @@ if ($cover):
   <div class="media-body">
     <div class="result-body">
       <div>
-        <a href="<?=$this->recordLink()->getUrl($this->driver)?>" class="title getFull" data-view="<?=$this->params->getOptions()->getListViewOption()?>" lang="">
+        <a id="<?=$describedById?>" href="<?=$this->recordLink()->getUrl($this->driver)?>" class="title getFull" data-view="<?=$this->params->getOptions()->getListViewOption()?>" lang="">
           <?=$this->record($this->driver)->getTitleHtml()?>
         </a>
       </div>
@@ -104,30 +105,6 @@ if ($cover):
         <?php endif; ?>
       <?php endif; ?>
 
-      <?php
-      /* Display information on duplicate records if available */
-      if ($dedupData = $this->driver->getDedupData()): ?>
-        <div class="dedupInformation">
-          <?php
-          $i = 0;
-          foreach ($dedupData as $source => $current) {
-          if (++$i == 1) {
-              ?><span class="currentSource"><a href="<?=$this->recordLink()->getUrl($this->driver)?>"><?=$this->transEsc("source_$source", [], $source)?></a></span><?php
-          } else {
-          if ($i == 2) {
-          ?> <span class="otherSources">(<?=$this->transEsc('Other Sources')?>: <?php
-            } else {
-              ?>, <?php
-            }
-              ?><a href="<?=$this->recordLink()->getUrl($current['id'])?>"><?=$this->transEsc("source_$source", [], $source)?></a><?php
-            }
-            }
-            if ($i > 1) {
-            ?>)</span><?php
-        } ?>
-        </div>
-      <?php endif; ?>
-
       <div class="callnumAndLocation ajax-availability hidden">
         <?php if ($this->driver->supportsAjaxStatus()): ?>
           <strong class="hideIfDetailed"><?=$this->transEsc('Call Number')?>:</strong>
@@ -170,10 +147,13 @@ if ($cover):
         <?php if (!is_array($urls)) $urls = [];
         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>
+              <?= $this->externalLink(
+                    $this->escapeHtmlAttr($this->proxyUrl($current['url'])),
+                    '<i class="fa fa-external-link" aria-hidden="true"></i>'
+                      . ($current['url'] == $current['desc'] ? $this->transEsc('Get full text') : $this->escapeHtml($current['desc'])),
+                    ['class' => 'fulltext'],
+                    true
+              ) ?>
             <br/>
           <?php endforeach; ?>
         <?php endif; ?>
diff --git a/themes/finc/templates/RecordTab/acquisitionpda.phtml b/themes/finc/templates/RecordTab/acquisitionpda.phtml
index ed7a386cde1c1ae3812954f441cc60ef35cb81b2..e069017a899ee0ec5596fda3bb820e5e9df2dbb3 100644
--- a/themes/finc/templates/RecordTab/acquisitionpda.phtml
+++ b/themes/finc/templates/RecordTab/acquisitionpda.phtml
@@ -4,7 +4,6 @@
 $this->headTitle(
   $this->translate('PDA::Acquisition') . ': ' .
   $this->driver->getBreadcrumb()
-  . ' | ' . $this->translate("LibraryName")
 );
 // Get some variables
 $id = $this->driver->getUniqueId();
@@ -16,9 +15,13 @@ $controllerClass = 'controller:SolrMarcFincPDA';
 <p class="alert alert-info"><?=$this->transEsc('PDA::pda_restriction_text')?></p>
 <div class="btn-group">
   <?php /* Leave title in here - it is used for the tooltip! - CK */ ?>
-  <a class="btn btn-primary" data-toggle="tooltip" title="<?=$this->transEsc('PDA::pda_open_new_window')?>" href="<?=$this->interlibraryloan()->getSwbLink($this->driver)?>" target="_blank">
-    <?=$this->transEsc('PDA::pda_tab_interlibrary_button')?>
-  </a>
+  <?= $this->externalLink(
+        $this->interlibraryloan()->getSwbLink($this->driver),
+        $this->translate('PDA::pda_tab_interlibrary_button'),
+        [ 'class' => 'btn btn-primary',
+          'data-toggle' => 'tooltip',
+          'title' => $this->translate('PDA::pda_open_new_window')]
+      ) ?>
   <a class="btn btn-primary pda-button <?=$controllerClass?>" data-lightbox href="<?=$this->url('record-pda', array('id' => $id))?>" rel="nofollow">
     <?=$this->transEsc('PDA::pda_tab_order_button')?>
   </a>
diff --git a/themes/finc/templates/RecordTab/description.phtml b/themes/finc/templates/RecordTab/description.phtml
index 9978227ede0bfccc83dc8c95544d3e674b78b736..0e39ff89ba9bad658a112800f42272aa2d5adde1 100644
--- a/themes/finc/templates/RecordTab/description.phtml
+++ b/themes/finc/templates/RecordTab/description.phtml
@@ -1,7 +1,7 @@
 <!-- finc: recordtab - description -->
 <?php
 // Set page title.
-$this->headTitle($this->translate('Description') . ': ' . $this->driver->getBreadcrumb() . ' | ' . $this->translate("LibraryName"));
+$this->headTitle($this->translate('Description') . ': ' . $this->driver->getBreadcrumb());
 
 $formatter = $this->recordDataFormatter();
 $mainFields = $formatter->getData($driver, $formatter->getDefaults('description'));
diff --git a/themes/finc/templates/RecordTab/descriptionlido.phtml b/themes/finc/templates/RecordTab/descriptionlido.phtml
index 221d9845697b85d4f1958a4f7e8acaca99247eff..939b171f95eefcc3f9f00317a898dafd25cf85b9 100644
--- a/themes/finc/templates/RecordTab/descriptionlido.phtml
+++ b/themes/finc/templates/RecordTab/descriptionlido.phtml
@@ -1,7 +1,7 @@
 <!-- finc: recordtab - descriptionlido -->
 <?php
 // Set page title.
-$this->headTitle($this->translate('Description') . ': ' . $this->driver->getBreadcrumb() . ' | ' . $this->translate("LibraryName"));
+$this->headTitle($this->translate('Description') . ': ' . $this->driver->getBreadcrumb());
 
 $formatter = $this->recordDataFormatter();
 $mainFields = $formatter->getData($driver, $formatter->getDefaults('description-lido'));
diff --git a/themes/finc/templates/RecordTab/hierarchytree.phtml b/themes/finc/templates/RecordTab/hierarchytree.phtml
index dfc402d78303083e7f2f1c81097c7fee6c9dec90..0c5f7f1879a63203bbb26f691421c32928f8dad5 100644
--- a/themes/finc/templates/RecordTab/hierarchytree.phtml
+++ b/themes/finc/templates/RecordTab/hierarchytree.phtml
@@ -1,7 +1,7 @@
 <!-- finc: record-tab - hierarchytree -->
 <?php
   // Set page title.
-  $this->headTitle($this->translate('hierarchy_tree') . ': ' . $this->driver->getBreadcrumb() . ' | ' . $this->translate("LibraryName"));
+  $this->headTitle($this->translate('hierarchy_tree') . ': ' . $this->driver->getBreadcrumb());
   $hierarchyTreeList = $this->tab->getTreeList();
   $activeTree = $this->tab->getActiveTree();
 
diff --git a/themes/finc/templates/RecordTab/holdingsils.phtml b/themes/finc/templates/RecordTab/holdingsils.phtml
index b78c5f34b091958a8cc8ef0a7b03cfe56abd3173..ed99f581cf84e3bd1f396fba374371e32315551f 100644
--- a/themes/finc/templates/RecordTab/holdingsils.phtml
+++ b/themes/finc/templates/RecordTab/holdingsils.phtml
@@ -26,7 +26,7 @@
     }
   }
   // Set page title.
-  $this->headTitle($this->translate('Holdings') . ': ' . $this->driver->getBreadcrumb() . ' | ' . $this->translate("LibraryName"));
+  $this->headTitle($this->translate('Holdings') . ': ' . $this->driver->getBreadcrumb());
 ?>
 
 <?php /* finc-specific: nxt line - #7841@56988450 - CK */ ?>
@@ -65,7 +65,7 @@ if (!empty($holdingTitleHold)): ?>
   <h2><?=$this->transEsc("Internet")?></h2>
   <?php if (!empty($urls)): ?>
     <?php foreach ($urls as $current): ?>
-      <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>"><?=$this->escapeHtml($current['desc'])?></a><br/>
+      <?= $this->externalLink($this->escapeHtmlAttr($this->proxyUrl($current['url'])), $current['desc']) ?><br/>
     <?php endforeach; ?>
   <?php endif; ?>
   <?php /* finc-specific snippet - #9274 - replaces if ($openUrlActive): ... - CK */ ?>
@@ -75,7 +75,7 @@ if (!empty($holdingTitleHold)): ?>
       if (!empty($fallbackUrls)): ?>
         <span id="urlsHideable" style="display: none">
           <?php foreach ($fallbackUrls as $current): ?>
-            <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>" target="_blank"><?=$this->escapeHtml($current['desc'] ?? $current['url'])?></a><br/>
+            <?= $this->externalLink($this->escapeHtmlAttr($this->proxyUrl($current['url'])), $current['desc'] ?? $current['url']) ?><br/>
           <?php endforeach; ?>
         </span>
       <?php endif; ?>
@@ -93,7 +93,7 @@ if (!empty($holdingTitleHold)): ?>
   <h2>
     <?php $locationText = $this->transEsc('location_' . $holding['location'], [], $holding['location']); ?>
     <?php if (isset($holding['locationhref']) && $holding['locationhref']): ?>
-      <a href="<?=$holding['locationhref']?>" target="_blank"><?=$locationText?></a>
+      <?= $this->externalLink($holding['locationhref'], $locationText) ?>
     <?php else: ?>
       <?=$locationText?>
     <?php endif; ?>
diff --git a/themes/finc/templates/RecordTab/serviceebl.phtml b/themes/finc/templates/RecordTab/serviceebl.phtml
index 5ef8e11a1e920bb79aafc7a5a75c536fecd8bd66..edb3e1171bcbc3daeae2214b6fe827fb5b0105e2 100644
--- a/themes/finc/templates/RecordTab/serviceebl.phtml
+++ b/themes/finc/templates/RecordTab/serviceebl.phtml
@@ -1,6 +1,6 @@
 <?php
 // Set page title.
-$this->headTitle($this->translate('EBL') . ': ' . $this->driver->getBreadcrumb() . ' | ' . $this->translate("LibraryName"));
+$this->headTitle($this->translate('EBL') . ': ' . $this->driver->getBreadcrumb());
 
 // Get EBL url
 $link = $this->tab->getLinkEBL();
diff --git a/themes/finc/templates/RecordTab/staffviewai.phtml b/themes/finc/templates/RecordTab/staffviewai.phtml
index 62a5748a6bf89b2aa11b6070c638923dd7f5ed85..d38b62fdc2e8e2c10139f41c3ef7feafe24b00ea 100644
--- a/themes/finc/templates/RecordTab/staffviewai.phtml
+++ b/themes/finc/templates/RecordTab/staffviewai.phtml
@@ -1,7 +1,7 @@
 <!-- finc: recordtab - staffviewai -->
 <?php
 // Set page title.
-$this->headTitle($this->translate('Staff View') . ': ' . $this->driver->getBreadcrumb() . ' | ' . $this->translate("LibraryName"));
+$this->headTitle($this->translate('Staff View') . ': ' . $this->driver->getBreadcrumb());
 ?>
 <?php /* include responsive data table - CK */ ?>
 <table class="citation table table-striped table-resp-data">
diff --git a/themes/finc/templates/RecordTab/staffviewarray.phtml b/themes/finc/templates/RecordTab/staffviewarray.phtml
index 73fac7db40f4c14da918d763e6626f7e32bef0b8..c046901cfae8ac587a7212b2c298778d27e6bf99 100644
--- a/themes/finc/templates/RecordTab/staffviewarray.phtml
+++ b/themes/finc/templates/RecordTab/staffviewarray.phtml
@@ -1,7 +1,7 @@
 <!-- finc: recordtab - staffviewarray -->
 <?php
     // Set page title.
-    $this->headTitle($this->translate('Staff View') . ': ' . $this->driver->getBreadcrumb() . ' | ' . $this->translate("LibraryName"));
+    $this->headTitle($this->translate('Staff View') . ': ' . $this->driver->getBreadcrumb());
 ?>
 <?php /* include responsive data table - CK */ ?>
 <table class="citation table table-striped table-resp-data">
diff --git a/themes/finc/templates/RecordTab/staffviewmarc.phtml b/themes/finc/templates/RecordTab/staffviewmarc.phtml
index 19f2aa691b4c7e449cbb5031ff7b35fa277773a6..ebd800bbd7d5e6d2d6ed8fbd27770e893a99748a 100644
--- a/themes/finc/templates/RecordTab/staffviewmarc.phtml
+++ b/themes/finc/templates/RecordTab/staffviewmarc.phtml
@@ -1,7 +1,7 @@
 <!-- finc: recordtab - staffviewmarc -->
 <?php
 // Set page title.
-$this->headTitle($this->translate('Staff View') . ': ' . $this->driver->getBreadcrumb() . ' | ' . $this->translate("LibraryName"));
+$this->headTitle($this->translate('Staff View') . ': ' . $this->driver->getBreadcrumb());
 ?>
 <?=\VuFind\XSLT\Processor::process('record-marc.xsl', $this->driver->getXML('marc21'))?>
 <?php /* the following introduced in 9934*/ ?>
diff --git a/themes/finc/templates/RecordTab/topics.phtml b/themes/finc/templates/RecordTab/topics.phtml
index eac80af00c6e507c3d5e595f6dea59ab42a37f47..40d1f149f839a6b4f7ab6fa43499d9ce7711dd26 100644
--- a/themes/finc/templates/RecordTab/topics.phtml
+++ b/themes/finc/templates/RecordTab/topics.phtml
@@ -1,7 +1,7 @@
 <!-- finc: recordtab - topics -->
 <?php
 // Set page title.
-$this->headTitle($this->translate('Topics') . ': ' . $this->driver->getBreadcrumb() . ' | ' . $this->translate("LibraryName"));
+$this->headTitle($this->translate('Topics') . ': ' . $this->driver->getBreadcrumb());
 
 ?>
 <table class="table table-striped table-resp-data">
diff --git a/themes/finc/templates/admin/home.phtml b/themes/finc/templates/admin/home.phtml
index 57ba0f0328634cd6ce63370cb6a12c8c0308ebda..5e8aa62a4df836ff1d9e1273b9cc352803b0394d 100644
--- a/themes/finc/templates/admin/home.phtml
+++ b/themes/finc/templates/admin/home.phtml
@@ -5,7 +5,7 @@
   */
 
   // Set page title.
-  $this->headTitle($this->translate('VuFind Administration - Home') . ' | ' . $this->translate("LibraryName"));
+  $this->headTitle($this->translate('VuFind Administration - Home'));
 
   // Set up map of core name => label
   $coreLabels = [
diff --git a/themes/finc/templates/ajax/resolverLinks.phtml b/themes/finc/templates/ajax/resolverLinks.phtml
index d9b82875c17cd7e6184f08cc5721db62b1dcad85..4b2e0a9ed2b4ee8050d643752941eb0adb76f175 100644
--- a/themes/finc/templates/ajax/resolverLinks.phtml
+++ b/themes/finc/templates/ajax/resolverLinks.phtml
@@ -20,9 +20,21 @@
                 <span class="last"></span>
               </div>
               <?php /* finc-specific change #7986 - END */ ?>
-              <a href="<?=$this->escapeHtmlAttr($link['href'])?>" title="<?=isset($link['service_type'])?$this->escapeHtmlAttr($link['service_type']):''?>"<?=!empty($link['access'])?' class="access-'.$link['access'].'"':''?>><?=isset($link['title'])?$this->escapeHtml($link['title']):''?></a> <br />
+              <?= $this->externalLink(
+                    $this->escapeHtmlAttr($link['href']),
+                    $link['title'] ?? '',
+                    [
+                        'title' => $link['service_type'] ?? '',
+                        'class' => !empty($link['access']) ? 'access-' . $link['access'] : ''
+                    ]
+                  ) ?> <br />
               <?php /* finc-specific change #5334 - CK */ ?>
-              <small><?=isset($link['coverage'])?$this->escapeHtml($link['coverage']):''?><?=isset($link['coverageHref'])?' <a href="'.$link['coverageHref'].'" target="_blank">'.$this->translate('Readme').'</a>':''?></small>
+              <small>
+                <?= isset($link['coverage']) ? $this->escapeHtml($link['coverage']) : '' ?>
+                <?= isset($link['coverageHref'])
+                      ? $this->externalLink($link['coverageHref'], $this->translate('Readme'))
+                      : '' ?>
+              </small>
               <?php /* finc-specific change #5334 - END */ ?>
             <?php else: ?>
               <?=isset($link['title'])?$this->escapeHtml($link['title']):''?> <?=isset($link['coverage'])?$this->transEsc($link['coverage']):''?>
diff --git a/themes/finc/templates/ajax/status-full.phtml b/themes/finc/templates/ajax/status-full.phtml
index 303067afd3f54d49ba871af84d7028fc758dcb9f..f48411b6a7613839ee6b963ee2510646bc2053be 100644
--- a/themes/finc/templates/ajax/status-full.phtml
+++ b/themes/finc/templates/ajax/status-full.phtml
@@ -12,7 +12,7 @@
       <td data-title="<?= $this->transEsc('Location') ?>:" class="fullLocation">
         <?php $locationText = $this->transEsc('location_' . $item['location'], [], $item['location']); ?>
         <?php if (isset($item['locationhref']) && $item['locationhref']): ?>
-          <a href="<?=$item['locationhref']?>" target="_blank"><?=$locationText?></a>
+          <?= $this->externalLink($item['locationhref'], $locationText) ?>
         <?php else: ?>
           <?=$locationText?>
         <?php endif; ?>
diff --git a/themes/finc/templates/alphabrowse/home.phtml b/themes/finc/templates/alphabrowse/home.phtml
index ccd0a1caca6663b2abf1e2b3c28650f5361659b3..0e024ed7736b62ce650b2ecb94301eaa95c34525 100644
--- a/themes/finc/templates/alphabrowse/home.phtml
+++ b/themes/finc/templates/alphabrowse/home.phtml
@@ -1,6 +1,6 @@
 <!-- finc - templates - alphabrowse - home -->
 <?php
-  $this->headTitle($this->translate('Browse the Collection Alphabetically') . ' | ' . $this->translate("LibraryName"));
+  $this->headTitle($this->translate('Browse the Collection Alphabetically'));
   $this->layout()->breadcrumbs = '<a href="' . $this->url('alphabrowse-home') . '">' . $this->transEsc('Browse Alphabetically') . '</a>';
   $baseQuery = ['source' => $this->source, 'from' => $this->from];
 
diff --git a/themes/finc/templates/amsl/sources-list.phtml b/themes/finc/templates/amsl/sources-list.phtml
index 5946ef486e2eb1b9155d158144cf9845ed0c7bb8..8970d0d041d4de5d3bbc0838e7a59a97c667e406 100644
--- a/themes/finc/templates/amsl/sources-list.phtml
+++ b/themes/finc/templates/amsl/sources-list.phtml
@@ -8,7 +8,7 @@
 <!-- finc: amsl/sources-list - home -->
 <?php
 // Set up page title:
-$this->headTitle($this->translate('List of available Sources') . ' | ' . $this->translate("LibraryName"));
+$this->headTitle($this->translate('List of available Sources'));
 
 // Set up breadcrumbs:
 $this->layout()->breadcrumbs .= '</li> <li class="active">' . $this->transEsc('List of available Sources') . '</li>';
@@ -49,9 +49,11 @@ $this->layout()->breadcrumbs .= '</li> <li class="active">' . $this->transEsc('L
             <?php foreach ($source as $sub_label => $collection): ?>
               <li>
                 <?php if (!empty($collection['href'])): ?>
-                  <a title="<?=$this->transEsc("Search For")?> <?=$sub_label?>" href='<?=$collection["href"]?>' target="_blank">
-                    <?=$sub_label?>
-                  </a>
+                <?= $this->externalLink(
+                      $collection["href"],
+                      $sub_label,
+                      ['title' => "{$this->transEsc("Search For")} {$sub_label}"]
+                    ) ?>
                 <?php else: ?>
                   <div tabindex="0" aria-label="<?=$this->transEsc("Source Title")?>">
                       <?=$sub_label?>
@@ -77,8 +79,12 @@ $this->layout()->breadcrumbs .= '</li> <li class="active">' . $this->transEsc('L
       <span>
         <?=$this->transEsc('support_by_dfg');?>
       </span>
-      <a href='http://www.dfg.de' target='_blank'>
-        <img src='<?=$this->imageLink('dfg_logo_text.png')?>' alt='Deutsche Forschungsgemeinschaft, DFG'>
+      <?= $this->externalLink(
+            'http://www.dfg.de',
+            "<img src='{$this->imageLink('dfg_logo_text.png')}' alt='Deutsche Forschungsgemeinschaft, DFG'>",
+            [],
+            true
+          ) ?>
       </a>
     </div>
   </div>
diff --git a/themes/finc/templates/browse/home.phtml b/themes/finc/templates/browse/home.phtml
index bac20ae20af94ca87b00416f6e717201e4807567..d20402286c31d1e1cb1a62bc133202e76d32be3a 100644
--- a/themes/finc/templates/browse/home.phtml
+++ b/themes/finc/templates/browse/home.phtml
@@ -2,7 +2,7 @@
 <?php /* copied from bootstrap3 - added h1 for sr-only - #17596 - HR */?>
 
 <?php
-  $this->headTitle($this->translate('Browse the Catalog') . ' | ' . $this->translate("LibraryName"));
+  $this->headTitle($this->translate('Browse the Catalog'));
   $this->layout()->breadcrumbs = '<a href="' . $this->url('browse-home') . '">' . $this->transEsc('Browse') . '</a>';
 
   $BROWSE_BASE = $this->url('browse-' . strtolower($this->currentAction));
diff --git a/themes/finc/templates/cart/cart.phtml b/themes/finc/templates/cart/cart.phtml
index 53de8590ca3166083e4306543a0e650e8f76747d..7ac208d9e771e3d811ae9d85a734363d7bf9ab7f 100644
--- a/themes/finc/templates/cart/cart.phtml
+++ b/themes/finc/templates/cart/cart.phtml
@@ -1,7 +1,7 @@
 <!-- finc: cart - cart -->
 <?php
   // Set page title.
-  $this->headTitle($this->translate('Book Bag') . ' | ' . $this->translate("LibraryName"));
+  $this->headTitle($this->translate('Book Bag'));
 
   // Set up breadcrumbs:
   $this->layout()->breadcrumbs = '<li>' . $this->searchMemory()->getLastSearchLink($this->transEsc('Search'), '', '</li> ')
diff --git a/themes/finc/templates/cart/email.phtml b/themes/finc/templates/cart/email.phtml
index e4498df745d3b85842e6f3c979f61e920a4985c1..54d82cec86f881f049b263075dbd504ce3b1bec2 100644
--- a/themes/finc/templates/cart/email.phtml
+++ b/themes/finc/templates/cart/email.phtml
@@ -3,7 +3,7 @@
 
 <?php
   // Set page title.
-  $this->headTitle($this->translate('email_selected_favorites') . ' | ' . $this->translate("LibraryName"));
+  $this->headTitle($this->translate('email_selected_favorites'));
 
   // Set up breadcrumbs:
   $this->layout()->breadcrumbs = '<li>' . $this->searchMemory()->getLastSearchLink($this->transEsc('Search'), '', '</li> ')
diff --git a/themes/finc/templates/cart/save.phtml b/themes/finc/templates/cart/save.phtml
index dd40f5249f412408ae436a86365ffb3833155def..92183fe7ae68d337ba0517f85ad01e5049ff4638 100644
--- a/themes/finc/templates/cart/save.phtml
+++ b/themes/finc/templates/cart/save.phtml
@@ -3,7 +3,7 @@
 
 <?php
     // Set page title.
-    $this->headTitle($this->translate('bookbag_save_selected') . ' | ' . $this->translate("LibraryName"));
+    $this->headTitle($this->translate('bookbag_save_selected'));
 
     // Set up breadcrumbs:
     $this->layout()->breadcrumbs = '<li>' . $this->searchMemory()->getLastSearchLink($this->transEsc('Search'), '', '</li> ') .
diff --git a/themes/finc/templates/channels/home.phtml b/themes/finc/templates/channels/home.phtml
index 5220503f93636b5e0b7bb097ad31ca3fe70d1923..5bf072cc53b5b52ba409d30d005d485f67a0ac57 100644
--- a/themes/finc/templates/channels/home.phtml
+++ b/themes/finc/templates/channels/home.phtml
@@ -3,7 +3,7 @@
 
 <?php
     // Set up page title:
-    $this->headTitle($this->translate('Channels') . ' | ' . $this->translate("LibraryName"));
+    $this->headTitle($this->translate('Channels'));
 
     // Set up breadcrumbs:
     $this->layout()->breadcrumbs = '<li class="active">' . $this->transEsc('Channels') . '</li>';
diff --git a/themes/finc/templates/documentdeliveryservice/home.phtml b/themes/finc/templates/documentdeliveryservice/home.phtml
index d92c526dd57cddd74c48d8f4bb696bbdbf4b6f47..db283942371cf432ffc274e3b675f55af9d3ed8c 100644
--- a/themes/finc/templates/documentdeliveryservice/home.phtml
+++ b/themes/finc/templates/documentdeliveryservice/home.phtml
@@ -1,6 +1,6 @@
 <?php
 // Set up page title:
-$this->headTitle($this->translate('Delivery service for documents') . ' | ' . $this->translate("LibraryName"));
+$this->headTitle($this->translate('Delivery service for documents'));
 
 ?>
 <?=($this->loadForm ? $this->render('documentdeliveryservice/zform.phtml') : $this->flashmessages());?>
\ No newline at end of file
diff --git a/themes/finc/templates/footer.phtml b/themes/finc/templates/footer.phtml
index 301b47e88a484d27332358c9a3aea934023687ec..719d70099b343d088d6db736236e067b6fa92110 100644
--- a/themes/finc/templates/footer.phtml
+++ b/themes/finc/templates/footer.phtml
@@ -37,8 +37,8 @@
         <span>
           <?= $this->transEsc("Footer-Powered-By-Text") ?>
         </span>
-        <?= $this->externalLink("https://vufind.org", '<img src="' . $this->imageLink('vufind_logo.png') . '" alt="' . $this->translate('vufind-logo_alt') . '" aria-hidden="true"/>', ['title' => $this->translate('vufind-logo_title')]) ?>
-        <?= $this->externalLink("https://finc.info", '<img src="' . $this->imageLink('finc_logo.png') . '" alt="' . $this->translate('finc-logo_alt') . '" aria-hidden="true"/>', ['title' => $this->translate('finc-logo_title')]) ?>
+        <?= $this->externalLink("https://vufind.org", '<img src="' . $this->imageLink('vufind_logo.png') . '" alt="' . $this->translate('vufind-logo_alt') . '" aria-hidden="true"/>', ['title' => $this->translate('vufind-logo_title')], true) ?>
+        <?= $this->externalLink("https://finc.info", '<img src="' . $this->imageLink('finc_logo.png') . '" alt="' . $this->translate('finc-logo_alt') . '" aria-hidden="true"/>', ['title' => $this->translate('finc-logo_title')], true) ?>
       </div>
     </div>
 </footer>
diff --git a/themes/finc/templates/header.phtml b/themes/finc/templates/header.phtml
index e5220854a619639dc3b6406eabb204102b6dce00..67b8f3acd01568715ac098fdb5c6741fe52f82d9 100644
--- a/themes/finc/templates/header.phtml
+++ b/themes/finc/templates/header.phtml
@@ -37,8 +37,8 @@
           <?php $cart = $this->cart();
           if ($cart->isActive()): ?>
             <li id="cartSummary">
-              <a id="cartItems" class="btn" data-lightbox title="<?=$this->transEsc('View Book Bag')?>" href="<?=$this->url('cart-home')?>" aria-describedby="cartStatus">
-                <i class="fa fa-clipboard" aria-hidden="true"></i> <span class="sr-only"><?=$this->transEsc('Book Bag')?>:</span> <strong><?=count($cart->getItems())?></strong> <span class="cart-label"><?=$this->transEsc('items')?></span>
+              <a id="cartItems" class="btn" data-lightbox title="<?=$this->transEsc('View Book Bag')?>" href="<?=$this->url('cart-home')?>">
+                <i class="fa fa-clipboard" aria-hidden="true"></i> <span role="status"><span class="sr-only"><?=$this->transEsc('Book Bag')?>:</span> <strong><?=count($cart->getItems())?></strong> <span class="cart-label"><?=$this->transEsc('items')?></span></span>
                 <span class="sr-only full<?=!$cart->isFull() ? ' hidden' : ''?>">(<?=$this->transEsc('bookbag_full')?>)</span>
               </a>
             </li>
@@ -109,7 +109,7 @@
                   <?php foreach ($this->layout()->allLangs as $langCode => $langName): ?>
                     <?php if ($langCode !== $this->layout()->userLang) : ?>
                       <li>
-                        <button type="submit" class="btn <?=(count($this->layout()->allLangs) == 2) ? ' btn-secondary' : ''?>" href="#" onClick="document.langForm.mylang.value='<?=$langCode?>';document.langForm.submit()">
+                        <button type="submit" class="btn <?=(count($this->layout()->allLangs) == 2) ? ' btn-secondary' : ''?>" data-href="#" onClick="document.langForm.mylang.value='<?=$langCode?>';document.langForm.submit()">
                           <span class="visible-sm-md-only"><?=$langCode?></span>
                           <span class="hidden-sm-md"><?=$this->displayLanguageOption($langName)?></span>
                         </button>
@@ -127,8 +127,8 @@
   <?php /* finc searchbox: we use searchbox here so it becomes part of the sticky header,
         we need to place this after the navbar-right for anything but mobile  - see flex-container in SCSS:*/ ?>
   <?php if ($this->layout()->searchbox !== false): ?>
-    <div class="search container">
-      <nav class="nav searchbox hidden-print" role="search">
+    <div class="search container" role="search">
+      <nav class="nav searchbox hidden-print">
         <?=$this->layout()->searchbox?>
       </nav>
     </div>
diff --git a/themes/finc/templates/layout/layout.phtml b/themes/finc/templates/layout/layout.phtml
index 898b0e194a6543dee78370def3c9e928c51b3e5e..8f4a34ab4c74a4cf5262f19e35e5843b65ff16ab 100644
--- a/themes/finc/templates/layout/layout.phtml
+++ b/themes/finc/templates/layout/layout.phtml
@@ -8,8 +8,20 @@
   <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
   <meta name="viewport" content="width=device-width,initial-scale=1.0"/>
   <?=$this->headMeta()?>
-  <?=$this->headTitle()?>
   <?php
+  // Pullrequest 2157 Ticket #20826
+  // Format the page title using the translation system:
+  $siteConfig = $this->config()->get('config')->Site;
+  $fullTitle = $this->translate(
+    'title_wrapper',
+    [
+      '%%pageTitle%%' => $this->headTitle()->renderTitle(),
+      '%%siteTitle%%' => $siteConfig->title,
+      '%%titleSeparator%%' => $siteConfig->titleSeparator ?? '::'
+    ]
+  );
+  echo $this->headTitle($fullTitle, \Zend\View\Helper\Placeholder\Container\AbstractContainer::SET);
+
   // Set up OpenSearch link:
   $this->headLink(
     [
@@ -245,7 +257,7 @@ if (!isset($this->layout()->searchbox)) {
 
 <!-- MODAL IN CASE WE NEED ONE -->
 <?php /* move X button to logical pos. in structure + make accessible via tab - CK */ ?>
-<div id="modal" class="modal fade hidden-print" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="modal-title" aria-hidden="true" aria-describedby="modal-description">
+<div id="modal" class="modal fade hidden-print" tabindex="-1" role="dialog" aria-modal="true" aria-hidden="true" aria-describedby="modal-description">
   <div class="modal-dialog">
     <div class="modal-content">
       <button type="button" class="close" data-dismiss="modal" tabindex="0" aria-label="<?= $this->transEsc('CloseModal') ?>">
diff --git a/themes/finc/templates/librarycards/editcard.phtml b/themes/finc/templates/librarycards/editcard.phtml
index 34c7edc473a76f2e50c49eca4f540d84d4fc42e0..9a7926db76b7240eaabdc86e678bccbaf0ab8cb3 100644
--- a/themes/finc/templates/librarycards/editcard.phtml
+++ b/themes/finc/templates/librarycards/editcard.phtml
@@ -2,7 +2,7 @@
 <?php
   // Set up page title:
   $pageTitle = empty($this->card->id) ? 'Add a Library Card' : "Edit Library Card";
-  $this->headTitle($this->translate($pageTitle) . ' | ' . $this->translate("LibraryName"));
+  $this->headTitle($this->translate($pageTitle));
 
   // Set up breadcrumbs:
   $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li>'
diff --git a/themes/finc/templates/librarycards/home.phtml b/themes/finc/templates/librarycards/home.phtml
index 5ded3c3ad5ab34855ee8dc96658d5d455be730cd..25338aa28e5edea51bc2a71d4f43f48a6918bd21 100644
--- a/themes/finc/templates/librarycards/home.phtml
+++ b/themes/finc/templates/librarycards/home.phtml
@@ -1,7 +1,7 @@
 <!-- finc: librarycards - home -->
 <?php
     // Set up page title:
-    $this->headTitle($this->translate('Library Cards') . ' | ' . $this->translate("LibraryName"));
+    $this->headTitle($this->translate('Library Cards'));
 
     // 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>';
diff --git a/themes/finc/templates/myresearch/account.phtml b/themes/finc/templates/myresearch/account.phtml
index 93352dd3908d86ca3485ed1c6c20d99ea20bcb2b..f4e40c2f045ce098ba788dd2cc29355671bfa88a 100644
--- a/themes/finc/templates/myresearch/account.phtml
+++ b/themes/finc/templates/myresearch/account.phtml
@@ -2,7 +2,7 @@
 
 <?php
     // Set up page title:
-    $this->headTitle($this->translate('User Account') . ' | ' . $this->translate("LibraryName"));
+    $this->headTitle($this->translate('User Account'));
 
     // Set up breadcrumbs:
     $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('Account') . '</li>';
@@ -11,7 +11,6 @@
 <?=$this->flashmessages()?>
 
 <form method="post" name="accountForm" id="accountForm" class="form-user-create" data-toggle="validator" role="form">
-  <legend class="sr-only"><?=$this->transEsc('form-legend')?></legend>
   <?=$this->auth()->getCreateFields()?>
   <?=$this->recaptcha()->html($this->useRecaptcha) ?>
   <div class="form-group">
diff --git a/themes/finc/templates/myresearch/acquisition.phtml b/themes/finc/templates/myresearch/acquisition.phtml
index 0d2140246d9337b1bc9ef9ea63855496878d6bfd..62d81badc6f0194afb2e0de9effce3391e3e3ab6 100644
--- a/themes/finc/templates/myresearch/acquisition.phtml
+++ b/themes/finc/templates/myresearch/acquisition.phtml
@@ -1,7 +1,7 @@
 <!-- finc: myresearch - acquisition -->
 <?php
 // Set up page title:
-$this->headTitle($this->translate('PDA::pda_form_title') . ' | ' . $this->translate("LibraryName"));
+$this->headTitle($this->translate('PDA::pda_form_title'));
 
 // Set up breadcrumbs:
 $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('PDA::pda_form_title') . '</li>';
diff --git a/themes/finc/templates/myresearch/cataloglogin.phtml b/themes/finc/templates/myresearch/cataloglogin.phtml
index 1f89d9181e8f2d8788f28707721dfd0244ffc9fa..0ae0ff0c85d5f04b38dacde8f2ea2eb076b066f0 100644
--- a/themes/finc/templates/myresearch/cataloglogin.phtml
+++ b/themes/finc/templates/myresearch/cataloglogin.phtml
@@ -1,6 +1,6 @@
 <?php
     // Set up page title:
-    $this->headTitle($this->translate('Login') . ' | ' . $this->translate("LibraryName"));
+    $this->headTitle($this->translate('Login'));
 
     // Set up breadcrumbs:
     $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('Login') . '</li>';
diff --git a/themes/finc/templates/myresearch/checkedout.phtml b/themes/finc/templates/myresearch/checkedout.phtml
index da91dd35e27a562a426a54b8bf6fd13452ec3339..a6b6773c1a96c29bef8e5892db1ffae744b4d08a 100644
--- a/themes/finc/templates/myresearch/checkedout.phtml
+++ b/themes/finc/templates/myresearch/checkedout.phtml
@@ -1,7 +1,7 @@
 <!-- finc: myresearch - checkedout -->
 <?php
   // Set up page title:
-  $this->headTitle($this->translate('Checked Out Items') . ' | ' . $this->translate("LibraryName"));
+  $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>';
diff --git a/themes/finc/templates/myresearch/edit.phtml b/themes/finc/templates/myresearch/edit.phtml
index 71a923eaa555fe996483ffe554ab969699d7d453..0484ff434fbfb08d8b1806970c946cb7d0545bd3 100644
--- a/themes/finc/templates/myresearch/edit.phtml
+++ b/themes/finc/templates/myresearch/edit.phtml
@@ -3,7 +3,7 @@
 
 <?php
   // Set up page title:
-  $this->headTitle($this->translate('Edit') . ' : ' . $this->driver->getBreadcrumb() . ' | ' . $this->translate("LibraryName"));
+  $this->headTitle($this->translate('Edit') . ' : ' . $this->driver->getBreadcrumb());
 
   // 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>';
diff --git a/themes/finc/templates/myresearch/editlist.phtml b/themes/finc/templates/myresearch/editlist.phtml
index 91994836d6b1db9cf7916e333b35a6874dc2fccb..929bb53ca801ed12daec205700970390de96cb04 100644
--- a/themes/finc/templates/myresearch/editlist.phtml
+++ b/themes/finc/templates/myresearch/editlist.phtml
@@ -4,7 +4,7 @@
 <?php
   // Set up page title:
   $pageTitle = empty($this->list->id) ? 'Create a List' : "edit_list";
-  $this->headTitle($this->translate($pageTitle) . ' | ' . $this->translate("LibraryName"));
+  $this->headTitle($this->translate($pageTitle));
 
   // Set up breadcrumbs:
   $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li>'
diff --git a/themes/finc/templates/myresearch/fines.phtml b/themes/finc/templates/myresearch/fines.phtml
index 2762ecb0504a0a1fad0987a38f3528daac1f03de..a4054ab251ff02135bbac77bc1fddac309500dbb 100644
--- a/themes/finc/templates/myresearch/fines.phtml
+++ b/themes/finc/templates/myresearch/fines.phtml
@@ -1,7 +1,7 @@
 <!-- finc: myresearch - fines -->
 <?php
     // Set up page title:
-    $this->headTitle($this->translate('My Fines') . ' | ' . $this->translate("LibraryName"));
+    $this->headTitle($this->translate('My Fines'));
 
     // Set up breadcrumbs:
     $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('Fines') . '</li>';
diff --git a/themes/finc/templates/myresearch/historicloans.phtml b/themes/finc/templates/myresearch/historicloans.phtml
index 16cf3c34b27a7a3cdadf23034fd3d30ced416536..44605abc8de8fafa023af8ba0b70903984ef3263 100644
--- a/themes/finc/templates/myresearch/historicloans.phtml
+++ b/themes/finc/templates/myresearch/historicloans.phtml
@@ -1,7 +1,7 @@
 <!-- finc: myresearch - historicloans -->
 <?php
   // Set up page title:
-  $this->headTitle($this->translate('Loan History') . ' | ' . $this->translate("LibraryName"));
+  $this->headTitle($this->translate('Loan History'));
 
   // Set up breadcrumbs:
   $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('Loan History') . '</li>';
diff --git a/themes/finc/templates/myresearch/holds.phtml b/themes/finc/templates/myresearch/holds.phtml
index 7131cf6092de4f611c1d37361391d1bf7d624ee6..6b584c7355cd127ed8e15dc3c689e737e098636d 100644
--- a/themes/finc/templates/myresearch/holds.phtml
+++ b/themes/finc/templates/myresearch/holds.phtml
@@ -1,7 +1,7 @@
 <!-- finc: myresearch - holds -->
 <?php
   // Set up page title:
-  $this->headTitle($this->translate('My Holds') . ' | ' . $this->translate("LibraryName"));
+  $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>';
diff --git a/themes/finc/templates/myresearch/illrequests.phtml b/themes/finc/templates/myresearch/illrequests.phtml
index 27320ac4a5b5bfea69fdd1a80ce8ed1f5bbba97d..6f87f860b07bdb742a7a115a18a82eabeb1a8a79 100644
--- a/themes/finc/templates/myresearch/illrequests.phtml
+++ b/themes/finc/templates/myresearch/illrequests.phtml
@@ -1,7 +1,7 @@
 <!-- finc: myresearch - illrequests -->
 <?php
     // Set up page title:
-    $this->headTitle($this->translate('Interlibrary Loan Requests') . ' | ' . $this->translate("LibraryName"));
+    $this->headTitle($this->translate('Interlibrary Loan Requests'));
 
     // Set up breadcrumbs:
     $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li>'
diff --git a/themes/finc/templates/myresearch/menu.phtml b/themes/finc/templates/myresearch/menu.phtml
index 65978bf3e042238e103e089fd5d9d4765117cd78..5178f89f59527145797307d0384824c85fa92e9b 100644
--- a/themes/finc/templates/myresearch/menu.phtml
+++ b/themes/finc/templates/myresearch/menu.phtml
@@ -34,9 +34,7 @@ $capabilityParams = $patron ? ['patron' => $patron] : [];
     <?php endif; ?>
     <?php if ($this->ils()->checkFunction('getMyTransactionHistory', $capabilityParams)): ?>
       <li class="facet">
-        <a href="<?=$this->url('myresearch-historicloans')?>"<?=$this->active == 'historicloans' ? ' class="active"' : ''?>
-          <?=$this->active == 'historicloans' ? ' aria-current="page"' : ''?>
-        >
+        <a href="<?=$this->url('myresearch-historicloans')?>"<?=$this->active == 'historicloans' ? ' class="active" aria-current="page"' : ''?>>
         <i class="fa fa-fw fa-history" aria-hidden="true"></i> <?=$this->transEsc('Loan History')?>
       </a>
       </li>
@@ -45,8 +43,8 @@ $capabilityParams = $patron ? ['patron' => $patron] : [];
 
       <li class="facet">
         <a href="<?=$this->url('myresearch-holds')?>" class="flex<?=$this->active == 'holds' ? ' active' : ''?>"
-          <?=$this->active == 'holds' ? ' aria-current="page"' : ''?>
-        >
+        <?=$this->active == 'holds' ? ' aria-current="page"' : ''?>
+      >
         <span class="flex-col"><i class="fa fa-fw fa-flag" aria-hidden="true"></i>&nbsp;<?=$this->transEsc('Holds and Recalls')?></span>
         <span class="holds-status status hidden"><i class="fa fa-spin fa-spinner" aria-hidden="true"></i></span>
         <?php /* nxt line finc specific - CK */ ?>
@@ -58,8 +56,8 @@ $capabilityParams = $patron ? ['patron' => $patron] : [];
     <?php if ($this->ils()->checkFunction('StorageRetrievalRequests', $capabilityParams)): ?>
       <li class="facet">
         <a href="<?=$this->url('myresearch-storageretrievalrequests')?>" class="flex<?=$this->active == 'storageRetrievalRequests' ? ' active' : ''?>"
-          <?=$this->active == 'storageRetrievalRequests' ? ' aria-current="page"' : ''?>
-        >
+        <?=$this->active == 'storageRetrievalRequests' ? ' aria-current="page"' : ''?>
+      >
         <span class="flex-col"><i class="fa fa-fw fa-archive" aria-hidden="true"></i> <?=$this->transEsc('Storage Retrieval Requests')?></span>
         <span class="storageretrievalrequests-status status hidden"><i class="fa fa-spin fa-spinner" aria-hidden="true"></i></span>
         <?php /* nxt line finc specific - CK */ ?>
@@ -71,8 +69,8 @@ $capabilityParams = $patron ? ['patron' => $patron] : [];
     <?php if ($this->ils()->checkFunction('ILLRequests', $capabilityParams)): ?>
       <li class="facet">
         <a href="<?=$this->url('myresearch-illrequests')?>" class="flex<?=$this->active == 'ILLRequests' ? ' active' : ''?>"
-          <?=$this->active == 'ILLRequests' ? ' aria-current="page"' : ''?>
-        >
+        <?=$this->active == 'ILLRequests' ? ' aria-current="page"' : ''?>
+      >
         <span class="flex-col"><i class="fa fa-fw fa-exchange" aria-hidden="true"></i>&nbsp;<?=$this->transEsc('Interlibrary Loan Requests')?></span>
         <span class="illrequests-status status hidden"><i class="fa fa-spin fa-spinner" aria-hidden="true"></i></span>
         <?php /* nxt line finc specific - CK */ ?>
@@ -84,25 +82,21 @@ $capabilityParams = $patron ? ['patron' => $patron] : [];
     <?php if ($this->ils()->checkCapability('getMyFines', $capabilityParams)): ?>
       <li class="facet">
         <a href="<?=$this->url('myresearch-fines')?>" class="flex<?=$this->active == 'fines' ? ' active' : ''?>"
-          <?=$this->active == 'fines' ? ' aria-current="page"' : ''?>
-        >
+        <?=$this->active == 'fines' ? ' aria-current="page"' : ''?>
+      >
         <span class="flex-col"><i class="fa fa-fw fa-usd" aria-hidden="true"></i>&nbsp;<?=$this->transEsc('Fines')?></span>
         <span class="fines-status status hidden"><i class="fa fa-spin fa-spinner" aria-hidden="true"></i></span>
       </a>
       </li>
     <?php endif; ?>
     <li class="facet">
-      <a href="<?=$this->url('myresearch-profile')?>"<?=$this->active == 'profile' ? ' class="active"' : ''?>
-        <?=$this->active == 'profile' ? ' aria-current="page"' : ''?>
-      >
+      <a href="<?=$this->url('myresearch-profile')?>"<?=$this->active == 'profile' ? ' class="active" aria-current="page"' : ''?>>
       <i class="fa fa-fw fa-user" aria-hidden="true"></i> <?=$this->transEsc('Profile')?>
     </a>
     </li>
     <?php if ($user && $user->libraryCardsEnabled()): ?>
       <li class="facet">
-        <a href="<?=$this->url('librarycards-home')?>"<?=$this->active == 'librarycards' ? ' class="active"' : ''?>
-          <?=$this->active == 'librarycards' ? ' aria-current="page"' : ''?>
-        >
+        <a href="<?=$this->url('librarycards-home')?>"<?=$this->active == 'librarycards' ? ' class="active" aria-current="page"' : ''?>>
         <i class="fa fa-fw fa-barcode" aria-hidden="true"></i> <?=$this->transEsc('Library Cards')?>
       </a>
       </li>
@@ -110,9 +104,7 @@ $capabilityParams = $patron ? ['patron' => $patron] : [];
   <?php endif; ?>
   <?php if ($this->accountCapabilities()->getSavedSearchSetting() === 'enabled'): ?>
     <li class="facet">
-      <a href="<?=$this->url('search-history')?>?require_login"<?=$this->active == 'history' ? ' class="active"' : ''?>
-        <?=$this->active == 'history' ? ' aria-current="page"' : ''?>
-      >
+      <a href="<?=$this->url('search-history')?>?require_login"<?=$this->active == 'history' ? ' class="active" aria-current="page"' : ''?>>
       <i class="fa fa-fw fa-search" aria-hidden="true"></i> <?=$this->transEsc('history_saved_searches')?>
     </a>
     </li>
diff --git a/themes/finc/templates/myresearch/mylist.phtml b/themes/finc/templates/myresearch/mylist.phtml
index f210befcf16ca777958f1b0fc3c1fdfba48dbb41..ed7bf00413d20dec9fd6795100a4b9f99b4e0d0c 100644
--- a/themes/finc/templates/myresearch/mylist.phtml
+++ b/themes/finc/templates/myresearch/mylist.phtml
@@ -4,7 +4,7 @@
 $list = $this->results->getListObject();
 
 // Set up page title:
-$this->headTitle(isset($list) ? $list->title : $this->translate('Favorites') . ' | ' . $this->translate("LibraryName"));
+$this->headTitle(isset($list) ? $list->title : $this->translate('Favorites'));
 
 // Set up breadcrumbs:
 $currPage = isset($list) ? 'List' : 'Favorites';
@@ -57,7 +57,7 @@ $user = $this->auth()->isLoggedIn();
             </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>
+              <li><a href="#" class="dropdown-abort"><?=$this->transEsc('confirm_dialog_no')?></a></li>
             </ul>
           </div>
         <?php endif; ?>
@@ -95,5 +95,4 @@ $user = $this->auth()->isLoggedIn();
     <br/><?=$this->recommend($current)?>
   <?php endforeach; ?>
 </div>
-
-<!-- finc: myresearch - mylist - END -->
\ No newline at end of file
+<!-- finc: myresearch - mylist - END -->
diff --git a/themes/finc/templates/myresearch/newpassword.phtml b/themes/finc/templates/myresearch/newpassword.phtml
index 713a5234ad4e995b5c03bce04913431e447a46bd..e493278a4bcba753d7aed4bbb79edfc44bffe16a 100644
--- a/themes/finc/templates/myresearch/newpassword.phtml
+++ b/themes/finc/templates/myresearch/newpassword.phtml
@@ -1,7 +1,7 @@
 <!-- finc - templates - myresearch - newpassword -->
 <?php
     // Set up page title:
-    $this->headTitle($this->translate('Create New Password') . ' | ' . $this->translate("LibraryName"));
+    $this->headTitle($this->translate('Create New Password'));
 
     // Set up breadcrumbs:
     $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li>'
@@ -23,7 +23,6 @@
   <div class="error"><?=$this->transEsc('recovery_user_not_found') ?></div>
 <?php else: ?>
   <form id="newpassword" class="form-new-password" action="<?=$this->url('myresearch-newpassword') ?>" method="post" data-toggle="validator" role="form">
-    <legend class="sr-only"><?=$this->transEsc('form-legend')?></legend>
     <input type="hidden" value="<?=$this->escapeHtmlAttr($this->auth()->getManager()->getCsrfHash())?>" name="csrf"/>
     <input type="hidden" value="<?=$this->escapeHtmlAttr($this->hash) ?>" name="hash"/>
     <input type="hidden" value="<?=$this->escapeHtmlAttr($this->username) ?>" name="username"/>
diff --git a/themes/finc/templates/myresearch/profile.phtml b/themes/finc/templates/myresearch/profile.phtml
index e3ad22b6eee0b6e85635afc077f9a5b98002452a..8360cd61d7bb948c9826c2a4ef1c035eaa4718fe 100644
--- a/themes/finc/templates/myresearch/profile.phtml
+++ b/themes/finc/templates/myresearch/profile.phtml
@@ -1,7 +1,7 @@
 <!-- finc: myresearch - profile -->
 <?php
     // Set up page title:
-    $this->headTitle($this->translate('My Profile') . ' | ' . $this->translate("LibraryName"));
+    $this->headTitle($this->translate('My Profile'));
     
     // Set up breadcrumbs:
     $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('Profile') . '</li>';
diff --git a/themes/finc/templates/myresearch/setpin.phtml b/themes/finc/templates/myresearch/setpin.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..7d57c304752daa033d9e22475f432ca036205df7
--- /dev/null
+++ b/themes/finc/templates/myresearch/setpin.phtml
@@ -0,0 +1,66 @@
+<!-- finc: myresearch - setpin -->
+<?php
+// Set up page title:
+$this->headTitle($this->translate('LiberoAccount::change_user_pin'));
+
+// Set up breadcrumbs:
+$this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li>'
+    . '<li class="active">' . $this->transEsc('LiberoAccount::change_user_pin') . '</li>';
+?>
+<?php if ($this->auth()->isLoggedIn()): ?>
+  <a class="search-filter-toggle visible-xs" href="#myresearch-sidebar" data-toggle="offcanvas" aria-label="<?=$this->transEsc('sidebar_expand')?>">
+    <?=$this->transEsc('Your Account') ?>
+  </a>
+  <div class="<?=$this->layoutClass('mainbody')?>">
+<?php endif; ?>
+
+  <h1><?=$this->transEsc('LiberoAccount::change_user_pin')?></h1>
+  <p class="alert alert-info"><?=$this->transEsc('LiberoAccount::set_pin_note')?></p>
+  <?=$this->flashmessages()?>
+
+    <?php if (!$this->auth()->getManager()->supportsPasswordChange($this->auth_method)): ?>
+      <div class="error"><?=$this->transEsc('recovery_new_disabled')?></div>
+    <?php elseif (!isset($this->hash)): ?>
+      <div class="error"><?=$this->transEsc('recovery_user_not_found')?></div>
+    <?php else: ?>
+      <form id="setpin" class="form-set-pin" action="<?=$this->url('myresearch-setpin')?>" 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"/>
+        <input type="hidden" value="<?=$this->escapeHtmlAttr($this->auth_method)?>" name="auth_method"/>
+
+          <?php if (isset($this->cat_username)): ?>
+            <div class="form-group">
+              <label class="control-label"><?=$this->transEsc('Username')?>:</label>
+              <p class="form-control"><?=$this->cat_username?></p>
+            </div>
+          <?php endif; ?>
+
+        <div class="form-group">
+          <label for="pin" class="control-label"><?=$this->transEsc('LiberoAccount::new_pin')?>:</label>
+          <input type="password" id="pin" name="pin" class="form-control" required aria-required="true" aria-describedby="pin-policy-error"
+              <?=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="[0-9]{4}" />
+          <div id="pin-policy-error" class="help-block with-errors"></div>
+        </div>
+
+        <div class="form-group">
+          <label for="confirm-pin" class="control-label"><?=$this->transEsc('LiberoAccount::confirm_new_pin')?>:</label>
+          <input type="password" id="confirm-pin" name="pin2" class="form-control" required aria-required="true" data-match="#pin" data-match-error="<?=$this->escapeHtmlAttr($this->translate('LiberoAccount::new_pin_missmatch'))?>" aria-describedby="pin-confirmation-error"/>
+          <div id="pin-confirmation-error" class="help-block with-errors"></div>
+        </div>
+
+        <div class="form-group">
+          <input class="btn btn-primary" name="submit" type="submit" value="<?=$this->transEsc('LiberoAccount::change_user_pin')?>"/>
+        </div>
+      </form>
+    <?php endif; ?>
+
+<?php if ($this->auth()->isLoggedIn()): ?>
+  </div>
+
+  <div class="<?=$this->layoutClass('sidebar')?>">
+      <?=$this->context($this)->renderInContext("myresearch/menu.phtml", ['active' => 'setpin'])?>
+  </div>
+<?php endif; ?>
+<!-- finc: myresearch - setpin - END -->
diff --git a/themes/finc/templates/myresearch/storageretrievalrequests.phtml b/themes/finc/templates/myresearch/storageretrievalrequests.phtml
index 7b34bcd48b0cd96bc58d09608690c419f73e3a9e..a7ec9c253467e5a0395fceac4257cbfb79c20a62 100644
--- a/themes/finc/templates/myresearch/storageretrievalrequests.phtml
+++ b/themes/finc/templates/myresearch/storageretrievalrequests.phtml
@@ -1,7 +1,7 @@
 <!-- finc: myresearch - storageretrievalrequests -->
 <?php
   // Set up page title:
-  $this->headTitle($this->translate('Storage Retrieval Requests') . ' | ' . $this->translate("LibraryName"));
+  $this->headTitle($this->translate('Storage Retrieval Requests'));
 
   // 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>';
diff --git a/themes/finc/templates/record/cart-buttons.phtml b/themes/finc/templates/record/cart-buttons.phtml
index edb7d83ea32988fbf3970619cf617a6174abcc5b..beaa7cbe11028a7347ce015293c8cd923e53f0b9 100644
--- a/themes/finc/templates/record/cart-buttons.phtml
+++ b/themes/finc/templates/record/cart-buttons.phtml
@@ -3,7 +3,7 @@
 <?php if ($cart->isActive()): ?>
 
     <?php $cartId = $this->source . '|' . $this->id; ?>
-    <span class="btn-bookbag-toggle" data-cart-id="<?=$this->escapeHtmlAttr($this->id)?>" data-cart-source="<?=$this->escapeHtmlAttr($this->source)?>">
+    <div class="btn-bookbag-toggle" data-cart-id="<?=$this->escapeHtmlAttr($this->id)?>" data-cart-source="<?=$this->escapeHtmlAttr($this->source)?>">
       <?php /* Make add-to/remove-from bookbag accessible for keyboard navigation - CK */ ?>
     <a class="cart-add hidden<?php if (!$cart->contains($cartId)): ?> correct<?php endif ?>" href="javascript:" tabindex="0">
       <i class="cart-link-icon fa fa-plus" aria-hidden="true"></i><span class="cart-link-label"><?=$this->transEsc('Add to Book Bag')?></span>
@@ -11,16 +11,17 @@
     <a class="cart-remove hidden<?php if ($cart->contains($cartId)): ?> correct<?php endif ?>" href="javascript:" tabindex="0">
       <i class="cart-link-icon fa fa-minus-circle" aria-hidden="true"></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')?>">
+    <form class="cartProcessorNoJs" method="post" name="addForm" action="<?=$this->url('cart-processor')?>">
+      <noscript>
         <input type="hidden" name="ids[]" value="<?=$this->escapeHtmlAttr($cartId)?>"/>
         <?php if ($cart->contains($cartId)): ?>
           <input class="btn btn-default" type="submit" name="delete" value="<?=$this->transEsc('Remove from Book Bag')?>"/>
         <?php else: ?>
           <input class="btn btn-default" type="submit" name="add" value="<?=$this->transEsc('Add to Book Bag')?>"/>
         <?php endif; ?>
-      </form>
-    </noscript>
-  </span>
+      </noscript>
+    </form>
+    <script>$(document).ready(function() { $(".cartProcessorNoJs").css('display', 'none'); });</script>
+  </div>
 <?php endif; ?>
 <!-- finc: record - cart-buttons END -->
diff --git a/themes/finc/templates/record/cover.phtml b/themes/finc/templates/record/cover.phtml
index 6ee4c1314def4f1e730897354bd89f36958b8d40..3d0b10c5e0f9e40e472b9ab06193ed40ef5ca547 100644
--- a/themes/finc/templates/record/cover.phtml
+++ b/themes/finc/templates/record/cover.phtml
@@ -27,7 +27,7 @@
       <div class="cover-container">
         <?=$this->render('record/coverReplacement')?>
         <a class="coverlink hidden" aria-hidden="true" tabindex="-1">
-          <img <?php if ($linkPreview): ?>data-linkpreview="true" <?php endif; ?> class="recordcover ajax" alt="<?=$this->escapeHtmlAttr($alt); ?>" />
+          <img <?php if ($linkPreview): ?>data-linkpreview="true" <?php endif; ?> class="recordcover ajax" src="<?=$this->imageLink('noCover2.gif')?>" alt="<?=$this->escapeHtmlAttr($alt); ?>" />
         </a>
         <script>
           loadCoverByElement({source:'<?=$this->escapeHtmlAttr($driver->getSourceIdentifier())?>', recordId:'<?=$this->escapeHtmlAttr($driver->getUniqueID())?>', size:'<?=$this->escapeHtmlAttr($size)?>'}, $('#<?=$coverId?>'));
diff --git a/themes/finc/templates/record/pdaform.phtml b/themes/finc/templates/record/pdaform.phtml
index a7faa1f04c5d4fdb60d1075833acab13f2d9eb4f..ab7cb4438655e44e234fa26104d70738ca39a50a 100644
--- a/themes/finc/templates/record/pdaform.phtml
+++ b/themes/finc/templates/record/pdaform.phtml
@@ -36,8 +36,14 @@ $this->layout()->breadcrumbs = '<li>' . $this->searchMemory()->getLastSearchLink
       <?=$this->recaptcha()->html($this->useRecaptcha)?>
     </span>
     <input type="submit" class="btn btn-primary" role="button" name="submit" value="<?=$this->transEsc('Submit')?>"/>
-    <a class="btn btn-primary" data-lightbox-ignore data-toggle="tooltip" title="<?=$this->transEsc('PDA::pda_open_new_window')?>" href="<?=$this->interlibraryloan()->getSwbLink($this->driver)?>" target="_blank"><?=$this->transEsc('PDA::pda_tab_interlibrary_button')?>
-    </a>
+    <?= $this->externalLink(
+          $this->interlibraryloan()->getSwbLink($this->driver),
+          $this->translate('PDA::pda_tab_interlibrary_button'),
+          ['class' => 'btn btn-primary',
+           'data-lightbox-ignore' => '',
+           'data-toggle' => 'tooltip',
+           'title' => $this->translate('PDA::pda_open_new_window')]
+         ) ?>
     <button class="btn btn-transparent" type="button" data-dismiss="modal" href="#"><?=$this->transEsc('Reset')?></button>
   </div>
 
diff --git a/themes/finc/templates/record/view.phtml b/themes/finc/templates/record/view.phtml
index 1f97d387fad4ff410d80c391850a4220a5bfe5a1..076ef6fb512970578a5aac9a2f531bdacdc6a6c8 100644
--- a/themes/finc/templates/record/view.phtml
+++ b/themes/finc/templates/record/view.phtml
@@ -40,15 +40,17 @@
       <?= $this->record($this->driver)->getCoreMetadata() ?>
       
       <?php if (count($this->tabs) > 0): ?>
-        <a name="tabnav"></a>
+        <?php /* swap deprecated 'name' for 'ID' - CK */ ?>
+        <a id="tabnav"></a>
         <div class="record-tabs">
+          <?php /* DO NOT add 'role=tablist' for accessibility, see #19938 - CK */ ?>
           <ul class="nav nav-tabs">
               <?php foreach ($this->tabs as $tab => $obj): ?>
                   <?php // add current tab to breadcrumbs if applicable:
                   $desc = $obj->getDescription();
                   $tabName = preg_replace("/\W/", "-", strtolower($tab));
                   $tabClasses = ['record-tab', $tabName];
-                  if (0 === strcasecmp($this->activeTab, $tab)) {
+                  if (($isActiveTab = 0 === strcasecmp($this->activeTab, $tab))) {
                       if (!$this->loadInitialTabWithAjax || !$obj->supportsAjax()) {
                           $tabClasses[] = 'active';
                       }
@@ -63,16 +65,27 @@
                       $tabClasses[] = 'noajax';
                   }
                   ?>
+                <?php /* DO NOT add role="tab" BUT DO ADD aria-controls and ID for accessibility --
+                      'aria-selected' (true/false) needs to be set via record.js - CK */ ?>
                 <li class="<?= implode(' ', $tabClasses) ?>" data-tab="<?= $tabName ?>">
-                  <a
-                    href="<?= $this->recordLink()->getTabUrl($this->driver, $tab) ?>#tabnav"<?php if ($obj->supportsAjax() && in_array($tab, $this->backgroundTabs)): ?> data-background<?php endif ?>><?= $this->transEsc($desc) ?></a>
+                  <a href="<?= $this->recordLink()->getTabUrl($this->driver, $tab) ?>#tabnav"
+                    <?php if ($obj->supportsAjax() && in_array($tab, $this->backgroundTabs)): ?> data-background<?php endif ?>
+                     aria-selected="<?= $isActiveTab ? "true" : "false" ?>"
+                     <?php if($isActiveTab): ?>aria-controls="<?= $tabName ?>"<?php endif; ?>
+                     id="<?= $tabName ?>-tabselector">
+                    <?= $this->transEsc($desc) ?>
+                    <span class="sr-only load-tab-content"><?= $this->transEsc('load_tab_content_hint') ?></span></a>
                 </li>
               <?php endforeach; ?>
           </ul>
 
-          <div class="tab-content">
+          <div class="tab-content" aria-live="polite" tabindex="-1">
               <?php if (!$this->loadInitialTabWithAjax || !isset($activeTabObj) || !$activeTabObj->supportsAjax()): ?>
-                <div class="tab-pane active <?= $this->escapeHtmlAttr($this->activeTab) ?>-tab">
+                <?php /* Add ID, role and aria-labelledby for accessibility - CK */ ?>
+                <div class="tab-pane active <?= $this->escapeHtmlAttr($this->activeTab) ?>-tab"
+                     role="tabpanel"
+                     id="<?= $this->escapeHtmlAttr($this->activeTab) ?>"
+                     aria-labelledby="<?= $this->activeTab ?>-tabselector">
                     <?= isset($activeTabObj) ? $this->record($this->driver)->getTab($activeTabObj) : '' ?>
                 </div>
               <?php endif; ?>
diff --git a/themes/finc/templates/search/advanced/layout.phtml b/themes/finc/templates/search/advanced/layout.phtml
index a4e70ff5492cf39cdeac32fda623cb86ecd2e3a5..350eabbcb32299defd5719084c250809c70a3ffc 100644
--- a/themes/finc/templates/search/advanced/layout.phtml
+++ b/themes/finc/templates/search/advanced/layout.phtml
@@ -1,7 +1,7 @@
 <!-- finc: search - advanced - layout -->
 <?php
 // Set page title.
-$this->headTitle($this->translate('Advanced Search') . ' | ' . $this->translate("LibraryName"));
+$this->headTitle($this->translate('Advanced Search'));
 
 // Disable top search box -- this page has a special layout.
 $this->layout()->searchbox = false;
diff --git a/themes/finc/templates/search/history.phtml b/themes/finc/templates/search/history.phtml
index e5a71ac83b056b1722c83e26f6dfd9ce54a87310..04a7ee298e0aba39bd1d24479b4888e5c268933f 100644
--- a/themes/finc/templates/search/history.phtml
+++ b/themes/finc/templates/search/history.phtml
@@ -1,7 +1,7 @@
 <!-- finc - templates - search - history -->
 <?php
   // Set page title.
-  $this->headTitle($this->translate('Search History') . ' | ' . $this->translate("LibraryName"));
+  $this->headTitle($this->translate('Search History'));
 
   $loginEnabled = is_object($account = $this->auth()->getManager()) && $account->loginEnabled();
 
diff --git a/themes/finc/templates/search/home.phtml b/themes/finc/templates/search/home.phtml
index 781d4415bfc0377c3800d58c1f039a9aabecc575..4fc8d20045f806bc73c723704385410dd97f7cd5 100644
--- a/themes/finc/templates/search/home.phtml
+++ b/themes/finc/templates/search/home.phtml
@@ -1,7 +1,7 @@
 <!-- finc: search - home -->
 <?php
     // Set page title.
-    $this->headTitle($this->translate('Search Home') . ' | ' . $this->translate("LibraryName"));
+    $this->headTitle($this->translate('Search Home'));
     
     // finc: disable top search box here if you want the old look, see also below
     // $this->layout()->searchbox = false;
diff --git a/themes/finc/templates/search/results.phtml b/themes/finc/templates/search/results.phtml
index 57048aa134330644849f05c4053b886b44022015..8bac2e91e997dee739e6556a1349061de5c306b5 100644
--- a/themes/finc/templates/search/results.phtml
+++ b/themes/finc/templates/search/results.phtml
@@ -7,7 +7,7 @@ $lookfor = $this->results->getUrlQuery()->isQuerySuppressed() ? '' : $this->para
 if (isset($this->overrideTitle)) {
   $this->headTitle($this->overrideTitle);
 } else {
-  $this->headTitle($this->translate('Search Results') . (empty($lookfor) ? '' : " - {$lookfor}") . ' | ' . $this->translate("LibraryName"));
+  $this->headTitle($this->translate('Search Results') . (empty($lookfor) ? '' : " - {$lookfor}"));
 }
 
 // Set up search box:
@@ -85,15 +85,15 @@ $this->headScript()->appendFile("check_save_statuses.js");
     <?php if ($recordTotal > 0): ?>
     <?php /* finc: use spans for easier to show/hide choices - CK */ ?>
       <div class="search-controls">
-        <span class="limit">
+        <div class="limit">
         <?=$this->render('search/controls/limit.phtml')?>
-        </span>
-        <span class="sort right">
+        </div>
+        <div class="sort right">
         <?=$this->render('search/controls/sort.phtml')?>
-        </span>
-        <span class="view">
+        </div>
+        <div class="view">
         <?=$this->render('search/controls/view.phtml')?>
-        </span>
+        </div>
       </div>
     <?php endif; ?>
   </div>
diff --git a/themes/finc/theme.config.php b/themes/finc/theme.config.php
index 3896a57fa8beb2d1e681c1a4b599d47299116f8c..652545a3d02d4d550bb1be2fc57cace7edd3cac8 100644
--- a/themes/finc/theme.config.php
+++ b/themes/finc/theme.config.php
@@ -5,8 +5,7 @@ return [
         'check_item_statuses.js',
         'lightbox_form_cache.js',
         'covers.js',
-        'common-finc.js',
-        'cart-finc.js'
+        'common-finc.js'
     ],
     'helpers' => [
         'aliases' => [
@@ -18,7 +17,6 @@ return [
             'recordLink' => 'finc\View\Helper\Root\RecordLink',
             'record' => 'finc\View\Helper\Root\Record',
             'flashmessages' => 'finc\View\Helper\Root\Flashmessages',
-            'headTitle' => 'finc\View\Helper\Root\HeadTitle',
             'externalLink' => 'finc\View\Helper\Root\ExternalLink',
         ],
         'factories' => [
@@ -44,8 +42,6 @@ return [
                 'VuFind\View\Helper\Root\ResultFeedFactory',
             'finc\View\Helper\Root\Flashmessages' =>
                 'VuFind\View\Helper\Root\FlashmessagesFactory',
-            'finc\View\Helper\Root\HeadTitle' =>
-                'finc\View\Helper\Root\Factory::getHeadTitle',
             'finc\View\Helper\Root\ExternalLink' =>
                 'finc\View\Helper\Root\Factory::getExternalLink',
         ]
diff --git a/themes/foundation5/templates/myresearch/bulk-action-buttons.phtml b/themes/foundation5/templates/myresearch/bulk-action-buttons.phtml
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000