├── .htaccess ├── Dockerfile ├── LICENSE ├── app ├── controller │ ├── cfginit.php │ ├── index.php │ └── teambition │ │ ├── pan.php │ │ └── project.php ├── function.php ├── route.php └── view │ ├── cfginit.html │ ├── common │ ├── foot.html │ └── head.html │ ├── index │ ├── _preview.html │ ├── index.html │ └── pan.html │ └── password.html ├── assets └── index.css ├── config └── sys.cfg.php ├── extend └── teambition.php ├── favicon.ico ├── framework ├── flx.php ├── function.php ├── route.php └── view │ ├── app_error.php │ └── sys_error.php ├── index.php ├── nginx └── readme.md /.htaccess: -------------------------------------------------------------------------------- 1 | 2 | Options +FollowSymlinks -Multiviews 3 | RewriteEngine On 4 | RewriteCond %{REQUEST_FILENAME} !-d 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteRule ^(.*)$ index.php/?s=$1 [QSA,PT,L] 7 | 8 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.0-apache 2 | 3 | RUN apt-get update && \ 4 | apt-get clean 5 | 6 | RUN a2enmod rewrite 7 | 8 | COPY ./ /var/www/html/ 9 | 10 | RUN chown -R www-data:www-data /var/www/html/ 11 | 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 FlxSNX 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /app/controller/cfginit.php: -------------------------------------------------------------------------------- 1 | _CFG = $Flx->_CFG; 8 | if(!$this->_CFG['teambition'] && !$this->_CFG['pan']){ 9 | if(is_ajax()){ 10 | $type = authstr($_POST['type']) ?: NULL; 11 | $title = authstr($_POST['title']) ?: NULL; 12 | $url = authstr($_POST['url']) ?: NULL; 13 | $cookie = authstr($_POST['cookie']) ?: NULL; 14 | if(!$type || !$title || !$url || !$cookie)exit('{"code":500,"msg":"参数错误"}'); 15 | if($type == 'pan'){ 16 | $result = teambition::get_pan_config($cookie); 17 | if($result){ 18 | $config = << '$type', 22 | 'url' => '$url', 23 | 'pan' => [ 24 | 'cookie' => '$cookie', 25 | 'orgId' => '$result[orgId]', 26 | 'spaceId' => '$result[spaceId]', 27 | 'driveId' => '$result[driveId]', 28 | 'rootId' => '$result[rootId]', 29 | 'maxCount' => 1000 30 | ], 31 | 'title' => '$title' 32 | ]; 33 | TEXT; 34 | 35 | $savecfg = file_put_contents(ROOTDIR.'config/app.cfg.php', $config); 36 | if($savecfg){ 37 | exit('{"code":200,"msg":"配置成功"}'); 38 | }else{ 39 | exit('{"code":500,"msg":"保存信息时出错"}'); 40 | } 41 | }else{ 42 | exit('{"code":500,"msg":"获取网盘信息失败:cookie错误或未开通网盘"}'); 43 | } 44 | }elseif($type == 'project'){ 45 | $projectId = authstr($_POST['projectId']) ?: NULL; 46 | if(!$projectId)exit('{"code":500,"msg":"缺少projectId"}'); 47 | $project = teambition::get_project($projectId,$cookie); 48 | if($project){ 49 | $config = << '$type', 53 | 'url' => '$url', 54 | 'teambition' => [ 55 | 'cookie' => '$cookie', 56 | 'projectId' => '$projectId', 57 | 'maxCount' => 1000 58 | ], 59 | 'title' => '$title' 60 | ]; 61 | TEXT; 62 | 63 | $savecfg = file_put_contents(ROOTDIR.'config/app.cfg.php', $config); 64 | if($savecfg){ 65 | exit('{"code":200,"msg":"配置成功"}'); 66 | }else{ 67 | exit('{"code":500,"msg":"保存信息时出错"}'); 68 | } 69 | }else{ 70 | exit('{"code":500,"msg":"获取项目信息失败:cookie或projectId错误"}'); 71 | } 72 | } 73 | } 74 | assign([ 75 | 'title' => '配置向导', 76 | 'version' => '1.14' 77 | ]); 78 | view('cfginit'); 79 | }else{ 80 | app_error([ 81 | 'code' => 403, 82 | 'title' => '拒绝访问', 83 | 'error' => '请问重复配置', 84 | 'info' => '如果需要重新配置,请将配置文件{app.cfg.php}清空!' 85 | ]); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /app/controller/index.php: -------------------------------------------------------------------------------- 1 | _CFG = $Flx->_CFG; 11 | $this->cookie = $this->_CFG['teambition']['cookie']; 12 | assign(['_CFG' => $this->_CFG,'version' => $version]); 13 | // 全局密码 14 | if(isset($this->_CFG['password']) && $this->_CFG['password'] != false){ 15 | session_start(); 16 | if(is_ajax()){ 17 | if(!$_POST['id']){ 18 | $password = $_POST['password']; 19 | if($_POST['password'] == $this->_CFG['password']){ 20 | $_SESSION['password'] = $_POST['password']; 21 | exit('{"code":200,"msg":"密码正确,3秒后跳转"}'); 22 | }else{ 23 | exit('{"code":500,"msg":"密码错误"}'); 24 | } 25 | } 26 | } 27 | if($_SESSION['password'] != $this->_CFG['password']){ 28 | assign(['title' => $this->_CFG['title']]); 29 | view('password'); 30 | exit; 31 | } 32 | } 33 | } 34 | 35 | public function index($id=false){ 36 | if(!$this->_CFG['teambition'] && !$this->_CFG['pan']){ 37 | header('Location:init'); 38 | }else{ 39 | if($this->_CFG['type'] == 'project'){ 40 | $project = new project($this->_CFG); 41 | 42 | if(!$id)$id = $project->info['_rootCollectionId']; 43 | 44 | $list = $project->get_list($id); 45 | 46 | $dirlist = $list['dirs']; 47 | $filelist = $list['files']; 48 | $dir = $project->get_dir($id); 49 | 50 | // 查询是否有.password文件 51 | $fileindex = 0; 52 | $pass = false; 53 | foreach($filelist as $file){ 54 | if($file['fileName'] == '.password'){ 55 | // 如果文件大于2kb忽略掉 56 | if($file['fileSize'] < 2048){ 57 | $pass = curl($file['downloadUrl']); 58 | unset($filelist[$fileindex]); 59 | $filelist = array_values($filelist); 60 | } 61 | break; 62 | } 63 | $fileindex++; 64 | } 65 | 66 | assign([ 67 | 'dirlist' => $dirlist, 68 | 'filelist' => $filelist, 69 | 'title' => $this->_CFG['title'], 70 | 'dir' => $dir 71 | ]); 72 | 73 | // 目录密码验证 74 | if($pass !== false){ 75 | session_start(); 76 | if(is_ajax() && !empty($_POST['id'])){ 77 | if($_POST['password'] == $pass){ 78 | $_SESSION[$_POST['id']] = $_POST['password']; 79 | exit('{"code":200,"msg":"密码正确,3秒后跳转"}'); 80 | }else{ 81 | exit('{"code":500,"msg":"密码错误"}'); 82 | } 83 | } 84 | if($_SESSION[$id] == $pass){ 85 | view(); 86 | }else{ 87 | assign(['id' => $id]); 88 | view('password'); 89 | } 90 | }else{ 91 | view(); 92 | } 93 | }elseif($this->_CFG['type'] == 'pan'){ 94 | $pan = new pan($this->_CFG); 95 | if(!$id)$id = $this->_CFG['pan']['rootId']; 96 | 97 | $list = $pan->get_list($id); 98 | $dir = $pan->get_dir($id); 99 | 100 | // 查询是否有.password文件 101 | $fileindex = 0; 102 | $pass = false; 103 | foreach($list['data'] as $file){ 104 | if($file['kind'] != 'folder' && $file['name'] == '.password'){ 105 | // 如果文件大于2kb忽略掉 106 | if($file['fileSize'] < 2048){ 107 | $pass = curl($file['downloadUrl']); 108 | unset($list['data'][$fileindex]); 109 | $list['data'] = array_values($list['data']); 110 | } 111 | break; 112 | } 113 | $fileindex++; 114 | } 115 | 116 | assign([ 117 | 'panlist' => $list, 118 | 'title' => $this->_CFG['title'], 119 | 'dir' => $dir 120 | ]); 121 | 122 | // 目录密码验证 123 | if($pass !== false){ 124 | session_start(); 125 | if(is_ajax() && !empty($_POST['id'])){ 126 | if($_POST['password'] == $pass){ 127 | $_SESSION[$_POST['id']] = $_POST['password']; 128 | exit('{"code":200,"msg":"密码正确,3秒后跳转"}'); 129 | }else{ 130 | exit('{"code":500,"msg":"密码错误"}'); 131 | } 132 | } 133 | if($_SESSION[$id] == $pass){ 134 | view('index/pan'); 135 | }else{ 136 | assign(['id' => $id]); 137 | view('password'); 138 | } 139 | }else{ 140 | view('index/pan'); 141 | } 142 | }else{ 143 | app_error([ 144 | 'code' => 500, 145 | 'title' => '应用配置错误', 146 | 'error' => '配置错误', 147 | 'info' => '类型只能为project或pan' 148 | ]); 149 | } 150 | } 151 | } 152 | 153 | public function getDownload($id){ 154 | $type = authstr($_GET['type']) ?: 302; 155 | if($this->_CFG['type'] == 'project'){ 156 | $result = teambition::get_download_url($id,$this->cookie); 157 | if($result){ 158 | if($result['downloadUrl']){ 159 | if(isset($_GET['preview'])){ 160 | assign([ 161 | 'fileid' => $id, 162 | 'filename' => $result['fileName'], 163 | 'filetype' => $result['fileType'], 164 | 'downloadUrl' => $result['downloadUrl'], 165 | 'title' => $this->_CFG['title'] 166 | ]); 167 | view('index/_preview'); 168 | }else{ 169 | if($type == 'json'){ 170 | $result = [ 171 | 'code' => 200, 172 | 'msg' => '解析成功', 173 | 'data' => $result 174 | ]; 175 | exit(json_encode($result)); 176 | }elseif($type == 302){ 177 | header('Location:'.$result['downloadUrl']); 178 | }elseif($type == 'url'){ 179 | exit($result['downloadUrl']); 180 | } 181 | } 182 | }else{ 183 | exit('{"code":500,"msg":"解析失败"}'); 184 | } 185 | }else{ 186 | exit('{"code":500,"msg":"解析失败"}'); 187 | } 188 | }elseif($this->_CFG['type'] == 'pan'){ 189 | $result = teambition::get_pan_file($this->_CFG['pan']['cookie'],$this->_CFG['pan']['orgId'],$this->_CFG['pan']['spaceId'],$this->_CFG['pan']['driveId'],$id); 190 | if($result){ 191 | if($result['downloadUrl']){ 192 | if(isset($_GET['preview'])){ 193 | assign([ 194 | 'fileid' => $id, 195 | 'filename' => $result['name'], 196 | 'filetype' => $result['ext'], 197 | 'downloadUrl' => $result['downloadUrl'], 198 | 'title' => $this->_CFG['title'] 199 | ]); 200 | view('index/_preview'); 201 | }else{ 202 | if($type == 'json'){ 203 | $result = [ 204 | 'code' => 200, 205 | 'msg' => '解析成功', 206 | 'data' => $result 207 | ]; 208 | exit(json_encode($result)); 209 | }elseif($type == 302){ 210 | header('Location:'.$result['downloadUrl']); 211 | }elseif($type == 'url'){ 212 | exit($result['downloadUrl']); 213 | } 214 | } 215 | }else{ 216 | exit('{"code":500,"msg":"解析失败"}'); 217 | } 218 | } 219 | } 220 | } 221 | } -------------------------------------------------------------------------------- /app/controller/teambition/pan.php: -------------------------------------------------------------------------------- 1 | cookie = $_CFG['pan']['cookie']; 15 | $this->_CFG = $_CFG; 16 | }else{ 17 | app_error([ 18 | 'code' => 500, 19 | 'title' => '应用配置错误', 20 | 'error' => 'cookie配置错误', 21 | 'info' => '请检查cookie是否已失效后重新配置' 22 | ]); 23 | } 24 | } 25 | 26 | public function get_list($id,$order='updateTime'){ 27 | $result = teambition::get_pan_list($this->_CFG['pan']['cookie'],$this->_CFG['pan']['orgId'],$this->_CFG['pan']['spaceId'],$this->_CFG['pan']['driveId'],$id,$this->_CFG['pan']['maxCount']); 28 | if($result['data']['message']){ 29 | return app_error(404); 30 | }else{ 31 | return $result; 32 | } 33 | } 34 | 35 | public function get_dir($id){ 36 | $result = teambition::get_pan_file($this->_CFG['pan']['cookie'],$this->_CFG['pan']['orgId'],$this->_CFG['pan']['spaceId'],$this->_CFG['pan']['driveId'],$id); 37 | if($result['status'] != '400'){ 38 | return $result; 39 | }else{ 40 | return app_error(404); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /app/controller/teambition/project.php: -------------------------------------------------------------------------------- 1 | cookie = $_CFG['teambition']['cookie']; 17 | $this->projectId = $_CFG['teambition']['projectId']; 18 | $this->info = $project; 19 | $this->_CFG = $_CFG; 20 | }else{ 21 | app_error([ 22 | 'code' => 500, 23 | 'title' => '应用配置错误', 24 | 'error' => 'cookie或projectId配置错误', 25 | 'info' => '请检查projectId是否配置正确或cookie是否已失效后重新配置' 26 | ]); 27 | } 28 | } 29 | 30 | public function get_list($id=false,$order='updatedDesc'){ 31 | if(!$id)$id = $this->project['_rootCollectionId']; 32 | $dirs = $this->get_dirs($id,$order); 33 | $files = $this->get_files($id,$order); 34 | return ['dirs' => $dirs,'files' => $files]; 35 | } 36 | 37 | public function get_dirs($id,$order='updatedDesc'){ 38 | // 因为project的获取目录和文件是分开的所以数量除以2 39 | $maxCount = ceil($this->_CFG['teambition']['maxCount']/2); 40 | $result = teambition::get_dirs($this->projectId,$id,$this->cookie,$maxCount,$order); 41 | // 如果有message则代表ID错误 返回404 42 | if($result['message'])return app_error(404); 43 | return $result; 44 | } 45 | 46 | public function get_files($id,$order='updatedDesc'){ 47 | // 因为project的获取目录和文件是分开的所以数量除以2 48 | $maxCount = ceil($this->_CFG['teambition']['maxCount']/2); 49 | $result = teambition::get_files($this->projectId,$id,$this->cookie,$maxCount,$order); 50 | // 如果有message则代表ID错误 返回404 51 | if($result['message'])return app_error(404); 52 | return $result; 53 | } 54 | 55 | public function get_dir($id){ 56 | $result = teambition::get_dir($id,$this->cookie); 57 | if($result){ 58 | return $result; 59 | }else{ 60 | return app_error(404); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /app/function.php: -------------------------------------------------------------------------------- 1 | = 1073741824) { 5 | $filesize = round($filesize / 1073741824 * 100) / 100 . ' GB'; 6 | 7 | } elseif($filesize >= 1048576) { 8 | $filesize = round($filesize / 1048576 * 100) / 100 . ' MB'; 9 | 10 | } elseif($filesize >= 1024) { 11 | $filesize = round($filesize / 1024 * 100) / 100 . ' KB'; 12 | 13 | } else { 14 | $filesize = $filesize . ' 字节'; 15 | 16 | } 17 | return $filesize; 18 | } 19 | 20 | function getFileicon($type){ 21 | $type = strtolower($type); 22 | if($type == 'mp4'){ 23 | return 'play_circle_filled'; 24 | }elseif(in_array($type,["gif","jpeg","jpg","png"])){ 25 | return 'photo'; 26 | }elseif(in_array($type,["mp3","ogg","wav"])){ 27 | return 'music_note'; 28 | }else{ 29 | return 'insert_drive_file'; 30 | } 31 | } 32 | 33 | function isPreview($type){ 34 | $type = strtolower($type); 35 | if($type == 'mp4' || in_array($type,["gif","jpeg","jpg","png"]) || in_array($type,["mp3","ogg","wav"])){ 36 | return '?preview'; 37 | }else{ 38 | return false; 39 | } 40 | } 41 | 42 | function curl($url,$post=false,$cookie=false,$header=false,$split=false,$referer=false){ 43 | $ch = curl_init(); 44 | if($header){ 45 | curl_setopt($ch,CURLOPT_HEADER, 1); 46 | }else{ 47 | curl_setopt($ch,CURLOPT_HEADER, 0); 48 | } 49 | curl_setopt($ch, CURLOPT_URL,$url); 50 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 51 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 52 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 53 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); 54 | curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36'); 55 | if($post){ 56 | curl_setopt($ch, CURLOPT_POST, 1); 57 | curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($post)); 58 | } 59 | if($cookie){ 60 | curl_setopt($ch, CURLOPT_COOKIE,$cookie); 61 | } 62 | if($referer){ 63 | curl_setopt($ch, CURLOPT_REFERER, $referer); 64 | } 65 | $result = curl_exec($ch); 66 | if($split){ 67 | $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 68 | $header = substr($result, 0, $headerSize); 69 | $body = substr($result, $headerSize); 70 | $result=array(); 71 | $result['header']=$header; 72 | $result['body']=$body; 73 | } 74 | curl_close($ch); 75 | return $result; 76 | } 77 | 78 | function is_post(){ 79 | return isset($_SERVER['REQUEST_METHOD']) && strtoupper($_SERVER['REQUEST_METHOD'])=='POST'; 80 | } 81 | 82 | function is_ajax(){ 83 | return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtoupper($_SERVER['HTTP_X_REQUESTED_WITH'])=='XMLHTTPREQUEST'; 84 | } -------------------------------------------------------------------------------- /app/route.php: -------------------------------------------------------------------------------- 1 | where([ 9 | 'dirid' => '[A-Za-z0-9]+' 10 | ]); 11 | 12 | Route::get('download/{fileid}','index@getDownload')->where([ 13 | 'fileid' => '[A-Za-z0-9]+' 14 | ]); -------------------------------------------------------------------------------- /app/view/cfginit.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 | 11 | 12 |
如果放在二级目录,请填写对应地址 例如http://xxx.com/pan
13 |
14 |
15 | 16 |
17 |
18 | 23 |
24 |
25 | 30 |
31 |
32 |
33 | 37 |
38 | 39 | 40 |
41 | 42 |
43 |
44 |
45 | 46 | -------------------------------------------------------------------------------- /app/view/common/foot.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 40 | 41 | -------------------------------------------------------------------------------- /app/view/common/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | <?=$title?> 12 | 13 | 14 | 15 | 119 | 120 |
121 |
122 |
123 | cloud_circle 124 |
125 | 126 |
127 |
128 |
-------------------------------------------------------------------------------- /app/view/index/_preview.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 | 9 | 10 |
11 | 19 | 22 | 23 | 26 | 27 | 30 | get_app下载 31 |
32 | -------------------------------------------------------------------------------- /app/view/index/index.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 6 |
7 |
8 |
9 | arrow_back 10 | folder_open
11 |
12 |
13 |
14 | 17 |
18 | 19 |
20 | Name 21 |
22 |
23 | Size 24 |
25 | 26 |
27 | 59 |
60 | -------------------------------------------------------------------------------- /app/view/index/pan.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 6 |
7 |
8 |
9 | arrow_back 10 | folder_open
11 |
12 |
13 |
14 | 17 |
18 | 19 |
20 | Name 21 |
22 |
23 | Size 24 |
25 | 26 |
27 | 58 |
59 | -------------------------------------------------------------------------------- /app/view/password.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 | 6 |
7 | 8 | arrow_back 9 | 10 | folder 11 | 19 |
20 |
21 |
此目录设置了访问权限,请输入密码!
22 | 23 |
网站设置了访问权限,请输入密码!
24 | 25 |
26 | 27 | 28 |
29 | 30 |
31 |
32 |
33 | 34 | -------------------------------------------------------------------------------- /assets/index.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}*{-webkit-tap-highlight-color:transparent}body{color:rgba(0,0,0,.87);font-size:14px;font-family:Roboto,Noto,Helvetica,Arial,sans-serif;background-color:#fff}@media (min-width:600px){body{font-size:14.5px}}@media (min-width:1024px){body{font-size:15px}}body ::-webkit-scrollbar{width:5px;height:5px;background:transparent}@media (min-width:1024px){body ::-webkit-scrollbar{width:8px;height:8px}}body ::-webkit-scrollbar-thumb{background:rgba(0,0,0,.2)}body.mdui-locked{overflow:hidden}.mdui-overlay{position:fixed;top:-5000px;right:-5000px;bottom:-5000px;left:-5000px;z-index:2000;background:rgba(0,0,0,.4);backface-visibility:hidden;visibility:hidden;opacity:0;transition-duration:.3s;transition-property:opacity,visibility;will-change:opacity}.mdui-overlay-show{visibility:visible;opacity:1}.mdui-no-transition{transition-property:none!important}.mdui-theme-layout-dark{color:#fff;background-color:#303030}.mdui-theme-layout-dark ::-webkit-scrollbar{width:5px;height:5px;background:transparent}@media (min-width:1024px){.mdui-theme-layout-dark ::-webkit-scrollbar{width:8px;height:8px}}.mdui-theme-layout-dark ::-webkit-scrollbar-thumb{background:hsla(0,0%,100%,.3)}.mdui-color-theme{color:#fff!important;background-color:#1a73e8!important}.mdui-text-color-theme{color:#1a73e8!important}.mdui-theme-layout-dark .mdui-color-theme{background-color:#8ab4f8!important}.mdui-theme-layout-dark .mdui-text-color-theme{color:#8ab4f8!important}.mdui-text-color-theme-text{color:rgba(0,0,0,.87)!important}.mdui-text-color-theme-icon,.mdui-text-color-theme-secondary{color:rgba(0,0,0,.54)!important}.mdui-theme-layout-dark .mdui-text-color-theme-text{color:#fff!important}.mdui-theme-layout-dark .mdui-text-color-theme-secondary{color:hsla(0,0%,100%,.7)!important}.mdui-theme-layout-dark .mdui-text-color-theme-icon{color:#fff!important}.mdui-clearfix:after,.mdui-clearfix:before{display:table;content:" "}.mdui-clearfix:after{clear:both}.mdui-hidden,[hidden]{display:none!important}.mdui-icon,.mdui-icon:before{color:inherit;font-weight:400;font-size:24px;font-style:normal;line-height:1;direction:ltr;letter-spacing:normal;white-space:nowrap;text-transform:none;vertical-align:middle;word-wrap:normal}.mdui-icon{display:inline-block;text-align:center}.mdui-icon:before{display:block!important;width:24px;height:24px}@font-face{font-weight:400;font-family:Material Icons;font-style:normal;src:local("Material Icons"),local("MaterialIcons-Regular"),url(cff684e59ffb052d72cb8d5e49471553.woff2) format("woff2"),url(83bebaf37c09c7e1c3ee52682892ae14.woff) format("woff")}.material-icons{font-family:Material Icons;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:"liga"}@font-face{font-weight:400;font-family:Roboto;font-style:normal;font-display:swap;src:local("Roboto Regular"),local("Roboto-Regular"),url(c065bd9fa03a7a797d95ba7f198a9dcf.woff2) format("woff2"),url(770a8fca674a3550e241a6de7fa82d8b.woff) format("woff")}@font-face{font-weight:400;font-family:Roboto;font-style:italic;font-display:swap;src:local("Roboto RegularItalic"),local("Roboto-RegularItalic"),url(3a0ee5b0beec8d0ead1336016cbe19ad.woff2) format("woff2"),url(33d48155cd9f38c64e71b9d016dd61fb.woff) format("woff")}@font-face{font-weight:500;font-family:Roboto;font-style:normal;font-display:swap;src:local("Roboto Medium"),local("Roboto-Medium"),url(b92cc2170a4d5438fd3d19f349ce3785.woff2) format("woff2"),url(eb797abfa6a5cca2463e423c07c4f6ea.woff) format("woff")}@font-face{font-weight:500;font-family:Roboto;font-style:italic;font-display:swap;src:local("Roboto MediumItalic"),local("Roboto-MediumItalic"),url(113e7623163d4cb7f965cd8f8d3859eb.woff2) format("woff2"),url(8be651082cc0d07c84f633965e8ced59.woff) format("woff")}@font-face{font-weight:700;font-family:Roboto;font-style:normal;font-display:swap;src:local("Roboto Bold"),local("Roboto-Bold"),url(3b52bc86749058f144deb815c481ca5b.woff2) format("woff2"),url(8bd7856b64b4313341ebfbc0136c9d74.woff) format("woff")}@font-face{font-weight:700;font-family:Roboto;font-style:italic;font-display:swap;src:local("Roboto BoldItalic"),local("Roboto-BoldItalic"),url(f21b7e045fd077321cdaf92cab817cd3.woff2) format("woff2"),url(d85436fa35b78a399a68b44491fa3478.woff) format("woff")}.mdui-typo{line-height:1.8;word-wrap:break-word}.mdui-typo address,.mdui-typo caption,.mdui-typo cite,.mdui-typo code,.mdui-typo dfn,.mdui-typo th{font-weight:400;font-style:normal}.mdui-typo caption,.mdui-typo th{text-align:left}.mdui-typo q:after,.mdui-typo q:before{content:""}.mdui-typo code,.mdui-typo kbd,.mdui-typo pre,.mdui-typo pre tt,.mdui-typo samp{font-family:Consolas,Courier,Courier New,monospace}.mdui-typo figcaption{color:rgba(0,0,0,.54);font-size:80%}.mdui-typo [draggable=true],.mdui-typo [draggable]{cursor:move}.mdui-typo [draggable=false]{cursor:inherit}.mdui-typo .mdui-table,.mdui-typo .mdui-table-fluid,.mdui-typo dl,.mdui-typo figure,.mdui-typo form,.mdui-typo hr,.mdui-typo ol,.mdui-typo p,.mdui-typo pre,.mdui-typo table,.mdui-typo ul{margin:0 0 1.2em}.mdui-typo .mdui-table-fluid:last-child,.mdui-typo .mdui-table:last-child,.mdui-typo dl:last-child,.mdui-typo figure:last-child,.mdui-typo form:last-child,.mdui-typo hr:last-child,.mdui-typo ol:last-child,.mdui-typo p:last-child,.mdui-typo pre:last-child,.mdui-typo table:last-child,.mdui-typo ul:last-child{margin-bottom:0}.mdui-typo a{color:#448aff;position:relative;display:inline-block;overflow:hidden;text-decoration:none;vertical-align:top;outline:none}.mdui-typo a:before{position:absolute;top:auto;bottom:1px;left:0;width:100%;height:1px;background-color:#448aff;transform:scaleX(0);backface-visibility:hidden;transition:all .2s;content:" "}.mdui-typo a:focus:before,.mdui-typo a:hover:before{transform:scaleX(1)}.mdui-typo small{font-size:80%}.mdui-typo blockquote{margin:1em 3em 1em 2em;padding-left:1em;font-weight:400;border-left:4px solid rgba(0,0,0,.12)}@media only screen and (max-width:599.9px){.mdui-typo blockquote{margin:1em 0}}.mdui-typo blockquote:last-child{margin-bottom:0}.mdui-typo blockquote footer{color:rgba(0,0,0,.54);font-size:86%}.mdui-typo mark{margin:0 5px;padding:2px;background:#fffdd1;border-bottom:1px solid #ffedce}.mdui-typo h1,.mdui-typo h2,.mdui-typo h3,.mdui-typo h4,.mdui-typo h5,.mdui-typo h6{margin-top:1.2em;margin-bottom:.6em;color:inherit;font-weight:400;font-family:inherit;line-height:1.35}.mdui-typo h1:last-child,.mdui-typo h2:last-child,.mdui-typo h3:last-child,.mdui-typo h4:last-child,.mdui-typo h5:last-child,.mdui-typo h6:last-child{margin-bottom:0}.mdui-typo h1 small,.mdui-typo h2 small,.mdui-typo h3 small,.mdui-typo h4 small,.mdui-typo h5 small,.mdui-typo h6 small{color:rgba(0,0,0,.54);font-weight:400;font-size:65%;line-height:1}.mdui-typo h1{font-size:2em}.mdui-typo h2{font-size:1.8em}.mdui-typo h3{font-size:1.6em}.mdui-typo h4{font-size:1.4em}.mdui-typo h5{font-size:1.2em}.mdui-typo h6{font-size:1.1em}.mdui-typo code{padding:2px 6px;color:#c7254e;background-color:#f7f7f9;border-radius:2px}.mdui-typo pre code{padding:0;color:inherit;font-size:inherit;line-height:1.7;background-color:transparent;border-radius:0}.mdui-typo abbr[title]{text-decoration:none;border-bottom:1px dotted;cursor:help}.mdui-typo ins,.mdui-typo u{text-decoration:none;border-bottom:1px solid}.mdui-typo del{text-decoration:line-through}.mdui-typo hr{height:10px;margin-bottom:.8em;border:none;border-bottom:1px solid rgba(0,0,0,.12)}.mdui-typo pre{padding:12px 16px;overflow-x:auto;border:1px solid rgba(0,0,0,.12);border-radius:2px;-webkit-overflow-scrolling:touch}.mdui-typo kbd{padding:2px 6px;color:#fff;font-size:90%;background-color:#333;border-radius:2px}.mdui-typo ul{padding-left:2em;list-style:disc}.mdui-typo ol{padding-left:2em;list-style:decimal}.mdui-typo li ol,.mdui-typo li ul{margin:.8em 0}.mdui-typo li ul{list-style:circle}.mdui-typo img,.mdui-typo video{max-width:100%}.mdui-typo figure{text-align:center}.mdui-typo figure figcaption{margin-top:8px;color:#999;font-size:14px}.mdui-typo figure figcaption:empty:before{z-index:-1;color:#bfbfbf;cursor:text;content:attr(placeholder)}.mdui-theme-layout-dark .mdui-typo blockquote{border-left-color:hsla(0,0%,100%,.12)}.mdui-theme-layout-dark .mdui-typo blockquote footer,.mdui-theme-layout-dark .mdui-typo figcaption{color:hsla(0,0%,100%,.7)}.mdui-theme-layout-dark .mdui-typo mark{background:#aaa;border-bottom-color:#bbb}.mdui-theme-layout-dark .mdui-typo h1 small,.mdui-theme-layout-dark .mdui-typo h2 small,.mdui-theme-layout-dark .mdui-typo h3 small,.mdui-theme-layout-dark .mdui-typo h4 small,.mdui-theme-layout-dark .mdui-typo h5 small,.mdui-theme-layout-dark .mdui-typo h6 small{color:hsla(0,0%,100%,.7)}.mdui-theme-layout-dark .mdui-typo code{color:#ffcdd2;background-color:#424242}.mdui-theme-layout-dark .mdui-typo pre{background:#424242;border-color:hsla(0,0%,100%,.12)}.mdui-theme-layout-dark .mdui-typo kbd{background:#424242}.mdui-theme-layout-dark .mdui-typo hr{border-color:hsla(0,0%,100%,.12)}.mdui-container{box-sizing:border-box;margin-right:auto;margin-left:auto;padding-right:8px;padding-left:8px}.mdui-container:after{display:table;clear:both;content:""}.mdui-container{width:96%;max-width:1280px}@media (min-width:600px){.mdui-container{width:94%}}@media (min-width:1024px){.mdui-container{width:92%}}.mdui-headroom{transition:all .3s cubic-bezier(.4,0,.2,1)!important}.mdui-headroom-pinned-down{transform:translateZ(0)!important}.mdui-headroom-unpinned-down{transform:translate3d(0,100%,0)!important;box-shadow:none!important}.mdui-headroom-pinned-toolbar{transform:translateZ(0)!important}.mdui-headroom-unpinned-toolbar{transform:translate3d(0,-56px,0)!important}@media (min-width:600px){.mdui-headroom-unpinned-toolbar{transform:translate3d(0,-64px,0)!important}}@media (orientation:landscape) and (max-width:959.9px){.mdui-headroom-unpinned-toolbar{transform:translate3d(0,-48px,0)!important}}.mdui-divider{height:1px;margin:-1px 0 0;border:none;background-color:rgba(0,0,0,.12)}.mdui-theme-layout-dark .mdui-divider{background-color:hsla(0,0%,100%,.12)}.mdui-ripple{position:relative;overflow:hidden;cursor:pointer;-ms-user-select:none;user-select:none}.mdui-ripple-wave{position:absolute!important;top:0;left:0;z-index:1;margin:0;padding:0;font-size:0;background-color:rgba(0,0,0,.1);border-radius:50%;transform:translateZ(0) scale(0);transition-duration:1.4s;pointer-events:none}.mdui-ripple[class*=mdui-color-] .mdui-ripple-wave{background-color:hsla(0,0%,100%,.3)}.mdui-ripple-wave-fill{opacity:.35;transition-duration:.3s}.mdui-ripple-wave-out{opacity:0;transition-duration:.6s}.mdui-theme-layout-dark .mdui-ripple-wave{background-color:hsla(0,0%,100%,.3)}.mdui-textfield{position:relative;padding-top:16px;padding-bottom:8px;overflow:hidden}.mdui-textfield-has-bottom{padding-bottom:28px}.mdui-textfield-input{display:block;box-sizing:border-box;width:100%;height:36px;margin:0;padding:8px 0;overflow:hidden;color:rgba(0,0,0,.87);font-size:16px;font-family:inherit;line-height:20px;background:none;border:none;border-bottom:1px solid rgba(0,0,0,.42);border-radius:0;outline:none;box-shadow:none;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s;transition-property:border-bottom-color,padding-right,box-shadow;appearance:none;resize:none}.mdui-textfield-input::-webkit-input-placeholder{color:inherit;opacity:.42}.mdui-textfield-input:not([disabled]):hover{border-bottom:1px solid rgba(0,0,0,.87);box-shadow:0 1px 0 0 rgba(0,0,0,.87);cursor:pointer}.mdui-textfield-input[rows]{height:auto!important;overflow:auto;-webkit-overflow-scrolling:touch}.mdui-textfield-label{display:block;width:100%;color:rgba(0,0,0,.54);font-size:16px;transform:scale(.75) translateY(0);transform-origin:left;transition:all .2s;pointer-events:none}.mdui-textfield-error,.mdui-textfield-helper{position:absolute;bottom:8px;height:12px;font-size:12px;line-height:12px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.mdui-textfield-error{color:rgba(255,23,68,.87);visibility:hidden}.mdui-textfield-helper{color:rgba(0,0,0,.54)}.mdui-textfield-focus .mdui-textfield-input,.mdui-textfield-focus .mdui-textfield-input:hover{border-bottom-color:#2962ff;box-shadow:0 1px 0 0 #2962ff}.mdui-textfield-focus .mdui-icon,.mdui-textfield-focus .mdui-textfield-label{color:rgba(41,98,255,.87)}.mdui-textfield-floating-label .mdui-textfield-label{color:rgba(0,0,0,.35);transform:scale(1) translateY(27px)}.mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,.mdui-textfield-floating-label.mdui-textfield-not-empty .mdui-textfield-label{color:rgba(0,0,0,.65);transform:scale(.75) translateY(0)}.mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label{color:#1a73e8}.mdui-theme-layout-dark .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label{color:#8ab4f8}.mdui-textfield-invalid-html5 .mdui-textfield-input,.mdui-textfield-invalid-html5.mdui-textfield-focus .mdui-textfield-input,.mdui-textfield-invalid.mdui-textfield-focus .mdui-textfield-input,.mdui-textfield-invalid .mdui-textfield-input{border-bottom-color:#ff1744!important;box-shadow:0 1px 0 0 #ff1744!important}.mdui-textfield-invalid-html5 .mdui-textfield-label,.mdui-textfield-invalid .mdui-textfield-label{color:#ff1744!important}.mdui-textfield-invalid-html5.mdui-textfield-floating-label .mdui-textfield-label,.mdui-textfield-invalid.mdui-textfield-floating-label .mdui-textfield-label{color:rgba(255,23,68,.35)!important}.mdui-textfield-invalid-html5.mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,.mdui-textfield-invalid-html5.mdui-textfield-floating-label.mdui-textfield-not-empty .mdui-textfield-label,.mdui-textfield-invalid.mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,.mdui-textfield-invalid.mdui-textfield-floating-label.mdui-textfield-not-empty .mdui-textfield-label{color:#ff1744!important}.mdui-textfield-invalid-html5 .mdui-textfield-error,.mdui-textfield-invalid .mdui-textfield-error{visibility:visible}.mdui-textfield-invalid-html5 .mdui-textfield-error+.mdui-textfield-helper,.mdui-textfield-invalid .mdui-textfield-error+.mdui-textfield-helper{visibility:hidden}.mdui-textfield-counter{position:absolute;right:8px;bottom:8px;height:12px;color:rgba(0,0,0,.54);font-size:12px;line-height:12px}.mdui-theme-layout-dark .mdui-textfield-input{color:#fff;border-bottom-color:hsla(0,0%,100%,.7)}.mdui-theme-layout-dark .mdui-textfield-input::-webkit-input-placeholder{color:hsla(0,0%,100%,.5)}.mdui-theme-layout-dark .mdui-textfield-input:not([disabled]):hover{border-bottom-color:#fff;box-shadow:0 1px 0 0 #fff}.mdui-theme-layout-dark .mdui-textfield-label,.mdui-theme-layout-dark .mdui-textfield .mdui-icon{color:hsla(0,0%,100%,.7)}.mdui-theme-layout-dark .mdui-textfield-floating-label .mdui-textfield-label{color:hsla(0,0%,100%,.35)}.mdui-theme-layout-dark .mdui-textfield-error{color:#ff1744}.mdui-theme-layout-dark .mdui-textfield-counter,.mdui-theme-layout-dark .mdui-textfield-helper{color:hsla(0,0%,100%,.7)}.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input,.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input:hover{border-bottom-color:#8ab4f8;box-shadow:0 1px 0 0 #8ab4f8}.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label{color:#8ab4f8}.mdui-theme-layout-dark .mdui-textfield-disabled .mdui-textfield-input::-webkit-input-placeholder,.mdui-theme-layout-dark .mdui-textfield-disabled .mdui-textfield-label{color:hsla(0,0%,100%,.5)}.mdui-theme-layout-dark .mdui-textfield-disabled .mdui-textfield-input{color:hsla(0,0%,100%,.5);border-bottom-color:hsla(0,0%,100%,.7)}.mdui-checkbox{position:relative;display:inline-block;height:36px;padding-left:36px;line-height:36px;cursor:pointer;-ms-user-select:none;user-select:none}.mdui-checkbox input[type=checkbox]{position:absolute;width:0;height:0;overflow:hidden;opacity:0}.mdui-checkbox-icon{top:9px;display:inline-block;vertical-align:middle;background-color:transparent;border:none;border-radius:18px;transition:box-shadow .14s cubic-bezier(.4,0,.2,1)}.mdui-checkbox-icon,.mdui-checkbox-icon:after{position:absolute;left:0;width:18px;height:18px}.mdui-checkbox-icon:after{top:0;z-index:0;border:2px solid rgba(0,0,0,.54);border-radius:2px}.mdui-checkbox-icon:after,.mdui-checkbox-icon:before{box-sizing:border-box;transition:all .3s cubic-bezier(.4,0,.2,1);content:" "}.mdui-checkbox-icon:before{position:absolute;top:2px;left:0;z-index:1;width:8px;height:13px;border-right:2px solid #fff;border-bottom:2px solid #fff;transform:rotate(37deg) scale(0);transform-origin:100% 100%;opacity:0}.mdui-checkbox input[type=checkbox]:checked+.mdui-checkbox-icon:after{background-color:#448aff;border-color:#448aff}.mdui-checkbox input[type=checkbox]:checked+.mdui-checkbox-icon:before{transform:rotate(37deg) scale(1);opacity:1}.mdui-theme-layout-dark .mdui-checkbox input[type=checkbox]:checked+.mdui-checkbox-icon:after{background-color:#8ab4f8;border-color:#8ab4f8}.mdui-checkbox:active input[type=checkbox]+.mdui-checkbox-icon,.mdui-checkbox input[type=checkbox]:focus+.mdui-checkbox-icon{box-shadow:0 0 0 15px rgba(0,0,0,.1)}.mdui-checkbox:active input[type=checkbox]:not(:disabled):checked+.mdui-checkbox-icon,.mdui-checkbox:active input[type=checkbox]:not(:disabled):indeterminate+.mdui-checkbox-icon,.mdui-checkbox input[type=checkbox]:focus:not(:disabled):checked+.mdui-checkbox-icon,.mdui-checkbox input[type=checkbox]:focus:not(:disabled):indeterminate+.mdui-checkbox-icon{box-shadow:0 0 0 15px rgba(68,138,255,.16)}.mdui-theme-layout-dark .mdui-checkbox:active input[type=checkbox]:not(:disabled):checked+.mdui-checkbox-icon,.mdui-theme-layout-dark .mdui-checkbox:active input[type=checkbox]:not(:disabled):indeterminate+.mdui-checkbox-icon,.mdui-theme-layout-dark .mdui-checkbox input[type=checkbox]:focus:not(:disabled):checked+.mdui-checkbox-icon,.mdui-theme-layout-dark .mdui-checkbox input[type=checkbox]:focus:not(:disabled):indeterminate+.mdui-checkbox-icon{box-shadow:0 0 0 15px rgba(138,180,248,.16)}.mdui-theme-layout-dark .mdui-checkbox-icon:after{border-color:hsla(0,0%,100%,.7)}.mdui-theme-layout-dark .mdui-checkbox-icon:before{border-right-color:#303030!important;border-bottom-color:#303030!important}.mdui-theme-layout-dark .mdui-checkbox:active input[type=checkbox]+.mdui-checkbox-icon,.mdui-theme-layout-dark .mdui-checkbox input[type=checkbox]:focus+.mdui-checkbox-icon{box-shadow:0 0 0 15px hsla(0,0%,100%,.1)}.mdui-radio{position:relative;display:inline-block;height:36px;padding-left:36px;line-height:36px;cursor:pointer;-ms-user-select:none;user-select:none}.mdui-radio input{position:absolute;width:0;height:0;overflow:hidden;opacity:0}.mdui-radio-icon{position:absolute;top:9px;left:0;display:inline-block;box-sizing:border-box;width:18px;height:18px;vertical-align:middle;border:2px solid rgba(0,0,0,.54);border-radius:18px;transition:all .3s cubic-bezier(.4,0,.2,1),box-shadow .14s cubic-bezier(.4,0,.2,1)}.mdui-radio-icon:before{position:absolute;top:0;left:0;width:14px;height:14px;background-color:#448aff;border-radius:14px;transform:scale(0);opacity:0;transition:all .3s cubic-bezier(.4,0,.2,1);content:" "}.mdui-theme-layout-dark .mdui-radio-icon:before{background-color:#8ab4f8}.mdui-radio input[type=radio]:checked+.mdui-radio-icon{border-color:#448aff}.mdui-radio input[type=radio]:checked+.mdui-radio-icon:before{transform:scale(.68);opacity:1}.mdui-theme-layout-dark .mdui-radio input[type=radio]:checked+.mdui-radio-icon{border-color:#8ab4f8}.mdui-radio:active input[type=radio]+.mdui-radio-icon,.mdui-radio input[type=radio]:focus+.mdui-radio-icon{box-shadow:0 0 0 15px rgba(0,0,0,.1)}.mdui-radio:active input[type=radio]:checked:not(:disabled)+.mdui-radio-icon,.mdui-radio input[type=radio]:focus:checked:not(:disabled)+.mdui-radio-icon{box-shadow:0 0 0 15px rgba(68,138,255,.16)}.mdui-theme-layout-dark .mdui-radio:active input[type=radio]:checked:not(:disabled)+.mdui-radio-icon,.mdui-theme-layout-dark .mdui-radio input[type=radio]:focus:checked:not(:disabled)+.mdui-radio-icon{box-shadow:0 0 0 15px rgba(138,180,248,.16)}.mdui-theme-layout-dark .mdui-radio-icon{border-color:hsla(0,0%,100%,.7)}.mdui-theme-layout-dark .mdui-radio:active input[type=radio]+.mdui-radio-icon,.mdui-theme-layout-dark .mdui-radio input[type=radio]:focus+.mdui-radio-icon{box-shadow:0 0 0 15px hsla(0,0%,100%,.1)}.mdui-btn,.mdui-fab{position:relative;display:inline-block;box-sizing:border-box;min-width:66px;height:36px;margin:0;padding:0 16px;overflow:hidden;color:inherit;font-weight:500;font-size:14px;line-height:36px;letter-spacing:.04em;white-space:nowrap;text-align:center;text-transform:uppercase;text-decoration:none;vertical-align:middle;background:transparent;border:none;border-radius:4px;outline:none;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,1,1);-ms-user-select:none;user-select:none;touch-action:manipulation;will-change:box-shadow;zoom:1;-webkit-user-drag:none}.mdui-btn:hover,.mdui-fab:hover{background-color:rgba(0,0,0,.1)}.mdui-btn:not(.mdui-ripple):active,.mdui-fab:not(.mdui-ripple):active{background-color:rgba(0,0,0,.165)}.mdui-btn:not(.mdui-ripple)[class*=mdui-color-]:active,.mdui-fab:not(.mdui-ripple)[class*=mdui-color-]:active{opacity:.76}.mdui-btn.mdui-color-theme:not(.mdui-btn-raised){color:#1a73e8!important;background-color:transparent!important}.mdui-btn.mdui-color-theme:not(.mdui-btn-raised):hover{background-color:rgba(26,115,232,.1)!important}.mdui-btn.mdui-color-theme:not(.mdui-btn-raised):not(.mdui-ripple).mdui-btn-active,.mdui-btn.mdui-color-theme:not(.mdui-btn-raised):not(.mdui-ripple):active{background-color:rgba(26,115,232,.165)!important}.mdui-btn.mdui-color-theme:not(.mdui-btn-raised).mdui-ripple .mdui-ripple-wave{background-color:rgba(26,115,232,.3)!important}.mdui-theme-layout-dark .mdui-btn.mdui-color-theme:not(.mdui-btn-raised){color:#8ab4f8!important}.mdui-theme-layout-dark .mdui-btn.mdui-color-theme:not(.mdui-btn-raised):hover{background-color:rgba(138,180,248,.1)!important}.mdui-theme-layout-dark .mdui-btn.mdui-color-theme:not(.mdui-btn-raised):not(.mdui-ripple).mdui-btn-active,.mdui-theme-layout-dark .mdui-btn.mdui-color-theme:not(.mdui-btn-raised):not(.mdui-ripple):active{background-color:rgba(138,180,248,.165)!important}.mdui-theme-layout-dark .mdui-btn.mdui-color-theme:not(.mdui-btn-raised).mdui-ripple .mdui-ripple-wave{background-color:rgba(138,180,248,.3)!important}.mdui-btn .mdui-icon-left,.mdui-btn .mdui-icon-left:before{height:inherit;font-size:1.3em;line-height:inherit}.mdui-btn .mdui-icon-left{float:left;margin-right:.4em}input.mdui-btn[type=submit]{appearance:none}.mdui-btn-raised{box-shadow:0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12)}.mdui-btn-raised:hover{box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12)}.mdui-btn-raised:active{box-shadow:0 5px 5px -3px rgba(0,0,0,.2),0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12)}.mdui-btn[disabled],.mdui-btn[disabled]:active,.mdui-btn[disabled]:focus,.mdui-btn[disabled]:hover{color:rgba(0,0,0,.26)!important;background-color:transparent!important;cursor:default!important;opacity:1!important;box-shadow:none!important}.mdui-btn[disabled] .mdui-icon,.mdui-btn[disabled]:active .mdui-icon,.mdui-btn[disabled]:focus .mdui-icon,.mdui-btn[disabled]:hover .mdui-icon{color:rgba(0,0,0,.26)!important}.mdui-btn-raised[disabled],.mdui-btn-raised[disabled]:active,.mdui-btn-raised[disabled]:focus,.mdui-btn-raised[disabled]:hover{background-color:rgba(0,0,0,.12)!important;box-shadow:0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12)!important}.mdui-btn-icon{width:36px;min-width:36px;height:36px;margin-right:0;margin-left:0;padding:0;overflow:hidden;font-size:24px;line-height:normal;border-radius:50%}.mdui-btn-icon .mdui-icon{position:absolute;top:50%;left:50%;width:24px;line-height:24px;transform:translate(-12px,-12px)}.mdui-btn-icon.mdui-ripple{transform:translateZ(0)}.mdui-btn-dense{height:32px;font-size:13px;line-height:32px}.mdui-btn-dense.mdui-btn-icon{width:32px;min-width:32px}.mdui-theme-layout-dark .mdui-btn:hover,.mdui-theme-layout-dark .mdui-fab:hover{background-color:hsla(0,0%,100%,.1)}.mdui-theme-layout-dark .mdui-btn:not(.mdui-ripple):active,.mdui-theme-layout-dark .mdui-fab:not(.mdui-ripple):active{background-color:hsla(0,0%,100%,.165)}.mdui-theme-layout-dark .mdui-btn:not(.mdui-ripple)[class*=mdui-color-]:active,.mdui-theme-layout-dark .mdui-fab:not(.mdui-ripple)[class*=mdui-color-]:active{opacity:.76}.mdui-theme-layout-dark .mdui-btn[disabled],.mdui-theme-layout-dark .mdui-btn[disabled]:active,.mdui-theme-layout-dark .mdui-btn[disabled]:focus,.mdui-theme-layout-dark .mdui-btn[disabled]:hover{color:hsla(0,0%,100%,.3)!important;background-color:transparent!important}.mdui-theme-layout-dark .mdui-btn[disabled] .mdui-icon,.mdui-theme-layout-dark .mdui-btn[disabled]:active .mdui-icon,.mdui-theme-layout-dark .mdui-btn[disabled]:focus .mdui-icon,.mdui-theme-layout-dark .mdui-btn[disabled]:hover .mdui-icon{color:hsla(0,0%,100%,.3)!important}.mdui-theme-layout-dark .mdui-btn-raised[disabled],.mdui-theme-layout-dark .mdui-btn-raised[disabled]:active,.mdui-theme-layout-dark .mdui-btn-raised[disabled]:focus,.mdui-theme-layout-dark .mdui-btn-raised[disabled]:hover,.mdui-theme-layout-dark .mdui-fab[disabled],.mdui-theme-layout-dark .mdui-fab[disabled]:active,.mdui-theme-layout-dark .mdui-fab[disabled]:focus,.mdui-theme-layout-dark .mdui-fab[disabled]:hover{background-color:hsla(0,0%,100%,.12)!important}.mdui-fab{width:56px;min-width:56px;height:56px;margin:auto;padding:0!important;overflow:hidden;font-size:24px;line-height:normal!important;border-radius:50%;box-shadow:0 3px 5px -1px rgba(0,0,0,.2),0 6px 10px 0 rgba(0,0,0,.14),0 1px 18px 0 rgba(0,0,0,.12)}.mdui-fab:hover{box-shadow:0 5px 5px -3px rgba(0,0,0,.2),0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12)}.mdui-fab:active{box-shadow:0 7px 8px -4px rgba(0,0,0,.2),0 12px 17px 2px rgba(0,0,0,.14),0 5px 22px 4px rgba(0,0,0,.12)}.mdui-fab .mdui-icon{position:absolute;top:0;left:0;width:24px;margin-top:16px;margin-left:16px;line-height:24px}.mdui-fab-fixed{position:fixed!important;right:16px;bottom:16px}@media (min-width:1024px){.mdui-fab-fixed{right:24px;bottom:24px}}.mdui-toolbar{display:flex;align-items:center;box-sizing:border-box;width:100%}.mdui-toolbar>*{margin:0 16px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.mdui-toolbar[class*=mdui-color-]:not(.mdui-color-transparent) .mdui-btn:hover{background-color:hsla(0,0%,100%,.1)}.mdui-toolbar[class*=mdui-color-]:not(.mdui-color-transparent) .mdui-btn:active{background-color:hsla(0,0%,100%,.165)}.mdui-toolbar>a{color:inherit;text-decoration:none;-ms-user-select:none;user-select:none}.mdui-toolbar>.mdui-btn-icon{width:48px;min-width:48px;height:48px}@media (orientation:landscape) and (max-width:959.9px){.mdui-toolbar>.mdui-btn-icon{width:40px;min-width:40px;height:40px}}.mdui-toolbar>.mdui-btn-icon .mdui-icon{height:24px;line-height:24px}.mdui-toolbar .mdui-icon{color:inherit}.mdui-toolbar-spacer{flex-grow:1;margin:0}.mdui-toolbar{height:56px;line-height:56px}.mdui-toolbar>.mdui-btn{margin:0 4px}.mdui-toolbar>.mdui-btn+.mdui-btn{margin-left:0}@media (min-width:600px){.mdui-appbar .mdui-toolbar{height:64px;line-height:64px}.mdui-appbar .mdui-toolbar>.mdui-btn{margin:0 8px}.mdui-appbar .mdui-toolbar>.mdui-btn+.mdui-btn{margin-left:0}}@media (orientation:landscape) and (max-width:959.9px){.mdui-appbar .mdui-toolbar{height:48px;line-height:48px}.mdui-appbar .mdui-toolbar>.mdui-btn{margin:0 4px}.mdui-appbar .mdui-toolbar>.mdui-btn+.mdui-btn{margin-left:0}}.mdui-appbar{z-index:1000;box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12)}.mdui-appbar-fixed{position:fixed;top:0;right:0;left:0;transition-timing-function:cubic-bezier(0,0,.2,1);transition-duration:.3s;transition-property:left,right;will-change:left,right}.mdui-appbar-with-toolbar{padding-top:56px}@media (min-width:600px){.mdui-appbar-with-toolbar{padding-top:64px}}@media (orientation:landscape) and (max-width:959.9px){.mdui-appbar-with-toolbar{padding-top:48px}}.mdui-appbar-with-tab{padding-top:48px}.mdui-appbar-with-toolbar.mdui-appbar-with-tab{padding-top:104px}@media (min-width:600px){.mdui-appbar-with-toolbar.mdui-appbar-with-tab{padding-top:112px}}@media (orientation:landscape) and (max-width:959.9px){.mdui-appbar-with-toolbar.mdui-appbar-with-tab{padding-top:96px}}.mdui-theme-layout-dark .mdui-appbar>[class*=mdui-color-]:not(.mdui-color-transparent){color:#fff!important;background-color:#212121!important}.mdui-appbar{box-shadow:0 1px 6px 0 rgba(32,33,36,.28)}.mdui-card{position:relative;box-sizing:border-box;border:1px solid rgba(0,0,0,.12);border-radius:8px}.mdui-card-shadow{border:none;box-shadow:0 1px 2px 0 rgba(60,64,67,.3),0 1px 3px 1px rgba(60,64,67,.15)}.mdui-theme-layout-dark .mdui-card{color:#fff;border-color:hsla(0,0%,100%,.12)}.mdui-theme-layout-dark .mdui-card-shadow{border:1px solid hsla(0,0%,100%,.12);box-shadow:none}.mdui-tab{position:relative;margin:0 auto;padding:0;overflow-x:auto;overflow-y:hidden;white-space:nowrap;-webkit-overflow-scrolling:touch}.mdui-tab,.mdui-tab a{display:flex;min-height:48px;max-height:72px}.mdui-tab a{flex:1;flex-direction:column;align-items:center;justify-content:center;box-sizing:border-box;min-width:72px;padding:12px;overflow:hidden;color:inherit;font-size:14px;text-align:center;text-transform:uppercase;text-decoration:none;text-overflow:ellipsis;outline:none;cursor:pointer;opacity:.7;-ms-user-select:none;user-select:none}@media (min-width:600px){.mdui-tab a{flex:none;min-width:99px;max-width:264px;padding:12px 24px}}@media (min-width:1024px){.mdui-tab a{min-width:112px}}@media (min-width:1440px){.mdui-tab a{min-width:136px}}@media (min-width:1920px){.mdui-tab a{min-width:160px}}.mdui-tab .mdui-tab-active{color:#1a73e8;opacity:1}.mdui-theme-layout-dark .mdui-tab .mdui-tab-active{color:#fff}@media (min-width:600px){.mdui-tab-centered:after,.mdui-tab-centered:before{flex-grow:1;content:" "}.mdui-tab-centered a{flex:none}}.mdui-tab-indicator{position:absolute;bottom:0;height:2px;background-color:#1a73e8;transition:all .35s cubic-bezier(.4,0,.2,1);will-change:left,width}.mdui-theme-layout-dark .mdui-tab-indicator{background-color:#fff}.mdui-list{margin:0;padding:8px 0;list-style:none;background-color:transparent}.mdui-list>.mdui-divider{margin-top:8px;margin-bottom:8px}.mdui-list a{color:inherit;text-decoration:none}.mdui-list-item{display:flex;align-items:center;box-sizing:border-box;min-height:48px;padding:0 16px;text-decoration:none;cursor:pointer;transition:background-color .3s cubic-bezier(.4,0,.2,1)}.mdui-list-item:hover{background-color:rgba(0,0,0,.04)}.mdui-list-item:after{height:48px;visibility:hidden;content:" "}.mdui-list-item-icon{width:24px;min-width:24px;height:24px;color:rgba(0,0,0,.54)}.mdui-list-item-avatar{min-width:40px;max-width:40px;height:40px;margin-top:8px;margin-bottom:8px;color:#fff;line-height:40px;text-align:center;background-color:#bdbdbd;border-radius:50%}.mdui-list-item-avatar img{width:100%;height:100%;border-radius:50%}.mdui-list-item-content{flex-grow:1;padding-top:14px;padding-bottom:14px;font-weight:400;font-size:16px;line-height:20px}.mdui-list-item-text{font-size:14px;opacity:.54}.mdui-list-item-title~.mdui-list-item-text{margin-top:4px}.mdui-list-item-active{font-weight:700;background-color:rgba(0,0,0,.04)}.mdui-list-item-active .mdui-list-item-content{font-weight:700}.mdui-list-item-active .mdui-list-item-text{font-weight:400}.mdui-list-item-one-line{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical;-webkit-line-clamp:1;height:20px}.mdui-list-item-icon~.mdui-list-item-content{margin-left:32px}.mdui-list-item-avatar~.mdui-list-item-content,.mdui-list-item-content~.mdui-checkbox{margin-left:16px}.mdui-list-item-content~.mdui-checkbox{padding-left:24px}.mdui-theme-layout-dark .mdui-list-item{color:#fff}.mdui-theme-layout-dark .mdui-list-item:hover{background-color:hsla(0,0%,100%,.04)}.mdui-theme-layout-dark .mdui-list-item-icon{color:#fff}.mdui-theme-layout-dark .mdui-list-item-text{opacity:.7}.mdui-theme-layout-dark .mdui-list-item-active{background-color:hsla(0,0%,100%,.04)}body.mdui-loaded{transition:padding .3s cubic-bezier(0,0,.2,1)}body.mdui-loaded .mdui-drawer{transition:all .3s cubic-bezier(0,0,.2,1)}.mdui-drawer{position:fixed;top:0;bottom:0;left:0;z-index:5000;box-sizing:border-box;width:calc(100% - 56px);max-width:280px;margin:0;overflow-x:hidden;overflow-y:auto;white-space:nowrap;will-change:transform;-webkit-overflow-scrolling:touch}@media (max-width:1023.9px){.mdui-drawer:not(.mdui-drawer-open){box-shadow:none!important}}@media (min-width:600px){.mdui-drawer{width:calc(100% - 64px);max-width:320px}}@media (min-width:1024px){.mdui-drawer{z-index:auto;width:240px;max-width:none}.mdui-drawer.mdui-drawer-close{box-shadow:none!important}}@media (max-width:1023.9px){.mdui-drawer{background-color:#fff;transform:translateX(-330px);box-shadow:0 8px 10px -5px rgba(0,0,0,.2),0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12)}}@media (max-width:599.9px){.mdui-drawer{transform:translateX(-290px)}}.mdui-drawer-close{transform:translateX(-290px)}@media (min-width:600px){.mdui-drawer-close{transform:translateX(-330px)}}@media (min-width:1024px){.mdui-drawer-close{transform:translateX(-250px)}}.mdui-drawer-open{transform:translateX(0)!important}@media (min-width:1024px){.mdui-drawer-body-left{padding-left:240px}.mdui-appbar-with-toolbar .mdui-drawer{top:64px}.mdui-appbar-with-tab .mdui-drawer{top:48px}.mdui-appbar-with-toolbar.mdui-appbar-with-tab .mdui-drawer{top:112px}}.mdui-drawer[class*=mdui-color-]:not(.mdui-color-transparent){box-shadow:0 8px 10px -5px rgba(0,0,0,.2),0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12)}@media (max-width:1023.9px){.mdui-theme-layout-dark .mdui-drawer{background-color:#424242}}.mdui-dialog{position:fixed;right:0;left:0;z-index:6000;display:none;box-sizing:border-box;width:92%;min-width:180px;max-width:728px;max-height:90%;margin:auto;overflow:hidden;color:#000;background-color:#fff;border-radius:8px;transform:scale(.95);opacity:0;transition-duration:.3s;transition-property:transform,opacity,visibility;will-change:top,opacity,transform;box-shadow:0 11px 15px -7px rgba(0,0,0,.2),0 24px 38px 3px rgba(0,0,0,.14),0 9px 46px 8px rgba(0,0,0,.12)}@media (min-width:600px){.mdui-dialog{width:85%;max-height:85%}}@media (min-width:1024px){.mdui-dialog{width:80%;max-height:80%}}.mdui-dialog-open{transform:scale(1);opacity:1}.mdui-dialog-title{box-sizing:border-box;font-weight:500;font-size:20px;line-height:24px;text-align:left}.mdui-dialog>.mdui-dialog-title{padding:24px 24px 20px}.mdui-dialog-content{box-sizing:border-box;padding:24px;overflow-y:auto;color:rgba(0,0,0,.7);font-size:15px;line-height:1.5;-webkit-overflow-scrolling:touch}.mdui-dialog-title+.mdui-dialog-content{padding-top:0}.mdui-dialog-actions{box-sizing:border-box;padding:8px;text-align:right}.mdui-dialog-actions .mdui-btn{min-width:64px;margin-left:8px;color:#1a73e8}.mdui-dialog-actions .mdui-btn:first-child{margin-left:0}.mdui-theme-layout-dark .mdui-dialog{color:#fff;background-color:#424242}.mdui-theme-layout-dark .mdui-dialog-content{color:hsla(0,0%,100%,.7)}.mdui-theme-layout-dark .mdui-dialog-actions .mdui-btn{color:#8ab4f8}.mdui-dialog-alert,.mdui-dialog-confirm,.mdui-dialog-prompt{max-width:448px}.mdui-dialog-prompt .mdui-dialog-content{padding-bottom:16px}.mdui-dialog-prompt .mdui-textfield{padding-top:0}.mdui-tooltip{position:absolute;z-index:9000;display:inline-block;box-sizing:border-box;max-width:180px;min-height:32px;padding:8px 16px;color:#fff;font-weight:500;font-size:14px;line-height:22px;text-align:left;background-color:rgba(97,97,97,.9);border-radius:2px;transform:scale(0);opacity:0;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;transition-property:opacity,transform;will-change:opacity,transform}@media (min-width:1024px){.mdui-tooltip{max-width:200px;min-height:24px;padding:4px 8px;font-size:12px;line-height:18px}}.mdui-tooltip-open{transform:scale(1);opacity:1}.mdui-snackbar{position:fixed;z-index:7000;display:flex;align-items:center;justify-content:space-between;box-sizing:border-box;width:100%;min-height:48px;padding:0 24px;color:#fff;font-size:14px;line-height:20px;background-color:#323232;will-change:transform}@media (min-width:600px){.mdui-snackbar{width:auto;min-width:288px;max-width:568px;border-radius:2px}}.mdui-snackbar-bottom,.mdui-snackbar-left-bottom{transition:transform .3s cubic-bezier(.4,0,.2,1);bottom:0}.mdui-snackbar-bottom{left:50%}@media (min-width:600px){.mdui-snackbar-left-bottom{bottom:24px;left:24px}}.mdui-snackbar-text{position:relative;max-width:100%;padding:14px 0;overflow:hidden;text-overflow:ellipsis}.mdui-theme-layout-dark .mdui-snackbar{background-color:#5d5d5d}.mdui-chip{display:inline-block;box-sizing:border-box;height:32px;margin:2px 0;color:inherit;white-space:nowrap;border-radius:16px;cursor:pointer;-ms-user-select:none;user-select:none;transition:box-shadow .25s cubic-bezier(.4,0,.2,1);will-change:box-shadow}.mdui-chip:focus,.mdui-chip:hover{box-shadow:0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12)}.mdui-chip:active{background-color:#d6d6d6}.mdui-chip-icon{position:relative;display:inline-block;overflow:hidden;color:#fff;font-size:18px;line-height:32px;text-align:center;vertical-align:middle;background-color:#989898;border-radius:50%}.mdui-chip-icon .mdui-icon{position:absolute;top:4px;left:4px;color:#fff}.mdui-chip-title{height:32px;font-size:14px;line-height:32px}.mdui-chip-delete,.mdui-chip-title{display:inline-block;vertical-align:middle}.mdui-chip-delete{overflow:hidden;text-align:center;text-decoration:none;border-radius:50%;cursor:pointer;opacity:.54;transition:opacity .25s cubic-bezier(.4,0,.2,1);will-change:opacity}.mdui-chip-delete:focus,.mdui-chip-delete:hover{opacity:.87}.mdui-theme-layout-dark .mdui-chip{background-color:#484848}.mdui-theme-layout-dark .mdui-chip:active{background-color:#5d5d5d}.mdui-chip{background-color:transparent;border:1px solid rgba(0,0,0,.12);box-shadow:none!important}.mdui-chip:hover{background-color:rgba(0,0,0,.04)}.mdui-chip-icon{float:left;width:24px;height:24px;margin:3px}.mdui-chip-title{padding-right:12px;padding-left:8px}.mdui-chip-delete{float:right;width:18px;height:18px;margin:6px 6px 6px -4px}.mdui-chip-delete i{font-size:18px}.mdui-theme-layout-dark .mdui-chip{border-color:hsla(0,0%,100%,.12)}.mdui-theme-layout-dark .mdui-chip:hover{background-color:hsla(0,0%,100%,.08)}.mdui-spinner{position:relative;display:inline-block;width:28px;height:28px;animation:mdui-spinner 1568ms linear infinite}@keyframes mdui-spinner{to{transform:rotate(1turn)}}.mdui-spinner-layer{position:absolute;width:100%;height:100%;border-color:#1a73e8;opacity:0;opacity:1;animation:mdui-spinner-layer-fill-unfill-rotate 5332ms cubic-bezier(.4,0,.2,1) infinite both}.mdui-theme-layout-dark .mdui-spinner-layer{border-color:#8ab4f8}@keyframes mdui-spinner-layer-fill-unfill-rotate{12.5%{transform:rotate(135deg)}25%{transform:rotate(270deg)}37.5%{transform:rotate(405deg)}50%{transform:rotate(540deg)}62.5%{transform:rotate(675deg)}75%{transform:rotate(810deg)}87.5%{transform:rotate(945deg)}to{transform:rotate(3turn)}}.mdui-spinner-gap-patch{position:absolute;top:0;left:45%;width:10%;height:100%;overflow:hidden;border-color:inherit}.mdui-spinner-gap-patch .mdui-spinner-circle{left:-450%;box-sizing:border-box;width:1000%}.mdui-spinner-circle-clipper{position:relative;display:inline-block;width:50%;height:100%;overflow:hidden;border-color:inherit}.mdui-spinner-circle-clipper .mdui-spinner-circle{position:absolute;top:0;right:0;bottom:0;box-sizing:border-box;width:200%;height:100%;border:3px solid;border-color:inherit;border-bottom-color:transparent!important;border-radius:50%;animation:none}.mdui-spinner-circle-clipper.mdui-spinner-left{float:left}.mdui-spinner-circle-clipper.mdui-spinner-left .mdui-spinner-circle{left:0;border-right-color:transparent!important;transform:rotate(129deg);animation:mdui-spinner-left-spin 1333ms cubic-bezier(.4,0,.2,1) infinite both}.mdui-spinner-circle-clipper.mdui-spinner-right{float:right}.mdui-spinner-circle-clipper.mdui-spinner-right .mdui-spinner-circle{left:-100%;border-left-color:transparent!important;transform:rotate(-129deg);animation:mdui-spinner-right-spin 1333ms cubic-bezier(.4,0,.2,1) infinite both}@keyframes mdui-spinner-left-spin{0%{transform:rotate(130deg)}50%{transform:rotate(-5deg)}to{transform:rotate(130deg)}}@keyframes mdui-spinner-right-spin{0%{transform:rotate(-130deg)}50%{transform:rotate(5deg)}to{transform:rotate(-130deg)}}.mdui-menu{position:fixed;z-index:99999;display:block;box-sizing:border-box;width:168px;margin:0;padding:8px 0;overflow-y:auto;color:rgba(0,0,0,.87);font-size:16px;list-style:none;background-color:#fff;border-radius:8px;transform:scale(0);visibility:hidden;opacity:0;transition-timing-function:cubic-bezier(0,0,.2,1);transition-duration:.3s;transition-property:transform,opacity,visibility;will-change:transform,opacity,visibility;-webkit-overflow-scrolling:touch;box-shadow:0 5px 5px -3px rgba(0,0,0,.2),0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12)}.mdui-menu-open{opacity:1}.mdui-menu-closing,.mdui-menu-open{transform:scale(1);visibility:visible}.mdui-menu-closing{opacity:0}.mdui-menu-item{position:relative}.mdui-menu-item>a{position:relative;display:block;height:48px;padding:0 16px;color:inherit;line-height:48px;text-decoration:none;-ms-user-select:none;user-select:none;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.mdui-menu-item>a:hover{background-color:#eee}.mdui-menu-item-icon{display:inline-block;box-sizing:border-box;width:40px;padding-right:16px;color:rgba(0,0,0,.54)}.mdui-theme-layout-dark .mdui-menu{color:#fff;background-color:#424242}.mdui-theme-layout-dark .mdui-menu-item>a:hover{background-color:#616161}.mdui-theme-layout-dark .mdui-menu-item[disabled]>a{color:hsla(0,0%,100%,.5)!important}.mdui-theme-layout-dark .mdui-menu-item-icon{color:#fff}.mdui_editor-toolbar{display:flex;align-items:center;padding:12px 16px}.mdui_editor-toolbar:after{display:table;clear:both;content:""}.mdui_editor-toolbar-menu{width:28px;min-width:28px;height:28px;padding:0;color:#212121;line-height:28px;border-radius:3px;box-shadow:inset 0 0 0 1px transparent;opacity:.6}.mdui_editor-toolbar-menu i{font-size:21px}.mdui_editor-toolbar-menu:hover{background-color:transparent;opacity:1}.mdui_editor-toolbar-menu+.mdui_editor-toolbar-menu{margin-left:2px}.mdui_editor-toolbar-menu-active{background-color:rgba(0,0,0,.12)!important;opacity:1}.mdui_editor-toolbar-menu-image+input[type=file]{display:none}.mdui_editor-content{box-sizing:border-box;height:calc(100% - 60px);padding:16px;overflow-y:auto;color:rgba(0,0,0,.87);font-size:14px;line-height:22px;white-space:pre-wrap;word-wrap:break-word;outline:none;-webkit-overflow-scrolling:touch}.mdui_editor-content-empty:before{position:absolute;color:rgba(0,0,0,.42);cursor:text;content:attr(placeholder)}.mdui_editor-upload-progress-dialog{max-width:448px}.mdui-theme-layout-dark img{filter:brightness(.8)}::-webkit-input-placeholder{color:rgba(0,0,0,.42)}.mdui-theme-layout-dark ::-webkit-input-placeholder{color:hsla(0,0%,100%,.42)}:-moz-placeholder{color:rgba(0,0,0,.42)}.mdui-theme-layout-dark :-moz-placeholder{color:hsla(0,0%,100%,.42)}::-moz-placeholder{color:rgba(0,0,0,.42)}.mdui-theme-layout-dark ::-moz-placeholder{color:hsla(0,0%,100%,.42)}:-ms-input-placeholder{color:rgba(0,0,0,.42)}.mdui-theme-layout-dark :-ms-input-placeholder{color:hsla(0,0%,100%,.42)}.flex-grow{flex-grow:1}.mdui-typo pre{background-color:#f6f6f6;border:none;border-radius:4px}.mdui-typo p{min-height:.3em}.mg-app{box-sizing:border-box;min-height:100vh}.mdui-fab-extended{width:auto;min-width:auto;height:48px;padding-left:48px!important;border-radius:24px}.mdui-fab-extended .mdui-icon{margin-top:12px;margin-left:12px}.mdui-fab-extended span{float:left;margin-right:20px;font-size:14px}@media (max-width:599.9px){.mdui-fab-extended span{display:none}}.mc-loading-overlay{position:fixed;top:0;left:0;z-index:9999999;display:flex;align-items:center;justify-content:center;width:100%;height:100%;background:hsla(0,0%,100%,.65);opacity:0;transition:opacity .2s ease;will-change:opacity}.mc-loading-overlay-show{opacity:1}.mdui-container{width:100%;max-width:1100px;padding:8px 0 62px}@media (min-width:600px){.mdui-container{width:96%;padding-top:16px}}@media (min-width:1024px){.mdui-container{padding:24px 8px 62px}}.mdui-theme-layout-dark .mdui-btn-raised{background-color:#424242}.mdui-btn-outlined{line-height:34px;border:1px solid rgba(0,0,0,.12)}.mdui-btn-outlined.mdui-btn-dense{line-height:30px}.mdui-btn-outlined.mdui-color-theme{border-color:#1a73e8}.mdui-theme-layout-dark .mdui-btn-outlined{border-color:hsla(0,0%,100%,.12)}#page-index{padding-right:16px;padding-left:16px;color:#3c5675;line-height:1.6}@media screen and (prefers-color-scheme:dark){#page-index{color:#bfbfbf}#page-index a{color:#8ab4f8!important}#page-index a:before{background-color:#8ab4f8}}#page-index .banner{padding-top:96px;padding-bottom:64px;text-align:center}#page-index .banner h1{margin:0 0 24px;font-weight:400;font-size:32px}#page-index .banner h1 strong{color:#1a73e8;font-weight:400}@media screen and (prefers-color-scheme:dark){#page-index .banner h1 strong{color:#8ab4f8}}#page-index .banner .meta{margin:0 auto 48px;font-size:20px;opacity:.76}#page-index .banner .actions a{height:46px;margin-right:8px;margin-left:8px;padding:0 24px;color:#1a73e8;font-size:16px;line-height:46px;border:1px solid #1a73e8}#page-index .banner .actions a:hover{background-color:rgba(26,115,132,.06)}#page-index .banner .actions a:active{background-color:rgba(26,115,132,.12)}@media screen and (prefers-color-scheme:dark){#page-index .banner .actions a{border-color:#8ab4f8}}#page-index .banner .more-meta{padding-top:48px}#page-index .banner .more-meta .current{opacity:.76}#page-index .banner .more-meta span+span{padding-left:32px}@media screen and (max-width:600px){#page-index .banner{padding-top:40px;padding-bottom:32px}#page-index .banner h1{font-size:22px}#page-index .banner .meta{margin-bottom:38px;font-size:16px}#page-index .banner .more-meta{padding-top:38px}#page-index .banner .more-meta span:first-child{display:block}}#page-index .feature{padding:48px 0 56px}#page-index .feature .icon{display:block;width:56px;height:56px;margin:0 auto 20px}#page-index .feature .icon path{fill:#1a73e8}@media screen and (prefers-color-scheme:dark){#page-index .feature .icon path{fill:#8ab4f8}}#page-index .feature h2{margin:0;padding-bottom:24px;color:#1a73e8;font-weight:400;font-size:28px;text-align:center}@media screen and (prefers-color-scheme:dark){#page-index .feature h2{color:#8ab4f8}}#page-index .feature pre{padding:16px 20px}@media screen and (max-width:600px){#page-index .feature{padding:32px 0 40px}#page-index .feature .icon{width:40px;height:40px;margin-bottom:16px}#page-index .feature h2{padding-bottom:16px;font-size:20px}#page-index .feature pre{padding:12px 16px}}#page-index .advantage h2{padding-bottom:40px}#page-index .advantage .item{float:left;box-sizing:border-box;width:50%}#page-index .advantage .item:nth-child(odd){padding-right:40px}#page-index .advantage .item .svg{float:left;width:24px;height:24px}#page-index .advantage .item .svg path{fill:#1a73e8}@media screen and (prefers-color-scheme:dark){#page-index .advantage .item .svg path{fill:#8ab4f8}}#page-index .advantage .item label{display:block;height:24px;padding-left:48px;font-weight:700;line-height:24px}#page-index .advantage .item span{display:block;height:80px;padding-top:16px;padding-left:48px;line-height:24px}@media screen and (max-width:1300px){#page-index .advantage .item span{height:96px}}@media screen and (max-width:776px){#page-index .advantage .item{width:100%}#page-index .advantage .item span{height:auto;padding-top:10px;padding-bottom:32px}}#page-index .case h2{padding-bottom:40px}#page-index .case .item{float:left;box-sizing:border-box;width:50%;padding:16px;color:inherit!important;text-decoration:none;transition:all .2s cubic-bezier(.4,0,.2,1)}#page-index .case .item:hover{background-color:rgba(26,115,132,.06)}#page-index .case .item .logo{float:left;width:32px;height:32px;border-radius:50%}#page-index .case .item label{display:block;height:32px;padding-left:48px;font-weight:700;line-height:32px;cursor:pointer}#page-index .case .item span{display:block;padding-top:8px;padding-left:48px}@media screen and (max-width:720px){#page-index .case .item{width:calc(100% + 32px);margin-right:-16px;margin-left:-16px}}.hljs{display:block;overflow-x:auto;padding:.5em;background:#fff;color:#000}.hljs-comment,.hljs-quote,.hljs-variable{color:green}.hljs-built_in,.hljs-keyword,.hljs-name,.hljs-selector-tag,.hljs-tag{color:#00f}.hljs-addition,.hljs-attribute,.hljs-literal,.hljs-section,.hljs-string,.hljs-template-tag,.hljs-template-variable,.hljs-title,.hljs-type{color:#a31515}.hljs-deletion,.hljs-meta,.hljs-selector-attr,.hljs-selector-pseudo{color:#2b91af}.hljs-doctag{color:grey}.hljs-attr{color:red}.hljs-bullet,.hljs-link,.hljs-symbol{color:#00b0e8}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.mdui-theme-layout-dark .hljs{display:block;overflow-x:auto;padding:.5em;background:#303030;color:#dcdcdc}.mdui-theme-layout-dark .hljs-keyword,.mdui-theme-layout-dark .hljs-literal,.mdui-theme-layout-dark .hljs-name,.mdui-theme-layout-dark .hljs-symbol{color:#569cd6}.mdui-theme-layout-dark .hljs-link{color:#569cd6;text-decoration:underline}.mdui-theme-layout-dark .hljs-built_in,.mdui-theme-layout-dark .hljs-type{color:#4ec9b0}.mdui-theme-layout-dark .hljs-class,.mdui-theme-layout-dark .hljs-number{color:#b8d7a3}.mdui-theme-layout-dark .hljs-meta-string,.mdui-theme-layout-dark .hljs-string{color:#d69d85}.mdui-theme-layout-dark .hljs-regexp,.mdui-theme-layout-dark .hljs-template-tag{color:#9a5334}.mdui-theme-layout-dark .hljs-formula,.mdui-theme-layout-dark .hljs-function,.mdui-theme-layout-dark .hljs-params,.mdui-theme-layout-dark .hljs-subst,.mdui-theme-layout-dark .hljs-title{color:#dcdcdc}.mdui-theme-layout-dark .hljs-comment,.mdui-theme-layout-dark .hljs-quote{color:#57a64a;font-style:italic}.mdui-theme-layout-dark .hljs-doctag{color:#608b4e}.mdui-theme-layout-dark .hljs-meta,.mdui-theme-layout-dark .hljs-meta-keyword,.mdui-theme-layout-dark .hljs-tag{color:#9b9b9b}.mdui-theme-layout-dark .hljs-template-variable,.mdui-theme-layout-dark .hljs-variable{color:#bd63c5}.mdui-theme-layout-dark .hljs-attr,.mdui-theme-layout-dark .hljs-attribute,.mdui-theme-layout-dark .hljs-builtin-name{color:#9cdcfe}.mdui-theme-layout-dark .hljs-section{color:gold}.mdui-theme-layout-dark .hljs-emphasis{font-style:italic}.mdui-theme-layout-dark .hljs-strong{font-weight:700}.mdui-theme-layout-dark .hljs-bullet,.mdui-theme-layout-dark .hljs-selector-attr,.mdui-theme-layout-dark .hljs-selector-class,.mdui-theme-layout-dark .hljs-selector-id,.mdui-theme-layout-dark .hljs-selector-pseudo,.mdui-theme-layout-dark .hljs-selector-tag{color:#d7ba7d}.mdui-theme-layout-dark .hljs-addition{background-color:#144212;display:inline-block;width:100%}.mdui-theme-layout-dark .hljs-deletion{background-color:#600;display:inline-block;width:100%}.mc-loading{display:block;padding:17px 0}.mc-loading .mdui-spinner{display:block;margin:0 auto}.mc-loaded{margin:24px 0 -38px!important;font-size:13px;letter-spacing:.5px;text-align:center;opacity:.54}.mc-empty{box-sizing:border-box;width:100%;margin-top:80px;padding:108px 16px 64px;text-align:center;background-repeat:no-repeat;background-position:top}.mc-empty .title{margin-bottom:20px;color:rgba(0,0,0,.54);font-size:18px}.mdui-theme-layout-dark .mc-empty .title{color:hsla(0,0%,100%,.87)}.mc-empty .description{margin-bottom:20px;color:rgba(0,0,0,.54);font-size:15px;line-height:24px}.mdui-theme-layout-dark .mc-empty .description{color:hsla(0,0%,100%,.64)}.mc-editor{position:fixed;right:74px;bottom:0;z-index:5000;display:flex;flex-direction:column;width:450px;height:608px;overflow:hidden;border-radius:8px 8px 0 0;box-shadow:0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12),0 5px 5px -3px rgba(0,0,0,.2)}.mc-editor .header{display:flex;align-items:center;height:40px;background-color:#404040;-ms-user-select:none;user-select:none}.mdui-theme-layout-dark .mc-editor .header{background-color:#303030}.mc-editor .header-title{display:flex;flex:1;align-items:center;height:100%;padding-left:16px;color:#fff;font-size:14px;cursor:pointer}.mc-editor .header-actions{padding-right:8px;padding-left:8px}.mc-editor .header-actions i{padding:3px;color:#fff;font-size:18px;font-style:normal;cursor:pointer;opacity:.6}.mc-editor .header-actions i:hover{background-color:#737373;opacity:1}.mc-editor.maximize:not(.minimize){right:calc(50% - 368px);bottom:4vh;width:100%;max-width:736px;height:92vh}@media (max-width:736px){.mc-editor.maximize:not(.minimize){right:0;bottom:0;height:100vh;border-radius:0}}.mc-editor.minimize{width:260px;height:40px}.mc-editor .body{flex:1;padding:0 16px;overflow:hidden;background-color:#fff}.mdui-theme-layout-dark .mc-editor .body{background-color:#424242}.mc-editor .body .submit{min-width:76px;margin-right:10px}.mc-editor .editor-title{position:relative;box-sizing:border-box;width:100%;height:48px;font-size:16px;line-height:34px;background-color:transparent;border:none;border-bottom:1px solid rgba(0,0,0,.08);outline:none}.mdui-theme-layout-dark .mc-editor .editor-title{border-color:hsla(0,0%,100%,.12)}.mc-editor .editor-topics{position:relative;display:flex;align-items:center;width:100%;height:48px;border-bottom:1px solid rgba(0,0,0,.08)}.mdui-theme-layout-dark .mc-editor .editor-topics{border-color:hsla(0,0%,100%,.12)}.mc-editor .editor-topics .chip-wrapper,.mc-editor .editor-topics .placeholder{display:flex;flex:1;align-items:center;height:100%;-ms-user-select:none;user-select:none}.mc-editor .editor-topics .placeholder{color:rgba(0,0,0,.42);cursor:pointer}.mdui-theme-layout-dark .mc-editor .editor-topics .placeholder{color:hsla(0,0%,100%,.42)}.mc-editor .editor-toolbar{padding:12px 0;box-shadow:inset 0 1px 0 0 rgba(100,121,143,.122)}.mdui-theme-layout-dark .mc-editor .editor-toolbar .mdui_editor-toolbar-menu-active{background-color:#565656!important}.mdui-theme-layout-dark .mc-editor .editor-toolbar i{color:#fff}.mc-editor .editor-content{height:calc(100% - 60px);padding:10px 0}.mdui-theme-layout-dark .mc-editor .editor-content:before{color:hsla(0,0%,100%,.42)}.mc-editor.with-title .editor-content,.mc-editor.with-topics .editor-content{height:calc(100% - 108px)}.mc-editor.with-title.with-topics .editor-content{height:calc(100% - 156px)}@media (max-width:599.9px){.mc-editor{right:0;bottom:0;width:100%;height:100vh;border-radius:0}.mc-editor.minimize{width:100%;height:56px}.mc-editor .header{height:56px}.mc-editor .header-title{font-size:16px}.mc-editor .header-actions i{padding:8px;font-size:20px;border-radius:3px}.mc-editor .header-actions i:nth-child(2),.mc-editor .icon-maximize,.mc-editor .mdui_editor-toolbar-menu-code,.mc-editor .mdui_editor-toolbar-menu-italic,.mc-editor .mdui_editor-toolbar-menu-ol,.mc-editor .mdui_editor-toolbar-menu-ul{display:none}.mc-editor .mdui_editor-toolbar-menu{width:36px;min-width:36px;height:36px;line-height:36px}.mc-editor .mdui_editor-toolbar-menu i{font-size:22px}}.mc-editor .mdui-chip{margin-right:8px}.mc-list-item{position:relative;display:block;padding:16px 24px 16px 64px;text-decoration:none;border-bottom:1px solid rgba(0,0,0,.08);cursor:pointer;transition:background-color .18s cubic-bezier(.4,0,.2,1)}.mdui-theme-layout-dark .mc-list-item{border-bottom-color:hsla(0,0%,100%,.12)}.mc-list-item:last-child{border-bottom:none}.mc-list-item:hover{background-color:rgba(0,0,0,.04)}.mdui-theme-layout-dark .mc-list-item:hover{background-color:hsla(0,0%,100%,.04)}.mc-list-item:active{background-color:#eee}.mdui-theme-layout-dark .mc-list-item:active{background-color:#484848}.mc-list-item.last-visit:before{position:absolute;top:0;left:0;width:2px;height:100%;background-color:#1a73e8;content:" "}.mdui-theme-layout-dark .mc-list-item.last-visit:before{background-color:hsla(0,0%,100%,.7)}.mc-list-item .mc-user-popover{position:absolute;left:26px;width:20px;height:20px}.mc-list-item .mc-user-popover>.avatar{position:absolute;left:0;width:100%;height:100%;background-repeat:no-repeat;background-position:50%;background-size:20px 20px;border-radius:50%}.mc-list-item .title{height:20px;overflow:hidden;font-size:16px;line-height:20px;white-space:nowrap;text-overflow:ellipsis}@media (max-width:599.9px){.mc-list-item .title{font-size:15px}}.mc-list-item .content{display:flex;align-items:center;height:16px;margin-top:8px}.mc-list-item .snippet{flex:1;overflow:hidden;font-size:14px;white-space:nowrap;text-overflow:ellipsis}.mc-list-item .meta{display:flex;padding-left:48px;font-size:13px}.mc-list-item .update_time{display:none}.mc-list-item .replys{margin-left:16px}.mc-list-item:hover .meta{padding-left:12px}.mc-list-item:hover .update_time{display:block}@media (max-width:599.9px){.mc-list-item{padding-left:50px}.mc-list-item .mc-user-popover{left:16px}.mc-list-item .snippet{display:none}.mc-list-item .meta{flex-direction:row-reverse;padding-left:0!important}.mc-list-item .update_time{display:block}.mc-list-item .replys{margin-right:16px;margin-left:0}}.mc-user-popover .popover{z-index:5999;width:320px;padding:16px;overflow:visible;cursor:default}.mc-user-popover .mdui-spinner{display:block;margin:20px auto}.mc-user-popover .mc-user-line{height:48px;padding-bottom:16px}.mc-user-popover .mc-user-line .avatar{width:48px;height:48px;background-size:48px 48px}.mc-user-popover .mc-user-line .username{margin-left:16px;font-size:17px;line-height:28px}.mc-user-popover .mc-user-line .headline{margin-left:64px;font-size:14px;line-height:20px}.mc-user-popover .stats{display:flex}.mc-user-popover .stats a,.mc-user-popover .stats button{display:flex;flex:1;flex-direction:column;align-items:center;min-width:auto;height:auto;padding:4px 0 3px;line-height:24px}.mc-user-popover .stats a label,.mc-user-popover .stats a span,.mc-user-popover .stats button label,.mc-user-popover .stats button span{cursor:pointer}.mc-user-popover .stats a label,.mc-user-popover .stats button label{font-size:13px}.mc-user-popover .stats a span,.mc-user-popover .stats button span{font-size:16px}.mc-user-popover .bottom{display:flex;justify-content:space-between;padding-top:16px}.mc-follow i{font-size:21px!important}.mc-follow.mdui-btn-dense i{font-size:19px!important}.mc-icon-button{overflow:visible}.mc-icon-button.active .mdui-icon{color:#1a73e8!important}.mdui-theme-layout-dark .mc-icon-button.active .mdui-icon{color:#8ab4f8!important}.mc-icon-button+button{margin-left:8px}.mc-icon-button .badge{position:absolute;top:-2px;right:-4px;height:14px;padding:0 4px;color:#fff;font-size:10px;line-height:14px;background-color:rgba(26,115,232,.64);border-radius:7px}.mdui-theme-layout-dark .mc-icon-button .badge{background-color:rgba(138,180,248,.64)}.mc-icon-button i{font-size:15px}.mc-icon-button.mdui-btn-dense i{font-size:14px}.mc-options-button{display:inline-block}.mc-topic-selector{max-width:530px;height:94%!important;max-height:720px!important}.mc-topic-selector .mdui-dialog-title{padding:16px 24px;line-height:36px}.mc-topic-selector .mdui-dialog-content,.mc-topic-selector .mdui-list{padding:0}.mc-topic-selector .mdui-dialog-content{padding-bottom:62px}.mc-topic-selector .mdui-list-item{padding-right:24px;padding-left:24px}.mc-topic-selector .mdui-list-item-avatar{overflow:hidden}.mc-topic-selector .mdui-list-item-avatar img{width:auto;margin-left:-16px;border-radius:0}.mc-topic-selector .close{display:none}.mc-topic-selector .selected{padding:0 24px 8px;line-height:1}.mc-topic-selector .selected .mdui-chip{margin-right:8px}@media (max-width:599px){.mc-topic-selector{position:fixed!important;top:0!important;right:0!important;bottom:0!important;left:0!important;width:100%!important;max-width:none!important;height:100%!important;max-height:none!important;margin:0!important;border-radius:0!important}.mc-topic-selector .mdui-dialog-title{padding:10px 8px 10px 16px;border-bottom:1px solid rgba(0,0,0,.12)}.mdui-theme-layout-dark .mc-topic-selector .mdui-dialog-title{border-bottom-color:hsla(0,0%,100%,.12)}.mc-topic-selector .selected{padding-top:12px}.mc-topic-selector .close{display:inline-block;float:left;margin-right:16px}}#page-question{max-width:846px}#page-question.mdui-container{padding-top:0}#page-question .question{padding:0 64px}#page-question .question .title{position:relative;margin:0;padding:36px 0 24px;font-weight:400;font-size:24px;line-height:36px}#page-question .question .content{padding:48px 0 32px}#page-question .question .mc-topics-bar{padding-bottom:16px}#page-question .question .actions{display:flex;margin-right:-64px;margin-left:-64px;padding:8px 64px;background-color:rgba(0,0,0,.04)}#page-question .mc-list-header{margin-top:32px;margin-bottom:20px}#page-question .all-answers{display:flex;align-items:center;justify-content:center;height:50px;margin:16px 0;text-decoration:none;border:1px solid rgba(0,0,0,.12);border-radius:8px;opacity:.56}.mdui-theme-layout-dark #page-question .all-answers{border-color:hsla(0,0%,100%,.12)}#page-question .all-answers:hover{opacity:1}#page-question .answers{min-height:148px}@media (max-width:599.9px){#page-question .question{padding:0 16px;border-right:none;border-left:none;border-radius:0}#page-question .question .title{padding:16px 0;font-size:22px;line-height:32px}#page-question .question .content{padding:28px 0}#page-question .question .mc-topics-bar{padding-bottom:8px}#page-question .question .actions{margin-right:-16px;margin-left:-16px;padding-right:16px;padding-left:16px}#page-question .mc-list-header{margin-top:20px;margin-bottom:12px;padding:0 16px}#page-question .mc-list-header .mdui-btn{padding-right:0}#page-question .answers{border-right:none;border-left:none;border-radius:0}}.mc-user-line{position:relative;height:40px}.mc-user-line .avatar{float:left;width:40px;height:40px;background-repeat:no-repeat;background-position:50%;background-size:40px 40px;border-radius:50%}.mc-user-line .username{margin-left:24px;font-weight:500;font-size:15px;line-height:22px;text-decoration:none}.mc-user-line .headline{margin-left:64px;overflow:hidden;font-size:13px;line-height:18px;white-space:nowrap;text-overflow:ellipsis}.mc-user-line .more{position:absolute;top:0;right:0}.mc-user-line .time{font-size:13px;line-height:20px}.mc-topics-bar .mdui-chip{margin-right:8px}.mc-list-header{display:flex;align-items:center;justify-content:space-between}.mc-list-header .title{font-size:18px}.mc-list-header .mdui-menu{width:236px}@media (max-width:599.9px){.mc-list-header .title{font-size:16px}}.mc-nav{display:flex;justify-content:space-between;margin:16px 0}.mc-nav .back i{font-size:20px}#page-question .answers .item,.mc-comments .item{padding:16px 64px;border-bottom:1px solid rgba(0,0,0,.12)}.mdui-theme-layout-dark #page-question .answers .item,.mdui-theme-layout-dark .mc-comments .item{border-bottom-color:hsla(0,0%,100%,.12)}#page-question .answers .item:last-child,.mc-comments .item:last-child{border-bottom:none}#page-question .answers .item .content,.mc-comments .item .content{padding-top:16px;padding-left:64px}#page-question .answers .item .reply_count,#page-question .answers .item .reply_more,.mc-comments .item .reply_count,.mc-comments .item .reply_more{margin-top:16px;margin-left:64px}#page-question .answers .item .actions,.mc-comments .item .actions{display:flex;margin-top:16px;padding-left:64px}#page-question .answers .item .new-comment,.mc-comments .item .new-comment{padding-left:64px}@media (max-width:849px){#page-question .answers .item .actions,#page-question .answers .item .content,#page-question .answers .item .new-comment,.mc-comments .item .actions,.mc-comments .item .content,.mc-comments .item .new-comment{padding-left:0}#page-question .answers .item .reply_count,.mc-comments .item .reply_count{margin-left:0}#page-question .answers .item .reply_more,.mc-comments .item .reply_more{margin-left:40px}}@media (max-width:599.9px){#page-question .answers .item,.mc-comments .item{padding-right:16px;padding-left:16px}#page-question .answers .item .content,.mc-comments .item .content{padding-top:16px}}#page-question .comment{margin-left:16px}#page-question .comment i{font-size:16px}#page-article{max-width:846px}#page-article.mdui-container{padding-top:0}#page-article .article{padding:0 64px}#page-article .article .title{position:relative;margin:0;padding:36px 0 24px;font-weight:400;font-size:24px;line-height:36px}#page-article .article .content{padding:48px 0 32px}#page-article .article .mc-topics-bar{padding-bottom:16px}#page-article .article .actions{display:flex;margin-right:-64px;margin-left:-64px;padding:8px 64px;background-color:rgba(0,0,0,.04)}#page-article .article .mc-follow{margin-left:16px}@media (max-width:599.9px){#page-article .article{padding:0 16px;border-right:none;border-left:none;border-radius:0}#page-article .article .title{padding:16px 0;font-size:22px;line-height:32px}#page-article .article .content{padding:28px 0}#page-article .article .mc-topics-bar{padding-bottom:8px}#page-article .article .actions{margin-right:-16px;margin-left:-16px;padding-right:16px;padding-left:16px}}.mc-comments-page .mc-list-header{margin-top:32px;margin-bottom:20px}@media (max-width:599.9px){.mc-comments-page .mc-list-header{margin-top:20px;margin-bottom:12px;padding:0 16px}.mc-comments-page .mc-list-header .mdui-btn{padding-right:0}}.mc-comments-page .comments-wrapper{margin-bottom:16px;overflow:hidden;border:1px solid rgba(0,0,0,.12);border-radius:8px}.mdui-theme-layout-dark .mc-comments-page .comments-wrapper{border-color:hsla(0,0%,100%,.12)}.mc-comments-page .comments-wrapper .mc-loaded{margin-bottom:24px!important}@media (max-width:599.9px){.mc-comments-page .comments-wrapper{border-right:none;border-left:none;border-radius:0}}.mc-comments-page .comments{border:none}.mc-comments-page .new-comment-fixed{position:fixed;right:0;bottom:0;left:0}@media (min-width:1024px){.mdui-drawer-body-left .mc-comments-page .new-comment-fixed{left:240px}}.mc-comments-page .new-comment-fixed .mdui-container{max-width:846px;padding-top:0;padding-bottom:0}.mc-comments-page .new-comment-fixed .new-comment{box-sizing:border-box;padding-right:64px!important;padding-left:64px!important;border-right:1px solid rgba(0,0,0,.12);border-left:1px solid rgba(0,0,0,.12);border-top-left-radius:8px;border-top-right-radius:8px;box-shadow:0 -1px 3px rgba(26,26,26,.1)}.mdui-theme-layout-dark .mc-comments-page .new-comment-fixed .new-comment{border-top-color:hsla(0,0%,100%,.12)}@media (max-width:599.9px){.mc-comments-page .new-comment-fixed .new-comment{padding-right:16px!important;padding-left:16px!important;border-right:none;border-left:none;border-radius:0}}.mc-comments .comments{min-height:148px}@media (max-width:599.9px){.mc-comments .comments{border-right:none;border-left:none;border-radius:0}}.mc-comments .item .content{line-height:1.6}.mc-comments .item .actions>.mc-icon-button{margin-left:8px}.mc-comments .item .actions>.mc-icon-button i{font-size:22px}.mc-comments .item .reply_count,.mc-comments .item .reply_more{display:inline-block;height:24px;color:#1a73e8;line-height:24px;cursor:pointer}.mc-comments .item .reply_count i,.mc-comments .item .reply_more i{float:left;transition:transform .3s}.mc-comments .item .reply_count span,.mc-comments .item .reply_more span{font-size:14px}.mdui-theme-layout-dark .mc-comments .item .reply_count,.mdui-theme-layout-dark .mc-comments .item .reply_more{color:#8ab4f8}.mc-comments .item .reply_more i{margin-right:3px;font-size:20px}.mc-comments .item .show-replies i{transform:rotate(180deg)}.mc-comments-dialog .new-comment,.mc-comments-page .new-comment{display:flex;align-items:flex-end;box-sizing:border-box;width:100%;padding:12px 0;background-color:#fff}.mdui-theme-layout-dark .mc-comments-dialog .new-comment,.mdui-theme-layout-dark .mc-comments-page .new-comment{background-color:#424242}.mc-comments-dialog .new-comment textarea,.mc-comments-page .new-comment textarea{flex:1;max-height:60vh;margin-right:16px;overflow:auto;font-size:inherit;border-bottom:none!important;box-shadow:0 1px 0 0 rgba(0,0,0,.42)}.mdui-theme-layout-dark .mc-comments-dialog .new-comment textarea,.mdui-theme-layout-dark .mc-comments-page .new-comment textarea{box-shadow:0 1px 0 0 hsla(0,0%,100%,.7)}.mc-comments-dialog .new-comment textarea:focus,.mc-comments-dialog .new-comment textarea:hover,.mc-comments-page .new-comment textarea:focus,.mc-comments-page .new-comment textarea:hover{box-shadow:0 2px 0 0 rgba(0,0,0,.87)}.mdui-theme-layout-dark .mc-comments-dialog .new-comment textarea:focus,.mdui-theme-layout-dark .mc-comments-dialog .new-comment textarea:hover,.mdui-theme-layout-dark .mc-comments-page .new-comment textarea:focus,.mdui-theme-layout-dark .mc-comments-page .new-comment textarea:hover{box-shadow:0 2px 0 0 #fff}.mc-comments-dialog .new-comment .submit,.mc-comments-page .new-comment .submit{width:76px}.mc-comments .item .item{padding-right:0;border-bottom:none}.mc-comments .item .item .mc-user-line{height:24px}.mc-comments .item .item .mc-user-line .avatar{width:24px;height:24px;background-size:24px 24px}.mc-comments .item .item .mc-user-line .username{margin-left:16px;line-height:24px}.mc-comments .item .item .mc-user-line .headline{display:none}.mc-comments .item .item .actions,.mc-comments .item .item .content{padding-left:40px}@media (max-width:849px){.mc-comments .item .item{padding-left:40px}.mc-comments .item .item .actions,.mc-comments .item .item .content{padding-left:0}}@media (max-width:599.9px){.mc-comments .item .item{padding-right:0;padding-left:40px}}#page-topics .subheading,#page-users .subheading{padding:8px 8px 16px;font-weight:400;font-size:15px;letter-spacing:.04em}@media (min-width:600px){#page-topics .subheading,#page-users .subheading{padding-bottom:24px;font-size:16px}}#page-topics .items-wrapper,#page-users .items-wrapper{margin-right:0;margin-left:0}#page-topics .items-wrapper:after,#page-users .items-wrapper:after{display:table;clear:both;content:""}@media (min-width:600px){#page-topics .items-wrapper,#page-users .items-wrapper{margin-right:-8px;margin-left:-8px}}#page-topics .item-inner,#page-users .item-inner{position:relative;float:left;box-sizing:border-box;width:50%}#page-topics .item-inner:nth-child(odd),#page-users .item-inner:nth-child(odd){padding-right:4px;padding-left:8px}#page-topics .item-inner:nth-child(2n),#page-users .item-inner:nth-child(2n){padding-right:8px;padding-left:4px}@media (min-width:600px){#page-topics .item-inner,#page-users .item-inner{width:33.333333%;padding-right:8px!important;padding-left:8px!important}}@media (min-width:1024px){#page-topics .item-inner,#page-users .item-inner{width:25%}}#page-topics .mc-follow,#page-users .mc-follow{min-width:0;padding:0 8px}#page-topics .mc-loading,#page-users .mc-loading{margin-bottom:-62px}.mc-topic-item .item{margin-bottom:16px;background-repeat:no-repeat;background-size:contain}@media (max-width:599.9px){.mc-topic-item .item{margin-bottom:8px}}.mc-topic-item .item .info{display:block;box-sizing:border-box;padding:56% 16px 0;text-decoration:none}.mc-topic-item .item .name{padding-top:16px;padding-bottom:8px;overflow:hidden;font-size:16px;white-space:nowrap;text-overflow:ellipsis;word-break:break-all}.mc-topic-item .item .actions{display:flex;justify-content:space-between;padding:8px 0 8px 16px}.mc-topic-item .item .followers{border-top-right-radius:0;border-bottom-right-radius:0}#page-topic{max-width:846px;padding-top:0}#page-topic .topic{padding:24px 24px 16px}#page-topic .topic .info{display:flex}#page-topic .topic .info .cover{width:180px;min-width:180px;height:101px;background-size:contain;border-radius:4px}#page-topic .topic .info .main{padding-left:24px}#page-topic .topic .info .name{height:26px;font-size:22px}#page-topic .topic .info .meta{padding-top:10px;font-size:13px}#page-topic .topic .info .meta span+span:before{margin:0 8px;content:"•"}#page-topic .topic .info .description{box-sizing:border-box;padding-top:10px;font-size:14px;line-height:22px}#page-topic .topic .actions{display:flex;padding-top:16px}@media (max-width:800px){#page-topic .topic .info .main{padding-left:16px}}@media (max-width:599.9px){#page-topic .topic{padding:16px;border-right:none;border-left:none;border-radius:0}#page-topic .topic .info .cover{width:108px;min-width:108px;height:60px}#page-topic .topic .info .name{padding-top:2px}#page-topic .topic .info .meta{padding-top:12px}#page-topic .topic .info .description{margin-top:8px;margin-left:-124px}}#page-topic .contexts,#page-user .contexts{margin-top:16px}#page-topic .contexts .mc-list-header,#page-user .contexts .mc-list-header{padding:16px}#page-topic .contexts .mc-list-header .title,#page-user .contexts .mc-list-header .title{font-size:16px}#page-topic .contexts .mc-list-header button,#page-user .contexts .mc-list-header button{padding-right:0}#page-topic .contexts .item-list,#page-user .contexts .item-list{border-top:1px solid rgba(0,0,0,.12)}.mdui-theme-layout-dark #page-topic .contexts .item-list,.mdui-theme-layout-dark #page-user .contexts .item-list{border-top-color:hsla(0,0%,100%,.12)}@media (max-width:599.9px){#page-topic .contexts,#page-user .contexts{border-right:none;border-left:none;border-radius:0}#page-topic .contexts .mc-list-header .title,#page-user .contexts .mc-list-header .title{font-size:15px}}.mc-tab a{flex-direction:row}.mc-tab a span{margin-left:6px;transform:scale(.9);opacity:.56}#page-users .item{margin-bottom:16px}@media (max-width:599.9px){#page-users .item{margin-bottom:8px}}#page-users .item .info{display:block;box-sizing:border-box;text-decoration:none}#page-users .item .avatar{width:96px;height:96px;margin:24px auto 16px;background-repeat:no-repeat;background-position:50%;background-size:96px 96px;border-radius:50%}@media (max-width:599.9px){#page-users .item .avatar{width:80px;height:80px;margin:16px auto 12px;background-size:80px 80px}}#page-users .item .headline,#page-users .item .username{padding:0 16px;overflow:hidden;white-space:nowrap;text-align:center;text-overflow:ellipsis;word-break:break-all}#page-users .item .username{height:20px;font-size:17px;line-height:20px}#page-users .item .headline{height:20px;margin:8px 0 16px;font-size:15px;line-height:20px}@media (max-width:599.9px){#page-users .item .headline{margin:8px 0}}#page-users .item .actions{display:flex;justify-content:space-between;padding:8px 8px 8px 16px}#page-user{max-width:846px;padding-top:0}#page-user .user{border-top-left-radius:0;border-top-right-radius:0}#page-user .user .cover{position:relative;box-sizing:border-box;height:0;padding-bottom:56%;overflow:visible;background-repeat:no-repeat;background-position:50%;background-size:cover}#page-user .user .cover .mc-cover-upload{position:absolute;top:16px;right:16px;display:none}#page-user .user .cover:hover .mc-cover-upload{display:block}#page-user .user .info{position:relative;display:flex;padding:20px 24px 20px 20px}#page-user .user .info .avatar-box{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;width:110px;min-width:110px;height:110px;background-color:rgba(0,0,0,.06);border-radius:50%}.mdui-theme-layout-dark #page-user .user .info .avatar-box{background-color:hsla(0,0%,100%,.06)}#page-user .user .info .avatar-box .avatar{width:102px;height:102px;border-radius:50%;-ms-user-select:none;user-select:none}#page-user .user .info .avatar-box .mc-avatar-upload{display:none}#page-user .user .info .avatar-box:hover .mc-avatar-upload{display:block}#page-user .user .info .profile{padding-left:32px}#page-user .user .info .profile .meta{display:block;align-items:center;padding-left:30px;line-height:22px}#page-user .user .info .profile .meta+.meta{margin-top:8px}#page-user .user .info .profile .meta i{float:left;margin-left:-30px;padding-top:2px;font-size:18px}#page-user .user .info .profile .username{padding-top:8px;padding-bottom:4px;padding-left:0;font-size:32px;line-height:32px}#page-user .user .info .profile.fold .meta{display:none}#page-user .user .info .profile.fold .meta:first-child,#page-user .user .info .profile.fold .meta:nth-child(2){display:block}#page-user .user .info .profile .fold-button{margin-top:8px;margin-left:-16px}#page-user .user .actions{display:flex;align-items:center;justify-content:space-between;padding:0 24px 16px 57px}#page-user .user .actions .edit,#page-user .user .actions .mc-follow{margin-right:58px}#page-user .user .actions .edit i{font-size:21px}#page-user .user .actions .follow{display:flex;flex:1;align-items:center}#page-user .user .actions .divider{width:1px;height:16px;margin:0 8px;background-color:rgba(0,0,0,.12)}.mdui-theme-layout-dark #page-user .user .actions .divider{background-color:hsla(0,0%,100%,.12)}@media (max-width:599.9px){#page-user .user,#page-user .user .cover{border-radius:0}#page-user .user .info{flex-direction:column;align-items:center;padding:0 16px 16px}#page-user .user .info .avatar-box{width:106px;min-width:106px;height:106px;margin-top:-53px}#page-user .user .info .profile{width:100%;padding-left:0}#page-user .user .info .profile.fold{width:auto}#page-user .user .info .profile .username{padding-top:10px;font-size:24px;text-align:center}#page-user .user .actions{position:relative;margin-top:54px;padding:0 16px 16px}#page-user .user .actions .edit,#page-user .user .actions .mc-follow{margin-right:0}#page-user .user .actions .follow{position:absolute;top:-54px;right:16px;left:16px;border-top:1px solid rgba(0,0,0,.06);border-bottom:1px solid rgba(0,0,0,.06)}.mdui-theme-layout-dark #page-user .user .actions .follow{border-color:hsla(0,0%,100%,.06)}#page-user .user .actions .followees,#page-user .user .actions .followers{width:50%;border-radius:0}#page-user .user .actions .divider{margin:0}}.mc-avatar-upload{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.mc-avatar-upload,.mc-cover-upload{width:48px;height:48px;overflow:hidden}.mc-avatar-upload .upload-btn,.mc-cover-upload .upload-btn{display:block;width:48px;min-width:48px;height:48px;background-color:rgba(0,0,0,.26)!important}.mc-avatar-upload .upload-btn i,.mc-cover-upload .upload-btn i{color:#fff!important;opacity:.9}.mc-avatar-upload .upload-btn:active,.mc-avatar-upload .upload-btn:hover,.mc-cover-upload .upload-btn:active,.mc-cover-upload .upload-btn:hover{background-color:rgba(0,0,0,.26)!important}.mc-avatar-upload .upload-btn:active i,.mc-avatar-upload .upload-btn:hover i,.mc-cover-upload .upload-btn:active i,.mc-cover-upload .upload-btn:hover i{opacity:1}.mc-avatar-upload .upload-btn+input[type=file],.mc-cover-upload .upload-btn+input[type=file]{width:0;height:0;overflow:hidden;opacity:0}#page-user .edit-info{max-width:530px}#page-user .edit-info .mdui-dialog-title{padding:16px 24px;line-height:36px}#page-user .edit-info .close{display:none}#page-user .edit-info .mdui-textfield{padding-top:0}@media (max-width:599px){#page-user .edit-info{position:fixed!important;top:0!important;right:0!important;bottom:0!important;left:0!important;width:100%!important;max-width:none!important;height:100%!important;max-height:none!important;margin:0!important;border-radius:0!important}#page-user .edit-info .mdui-dialog-title{padding:10px 8px;border-bottom:1px solid rgba(0,0,0,.12)}#page-user .edit-info .mdui-dialog-content{padding-top:16px}#page-user .edit-info .close{display:inline-block;float:left;margin-right:8px}}#page-articles,#page-notifications,#page-questions{max-width:800px}@media (max-width:599.9px){#page-articles .item-list,#page-notifications .item-list,#page-questions .item-list{border:1px solid rgba(0,0,0,.12);border-right:none;border-left:none;border-radius:0;box-shadow:none}.mdui-theme-layout-dark #page-articles .item-list,.mdui-theme-layout-dark #page-notifications .item-list,.mdui-theme-layout-dark #page-questions .item-list{border-top-color:hsla(0,0%,100%,.12);border-bottom-color:hsla(0,0%,100%,.12)}}#page-articles .mc-loading,#page-notifications .mc-loading,#page-questions .mc-loading{margin-bottom:-62px}#page-notifications .item{position:relative;padding:20px 24px}@media (max-width:599.9px){#page-notifications .item{padding-right:16px;padding-left:16px}}#page-notifications .item:after{position:absolute;right:24px;bottom:0;left:24px;height:1px;background-color:rgba(0,0,0,.08);content:" "}@media (max-width:599.9px){#page-notifications .item:after{right:16px;left:16px}}.mdui-theme-layout-dark #page-notifications .item:after{background-color:hsla(0,0%,100%,.08)}#page-notifications .item .title{padding-right:32px;line-height:24px}#page-notifications .item .title .article,#page-notifications .item .title .question,#page-notifications .item .title .user{color:#1a73e8;text-decoration:none}.mdui-theme-layout-dark #page-notifications .item .title .article,.mdui-theme-layout-dark #page-notifications .item .title .question,.mdui-theme-layout-dark #page-notifications .item .title .user{color:#8ab4f8}#page-notifications .item .title .article.deleted,#page-notifications .item .title .question.deleted,#page-notifications .item .title .user.deleted{color:inherit;font-weight:700;opacity:.68}#page-notifications .item .content{box-sizing:border-box;min-height:34px;margin-top:10px;padding:6px 32px 6px 8px;color:rgba(0,0,0,.7);font-size:14px;line-height:22px;background-color:rgba(0,0,0,.04);border-radius:4px}.mdui-theme-layout-dark #page-notifications .item .content{color:hsla(0,0%,100%,.7);background-color:#424242}#page-notifications .item .content .mc-loading{margin-bottom:0}#page-notifications .item .mdui-typo{padding-top:16px;padding-bottom:16px}#page-notifications .item .mdui-typo pre.hljs{background-color:transparent;border:1px solid rgba(0,0,0,.12)}.mdui-theme-layout-dark #page-notifications .item .mdui-typo pre.hljs{border-color:hsla(0,0%,100%,.12)}#page-notifications .item .delete,#page-notifications .item .more{position:absolute;right:28px;display:none;width:24px;min-width:24px;height:24px;color:#1a73e8;cursor:pointer}.mdui-theme-layout-dark #page-notifications .item .delete,.mdui-theme-layout-dark #page-notifications .item .more{color:#8ab4f8}@media (max-width:599.9px){#page-notifications .item .delete,#page-notifications .item .more{right:20px}}#page-notifications .item .more{bottom:25px}@media (max-width:599.9px){#page-notifications .item .more{display:block}}#page-notifications .item .delete{top:16px}#page-notifications .item .delete .mdui-icon{font-size:16px}#page-notifications .item:hover .delete,#page-notifications .item:hover .more{display:block}.mc-appbar{background-color:#fff}.mdui-theme-layout-dark .mc-appbar{background-color:#303030}.mc-appbar .toolbar{position:relative}.mc-appbar .toolbar .headline,.mc-appbar .toolbar .title{overflow:visible;opacity:.87}.mc-appbar .toolbar .headline{font-weight:400;font-size:24px}@media (max-width:599.9px){.mc-appbar .toolbar .headline{overflow:hidden}}.mc-appbar .toolbar .title{font-size:20px;letter-spacing:.02em}@media (max-width:599.9px){.mc-appbar .toolbar .title{display:none}}.mc-appbar .toolbar .login,.mc-appbar .toolbar .register{min-width:64px!important;margin:0 24px 0 0!important}@media (max-width:1023.9px){.mc-appbar .toolbar .login,.mc-appbar .toolbar .register{margin-right:16px!important;padding:0 12px}}@media (max-width:599.9px){.mc-appbar .toolbar .login,.mc-appbar .toolbar .register{margin-right:8px!important;padding:0 8px}}.mc-appbar .toolbar .avatar{display:block;min-width:32px}.mc-appbar .toolbar .avatar .user{transition:box-shadow .2s cubic-bezier(.4,0,1,1)}.mc-appbar .toolbar .avatar .user:hover{box-shadow:0 2px 1px -1px rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 1px 3px 0 rgba(0,0,0,.12)}.mc-appbar .toolbar .avatar .user img{border-radius:50%}.mc-appbar .toolbar .avatar .popover{width:330px;height:192px;padding:0}.mc-appbar .toolbar .avatar .popover .bottom,.mc-appbar .toolbar .avatar .popover .info{position:absolute;box-sizing:border-box;width:100%}.mc-appbar .toolbar .avatar .popover .info{top:0;left:0;height:139px;padding:22px 20px}.mc-appbar .toolbar .avatar .popover .bottom{bottom:0;left:0;display:flex;justify-content:space-between;padding:10px 20px;background-color:#f5f5f5;border-color:rgba(0,0,0,.2);border-top:1px solid rgba(0,0,0,.12)}.mdui-theme-layout-dark .mc-appbar .toolbar .avatar .popover .bottom{background-color:#424242;border-top-color:hsla(0,0%,100%,.12)}.mc-appbar .toolbar .avatar .popover .bottom button{min-width:46px}.mc-appbar .toolbar .avatar .popover .avatar-box{position:relative;float:left;width:96px;height:96px;overflow:hidden;border-radius:50%}.mc-appbar .toolbar .avatar .popover .avatar-box .mc-avatar-upload{display:none}.mc-appbar .toolbar .avatar .popover .avatar-box:hover .mc-avatar-upload{display:block}.mc-appbar .toolbar .avatar .popover .email,.mc-appbar .toolbar .avatar .popover .username{margin-left:112px;line-height:20px}.mc-appbar .toolbar .avatar .popover .username{font-weight:700;font-size:14px}.mc-appbar .toolbar .avatar .popover .email{font-size:13px}.mc-appbar .toolbar .avatar .popover .personal{margin-left:16px}@media (max-width:599.9px){.mc-appbar .toolbar .notification{width:40px;min-width:40px;height:40px;margin-right:-4px}}.mc-appbar .toolbar .notification .count{position:absolute;top:50%;left:50%;width:8px;height:8px;margin-top:-14px;margin-left:2px;background:#1a73e8;border-radius:50%}.mc-appbar .toolbar .search-bar{display:flex;align-items:center;width:100%;max-width:722px;height:46px;margin-left:30px;background-color:#f1f3f4;border-radius:8px;transition-duration:.18s;transition-property:background-color,box-shadow}@media (max-width:599.9px){.mc-appbar .toolbar .search-bar{display:none}}.mc-appbar .toolbar .search-bar.focus{background-color:#fff;box-shadow:0 1px 1px 0 rgba(65,69,73,.3),0 1px 3px 1px rgba(65,69,73,.15)}.mdui-theme-layout-dark .mc-appbar .toolbar .search-bar{background-color:#424242!important}.mdui-theme-layout-dark .mc-appbar .toolbar .search-bar input{color:#fff}.mdui-theme-layout-dark .mc-appbar .toolbar .search-bar.focus{box-shadow:0 2px 3px 0 rgba(0,0,0,.6),0 6px 10px 4px rgba(0,0,0,.3)}.mc-appbar .toolbar .search-bar input{flex:1;height:46px;background-color:transparent;border:none;outline:none}.mc-appbar .toolbar .search-bar .back,.mc-appbar .toolbar .search-bar .cancel,.mc-appbar .toolbar .search-bar .submit{margin:0 5px}.mc-appbar .toolbar .search-bar .back,.mc-appbar .toolbar .search-bar .cancel{display:none}.mc-appbar .toolbar .search-bar.not-empty .cancel{display:flex}.mc-appbar .toolbar.mobile .avatar,.mc-appbar .toolbar.mobile .headline,.mc-appbar .toolbar.mobile .login,.mc-appbar .toolbar.mobile .notification,.mc-appbar .toolbar.mobile .register,.mc-appbar .toolbar.mobile .search-icon,.mc-appbar .toolbar.mobile .title{display:none}.mc-appbar .toolbar.mobile .search-bar{position:absolute;display:flex;height:100%;margin:0;background-color:#fff;border-radius:0}.mdui-theme-layout-dark .mc-appbar .toolbar.mobile .search-bar{background-color:#424242!important}.mc-appbar .toolbar.mobile .search-bar.focus{box-shadow:none}.mc-appbar .toolbar.mobile .search-bar .back{display:flex}.mc-appbar .toolbar.mobile .search-bar .submit,.mc-appbar .toolbar .search-icon{display:none}@media (max-width:599.9px){.mc-appbar .toolbar .search-icon{display:flex;width:40px;min-width:40px;height:40px}}.mc-drawer{display:flex;flex-direction:column}.mc-drawer .mdui-list{flex:1;box-sizing:border-box}.mc-drawer .mdui-list-item{padding-left:20px;border-radius:0 50px 50px 0}.mc-drawer .mdui-list-item-icon{transform:scale(.875)}.mc-drawer .mdui-list-item-content{font-weight:400;font-size:14px}.mc-drawer .mdui-list-item-active{color:#1a73e8;background-color:#e8f0fe}.mdui-theme-layout-dark .mc-drawer .mdui-list-item-active{color:#fff;background-color:#424242}.mc-drawer .mdui-list-item-active .mdui-list-item-icon{color:#1a73e8}.mdui-theme-layout-dark .mc-drawer .mdui-list-item-active .mdui-list-item-icon{color:#fff}.mc-drawer .copyright{box-sizing:border-box;width:100%;padding:20px 16px}.mc-drawer .copyright p{margin:0;overflow:hidden;color:rgba(0,0,0,.38);font-size:13px;line-height:20px;white-space:nowrap;text-overflow:ellipsis}.mdui-theme-layout-dark .mc-drawer .copyright p{color:hsla(0,0%,100%,.38)}.mc-drawer .copyright a{color:rgba(0,0,0,.52);text-decoration:none}.mdui-theme-layout-dark .mc-drawer .copyright a{color:hsla(0,0%,100%,.52)}.mc-drawer .copyright a:hover{text-decoration:underline}.mc-login .mdui-dialog-title{background-color:#3f51b5}.mc-register .mdui-dialog-title{background-color:#4caf50}.mc-account{max-width:448px;overflow-y:auto}.mc-account .arrow_back,.mc-account .close{position:absolute;top:4px;left:4px;display:block;color:#fff}.mc-account .avatar{position:absolute;top:40px;left:36px;display:block;color:hsla(0,0%,100%,.56);font-size:76px}.mc-account .mdui-dialog-title{margin-bottom:24px;padding:146px 40px 28px;color:#fff}.mdui-theme-layout-dark .mc-account .mdui-dialog-title{background-color:#303030}.mc-account form{padding:0 40px 62px}.mc-account .more-option{margin-left:-16px}.mc-account .captcha-field{margin-right:116px;overflow:visible}.mc-account .captcha-image{position:absolute;right:-116px;bottom:29px;cursor:pointer}.mc-account .send-email-field{margin-right:116px;overflow:visible}.mc-account .send-email{position:absolute;right:-116px;bottom:29px}.mc-account .actions{margin-top:24px}.mc-account .action-btn{float:right}.mdui-theme-layout-dark .mc-account .action-btn{background-color:#525252!important}@media (max-width:599.9px){.mc-account{position:fixed!important;top:0!important;right:0!important;bottom:0!important;left:0!important;width:100%!important;max-width:none!important;height:100%!important;max-height:none!important;margin:0!important;border-radius:0!important}.mc-account .back,.mc-account .close{top:10px;left:8px}.mc-account .avatar{display:none}.mc-account .mdui-dialog-title{padding:10px 16px 10px 52px;line-height:36px}.mc-account form{padding:0 24px 24px}.mc-account form .mdui-textfield{padding-top:4px}.mc-account .actions{margin-top:14px}}.mc-reset .mdui-dialog-title{background-color:#ff5722}.mc-users-dialog{max-width:530px;height:94%!important;max-height:720px!important}.mc-users-dialog .mdui-dialog-title{padding:16px 24px;line-height:36px}.mc-users-dialog .mdui-dialog-content,.mc-users-dialog .mdui-list{padding:0}.mc-users-dialog .mdui-dialog-content{padding-bottom:62px}.mc-users-dialog .item{position:relative}.mc-users-dialog .mc-follow{position:absolute;top:18px;right:24px}.mc-users-dialog .mdui-list-item{padding:8px 24px}.mc-users-dialog .close{display:none}@media (max-width:599.9px){.mc-users-dialog{position:fixed!important;top:0!important;right:0!important;bottom:0!important;left:0!important;width:100%!important;max-width:none!important;height:100%!important;max-height:none!important;margin:0!important;border-radius:0!important}.mc-users-dialog .mdui-dialog-title{padding:10px 8px;font-size:16px;border-bottom:1px solid rgba(0,0,0,.12)}.mdui-theme-layout-dark .mc-users-dialog .mdui-dialog-title{border-bottom-color:hsla(0,0%,100%,.12)}.mc-users-dialog .mdui-list-item{padding-right:16px;padding-left:16px}.mc-users-dialog .close{display:inline-block;float:left;margin-right:16px}}.mc-report-dialog{width:280px}.mc-report-dialog .mdui-dialog-title{padding-bottom:16px}.mc-report-dialog .mdui-dialog-title button{float:right;margin-top:-10px}.mc-report-dialog .mdui-dialog-content{padding:0 0 8px}.mc-report-dialog .mdui-list-item{padding-left:24px}.mc-report-dialog .mdui-list-item-content{margin-left:2px}.mc-report-dialog .mdui-textfield{margin-right:24px;margin-left:24px;padding-top:8px}.mc-share-dialog{width:280px}.mc-share-dialog .mdui-dialog-title{padding-bottom:16px}.mc-share-dialog .mdui-dialog-title button{float:right;margin-top:-10px}.mc-share-dialog .mdui-dialog-content{padding:0 0 8px}.mc-share-dialog .mdui-list-item{padding-left:24px}.mc-share-dialog .mdui-list-item-content{margin-left:24px}.mc-comments-dialog{position:fixed;top:3%;z-index:2001;max-width:750px;height:100vh;max-height:94%}@media (max-width:599.9px){.mc-comments-dialog{top:0;left:0;width:100%;max-height:100%;border-radius:0}}.mc-comments-dialog .mc-comments{height:100%}.mc-comments-dialog .mc-list-header{display:flex;align-items:center;box-sizing:border-box;height:60px;margin:0!important;padding:0 16px;border-bottom:1px solid rgba(0,0,0,.12)}.mc-comments-dialog .mc-list-header .close{display:none}.mc-comments-dialog .mc-list-header button{padding-right:0}.mdui-theme-layout-dark .mc-comments-dialog .mc-list-header{border-bottom-color:hsla(0,0%,100%,.12)}@media (max-width:1023.9px){.mc-comments-dialog .mc-list-header{height:56px}}@media (max-width:599.9px){.mc-comments-dialog .mc-list-header{padding-left:8px}.mc-comments-dialog .mc-list-header .close{display:inline-block;margin-right:16px}}.mc-comments-dialog .comments-wrapper{height:calc(100% - 120px);overflow:auto;-webkit-overflow-scrolling:touch}@media (max-width:1023.9px){.mc-comments-dialog .comments-wrapper{height:calc(100% - 116px)}}.mc-comments-dialog .comments-wrapper .mc-loaded{margin-bottom:24px!important}.mc-comments-dialog .comments{border-top:none;border-right:none;border-left:none;border-radius:0}.mc-comments-dialog .mc-comments>.new-comment{position:absolute;bottom:0;box-shadow:0 -1px 3px rgba(26,26,26,.1)}.mdui-theme-layout-dark .mc-comments-dialog .mc-comments>.new-comment{box-shadow:0 -1px 3px hsla(0,0%,89.4%,.1)}.mc-comments-dialog .comments>.item,.mc-comments-dialog .mc-comments>.new-comment{padding-right:24px;padding-left:24px}@media (max-width:599.9px){.mc-comments-dialog .comments>.item,.mc-comments-dialog .mc-comments>.new-comment{padding-right:16px;padding-left:16px}} -------------------------------------------------------------------------------- /config/sys.cfg.php: -------------------------------------------------------------------------------- 1 | false, //调试模式 4 | ]; -------------------------------------------------------------------------------- /extend/teambition.php: -------------------------------------------------------------------------------- 1 | 5 | * @version 1.1 6 | */ 7 | 8 | namespace extend; 9 | class teambition{ 10 | /** 11 | * 获取登录所需的Token 12 | * @return string 13 | */ 14 | public static function get_login_token(){ 15 | $html = self::get('https://account.teambition.com/login/password'); 16 | if(preg_match('/"TOKEN":"([a-zA-Z0-9_\-\.]+)"/',$html,$match)){ 17 | return $match[1]; 18 | }else{ 19 | return false; 20 | } 21 | 22 | } 23 | 24 | /** 25 | * 登录获取Cookie 26 | * @param string $username 账号 27 | * @param string $password 密码 28 | * @return string 29 | */ 30 | public static function login($username,$password){ 31 | $token = self::get_login_token(); 32 | $postJson = json_encode([ 33 | 'phone' => $username, 34 | 'password' => $password, 35 | 'token' => $token, 36 | 'client_id' => '90727510-5e9f-11e6-bf41-15ed35b6cc41', 37 | 'response_type' => 'session' 38 | ]); 39 | $result = self::get('https://account.teambition.com/api/login/phone',0,$postJson,1); 40 | if($result){ 41 | $cookie = ''; 42 | if(preg_match('/TEAMBITION_SESSIONID=([a-zA-Z0-9=]+);/',$result['header'],$match)){ 43 | $cookie .= $match[0]; 44 | } 45 | if(preg_match('/TEAMBITION_SESSIONID\.sig=([a-zA-Z0-9=\-_]+);/',$result['header'],$match)){ 46 | $cookie .= $match[0]; 47 | } 48 | return $cookie; 49 | }else{ 50 | return false; 51 | } 52 | } 53 | 54 | /** 55 | * 获取项目列表 56 | * @param string $cookie teambitionCookie 57 | * @return array 58 | */ 59 | public static function get_projects($cookie){ 60 | $api = 'https://www.teambition.com/api/v2/projects?'; 61 | $param = [ 62 | '_organizationId' => '000000000000000000000405', 63 | 'selectBy' => 'joined', 64 | 'orderBy' => 'name', 65 | 'pageToken' => '', 66 | 'pageSize' => 20 67 | ]; 68 | $result = self::get($api.http_build_query($param),$cookie); 69 | if($result){ 70 | $result = json_decode($result,true); 71 | return $result; 72 | }else{ 73 | return false; 74 | } 75 | } 76 | 77 | /** 78 | * 获取项目信息 79 | * @param string $projectID 项目ID 80 | * @param string $cookie teambitionCookie 81 | * @return array 82 | */ 83 | public static function get_project($projectId,$cookie){ 84 | $api = 'https://www.teambition.com/api/projects/'.$projectId; 85 | $result = self::get($api,$cookie); 86 | if($result){ 87 | $result = json_decode($result,true); 88 | return $result; 89 | }else{ 90 | return false; 91 | } 92 | } 93 | 94 | /** 95 | * 获取文件夹下的文件夹 96 | * @param string $projectID 项目ID 97 | * @param string $dirid 文件夹ID 98 | * @param string $cookie teambitionCookie 99 | * @param int $page 页码 100 | * @return array 101 | */ 102 | public static function get_dirs($projectId,$dirId,$cookie,$count=100,$order='updatedDesc',$page=1){ 103 | $api = 'https://www.teambition.com/api/collections?'; 104 | $param = [ 105 | '_parentId' => $dirId, 106 | '_projectId' => $projectId, 107 | 'order' => $order, 108 | 'count' => $count, 109 | 'page' => $page 110 | ]; 111 | $result = self::get($api.http_build_query($param),$cookie); 112 | if($result){ 113 | $result = json_decode($result,true); 114 | return $result; 115 | }else{ 116 | return false; 117 | } 118 | } 119 | 120 | /** 121 | * 获取文件夹下的文件 122 | * @param string $projectID 项目ID 123 | * @param string $dirid 文件夹ID 124 | * @param string $cookie teambitionCookie 125 | * @param int $page 页码 126 | * @return array 127 | */ 128 | public static function get_files($projectId,$dirId,$cookie,$count=100,$order='updatedDesc',$page=1){ 129 | $api = 'https://www.teambition.com/api/works?'; 130 | $param = [ 131 | '_parentId' => $dirId, 132 | '_projectId' => $projectId, 133 | 'order' => $order, 134 | 'count' => $count, 135 | 'page' => $page 136 | ]; 137 | $result = self::get($api.http_build_query($param),$cookie); 138 | if($result){ 139 | $result = json_decode($result,true); 140 | return $result; 141 | }else{ 142 | return false; 143 | } 144 | } 145 | 146 | /** 147 | * 获取文件下载链接(获取文件信息) 148 | * @param string $parentId 文件ID 149 | * @param string $cookie teambitionCookie 150 | * @return array 151 | */ 152 | public static function get_download_url($parentId,$cookie){ 153 | $result = self::get('https://www.teambition.com/api/works/'.$parentId,$cookie); 154 | if($result){ 155 | $result = json_decode($result,true); 156 | if($result['downloadUrl']){ 157 | return $result; 158 | }else{ 159 | return false; 160 | } 161 | }else{ 162 | return false; 163 | } 164 | } 165 | 166 | public static function get_dir($parentId,$cookie){ 167 | $result = self::get('https://www.teambition.com/api/collections/'.$parentId,$cookie); 168 | if($result){ 169 | $result = json_decode($result,true); 170 | if($result){ 171 | return $result; 172 | }else{ 173 | return false; 174 | } 175 | }else{ 176 | return false; 177 | } 178 | } 179 | 180 | /** 181 | * 获取挂载网盘的相关配置 182 | * @param string $cookie teambitionCookie 183 | * @return array 184 | */ 185 | public static function get_pan_config($cookie){ 186 | $config = []; 187 | $org = self::get_orgId($cookie); 188 | if($org){ 189 | $config['orgId'] = $org['_id']; 190 | $config['memberId'] = $org['_creatorId']; 191 | $space = self::get_spaceId($cookie,$config['orgId'],$config['memberId']); 192 | if($space){ 193 | $config['spaceId'] = $space[0]['spaceId']; 194 | $config['rootId'] = $space[0]['rootId']; 195 | $drive = self::get_driveId($cookie,$config['orgId']); 196 | if($drive){ 197 | $config['driveId'] = $drive['data']['driveId']; 198 | return $config; 199 | }else{ 200 | return false; 201 | } 202 | }else{ 203 | return false; 204 | } 205 | }else{ 206 | return false; 207 | } 208 | } 209 | 210 | /** 211 | * 获取网盘文件列表 212 | * @param string $cookie teambitionCookie 213 | * @param string $orgId 214 | * @param string $spaceId 215 | * @param int $driveId 216 | * @param string $parentId 217 | * @param int $limit 218 | * @param int $offset 219 | * @return array 220 | */ 221 | public static function get_pan_list($cookie,$orgId,$spaceId,$driveId,$parentId,$limit=100,$offset=0){ 222 | $api = 'https://pan.teambition.com/pan/api/nodes?'; 223 | $param = [ 224 | 'orgId' => $orgId, 225 | 'spaceId' => $spaceId, 226 | 'driveId' => $driveId, 227 | 'parentId' => $parentId, 228 | 'offset' => $offset, 229 | 'limit' => $limit, 230 | 'orderBy' => 'updateTime', 231 | 'orderDirection' => 'desc' 232 | ]; 233 | $result = self::get($api.http_build_query($param),$cookie); 234 | if($result){ 235 | $result = json_decode($result,true); 236 | return $result; 237 | }else{ 238 | return false; 239 | } 240 | } 241 | 242 | /** 243 | * 获取网盘文件(文件夹)信息 244 | * @param string $cookie teambitionCookie 245 | * @param string $orgId 246 | * @param string $spaceId 247 | * @param int $driveId 248 | * @param string $parentId 249 | * @return array 250 | */ 251 | public static function get_pan_file($cookie,$orgId,$spaceId,$driveId,$parentId){ 252 | $api = 'https://pan.teambition.com/pan/api/nodes/'.$parentId.'?'; 253 | $param = [ 254 | 'orgId' => $orgId, 255 | 'spaceId' => $spaceId, 256 | 'driveId' => $driveId, 257 | ]; 258 | $result = self::get($api.http_build_query($param),$cookie); 259 | if($result){ 260 | $result = json_decode($result,true); 261 | return $result; 262 | }else{ 263 | return false; 264 | } 265 | } 266 | 267 | /** 268 | * 获取网盘的orgId&memberId 269 | * @param string $cookie teambitionCookie 270 | * @return array 271 | */ 272 | public static function get_orgId($cookie){ 273 | $api = 'https://www.teambition.com/api/organizations/personal'; 274 | $result = self::get($api,$cookie); 275 | if($result){ 276 | $result = json_decode($result,true); 277 | if($result['_id'] && $result['_creatorId']){ 278 | return $result; 279 | }else{ 280 | return false; 281 | } 282 | }else{ 283 | return false; 284 | } 285 | } 286 | 287 | /** 288 | * 获取网盘的spaceId&根rootId 289 | * @param string $cookie teambitionCookie 290 | * @param string $orgId 291 | * @param string $memberId 292 | * @return array 293 | */ 294 | public static function get_spaceId($cookie,$orgId,$memberId){ 295 | $api = 'https://pan.teambition.com/pan/api/spaces?'; 296 | $param = [ 297 | 'orgId' => $orgId, 298 | 'memberId' => $memberId 299 | ]; 300 | $result = self::get($api.http_build_query($param),$cookie); 301 | if($result){ 302 | $result = json_decode($result,true); 303 | if($result[0]['spaceId'] && $result[0]['rootId']){ 304 | return $result; 305 | }else{ 306 | return false; 307 | } 308 | }else{ 309 | return false; 310 | } 311 | } 312 | 313 | /** 314 | * 获取网盘的driveId 315 | * @param string $cookie teambitionCookie 316 | * @param string $orgId 317 | * @return array 318 | */ 319 | public static function get_driveId($cookie,$orgId){ 320 | $api = 'https://pan.teambition.com/pan/api/orgs/'.$orgId; 321 | $result = self::get($api,$cookie); 322 | if($result){ 323 | $result = json_decode($result,true); 324 | if($result['data']['driveId']){ 325 | return $result; 326 | }else{ 327 | return false; 328 | } 329 | }else{ 330 | return false; 331 | } 332 | } 333 | 334 | /** 335 | * Curl Json Post & Get 336 | * @param string $url 请求地址 337 | * @param string $cookie 请求携带Cookie 338 | * @param int $post 是否为POST 339 | * @param int $header 是否返回header 340 | */ 341 | public static function get($url,$cookie=false,$post=false,$header=false){ 342 | $ch = curl_init(); 343 | curl_setopt($ch, CURLOPT_URL,$url); 344 | curl_setopt($ch,CURLOPT_HEADER,$header); 345 | curl_setopt($ch, CURLOPT_COOKIE,$cookie); 346 | if($post){ 347 | curl_setopt($ch, CURLOPT_POST, 1); 348 | curl_setopt($ch, CURLOPT_POSTFIELDS,$post); 349 | curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); 350 | } 351 | curl_setopt($ch, CURLOPT_TIMEOUT,10); 352 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 353 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 354 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 355 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); 356 | curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36'); 357 | $result = curl_exec($ch); 358 | if($header){ 359 | $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 360 | $header = substr($result, 0, $headerSize); 361 | $body = substr($result, $headerSize); 362 | $result = []; 363 | $result['header'] = $header; 364 | $result['body'] = $body; 365 | } 366 | curl_close($ch); 367 | return $result; 368 | } 369 | } -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Healer-synwzx/TeambitionShare/cafee306a9c0a6698dd921515b753fabc0a8df72/favicon.ico -------------------------------------------------------------------------------- /framework/flx.php: -------------------------------------------------------------------------------- 1 | 5 | * [框架核心文件] 6 | */ 7 | namespace FlxPHP; 8 | class Flx{ 9 | public $_CFG; 10 | public $_SYS; 11 | 12 | public function run(){ 13 | //初始化 14 | $this->base(); 15 | 16 | //自动加载 17 | $this->autoload(); 18 | 19 | //框架函数 20 | include SYSTEMDIR.'function.php'; 21 | 22 | //检测加载应用目录的函数文件 23 | if(file_exists(APPDIR.'function.php'))include APPDIR.'function.php'; 24 | 25 | //加载配置 26 | $this->loadCfg(); 27 | 28 | //加载路由 29 | include_once SYSTEMDIR.'route.php'; 30 | include_once APPDIR.'route.php'; 31 | 32 | //处理请求 33 | $response = $this->request(); 34 | echo $response; 35 | } 36 | 37 | private function base(){ 38 | //设置编码 39 | header("Content-type: text/html; charset=utf-8"); 40 | 41 | //屏蔽NOTICE&WARNING报错 42 | error_reporting(E_ALL^E_WARNING^E_NOTICE); 43 | 44 | //设置时区 45 | date_default_timezone_set("PRC"); 46 | 47 | //根目录 48 | define('ROOTDIR', dirname(__DIR__) . '/'); 49 | 50 | //应用目录 51 | define('APPDIR', dirname(__DIR__) . '/app/'); 52 | 53 | //框架目录 54 | define('SYSTEMDIR', __DIR__ . '/'); 55 | 56 | //扩展目录 57 | define('EXTENDDIR', dirname(__DIR__). '/extend/'); 58 | 59 | //资源目录 60 | define('ASSETSDIR', dirname(__DIR__). '/public/'); 61 | 62 | //框架版本 63 | define('FLXPHP_VER','3.1'); 64 | 65 | //框架内部版本号 66 | define('FLXPHP_BUILD','3100'); 67 | 68 | //应用URL 69 | define('APPURL',((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://'). $_SERVER['HTTP_HOST']); 70 | } 71 | 72 | private function autoload(){ 73 | //设置加载目录 74 | set_include_path(APPDIR.PATH_SEPARATOR.EXTENDDIR.PATH_SEPARATOR.ROOTDIR.PATH_SEPARATOR.get_include_path()); 75 | 76 | //注册自动加载 77 | spl_autoload_register(function($classname){ 78 | if(substr($classname,0,3) == 'app'){ 79 | $classname = substr($classname,4); 80 | }elseif(substr($classname,0,6) == 'FlxPHP'){ 81 | $classname = substr($classname,7); 82 | } 83 | $classname = str_replace("\\","/",$classname); 84 | include_once $classname . '.php'; 85 | }); 86 | } 87 | 88 | private function request(){ 89 | $s = !empty($_GET['s']) ? $_GET['s'] : '/'; 90 | //去除首尾的 "/" 91 | if($s != '/' and substr($s,0,1) == '/'){ 92 | $s = substr($s,1); 93 | } 94 | if($s != '/' and substr($s,-1) == '/'){ 95 | $s = substr($s,0,-1); 96 | } 97 | 98 | $this->_SYS['route'] = Route::$instance->route; 99 | 100 | if(!$this->_SYS['route'])sys_error(['error' => '应用未设置路由']); 101 | 102 | $method = get_method(); 103 | 104 | if($method == 'get'){ 105 | $routes = $this->_SYS['route']['get']; 106 | }elseif($method == 'post'){ 107 | $routes = $this->_SYS['route']['post']; 108 | }else{ 109 | if(!$this->_SYS['route'])sys_error(['error' => '非法的请求方式']); 110 | } 111 | 112 | foreach($routes as $k => $v){ 113 | if($v['type'] == 'regex'){ 114 | preg_match_all('/{([^\/]+)}/',$k,$regexResult); 115 | if(!$regexResult)sys_error(['error' => '路由规则出错:'.$k]); 116 | $rule = str_replace('/','\\/',$k); 117 | $rule = '/^'.$rule.'$/'; 118 | 119 | $names = $regexResult[1]; 120 | foreach($names as $name){ 121 | if($v['regex'][$name]){ 122 | $rule = str_replace('{'.$name.'}','('.$v['regex'][$name].')',$rule); 123 | }else{ 124 | $rule = str_replace('{'.$name.'}','([^\/]+)',$rule); 125 | } 126 | } 127 | if(preg_match($rule,$s,$val)){ 128 | $val[count($val)] = $val[0]; 129 | unset($val[0]); 130 | if($v['method'] instanceof \Closure){ 131 | $run = $v['method']; 132 | return $run(...$val); 133 | }else{ 134 | $v['method'] = explode('@',$v['method']); 135 | $this->_SYS['controller'] = $v['method'][0]; 136 | $this->_SYS['action'] = $v['method'][1]; 137 | $this->_SYS['routeVal'] = $val; 138 | $this->_SYS['s'] = $s; 139 | break; 140 | } 141 | } 142 | }else{ 143 | if($s == $k){ 144 | if($v['method'] instanceof \Closure){ 145 | $run = $v['method']; 146 | return $run(); 147 | }else{ 148 | $v['method'] = explode('@',$v['method']); 149 | $this->_SYS['controller'] = $v['method'][0]; 150 | $this->_SYS['action'] = $v['method'][1]; 151 | $this->_SYS['routeVal'] = false; 152 | $this->_SYS['s'] = $s; 153 | break; 154 | } 155 | } 156 | } 157 | } 158 | 159 | if($this->_SYS['controller'] && $this->_SYS['action']){ 160 | //检查controller对应的文件是否存在 161 | if(!file_exists(APPDIR.'controller/'.$this->_SYS['controller'].'.php')){ 162 | sys_error([ 163 | 'error' => '未找到'.$this->_SYS['controller'].'控制器', 164 | 'info' => '在'.APPDIR.'controller目录未找到'.$this->_SYS['controller'].'.php文件' 165 | ]); 166 | } 167 | //实例化类并执行对应的类方法 168 | $run_class_name = 'app\\controller\\'. $this->_SYS['controller']; 169 | $run_action = $this->_SYS['action']; 170 | $run = new $run_class_name; 171 | if(method_exists($run,$run_action)) {//检查是否存在对应的方法 172 | //检查是否存在__init方法 用于防止子类重写父类的__construct方法 173 | if(method_exists($run,'__init'))$run->__init(); 174 | if($this->_SYS['routeVal']){ 175 | return $run->$run_action(...$this->_SYS['routeVal']); 176 | }else{ 177 | return $run->$run_action(); 178 | } 179 | }else{ 180 | sys_error([ 181 | 'error' => $this->_SYS['controller'].'控制器缺少'.$this->_SYS['action'].'方法', 182 | 'info' => '在'.APPDIR.'controller/'.$this->_SYS['controller'].'.php未找到'.$this->_SYS['action'].'方法' 183 | ]); 184 | } 185 | }else{ 186 | sys_error(['error' => '未匹配到路由']); 187 | } 188 | } 189 | 190 | private function loadCfg(){ 191 | $this->_CFG = []; 192 | //获取系统配置 193 | $this->_CFG = get_cfg(ROOTDIR . 'config/'); 194 | } 195 | } -------------------------------------------------------------------------------- /framework/function.php: -------------------------------------------------------------------------------- 1 | 5 | * [框架函数] 6 | */ 7 | 8 | /** 9 | * 系统错误提示 10 | * 系统级出错提示,关闭调试模式时显示系统出错 11 | */ 12 | function sys_error($error = []){ 13 | global $Flx; 14 | $debug = debug_backtrace(); 15 | $error['file'] = $debug[0]['file']; 16 | $error['line'] = $debug[0]['line']; 17 | if($Flx->_CFG['debug'] == true){ 18 | include SYSTEMDIR.'view/sys_error.php'; 19 | exit(); 20 | }else{ 21 | app_error(500); 22 | } 23 | } 24 | 25 | /** 26 | * 应用错误提示 27 | * 应用级别出错提示,不受调试模式影响 通常为开发者给用户的错误提示 28 | */ 29 | function app_error($e){ 30 | if(!is_array($e)){ 31 | if($e == 404){ 32 | $error['code'] = 404; 33 | $error['title'] = '啊哦~ 页面走丢辣~~~'; 34 | $error['error'] = '你的页面走丢辣(>﹏<)'; 35 | $error['info'] = '请确认地址是否正确或返回首页'; 36 | }elseif($e == 500){ 37 | $error['code'] = 500; 38 | $error['title'] = '系统出错'; 39 | $error['error'] = '系统在运行中出现错误'; 40 | $error['info'] = '如果你是网站用户请联系管理员解决'; 41 | } 42 | include SYSTEMDIR.'view/app_error.php'; 43 | exit(); 44 | }else{ 45 | $error = $e; 46 | include SYSTEMDIR.'view/app_error.php'; 47 | exit(); 48 | } 49 | } 50 | 51 | /** 52 | * 获取IP 53 | */ 54 | function real_ip() 55 | { 56 | $ip = $_SERVER['REMOTE_ADDR']; 57 | if (isset($_SERVER['HTTP_CF_CONNECTING_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CF_CONNECTING_IP'])) { 58 | $ip = $_SERVER['HTTP_CF_CONNECTING_IP']; 59 | } elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) { 60 | $ip = $_SERVER['HTTP_CLIENT_IP']; 61 | } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) { 62 | foreach ($matches[0] AS $xip) { 63 | if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) { 64 | $ip = $xip; 65 | break; 66 | } 67 | } 68 | } 69 | return $ip; 70 | } 71 | 72 | /** 73 | * 获取指定目录所有配置文件 74 | */ 75 | function get_cfg($path) 76 | { 77 | if (!file_exists($path)) { 78 | sys_error([ 79 | 'error' => '加载配置文件失败', 80 | 'info' => '请检查是否文件夹或文件是否存在' 81 | ]); 82 | } 83 | $cfg = []; 84 | chdir($path); 85 | $cfgs = glob('*.cfg.php'); 86 | if ($cfgs) { 87 | foreach ($cfgs as $c) { 88 | $content = include($path . $c); 89 | if (is_array($content)) { 90 | $cfg = array_merge($content, $cfg); 91 | } 92 | } 93 | return $cfg; 94 | } else { 95 | return []; 96 | } 97 | } 98 | 99 | /** 100 | * 将变量传入模板中 101 | */ 102 | function assign($name, $value = '') 103 | { 104 | global $Flx; 105 | if (empty($Flx->_SYS['tplval'])) { 106 | $Flx->_SYS['tplval'] = []; 107 | } 108 | if (is_array($name)) { 109 | $Flx->_SYS['tplval'] = array_merge($Flx->_SYS['tplval'], $name); 110 | } else { 111 | $Flx->_SYS['tplval'][$name] = $value; 112 | } 113 | } 114 | 115 | /** 116 | * 显示模板 117 | */ 118 | function view($t = 'default') 119 | { 120 | global $Flx; 121 | $type = '.html'; 122 | if (!empty($Flx->_SYS['tplval'])) extract($Flx->_SYS['tplval']); 123 | if ($t == 'default') { 124 | if (!file_exists(APPDIR . '/view/' . $Flx->_SYS['controller'] . '/' . $Flx->_SYS['action'] . $type)) { 125 | sys_error([ 126 | 'error' => '未找到' . $Flx->_SYS['controller'] . '/' . $Flx->_SYS['action'] . '模板', 127 | 'info' => '系统未找到'.$Flx->_SYS['controller'] . '/' . $Flx->_SYS['action'].'对应的模板' 128 | ]); 129 | } 130 | include_once APPDIR . '/view/' . $Flx->_SYS['controller'] . '/' . $Flx->_SYS['action'] . $type; 131 | } else { 132 | if (!file_exists(APPDIR . '/view/' . $t . $type)) { 133 | sys_error([ 134 | 'error' => '未找到' . $Flx->_SYS['controller'] . '/' . $Flx->_SYS['action'] . '模板', 135 | 'info' => '系统未找到'.$Flx->_SYS['controller'] . '/' . $Flx->_SYS['action'].'对应的模板' 136 | ]); 137 | } 138 | include_once APPDIR . '/view/' . $t . $type; 139 | } 140 | } 141 | 142 | /** 143 | * 模板路径助手函数 144 | */ 145 | function template($t) 146 | { 147 | global $Flx; 148 | $type = '.html'; 149 | $template = APPDIR . '/view/' . $t . $type; 150 | if (!file_exists($template)) { 151 | sys_error([ 152 | 'error' => '缺失' . $t . '模板', 153 | 'info' => '请检查是否文件夹或文件是否存在' 154 | ]); 155 | } 156 | return $template; 157 | } 158 | 159 | /** 160 | * 过滤字符 161 | */ 162 | function authstr($string, $force = 0, $strip = FALSE) 163 | { 164 | if (is_array($string)) { 165 | foreach ($string as $key => $val) { 166 | $string[$key] = authstr($val, $force, $strip); 167 | } 168 | } else { 169 | $string = addslashes($strip ? stripslashes($string) : $string); 170 | } 171 | return $string; 172 | } 173 | 174 | 175 | function get_method(){ 176 | $method = $_SERVER['REQUEST_METHOD']; 177 | 178 | if($method){ 179 | $method = strtolower($method); 180 | return $method; 181 | }else{ 182 | return false; 183 | } 184 | } -------------------------------------------------------------------------------- /framework/route.php: -------------------------------------------------------------------------------- 1 | 5 | * [路由模块] 6 | */ 7 | namespace FlxPHP; 8 | class Route{ 9 | /** 10 | * @var $instance Route实例 11 | * @var $route 路由规则数组 12 | * @var $tmp 用于传递信息的临时变量 13 | */ 14 | public static $instance; 15 | public $route; 16 | private $tmp; 17 | 18 | public static function match($type,$match,$method){ 19 | if(!self::$instance instanceof self)self::$instance = new Route(); 20 | $requestMethod = ['get','post']; 21 | if(!is_array($type)){ 22 | if(in_array($type,$requestMethod)){ 23 | if(preg_match('/{(.+)}/',$match)){ 24 | $matchType = 'regex'; 25 | }else{ 26 | $matchType = 'default'; 27 | } 28 | self::$instance->route[$type][$match] = ['method' => $method,'type' => $matchType]; 29 | self::$instance->tmp = ['type' => $type,'match' => $match]; 30 | return self::$instance; 31 | }else{ 32 | return sys_error(['error' => '不支持的请求类型']); 33 | } 34 | }else{ 35 | foreach($type as $t){ 36 | self::match($t,$match,$method); 37 | } 38 | self::$instance->tmp = ['type' => $type,'match' => $match]; 39 | return self::$instance; 40 | } 41 | } 42 | 43 | public static function get($match,$method){ 44 | return self::match('get',$match,$method); 45 | } 46 | 47 | public static function post($match,$method){ 48 | return self::match('post',$match,$method); 49 | } 50 | 51 | public static function any($match,$method){ 52 | return self::match(['get','post'],$match,$method); 53 | } 54 | 55 | public function where($param,$tmp=false){ 56 | if(!is_array($param))return; 57 | if(!$tmp)$tmp = self::$instance->tmp; 58 | 59 | if(!is_array($tmp['type'])){ 60 | foreach($param as $k => $v){ 61 | self::$instance->route[$tmp['type']][$tmp['match']]['regex'][$k] = $v; 62 | } 63 | }else{ 64 | foreach($tmp['type'] as $t){ 65 | $this->where($param,['type' => $t,'match' => $tmp['match']]); 66 | } 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /framework/view/app_error.php: -------------------------------------------------------------------------------- 1 | 5 | * [应用错误提示页模板] 6 | */ 7 | ?> 8 | 9 | 10 | 11 | 12 | 13 | <?=$error['title']?> 14 | 61 | 62 | 63 |
64 |

65 |

66 | 67 |

68 | 69 |

返回上一页

70 |
71 | 72 | -------------------------------------------------------------------------------- /framework/view/sys_error.php: -------------------------------------------------------------------------------- 1 | 5 | * [系统错误提示页模板] 6 | */ 7 | ?> 8 | 9 | 10 | 11 | 12 | 13 | Sysetm Error 14 | 61 | 62 | 63 |
64 |

SysetmError

65 |

66 | 67 |

[]

68 | 69 |

ErrorIN->#

70 |

FlxPHP V build

71 |

返回上一页

72 |
73 | 74 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 5 | * [入口文件] 6 | */ 7 | 8 | //引入框架 9 | include_once 'framework/flx.php'; 10 | 11 | $Flx = new FlxPHP\Flx(); 12 | 13 | $Flx->run(); -------------------------------------------------------------------------------- /nginx: -------------------------------------------------------------------------------- 1 | #根目录伪静态 2 | location / { 3 | if (!-e $request_filename){ 4 | rewrite ^(.*)$ /index.php/?s=$1; 5 | } 6 | } 7 | 8 | #二级目录伪静态(如果程序放在二级目录运行使用这个规则),自行修改pan为你的二级目录名字 9 | location /pan { 10 | if (!-e $request_filename){ 11 | rewrite ^/pan/(.*)$ /pan/index.php/?s=$1; 12 | } 13 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # TeambitionShare 2 | 挂载Teambition文件(网盘文件列表程序) 3 | ## 说明 4 | 已支持Teambition网盘(需申请)与Teambition项目 5 | **希望各位修改页面底部信息时保留本项目的github链接!** 6 | **如果升级版本时出现报错 请删除 config/app.cfg.php 然后在配置向导中重新生成配置** 7 | 8 | PHP版本要求 ≥ 5.6 9 | PHP版本推荐 ≥ 7.0 10 | 项目挂载演示站点:[tbfile.ouoacg.com](http://tbfile.ouoacg.com) 11 | 网盘挂载演示站点:[tbfile.ouoacg.com/pan](http://tbfile.ouoacg.com/pan) 访问密码:123456 12 | ## 一些问题 13 | 1.Cookie有效期 14 | 目前未遇到cookie失效的情况,猜测只要你不在官网手动退出登录就不会失效 15 | 2.下载速度 16 | 下载速度有些不稳定,有时快有时慢(1MB/S); 17 | 3.访问密码 18 | ①)全局密码 19 | 在config/app.cfg.php中添加 `'password' => '你要设置的密码'` 即可 20 | ②)目录密码 21 | 在目录下上传一个文件`.password`,文件内容即为目录密码 22 | 4.二级目录运行 23 | 放在二级目录运行,配置的时候填入对应的URL和[修改伪静态规则](#伪静态规则)(Apache无需修改)即可 24 | ## 如何使用 25 | 在没有配置文件时访问网站会跳转到配置向导,在配置向导页面填写对应的参数即可生成配置文件 26 | 27 | 先去 www.teambition.com 注册登录 28 | Cookie获取: 29 | F12 -> Network -> 刷新一下 找到如图所示的cookie 30 | ![image](https://ae01.alicdn.com/kf/U6ac816255ae44212a0b10f8d56b8cc01k.jpg) 31 | 32 | 项目ID(projectId)获取: 33 | 先创建一个项目,然后进入创建的项目 34 | ![image](https://ae01.alicdn.com/kf/U78fa30b3f30b47de96af1449808e153cV.jpg) 35 | ![image](https://ae01.alicdn.com/kf/Ube8a1476632a48c59f760d19fec97f79F.jpg) 36 | 37 | ## 伪静态规则 38 | 39 | ### Nginx 40 | ``` 41 | # 根目录伪静态 42 | location / { 43 | if (!-e $request_filename){ 44 | rewrite ^(.*)$ /index.php/?s=$1; 45 | } 46 | } 47 | # 二级目录伪静态,自行修改pan为你的二级目录名字 48 | location /pan { 49 | if (!-e $request_filename){ 50 | rewrite ^/pan/(.*)$ /pan/index.php/?s=$1; 51 | } 52 | } 53 | ``` 54 | 55 | ### Apache 56 | ``` 57 | 58 | Options +FollowSymlinks -Multiviews 59 | RewriteEngine On 60 | RewriteCond %{REQUEST_FILENAME} !-d 61 | RewriteCond %{REQUEST_FILENAME} !-f 62 | RewriteRule ^(.*)$ index.php/?s=$1 [QSA,PT,L] 63 | 64 | ``` 65 | 66 | ## Docker 67 | ``` 68 | docker pull flxsnx/teambitionshare 69 | docker run -d -p 8081:80 flxsnx/teambitionshare:latest 70 | # 访问: http://ip:8081 71 | ``` --------------------------------------------------------------------------------