diff --git a/app/environment.ini b/app/environment.ini index fdc37c0c9..7d84873ed 100644 --- a/app/environment.ini +++ b/app/environment.ini @@ -2,16 +2,16 @@ [ENVIRONMENT] ; project environment (DEVELOP, PRODUCTION). -; This effects: DB connection, Mail-Server connection +; This effects: DB connection, Mail-Server, SSO, CREST configurations in this file ; configuration below SERVER = DEVELOP [ENVIRONMENT.DEVELOP] -; base dir (Default: "auto-detect" +; base dir (Default: "auto-detect") BASE = -; deployment URL e.g. http://localhost +; deployment URL (e.g. http://localhost) URL = http://pathfinder.local -; Verbosity level of the stack trace +; level of debug/error stack trace DEBUG = 3 ; main db DB_DNS = mysql:host=localhost;port=3306;dbname= @@ -25,11 +25,13 @@ DB_CCP_NAME = eve_parallax_min DB_CCP_USER = root DB_CCP_PASS = -; CCP SSO settings +; CCP SSO settings (OAuth2) - visit: https://developers.eveonline.com/applications +CCP_CREST_URL = https://api-sisi.testeveonline.com +SSO_CCP_URL = https://sisilogin.testeveonline.com SSO_CCP_CLIENT_ID = SSO_CCP_SECRET_KEY = -; SMTP settings. see: https://developers.eveonline.com/applications +; SMTP settings (optional) SMTP_HOST = localhost SMTP_PORT = 25 SMTP_SCHEME = "" @@ -40,10 +42,11 @@ SMTP_FROM = pathfinder@localhost.com SMTP_ERROR = pathfinder@localhost.com [ENVIRONMENT.PRODUCTION] +; base dir (Default: "auto-detect" BASE = /www/htdocs/www.pathfinder-w.space -; deployment URL +; deployment URL (e.g. https://www.pathfinder-w.space) URL = https://www.pathfinder-w.space -; Verbosity level of the stack trace +; level of debug/error stack trace DEBUG = 0 ; main db DB_DNS = mysql:host=localhost;port=3306;dbname= @@ -58,10 +61,12 @@ DB_CCP_USER = DB_CCP_PASS = ; CCP SSO settings +CCP_CREST_URL = https://crest-tq.eveonline.com +SSO_CCP_URL = https://login.eveonline.com SSO_CCP_CLIENT_ID = SSO_CCP_SECRET_KEY = -; SMTP settings +; SMTP settings (optional) SMTP_HOST = localhost SMTP_PORT = 25 SMTP_SCHEME = TLS diff --git a/app/main/controller/accesscontroller.php b/app/main/controller/accesscontroller.php index d3c762196..e025eb0ee 100644 --- a/app/main/controller/accesscontroller.php +++ b/app/main/controller/accesscontroller.php @@ -7,20 +7,21 @@ */ namespace Controller; +use Controller\Api as Api; use Model; class AccessController extends Controller { /** * event handler - * @param $f3 + * @param \Base $f3 */ - function beforeroute($f3) { + function beforeroute(\Base $f3) { parent::beforeroute($f3); // Any CMS route of a child class of this one, requires a // valid logged in user! - $loginCheck = $this->_checkLogIn(); + $loginCheck = $this->checkLogIn($f3); if( !$loginCheck ){ // no user found or LogIn timer expired @@ -30,16 +31,16 @@ function beforeroute($f3) { /** * checks weather a user is currently logged in + * @param \Base $f3 * @return bool */ - private function _checkLogIn(){ - + private function checkLogIn($f3){ $loginCheck = false; - if($this->f3->get('SESSION.user.time') > 0){ + if($f3->get(Api\User::SESSION_KEY_CHARACTER_TIME) > 0){ // check logIn time $logInTime = new \DateTime(); - $logInTime->setTimestamp($this->f3->get('SESSION.user.time')); + $logInTime->setTimestamp( $f3->get(Api\User::SESSION_KEY_CHARACTER_TIME) ); $now = new \DateTime(); $timeDiff = $now->diff($logInTime); @@ -48,7 +49,7 @@ private function _checkLogIn(){ $minutes += $timeDiff->h * 60; $minutes += $timeDiff->i; - if($minutes <= $this->f3->get('PATHFINDER.TIMER.LOGGED')){ + if($minutes <= $f3->get('PATHFINDER.TIMER.LOGGED')){ $loginCheck = true; } } diff --git a/app/main/controller/api/connection.php b/app/main/controller/api/connection.php index aefbca822..6bd2d4093 100644 --- a/app/main/controller/api/connection.php +++ b/app/main/controller/api/connection.php @@ -7,27 +7,26 @@ */ namespace Controller\Api; +use Controller; use Model; -class Connection extends \Controller\AccessController{ +class Connection extends Controller\AccessController{ /** - * @param $f3 + * @param \Base $f3 */ - function beforeroute($f3) { - - parent::beforeroute($f3); - + function beforeroute(\Base $f3) { // set header for all routes header('Content-type: application/json'); + parent::beforeroute($f3); } /** * save a new connection or updates an existing (drag/drop) between two systems * if a connection is changed (drag&drop) to another system. -> this function is called for update - * @param $f3 + * @param \Base $f3 */ - public function save($f3){ + public function save(\Base $f3){ $postData = (array)$f3->get('POST'); $newConnectionData = []; @@ -38,10 +37,15 @@ public function save($f3){ $mapData = (array)$postData['mapData']; $connectionData = (array)$postData['connectionData']; - $user = $this->_getUser(); + $activeCharacter = $this->getCharacter(); + + if($activeCharacter){ + $user = $activeCharacter->getUser(); - if($user){ // get map model and check map access + /** + * @var Model\MapModel $map + */ $map = Model\BasicModel::getNew('MapModel'); $map->getById( (int)$mapData['id'] ); @@ -90,16 +94,22 @@ public function save($f3){ echo json_encode($newConnectionData); } - public function delete($f3){ + /** + * delete connection + * @param \Base $f3 + * @throws \Exception + */ + public function delete(\Base $f3){ $connectionIds = $f3->get('POST.connectionIds'); + $activeCharacter = $this->getCharacter(); - $user = $this->_getUser(); + /** + * @var Model\ConnectionModel $connection + */ $connection = Model\BasicModel::getNew('ConnectionModel'); - foreach($connectionIds as $connectionId){ - $connection->getById($connectionId); - $connection->delete($user); + $connection->delete( $activeCharacter->getUser() ); $connection->reset(); } diff --git a/app/main/controller/api/map.php b/app/main/controller/api/map.php index fc18a886f..06557d049 100644 --- a/app/main/controller/api/map.php +++ b/app/main/controller/api/map.php @@ -7,6 +7,7 @@ */ namespace Controller\Api; +use Controller; use Model; /** @@ -14,25 +15,23 @@ * Class Map * @package Controller\Api */ -class Map extends \Controller\AccessController { +class Map extends Controller\AccessController { /** * event handler - * @param $f3 + * @param \Base $f3 */ - function beforeroute($f3) { - + function beforeroute(\Base $f3) { // set header for all routes header('Content-type: application/json'); - parent::beforeroute($f3); } /** * Get all required static config data for program initialization - * @param $f3 + * @param \Base $f3 */ - public function init($f3){ + public function init(\Base $f3){ // expire time in seconds $expireTimeHead = 60 * 60 * 12; @@ -143,9 +142,9 @@ public function init($f3){ /** * import new map data - * @param $f3 + * @param \Base $f3 */ - public function import($f3){ + public function import(\Base $f3){ $importData = (array)$f3->get('POST'); $return = (object) []; @@ -155,13 +154,24 @@ public function import($f3){ isset($importData['typeId']) && count($importData['mapData']) > 0 ){ - $user = $this->_getUser(); + $activeCharacter = $this->getCharacter(); - if($user){ - $activeCharacter = $user->getActiveUserCharacter(); + if($activeCharacter){ + $user = $activeCharacter->getUser(); + /** + * @var $map Model\MapModel + */ $map = Model\BasicModel::getNew('MapModel'); + + /** + * @var $system Model\SystemModel + */ $system = Model\BasicModel::getNew('SystemModel'); + + /** + * @var $connection Model\ConnectionModel + */ $connection = Model\BasicModel::getNew('ConnectionModel'); foreach($importData['mapData'] as $mapData){ @@ -194,8 +204,8 @@ public function import($f3){ $system->setData($systemData); $system->mapId = $map; - $system->createdCharacterId = $activeCharacter->characterId; - $system->updatedCharacterId = $activeCharacter->characterId; + $system->createdCharacterId = $activeCharacter; + $system->updatedCharacterId = $activeCharacter; $system->save(); $tempSystemIdMapping[$oldId] = $system->id; @@ -228,13 +238,11 @@ public function import($f3){ if($map->isPrivate()){ $map->setAccess($user); }elseif($map->isCorporation()){ - $corporation = $activeCharacter->getCharacter()->getCorporation(); - if($corporation){ + if($corporation = $activeCharacter->getCorporation()){ $map->setAccess($corporation); } }elseif($map->isAlliance()){ - $alliance = $activeCharacter->getCharacter()->getAlliance(); - if($alliance){ + if($alliance = $activeCharacter->getAlliance()){ $map->setAccess($alliance); } } @@ -260,7 +268,7 @@ public function import($f3){ } }else{ // user not found - $return->error[] = $this->getUserLoggedOffError(); + $return->error[] = $this->getLogoutError(); } }else{ // map data missing @@ -276,19 +284,23 @@ public function import($f3){ /** * save a new map or update an existing map - * @param $f3 + * @param \Base $f3 */ - public function save($f3){ + public function save(\Base $f3){ $formData = (array)$f3->get('POST.formData'); $return = (object) []; $return->error = []; if( isset($formData['id']) ){ + $activeCharacter = $this->getCharacter(0); - $user = $this->_getUser(0); + if($activeCharacter){ + $user = $activeCharacter->getUser(); - if($user){ + /** + * @var $map Model\MapModel + */ $map = Model\BasicModel::getNew('MapModel'); $map->getById( (int)$formData['id'] ); @@ -311,6 +323,9 @@ public function save($f3){ // clear map access. In case something has removed from access list $map->clearAccess(); + /** + * @var $tempUser Model\UserModel + */ $tempUser = Model\BasicModel::getNew('UserModel'); foreach($accessUsers as $userId){ @@ -331,90 +346,86 @@ public function save($f3){ // just in case he removed himself :) $map->setAccess($user); }elseif($map->isCorporation()){ - $activeCharacter = $user->getActiveUserCharacter(); - - if($activeCharacter){ - $corporation = $activeCharacter->getCharacter()->getCorporation(); + $corporation = $activeCharacter->getCorporation(); - if($corporation){ - // the current user has to have a corporation when - // working on corporation maps! + if($corporation){ + // the current user has to have a corporation when + // working on corporation maps! - // share map between corporations -> set access - if(isset($formData['mapCorporations'])){ - // avoid abuse -> respect share limits - $accessCorporations = array_slice( $formData['mapCorporations'], 0, $f3->get('PATHFINDER.MAX_SHARED_CORPORATION') ); + // share map between corporations -> set access + if(isset($formData['mapCorporations'])){ + // avoid abuse -> respect share limits + $accessCorporations = array_slice( $formData['mapCorporations'], 0, $f3->get('PATHFINDER.MAX_SHARED_CORPORATION') ); - // clear map access. In case something has removed from access list - $map->clearAccess(); + // clear map access. In case something has removed from access list + $map->clearAccess(); - $tempCorporation = Model\BasicModel::getNew('CorporationModel'); + /** + * @var $tempCorporation Model\CorporationModel + */ + $tempCorporation = Model\BasicModel::getNew('CorporationModel'); - foreach($accessCorporations as $corporationId){ - $tempCorporation->getById( (int)$corporationId ); + foreach($accessCorporations as $corporationId){ + $tempCorporation->getById( (int)$corporationId ); - if( - !$tempCorporation->dry() && - $tempCorporation->shared == 1 // check if map shared is enabled - ){ - $map->setAccess($tempCorporation); - } - - $tempCorporation->reset(); + if( + !$tempCorporation->dry() && + $tempCorporation->shared == 1 // check if map shared is enabled + ){ + $map->setAccess($tempCorporation); } - } - // the corporation of the current user should always have access - $map->setAccess($corporation); + $tempCorporation->reset(); + } } + + // the corporation of the current user should always have access + $map->setAccess($corporation); } }elseif($map->isAlliance()){ - $activeCharacter = $user->getActiveUserCharacter(); + $alliance = $activeCharacter->getAlliance(); - if($activeCharacter){ - $alliance = $activeCharacter->getCharacter()->getAlliance(); + if($alliance){ + // the current user has to have a alliance when + // working on alliance maps! - if($alliance){ - // the current user has to have a alliance when - // working on alliance maps! + // share map between alliances -> set access + if(isset($formData['mapAlliances'])){ + // avoid abuse -> respect share limits + $accessAlliances = array_slice( $formData['mapAlliances'], 0, $f3->get('PATHFINDER.MAX_SHARED_ALLIANCE') ); - // share map between alliances -> set access - if(isset($formData['mapAlliances'])){ - // avoid abuse -> respect share limits - $accessAlliances = array_slice( $formData['mapAlliances'], 0, $f3->get('PATHFINDER.MAX_SHARED_ALLIANCE') ); + // clear map access. In case something has removed from access list + $map->clearAccess(); - // clear map access. In case something has removed from access list - $map->clearAccess(); + /** + * @var $tempAlliance Model\AllianceModel + */ + $tempAlliance = Model\BasicModel::getNew('AllianceModel'); - $tempAlliance = Model\BasicModel::getNew('AllianceModel'); + foreach($accessAlliances as $allianceId){ + $tempAlliance->getById( (int)$allianceId ); - foreach($accessAlliances as $allianceId){ - $tempAlliance->getById( (int)$allianceId ); - - if( - !$tempAlliance->dry() && - $tempAlliance->shared == 1 // check if map shared is enabled - ){ - $map->setAccess($tempAlliance); - } - - $tempAlliance->reset(); + if( + !$tempAlliance->dry() && + $tempAlliance->shared == 1 // check if map shared is enabled + ){ + $map->setAccess($tempAlliance); } + $tempAlliance->reset(); } - // the alliance of the current user should always have access - $map->setAccess($alliance); } + + // the alliance of the current user should always have access + $map->setAccess($alliance); } } // reload the same map model (refresh) // this makes sure all data is up2date $map->getById( $map->id, 0 ); - $return->mapData = $map->getData(); - }else{ // map access denied $captchaError = (object) []; @@ -423,7 +434,6 @@ public function save($f3){ $return->error[] = $captchaError; } } - }else{ // map id field missing $idError = (object) []; @@ -437,17 +447,19 @@ public function save($f3){ /** * delete a map and all dependencies - * @param $f3 + * @param \Base $f3 */ - public function delete($f3){ + public function delete(\Base $f3){ $mapData = (array)$f3->get('POST.mapData'); + $activeCharacter = $this->getCharacter(); - $user = $this->_getUser(); - - if($user){ + if($activeCharacter){ + /** + * @var $map Model\MapModel + */ $map = Model\BasicModel::getNew('MapModel'); $map->getById($mapData['id']); - $map->delete($user); + $map->delete( $activeCharacter->getUser() ); } echo json_encode([]); @@ -455,34 +467,28 @@ public function delete($f3){ /** * update map data - * function is called continuously - * @param $f3 + * -> function is called continuously (trigger) by any active client + * @param \Base $f3 */ - public function updateData($f3){ - - // cache time(s) per user should be equal or less than this function is called - // prevent request flooding - $responseTTL = $f3->get('PATHFINDER.TIMER.UPDATE_SERVER_MAP.DELAY') / 1000; + public function updateData(\Base $f3){ $mapData = (array)$f3->get('POST.mapData'); - $user = $this->_getUser(); + $activeCharacter = $this->getCharacter(); + $return = (object) []; $return->error = []; - if($user){ - // -> get active character - $activeCharacter = $user->getActiveUserCharacter(); + if($activeCharacter){ $cacheKey = 'user_map_data_' . $activeCharacter->id; // if there is any system/connection change data submitted -> save new data if( - $f3->exists($cacheKey) === false || + !$f3->exists($cacheKey) || !empty($mapData) ){ - // get current map data ======================================================== - $maps = $user->getMaps(); + $maps = $activeCharacter->getUser()->getMaps(); // loop all submitted map data that should be saved // -> currently there will only be ONE map data change submitted -> single loop @@ -532,7 +538,7 @@ public function updateData($f3){ unset($systemData['updated']); $system = $filteredMap->systems->current(); $system->setData($systemData); - $system->updatedCharacterId = $activeCharacter->characterId; + $system->updatedCharacterId = $activeCharacter; $system->save(); // a system belongs to ONE map -> speed up for multiple maps @@ -561,7 +567,7 @@ public function updateData($f3){ unset($connectionData['updated']); $connection = $filteredMap->connections->current(); $connection->setData($connectionData); - $connection->save($user); + $connection->save(); // a connection belongs to ONE map -> speed up for multiple maps unset($connectionData[$i]); @@ -574,6 +580,11 @@ public function updateData($f3){ // format map Data for return $return->mapData = self::getFormattedMapData($maps); + + // cache time(s) per user should be equal or less than this function is called + // prevent request flooding + $responseTTL = $f3->get('PATHFINDER.TIMER.UPDATE_SERVER_MAP.DELAY') / 1000; + $f3->set($cacheKey, $return, $responseTTL); }else{ // get from cache @@ -582,23 +593,24 @@ public function updateData($f3){ }else{ // user logged off - $return->error[] = $this->getUserLoggedOffError(); + $return->error[] = $this->getLogoutError(); } echo json_encode( $return ); } /** + * get formatted map data * @param $mapModels - * @return Model\MapModel[] + * @return array */ public static function getFormattedMapData($mapModels){ - $mapData = []; - foreach($mapModels as $mapModel){ - + foreach($mapModels as &$mapModel){ + /** + * @var $mapModel Model\MapModel + */ $allMapData = $mapModel->getData(); - $mapData[] = [ 'config' => $allMapData->mapData, 'data' => [ @@ -613,33 +625,23 @@ public static function getFormattedMapData($mapModels){ /** * update map data api - * function is called continuously - * @param $f3 + * -> function is called continuously by any active client + * @param \Base $f3 */ - public function updateUserData($f3){ - - // cache time(s) should be equal or less than request trigger time - // prevent request flooding - $responseTTL = $f3->get('PATHFINDER.TIMER.UPDATE_SERVER_USER_DATA.DELAY') / 1000; - - // if the cache key will be set -> cache request - $cacheKey = null; - + public function updateUserData(\Base $f3){ $return = (object) []; $return->error = []; + $activeCharacter = $this->getCharacter(); - $user = $this->_getUser(); - - if($user){ + if($activeCharacter){ + $user = $activeCharacter->getUser(); if( !empty($f3->get('POST.mapIds')) ){ $mapIds = (array)$f3->get('POST.mapIds'); // check if data for specific system is requested $systemData = (array)$f3->get('POST.systemData'); - - - // update current location (IGB data) - $user->updateCharacterLog(60 * 5); + // update current location + $activeCharacter->updateLog(); // if data is requested extend the cache key in order to get new data $requestSystemData = (object) []; @@ -649,12 +651,11 @@ public function updateUserData($f3){ // IMPORTANT for now -> just update a single map (save performance) $mapIds = array_slice($mapIds, 0, 1); - // the userMasData is cached per map (this must be changed if multiple maps + // the userMapData is cached per map (this must be changed if multiple maps // will be allowed in future... $tempId = (int)$mapIds[0]; $cacheKey = 'user_data_' . $tempId . '_' . $requestSystemData->systemId; - - if( $f3->exists($cacheKey) === false ){ + if( !$f3->exists($cacheKey) ){ foreach($mapIds as $mapId){ $map = $user->getMap($mapId); @@ -666,7 +667,7 @@ public function updateUserData($f3){ $system = $map->getSystem( $requestSystemData->systemId ); if( !is_null($system) ){ - // data for the current selected system + // data for currently selected system $return->system = $system->getData(); $return->system->signatures = $system->getSignaturesData(); } @@ -674,6 +675,10 @@ public function updateUserData($f3){ } } + // cache time (seconds) should be equal or less than request trigger time + // prevent request flooding + $responseTTL = $f3->get('PATHFINDER.TIMER.UPDATE_SERVER_USER_DATA.DELAY') / 1000; + // cache response $f3->set($cacheKey, $return, $responseTTL); }else{ @@ -683,17 +688,14 @@ public function updateUserData($f3){ $return = $f3->get($cacheKey); } } - // get current user data -> this should not be cached because each user has different personal data // even if they have multiple characters using the same map! $return->userData = $user->getData(); - }else{ // user logged off - $return->error[] = $this->getUserLoggedOffError(); + $return->error[] = $this->getLogoutError(); } - echo json_encode( $return ); } diff --git a/app/main/controller/api/signature.php b/app/main/controller/api/signature.php index bd43f3440..6b7292248 100644 --- a/app/main/controller/api/signature.php +++ b/app/main/controller/api/signature.php @@ -14,14 +14,12 @@ class Signature extends \Controller\AccessController{ /** * event handler - * @param $f3 + * @param \Base $f3 */ - function beforeroute($f3) { - - parent::beforeroute($f3); - + function beforeroute(\Base $f3) { // set header for all routes header('Content-type: application/json'); + parent::beforeroute($f3); } /** @@ -31,18 +29,18 @@ function beforeroute($f3) { public function getAll($f3){ $signatureData = []; $systemIds = $f3->get('POST.systemIds'); + $activeCharacter = $this->getCharacter(); - $user = $this->_getUser(); - + /** + * @var Model\SystemModel $system + */ $system = Model\BasicModel::getNew('SystemModel'); - foreach($systemIds as $systemId){ $system->getById($systemId); if(!$system->dry()){ - // check access - if($system->hasAccess($user)){ + if( $system->hasAccess($activeCharacter->getUser()) ){ $signatureData = $system->getSignaturesData(); } } @@ -74,11 +72,14 @@ public function save($f3){ } if( !is_null($signatureData) ){ - $user = $this->_getUser(); + $activeCharacter = $this->getCharacter(); + + if($activeCharacter){ + $user = $activeCharacter->getUser(); - if($user){ - $activeUserCharacter = $user->getActiveUserCharacter(); - $activeCharacter = $activeUserCharacter->getCharacter(); + /** + * @var Model\SystemModel $system + */ $system = Model\BasicModel::getNew('SystemModel'); // update/add all submitted signatures @@ -173,23 +174,23 @@ public function save($f3){ /** * delete signatures - * @param $f3 + * @param \Base $f3 */ public function delete($f3){ $signatureIds = $f3->get('POST.signatureIds'); + $activeCharacter = $this->getCharacter(); - $user = $this->_getUser(); + /** + * @var Model\SystemSignatureModel $signature + */ $signature = Model\BasicModel::getNew('SystemSignatureModel'); - foreach($signatureIds as $signatureId){ $signature->getById($signatureId); - - $signature->delete($user); + $signature->delete( $activeCharacter->getUser() ); $signature->reset(); } echo json_encode([]); } - } \ No newline at end of file diff --git a/app/main/controller/api/system.php b/app/main/controller/api/system.php index 3b2a78f48..ea57f9563 100644 --- a/app/main/controller/api/system.php +++ b/app/main/controller/api/system.php @@ -63,9 +63,9 @@ class System extends \Controller\AccessController { private $limitQuery = ""; /** - * @param $f3 + * @param \Base $f3 */ - function beforeroute($f3) { + function beforeroute(\Base $f3) { parent::beforeroute($f3); @@ -92,7 +92,8 @@ private function _getQuery(){ * get static system Data from CCPs Static DB export * search column for IDs can be (solarSystemID, regionID, constellationID) * @param array $columnIDs - * @return null + * @param string $column + * @return Model\SystemModel[] * @throws \Exception */ protected function _getSystemModelByIds($columnIDs = [], $column = 'solarSystemID'){ @@ -110,10 +111,12 @@ protected function _getSystemModelByIds($columnIDs = [], $column = 'solarSystemI // format result $mapper = new Mapper\CcpSystemsMapper($rows); - $ccpSystemsData = $mapper->getData(); foreach($ccpSystemsData as $ccpSystemData){ + /** + * @var Model\SystemModel $system + */ $system = Model\BasicModel::getNew('SystemModel'); $system->setData($ccpSystemData); $systemModels[] = $system; @@ -142,10 +145,10 @@ public function getSystems(){ /** * search systems by name - * @param $f3 - * @param $params + * @param \Base $f3 + * @param array $params */ - public function search($f3, $params){ + public function search(\Base $f3, $params){ $ccpDB = $this->getDB('CCP'); @@ -172,10 +175,9 @@ public function search($f3, $params){ /** * save a new system to a a map - * @param $f3 + * @param \Base $f3 */ - public function save($f3){ - + public function save(\Base $f3){ $newSystemData = []; $postData = (array)$f3->get('POST'); @@ -187,20 +189,21 @@ public function save($f3){ isset($postData['systemData']) && isset($postData['mapData']) ){ - $user = $this->_getUser(); + $activeCharacter = $this->getCharacter(); - if($user){ + if($activeCharacter){ + $user = $activeCharacter->getUser(); $systemData = (array)$postData['systemData']; $mapData = (array)$postData['mapData']; - $activeCharacter = $user->getActiveUserCharacter(); - if( isset($systemData['id']) ){ // update existing system + /** + * @var $system Model\SystemModel + */ $system = Model\BasicModel::getNew('SystemModel'); $system->getById($systemData['id']); - if( !$system->dry() ){ if( $system->hasAccess($user) ){ // system model found @@ -210,9 +213,11 @@ public function save($f3){ }elseif( isset($mapData['id']) ){ // save NEW system + /** + * @var $map Model\MapModel + */ $map = Model\BasicModel::getNew('MapModel'); $map->getById($mapData['id']); - if( !$map->dry() ){ if( $map->hasAccess($user) ){ @@ -221,7 +226,7 @@ public function save($f3){ // get static system data (CCP DB) $systemModel = array_values( $this->_getSystemModelByIds([$systemData['systemId']]) )[0]; - $systemModel->createdCharacterId = $activeCharacter->characterId; + $systemModel->createdCharacterId = $activeCharacter; } } @@ -229,50 +234,23 @@ public function save($f3){ } } - if( !is_null($systemModel) ){ // set/update system - $systemModel->setData($systemData); - $systemModel->updatedCharacterId = $activeCharacter->characterId; + $systemModel->updatedCharacterId = $activeCharacter; $systemModel->save(); - $newSystemData = $systemModel->getData(); } echo json_encode($newSystemData); } - /** - * delete systems and all its connections - * @param $f3 - */ - public function delete($f3){ - $systemIds = $f3->get('POST.systemIds'); - - $user = $this->_getUser(); - - if($user){ - $system = Model\BasicModel::getNew('SystemModel'); - - foreach((array)$systemIds as $systemId){ - - $system->getById($systemId); - $system->delete($user); - - $system->reset(); - } - } - - echo json_encode([]); - } - /** * get system log data from CCP API import * system Kills, Jumps,.... - * @param $f3 + * @param \Base $f3 */ - public function graphData($f3){ + public function graphData(\Base $f3){ $graphData = []; $systemIds = $f3->get('POST.systemIds'); @@ -288,7 +266,6 @@ public function graphData($f3){ ]; foreach($systemIds as $systemId){ - foreach($logTables as $label => $ModelClass){ $systemLogModel = Model\BasicModel::getNew($ModelClass); @@ -313,7 +290,6 @@ public function graphData($f3){ $counter++; } } - } } @@ -322,25 +298,22 @@ public function graphData($f3){ /** * get system data for all systems within a constellation - * @param $f3 - * @param $params + * @param \Base $f3 + * @param array $params */ - public function constellationData($f3, $params){ - + public function constellationData(\Base $f3, $params){ $return = (object) []; $return->error = []; $return->systemData = []; $constellationId = 0; + $activeCharacter = $this->getCharacter(); - $user = $this->_getUser(); - - if($user){ + if($activeCharacter){ // check for search parameter if( isset($params['arg1']) ){ $constellationId = (int)$params['arg1']; } - $cacheKey = 'CACHE_CONSTELLATION_SYSTEMS_' . self::formatHiveKey($constellationId); if($f3->exists($cacheKey)){ @@ -361,7 +334,29 @@ public function constellationData($f3, $params){ echo json_encode($return); } + /** + * delete systems and all its connections + * @param \Base $f3 + */ + public function delete(\Base $f3){ + $systemIds = $f3->get('POST.systemIds'); + $activeCharacter = $this->getCharacter(); + + if($activeCharacter){ + $user = $activeCharacter->getUser(); + /** + * @var Model\SystemModel $system + */ + $system = Model\BasicModel::getNew('SystemModel'); + foreach((array)$systemIds as $systemId){ + $system->getById($systemId); + $system->delete($user); + $system->reset(); + } + } + echo json_encode([]); + } } diff --git a/app/main/controller/api/user.php b/app/main/controller/api/user.php index ffd1445e0..2014ab475 100644 --- a/app/main/controller/api/user.php +++ b/app/main/controller/api/user.php @@ -15,87 +15,76 @@ class User extends Controller\Controller{ - /** - * valid reasons for captcha images - * @var array - */ - private static $captchaReason = ['createAccount', 'deleteAccount']; - - /** - * login function - * @param $f3 - */ - public function logIn($f3){ - $data = $data = $f3->get('POST'); - - $return = (object) []; + // user specific session keys + const SESSION_KEY_USER = 'SESSION.USER'; + const SESSION_KEY_USER_ID = 'SESSION.USER.ID'; + const SESSION_KEY_USER_NAME = 'SESSION.USER.NAME'; - $user = null; + // character specific session keys + const SESSION_KEY_CHARACTER = 'SESSION.CHARACTER'; + const SESSION_KEY_CHARACTER_ID = 'SESSION.CHARACTER.ID'; + const SESSION_KEY_CHARACTER_NAME = 'SESSION.CHARACTER.NAME'; + const SESSION_KEY_CHARACTER_TIME = 'SESSION.CHARACTER.TIME'; - if($data['loginData']){ - $loginData = $data['loginData']; - $user = $this->logUserIn( $loginData['userName'], $loginData['userPassword'] ); - } + const SESSION_KEY_CHARACTER_ACCESS_TOKEN = 'SESSION.CHARACTER.ACCESS_TOKEN'; + const SESSION_KEY_CHARACTER_REFRESH_TOKEN = 'SESSION.CHARACTER.REFRESH_TOKEN'; - // set "vague" error - if(is_null($user)){ - $return->error = []; - $loginError = (object) []; - $loginError->type = 'login'; - $return->error[] = $loginError; - }else{ - // update/check api data - $user->updateApiData(); - - // route user to map app - $return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $f3->alias('map'); - } - - echo json_encode($return); - } + // log text + const LOG_LOGGED_IN = 'userId: %s, userName: %s, charId: %s, charName: %s'; /** - * core function for user login - * @param $userName - * @param $password - * @return Model\UserModel|null + * valid reasons for captcha images + * @var string array */ - private function logUserIn($userName, $password){ - - // try to verify user - $user = $this->_verifyUser($userName, $password); + private static $captchaReason = ['createAccount', 'deleteAccount']; - if( !is_null($user)){ - // user is verified -> ready for login + /** + * login a valid character + * @param Model\CharacterModel $characterModel + * @return bool + */ + protected function loginByCharacter(Model\CharacterModel &$characterModel){ + $login = false; + + if($user = $characterModel->getUser()){ + // set user/character data to session ------------------- + $this->f3->set(self::SESSION_KEY_USER, [ + 'ID' => $user->_id, + 'NAME' => $user->name + ]); - // set Session login $dateTime = new \DateTime(); - - $this->f3->set('SESSION.user', [ - 'time' => $dateTime->getTimestamp(), - 'name' => $user->name, - 'id' => $user->id + $this->f3->set(self::SESSION_KEY_CHARACTER, [ + 'ID' => $characterModel->_id, + 'NAME' => $characterModel->name, + 'TIME' => $dateTime->getTimestamp() ]); - // save user login information - $user->touch('lastLogin'); - $user->save(); + // save user login information --------------------------- + $characterModel->touch('lastLogin'); + $characterModel->save(); - // save log - $logText = "id: %s, name: %s, ip: %s"; + // write login log -------------------------------------- self::getLogger( $this->f3->get('PATHFINDER.LOGFILES.LOGIN') )->write( - sprintf($logText, $user->id, $user->name, $this->f3->get('IP')) + sprintf(self::LOG_LOGGED_IN, + $user->_id, + $user->name, + $characterModel->_id, + $characterModel->name + ) ); + + $login = true; } - return $user; + return $login; } /** * get captcha image and store key to session - * @param $f3 + * @param \Base $f3 */ - public function getCaptcha($f3){ + public function getCaptcha(\Base $f3){ $data = $f3->get('POST'); $return = (object) []; @@ -136,29 +125,22 @@ public function getCaptcha($f3){ /** * delete the character log entry for the current active (main) character - * @param $f3 + * @param \Base $f3 */ - public function deleteLog($f3){ - - $user = $this->_getUser(); - if($user){ - $activeUserCharacter = $user->getActiveUserCharacter(); - - if($activeUserCharacter){ - $character = $activeUserCharacter->getCharacter(); - - if($characterLog = $character->getLog()){ - $characterLog->erase(); - } + public function deleteLog(\Base $f3){ + $activeCharacter = $this->getCharacter(); + if($activeCharacter){ + if($characterLog = $activeCharacter->getLog()){ + $characterLog->erase(); } } } /** * log the current user out + clear character system log data - * @param $f3 + * @param \Base $f3 */ - public function logOut($f3){ + public function logOut(\Base $f3){ $this->deleteLog($f3); parent::logOut($f3); } @@ -166,9 +148,9 @@ public function logOut($f3){ /** * save/update "map sharing" configurations for all map types * the user has access to - * @param $f3 + * @param \Base $f3 */ - public function saveSharingConfig($f3){ + public function saveSharingConfig(\Base $f3){ $data = $f3->get('POST'); $return = (object) []; @@ -177,9 +159,10 @@ public function saveSharingConfig($f3){ $corporationSharing = 0; $allianceSharing = 0; - $user = $this->_getUser(); + $activeCharacter = $this->getCharacter(); - if($user){ + if($activeCharacter){ + $user = $activeCharacter->getUser(); // form values if(isset($data['formData'])){ @@ -202,22 +185,17 @@ public function saveSharingConfig($f3){ $user->save(); // update corp/ally --------------------------------------------------------------- + $corporation = $activeCharacter->getCorporation(); + $alliance = $activeCharacter->getAlliance(); - $activeUserCharacter = $user->getActiveUserCharacter(); - - if(is_object($activeUserCharacter)){ - $corporation = $activeUserCharacter->getCharacter()->getCorporation(); - $alliance = $activeUserCharacter->getCharacter()->getAlliance(); - - if(is_object($corporation)){ - $corporation->shared = $corporationSharing; - $corporation->save(); - } + if(is_object($corporation)){ + $corporation->shared = $corporationSharing; + $corporation->save(); + } - if(is_object($alliance)){ - $alliance->shared = $allianceSharing; - $alliance->save(); - } + if(is_object($alliance)){ + $alliance->shared = $allianceSharing; + $alliance->save(); } $return->userData = $user->getData(); @@ -282,9 +260,9 @@ protected function findRegistrationKey($email, $used = false){ /** * save/update user account data - * @param $f3 + * @param \Base $f3 */ - public function saveAccount($f3){ + public function saveAccount(\Base $f3){ $data = $f3->get('POST'); $return = (object) []; @@ -308,7 +286,8 @@ public function saveAccount($f3){ $settingsData = $data['settingsData']; try{ - $user = $this->_getUser(0); + $activeCharacter = $this->getCharacter(0); + $user = $activeCharacter->getUser(); // captcha is send -> check captcha if( @@ -320,7 +299,7 @@ public function saveAccount($f3){ if($settingsData['captcha'] === $captcha){ // change/set sensitive user data requires captcha! - if($user === false){ + if(is_null($user)){ // check if registration key invite function is enabled if($f3->get('PATHFINDER.REGISTRATION.INVITE') === 1 ){ @@ -332,7 +311,7 @@ public function saveAccount($f3){ } // new user registration - $user = $mapType = Model\BasicModel::getNew('UserModel'); + $user = Model\BasicModel::getNew('UserModel'); $loginAfterSave = true; // set username @@ -429,7 +408,7 @@ public function saveAccount($f3){ } // get fresh updated user object (API info may have has changed) - $user = $this->_getUser(0); + //$user = $this->_getUser(0); } // set main character @@ -457,14 +436,13 @@ public function saveAccount($f3){ // log user in (in case he is new if($loginAfterSave){ - $this->logUserIn( $user->name, $settingsData['password'] ); + $this->logInByData( $user->name, $settingsData['password'] ); // return reroute path $return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $this->f3->alias('map'); } // get fresh updated user object - $user = $this->_getUser(0); $newUserData = $user->getData(); } }catch(Exception\ValidationException $e){ @@ -491,10 +469,10 @@ public function saveAccount($f3){ /** * send mail with registration key * -> check INVITE in pathfinder.ini - * @param $f3 + * @param \Base $f3 * @throws Exception */ - public function sendInvite($f3){ + public function sendInvite(\Base $f3){ $data = $f3->get('POST.settingsData'); $return = (object) []; @@ -593,9 +571,9 @@ public function sendInvite($f3){ /** * delete current user account from DB - * @param $f3 + * @param \Base $f3 */ - public function deleteAccount($f3){ + public function deleteAccount(\Base $f3){ $data = $f3->get('POST.formData'); $return = (object) []; @@ -609,8 +587,8 @@ public function deleteAccount($f3){ !empty($data['captcha']) && $data['captcha'] === $captcha ){ - $user = $this->_getUser(0); - + $activeCharacter = $this->getCharacter(0); + $user = $activeCharacter->getUser(); $validUser = $this->_verifyUser( $user->name, $data['password']); if( diff --git a/app/main/controller/appcontroller.php b/app/main/controller/appcontroller.php index 62aec0c8f..8317796bd 100644 --- a/app/main/controller/appcontroller.php +++ b/app/main/controller/appcontroller.php @@ -7,15 +7,26 @@ */ namespace Controller; - +use Controller\Ccp as Ccp; class AppController extends Controller { + /** + * event handler after routing + * @param \Base $f3 + */ + public function afterroute(\Base $f3){ + parent::afterroute($f3); + + // clear all SSO related temp data + $f3->clear(Ccp\Sso::SESSION_KEY_SSO); + } + /** * show main login (index) page - * @param $f3 + * @param \Base $f3 */ - public function init($f3) { + public function init(\Base $f3) { // page title $f3->set('pageTitle', 'Login'); diff --git a/app/main/controller/ccp/sso.php b/app/main/controller/ccp/sso.php new file mode 100644 index 000000000..956d80504 --- /dev/null +++ b/app/main/controller/ccp/sso.php @@ -0,0 +1,604 @@ +request automatically caches responses by their response "Cache-Control" header! + */ + +namespace Controller\Ccp; +use Controller; +use Controller\Api as Api; +use Data\Mapper as Mapper; +use Model; +use Lib; + +class Sso extends Api\User{ + + /** + * @var int timeout (seconds) for API calls + */ + const CREST_TIMEOUT = 3; + + /** + * @var int expire time (seconds) for an valid "accessToken" + */ + const ACCESS_KEY_EXPIRE_TIME = 20 * 60; + + // SSO specific session keys + const SESSION_KEY_SSO = 'SESSION.SSO'; + const SESSION_KEY_SSO_ERROR = 'SESSION.SSO.ERROR'; + const SESSION_KEY_SSO_STATE = 'SESSION.SSO.STATE'; + + // error messages + const ERROR_CCP_SSO_URL = 'Invalid "ENVIRONMENT.[ENVIRONMENT].SSO_CCP_URL" url. %s'; + const ERROR_CCP_CREST_URL = 'Invalid "ENVIRONMENT.[ENVIRONMENT].CCP_CREST_URL" url. %s'; + const ERROR_RESOURCE_DEPRECATED = 'Resource: %s has been marked as deprecated. %s'; + const ERROR_ACCESS_TOKEN = 'Unable to get a valid "access_token. %s'; + const ERROR_VERIFY_CHARACTER = 'Unable to verify character data. %s'; + const ERROR_GET_ENDPOINT = 'Unable to get endpoint data. $s'; + const ERROR_FIND_ENDPOINT = 'Unable to find endpoint: %s'; + const ERROR_LOGIN_FAILED = 'Failed authentication due to technical problems: %s'; + + /** + * CREST "Scopes" are used by pathfinder + * -> Enable scopes: https://developers.eveonline.com + * @var array + */ + private $requestScopes = [ + // 'characterFittingsRead', + // 'characterFittingsWrite', + 'characterLocationRead', + 'characterNavigationWrite' + ]; + + /** + * redirect user to CCP SSO page and request authorization + * @param \Base $f3 + */ + public function requestAuthorization($f3){ + + // used for "state" check between request and callback + $state = bin2hex(mcrypt_create_iv(12, MCRYPT_DEV_URANDOM)); + $f3->set(self::SESSION_KEY_SSO_STATE, $state); + + $urlParams = [ + 'response_type' => 'code', + 'redirect_uri' => Controller\Controller::getEnvironmentData('URL') . $f3->build('/sso/callbackAuthorization'), + 'client_id' => Controller\Controller::getEnvironmentData('SSO_CCP_CLIENT_ID'), + 'scope' => implode(' ', $this->requestScopes), + 'state' => $state + ]; + + $ssoAuthUrl = self::getAuthorizationEndpoint() . '?' . http_build_query($urlParams, '', '&', PHP_QUERY_RFC3986 ); + + $f3->status(302); + $f3->reroute($ssoAuthUrl); + } + + /** + * callback handler for CCP SSO user Auth + * -> see requestAuthorization() + * @param \Base $f3 + */ + public function callbackAuthorization($f3){ + $getParams = (array)$f3->get('GET'); + + if($f3->exists(self::SESSION_KEY_SSO_STATE)){ + // check response and validate 'state' + if( + isset($getParams['code']) && + isset($getParams['state']) && + !empty($getParams['code']) && + !empty($getParams['state']) && + $f3->get(self::SESSION_KEY_SSO_STATE) === $getParams['state'] + ){ + // clear 'state' for new next request + $f3->clear(self::SESSION_KEY_SSO_STATE); + + $accessData = $this->getCrestAccessData($getParams['code']); + + if( + isset($accessData->accessToken) && + isset($accessData->refreshToken) + ){ + // login succeeded -> get basic character data for current login + $verificationCharacterData = $this->verifyCharacterData($accessData->accessToken); + + if( !is_null($verificationCharacterData)){ + // verification data available. Data is needed for "ownerHash" check + + // get character data from CREST + $characterData = $this->getCharacterData($accessData->accessToken); + + if(isset($characterData->character)){ + // add "ownerHash" and CREST tokens + $characterData->character['ownerHash'] = $verificationCharacterData->CharacterOwnerHash; + $characterData->character['crestAccessToken'] = $accessData->accessToken; + $characterData->character['crestRefreshToken'] = $accessData->refreshToken; + + // add/update static character data + $characterModel = $this->updateCharacter($characterData); + + if( !is_null($characterModel) ){ + // check if character is authorized to log in + if($characterModel->isAuthorized()){ + + // character is authorized to log in + // -> update character log (current location,...) + $characterModel = $characterModel->updateLog(); + + // check if there is already a user created who owns this char + $user = $characterModel->getUser(); + + if(is_null($user)){ + // no user found -> create one and connect to character + /** + * @var Model\UserModel $user + */ + $user = Model\BasicModel::getNew('UserModel'); + $user->name = $characterModel->name; + $user->save(); + + /** + * @var Model\UserCharacterModel $userCharactersModel + */ + $userCharactersModel = Model\BasicModel::getNew('UserCharacterModel'); + $userCharactersModel->userId = $user; + $userCharactersModel->characterId = $characterModel; + $userCharactersModel->save(); + + // get updated character model + $characterModel = $userCharactersModel->getCharacter(); + } + + // login by character + $loginCheck = $this->loginByCharacter($characterModel); + + if($loginCheck){ + // route to "map" + $f3->reroute('@map'); + }else{ + $f3->set(self::SESSION_KEY_SSO_ERROR, sprintf(self::ERROR_LOGIN_FAILED, $characterModel->name)); + } + }else{ + // character is not authorized to log in + $f3->set(self::SESSION_KEY_SSO_ERROR, 'Character "' . $characterModel->name . '" is not authorized to log in.'); + } + } + } + } + } + } + } + + // on error -> route back to login form + $f3->reroute('@login'); + } + + /** + * get a valid "access_token" for oAuth 2.0 verification + * -> if $authCode is set -> request NEW "access_token" + * -> else check for existing (not expired) "access_token" + * -> else try to refresh auth and get fresh "access_token" + * @param bool $authCode + * @return null|\stdClass + */ + public function getCrestAccessData($authCode){ + $accessData = null; + + if( !empty($authCode) ){ + // Authentication Code is set -> request new "accessToken" + $accessData = $this->verifyAuthorizationCode($authCode); + }else{ + // Unable to get Token -> trigger error + self::getCrestLogger()->write(sprintf(self::ERROR_ACCESS_TOKEN, $authCode)); + } + + return $accessData; + } + + /** + * verify authorization code, and get an "access_token" data + * @param $authCode + * @return \stdClass + */ + protected function verifyAuthorizationCode($authCode){ + $requestParams = [ + 'grant_type' => 'authorization_code', + 'code' => $authCode + ]; + + return $this->requestAccessData($requestParams); + } + + /** + * get new "access_token" by an existing "refresh_token" + * -> if "access_token" is expired, this function gets a fresh one + * @param $refreshToken + * @return \stdClass + */ + public function refreshAccessToken($refreshToken){ + $requestParams = [ + 'grant_type' => 'refresh_token', + 'refresh_token' => $refreshToken + ]; + + return $this->requestAccessData($requestParams); + } + + /** + * request an "access_token" AND "refresh_token" data + * -> this can either be done by sending a valid "authorization code" + * OR by providing a valid "refresh_token" + * @param $requestParams + * @return \stdClass + */ + protected function requestAccessData($requestParams){ + $verifyAuthCodeUrl = self::getVerifyAuthorizationCodeEndpoint(); + $verifyAuthCodeUrlParts = parse_url($verifyAuthCodeUrl); + + $accessData = (object) []; + $accessData->accessToken = null; + $accessData->refreshToken = null; + + if($verifyAuthCodeUrlParts){ + $contentType = 'application/x-www-form-urlencoded'; + $requestOptions = [ + 'timeout' => self::CREST_TIMEOUT, + 'method' => 'POST', + 'user_agent' => $this->getUserAgent(), + 'header' => [ + 'Authorization: Basic ' . $this->getAuthorizationHeader(), + 'Content-Type: ' . $contentType, + 'Host: ' . $verifyAuthCodeUrlParts['host'] + ] + ]; + + // content (parameters to send with) + $requestOptions['content'] = http_build_query($requestParams); + + $apiResponse = Lib\Web::instance()->request($verifyAuthCodeUrl, $requestOptions); + + if($apiResponse['body']){ + $authCodeRequestData = json_decode($apiResponse['body']); + + if(isset($authCodeRequestData->access_token)){ + // this token is required for endpoints that require Auth + $accessData->accessToken = $authCodeRequestData->access_token; + } + + if(isset($authCodeRequestData->refresh_token)){ + // this token is used to refresh/get a new access_token when expires + $accessData->refreshToken = $authCodeRequestData->refresh_token; + } + }else{ + self::getCrestLogger()->write( + sprintf( + self::ERROR_ACCESS_TOKEN, + print_r($requestParams, true) + ) + ); + } + }else{ + self::getCrestLogger()->write( + sprintf(self::ERROR_CCP_SSO_URL, __METHOD__) + ); + } + + return $accessData; + } + + /** + * verify character data by "access_token" + * -> get some basic information (like character id) + * -> if more character information is required, use CREST endpoints request instead + * @param $accessToken + * @return mixed|null + */ + protected function verifyCharacterData($accessToken){ + $verifyUserUrl = self::getVerifyUserEndpoint(); + $verifyUrlParts = parse_url($verifyUserUrl); + $characterData = null; + + if($verifyUrlParts){ + $requestOptions = [ + 'timeout' => self::CREST_TIMEOUT, + 'method' => 'GET', + 'user_agent' => $this->getUserAgent(), + 'header' => [ + 'Authorization: Bearer ' . $accessToken, + 'Host: ' . $verifyUrlParts['host'] + ] + ]; + + $apiResponse = Lib\Web::instance()->request($verifyUserUrl, $requestOptions); + + if($apiResponse['body']){ + $characterData = json_decode($apiResponse['body']); + }else{ + self::getCrestLogger()->write(sprintf(self::ERROR_VERIFY_CHARACTER, __METHOD__)); + } + }else{ + self::getCrestLogger()->write(sprintf(self::ERROR_CCP_SSO_URL, __METHOD__)); + } + + return $characterData; + } + + /** + * get all available Endpoints + * @param $accessToken + * @return mixed|null + */ + protected function getEndpoints($accessToken){ + $crestUrl = self::getCrestEndpoint(); + $contentType = 'application/vnd.ccp.eve.Api-v3+json'; + $endpoint = $this->getEndpoint($accessToken, $crestUrl, $contentType); + + return $endpoint; + } + + /** + * get a specific endpoint by its $resourceUrl + * @param $accessToken + * @param $resourceUrl + * @param string $contentType + * @return mixed|null + */ + protected function getEndpoint($accessToken, $resourceUrl, $contentType = ''){ + $resourceUrlParts = parse_url($resourceUrl); + $endpoint = null; + + if($resourceUrlParts){ + $requestOptions = [ + 'timeout' => self::CREST_TIMEOUT, + 'method' => 'GET', + 'user_agent' => $this->getUserAgent(), + 'header' => [ + 'Authorization: Bearer ' . $accessToken, + 'Host: login.eveonline.com', + 'Host: ' . $resourceUrlParts['host'] + ] + ]; + + // if specific contentType is required -> add it to request header + // CREST versioning can be done by calling different "Accept:" Headers + if( !empty($contentType) ){ + $requestOptions['header'][] = 'Accept: ' . $contentType; + } + + $apiResponse = Lib\Web::instance()->request($resourceUrl, $requestOptions); + + if($apiResponse['headers']){ + // check headers for error + $this->checkResponseHeaders($apiResponse['headers'], $requestOptions); + + if($apiResponse['body']){ + $endpoint = json_decode($apiResponse['body'], true); + }else{ + self::getCrestLogger()->write(sprintf(self::ERROR_GET_ENDPOINT, __METHOD__)); + } + } + }else{ + self::getCrestLogger()->write(sprintf(self::ERROR_CCP_CREST_URL, __METHOD__)); + } + + return $endpoint; + } + + /** + * recursively walk down the CREST API tree by a given $path array + * -> return "leaf" endpoint + * @param $accessToken + * @param $endpoint + * @param array $path + * @return null|string + */ + protected function walkEndpoint($accessToken, $endpoint, $path = []){ + $targetEndpoint = null; + + if( !empty($path) ){ + $newNode = array_shift($path); + if(isset($endpoint[$newNode])){ + $currentEndpoint = $endpoint[$newNode]; + if(isset($currentEndpoint['href'])){ + $newEndpoint = $this->getEndpoint($accessToken, $currentEndpoint['href']); + $targetEndpoint = $this->walkEndpoint($accessToken, $newEndpoint, $path); + }else{ + // leaf found + $targetEndpoint = $currentEndpoint; + } + }else{ + // endpoint not found + self::getCrestLogger()->write(sprintf(self::ERROR_FIND_ENDPOINT, $newNode)); + } + }else{ + $targetEndpoint = $endpoint; + } + + return $targetEndpoint; + } + + /** + * get character data + * @param $accessToken + * @return array + */ + protected function getCharacterData($accessToken){ + $endpoints = $this->getEndpoints($accessToken); + $characterData = (object) []; + + $endpoint = $this->walkEndpoint($accessToken, $endpoints, [ + 'decode', + 'character' + ]); + + if( !empty($endpoint) ){ + $characterData->character = (new Mapper\CrestCharacter($endpoint))->getData(); + if(isset($endpoint['corporation'])){ + $characterData->corporation = (new Mapper\CrestCorporation($endpoint['corporation']))->getData(); + } + } + + return $characterData; + } + + /** + * get current character location data + * -> solarSystem data where character is currently active + * @param $accessToken + * @return object + */ + public function getCharacterLocationData($accessToken){ + $endpoints = $this->getEndpoints($accessToken); + $locationData = (object) []; + + $endpoint = $this->walkEndpoint($accessToken, $endpoints, [ + 'decode', + 'character', + 'location' + ]); + + if( !empty($endpoint) ){ + if(isset($endpoint['solarSystem'])){ + $locationData->system = (new Mapper\CrestSystem($endpoint['solarSystem']))->getData(); + } + } + + return $locationData; + } + + /** + * update character + * @param $characterData + * @return \Model\CharacterModel + * @throws \Exception + */ + protected function updateCharacter($characterData){ + + $characterModel = null; + $corporationModel = null; + $allianceModel = null; + + if( isset($characterData->corporation) ){ + /** + * @var Model\CorporationModel $corporationModel + */ + $corporationModel = Model\BasicModel::getNew('CorporationModel'); + $corporationModel->getById($characterData->corporation['id'], 0); + $corporationModel->copyfrom($characterData->corporation); + $corporationModel->save(); + } + + if( isset($characterData->alliance) ){ + /** + * @var Model\AllianceModel $allianceModel + */ + $allianceModel = Model\BasicModel::getNew('AllianceModel'); + $allianceModel->getById($characterData->alliance['id'], 0); + $allianceModel->copyfrom($characterData->alliance); + $allianceModel->save(); + } + + if( isset($characterData->character) ){ + /** + * @var Model\CharacterModel $characterModel + */ + $characterModel = Model\BasicModel::getNew('CharacterModel'); + $characterModel->getById($characterData->character['id'], 0); + $characterModel->copyfrom($characterData->character); + $characterModel->corporationId = $corporationModel; + $characterModel->allianceId = $allianceModel; + $characterModel = $characterModel->save(); + } + + return $characterModel; + } + + /** + * check response "Header" data for errors + * @param $headers + * @param string $requestUrl + * @param string $contentType + */ + protected function checkResponseHeaders($headers, $requestUrl = '', $contentType = ''){ + $headers = (array)$headers; + if(preg_grep ('/^X-Deprecated/i', $headers)){ + self::getCrestLogger()->write(sprintf(self::ERROR_RESOURCE_DEPRECATED, $requestUrl, $contentType)); + } + } + + /** + * get "Authorization:" Header data + * -> This header is required for any Auth-required endpoints! + * @return string + */ + protected function getAuthorizationHeader(){ + return base64_encode( + Controller\Controller::getEnvironmentData('SSO_CCP_CLIENT_ID') . ':' + . Controller\Controller::getEnvironmentData('SSO_CCP_SECRET_KEY') + ); + } + + /** + * get CCP CREST url from configuration file + * -> throw error if url is broken/missing + * @return string + */ + static function getCrestEndpoint(){ + $url = ''; + if( \Audit::instance()->url(self::getEnvironmentData('CCP_CREST_URL')) ){ + $url = self::getEnvironmentData('CCP_CREST_URL'); + }else{ + $error = sprintf(self::ERROR_CCP_CREST_URL, __METHOD__); + self::getCrestLogger()->write($error); + \Base::instance()->error(502, $error); + } + + return $url; + } + + /** + * get CCP SSO url from configuration file + * -> throw error if url is broken/missing + * @return string + */ + static function getSsoUrlRoot(){ + $url = ''; + if( \Audit::instance()->url(self::getEnvironmentData('SSO_CCP_URL')) ){ + $url = self::getEnvironmentData('SSO_CCP_URL'); + }else{ + $error = sprintf(self::ERROR_CCP_SSO_URL, __METHOD__); + self::getCrestLogger()->write($error); + \Base::instance()->error(502, $error); + } + + return $url; + } + + static function getAuthorizationEndpoint(){ + return self::getSsoUrlRoot() . '/oauth/authorize'; + } + + static function getVerifyAuthorizationCodeEndpoint(){ + return self::getSsoUrlRoot() . '/oauth/token'; + } + + static function getVerifyUserEndpoint(){ + return self::getSsoUrlRoot() . '/oauth/verify'; + } + + /** + * get logger for CREST logging + * @return \Log + */ + static function getCrestLogger(){ + return parent::getLogger('crest'); + } +} \ No newline at end of file diff --git a/app/main/controller/ccpapicontroller.php b/app/main/controller/ccpapicontroller.php deleted file mode 100644 index 1e3729408..000000000 --- a/app/main/controller/ccpapicontroller.php +++ /dev/null @@ -1,184 +0,0 @@ - 8, - 'method' => 'POST', - 'user_agent' => $this->getUserAgent(), - 'follow_location' => false // otherwise CURLOPT_FOLLOWLOCATION will fail - ]; - - return $requestOptions; - } - - /** - * request character information from CCP API - * @param $keyID - * @param $vCode - * @return bool|\SimpleXMLElement - */ - public function requestCharacters($keyID, $vCode){ - - $apiPath = $this->getF3()->get('PATHFINDER.API.CCP_XML') . '/account/APIKeyInfo.xml.aspx'; - - $xml = false; - - // build request URL - $options = $this->getRequestOptions(); - $options['content'] = http_build_query( [ - 'keyID' => $keyID, - 'vCode' => $vCode - ]); - - $apiResponse = \Web::instance()->request($apiPath, $options ); - - if($apiResponse['body']){ - $xml = simplexml_load_string($apiResponse['body']); - } - - return $xml; - } - - /** - * update all character information for a given apiModel - * @param $userApiModel - * @return int - * @throws \Exception - */ - public function updateCharacters($userApiModel){ - - $xml = $this->requestCharacters($userApiModel->keyId, $userApiModel->vCode); - - $characterCount = 0; - - // important -> user API model must be up2date - // if not -> matched userCharacter cant be found - $userApiModel->getById($userApiModel->id, 0); - - if($xml){ - // request successful - $rowApiData = $xml->result->key->rowset; - - if( - is_object($rowApiData) && - $rowApiData->children() - ){ - $characterModel = Model\BasicModel::getNew('CharacterModel'); - $corporationModel = Model\BasicModel::getNew('CorporationModel'); - $allianceModel = Model\BasicModel::getNew('AllianceModel'); - - foreach($rowApiData->children() as $characterApiData){ - // map attributes to array - $attributeData = current( $characterApiData->attributes() ); - - $newCharacter = true; - - $characterId = (int)$attributeData['characterID']; - $characterModel->getById($characterId, 0); - - $corporationModelTemp = null; - $allianceModelTemp = null; - - // check if corporation already exists - if($attributeData['corporationID'] > 0){ - $corporationModel->getById($attributeData['corporationID'], 0); - if( $corporationModel->dry() ){ - $corporationModel->id = $attributeData['corporationID']; - $corporationModel->name = $attributeData['corporationName']; - $corporationModel->save(); - } - $corporationModelTemp = $corporationModel; - } - - // check if alliance already exists - if($attributeData['allianceID'] > 0){ - $allianceModel->getById($attributeData['allianceID'], 0); - if( $allianceModel->dry() ){ - $allianceModel->id = $attributeData['allianceID']; - $allianceModel->name = $attributeData['allianceName']; - $allianceModel->save(); - } - $allianceModelTemp = $allianceModel; - } - - if($userApiModel->userCharacters){ - $userApiModel->userCharacters->rewind(); - while($userApiModel->userCharacters->valid()){ - $tempCharacterModel = $userApiModel->userCharacters->current()->getCharacter(); - - // character already exists -> update - if($tempCharacterModel->id == $characterId){ - $characterModel = $tempCharacterModel; - - // unset userCharacter -> all leftover models are no longer part of this API - // --> delete leftover models at the end - $userApiModel->userCharacters->offsetUnset($userApiModel->userCharacters->key()); - - $newCharacter = false; - break; - }else{ - $userApiModel->userCharacters->next(); - } - } - $userApiModel->userCharacters->rewind(); - } - - $characterModel->id = $characterId; - $characterModel->name = $attributeData['characterName']; - $characterModel->corporationId = $corporationModelTemp; - $characterModel->allianceId = $allianceModelTemp; - $characterModel->factionId = $attributeData['factionID']; - $characterModel->factionName = $attributeData['factionName']; - $characterModel->save(); - - if($newCharacter){ - // new character for this API - $userCharactersModel = Model\BasicModel::getNew('UserCharacterModel', 0); - $userCharactersModel->userId = $userApiModel->userId; - $userCharactersModel->apiId = $userApiModel; - $userCharactersModel->characterId = $characterModel; - $userCharactersModel->save(); - } - - $corporationModel->reset(); - $allianceModel->reset(); - $characterModel->reset(); - - $characterCount++; - } - } - - // delete leftover userCharacters from this API - if(count($userApiModel->userCharacters) > 0){ - while($userApiModel->userCharacters->valid()){ - $userApiModel->userCharacters->current()->erase(); - $userApiModel->userCharacters->next(); - } - } - - } - - return $characterCount; - } - -} \ No newline at end of file diff --git a/app/main/controller/ccpssocontroller.php b/app/main/controller/ccpssocontroller.php deleted file mode 100644 index f5f95ce32..000000000 --- a/app/main/controller/ccpssocontroller.php +++ /dev/null @@ -1,503 +0,0 @@ -request automatically caches responses by their response "Cache-Control" header! - */ - -namespace Controller; - -use Data\Mapper as Mapper; -use Model; - -class CcpSsoController extends Controller { - - const SESSION_KEY_ACCESS_TOKEN = 'SESSION.sso.access_token'; - const SESSION_KEY_REFRESH_TOKEN = 'SESSION.sso.refresh_token'; - - const ERROR_CCP_SSO_URL = 'Invalid "PATHFINDER.API.CCP_SSO" url. %s'; - const ERROR_CCP_CREST_URL = 'Invalid "PATHFINDER.API.CCP_CREST" url. %s'; - const ERROR_RESOURCE_DEPRECATED = 'Resource: %s has been marked deprecated. %s'; - const ERROR_ACCESS_TOKEN = 'Unable to get a valid "access_token. %s'; - const ERROR_VERIFY_CHARACTER = 'Unable to verify character data. %s'; - const ERROR_GET_ENDPOINTS = 'Unable to get endpoints data. $s'; - const ERROR_GET_ENDPOINT = 'Unable to get endpoint data. $s'; - const ERROR_FIND_ENDPOINT = 'Unable to find endpoint: %s'; - - /** - * "Scopes" that are used by pathfinder - * -> Enable scopes: https://developers.eveonline.com - * @var array - */ - private $requestScopes = [ - 'characterLocationRead', - 'characterNavigationWrite' - ]; - - /** - * timeout for API calls - * @var int - */ - private $apiTimeout = 3; - - /** - * redirect user to CCP SSO page and request authorization - * @param $f3 - */ - public function requestAuthorization($f3){ - // used for state check between request and callback - $state = bin2hex(mcrypt_create_iv(12, MCRYPT_DEV_URANDOM)); - $f3->set('SESSION.sso.state', $state); - - $urlParams = [ - 'response_type' => 'code', - 'redirect_uri' => Controller::getEnvironmentData('URL') . $f3->build('/sso/callbackAuthorization'), - 'client_id' => Controller::getEnvironmentData('SSO_CCP_CLIENT_ID'), - 'scope' => implode(' ', $this->requestScopes), - 'state' => $state - ]; - - $ssoAuthUrl = self::getAuthorizationEndpoint() . '?' . http_build_query($urlParams, '', '&', PHP_QUERY_RFC3986 ); - - $f3->status(302); - $f3->reroute($ssoAuthUrl); - } - - /** - * callback handler for CCP SSO user Auth - * -> see requestAuthorization() - * @param $f3 - */ - public function callbackAuthorization($f3){ - $getParams = (array)$f3->get('GET'); - - if($f3->exists('SESSION.sso.state')){ - // check response and validate 'state' - if( - isset($getParams['code']) && - isset($getParams['state']) && - !empty($getParams['code']) && - !empty($getParams['state']) && - $f3->get('SESSION.sso.state') === $getParams['state'] - ){ - - // clear 'state' for new next request - $f3->clear('SESSION.sso.state'); - - $accessToken = $this->getAccessToken($getParams['code']); - if($accessToken){ - $data = $this->verifyCharacterData($accessToken); - - $characterData = $this->getCharacterData($accessToken); - $characterModel = $this->updateCharacter($characterData); - - if( !is_null($characterModel) ){ - // everything OK -> login succeeded - var_dump( $characterModel->cast() ); - die(); - - } - } - } - } - - // on error -> route back to login form - $this->getF3()->reroute('@login'); - } - - /** - * get a valid "access_token" for oAuth 2.0 verification - * -> if $authCode is set -> request NEW "access_token" - * -> else check for existing (not expired) "access_token" - * -> else try to refresh auth and get fresh "access_token" - * @param bool $authCode - * @return bool|mixed - */ - private function getAccessToken($authCode = false){ - $accessToken = false; - - if( !empty($authCode) ){ - // Authentication Code is set -> request new Access Token ------------------------------------------------- - - // clear "old" token (if exist and still valid) - $this->getF3()->clear(self::SESSION_KEY_ACCESS_TOKEN); - - $accessToken = $this->verifyAuthorizationCode($authCode); - }elseif($this->getF3()->exists(self::SESSION_KEY_ACCESS_TOKEN)){ - // Access Token exists and not expired -------------------------------------------------------------------- - $accessToken = $this->getF3()->get(self::SESSION_KEY_ACCESS_TOKEN); - }elseif($this->getF3()->exists(self::SESSION_KEY_REFRESH_TOKEN)){ - // Refresh Token exists -> refresh Access Token ----------------------------------------------------------- - $accessToken = $this->refreshAccessToken($this->getF3()->get(self::SESSION_KEY_REFRESH_TOKEN)); - }else{ - // Unable to get Token -> trigger error ------------------------------------------------------------------- - $this->getLogger('error')->write(sprintf(self::ERROR_ACCESS_TOKEN, $authCode)); - } - - return $accessToken; - } - - /** - * verify authorization code, and get an "access_token" data - * @param $authCode - * @return bool|mixed - */ - private function verifyAuthorizationCode($authCode){ - $requestParams = [ - 'grant_type' => 'authorization_code', - 'code' => $authCode - ]; - - return $this->requestAccessToken($requestParams); - } - - /** - * get new "access_token" by an existing "refresh_token" - * -> if "access_token" is expired, this function gets a fresh one - * @param $refreshToken - * @return bool|mixed - */ - private function refreshAccessToken($refreshToken){ - $requestParams = [ - 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken - ]; - - return $this->requestAccessToken($requestParams); - } - - /** - * request an "access_token" AND "refresh_token" data - * -> this can either be done by sending a valid "authorization code" - * OR by providing a valid "refresh_token" - * @param $requestParams - * @return bool|mixed - */ - private function requestAccessToken($requestParams){ - $verifyAuthCodeUrl = self::getVerifyAuthorizationCodeEndpoint(); - $verifyAuthCodeUrlParts = parse_url($verifyAuthCodeUrl); - $accessToken = false; - - if($verifyAuthCodeUrlParts){ - $contentType = 'application/x-www-form-urlencoded'; - $requestOptions = [ - 'timeout' => $this->apiTimeout, - 'method' => 'POST', - 'user_agent' => $this->getUserAgent(), - 'header' => [ - 'Authorization: Basic ' . $this->getAuthorizationHeader(), - 'Content-Type: ' . $contentType, - 'Host: ' . $verifyAuthCodeUrlParts['host'] - ] - ]; - - // content (parameters to send with) - $requestOptions['content'] = http_build_query($requestParams); - - $apiResponse = \Web::instance()->request($verifyAuthCodeUrl, $requestOptions); - - if($apiResponse['body']){ - $authCodeRequestData = json_decode($apiResponse['body']); - - if(property_exists($authCodeRequestData, 'refresh_token')){ - // this token is used to refresh/get a new access_token when expires - $this->getF3()->set(self::SESSION_KEY_REFRESH_TOKEN, $authCodeRequestData->refresh_token); - } - - if(property_exists($authCodeRequestData, 'access_token')){ - // this token is required for endpoints that require Auth - $accessToken = $this->getF3()->set(self::SESSION_KEY_ACCESS_TOKEN, $authCodeRequestData->access_token); - } - }else{ - $this->getLogger('error')->write(sprintf(self::ERROR_ACCESS_TOKEN, print_r($requestParams, true))); - } - }else{ - $this->getLogger('error')->write(sprintf(self::ERROR_CCP_SSO_URL, __METHOD__)); - } - - return $accessToken; - } - - - - /** - * verify character data by "access_token" - * -> get some basic information (like character id) - * -> if more character information is required, use CREST endpoints request instead - * @param $accessToken - * @return bool|mixed - */ - private function verifyCharacterData($accessToken){ - $verifyUserUrl = self::getVerifyUserEndpoint(); - $verifyUrlParts = parse_url($verifyUserUrl); - $characterData = false; - - if($verifyUrlParts){ - $requestOptions = [ - 'timeout' => $this->apiTimeout, - 'method' => 'GET', - 'user_agent' => $this->getUserAgent(), - 'header' => [ - 'Authorization: Bearer ' . $accessToken, - 'Host: ' . $verifyUrlParts['host'] - ] - ]; - - $apiResponse = \Web::instance()->request($verifyUserUrl, $requestOptions); - - if($apiResponse['body']){ - $characterData = json_decode($apiResponse['body']); - }else{ - $this->getLogger('error')->write(sprintf(self::ERROR_VERIFY_CHARACTER, __METHOD__)); - } - }else{ - $this->getLogger('error')->write(sprintf(self::ERROR_CCP_SSO_URL, __METHOD__)); - } - - return $characterData; - } - - /** - * get all available Endpoints - * @param $accessToken - * @return bool|mixed - */ - private function getEndpoints($accessToken){ - $crestUrl = self::getCrestEndpoint(); - $endpointsData = false; - $crestUrlParts = parse_url($crestUrl); - - if($crestUrlParts){ - // represents API version - $contentType = 'application/vnd.ccp.eve.Api-v3+json'; - $requestOptions = [ - 'timeout' => $this->apiTimeout, - 'method' => 'GET', - 'user_agent' => $this->getUserAgent(), - 'header' => [ - 'Authorization: Bearer ' . $accessToken, - 'Accept: ' . $contentType, - 'Host: ' . $crestUrlParts['host'] - ] - ]; - - $apiResponse = \Web::instance()->request($crestUrl, $requestOptions); - - if($apiResponse['headers']){ - // check headers for error - $this->checkResponseHeaders($apiResponse['headers'], $crestUrl, $contentType); - - if($apiResponse['body']){ - $endpointsData = json_decode($apiResponse['body'], true); - }else{ - $this->getLogger('error')->write(sprintf(self::ERROR_GET_ENDPOINTS, __METHOD__)); - } - } - }else{ - $this->getLogger('error')->write(sprintf(self::ERROR_CCP_CREST_URL, __METHOD__)); - } - - return $endpointsData; - } - - private function walkEndpoint($accessToken, $endpoint, $path = []){ - $targetEndpoint = null; - - - if( !empty($path) ){ - $newNode = array_shift($path); - - if(isset($endpoint[$newNode])){ - $currentEndpoint = $endpoint[$newNode]; - if(isset($currentEndpoint['href'])){ - $newEndpoint = $this->getEndpoint($accessToken, $currentEndpoint['href']); - $targetEndpoint = $this->walkEndpoint($accessToken, $newEndpoint, $path); - - }else{ - // TODO leaf - $targetEndpoint = ' target:) '; - } - }else{ - // endpoint not found - $this->getLogger('error')->write(sprintf(self::ERROR_FIND_ENDPOINT, $newNode)); - } - }else{ - $targetEndpoint = $endpoint; - } - - - - return $targetEndpoint; - } - - - /** - * get a specific endpoint by its $resourceUrl - * @param $accessToken - * @param $resourceUrl - * @return mixed|null - */ - private function getEndpoint($accessToken, $resourceUrl){ - $resourceUrlParts = parse_url($resourceUrl); - $endpoint = null; - - if($resourceUrlParts){ - $requestOptions = [ - 'timeout' => $this->apiTimeout, - 'method' => 'GET', - 'user_agent' => $this->getUserAgent(), - 'header' => [ - 'Authorization: Bearer ' . $accessToken, - 'Host: login.eveonline.com', - 'Host: ' . $resourceUrlParts['host'] - ] - ]; - - $apiResponse = \Web::instance()->request($resourceUrl, $requestOptions); - - if($apiResponse['headers']){ - // check headers for error - $this->checkResponseHeaders($apiResponse['headers'], $requestOptions); - - if($apiResponse['body']){ - $endpoint = json_decode($apiResponse['body'], true); - }else{ - $this->getLogger('error')->write(sprintf(self::ERROR_GET_ENDPOINT, __METHOD__)); - } - } - }else{ - $this->getLogger('error')->write(sprintf(self::ERROR_CCP_CREST_URL, __METHOD__)); - } - - return $endpoint; - } - - /** - * get character data - * @param $accessToken - * @return array - */ - private function getCharacterData($accessToken){ - $endpoints = $this->getEndpoints($accessToken); - $characterData = []; - - $endpoint = $this->walkEndpoint($accessToken, $endpoints, [ - 'decode', - 'character' - ]); - - if( !empty($endpoint) ){ - $characterData['character'] = (new Mapper\CrestCharacter($endpoint))->getData(); - - if(isset($endpoint['corporation'])){ - $characterData['corporation'] = (new Mapper\CrestCorporation($endpoint['corporation']))->getData(); - } - } - - return $characterData; - } - - /* - private function getCharacterLocation($accessToken){ - $endpoints = $this->getEndpoints($accessToken); - $endpoint = $this->walkEndpoint($accessToken, $endpoints, [ - 'decode', - 'character', - 'location' - ]); - - var_dump($endpoint); - - die(' END getCharacterLocation() '); - - - $characterData = []; - return $characterData; - } */ - - /** - * update character - * @param $characterData - * @return \Model\CharacterModel - * @throws \Exception - */ - private function updateCharacter($characterData){ - - $characterModel = null; - $corporationModel = null; - $allianceModel = null; - - if( !empty($characterData['corporation']) ){ - $corporationModel = Model\BasicModel::getNew('CorporationModel'); - $corporationModel->getById($characterData['corporation']['id'], 0); - $corporationModel->copyfrom($characterData['corporation']); - $corporationModel->save(); - } - - if( !empty($characterData['alliance']) ){ - $allianceModel = Model\BasicModel::getNew('AllianceModel'); - $allianceModel->getById($characterData['alliance']['id'], 0); - $allianceModel->copyfrom($characterData['alliance']); - $allianceModel->save(); - } - - if( !empty($characterData['character']) ){ - $characterModel = Model\BasicModel::getNew('CharacterModel'); - $characterModel->getById($characterData['character']['id'], 0); - $characterModel->copyfrom($characterData['character']); - $characterModel->corporationId = $corporationModel; - $characterModel->allianceId = $allianceModel; - $characterModel->save(); - } - - return $characterModel; - } - - /** - * check response "Header" data for errors - * @param $headers - * @param string $requestUrl - * @param string $contentType - */ - private function checkResponseHeaders($headers, $requestUrl = '', $contentType = ''){ - $headers = (array)$headers; - if(preg_grep ('/^X-Deprecated/i', $headers)){ - $this->getLogger('error')->write(sprintf(self::ERROR_RESOURCE_DEPRECATED, $requestUrl, $contentType)); - } - } - - /** - * get "Authorization:" Header data - * -> This header is required for any Auth-required endpoints! - * @return string - */ - private function getAuthorizationHeader(){ - return base64_encode( - Controller::getEnvironmentData('SSO_CCP_CLIENT_ID') . ':' - . Controller::getEnvironmentData('SSO_CCP_SECRET_KEY') - ); - } - - - static function getAuthorizationEndpoint(){ - return \Base::instance()->get('PATHFINDER.API.CCP_SSO') . '/oauth/authorize'; - } - - static function getVerifyAuthorizationCodeEndpoint(){ - return \Base::instance()->get('PATHFINDER.API.CCP_SSO') . '/oauth/token'; - } - - static function getVerifyUserEndpoint(){ - return \Base::instance()->get('PATHFINDER.API.CCP_SSO') . '/oauth/verify'; - } - - static function getCrestEndpoint(){ - return \Base::instance()->get('PATHFINDER.API.CCP_CREST'); - } -} \ No newline at end of file diff --git a/app/main/controller/controller.php b/app/main/controller/controller.php index 10c11dd44..bdee6ad79 100644 --- a/app/main/controller/controller.php +++ b/app/main/controller/controller.php @@ -7,50 +7,62 @@ */ namespace Controller; +use Controller\Api as Api; use Model; use DB; class Controller { + /** + * @var \Base + */ protected $f3; - private $template; /** - * @param mixed $template + * @var string template for render + */ + protected $template; + + /** + * @param string $template */ - public function setTemplate($template){ + protected function setTemplate($template){ $this->template = $template; } /** - * @return mixed + * @return string */ - public function getTemplate(){ + protected function getTemplate(){ return $this->template; } /** - * set global f3 instance - * @param null $f3 - * @return null|static + * set $f3 base object + * @param \Base $f3 */ - protected function getF3($f3 = null){ - if(is_object($f3)){ - $this->f3 = $f3; - }else{ - $this->f3 = \Base::instance(); - } + protected function setF3(\Base $f3){ + $this->f3 = $f3; + } + /** + * get $f3 base object + * @return \Base + */ + protected function getF3(){ + if( !($this->f3 instanceof \Base) ){ + $this->setF3( \Base::instance() ); + } return $this->f3; } /** * event handler for all "views" * some global template variables are set in here - * @param $f3 + * @param \Base $f3 */ - function beforeroute($f3) { - $this->getF3($f3); + function beforeroute(\Base $f3) { + $this->setF3($f3); // initiate DB connection DB\Database::instance('PF'); @@ -73,8 +85,9 @@ function beforeroute($f3) { /** * event handler after routing * -> render view + * @param \Base $f3 */ - public function afterroute($f3){ + public function afterroute(\Base $f3){ if($this->getTemplate()){ // Ajax calls don´t need a page render.. // this happens on client side @@ -85,7 +98,7 @@ public function afterroute($f3){ /** * set change the DB connection * @param string $database - * @return mixed|void + * @return DB\SQL */ protected function getDB($database = 'PF'){ return DB\Database::instance()->getDB($database); @@ -96,49 +109,47 @@ protected function getDB($database = 'PF'){ */ protected function initSession(){ // init DB Session (not file based) - if( $this->getDB('PF') instanceof \DB\SQL){ - new \DB\SQL\Session($this->getDB('PF')); + if( $this->getDB('PF') instanceof DB\SQL){ + new DB\SQL\Session($this->getDB('PF')); } } /** - * get current user model + * get current character model * @param int $ttl - * @return bool|null + * @return Model\CharacterModel|null * @throws \Exception */ - protected function _getUser($ttl = 5){ - $user = false; - - if( $this->f3->exists('SESSION.user.id') ){ - $userId = (int)$this->f3->get('SESSION.user.id'); - - if($userId > 0){ - $userModel = Model\BasicModel::getNew('UserModel', $ttl); - $userModel->getById($userId, $ttl); - - if( !$userModel->dry() ){ - $user = $userModel; + public function getCharacter($ttl = 5){ + $character = null; + + if( $this->getF3()->exists(Api\User::SESSION_KEY_CHARACTER_ID) ){ + $characterId = (int)$this->getF3()->get(Api\User::SESSION_KEY_CHARACTER_ID); + if($characterId){ + /** + * @var $characterModel \Model\CharacterModel + */ + $characterModel = Model\BasicModel::getNew('CharacterModel'); + $characterModel->getById($characterId, $ttl); + + if( !$characterModel->dry() ){ + $character = &$characterModel; } } } - return $user; + return $character; } /** - * log the current user out - * @param $f3 + * log out current user + * @param \Base $f3 */ - public function logOut($f3){ - + public function logOut(\Base $f3){ // destroy session $f3->clear('SESSION'); - if( !$f3->get('AJAX') ){ - // redirect to landing page - $f3->reroute('@login'); - }else{ + if( $f3->get('AJAX') ){ $params = $f3->get('POST'); $return = (object) []; if( @@ -148,33 +159,36 @@ public function logOut($f3){ $return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $f3->alias('login'); }else{ // no reroute -> errors can be shown - $return->error[] = $this->getUserLoggedOffError(); + $return->error[] = $this->getLogoutError(); } echo json_encode($return); die(); + }else{ + // redirect to landing page + $f3->reroute('@login'); } } /** * verifies weather a given username and password is valid - * @param $userName - * @param $password + * @param string $userName + * @param string $password * @return Model\UserModel|null */ protected function _verifyUser($userName, $password) { - $validUser = null; + /** + * @var $user \Model\UserModel + */ $user = Model\BasicModel::getNew('UserModel', 0); - $user->getByName($userName); // check userName is valid if( !$user->dry() ){ // check if password is valid $isValid = $user->verify($password); - if($isValid === true){ $validUser = $user; } @@ -185,18 +199,16 @@ protected function _verifyUser($userName, $password) { /** * check weather the page is IGB trusted or not - * @return mixed + * @return boolean */ static function isIGBTrusted(){ - $igbHeaderData = self::getIGBHeaderData(); - return $igbHeaderData->trusted; } /** * get all eve IGB specific header data - * @return object + * @return \stdClass */ static function getIGBHeaderData(){ $data = (object) []; @@ -229,7 +241,6 @@ static function getIGBHeaderData(){ /** * Helper function to return all headers because * getallheaders() is not available under nginx - * * @return array (string $key -> string $value) */ static function getRequestHeaders(){ @@ -261,7 +272,7 @@ function_exists('apache_request_headers') && /** * get some server information * @param int $ttl cache time (default: 1h) - * @return object + * @return \stdClass */ static function getServerData($ttl = 3600){ $f3 = \Base::instance(); @@ -308,25 +319,21 @@ static function getServerData($ttl = 3600){ */ static function isIGB(){ $isIGB = false; - $igbHeaderData = self::getIGBHeaderData(); - if(count($igbHeaderData->values) > 0){ $isIGB = true; } - return $isIGB; } /** * get error object is a user is not found/logged of - * @return object + * @return \stdClass */ - protected function getUserLoggedOffError(){ + protected function getLogoutError(){ $userError = (object) []; $userError->type = 'error'; $userError->message = 'User not found'; - return $userError; } @@ -341,8 +348,8 @@ static function getRegistrationStatus(){ /** * get a log controller e.g. "debug" - * @param $loggerType - * @return mixed + * @param string $loggerType + * @return \Log */ static function getLogger($loggerType){ return LogController::getLogger($loggerType); @@ -351,7 +358,7 @@ static function getLogger($loggerType){ /** * removes illegal characters from a Hive-key that are not allowed * @param $key - * @return mixed + * @return string */ static function formatHiveKey($key){ $illegalCharacters = ['-', ' ']; @@ -360,8 +367,8 @@ static function formatHiveKey($key){ /** * get environment specific configuration data - * @param $key - * @return mixed|null + * @param string $key + * @return string|null */ static function getEnvironmentData($key){ $f3 = \Base::instance(); @@ -378,7 +385,7 @@ static function getEnvironmentData($key){ /** * get current server environment status * -> "DEVELOP" or "PRODUCTION" - * @return mixed + * @return string */ static function getEnvironment(){ $f3 = \Base::instance(); @@ -396,7 +403,7 @@ static function isProduction(){ /** * get required MySQL variable value * @param $key - * @return mixed|null + * @return string|null */ static function getRequiredMySqlVariables($key){ $f3 = \Base::instance(); @@ -413,7 +420,7 @@ static function getRequiredMySqlVariables($key){ * get a program URL by alias * -> if no $alias given -> get "default" route (index.php) * @param null $alias - * @return bool + * @return bool|string */ protected function getRouteUrl($alias = null){ $url = false; @@ -452,9 +459,9 @@ protected function getUserAgent(){ * onError() callback function * -> on AJAX request -> return JSON with error information * -> on HTTP request -> render error page - * @param $f3 + * @param \Base $f3 */ - public function showError($f3){ + public function showError(\Base $f3){ // set HTTP status $errorCode = $f3->get('ERROR.code'); if(!empty($errorCode)){ @@ -510,8 +517,10 @@ public function showError($f3){ /** * Callback for framework "unload" * check -> config.ini + * @param \Base $f3 + * @return bool */ - public function unload($f3){ + public function unload(\Base $f3){ return true; } diff --git a/app/main/controller/mapcontroller.php b/app/main/controller/mapcontroller.php index f86e96765..e05bbd9fc 100644 --- a/app/main/controller/mapcontroller.php +++ b/app/main/controller/mapcontroller.php @@ -8,8 +8,11 @@ namespace Controller; -class MapController extends \Controller\AccessController { +class MapController extends AccessController { + /** + * @param \Base $f3 + */ public function init($f3) { // page title diff --git a/app/main/controller/setup.php b/app/main/controller/setup.php index 2b254d334..709086e23 100644 --- a/app/main/controller/setup.php +++ b/app/main/controller/setup.php @@ -36,6 +36,7 @@ class Setup extends Controller { 'Model\ConnectionScopeModel', 'Model\UserMapModel', + 'Model\CharacterMapModel', 'Model\AllianceMapModel', 'Model\CorporationMapModel', @@ -76,9 +77,9 @@ class Setup extends Controller { /** * event handler for all "views" * some global template variables are set in here - * @param $f3 + * @param \Base $f3 */ - function beforeroute($f3) { + function beforeroute(\Base $f3) { // page title $f3->set('pageTitle', 'Setup'); @@ -92,7 +93,7 @@ function beforeroute($f3) { $f3->set('pathJs', 'public/js/' . $f3->get('PATHFINDER.VERSION') ); } - public function afterroute($f3) { + public function afterroute(\Base $f3) { // js view (file) $f3->set('jsView', 'setup'); @@ -103,7 +104,7 @@ public function afterroute($f3) { /** * main setup route handler * works as dispatcher for setup functions - * @param $f3 + * @param \Base $f3 */ public function init($f3){ $params = $f3->get('GET'); @@ -141,7 +142,7 @@ public function init($f3){ /** * get server information - * @param $f3 + * @param \Base $f3 * @return array */ protected function getServerInformation($f3){ @@ -178,7 +179,7 @@ protected function getServerInformation($f3){ /** * check all required backend requirements * (Fat Free Framework) - * @param $f3 + * @param \Base $f3 * @return array */ protected function checkRequirements($f3){ @@ -288,7 +289,7 @@ protected function checkRequirements($f3){ /** * get database connection information - * @param $f3 + * @param \Base $f3 * @param bool|false $exec * @return array */ @@ -413,6 +414,7 @@ protected function checkDatabase($f3, $exec = false){ $changedType = false; $changedUnique = false; $changedIndex = false; + $addConstraints = []; // set (new) column information ------------------------------------------------------- $requiredTables[$requiredTableName]['fieldConf'][$columnName]['exists'] = true; @@ -427,17 +429,22 @@ protected function checkDatabase($f3, $exec = false){ $constraint = $col->newConstraint($constraintData); $foreignKeyExists = $col->constraintExists($constraint); + + // constraint information -> show in template $requiredTables[$requiredTableName]['foreignKeys'][] = [ 'exists' => $foreignKeyExists, 'keyName' => $constraint->getConstraintName() ]; - $col->addConstraint($constraint); - - if(!$foreignKeyExists){ + if($foreignKeyExists){ + // drop constraint and re-add again at the and, in case something has changed + $col->dropConstraint($constraint); + }else{ $tableStatusCheckCount++; $foreignKeyStatusCheck = false; } + + $addConstraints[] = $constraint; } } @@ -452,29 +459,30 @@ protected function checkDatabase($f3, $exec = false){ $tableStatusCheckCount++; } - // check if column unique changed ----------------------------------------------------- + // check if column index changed ------------------------------------------------------ $indexUpdate = false; $indexKey = (bool)$hasIndex; $indexUnique = (bool)$hasUnique; - if($currentColIndexData['unique'] != $fieldConf['unique']){ - $changedUnique = true; + if($currentColIndex != $fieldConf['index']){ + $changedIndex = true; $columnStatusCheck = false; $tableStatusCheckCount++; $indexUpdate = true; - $indexUnique =(bool)$fieldConf['unique']; + $indexKey = (bool) $fieldConf['index']; } - // check if column index changed ------------------------------------------------------ - if($currentColIndex != $fieldConf['index']){ - $changedIndex = true; + // check if column unique changed ----------------------------------------------------- + if($currentColIndexData['unique'] != $fieldConf['unique']){ + $changedUnique = true; $columnStatusCheck = false; $tableStatusCheckCount++; $indexUpdate = true; - $indexKey = (bool) $fieldConf['index']; + $indexUnique =(bool)$fieldConf['unique']; } + // build table with changed columns --------------------------------------------------- if(!$columnStatusCheck || !$foreignKeyStatusCheck){ @@ -495,6 +503,12 @@ protected function checkDatabase($f3, $exec = false){ $tableModifier->updateColumn($columnName, $col); } + // (re-)add constraints !after! index update is done + // otherwise index update will fail if there are existing constraints + foreach($addConstraints as $constraint){ + $col->addConstraint($constraint); + } + $buildStatus = $tableModifier->build($exec); if( @@ -559,7 +573,7 @@ protected function checkDatabase($f3, $exec = false){ } /** check MySQL params - * @param $f3 + * @param \Base $f3 * @param $db * @return array */ diff --git a/app/main/data/mapper/crestsystem.php b/app/main/data/mapper/crestsystem.php new file mode 100644 index 000000000..bbdeb619e --- /dev/null +++ b/app/main/data/mapper/crestsystem.php @@ -0,0 +1,18 @@ + 'id', + 'name' => 'name' + ]; +} \ No newline at end of file diff --git a/app/main/db/sql/mysql/tablemodifier.php b/app/main/db/sql/mysql/tablemodifier.php index 6f5992b63..c620e5216 100644 --- a/app/main/db/sql/mysql/tablemodifier.php +++ b/app/main/db/sql/mysql/tablemodifier.php @@ -80,7 +80,7 @@ public function constraintExists($constraint){ public function dropConstraint($constraint){ if($constraint->isValid()){ $this->queries[] = "ALTER TABLE " . $this->db->quotekey($this->name) . " - DROP FOREIGN KEY " . $this->db->quotekey($constraint->getConstraintName()); + DROP FOREIGN KEY " . $this->db->quotekey($constraint->getConstraintName()) . ";"; }else{ trigger_error(sprintf(self::TEXT_ConstraintNotValid, 'table: ' . $this->name . ' constraintName: ' . $constraint->getConstraintName())); } @@ -93,18 +93,13 @@ public function dropConstraint($constraint){ public function addConstraint($constraint){ if($constraint->isValid()){ - if($this->constraintExists($constraint)){ - // drop constraint and re-add in case something has changed - $this->dropConstraint($constraint); - } - $this->queries[] = " ALTER TABLE " . $this->db->quotekey($this->name) . " ADD CONSTRAINT " . $this->db->quotekey($constraint->getConstraintName()) . " FOREIGN KEY (" . implode(', ', $constraint->getKeys()) . ") REFERENCES " . $this->db->quotekey($constraint->getReferencedTable()) . " (" . implode(', ', $constraint->getReferencedCols()) . ") ON DELETE " . $constraint->getOnDelete() . " - ON UPDATE " . $constraint->getOnUpdate(); + ON UPDATE " . $constraint->getOnUpdate() . ";"; }else{ trigger_error(sprintf(self::TEXT_ConstraintNotValid, 'table: ' . $this->name . ' constraintName: ' . $constraint->getConstraintName())); } @@ -120,7 +115,15 @@ class Column extends SQL\Column { const TEXT_TableNameMissing = 'Table name missing for FOREIGN KEY in `%s`'; /** - * ass constraint to this column + * drop constraint from this column + * @param Constraint $constraint + */ + public function dropConstraint(Constraint $constraint){ + $this->table->dropConstraint($constraint); + } + + /** + * add constraint to this column * @param Constraint $constraint */ public function addConstraint(Constraint $constraint){ diff --git a/app/main/lib/web.php b/app/main/lib/web.php new file mode 100644 index 000000000..7c9e89b92 --- /dev/null +++ b/app/main/lib/web.php @@ -0,0 +1,112 @@ +eol, $headers), + $matches + ) + ){ + $statusCode = (int)$matches[1]; + } + return $statusCode; + } + + /** + * get cache time in seconds from Header data array + * @param array $headers + * @return int + */ + protected function getCacheTimeFromHeaders($headers = []){ + $cacheTime = 0; + + if( + preg_match( + '/Cache-Control:(.*?)max-age=([0-9]+)/', + implode($this->eol, $headers), + $matches + ) + ){ + $cacheTime = (int)$matches[2]; + }elseif( + preg_match( + '/Access-Control-Max-Age: ([0-9]+)/', + implode($this->eol, $headers), + $matches + ) + ){ + $cacheTime = (int)$matches[1]; + } + return $cacheTime; + } + + /** + * get a unique cache kay for a request + * @param $url + * @param null $options + * @return string + */ + protected function getCacheKey($url, $options = null){ + $f3 = \Base::instance(); + + $headers = isset($options['header']) ? implode($this->eol, (array) $options['header']) : ''; + + return $f3->hash( + $options['method'] . ' ' + . $url . ' ' + . $headers + ).'.url'; + } + + /** + * perform curl() request + * -> caches response by returned HTTP Cache header data + * @param string $url + * @param array|null $options + * @return array|FALSE|mixed + */ + public function request($url,array $options = null) { + $f3 = \Base::instance(); + + if( !$f3->exists( $hash = $this->getCacheKey($url, $options) ) ){ + $result = parent::request($url, $options); + $statusCode = $this->getStatuscodeFromHeaders( $result['headers'] ); + + if($statusCode == 200){ + // request succeeded -> check if response should be cached + if( $ttl = $this->getCacheTimeFromHeaders( $result['headers'] ) ){ + $f3->set($hash, $result, $ttl); + } + } + }else{ + $result = $f3->get($hash); + } + + return $result; + } + +} \ No newline at end of file diff --git a/app/main/model/basicmodel.php b/app/main/model/basicmodel.php index c70d0d212..900a88e62 100644 --- a/app/main/model/basicmodel.php +++ b/app/main/model/basicmodel.php @@ -13,7 +13,7 @@ use Controller; use DB; -class BasicModel extends \DB\Cortex { +abstract class BasicModel extends \DB\Cortex { /** * Hive key with DB object @@ -81,15 +81,17 @@ public function __construct($db = NULL, $table = NULL, $fluid = NULL, $ttl = 0){ $self->clearCacheData(); }); - // model updated $this->afterupdate( function($self){ $self->clearCacheData(); }); - // model updated $this->beforeinsert( function($self){ $self->beforeInsertEvent($self); }); + + $this->aftererase( function($self){ + $self->aftereraseEvent($self); + }); } @@ -226,7 +228,7 @@ protected function getCacheKey($dataCacheTableKeyPrefix = ''){ $cacheKey = null; // set a model unique cache key if the model is saved - if( $this->_id > 0){ + if( $this->id > 0){ // check if there is a given key prefix // -> if not, use the standard key. // this is useful for caching multiple data sets according to one row entry @@ -337,12 +339,21 @@ public function beforeInsertEvent(){ return true; } + /** + * Event "Hook" function + * can be overwritten + * @return bool + */ + public function aftereraseEvent($self){ + return true; + } + /** * function should be overwritten in child classes with access restriction - * @param $accessObject + * @param UserModel $user * @return bool */ - public function hasAccess($accessObject){ + public function hasAccess(UserModel $user){ return true; } @@ -357,7 +368,7 @@ public function isValid(){ /** * get cached data from this model * @param string $dataCacheKeyPrefix - optional key prefix - * @return mixed|null + * @return \stdClass|null */ protected function getCacheData($dataCacheKeyPrefix = ''){ @@ -427,9 +438,9 @@ public static function getClassName(){ /** * factory for all Models - * @param $model + * @param string $model * @param int $ttl - * @return null + * @return BasicModel * @throws \Exception */ public static function getNew($model, $ttl = 86400){ @@ -447,7 +458,7 @@ public static function getNew($model, $ttl = 86400){ /** * get the framework instance (singleton) - * @return static + * @return \Base */ public static function getF3(){ return \Base::instance(); @@ -455,7 +466,7 @@ public static function getF3(){ /** * debug log function - * @param $text + * @param string $text */ public static function log($text){ Controller\LogController::getLogger('debug')->write($text); diff --git a/app/main/model/characterlogmodel.php b/app/main/model/characterlogmodel.php index 2b9a7acf0..fd47696cb 100644 --- a/app/main/model/characterlogmodel.php +++ b/app/main/model/characterlogmodel.php @@ -14,6 +14,14 @@ class CharacterLogModel extends BasicModel { protected $table = 'character_log'; + /** + * caching for relational data + * -> 10s matches REST API - Expire: Header-Data + * for "Location" calls + * @var int + */ + protected $rel_ttl = 10; + protected $fieldConf = [ 'active' => [ 'type' => Schema::DT_BOOL, @@ -68,6 +76,17 @@ public function __construct($db = NULL, $table = NULL, $fluid = NULL, $ttl = 0){ }); } + /** + * set log data from object + * @param object $logData + */ + public function setData($logData){ + if( !empty($logData->system) ){ + $this->systemId = $logData->system['id']; + $this->systemName = $logData->system['name']; + } + } + /** * get all character log data * @return object diff --git a/app/main/model/charactermapmodel.php b/app/main/model/charactermapmodel.php new file mode 100644 index 000000000..fadb87934 --- /dev/null +++ b/app/main/model/charactermapmodel.php @@ -0,0 +1,75 @@ + [ + 'type' => Schema::DT_BOOL, + 'nullable' => false, + 'default' => 1, + 'index' => true + ], + 'characterId' => [ + 'type' => Schema::DT_INT, + 'index' => true, + 'belongs-to-one' => 'Model\CharacterModel', + 'constraint' => [ + [ + 'table' => 'character', + 'on-delete' => 'CASCADE' + ] + ] + ], + 'mapId' => [ + 'type' => Schema::DT_INT, + 'index' => true, + 'belongs-to-one' => 'Model\MapModel', + 'constraint' => [ + [ + 'table' => 'map', + 'on-delete' => 'CASCADE' + ] + ] + ] + ]; + + /** + * see parent + */ + public function clearCacheData(){ + parent::clearCacheData(); + + // clear map cache as well + $this->mapId->clearCacheData(); + } + + /** + * overwrites parent + * @param null $db + * @param null $table + * @param null $fields + * @return bool + */ + public static function setup($db=null, $table=null, $fields=null){ + $status = parent::setup($db,$table,$fields); + + if($status === true){ + $status = parent::setMultiColumnIndex(['characterId', 'mapId'], true); + } + + return $status; + } + +} \ No newline at end of file diff --git a/app/main/model/charactermodel.php b/app/main/model/charactermodel.php index fd58eda7b..3e16177a4 100644 --- a/app/main/model/charactermodel.php +++ b/app/main/model/charactermodel.php @@ -8,6 +8,7 @@ namespace Model; +use Controller\Ccp; use DB\SQL\Schema; class CharacterModel extends BasicModel { @@ -15,6 +16,10 @@ class CharacterModel extends BasicModel { protected $table = 'character'; protected $fieldConf = [ + 'lastLogin' => [ + 'type' => Schema::DT_TIMESTAMP, + 'index' => true + ], 'active' => [ 'type' => Schema::DT_BOOL, 'nullable' => false, @@ -26,6 +31,22 @@ class CharacterModel extends BasicModel { 'nullable' => false, 'default' => '' ], + 'ownerHash' => [ + 'type' => Schema::DT_VARCHAR128, + 'nullable' => false, + 'default' => '' + ], + 'crestAccessToken' => [ + 'type' => Schema::DT_VARCHAR256 + ], + 'crestAccessTokenUpdated' => [ + 'type' => Schema::DT_TIMESTAMP, + 'default' => Schema::DF_CURRENT_TIMESTAMP, + 'index' => true + ], + 'crestRefreshToken' => [ + 'type' => Schema::DT_VARCHAR256 + ], 'corporationId' => [ 'type' => Schema::DT_INT, 'index' => true, @@ -57,6 +78,9 @@ class CharacterModel extends BasicModel { 'nullable' => false, 'default' => '' ], + 'userCharacter' => [ + 'has-one' => ['Model\UserCharacterModel', 'characterId'] + ], 'characterLog' => [ 'has-one' => ['Model\CharacterLogModel', 'characterId'] ] @@ -65,19 +89,17 @@ class CharacterModel extends BasicModel { /** * get character data * @param bool|false $addCharacterLogData - * @return object + * @return \stdClass */ public function getData($addCharacterLogData = false){ // check if there is cached data // temporary disabled (performance test) - $characterData = null; //$this->getCacheData(); + $characterData = $this->getCacheData(); if(is_null($characterData)){ // no cached character data found - $characterData = (object) []; - $characterData->id = $this->id; $characterData->name = $this->name; @@ -107,17 +129,49 @@ public function getData($addCharacterLogData = false){ } /** - * check whether this character has a corporation - * @return bool + * set unique "ownerHash" for this character + * -> Hash will change when character is transferred (sold) + * @param string $ownerHash + * @return string */ - public function hasCorporation(){ - $hasCorporation = false; + public function set_ownerHash($ownerHash){ + if ( + $this->hasUserCharacter() && + $this->ownerHash !== $ownerHash + ){ + $this->userCharacter->erase(); + } + return $ownerHash; + } - if($this->corporationId){ - $hasCorporation = true; + /** + * set CREST accessToken for current session + * -> update "tokenUpdated" column on change + * -> this is required for expire checking! + * @param string $accessToken + * @return string + */ + public function set_crestAccessToken($accessToken){ + if($this->crestAccessToken !== $accessToken){ + $this->touch('crestAccessTokenUpdated'); } + return $accessToken; + } + + /** + * check whether this character has already a user assigned to it + * @return bool + */ + public function hasUserCharacter(){ + return is_object($this->userCharacter); + } - return $hasCorporation; + /** + * check whether this character has a corporation + * @return bool + */ + public function hasCorporation(){ + return is_object($this->corporationId); } /** @@ -125,46 +179,177 @@ public function hasCorporation(){ * @return bool */ public function hasAlliance(){ - $hasAlliance = false; + return is_object($this->allianceId); + } - if($this->allianceId){ - $hasAlliance = true; + /** + * @return UserModel|null + */ + public function getUser(){ + $user = null; + if($this->hasUserCharacter()){ + /** + * @var $user UserModel + */ + $user = $this->userCharacter->userId; } - - return $hasAlliance; + return $user; } /** * get the corporation for this user - * @return mixed|null + * @return \Model\CorporationModel|null */ public function getCorporation(){ - $corporation = null; + return $this->corporationId; + } - if($this->hasCorporation()){ - $corporation = $this->corporationId; + /** + * get the alliance of this user + * @return \Model\AllianceModel|null + */ + public function getAlliance(){ + return $this->allianceId; + } + + /** + * get CREST API "access_token" from OAuth + * @return bool|string + */ + private function getAccessToken(){ + $accessToken = false; + + // check if there is already an "accessToken" for this user + // check expire timer for stored "accessToken" + if( + !empty($this->crestAccessToken) && + !empty($this->crestAccessTokenUpdated) + ){ + $timezone = new \DateTimeZone( $this->getF3()->get('TZ') ); + $tokenTime = \DateTime::createFromFormat( + 'Y-m-d H:i:s', + $this->crestAccessTokenUpdated, + $timezone + ); + // add expire time buffer for this "accessToken" + // token should be marked as "deprecated" BEFORE it actually expires. + $timeBuffer = 2 * 60; + $tokenTime->add(new \DateInterval('PT' . (Ccp\Sso::ACCESS_KEY_EXPIRE_TIME - $timeBuffer) . 'S')); + + $now = new \DateTime('now', $timezone); + if($tokenTime->getTimestamp() > $now->getTimestamp()){ + $accessToken = $this->crestAccessToken; + } } - return $corporation; + // if no "accessToken" was found -> get a fresh one by an existing "refreshToken" + if( + !$accessToken && + !empty($this->crestRefreshToken) + ){ + // no accessToken found OR token is deprecated + $ssoController = new Ccp\Sso(); + $accessData = $ssoController->refreshAccessToken($this->crestRefreshToken); + + if( + isset($accessData->accessToken) && + isset($accessData->refreshToken) + ){ + $this->crestAccessToken = $accessData->accessToken; + $this->save(); + + $accessToken = $this->crestAccessToken; + } + } + + return $accessToken; } /** - * get the alliance of this user - * @return mixed|null + * checks whether this character is authorized to log in + * -> check corp/ally whitelist config (pathfinder.ini) + * @return bool */ - public function getAlliance(){ - $alliance = null; + public function isAuthorized(){ + $isAuthorized = false; + $f3 = self::getF3(); - if($this->hasAlliance()){ - $alliance = $this->allianceId; + $whitelistCorporations = $whitelistAlliance = []; + if( !empty($f3->get('PATHFINDER.LOGIN.CORPORATION')) ){ + $whitelistCorporations = array_map('trim',(array) $f3->get('PATHFINDER.LOGIN.CORPORATION') ); + } + if( !empty($f3->get('PATHFINDER.LOGIN.ALLIANCE')) ){ + $whitelistAlliance = array_map('trim',(array) $f3->get('PATHFINDER.LOGIN.ALLIANCE') ); + } + + if( + empty($whitelistCorporations) && + empty($whitelistAlliance) + ){ + // no corp/ally restrictions set -> any character is allowed to login + $isAuthorized = true; + }else{ + // check if character corporation is set in whitelist + if( + !empty($whitelistCorporations) && + $this->hasCorporation() && + in_array($this->getCorporation()->_id, $whitelistCorporations) + ){ + $isAuthorized = true; + } + + // check if character alliance is set in whitelist + if( + !$isAuthorized && + !empty($whitelistAlliance) && + $this->hasAlliance() && + in_array($this->getAlliance()->_id, $whitelistAlliance) + ){ + $isAuthorized = true; + } + } + + return $isAuthorized; + } + + /** + * update character log (active system, ...) + * -> CREST API request for character log data + * @return CharacterModel + */ + public function updateLog(){ + + $characterModel = $this; + $ssoController = new Ccp\Sso(); + + $locationData = $ssoController->getCharacterLocationData($this->getAccessToken()); + + if( empty((array)$locationData) ){ + // character is not in-game + if(is_object($this->characterLog)){ + // delete existing log + $this->characterLog->erase(); + $characterModel = $this->save(); + } + }else{ + // character is currently in-game + if( !$characterLog = $this->getLog() ){ + // create new log + $characterLog = $this->rel('characterLog'); + $characterLog->characterId = $this; + } + $characterLog->setData($locationData); + $characterLog->save(); + $this->characterLog = $characterLog; + $characterModel = $this->save(); } - return $alliance; + return $characterModel; } /** * get the character log entry for this character - * @return bool|null + * @return bool|CharacterLogModel */ public function getLog(){ diff --git a/app/main/model/connectionmodel.php b/app/main/model/connectionmodel.php index 51d53a84b..26a999cd9 100644 --- a/app/main/model/connectionmodel.php +++ b/app/main/model/connectionmodel.php @@ -103,11 +103,11 @@ public function getData(){ /** * check object for model access - * @param $accessObject - * @return bool + * @param UserModel $user + * @return mixed */ - public function hasAccess($accessObject){ - return $this->mapId->hasAccess($accessObject); + public function hasAccess(UserModel $user){ + return $this->mapId->hasAccess($user); } /** @@ -127,13 +127,13 @@ public function isValid(){ /** * delete a connection - * @param $accessObject + * @param UserModel $user */ - public function delete($accessObject){ + public function delete(UserModel $user){ if(!$this->dry()){ // check if editor has access - if($this->hasAccess($accessObject)){ + if($this->hasAccess($user)){ $this->erase(); } } diff --git a/app/main/model/mapmodel.php b/app/main/model/mapmodel.php index 9dc4890df..254e537ba 100644 --- a/app/main/model/mapmodel.php +++ b/app/main/model/mapmodel.php @@ -8,6 +8,7 @@ namespace Model; +use Controller\Api\User; use DB\SQL\Schema; class MapModel extends BasicModel { @@ -117,16 +118,14 @@ public function setData($data){ } } - /** * get map data * -> this includes system and connection data as well! - * @return array + * @return \stdClass */ public function getData(){ - - // check if there is cached data - $mapDataAll = $this->getCacheData(); + // check if there is cached data + $mapDataAll = $this->getCacheData(); if(is_null($mapDataAll)){ // no cached map data found @@ -355,25 +354,34 @@ public function setAccess($obj){ /** * clear access for a given type of objects - * @param $clearKeys + * @param array $clearKeys */ public function clearAccess($clearKeys = ['user', 'corporation', 'alliance']){ foreach($clearKeys as $key){ switch($key){ case 'user': - foreach((array)$this->mapUsers as $obj){ - $obj->erase(); + foreach((array)$this->mapUsers as $userMapModel){ + /** + * @var UserMapModel $userMapModel + */ + $userMapModel->erase(); }; break; case 'corporation': - foreach((array)$this->mapCorporations as $obj){ - $obj->erase(); + foreach((array)$this->mapCorporations as $corporationMapModel){ + /** + * @var CorporationMapModel $corporationMapModel + */ + $corporationMapModel->erase(); }; break; case 'alliance': - foreach((array)$this->mapAlliances as $obj){ - $obj->erase(); + foreach((array)$this->mapAlliances as $allianceMapModel){ + /** + * @var AllianceMapModel $allianceMapModel + */ + $allianceMapModel->erase(); }; break; } @@ -382,21 +390,16 @@ public function clearAccess($clearKeys = ['user', 'corporation', 'alliance']){ /** * checks weather a user has access to this map or not - * @param $user + * @param UserModel $user * @return bool */ - public function hasAccess($user){ + public function hasAccess(UserModel $user){ $hasAccess = false; - if( - !$this->dry() && - $user instanceof UserModel - ){ - + if( !$this->dry() ){ // get all maps the user has access to // this includes corporation and alliance maps $maps = $user->getMaps(); - foreach($maps as $map){ if($map->id === $this->id){ $hasAccess = true; @@ -411,7 +414,7 @@ public function hasAccess($user){ /** * get all user models that have access to this map * note: This function is just for "private" maps - * @return array + * @return UserModel[] */ public function getUsers(){ $users = []; @@ -431,7 +434,7 @@ public function getUsers(){ /** * get all character models that are currently online "viewing" this map - * @return array + * @return CharacterModel[] */ private function getCharacters(){ $characters = []; @@ -439,24 +442,29 @@ private function getCharacters(){ if($this->isPrivate()){ $users = $this->getUsers(); + // add active character for each user foreach($users as $user){ - // get all active character logs for a user - $tempActiveUserCharacters = $user->getActiveUserCharacters(); - - foreach($tempActiveUserCharacters as $tempActiveUserCharacter){ - $characters[] = $tempActiveUserCharacter; - } + /** + * @var UserModel $user + */ + $characters = array_merge($characters, $user->getActiveCharacters()); } }elseif($this->isCorporation()){ $corporations = $this->getCorporations(); foreach($corporations as $corporation){ + /** + * @var CorporationModel $corporation + */ $characters = array_merge($characters, $corporation->getCharacters()); } }elseif($this->isAlliance()){ $alliances = $this->getAlliances(); foreach($alliances as $alliance){ + /** + * @var AllianceModel $alliance + */ $characters = array_merge($characters, $alliance->getCharacters()); } } @@ -531,16 +539,15 @@ public function getAlliances(){ return $alliances; } - /** * delete this map and all dependencies - * @param $accessObject + * @param UserModel $user */ - public function delete($accessObject){ + public function delete(UserModel $user){ if(!$this->dry()){ - // check if editor has access - if($this->hasAccess($accessObject)){ + // check if user has access + if($this->hasAccess($user)){ // all map related tables will be deleted on cascade // delete map diff --git a/app/main/model/systemmodel.php b/app/main/model/systemmodel.php index d338451dd..7a40d6694 100644 --- a/app/main/model/systemmodel.php +++ b/app/main/model/systemmodel.php @@ -313,23 +313,23 @@ public function set_posY($posY){ /** * check object for model access - * @param $accessObject - * @return bool + * @param UserModel $user + * @return mixed */ - public function hasAccess($accessObject){ - return $this->mapId->hasAccess($accessObject); + public function hasAccess(UserModel $user){ + return $this->mapId->hasAccess($user); } /** * delete a system from a map * hint: signatures and connections will be deleted on cascade - * @param $accessObject + * @param UserModel $user */ - public function delete($accessObject){ + public function delete(UserModel $user){ if(! $this->dry()){ // check if user has access - if($this->hasAccess($accessObject)){ + if($this->hasAccess($user)){ $this->erase(); } } @@ -367,14 +367,14 @@ public function getSignaturesData(){ /** * get Signature by id and check for access - * @param $accessObject + * @param UserModel $user * @param $id * @return bool|null */ - public function getSignatureById($accessObject, $id){ + public function getSignatureById(UserModel $user, $id){ $signature = null; - if($this->hasAccess($accessObject)){ + if($this->hasAccess($user)){ $this->filter('signatures', ['active = ? AND id = ?', 1, $id]); if($this->signatures){ $signature = reset( $this->signatures ); @@ -386,14 +386,14 @@ public function getSignatureById($accessObject, $id){ /** * get a signature by its "unique" 3-digit name - * @param $accessObject + * @param UserModel $user * @param $name * @return mixed|null */ - public function getSignatureByName($accessObject, $name){ + public function getSignatureByName(UserModel $user, $name){ $signature = null; - if($this->hasAccess($accessObject)){ + if($this->hasAccess($user)){ $this->filter('signatures', ['active = ? AND name = ?', 1, $name]); if($this->signatures){ $signature = reset( $this->signatures ); diff --git a/app/main/model/systemsignaturemodel.php b/app/main/model/systemsignaturemodel.php index 445635cff..682b3caab 100644 --- a/app/main/model/systemsignaturemodel.php +++ b/app/main/model/systemsignaturemodel.php @@ -151,18 +151,21 @@ public function hasChanged($signatureData){ /** * check object for model access - * @param $accessObject + * @param UserModel $user * @return bool */ - public function hasAccess($accessObject){ - return $this->systemId->hasAccess($accessObject); + public function hasAccess(UserModel $user){ + return $this->systemId->hasAccess($user); } - public function delete($accessObject){ - + /** + * delete signature + * @param UserModel $user + */ + public function delete(UserModel $user){ if(!$this->dry()){ // check if editor has access - if($this->hasAccess($accessObject)){ + if($this->hasAccess($user)){ $this->erase(); } } diff --git a/app/main/model/userapimodel.php b/app/main/model/userapimodel.php index 9ebb7c462..a43701c15 100644 --- a/app/main/model/userapimodel.php +++ b/app/main/model/userapimodel.php @@ -60,15 +60,6 @@ public function getData(){ return $apiData; } - /** - * @return int - */ - public function updateCharacters(){ - $apiController = new Controller\CcpApiController(); - - return $apiController->updateCharacters($this); - } - /** * get all characters for this API * @return array|mixed diff --git a/app/main/model/usercharactermodel.php b/app/main/model/usercharactermodel.php index 9463a425e..eb852d2b6 100644 --- a/app/main/model/usercharactermodel.php +++ b/app/main/model/usercharactermodel.php @@ -46,6 +46,7 @@ class UserCharacterModel extends BasicModel { 'characterId' => [ 'type' => Schema::DT_INT, 'index' => true, + 'unique' => true, 'belongs-to-one' => 'Model\CharacterModel', 'constraint' => [ [ @@ -79,34 +80,22 @@ public function setData($characterData){ } /** - * get all character data - * @param $addCharacterLogData - * @return array + * event "Hook" + * -> remove user if there are no other characters bound to this user + * @param $self + * @return bool */ - public function getData($addCharacterLogData = false){ - - // get characterModel - $characterModel = $this->getCharacter(); - - // get static character data - $characterData = $characterModel->getData($addCharacterLogData); - - // add user specific character data - $characterData->isMain = $this->isMain; - - // check for corporation - if( is_object( $characterModel->corporationId ) ){ - $characterData->corporation = $characterModel->corporationId->getData(); + public function aftereraseEvent($self){ + if( + is_object($self->userId) && + is_null($self->userId->userCharacters) + ){ + $self->userId->erase(); } - - // check for alliance - if( is_object( $characterModel->allianceId ) ){ - $characterData->alliance = $characterModel->allianceId->getData(); - } - - return $characterData; + return true; } + /** * check if this character is Main character or not * @return bool diff --git a/app/main/model/usermodel.php b/app/main/model/usermodel.php index 42c4ab8e6..195b06459 100644 --- a/app/main/model/usermodel.php +++ b/app/main/model/usermodel.php @@ -10,6 +10,7 @@ use DB\SQL\Schema; use Controller; +use Controller\Api; use Exception; class UserModel extends BasicModel { @@ -17,10 +18,6 @@ class UserModel extends BasicModel { protected $table = 'user'; protected $fieldConf = [ - 'lastLogin' => [ - 'type' => Schema::DT_TIMESTAMP, - 'index' => true - ], 'active' => [ 'type' => Schema::DT_BOOL, 'nullable' => false, @@ -31,15 +28,12 @@ class UserModel extends BasicModel { 'type' => Schema::DT_VARCHAR128, 'nullable' => false, 'default' => '', - 'index' => true, - 'unique' => true + 'index' => true ], 'email' => [ 'type' => Schema::DT_VARCHAR128, 'nullable' => false, - 'default' => '', - 'index' => true, - 'unique' => true + 'default' => '' ], 'password' => [ 'type' => Schema::DT_VARCHAR128, @@ -69,11 +63,6 @@ class UserModel extends BasicModel { 'max' => 25 ] ], - 'email' => [ - 'length' => [ - 'min' => 5 - ] - ], 'password' => [ 'length' => [ 'min' => 6 @@ -83,9 +72,9 @@ class UserModel extends BasicModel { /** * get all data for this user - * ! caution ! this function returns sensitive data! + * -> ! caution ! this function returns sensitive data! (e.g. email,..) * -> user getSimpleData() for faster performance and public user data - * @return object + * @return \stdClass */ public function getData(){ @@ -98,24 +87,19 @@ public function getData(){ // user shared info $userData->shared = $this->shared; - // api data - $APIs = $this->getAPIs(); - foreach($APIs as $api){ - $userData->api[] = $api->getData(); - } - // all chars $userData->characters = []; - $userCharacters = $this->getUserCharacters(); - foreach($userCharacters as $userCharacter){ - $userData->characters[] = $userCharacter->getData(); + $characters = $this->getCharacters(); + foreach($characters as $character){ + /** + * @var $character CharacterModel + */ + $userData->characters[] = $character->getData(); } // set active character with log data - $activeUserCharacter = $this->getActiveUserCharacter(); - if($activeUserCharacter){ - $userData->character = $activeUserCharacter->getData(true); - } + $activeCharacter = $this->getActiveCharacter(); + $userData->character = $activeCharacter->getData(true); return $userData; } @@ -123,7 +107,7 @@ public function getData(){ /** * get public user data * - check out getData() for all user data - * @return object + * @return \stdClass */ public function getSimpleData(){ $userData = (object) []; @@ -135,11 +119,15 @@ public function getSimpleData(){ /** * validate and set a email address for this user - * @param $email - * @return mixed + * -> empty email is allowed! + * @param string $email + * @return string */ public function set_email($email){ - if (\Audit::instance()->email($email) == false) { + if ( + !empty($email) && + \Audit::instance()->email($email) == false + ) { // no valid email address $this->throwValidationError('email'); } @@ -148,8 +136,8 @@ public function set_email($email){ /** * set a password hash for this user - * @param $password - * @return FALSE|string + * @param string $password + * @return string */ public function set_password($password){ if(strlen($password) < 6){ @@ -208,10 +196,9 @@ public function verify($password){ /** * get all accessible map models for this user - * @return array + * @return MapModel[] */ public function getMaps(){ - $f3 = self::getF3(); $this->filter( 'userMaps', @@ -222,34 +209,29 @@ public function getMaps(){ $maps = []; if($this->userMaps){ $mapCountPrivate = 0; - foreach($this->userMaps as $userMap){ + foreach($this->userMaps as &$userMap){ if( $userMap->mapId->isActive() && - $mapCountPrivate < $f3->get('PATHFINDER.MAX_MAPS_PRIVATE') + $mapCountPrivate < self::getF3()->get('PATHFINDER.MAX_MAPS_PRIVATE') ){ - $maps[] = $userMap->mapId; + $maps[] = &$userMap->mapId; $mapCountPrivate++; } } } - $activeUserCharacter = $this->getActiveUserCharacter(); + // get current active character + $controller = new Controller\Controller(); + $activeCharacter = $controller->getCharacter(); + $corporation = $activeCharacter->getCorporation(); + $alliance = $activeCharacter->getAlliance(); - if($activeUserCharacter){ - $character = $activeUserCharacter->getCharacter(); - $corporation = $character->getCorporation(); - $alliance = $character->getAlliance(); - - if($alliance){ - $allianceMaps = $alliance->getMaps(); - $maps = array_merge($maps, $allianceMaps); - } - - if($corporation){ - $corporationMaps = $corporation->getMaps(); - $maps = array_merge($maps, $corporationMaps); + if($alliance){ + $maps = array_merge($maps, $alliance->getMaps()); + } - } + if($corporation){ + $maps = array_merge($maps, $corporation->getMaps()); } return $maps; @@ -257,13 +239,16 @@ public function getMaps(){ /** * get mapModel by id and check if user has access - * @param $mapId - * @return null - * @throws \Exception + * @param int $mapId + * @return MapModel|null + * @throws Exception */ - public function getMap($mapId){ + public function getMap(int $mapId){ + /** + * @var $map MapModel + */ $map = self::getNew('MapModel'); - $map->getById( (int)$mapId ); + $map->getById( $mapId ); $returnMap = null; if($map->hasAccess($this)){ @@ -324,35 +309,14 @@ public function setMainCharacterId($characterId = 0){ /** * get all userCharacters models for a user * characters will be checked/updated on login by CCP API call - * @return array|mixed + * @return UserCharacterModel[] */ public function getUserCharacters(){ + $this->filter('userCharacters', ['active = ?', 1]); - $this->filter('apis', ['active = ?', 1]); - - // if a user has multiple API keys saved for ONE character, - // skip double characters! $userCharacters = []; - - if($this->apis){ - $this->apis->rewind(); - while($this->apis->valid()){ - - $this->apis->current()->filter('userCharacters', ['active = ?', 1]); - - if($this->apis->current()->userCharacters){ - $this->apis->current()->userCharacters->rewind(); - while($this->apis->current()->userCharacters->valid()){ - - $tempCharacterId = $this->apis->current()->userCharacters->current()->characterId->get('id'); - if( !isset($userCharacters[ $tempCharacterId ]) ){ - $userCharacters[ $tempCharacterId ] = $this->apis->current()->userCharacters->current(); - } - $this->apis->current()->userCharacters->next(); - } - } - $this->apis->next(); - } + if($this->userCharacters){ + $userCharacters = $this->userCharacters; } return $userCharacters; @@ -377,82 +341,72 @@ public function getMainUserCharacter(){ } /** - * get the active user character for this user - * either there is an active Character (IGB) or the character labeled as "main" - * @return null + * get the current active character for this user + * -> EITHER - the current active one for the current user + * -> OR - get the first active one + * @return null|CharacterModel */ - public function getActiveUserCharacter(){ - $activeUserCharacter = null; - - $headerData = Controller\CcpApiController::getIGBHeaderData(); - - // check if IGB Data is available - if( !empty($headerData->values) ){ - // search for the active character by IGB Header Data - - $this->filter('userCharacters', - [ - 'active = :active AND characterId = :characterId', - ':active' => 1, - ':characterId' => intval($headerData->values['charid']) - ], - ['limit' => 1] - ); - - if($this->userCharacters){ - // check if userCharacter has active log - $userCharacter = current($this->userCharacters); - - if( $userCharacter->getCharacter()->getLog() ){ - $activeUserCharacter = $userCharacter; - } + public function getActiveCharacter(){ + $activeCharacter = null; + $controller = new Controller\Controller(); + $currentActiveCharacter = $controller->getCharacter(); + + if( + !is_null($currentActiveCharacter) && + $currentActiveCharacter->getUser()->_id === $this->id + ){ + $activeCharacter = &$currentActiveCharacter; + }else{ + // set "first" found as active for this user + if($activeCharacters = $this->getActiveCharacters()){ + $activeCharacter = &$activeCharacters[0]; } } - // if no active character is found - // e.g. not online in IGB - // -> get main Character - if(is_null($activeUserCharacter)){ - $activeUserCharacter = $this->getMainUserCharacter(); - } - - return $activeUserCharacter; + return $activeCharacter; } /** - * get all active user characters (with log entry) - * hint: a user can have multiple active characters - * @return array + * get all characters for this user + * @return CharacterModel[] */ - public function getActiveUserCharacters(){ + public function getCharacters(){ $userCharacters = $this->getUserCharacters(); - - $activeUserCharacters = []; + $characters = []; foreach($userCharacters as $userCharacter){ - $characterLog = $userCharacter->getCharacter()->getLog(); - - if($characterLog){ - $activeUserCharacters[] = $userCharacter; + /** + * @var $userCharacter UserCharacterModel + */ + if( $currentCharacter = $userCharacter->getCharacter() ){ + // check if userCharacter has a valid character + // -> this should never fail! + $characters[] = $currentCharacter; } } - return $activeUserCharacters; + return $characters; } /** - * update/check API information. - * request API information from CCP + * get all active characters (with log entry) + * hint: a user can have multiple active characters + * @return CharacterModel[] */ - public function updateApiData(){ - $this->filter('apis', ['active = ?', 1]); + public function getActiveCharacters(){ + $userCharacters = $this->getUserCharacters(); - if($this->apis){ - $this->apis->rewind(); - while($this->apis->valid()){ - $this->apis->current()->updateCharacters(); - $this->apis->next(); + $activeCharacters = []; + foreach($userCharacters as $userCharacter){ + /** + * @var $userCharacter UserCharacterModel + */ + $characterModel = $userCharacter->getCharacter(); + if($characterLog = $characterModel->getLog()){ + $activeCharacters[] = $characterModel; } } + + return $activeCharacters; } /** @@ -460,8 +414,10 @@ public function updateApiData(){ * @param int $ttl cache time in seconds * @throws \Exception */ + /* public function updateCharacterLog($ttl = 0){ - $headerData = Controller\CcpApiController::getIGBHeaderData(); + + $headerData = Controller\Controller::getIGBHeaderData(); // check if IGB Data is available if( !empty($headerData->values) ){ @@ -551,6 +507,7 @@ public function updateCharacterLog($ttl = 0){ } } } + */ } \ No newline at end of file diff --git a/app/pathfinder.ini b/app/pathfinder.ini index 6a77d0c7e..e793d78b3 100644 --- a/app/pathfinder.ini +++ b/app/pathfinder.ini @@ -34,6 +34,11 @@ INVITE = 0 ; the limit of registration keys. Increase it to hand out more keys INVITE_LIMIT = 50 +[PATHFINDER.LOGIN] + +CORPORATION = 1000166 +ALLIANCE = + ; View ============================================================================================ [PATHFINDER.VIEW] ; static page templates @@ -102,11 +107,6 @@ DELETE_ACCOUNT = delete_account ; API ============================================================================================= [PATHFINDER.API] -; CCP SSO OAuth 2.0 -CCP_SSO = https://login.eveonline.com -; CCP CREST API -CCP_CREST = https://crest-tq.eveonline.com -; CCP_CREST = https://api-sisi.testeveonline.com ; CCP XML APIv2 CCP_XML = https://api.eveonline.com ; GitHub Developer API diff --git a/app/routes.ini b/app/routes.ini index e319b8917..a389954fd 100644 --- a/app/routes.ini +++ b/app/routes.ini @@ -7,7 +7,7 @@ GET @setup: /setup = Controller\Setup->in ; login (index) page GET @login: / = Controller\AppController->init, 0 ; CCP SSO redirect -GET @sso: /sso/@action = Controller\CcpSsoController->@action, 0 +GET @sso: /sso/@action = Controller\Ccp\Sso->@action, 0 ; map page GET @map: /map = Controller\MapController->init, 0 diff --git a/js/app/ui/dialog/map_info.js b/js/app/ui/dialog/map_info.js index 5b8ec6064..4f65b8db5 100644 --- a/js/app/ui/dialog/map_info.js +++ b/js/app/ui/dialog/map_info.js @@ -642,7 +642,7 @@ define([ } } } - +console.log(usersData); var userDataTable = userTable.dataTable( { pageLength: 20, diff --git a/public/css/pathfinder.css b/public/css/pathfinder.css index 8dccc9c2a..e52841ad8 100644 --- a/public/css/pathfinder.css +++ b/public/css/pathfinder.css @@ -38,4 +38,4 @@ * ======================================================================== * Copyright 2014 Min Hur, The New York Times Company * Licensed under MIT - * ======================================================================== */label.checkbox .toggle,label.checkbox.inline .toggle{margin-left:-20px;margin-right:5px}.toggle{min-width:40px;height:20px;position:relative;overflow:hidden}.toggle input[type="checkbox"]{display:none}.toggle-group{position:absolute;width:200%;top:0;bottom:0;left:0;transition:left 0.35s;-webkit-transition:left 0.35s;-moz-user-select:none;-webkit-user-select:none}.toggle.off .toggle-group{left:-100%}.toggle-on{position:absolute;top:0;bottom:0;left:0;right:50%;margin:0;border:0;border-radius:0}.toggle-off{position:absolute;top:0;bottom:0;left:50%;right:0;margin:0;border:0;border-radius:0}.toggle-handle{position:relative;margin:0 auto;padding-top:0px;padding-bottom:0px;height:100%;width:0px;border-width:0 1px}.toggle-handle.btn-mini{top:-2px}.toggle.btn,button.toggle.DTTT_button,div.toggle.DTTT_button,a.toggle.DTTT_button{min-width:30px}.toggle-on.btn,button.toggle-on.DTTT_button,div.toggle-on.DTTT_button,a.toggle-on.DTTT_button{padding-right:24px}.toggle-off.btn,button.toggle-off.DTTT_button,div.toggle-off.DTTT_button,a.toggle-off.DTTT_button{padding-left:24px}.toggle.btn-large{min-width:40px}.toggle-on.btn-large{padding-right:35px}.toggle-off.btn-large{padding-left:35px}.toggle.btn-small{min-width:25px}.toggle-on.btn-small{padding-right:20px}.toggle-off.btn-small{padding-left:20px}.toggle.btn-mini{min-width:20px}.toggle-on.btn-mini{padding-right:12px}.toggle-off.btn-mini{padding-left:12px}html{margin:0;padding:0;height:100%;position:relative}body{margin:0;padding:0;min-height:100%;direction:ltr}body.mobile-view-activated.hidden-menu{overflow-x:hidden}body.modal-open{overflow:hidden !important}a:hover,a:active,a:focus,button,button:active,button:focus,object,embed,input::-moz-focus-inner{outline:0}h1,h3,h4{margin:0;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif}.page-title{margin:12px 0 28px}.page-title span{font-size:15px;color:#313335;display:inline-block;vertical-align:1px}label{font-weight:normal}*:focus{outline:0 !important}a,input,button{-ms-touch-action:none !important}textarea:focus,select:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{outline:0;outline:thin dotted \9;box-shadow:inset -1px 1px 5px 0 rgba(0,0,0,0.8) !important}.input-sm,.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn,.input-group-sm>.input-group-btn>button.DTTT_button,.input-group-sm>.input-group-btn>div.DTTT_button,.input-group-sm>.input-group-btn>a.DTTT_button,.input-lg,.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn,.input-group-lg>.input-group-btn>button.DTTT_button,.input-group-lg>.input-group-btn>div.DTTT_button,.input-group-lg>.input-group-btn>a.DTTT_button,.input-xs,.form-control{border-radius:0px !important;-webkit-border-radius:0px !important;-moz-border-radius:0px !important}.input-xs{height:24px;padding:2px 10px;font-size:11px;line-height:1.5}.btn-xs,.btn-group-xs>.btn,.btn-group-xs>button.DTTT_button,.btn-group-xs>div.DTTT_button,.btn-group-xs>a.DTTT_button{padding:0px 2px;font-size:10px;line-height:1.3}.btn-sm,.btn-group-sm>.btn,.btn-group-sm>button.DTTT_button,.btn-group-sm>div.DTTT_button,.btn-group-sm>a.DTTT_button,button.DTTT_button,div.DTTT_button,a.DTTT_button{padding:5px 8px 4px}.btn-lg,.btn-group-lg>.btn,.btn-group-lg>button.DTTT_button,.btn-group-lg>div.DTTT_button,.btn-group-lg>a.DTTT_button{padding:10px 16px}.no-space{margin:0}.no-space>[class*="col-"]{margin:0 !important;padding-right:0;padding-left:0}h1{letter-spacing:-1px;font-size:22px;margin:10px 0}h1 small{font-size:12px;font-weight:300;letter-spacing:-1px}h2{font-size:20px;margin:20px 0;line-height:normal}h3{display:block;font-size:17px;font-weight:400;margin:20px 0;line-height:normal}h4{line-height:normal;margin:20px 0 10px 0}h5{font-size:14px;font-weight:300;margin-top:0;margin-bottom:10px;line-height:normal}h6{font-size:13px;margin:10px 0;font-weight:bold;line-height:normal}.row-seperator-header{margin:15px 14px 20px;border-bottom:none;display:block;color:#303133;font-size:20px;font-weight:400}.center-canvas,.center-child-canvas>canvas{display:block !important;margin:0 auto !important}.smart-accordion-default.panel-group{margin-bottom:0px}.smart-accordion-default.panel-group .panel+.panel{margin-top:-1px}.smart-accordion-default.panel-group .panel-heading{padding:0px}.smart-accordion-default.panel-group .panel-title a{display:block;padding:10px 15px;text-decoration:none !important}.smart-accordion-default .panel-heading,.panel-group .panel{border-radius:0px;-webkit-border-radius:0px;-moz-border-radius:0px}.smart-accordion-default .panel-default>.panel-heading{background-color:#f3f3f3}.smart-accordion-default .panel-default{border-color:#8d9194}.smart-accordion-default .panel-title>a>:first-child{display:none}.smart-accordion-default .panel-title>a.collapsed>.fa,.smart-accordion-default .pf-landing .pf-landing-list li .panel-title>a.collapsed>i,.pf-landing .pf-landing-list li .smart-accordion-default .panel-title>a.collapsed>i{display:none}.smart-accordion-default .panel-title>a.collapsed>:first-child{display:inline-block}.no-padding .smart-accordion-default>div{border-left:none !important;border-right:none !important}.no-padding .smart-accordion-default>div:first-child{border-top:none !important}.no-padding .smart-accordion-default>div:last-child{border-bottom:none !important}.onoffswitch-container{margin-top:4px;margin-left:7px;display:inline-block}.onoffswitch{position:relative;width:50px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;margin-top:3px;margin-bottom:3px;margin-left:5px;display:inline-block;vertical-align:middle}.onoffswitch-checkbox{display:none}.onoffswitch-label{display:block;overflow:hidden;cursor:pointer;border:1px solid #484c4e;border-radius:50px;border-color:#777b7f #7c8184 #686c6f;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.onoffswitch-inner{width:200%;margin-left:-100%;display:block}.onoffswitch-inner:before,.onoffswitch-inner:after{float:left;width:50%;height:15px;padding:0;line-height:15px;font-size:10px;color:#fff;font-family:Trebuchet, Arial, sans-serif;font-weight:bold;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.onoffswitch-inner:before{content:attr(data-swchon-text);text-shadow:0 -1px 0 #313335;padding-left:7px;background-color:#3276b1;color:#fff;box-shadow:inset 0 2px 6px rgba(0,0,0,0.5),0 1px 2px rgba(0,0,0,0.05);text-align:left}.onoffswitch-inner:after{content:attr(data-swchoff-text);padding-right:7px;text-shadow:0 -1px 0 #fff;background-color:#fff;color:#3c3f41;text-align:right;box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.onoffswitch-switch{width:19px;height:19px;margin:-2px;background:white;border:1px solid #64686b;border-radius:50px;position:absolute;top:0;bottom:0;right:32px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;background-color:#eaeaea;background-image:-moz-linear-gradient(top, #fff, #adadad);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#adadad));background-image:-webkit-linear-gradient(top, #fff, #adadad);background-image:-o-linear-gradient(top, #fff, #adadad);background-image:linear-gradient(to bottom, #ffffff,#adadad);background-repeat:repeat-x;-webkit-box-shadow:1px 1px 4px 0px rgba(0,0,0,0.3);box-shadow:1px 1px 4px 0px rgba(0,0,0,0.3)}.onoffswitch-checkbox+.onoffswitch-label .onoffswitch-switch:before,.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-switch:before{content:"\f00d";color:#a52521;display:block;text-align:center;line-height:19px;font-size:10px;text-shadow:0 -1px 0 #fff;font-weight:bold;font-family:FontAwesome}.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-switch:before{content:"\f00c";color:#428bca}.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-inner{margin-left:0;display:block}.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-switch{right:0px}.onoffswitch-switch:hover{background-color:#adadad}.onoffswitch-switch:active{background-color:#adadad;box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.onoffswitch-checkbox:disabled+.onoffswitch-label .onoffswitch-inner:after,.onoffswitch-checkbox:checked:disabled+.onoffswitch-label .onoffswitch-inner:before{text-shadow:0 1px 0 #fff;background:#bfbfbf;color:#313335}.onoffswitch-checkbox:checked:disabled+.onoffswitch-label .onoffswitch-switch,.onoffswitch-checkbox:disabled+.onoffswitch-label .onoffswitch-switch{background-color:#eaeaea;background-image:-moz-linear-gradient(top, #bfbfbf, #eaeaea);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#bfbfbf), to(#eaeaea));background-image:-webkit-linear-gradient(top, #bfbfbf, #eaeaea);background-image:-o-linear-gradient(top, #bfbfbf, #eaeaea);background-image:linear-gradient(to bottom, #bfbfbf,#eaeaea);box-shadow:none !important}.onoffswitch-checkbox:disabled+.onoffswitch-label,.onoffswitch-checkbox:checked:disabled+.onoffswitch-label .onoffswitch-label{border-color:#74797c #63676a #525558 !important}.onoffswitch-checkbox:checked+.onoffswitch-label{border-color:#3276b1 #2a6395 #255681}.onoffswitch+span,.onoffswitch-title{display:inline-block;vertical-align:middle;margin-top:-5px}.form-control{box-shadow:none !important;-webkit-box-shadow:none !important;-moz-box-shadow:none !important}.form hr{margin-left:-13px;margin-right:-13px;border-color:rgba(0,0,0,0.1);margin-top:20px;margin-bottom:20px}.form fieldset{display:block;border:none;background:rgba(255,255,255,0.9);position:relative}fieldset{position:relative}.form-actions{display:block;padding:13px 14px 15px;border-top:1px solid rgba(0,0,0,0.1);background:rgba(239,239,239,0.9);margin-top:25px;margin-left:-13px;margin-right:-13px;margin-bottom:-13px;text-align:right}.well .form-actions{margin-left:-19px;margin-right:-19px;margin-bottom:-19px}.well.well-lg .form-actions{margin-left:-24px;margin-right:-24px;margin-bottom:-24px}.well.well-sm .form-actions{margin-left:-9px;margin-right:-9px;margin-bottom:-9px}.popover-content .form-actions{margin:0 -14px -9px;border-radius:0 0 3px 3px;padding:9px 14px}.no-padding .form .form-actions{margin:0;display:block;padding:13px 14px 15px;border-top:1px solid rgba(0,0,0,0.1);background:rgba(248,248,248,0.9);text-align:right;margin-top:25px}.form header,legend{display:block;padding:8px 0;border-bottom:1px dashed rgba(0,0,0,0.2);background:#fff;font-size:16px;font-weight:300;color:#2b2b2b;margin:25px 0px 20px}.no-padding .form header{margin:25px 14px 0}.form header:first-child{margin-top:10px}legend{font-weight:400;margin-top:0px;background:none}.input-group-addon{padding:6px 10px;will-change:background-color, border-color;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;-webkit-transition:all ease-out 0.15s;transition:all ease-out 0.15s}.input-group-addon .fa,.input-group-addon .pf-landing .pf-landing-list li i,.pf-landing .pf-landing-list li .input-group-addon i{font-size:14px}.input-group-addon .fa-lg,.input-group-addon .fa-2x{font-size:2em}.input-group-addon .fa-3x,.input-group-addon .fa-4x,.input-group-addon .fa-5x{font-size:30px}input[type="text"]:focus+.input-group-addon,input[type="password"]:focus+.input-group-addon,input[type="email"]:focus+.input-group-addon{border-color:#568a89;color:#568a89}.has-warning input[type="text"],.has-warning input[type="text"]+.input-group-addon{border-color:#e28a0d}.has-warning input[type="text"]+.input-group-addon{background-color:#fbe3c0;color:#2b2b2b}.has-warning input[type="text"]:focus,.has-warning input[type="text"]:focus+.input-group-addon{border-color:#e28a0d}.has-warning input[type="text"]:focus+.input-group-addon{background-color:#e28a0d;color:#fff}.has-error .input-group-addon{border-color:#d9534f !important;background:#d9534f !important;color:#2b2b2b !important}.has-success .input-group-addon{border-color:#4f9e4f !important;background-color:#2b2b2b !important;color:#4f9e4f !important}.form fieldset .form-group:last-child,.form fieldset .form-group:last-child .note,.form .form-group:last-child,.form .form-group:last-child .note{margin-bottom:0}.note{margin-top:6px;padding:0 1px;font-size:11px;line-height:15px;color:#63676a}.input-icon-right{position:relative}.input-icon-right>i,.input-icon-left>i{position:absolute;right:10px;top:30%;font-size:16px;color:#bfbfbf}.input-icon-left>i{right:auto;left:24px}.input-icon-right .form-control{padding-right:27px}.input-icon-left .form-control{padding-left:29px}input[type="text"].ui-autocomplete-loading,input[type="password"].ui-autocomplete-loading,input[type="datetime"].ui-autocomplete-loading,input[type="datetime-local"].ui-autocomplete-loading,input[type="date"].ui-autocomplete-loading,input[type="month"].ui-autocomplete-loading,input[type="time"].ui-autocomplete-loading,input[type="week"].ui-autocomplete-loading,input[type="number"].ui-autocomplete-loading,input[type="email"].ui-autocomplete-loading,input[type="url"].ui-autocomplete-loading,input[type="search"].ui-autocomplete-loading,input[type="tel"].ui-autocomplete-loading,input[type="color"].ui-autocomplete-loading{background-image:url("../img/select2-spinner.gif") !important;background-repeat:no-repeat;background-position:99% 50%;padding-right:27px}.input-group-addon .checkbox,.input-group-addon .radio{min-height:0px;margin-right:0px !important;padding-top:0}.input-group-addon label input[type="checkbox"].checkbox+span,.input-group-addon label input[type="radio"].radiobox+span,.input-group-addon label input[type="radio"].radiobox+span:before,.input-group-addon label input[type="checkbox"].checkbox+span:before{margin-right:0px}.input-group-addon .onoffswitch,.input-group-addon .onoffswitch-label{margin:0}.alert{margin-bottom:10px;margin-top:0px;padding:5px 15px 5px 34px;color:#675100;border-width:0px;border-left-width:3px;padding:10px}.alert .ui-pnotify-title{line-height:12px}.alert .ui-pnotify-text{font-size:10px}.alert .close{top:0px;right:-5px;line-height:20px}.alert-heading{font-weight:600}.alert-danger{border-color:#a52521;color:#2b2b2b;background:#f6d1d0;text-shadow:none}.alert-danger .ui-pnotify-icon{color:#a52521}.alert-warning{border-color:#e28a0d;color:#2b2b2b;background:#fdedd8}.alert-warning .ui-pnotify-icon{color:#e28a0d}.alert-success{border-color:#4f9e4f;color:#2b2b2b;background:#d1e8d1}.alert-success .ui-pnotify-icon{color:#4f9e4f}.alert-info{border-color:#316490;color:#2b2b2b;background:#abc9e2}.alert-info .ui-pnotify-icon{color:#316490}.progress-micro{height:3px !important;line-height:3px !important}.progress-xs{height:7px !important;line-height:7px !important}.progress-sm{height:14px !important;line-height:14px !important}.progress-lg{height:30px !important;line-height:30px !important}.progress .progress-bar{position:absolute;overflow:hidden;line-height:18px}.progress .progressbar-back-text{position:absolute;width:100%;height:100%;font-size:12px;line-height:20px;text-align:center}.progress .progressbar-front-text{display:block;width:100%;font-size:12px;line-height:20px;text-align:center}.progress.right .progress-bar{right:0}.progress.right .progressbar-front-text{position:absolute;right:0}.progress.vertical{width:25px;height:100%;min-height:150px;margin-right:20px;display:inline-block;margin-bottom:0px}.progress.wide-bar{width:40px}.progress.vertical.bottom{position:relative}.progress.vertical.bottom .progressbar-front-text{position:absolute;bottom:0}.progress.vertical .progress-bar{width:100%;height:0;-webkit-transition:height 0.6s ease;transition:height 0.6s ease}.progress.vertical.bottom .progress-bar{position:absolute;bottom:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{position:relative;margin-bottom:20px;overflow:hidden;height:18px;background:#adadad;box-shadow:0 1px 0 transparent,0 0 0 1px #aeb1b3 inset;-webkit-box-shadow:0 1px 0 transparent,0 0 0 1px #aeb1b3 inset;-moz-box-shadow:0 1px 0 transparent,0 0 0 1px #aeb1b3 inset;border-radius:0px;-moz-border-radius:0px;-webkit-border-radius:0px}.progress-bar{float:left;width:0;height:100%;font-size:11px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);font-weight:bold;text-shadow:0 -1px 0 rgba(0,0,0,0.25);-webkit-transition:width 1.5s ease-in-out;transition:width 1.5s ease-in-out}.progress-striped .progress-bar{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255,255,255,0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255,255,255,0.15)), color-stop(0.75, rgba(255,255,255,0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0));background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-danger{background-color:#a52521}.progress-striped .progress-bar-danger{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255,255,255,0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255,255,255,0.15)), color-stop(0.75, rgba(255,255,255,0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0))}.progress-bar-success{background-color:#4f9e4f}.progress-striped .progress-bar-success{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255,255,255,0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255,255,255,0.15)), color-stop(0.75, rgba(255,255,255,0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0))}.progress-bar-warning{background-color:#e28a0d}.progress-striped .progress-bar-warning{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255,255,255,0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255,255,255,0.15)), color-stop(0.75, rgba(255,255,255,0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0))}.progress-bar-info{background-color:#316490}.progress-striped .progress-bar-info{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255,255,255,0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255,255,255,0.15)), color-stop(0.75, rgba(255,255,255,0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0))}.progress-info .bar,.progress .bar-info{background:#316490}.vertical-bars{padding:0;margin:0}.vertical-bars:after{content:"";display:block;height:0;clear:both}.vertical-bars li{padding:14px 0;width:25%;display:block;float:left;text-align:center}.vertical-bars li:first-child{border-left:none}.vertical-bars>li>.progress.vertical:first-child{margin-left:auto}.vertical-bars>li>.progress.vertical{margin:0 auto;float:none}.nav-tabs{border-bottom:none}.nav-tabs>li>a .badge{font-size:11px;padding:3px 5px 3px 5px;opacity:.5;margin-left:5px;min-width:17px;font-weight:normal}.tabs-left .nav-tabs>li>a .badge{margin-right:5px;margin-left:0px}.nav-tabs>li>a .label{display:inline-block;font-size:11px;margin-left:5px;opacity:.5}.nav-tabs>li>a{color:#adadad;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif}.nav-tabs>li>a:hover{color:#1d1d1d;border-color:transparent transparent #adadad transparent;margin-top:1px;border-top-width:0}.nav-tabs>li.active>a{background-color:#adadad;color:#2b2b2b;border-top-width:0px !important;margin-top:1px !important;font-weight:bold}.tabs-left .nav-tabs>li.active>a{-webkit-box-shadow:-2px 0 0 #428bca;-moz-box-shadow:-2px 0 0 #428bca;box-shadow:-2px 0 0 #428bca;border-top-width:1px !important;border-left:none !important;margin-left:1px !important}.tabs-left .nav-pills>li.active>a{border:none !important;box-shadow:none !important;-webkit-box-shadow:none !important;-moz-box-shadow:none !important}.tabs-right .nav-tabs>li.active>a{-webkit-box-shadow:2px 0 0 #428bca;-moz-box-shadow:2px 0 0 #428bca;box-shadow:2px 0 0 #428bca;border-top-width:1px !important;border-right:none !important;margin-right:1px !important}.tabs-below .nav-tabs>li.active>a{-webkit-box-shadow:0 2px 0 #428bca;-moz-box-shadow:0 2px 0 #428bca;box-shadow:0 2px 0 #428bca;border-bottom-width:0px !important;border-top:none !important;margin-top:0px !important}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #9b9b9b}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li,.tabs-left>.nav-pills>li,.tabs-right>.nav-pills>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a,.tabs-left>.nav-pills>li>a,.tabs-right>.nav-pills>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs,.tabs-left>.nav-pills{float:left;margin-right:19px;border-right:1px solid #9b9b9b}.tabs-left>.nav-pills{border-right:none}.tabs-left>.nav-tabs>li>a{margin-right:-1px}.tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#adadad #949494 #adadad #adadad}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#949494 transparent #949494 #9b9b9b;*border-right-color:#fff}.tabs-left>.tab-content{margin-left:109px}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #9b9b9b}.tabs-right>.nav-tabs>li>a{margin-left:-1px}.tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#adadad #adadad #adadad #9b9b9b}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs .active>a:focus{border-color:#9b9b9b #9b9b9b #9b9b9b transparent;*border-left-color:#fff}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #9b9b9b}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-top-color:#9b9b9b;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #9b9b9b #9b9b9b #9b9b9b}.nav-tabs.bordered{background:#fff;border:1px solid #9b9b9b}.nav-tabs.bordered>:first-child a{border-left-width:0px !important}.nav-tabs.bordered+.tab-content{border:1px solid #9b9b9b;border-top:none}.tabs-pull-right.nav-tabs>li,.tabs-pull-right.nav-pills>li{float:right}.tabs-pull-right.nav-tabs>li:first-child>a,.tabs-pull-right.nav-pills>li:first-child>a{margin-right:1px}.tabs-pull-right.bordered.nav-tabs>li:first-child>a,.tabs-pull-right.bordered.nav-pills>li:first-child>a{border-left-width:1px !important;margin-right:0px;border-right-width:0px}.dropdown-menu-xs{min-width:37px}.dropdown-menu-xs>li>a{padding:3px 10px}.dropdown-menu-xs>li>a:hover i{color:#fff !important}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropdown-submenu>a:after{display:block;content:" ";float:right;width:0;height:0;border-color:transparent;border-style:solid;border-width:5px 0 5px 5px;border-left-color:#2b2b2b;margin-top:5px;margin-right:-10px}.dropdown-submenu:hover>a:after{border-left-color:#adadad}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px}.pagination>li>a,.pagination>li>span{box-shadow:inset 0 -2px 0 rgba(0,0,0,0.05);-moz-box-shadow:inset 0 -2px 0 rgba(0,0,0,0.05);-webkit-box-shadow:inset 0 -2px 0 rgba(0,0,0,0.05)}.btn-default.disabled,button.disabled.DTTT_button,div.disabled.DTTT_button,a.disabled.DTTT_button{color:#adadad}.btn,button.DTTT_button,div.DTTT_button,a.DTTT_button{font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;will-change:background-color, border-color;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-transition:all 0.18s ease-in-out;transition:all 0.18s ease-in-out}.btn.btn-ribbon,button.btn-ribbon.DTTT_button,div.btn-ribbon.DTTT_button,a.btn-ribbon.DTTT_button{background-color:#707070;background-image:-moz-linear-gradient(top, #777, #666);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#777), to(#666));background-image:-webkit-linear-gradient(top, #777, #666);background-image:-o-linear-gradient(top, #777, #666);background-image:linear-gradient(to bottom, #777777,#666666);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff777777', endColorstr='#ff666666', GradientType=0);color:white;padding:0 5px;line-height:20px;vertical-align:middle;height:20px;display:block;border:none;float:left;margin:0 8px 0 0;cursor:pointer}.btn.btn-ribbon>i,button.btn-ribbon.DTTT_button>i,div.btn-ribbon.DTTT_button>i,a.btn-ribbon.DTTT_button>i{font-size:111%}.ribbon-button-alignment{padding-top:10px;display:inline-block}.ribbon-button-alignment.pull-right>.btn.btn-ribbon,.ribbon-button-alignment.pull-right>button.btn-ribbon.DTTT_button,.ribbon-button-alignment.pull-right>div.btn-ribbon.DTTT_button,.ribbon-button-alignment.pull-right>a.btn-ribbon.DTTT_button{margin:0 0 0 8px}.panel-purple{border-color:#6e587a}.panel-purple>.panel-heading{color:#fff;background-color:#6e587a;border-color:#6e587a}.panel-greenLight{border-color:#71843f}.panel-greenLight>.panel-heading{color:#fff;background-color:#71843f;border-color:#71843f}.panel-greenDark{border-color:#496949}.panel-greenDark>.panel-heading{color:#fff;background-color:#496949;border-color:#496949}.panel-darken{border-color:#313335}.panel-darken>.panel-heading{color:#fff;background-color:#404040;border-color:#404040}.panel-pink{border-color:#e06fdf}.panel-pink>.panel-heading{color:#fff;background-color:#e06fdf;border-color:#e06fdf}.panel-green{border-color:#5cb85c}.panel-green>.panel-heading{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.panel-blueLight{border-color:#92a2a8}.panel-blueLight>.panel-heading{color:#fff;background-color:#92a2a8;border-color:#92a2a8}.panel-pinkDark{border-color:#a8829f}.panel-pinkDark>.panel-heading{color:#fff;background-color:#a8829f;border-color:#a8829f}.panel-redLight{border-color:#a65858}.panel-redLight>.panel-heading{color:#fff;background-color:#a65858;border-color:#a65858}.panel-red{border-color:#d9534f}.panel-red>.panel-heading{color:#fff;background-color:#d9534f;border-color:#d9534f}.panel-teal{border-color:#568a89}.panel-teal>.panel-heading{color:#fff;background-color:#568a89;border-color:#568a89}.panel-orange{border-color:#e28a0d}.panel-orange>.panel-heading{color:#fff;background-color:#e28a0d;border-color:#e28a0d}.panel-blueDark{border-color:#4c4f53}.panel-blueDark>.panel-heading{color:#fff;background-color:#4c4f53;border-color:#4c4f53}.panel-magenta{border-color:#6e3671}.panel-magenta>.panel-heading{color:#fff;background-color:#6e3671;border-color:#6e3671}.panel-blue{border-color:#428bca}.panel-blue>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-footer>.btn-block{border-radius:0px;-moz-border-radius:0px;-webkit-border-radius:0px;border-bottom:none;border-left:none;border-right:none}.btn-circle{width:30px;height:30px;text-align:center;padding:6px 0;font-size:12px;line-height:18px;border-radius:50%;-moz-border-radius:50%;-webkit-border-radius:50%;-webkit-box-shadow:0 1px 6px 0 rgba(0,0,0,0.12),0 1px 6px 0 rgba(0,0,0,0.12);box-shadow:0 1px 6px 0 rgba(0,0,0,0.12),0 1px 6px 0 rgba(0,0,0,0.12)}.btn-circle.btn-sm,.btn-group-sm>.btn-circle.btn,button.btn-circle.DTTT_button,div.btn-circle.DTTT_button,a.btn-circle.DTTT_button{width:22px;height:22px;padding:4px 0;font-size:12px;line-height:14px;border-radius:50%;-moz-border-radius:50%;-webkit-border-radius:50%}.btn-circle.btn-lg,.btn-group-lg>.btn-circle.btn,.btn-group-lg>button.btn-circle.DTTT_button,.btn-group-lg>div.btn-circle.DTTT_button,.btn-group-lg>a.btn-circle.DTTT_button{width:50px;height:50px;padding:10px 15px;font-size:18px;line-height:30px;border-radius:50%;-moz-border-radius:50%;-webkit-border-radius:50%}.btn-circle.btn-xl{width:70px;height:70px;padding:10px 15px;font-size:24px;line-height:50px;border-radius:50%;-moz-border-radius:50%;-webkit-border-radius:50%}.btn-metro{margin:0 0 20px;padding-top:15px;padding-bottom:15px}.btn-metro>span{display:block;vertical-align:bottom;margin-top:10px;text-transform:uppercase}.btn-metro>span.label{position:absolute;top:0px;right:0px}.btn-label{position:relative;left:-8px;display:inline-block;padding:5px 8px;background:rgba(0,0,0,0.15);border-radius:3px 0 0 3px}.btn-labeled{padding-top:0;padding-bottom:0}.btn-link{box-shadow:none;-webkit-box-shadow:none;font-size:13px}.morris-hover.morris-default-style{border-radius:5px;padding:5px;color:#666;background:rgba(29,29,29,0.9);border:solid 2px #375959;font-family:'Oxygen Bold';font-size:10px;text-align:left;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.4);box-shadow:0 6px 12px rgba(0,0,0,0.4)}.morris-hover.morris-default-style .morris-hover-row-label{font-weight:bold}.morris-hover.morris-default-style .morris-hover-point{white-space:nowrap}.morris-hover{position:absolute;z-index:903}.fixed-page-footer .morris-hover{z-index:900}.txt-color.txt-color-blue,.txt-color-blue.pf-help,.pf-help:hover,.pf-landing .pf-landing-list li i.pf-help:hover,.pf-landing .pf-landing-list li i.txt-color-blue{color:#428bca !important}.txt-color.txt-color-blueLight,.txt-color-blueLight.pf-help,.pf-landing .pf-landing-list li i.txt-color-blueLight{color:#92a2a8 !important}.txt-color.txt-color-blueDark,.txt-color-blueDark.pf-help,.pf-landing .pf-landing-list li i.txt-color-blueDark{color:#4c4f53 !important}.txt-color.txt-color-grayLightest,.txt-color-grayLightest.pf-help,.pf-landing .pf-landing-list li i.txt-color-grayLightest{color:#eaeaea !important}.txt-color.txt-color-grayLighter,.txt-color-grayLighter.pf-help,.pf-landing .pf-landing-list li i.txt-color-grayLighter{color:#adadad !important}.txt-color.txt-color-grayLight,.txt-color-grayLight.pf-help,.pf-landing .pf-landing-list li i.txt-color-grayLight{color:#63676a !important}.txt-color.txt-color-gray,.pf-help,.pf-landing .pf-landing-list li i.txt-color-gray,.pf-landing .pf-landing-list li i.pf-help{color:#3c3f41 !important}.txt-color.txt-color-grayDark,.txt-color-grayDark.pf-help,.pf-landing .pf-landing-list li i.txt-color-grayDark{color:#313335 !important}.txt-color.txt-color-greenLight,.txt-color-greenLight.pf-help,.pf-landing .pf-landing-list li i.txt-color-greenLight{color:#66c84f !important}.txt-color.txt-color-green,.txt-color-green.pf-help,.pf-help.pf-log-info,.txt-color.pf-log-info,.pf-landing .pf-landing-list li i.pf-log-info,.pf-landing .pf-landing-list li i.txt-color-green{color:#5cb85c !important}.txt-color.txt-color-greenDark,.txt-color-greenDark.pf-help,.pf-landing .pf-landing-list li i.txt-color-greenDark{color:#4f9e4f !important}.txt-color.txt-color-redLight,.txt-color-redLight.pf-help,.pf-landing .pf-landing-list li i.txt-color-redLight{color:#a65858 !important}.txt-color.txt-color-red,.txt-color-red.pf-help,.pf-help.pf-log-error,.txt-color.pf-log-error,.pf-landing .pf-landing-list li i.pf-log-error,.pf-landing .pf-landing-list li i.txt-color-red{color:#d9534f !important}.txt-color.txt-color-redDarker,.txt-color-redDarker.pf-help,.pf-landing .pf-landing-list li i.txt-color-redDarker{color:#a52521 !important}.txt-color.txt-color-yellow,.txt-color-yellow.pf-help,.pf-landing .pf-landing-list li i.txt-color-yellow{color:#b09b5b !important}.txt-color.txt-color-orange,.txt-color-orange.pf-help,.pf-landing .pf-landing-list li i.txt-color-orange{color:#e28a0d !important}.txt-color.txt-color-orangeDark,.txt-color-orangeDark.pf-help,.pf-landing .pf-landing-list li i.txt-color-orangeDark{color:#c2760c !important}.txt-color.txt-color-pink,.txt-color-pink.pf-help,.pf-landing .pf-landing-list li i.txt-color-pink{color:#e06fdf !important}.txt-color.txt-color-pinkDark,.txt-color-pinkDark.pf-help,.pf-landing .pf-landing-list li i.txt-color-pinkDark{color:#a8829f !important}.txt-color.txt-color-purple,.txt-color-purple.pf-help,.pf-landing .pf-landing-list li i.txt-color-purple{color:#6e587a !important}.txt-color.txt-color-darken,.txt-color-darken.pf-help,.pf-landing .pf-landing-list li i.txt-color-darken{color:#404040 !important}.txt-color.txt-color-lighten,.txt-color-lighten.pf-help,.pf-landing .pf-landing-list li i.txt-color-lighten{color:#d5e7ec !important}.txt-color.txt-color-white,.txt-color-white.pf-help,.pf-landing .pf-landing-list li i.txt-color-white{color:#fff !important}.txt-color.txt-color-magenta,.txt-color-magenta.pf-help,.pf-landing .pf-landing-list li i.txt-color-magenta{color:#6e3671 !important}.txt-color.txt-color-tealLighter,.txt-color-tealLighter.pf-help,.pf-landing .pf-landing-list li i{color:#568a89 !important}.txt-color.txt-color-indigoDark,.txt-color-indigoDark.pf-help,.pf-landing .pf-landing-list li i.txt-color-indigoDark{color:#5c6bc0 !important}.txt-color.txt-color-indigoDarkest,.txt-color-indigoDarkest.pf-help,.pf-landing .pf-landing-list li i.txt-color-indigoDarkest{color:#313966 !important}.txt-color.txt-color-primary,.txt-color-primary.pf-help,.pf-landing .pf-landing-list li i.txt-color-primary{color:#375959 !important}.txt-color.txt-color-success,.txt-color-success.pf-help,.pf-landing .pf-landing-list li i.txt-color-success{color:#4f9e4f !important}.txt-color.txt-color-information,.txt-color-information.pf-help,.pf-landing .pf-landing-list li i.txt-color-information{color:#316490 !important}.txt-color.txt-color-warning,.txt-color-warning.pf-help,.pf-help.pf-log-warning,.txt-color.pf-log-warning,.pf-landing .pf-landing-list li i.pf-log-warning,.pf-landing .pf-landing-list li i.txt-color-warning{color:#e28a0d !important}.txt-color.txt-color-danger,.txt-color-danger.pf-help,.pf-landing .pf-landing-list li i.txt-color-danger{color:#a52521 !important}.bg-color.bg-color-blue{background-color:#428bca !important}.bg-color.bg-color-blueLight{background-color:#92a2a8 !important}.bg-color.bg-color-blueDark{background-color:#4c4f53 !important}.bg-color.bg-color-green{background-color:#5cb85c !important}.bg-color.bg-color-greenLight{background-color:#71843f !important}.bg-color.bg-color-greenDark{background-color:#496949 !important}.bg-color.bg-color-red{background-color:#d9534f !important}.bg-color.bg-color-yellow{background-color:#b09b5b !important}.bg-color.bg-color-orange{background-color:#e28a0d !important}.bg-color.bg-color-orangeDark{background-color:#c2760c !important}.bg-color.bg-color-pink{background-color:#e06fdf !important}.bg-color.bg-color-pinkDark{background-color:#a8829f !important}.bg-color.bg-color-purple{background-color:#6e587a !important}.bg-color.bg-color-darken{background-color:#404040 !important}.bg-color.bg-color-lighten{background-color:#d5e7ec !important}.bg-color.bg-color-white{background-color:#fff !important}.bg-color.bg-color-grayDark{background-color:#525252 !important}.bg-color.bg-color-magenta{background-color:#6e3671 !important}.bg-color.bg-color-tealLighter{background-color:#568a89 !important}.bg-color.bg-color-tealDarker{background-color:#212C30 !important}.bg-color.bg-color-tealDarkest{background-color:#1b2326 !important}.bg-color.bg-color-redLight{background-color:#a65858 !important}body{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pf-body{overflow:hidden}a{color:#477372;will-change:color;text-decoration:none;-webkit-transition:color 0.08s ease-out;transition:color 0.08s ease-out}a:hover{color:#6caead;text-decoration:none}a:focus{color:#477372}em{font-style:italic}em.pf-brand{text-transform:uppercase}.pf-font-capitalize{text-transform:capitalize}.no-padding{padding:0 !important}.pf-help{cursor:pointer;cursor:help;-webkit-transition:color 0.08s ease-out;transition:color 0.08s ease-out}.pf-dialog-icon-button,.pf-sig-table-module .pf-sig-table .pf-sig-table-edit-desc-text.editable-empty,.pf-sig-table-module .pf-sig-table .fa-plus{cursor:pointer;-webkit-transition:color 0.15s ease-out;transition:color 0.15s ease-out}.pf-dialog-icon-button:not(.collapsed),.pf-sig-table-module .pf-sig-table .pf-sig-table-edit-desc-text.editable-empty:not(.collapsed),.pf-sig-table-module .pf-sig-table .fa-plus:not(.collapsed),.pf-dialog-icon-button:hover,.pf-sig-table-module .pf-sig-table .pf-sig-table-edit-desc-text.editable-empty:hover,.pf-sig-table-module .pf-sig-table .fa-plus:hover{color:#e28a0d}.pf-module-icon-button{cursor:pointer;-webkit-transition:color 0.15s ease-out;transition:color 0.15s ease-out}.pf-module-icon-button:hover{color:#e28a0d}.alert{will-change:opacity, transform}.editable-input optgroup[label]{background-color:#3c3f41;color:#63676a}.editable-input optgroup[label] option{background-color:#313335;color:#adadad;font-family:Consolas,monospace,Menlo,Monaco,"Courier New"}select:active,select:hover{outline:none}select:active,select:hover{outline-color:red}.select2-results [class*="col-"]{line-height:22px}.select2 ::-webkit-search-cancel-button{-webkit-appearance:none !important}.select2 .select2-selection__choice__remove{float:left}.select2 .select2-selection--multiple input{box-shadow:none !important}.dataTable th.pf-table-image-cell,.dataTable th.pf-table-image-small-cell{padding-left:0 !important;padding-right:0 !important}.dataTable th.sorting,.dataTable th.sorting_asc,.dataTable th.sorting_desc{padding-right:18px !important}.dataTable td.pf-table-action-cell{cursor:pointer}.dataTable td.pf-table-image-cell{padding:0 !important}.dataTable td.pf-table-image-cell img{width:26px;border-left:1px solid #3c3f41;border-right:1px solid #3c3f41}.dataTable td.pf-table-image-small-cell img{width:24px;border-left:1px solid transparent;border-right:1px solid transparent}.dataTable td.pf-table-counter-cell{color:#63676a}.dataTable td.pf-table-counter-cell .pf-digit-counter-small{width:20px;display:inline-block;font-size:10px}.dataTable td.pf-table-counter-cell .pf-digit-counter-large{width:26px;display:inline-block;font-size:10px}table tr.collapsing{-webkit-transition:height 0.01s ease;transition:height 0.01s ease}table tr.collapse.in{display:table-row !important}.pf-table-tools{height:45px}.pf-table-tools .btn:not(:last-child),.pf-table-tools button.DTTT_button:not(:last-child),.pf-table-tools div.DTTT_button:not(:last-child),.pf-table-tools a.DTTT_button:not(:last-child){margin-right:10px}.pf-table-tools-action{will-change:height, opacity, display;opacity:0;display:none;height:0;visibility:hidden}.pf-loading-overlay{position:absolute;width:100%;height:100%;top:0;left:0;opacity:0;background:#2b2b2b;z-index:1060;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.pf-loading-overlay .pf-loading-overlay-wrapper{width:25px;height:25px;margin:auto;text-align:center;position:absolute;top:0;left:0;bottom:0;right:0}.pf-loading-overlay .pf-loading-overlay-wrapper i{padding:3px}.navbar-nav li:hover:before,.navbar-nav li.active:before{top:-4px;opacity:1}.navbar-nav li:before{content:'';position:absolute;width:100%;height:2px;background-color:#5cb85c;top:0;opacity:0;will-change:opacity, top;-webkit-transition:top 0.15s ease-out,opacity 0.15s ease-out;transition:top 0.15s ease-out,opacity 0.15s ease-out}.pf-navbar-version-info{cursor:pointer}.pf-site{will-change:transform}.sb-slidebar{will-change:transform}.sb-left .list-group-item{-webkit-box-shadow:inset -10px 0px 5px -5px rgba(0,0,0,0.4);box-shadow:inset -10px 0px 5px -5px rgba(0,0,0,0.4)}.sb-right .list-group-item{-webkit-box-shadow:inset 10px 0px 5px -5px rgba(0,0,0,0.4);box-shadow:inset 10px 0px 5px -5px rgba(0,0,0,0.4)}.mCSB_container,.mCSB_dragger{will-change:top, left}.pf-map-type-private{color:#7986cb}.pf-map-type-corporation{color:#5cb85c}.pf-map-type-alliance{color:#428bca}.pf-map-type-global{color:#568a89}#pf-map-module{margin:20px 10px 0 10px}#pf-map-module #pf-map-tabs .pf-map-type-tab-default{border-top:2px solid transparent}#pf-map-module #pf-map-tabs .pf-map-type-tab-private{border-top:2px solid #7986cb}#pf-map-module #pf-map-tabs .pf-map-type-tab-corporation{border-top:2px solid #5cb85c}#pf-map-module #pf-map-tabs .pf-map-type-tab-alliance{border-top:2px solid #428bca}#pf-map-module #pf-map-tabs .pf-map-type-tab-global{border-top:2px solid #568a89}#pf-map-module #pf-map-tabs .pf-map-tab-icon{margin-right:5px}#pf-map-module #pf-map-tabs .pf-map-tab-shared-icon{margin-left:5px}.pf-map-content-row{margin-top:10px;padding-bottom:40px}.pf-map-content-row .pf-module{font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;background:rgba(60,63,65,0.3);padding:10px;width:100%;margin-bottom:10px;will-change:height, transform, opacity;overflow:hidden;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.pf-map-content-row .pf-module:before{content:'';position:absolute;top:0;left:0;border-style:solid;border-width:0 0 6px 6px;border-color:transparent transparent transparent #3c3f41;cursor:pointer}.pf-map-content-row .pf-module .label{margin-bottom:10px}.pf-map-content-row .pf-module .pf-dynamic-area{background:rgba(43,43,43,0.4)}.pf-user-status{color:#a52521}.pf-user-status-corp{color:#5cb85c}.pf-user-status-ally{color:#428bca}.pf-user-status-own{color:#7986cb}.pf-system-effect{display:none;cursor:default;color:#adadad}.pf-system-effect-magnetar{color:#e06fdf;display:inline-block}.pf-system-effect-redgiant{color:#d9534f;display:inline-block}.pf-system-effect-pulsar{color:#428bca;display:inline-block}.pf-system-effect-wolfrayet{color:#e28a0d;display:inline-block}.pf-system-effect-cataclysmic{color:#ffb;display:inline-block}.pf-system-effect-blackhole{color:#000;display:inline-block}.pf-system-info-rally .pf-system-head{background-color:#782d77;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjEuMCIgeTE9IjEuMCIgeDI9IjAuMCIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSIyNSUiIHN0b3AtY29sb3I9IiMzZTI2NGUiLz48c3RvcCBvZmZzZXQ9IjI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iIzNlMjY0ZSIvPjxzdG9wIG9mZnNldD0iNzUlIiBzdG9wLWNvbG9yPSIjM2UyNjRlIi8+PHN0b3Agb2Zmc2V0PSI3NSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');background-size:100%;background-image:-moz-linear-gradient(135deg, #3e264e 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,#3e264e 50%,#3e264e 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0));background-image:-webkit-linear-gradient(135deg, #3e264e 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,#3e264e 50%,#3e264e 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0));background-image:linear-gradient(-45deg, #3e264e 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,#3e264e 50%,#3e264e 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0));background-size:25px 25px;-webkit-animation:move 3s linear infinite;-moz-animation:move 3s linear infinite;-ms-animation:move 3s linear infinite;animation:move 3s linear infinite}.pf-system-security-0-0{color:#be0000}.pf-system-security-0-1{color:#ab2600}.pf-system-security-0-2{color:#be3900}.pf-system-security-0-3{color:#c24e02}.pf-system-security-0-4{color:#ab5f00}.pf-system-security-0-5{color:#bebe00}.pf-system-security-0-6{color:#73bf26}.pf-system-security-0-7{color:#00bf00}.pf-system-security-0-8{color:#00bf39}.pf-system-security-0-9{color:#39bf99}.pf-system-security-1-0{color:#28c0bf}.pf-system-sec{margin-right:5px;cursor:-moz-grab;cursor:-webkit-grab}.pf-system-sec-highSec{color:#5cb85c}.pf-system-sec-lowSec{color:#e28a0d}.pf-system-sec-nullSec{color:#d9534f}.pf-system-sec-high{color:#d9534f}.pf-system-sec-mid{color:#e28a0d}.pf-system-sec-low{color:#428bca}.pf-system-sec-unknown{color:#7986cb}.pf-system-status-friendly{border-color:#428bca !important;color:#428bca}.pf-system-status-occupied{border-color:#e28a0d !important;color:#e28a0d}.pf-system-status-hostile{border-color:#d9534f !important;color:#d9534f}.pf-system-status-empty{border-color:#5cb85c !important;color:#5cb85c}.pf-system-status-unscanned{border-color:#568a89 !important;color:#568a89}.pf-system-info-status-label{background-color:#63676a;color:#000;will-change:background-color;-webkit-transition:background-color 0.5s ease-out;transition:background-color 0.5s ease-out}.pf-system-info-status-label.pf-system-status-friendly{background-color:#428bca}.pf-system-info-status-label.pf-system-status-occupied{background-color:#e28a0d}.pf-system-info-status-label.pf-system-status-hostile{background-color:#d9534f}.pf-system-info-status-label.pf-system-status-empty{background-color:#5cb85c}.pf-system-info-status-label.pf-system-status-unscanned{background-color:#568a89}.pf-system-effect-dialog-wrapper .table,.pf-jump-info-dialog .table{margin:15px 0}.pf-system-effect-dialog-wrapper .table td,.pf-jump-info-dialog .table td{text-transform:capitalize}.pf-fake-connection{box-sizing:content-box;display:inline-block;width:70px;height:4px;margin-right:5px;border-top:2px solid #63676a;border-bottom:2px solid #63676a;background-color:#3c3f41;position:relative;font-family:"Oxygen","Helvetica Neue",Helvetica,Arial,sans-serif}.pf-fake-connection.pf-map-connection-stargate{background-color:#313966;border-color:#63676a}.pf-fake-connection.pf-map-connection-jumpbridge{background-color:#6caead;border-color:#3c3f41;background:repeating-linear-gradient(to right, #6caead, #6caead 10px, #3c3f41 10px, #3c3f41 20px)}.pf-fake-connection.pf-map-connection-wh-eol{border-color:#d747d6}.pf-fake-connection.pf-map-connection-wh-reduced{background-color:#e28a0d}.pf-fake-connection.pf-map-connection-wh-critical{background-color:#a52521}.pf-fake-connection.pf-map-connection-frig{border-style:dashed;border-left:none;border-right:none}.pf-fake-connection.pf-map-connection-frig:after{content:'frig';background-color:#e28a0d;color:#1d1d1d;padding:0px 3px;position:absolute;left:25px;top:-6px;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.pf-fake-connection.pf-map-connection-preserve-mass:after{content:'save mass';background-color:#a52521;color:#eaeaea;padding:0px 3px;position:absolute;left:9px;top:-6px;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.tooltip-inner{color:#5cb85c;background-color:#3c3f41;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;padding:5px 5px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.4);box-shadow:0 6px 12px rgba(0,0,0,0.4)}.modal .tooltip{z-index:1060}.modal .tooltip .tooltip-inner{color:#313335;background-color:#adadad}.tooltip.top .tooltip-arrow{border-top-color:#63676a}.tooltip.right .tooltip-arrow{border-right-color:#63676a}.tooltip.bottom .tooltip-arrow{border-bottom-color:#63676a}.tooltip.left .tooltip-arrow{border-left-color:#63676a}.popover{z-index:1060}.popover img{-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.popover h4{color:#adadad}.popover table{color:#adadad;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;line-height:16px;font-size:11px}.popover table td{padding:0 5px}.pf-dynamic-area{padding:10px;min-height:100px;position:relative;background-color:#313335;overflow:hidden;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.pf-dynamic-area .dl-horizontal{margin-bottom:0}.pf-dynamic-area .dl-horizontal dd{min-width:100px}#pf-logo-wrapper{display:block}#pf-head{margin-bottom:0px}#pf-head a{-webkit-transition:color 0.15s ease-out;transition:color 0.15s ease-out;will-change:color}#pf-head a:focus{color:#477372}#pf-head a:focus img{border-color:#3c3f41}#pf-head a:hover{text-decoration:none}#pf-head a:hover .badge{color:#6caead}#pf-head a:hover img{border-color:#568a89}#pf-head i{margin-right:2px}#pf-head .pf-brand-desc{margin:6px 10px 0 90px;width:180px}#pf-head .pf-head-menu{padding:3px 10px;line-height:24px}#pf-head .pf-head-menu .pf-head-menu-logo{width:24px;height:24px;display:inline-block;float:left}#pf-head .badge{background-color:#3c3f41;color:#adadad}#pf-head .pf-head-user-character,#pf-head .pf-head-user-ship{opacity:0;visibility:hidden}#pf-head .pf-head-active-user,#pf-head .pf-head-current-location{display:none}#pf-head .pf-head-active-user .badge,#pf-head .pf-head-current-location .badge{-webkit-transition:color 0.3s ease-out;transition:color 0.3s ease-out}#pf-head .pf-head-user-character-image,#pf-head .pf-head-user-ship-image{display:inline-block;margin-top:-6px;margin-bottom:-6px;width:27px;border:1px solid #3c3f41;margin-right:3px;-webkit-transition:border-color 0.15s ease-out;transition:border-color 0.15s ease-out;will-change:border-color}#pf-head .pf-head-program-status{cursor:pointer}#pf-head .navbar-text{min-width:60px}#pf-head .tooltip .tooltip-inner{color:#adadad}.pf-head{-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.4);box-shadow:0 6px 12px rgba(0,0,0,0.4)}#pf-footer{position:absolute;bottom:0;left:0;width:100%;margin:0;background:rgba(60,63,65,0.3)}#pf-footer a{font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;color:#375959}#pf-footer a:hover{color:#477372;text-decoration:none}@-webkit-keyframes move{0%{background-position:0 0}100%{background-position:50px 50px}}@-moz-keyframes move{0%{background-position:0 0}100%{background-position:50px 50px}}@-ms-keyframes move{0%{background-position:0 0}100%{background-position:50px 50px}}@keyframes move{0%{background-position:0 0}100%{background-position:50px 50px}}.pf-animate{visibility:hidden;opacity:0}.pf-color-line{position:fixed;top:0;left:0;width:100%;height:3px;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzY2Yzg0ZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzY2Yzg0ZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');background-size:100%;background-image:-webkit-gradient(linear, 0% 50%, 100% 50%, color-stop(0%, #66c84f),color-stop(100%, #66c84f));background-image:-moz-linear-gradient(left, #66c84f,#66c84f 100%);background-image:-webkit-linear-gradient(left, #66c84f,#66c84f 100%);background-image:linear-gradient(to right, #66c84f,#66c84f 100%)}.pf-color-line.warning{background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2UyOGEwZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2UyOGEwZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');background-size:100%;background-image:-webkit-gradient(linear, 0% 50%, 100% 50%, color-stop(0%, #e28a0d),color-stop(100%, #e28a0d));background-image:-moz-linear-gradient(left, #e28a0d,#e28a0d 100%);background-image:-webkit-linear-gradient(left, #e28a0d,#e28a0d 100%);background-image:linear-gradient(to right, #e28a0d,#e28a0d 100%)}.pf-color-line.danger{background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2E1MjUyMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2E1MjUyMSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');background-size:100%;background-image:-webkit-gradient(linear, 0% 50%, 100% 50%, color-stop(0%, #a52521),color-stop(100%, #a52521));background-image:-moz-linear-gradient(left, #a52521,#a52521 100%);background-image:-webkit-linear-gradient(left, #a52521,#a52521 100%);background-image:linear-gradient(to right, #a52521,#a52521 100%)}.pf-splash{position:absolute;z-index:2000;background-color:#1d1d1d;color:#63676a;top:0;bottom:0;left:0;right:0;will-change:opacity}.pf-splash .pf-splash-title{position:fixed;left:50%;top:30%;text-align:center;max-width:500px;padding:20px;-moz-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%)}@media (max-width: 1200px){.pf-landing #pf-logo-container{margin:5px auto}.pf-landing .pf-brand-desc{display:none}.pf-landing .navbar .navbar-brand{margin-left:10px}}.pf-landing section{min-height:200px;padding:20px 0 40px 0;border-bottom:1px solid #2b2b2b}.pf-landing section h4{font-size:18px;font-family:"Oxygen","Helvetica Neue",Helvetica,Arial,sans-serif;margin:5px 0 10px 0;border-bottom:1px solid #2b2b2b;line-height:34px}.pf-landing .container>.row{margin-bottom:30px}.pf-landing .alert{box-shadow:0 4px 10px rgba(0,0,0,0.4)}.pf-landing a[data-gallery]{position:relative}.pf-landing a[data-gallery]:before{content:'\f002';font-family:'FontAwesome';font-size:20px;line-height:20px;color:#e28a0d;position:absolute;top:9px;left:8px;height:100%;width:100%;padding-top:calc(50% - 10px);z-index:10;text-align:center;-webkit-transition:transform 0.1s 0.06s ease-in,opacity 0.1s ease-out;transition:transform 0.1s 0.06s ease-in,opacity 0.1s ease-out;will-change:transform, opacity;transform:scale(0, 0);opacity:0}.pf-landing a[data-gallery]:hover img{border-color:#6caead;-webkit-filter:brightness(50%);filter:brightness(50%)}.pf-landing a[data-gallery]:hover:before{-webkit-transition-delay:0.1s;transition-delay:0.1s;transform:scale(1, 1);opacity:1}.pf-landing a[data-gallery] .pf-landing-image-preview{border-width:1px;border-style:solid;border-color:#1d1d1d;margin:5px 0 15px 0;display:inline-block;will-change:all;-webkit-filter:brightness(100%);filter:brightness(100%);-webkit-transition:all 0.2s ease-out;transition:all 0.2s ease-out;-webkit-box-shadow:0 4px 10px rgba(0,0,0,0.4);box-shadow:0 4px 10px rgba(0,0,0,0.4)}.pf-landing a[data-gallery] .pf-landing-image-preview.pf-landing-image-preview-small{height:160px}.pf-landing a[data-gallery] .pf-landing-image-preview.pf-landing-image-preview-medium{height:256px}#pf-landing-top{height:450px;border-bottom:1px solid #313335;position:relative}#pf-landing-top:before{content:'';width:100%;height:100%;position:absolute;background:url("../img/pf-bg.jpg") #05050a;background-repeat:no-repeat;background-position:0 0;-webkit-filter:brightness(0.9);filter:brightness(0.9)}#pf-landing-top.pf-logo-fallback{height:370px}#pf-landing-top.pf-logo-fallback:after{content:'';width:100%;height:100%;position:absolute;background:url("../img/logo_alpha.png");background-repeat:no-repeat;background-position:50% 0;margin-top:50px}#pf-landing-top #pf-header-container{position:absolute;width:100%;background-position:center center}#pf-landing-top #pf-header-container #pf-header-canvas{position:absolute;visibility:hidden;top:0;left:0}#pf-landing-top #pf-header-container #pf-logo-container{z-index:110}#pf-landing-top #pf-header-container #pf-header-preview-container{position:absolute;left:400px;width:590px;height:350px;top:92px}#pf-landing-top #pf-header-container #pf-header-preview-container .pf-header-preview-element{position:relative;margin-left:12px;margin-top:12px;height:155px;width:180px;padding:7px;opacity:0;will-change:opacity, transform;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;background-color:rgba(43,43,43,0.5)}#pf-landing-top #pf-header-container #pf-header-preview-container .pf-header-preview-element:nth-child(n+4){box-shadow:0 4px 10px rgba(0,0,0,0.4)}#pf-landing-top #pf-header-container #pf-header-preview-container .pf-header-preview-element:after{content:'';position:absolute;width:calc(100% - 14px);height:calc(100% - 14px);-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-repeat:no-repeat;background-position:50% 50%;background-color:rgba(29,29,29,0.75)}#pf-landing-top .container{position:relative;margin-top:50px}#pf-header-preview-intel:after{background-image:url("../img/landing/intel.png")}#pf-header-preview-map:after{background-image:url("../img/landing/map.png")}#pf-header-preview-scope:after{background-image:url("../img/landing/scope.png")}#pf-header-preview-signature:after{background-image:url("../img/landing/signature.png")}#pf-header-preview-data:after{background-image:url("../img/landing/data.png")}#pf-header-preview-gameplay:after{background-image:url("../img/landing/gameplay.png")}#pf-landing-login{padding-top:40px}#pf-landing-login .row{margin-bottom:0px}#pf-header-map{position:relative;margin:0 auto;height:380px;width:600px;pointer-events:none}#pf-header-map .pf-header-svg-layer{position:absolute;top:0;left:0;right:0;bottom:0}#pf-header-map #pf-header-systems{z-index:100}#pf-header-map #pf-header-connectors{z-index:90}#pf-header-map #pf-header-connections{z-index:80}#pf-header-map #pf-header-background{z-index:70}#pf-header-map #pf-header-background .pf-header-system{display:none}#pf-header-map-bg{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none}#pf-header-map-bg img{pointer-events:none}#pf-header-map-bg #pf-map-bg-image{opacity:0;position:absolute;bottom:0;right:0;width:100%;height:100%}#pf-header-map-bg #pf-map-neocom{opacity:0;height:665px;width:21px}#pf-header-map-bg #pf-map-browser{opacity:0;position:absolute;top:110px;left:21px;height:560px;width:515px}#pf-landing-gallery-carousel{background-image:url("../img/pf-header-bg.jpg")}#pf-landing-gallery-carousel .slide-content{border-radius:5px}#pf-landing-gallery-carousel h3{width:100%;text-align:left}.pf-landing-pricing-panel{margin-top:20px}.pricing-big{-webkit-box-shadow:0 4px 10px rgba(0,0,0,0.4);box-shadow:0 4px 10px rgba(0,0,0,0.4)}.pricing-big .panel-heading{border-color:#3c3f41}.pricing-big .the-price{padding:1px 0;background:#2d3031;text-align:center}.pricing-big .the-price .subscript{font-size:12px;color:#63676a}.pricing-big .price-features{background:#3c3f41;color:#adadad;padding:20px 15px;min-height:205px;line-height:22px}.pricing-big table tr td{line-height:1}#pf-landing-about .pf-landing-about-me{width:256px;height:256px;border:none;-webkit-box-shadow:0 4px 10px rgba(0,0,0,0.4);box-shadow:0 4px 10px rgba(0,0,0,0.4)}.pf-landing-footer{padding:30px 0;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;background-color:#171717}.pf-landing-footer .pf-social-networks>li{display:inline-block;line-height:1}.pf-landing-footer .pf-social-networks>li a{display:inline-block;background:rgba(99,103,106,0.5);line-height:24px;text-align:center;font-size:12px;margin-right:5px;width:28px;height:24px}#pf-static-logo-svg{opacity:0;position:absolute;z-index:105;overflow:visible}#pf-static-logo-svg path{will-change:fill, opacity, transform, translateZ, translateX, translateY;pointer-events:all;-moz-transform:translate3d(0, 0, 0);-ms-transform:translate3d(0, 0, 0);-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}.logo-ploygon-top-right{fill:#477372;fill-rule:evenodd;stroke:#477372;stroke-width:0px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1}.logo-ploygon-bottom-left{fill:#5cb85c;fill-rule:evenodd;stroke:#5cb85c;stroke-width:0px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1}.logo-ploygon-bottom-right{fill:#375959;fill-rule:evenodd;stroke:#375959;stroke-width:0px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1}.logo-ploygon-top-left{fill:#63676a;fill-opacity:1;fill-rule:evenodd;stroke:#63676a;stroke-width:0px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1}@-webkit-keyframes bounce{0%, 20%, 50%, 80%, 100%{-webkit-transform:translateY(0)}40%{-webkit-transform:translateY(-8px)}60%{-webkit-transform:translateY(-4px)}}@keyframes bounce{0%, 20%, 50%, 80%, 100%{transform:translateY(0)}40%{transform:translateY(-8px)}60%{transform:translateY(-4px)}}#pf-map-tab-element{max-width:2515px;margin:0 auto}.pf-map-tab-content .pf-map-wrapper{position:relative;width:100%;max-width:2515px;height:550px;overflow:auto;padding:5px;background:rgba(43,43,43,0.93);box-shadow:inset -3px 3px 10px 0 rgba(0,0,0,0.3);border-bottom-right-radius:5px;border-bottom-left-radius:5px;border-width:1px;border-style:solid;border-color:#313335}.pf-map-overlay{position:absolute;display:none;z-index:10000;height:36px;right:10px;background:rgba(0,0,0,0.25);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.pf-map-overlay.pf-map-overlay-timer{width:36px;bottom:23px}.pf-map-overlay.pf-map-overlay-info{top:8px;color:#2b2b2b;padding:3px;line-height:26px;min-height:36px;min-width:36px}.pf-map-overlay.pf-map-overlay-info i{display:none;margin:2px;width:26px;height:26px;opacity:0.8;color:#c2760c}.pf-map-overlay.pf-map-overlay-info i.fa,.pf-map-overlay.pf-map-overlay-info .pf-landing .pf-landing-list li i,.pf-landing .pf-landing-list li .pf-map-overlay.pf-map-overlay-info i{font-size:26px}.pf-map-overlay.pf-map-overlay-info i.glyphicon{margin-left:4px;font-size:25px}.pf-grid-small{background:url('data:image/png;base64,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') !important}.pf-map{width:2500px;height:520px;position:relative;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif}.pf-map .jsplumb-overlay{opacity:1;pointer-events:none;will-change:opacity;-webkit-transition:opacity 0.18s ease-out;transition:opacity 0.18s ease-out}.pf-map .jsplumb-hover.jsplumb-overlay{opacity:0 !important}.pf-map .jsplumb-hover:not(.jsplumb-overlay){-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-delay:0.5s;animation-delay:0.5s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-timing-function:linear;animation-timing-function:linear;animation-iteration-count:infinite;-webkit-animation-iteration-count:infinite;-webkit-animation-name:bounce;animation-name:bounce}.pf-map .jsplumb-target-hover,.pf-map .jsplumb-source-hover{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-delay:0.5s;animation-delay:0.5s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-timing-function:linear;animation-timing-function:linear;animation-iteration-count:infinite;-webkit-animation-iteration-count:infinite;-webkit-animation-name:bounce;animation-name:bounce;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.3);box-shadow:0 6px 12px rgba(0,0,0,0.3)}.pf-map .pf-system{position:absolute;min-width:60px;height:auto;overflow:hidden;background-color:#313335;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;z-index:100;will-change:top, left, opacity, transform;border-width:2px;border-style:solid;border-color:#63676a;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-webkit-transition:border-color 0.5s ease-out,box-shadow 0.2s ease-out;transition:border-color 0.5s ease-out,box-shadow 0.2s ease-out;-moz-transform:translate3d(0, 0, 0);-ms-transform:translate3d(0, 0, 0);-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}.pf-map .pf-system:hover{-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.3);box-shadow:0 6px 12px rgba(0,0,0,0.3);-moz-transform:translate3d(0, -2px, 0);-ms-transform:translate3d(0, -2px, 0);-webkit-transform:translate3d(0, -2px, 0);transform:translate3d(0, -2px, 0)}.pf-map .pf-system .pf-system-head{padding:0px 3px 0px 3px;cursor:pointer;font-family:Arial;font-weight:bold}.pf-map .pf-system .pf-system-head .pf-system-head-name{border:none;display:inline-block;min-width:41px;color:#adadad;margin-right:2px}.pf-map .pf-system .pf-system-head .fa-lock{display:none}.pf-map .pf-system .pf-system-head .pf-system-head-expand{margin-left:2px;color:#63676a;display:none}.pf-map .pf-system .pf-system-head .editable-empty{font-style:normal}.pf-map .pf-system .pf-system-body{height:0px;width:100%;overflow:hidden;cursor:-moz-grab;cursor:-webkit-grab;cursor:grab;padding:0 4px;white-space:nowrap;display:none;will-change:width;border-top-width:1px;border-top-style:dashed;border-top-color:#63676a}.pf-map .pf-system .pf-system-body .pf-system-body-item{color:#63676a;font-size:10px}.pf-map .pf-system .pf-system-body .pf-system-body-item .pf-system-body-right{text-overflow:ellipsis;float:right;color:#f0ad4e;display:none}.pf-map .pf-system .pf-system-body .pf-system-body-item .pf-user-status{font-size:7px;width:10px}.pf-map .pf-system .pf-system-body .pf-system-body-item .pf-system-body-item-name{display:inline-block;width:65px;overflow:hidden;height:11px;white-space:nowrap;text-overflow:ellipsis}.pf-map .pf-system .tooltip.in{opacity:1}.pf-map .pf-system .tooltip .tooltip-inner{color:#313335;background-color:#adadad;padding:3px 3px}.pf-map .pf-system-active:not(.pf-map-endpoint-source):not(.pf-map-endpoint-target){-webkit-box-shadow:#ffb 0px 0px 8px 0px;box-shadow:#ffb 0px 0px 8px 0px}.pf-map .pf-system-selected:not(.pf-map-endpoint-source):not(.pf-map-endpoint-target),.pf-map .jsPlumb_dragged:not(.pf-map-endpoint-source):not(.pf-map-endpoint-target){-webkit-box-shadow:#58100d 0px 0px 8px 0px;box-shadow:#58100d 0px 0px 8px 0px}.pf-map .pf-system-selected:not(.pf-map-endpoint-source):not(.pf-map-endpoint-target) .pf-system-head,.pf-map .jsPlumb_dragged:not(.pf-map-endpoint-source):not(.pf-map-endpoint-target) .pf-system-head,.pf-map .pf-system-selected:not(.pf-map-endpoint-source):not(.pf-map-endpoint-target) .pf-system-body,.pf-map .jsPlumb_dragged:not(.pf-map-endpoint-source):not(.pf-map-endpoint-target) .pf-system-body{background-color:#58100d}.pf-map .pf-system-locked .pf-system-sec{cursor:default !important}.pf-map .pf-system-locked .pf-system-body{cursor:default !important}.pf-map .pf-system-locked .fa-lock{color:#63676a !important;display:inline-block !important}.pf-map .pf-map-endpoint-source,.pf-map .pf-map-endpoint-target{z-index:90}.pf-map .pf-map-endpoint-source svg,.pf-map .pf-map-endpoint-target svg{overflow:visible}.pf-map .pf-map-endpoint-source svg circle,.pf-map .pf-map-endpoint-target svg circle{-webkit-transition:stroke 0.18s ease-out,fill 0.18s ease-out;transition:stroke 0.18s ease-out,fill 0.18s ease-out}.pf-map .pf-map-endpoint-source svg *,.pf-map .pf-map-endpoint-target svg *{stroke:#63676a;stroke-width:2;fill:#3c3f41;cursor:pointer}.pf-map .pf-map-endpoint-source:hover circle,.pf-map .pf-map-endpoint-target:hover circle{stroke:#e28a0d !important}.pf-map .pf-map-endpoint-source.jsplumb-hover,.pf-map .pf-map-endpoint-target.jsplumb-hover{z-index:95}.pf-map .pf-map-endpoint-source.jsplumb-dragging circle,.pf-map .pf-map-endpoint-target.jsplumb-dragging circle{stroke:#e28a0d}.pf-map .jsplumb-endpoint-drop-allowed circle{stroke:#5cb85c !important;fill:#5cb85c !important}.pf-map .jsplumb-endpoint-drop-forbidden circle{stroke:#a52521 !important;fill:#a52521 !important}.pf-map svg.jsplumb-connector{cursor:pointer;stroke-linecap:round;-webkit-transition:stroke 0.18s ease-out;transition:stroke 0.18s ease-out;will-change:all}.pf-map svg.jsplumb-connector path{-webkit-transition:stroke 0.18s ease-out;transition:stroke 0.18s ease-out}.pf-map svg.jsplumb-connector path:not(:first-child){stroke:#3c3f41}.pf-map svg.jsplumb-connector path:first-child{stroke:#63676a}.pf-map svg.jsplumb-connector.jsplumb-hover{z-index:80}.pf-map svg.jsplumb-connector.jsplumb-hover path:first-child{stroke:#eaeaea}.pf-map svg.jsplumb-connector.jsplumb-dragging{-webkit-transition:opacity 0.18s ease-out;transition:opacity 0.18s ease-out;opacity:0.4;z-index:80}.pf-map svg.pf-map-connection-jumpbridge{z-index:50}.pf-map svg.pf-map-connection-jumpbridge path:first-child{stroke:rgba(255,255,255,0)}.pf-map svg.pf-map-connection-jumpbridge path:not(:first-child){stroke:#568a89}.pf-map svg.pf-map-connection-jumpbridge:hover path:first-child{stroke:rgba(255,255,255,0)}.pf-map svg.pf-map-connection-jumpbridge:hover path:not(:first-child){stroke:#eaeaea}.pf-map svg.pf-map-connection-stargate{z-index:60}.pf-map svg.pf-map-connection-stargate path:first-child{stroke:#63676a}.pf-map svg.pf-map-connection-stargate path:not(:first-child){stroke:#313966}.pf-map svg.pf-map-connection-stargate:hover path:first-child{stroke:#eaeaea}.pf-map svg.pf-map-connection-wh-fresh,.pf-map svg.pf-map-connection-wh-reduced,.pf-map svg.pf-map-connection-wh-critical,.pf-map svg.pf-map-connection-wh-eol{z-index:70}.pf-map svg.pf-map-connection-wh-eol path:first-child{stroke:#d747d6}.pf-map svg.pf-map-connection-wh-eol:hover path:first-child{stroke:#eaeaea}.pf-map svg.pf-map-connection-wh-reduced path:not(:first-child){stroke:#e28a0d}.pf-map svg.pf-map-connection-wh-critical path:not(:first-child){stroke:#a52521}.pf-map .pf-map-connection-overlay{padding:1px 4px;font-size:11px;z-index:1020;-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.4);box-shadow:0 6px 12px rgba(0,0,0,0.4)}.pf-map .frig{background-color:#f0ad4e;color:#1d1d1d}.pf-map .mass{background-color:#a52521;color:#eaeaea}.ui-dialog-content label{min-width:60px}.dropdown-menu{font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;z-index:1020;will-change:opacity, top, left, transform}.dropdown-menu i{width:20px}.pf-system-tooltip-inner{color:#adadad;padding:2px 4px;min-width:25px;-webkit-transition:color 0.2s ease-out;transition:color 0.2s ease-out}.pf-system-info-popover{display:initial}.pf-system-info-popover img{width:39px}.pf-system-info-popover h6{white-space:nowrap;margin-right:50px}.pf-system-info-popover h6:before,.pf-system-info-popover h6:after{content:" ";display:table}.pf-system-info-popover h6:after{clear:both}.pf-system-info-popover .well{margin-top:7px;margin-bottom:10px}.pf-system-info-module h5{text-transform:capitalize}.pf-system-info-module .pf-system-info-description-area{min-height:123px}.pf-system-info-module .pf-system-info-description-area .pf-system-info-description{width:330px}.pf-system-info-module .pf-system-info-table{font-size:11px;white-space:nowrap}.pf-sig-table-module .pf-sig-table-clear-button{will-change:opacity, transform;display:none}.pf-sig-table-module .pf-sig-table{font-size:10px}.pf-sig-table-module .pf-sig-table .pf-sig-table-edit-desc-text{white-space:normal}.pf-sig-table-module .pf-sig-table .pf-sig-table-edit-desc-text.editable-empty{border-bottom:none}.pf-sig-table-module .pf-sig-table .pf-editable-description{background-color:#2b2b2b;max-height:50px}.pf-sig-table-module .pf-sig-table .pf-sig-table-edit-name-input{text-transform:uppercase}.pf-system-graph-module .pf-system-graph{width:100%;height:100px}.pf-system-route-module .pf-system-route-table{width:100%;font-size:11px}.pf-system-route-module .pf-system-route-table td{text-transform:capitalize}.pf-system-route-module .pf-system-route-table td>.fa,.pf-system-route-module .pf-system-route-table .pf-landing .pf-landing-list li td>i,.pf-landing .pf-landing-list li .pf-system-route-module .pf-system-route-table td>i{font-size:10px}.pf-system-killboard-module .pf-system-killboard-graph-kills{width:100%;height:100px;position:relative;margin-bottom:30px}.pf-system-killboard-module .pf-system-killboard-list{padding-bottom:10px;border-bottom:1px solid #2b2b2b}.pf-system-killboard-module .pf-system-killboard-list li{margin-left:0;overflow:visible;min-height:50px;will-change:margin-left;-webkit-transition:margin-left 0.12s cubic-bezier(0.3, 0.8, 0.8, 1.7);transition:margin-left 0.12s cubic-bezier(0.3, 0.8, 0.8, 1.7)}.pf-system-killboard-module .pf-system-killboard-list li h5{white-space:nowrap}.pf-system-killboard-module .pf-system-killboard-list li h3{width:120px;display:inline-block}.pf-system-killboard-module .pf-system-killboard-list li .pf-system-killboard-img-corp{margin-right:10px;width:16px}.pf-system-killboard-module .pf-system-killboard-list li .pf-system-killboard-img-ship{width:50px;margin-right:10px;border:1px solid #2b2b2b;transform:translateZ(1px);will-change:border-color;-moz-border-radius:25px;-webkit-border-radius:25px;border-radius:25px;-webkit-transition:border-color 0.12s ease-out;transition:border-color 0.12s ease-out}.pf-system-killboard-module .pf-system-killboard-list li:before{content:"\f054";font-family:FontAwesome;position:absolute;z-index:10;left:-25px;top:15px;color:#477372;opacity:0;will-change:opacity, left;-webkit-transition:all 0.12s ease-out;transition:all 0.12s ease-out}.pf-system-killboard-module .pf-system-killboard-list li:hover{margin-left:20px}.pf-system-killboard-module .pf-system-killboard-list li:hover .pf-system-killboard-img-ship{border-color:#568a89}.pf-system-killboard-module .pf-system-killboard-list li:hover:before{opacity:1;left:-20px}input,select{background-color:#313335;color:#adadad;border:1px solid #63676a;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif}input:focus,select:focus{border-color:#568a89}input:-webkit-autofill,select:-webkit-autofill{background-color:#313335 !important;-webkit-box-shadow:0 0 0 50px #313335 inset !important;box-shadow:0 0 0 50px #313335 inset !important;-webkit-text-fill-color:#adadad}input:-webkit-autofill:focus,select:-webkit-autofill:focus{-webkit-box-shadow:0 0 0 50px #313335 inset !important;box-shadow:0 0 0 50px #313335 inset !important;-webkit-text-fill-color:#adadad}input::-webkit-file-upload-button,select::-webkit-file-upload-button{background-color:transparent;border:none;color:#63676a;outline:none}.pf-form-dropzone{border:2px dashed #2b2b2b;height:100px;background-color:#353739;text-align:center;font-size:20px;line-height:100px;margin:15px 0;color:#2b2b2b;-moz-border-radius:10px;-webkit-border-radius:10px;border-radius:10px;-webkit-transition:color 0.18s ease-out,border-color 0.18s ease-out;transition:color 0.18s ease-out,border-color 0.18s ease-out}.pf-form-dropzone:hover{color:#568a89;border-color:#568a89;cursor:-moz-grabbing;cursor:-webkit-grabbing;cursor:grabbing}.toggle.btn:active,button.toggle.DTTT_button:active,div.toggle.DTTT_button:active,a.toggle.DTTT_button:active{box-shadow:none}.toggle .toggle-group .btn,.toggle .toggle-group button.DTTT_button,.toggle .toggle-group div.DTTT_button,.toggle .toggle-group a.DTTT_button{padding:0px 5px}.pf-icon{display:inline-block}.pf-icon.disabled{opacity:0.5;color:#63676a}.pf-icon-dotlan{background:url('data:image/png;base64,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');width:17px;height:17px;opacity:0.8;margin:-5px 0px 0 10px}.pf-icon-wormhol-es{background:url('data:image/png;base64,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');width:17px;height:17px;opacity:0.8;margin:-5px 0px 0 10px}.modal-content h2{font-family:"Oxygen","Helvetica Neue",Helvetica,Arial,sans-serif;letter-spacing:0px;font-size:14px;margin:20px 0;line-height:normal}.modal-content .dataTable,.modal-content .table{font-size:10px;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif}.modal-content hr{margin:5px 0 15px 0;border-color:#63676a}.modal-content .pf-wizard-navigation{margin:0}.modal-content .pf-wizard-navigation li:not(:last-child):before{border-top:1px solid #63676a;content:"";display:block;font-size:0;overflow:hidden;position:relative;top:12px;left:71px;right:1px;width:100%}.modal-content .pf-wizard-navigation li.finished:before{-moz-border-image:-moz-linear-gradient(left, #375959,#375959) 1 1%;-moz-border-image:linear-gradient(to right, #375959,#375959) 1 1%;-o-border-image:linear-gradient(to right, #375959,#375959) 1 1%;-webkit-border-image:-webkit-linear-gradient(left, #375959,#375959) 1 1%;-webkit-border-image:linear-gradient(to right, #375959,#375959) 1 1%;border-image:-moz-linear-gradient(left, #375959,#375959) 1 1%;border-image:-webkit-linear-gradient(left, #375959,#375959) 1 1%;border-image:linear-gradient(to right, #375959,#375959) 1 1%;border-bottom:0}.modal-content .pf-wizard-navigation li.active:before{-moz-border-image:-moz-linear-gradient(left, #4f9e4f,#63676a) 1 1%;-moz-border-image:linear-gradient(to right, #4f9e4f,#63676a) 1 1%;-o-border-image:linear-gradient(to right, #4f9e4f,#63676a) 1 1%;-webkit-border-image:-webkit-linear-gradient(left, #4f9e4f,#63676a) 1 1%;-webkit-border-image:linear-gradient(to right, #4f9e4f,#63676a) 1 1%;border-image:-moz-linear-gradient(left, #4f9e4f,#63676a) 1 1%;border-image:-webkit-linear-gradient(left, #4f9e4f,#63676a) 1 1%;border-image:linear-gradient(to right, #4f9e4f,#63676a) 1 1%;border-bottom:0}.modal-content .pf-wizard-navigation li>h6{color:#63676a;font-size:11px;margin:5px}.modal-content .pf-wizard-navigation li a:hover+h6{color:#adadad}.modal-content .pf-wizard-navigation li.active a:not(.btn-danger)+h6{color:#adadad}.modal-content .pf-dialog-finish-button,.modal-content .pf-dialog-prev-button{display:none}#pf-settings-dialog .form-group .btn-sm,#pf-settings-dialog .form-group .btn-group-sm>.btn,#pf-settings-dialog .form-group button.DTTT_button,#pf-settings-dialog .form-group div.DTTT_button,#pf-settings-dialog .form-group a.DTTT_button{padding:4px 7px 3px}#pf-settings-dialog .pf-dialog-api-row:not(:nth-last-child(3)) .pf-dialog-clone-button{display:none}#pf-settings-dialog .pf-dialog-api-row:nth-child(2):nth-last-child(3) .pf-dialog-delete-button{display:none}#pf-settings-dialog #pf-dialog-captcha-wrapper{margin:0;padding:3px 0}#pf-settings-dialog .pf-dynamic-area{display:inline-block;margin:10px 5px 20px 5px;padding:10px 10px 5px 10px;-moz-border-radius:10px;-webkit-border-radius:10px;border-radius:10px}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper{opacity:0;width:128px;border:2px solid #63676a;-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px;-webkit-transition:border-color 0.2s ease-out,box-shadow 0.2s ease-out;transition:border-color 0.2s ease-out,box-shadow 0.2s ease-out;-moz-transform:translate3d(0, 0, 0);-ms-transform:translate3d(0, 0, 0);-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);will-change:border-color, transition;overflow:hidden;cursor:pointer;display:inline-block;background-color:#2b2b2b;box-sizing:content-box}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper:before{content:"\f005";font-family:FontAwesome;position:absolute;z-index:10;left:6px;top:4px;color:#adadad;-webkit-transition:color 0.2s ease-out;transition:color 0.2s ease-out}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper.pf-dialog-character-main{border-color:#c2760c}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper.pf-dialog-character-main:hover{border-color:#e28a0d}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper.pf-dialog-character-main:before{color:#e28a0d}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper:hover{border-color:#375959;-webkit-box-shadow:0 4px 10px rgba(0,0,0,0.4);box-shadow:0 4px 10px rgba(0,0,0,0.4)}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper:hover .pf-dialog-character-name{color:#568a89}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper:hover .pf-dialog-character-image{-webkit-filter:grayscale(50%);filter:grayscale(50%)}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper:hover:before{color:#e28a0d}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper .pf-dialog-image{overflow:hidden;width:128px;height:128px;position:relative}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper .pf-dialog-image .pf-dialog-character-info{position:absolute;top:0;left:0;width:0;height:100%;background:rgba(60,63,65,0.8);overflow:hidden;will-change:width, transition;padding:10px 0}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper .pf-dialog-image .pf-dialog-character-info .pf-dialog-character-info-text{line-height:25px}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper .pf-dialog-character-name{font-size:13px;line-height:30px;border-top:1px solid #313335;-webkit-transition:color 0.2s ease-out;transition:color 0.2s ease-out}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper .pf-dialog-character-image{-webkit-transition:all 0.3s ease-out;transition:all 0.3s ease-out;-webkit-filter:grayscale(0%);filter:grayscale(0%)}#pf-map-dialog #pf-map-dialog-user-select,#pf-map-dialog #pf-map-dialog-corporation-select,#pf-map-dialog #pf-map-dialog-alliance-select{width:300px}#pf-manual-scrollspy{position:relative;height:500px;overflow:auto}.pf-system-dialog-select{width:270px !important}h2.pf-dynamic-area,h4.pf-dynamic-area{min-height:0}.pf-credits-dialog .pf-credits-logo-background{overflow:visible;background:url("../img/logo_bg.png");padding:20px;margin-bottom:20px}.pf-credits-dialog #pf-logo-container{width:355px;height:366px;margin:0 auto}.pf-log-graph{height:100px;width:100%}.pf-animation-slide-in{-moz-animation-duration:1.2s;-webkit-animation-duration:1.2s;-moz-animation-name:pfSlideIn;-webkit-animation-name:pfSlideIn;position:relative}@-webkit-keyframes pfSlideIn{from{opacity:0;top:-20px}to{opacity:1;top:0px}}@-moz-keyframes pfSlideIn{from{opacity:0;top:-20px}to{opacity:1;top:0px}}@-ms-keyframes pfSlideIn{from{opacity:0;top:-20px}to{opacity:1;top:0px}}@keyframes pfSlideIn{from{opacity:0;top:-20px}to{opacity:1;top:0px}}.pf-animation-pulse-success{-webkit-animation:pulseBackgroundSuccess 3s 1;animation:pulseBackgroundSuccess 3s 1;-webkit-animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38);animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38)}.pf-animation-pulse-success .sorting_1{-webkit-animation:pulseBackgroundSuccessActive 3s 1;animation:pulseBackgroundSuccessActive 3s 1;-webkit-animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38);animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38)}.pf-animation-pulse-warning{-webkit-animation:pulseBackgroundWarning 3s 1;animation:pulseBackgroundWarning 3s 1;-webkit-animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38);animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38)}.pf-animation-pulse-warning .sorting_1{-webkit-animation:pulseBackgroundWarningActive 3s 1;animation:pulseBackgroundWarningActive 3s 1;-webkit-animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38);animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38)}@-webkit-keyframes pulseBackgroundSuccess{5%{background-color:#5cb85c;color:#313335}}@-moz-keyframes pulseBackgroundSuccess{5%{background-color:#5cb85c;color:#313335}}@-ms-keyframes pulseBackgroundSuccess{5%{background-color:#5cb85c;color:#313335}}@keyframes pulseBackgroundSuccess{5%{background-color:#5cb85c;color:#313335}}@-webkit-keyframes pulseBackgroundSuccessActive{5%{background-color:#4cae4c;color:#313335}}@-moz-keyframes pulseBackgroundSuccessActive{5%{background-color:#4cae4c;color:#313335}}@-ms-keyframes pulseBackgroundSuccessActive{5%{background-color:#4cae4c;color:#313335}}@keyframes pulseBackgroundSuccessActive{5%{background-color:#4cae4c;color:#313335}}@-webkit-keyframes pulseBackgroundWarning{5%{background-color:#e28a0d;color:#2b2b2b}}@-moz-keyframes pulseBackgroundWarning{5%{background-color:#e28a0d;color:#2b2b2b}}@-ms-keyframes pulseBackgroundWarning{5%{background-color:#e28a0d;color:#2b2b2b}}@keyframes pulseBackgroundWarning{5%{background-color:#e28a0d;color:#2b2b2b}}@-webkit-keyframes pulseBackgroundWarningActive{5%{background-color:#ca7b0c;color:#2b2b2b}}@-moz-keyframes pulseBackgroundWarningActive{5%{background-color:#ca7b0c;color:#2b2b2b}}@-ms-keyframes pulseBackgroundWarningActive{5%{background-color:#ca7b0c;color:#2b2b2b}}@keyframes pulseBackgroundWarningActive{5%{background-color:#ca7b0c;color:#2b2b2b}}.pf-animate-rotate{-webkit-transition:all 0.08s linear;transition:all 0.08s linear}.pf-animate-rotate.right{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.timeline{list-style:none;position:relative}.timeline:before{top:0;bottom:0;position:absolute;content:" ";width:1px;left:50%;margin-top:20px;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzRmOWU0ZiIvPjxzdG9wIG9mZnNldD0iMjUlIiBzdG9wLWNvbG9yPSIjNjM2NzZhIi8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');background-size:100%;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #4f9e4f),color-stop(25%, #63676a));background-image:-moz-linear-gradient(top, #4f9e4f,#63676a 25%);background-image:-webkit-linear-gradient(top, #4f9e4f,#63676a 25%);background-image:linear-gradient(to bottom, #4f9e4f,#63676a 25%)}.timeline>li{margin-bottom:20px;position:relative}.timeline>li.timeline-first .timeline-title{color:#4f9e4f}.timeline>li.timeline-first .timeline-badge{background-color:#4f9e4f}.timeline>li:before,.timeline>li:after{content:" ";display:table}.timeline>li:after{clear:both}.timeline>li:before,.timeline>li:after{content:" ";display:table}.timeline>li:after{clear:both}.timeline>li>.timeline-panel{width:47%;float:left;border:1px solid #313335;padding:8px;position:relative;background-color:#313335;-webkit-box-shadow:0 4px 10px rgba(0,0,0,0.4);box-shadow:0 4px 10px rgba(0,0,0,0.4);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.timeline>li>.timeline-panel:before{content:" ";position:absolute;top:10px;right:-8px;display:inline-block;border-top:7px solid transparent;border-left:7px solid #63676a;border-right:0 solid #63676a;border-bottom:7px solid transparent}.timeline>li>.timeline-panel:after{content:" ";position:absolute;top:10px;right:-8px;display:inline-block;border-top:7px solid transparent;border-left:7px solid #63676a;border-right:0 solid #63676a;border-bottom:7px solid transparent}.timeline>li>.timeline-badge{color:#2b2b2b;width:22px;height:22px;line-height:22px;text-align:center;position:absolute;top:7px;left:50%;margin-left:-11px;background-color:#63676a;z-index:100;-moz-border-radius:50%;-webkit-border-radius:50%;border-radius:50%}.timeline>li.timeline-inverted>.timeline-panel{float:right}.timeline>li.timeline-inverted>.timeline-panel:before{border-left-width:0;border-right-width:7px;left:-8px;right:auto}.timeline>li.timeline-inverted>.timeline-panel:after{border-left-width:0;border-right-width:8px;left:-9px;right:auto}.timeline-title{margin-top:0;color:inherit}.timeline-body>p,.timeline-body>ul{margin-bottom:0;list-style-type:disc;margin-left:15px}.timeline-body>p+p{margin-top:5px}@media (max-width: 1200px){ul.timeline:before{left:40px}ul.timeline>li>.timeline-panel{width:calc(100% - 62px)}ul.timeline>li>.timeline-badge{left:29px;margin-left:0;top:6px}ul.timeline>li>.timeline-panel{float:right}ul.timeline>li>.timeline-panel:before{border-left-width:0;border-right-width:7px;left:-8px;right:auto}ul.timeline>li>.timeline-panel:after{border-left-width:0;border-right-width:7px;left:-8px;right:auto}}.ribbon-wrapper{width:72px;height:88px;overflow:hidden;position:absolute;top:-3px;right:7px}.ribbon{font:bold 12px "Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;color:#2b2b2b;text-align:center;text-shadow:rgba(255,255,255,0.2) 0px 1px 0px;position:relative;padding:3px 0;left:-4px;top:16px;width:99px;-webkit-box-shadow:2px 3px 3px rgba(0,0,0,0.2);box-shadow:2px 3px 3px rgba(0,0,0,0.2);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-webkit-transform:rotate(45deg);transform:rotate(45deg)}.ribbon:before,.ribbon:after{content:"";border-left:3px solid transparent;border-right:3px solid transparent;position:absolute;bottom:-3px}.ribbon.ribbon-green{background-color:#5cb85c;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzUxYjM1MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzRhOTQ0YSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');background-size:100%;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #51b351),color-stop(100%, #4a944a));background-image:-moz-linear-gradient(top, #51b351,#4a944a);background-image:-webkit-linear-gradient(top, #51b351,#4a944a);background-image:linear-gradient(to bottom, #51b351,#4a944a)}.ribbon.ribbon-green:before,.ribbon.ribbon-green:after{border-top:3px solid #285028}.ribbon.ribbon-orange{background-color:#e28a0d;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2Q0ODEwYyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2I0NmQwYiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');background-size:100%;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #d4810c),color-stop(100%, #b46d0b));background-image:-moz-linear-gradient(top, #d4810c,#b46d0b);background-image:-webkit-linear-gradient(top, #d4810c,#b46d0b);background-image:linear-gradient(to bottom, #d4810c,#b46d0b)}.ribbon.ribbon-orange:before,.ribbon.ribbon-orange:after{border-top:3px solid #6c4107}.ribbon:before{left:0}.ribbon:after{right:0}.pf-loading-bars-container{position:relative;z-index:4;margin:0 auto;left:5px;right:19px;width:70px;height:50px;list-style:none}.pf-loading-bars-container .pf-loading-bars-loader{position:absolute;z-index:3;margin:0 auto;left:0;right:0;top:50%;margin-top:-19px;width:56px;height:37px;list-style:none}.pf-loading-bars-container .pf-loading-bars-loader li{background-color:#5cb85c;width:6px;height:6px;float:right;margin-right:3px !important;-webkit-box-shadow:0px 12px 6px rgba(0,0,0,0.2);box-shadow:0px 12px 6px rgba(0,0,0,0.2)}.pf-loading-bars-container .pf-loading-bars-loader li:first-child{-webkit-animation:cssload-loadbars 1.75s cubic-bezier(0.645, 0.045, 0.355, 1) infinite 0s;animation:cssload-loadbars 1.75s cubic-bezier(0.645, 0.045, 0.355, 1) infinite 0s}.pf-loading-bars-container .pf-loading-bars-loader li:nth-child(2){-webkit-animation:cssload-loadbars 1.75s ease-in-out infinite -0.35s;animation:cssload-loadbars 1.75s ease-in-out infinite -0.35s}.pf-loading-bars-container .pf-loading-bars-loader li:nth-child(3){-webkit-animation:cssload-loadbars 1.75s ease-in-out infinite -0.7s;animation:cssload-loadbars 1.75s ease-in-out infinite -0.7s}.pf-loading-bars-container .pf-loading-bars-loader li:nth-child(4){-webkit-animation:cssload-loadbars 1.75s ease-in-out infinite -1.05s;animation:cssload-loadbars 1.75s ease-in-out infinite -1.05s}.pf-loading-bars-container .pf-loading-bars-loader li:nth-child(5){-webkit-animation:cssload-loadbars 1.75s ease-in-out infinite -1.4s;animation:cssload-loadbars 1.75s ease-in-out infinite -1.4s}.pf-loading-bars-container .pf-loading-bars-loader li:nth-child(6){-webkit-animation:cssload-loadbars 1.75s ease-in-out infinite -1.75s;animation:cssload-loadbars 1.75s ease-in-out infinite -1.75s}@-webkit-keyframes cssload-loadbars{0%{height:6px;margin-top:16px}33%{height:6px;margin-top:16px}66%{height:31px;margin-top:0px}100%{height:6px;margin-top:16px}}@-moz-keyframes cssload-loadbars{0%{height:6px;margin-top:16px}33%{height:6px;margin-top:16px}66%{height:31px;margin-top:0px}100%{height:6px;margin-top:16px}}@-ms-keyframes cssload-loadbars{0%{height:6px;margin-top:16px}33%{height:6px;margin-top:16px}66%{height:31px;margin-top:0px}100%{height:6px;margin-top:16px}}@keyframes cssload-loadbars{0%{height:6px;margin-top:16px}33%{height:6px;margin-top:16px}66%{height:31px;margin-top:0px}100%{height:6px;margin-top:16px}}.youtube{background-position:center;background-repeat:no-repeat;position:relative;display:inline-block;overflow:hidden;transition:all 200ms ease-out;cursor:pointer}.youtube .play{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAERklEQVR4nOWbTWhcVRTHb1IJVoxGtNCNdal2JYJReC6GWuO83PM/59yUS3FRFARdFlwYP1CfiojQWt36sRCUurRIdVFXIn41lAoVdRGrG1M01YpKrWjiYmaSl8ybZJL3cd+YA//NLObd3++eO8x79z5jSq5Gw+8kov0AP8vMR5l1BtBZQM4B8ks75wCdZdYZZj5qLZ4hov2Nht9Z9vhKKSIaB/gI4M4w62KeAO6Mte4lYOq20FxrlqqOibhHmeWbvNC9ZfDX1mLae391aN6limO/gwgvAPJbWeAZuSDingdwXTBw7/0IsyaA/Fkh+KqOkD+YNfHej1QKD+y7iVlOhgLvFqFfNJvNGyuBJ+KDAF8MDd0tgS8y64OlgSdJMsysL4cG7SOHkyQZLhTee7+d2R2rAVy/S+Jd7/32ouBHAP4gNNRGQyTHc/84NhqNywZp5rvjjnnvt21aABFeCQ+RLwAf2hQ8s7sv9OCLk6AHNgQvIrvbfzKCD76g/O6cu7lf/iER/aQGgy448pExZmhdegAPhR9sObFWH1gT3lp7DaA/5bkIgJhZPgsNmz02novj+KqeApj1ubwXWe4kdyeznAgNvTpE/HQmvKqOMeuFogTUVQSRno+iaLRLAJF7uIgL9O4ubgL8aWgB7S44mNX+35YpICUiAvS9sBLkq1WzT+NFffl6AuoiApi6NT37h6sWkBIRZGkQ8YtLgyji6e1mBYTqCEBPG2Naz+0BWQgtoGoRgCzEsd9hAN1X5BfnFZASUfrSAFQNsyZ1FJASUVpHiLinDJG8U2cBZYogkrcNs5waBAGdstbeU9zdqpw0gPwwSAI6VUxHyFlDpOcHUUBBIuYNs14aZAE5RVwyzPr3/0EAEY0TyfGNjBWQvwZ +CTSbehfAH29mrID8bET0+0EUkAd8WYDOmqJ3ecsG30yr9wqRfm6Y+a1BEFDEjHfHvWmY9ck6CygHvBVr8Xhtb4ZE5HZA3y8DvBNA1TjnrmXWf+sioMwZX5V/VHXMGGMMoKdDCxCRvRWBdzKzdHEO+EisilbPyopHYqp6S9UCAsz4iojI7hUDAtyXVQgIDd6KnOoaWNkbI6FaPSuZGyMArsi7MZoloB4zviI/Nhr3X95jltwTRQmoIfgisy5ai+me67OI7fE4nrqjrqfK1t0eby0FPRB6oGVlchL3rgnfrq19RKbVBdhV9IOSwJmfmJi4vi/4ThERitwyCxVAFqydshuCX5awhQ9KtmuIWd8IDZED/nXT77rvVVv6sHRKwjYi91poqP7Dr+Y6JJ1VSZIMA3wkPNy6bX+o8Bcm0sXMdwM8Fxo0A3xORPaWBp6uPXsmbxCRD0NDL0dOANhVCXy6iAjMcjbcrMt3RITKwdMVRdFo+y5yvkL4eWZ+zHt/ZVD4dEVRNGotpst+dZZZH8k86lqn2pIvT/eqrNfn2xuyqYPZ8mv7s8pfn/8Pybm4TIjanscAAAAASUVORK5CYII=") no-repeat center center;background-size:64px 64px;position:absolute;height:100%;width:100%;opacity:.8;filter:alpha(opacity=80);transition:all 0.2s ease-out}.youtube .play:hover{opacity:1;filter:alpha(opacity=100)} + * ======================================================================== */label.checkbox .toggle,label.checkbox.inline .toggle{margin-left:-20px;margin-right:5px}.toggle{min-width:40px;height:20px;position:relative;overflow:hidden}.toggle input[type="checkbox"]{display:none}.toggle-group{position:absolute;width:200%;top:0;bottom:0;left:0;transition:left 0.35s;-webkit-transition:left 0.35s;-moz-user-select:none;-webkit-user-select:none}.toggle.off .toggle-group{left:-100%}.toggle-on{position:absolute;top:0;bottom:0;left:0;right:50%;margin:0;border:0;border-radius:0}.toggle-off{position:absolute;top:0;bottom:0;left:50%;right:0;margin:0;border:0;border-radius:0}.toggle-handle{position:relative;margin:0 auto;padding-top:0px;padding-bottom:0px;height:100%;width:0px;border-width:0 1px}.toggle-handle.btn-mini{top:-2px}.toggle.btn,button.toggle.DTTT_button,div.toggle.DTTT_button,a.toggle.DTTT_button{min-width:30px}.toggle-on.btn,button.toggle-on.DTTT_button,div.toggle-on.DTTT_button,a.toggle-on.DTTT_button{padding-right:24px}.toggle-off.btn,button.toggle-off.DTTT_button,div.toggle-off.DTTT_button,a.toggle-off.DTTT_button{padding-left:24px}.toggle.btn-large{min-width:40px}.toggle-on.btn-large{padding-right:35px}.toggle-off.btn-large{padding-left:35px}.toggle.btn-small{min-width:25px}.toggle-on.btn-small{padding-right:20px}.toggle-off.btn-small{padding-left:20px}.toggle.btn-mini{min-width:20px}.toggle-on.btn-mini{padding-right:12px}.toggle-off.btn-mini{padding-left:12px}html{margin:0;padding:0;height:100%;position:relative}body{margin:0;padding:0;min-height:100%;direction:ltr}body.mobile-view-activated.hidden-menu{overflow-x:hidden}body.modal-open{overflow:hidden !important}a:hover,a:active,a:focus,button,button:active,button:focus,object,embed,input::-moz-focus-inner{outline:0}h1,h3,h4{margin:0;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif}.page-title{margin:12px 0 28px}.page-title span{font-size:15px;color:#313335;display:inline-block;vertical-align:1px}label{font-weight:normal}*:focus{outline:0 !important}a,input,button{-ms-touch-action:none !important}textarea:focus,select:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{outline:0;outline:thin dotted \9;box-shadow:inset -1px 1px 5px 0 rgba(0,0,0,0.8) !important}.input-sm,.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn,.input-group-sm>.input-group-btn>button.DTTT_button,.input-group-sm>.input-group-btn>div.DTTT_button,.input-group-sm>.input-group-btn>a.DTTT_button,.input-lg,.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn,.input-group-lg>.input-group-btn>button.DTTT_button,.input-group-lg>.input-group-btn>div.DTTT_button,.input-group-lg>.input-group-btn>a.DTTT_button,.input-xs,.form-control{border-radius:0px !important;-webkit-border-radius:0px !important;-moz-border-radius:0px !important}.input-xs{height:24px;padding:2px 10px;font-size:11px;line-height:1.5}.btn-xs,.btn-group-xs>.btn,.btn-group-xs>button.DTTT_button,.btn-group-xs>div.DTTT_button,.btn-group-xs>a.DTTT_button{padding:0px 2px;font-size:10px;line-height:1.3}.btn-sm,.btn-group-sm>.btn,.btn-group-sm>button.DTTT_button,.btn-group-sm>div.DTTT_button,.btn-group-sm>a.DTTT_button,button.DTTT_button,div.DTTT_button,a.DTTT_button{padding:5px 8px 4px}.btn-lg,.btn-group-lg>.btn,.btn-group-lg>button.DTTT_button,.btn-group-lg>div.DTTT_button,.btn-group-lg>a.DTTT_button{padding:10px 16px}.no-space{margin:0}.no-space>[class*="col-"]{margin:0 !important;padding-right:0;padding-left:0}h1{letter-spacing:-1px;font-size:22px;margin:10px 0}h1 small{font-size:12px;font-weight:300;letter-spacing:-1px}h2{font-size:20px;margin:20px 0;line-height:normal}h3{display:block;font-size:17px;font-weight:400;margin:20px 0;line-height:normal}h4{line-height:normal;margin:20px 0 10px 0}h5{font-size:14px;font-weight:300;margin-top:0;margin-bottom:10px;line-height:normal}h6{font-size:13px;margin:10px 0;font-weight:bold;line-height:normal}.row-seperator-header{margin:15px 14px 20px;border-bottom:none;display:block;color:#303133;font-size:20px;font-weight:400}.center-canvas,.center-child-canvas>canvas{display:block !important;margin:0 auto !important}.smart-accordion-default.panel-group{margin-bottom:0px}.smart-accordion-default.panel-group .panel+.panel{margin-top:-1px}.smart-accordion-default.panel-group .panel-heading{padding:0px}.smart-accordion-default.panel-group .panel-title a{display:block;padding:10px 15px;text-decoration:none !important}.smart-accordion-default .panel-heading,.panel-group .panel{border-radius:0px;-webkit-border-radius:0px;-moz-border-radius:0px}.smart-accordion-default .panel-default>.panel-heading{background-color:#f3f3f3}.smart-accordion-default .panel-default{border-color:#8d9194}.smart-accordion-default .panel-title>a>:first-child{display:none}.smart-accordion-default .panel-title>a.collapsed>.fa,.smart-accordion-default .pf-landing .pf-landing-list li .panel-title>a.collapsed>i,.pf-landing .pf-landing-list li .smart-accordion-default .panel-title>a.collapsed>i{display:none}.smart-accordion-default .panel-title>a.collapsed>:first-child{display:inline-block}.no-padding .smart-accordion-default>div{border-left:none !important;border-right:none !important}.no-padding .smart-accordion-default>div:first-child{border-top:none !important}.no-padding .smart-accordion-default>div:last-child{border-bottom:none !important}.onoffswitch-container{margin-top:4px;margin-left:7px;display:inline-block}.onoffswitch{position:relative;width:50px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;margin-top:3px;margin-bottom:3px;margin-left:5px;display:inline-block;vertical-align:middle}.onoffswitch-checkbox{display:none}.onoffswitch-label{display:block;overflow:hidden;cursor:pointer;border:1px solid #484c4e;border-radius:50px;border-color:#777b7f #7c8184 #686c6f;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.onoffswitch-inner{width:200%;margin-left:-100%;display:block}.onoffswitch-inner:before,.onoffswitch-inner:after{float:left;width:50%;height:15px;padding:0;line-height:15px;font-size:10px;color:#fff;font-family:Trebuchet, Arial, sans-serif;font-weight:bold;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.onoffswitch-inner:before{content:attr(data-swchon-text);text-shadow:0 -1px 0 #313335;padding-left:7px;background-color:#3276b1;color:#fff;box-shadow:inset 0 2px 6px rgba(0,0,0,0.5),0 1px 2px rgba(0,0,0,0.05);text-align:left}.onoffswitch-inner:after{content:attr(data-swchoff-text);padding-right:7px;text-shadow:0 -1px 0 #fff;background-color:#fff;color:#3c3f41;text-align:right;box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.onoffswitch-switch{width:19px;height:19px;margin:-2px;background:white;border:1px solid #64686b;border-radius:50px;position:absolute;top:0;bottom:0;right:32px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;background-color:#eaeaea;background-image:-moz-linear-gradient(top, #fff, #adadad);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#adadad));background-image:-webkit-linear-gradient(top, #fff, #adadad);background-image:-o-linear-gradient(top, #fff, #adadad);background-image:linear-gradient(to bottom, #ffffff,#adadad);background-repeat:repeat-x;-webkit-box-shadow:1px 1px 4px 0px rgba(0,0,0,0.3);box-shadow:1px 1px 4px 0px rgba(0,0,0,0.3)}.onoffswitch-checkbox+.onoffswitch-label .onoffswitch-switch:before,.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-switch:before{content:"\f00d";color:#a52521;display:block;text-align:center;line-height:19px;font-size:10px;text-shadow:0 -1px 0 #fff;font-weight:bold;font-family:FontAwesome}.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-switch:before{content:"\f00c";color:#428bca}.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-inner{margin-left:0;display:block}.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-switch{right:0px}.onoffswitch-switch:hover{background-color:#adadad}.onoffswitch-switch:active{background-color:#adadad;box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.onoffswitch-checkbox:disabled+.onoffswitch-label .onoffswitch-inner:after,.onoffswitch-checkbox:checked:disabled+.onoffswitch-label .onoffswitch-inner:before{text-shadow:0 1px 0 #fff;background:#bfbfbf;color:#313335}.onoffswitch-checkbox:checked:disabled+.onoffswitch-label .onoffswitch-switch,.onoffswitch-checkbox:disabled+.onoffswitch-label .onoffswitch-switch{background-color:#eaeaea;background-image:-moz-linear-gradient(top, #bfbfbf, #eaeaea);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#bfbfbf), to(#eaeaea));background-image:-webkit-linear-gradient(top, #bfbfbf, #eaeaea);background-image:-o-linear-gradient(top, #bfbfbf, #eaeaea);background-image:linear-gradient(to bottom, #bfbfbf,#eaeaea);box-shadow:none !important}.onoffswitch-checkbox:disabled+.onoffswitch-label,.onoffswitch-checkbox:checked:disabled+.onoffswitch-label .onoffswitch-label{border-color:#74797c #63676a #525558 !important}.onoffswitch-checkbox:checked+.onoffswitch-label{border-color:#3276b1 #2a6395 #255681}.onoffswitch+span,.onoffswitch-title{display:inline-block;vertical-align:middle;margin-top:-5px}.form-control{box-shadow:none !important;-webkit-box-shadow:none !important;-moz-box-shadow:none !important}.form hr{margin-left:-13px;margin-right:-13px;border-color:rgba(0,0,0,0.1);margin-top:20px;margin-bottom:20px}.form fieldset{display:block;border:none;background:rgba(255,255,255,0.9);position:relative}fieldset{position:relative}.form-actions{display:block;padding:13px 14px 15px;border-top:1px solid rgba(0,0,0,0.1);background:rgba(239,239,239,0.9);margin-top:25px;margin-left:-13px;margin-right:-13px;margin-bottom:-13px;text-align:right}.well .form-actions{margin-left:-19px;margin-right:-19px;margin-bottom:-19px}.well.well-lg .form-actions{margin-left:-24px;margin-right:-24px;margin-bottom:-24px}.well.well-sm .form-actions{margin-left:-9px;margin-right:-9px;margin-bottom:-9px}.popover-content .form-actions{margin:0 -14px -9px;border-radius:0 0 3px 3px;padding:9px 14px}.no-padding .form .form-actions{margin:0;display:block;padding:13px 14px 15px;border-top:1px solid rgba(0,0,0,0.1);background:rgba(248,248,248,0.9);text-align:right;margin-top:25px}.form header,legend{display:block;padding:8px 0;border-bottom:1px dashed rgba(0,0,0,0.2);background:#fff;font-size:16px;font-weight:300;color:#2b2b2b;margin:25px 0px 20px}.no-padding .form header{margin:25px 14px 0}.form header:first-child{margin-top:10px}legend{font-weight:400;margin-top:0px;background:none}.input-group-addon{padding:6px 10px;will-change:background-color, border-color;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;-webkit-transition:all ease-out 0.15s;transition:all ease-out 0.15s}.input-group-addon .fa,.input-group-addon .pf-landing .pf-landing-list li i,.pf-landing .pf-landing-list li .input-group-addon i{font-size:14px}.input-group-addon .fa-lg,.input-group-addon .fa-2x{font-size:2em}.input-group-addon .fa-3x,.input-group-addon .fa-4x,.input-group-addon .fa-5x{font-size:30px}input[type="text"]:focus+.input-group-addon,input[type="password"]:focus+.input-group-addon,input[type="email"]:focus+.input-group-addon{border-color:#568a89;color:#568a89}.has-warning input[type="text"],.has-warning input[type="text"]+.input-group-addon{border-color:#e28a0d}.has-warning input[type="text"]+.input-group-addon{background-color:#fbe3c0;color:#2b2b2b}.has-warning input[type="text"]:focus,.has-warning input[type="text"]:focus+.input-group-addon{border-color:#e28a0d}.has-warning input[type="text"]:focus+.input-group-addon{background-color:#e28a0d;color:#fff}.has-error .input-group-addon{border-color:#d9534f !important;background:#d9534f !important;color:#2b2b2b !important}.has-success .input-group-addon{border-color:#4f9e4f !important;background-color:#2b2b2b !important;color:#4f9e4f !important}.form fieldset .form-group:last-child,.form fieldset .form-group:last-child .note,.form .form-group:last-child,.form .form-group:last-child .note{margin-bottom:0}.note{margin-top:6px;padding:0 1px;font-size:11px;line-height:15px;color:#63676a}.input-icon-right{position:relative}.input-icon-right>i,.input-icon-left>i{position:absolute;right:10px;top:30%;font-size:16px;color:#bfbfbf}.input-icon-left>i{right:auto;left:24px}.input-icon-right .form-control{padding-right:27px}.input-icon-left .form-control{padding-left:29px}input[type="text"].ui-autocomplete-loading,input[type="password"].ui-autocomplete-loading,input[type="datetime"].ui-autocomplete-loading,input[type="datetime-local"].ui-autocomplete-loading,input[type="date"].ui-autocomplete-loading,input[type="month"].ui-autocomplete-loading,input[type="time"].ui-autocomplete-loading,input[type="week"].ui-autocomplete-loading,input[type="number"].ui-autocomplete-loading,input[type="email"].ui-autocomplete-loading,input[type="url"].ui-autocomplete-loading,input[type="search"].ui-autocomplete-loading,input[type="tel"].ui-autocomplete-loading,input[type="color"].ui-autocomplete-loading{background-image:url("../img/select2-spinner.gif") !important;background-repeat:no-repeat;background-position:99% 50%;padding-right:27px}.input-group-addon .checkbox,.input-group-addon .radio{min-height:0px;margin-right:0px !important;padding-top:0}.input-group-addon label input[type="checkbox"].checkbox+span,.input-group-addon label input[type="radio"].radiobox+span,.input-group-addon label input[type="radio"].radiobox+span:before,.input-group-addon label input[type="checkbox"].checkbox+span:before{margin-right:0px}.input-group-addon .onoffswitch,.input-group-addon .onoffswitch-label{margin:0}.alert{margin-bottom:10px;margin-top:0px;padding:5px 15px 5px 34px;color:#675100;border-width:0px;border-left-width:3px;padding:10px}.alert .ui-pnotify-title{line-height:12px}.alert .ui-pnotify-text{font-size:10px}.alert .close{top:0px;right:-5px;line-height:20px}.alert-heading{font-weight:600}.alert-danger{border-color:#a52521;color:#2b2b2b;background:#f6d1d0;text-shadow:none}.alert-danger .ui-pnotify-icon{color:#a52521}.alert-warning{border-color:#e28a0d;color:#2b2b2b;background:#fdedd8}.alert-warning .ui-pnotify-icon{color:#e28a0d}.alert-success{border-color:#4f9e4f;color:#2b2b2b;background:#d1e8d1}.alert-success .ui-pnotify-icon{color:#4f9e4f}.alert-info{border-color:#316490;color:#2b2b2b;background:#abc9e2}.alert-info .ui-pnotify-icon{color:#316490}.progress-micro{height:3px !important;line-height:3px !important}.progress-xs{height:7px !important;line-height:7px !important}.progress-sm{height:14px !important;line-height:14px !important}.progress-lg{height:30px !important;line-height:30px !important}.progress .progress-bar{position:absolute;overflow:hidden;line-height:18px}.progress .progressbar-back-text{position:absolute;width:100%;height:100%;font-size:12px;line-height:20px;text-align:center}.progress .progressbar-front-text{display:block;width:100%;font-size:12px;line-height:20px;text-align:center}.progress.right .progress-bar{right:0}.progress.right .progressbar-front-text{position:absolute;right:0}.progress.vertical{width:25px;height:100%;min-height:150px;margin-right:20px;display:inline-block;margin-bottom:0px}.progress.wide-bar{width:40px}.progress.vertical.bottom{position:relative}.progress.vertical.bottom .progressbar-front-text{position:absolute;bottom:0}.progress.vertical .progress-bar{width:100%;height:0;-webkit-transition:height 0.6s ease;transition:height 0.6s ease}.progress.vertical.bottom .progress-bar{position:absolute;bottom:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{position:relative;margin-bottom:20px;overflow:hidden;height:18px;background:#adadad;box-shadow:0 1px 0 transparent,0 0 0 1px #aeb1b3 inset;-webkit-box-shadow:0 1px 0 transparent,0 0 0 1px #aeb1b3 inset;-moz-box-shadow:0 1px 0 transparent,0 0 0 1px #aeb1b3 inset;border-radius:0px;-moz-border-radius:0px;-webkit-border-radius:0px}.progress-bar{float:left;width:0;height:100%;font-size:11px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);font-weight:bold;text-shadow:0 -1px 0 rgba(0,0,0,0.25);-webkit-transition:width 1.5s ease-in-out;transition:width 1.5s ease-in-out}.progress-striped .progress-bar{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255,255,255,0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255,255,255,0.15)), color-stop(0.75, rgba(255,255,255,0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0));background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-danger{background-color:#a52521}.progress-striped .progress-bar-danger{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255,255,255,0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255,255,255,0.15)), color-stop(0.75, rgba(255,255,255,0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0))}.progress-bar-success{background-color:#4f9e4f}.progress-striped .progress-bar-success{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255,255,255,0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255,255,255,0.15)), color-stop(0.75, rgba(255,255,255,0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0))}.progress-bar-warning{background-color:#e28a0d}.progress-striped .progress-bar-warning{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255,255,255,0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255,255,255,0.15)), color-stop(0.75, rgba(255,255,255,0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0))}.progress-bar-info{background-color:#316490}.progress-striped .progress-bar-info{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255,255,255,0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255,255,255,0.15)), color-stop(0.75, rgba(255,255,255,0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0))}.progress-info .bar,.progress .bar-info{background:#316490}.vertical-bars{padding:0;margin:0}.vertical-bars:after{content:"";display:block;height:0;clear:both}.vertical-bars li{padding:14px 0;width:25%;display:block;float:left;text-align:center}.vertical-bars li:first-child{border-left:none}.vertical-bars>li>.progress.vertical:first-child{margin-left:auto}.vertical-bars>li>.progress.vertical{margin:0 auto;float:none}.nav-tabs{border-bottom:none}.nav-tabs>li>a .badge{font-size:11px;padding:3px 5px 3px 5px;opacity:.5;margin-left:5px;min-width:17px;font-weight:normal}.tabs-left .nav-tabs>li>a .badge{margin-right:5px;margin-left:0px}.nav-tabs>li>a .label{display:inline-block;font-size:11px;margin-left:5px;opacity:.5}.nav-tabs>li>a{color:#adadad;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif}.nav-tabs>li>a:hover{color:#1d1d1d;border-color:transparent transparent #adadad transparent;margin-top:1px;border-top-width:0}.nav-tabs>li.active>a{background-color:#adadad;color:#2b2b2b;border-top-width:0px !important;margin-top:1px !important;font-weight:bold}.tabs-left .nav-tabs>li.active>a{-webkit-box-shadow:-2px 0 0 #428bca;-moz-box-shadow:-2px 0 0 #428bca;box-shadow:-2px 0 0 #428bca;border-top-width:1px !important;border-left:none !important;margin-left:1px !important}.tabs-left .nav-pills>li.active>a{border:none !important;box-shadow:none !important;-webkit-box-shadow:none !important;-moz-box-shadow:none !important}.tabs-right .nav-tabs>li.active>a{-webkit-box-shadow:2px 0 0 #428bca;-moz-box-shadow:2px 0 0 #428bca;box-shadow:2px 0 0 #428bca;border-top-width:1px !important;border-right:none !important;margin-right:1px !important}.tabs-below .nav-tabs>li.active>a{-webkit-box-shadow:0 2px 0 #428bca;-moz-box-shadow:0 2px 0 #428bca;box-shadow:0 2px 0 #428bca;border-bottom-width:0px !important;border-top:none !important;margin-top:0px !important}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #9b9b9b}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li,.tabs-left>.nav-pills>li,.tabs-right>.nav-pills>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a,.tabs-left>.nav-pills>li>a,.tabs-right>.nav-pills>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs,.tabs-left>.nav-pills{float:left;margin-right:19px;border-right:1px solid #9b9b9b}.tabs-left>.nav-pills{border-right:none}.tabs-left>.nav-tabs>li>a{margin-right:-1px}.tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#adadad #949494 #adadad #adadad}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#949494 transparent #949494 #9b9b9b;*border-right-color:#fff}.tabs-left>.tab-content{margin-left:109px}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #9b9b9b}.tabs-right>.nav-tabs>li>a{margin-left:-1px}.tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#adadad #adadad #adadad #9b9b9b}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs .active>a:focus{border-color:#9b9b9b #9b9b9b #9b9b9b transparent;*border-left-color:#fff}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #9b9b9b}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-top-color:#9b9b9b;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #9b9b9b #9b9b9b #9b9b9b}.nav-tabs.bordered{background:#fff;border:1px solid #9b9b9b}.nav-tabs.bordered>:first-child a{border-left-width:0px !important}.nav-tabs.bordered+.tab-content{border:1px solid #9b9b9b;border-top:none}.tabs-pull-right.nav-tabs>li,.tabs-pull-right.nav-pills>li{float:right}.tabs-pull-right.nav-tabs>li:first-child>a,.tabs-pull-right.nav-pills>li:first-child>a{margin-right:1px}.tabs-pull-right.bordered.nav-tabs>li:first-child>a,.tabs-pull-right.bordered.nav-pills>li:first-child>a{border-left-width:1px !important;margin-right:0px;border-right-width:0px}.dropdown-menu-xs{min-width:37px}.dropdown-menu-xs>li>a{padding:3px 10px}.dropdown-menu-xs>li>a:hover i{color:#fff !important}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropdown-submenu>a:after{display:block;content:" ";float:right;width:0;height:0;border-color:transparent;border-style:solid;border-width:5px 0 5px 5px;border-left-color:#2b2b2b;margin-top:5px;margin-right:-10px}.dropdown-submenu:hover>a:after{border-left-color:#adadad}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px}.pagination>li>a,.pagination>li>span{box-shadow:inset 0 -2px 0 rgba(0,0,0,0.05);-moz-box-shadow:inset 0 -2px 0 rgba(0,0,0,0.05);-webkit-box-shadow:inset 0 -2px 0 rgba(0,0,0,0.05)}.btn-default.disabled,button.disabled.DTTT_button,div.disabled.DTTT_button,a.disabled.DTTT_button{color:#adadad}.btn,button.DTTT_button,div.DTTT_button,a.DTTT_button{font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;will-change:background-color, border-color;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-transition:all 0.18s ease-in-out;transition:all 0.18s ease-in-out}.btn.btn-ribbon,button.btn-ribbon.DTTT_button,div.btn-ribbon.DTTT_button,a.btn-ribbon.DTTT_button{background-color:#707070;background-image:-moz-linear-gradient(top, #777, #666);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#777), to(#666));background-image:-webkit-linear-gradient(top, #777, #666);background-image:-o-linear-gradient(top, #777, #666);background-image:linear-gradient(to bottom, #777777,#666666);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff777777', endColorstr='#ff666666', GradientType=0);color:white;padding:0 5px;line-height:20px;vertical-align:middle;height:20px;display:block;border:none;float:left;margin:0 8px 0 0;cursor:pointer}.btn.btn-ribbon>i,button.btn-ribbon.DTTT_button>i,div.btn-ribbon.DTTT_button>i,a.btn-ribbon.DTTT_button>i{font-size:111%}.ribbon-button-alignment{padding-top:10px;display:inline-block}.ribbon-button-alignment.pull-right>.btn.btn-ribbon,.ribbon-button-alignment.pull-right>button.btn-ribbon.DTTT_button,.ribbon-button-alignment.pull-right>div.btn-ribbon.DTTT_button,.ribbon-button-alignment.pull-right>a.btn-ribbon.DTTT_button{margin:0 0 0 8px}.panel-purple{border-color:#6e587a}.panel-purple>.panel-heading{color:#fff;background-color:#6e587a;border-color:#6e587a}.panel-greenLight{border-color:#71843f}.panel-greenLight>.panel-heading{color:#fff;background-color:#71843f;border-color:#71843f}.panel-greenDark{border-color:#496949}.panel-greenDark>.panel-heading{color:#fff;background-color:#496949;border-color:#496949}.panel-darken{border-color:#313335}.panel-darken>.panel-heading{color:#fff;background-color:#404040;border-color:#404040}.panel-pink{border-color:#e06fdf}.panel-pink>.panel-heading{color:#fff;background-color:#e06fdf;border-color:#e06fdf}.panel-green{border-color:#5cb85c}.panel-green>.panel-heading{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.panel-blueLight{border-color:#92a2a8}.panel-blueLight>.panel-heading{color:#fff;background-color:#92a2a8;border-color:#92a2a8}.panel-pinkDark{border-color:#a8829f}.panel-pinkDark>.panel-heading{color:#fff;background-color:#a8829f;border-color:#a8829f}.panel-redLight{border-color:#a65858}.panel-redLight>.panel-heading{color:#fff;background-color:#a65858;border-color:#a65858}.panel-red{border-color:#d9534f}.panel-red>.panel-heading{color:#fff;background-color:#d9534f;border-color:#d9534f}.panel-teal{border-color:#568a89}.panel-teal>.panel-heading{color:#fff;background-color:#568a89;border-color:#568a89}.panel-orange{border-color:#e28a0d}.panel-orange>.panel-heading{color:#fff;background-color:#e28a0d;border-color:#e28a0d}.panel-blueDark{border-color:#4c4f53}.panel-blueDark>.panel-heading{color:#fff;background-color:#4c4f53;border-color:#4c4f53}.panel-magenta{border-color:#6e3671}.panel-magenta>.panel-heading{color:#fff;background-color:#6e3671;border-color:#6e3671}.panel-blue{border-color:#428bca}.panel-blue>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-footer>.btn-block{border-radius:0px;-moz-border-radius:0px;-webkit-border-radius:0px;border-bottom:none;border-left:none;border-right:none}.btn-circle{width:30px;height:30px;text-align:center;padding:6px 0;font-size:12px;line-height:18px;border-radius:50%;-moz-border-radius:50%;-webkit-border-radius:50%;-webkit-box-shadow:0 1px 6px 0 rgba(0,0,0,0.12),0 1px 6px 0 rgba(0,0,0,0.12);box-shadow:0 1px 6px 0 rgba(0,0,0,0.12),0 1px 6px 0 rgba(0,0,0,0.12)}.btn-circle.btn-sm,.btn-group-sm>.btn-circle.btn,button.btn-circle.DTTT_button,div.btn-circle.DTTT_button,a.btn-circle.DTTT_button{width:22px;height:22px;padding:4px 0;font-size:12px;line-height:14px;border-radius:50%;-moz-border-radius:50%;-webkit-border-radius:50%}.btn-circle.btn-lg,.btn-group-lg>.btn-circle.btn,.btn-group-lg>button.btn-circle.DTTT_button,.btn-group-lg>div.btn-circle.DTTT_button,.btn-group-lg>a.btn-circle.DTTT_button{width:50px;height:50px;padding:10px 15px;font-size:18px;line-height:30px;border-radius:50%;-moz-border-radius:50%;-webkit-border-radius:50%}.btn-circle.btn-xl{width:70px;height:70px;padding:10px 15px;font-size:24px;line-height:50px;border-radius:50%;-moz-border-radius:50%;-webkit-border-radius:50%}.btn-metro{margin:0 0 20px;padding-top:15px;padding-bottom:15px}.btn-metro>span{display:block;vertical-align:bottom;margin-top:10px;text-transform:uppercase}.btn-metro>span.label{position:absolute;top:0px;right:0px}.btn-label{position:relative;left:-8px;display:inline-block;padding:5px 8px;background:rgba(0,0,0,0.15);border-radius:3px 0 0 3px}.btn-labeled{padding-top:0;padding-bottom:0}.btn-link{box-shadow:none;-webkit-box-shadow:none;font-size:13px}.morris-hover.morris-default-style{border-radius:5px;padding:5px;color:#666;background:rgba(29,29,29,0.9);border:solid 2px #375959;font-family:'Oxygen Bold';font-size:10px;text-align:left;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.4);box-shadow:0 6px 12px rgba(0,0,0,0.4)}.morris-hover.morris-default-style .morris-hover-row-label{font-weight:bold}.morris-hover.morris-default-style .morris-hover-point{white-space:nowrap}.morris-hover{position:absolute;z-index:903}.fixed-page-footer .morris-hover{z-index:900}.txt-color.txt-color-blue,.txt-color-blue.pf-help,.pf-help:hover,.pf-landing .pf-landing-list li i.pf-help:hover,.pf-landing .pf-landing-list li i.txt-color-blue{color:#428bca !important}.txt-color.txt-color-blueLight,.txt-color-blueLight.pf-help,.pf-landing .pf-landing-list li i.txt-color-blueLight{color:#92a2a8 !important}.txt-color.txt-color-blueDark,.txt-color-blueDark.pf-help,.pf-landing .pf-landing-list li i.txt-color-blueDark{color:#4c4f53 !important}.txt-color.txt-color-grayLightest,.txt-color-grayLightest.pf-help,.pf-landing .pf-landing-list li i.txt-color-grayLightest{color:#eaeaea !important}.txt-color.txt-color-grayLighter,.txt-color-grayLighter.pf-help,.pf-landing .pf-landing-list li i.txt-color-grayLighter{color:#adadad !important}.txt-color.txt-color-grayLight,.txt-color-grayLight.pf-help,.pf-landing .pf-landing-list li i.txt-color-grayLight{color:#63676a !important}.txt-color.txt-color-gray,.pf-help,.pf-landing .pf-landing-list li i.txt-color-gray,.pf-landing .pf-landing-list li i.pf-help{color:#3c3f41 !important}.txt-color.txt-color-grayDark,.txt-color-grayDark.pf-help,.pf-landing .pf-landing-list li i.txt-color-grayDark{color:#313335 !important}.txt-color.txt-color-greenLight,.txt-color-greenLight.pf-help,.pf-landing .pf-landing-list li i.txt-color-greenLight{color:#66c84f !important}.txt-color.txt-color-green,.txt-color-green.pf-help,.pf-help.pf-log-info,.txt-color.pf-log-info,.pf-landing .pf-landing-list li i.pf-log-info,.pf-landing .pf-landing-list li i.txt-color-green{color:#5cb85c !important}.txt-color.txt-color-greenDark,.txt-color-greenDark.pf-help,.pf-landing .pf-landing-list li i.txt-color-greenDark{color:#4f9e4f !important}.txt-color.txt-color-redLight,.txt-color-redLight.pf-help,.pf-landing .pf-landing-list li i.txt-color-redLight{color:#a65858 !important}.txt-color.txt-color-red,.txt-color-red.pf-help,.pf-help.pf-log-error,.txt-color.pf-log-error,.pf-landing .pf-landing-list li i.pf-log-error,.pf-landing .pf-landing-list li i.txt-color-red{color:#d9534f !important}.txt-color.txt-color-redDarker,.txt-color-redDarker.pf-help,.pf-landing .pf-landing-list li i.txt-color-redDarker{color:#a52521 !important}.txt-color.txt-color-yellow,.txt-color-yellow.pf-help,.pf-landing .pf-landing-list li i.txt-color-yellow{color:#b09b5b !important}.txt-color.txt-color-orange,.txt-color-orange.pf-help,.pf-landing .pf-landing-list li i.txt-color-orange{color:#e28a0d !important}.txt-color.txt-color-orangeDark,.txt-color-orangeDark.pf-help,.pf-landing .pf-landing-list li i.txt-color-orangeDark{color:#c2760c !important}.txt-color.txt-color-pink,.txt-color-pink.pf-help,.pf-landing .pf-landing-list li i.txt-color-pink{color:#e06fdf !important}.txt-color.txt-color-pinkDark,.txt-color-pinkDark.pf-help,.pf-landing .pf-landing-list li i.txt-color-pinkDark{color:#a8829f !important}.txt-color.txt-color-purple,.txt-color-purple.pf-help,.pf-landing .pf-landing-list li i.txt-color-purple{color:#6e587a !important}.txt-color.txt-color-darken,.txt-color-darken.pf-help,.pf-landing .pf-landing-list li i.txt-color-darken{color:#404040 !important}.txt-color.txt-color-lighten,.txt-color-lighten.pf-help,.pf-landing .pf-landing-list li i.txt-color-lighten{color:#d5e7ec !important}.txt-color.txt-color-white,.txt-color-white.pf-help,.pf-landing .pf-landing-list li i.txt-color-white{color:#fff !important}.txt-color.txt-color-magenta,.txt-color-magenta.pf-help,.pf-landing .pf-landing-list li i.txt-color-magenta{color:#6e3671 !important}.txt-color.txt-color-tealLighter,.txt-color-tealLighter.pf-help,.pf-landing .pf-landing-list li i{color:#568a89 !important}.txt-color.txt-color-indigoDark,.txt-color-indigoDark.pf-help,.pf-landing .pf-landing-list li i.txt-color-indigoDark{color:#5c6bc0 !important}.txt-color.txt-color-indigoDarkest,.txt-color-indigoDarkest.pf-help,.pf-landing .pf-landing-list li i.txt-color-indigoDarkest{color:#313966 !important}.txt-color.txt-color-primary,.txt-color-primary.pf-help,.pf-landing .pf-landing-list li i.txt-color-primary{color:#375959 !important}.txt-color.txt-color-success,.txt-color-success.pf-help,.pf-landing .pf-landing-list li i.txt-color-success{color:#4f9e4f !important}.txt-color.txt-color-information,.txt-color-information.pf-help,.pf-landing .pf-landing-list li i.txt-color-information{color:#316490 !important}.txt-color.txt-color-warning,.txt-color-warning.pf-help,.pf-help.pf-log-warning,.txt-color.pf-log-warning,.pf-landing .pf-landing-list li i.pf-log-warning,.pf-landing .pf-landing-list li i.txt-color-warning{color:#e28a0d !important}.txt-color.txt-color-danger,.txt-color-danger.pf-help,.pf-landing .pf-landing-list li i.txt-color-danger{color:#a52521 !important}.bg-color.bg-color-blue{background-color:#428bca !important}.bg-color.bg-color-blueLight{background-color:#92a2a8 !important}.bg-color.bg-color-blueDark{background-color:#4c4f53 !important}.bg-color.bg-color-green{background-color:#5cb85c !important}.bg-color.bg-color-greenLight{background-color:#71843f !important}.bg-color.bg-color-greenDark{background-color:#496949 !important}.bg-color.bg-color-red{background-color:#d9534f !important}.bg-color.bg-color-yellow{background-color:#b09b5b !important}.bg-color.bg-color-orange{background-color:#e28a0d !important}.bg-color.bg-color-orangeDark{background-color:#c2760c !important}.bg-color.bg-color-pink{background-color:#e06fdf !important}.bg-color.bg-color-pinkDark{background-color:#a8829f !important}.bg-color.bg-color-purple{background-color:#6e587a !important}.bg-color.bg-color-darken{background-color:#404040 !important}.bg-color.bg-color-lighten{background-color:#d5e7ec !important}.bg-color.bg-color-white{background-color:#fff !important}.bg-color.bg-color-grayDark{background-color:#525252 !important}.bg-color.bg-color-magenta{background-color:#6e3671 !important}.bg-color.bg-color-tealLighter{background-color:#568a89 !important}.bg-color.bg-color-tealDarker{background-color:#212C30 !important}.bg-color.bg-color-tealDarkest{background-color:#1b2326 !important}.bg-color.bg-color-redLight{background-color:#a65858 !important}body{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pf-body{overflow:hidden}a{color:#477372;will-change:color;text-decoration:none;-webkit-transition:color 0.08s ease-out;transition:color 0.08s ease-out}a:hover{color:#6caead;text-decoration:none}a:focus{color:#477372}em{font-style:italic}em.pf-brand{text-transform:uppercase}.pf-font-capitalize{text-transform:capitalize}.no-padding{padding:0 !important}.pf-help{cursor:pointer;cursor:help;-webkit-transition:color 0.08s ease-out;transition:color 0.08s ease-out}.pf-dialog-icon-button,.pf-sig-table-module .pf-sig-table .pf-sig-table-edit-desc-text.editable-empty,.pf-sig-table-module .pf-sig-table .fa-plus{cursor:pointer;-webkit-transition:color 0.15s ease-out;transition:color 0.15s ease-out}.pf-dialog-icon-button:not(.collapsed),.pf-sig-table-module .pf-sig-table .pf-sig-table-edit-desc-text.editable-empty:not(.collapsed),.pf-sig-table-module .pf-sig-table .fa-plus:not(.collapsed),.pf-dialog-icon-button:hover,.pf-sig-table-module .pf-sig-table .pf-sig-table-edit-desc-text.editable-empty:hover,.pf-sig-table-module .pf-sig-table .fa-plus:hover{color:#e28a0d}.pf-module-icon-button{cursor:pointer;-webkit-transition:color 0.15s ease-out;transition:color 0.15s ease-out}.pf-module-icon-button:hover{color:#e28a0d}.alert{will-change:opacity, transform}.editable-input optgroup[label]{background-color:#3c3f41;color:#63676a}.editable-input optgroup[label] option{background-color:#313335;color:#adadad;font-family:Consolas,monospace,Menlo,Monaco,"Courier New"}select:active,select:hover{outline:none}select:active,select:hover{outline-color:red}.select2-results [class*="col-"]{line-height:22px}.select2 ::-webkit-search-cancel-button{-webkit-appearance:none !important}.select2 .select2-selection__choice__remove{float:left}.select2 .select2-selection--multiple input{box-shadow:none !important}.dataTable th.pf-table-image-cell,.dataTable th.pf-table-image-small-cell{padding-left:0 !important;padding-right:0 !important}.dataTable th.sorting,.dataTable th.sorting_asc,.dataTable th.sorting_desc{padding-right:18px !important}.dataTable td.pf-table-action-cell{cursor:pointer}.dataTable td.pf-table-image-cell{padding:0 !important}.dataTable td.pf-table-image-cell img{width:26px;border-left:1px solid #3c3f41;border-right:1px solid #3c3f41}.dataTable td.pf-table-image-small-cell img{width:24px;border-left:1px solid transparent;border-right:1px solid transparent}.dataTable td.pf-table-counter-cell{color:#63676a}.dataTable td.pf-table-counter-cell .pf-digit-counter-small{width:20px;display:inline-block;font-size:10px}.dataTable td.pf-table-counter-cell .pf-digit-counter-large{width:26px;display:inline-block;font-size:10px}table tr.collapsing{-webkit-transition:height 0.01s ease;transition:height 0.01s ease}table tr.collapse.in{display:table-row !important}.pf-table-tools{height:45px}.pf-table-tools .btn:not(:last-child),.pf-table-tools button.DTTT_button:not(:last-child),.pf-table-tools div.DTTT_button:not(:last-child),.pf-table-tools a.DTTT_button:not(:last-child){margin-right:10px}.pf-table-tools-action{will-change:height, opacity, display;opacity:0;display:none;height:0;visibility:hidden}.pf-loading-overlay{position:absolute;width:100%;height:100%;top:0;left:0;opacity:0;background:#2b2b2b;z-index:1060;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.pf-loading-overlay .pf-loading-overlay-wrapper{width:25px;height:25px;margin:auto;text-align:center;position:absolute;top:0;left:0;bottom:0;right:0}.pf-loading-overlay .pf-loading-overlay-wrapper i{padding:3px}.navbar-nav li:hover:before,.navbar-nav li.active:before{top:-4px;opacity:1}.navbar-nav li:before{content:'';position:absolute;width:100%;height:2px;background-color:#5cb85c;top:0;opacity:0;will-change:opacity, top;-webkit-transition:top 0.15s ease-out,opacity 0.15s ease-out;transition:top 0.15s ease-out,opacity 0.15s ease-out}.pf-navbar-version-info{cursor:pointer}.pf-site{will-change:transform}.sb-slidebar{will-change:transform}.sb-left .list-group-item{-webkit-box-shadow:inset -10px 0px 5px -5px rgba(0,0,0,0.4);box-shadow:inset -10px 0px 5px -5px rgba(0,0,0,0.4)}.sb-right .list-group-item{-webkit-box-shadow:inset 10px 0px 5px -5px rgba(0,0,0,0.4);box-shadow:inset 10px 0px 5px -5px rgba(0,0,0,0.4)}.mCSB_container,.mCSB_dragger{will-change:top, left}.pf-map-type-private{color:#7986cb}.pf-map-type-corporation{color:#5cb85c}.pf-map-type-alliance{color:#428bca}.pf-map-type-global{color:#568a89}#pf-map-module{margin:20px 10px 0 10px}#pf-map-module #pf-map-tabs .pf-map-type-tab-default{border-top:2px solid transparent}#pf-map-module #pf-map-tabs .pf-map-type-tab-private{border-top:2px solid #7986cb}#pf-map-module #pf-map-tabs .pf-map-type-tab-corporation{border-top:2px solid #5cb85c}#pf-map-module #pf-map-tabs .pf-map-type-tab-alliance{border-top:2px solid #428bca}#pf-map-module #pf-map-tabs .pf-map-type-tab-global{border-top:2px solid #568a89}#pf-map-module #pf-map-tabs .pf-map-tab-icon{margin-right:5px}#pf-map-module #pf-map-tabs .pf-map-tab-shared-icon{margin-left:5px}.pf-map-content-row{margin-top:10px;padding-bottom:40px}.pf-map-content-row .pf-module{font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;background:rgba(60,63,65,0.3);padding:10px;width:100%;margin-bottom:10px;will-change:height, transform, opacity;overflow:hidden;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.pf-map-content-row .pf-module:before{content:'';position:absolute;top:0;left:0;border-style:solid;border-width:0 0 6px 6px;border-color:transparent transparent transparent #3c3f41;cursor:pointer}.pf-map-content-row .pf-module .label{margin-bottom:10px}.pf-map-content-row .pf-module .pf-dynamic-area{background:rgba(43,43,43,0.4)}.pf-user-status{color:#a52521}.pf-user-status-corp{color:#5cb85c}.pf-user-status-ally{color:#428bca}.pf-user-status-own{color:#7986cb}.pf-system-effect{display:none;cursor:default;color:#adadad}.pf-system-effect-magnetar{color:#e06fdf;display:inline-block}.pf-system-effect-redgiant{color:#d9534f;display:inline-block}.pf-system-effect-pulsar{color:#428bca;display:inline-block}.pf-system-effect-wolfrayet{color:#e28a0d;display:inline-block}.pf-system-effect-cataclysmic{color:#ffb;display:inline-block}.pf-system-effect-blackhole{color:#000;display:inline-block}.pf-system-info-rally .pf-system-head{background-color:#782d77;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjEuMCIgeTE9IjEuMCIgeDI9IjAuMCIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSIyNSUiIHN0b3AtY29sb3I9IiMzZTI2NGUiLz48c3RvcCBvZmZzZXQ9IjI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iIzNlMjY0ZSIvPjxzdG9wIG9mZnNldD0iNzUlIiBzdG9wLWNvbG9yPSIjM2UyNjRlIi8+PHN0b3Agb2Zmc2V0PSI3NSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');background-size:100%;background-image:-moz-linear-gradient(135deg, #3e264e 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,#3e264e 50%,#3e264e 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0));background-image:-webkit-linear-gradient(135deg, #3e264e 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,#3e264e 50%,#3e264e 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0));background-image:linear-gradient(-45deg, #3e264e 25%,rgba(0,0,0,0) 25%,rgba(0,0,0,0) 50%,#3e264e 50%,#3e264e 75%,rgba(0,0,0,0) 75%,rgba(0,0,0,0));background-size:25px 25px;-webkit-animation:move 3s linear infinite;-moz-animation:move 3s linear infinite;-ms-animation:move 3s linear infinite;animation:move 3s linear infinite}.pf-system-security-0-0{color:#be0000}.pf-system-security-0-1{color:#ab2600}.pf-system-security-0-2{color:#be3900}.pf-system-security-0-3{color:#c24e02}.pf-system-security-0-4{color:#ab5f00}.pf-system-security-0-5{color:#bebe00}.pf-system-security-0-6{color:#73bf26}.pf-system-security-0-7{color:#00bf00}.pf-system-security-0-8{color:#00bf39}.pf-system-security-0-9{color:#39bf99}.pf-system-security-1-0{color:#28c0bf}.pf-system-sec{margin-right:5px;cursor:-moz-grab;cursor:-webkit-grab}.pf-system-sec-highSec{color:#5cb85c}.pf-system-sec-lowSec{color:#e28a0d}.pf-system-sec-nullSec{color:#d9534f}.pf-system-sec-high{color:#d9534f}.pf-system-sec-mid{color:#e28a0d}.pf-system-sec-low{color:#428bca}.pf-system-sec-unknown{color:#7986cb}.pf-system-status-friendly{border-color:#428bca !important;color:#428bca}.pf-system-status-occupied{border-color:#e28a0d !important;color:#e28a0d}.pf-system-status-hostile{border-color:#d9534f !important;color:#d9534f}.pf-system-status-empty{border-color:#5cb85c !important;color:#5cb85c}.pf-system-status-unscanned{border-color:#568a89 !important;color:#568a89}.pf-system-info-status-label{background-color:#63676a;color:#000;will-change:background-color;-webkit-transition:background-color 0.5s ease-out;transition:background-color 0.5s ease-out}.pf-system-info-status-label.pf-system-status-friendly{background-color:#428bca}.pf-system-info-status-label.pf-system-status-occupied{background-color:#e28a0d}.pf-system-info-status-label.pf-system-status-hostile{background-color:#d9534f}.pf-system-info-status-label.pf-system-status-empty{background-color:#5cb85c}.pf-system-info-status-label.pf-system-status-unscanned{background-color:#568a89}.pf-system-effect-dialog-wrapper .table,.pf-jump-info-dialog .table{margin:15px 0}.pf-system-effect-dialog-wrapper .table td,.pf-jump-info-dialog .table td{text-transform:capitalize}.pf-fake-connection{box-sizing:content-box;display:inline-block;width:70px;height:4px;margin-right:5px;border-top:2px solid #63676a;border-bottom:2px solid #63676a;background-color:#3c3f41;position:relative;font-family:"Oxygen","Helvetica Neue",Helvetica,Arial,sans-serif}.pf-fake-connection.pf-map-connection-stargate{background-color:#313966;border-color:#63676a}.pf-fake-connection.pf-map-connection-jumpbridge{background-color:#6caead;border-color:#3c3f41;background:repeating-linear-gradient(to right, #6caead, #6caead 10px, #3c3f41 10px, #3c3f41 20px)}.pf-fake-connection.pf-map-connection-wh-eol{border-color:#d747d6}.pf-fake-connection.pf-map-connection-wh-reduced{background-color:#e28a0d}.pf-fake-connection.pf-map-connection-wh-critical{background-color:#a52521}.pf-fake-connection.pf-map-connection-frig{border-style:dashed;border-left:none;border-right:none}.pf-fake-connection.pf-map-connection-frig:after{content:'frig';background-color:#e28a0d;color:#1d1d1d;padding:0px 3px;position:absolute;left:25px;top:-6px;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.pf-fake-connection.pf-map-connection-preserve-mass:after{content:'save mass';background-color:#a52521;color:#eaeaea;padding:0px 3px;position:absolute;left:9px;top:-6px;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.tooltip-inner{color:#5cb85c;background-color:#3c3f41;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;padding:5px 5px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.4);box-shadow:0 6px 12px rgba(0,0,0,0.4)}.modal .tooltip{z-index:1060}.modal .tooltip .tooltip-inner{color:#313335;background-color:#adadad}.tooltip.top .tooltip-arrow{border-top-color:#63676a}.tooltip.right .tooltip-arrow{border-right-color:#63676a}.tooltip.bottom .tooltip-arrow{border-bottom-color:#63676a}.tooltip.left .tooltip-arrow{border-left-color:#63676a}.popover{z-index:1060}.popover img{-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.popover h4{color:#adadad}.popover table{color:#adadad;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;line-height:16px;font-size:11px}.popover table td{padding:0 5px}.pf-dynamic-area{padding:10px;min-height:100px;position:relative;background-color:#313335;overflow:hidden;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.pf-dynamic-area .dl-horizontal{margin-bottom:0}.pf-dynamic-area .dl-horizontal dd{min-width:100px}#pf-logo-wrapper{display:block}#pf-head{margin-bottom:0px}#pf-head a{-webkit-transition:color 0.15s ease-out;transition:color 0.15s ease-out;will-change:color}#pf-head a:focus{color:#477372}#pf-head a:focus img{border-color:#3c3f41}#pf-head a:hover{text-decoration:none}#pf-head a:hover .badge{color:#6caead}#pf-head a:hover img{border-color:#568a89}#pf-head i{margin-right:2px}#pf-head .pf-brand-desc{margin:6px 10px 0 90px;width:180px}#pf-head .pf-head-menu{padding:3px 10px;line-height:24px}#pf-head .pf-head-menu .pf-head-menu-logo{width:24px;height:24px;display:inline-block;float:left}#pf-head .badge{background-color:#3c3f41;color:#adadad}#pf-head .pf-head-user-character,#pf-head .pf-head-user-ship{opacity:0;visibility:hidden}#pf-head .pf-head-active-user,#pf-head .pf-head-current-location{display:none}#pf-head .pf-head-active-user .badge,#pf-head .pf-head-current-location .badge{-webkit-transition:color 0.3s ease-out;transition:color 0.3s ease-out}#pf-head .pf-head-user-character-image,#pf-head .pf-head-user-ship-image{display:inline-block;margin-top:-6px;margin-bottom:-6px;width:27px;border:1px solid #3c3f41;margin-right:3px;-webkit-transition:border-color 0.15s ease-out;transition:border-color 0.15s ease-out;will-change:border-color}#pf-head .pf-head-program-status{cursor:pointer}#pf-head .navbar-text{min-width:60px}#pf-head .tooltip .tooltip-inner{color:#adadad}.pf-head{-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.4);box-shadow:0 6px 12px rgba(0,0,0,0.4)}#pf-footer{position:absolute;bottom:0;left:0;width:100%;margin:0;background:rgba(60,63,65,0.3)}#pf-footer a{font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;color:#375959}#pf-footer a:hover{color:#477372;text-decoration:none}@-webkit-keyframes move{0%{background-position:0 0}100%{background-position:50px 50px}}@-moz-keyframes move{0%{background-position:0 0}100%{background-position:50px 50px}}@-ms-keyframes move{0%{background-position:0 0}100%{background-position:50px 50px}}@keyframes move{0%{background-position:0 0}100%{background-position:50px 50px}}.pf-animate{visibility:hidden;opacity:0}.pf-color-line{position:fixed;top:0;left:0;width:100%;height:3px;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzY2Yzg0ZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzY2Yzg0ZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');background-size:100%;background-image:-webkit-gradient(linear, 0% 50%, 100% 50%, color-stop(0%, #66c84f),color-stop(100%, #66c84f));background-image:-moz-linear-gradient(left, #66c84f,#66c84f 100%);background-image:-webkit-linear-gradient(left, #66c84f,#66c84f 100%);background-image:linear-gradient(to right, #66c84f,#66c84f 100%)}.pf-color-line.warning{background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2UyOGEwZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2UyOGEwZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');background-size:100%;background-image:-webkit-gradient(linear, 0% 50%, 100% 50%, color-stop(0%, #e28a0d),color-stop(100%, #e28a0d));background-image:-moz-linear-gradient(left, #e28a0d,#e28a0d 100%);background-image:-webkit-linear-gradient(left, #e28a0d,#e28a0d 100%);background-image:linear-gradient(to right, #e28a0d,#e28a0d 100%)}.pf-color-line.danger{background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2E1MjUyMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2E1MjUyMSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');background-size:100%;background-image:-webkit-gradient(linear, 0% 50%, 100% 50%, color-stop(0%, #a52521),color-stop(100%, #a52521));background-image:-moz-linear-gradient(left, #a52521,#a52521 100%);background-image:-webkit-linear-gradient(left, #a52521,#a52521 100%);background-image:linear-gradient(to right, #a52521,#a52521 100%)}.pf-splash{position:absolute;z-index:2000;background-color:#1d1d1d;color:#63676a;top:0;bottom:0;left:0;right:0;will-change:opacity}.pf-splash .pf-splash-title{position:fixed;left:50%;top:30%;text-align:center;max-width:500px;padding:20px;-moz-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%)}@media (max-width: 1200px){.pf-landing #pf-logo-container{margin:5px auto}.pf-landing .pf-brand-desc{display:none}.pf-landing .navbar .navbar-brand{margin-left:10px}}.pf-landing section{min-height:200px;padding:20px 0 40px 0;border-bottom:1px solid #2b2b2b}.pf-landing section h4{font-size:18px;font-family:"Oxygen","Helvetica Neue",Helvetica,Arial,sans-serif;margin:5px 0 10px 0;border-bottom:1px solid #2b2b2b;line-height:34px}.pf-landing .container>.row{margin-bottom:30px}.pf-landing .alert{box-shadow:0 4px 10px rgba(0,0,0,0.4)}.pf-landing a[data-gallery]{position:relative}.pf-landing a[data-gallery]:before{content:'\f002';font-family:'FontAwesome';font-size:20px;line-height:20px;color:#e28a0d;position:absolute;top:9px;left:8px;height:100%;width:100%;padding-top:calc(50% - 10px);z-index:10;text-align:center;-webkit-transition:transform 0.1s 0.06s ease-in,opacity 0.1s ease-out;transition:transform 0.1s 0.06s ease-in,opacity 0.1s ease-out;will-change:transform, opacity;transform:scale(0, 0);opacity:0}.pf-landing a[data-gallery]:hover img{border-color:#6caead;-webkit-filter:brightness(50%);filter:brightness(50%)}.pf-landing a[data-gallery]:hover:before{-webkit-transition-delay:0.1s;transition-delay:0.1s;transform:scale(1, 1);opacity:1}.pf-landing a[data-gallery] .pf-landing-image-preview{border-width:1px;border-style:solid;border-color:#1d1d1d;margin:5px 0 15px 0;display:inline-block;will-change:all;-webkit-filter:brightness(100%);filter:brightness(100%);-webkit-transition:all 0.2s ease-out;transition:all 0.2s ease-out;-webkit-box-shadow:0 4px 10px rgba(0,0,0,0.4);box-shadow:0 4px 10px rgba(0,0,0,0.4)}.pf-landing a[data-gallery] .pf-landing-image-preview.pf-landing-image-preview-small{height:160px}.pf-landing a[data-gallery] .pf-landing-image-preview.pf-landing-image-preview-medium{height:256px}#pf-landing-top{height:450px;border-bottom:1px solid #313335;position:relative}#pf-landing-top:before{content:'';width:100%;height:100%;position:absolute;background:url("../img/pf-bg.jpg") #05050a;background-repeat:no-repeat;background-position:0 0;-webkit-filter:brightness(0.9);filter:brightness(0.9)}#pf-landing-top.pf-logo-fallback{height:370px}#pf-landing-top.pf-logo-fallback:after{content:'';width:100%;height:100%;position:absolute;background:url("../img/logo_alpha.png");background-repeat:no-repeat;background-position:50% 0;margin-top:50px}#pf-landing-top #pf-header-container{position:absolute;width:100%;background-position:center center}#pf-landing-top #pf-header-container #pf-header-canvas{position:absolute;visibility:hidden;top:0;left:0}#pf-landing-top #pf-header-container #pf-logo-container{z-index:110}#pf-landing-top #pf-header-container #pf-header-preview-container{position:absolute;left:400px;width:590px;height:350px;top:92px}#pf-landing-top #pf-header-container #pf-header-preview-container .pf-header-preview-element{position:relative;margin-left:12px;margin-top:12px;height:155px;width:180px;padding:7px;opacity:0;will-change:opacity, transform;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;background-color:rgba(43,43,43,0.5)}#pf-landing-top #pf-header-container #pf-header-preview-container .pf-header-preview-element:nth-child(n+4){box-shadow:0 4px 10px rgba(0,0,0,0.4)}#pf-landing-top #pf-header-container #pf-header-preview-container .pf-header-preview-element:after{content:'';position:absolute;width:calc(100% - 14px);height:calc(100% - 14px);-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-repeat:no-repeat;background-position:50% 50%;background-color:rgba(29,29,29,0.75)}#pf-landing-top .container{position:relative;margin-top:50px}#pf-header-preview-intel:after{background-image:url("../img/landing/intel.png")}#pf-header-preview-map:after{background-image:url("../img/landing/map.png")}#pf-header-preview-scope:after{background-image:url("../img/landing/scope.png")}#pf-header-preview-signature:after{background-image:url("../img/landing/signature.png")}#pf-header-preview-data:after{background-image:url("../img/landing/data.png")}#pf-header-preview-gameplay:after{background-image:url("../img/landing/gameplay.png")}#pf-landing-login{padding-top:40px;padding-bottom:30px}#pf-landing-login .row{margin-bottom:0}#pf-landing-login .pf-sso-login-button{position:relative;display:inline-block;width:270px;height:45px;border:none;margin-bottom:10px;background-color:transparent;background-image:url("../img/landing/eve_sso_login_buttons_large_black_hover.png");cursor:pointer;box-shadow:0 2px 5px rgba(0,0,0,0.2);-webkit-transition:box-shadow 0.12s ease-out;transition:box-shadow 0.12s ease-out;will-change:box-shadow}#pf-landing-login .pf-sso-login-button:after{content:' ';position:absolute;width:270px;height:45px;left:0;top:0;background-image:url("../img/landing/eve_sso_login_buttons_large_black.png");-webkit-transition:opacity 0.12s ease-in-out;transition:opacity 0.12s ease-in-out;will-change:opacity}#pf-landing-login .pf-sso-login-button:hover{box-shadow:0 4px 5px rgba(0,0,0,0.2)}#pf-landing-login .pf-sso-login-button:hover:after{opacity:0}#pf-header-map{position:relative;margin:0 auto;height:380px;width:600px;pointer-events:none}#pf-header-map .pf-header-svg-layer{position:absolute;top:0;left:0;right:0;bottom:0}#pf-header-map #pf-header-systems{z-index:100}#pf-header-map #pf-header-connectors{z-index:90}#pf-header-map #pf-header-connections{z-index:80}#pf-header-map #pf-header-background{z-index:70}#pf-header-map #pf-header-background .pf-header-system{display:none}#pf-header-map-bg{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none}#pf-header-map-bg img{pointer-events:none}#pf-header-map-bg #pf-map-bg-image{opacity:0;position:absolute;bottom:0;right:0;width:100%;height:100%}#pf-header-map-bg #pf-map-neocom{opacity:0;height:665px;width:21px}#pf-header-map-bg #pf-map-browser{opacity:0;position:absolute;top:110px;left:21px;height:560px;width:515px}#pf-landing-gallery-carousel{background-image:url("../img/pf-header-bg.jpg")}#pf-landing-gallery-carousel .slide-content{border-radius:5px}#pf-landing-gallery-carousel h3{width:100%;text-align:left}.pf-landing-pricing-panel{margin-top:20px}.pricing-big{-webkit-box-shadow:0 4px 10px rgba(0,0,0,0.4);box-shadow:0 4px 10px rgba(0,0,0,0.4)}.pricing-big .panel-heading{border-color:#3c3f41}.pricing-big .the-price{padding:1px 0;background:#2d3031;text-align:center}.pricing-big .the-price .subscript{font-size:12px;color:#63676a}.pricing-big .price-features{background:#3c3f41;color:#adadad;padding:20px 15px;min-height:205px;line-height:22px}.pricing-big table tr td{line-height:1}#pf-landing-about .pf-landing-about-me{width:256px;height:256px;border:none;-webkit-box-shadow:0 4px 10px rgba(0,0,0,0.4);box-shadow:0 4px 10px rgba(0,0,0,0.4)}.pf-landing-footer{padding:30px 0;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;background-color:#171717}.pf-landing-footer .pf-social-networks>li{display:inline-block;line-height:1}.pf-landing-footer .pf-social-networks>li a{display:inline-block;background:rgba(99,103,106,0.5);line-height:24px;text-align:center;font-size:12px;margin-right:5px;width:28px;height:24px}#pf-static-logo-svg{opacity:0;position:absolute;z-index:105;overflow:visible}#pf-static-logo-svg path{will-change:fill, opacity, transform, translateZ, translateX, translateY;pointer-events:all;-moz-transform:translate3d(0, 0, 0);-ms-transform:translate3d(0, 0, 0);-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}.logo-ploygon-top-right{fill:#477372;fill-rule:evenodd;stroke:#477372;stroke-width:0px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1}.logo-ploygon-bottom-left{fill:#5cb85c;fill-rule:evenodd;stroke:#5cb85c;stroke-width:0px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1}.logo-ploygon-bottom-right{fill:#375959;fill-rule:evenodd;stroke:#375959;stroke-width:0px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1}.logo-ploygon-top-left{fill:#63676a;fill-opacity:1;fill-rule:evenodd;stroke:#63676a;stroke-width:0px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1}@-webkit-keyframes bounce{0%, 20%, 50%, 80%, 100%{-webkit-transform:translateY(0)}40%{-webkit-transform:translateY(-8px)}60%{-webkit-transform:translateY(-4px)}}@keyframes bounce{0%, 20%, 50%, 80%, 100%{transform:translateY(0)}40%{transform:translateY(-8px)}60%{transform:translateY(-4px)}}#pf-map-tab-element{max-width:2515px;margin:0 auto}.pf-map-tab-content .pf-map-wrapper{position:relative;width:100%;max-width:2515px;height:550px;overflow:auto;padding:5px;background:rgba(43,43,43,0.93);box-shadow:inset -3px 3px 10px 0 rgba(0,0,0,0.3);border-bottom-right-radius:5px;border-bottom-left-radius:5px;border-width:1px;border-style:solid;border-color:#313335}.pf-map-overlay{position:absolute;display:none;z-index:10000;height:36px;right:10px;background:rgba(0,0,0,0.25);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.pf-map-overlay.pf-map-overlay-timer{width:36px;bottom:23px}.pf-map-overlay.pf-map-overlay-info{top:8px;color:#2b2b2b;padding:3px;line-height:26px;min-height:36px;min-width:36px}.pf-map-overlay.pf-map-overlay-info i{display:none;margin:2px;width:26px;height:26px;opacity:0.8;color:#c2760c}.pf-map-overlay.pf-map-overlay-info i.fa,.pf-map-overlay.pf-map-overlay-info .pf-landing .pf-landing-list li i,.pf-landing .pf-landing-list li .pf-map-overlay.pf-map-overlay-info i{font-size:26px}.pf-map-overlay.pf-map-overlay-info i.glyphicon{margin-left:4px;font-size:25px}.pf-grid-small{background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAG1JREFUeNrs18EJgDAQRNGJpoQQSC+CWMSWEwhYrCAWYRNz2MP/BQzvOiUi5Op5vzl6u+VrbUoeQIAAAQIECBAgQICpK8d5zay40dtenR+CTwIQIECAAAECBAgQYLaqpGX8EHLuSdIPAAD//wMAuMQN2uF+ypQAAAAASUVORK5CYII=') !important}.pf-map{width:2500px;height:520px;position:relative;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif}.pf-map .jsplumb-overlay{opacity:1;pointer-events:none;will-change:opacity;-webkit-transition:opacity 0.18s ease-out;transition:opacity 0.18s ease-out}.pf-map .jsplumb-hover.jsplumb-overlay{opacity:0 !important}.pf-map .jsplumb-hover:not(.jsplumb-overlay){-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-delay:0.5s;animation-delay:0.5s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-timing-function:linear;animation-timing-function:linear;animation-iteration-count:infinite;-webkit-animation-iteration-count:infinite;-webkit-animation-name:bounce;animation-name:bounce}.pf-map .jsplumb-target-hover,.pf-map .jsplumb-source-hover{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-delay:0.5s;animation-delay:0.5s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-timing-function:linear;animation-timing-function:linear;animation-iteration-count:infinite;-webkit-animation-iteration-count:infinite;-webkit-animation-name:bounce;animation-name:bounce;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.3);box-shadow:0 6px 12px rgba(0,0,0,0.3)}.pf-map .pf-system{position:absolute;min-width:60px;height:auto;overflow:hidden;background-color:#313335;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;z-index:100;will-change:top, left, opacity, transform;border-width:2px;border-style:solid;border-color:#63676a;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-webkit-transition:border-color 0.5s ease-out,box-shadow 0.2s ease-out;transition:border-color 0.5s ease-out,box-shadow 0.2s ease-out;-moz-transform:translate3d(0, 0, 0);-ms-transform:translate3d(0, 0, 0);-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}.pf-map .pf-system:hover{-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.3);box-shadow:0 6px 12px rgba(0,0,0,0.3);-moz-transform:translate3d(0, -2px, 0);-ms-transform:translate3d(0, -2px, 0);-webkit-transform:translate3d(0, -2px, 0);transform:translate3d(0, -2px, 0)}.pf-map .pf-system .pf-system-head{padding:0px 3px 0px 3px;cursor:pointer;font-family:Arial;font-weight:bold}.pf-map .pf-system .pf-system-head .pf-system-head-name{border:none;display:inline-block;min-width:41px;color:#adadad;margin-right:2px}.pf-map .pf-system .pf-system-head .fa-lock{display:none}.pf-map .pf-system .pf-system-head .pf-system-head-expand{margin-left:2px;color:#63676a;display:none}.pf-map .pf-system .pf-system-head .editable-empty{font-style:normal}.pf-map .pf-system .pf-system-body{height:0px;width:100%;overflow:hidden;cursor:-moz-grab;cursor:-webkit-grab;cursor:grab;padding:0 4px;white-space:nowrap;display:none;will-change:width;border-top-width:1px;border-top-style:dashed;border-top-color:#63676a}.pf-map .pf-system .pf-system-body .pf-system-body-item{color:#63676a;font-size:10px}.pf-map .pf-system .pf-system-body .pf-system-body-item .pf-system-body-right{text-overflow:ellipsis;float:right;color:#f0ad4e;display:none}.pf-map .pf-system .pf-system-body .pf-system-body-item .pf-user-status{font-size:7px;width:10px}.pf-map .pf-system .pf-system-body .pf-system-body-item .pf-system-body-item-name{display:inline-block;width:65px;overflow:hidden;height:11px;white-space:nowrap;text-overflow:ellipsis}.pf-map .pf-system .tooltip.in{opacity:1}.pf-map .pf-system .tooltip .tooltip-inner{color:#313335;background-color:#adadad;padding:3px 3px}.pf-map .pf-system-active:not(.pf-map-endpoint-source):not(.pf-map-endpoint-target){-webkit-box-shadow:#ffb 0px 0px 8px 0px;box-shadow:#ffb 0px 0px 8px 0px}.pf-map .pf-system-selected:not(.pf-map-endpoint-source):not(.pf-map-endpoint-target),.pf-map .jsPlumb_dragged:not(.pf-map-endpoint-source):not(.pf-map-endpoint-target){-webkit-box-shadow:#58100d 0px 0px 8px 0px;box-shadow:#58100d 0px 0px 8px 0px}.pf-map .pf-system-selected:not(.pf-map-endpoint-source):not(.pf-map-endpoint-target) .pf-system-head,.pf-map .jsPlumb_dragged:not(.pf-map-endpoint-source):not(.pf-map-endpoint-target) .pf-system-head,.pf-map .pf-system-selected:not(.pf-map-endpoint-source):not(.pf-map-endpoint-target) .pf-system-body,.pf-map .jsPlumb_dragged:not(.pf-map-endpoint-source):not(.pf-map-endpoint-target) .pf-system-body{background-color:#58100d}.pf-map .pf-system-locked .pf-system-sec{cursor:default !important}.pf-map .pf-system-locked .pf-system-body{cursor:default !important}.pf-map .pf-system-locked .fa-lock{color:#63676a !important;display:inline-block !important}.pf-map .pf-map-endpoint-source,.pf-map .pf-map-endpoint-target{z-index:90}.pf-map .pf-map-endpoint-source svg,.pf-map .pf-map-endpoint-target svg{overflow:visible}.pf-map .pf-map-endpoint-source svg circle,.pf-map .pf-map-endpoint-target svg circle{-webkit-transition:stroke 0.18s ease-out,fill 0.18s ease-out;transition:stroke 0.18s ease-out,fill 0.18s ease-out}.pf-map .pf-map-endpoint-source svg *,.pf-map .pf-map-endpoint-target svg *{stroke:#63676a;stroke-width:2;fill:#3c3f41;cursor:pointer}.pf-map .pf-map-endpoint-source:hover circle,.pf-map .pf-map-endpoint-target:hover circle{stroke:#e28a0d !important}.pf-map .pf-map-endpoint-source.jsplumb-hover,.pf-map .pf-map-endpoint-target.jsplumb-hover{z-index:95}.pf-map .pf-map-endpoint-source.jsplumb-dragging circle,.pf-map .pf-map-endpoint-target.jsplumb-dragging circle{stroke:#e28a0d}.pf-map .jsplumb-endpoint-drop-allowed circle{stroke:#5cb85c !important;fill:#5cb85c !important}.pf-map .jsplumb-endpoint-drop-forbidden circle{stroke:#a52521 !important;fill:#a52521 !important}.pf-map svg.jsplumb-connector{cursor:pointer;stroke-linecap:round;-webkit-transition:stroke 0.18s ease-out;transition:stroke 0.18s ease-out;will-change:all}.pf-map svg.jsplumb-connector path{-webkit-transition:stroke 0.18s ease-out;transition:stroke 0.18s ease-out}.pf-map svg.jsplumb-connector path:not(:first-child){stroke:#3c3f41}.pf-map svg.jsplumb-connector path:first-child{stroke:#63676a}.pf-map svg.jsplumb-connector.jsplumb-hover{z-index:80}.pf-map svg.jsplumb-connector.jsplumb-hover path:first-child{stroke:#eaeaea}.pf-map svg.jsplumb-connector.jsplumb-dragging{-webkit-transition:opacity 0.18s ease-out;transition:opacity 0.18s ease-out;opacity:0.4;z-index:80}.pf-map svg.pf-map-connection-jumpbridge{z-index:50}.pf-map svg.pf-map-connection-jumpbridge path:first-child{stroke:rgba(255,255,255,0)}.pf-map svg.pf-map-connection-jumpbridge path:not(:first-child){stroke:#568a89}.pf-map svg.pf-map-connection-jumpbridge:hover path:first-child{stroke:rgba(255,255,255,0)}.pf-map svg.pf-map-connection-jumpbridge:hover path:not(:first-child){stroke:#eaeaea}.pf-map svg.pf-map-connection-stargate{z-index:60}.pf-map svg.pf-map-connection-stargate path:first-child{stroke:#63676a}.pf-map svg.pf-map-connection-stargate path:not(:first-child){stroke:#313966}.pf-map svg.pf-map-connection-stargate:hover path:first-child{stroke:#eaeaea}.pf-map svg.pf-map-connection-wh-fresh,.pf-map svg.pf-map-connection-wh-reduced,.pf-map svg.pf-map-connection-wh-critical,.pf-map svg.pf-map-connection-wh-eol{z-index:70}.pf-map svg.pf-map-connection-wh-eol path:first-child{stroke:#d747d6}.pf-map svg.pf-map-connection-wh-eol:hover path:first-child{stroke:#eaeaea}.pf-map svg.pf-map-connection-wh-reduced path:not(:first-child){stroke:#e28a0d}.pf-map svg.pf-map-connection-wh-critical path:not(:first-child){stroke:#a52521}.pf-map .pf-map-connection-overlay{padding:1px 4px;font-size:11px;z-index:1020;-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.4);box-shadow:0 6px 12px rgba(0,0,0,0.4)}.pf-map .frig{background-color:#f0ad4e;color:#1d1d1d}.pf-map .mass{background-color:#a52521;color:#eaeaea}.ui-dialog-content label{min-width:60px}.dropdown-menu{font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;z-index:1020;will-change:opacity, top, left, transform}.dropdown-menu i{width:20px}.pf-system-tooltip-inner{color:#adadad;padding:2px 4px;min-width:25px;-webkit-transition:color 0.2s ease-out;transition:color 0.2s ease-out}.pf-system-info-popover{display:initial}.pf-system-info-popover img{width:39px}.pf-system-info-popover h6{white-space:nowrap;margin-right:50px}.pf-system-info-popover h6:before,.pf-system-info-popover h6:after{content:" ";display:table}.pf-system-info-popover h6:after{clear:both}.pf-system-info-popover .well{margin-top:7px;margin-bottom:10px}.pf-system-info-module h5{text-transform:capitalize}.pf-system-info-module .pf-system-info-description-area{min-height:123px}.pf-system-info-module .pf-system-info-description-area .pf-system-info-description{width:330px}.pf-system-info-module .pf-system-info-table{font-size:11px;white-space:nowrap}.pf-sig-table-module .pf-sig-table-clear-button{will-change:opacity, transform;display:none}.pf-sig-table-module .pf-sig-table{font-size:10px}.pf-sig-table-module .pf-sig-table .pf-sig-table-edit-desc-text{white-space:normal}.pf-sig-table-module .pf-sig-table .pf-sig-table-edit-desc-text.editable-empty{border-bottom:none}.pf-sig-table-module .pf-sig-table .pf-editable-description{background-color:#2b2b2b;max-height:50px}.pf-sig-table-module .pf-sig-table .pf-sig-table-edit-name-input{text-transform:uppercase}.pf-system-graph-module .pf-system-graph{width:100%;height:100px}.pf-system-route-module .pf-system-route-table{width:100%;font-size:11px}.pf-system-route-module .pf-system-route-table td{text-transform:capitalize}.pf-system-route-module .pf-system-route-table td>.fa,.pf-system-route-module .pf-system-route-table .pf-landing .pf-landing-list li td>i,.pf-landing .pf-landing-list li .pf-system-route-module .pf-system-route-table td>i{font-size:10px}.pf-system-killboard-module .pf-system-killboard-graph-kills{width:100%;height:100px;position:relative;margin-bottom:30px}.pf-system-killboard-module .pf-system-killboard-list{padding-bottom:10px;border-bottom:1px solid #2b2b2b}.pf-system-killboard-module .pf-system-killboard-list li{margin-left:0;overflow:visible;min-height:50px;will-change:margin-left;-webkit-transition:margin-left 0.12s cubic-bezier(0.3, 0.8, 0.8, 1.7);transition:margin-left 0.12s cubic-bezier(0.3, 0.8, 0.8, 1.7)}.pf-system-killboard-module .pf-system-killboard-list li h5{white-space:nowrap}.pf-system-killboard-module .pf-system-killboard-list li h3{width:120px;display:inline-block}.pf-system-killboard-module .pf-system-killboard-list li .pf-system-killboard-img-corp{margin-right:10px;width:16px}.pf-system-killboard-module .pf-system-killboard-list li .pf-system-killboard-img-ship{width:50px;margin-right:10px;border:1px solid #2b2b2b;transform:translateZ(1px);will-change:border-color;-moz-border-radius:25px;-webkit-border-radius:25px;border-radius:25px;-webkit-transition:border-color 0.12s ease-out;transition:border-color 0.12s ease-out}.pf-system-killboard-module .pf-system-killboard-list li:before{content:"\f054";font-family:FontAwesome;position:absolute;z-index:10;left:-25px;top:15px;color:#477372;opacity:0;will-change:opacity, left;-webkit-transition:all 0.12s ease-out;transition:all 0.12s ease-out}.pf-system-killboard-module .pf-system-killboard-list li:hover{margin-left:20px}.pf-system-killboard-module .pf-system-killboard-list li:hover .pf-system-killboard-img-ship{border-color:#568a89}.pf-system-killboard-module .pf-system-killboard-list li:hover:before{opacity:1;left:-20px}input,select{background-color:#313335;color:#adadad;border:1px solid #63676a;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif}input:focus,select:focus{border-color:#568a89}input:-webkit-autofill,select:-webkit-autofill{background-color:#313335 !important;-webkit-box-shadow:0 0 0 50px #313335 inset !important;box-shadow:0 0 0 50px #313335 inset !important;-webkit-text-fill-color:#adadad}input:-webkit-autofill:focus,select:-webkit-autofill:focus{-webkit-box-shadow:0 0 0 50px #313335 inset !important;box-shadow:0 0 0 50px #313335 inset !important;-webkit-text-fill-color:#adadad}input::-webkit-file-upload-button,select::-webkit-file-upload-button{background-color:transparent;border:none;color:#63676a;outline:none}.pf-form-dropzone{border:2px dashed #2b2b2b;height:100px;background-color:#353739;text-align:center;font-size:20px;line-height:100px;margin:15px 0;color:#2b2b2b;-moz-border-radius:10px;-webkit-border-radius:10px;border-radius:10px;-webkit-transition:color 0.18s ease-out,border-color 0.18s ease-out;transition:color 0.18s ease-out,border-color 0.18s ease-out}.pf-form-dropzone:hover{color:#568a89;border-color:#568a89;cursor:-moz-grabbing;cursor:-webkit-grabbing;cursor:grabbing}.toggle.btn:active,button.toggle.DTTT_button:active,div.toggle.DTTT_button:active,a.toggle.DTTT_button:active{box-shadow:none}.toggle .toggle-group .btn,.toggle .toggle-group button.DTTT_button,.toggle .toggle-group div.DTTT_button,.toggle .toggle-group a.DTTT_button{padding:0px 5px}.pf-icon{display:inline-block}.pf-icon.disabled{opacity:0.5;color:#63676a}.pf-icon-dotlan{background:url('data:image/png;base64,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');width:17px;height:17px;opacity:0.8;margin:-5px 0px 0 10px}.pf-icon-wormhol-es{background:url('data:image/png;base64,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');width:17px;height:17px;opacity:0.8;margin:-5px 0px 0 10px}.modal-content h2{font-family:"Oxygen","Helvetica Neue",Helvetica,Arial,sans-serif;letter-spacing:0px;font-size:14px;margin:20px 0;line-height:normal}.modal-content .dataTable,.modal-content .table{font-size:10px;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif}.modal-content hr{margin:5px 0 15px 0;border-color:#63676a}.modal-content .pf-wizard-navigation{margin:0}.modal-content .pf-wizard-navigation li:not(:last-child):before{border-top:1px solid #63676a;content:"";display:block;font-size:0;overflow:hidden;position:relative;top:12px;left:71px;right:1px;width:100%}.modal-content .pf-wizard-navigation li.finished:before{-moz-border-image:-moz-linear-gradient(left, #375959,#375959) 1 1%;-moz-border-image:linear-gradient(to right, #375959,#375959) 1 1%;-o-border-image:linear-gradient(to right, #375959,#375959) 1 1%;-webkit-border-image:-webkit-linear-gradient(left, #375959,#375959) 1 1%;-webkit-border-image:linear-gradient(to right, #375959,#375959) 1 1%;border-image:-moz-linear-gradient(left, #375959,#375959) 1 1%;border-image:-webkit-linear-gradient(left, #375959,#375959) 1 1%;border-image:linear-gradient(to right, #375959,#375959) 1 1%;border-bottom:0}.modal-content .pf-wizard-navigation li.active:before{-moz-border-image:-moz-linear-gradient(left, #4f9e4f,#63676a) 1 1%;-moz-border-image:linear-gradient(to right, #4f9e4f,#63676a) 1 1%;-o-border-image:linear-gradient(to right, #4f9e4f,#63676a) 1 1%;-webkit-border-image:-webkit-linear-gradient(left, #4f9e4f,#63676a) 1 1%;-webkit-border-image:linear-gradient(to right, #4f9e4f,#63676a) 1 1%;border-image:-moz-linear-gradient(left, #4f9e4f,#63676a) 1 1%;border-image:-webkit-linear-gradient(left, #4f9e4f,#63676a) 1 1%;border-image:linear-gradient(to right, #4f9e4f,#63676a) 1 1%;border-bottom:0}.modal-content .pf-wizard-navigation li>h6{color:#63676a;font-size:11px;margin:5px}.modal-content .pf-wizard-navigation li a:hover+h6{color:#adadad}.modal-content .pf-wizard-navigation li.active a:not(.btn-danger)+h6{color:#adadad}.modal-content .pf-dialog-finish-button,.modal-content .pf-dialog-prev-button{display:none}#pf-settings-dialog .form-group .btn-sm,#pf-settings-dialog .form-group .btn-group-sm>.btn,#pf-settings-dialog .form-group button.DTTT_button,#pf-settings-dialog .form-group div.DTTT_button,#pf-settings-dialog .form-group a.DTTT_button{padding:4px 7px 3px}#pf-settings-dialog .pf-dialog-api-row:not(:nth-last-child(3)) .pf-dialog-clone-button{display:none}#pf-settings-dialog .pf-dialog-api-row:nth-child(2):nth-last-child(3) .pf-dialog-delete-button{display:none}#pf-settings-dialog #pf-dialog-captcha-wrapper{margin:0;padding:3px 0}#pf-settings-dialog .pf-dynamic-area{display:inline-block;margin:10px 5px 20px 5px;padding:10px 10px 5px 10px;-moz-border-radius:10px;-webkit-border-radius:10px;border-radius:10px}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper{opacity:0;width:128px;border:2px solid #63676a;-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px;-webkit-transition:border-color 0.2s ease-out,box-shadow 0.2s ease-out;transition:border-color 0.2s ease-out,box-shadow 0.2s ease-out;-moz-transform:translate3d(0, 0, 0);-ms-transform:translate3d(0, 0, 0);-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);will-change:border-color, transition;overflow:hidden;cursor:pointer;display:inline-block;background-color:#2b2b2b;box-sizing:content-box}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper:before{content:"\f005";font-family:FontAwesome;position:absolute;z-index:10;left:6px;top:4px;color:#adadad;-webkit-transition:color 0.2s ease-out;transition:color 0.2s ease-out}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper.pf-dialog-character-main{border-color:#c2760c}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper.pf-dialog-character-main:hover{border-color:#e28a0d}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper.pf-dialog-character-main:before{color:#e28a0d}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper:hover{border-color:#375959;-webkit-box-shadow:0 4px 10px rgba(0,0,0,0.4);box-shadow:0 4px 10px rgba(0,0,0,0.4)}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper:hover .pf-dialog-character-name{color:#568a89}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper:hover .pf-dialog-character-image{-webkit-filter:grayscale(50%);filter:grayscale(50%)}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper:hover:before{color:#e28a0d}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper .pf-dialog-image{overflow:hidden;width:128px;height:128px;position:relative}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper .pf-dialog-image .pf-dialog-character-info{position:absolute;top:0;left:0;width:0;height:100%;background:rgba(60,63,65,0.8);overflow:hidden;will-change:width, transition;padding:10px 0}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper .pf-dialog-image .pf-dialog-character-info .pf-dialog-character-info-text{line-height:25px}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper .pf-dialog-character-name{font-size:13px;line-height:30px;border-top:1px solid #313335;-webkit-transition:color 0.2s ease-out;transition:color 0.2s ease-out}#pf-settings-dialog .pf-dynamic-area .pf-dialog-image-wrapper .pf-dialog-character-image{-webkit-transition:all 0.3s ease-out;transition:all 0.3s ease-out;-webkit-filter:grayscale(0%);filter:grayscale(0%)}#pf-map-dialog #pf-map-dialog-user-select,#pf-map-dialog #pf-map-dialog-corporation-select,#pf-map-dialog #pf-map-dialog-alliance-select{width:300px}#pf-manual-scrollspy{position:relative;height:500px;overflow:auto}.pf-system-dialog-select{width:270px !important}h2.pf-dynamic-area,h4.pf-dynamic-area{min-height:0}.pf-credits-dialog .pf-credits-logo-background{overflow:visible;background:url("../img/logo_bg.png");padding:20px;margin-bottom:20px}.pf-credits-dialog #pf-logo-container{width:355px;height:366px;margin:0 auto}.pf-log-graph{height:100px;width:100%}.pf-animation-slide-in{-moz-animation-duration:1.2s;-webkit-animation-duration:1.2s;-moz-animation-name:pfSlideIn;-webkit-animation-name:pfSlideIn;position:relative}@-webkit-keyframes pfSlideIn{from{opacity:0;top:-20px}to{opacity:1;top:0px}}@-moz-keyframes pfSlideIn{from{opacity:0;top:-20px}to{opacity:1;top:0px}}@-ms-keyframes pfSlideIn{from{opacity:0;top:-20px}to{opacity:1;top:0px}}@keyframes pfSlideIn{from{opacity:0;top:-20px}to{opacity:1;top:0px}}.pf-animation-pulse-success{-webkit-animation:pulseBackgroundSuccess 3s 1;animation:pulseBackgroundSuccess 3s 1;-webkit-animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38);animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38)}.pf-animation-pulse-success .sorting_1{-webkit-animation:pulseBackgroundSuccessActive 3s 1;animation:pulseBackgroundSuccessActive 3s 1;-webkit-animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38);animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38)}.pf-animation-pulse-warning{-webkit-animation:pulseBackgroundWarning 3s 1;animation:pulseBackgroundWarning 3s 1;-webkit-animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38);animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38)}.pf-animation-pulse-warning .sorting_1{-webkit-animation:pulseBackgroundWarningActive 3s 1;animation:pulseBackgroundWarningActive 3s 1;-webkit-animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38);animation-timing-function:cubic-bezier(0.53, -0.03, 0.68, 0.38)}@-webkit-keyframes pulseBackgroundSuccess{5%{background-color:#5cb85c;color:#313335}}@-moz-keyframes pulseBackgroundSuccess{5%{background-color:#5cb85c;color:#313335}}@-ms-keyframes pulseBackgroundSuccess{5%{background-color:#5cb85c;color:#313335}}@keyframes pulseBackgroundSuccess{5%{background-color:#5cb85c;color:#313335}}@-webkit-keyframes pulseBackgroundSuccessActive{5%{background-color:#4cae4c;color:#313335}}@-moz-keyframes pulseBackgroundSuccessActive{5%{background-color:#4cae4c;color:#313335}}@-ms-keyframes pulseBackgroundSuccessActive{5%{background-color:#4cae4c;color:#313335}}@keyframes pulseBackgroundSuccessActive{5%{background-color:#4cae4c;color:#313335}}@-webkit-keyframes pulseBackgroundWarning{5%{background-color:#e28a0d;color:#2b2b2b}}@-moz-keyframes pulseBackgroundWarning{5%{background-color:#e28a0d;color:#2b2b2b}}@-ms-keyframes pulseBackgroundWarning{5%{background-color:#e28a0d;color:#2b2b2b}}@keyframes pulseBackgroundWarning{5%{background-color:#e28a0d;color:#2b2b2b}}@-webkit-keyframes pulseBackgroundWarningActive{5%{background-color:#ca7b0c;color:#2b2b2b}}@-moz-keyframes pulseBackgroundWarningActive{5%{background-color:#ca7b0c;color:#2b2b2b}}@-ms-keyframes pulseBackgroundWarningActive{5%{background-color:#ca7b0c;color:#2b2b2b}}@keyframes pulseBackgroundWarningActive{5%{background-color:#ca7b0c;color:#2b2b2b}}.pf-animate-rotate{-webkit-transition:all 0.08s linear;transition:all 0.08s linear}.pf-animate-rotate.right{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.timeline{list-style:none;position:relative}.timeline:before{top:0;bottom:0;position:absolute;content:" ";width:1px;left:50%;margin-top:20px;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzRmOWU0ZiIvPjxzdG9wIG9mZnNldD0iMjUlIiBzdG9wLWNvbG9yPSIjNjM2NzZhIi8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');background-size:100%;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #4f9e4f),color-stop(25%, #63676a));background-image:-moz-linear-gradient(top, #4f9e4f,#63676a 25%);background-image:-webkit-linear-gradient(top, #4f9e4f,#63676a 25%);background-image:linear-gradient(to bottom, #4f9e4f,#63676a 25%)}.timeline>li{margin-bottom:20px;position:relative}.timeline>li.timeline-first .timeline-title{color:#4f9e4f}.timeline>li.timeline-first .timeline-badge{background-color:#4f9e4f}.timeline>li:before,.timeline>li:after{content:" ";display:table}.timeline>li:after{clear:both}.timeline>li:before,.timeline>li:after{content:" ";display:table}.timeline>li:after{clear:both}.timeline>li>.timeline-panel{width:47%;float:left;border:1px solid #313335;padding:8px;position:relative;background-color:#313335;-webkit-box-shadow:0 4px 10px rgba(0,0,0,0.4);box-shadow:0 4px 10px rgba(0,0,0,0.4);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.timeline>li>.timeline-panel:before{content:" ";position:absolute;top:10px;right:-8px;display:inline-block;border-top:7px solid transparent;border-left:7px solid #63676a;border-right:0 solid #63676a;border-bottom:7px solid transparent}.timeline>li>.timeline-panel:after{content:" ";position:absolute;top:10px;right:-8px;display:inline-block;border-top:7px solid transparent;border-left:7px solid #63676a;border-right:0 solid #63676a;border-bottom:7px solid transparent}.timeline>li>.timeline-badge{color:#2b2b2b;width:22px;height:22px;line-height:22px;text-align:center;position:absolute;top:7px;left:50%;margin-left:-11px;background-color:#63676a;z-index:100;-moz-border-radius:50%;-webkit-border-radius:50%;border-radius:50%}.timeline>li.timeline-inverted>.timeline-panel{float:right}.timeline>li.timeline-inverted>.timeline-panel:before{border-left-width:0;border-right-width:7px;left:-8px;right:auto}.timeline>li.timeline-inverted>.timeline-panel:after{border-left-width:0;border-right-width:8px;left:-9px;right:auto}.timeline-title{margin-top:0;color:inherit}.timeline-body>p,.timeline-body>ul{margin-bottom:0;list-style-type:disc;margin-left:15px}.timeline-body>p+p{margin-top:5px}@media (max-width: 1200px){ul.timeline:before{left:40px}ul.timeline>li>.timeline-panel{width:calc(100% - 62px)}ul.timeline>li>.timeline-badge{left:29px;margin-left:0;top:6px}ul.timeline>li>.timeline-panel{float:right}ul.timeline>li>.timeline-panel:before{border-left-width:0;border-right-width:7px;left:-8px;right:auto}ul.timeline>li>.timeline-panel:after{border-left-width:0;border-right-width:7px;left:-8px;right:auto}}.ribbon-wrapper{width:72px;height:88px;overflow:hidden;position:absolute;top:-3px;right:7px}.ribbon{font:bold 12px "Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;color:#2b2b2b;text-align:center;text-shadow:rgba(255,255,255,0.2) 0px 1px 0px;position:relative;padding:3px 0;left:-4px;top:16px;width:99px;-webkit-box-shadow:2px 3px 3px rgba(0,0,0,0.2);box-shadow:2px 3px 3px rgba(0,0,0,0.2);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-webkit-transform:rotate(45deg);transform:rotate(45deg)}.ribbon:before,.ribbon:after{content:"";border-left:3px solid transparent;border-right:3px solid transparent;position:absolute;bottom:-3px}.ribbon.ribbon-green{background-color:#5cb85c;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzUxYjM1MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzRhOTQ0YSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');background-size:100%;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #51b351),color-stop(100%, #4a944a));background-image:-moz-linear-gradient(top, #51b351,#4a944a);background-image:-webkit-linear-gradient(top, #51b351,#4a944a);background-image:linear-gradient(to bottom, #51b351,#4a944a)}.ribbon.ribbon-green:before,.ribbon.ribbon-green:after{border-top:3px solid #285028}.ribbon.ribbon-orange{background-color:#e28a0d;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2Q0ODEwYyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2I0NmQwYiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');background-size:100%;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #d4810c),color-stop(100%, #b46d0b));background-image:-moz-linear-gradient(top, #d4810c,#b46d0b);background-image:-webkit-linear-gradient(top, #d4810c,#b46d0b);background-image:linear-gradient(to bottom, #d4810c,#b46d0b)}.ribbon.ribbon-orange:before,.ribbon.ribbon-orange:after{border-top:3px solid #6c4107}.ribbon:before{left:0}.ribbon:after{right:0}.pf-loading-bars-container{position:relative;z-index:4;margin:0 auto;left:5px;right:19px;width:70px;height:50px;list-style:none}.pf-loading-bars-container .pf-loading-bars-loader{position:absolute;z-index:3;margin:0 auto;left:0;right:0;top:50%;margin-top:-19px;width:56px;height:37px;list-style:none}.pf-loading-bars-container .pf-loading-bars-loader li{background-color:#5cb85c;width:6px;height:6px;float:right;margin-right:3px !important;-webkit-box-shadow:0px 12px 6px rgba(0,0,0,0.2);box-shadow:0px 12px 6px rgba(0,0,0,0.2)}.pf-loading-bars-container .pf-loading-bars-loader li:first-child{-webkit-animation:cssload-loadbars 1.75s cubic-bezier(0.645, 0.045, 0.355, 1) infinite 0s;animation:cssload-loadbars 1.75s cubic-bezier(0.645, 0.045, 0.355, 1) infinite 0s}.pf-loading-bars-container .pf-loading-bars-loader li:nth-child(2){-webkit-animation:cssload-loadbars 1.75s ease-in-out infinite -0.35s;animation:cssload-loadbars 1.75s ease-in-out infinite -0.35s}.pf-loading-bars-container .pf-loading-bars-loader li:nth-child(3){-webkit-animation:cssload-loadbars 1.75s ease-in-out infinite -0.7s;animation:cssload-loadbars 1.75s ease-in-out infinite -0.7s}.pf-loading-bars-container .pf-loading-bars-loader li:nth-child(4){-webkit-animation:cssload-loadbars 1.75s ease-in-out infinite -1.05s;animation:cssload-loadbars 1.75s ease-in-out infinite -1.05s}.pf-loading-bars-container .pf-loading-bars-loader li:nth-child(5){-webkit-animation:cssload-loadbars 1.75s ease-in-out infinite -1.4s;animation:cssload-loadbars 1.75s ease-in-out infinite -1.4s}.pf-loading-bars-container .pf-loading-bars-loader li:nth-child(6){-webkit-animation:cssload-loadbars 1.75s ease-in-out infinite -1.75s;animation:cssload-loadbars 1.75s ease-in-out infinite -1.75s}@-webkit-keyframes cssload-loadbars{0%{height:6px;margin-top:16px}33%{height:6px;margin-top:16px}66%{height:31px;margin-top:0px}100%{height:6px;margin-top:16px}}@-moz-keyframes cssload-loadbars{0%{height:6px;margin-top:16px}33%{height:6px;margin-top:16px}66%{height:31px;margin-top:0px}100%{height:6px;margin-top:16px}}@-ms-keyframes cssload-loadbars{0%{height:6px;margin-top:16px}33%{height:6px;margin-top:16px}66%{height:31px;margin-top:0px}100%{height:6px;margin-top:16px}}@keyframes cssload-loadbars{0%{height:6px;margin-top:16px}33%{height:6px;margin-top:16px}66%{height:31px;margin-top:0px}100%{height:6px;margin-top:16px}}.youtube{background-position:center;background-repeat:no-repeat;position:relative;display:inline-block;overflow:hidden;transition:all 200ms ease-out;cursor:pointer}.youtube .play{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAERklEQVR4nOWbTWhcVRTHb1IJVoxGtNCNdal2JYJReC6GWuO83PM/59yUS3FRFARdFlwYP1CfiojQWt36sRCUurRIdVFXIn41lAoVdRGrG1M01YpKrWjiYmaSl8ybZJL3cd+YA//NLObd3++eO8x79z5jSq5Gw+8kov0AP8vMR5l1BtBZQM4B8ks75wCdZdYZZj5qLZ4hov2Nht9Z9vhKKSIaB/gI4M4w62KeAO6Mte4lYOq20FxrlqqOibhHmeWbvNC9ZfDX1mLae391aN6limO/gwgvAPJbWeAZuSDingdwXTBw7/0IsyaA/Fkh+KqOkD+YNfHej1QKD+y7iVlOhgLvFqFfNJvNGyuBJ+KDAF8MDd0tgS8y64OlgSdJMsysL4cG7SOHkyQZLhTee7+d2R2rAVy/S+Jd7/32ouBHAP4gNNRGQyTHc/84NhqNywZp5rvjjnnvt21aABFeCQ+RLwAf2hQ8s7sv9OCLk6AHNgQvIrvbfzKCD76g/O6cu7lf/iER/aQGgy448pExZmhdegAPhR9sObFWH1gT3lp7DaA/5bkIgJhZPgsNmz02novj+KqeApj1ubwXWe4kdyeznAgNvTpE/HQmvKqOMeuFogTUVQSRno+iaLRLAJF7uIgL9O4ubgL8aWgB7S44mNX+35YpICUiAvS9sBLkq1WzT+NFffl6AuoiApi6NT37h6sWkBIRZGkQ8YtLgyji6e1mBYTqCEBPG2Naz+0BWQgtoGoRgCzEsd9hAN1X5BfnFZASUfrSAFQNsyZ1FJASUVpHiLinDJG8U2cBZYogkrcNs5waBAGdstbeU9zdqpw0gPwwSAI6VUxHyFlDpOcHUUBBIuYNs14aZAE5RVwyzPr3/0EAEY0TyfGNjBWQvwZ +CTSbehfAH29mrID8bET0+0EUkAd8WYDOmqJ3ecsG30yr9wqRfm6Y+a1BEFDEjHfHvWmY9ck6CygHvBVr8Xhtb4ZE5HZA3y8DvBNA1TjnrmXWf+sioMwZX5V/VHXMGGMMoKdDCxCRvRWBdzKzdHEO+EisilbPyopHYqp6S9UCAsz4iojI7hUDAtyXVQgIDd6KnOoaWNkbI6FaPSuZGyMArsi7MZoloB4zviI/Nhr3X95jltwTRQmoIfgisy5ai+me67OI7fE4nrqjrqfK1t0eby0FPRB6oGVlchL3rgnfrq19RKbVBdhV9IOSwJmfmJi4vi/4ThERitwyCxVAFqydshuCX5awhQ9KtmuIWd8IDZED/nXT77rvVVv6sHRKwjYi91poqP7Dr+Y6JJ1VSZIMA3wkPNy6bX+o8Bcm0sXMdwM8Fxo0A3xORPaWBp6uPXsmbxCRD0NDL0dOANhVCXy6iAjMcjbcrMt3RITKwdMVRdFo+y5yvkL4eWZ+zHt/ZVD4dEVRNGotpst+dZZZH8k86lqn2pIvT/eqrNfn2xuyqYPZ8mv7s8pfn/8Pybm4TIjanscAAAAASUVORK5CYII=") no-repeat center center;background-size:64px 64px;position:absolute;height:100%;width:100%;opacity:.8;filter:alpha(opacity=80);transition:all 0.2s ease-out}.youtube .play:hover{opacity:1;filter:alpha(opacity=100)} diff --git a/public/img/landing/eve_sso_login_buttons_large_black.png b/public/img/landing/eve_sso_login_buttons_large_black.png new file mode 100644 index 000000000..cfb3a6f53 Binary files /dev/null and b/public/img/landing/eve_sso_login_buttons_large_black.png differ diff --git a/public/img/landing/eve_sso_login_buttons_large_black_hover.png b/public/img/landing/eve_sso_login_buttons_large_black_hover.png new file mode 100644 index 000000000..de56dbb8f Binary files /dev/null and b/public/img/landing/eve_sso_login_buttons_large_black_hover.png differ diff --git a/public/img/logo.png b/public/img/logo.png index 948a55728..3433792f3 100644 Binary files a/public/img/logo.png and b/public/img/logo.png differ diff --git a/public/img/logo_bg.png b/public/img/logo_bg.png index 30d847583..b7014d393 100644 Binary files a/public/img/logo_bg.png and b/public/img/logo_bg.png differ diff --git a/public/js/v1.0.0RC3/app/ui/dialog/map_info.js b/public/js/v1.0.0RC3/app/ui/dialog/map_info.js index 5b8ec6064..4f65b8db5 100644 --- a/public/js/v1.0.0RC3/app/ui/dialog/map_info.js +++ b/public/js/v1.0.0RC3/app/ui/dialog/map_info.js @@ -642,7 +642,7 @@ define([ } } } - +console.log(usersData); var userDataTable = userTable.dataTable( { pageLength: 20, diff --git a/public/templates/view/login.html b/public/templates/view/login.html index 9a16ec4d2..835bf9b32 100644 --- a/public/templates/view/login.html +++ b/public/templates/view/login.html @@ -75,31 +75,21 @@

Please log in

-
-
-
-
-
- -
-
-
-
-
- -
+ + {* login message container *} + +
+
+
+
+ Access denied + {{ @SESSION.SSO.ERROR }} +
-
- - {* login message container *} -
-
-
-
-
+ {* check for setup mode *} @@ -130,23 +120,20 @@

Please log in

- {* signUp/logIn buttons *} -
-
-
- -
-
- + {* SSO login *} +
+
+
-SSO login - {* features/ gallery *}