├── README.md ├── _files ├── config │ └── config.php └── plugins │ └── tasks.php ├── css └── files.css ├── index.php └── js └── files.js /README.md: -------------------------------------------------------------------------------- 1 | # 简单介绍一下 2 | 3 | 文件是一个单文件PHP应用程序,可以下降到你的服务器上的任何目录,立即创建文件和文件夹库。它支持所有文件类型,并允许您预览图像、视频、音频和代码。 4 | 5 | - 单个文件。只需将它放入服务器上的任何目录中即可。 6 | - 实时搜索和排序文件。 7 | - 可实时切换的高级列表和库布局。 8 | - 预览照片的 IPTC、EXIF 和 GPS 地图。 9 | - 使用缓存机制和 CDN 快速加载。 10 | - 高级树菜单导航显示整个目录结构。 11 | - 美丽的代码荧光笔,用于查看和编辑代码格式。 12 | - 可选登录以保护访问。 13 | - 上传,移动,复制和删除文件即将推出! 14 | 15 | # 安装教程 16 | 17 | - 🔗传送门:[https://www.skyqian.com/archives/files_photo_gallery.html](https://www.skyqian.com/archives/files_photo_gallery.html) 18 | -------------------------------------------------------------------------------- /_files/config/config.php: -------------------------------------------------------------------------------- 1 | '', 7 | //'start_path' => false, 8 | //'username' => '', 9 | //'password' => '', 10 | //'load_images' => true, 11 | //'load_files_proxy_php' => false, 12 | //'load_images_max_filesize' => 1000000, 13 | //'load_svg_max_filesize' => 100000, 14 | //'image_resize_enabled' => true, 15 | //'image_resize_cache' => true, 16 | //'image_resize_dimensions' => 320, 17 | //'image_resize_dimensions_retina' => 480, 18 | //'image_resize_quality' => 85, 19 | //'image_resize_function' => 'imagecopyresampled', 20 | //'image_resize_sharpen' => true, 21 | //'image_resize_memory_limit' => 128, 22 | //'image_resize_max_pixels' => 30000000, 23 | //'image_resize_min_ratio' => 1.5, 24 | //'image_resize_cache_direct' => false, 25 | //'menu_enabled' => true, 26 | //'menu_show' => true, 27 | //'menu_max_depth' => 5, 28 | //'menu_sort' => 'name_asc', 29 | //'menu_cache_validate' => true, 30 | //'menu_load_all' => false, 31 | //'menu_recursive_symlinks' => true, 32 | //'layout' => 'rows', 33 | //'image_cover' => true, 34 | //'sort' => 'name_asc', 35 | //'sort_dirs_first' => true, 36 | //'cache' => true, 37 | //'cache_key' => 0, 38 | //'storage_path' => '_files', 39 | //'files_exclude' => '', 40 | //'dirs_exclude' => '', 41 | //'allow_symlinks' => true, 42 | //'history' => true, 43 | //'breadcrumbs' => true, 44 | //'transitions' => true, 45 | //'click' => 'popup', 46 | //'code_max_load' => 100000, 47 | //'code_allow_edit' => false, 48 | //'popup_interval' => 5000, 49 | //'topbar_sticky' => 'scroll', 50 | //'check_updates' => true, 51 | //'allow_tasks' => true, 52 | //'get_mime_type' => false, 53 | //'context_menu' => true, 54 | //'prevent_right_click' => false, 55 | //'license_key' => '', 56 | ); -------------------------------------------------------------------------------- /_files/plugins/tasks.php: -------------------------------------------------------------------------------- 1 | ?task=$task

Available tasks
[" . implode(', ', $tasks_array) . ']', 400); 27 | 28 | // set time limit 29 | $time_limit = get('time_limit'); 30 | if($time_limit) set_time_limit(intval($time_limit)); 31 | 32 | // vars 33 | function iz($p){ return isset($_GET[$p]);} 34 | $output = ''; 35 | $force = iz('force'); 36 | $do_all = iz('all'); 37 | $do_menu = $do_all || iz('menu'); 38 | $do_folders = $do_all || iz('folders'); 39 | $do_images = $do_all || iz('images'); 40 | 41 | // memory limit (used when $do_images) 42 | $memory_limit = $do_images ? (get('memory_limit') ?: config::$config['image_resize_memory_limit']) : false; 43 | if($memory_limit && is_numeric($memory_limit) && function_exists('ini_get') && $memory_limit > (int) @ini_get('memory_limit') && (!function_exists('ini_set') || !@ini_set('memory_limit', $memory_limit . 'M'))) error('Failed to set memory limit [' . $memory_limit . ']'); 44 | 45 | // processed 46 | class processed { 47 | public static $folders = 0; 48 | public static $folders_count = 0; 49 | public static $images = 0; 50 | public static $images_count = 0; 51 | public static $menu = 0; 52 | public static $menu_count = 0; 53 | } 54 | 55 | // add output 56 | function add_output($create = true, $count, $total, $force){ 57 | $action = $create ? 'created' : 'removed'; 58 | $items = $total === 1 ? 'item' : 'items'; 59 | return ' cache items ' . $action . ': [' . $count . ' / ' . $total . ']' . ($total && $force ? ' (force ' . $action . ')' : '') . ($count === $total ? '' : ' (' . ($total - $count) . ' ' . $items . ' still valid)') . '
'; 60 | } 61 | 62 | // task: create_html [beta] 63 | if($task === 'create_html'){ 64 | if(config::$has_login) error('Cannot create html when login is enabled. Pointless!', 400); 65 | $time = time(); 66 | $url = 'http' . (!empty($_SERVER['HTTPS']) ? 's' : '' ) . '://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'] . '?index_html=' . $time; 67 | $content = file_get_contents($url); 68 | if(!$content) error("Failed to execute file_get_contents('$url');", 500); 69 | $put = file_put_contents('index.html', '' . PHP_EOL . preg_replace('/\s+/', ' ', $content)); 70 | if(!$put) error("Failed to execute file_put_contents('$url');", 500); 71 | $output = "Successfully created index.html at $time"; 72 | 73 | // task: create_cache [beta] 74 | } else if($task === 'create_cache') { 75 | 76 | // early exit 77 | if(!config::$config['cache']) exit('cache is disabled.'); 78 | 79 | // create folders and images 80 | if($do_folders || $do_images) { 81 | 82 | // create cache loop function 83 | function create_cache($dir, $do_folders = false, $do_images = false, $force = false, $depth = 0){ 84 | 85 | // exclude 86 | if(is_exclude($dir)) return 0; 87 | 88 | // dir cache path 89 | processed::$folders_count ++; 90 | $cache = get_dir_cache_path($dir); 91 | $cache_exists = file_exists($cache); 92 | $cache_recreate = $force || !$cache_exists ? true : false; 93 | $get_dir = $do_images || $cache_recreate ? true : false; 94 | 95 | // get dir 96 | if($get_dir){ 97 | 98 | // dir from cache or new 99 | $arr = $cache_recreate ? get_dir($dir, true) : json_decode(file_get_contents($cache), true); 100 | 101 | // resize images 102 | if($do_images && config::$config['image_resize_enabled'] && config::$config['image_resize_cache'] && !empty($arr) && !empty($arr['files'])){ 103 | $dirs = array(); 104 | $image_sizes = array(config::$config['image_resize_dimensions']); 105 | if(config::$image_resize_dimensions_retina) $image_sizes[] = config::$image_resize_dimensions_retina; 106 | foreach ($arr['files'] as $filename => $props) { 107 | if($props['filetype'] === 'dir'){ 108 | $dirs[] = root_absolute($props['path']); 109 | continue; 110 | } 111 | if(!isset($props['image'])) continue; 112 | 113 | // exif orientation 114 | $orientation = isset($props['image']['exif']['Orientation']) ? $props['image']['exif']['Orientation'] : 0; 115 | 116 | // original dimensions / get physical 117 | $original_width = $props['image'][($orientation > 4 && $orientation < 9 ? 'height' : 'width')]; 118 | $original_height = $props['image'][($orientation > 4 && $orientation < 9 ? 'width' : 'height')]; 119 | 120 | // image_resize_max_pixels early exit 121 | if(config::$config['image_resize_max_pixels'] && $original_width * $original_height > config::$config['image_resize_max_pixels']) continue; 122 | 123 | // vars 124 | $type = $props['image']['type']; 125 | $path = root_absolute($props['path']); 126 | 127 | // loop image sizes 128 | foreach ($image_sizes as $index => $image_size) { 129 | 130 | // ratio 131 | $ratio = max($original_width, $original_height) / $image_size; 132 | if($ratio < max(config::$config['image_resize_min_ratio'], 1)) continue; 133 | 134 | // cache path 135 | $image_cache = get_image_cache_path($path, $image_size, $props['filesize'], $props['mtime']); 136 | $image_cache_exists = file_exists($image_cache); 137 | 138 | // skip if cache exists 139 | if($image_cache_exists){ 140 | processed::$images_count ++; 141 | 142 | // create image acche 143 | } else { 144 | 145 | // image create 146 | $image = image_create_from($path, $type); 147 | if(!$image) break; 148 | 149 | // count 150 | processed::$images_count ++; 151 | 152 | // Calculate new image dimensions. 153 | $new_width = round($original_width / $ratio); 154 | $new_height = round($original_height / $ratio); 155 | 156 | // new image 157 | $new_image = imagecreatetruecolor($new_width, $new_height); 158 | call_user_func(config::$config['image_resize_function'], $new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $original_width, $original_height); 159 | 160 | // destroy original $image resource 161 | imagedestroy($image); 162 | 163 | // fix orientation according to exif 164 | exif_orientation($orientation, $new_image); 165 | 166 | // sharpen resized image 167 | if(config::$config['image_resize_sharpen']) sharpen_image($new_image); 168 | 169 | // save as cache 170 | if(imagejpeg($new_image, $image_cache, config::$config['image_resize_quality'])) processed::$images ++; 171 | 172 | // detroy $new_image resource 173 | imagedestroy($new_image); 174 | } 175 | 176 | // add image resize cache direct to $arr 177 | if($cache_recreate && config::$image_resize_cache_direct) $arr['files'][$filename]['image']['resize' . $image_size] = get_url_path($image_cache); 178 | } 179 | } 180 | } 181 | 182 | // save json 183 | if($cache_recreate) { 184 | $json = empty($arr) ? '{}' : json_encode($arr, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); 185 | if(file_put_contents($cache, $json)) processed::$folders ++; 186 | } 187 | } 188 | 189 | // max depth 190 | if(!iz('ignore_max_depth') && config::$config['menu_max_depth'] && $depth >= config::$config['menu_max_depth']) return; 191 | 192 | // subdirs 193 | if($get_dir){ 194 | if(!isset($dirs)){ 195 | $dirs = array(); 196 | foreach ($arr['files'] as $key => $val) if($val['filetype'] === 'dir') $dirs[] = root_absolute($val['path']); 197 | } 198 | 199 | // glob subdirs 200 | } else { 201 | $dirs = glob($dir . '/*', GLOB_NOSORT|GLOB_ONLYDIR); 202 | } 203 | 204 | // sub dirs 205 | if(!empty($dirs)) foreach($dirs as $dir) create_cache($dir, $do_folders, $do_images, $force, $depth + 1); 206 | } 207 | 208 | // start create cache loop 209 | $start_dir = get('dir'); 210 | if($start_dir){ 211 | $start_dir = real_path($start_dir); 212 | if(!$start_dir) error('Dir does not exist dir=' . get('dir') . '', 404); 213 | } 214 | create_cache($start_dir?:config::$root, $do_folders, $do_images, $force); 215 | } 216 | 217 | // create menu 218 | if($do_menu) { 219 | $menu_cache_hash = get_menu_cache_hash(get_root_dirs()); 220 | $menu_cache_file = config::$cache_path . DIRECTORY_SEPARATOR . 'menu' . DIRECTORY_SEPARATOR . $menu_cache_hash . '.json'; 221 | processed::$menu_count = 1; 222 | 223 | // recreate menu 224 | if($force || !get_valid_menu_cache($menu_cache_file)){ 225 | $menu_cache_arr = get_dirs(config::$root); 226 | $menu_cache_json = empty($menu_cache_arr) ? '{}' : json_encode($menu_cache_arr, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); 227 | if(file_put_contents($menu_cache_file, $menu_cache_json)) processed::$menu ++; 228 | } 229 | } 230 | 231 | // output 232 | if($do_menu) $output .= 'Menu' . add_output(true, processed::$menu, processed::$menu_count, $force); 233 | if($do_folders || $do_images) $output .= 'Folders' . add_output(true, processed::$folders, processed::$folders_count, $force); 234 | if($do_images) $output .= 'Images' . add_output(true, processed::$images, processed::$images_count, false); 235 | 236 | // clear cache [beta] 237 | } else if($task === 'clear_cache'){ 238 | 239 | // get cache items 240 | function get_cache_items($dir, $ext){ 241 | $cache_path = config::$cache_path . DIRECTORY_SEPARATOR . $dir; 242 | if(!file_exists($cache_path)) return array(); 243 | return glob($cache_path . '/*.' . $ext, GLOB_NOSORT); 244 | } 245 | 246 | // menu 247 | if($do_menu){ 248 | $menu_cache_items = get_cache_items('menu', 'json'); 249 | processed::$menu_count = count($menu_cache_items); 250 | if(processed::$menu_count){ 251 | $menu_cache_hash = $force ? false : get_menu_cache_hash(get_root_dirs()); 252 | foreach ($menu_cache_items as $menu_cache_item) { 253 | if($force || basename($menu_cache_item) !== $menu_cache_hash . '.json') { 254 | if(unlink($menu_cache_item)) processed::$menu ++; 255 | } 256 | } 257 | } 258 | $output .= 'Menu' . add_output(false, processed::$menu, processed::$menu_count, $force); 259 | } 260 | 261 | // folders 262 | if($do_folders){ 263 | $dirs_cache_items = get_cache_items('folders', 'json'); 264 | processed::$folders_count = count($dirs_cache_items); 265 | if(processed::$folders_count){ 266 | foreach ($dirs_cache_items as $dirs_cache_item) { 267 | if($force || strpos(basename($dirs_cache_item), config::$dirs_hash) !== 0) { 268 | if(unlink($dirs_cache_item)) processed::$folders ++; 269 | continue; 270 | } 271 | $dir_cache_content = file_get_contents($dirs_cache_item); 272 | if($dir_cache_content){ 273 | $dir_cache_json = json_decode($dir_cache_content, true); 274 | $dir_abs_path = root_absolute($dir_cache_json['path']); 275 | if(!file_exists($dir_abs_path) || $dir_cache_json['mtime'] !== filemtime($dir_abs_path)) { 276 | if(unlink($dirs_cache_item)) processed::$folders ++; 277 | } 278 | } 279 | } 280 | } 281 | $output .= 'Folders' . add_output(false, processed::$folders, processed::$folders_count, $force); 282 | } 283 | 284 | // images 285 | if($do_images){ 286 | $image_cache_items = get_cache_items('images', 'jpg'); 287 | processed::$images_count = count($image_cache_items); 288 | if(processed::$images_count){ 289 | foreach ($image_cache_items as $image_cache_item) { 290 | if($force){ 291 | if(unlink($image_cache_item)) processed::$images ++; 292 | continue; 293 | } 294 | $image_cache_item_arr = explode('.', basename($image_cache_item)); 295 | $resize_val = isset($image_cache_item_arr[3]) && is_numeric($image_cache_item_arr[3]) ? intval($image_cache_item_arr[3]) : false; 296 | if(!$resize_val || !in_array($resize_val, [config::$config['image_resize_dimensions'], config::$image_resize_dimensions_retina])) { 297 | if(unlink($image_cache_item)) processed::$images ++; 298 | } 299 | } 300 | } 301 | $output .= 'Image' . add_output(false, processed::$images, processed::$images_count, $force); 302 | } 303 | 304 | // invalid task command 305 | } else { 306 | error("Invalid task command task=$task", 400); 307 | } 308 | 309 | // output 310 | header('files-msg: task [' . header_memory_time() . ']'); 311 | if(!$output) error('No cache parameters selected [menu, folders, images, all]', 400); 312 | echo $output . '
-
Processed in ' . round((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']), 2) . ' seconds.'; 313 | 314 | 315 | -------------------------------------------------------------------------------- /css/files.css: -------------------------------------------------------------------------------- 1 | :root{--col25: #F8F9Fa;--col50: #ECEFF1;--col100: #CFD8DC;--col200: #B0BEC5;--col300: #90A4AE;--col400: #78909C;--col500: #607D8B;--col600: #546E7A;--col700: #455A64;--col800: #37474F;--col900: #263238;--col950: #1c2429;--google-red: #d85040;--strong-color: #2e8b57}:root{--bs-blue: #0d6efd;--bs-indigo: #6610f2;--bs-purple: #6f42c1;--bs-pink: #d63384;--bs-red: #dc3545;--bs-orange: #fd7e14;--bs-yellow: #ffc107;--bs-green: #78a642;--bs-teal: #20c997;--bs-cyan: #17a2b8;--bs-white: #fff;--bs-gray: #6c757d;--bs-gray-dark: #343a40;--bs-primary: #2e8b57;--bs-secondary: #6c757d;--bs-success: #78a642;--bs-info: #17a2b8;--bs-warning: #ffc107;--bs-danger: #dc3545;--bs-light: #f8f9fa;--bs-dark: #343a40;--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--bs-gradient: linear-gradient(180deg, rgba(255,255,255,0.15), rgba(255,255,255,0))}*,*::before,*::after{box-sizing:border-box}body{margin:0;font-family:var(--bs-font-sans-serif);font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#ECEFF1;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}[tabindex="-1"]:focus:not(:focus-visible){outline:0 !important}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,.h1,h2,.h2,h3,.h3,h4,.h4,h5,.h5,h6,.h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:#455A64}h1,.h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width: 1200px){h1,.h1{font-size:2.5rem}}h2,.h2{font-size:calc(1.325rem + .9vw)}@media (min-width: 1200px){h2,.h2{font-size:2rem}}h3,.h3{font-size:calc(1.3rem + .6vw)}@media (min-width: 1200px){h3,.h3{font-size:1.75rem}}h4,.h4{font-size:calc(1.275rem + .3vw)}@media (min-width: 1200px){h4,.h4{font-size:1.5rem}}h5,.h5{font-size:1.25rem}h6,.h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-original-title]{text-decoration:underline;text-decoration:underline dotted;cursor:help;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:600}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:600}small,.small{font-size:.875em}mark,.mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#2e8b57;text-decoration:none}a:hover{color:#1b5233;text-decoration:underline}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:var(--bs-font-monospace);font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em;-ms-overflow-style:scrollbar}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:600}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}thead,tbody,tfoot,tr,td,th{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role="button"]{cursor:pointer}select{word-wrap:normal}[list]::-webkit-calendar-picker-indicator{display:none}button,[type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button:not(:disabled),[type="button"]:not(:disabled),[type="reset"]:not(:disabled),[type="submit"]:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit;white-space:normal}@media (min-width: 1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-text,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type="search"]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none !important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.form-label{margin-bottom:.5rem;font-weight:500}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;font-weight:500;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:#6c757d}.form-control{display:block;width:100%;min-height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#546E7A;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;appearance:none;border-radius:.15rem;transition:border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-control{transition:none}}.form-control:focus{color:#546E7A;background-color:#fff;border-color:#6bce96;outline:0;box-shadow:0 0 0 .2rem rgba(46,139,87,0.25)}.form-control::placeholder{color:#90A4AE;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.form-control-lg{min-height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;border-radius:3px}.form-control-color{max-width:3rem;padding:.375rem}.form-control-color::-moz-color-swatch{border-radius:.15rem}.form-control-color::-webkit-color-swatch{border-radius:.15rem}.form-select{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#546E7A;vertical-align:middle;background-color:#fff;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:1px solid #ced4da;border-radius:.15rem;appearance:none}.form-select:focus{border-color:#6bce96;outline:0;box-shadow:0 0 0 .2rem rgba(46,139,87,0.25)}.form-select:focus::-ms-value{color:#546E7A;background-color:#fff}.form-select[multiple],.form-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.form-select:disabled{color:#6c757d;background-color:#e9ecef}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #546E7A}.form-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.form-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.form-check{display:block;min-height:1.5rem;padding-left:1.75em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.75em}.form-check-input{width:1.25em;height:1.25em;margin-top:.125em;vertical-align:top;background-color:#ECEFF1;background-repeat:no-repeat;background-position:center;background-size:contain;border:1px solid rgba(0,0,0,0.25);appearance:none;color-adjust:exact;transition:background-color 0.15s ease-in-out,background-position 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-check-input{transition:none}}.form-check-input[type="checkbox"]{border-radius:.25em}.form-check-input[type="radio"]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#6bce96;outline:0;box-shadow:0 0 0 .2rem rgba(46,139,87,0.25)}.form-check-input:checked{background-color:#2e8b57;border-color:#2e8b57}.form-check-input:checked[type="checkbox"]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type="radio"]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type="checkbox"]:indeterminate{background-color:#2e8b57;border-color:#2e8b57;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input[disabled] ~ .form-check-label,.form-check-input:disabled ~ .form-check-label{opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{width:2em;margin-left:-2.5em;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280,0,0,0.25%29'/%3e%3c/svg%3e");background-position:left center;border-radius:2em}.form-switch .form-check-input:focus{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%236bce96'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.form-file{--bs-form-file-height: calc(1.5em + .75rem + 2px);position:relative}.form-file-input{position:relative;z-index:2;width:100%;height:var(--bs-form-file-height);margin:0;opacity:0}.form-file-input:focus-within ~ .form-file-label{border-color:#6bce96;box-shadow:0 0 0 .2rem rgba(46,139,87,0.25)}.form-file-input[disabled] ~ .form-file-label .form-file-text,.form-file-input:disabled ~ .form-file-label .form-file-text{background-color:#e9ecef}.form-file-label{position:absolute;top:0;right:0;left:0;z-index:1;display:flex;height:var(--bs-form-file-height);border-color:#ced4da;border-radius:.15rem}.form-file-text{display:block;flex-grow:1;padding:.375rem .75rem;overflow:hidden;font-weight:400;line-height:1.5;color:#546E7A;text-overflow:ellipsis;white-space:nowrap;background-color:#fff;border-color:inherit;border-style:solid;border-width:1px;border-top-left-radius:inherit;border-bottom-left-radius:inherit}.form-file-button{display:block;flex-shrink:0;padding:.375rem .75rem;margin-left:-1px;line-height:1.5;color:#546E7A;background-color:#e9ecef;border-color:inherit;border-style:solid;border-width:1px;border-top-right-radius:inherit;border-bottom-right-radius:inherit}.form-file-sm{--bs-form-file-height: calc(1.5em + .5rem + 2px);font-size:.875rem}.form-file-sm .form-file-text,.form-file-sm .form-file-button{padding:.25rem .5rem}.form-file-lg{--bs-form-file-height: calc(1.5em + 1rem + 2px);font-size:1.25rem}.form-file-lg .form-file-text,.form-file-lg .form-file-button{padding:.5rem 1rem}.form-range{width:100%;height:1.4rem;padding:0;background-color:transparent;appearance:none}.form-range:focus{outline:none}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #ECEFF1,0 0 0 .2rem rgba(46,139,87,0.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #ECEFF1,0 0 0 .2rem rgba(46,139,87,0.25)}.form-range:focus::-ms-thumb{box-shadow:0 0 0 1px #ECEFF1,0 0 0 .2rem rgba(46,139,87,0.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#2e8b57;border:0;border-radius:1rem;transition:background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out;appearance:none}@media (prefers-reduced-motion: reduce){.form-range::-webkit-slider-thumb{transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#91dbb1}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#2e8b57;border:0;border-radius:1rem;transition:background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out;appearance:none}@media (prefers-reduced-motion: reduce){.form-range::-moz-range-thumb{transition:none}}.form-range::-moz-range-thumb:active{background-color:#91dbb1}.form-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.form-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#2e8b57;border:0;border-radius:1rem;transition:background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out;appearance:none}@media (prefers-reduced-motion: reduce){.form-range::-ms-thumb{transition:none}}.form-range::-ms-thumb:active{background-color:#91dbb1}.form-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.form-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.form-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.form-range:disabled::-moz-range-thumb{background-color:#adb5bd}.form-range:disabled::-ms-thumb{background-color:#adb5bd}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select,.input-group>.form-file{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-select:focus,.input-group>.form-file .form-file-input:focus ~ .form-file-label{z-index:3}.input-group>.form-file>.form-file-input:focus{z-index:4}.input-group>.form-file:not(:last-child)>.form-file-label{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.form-file:not(:first-child)>.form-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:3}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#546E7A;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.15rem}.input-group-lg>.form-control{min-height:calc(1.5em + 1rem + 2px)}.input-group-lg>.form-select{height:calc(1.5em + 1rem + 2px)}.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text,.input-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem;border-radius:3px}.input-group-sm>.form-control{min-height:calc(1.5em + .5rem + 2px)}.input-group-sm>.form-select{height:calc(1.5em + .5rem + 2px)}.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text,.input-group-sm>.btn{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:1.75rem}.input-group>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu),.input-group>.dropdown-toggle:nth-last-child(n+3){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu){margin-left:-1px;border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#78a642}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#212529;background-color:rgba(120,166,66,0.9);border-radius:.15rem}.was-validated :valid ~ .valid-feedback,.was-validated :valid ~ .valid-tooltip,.is-valid ~ .valid-feedback,.is-valid ~ .valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:#78a642;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2378a642' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:#78a642;box-shadow:0 0 0 .2rem rgba(120,166,66,0.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.was-validated .form-select:valid,.form-select.is-valid{border-color:#78a642;padding-right:calc(.75em + 2.3125rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2378a642' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-position:right .75rem center,center right 1.75rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-select:valid:focus,.form-select.is-valid:focus{border-color:#78a642;box-shadow:0 0 0 .2rem rgba(120,166,66,0.25)}.was-validated .form-check-input:valid,.form-check-input.is-valid{border-color:#78a642}.was-validated .form-check-input:valid:checked,.form-check-input.is-valid:checked{background-color:#78a642}.was-validated .form-check-input:valid:focus,.form-check-input.is-valid:focus{box-shadow:0 0 0 .2rem rgba(120,166,66,0.25)}.was-validated .form-check-input:valid ~ .form-check-label,.form-check-input.is-valid ~ .form-check-label{color:#78a642}.form-check-inline .form-check-input ~ .valid-feedback{margin-left:.5em}.was-validated .form-file-input:valid ~ .form-file-label,.form-file-input.is-valid ~ .form-file-label{border-color:#78a642}.was-validated .form-file-input:valid:focus ~ .form-file-label,.form-file-input.is-valid:focus ~ .form-file-label{border-color:#78a642;box-shadow:0 0 0 .2rem rgba(120,166,66,0.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(220,53,69,0.9);border-radius:.15rem}.was-validated :invalid ~ .invalid-feedback,.was-validated :invalid ~ .invalid-tooltip,.is-invalid ~ .invalid-feedback,.is-invalid ~ .invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,0.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.was-validated .form-select:invalid,.form-select.is-invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-position:right .75rem center,center right 1.75rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-select:invalid:focus,.form-select.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,0.25)}.was-validated .form-check-input:invalid,.form-check-input.is-invalid{border-color:#dc3545}.was-validated .form-check-input:invalid:checked,.form-check-input.is-invalid:checked{background-color:#dc3545}.was-validated .form-check-input:invalid:focus,.form-check-input.is-invalid:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,0.25)}.was-validated .form-check-input:invalid ~ .form-check-label,.form-check-input.is-invalid ~ .form-check-label{color:#dc3545}.form-check-inline .form-check-input ~ .invalid-feedback{margin-left:.5em}.was-validated .form-file-input:invalid ~ .form-file-label,.form-file-input.is-invalid ~ .form-file-label{border-color:#dc3545}.was-validated .form-file-input:invalid:focus ~ .form-file-label,.form-file-input.is-invalid:focus ~ .form-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,0.25)}.btn{display:inline-block;font-weight:500;line-height:1.5;color:#212529;text-align:center;vertical-align:middle;cursor:pointer;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;border-radius:.15rem;transition:color 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn-check:focus+.btn,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(46,139,87,0.25)}.btn:disabled,.btn.disabled,fieldset:disabled .btn{pointer-events:none;opacity:1}.btn-primary{color:#fff;background-color:#2e8b57;border-color:#2e8b57}.btn-primary:hover{color:#fff;background-color:#246e45;border-color:#21653f}.btn-check:focus+.btn-primary,.btn-primary:focus{color:#fff;background-color:#246e45;border-color:#21653f;box-shadow:0 0 0 .2rem rgba(77,156,112,0.5)}.btn-check:checked+.btn-primary,.btn-check:active+.btn-primary,.btn-primary:active,.btn-primary.active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#21653f;border-color:#1e5b39}.btn-check:checked+.btn-primary:focus,.btn-check:active+.btn-primary:focus,.btn-primary:active:focus,.btn-primary.active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(77,156,112,0.5)}.btn-primary:disabled,.btn-primary.disabled{color:#fff;background-color:#2e8b57;border-color:#2e8b57}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-check:focus+.btn-secondary,.btn-secondary:focus{color:#fff;background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(130,138,145,0.5)}.btn-check:checked+.btn-secondary,.btn-check:active+.btn-secondary,.btn-secondary:active,.btn-secondary.active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-check:checked+.btn-secondary:focus,.btn-check:active+.btn-secondary:focus,.btn-secondary:active:focus,.btn-secondary.active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,0.5)}.btn-secondary:disabled,.btn-secondary.disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-success{color:#212529;background-color:#78a642;border-color:#78a642}.btn-success:hover{color:#fff;background-color:#648b37;border-color:#5e8233}.btn-check:focus+.btn-success,.btn-success:focus{color:#fff;background-color:#648b37;border-color:#5e8233;box-shadow:0 0 0 .2rem rgba(107,147,62,0.5)}.btn-check:checked+.btn-success,.btn-check:active+.btn-success,.btn-success:active,.btn-success.active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#5e8233;border-color:#577830}.btn-check:checked+.btn-success:focus,.btn-check:active+.btn-success:focus,.btn-success:active:focus,.btn-success.active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(107,147,62,0.5)}.btn-success:disabled,.btn-success.disabled{color:#212529;background-color:#78a642;border-color:#78a642}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-check:focus+.btn-info,.btn-info:focus{color:#fff;background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(58,176,195,0.5)}.btn-check:checked+.btn-info,.btn-check:active+.btn-info,.btn-info:active,.btn-info.active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-check:checked+.btn-info:focus,.btn-check:active+.btn-info:focus,.btn-info:active:focus,.btn-info.active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,0.5)}.btn-info:disabled,.btn-info.disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-check:focus+.btn-warning,.btn-warning:focus{color:#212529;background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(222,170,12,0.5)}.btn-check:checked+.btn-warning,.btn-check:active+.btn-warning,.btn-warning:active,.btn-warning.active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-check:checked+.btn-warning:focus,.btn-check:active+.btn-warning:focus,.btn-warning:active:focus,.btn-warning.active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,0.5)}.btn-warning:disabled,.btn-warning.disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-check:focus+.btn-danger,.btn-danger:focus{color:#fff;background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(225,83,97,0.5)}.btn-check:checked+.btn-danger,.btn-check:active+.btn-danger,.btn-danger:active,.btn-danger.active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-check:checked+.btn-danger:focus,.btn-check:active+.btn-danger:focus,.btn-danger:active:focus,.btn-danger.active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,0.5)}.btn-danger:disabled,.btn-danger.disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-check:focus+.btn-light,.btn-light:focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(216,217,219,0.5)}.btn-check:checked+.btn-light,.btn-check:active+.btn-light,.btn-light:active,.btn-light.active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-check:checked+.btn-light:focus,.btn-check:active+.btn-light:focus,.btn-light:active:focus,.btn-light.active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,0.5)}.btn-light:disabled,.btn-light.disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-check:focus+.btn-dark,.btn-dark:focus{color:#fff;background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(82,88,93,0.5)}.btn-check:checked+.btn-dark,.btn-check:active+.btn-dark,.btn-dark:active,.btn-dark.active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-check:checked+.btn-dark:focus,.btn-check:active+.btn-dark:focus,.btn-dark:active:focus,.btn-dark.active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,0.5)}.btn-dark:disabled,.btn-dark.disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-primary{color:#2e8b57;border-color:#2e8b57}.btn-outline-primary:hover{color:#fff;background-color:#2e8b57;border-color:#2e8b57}.btn-check:focus+.btn-outline-primary,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(46,139,87,0.5)}.btn-check:checked+.btn-outline-primary,.btn-check:active+.btn-outline-primary,.btn-outline-primary:active,.btn-outline-primary.active,.btn-outline-primary.dropdown-toggle.show{color:#fff;background-color:#2e8b57;border-color:#2e8b57}.btn-check:checked+.btn-outline-primary:focus,.btn-check:active+.btn-outline-primary:focus,.btn-outline-primary:active:focus,.btn-outline-primary.active:focus,.btn-outline-primary.dropdown-toggle.show:focus{box-shadow:0 0 0 .2rem rgba(46,139,87,0.5)}.btn-outline-primary:disabled,.btn-outline-primary.disabled{color:#2e8b57;background-color:transparent}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-check:focus+.btn-outline-secondary,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,0.5)}.btn-check:checked+.btn-outline-secondary,.btn-check:active+.btn-outline-secondary,.btn-outline-secondary:active,.btn-outline-secondary.active,.btn-outline-secondary.dropdown-toggle.show{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-check:checked+.btn-outline-secondary:focus,.btn-check:active+.btn-outline-secondary:focus,.btn-outline-secondary:active:focus,.btn-outline-secondary.active:focus,.btn-outline-secondary.dropdown-toggle.show:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,0.5)}.btn-outline-secondary:disabled,.btn-outline-secondary.disabled{color:#6c757d;background-color:transparent}.btn-outline-success{color:#78a642;border-color:#78a642}.btn-outline-success:hover{color:#212529;background-color:#78a642;border-color:#78a642}.btn-check:focus+.btn-outline-success,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(120,166,66,0.5)}.btn-check:checked+.btn-outline-success,.btn-check:active+.btn-outline-success,.btn-outline-success:active,.btn-outline-success.active,.btn-outline-success.dropdown-toggle.show{color:#212529;background-color:#78a642;border-color:#78a642}.btn-check:checked+.btn-outline-success:focus,.btn-check:active+.btn-outline-success:focus,.btn-outline-success:active:focus,.btn-outline-success.active:focus,.btn-outline-success.dropdown-toggle.show:focus{box-shadow:0 0 0 .2rem rgba(120,166,66,0.5)}.btn-outline-success:disabled,.btn-outline-success.disabled{color:#78a642;background-color:transparent}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-check:focus+.btn-outline-info,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,0.5)}.btn-check:checked+.btn-outline-info,.btn-check:active+.btn-outline-info,.btn-outline-info:active,.btn-outline-info.active,.btn-outline-info.dropdown-toggle.show{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-check:checked+.btn-outline-info:focus,.btn-check:active+.btn-outline-info:focus,.btn-outline-info:active:focus,.btn-outline-info.active:focus,.btn-outline-info.dropdown-toggle.show:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,0.5)}.btn-outline-info:disabled,.btn-outline-info.disabled{color:#17a2b8;background-color:transparent}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-check:focus+.btn-outline-warning,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,0.5)}.btn-check:checked+.btn-outline-warning,.btn-check:active+.btn-outline-warning,.btn-outline-warning:active,.btn-outline-warning.active,.btn-outline-warning.dropdown-toggle.show{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-check:checked+.btn-outline-warning:focus,.btn-check:active+.btn-outline-warning:focus,.btn-outline-warning:active:focus,.btn-outline-warning.active:focus,.btn-outline-warning.dropdown-toggle.show:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,0.5)}.btn-outline-warning:disabled,.btn-outline-warning.disabled{color:#ffc107;background-color:transparent}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-check:focus+.btn-outline-danger,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,0.5)}.btn-check:checked+.btn-outline-danger,.btn-check:active+.btn-outline-danger,.btn-outline-danger:active,.btn-outline-danger.active,.btn-outline-danger.dropdown-toggle.show{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-check:checked+.btn-outline-danger:focus,.btn-check:active+.btn-outline-danger:focus,.btn-outline-danger:active:focus,.btn-outline-danger.active:focus,.btn-outline-danger.dropdown-toggle.show:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,0.5)}.btn-outline-danger:disabled,.btn-outline-danger.disabled{color:#dc3545;background-color:transparent}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-check:focus+.btn-outline-light,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,0.5)}.btn-check:checked+.btn-outline-light,.btn-check:active+.btn-outline-light,.btn-outline-light:active,.btn-outline-light.active,.btn-outline-light.dropdown-toggle.show{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-check:checked+.btn-outline-light:focus,.btn-check:active+.btn-outline-light:focus,.btn-outline-light:active:focus,.btn-outline-light.active:focus,.btn-outline-light.dropdown-toggle.show:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,0.5)}.btn-outline-light:disabled,.btn-outline-light.disabled{color:#f8f9fa;background-color:transparent}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-check:focus+.btn-outline-dark,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,0.5)}.btn-check:checked+.btn-outline-dark,.btn-check:active+.btn-outline-dark,.btn-outline-dark:active,.btn-outline-dark.active,.btn-outline-dark.dropdown-toggle.show{color:#fff;background-color:#343a40;border-color:#343a40}.btn-check:checked+.btn-outline-dark:focus,.btn-check:active+.btn-outline-dark:focus,.btn-outline-dark:active:focus,.btn-outline-dark.active:focus,.btn-outline-dark.dropdown-toggle.show:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,0.5)}.btn-outline-dark:disabled,.btn-outline-dark.disabled{color:#343a40;background-color:transparent}.btn-link{font-weight:400;color:#2e8b57;text-decoration:none}.btn-link:hover{color:#1b5233;text-decoration:underline}.btn-link:focus{text-decoration:underline}.btn-link:disabled,.btn-link.disabled{color:#6c757d}.btn-lg{padding:.5rem 1rem;font-size:1.25rem;border-radius:3px}.btn-sm{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}.fade{transition:opacity 0.15s linear}@media (prefers-reduced-motion: reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height 0.35s ease}@media (prefers-reduced-motion: reduce){.collapsing{transition:none}}.dropup,.dropright,.dropdown,.dropleft{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:4px;vertical-align:4.25px;content:"";border-top:5px solid;border-right:5px solid transparent;border-bottom:0;border-left:5px solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;min-width:10rem;padding:.5rem 0;margin:1rem 0 0;font-size:1rem;color:#CFD8DC;text-align:left;list-style:none;background-color:#1c2429;background-clip:padding-box;border:0 solid rgba(0,0,0,0.15);border-radius:3px}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width: 576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width: 768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width: 992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width: 1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}@media (min-width: 1400px){.dropdown-menu-xxl-left{right:auto;left:0}.dropdown-menu-xxl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:1rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:4px;vertical-align:4.25px;content:"";border-top:0;border-right:5px solid transparent;border-bottom:5px solid;border-left:5px solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:1rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:4px;vertical-align:4.25px;content:"";border-top:5px solid transparent;border-right:0;border-bottom:5px solid transparent;border-left:5px solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:1rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:4px;vertical-align:4.25px;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:4px;vertical-align:4.25px;content:"";border-top:5px solid transparent;border-right:5px solid;border-bottom:5px solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^="top"],.dropdown-menu[x-placement^="right"],.dropdown-menu[x-placement^="bottom"],.dropdown-menu[x-placement^="left"]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:6px 0;overflow:hidden;border-top:1px solid #263238}.dropdown-item{display:block;width:100%;padding:3px 1rem;clear:both;font-weight:400;color:#ECEFF1;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:hover,.dropdown-item:focus{color:#ECEFF1;text-decoration:none;background-color:rgba(0,0,0,0.3)}.dropdown-item.active,.dropdown-item:active{color:#F8F9Fa;text-decoration:none;background-color:rgba(0,0,0,0.2)}.dropdown-item.disabled,.dropdown-item:disabled{color:#546E7A;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1rem;margin-bottom:0;font-size:.875rem;color:#CFD8DC;white-space:nowrap}.dropdown-item-text{display:block;padding:3px 1rem;color:#ECEFF1}.alert{position:relative;padding:1rem 1rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.15rem}.alert-heading{color:inherit}.alert-link{font-weight:600}.alert-dismissible{padding-right:3.5rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:1rem 1rem;color:inherit}.alert-primary{color:#18482d;background-color:#d5e8dd;border-color:#c4dfd0}.alert-primary .alert-link{color:#0b2215}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary .alert-link{color:#202326}.alert-success{color:#3e5622;background-color:#e4edd9;border-color:#d9e6ca}.alert-success .alert-link{color:#243114}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark .alert-link{color:#040505}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform 0.3s ease-out;transform:translate(0, -50px)}@media (prefers-reduced-motion: reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - 1rem)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:0 solid rgba(0,0,0,0.2);border-radius:3px;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:flex;flex-shrink:0;align-items:flex-start;justify-content:space-between;padding:1rem 1rem;border-bottom:0 solid #dee2e6;border-top-left-radius:3px;border-top-right-radius:3px}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;padding:1rem}.modal-footer{display:flex;flex-wrap:wrap;flex-shrink:0;align-items:center;justify-content:flex-end;padding:.75rem;border-top:0 solid #dee2e6;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width: 576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width: 992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width: 1200px){.modal-xl{max-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}.modal-fullscreen .modal-footer{border-radius:0}@media (max-width: 575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}.modal-fullscreen-sm-down .modal-footer{border-radius:0}}@media (max-width: 767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}.modal-fullscreen-md-down .modal-footer{border-radius:0}}@media (max-width: 991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}.modal-fullscreen-lg-down .modal-footer{border-radius:0}}@media (max-width: 1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}.modal-fullscreen-xl-down .modal-footer{border-radius:0}}@media (max-width: 1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}.modal-fullscreen-xxl-down .modal-footer{border-radius:0}}.clearfix::after{display:block;clear:both;content:""}.link-primary{color:#2e8b57}.link-primary:hover,.link-primary:focus{color:#1b5233}.link-secondary{color:#6c757d}.link-secondary:hover,.link-secondary:focus{color:#494f54}.link-success{color:#78a642}.link-success:hover,.link-success:focus{color:#506f2c}.link-info{color:#17a2b8}.link-info:hover,.link-info:focus{color:#0f6674}.link-warning{color:#ffc107}.link-warning:hover,.link-warning:focus{color:#ba8b00}.link-danger{color:#dc3545}.link-danger:hover,.link-danger:focus{color:#a71d2a}.link-light{color:#f8f9fa}.link-light:hover,.link-light:focus{color:#cbd3da}.link-dark{color:#343a40}.link-dark:hover,.link-dark:focus{color:#121416}.embed-responsive{position:relative;width:100%}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;width:100%;height:100%}.embed-responsive-21by9::before{padding-top:42.85714%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}@media (min-width: 576px){.sticky-sm-top{position:sticky;top:0;z-index:1020}}@media (min-width: 768px){.sticky-md-top{position:sticky;top:0;z-index:1020}}@media (min-width: 992px){.sticky-lg-top{position:sticky;top:0;z-index:1020}}@media (min-width: 1200px){.sticky-xl-top{position:sticky;top:0;z-index:1020}}@media (min-width: 1400px){.sticky-xxl-top{position:sticky;top:0;z-index:1020}}.sr-only,.sr-only-focusable:not(:focus){position:absolute !important;width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0, 0, 0, 0) !important;white-space:nowrap !important;border:0 !important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.float-left{float:left !important}.float-right{float:right !important}.float-none{float:none !important}.overflow-auto{overflow:auto !important}.overflow-hidden{overflow:hidden !important}.d-none{display:none !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:flex !important}.d-inline-flex{display:inline-flex !important}.shadow{box-shadow:0 0.5rem 1rem rgba(0,0,0,0.15) !important}.shadow-sm{box-shadow:0 0.125rem 0.25rem rgba(0,0,0,0.075) !important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,0.175) !important}.shadow-none{box-shadow:none !important}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:sticky !important}.border{border:1px solid #dee2e6 !important}.border-0{border:0 !important}.border-top{border-top:1px solid #dee2e6 !important}.border-top-0{border-top:0 !important}.border-right{border-right:1px solid #dee2e6 !important}.border-right-0{border-right:0 !important}.border-bottom{border-bottom:1px solid #dee2e6 !important}.border-bottom-0{border-bottom:0 !important}.border-left{border-left:1px solid #dee2e6 !important}.border-left-0{border-left:0 !important}.border-primary{border-color:#2e8b57 !important}.border-secondary{border-color:#6c757d !important}.border-success{border-color:#78a642 !important}.border-info{border-color:#17a2b8 !important}.border-warning{border-color:#ffc107 !important}.border-danger{border-color:#dc3545 !important}.border-light{border-color:#f8f9fa !important}.border-dark{border-color:#343a40 !important}.border-white{border-color:#fff !important}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.mw-100{max-width:100% !important}.vw-100{width:100vw !important}.min-vw-100{min-width:100vw !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mh-100{max-height:100% !important}.vh-100{height:100vh !important}.min-vh-100{min-height:100vh !important}.flex-fill{flex:1 1 auto !important}.flex-row{flex-direction:row !important}.flex-column{flex-direction:column !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column-reverse{flex-direction:column-reverse !important}.flex-grow-0{flex-grow:0 !important}.flex-grow-1{flex-grow:1 !important}.flex-shrink-0{flex-shrink:0 !important}.flex-shrink-1{flex-shrink:1 !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.justify-content-between{justify-content:space-between !important}.justify-content-around{justify-content:space-around !important}.justify-content-evenly{justify-content:space-evenly !important}.align-items-start{align-items:flex-start !important}.align-items-end{align-items:flex-end !important}.align-items-center{align-items:center !important}.align-items-baseline{align-items:baseline !important}.align-items-stretch{align-items:stretch !important}.align-content-start{align-content:flex-start !important}.align-content-end{align-content:flex-end !important}.align-content-center{align-content:center !important}.align-content-between{align-content:space-between !important}.align-content-around{align-content:space-around !important}.align-content-stretch{align-content:stretch !important}.align-self-auto{align-self:auto !important}.align-self-start{align-self:flex-start !important}.align-self-end{align-self:flex-end !important}.align-self-center{align-self:center !important}.align-self-baseline{align-self:baseline !important}.align-self-stretch{align-self:stretch !important}.order-first{order:-1 !important}.order-0{order:0 !important}.order-1{order:1 !important}.order-2{order:2 !important}.order-3{order:3 !important}.order-4{order:4 !important}.order-5{order:5 !important}.order-last{order:6 !important}.m-0{margin:0 !important}.m-1{margin:.25rem !important}.m-2{margin:.5rem !important}.m-3{margin:1rem !important}.m-4{margin:1.5rem !important}.m-5{margin:3rem !important}.m-auto{margin:auto !important}.mx-0{margin-right:0 !important;margin-left:0 !important}.mx-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-3{margin-right:1rem !important;margin-left:1rem !important}.mx-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-5{margin-right:3rem !important;margin-left:3rem !important}.mx-auto{margin-right:auto !important;margin-left:auto !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-0{margin-top:0 !important}.mt-1{margin-top:.25rem !important}.mt-2{margin-top:.5rem !important}.mt-3{margin-top:1rem !important}.mt-4{margin-top:1.5rem !important}.mt-5{margin-top:3rem !important}.mt-auto{margin-top:auto !important}.mr-0{margin-right:0 !important}.mr-1{margin-right:.25rem !important}.mr-2{margin-right:.5rem !important}.mr-3{margin-right:1rem !important}.mr-4{margin-right:1.5rem !important}.mr-5{margin-right:3rem !important}.mr-auto{margin-right:auto !important}.mb-0{margin-bottom:0 !important}.mb-1{margin-bottom:.25rem !important}.mb-2{margin-bottom:.5rem !important}.mb-3{margin-bottom:1rem !important}.mb-4{margin-bottom:1.5rem !important}.mb-5{margin-bottom:3rem !important}.mb-auto{margin-bottom:auto !important}.ml-0{margin-left:0 !important}.ml-1{margin-left:.25rem !important}.ml-2{margin-left:.5rem !important}.ml-3{margin-left:1rem !important}.ml-4{margin-left:1.5rem !important}.ml-5{margin-left:3rem !important}.ml-auto{margin-left:auto !important}.p-0{padding:0 !important}.p-1{padding:.25rem !important}.p-2{padding:.5rem !important}.p-3{padding:1rem !important}.p-4{padding:1.5rem !important}.p-5{padding:3rem !important}.px-0{padding-right:0 !important;padding-left:0 !important}.px-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-3{padding-right:1rem !important;padding-left:1rem !important}.px-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-5{padding-right:3rem !important;padding-left:3rem !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-0{padding-top:0 !important}.pt-1{padding-top:.25rem !important}.pt-2{padding-top:.5rem !important}.pt-3{padding-top:1rem !important}.pt-4{padding-top:1.5rem !important}.pt-5{padding-top:3rem !important}.pr-0{padding-right:0 !important}.pr-1{padding-right:.25rem !important}.pr-2{padding-right:.5rem !important}.pr-3{padding-right:1rem !important}.pr-4{padding-right:1.5rem !important}.pr-5{padding-right:3rem !important}.pb-0{padding-bottom:0 !important}.pb-1{padding-bottom:.25rem !important}.pb-2{padding-bottom:.5rem !important}.pb-3{padding-bottom:1rem !important}.pb-4{padding-bottom:1.5rem !important}.pb-5{padding-bottom:3rem !important}.pl-0{padding-left:0 !important}.pl-1{padding-left:.25rem !important}.pl-2{padding-left:.5rem !important}.pl-3{padding-left:1rem !important}.pl-4{padding-left:1.5rem !important}.pl-5{padding-left:3rem !important}.font-weight-light{font-weight:300 !important}.font-weight-lighter{font-weight:lighter !important}.font-weight-normal{font-weight:400 !important}.font-weight-bold{font-weight:600 !important}.font-weight-bolder{font-weight:600 !important}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.text-left{text-align:left !important}.text-right{text-align:right !important}.text-center{text-align:center !important}.text-primary{color:#2e8b57 !important}.text-secondary{color:#6c757d !important}.text-success{color:#78a642 !important}.text-info{color:#17a2b8 !important}.text-warning{color:#ffc107 !important}.text-danger{color:#dc3545 !important}.text-light{color:#f8f9fa !important}.text-dark{color:#343a40 !important}.text-white{color:#fff !important}.text-body{color:#212529 !important}.text-muted{color:#6c757d !important}.text-black-50{color:rgba(0,0,0,0.5) !important}.text-white-50{color:rgba(255,255,255,0.5) !important}.text-reset{color:inherit !important}.lh-1{line-height:1 !important}.lh-sm{line-height:1.25 !important}.lh-base{line-height:1.5 !important}.lh-lg{line-height:2 !important}.bg-primary{background-color:#2e8b57 !important}.bg-secondary{background-color:#6c757d !important}.bg-success{background-color:#78a642 !important}.bg-info{background-color:#17a2b8 !important}.bg-warning{background-color:#ffc107 !important}.bg-danger{background-color:#dc3545 !important}.bg-light{background-color:#f8f9fa !important}.bg-dark{background-color:#343a40 !important}.bg-body{background-color:#ECEFF1 !important}.bg-white{background-color:#fff !important}.bg-transparent{background-color:rgba(0,0,0,0) !important}.bg-gradient{background-image:var(--bs-gradient) !important}.text-wrap{white-space:normal !important}.text-nowrap{white-space:nowrap !important}.text-decoration-none{text-decoration:none !important}.text-decoration-underline{text-decoration:underline !important}.text-decoration-line-through{text-decoration:line-through !important}.font-italic{font-style:italic !important}.font-normal{font-style:normal !important}.text-break{word-wrap:break-word !important;word-break:break-word !important}.font-monospace{font-family:var(--bs-font-monospace) !important}.user-select-all{user-select:all !important}.user-select-auto{user-select:auto !important}.user-select-none{user-select:none !important}.pe-none{pointer-events:none !important}.pe-auto{pointer-events:auto !important}.rounded{border-radius:.15rem !important}.rounded-sm{border-radius:.2rem !important}.rounded-lg{border-radius:.3rem !important}.rounded-circle{border-radius:50% !important}.rounded-pill{border-radius:50rem !important}.rounded-0{border-radius:0 !important}.rounded-top{border-top-left-radius:.15rem !important;border-top-right-radius:.15rem !important}.rounded-right{border-top-right-radius:.15rem !important;border-bottom-right-radius:.15rem !important}.rounded-bottom{border-bottom-right-radius:.15rem !important;border-bottom-left-radius:.15rem !important}.rounded-left{border-bottom-left-radius:.15rem !important;border-top-left-radius:.15rem !important}.visible{visibility:visible !important}.invisible{visibility:hidden !important}@media (min-width: 576px){.float-sm-left{float:left !important}.float-sm-right{float:right !important}.float-sm-none{float:none !important}.d-sm-none{display:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:flex !important}.d-sm-inline-flex{display:inline-flex !important}.flex-sm-fill{flex:1 1 auto !important}.flex-sm-row{flex-direction:row !important}.flex-sm-column{flex-direction:column !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column-reverse{flex-direction:column-reverse !important}.flex-sm-grow-0{flex-grow:0 !important}.flex-sm-grow-1{flex-grow:1 !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-shrink-1{flex-shrink:1 !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-sm-start{justify-content:flex-start !important}.justify-content-sm-end{justify-content:flex-end !important}.justify-content-sm-center{justify-content:center !important}.justify-content-sm-between{justify-content:space-between !important}.justify-content-sm-around{justify-content:space-around !important}.justify-content-sm-evenly{justify-content:space-evenly !important}.align-items-sm-start{align-items:flex-start !important}.align-items-sm-end{align-items:flex-end !important}.align-items-sm-center{align-items:center !important}.align-items-sm-baseline{align-items:baseline !important}.align-items-sm-stretch{align-items:stretch !important}.align-content-sm-start{align-content:flex-start !important}.align-content-sm-end{align-content:flex-end !important}.align-content-sm-center{align-content:center !important}.align-content-sm-between{align-content:space-between !important}.align-content-sm-around{align-content:space-around !important}.align-content-sm-stretch{align-content:stretch !important}.align-self-sm-auto{align-self:auto !important}.align-self-sm-start{align-self:flex-start !important}.align-self-sm-end{align-self:flex-end !important}.align-self-sm-center{align-self:center !important}.align-self-sm-baseline{align-self:baseline !important}.align-self-sm-stretch{align-self:stretch !important}.order-sm-first{order:-1 !important}.order-sm-0{order:0 !important}.order-sm-1{order:1 !important}.order-sm-2{order:2 !important}.order-sm-3{order:3 !important}.order-sm-4{order:4 !important}.order-sm-5{order:5 !important}.order-sm-last{order:6 !important}.m-sm-0{margin:0 !important}.m-sm-1{margin:.25rem !important}.m-sm-2{margin:.5rem !important}.m-sm-3{margin:1rem !important}.m-sm-4{margin:1.5rem !important}.m-sm-5{margin:3rem !important}.m-sm-auto{margin:auto !important}.mx-sm-0{margin-right:0 !important;margin-left:0 !important}.mx-sm-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-sm-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-sm-3{margin-right:1rem !important;margin-left:1rem !important}.mx-sm-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-sm-5{margin-right:3rem !important;margin-left:3rem !important}.mx-sm-auto{margin-right:auto !important;margin-left:auto !important}.my-sm-0{margin-top:0 !important;margin-bottom:0 !important}.my-sm-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-sm-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-sm-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-sm-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-sm-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-sm-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-sm-0{margin-top:0 !important}.mt-sm-1{margin-top:.25rem !important}.mt-sm-2{margin-top:.5rem !important}.mt-sm-3{margin-top:1rem !important}.mt-sm-4{margin-top:1.5rem !important}.mt-sm-5{margin-top:3rem !important}.mt-sm-auto{margin-top:auto !important}.mr-sm-0{margin-right:0 !important}.mr-sm-1{margin-right:.25rem !important}.mr-sm-2{margin-right:.5rem !important}.mr-sm-3{margin-right:1rem !important}.mr-sm-4{margin-right:1.5rem !important}.mr-sm-5{margin-right:3rem !important}.mr-sm-auto{margin-right:auto !important}.mb-sm-0{margin-bottom:0 !important}.mb-sm-1{margin-bottom:.25rem !important}.mb-sm-2{margin-bottom:.5rem !important}.mb-sm-3{margin-bottom:1rem !important}.mb-sm-4{margin-bottom:1.5rem !important}.mb-sm-5{margin-bottom:3rem !important}.mb-sm-auto{margin-bottom:auto !important}.ml-sm-0{margin-left:0 !important}.ml-sm-1{margin-left:.25rem !important}.ml-sm-2{margin-left:.5rem !important}.ml-sm-3{margin-left:1rem !important}.ml-sm-4{margin-left:1.5rem !important}.ml-sm-5{margin-left:3rem !important}.ml-sm-auto{margin-left:auto !important}.p-sm-0{padding:0 !important}.p-sm-1{padding:.25rem !important}.p-sm-2{padding:.5rem !important}.p-sm-3{padding:1rem !important}.p-sm-4{padding:1.5rem !important}.p-sm-5{padding:3rem !important}.px-sm-0{padding-right:0 !important;padding-left:0 !important}.px-sm-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-sm-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-sm-3{padding-right:1rem !important;padding-left:1rem !important}.px-sm-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-sm-5{padding-right:3rem !important;padding-left:3rem !important}.py-sm-0{padding-top:0 !important;padding-bottom:0 !important}.py-sm-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-sm-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-sm-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-sm-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-sm-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-sm-0{padding-top:0 !important}.pt-sm-1{padding-top:.25rem !important}.pt-sm-2{padding-top:.5rem !important}.pt-sm-3{padding-top:1rem !important}.pt-sm-4{padding-top:1.5rem !important}.pt-sm-5{padding-top:3rem !important}.pr-sm-0{padding-right:0 !important}.pr-sm-1{padding-right:.25rem !important}.pr-sm-2{padding-right:.5rem !important}.pr-sm-3{padding-right:1rem !important}.pr-sm-4{padding-right:1.5rem !important}.pr-sm-5{padding-right:3rem !important}.pb-sm-0{padding-bottom:0 !important}.pb-sm-1{padding-bottom:.25rem !important}.pb-sm-2{padding-bottom:.5rem !important}.pb-sm-3{padding-bottom:1rem !important}.pb-sm-4{padding-bottom:1.5rem !important}.pb-sm-5{padding-bottom:3rem !important}.pl-sm-0{padding-left:0 !important}.pl-sm-1{padding-left:.25rem !important}.pl-sm-2{padding-left:.5rem !important}.pl-sm-3{padding-left:1rem !important}.pl-sm-4{padding-left:1.5rem !important}.pl-sm-5{padding-left:3rem !important}.text-sm-left{text-align:left !important}.text-sm-right{text-align:right !important}.text-sm-center{text-align:center !important}}@media (min-width: 768px){.float-md-left{float:left !important}.float-md-right{float:right !important}.float-md-none{float:none !important}.d-md-none{display:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:flex !important}.d-md-inline-flex{display:inline-flex !important}.flex-md-fill{flex:1 1 auto !important}.flex-md-row{flex-direction:row !important}.flex-md-column{flex-direction:column !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column-reverse{flex-direction:column-reverse !important}.flex-md-grow-0{flex-grow:0 !important}.flex-md-grow-1{flex-grow:1 !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-shrink-1{flex-shrink:1 !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-md-start{justify-content:flex-start !important}.justify-content-md-end{justify-content:flex-end !important}.justify-content-md-center{justify-content:center !important}.justify-content-md-between{justify-content:space-between !important}.justify-content-md-around{justify-content:space-around !important}.justify-content-md-evenly{justify-content:space-evenly !important}.align-items-md-start{align-items:flex-start !important}.align-items-md-end{align-items:flex-end !important}.align-items-md-center{align-items:center !important}.align-items-md-baseline{align-items:baseline !important}.align-items-md-stretch{align-items:stretch !important}.align-content-md-start{align-content:flex-start !important}.align-content-md-end{align-content:flex-end !important}.align-content-md-center{align-content:center !important}.align-content-md-between{align-content:space-between !important}.align-content-md-around{align-content:space-around !important}.align-content-md-stretch{align-content:stretch !important}.align-self-md-auto{align-self:auto !important}.align-self-md-start{align-self:flex-start !important}.align-self-md-end{align-self:flex-end !important}.align-self-md-center{align-self:center !important}.align-self-md-baseline{align-self:baseline !important}.align-self-md-stretch{align-self:stretch !important}.order-md-first{order:-1 !important}.order-md-0{order:0 !important}.order-md-1{order:1 !important}.order-md-2{order:2 !important}.order-md-3{order:3 !important}.order-md-4{order:4 !important}.order-md-5{order:5 !important}.order-md-last{order:6 !important}.m-md-0{margin:0 !important}.m-md-1{margin:.25rem !important}.m-md-2{margin:.5rem !important}.m-md-3{margin:1rem !important}.m-md-4{margin:1.5rem !important}.m-md-5{margin:3rem !important}.m-md-auto{margin:auto !important}.mx-md-0{margin-right:0 !important;margin-left:0 !important}.mx-md-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-md-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-md-3{margin-right:1rem !important;margin-left:1rem !important}.mx-md-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-md-5{margin-right:3rem !important;margin-left:3rem !important}.mx-md-auto{margin-right:auto !important;margin-left:auto !important}.my-md-0{margin-top:0 !important;margin-bottom:0 !important}.my-md-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-md-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-md-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-md-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-md-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-md-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-md-0{margin-top:0 !important}.mt-md-1{margin-top:.25rem !important}.mt-md-2{margin-top:.5rem !important}.mt-md-3{margin-top:1rem !important}.mt-md-4{margin-top:1.5rem !important}.mt-md-5{margin-top:3rem !important}.mt-md-auto{margin-top:auto !important}.mr-md-0{margin-right:0 !important}.mr-md-1{margin-right:.25rem !important}.mr-md-2{margin-right:.5rem !important}.mr-md-3{margin-right:1rem !important}.mr-md-4{margin-right:1.5rem !important}.mr-md-5{margin-right:3rem !important}.mr-md-auto{margin-right:auto !important}.mb-md-0{margin-bottom:0 !important}.mb-md-1{margin-bottom:.25rem !important}.mb-md-2{margin-bottom:.5rem !important}.mb-md-3{margin-bottom:1rem !important}.mb-md-4{margin-bottom:1.5rem !important}.mb-md-5{margin-bottom:3rem !important}.mb-md-auto{margin-bottom:auto !important}.ml-md-0{margin-left:0 !important}.ml-md-1{margin-left:.25rem !important}.ml-md-2{margin-left:.5rem !important}.ml-md-3{margin-left:1rem !important}.ml-md-4{margin-left:1.5rem !important}.ml-md-5{margin-left:3rem !important}.ml-md-auto{margin-left:auto !important}.p-md-0{padding:0 !important}.p-md-1{padding:.25rem !important}.p-md-2{padding:.5rem !important}.p-md-3{padding:1rem !important}.p-md-4{padding:1.5rem !important}.p-md-5{padding:3rem !important}.px-md-0{padding-right:0 !important;padding-left:0 !important}.px-md-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-md-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-md-3{padding-right:1rem !important;padding-left:1rem !important}.px-md-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-md-5{padding-right:3rem !important;padding-left:3rem !important}.py-md-0{padding-top:0 !important;padding-bottom:0 !important}.py-md-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-md-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-md-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-md-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-md-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-md-0{padding-top:0 !important}.pt-md-1{padding-top:.25rem !important}.pt-md-2{padding-top:.5rem !important}.pt-md-3{padding-top:1rem !important}.pt-md-4{padding-top:1.5rem !important}.pt-md-5{padding-top:3rem !important}.pr-md-0{padding-right:0 !important}.pr-md-1{padding-right:.25rem !important}.pr-md-2{padding-right:.5rem !important}.pr-md-3{padding-right:1rem !important}.pr-md-4{padding-right:1.5rem !important}.pr-md-5{padding-right:3rem !important}.pb-md-0{padding-bottom:0 !important}.pb-md-1{padding-bottom:.25rem !important}.pb-md-2{padding-bottom:.5rem !important}.pb-md-3{padding-bottom:1rem !important}.pb-md-4{padding-bottom:1.5rem !important}.pb-md-5{padding-bottom:3rem !important}.pl-md-0{padding-left:0 !important}.pl-md-1{padding-left:.25rem !important}.pl-md-2{padding-left:.5rem !important}.pl-md-3{padding-left:1rem !important}.pl-md-4{padding-left:1.5rem !important}.pl-md-5{padding-left:3rem !important}.text-md-left{text-align:left !important}.text-md-right{text-align:right !important}.text-md-center{text-align:center !important}}@media (min-width: 992px){.float-lg-left{float:left !important}.float-lg-right{float:right !important}.float-lg-none{float:none !important}.d-lg-none{display:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:flex !important}.d-lg-inline-flex{display:inline-flex !important}.flex-lg-fill{flex:1 1 auto !important}.flex-lg-row{flex-direction:row !important}.flex-lg-column{flex-direction:column !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column-reverse{flex-direction:column-reverse !important}.flex-lg-grow-0{flex-grow:0 !important}.flex-lg-grow-1{flex-grow:1 !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-shrink-1{flex-shrink:1 !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-lg-start{justify-content:flex-start !important}.justify-content-lg-end{justify-content:flex-end !important}.justify-content-lg-center{justify-content:center !important}.justify-content-lg-between{justify-content:space-between !important}.justify-content-lg-around{justify-content:space-around !important}.justify-content-lg-evenly{justify-content:space-evenly !important}.align-items-lg-start{align-items:flex-start !important}.align-items-lg-end{align-items:flex-end !important}.align-items-lg-center{align-items:center !important}.align-items-lg-baseline{align-items:baseline !important}.align-items-lg-stretch{align-items:stretch !important}.align-content-lg-start{align-content:flex-start !important}.align-content-lg-end{align-content:flex-end !important}.align-content-lg-center{align-content:center !important}.align-content-lg-between{align-content:space-between !important}.align-content-lg-around{align-content:space-around !important}.align-content-lg-stretch{align-content:stretch !important}.align-self-lg-auto{align-self:auto !important}.align-self-lg-start{align-self:flex-start !important}.align-self-lg-end{align-self:flex-end !important}.align-self-lg-center{align-self:center !important}.align-self-lg-baseline{align-self:baseline !important}.align-self-lg-stretch{align-self:stretch !important}.order-lg-first{order:-1 !important}.order-lg-0{order:0 !important}.order-lg-1{order:1 !important}.order-lg-2{order:2 !important}.order-lg-3{order:3 !important}.order-lg-4{order:4 !important}.order-lg-5{order:5 !important}.order-lg-last{order:6 !important}.m-lg-0{margin:0 !important}.m-lg-1{margin:.25rem !important}.m-lg-2{margin:.5rem !important}.m-lg-3{margin:1rem !important}.m-lg-4{margin:1.5rem !important}.m-lg-5{margin:3rem !important}.m-lg-auto{margin:auto !important}.mx-lg-0{margin-right:0 !important;margin-left:0 !important}.mx-lg-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-lg-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-lg-3{margin-right:1rem !important;margin-left:1rem !important}.mx-lg-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-lg-5{margin-right:3rem !important;margin-left:3rem !important}.mx-lg-auto{margin-right:auto !important;margin-left:auto !important}.my-lg-0{margin-top:0 !important;margin-bottom:0 !important}.my-lg-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-lg-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-lg-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-lg-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-lg-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-lg-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-lg-0{margin-top:0 !important}.mt-lg-1{margin-top:.25rem !important}.mt-lg-2{margin-top:.5rem !important}.mt-lg-3{margin-top:1rem !important}.mt-lg-4{margin-top:1.5rem !important}.mt-lg-5{margin-top:3rem !important}.mt-lg-auto{margin-top:auto !important}.mr-lg-0{margin-right:0 !important}.mr-lg-1{margin-right:.25rem !important}.mr-lg-2{margin-right:.5rem !important}.mr-lg-3{margin-right:1rem !important}.mr-lg-4{margin-right:1.5rem !important}.mr-lg-5{margin-right:3rem !important}.mr-lg-auto{margin-right:auto !important}.mb-lg-0{margin-bottom:0 !important}.mb-lg-1{margin-bottom:.25rem !important}.mb-lg-2{margin-bottom:.5rem !important}.mb-lg-3{margin-bottom:1rem !important}.mb-lg-4{margin-bottom:1.5rem !important}.mb-lg-5{margin-bottom:3rem !important}.mb-lg-auto{margin-bottom:auto !important}.ml-lg-0{margin-left:0 !important}.ml-lg-1{margin-left:.25rem !important}.ml-lg-2{margin-left:.5rem !important}.ml-lg-3{margin-left:1rem !important}.ml-lg-4{margin-left:1.5rem !important}.ml-lg-5{margin-left:3rem !important}.ml-lg-auto{margin-left:auto !important}.p-lg-0{padding:0 !important}.p-lg-1{padding:.25rem !important}.p-lg-2{padding:.5rem !important}.p-lg-3{padding:1rem !important}.p-lg-4{padding:1.5rem !important}.p-lg-5{padding:3rem !important}.px-lg-0{padding-right:0 !important;padding-left:0 !important}.px-lg-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-lg-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-lg-3{padding-right:1rem !important;padding-left:1rem !important}.px-lg-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-lg-5{padding-right:3rem !important;padding-left:3rem !important}.py-lg-0{padding-top:0 !important;padding-bottom:0 !important}.py-lg-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-lg-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-lg-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-lg-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-lg-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-lg-0{padding-top:0 !important}.pt-lg-1{padding-top:.25rem !important}.pt-lg-2{padding-top:.5rem !important}.pt-lg-3{padding-top:1rem !important}.pt-lg-4{padding-top:1.5rem !important}.pt-lg-5{padding-top:3rem !important}.pr-lg-0{padding-right:0 !important}.pr-lg-1{padding-right:.25rem !important}.pr-lg-2{padding-right:.5rem !important}.pr-lg-3{padding-right:1rem !important}.pr-lg-4{padding-right:1.5rem !important}.pr-lg-5{padding-right:3rem !important}.pb-lg-0{padding-bottom:0 !important}.pb-lg-1{padding-bottom:.25rem !important}.pb-lg-2{padding-bottom:.5rem !important}.pb-lg-3{padding-bottom:1rem !important}.pb-lg-4{padding-bottom:1.5rem !important}.pb-lg-5{padding-bottom:3rem !important}.pl-lg-0{padding-left:0 !important}.pl-lg-1{padding-left:.25rem !important}.pl-lg-2{padding-left:.5rem !important}.pl-lg-3{padding-left:1rem !important}.pl-lg-4{padding-left:1.5rem !important}.pl-lg-5{padding-left:3rem !important}.text-lg-left{text-align:left !important}.text-lg-right{text-align:right !important}.text-lg-center{text-align:center !important}}@media (min-width: 1200px){.float-xl-left{float:left !important}.float-xl-right{float:right !important}.float-xl-none{float:none !important}.d-xl-none{display:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:flex !important}.d-xl-inline-flex{display:inline-flex !important}.flex-xl-fill{flex:1 1 auto !important}.flex-xl-row{flex-direction:row !important}.flex-xl-column{flex-direction:column !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column-reverse{flex-direction:column-reverse !important}.flex-xl-grow-0{flex-grow:0 !important}.flex-xl-grow-1{flex-grow:1 !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-shrink-1{flex-shrink:1 !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-xl-start{justify-content:flex-start !important}.justify-content-xl-end{justify-content:flex-end !important}.justify-content-xl-center{justify-content:center !important}.justify-content-xl-between{justify-content:space-between !important}.justify-content-xl-around{justify-content:space-around !important}.justify-content-xl-evenly{justify-content:space-evenly !important}.align-items-xl-start{align-items:flex-start !important}.align-items-xl-end{align-items:flex-end !important}.align-items-xl-center{align-items:center !important}.align-items-xl-baseline{align-items:baseline !important}.align-items-xl-stretch{align-items:stretch !important}.align-content-xl-start{align-content:flex-start !important}.align-content-xl-end{align-content:flex-end !important}.align-content-xl-center{align-content:center !important}.align-content-xl-between{align-content:space-between !important}.align-content-xl-around{align-content:space-around !important}.align-content-xl-stretch{align-content:stretch !important}.align-self-xl-auto{align-self:auto !important}.align-self-xl-start{align-self:flex-start !important}.align-self-xl-end{align-self:flex-end !important}.align-self-xl-center{align-self:center !important}.align-self-xl-baseline{align-self:baseline !important}.align-self-xl-stretch{align-self:stretch !important}.order-xl-first{order:-1 !important}.order-xl-0{order:0 !important}.order-xl-1{order:1 !important}.order-xl-2{order:2 !important}.order-xl-3{order:3 !important}.order-xl-4{order:4 !important}.order-xl-5{order:5 !important}.order-xl-last{order:6 !important}.m-xl-0{margin:0 !important}.m-xl-1{margin:.25rem !important}.m-xl-2{margin:.5rem !important}.m-xl-3{margin:1rem !important}.m-xl-4{margin:1.5rem !important}.m-xl-5{margin:3rem !important}.m-xl-auto{margin:auto !important}.mx-xl-0{margin-right:0 !important;margin-left:0 !important}.mx-xl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xl-auto{margin-right:auto !important;margin-left:auto !important}.my-xl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xl-0{margin-top:0 !important}.mt-xl-1{margin-top:.25rem !important}.mt-xl-2{margin-top:.5rem !important}.mt-xl-3{margin-top:1rem !important}.mt-xl-4{margin-top:1.5rem !important}.mt-xl-5{margin-top:3rem !important}.mt-xl-auto{margin-top:auto !important}.mr-xl-0{margin-right:0 !important}.mr-xl-1{margin-right:.25rem !important}.mr-xl-2{margin-right:.5rem !important}.mr-xl-3{margin-right:1rem !important}.mr-xl-4{margin-right:1.5rem !important}.mr-xl-5{margin-right:3rem !important}.mr-xl-auto{margin-right:auto !important}.mb-xl-0{margin-bottom:0 !important}.mb-xl-1{margin-bottom:.25rem !important}.mb-xl-2{margin-bottom:.5rem !important}.mb-xl-3{margin-bottom:1rem !important}.mb-xl-4{margin-bottom:1.5rem !important}.mb-xl-5{margin-bottom:3rem !important}.mb-xl-auto{margin-bottom:auto !important}.ml-xl-0{margin-left:0 !important}.ml-xl-1{margin-left:.25rem !important}.ml-xl-2{margin-left:.5rem !important}.ml-xl-3{margin-left:1rem !important}.ml-xl-4{margin-left:1.5rem !important}.ml-xl-5{margin-left:3rem !important}.ml-xl-auto{margin-left:auto !important}.p-xl-0{padding:0 !important}.p-xl-1{padding:.25rem !important}.p-xl-2{padding:.5rem !important}.p-xl-3{padding:1rem !important}.p-xl-4{padding:1.5rem !important}.p-xl-5{padding:3rem !important}.px-xl-0{padding-right:0 !important;padding-left:0 !important}.px-xl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xl-0{padding-top:0 !important}.pt-xl-1{padding-top:.25rem !important}.pt-xl-2{padding-top:.5rem !important}.pt-xl-3{padding-top:1rem !important}.pt-xl-4{padding-top:1.5rem !important}.pt-xl-5{padding-top:3rem !important}.pr-xl-0{padding-right:0 !important}.pr-xl-1{padding-right:.25rem !important}.pr-xl-2{padding-right:.5rem !important}.pr-xl-3{padding-right:1rem !important}.pr-xl-4{padding-right:1.5rem !important}.pr-xl-5{padding-right:3rem !important}.pb-xl-0{padding-bottom:0 !important}.pb-xl-1{padding-bottom:.25rem !important}.pb-xl-2{padding-bottom:.5rem !important}.pb-xl-3{padding-bottom:1rem !important}.pb-xl-4{padding-bottom:1.5rem !important}.pb-xl-5{padding-bottom:3rem !important}.pl-xl-0{padding-left:0 !important}.pl-xl-1{padding-left:.25rem !important}.pl-xl-2{padding-left:.5rem !important}.pl-xl-3{padding-left:1rem !important}.pl-xl-4{padding-left:1.5rem !important}.pl-xl-5{padding-left:3rem !important}.text-xl-left{text-align:left !important}.text-xl-right{text-align:right !important}.text-xl-center{text-align:center !important}}@media (min-width: 1400px){.float-xxl-left{float:left !important}.float-xxl-right{float:right !important}.float-xxl-none{float:none !important}.d-xxl-none{display:none !important}.d-xxl-inline{display:inline !important}.d-xxl-inline-block{display:inline-block !important}.d-xxl-block{display:block !important}.d-xxl-table{display:table !important}.d-xxl-table-row{display:table-row !important}.d-xxl-table-cell{display:table-cell !important}.d-xxl-flex{display:flex !important}.d-xxl-inline-flex{display:inline-flex !important}.flex-xxl-fill{flex:1 1 auto !important}.flex-xxl-row{flex-direction:row !important}.flex-xxl-column{flex-direction:column !important}.flex-xxl-row-reverse{flex-direction:row-reverse !important}.flex-xxl-column-reverse{flex-direction:column-reverse !important}.flex-xxl-grow-0{flex-grow:0 !important}.flex-xxl-grow-1{flex-grow:1 !important}.flex-xxl-shrink-0{flex-shrink:0 !important}.flex-xxl-shrink-1{flex-shrink:1 !important}.flex-xxl-wrap{flex-wrap:wrap !important}.flex-xxl-nowrap{flex-wrap:nowrap !important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-xxl-start{justify-content:flex-start !important}.justify-content-xxl-end{justify-content:flex-end !important}.justify-content-xxl-center{justify-content:center !important}.justify-content-xxl-between{justify-content:space-between !important}.justify-content-xxl-around{justify-content:space-around !important}.justify-content-xxl-evenly{justify-content:space-evenly !important}.align-items-xxl-start{align-items:flex-start !important}.align-items-xxl-end{align-items:flex-end !important}.align-items-xxl-center{align-items:center !important}.align-items-xxl-baseline{align-items:baseline !important}.align-items-xxl-stretch{align-items:stretch !important}.align-content-xxl-start{align-content:flex-start !important}.align-content-xxl-end{align-content:flex-end !important}.align-content-xxl-center{align-content:center !important}.align-content-xxl-between{align-content:space-between !important}.align-content-xxl-around{align-content:space-around !important}.align-content-xxl-stretch{align-content:stretch !important}.align-self-xxl-auto{align-self:auto !important}.align-self-xxl-start{align-self:flex-start !important}.align-self-xxl-end{align-self:flex-end !important}.align-self-xxl-center{align-self:center !important}.align-self-xxl-baseline{align-self:baseline !important}.align-self-xxl-stretch{align-self:stretch !important}.order-xxl-first{order:-1 !important}.order-xxl-0{order:0 !important}.order-xxl-1{order:1 !important}.order-xxl-2{order:2 !important}.order-xxl-3{order:3 !important}.order-xxl-4{order:4 !important}.order-xxl-5{order:5 !important}.order-xxl-last{order:6 !important}.m-xxl-0{margin:0 !important}.m-xxl-1{margin:.25rem !important}.m-xxl-2{margin:.5rem !important}.m-xxl-3{margin:1rem !important}.m-xxl-4{margin:1.5rem !important}.m-xxl-5{margin:3rem !important}.m-xxl-auto{margin:auto !important}.mx-xxl-0{margin-right:0 !important;margin-left:0 !important}.mx-xxl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xxl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xxl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xxl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xxl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xxl-auto{margin-right:auto !important;margin-left:auto !important}.my-xxl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xxl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xxl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xxl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xxl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xxl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xxl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xxl-0{margin-top:0 !important}.mt-xxl-1{margin-top:.25rem !important}.mt-xxl-2{margin-top:.5rem !important}.mt-xxl-3{margin-top:1rem !important}.mt-xxl-4{margin-top:1.5rem !important}.mt-xxl-5{margin-top:3rem !important}.mt-xxl-auto{margin-top:auto !important}.mr-xxl-0{margin-right:0 !important}.mr-xxl-1{margin-right:.25rem !important}.mr-xxl-2{margin-right:.5rem !important}.mr-xxl-3{margin-right:1rem !important}.mr-xxl-4{margin-right:1.5rem !important}.mr-xxl-5{margin-right:3rem !important}.mr-xxl-auto{margin-right:auto !important}.mb-xxl-0{margin-bottom:0 !important}.mb-xxl-1{margin-bottom:.25rem !important}.mb-xxl-2{margin-bottom:.5rem !important}.mb-xxl-3{margin-bottom:1rem !important}.mb-xxl-4{margin-bottom:1.5rem !important}.mb-xxl-5{margin-bottom:3rem !important}.mb-xxl-auto{margin-bottom:auto !important}.ml-xxl-0{margin-left:0 !important}.ml-xxl-1{margin-left:.25rem !important}.ml-xxl-2{margin-left:.5rem !important}.ml-xxl-3{margin-left:1rem !important}.ml-xxl-4{margin-left:1.5rem !important}.ml-xxl-5{margin-left:3rem !important}.ml-xxl-auto{margin-left:auto !important}.p-xxl-0{padding:0 !important}.p-xxl-1{padding:.25rem !important}.p-xxl-2{padding:.5rem !important}.p-xxl-3{padding:1rem !important}.p-xxl-4{padding:1.5rem !important}.p-xxl-5{padding:3rem !important}.px-xxl-0{padding-right:0 !important;padding-left:0 !important}.px-xxl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xxl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xxl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xxl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xxl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xxl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xxl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xxl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xxl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xxl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xxl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xxl-0{padding-top:0 !important}.pt-xxl-1{padding-top:.25rem !important}.pt-xxl-2{padding-top:.5rem !important}.pt-xxl-3{padding-top:1rem !important}.pt-xxl-4{padding-top:1.5rem !important}.pt-xxl-5{padding-top:3rem !important}.pr-xxl-0{padding-right:0 !important}.pr-xxl-1{padding-right:.25rem !important}.pr-xxl-2{padding-right:.5rem !important}.pr-xxl-3{padding-right:1rem !important}.pr-xxl-4{padding-right:1.5rem !important}.pr-xxl-5{padding-right:3rem !important}.pb-xxl-0{padding-bottom:0 !important}.pb-xxl-1{padding-bottom:.25rem !important}.pb-xxl-2{padding-bottom:.5rem !important}.pb-xxl-3{padding-bottom:1rem !important}.pb-xxl-4{padding-bottom:1.5rem !important}.pb-xxl-5{padding-bottom:3rem !important}.pl-xxl-0{padding-left:0 !important}.pl-xxl-1{padding-left:.25rem !important}.pl-xxl-2{padding-left:.5rem !important}.pl-xxl-3{padding-left:1rem !important}.pl-xxl-4{padding-left:1.5rem !important}.pl-xxl-5{padding-left:3rem !important}.text-xxl-left{text-align:left !important}.text-xxl-right{text-align:right !important}.text-xxl-center{text-align:center !important}}@media print{.d-print-none{display:none !important}.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:flex !important}.d-print-inline-flex{display:inline-flex !important}}html{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;height:100%}.dropdown-header,.mime,.list-list .name,.list-list .ext-inner,.list-list-big .name,.list-list-big .ext-inner,.list-list-big .title,.list-blocks .name,.list-blocks .title,.list-grid .name,.list-rows .name,.list-columns .name,.menu-a,.pswp__search,.modal-code-fullscreen .modal-title,.modal-info-mime{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.btn-icon,.context-button,.info-search-reset,.dropdown-menu,.files-li,#files-sortbar,.menu-a,.pswp__top-bar,.pswp__caption__center{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;-o-user-select:none}.btn-icon,.context-button,.info-search-reset{cursor:pointer;border:none;padding:0;color:inherit;background:transparent;-webkit-user-drag:none}@keyframes rotate{to{transform:rotate(360deg)}}.body-loading:before,#topbar.topbar-spinner:after,.menu-spinner:before,.sidebar-spinner:before,.pswp__preloader--active:before{content:'';display:inline-block;width:24px;height:24px;border-style:solid;border-width:2px;border-color:#CFD8DC;border-top-color:var(--strong-color);border-radius:50%;animation:rotate .75s linear infinite}.body-loading #sidebar,.body-loading #main{display:none}.body-loading:before{width:48px;height:48px;position:absolute;left:calc(50vw - 24px);top:calc(50vh - 24px)}.btn-1{color:#90A4AE;border-color:#90A4AE;border-color:transparent}.btn-1:hover{color:#546E7A;background-color:#CFD8DC;border-color:rgba(0,0,0,0)}.btn-check:focus+.btn-1,.btn-1:focus{box-shadow:0 0 0 .2rem rgba(144,164,174,0.5)}.btn-check:checked+.btn-1,.btn-check:active+.btn-1,.btn-1:active,.btn-1.active,.btn-1.dropdown-toggle.show{color:#212529;background-color:#CFD8DC;border-color:rgba(0,0,0,0)}.btn-check:checked+.btn-1:focus,.btn-check:active+.btn-1:focus,.btn-1:active:focus,.btn-1.active:focus,.btn-1.dropdown-toggle.show:focus{box-shadow:0 0 0 .2rem rgba(144,164,174,0.5)}.btn-1:disabled,.btn-1.disabled{color:#90A4AE;background-color:transparent}.btn-icon{padding:7px;border-radius:2px;touch-action:manipulation}.btn-icon:focus{outline:none}.is-icon{padding:7px}#contextmenu{opacity:0;display:none;position:fixed;z-index:1600;margin:0}#contextmenu:before{position:absolute;border:solid 5px;left:calc(var(--offset) - 5px)}#contextmenu.cm-top:before{content:'';top:100%;border-color:#1c2429 transparent transparent transparent}#contextmenu.cm-bottom:before{content:'';bottom:100%;border-color:transparent transparent #1c2429 transparent}#contextmenu.cm-border{border:2px solid #78909C}#contextmenu.cm-border:before{border-width:8px;left:calc(var(--offset) - 8px)}#contextmenu.cm-border.cm-top:before{border-top-color:#78909C}#contextmenu.cm-border.cm-bottom:before{border-bottom-color:#78909C}.context-button{transition:color .2s, background-color .2s, border-color .2s;transition-timing-function:cubic-bezier(0.165, 0.84, 0.44, 1);border-radius:50%}.context-button:focus{outline:none}.context-button .svg-path-dots,.context-button .svg-path-minus{transition:transform 0.2s cubic-bezier(0.165, 0.84, 0.44, 1),opacity 0.2s cubic-bezier(0.165, 0.84, 0.44, 1);transform-origin:center}.context-button .svg-path-minus{opacity:0;transform:rotate(-90deg)}.context-button.cm-active{color:#ECEFF1 !important;background-color:#263238 !important}.context-button.cm-active .svg-path-dots{opacity:0;transform:rotate(90deg)}.context-button.cm-active .svg-path-minus{opacity:1;transform:rotate(0deg)}.dropdown-menu{background:linear-gradient(0deg, #1c2429, #263238);box-shadow:0 1rem 2rem rgba(0,0,0,0.2)}.dropdown-menu .svg-icon{margin:0 .5rem 0 -.5rem}.dropdown-menu-right:before{position:absolute;border:solid 5px;right:14px;content:'';bottom:100%;border-color:transparent transparent #1c2429 transparent}.dropdown-header{line-height:24px;background-color:#1c2429;margin-bottom:3px;max-width:200px;min-width:100%;margin-top:-.5rem;border-radius:3px 3px 0 0;margin-bottom:5px}.dropdown-item{transition:color .15s, background-color .15s;line-height:25px}.dropdown-item .svg-icon{color:#78909C}.dropdown-item:hover .svg-icon,.dropdown-item:focus .svg-icon,.dropdown-item:active .svg-icon,.dropdown-item.active .svg-icon{color:inherit}.dropdown-item:hover .svg-icon-marker{color:#d85040}.dropdown-item:focus{outline:none}.dropdown .dropdown-menu{display:block;visibility:hidden;opacity:0;transition:visibility 0s .15s, opacity .15s, transform 0s .15s;transform:translateY(-3px)}.dropdown .dropdown-header{text-transform:uppercase}.dropdown.touch-open .dropdown-menu,.dropdown.mouse-hover:hover .dropdown-menu{z-index:1001;transition:visibility 0s, opacity .15s, transform .15s;transition-timing-function:cubic-bezier(0.165, 0.84, 0.44, 1);visibility:visible;opacity:1;transform:translateY(0)}.dropdown.mouse-hover .dropdown-menu{transition:visibility 0s .4s, opacity .15s .25s, transform 0s .4s}.dropdown.mouse-hover:hover .dropdown-menu{transition-delay:.2s}@media screen and (hover: hover) and (pointer: fine){.dropdown-menu{font-size:15px}}#license_modal{color:var(--col800)}#pay .svg-icon-check{color:var(--bs-success)}#pay .svg-icon{margin-right:6px}#pay_info_expand_button{margin-left:3px}#pay_info_expand_button:after{content:'- less'}#pay_info_expand_button.collapsed:after{content:'+ more'}.ul-reset{line-height:22px;margin:.5rem 0;padding:0 0 0 28px;text-indent:0;list-style-type:none}.ul-reset .svg-icon{margin-left:-30px;vertical-align:middle}#files-login-container{max-width:360px;margin:0 auto;padding:10vh 0 50px}.header{font-weight:200;text-align:center}.mylogin{position:absolute;bottom:100%}.svg-icon{fill:currentColor}.svg-file-icon{fill:#90A4AE}.svg-icon-application{fill:#0064c8}.svg-icon-archive{fill:#f8c560}.svg-icon-audio{fill:#55617e}.svg-icon-cd{fill:#e9967a}.svg-icon-code{fill:#f19a3a}.svg-icon-excel{fill:#94cba2}.svg-icon-font,.svg-icon-font .svg-file-icon-icon{fill:#607D8B}.svg-icon-image{fill:#8cbd61}.svg-icon-image .svg-file-icon-text-bg{fill:#72a645}.svg-icon-pdf{fill:#ca4d50}.svg-icon-powerpoint{fill:#e67841}.svg-icon-text{fill:#90A4AE}.svg-icon-video{fill:#ec6068}.svg-icon-word{fill:#0399e1}#list-ul .svg-icon-folder{fill:#FFCA28}.svg-file-icon-bg{fill:#e9e9e0}.svg-file-icon-flip{fill:#d9d7ca}.svg-file-icon-icon{fill:#c8bdb8}.svg-file-icon-ext{fill:white;font-weight:600;text-transform:uppercase;text-anchor:middle;font-size:12px}.f_10{font-size:10px}.f_11{font-size:11px}.svg-folder-icon-bg{fill:#FFA000}.svg-folder-icon-fg{fill:#FFCA28}.svg-folder-icon-symlink{fill:#ffe9a8}.svg-icon-no{fill:#dc3545}.list{color:#546E7A;list-style:none;margin:0;padding:0}.files-li{position:relative;cursor:pointer}.files-li.cm-active{z-index:1}.files-li.cm-active:before{border:2px solid #CFD8DC;top:-1px;right:-2px;bottom:-1px;left:-2px}.files-li.cm-active:before{content:'';position:absolute;pointer-events:none;z-index:1}.img-wrapper{display:block;position:relative}.img-wrapper:hover{text-decoration:none}.img-bg{background-size:50%;background-repeat:no-repeat;background-position:center;background-image:url("data:image/svg+xml;utf8,")}.size,.dimensions,.exif,.date{white-space:nowrap}.gps,.google-maps-link{color:#B0BEC5}.gps:hover,.google-maps-link:hover{color:#d85040}.flex{display:none;flex-basis:100%}.list-grid .files-context,.list-rows .files-context,.list-columns .files-context{color:#90A4AE}@media screen and (hover: none){.list-grid .files-context,.list-rows .files-context,.list-columns .files-context{display:none;color:#B0BEC5}.list-columns .files-context,.list-large.list-grid .files-context,.list-large.list-rows .files-context,.list-large.list-columns .files-context{display:block}.list-grid .li-img .files-context,.list-rows .li-img .files-context,.list-columns .li-img .files-context{display:none}}.list-grid .img-loaded .files-context:not(.cm-active),.list-rows .img-loaded .files-context:not(.cm-active),.list-columns .img-loaded .files-context:not(.cm-active){color:white}.list-grid .img-loaded .files-context:hover,.list-rows .img-loaded .files-context:hover,.list-columns .img-loaded .files-context:hover{background-color:#263238;color:#ECEFF1}.files-context{position:absolute;top:1px;right:1px;color:#B0BEC5}@media screen and (hover: hover) and (pointer: fine){.files-context{color:#78909C;display:none}.files-li:hover .files-context,.files-context.cm-active{display:block}.files-context:hover{background-color:#CFD8DC;color:#455A64}}.list-list{margin:0;padding:0;background-color:white}@media (min-width: 1200px){.list-list{max-width:1000px}}.list-list .files-li:first-child{border-top:1px solid transparent}.list-list .files-li:not(:last-child){border-bottom:1px solid #ECEFF1}.list-list .files-li:nth-child(even){background-color:#F8F9Fa}.list-list .files-li.cm-active{background-color:#ECEFF1}@media (max-width: 767.98px){.list-list .files-li.cm-active:before{border:1px solid #CFD8DC;top:-1px;right:-1px;bottom:-1px;left:-1px}}.list-list .data{line-height:24px;display:flex;flex-wrap:wrap;align-items:flex-start}.list-list .img-wrapper,.list-list .title,.list-list .fileperms,.list-list .mime,.list-list .exif{display:none}.list-list .icon{order:1}.list-list .name{order:2;flex:1;font-weight:500;color:#455A64;padding-left:7px}.list-list .gps{order:3;margin-left:5px}.list-list .ext{text-transform:uppercase;order:5;font-weight:600;color:#607D8B;font-size:12px}.list-list .ext-inner{display:inline-block;background-color:#dee4e7;padding:0 7px;border-radius:2px;max-width:60px;float:right}@media (max-width: 767.98px){.list-list .data{padding:10px 0 10px 10px}.list-list .name{font-size:18px}.list-list .ext{order:4}.list-list .ext-inner{margin-left:10px}.list-list .flex{order:6;display:block}.list-list .date{order:7;margin-left:31px}.list-list .size{order:8}.list-list .dimensions{order:9}.list-list .size:before,.list-list .dimensions:before{content:'|';color:#CFD8DC;margin:0 10px}}@media (max-width: 575.98px){.list-list .data{padding:10px 0 10px 7px}.list-list .ext{width:0;visibility:hidden}}@media (max-width: 374px){.list-list .date{margin-left:2px}}@media (min-width: 768px){.list-list{margin:20px;padding:10px 0;border-radius:3px}.list-list .data{padding:6px 0 6px 8px}.list-list .dimensions{order:4;margin-left:.5rem;color:#78909C}.list-list .ext{order:5;flex-basis:65px}.list-list .size{order:6;font-weight:500;margin-right:20px;text-align:right;flex-basis:100px}.list-list .date{order:7;flex-basis:120px}}@media (min-width: 992px) and (max-width: 1199.98px){.sidebar-closed .list-list{padding:20px 0}.sidebar-closed .list-list .data{padding:6px 0 6px 15px}.sidebar-closed .list-list .name{padding-left:10px}.sidebar-closed .list-list .dimensions{margin-left:1rem}.sidebar-closed .list-list .ext{flex-basis:70px}.sidebar-closed .list-list .size{margin-right:30px;flex-basis:110px}}@media (min-width: 1200px){.list-list{padding:20px 0}.list-list .data{padding:6px 0 6px 15px}.list-list .name{padding-left:10px}.list-list .dimensions{margin-left:1rem}.list-list .ext{flex-basis:70px}.list-list .size{margin-right:30px;flex-basis:110px}}@media screen and (hover: hover) and (pointer: fine) and (min-width: 768px){.list-list .files-li:after{display:none;content:'';position:absolute;pointer-events:none;border-right:2px solid #78909C;border-left:2px solid #78909C;top:-1px;right:-2px;bottom:-1px;left:-2px;z-index:1}.list-list .files-li:hover:after{display:block}}@media screen and (hover: hover) and (pointer: fine){.list-list .files-li:hover{background-color:#ECEFF1}.list-list .files-li:hover .name{color:#37474F}.list-list .files-li:hover .size,.list-list .files-li:hover .date,.list-list .files-li:hover .dimensions,.list-list .files-li:hover .ext{color:#455A64}.list-list .files-li:hover .ext-inner{background-color:#CFD8DC}.list-list .files-li:hover .gps:not(:hover){color:#90A4AE}}@media (max-width: 767.98px){.list-list .files-context{padding:9px}.list-list .ext{margin-right:47px}}@media (min-width: 768px){.list-list .files-context{padding:5px}.list-list .date{margin-right:20px}}@media (min-width: 1200px){.list-list-big{max-width:1000px}}.list-list-big .files-li{display:flex;background-color:white}.list-list-big .files-li:not(:last-child){border-bottom:1px solid #ECEFF1}.list-list-big .files-li:nth-child(even){background-color:#F8F9Fa}.list-list-big .files-li.cm-active{background-color:#ECEFF1}@media (max-width: 991.98px){.list-list-big .files-li.cm-active:before{border:1px solid #CFD8DC;top:-1px;right:-1px;bottom:-1px;left:-1px}}.list-list-big .img-wrapper{flex-basis:100px;min-width:100px;background-color:rgba(0,0,0,0.02)}.list-list-big .img-wrapper-img{min-height:100px}.list-list-big .img-wrapper-svg{padding:10px}.list-list-big .img-wrapper-file{padding:15px}.list-list-big .img-wrapper-folder{padding:3px 18px}.list-list-big .svg-folder-icon{height:100%;max-width:100%}.list-list-big .img{width:100%}.list-list-big .img-img{object-fit:cover;min-height:calc(100px / var(--ratio));height:100%}.list-list-big .data{line-height:24px;display:flex;flex-wrap:wrap;flex:1;align-content:flex-start;max-width:calc(100% - 100px)}.list-list-big .icon,.list-list-big .fileperms,.list-list-big .mime,.list-list-big .gps{display:none}.list-list-big .name{order:2;flex:1;font-weight:500;color:#455A64;padding-right:1px}.list-list-big .ext{text-transform:uppercase;order:5;font-weight:600;color:#607D8B;font-size:12px}.list-list-big .ext-inner{display:inline-block;background-color:#dee4e7;padding:0 7px;border-radius:2px;max-width:60px;float:right}.list-list-big .title,.list-list-big .exif{flex-basis:100%}.list-list-big .title{order:16;margin-top:2px}.list-list-big .exif{order:17;color:#607D8B;margin-top:3px}.list-list-big .svg-icon-cellphone,.list-list-big .svg-icon-camera{color:#B0BEC5}.list-list-big .exif-item:after{color:#90A4AE}@media (max-width: 767.98px){.list-list-big .data{padding:10px 5px 10px 15px}.list-list-big .name{font-size:18px}.list-list-big .ext{order:4}.list-list-big .ext-inner{margin-left:15px}.list-list-big .flex{order:6;display:block}.list-list-big .date{order:7}.list-list-big .size{order:8}.list-list-big .dimensions{order:9;margin-right:-5px}.list-list-big .size:before,.list-list-big .dimensions:before{content:'|';color:#CFD8DC;margin:0 10px}}@media (max-width: 575.98px){.list-list-big .date{flex-basis:100%}.list-list-big .exif,.list-list-big .title{display:none}.list-list-big .size:before{content:none}.list-list-big .ext{width:0;visibility:hidden}}@media (min-width: 768px){.list-list-big .data{padding:10px 5px 5px 15px}.list-list-big .dimensions{order:4;margin-left:.5rem;color:#78909C}.list-list-big .ext{order:5;flex-basis:65px}.list-list-big .size{order:6;font-weight:500;margin-right:20px;text-align:right;flex-basis:100px}.list-list-big .date{order:7;flex-basis:120px}}@media (min-width: 992px){.list-list-big{margin:20px}.list-list-big .files-li:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.list-list-big .files-li:first-child .img-wrapper{border-top-left-radius:3px;overflow:hidden}.list-list-big .files-li:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.list-list-big .files-li:last-child .img-wrapper{border-bottom-left-radius:3px;overflow:hidden}.sidebar-closed .list-list-big .data{padding:10px 5px 5px 15px}.sidebar-closed .list-list-big .ext{flex-basis:70px}.sidebar-closed .list-list-big .size{margin-right:30px;flex-basis:110px}}@media (min-width: 1200px){.list-list-big .data{padding:10px 5px 5px 15px}.list-list-big .ext{flex-basis:70px}.list-list-big .size{margin-right:30px;flex-basis:110px}}@media screen and (hover: hover) and (pointer: fine) and (min-width: 992px){.list-list-big .files-li:after{display:none;content:'';position:absolute;pointer-events:none;border-right:2px solid #78909C;border-left:2px solid #78909C;top:-1px;right:-2px;bottom:-1px;left:-2px;z-index:1}.list-list-big .files-li:hover:after{display:block}}@media screen and (hover: hover) and (pointer: fine){.list-list-big .files-li:hover .name{color:#37474F}.list-list-big .files-li:hover .size,.list-list-big .files-li:hover .date,.list-list-big .files-li:hover .dimensions,.list-list-big .files-li:hover .ext{color:#455A64}}.list-list-big .files-context{padding:9px}@media (max-width: 767.98px){.list-list-big .ext{margin-right:44px}}@media (max-width: 575.98px){.list-list-big .ext{margin-right:39px}}@media (min-width: 768px){.list-list-big .date{margin-right:23px}}.list-blocks .files-li{overflow:hidden;display:flex;background-color:white;margin:0 0 1px}@media (max-width: 575.98px){.list-blocks .files-li.cm-active{overflow:visible;background-color:#ECEFF1}.list-blocks .files-li.cm-active:before{border:1px solid #CFD8DC;top:-1px;right:-1px;bottom:-1px;left:-1px}}@media (min-width: 576px){.list-blocks .files-li.cm-active{border-bottom-color:#CFD8DC !important}.list-blocks .files-li.cm-active:before{top:0;right:0;bottom:-1px;left:0}}.list-blocks .img-wrapper{flex-basis:140px;min-width:140px;height:140px;background-color:#F8F9Fa}.list-blocks .img-wrapper-file,.list-blocks .img-wrapper-folder{padding:29px}.list-blocks .img-wrapper-svg{padding:5px}.list-blocks .img{width:100%;height:100%}.list-blocks .img-img{object-fit:cover}.list-blocks .img-svg{object-fit:contain}.list-blocks .data{padding:10px 5px 5px 15px;overflow:hidden;width:100%;line-height:24px}.list-blocks .fileperms,.list-blocks .mime,.list-blocks .ext,.list-blocks .icon,.list-blocks .exif,.list-blocks .gps{display:none}.list-blocks .name,.list-blocks .title,.list-blocks .dimensions,.list-blocks .size,.list-blocks .date{display:block}.list-blocks .name{margin-bottom:2px;font-weight:500;order:1;color:#37474F}.list-blocks .title{color:#607D8B;margin:-2px 0 2px 0}.list-blocks .title,.list-blocks .dimensions,.list-blocks .size,.list-blocks .date{line-height:23px}@media (max-width: 374px){.list-blocks .data{padding-left:10px}}@media (min-width: 576px){.list-blocks .files-li{border-radius:3px;margin:10px;position:relative;border-bottom:1px solid #CFD8DC}}@media (min-width: 768px){.list-blocks{display:flex;flex-wrap:wrap;margin:5px}.list-blocks .files-li{flex-basis:356px;flex-grow:1;margin:5px}.list-blocks:after{content:'';flex-grow:1;flex-basis:366px}.list-blocks .name{font-size:16px}}@media (min-width: 992px){.list-blocks{margin:7px}.list-blocks .files-li{margin:7px}.list-blocks:after{flex-basis:370px}}.list-blocks .name{margin-right:32px}@media screen and (hover: hover) and (pointer: fine){.list-blocks .name{margin-right:0}.list-blocks .files-li:hover{border-bottom-color:#78909C}.list-blocks .files-li:hover .name{margin-right:32px}}.list-blocks [data-tooltip]:before,.list-blocks [data-tooltip]:after{display:none}.list-blocks .files-context{top:2px;right:2px;padding:8px}:root{--grid-small: 100px;--grid-large: 158px}.list-grid{margin:1px;display:grid;grid-template-columns:repeat(auto-fill, minmax(var(--grid-small), 1fr));grid-gap:1px}.list-grid .files-li.cm-active .img-wrapper{background-color:white}.list-grid .files-li.cm-active:before{border-radius:3px;right:-1px;left:-1px}.list-grid .files-li.cm-active.img-loaded:before{border-color:#263238}.list-grid .img-wrapper{background-color:#F8F9Fa;padding-top:100%;background-position-y:33%}.list-grid .img-img,.list-grid .img-svg{position:absolute;top:0;height:100%;width:100%}.list-grid .img-img{object-fit:cover}.list-grid .img-svg{object-fit:contain;padding:5%}.list-grid .svg-file-icon{padding:10% 10% 35%}.list-grid .svg-folder-icon{padding:5% 5% 30%}.list-grid .data{position:absolute;bottom:0;width:100%;padding:2px 6px 3px;text-align:center;background-color:white;font-size:14px;border-top:1px solid #ECEFF1}.list-grid .img-loaded .data{display:none;background:linear-gradient(rgba(0,0,0,0), rgba(0,0,0,0.5) 90%);color:white;font-weight:500;border:none;padding:3px 6px 4px}.list-grid .mime,.list-grid .date,.list-grid .icon,.list-grid .size,.list-grid .exif,.list-grid .dimensions,.list-grid .ext,.list-grid .title,.list-grid .gps{display:none}.list-grid .name{display:block}.list-grid.list-large{grid-template-columns:repeat(auto-fill, minmax(var(--grid-large), 1fr))}.list-grid.list-large .svg-file-icon{padding:12% 12% 33%}.list-grid.list-large .svg-folder-icon{padding:10% 10% 30%}.list-grid.list-large .data{padding:5px 8px;font-size:15px}.list-grid.list-large .img-loaded .data{display:block;padding:6px 7px 7px}@media (min-width: 576px){.list-grid{margin:5px;grid-gap:5px}.list-grid.list-large{margin:10px;grid-gap:10px}.list-grid .img-wrapper{border-radius:3px;overflow:hidden}.list-grid .data{border-bottom:1px solid #CFD8DC;border-radius:0 0 3px 3px}}@media (min-width: 768px){.list-grid{margin:10px;grid-gap:10px}}@media (min-width: 992px){.list-grid.list-large{margin:15px;grid-gap:15px}}.list-grid .files-context{padding:4px}.list-grid.list-large .files-context{padding:7px}:root{--row-small-height: 100px;--row-large-height: 160px}.list-rows{display:flex;flex-wrap:wrap;margin:3px}.list-rows .files-li{flex-basis:calc(var(--ratio) * var(--row-small-height));flex-grow:1;margin:3px}.list-rows .files-li.cm-active .img-wrapper,.list-rows .files-li:active .img-wrapper{background-color:white}.list-rows .files-li.cm-active:before,.list-rows .files-li:active:before{border-radius:3px;right:-1px;left:-1px}.list-rows .files-li.cm-active.img-loaded:before,.list-rows .files-li:active.img-loaded:before{border-color:#263238}.list-rows:after{content:'';flex-basis:var(--row-small-height);flex-grow:9999}.list-rows .img-wrapper{height:var(--row-small-height);background-color:#F8F9Fa;border-radius:3px;overflow:hidden;background-size:auto 50%;background-position-y:12px}.list-rows .img-img,.list-rows .img-svg{width:100%;height:100%}.list-rows .img-img{object-fit:cover}.list-rows .img-svg{object-fit:contain;padding:5%}.list-rows .svg-file-icon{padding:10px 0 38px}.list-rows .svg-folder-icon{padding:5px 0 33px}.list-rows .data{position:absolute;bottom:0;width:100%;font-size:14px;padding:2px 6px 3px;text-align:center;background-color:white;border-top:1px solid #ECEFF1;border-bottom:1px solid #CFD8DC;border-radius:0 0 3px 3px}.list-rows .img-loaded .data{font-weight:500;display:none;background:linear-gradient(rgba(0,0,0,0), rgba(0,0,0,0.5) 90%);color:white;border:none;padding:3px 6px 4px}.list-rows .mime,.list-rows .date,.list-rows .icon,.list-rows .size,.list-rows .exif,.list-rows .dimensions,.list-rows .ext,.list-rows .title,.list-rows .gps{display:none}.list-rows .name{display:block}@media (min-width: 576px){.list-rows{margin:5px}.list-rows .files-li{margin:5px}.list-rows.list-large .files-li{flex-basis:calc(var(--ratio) * var(--row-large-height))}.list-rows.list-large:after{flex-basis:var(--row-large-height)}.list-rows.list-large .img-wrapper{height:var(--row-large-height);background-position-y:25px}.list-rows.list-large .svg-file-icon{padding:20px 0 56px}.list-rows.list-large .svg-folder-icon{padding:15px 0 51px}.list-rows.list-large .data{padding:5px 8px;font-size:15px}.list-rows.list-large .img-loaded .data{display:block;padding:6px 7px 7px}}@media (min-width: 992px){.list-rows.list-large{margin:7px}.list-rows.list-large .files-li{margin:7px}}.list-rows .files-context{padding:4px}.list-rows.list-large .files-context{padding:7px}@media screen and (hover: hover) and (pointer: fine){.list-grid .files-li:hover:not(.img-loaded) .img-wrapper,.list-rows .files-li:hover:not(.img-loaded) .img-wrapper{background-color:white}.list-grid .files-li:hover:not(.img-loaded) .data,.list-rows .files-li:hover:not(.img-loaded) .data{color:#455A64;border-bottom-color:#78909C}.list-grid .img-loaded .data,.list-rows .img-loaded .data{display:block;opacity:0;transform:translateY(2px);bottom:2px}.list-grid .img-loaded:hover .data,.list-rows .img-loaded:hover .data{bottom:0;transition:background-color .2s, transform .2s .2s, opacity .2s .2s;transition-timing-function:cubic-bezier(0.165, 0.84, 0.44, 1);opacity:1;transform:translateY(0)}.list-grid .img-loaded:hover .data:hover,.list-rows .img-loaded:hover .data:hover{transition-delay:0s;background-color:rgba(0,0,0,0.8)}}:root{--columns-width: 160px}.list-columns{columns:var(--columns-width);column-gap:5px;margin:5px}.list-columns .files-li{-webkit-column-break-inside:avoid;page-break-inside:avoid;break-inside:avoid-column;padding-bottom:5px}.list-columns .files-li.cm-active .img-wrapper{background-color:white}.list-columns .files-li.cm-active:before{border-radius:3px;top:0;right:0;bottom:5px;left:0}.list-columns .files-li.cm-active.img-loaded:before{border-color:#263238}.list-columns .img-wrapper{background-color:#F8F9Fa;border-radius:3px 3px 0 0;overflow:hidden;background-size:40%}.list-columns .img-wrapper-img{padding-bottom:calc(100% / var(--ratio));height:0}.list-columns .img-wrapper-svg{height:var(--columns-width)}.list-columns .img-wrapper-file,.list-columns .img-wrapper-folder{height:calc(var(--columns-width) - 32px)}.list-columns .img-img,.list-columns .img-svg{width:100%}.list-columns .img-img{min-height:calc(var(--columns-width) / var(--ratio));object-fit:scale-down}.list-columns .img-svg{object-fit:contain;height:100%}.list-columns .svg-folder-icon{padding:10%}.list-columns .svg-file-icon{padding:15%}.list-columns .data{font-size:15px;text-align:center;padding:3px 8px 5px;background-color:white;border-radius:0 0 3px 3px;border-top:1px solid #ECEFF1;border-bottom:1px solid #CFD8DC;position:relative}.list-columns .li-img.img-loaded .data{border-top-color:transparent}.list-columns .mime,.list-columns .date,.list-columns .icon,.list-columns .size,.list-columns .exif,.list-columns .dimensions,.list-columns .ext,.list-columns .title,.list-columns .gps{display:none}.list-columns .name{display:block}@media (min-width: 576px){.list-columns{column-gap:10px;margin:10px}.list-columns .files-li{padding-bottom:10px}.list-columns .files-li.cm-active:before{bottom:10px}}@media (min-width: 992px){.list-columns{column-gap:15px;margin:15px}.list-columns .files-li{padding-bottom:15px}.list-columns .files-li.cm-active:before{bottom:15px}}@media screen and (hover: hover) and (pointer: fine){.list-columns .files-li:hover:not(.img-loaded) .img-wrapper{background-color:white}.list-columns .files-li:hover .data{color:#455A64;border-bottom-color:#78909C}}.list-columns .files-context{padding:7px;top:2px;right:2px}.img-contain .img-img{object-fit:scale-down}.img-contain .img-wrapper-img{background-color:#181f23 !important}#change-layout .active .svg-icon-layout_large{opacity:1}#change-layout .dropdown-item:first-of-type .svg-path-layout_small,#change-layout .dropdown-item:first-of-type.subindex1 .svg-path-layout_large{display:inline}#change-layout .dropdown-item:first-of-type .svg-path-layout_large,#change-layout .dropdown-item:first-of-type.subindex1 .svg-path-layout_small{display:none}.svg-icon-layout_large{float:right;margin:0 -.5rem 0 0 !important;opacity:0}.svg-path-layout_small,.subindex1 .svg-path-layout_large{display:none}.subindex1 .svg-path-layout_small{display:inline}.cover-toggle{margin-top:.5rem;padding:.5rem 0 .5rem 50px;background-color:rgba(0,0,0,0.3);transition:background-color .2s}.cover-toggle .form-check-input,.cover-toggle .form-check-label{cursor:pointer}.cover-toggle:hover{background-color:rgba(0,0,0,0.5);color:#ECEFF1}.form-check-input{-webkit-appearance:none;-moz-appearance:none}.info-search{background:linear-gradient(90deg, #263238, #37474F)}#files-sortbar{background:linear-gradient(90deg, #263238, #37474F)}.info-search+#files-sortbar,.has-breadcrumbs #files-sortbar{background:linear-gradient(90deg, #1c2429, #263238)}.info-search+#files-sortbar .sortbar-active,.info-search+#files-sortbar .sortbar-item:hover,.has-breadcrumbs #files-sortbar .sortbar-active,.has-breadcrumbs #files-sortbar .sortbar-item:hover{background-color:#1c2429}.has-breadcrumbs .info-search{background:linear-gradient(90deg, #1c2429, #263238)}.has-breadcrumbs .info-search+#files-sortbar{background:linear-gradient(90deg, #263238, #37474F)}.has-breadcrumbs .info-search+#files-sortbar .sortbar-active,.has-breadcrumbs .info-search+#files-sortbar .sortbar-item:hover{background-color:#263238}#topbar{z-index:2}#topbar:after{position:absolute;opacity:0;margin:7px 0 0 7px}@media (min-width: 768px){#topbar:after{margin:1rem 0 0 1rem}}#topbar.topbar-spinner:after{transition:opacity .2s;opacity:1}.topbar-sticky{position:-webkit-sticky;position:sticky;width:100%;top:0;z-index:2}.headroom{will-change:transform, opacity;transition:transform 0.2s cubic-bezier(0.215, 0.61, 0.355, 1),opacity 0.2s}.headroom--unpinned{transform:translateY(-10%);opacity:0;pointer-events:none}#topbar-top{background:linear-gradient(90deg, #1c2429, #263238);padding:10px;display:flex;min-height:58px;--transition-delay: 0s;--transition-delay-opacity: 0s;--transition-delay-visibility: .2s}@media (min-width: 768px){#topbar-top{padding-left:1rem}}.menu-enabled #topbar-top{padding-left:48px}@media (min-width: 992px){.menu-enabled #topbar-top{padding-left:10px}}.menu-enabled.sidebar-closed #topbar-top{padding-left:48px}#change-layout,#change-sort,#files-notifications,#logout,#topbar-fullscreen{margin-left:3px}#change-sort{margin-right:auto}#search{appearance:none;-webkit-appearance:none;margin-right:.5rem;outline:none;padding:0 10px;width:100%;transition:border-color 0.2s,width 0.15s cubic-bezier(0.165, 0.84, 0.44, 1);background-color:#37474F;border:2px solid transparent;border-radius:.15rem;color:#ECEFF1}#search:disabled{cursor:not-allowed;opacity:.5}#search::placeholder{color:#90A4AE}#search:focus{border-color:#90A4AE}#search:not(:placeholder-shown){border-color:#78a642}#search.nomatches{border-color:brown}@media (min-width: 768px){#search{width:200px}#search:focus,#search:not(:placeholder-shown){width:300px}}#search::-ms-input-placeholder{color:#90A4AE}.btn-topbar{color:#CFD8DC;border-radius:50%;padding:10px;margin:-3px 0}.btn-topbar:hover{transition:background-color .1s}.mouse-hover .btn-topbar{transition:color .1s .2s, background-color .1s .2s}.dropdown:hover .btn-topbar,.btn-topbar:hover{transition-delay:0s;background-color:#2e8b57;color:white}#breadcrumbs{list-style:none;margin:0;line-height:24px;color:#CFD8DC;background:linear-gradient(90deg, #263238, #37474F);padding:.5rem .5rem .5rem 39px}@media (min-width: 768px){#breadcrumbs{padding:.5rem .5rem .5rem 48px}}#breadcrumbs:before{font-size:15px;padding:0 8px;opacity:0;transition:opacity .2s;display:inline-block;content:attr(data-info);float:right;color:#ECEFF1;background-color:#263238;margin-left:1px;border-radius:2px}#breadcrumbs.breadcrumbs-info:before{opacity:1}@media (pointer: fine){#breadcrumbs{font-size:14px}#breadcrumbs:before{font-size:13px}}.crumb{transform-origin:left;display:inline-block;white-space:nowrap}.crumb:before{content:'/'}.crumb:first-child{margin-left:-40px}.crumb:first-child:before{content:none}.crumb-active .crumb-link{transition:transform 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);background-color:#1c2429;color:#F8F9Fa;border-radius:2px;transform:translateX(8px);margin-right:8px;font-weight:500}.crumb-link{display:inline-block;color:#CFD8DC;padding:0 8px}.crumb-link:hover{color:#F8F9Fa}@media screen and (hover: none){.crumb-link:hover{text-decoration:none}}@media screen and (hover: hover){.crumb-link{transition:color .2s}}#files-sortbar{color:#CFD8DC;font-weight:500;font-size:14px;line-height:24px}@media (max-width: 767.98px){#files-sortbar{display:none}}.sortbar-blocks,.sortbar-grid,.sortbar-rows,.sortbar-columns{display:none}.sortbar-inner{display:flex}@media (min-width: 1200px){.sortbar-inner{max-width:1020px}}.sortbar-item{padding-top:8px;padding-bottom:8px;cursor:pointer;transition:background-color .2s}.sortbar-item .svg-icon-menu_down{color:#607D8B;margin-left:3px;font-size:24px}.sortbar-active,.sortbar-item:hover{color:#ECEFF1;background-color:#263238}.sortbar-active .svg-icon-menu_down,.sortbar-item:hover .svg-icon-menu_down{color:inherit}.sortbar-name{flex:1;padding-left:59px}.sortbar-kind{padding-left:15px;padding-right:5px}.sortbar-filesize{text-align:right;flex-basis:100px;padding-right:5px}.sortbar-date{flex-basis:150px;padding-left:10px}@media (min-width: 992px) and (max-width: 1199.98px){.sidebar-closed .sortbar-name{padding-left:68px}.sidebar-closed .sortbar-kind{padding-right:10px}.sidebar-closed .sortbar-filesize{flex-basis:110px;padding-right:10px}.sidebar-closed .sortbar-date{flex-basis:155px;padding-left:15px}}@media (min-width: 1200px){.sortbar-name{padding-left:68px}.sortbar-kind{padding-right:10px}.sortbar-filesize{flex-basis:110px;padding-right:10px}.sortbar-date{flex-basis:155px;padding-left:15px}}.sortbar-list{padding:0 20px 0 0}.sortbar-list-big .sortbar-name{padding-left:115px}.sortbar-list-big .sortbar-date{flex-basis:158px}@media (max-width: 991.98px){.sortbar-list-big{margin-bottom:1px}}@media (min-width: 992px){.sortbar-list-big{padding:0 20px 0 0}.sortbar-list-big .sortbar-name{padding-left:135px}.sidebar-closed .sortbar-list-big .sortbar-date{flex-basis:163px}}@media (min-width: 1200px){.sortbar-list-big .sortbar-date{flex-basis:163px}}.sort-asc .svg-path-menu_down,.sort-desc .svg-path-menu_up{display:none}.sort-asc:hover .svg-path-menu_down,.sort-desc:hover .svg-path-menu_up{display:inline;fill:rgba(255,255,255,0.3)}#change-sort .svg-icon-menu_down{visibility:hidden;float:right;margin:0 -.5rem 0 0}#change-sort .dropdown-item:hover .svg-icon-menu_down,#change-sort .active .svg-icon-menu_down{visibility:visible}#topbar-info{display:none;padding:.5rem .5rem .5rem 7px;line-height:24px}@media (min-width: 768px){#topbar-info{padding:.5rem .5rem .5rem 1rem}}@media (pointer: fine){#topbar-info{font-size:14px}}#topbar-info>.svg-icon:first-child{margin-right:.5rem}#topbar-info.info-search,#topbar-info.info-warning,#topbar-info.info-error{display:block}.nomatches+#files-sortbar,.info-warning+#files-sortbar,.info-error+#files-sortbar{display:none}.info-search{color:#CFD8DC}.info-search.nomatches .info-search-count,.info-search.nomatches .info-search-phrase{background-color:brown}.info-warning{background-color:var(--strong-color);color:white}.info-error{background-color:brown;color:white}.info-search-count,.info-search-phrase{word-break:break-all;font-weight:500;border-radius:2px;background-color:#78a642;color:white;padding:0 8px;display:inline-block;text-align:center;min-width:24px}.info-search-count{margin:0 8px 0 0}.info-search-phrase{margin:0 8px}.info-search-reset{border-radius:50%;padding:4px;margin:-4px -4px}@media screen and (hover: hover){.info-search-reset:hover{background-color:#37474F;color:#ECEFF1}}:root{--sidebar-width: calc(10vw + 180px);--sidebar-width-small: 85vw;--sidebar-width-hover: 480px}body{overflow-x:hidden;min-height:100%}.has-scrollbars{scrollbar-width:thin;scrollbar-color:#78909C transparent}.has-scrollbars::-webkit-scrollbar{-webkit-appearance:none;width:10px}.has-scrollbars::-webkit-scrollbar-thumb{border:1px solid #ECEFF1;border-radius:5px;background-color:#90A4AE}.has-scrollbars::-webkit-scrollbar-thumb:hover{background-color:var(--strong-color)}.menu-enabled #main{width:100%}@media (min-width: 992px){.menu-enabled #main{width:calc(100% - var(--sidebar-width));transform:translateX(var(--sidebar-width));transition:transform .25s cubic-bezier(0.4, 0.5, 0, 1),width 0s .25s}}@media (min-width: 992px){.menu-enabled.sidebar-closed #main{width:100%;transition:transform .25s cubic-bezier(0.4, 0.5, 0, 1),width 0s 0s;transform:translateX(0)}}#sidebar,#sidebar-bg{position:fixed;top:0;left:0;height:100%}#sidebar{z-index:3}.svg-path-menu{display:none}@media (min-width: 992px){.svg-path-menu_back{display:inline;transform-origin:center}}.sidebar-closed #sidebar{width:0}.sidebar-closed .svg-path-menu{display:inline}.sidebar-closed .svg-path-menu_back{display:none}.sidebar-closed #sidebar-inner{transform:translateX(-100%)}@media screen and (hover: hover) and (pointer: fine) and (min-width: 992px){.sidebar-closed #sidebar{width:5px}.sidebar-closed #sidebar-inner{transition-delay:.3s;width:var(--sidebar-width-hover)}.sidebar-closed #sidebar-bg{transition:opacity .25s .3s,visibility 0s .55s}.sidebar-closed .svg-path-menu_back{transform:scaleX(-1)}.sidebar-closed #sidebar-toggle:hover .svg-path-menu{display:none}.sidebar-closed #sidebar-toggle:hover .svg-path-menu_back{display:inline}.sidebar-closed #sidebar:hover #sidebar-inner{transform:translateX(0);transition-delay:0s}.sidebar-closed #sidebar:hover+#sidebar-bg{transition-delay:0s;visibility:visible;opacity:.9}}@media (max-width: 991.98px){.sidebar-closed #sidebar-bg{transition:opacity .25s,visibility 0s .25s;visibility:hidden;opacity:0}}.sidebar-closed .sidebar-clicked{pointer-events:none}.sidebar-closed .sidebar-clicked #sidebar-inner,.sidebar-closed .sidebar-clicked #sidebar-bg{transition-delay:0s}#sidebar-bg{width:100%;background:black;will-change:opacity;z-index:2}@media (max-width: 991.98px){#sidebar-bg{transition:opacity .25s,visibility 0s;visibility:visible;opacity:.9}}@media (min-width: 992px){#sidebar-bg{pointer-events:none;transition:opacity .25s,visibility 0s .25s;visibility:hidden;opacity:0}}#sidebar-inner{width:var(--sidebar-width-small);height:100%;transition:transform .25s cubic-bezier(0.4, 0.5, 0, 1)}@media (min-width: 992px){#sidebar-inner{transition:transform .25s cubic-bezier(0.4, 0.5, 0, 1),width .25s cubic-bezier(0.4, 0.5, 0, 1);width:calc(var(--sidebar-width) + 1px)}}#sidebar-menu{-webkit-overflow-scrolling:touch;overflow-y:auto}.transition-disabled{transition:none !important}.google-maps-link{transition:.2s}.exif-item{display:inline-block;white-space:nowrap;transition:.2s}.exif-item:not(:last-child):after{content:'|';margin:0 8px;opacity:.3}.exif-item small,.exif-item .small{opacity:.8;line-height:1}.exif-Model .svg-icon{margin:0 6px 0 -2px}.exif-ISOSpeedRatings small,.exif-ISOSpeedRatings .small{margin-right:1px}.exif-FocalLength small,.exif-FocalLength .small{margin-left:1px}.exif-ApertureFNumber::first-letter{font-style:italic}#menu-toggle .svg-path-plus,.menu-icon-toggle .svg-path-plus,#menu-toggle .svg-path-minus,.menu-icon-toggle .svg-path-minus{transition:transform 0.25s cubic-bezier(0.4, 0.5, 0, 1),opacity 0.25s cubic-bezier(0.4, 0.5, 0, 1);transform-origin:center}#menu-toggle .svg-path-minus,.menu-icon-toggle .svg-path-minus{opacity:0;transform:rotate(-90deg)}#menu-toggle.is-expanded .svg-path-minus,.is-open>.menu-a .svg-path-minus{opacity:1;transform:rotate(0deg)}#menu-toggle.is-expanded .svg-path-plus,.is-open>.menu-a .svg-path-plus{opacity:0;transform:rotate(90deg)}#sidebar-toggle{position:absolute;z-index:1;top:10px;border-radius:0 .15rem .15rem 0;background-color:#2e8b57;color:white}#sidebar-inner{display:flex;flex-direction:column}#sidebar-topbar{padding:10px 0 10px 48px;background-color:#1c2429;min-height:58px}#menu-toggle{background-color:#263238;color:#CFD8DC}#menu-toggle:hover{background-color:#2e8b57;color:white}#sidebar-menu{background:linear-gradient(90deg, #1c2429, #263238);flex:1;scrollbar-width:thin}@media (max-width: 991.98px){#sidebar-menu{overscroll-behavior-y:contain}}.sidebar-closed #sidebar-menu{overscroll-behavior-y:contain}.has-scrollbars #sidebar-menu{scrollbar-color:transparent transparent}.has-scrollbars #sidebar-menu::-webkit-scrollbar{-webkit-appearance:none;width:8px}.has-scrollbars #sidebar-menu::-webkit-scrollbar-thumb{border:1px solid #263238;border-radius:4px;background-color:transparent}.has-scrollbars #sidebar:hover #sidebar-menu{scrollbar-color:#607D8B transparent}.has-scrollbars #sidebar:hover #sidebar-menu::-webkit-scrollbar-thumb{background-color:#607D8B}.files-link{transition:all .2s;margin-top:auto;background-color:rgba(0,0,0,0.3);color:#CFD8DC;font-size:14px;padding:5px 0;text-align:center}.files-link:hover{text-decoration:none;color:#F8F9Fa;background-color:rgba(0,0,0,0.6)}.menu-root,.menu-ul{padding:0;margin:0;list-style:none}.menu-root{padding:12px 0 48px;font-size:14px;line-height:24px}.menu-ul{overflow:hidden;height:0px;opacity:0;display:none}.menu-active-ancestor:not(.is-open)>.menu-a:not(:hover){background-color:rgba(0,0,0,0.2);border-left-color:#607D8B}.menu-li.cm-active>.menu-a{transition:background-color .2s;background-color:rgba(0,0,0,0.5)}.menu-a{display:block;text-decoration:none;color:#CFD8DC;border-left:2px solid transparent;padding:2px 0}.menu-a:hover{color:#F8F9Fa;text-decoration:none}.menu-active{color:#F8F9Fa;background-color:rgba(0,0,0,0.3);transition:border-left-color .2s;border-left-color:#2e8b57 !important}.menu-active .menu-icon-folder{transition:color .2s;color:#2e8b57 !important}.menu-a-1{padding-left:6px}.menu-a-2{padding-left:35px}.menu-a-3{padding-left:64px}.menu-a-4{padding-left:93px}.menu-a-5{padding-left:122px}.menu-a-6{padding-left:151px}.menu-a-7{padding-left:180px}.menu-a-8{padding-left:209px}.menu-a-9{padding-left:238px}.menu-icon-folder{padding-right:6px;color:#78909C}.menu-icon-folder:before{content:'';opacity:0}.menu-icon-folder-toggle .svg-path-folder_min{display:none}.li-forbidden .menu-icon-folder{color:indianred !important}.li-forbidden .menu-a{cursor:not-allowed}.menu-icon-toggle{position:relative;float:right;color:#B0BEC5;background-color:rgba(0,0,0,0.2);border-radius:2px 0 0 2px;padding:2px;margin:-2px 0 -2px -2px}.is-open>.menu-a .svg-path-folder_min{display:inline}.is-open>.menu-a .svg-path-folder_plus{display:none}.is-open>.menu-ul{height:auto;opacity:1;display:block}@media screen and (hover: hover) and (pointer: fine){.menu-a:hover{background-color:rgba(0,0,0,0.3);border-left-color:#ECEFF1}.menu-a:hover .menu-icon-folder,.menu-a:hover .menu-icon-toggle{color:#CFD8DC}.menu-active:hover .menu-icon-toggle,.menu-icon-toggle:hover{transition:background-color .15s;background-color:#2e8b57;color:white !important}.menu-icon-folder-toggle:hover{transition:color .15s;color:#2e8b57 !important}#menu-toggle{transition-delay:.2s;opacity:0}#sidebar:hover #menu-toggle{transition-delay:0s;opacity:1}}.is-open{transition:background-color .3s}.is-open:hover{transition-delay:.2s;background-color:rgba(0,0,0,0.15)}@media screen and (pointer: coarse){.menu-root{font-size:16px}.menu-a{padding-top:4px;padding-bottom:4px}.menu-icon-toggle{padding:4px;margin:-4px 0 -4px -4px}.menu-icon-folder{padding-left:3px}}.menu-spinner:before{transition:.15s opacity;opacity:1;width:20px;height:20px;border-width:1px;border-color:#37474F;border-top-color:#2e8b57;position:absolute;margin:2px 0 0 2px}.menu-spinner .svg-icon{transition:.15s opacity;opacity:0}.sidebar-spinner:before{margin:10px 10px 0 7px;vertical-align:bottom;border-color:#37474F;border-top-color:#CFD8DC}.sidebar-spinner:after{content:attr(data-title);color:#CFD8DC;font-size:14px}.pswp__button{color:white;background:none;cursor:pointer;-webkit-appearance:none;border:0;padding:10px;margin:0;float:right;opacity:0.75;transition:opacity .2s, background-color .15s}.pswp__button:focus,.pswp__button:hover{opacity:1;outline:0;color:white}.pswp__button:active{outline:0;opacity:0.9}.pswp__button::-moz-focus-inner{padding:0;border:0}.pswp__ui--over-close .pswp__button--close{opacity:1}.svg-path-collapse{display:none}.is-fullscreen .svg-path-collapse{display:block}.is-fullscreen .svg-path-expand{display:none}.pswp__contextmenu.cm-active{opacity:1}.pswp__button--zoom{display:none}.pswp--zoom-allowed .pswp__button--zoom{display:block}.pswp__button--zoom .svg-path-zoom_out{display:none}.pswp--zoomed-in .pswp__button--zoom .svg-path-zoom_out{display:block}.pswp--zoomed-in .pswp__button--zoom .svg-path-zoom_in{display:none}.pswp__play .svg-path-play,.pswp__play .svg-path-pause{transform-origin:center;transition:opacity .2s, transform .2s;transition-timing-function:cubic-bezier(0.165, 0.84, 0.44, 1)}.pswp__play .svg-path-pause{opacity:0;transform:rotate(-90deg)}.pswp__play.is-playing .svg-path-play{opacity:0;transform:rotate(90deg)}.pswp__play.is-playing .svg-path-pause{opacity:1;transform:rotate(0deg)}.pswp__timer{height:1px;background-color:#CFD8DC;position:absolute;width:100%;bottom:0;transform-origin:left;transform:scaleX(0)}.pswp__button--arrow--left,.pswp__button--arrow--right{top:calc(50% - 50px);width:70px;height:100px;position:absolute;z-index:1}.pswp--touch .pswp__button--arrow--left,.pswp--touch .pswp__button--arrow--right{visibility:hidden}.pswp__button--arrow--left{left:0;text-align:left}.pswp__button--arrow--right{right:0;text-align:right}.pswp__counter,.pswp__search{font-weight:300;float:left;font-size:14px;line-height:24px;margin:10px 1rem 0 0}.pswp__search{display:none;max-width:30%}@media (min-width: 576px){.pswp__search{max-width:320px}}.pswp__search .svg-icon{margin-right:5px}.pswp__preloader{float:left;opacity:0;transition:opacity .3s;margin-top:11px}.pswp__preloader--active{opacity:1}.pswp__preloader--active:before{width:22px;height:22px;border-width:1px;border-color:rgba(255,255,255,0.2);border-top-color:currentColor}.pswp__caption{position:absolute;left:0;bottom:0;width:100%;background-color:rgba(0,0,0,0.6);text-align:center}.pswp__caption:hover{background-color:rgba(0,0,0,0.9)}.pswp__caption--empty{display:none}.pswp__caption--fake{visibility:hidden}.pswp__ui{-webkit-font-smoothing:auto;visibility:visible;opacity:1;z-index:1550}.pswp__top-bar{color:#ECEFF1;background:rgba(0,0,0,0.3);position:absolute;left:0;top:0;width:100%;padding:0 0 0 12px}@media (min-width: 768px){.pswp__top-bar{padding:4px 16px 4px 20px;background:linear-gradient(to right, rgba(0,0,0,0.4) 0%, rgba(0,0,0,0) 300px),linear-gradient(to left, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0) 300px)}}@media (hover: hover){.pswp__top-bar .pswp__button{border-radius:50%}.pswp__top-bar .pswp__button:hover{background-color:var(--strong-color)}}.pswp__caption,.pswp__top-bar,.pswp--has_mouse .pswp__button--arrow--left,.pswp--has_mouse .pswp__button--arrow--right{-webkit-backface-visibility:hidden;will-change:opacity}.pswp--has_mouse .pswp__button--arrow--left,.pswp--has_mouse .pswp__button--arrow--right{visibility:visible}.pswp__ui--idle .pswp__top-bar:not(:hover),.pswp__ui--idle .pswp__caption:not(:hover),.pswp__ui--idle .pswp__button--arrow--left:not(:hover),.pswp__ui--idle .pswp__button--arrow--right:not(:hover){opacity:0}.pswp__top-bar,.pswp__caption{transition:all 0.3s cubic-bezier(0.23, 1, 0.32, 1)}.pswp__ui--idle .pswp__top-bar:not(:hover){transform:translateY(-2px)}.pswp__ui--idle .pswp__caption:not(:hover){transform:translateY(2px)}.pswp__ui--hidden .pswp__top-bar,.pswp__ui--hidden .pswp__caption,.pswp__ui--hidden .pswp__button--arrow--left,.pswp__ui--hidden .pswp__button--arrow--right{opacity:0}.pswp__ui--one-slide .pswp__button--arrow--left,.pswp__ui--one-slide .pswp__button--arrow--right,.pswp__ui--one-slide .pswp__counter,.pswp__ui--one-slide .pswp__play{display:none}.pswp__element--disabled{display:none !important}.pswp__img{image-orientation:none}@supports (image-orientation: from-image){.server-exif .pswp__img{image-orientation:from-image}}.popup-title,.popup-description,.popup-keywords{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@supports (--css: -webkit-line-clamp){@media (min-height: 300px){.popup-title,.popup-description,.popup-keywords{white-space:normal;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}}@media (min-height: 500px){.popup-title,.popup-description,.popup-keywords{-webkit-line-clamp:3}}@media (min-height: 800px){.popup-title,.popup-description,.popup-keywords{-webkit-line-clamp:4}}@media (min-height: 1100px){.popup-title,.popup-description,.popup-keywords{-webkit-line-clamp:5}}}.pswp__caption__center{text-align:left;padding:12px 1rem;position:relative;font-size:14px;line-height:24px;color:#CFD8DC;font-weight:300}@media (min-width: 992px){.pswp__caption__center{max-width:700px;display:inline-block}}.pswp__caption__center .tooltip-top{transition:.2s;--transition-delay: .2s}.pswp__caption__center .tooltip-top:before{border-color:#CFD8DC transparent transparent transparent}.pswp__caption__center .tooltip-top:after{font-weight:600;background-image:linear-gradient(white, #CFD8DC);color:#263238}.pswp__caption__center .tooltip-top:hover{color:white}.popup-context{float:right;position:relative;z-index:1;padding:5px;margin:-8px;color:inherit;border:3px solid transparent}.popup-context:hover{color:#CFD8DC;background-color:#37474F}.popup-context:active{border-color:#2d3940}.popup-context.cm-active:active{border-color:#1c2429}.popup-basename{word-break:break-all;font-weight:400;font-size:1rem;color:#F8F9Fa;line-height:22px;margin:0 40px 4px 0}.popup-dimensions,.popup-filesize,.popup-date{display:inline-block}.popup-dimensions:after,.popup-filesize:after{content:'|';margin:0 10px;opacity:.3}.popup-date{white-space:nowrap}.popup-date .relative-time{color:#B0BEC5}.popup-date .relative-time:before{content:'~';margin:0 .5rem}@media (max-width: 575.98px){.popup-date .relative-time{display:none}}.popup-exif{background-color:rgba(0,0,0,0.5);margin:3px -1rem;padding:5px 1rem}@media (min-width: 992px){.popup-exif{margin:3px -10px;padding:5px 10px;border-radius:3px}}.popup-exif .google-maps-link{color:inherit}.popup-exif .google-maps-link:hover{color:#d85040}.popup-title,.popup-description,.popup-keywords{line-height:20px;margin:3px 0}.popup-title{font-weight:400;color:#F8F9Fa;margin-top:5px}.popup-keywords{font-style:italic;margin-top:5px;color:#B0BEC5}.popup-keywords:before{content:'—';margin-right:.5rem}.modal{-webkit-overflow-scrolling:touch}.modal-preview-code,.modal-preview-file,.modal-preview-dir{border-top:1px solid #ECEFF1;border-bottom:1px solid #ECEFF1}.modal-preview-image,.modal-preview-audio,.modal-preview-code,.modal-preview-file,.modal-preview-dir{background-repeat:repeat;background-color:white;background-image:linear-gradient(45deg, #eff1f3 25%, transparent 25%, transparent 75%, #eff1f3 75%, #eff1f3),linear-gradient(45deg, #eff1f3 25%, transparent 25%, transparent 75%, #eff1f3 75%, #eff1f3);background-size:20px 20px;background-position:0 0, 30px 30px}#modal-bg{position:fixed;top:0;left:0;z-index:1040;width:100%;height:100%;background-color:#000;opacity:0;display:none}.modal-title{word-break:break-all;color:#37474F;line-height:26px;margin-top:2px}.modal-buttons{white-space:nowrap;margin:-4px -4px -4px .5rem}.modal-preview{display:block;position:relative;margin:-1rem -1rem 0 -1rem;min-height:160px}.modal-preview:hover{text-decoration:none}.modal-preview-image{cursor:zoom-in}.modal-preview-audio{border-top:1px solid #ECEFF1}.modal-preview-audio .modal-file-icon{background-image:linear-gradient(0, white, rgba(255,255,255,0))}.modal-file-icon{height:160px;width:100%;padding:29px 0 30px}.modal-image{max-width:100%;image-orientation:from-image}.modal-image-intrinsic{position:absolute;width:100%;height:100%;object-fit:scale-down}.modal-image-ico{display:block;margin:0 auto;padding:10px 0}.modal-video,.modal-audio{width:100%;outline:none;display:block}.modal-video{min-height:200px;max-height:80vh;background:#111}.modal-audio{background-color:white}.CodeMirror{background-color:#F8F9Fa;height:auto;font-size:14px;font-family:Consolas, monospace}@supports (-webkit-overflow-scrolling: touch){.CodeMirror{font-size:16px}}.CodeMirror-scroll{min-height:160px;max-height:50vh;-webkit-overflow-scrolling:touch}.CodeMirror-vscrollbar{scrollbar-width:thin}.has-scrollbars .CodeMirror-vscrollbar{outline:none;scrollbar-color:#90A4AE transparent}.has-scrollbars .CodeMirror-vscrollbar::-webkit-scrollbar{-webkit-appearance:none;width:8px}.has-scrollbars .CodeMirror-vscrollbar::-webkit-scrollbar-thumb{border:1px solid #F8F9Fa;border-radius:4px;background-color:#90A4AE}.has-scrollbars .CodeMirror-vscrollbar::-webkit-scrollbar-thumb:hover{background-color:var(--strong-color)}.CodeMirror-linenumber{color:#78909C}.CodeMirror-gutters{background-color:#ECEFF1;border-right-color:transparent}.modal-code-buttons{z-index:3;display:inline-block}.modal-content-code .svg-path-expand{display:inline}.modal-content-code .svg-path-collapse{display:none}.modal-preview-spinner{width:150px;height:150px;position:absolute;left:calc(50% - 75px);top:calc(50% - 75px);border-width:1px;border-bottom-color:#ECEFF1;border-left-color:#CFD8DC;border-top-color:#B0BEC5}.modal-code-fullscreen{overflow:hidden !important}.modal-code-fullscreen .modal-content{transform:none !important}.modal-code-fullscreen .modal-header,.modal-code-fullscreen .CodeMirror{position:fixed;left:0;right:0}.modal-code-fullscreen .modal-header{z-index:2;top:0;background-color:white;border-bottom:1px solid #ECEFF1;border-radius:0;height:63px}.modal-code-fullscreen .CodeMirror{top:63px;bottom:0;z-index:1}.modal-code-fullscreen .CodeMirror-scroll{max-height:none}.modal-code-fullscreen .svg-path-expand{display:none}.modal-code-fullscreen .svg-path-collapse{display:inline}.modal-info{margin:1rem 0 .5rem;color:#607D8B}.modal-info-context{float:right;padding:5px;margin:-8px;color:#78909C;border:3px solid transparent}.modal-info-context:hover{color:#455A64;background-color:#ECEFF1}.modal-info-context:active{border-color:#dde3e6}.modal-info-context.cm-active:active{border-color:#1c2429}.modal-info-name{color:#37474F;word-break:break-all;font-weight:500;line-height:23px;padding:1px 0}.modal-open-link,.modal-download-link{color:#CFD8DC;float:right;margin-left:3px;transition:.15s}.modal-open-link:hover,.modal-download-link:hover{color:#37474F}.modal-info-meta{margin:5px 0}.modal-info-mime,.modal-info-dimensions,.modal-info-filesize{margin-right:10px}.modal-info-mime:after,.modal-info-dimensions:after,.modal-info-filesize:after{color:#CFD8DC;content:'|';margin-left:10px}.modal-info-dimensions,.modal-info-filesize,.modal-info-permissions{display:inline-block;white-space:nowrap}.modal-info-mime{max-width:100%;float:left}@media (max-width: 575.98px){.modal-info-mime{float:none;margin:0 3px 3px 0}.modal-info-mime:after{content:none}}.modal-info-mime .svg-icon{margin:0 6px 0 -2px}.modal-info-filesize{margin-right:12px}.modal-info-permissions{font-weight:500}.modal-info-permissions .svg-icon{margin:0 3px 0 -2px}.is-readwrite{color:yellowgreen}.not-readwrite{color:#dc3545}.modal-info-date{margin:.5rem -1rem;background-color:#F8F9Fa;padding:.5rem 1rem;border-top:1px solid #ECEFF1;border-bottom:1px solid #ECEFF1}.modal-info-date .svg-icon{margin:0 6px 0 -2px;color:#90A4AE}.modal-info-date .relative-time{white-space:nowrap;color:#78909C;font-style:italic}.modal-info-date .relative-time:before{content:'—';margin:0 10px;color:#B0BEC5}.modal-info-exif{--transition-delay: .2s;margin:5px 0}.modal-info-exif .svg-icon-camera,.modal-info-exif .svg-icon-cellphone{color:#90A4AE}.modal-info-iptc{margin-top:1rem;line-height:1.4}.modal-info-title{font-weight:500;color:#455A64}.modal-info-title+.modal-info-description{margin-top:3px}.modal-info-description{color:#546E7A}.modal-info-keywords{color:#607D8B;font-style:italic;border-top:1px dashed #CFD8DC;margin-top:.5rem;padding-top:.5rem}:root{--touch-callout: default}img,video,.files-li,.menu-li{-webkit-touch-callout:var(--touch-callout)}.svg-icon{width:1em;height:1em;font-size:24px;vertical-align:bottom;pointer-events:none}body{--transition-delay: .5s;--transition-delay-opacity: .2s;--transition-delay-visibility: .4s}[data-tooltip]{position:relative}[data-tooltip]:hover{text-decoration:none}[data-tooltip] *{pointer-events:none}[data-tooltip]:before,[data-tooltip]:after{transform:translate(-50%, -10px);visibility:hidden;position:absolute;z-index:9999;left:50%;opacity:0;pointer-events:none;transition:opacity 0.2s var(--transition-delay-opacity),visibility 0s var(--transition-delay-visibility)}[data-tooltip]:before{content:'';border:solid 5px}[data-tooltip]:after{content:attr(data-tooltip);font-size:14px;font-weight:500;background-color:rgba(0,0,0,0.9);border-radius:.15rem;color:#ECEFF1;padding:.5em 1em;white-space:nowrap;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}[data-tooltip]:not(.cm-active):hover:before,[data-tooltip]:not(.cm-active):hover:after,[data-tooltip].show-tooltip:before,[data-tooltip].show-tooltip:after{transition:opacity .2s;visibility:visible;opacity:1;transition-delay:var(--transition-delay);transition-timing-function:cubic-bezier(0.215, 0.61, 0.355, 1)}[data-tooltip]:active:before,[data-tooltip]:active:after{transition-delay:0s}.tooltip-top:before,.tooltip-top:after{transform:translate(-50%, -10px)}.tooltip-top:before{top:0;border-color:rgba(0,0,0,0.9) transparent transparent transparent}.tooltip-top:after{bottom:100%}.tooltip-top.tooltip-left:after{transform:translate(calc(10px - 100%), -10px)}.tooltip-top.tooltip-right:after{transform:translate(-10px, -10px)}.tooltip-bottom:before,.tooltip-bottom:after{transform:translate(-50%, 10px)}.tooltip-bottom:before{bottom:0;border-color:transparent transparent rgba(0,0,0,0.9) transparent}.tooltip-bottom:after{top:100%}.tooltip-bottom.tooltip-left:after{transform:translate(calc(10px - 100%), 10px)}.tooltip-bottom.tooltip-right:after{transform:translate(-10px, 10px)} 2 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | '', // root path relative to script. 19 | 'start_path' => false, // start path relative to script. If empty, root is start path 20 | 21 | // login 22 | 'username' => '', 23 | 'password' => '', // Add password directly or use https://tinyfilemanager.github.io/docs/pwd.html to encrypt the password (encrypted password is more secure, as it prevents your password from being exposed directly in a file). 24 | 25 | // images 26 | 'load_images' => true, 27 | 'load_files_proxy_php' => false, 28 | 'load_images_max_filesize' => 1000000, // maximum file size (bytes) for un-resized images loaded into list 29 | 'load_svg_max_filesize' => 100000, // 100k 30 | 'image_resize_enabled' => true, 31 | 'image_resize_cache' => true, // todo: remove this option and just use 'cache? 32 | 'image_resize_dimensions' => 320, 33 | 'image_resize_dimensions_retina' => 480, 34 | 'image_resize_quality' => 85, 35 | 'image_resize_function' => 'imagecopyresampled', // imagecopyresampled / imagecopyresized 36 | 'image_resize_sharpen' => true, 37 | 'image_resize_memory_limit' => 128, // 128 MB is suffient to resize images around 6000 px / 0 = ignore memory 38 | 'image_resize_max_pixels' => 30000000, // 30 MP equivalent to an image 6000 x 5000 / 0 = no limit 39 | 'image_resize_min_ratio' => 1.5, // min size diff original vs resize. Only resizes if ratio > min ratio 40 | 'image_resize_cache_direct' => false, // if enabled and delete cache, must increase cache_key 41 | 42 | // menu 43 | 'menu_enabled' => true, 44 | 'menu_show' => true, 45 | 'menu_max_depth' => 5, 46 | 'menu_sort' => 'name_asc', // name_asc, name_desc, date_asc, date_desc 47 | 'menu_cache_validate' => true, 48 | 'menu_load_all' => false, 49 | 'menu_recursive_symlinks' => true, // List sub-directories of symlinks in the main menu. May cause menu loops and/or duplicate menu items 50 | 51 | // files layout 52 | 'layout' => 'rows', // list, blocks, grid, rows, columns 53 | 'image_cover' => true, // scales image inside container for list, block, grid and rows layouts. 54 | 'sort' => 'name_asc', // name, date, filesize, kind 55 | 'sort_dirs_first' => true, 56 | 57 | // cache 58 | 'cache' => true, 59 | 'cache_key' => 0, 60 | 'storage_path' => '_files', 61 | 62 | // exclude files directories regex 63 | 'files_exclude' => '', // '/\.(pdf|jpe?g)$/i' 64 | 'dirs_exclude' => '', //'/\/Convert|\/football|\/node_modules(\/|$)/i', 65 | 'allow_symlinks' => true, // allow symlinks 66 | 67 | // various 68 | 'history' => true, 69 | 'breadcrumbs' => true, 70 | 'transitions' => true, 71 | 'click' => 'popup', // popup, modal, download, window, menu 72 | 'code_max_load' => 100000, 73 | 'code_allow_edit' => false, 74 | 'popup_interval' => 5000, 75 | 'topbar_sticky' => 'scroll', // true, false, 'scroll' 76 | 'check_updates' => true, 77 | 'allow_tasks' => true, 78 | 'get_mime_type' => false, // get file mime type from server (slow) instead of from extension (fast) 79 | 'context_menu' => true, // disable context-menu button and right-click menu 80 | 'prevent_right_click' => false, // blocks browser right-click menu on sensitive items (images, list items, menu) 81 | 'license_key' => '' 82 | ); 83 | 84 | // config (will popuplate) 85 | public static $config = array(); 86 | 87 | // app vars 88 | static $__dir__ = __DIR__; 89 | static $__file__ = __FILE__; 90 | static $assets; 91 | static $prod = true; 92 | static $version = '0.2.2'; 93 | static $root; 94 | static $doc_root; 95 | static $has_login = false; 96 | static $storage_path; 97 | static $storage_is_within_doc_root = false; 98 | static $storage_config_realpath; 99 | static $storage_config; 100 | static $cache_path; 101 | static $image_resize_cache_direct; 102 | static $image_resize_dimensions_retina = false; 103 | static $dirs_hash = false; 104 | static $local_config_file = '_filesconfig.php'; 105 | 106 | // get config 107 | private function get_config($path) { 108 | if(empty($path) || !file_exists($path)) return array(); 109 | $config = include $path; 110 | return empty($config) || !is_array($config) ? array() : array_map(function($v){ 111 | return is_string($v) ? trim($v) : $v; 112 | }, $config); 113 | } 114 | 115 | // dump config 116 | private function dump_config($local_config, $storage_path, $storage_config, $user_config, $user_valid){ 117 | 118 | // invalid and duplicate arrays 119 | $user_invalid = array_diff_key($user_config, self::$default); 120 | $user_duplicate = array_intersect_assoc($user_valid, self::$default); 121 | 122 | // items 123 | $items = array( 124 | ['arr' => $local_config, 'comment' => "// LOCAL CONFIG\n// " . self::$local_config_file], 125 | ['arr' => $storage_config, 'comment' => "// STORAGE CONFIG\n// " . rtrim($storage_path ?: '', '\/') . '/config/config.php'], 126 | ['arr' => $user_invalid, 'comment' => "// INVALID PARAMS\n// The following custom parameters will be ignored as they are not valid:", 'var' => '$invalid', 'hide' => empty($user_invalid)], 127 | ['arr' => $user_duplicate, 'comment' => "// DUPLICATE DEFAULT PARAMS\n// The following custom parameters will have no effect as they are identical to defaults:", 'var' => '$duplicate', 'hide' => empty($user_duplicate)], 128 | ['arr' => $user_valid, 'comment' => "// USER CONFIG\n// User config parameters.", 'var' => '$user', 'hide' => (empty($local_config) || empty($storage_config)) && empty($user_invalid)], 129 | ['arr' => self::$config, 'comment' => "// CONFIG\n// User parameters merged with default parameters.", 'var' => '$config'], 130 | ['arr' => self::$default, 'comment' => "// DEFAULT CONFIG\n// Default config parameters.", 'var' => '$default'], 131 | ['arr' => array_diff_key(get_class_vars('config'), array_flip(['default', 'config'])), 'comment' => "// STATIC VARS\n// Static app vars.", 'var' => '$static'] 132 | ); 133 | 134 | // loop 135 | $output = ' $props) { 137 | $is_empty = empty($props['arr']); 138 | if(isset($props['hide']) && $props['hide']) continue; 139 | foreach (['username', 'password', 'allow_tasks', '__dir__', '__file__'] as $prop) if(isset($props['arr'][$prop]) && !empty($props['arr'][$prop]) && is_string($props['arr'][$prop])) $props['arr'][$prop] = '***'; 140 | $export = $is_empty ? 'array ()' : var_export($props['arr'], true); 141 | $comment = preg_replace('/\n/', " [" . count($props['arr']) . "]\n", $props['comment'], 1); 142 | $var = isset($props['var']) ? $props['var'] . ' = ' : 'return '; 143 | $output .= PHP_EOL . $comment . PHP_EOL . $var . $export . ';' . PHP_EOL; 144 | } 145 | highlight_string($output . PHP_EOL . ';?>'); 146 | exit; 147 | } 148 | 149 | 150 | 151 | 152 | //public static function helloWorld() { 153 | public static function save_config($config = array()){ 154 | $save_config = array_intersect_key(array_replace(self::$storage_config, $config), self::$default); 155 | $export = preg_replace("/ '/", " //'", var_export(array_replace(self::$default, $save_config), true)); 156 | foreach ($save_config as $key => $value) if($value !== self::$default[$key]) $export = str_replace("//'" . $key, "'" . $key, $export); 157 | return @file_put_contents(config::$storage_config_realpath, 'storage_path must be a unique dir.'); 176 | self::$storage_config_realpath = $storage_realpath ? $storage_realpath . '/config/config.php' : false; 177 | self::$storage_config = self::get_config(self::$storage_config_realpath); 178 | 179 | // config 180 | $user_config = array_replace(self::$storage_config, $local_config); 181 | $user_valid = array_intersect_key($user_config, self::$default); 182 | self::$config = array_replace(self::$default, $user_valid); 183 | 184 | // dump config and exit; 185 | if(isset($_GET['config'])) self::dump_config($local_config, $storage_path, self::$storage_config, $user_config, $user_valid); 186 | 187 | // CDN assets 188 | self::$assets = self::$prod ? 'https://cdn.jsdelivr.net/npm/files.photo.gallery@' . self::$version . '/' : ''; 189 | 190 | // root 191 | self::$root = real_path(self::$config['root']); 192 | if($is_doc && !self::$root) error('root dir "' . self::$config['root'] . '" does not exist.'); 193 | 194 | // doc root 195 | self::$doc_root = real_path($_SERVER['DOCUMENT_ROOT']); 196 | 197 | // login 198 | self::$has_login = self::$config['username'] || self::$config['password'] ? true : false; 199 | 200 | // $image_cache 201 | $image_cache = self::$config['image_resize_enabled'] && self::$config['image_resize_cache'] && self::$config['load_images'] ? true : false; 202 | 203 | // cache enabled 204 | if($image_cache || self::$config['cache']){ 205 | 206 | // create storage_path 207 | if(empty($storage_realpath)){ 208 | $storage_path = is_string($storage_path) ? rtrim($storage_path, '\/') : false; 209 | if(empty($storage_path)) error('Invalid storage_path parameter.'); 210 | mkdir_or_error($storage_path); 211 | $storage_realpath = real_path($storage_path); 212 | if(empty($storage_realpath)) error("storage_path $storage_path does not exist and can't be created."); 213 | } 214 | self::$storage_path = $storage_realpath; 215 | 216 | // storage path is within doc root 217 | if(is_within_docroot(self::$storage_path)) self::$storage_is_within_doc_root = true; 218 | 219 | // cache_path real path 220 | self::$cache_path = self::$storage_path . '/cache'; 221 | 222 | // create storage dirs 223 | if($is_doc){ 224 | $create_dirs = [$storage_realpath . '/config']; 225 | if($image_cache) $create_dirs[] = self::$cache_path . '/images'; 226 | if(self::$config['cache']) array_push($create_dirs, self::$cache_path . '/folders', self::$cache_path . '/menu'); 227 | foreach($create_dirs as $create_dir) mkdir_or_error($create_dir); 228 | } 229 | 230 | // create/update config file, with default parameters commented out. 231 | if($is_doc && self::$storage_config_realpath && (!file_exists(self::$storage_config_realpath) || filemtime(self::$storage_config_realpath) < filemtime(__FILE__))) self::save_config(); 232 | 233 | // image resize cache direct 234 | if(self::$config['image_resize_cache_direct'] && !self::$has_login && self::$config['load_images'] && self::$config['image_resize_cache'] && self::$config['image_resize_enabled'] && self::$storage_is_within_doc_root) self::$image_resize_cache_direct = true; 235 | } 236 | 237 | // image_resize_dimensions_retina 238 | if(self::$config['image_resize_dimensions_retina'] && self::$config['image_resize_dimensions_retina'] > self::$config['image_resize_dimensions']) self::$image_resize_dimensions_retina = self::$config['image_resize_dimensions_retina']; 239 | 240 | // dirs hash 241 | self::$dirs_hash = substr(md5(self::$doc_root . self::$__dir__ . self::$root . self::$version . self::$config['cache_key'] . self::$image_resize_cache_direct . self::$config['files_exclude'] . self::$config['dirs_exclude']), 0, 6); 242 | 243 | // login 244 | // $is_doc 245 | if(self::$has_login) check_login($is_doc); 246 | } 247 | }; 248 | 249 | // login page 250 | function login_page($is_login_attempt, $sidx, $is_logout, $client_hash){ 251 | ?> 252 | 253 | 254 | 255 | 256 | 257 | 258 | Login 259 | 260 | 261 | 262 |
263 | 285 | 286 | = 5.5 && !password_needs_rehash(config::$config['password'], PASSWORD_DEFAULT) ? password_verify(trim($_POST['fpassword']), config::$config['password']) : (trim($_POST['fpassword']) == config::$config['password'])) && 323 | $_POST['client_hash'] === $client_hash && 324 | $_POST['sidx'] === $sidx 325 | ){ 326 | $_SESSION['login'] = $login_hash; 327 | 328 | // display login page and exit 329 | } else { 330 | login_page($is_login_attempt, $sidx, $is_logout, $client_hash); 331 | } 332 | 333 | // not logged in (images or post API requests), don't show form. 334 | } else if(post('action')){ 335 | json_error('login'); 336 | 337 | } else { 338 | error('You are not logged in.', 401); 339 | } 340 | } 341 | } 342 | 343 | // 344 | function mkdir_or_error($path){ 345 | if(!file_exists($path) && !mkdir($path, 0777, true)) error('Failed to create ' . $path, 500); 346 | } 347 | function real_path($path){ 348 | $real_path = realpath($path); 349 | return $real_path ? str_replace('\\', '/', $real_path) : false; 350 | } 351 | function root_relative($dir){ 352 | return ltrim(substr($dir, strlen(config::$root)), '\/'); 353 | } 354 | function root_absolute($dir){ 355 | return config::$root . ($dir ? '/' . $dir : ''); 356 | } 357 | function is_within_path($path, $root){ 358 | return strpos($path . '/', $root . '/') === 0; 359 | } 360 | function is_within_root($path){ 361 | return is_within_path($path, config::$root); 362 | } 363 | function is_within_docroot($path){ 364 | return is_within_path($path, config::$doc_root); 365 | } 366 | function get_folders_cache_path($name){ 367 | return config::$cache_path . '/folders/' . $name . '.json'; 368 | } 369 | function get_json_cache_url($name){ 370 | $file = get_folders_cache_path($name); 371 | return file_exists($file) ? get_url_path($file) : false; 372 | } 373 | function get_dir_cache_path($dir, $mtime = false){ 374 | if(!config::$config['cache'] || !$dir) return; 375 | return get_folders_cache_path(get_dir_cache_hash($dir, $mtime)); 376 | } 377 | function get_dir_cache_hash($dir, $mtime = false){ 378 | return config::$dirs_hash . '.' . substr(md5($dir), 0, 6) . '.' . ($mtime ?: filemtime($dir)); 379 | } 380 | function header_memory_time(){ 381 | return (isset($_SERVER['REQUEST_TIME_FLOAT']) ? round(microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'], 3) . 's, ' : '') . round(memory_get_peak_usage() / 1048576, 1) . 'M'; 382 | } 383 | 384 | // read file 385 | // todo: add files-date header 386 | function read_file($path, $mime = 'image/jpeg', $msg = false, $props = false, $cache_headers = false){ 387 | if(!$path || !file_exists($path)) return false; 388 | if($mime == 'image/svg') $mime .= '+xml'; 389 | header('content-type: ' . $mime); 390 | header('content-length: ' . filesize($path)); 391 | header('content-disposition: filename="' . basename($path) . '"'); 392 | if($msg) header('files-msg: ' . $msg . ' [' . ($props ? $props . ', ' : '') . header_memory_time() . ']'); 393 | if($cache_headers) set_cache_headers(); 394 | if(!is_readable($path) || !readfile($path)) error('Failed to read file ' . $path . '.', 400); 395 | exit; 396 | } 397 | 398 | // get mime 399 | function get_mime($path){ 400 | if(function_exists('mime_content_type')){ 401 | return mime_content_type($path); 402 | } else { 403 | return function_exists('finfo_file') ? finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path) : false; 404 | } 405 | } 406 | 407 | // set cache headers 408 | function set_cache_headers(){ 409 | $seconds = 31536000; // 1 year; 410 | header('expires: ' . gmdate('D, d M Y H:i:s', time() + $seconds) . ' GMT'); 411 | header("cache-control: public, max-age=$seconds, s-maxage=$seconds, immutable"); 412 | header('pragma: cache'); 413 | // header("Last-Modified:" . gmdate('D, d M Y H:i:s', time() - $seconds) . ' GMT'); 414 | // etag? 415 | } 416 | 417 | // get image cache path 418 | function get_image_cache_path($path, $image_resize_dimensions, $filesize, $filemtime){ 419 | return config::$cache_path . '/images/' . substr(md5($path), 0, 6) . '.' . $filesize . '.' . $filemtime . '.' . $image_resize_dimensions . '.jpg'; 420 | } 421 | 422 | // is excluded 423 | function is_exclude($path = false, $is_dir = true, $symlinked = false){ 424 | 425 | // early exit 426 | if(!$path || $path === config::$root) return; 427 | 428 | // exclude files PHP application 429 | if($path === config::$__file__) return true; 430 | 431 | // symlinks not allowed 432 | if($symlinked && !config::$config['allow_symlinks']) return true; 433 | 434 | // exclude storage path 435 | if(config::$storage_path && is_within_path($path, config::$storage_path)) return true; 436 | 437 | // dirs_exclude: check root relative dir path 438 | if(config::$config['dirs_exclude']) { 439 | $dirname = $is_dir ? $path : dirname($path); 440 | if($dirname !== config::$root && preg_match(config::$config['dirs_exclude'], substr($dirname, strlen(config::$root)))) return true; 441 | } 442 | 443 | // files_exclude: check vs basename 444 | if(!$is_dir){ 445 | $basename = basename($path); 446 | if($basename === config::$local_config_file) return true; 447 | if(config::$config['files_exclude'] && preg_match(config::$config['files_exclude'], $basename)) return true; 448 | } 449 | } 450 | 451 | // valid root path 452 | function valid_root_path($path, $is_dir = false){ 453 | 454 | // invalid 455 | if($path === false) return; 456 | if(!$is_dir && empty($path)) return; // path cannot be empty if file 457 | if($path && substr($path, -1) == '/') return; // path should never be root absolute or end with / 458 | 459 | // absolute path may differ if path contains symlink 460 | $root_absolute = root_absolute($path); 461 | $real_path = real_path($root_absolute); 462 | 463 | // file does not exist 464 | if(!$real_path) return; 465 | 466 | // security checks if path contains symlink 467 | if($root_absolute !== $real_path) { 468 | if(strpos(($is_dir ? $path : dirname($path)), ':') !== false) return; // dir may not contain ':' 469 | if(strpos($path, '..') !== false) return; // path may not contain '..' 470 | if(is_exclude($root_absolute, $is_dir, true)) return; 471 | } 472 | 473 | // nope 474 | if(!is_readable($real_path)) return; // not readable 475 | if($is_dir && !is_dir($real_path)) return; // dir check 476 | if(!$is_dir && !is_file($real_path)) return; // file check 477 | if(is_exclude($real_path, $is_dir)) return; // exclude path 478 | 479 | // return root_absolute 480 | return $root_absolute; 481 | } 482 | 483 | // image create from 484 | function image_create_from($path, $type){ 485 | if(!$path || !$type) return; 486 | if($type === IMAGETYPE_JPEG){ 487 | return imagecreatefromjpeg($path); 488 | } else if ($type === IMAGETYPE_PNG) { 489 | return imagecreatefrompng($path); 490 | } else if ($type === IMAGETYPE_GIF) { 491 | return imagecreatefromgif($path); 492 | } else if ($type === 18/*IMAGETYPE_WEBP*/) { 493 | if(version_compare(PHP_VERSION, '5.4.0') >= 0) return imagecreatefromwebp($path); 494 | } else if ($type === IMAGETYPE_BMP) { 495 | if(version_compare(PHP_VERSION, '7.2.0') >= 0) return imagecreatefrombmp($path); 496 | } 497 | } 498 | 499 | // get file (proxy or resize image) 500 | function get_file($path, $resize = false){ 501 | 502 | // validate 503 | if(!$path) error('Invalid file request.', 404); 504 | $path = real_path($path); // in case of symlink path 505 | 506 | // mime 507 | $mime = get_mime($path); 508 | if(!$mime) error('Empty mime type.', 415); 509 | $mime_array = explode('/', $mime); 510 | 511 | // resize 512 | if($resize){ 513 | if($mime_array[0] !== 'image') error('' . basename($path) . ' (' . $mime . ') is not an image.', 415); 514 | if(!config::$config['load_images']) error('Load images disabled.', 400); 515 | if(!config::$config['image_resize_enabled']) error('Resize images disabled.', 400); 516 | $resize_dimensions = intval($resize); 517 | if(!$resize_dimensions) error("Invalid resize parameter $resize.", 400); 518 | if(!in_array($resize_dimensions, [config::$config['image_resize_dimensions'], config::$image_resize_dimensions_retina])) error("Resize parameter $resize_dimensions is not allowed.", 400); 519 | resize_image($path, $resize_dimensions); 520 | 521 | // proxy file 522 | } else { 523 | 524 | // disable if !proxy and path is within document root (file should never be proxied) 525 | if(!config::$config['load_files_proxy_php'] && is_within_docroot($path)) error('File cannot be proxied.', 400); 526 | 527 | // read file 528 | read_file($path, $mime, $msg = 'File ' . basename($path) . ' proxied.', false, true); 529 | } 530 | } 531 | 532 | // sharpen resized image 533 | function sharpen_image($image){ 534 | $matrix = array( 535 | array(-1, -1, -1), 536 | array(-1, 20, -1), 537 | array(-1, -1, -1), 538 | ); 539 | $divisor = array_sum(array_map('array_sum', $matrix)); 540 | $offset = 0; 541 | imageconvolution($image, $matrix, $divisor, $offset); 542 | } 543 | 544 | // exif orientation 545 | // https://github.com/gumlet/php-image-resize/blob/master/lib/ImageResize.php 546 | function exif_orientation($orientation, &$image){ 547 | if(empty($orientation) || !is_numeric($orientation) || $orientation < 3 || $orientation > 8) return; 548 | $image = imagerotate($image, array(6 => 270, 5 => 270, 3 => 180, 4 => 180, 8 => 90, 7 => 90)[$orientation], null); 549 | if(in_array($orientation, array(5, 4, 7)) && function_exists('imageflip')) imageflip($image, IMG_FLIP_HORIZONTAL); 550 | return true; 551 | } 552 | 553 | // resize image 554 | function resize_image($path, $resize_dimensions){ 555 | 556 | // file size 557 | $file_size = filesize($path); 558 | 559 | // header props 560 | $header_props = 'w:' . $resize_dimensions . ', q:' . config::$config['image_resize_quality'] . ', ' . config::$config['image_resize_function'] . ', cache:' . (config::$config['image_resize_cache'] ? '1' : '0'); 561 | 562 | // cache 563 | $cache = config::$config['image_resize_cache'] ? get_image_cache_path($path, $resize_dimensions, $file_size, filemtime($path)) : NULL; 564 | if($cache) read_file($cache, null, 'Resized image served from cache', $header_props, true); 565 | 566 | // imagesize 567 | $info = getimagesize($path); 568 | if(empty($info) || !is_array($info)) error('Invalid image / failed getimagesize().', 500); 569 | $resize_ratio = max($info[0], $info[1]) / $resize_dimensions; 570 | 571 | // image_resize_max_pixels early exit 572 | if(config::$config['image_resize_max_pixels'] && $info[0] * $info[1] > config::$config['image_resize_max_pixels']) error('Image resolution ' . $info[0] . ' x ' . $info[1] . ' (' . ($info[0] * $info[1]) . ' px) exceeds image_resize_max_pixels (' . config::$config['image_resize_max_pixels'] . ' px).', 400); 573 | 574 | // header props 575 | $header_props .= ', ' . $info['mime'] . ', ' . $info[0] . 'x' . $info[1] . ', ratio:' . round($resize_ratio, 2); 576 | 577 | // output original if resize ratio < image_resize_min_ratio 578 | if($resize_ratio < max(config::$config['image_resize_min_ratio'], 1) && !read_file($path, $info['mime'], 'Original image served', $header_props, true)) error('File does not exist.', 404); 579 | 580 | // Calculate new image dimensions. 581 | $resize_width = round($info[0] / $resize_ratio); 582 | $resize_height = round($info[1] / $resize_ratio); 583 | 584 | // memory 585 | $memory_limit = config::$config['image_resize_memory_limit'] && function_exists('ini_get') ? (int) @ini_get('memory_limit') : false; 586 | if($memory_limit && $memory_limit > -1){ 587 | // $memory_required = ceil(($info[0] * $info[1] * 4 + $resize_width * $resize_height * 4) / 1048576); 588 | $memory_required = round(($info[0] * $info[1] * (isset($info['bits']) ? $info['bits'] / 8 : 1) * (isset($info['channels']) ? $info['channels'] : 3) * 1.33 + $resize_width * $resize_height * 4) / 1048576, 1); 589 | $new_memory_limit = function_exists('ini_set') ? max($memory_limit, config::$config['image_resize_memory_limit']) : $memory_limit; 590 | if($memory_required > $new_memory_limit) error('Resizing this image requires at least ' . $memory_required . 'M. Your current PHP memory_limit is ' . $new_memory_limit .'M.', 400); 591 | if($memory_limit < $new_memory_limit && @ini_set('memory_limit', $new_memory_limit . 'M')) $header_props .= ', ' . $memory_limit . 'M => ' . $new_memory_limit . 'M (min ' . $memory_required . 'M)'; 592 | } 593 | 594 | // new dimensions headers 595 | $header_props .= ', ' . $resize_width . 'x' . $resize_height; 596 | 597 | // create new $image 598 | $image = image_create_from($path, $info[2]); 599 | if(!$image) error('Failed to create image resource.', 500); 600 | 601 | // Create final image with new dimensions. 602 | $new_image = imagecreatetruecolor($resize_width, $resize_height); 603 | if(!call_user_func(config::$config['image_resize_function'], $new_image, $image, 0, 0, 0, 0, $resize_width, $resize_height, $info[0], $info[1])) error('Failed to resize image.', 500); 604 | 605 | // destroy original $image resource 606 | imagedestroy($image); 607 | 608 | // exif orientation 609 | $exif = function_exists('exif_read_data') ? @exif_read_data($path) : false; 610 | if(!empty($exif) && is_array($exif) && isset($exif['Orientation']) && exif_orientation($exif['Orientation'], $new_image)) $header_props .= ', orientated from EXIF:' . $exif['Orientation']; 611 | 612 | // sharpen resized image 613 | if(config::$config['image_resize_sharpen']) sharpen_image($new_image); 614 | 615 | // save to cache 616 | if($cache){ 617 | if(!imagejpeg($new_image, $cache, config::$config['image_resize_quality'])) error('imagejpeg() failed to create and cache resized image.', 500); 618 | /* // store cache records in /images.json_decode(json)n 619 | $image_cache_path = config::$cache_path . '/images'; 620 | $image_cache_json = $image_cache_path . '/images.json'; 621 | $image_cache_arr = file_exists($image_cache_json) ? json_decode(file_get_contents($image_cache_json), true) : array(); 622 | $image_cache_arr[basename($cache)] = is_within_docroot($path) ? ltrim(substr($path, strlen(config::$doc_root)), '\/') : $path; 623 | file_put_contents($image_cache_json, json_encode($image_cache_arr, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES));*/ 624 | 625 | // not cache / direct output 626 | } else { 627 | set_cache_headers(); 628 | header('content-type: image/jpeg'); 629 | header('files-msg: Resized image served [' . $header_props . ', ' . header_memory_time() . ']'); 630 | if(!imagejpeg($new_image, null, config::$config['image_resize_quality'])) error('imagejpeg() failed to create and output resized image.', 500); 631 | } 632 | 633 | // destroy image 634 | imagedestroy($new_image); 635 | 636 | // cache readfile 637 | if($cache && !read_file($cache, null, 'Resized image cached and served', $header_props, true)) error('Cache file does not exist.', 404); 638 | 639 | // 640 | exit; 641 | // https://github.com/maxim/smart_resize_image/blob/master/smart_resize_image.function.php 642 | // https://github.com/gavmck/resize/blob/master/php/lib/resize-class.php 643 | // https://github.com/gumlet/php-image-resize/blob/master/lib/ImageResize.php 644 | // https://www.bitrepository.com/resize-an-image-keeping-its-aspect-ratio-using-php-and-gd.html 645 | } 646 | 647 | function get_url_path($dir){ 648 | if(!is_within_docroot($dir)) return false; 649 | 650 | // if in __dir__ path, __dir__ relative 651 | if(is_within_path($dir, config::$__dir__)) return $dir === config::$__dir__ ? '.' : substr($dir, strlen(config::$__dir__) + 1); 652 | 653 | // doc root, doc root relative 654 | return $dir === config::$doc_root ? '/' : substr($dir, strlen(config::$doc_root)); 655 | } 656 | 657 | // get dir 658 | function get_dir($path, $files = false, $json_url = false){ 659 | 660 | // realpath 661 | $realpath = $path ? real_path($path) : false; 662 | if(!$realpath) return; // no real path for any reason 663 | $symlinked = $realpath !== $path; // path is symlinked at some point 664 | 665 | // exclude 666 | if(is_exclude($path, true, $symlinked)) return; // exclude 667 | if($symlinked && is_exclude($realpath, true, $symlinked)) return; // exclude check again symlink realpath 668 | 669 | // vars 670 | $filemtime = filemtime($realpath); 671 | $url_path = get_url_path($realpath) ?: ($symlinked ? get_url_path($path) : false); 672 | 673 | // array 674 | $arr = array( 675 | 'basename' => basename($realpath) ?: basename($path) ?: '', 676 | 'fileperms' => substr(sprintf('%o', fileperms($realpath)), -4), 677 | 'filetype' => 'dir', 678 | 'is_writeable' => is_writeable($realpath), 679 | 'is_readable' => is_readable($realpath), 680 | 'is_link' => $symlinked ? is_link($path) : false, 681 | 'mime' => 'directory', 682 | 'mtime' => $filemtime, 683 | 'path' => root_relative($path) 684 | ); 685 | 686 | // url path 687 | if($url_path) $arr['url_path'] = $url_path; 688 | 689 | // $files || config::menu_load_all 690 | if($files) $arr['files'] = get_files_data($path, $url_path, $arr['dirsize'], $arr['files_count'], $arr['images_count']); 691 | 692 | // json cache path 693 | if($json_url && config::$storage_is_within_doc_root && !config::$has_login && config::$config['cache']){ 694 | $json_cache = get_json_cache_url(get_dir_cache_hash($realpath, $filemtime)); 695 | if($json_cache) $arr['json_cache'] = $json_cache; 696 | } 697 | 698 | // 699 | return $arr; 700 | } 701 | 702 | // get menu sort 703 | function get_menu_sort($dirs){ 704 | if(strpos(config::$config['menu_sort'], 'date') === 0){ 705 | usort($dirs, function($a, $b) { 706 | return filemtime($a) - filemtime($b); 707 | }); 708 | } else { 709 | /*usort($dirs, function($a, $b) { 710 | return strnatcasecmp(basename(real_path($a)), basename(real_path($b))); 711 | });*/ 712 | natcasesort($dirs); 713 | } 714 | return substr(config::$config['menu_sort'], -4) === 'desc' ? array_reverse($dirs) : $dirs; 715 | } 716 | 717 | // recursive directory scan 718 | function get_dirs($path = false, &$arr = array(), $depth = 0) { 719 | 720 | // get this dir (ignore root, unless load all ... root already loaded into page) 721 | if($depth || config::$config['menu_load_all']) { 722 | $data = get_dir($path, config::$config['menu_load_all'], !config::$config['menu_load_all']); 723 | if(!$data) return $arr; 724 | $arr[] = $data; 725 | 726 | // max depth 727 | if(config::$config['menu_max_depth'] && $depth >= config::$config['menu_max_depth']) return $arr; 728 | 729 | // don't recursive if symlink 730 | if($data['is_link'] && !config::$config['menu_recursive_symlinks']) return $arr; 731 | } 732 | 733 | // get dirs from files array if $data['files'] or glob subdirs 734 | $subdirs = isset($data['files']) ? array_filter(array_map(function($file){ 735 | return $file['filetype'] === 'dir' ? root_absolute($file['path']) : false; 736 | }, $data['files'])) : glob($path . '/*', GLOB_NOSORT|GLOB_ONLYDIR); 737 | 738 | // sort and loop subdirs 739 | if(!empty($subdirs)) foreach(get_menu_sort($subdirs) as $subdir) get_dirs($subdir, $arr, $depth + 1); 740 | 741 | // return 742 | return $arr; 743 | } 744 | 745 | function safe_iptc_tag($val, $max_str = 1000){ 746 | $val = @substr($val, 0, $max_str); 747 | return @mb_detect_encoding($val, 'UTF-8', true) ? $val : @utf8_encode($val); 748 | } 749 | 750 | function get_iptc($image_info){ 751 | if(!$image_info || !isset($image_info['APP13']) || !function_exists('iptcparse')) return; 752 | $app13 = @iptcparse($image_info['APP13']); 753 | if(empty($app13)) return; 754 | $iptc = array(); 755 | 756 | // title // ObjectName 757 | if(isset($app13['2#005'][0])) $iptc['title'] = safe_iptc_tag($app13['2#005'][0]); 758 | 759 | // description // Caption-Abstract 760 | if(isset($app13['2#120'][0])) $iptc['description'] = safe_iptc_tag($app13['2#120'][0]); 761 | 762 | // keywords array 763 | if(isset($app13['2#025']) && !empty($app13['2#025']) && is_array($app13['2#025'])) { 764 | $keywords = array_map(function($keyword){ 765 | return safe_iptc_tag($keyword, 100); 766 | }, $app13['2#025']); 767 | if(!empty($keywords)) $iptc['keywords'] = $keywords; 768 | } 769 | return $iptc; 770 | } 771 | 772 | // get exif 773 | function get_exif($path){ 774 | if(!function_exists('exif_read_data')) return; 775 | $exif_data = @exif_read_data($path, 'ANY_TAG', 0); // @exif_read_data($path); 776 | if(empty($exif_data) || !is_array($exif_data)) return; 777 | $exif = array(); 778 | foreach (array('DateTime', 'DateTimeOriginal', 'ExposureTime', 'FNumber', 'FocalLength', 'Make', 'Model', 'Orientation', 'ISOSpeedRatings', 'Software') as $name) { 779 | if(isset($exif_data[$name])) $exif[$name] = trim($exif_data[$name]); 780 | } 781 | if(isset($exif['DateTime'])) $exif['DateTime'] = @strtotime($exif['DateTime']); 782 | if(isset($exif['DateTimeOriginal'])) $exif['DateTimeOriginal'] = @strtotime($exif['DateTimeOriginal']); 783 | 784 | /*LensInfo 24-70mm f/? 785 | Lens EF24-70mm f/2.8L USM 786 | LensID 230*/ 787 | 788 | // ApertureFNumber (f_stop) 789 | if(isset($exif_data['COMPUTED']['ApertureFNumber'])) $exif['ApertureFNumber'] = $exif_data['COMPUTED']['ApertureFNumber']; 790 | 791 | // flash 792 | if(isset($exif_data['Flash'])) $exif['Flash'] = ($exif_data['Flash'] & 1) != 0; 793 | 794 | // GPS 795 | $gps = get_image_location($exif_data); 796 | if(!empty($gps)) $exif['gps'] = $gps; 797 | 798 | // return 799 | return $exif; 800 | } 801 | 802 | function get_image_location($exif){ 803 | $arr = array('GPSLatitudeRef', 'GPSLatitude', 'GPSLongitudeRef', 'GPSLongitude'); 804 | foreach ($arr as $val) { 805 | if(!isset($exif[$val])) return false; 806 | } 807 | 808 | $GPSLatitudeRef = $exif[$arr[0]]; 809 | $GPSLatitude = $exif[$arr[1]]; 810 | $GPSLongitudeRef= $exif[$arr[2]]; 811 | $GPSLongitude = $exif[$arr[3]]; 812 | 813 | $lat_degrees = count($GPSLatitude) > 0 ? gps2Num($GPSLatitude[0]) : 0; 814 | $lat_minutes = count($GPSLatitude) > 1 ? gps2Num($GPSLatitude[1]) : 0; 815 | $lat_seconds = count($GPSLatitude) > 2 ? gps2Num($GPSLatitude[2]) : 0; 816 | 817 | $lon_degrees = count($GPSLongitude) > 0 ? gps2Num($GPSLongitude[0]) : 0; 818 | $lon_minutes = count($GPSLongitude) > 1 ? gps2Num($GPSLongitude[1]) : 0; 819 | $lon_seconds = count($GPSLongitude) > 2 ? gps2Num($GPSLongitude[2]) : 0; 820 | 821 | $lat_direction = ($GPSLatitudeRef == 'W' or $GPSLatitudeRef == 'S') ? -1 : 1; 822 | $lon_direction = ($GPSLongitudeRef == 'W' or $GPSLongitudeRef == 'S') ? -1 : 1; 823 | 824 | $latitude = $lat_direction * ($lat_degrees + ($lat_minutes / 60) + ($lat_seconds / (60*60))); 825 | $longitude = $lon_direction * ($lon_degrees + ($lon_minutes / 60) + ($lon_seconds / (60*60))); 826 | 827 | return array($latitude, $longitude); 828 | } 829 | 830 | function gps2Num($coordPart){ 831 | $parts = explode('/', $coordPart); 832 | if(count($parts) <= 0) 833 | return 0; 834 | if(count($parts) == 1) 835 | return $parts[0]; 836 | return floatval($parts[0]) / floatval($parts[1]); 837 | } 838 | 839 | // 840 | function get_files_data($dir, $url_path = false, &$dirsize = 0, &$files_count = 0, &$images_count = 0){ 841 | 842 | // scandir 843 | $filenames = scandir($dir, SCANDIR_SORT_NONE); 844 | if(empty($filenames)) return array(); 845 | $items = array(); 846 | 847 | // loop filenames 848 | foreach($filenames as $filename) { 849 | 850 | // 851 | if($filename === '.' || $filename === '..') continue; 852 | $path = $dir . '/' . $filename; 853 | 854 | // paths 855 | $realpath = real_path($path); // differs from $path only if is symlinked 856 | if(!$realpath) continue; // no real path for any reason, for example symlink dead 857 | $symlinked = $realpath !== $path; // path is symlinked at some point 858 | 859 | // filetype 860 | $filetype = filetype($realpath); 861 | $is_dir = $filetype === 'dir' ? true : false; 862 | 863 | // exclude 864 | if(is_exclude($path, $is_dir, $symlinked)) continue; // exclude 865 | if($symlinked && is_exclude($realpath, $is_dir, $symlinked)) continue; // exclude check again symlink realpath 866 | 867 | // vars 868 | if(!$is_dir) $files_count ++; // files count 869 | $is_link = $symlinked ? is_link($path) : false; // symlink 870 | $basename = $is_link ? (basename($realpath) ?: $filename) : $filename; 871 | $filemtime = filemtime($realpath); 872 | $is_readable = is_readable($realpath); 873 | $filesize = $is_dir ? false : filesize($realpath); 874 | if($filesize) $dirsize += $filesize; 875 | 876 | // url_path / symlink 877 | $item_url_path = $symlinked ? get_url_path($realpath) : false; // url_path from realpath if symlinked 878 | if(!$item_url_path && $url_path) $item_url_path = $url_path . ($url_path === '/' ? '' : '/') . ($is_link ? basename($path) : $basename); 879 | 880 | // root path // path relative to config::$root 881 | if(!$symlinked || is_within_root($realpath)){ 882 | $root_path = root_relative($realpath); 883 | 884 | // path is symlinked and !is_within_root(), get path-relative 885 | } else { 886 | 887 | // root path to symlink 888 | $root_path = root_relative($path); 889 | 890 | // check for symlink loop 891 | if($is_link && $is_dir && $path && $root_path) { 892 | $basename_path = basename($root_path); 893 | if($basename_path && preg_match('/(\/|^)' . $basename_path. '\//', $root_path)){ 894 | $loop_path = ''; 895 | $segments = explode('/', $root_path); 896 | array_pop($segments); 897 | foreach ($segments as $segment) { 898 | $loop_path .= ($loop_path ? '/' : '') . $segment; 899 | if($segment !== $basename_path) continue; 900 | $loop_abs_path = root_absolute($loop_path); 901 | if(!is_link($loop_abs_path) || $realpath !== real_path($loop_abs_path)) continue; 902 | $root_path = $loop_path; 903 | $item_url_path = get_url_path($loop_abs_path) ?: $item_url_path; // new symlink is within doc_root 904 | break; 905 | } 906 | } 907 | } 908 | } 909 | 910 | // add properties 911 | $item = array( 912 | 'basename' => $basename, 913 | 'fileperms' => substr(sprintf('%o', fileperms($realpath)), -4), 914 | 'filetype' => $filetype, 915 | 'filesize' => $filesize, 916 | 'is_readable' => $is_readable, 917 | 'is_writeable' => is_writeable($realpath), 918 | 'is_link' => $is_link, 919 | 'mtime' => $filemtime, 920 | 'path' => $root_path 921 | ); 922 | 923 | // optional props 924 | $ext = !$is_dir ? pathinfo($realpath, PATHINFO_EXTENSION) : false; 925 | if($ext) { 926 | $ext = strtolower($ext); 927 | $item['ext'] = $ext; 928 | } 929 | $mime = $is_dir ? 'directory' : ($is_readable && (!$ext || config::$config['get_mime_type']) ? get_mime($realpath) : false); 930 | if($mime) $item['mime'] = $mime; 931 | if($item_url_path) $item['url_path'] = $item_url_path; 932 | 933 | // image / check from mime, fallback to extension 934 | $is_image = $is_dir ? false : ($mime ? (strtok($mime, '/') === 'image' && !strpos($mime, 'svg')) : in_array($ext, array('gif','jpg','jpeg','jpc','jp2','jpx','jb2','png','swf','psd','bmp','tiff','tif','wbmp','xbm','ico','webp'))); 935 | if($is_image){ 936 | 937 | // imagesize 938 | $imagesize = $is_readable ? @getimagesize($realpath, $info) : false; 939 | 940 | // image count and icon 941 | $images_count ++; 942 | $item['icon'] = 'image'; 943 | 944 | // is imagesize 945 | if(!empty($imagesize) && is_array($imagesize)){ 946 | 947 | // start image array 948 | $image = array(); 949 | foreach (array(0 => 'width', 1 => 'height', 2 => 'type', 'bits' => 'bits', 'channels' => 'channels', 'mime' => 'mime') as $key => $name) if(isset($imagesize[$key])) $image[$name] = $imagesize[$key]; 950 | 951 | // mime from image 952 | if(!$mime && isset($image['mime'])) $item['mime'] = $image['mime']; 953 | 954 | // IPTC 955 | $iptc = $info ? get_iptc($info) : false; 956 | if(!empty($iptc)) $image['iptc'] = $iptc; 957 | 958 | // EXIF 959 | $exif = get_exif($realpath); 960 | if(!empty($exif)) { 961 | $image['exif'] = $exif; 962 | if(isset($exif['DateTimeOriginal'])) $item['DateTimeOriginal'] = $exif['DateTimeOriginal']; 963 | // invert width/height if exif orientation 964 | if(isset($exif['Orientation']) && $exif['Orientation'] > 4 && $exif['Orientation'] < 9){ 965 | $image['width'] = $imagesize[1]; 966 | $image['height'] = $imagesize[0]; 967 | } 968 | } 969 | 970 | // image resize cache direct 971 | if(config::$image_resize_cache_direct){ 972 | $resize1 = get_image_cache_path($realpath, config::$config['image_resize_dimensions'], $filesize, $filemtime); 973 | if(file_exists($resize1)) $image['resize' . config::$config['image_resize_dimensions']] = get_url_path($resize1); 974 | $retina = config::$image_resize_dimensions_retina; 975 | if($retina){ 976 | $resize2 = get_image_cache_path($realpath, $retina, $filesize, $filemtime); 977 | if(file_exists($resize2)) $image['resize' . $retina] = get_url_path($resize2); 978 | } 979 | } 980 | 981 | // add image to item 982 | $item['image'] = $image; 983 | 984 | // get real mime if getimagesize fails. Could be non-image disguised as image extension 985 | } else if($is_readable && !$mime){ 986 | $mime = get_mime($realpath); 987 | if($mime) { 988 | $item['mime'] = $mime; 989 | if(strtok($mime, '/') !== 'image'){ // unset images_count and icon because is not image after all 990 | $images_count --; 991 | unset($item['icon']); 992 | } 993 | } 994 | } 995 | } 996 | 997 | // add to items with basename as key 998 | $items[$basename] = $item; 999 | } 1000 | 1001 | // 1002 | return $items; 1003 | } 1004 | 1005 | // get files 1006 | function get_files($dir){ 1007 | 1008 | // invalid $dir 1009 | if(!$dir) json_error('Invalid directory'); 1010 | 1011 | // cache 1012 | $cache = get_dir_cache_path(real_path($dir)); 1013 | 1014 | // read cache or get dir and cache 1015 | if(!read_file($cache, 'application/json', 'files json served from cache')) { 1016 | json_cache(get_dir($dir, true), 'files json created' . ($cache ? ' and cached' : ''), $cache); 1017 | } 1018 | } 1019 | 1020 | /* start here */ 1021 | function post($param){ 1022 | return isset($_POST[$param]) && !empty($_POST[$param]) ? $_POST[$param] : false; 1023 | } 1024 | function get($param){ 1025 | return isset($_GET[$param]) && !empty($_GET[$param]) ? $_GET[$param] : false; 1026 | } 1027 | function json_cache($arr = array(), $msg = false, $cache = true){ 1028 | header('content-type: application/json'); 1029 | $json = empty($arr) ? '{}' : json_encode($arr, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); 1030 | if($cache) @file_put_contents($cache, $json); 1031 | if($msg) header('files-msg: ' . $msg . ' [' . header_memory_time() . ']'); 1032 | echo $json; 1033 | } 1034 | function json_error($error = 'Error'){ 1035 | header('Content-Type: application/json'); 1036 | exit('{"error":"' . $error . '"}'); 1037 | } 1038 | function json_success($success){ 1039 | header('Content-Type: application/json'); 1040 | exit('{"success":"' . $success . '"}'); 1041 | } 1042 | function error($msg, $code = false){ 1043 | // 400 Bad Request, 403 Forbidden, 401 Unauthorized, 404 Not Found, 500 Internal Server Error 1044 | if($code) http_response_code($code); 1045 | header('content-type: text/html'); 1046 | header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT'); 1047 | header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0, s-maxage=0'); 1048 | header('Cache-Control: post-check=0, pre-check=0', false); 1049 | header('Pragma: no-cache'); 1050 | exit('

Error

' . $msg); 1051 | } 1052 | 1053 | // get valid menu cache 1054 | function get_valid_menu_cache($cache){ 1055 | if(!$cache || !file_exists($cache)) return; 1056 | $json = @file_get_contents($cache); 1057 | if(empty($json)) return; 1058 | if(!config::$config['menu_cache_validate']) return $json; 1059 | $arr = @json_decode($json, true); 1060 | if(empty($arr)) return; 1061 | foreach ($arr as $key => $val) { 1062 | $path = $val['path']; 1063 | if(strpos($path, '/') !== false && $val['mtime'] !== @filemtime(root_absolute($path))) return; // skip shallow 1st level dirs, and compare filemtime 1064 | } 1065 | return $json; 1066 | } 1067 | 1068 | // get root dirs 1069 | function get_root_dirs(){ 1070 | $root_dirs = glob(config::$root . '/*', GLOB_ONLYDIR|GLOB_NOSORT); 1071 | if(empty($root_dirs)) return array(); 1072 | return array_filter($root_dirs, function($dir){ 1073 | return !is_exclude($dir, true, is_link($dir)); 1074 | }); 1075 | } 1076 | 1077 | // get menu cache hash 1078 | function get_menu_cache_hash($root_dirs){ 1079 | $mtime_count = filemtime(config::$root); 1080 | foreach ($root_dirs as $root_dir) $mtime_count += filemtime($root_dir); 1081 | return substr(md5(config::$doc_root . config::$__dir__ . config::$root), 0, 6) . '.' . substr(md5(config::$version . config::$config['cache_key'] . config::$config['menu_max_depth'] . config::$config['menu_load_all'] . (config::$config['menu_load_all'] ? config::$config['files_exclude'] . config::$image_resize_cache_direct : '') . config::$has_login . config::$config['dirs_exclude'] . config::$config['menu_sort']), 0, 6) . '.' . $mtime_count; 1082 | } 1083 | 1084 | // get dirs 1085 | function dirs(){ 1086 | 1087 | // get menu_cache_hash 1088 | if(config::$config['cache']){ 1089 | $menu_cache_hash = post('menu_cache_hash'); // get menu cache hash 1090 | $menu_cache_arr = $menu_cache_hash ? explode('.', $menu_cache_hash) : false; 1091 | if(!$menu_cache_arr || 1092 | count($menu_cache_arr) !== 3 || 1093 | strlen($menu_cache_arr[0]) !== 6 || 1094 | strlen($menu_cache_arr[1]) !== 6 || 1095 | !is_numeric($menu_cache_arr[2]) 1096 | ) json_error('Invalid menu cache hash'); // early exit 1097 | } 1098 | $cache = config::$config['cache'] ? config::$cache_path . '/menu/' . $menu_cache_hash . '.json' : false; // get cache path 1099 | $json = $cache ? get_valid_menu_cache($cache) : false; // get valid json menu cache 1100 | 1101 | // $json is valid from menu cache file 1102 | if($json){ 1103 | header('content-type: application/json'); 1104 | header('files-msg: valid menu cache hash [' . $menu_cache_hash . ']' . (!config::$config['menu_cache_validate'] ? '[deep validation disabled]' : '') . '[' . header_memory_time() . ']'); 1105 | echo (post('localstorage') ? '{"localstorage":"1"}' : $json); 1106 | 1107 | // reload dirs 1108 | } else { 1109 | json_cache(get_dirs(config::$root), 'dirs reloaded' . ($cache ? ' and cached.' : ' [cache disabled]'), $cache); 1110 | } 1111 | } 1112 | 1113 | // custom_script (css + js in storage) 1114 | function custom_script($type){ 1115 | // todo maybe just use one file custom.css/js for easy edit? 1116 | if(!config::$storage_path || !config::$storage_is_within_doc_root) return; 1117 | $dir = config::$storage_path . '/' . $type; 1118 | $files = file_exists($dir) ? glob($dir . '/*.' . $type) : false; 1119 | if(empty($files)) return; 1120 | $template = $type === 'css' ? '' : ''; 1121 | foreach($files as $file) echo str_replace('%url%', get_url_path($file) . '?' . filemtime($file), $template) . PHP_EOL; 1122 | } 1123 | 1124 | // POST 1125 | if(post('action')){ 1126 | 1127 | // basic post access security: XMLHttpRequest + post_hash created from server paths 1128 | if(!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || 1129 | $_SERVER['HTTP_X_REQUESTED_WITH'] !== 'XMLHttpRequest' || 1130 | post('post_hash') !== md5(__FILE__ . $_SERVER['HTTP_HOST'])) json_error('Invalid request hash. Please Refresh browser.'); 1131 | 1132 | // post action 1133 | $action = post('action'); 1134 | 1135 | // 1136 | new config(); 1137 | 1138 | // dirs 1139 | if($action === 'dirs'){ 1140 | dirs(post('localstorage')); 1141 | 1142 | // files 1143 | } else if($action === 'files'){ 1144 | if(!isset($_POST['dir'])) json_error('Missing dir parameter'); 1145 | get_files(valid_root_path($_POST['dir'], true)); 1146 | 1147 | // file 1148 | } else if($action === 'file'){ 1149 | 1150 | // valid path 1151 | $file = valid_root_path(post('file')); 1152 | if(!$file) json_error('Invalid file path'); 1153 | $file = real_path($file); // in case of symlink path 1154 | 1155 | // file write 1156 | if(post('write')) { 1157 | if(!config::$config['code_allow_edit']) json_error('Code editing has been disabled.'); 1158 | if(!is_writeable($file) || !is_file($file)) json_error('File is not writeable.'); 1159 | $write_success = @file_put_contents($file, post('write')); 1160 | $cache_file = $write_success ? get_dir_cache_path(dirname($file)) : false; 1161 | if($cache_file && file_exists($cache_file)) @unlink($cache_file); 1162 | json_success($write_success); 1163 | 1164 | // get 1165 | } else { 1166 | header('content-type: text/plain; charset=utf-8'); 1167 | readfile($file); 1168 | } 1169 | 1170 | // check login 1171 | } else if($action === 'check_login'){ 1172 | header('content-type: application/json'); 1173 | echo '{"success":true}'; 1174 | 1175 | // check updates 1176 | } else if($action === 'check_updates'){ 1177 | header('Content-Type: application/json'); 1178 | $data = @file_get_contents('https://data.jsdelivr.com/v1/package/npm/files.photo.gallery'); 1179 | $json = $data ? @json_decode($data, true) : false; 1180 | $latest = !empty($json) && isset($json['versions']) ? $json['versions'][0] : false; 1181 | if($latest) { 1182 | $is_new = version_compare($latest, config::$version) > 0; 1183 | exit('{"success":' . ($is_new ? '"'.$latest.'"' : 'false') . ($is_new ? ',"writeable":' . (is_writable(__DIR__) && is_writable(__FILE__) ? 'true' : 'false') : '') . '}'); 1184 | } 1185 | exit('{"error": true }'); 1186 | 1187 | } else if($action === 'do_update'){ 1188 | header('Content-Type: application/json'); 1189 | $version = post('version'); 1190 | $file = 'https://cdn.jsdelivr.net/npm/files.photo.gallery' . ($version ? '@' . $version : '') . '/index.php'; 1191 | $update_is_newer = !$version || version_compare($version, config::$version) > 0; 1192 | $writeable = $update_is_newer && is_writable(__DIR__) && is_writable(__FILE__); 1193 | $get = $writeable ? @file_get_contents($file) : false; 1194 | $put = $get && strpos($get, '' && @file_put_contents(__FILE__, $get); 1195 | exit('{"success":' . ($put ? 'true' : 'false') . '}'); 1196 | 1197 | } else if($action === 'license'){ 1198 | header('Content-Type: application/json'); 1199 | $key = isset($_POST['key']) ? trim($_POST['key']) : false; 1200 | $success = config::$storage_config_realpath && $key && config::save_config(array('license_key' => $key)); 1201 | exit('{"success":' . ($success ? 'true, "md5" : "' . md5($key) . '"' : 'false') . '}'); 1202 | 1203 | // invalid action 1204 | } else { 1205 | json_error('invalid action: ' . $action); 1206 | } 1207 | 1208 | // GET 1209 | } else /*if($_SERVER['REQUEST_METHOD'] === 'GET')*/{ 1210 | 1211 | // file/image 1212 | if(isset($_GET['file'])){ 1213 | new config(); 1214 | get_file(valid_root_path(get('file')), get('resize')); 1215 | 1216 | // download 1217 | } else if(isset($_GET['download'])){ 1218 | new config(); 1219 | 1220 | // valid download 1221 | $download = valid_root_path(get('download')); 1222 | if(!$download) error('Invalid download path ' . get('download') . '', 404); 1223 | $download = real_path($download); // in case of symlink path 1224 | 1225 | // required for some browsers 1226 | if(@ini_get('zlib.output_compression')) @ini_set('zlib.output_compression', 'Off'); 1227 | 1228 | // headers 1229 | header('Content-Description: File Transfer'); 1230 | header('Content-Type: application/octet-stream'); 1231 | header('Content-Disposition: attachment; filename="' . basename($download) . '"'); 1232 | header('Content-Transfer-Encoding: binary'); 1233 | header('Expires: 0'); 1234 | header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 1235 | header('Pragma: public'); 1236 | header('Content-Length: ' . filesize($download)); 1237 | ob_clean(); 1238 | flush(); 1239 | readfile($download); 1240 | 1241 | // tasks plugin 1242 | } else if(get('task')){ 1243 | 1244 | // new config with tests 1245 | new config(true); 1246 | 1247 | // get plugin 1248 | $tasks_path = config::$storage_path . '/plugins/tasks.php'; 1249 | if(!file_exists($tasks_path)) error("Tasks plugin does not exist at $tasks_path", 404); 1250 | include $tasks_path; 1251 | exit; 1252 | 1253 | // main document 1254 | } else { 1255 | 1256 | // new config, with tests 1257 | new config(true); 1258 | 1259 | // validate exclude regex 1260 | if(config::$config['files_exclude'] && @preg_match(config::$config['files_exclude'], '') === false) error('Invalid files_exclude regex ' . config::$config['files_exclude'] . ''); 1261 | if(config::$config['dirs_exclude'] && @preg_match(config::$config['dirs_exclude'], '') === false) error('Invalid dirs_exclude regex ' . config::$config['dirs_exclude'] . ''); 1262 | 1263 | // start path 1264 | $start_path = config::$config['start_path']; 1265 | if($start_path){ 1266 | $real_start_path = real_path($start_path); 1267 | if(!$real_start_path) error('start_path ' . $start_path . ' does not exist.'); 1268 | if(!is_within_root($real_start_path)) error('start_path ' . $start_path . ' is not within root dir ' . config::$config['root']); 1269 | $start_path = root_relative($real_start_path); 1270 | } 1271 | 1272 | // root dirs (if menu) 1273 | $root_dirs = config::$config['menu_enabled'] || config::$config['breadcrumbs'] ? get_root_dirs() : false; 1274 | $menu_enabled = config::$config['menu_enabled'] && !empty($root_dirs) ? true : false; 1275 | $breadcrumbs = config::$config['breadcrumbs'] && !empty($root_dirs) ? true : false; 1276 | 1277 | // get menu cache hash 1278 | $menu_cache_hash = false; 1279 | $menu_cache_file = false; 1280 | if($menu_enabled){ 1281 | $menu_cache_hash = get_menu_cache_hash($root_dirs); 1282 | // menu cache file (if cache, !menu_cache_validate, exists and is within doc root) 1283 | if(config::$storage_is_within_doc_root && config::$config['cache'] && !config::$config['menu_cache_validate']) { 1284 | $menu_cache_path = config::$cache_path . '/menu/' . $menu_cache_hash . '.json'; 1285 | $menu_cache_file = file_exists($menu_cache_path) ? get_url_path($menu_cache_path) : false; 1286 | if($menu_cache_file) $menu_cache_file .= '?' . filemtime($menu_cache_path); 1287 | } 1288 | } 1289 | 1290 | // init path 1291 | $query = config::$config['history'] && $_SERVER['QUERY_STRING'] ? explode('&', $_SERVER['QUERY_STRING']) : false; 1292 | $query_path = $query && strpos($query[0], '=') === false && $query[0] != 'debug' ? rtrim(rawurldecode($query[0]), '/') : false; 1293 | $query_path_valid = $query_path ? valid_root_path($query_path, true) : false; 1294 | $init_path = $query_path ?: $start_path ?: ''; 1295 | 1296 | // init dirs, with files if cache 1297 | function get_dir_init($dir){ 1298 | $cache = get_dir_cache_path($dir); 1299 | if(file_exists($cache)) return json_decode(file_get_contents($cache), true); 1300 | return get_dir($dir); 1301 | } 1302 | 1303 | // get dirs for root and start path 1304 | $dirs = array('' => get_dir_init(config::$root)); 1305 | if($query_path){ 1306 | if($query_path_valid) $dirs[$query_path] = get_dir_init($query_path_valid); 1307 | } else if($start_path){ 1308 | $dirs[$start_path] = get_dir_init($real_start_path); 1309 | } 1310 | 1311 | // resize image types 1312 | $resize_image_types = array('jpeg', 'jpg', 'png', 'gif'); 1313 | if(version_compare(PHP_VERSION, '5.4.0') >= 0) { 1314 | $resize_image_types[] = 'webp'; 1315 | if(version_compare(PHP_VERSION, '7.2.0') >= 0) $resize_image_types[] = 'bmp'; 1316 | } 1317 | 1318 | // image resize memory limit 1319 | $image_resize_memory_limit = config::$config['image_resize_enabled'] && config::$config['image_resize_memory_limit'] && function_exists('ini_get') ? (int) @ini_get('memory_limit') : 0; 1320 | if($image_resize_memory_limit && function_exists('ini_set')) $image_resize_memory_limit = max($image_resize_memory_limit, config::$config['image_resize_memory_limit']); 1321 | 1322 | $wtc = config::$config[base64_decode('bGljZW5zZV9rZXk')]; 1323 | 1324 | // exclude some user settings from frontend 1325 | $exclude = array_diff_key(config::$config, array_flip(array('root', 'start_path', 'image_resize_cache', 'image_resize_quality', 'image_resize_function', 'image_resize_cache_direct', 'menu_sort', 'menu_load_all', 'cache_key', 'storage_path', 'files_exclude', 'dirs_exclude', 'username', 'password', 'breadcrumbs', 'allow_tasks', 'allow_symlinks', 'menu_recursive_symlinks', 'image_resize_sharpen', 'get_mime_type', 'license_key'))); 1326 | $json_config = array_replace($exclude, array( 1327 | 'breadcrumbs' => $breadcrumbs, 1328 | 'script' => basename(__FILE__), 1329 | 'menu_enabled' => $menu_enabled, 1330 | 'menu_cache_hash' => $menu_cache_hash, 1331 | 'menu_cache_file' => $menu_cache_file, 1332 | 'query_path' => $query_path, 1333 | 'query_path_valid' => $query_path_valid ? true : false, 1334 | 'init_path' => $init_path, 1335 | 'dirs' => $dirs, 1336 | 'dirs_hash' => config::$dirs_hash, 1337 | 'resize_image_types' => $resize_image_types, 1338 | 'post_hash' => md5(__FILE__ . $_SERVER['HTTP_HOST']), 1339 | 'image_cache_hash' => config::$config['load_images'] ? substr(md5(config::$doc_root . config::$root . config::$config['image_resize_function'] . config::$config['image_resize_quality']), 0, 6) : false, 1340 | 'image_resize_dimensions_retina' => config::$image_resize_dimensions_retina, 1341 | 'location_hash' => md5(config::$root), 1342 | 'has_login' => config::$has_login, 1343 | 'version' => config::$version, 1344 | 'index_html' => intval(get('index_html')), 1345 | 'server_exif' => function_exists('exif_read_data'), 1346 | 'image_resize_memory_limit' => $image_resize_memory_limit, 1347 | 'qrx' => $wtc && is_string($wtc) ? substr(md5($wtc), 0, strlen($wtc)) : false 1348 | )); 1349 | 1350 | // memory and time 1351 | header('files-msg: [' . header_memory_time() . ']'); 1352 | 1353 | // htmlstart 1354 | ?> 1355 | 1356 | > 1357 | 1358 | 1359 | 1360 | 1361 | <?php echo $init_path ? basename($init_path) : '/'; ?> 1362 | 1363 | 1364 | 1365 | 1366 | 1367 | 1368 |
1369 | 1374 | 1388 |
1389 | 1390 |
1391 |
1392 | 1393 | 1400 | 1401 | 1402 | 1403 | 1404 | 1405 | 1406 | 1407 | 1408 | 1409 | 1410 | 1411 | 1412 | 1413 | 1414 | 1415 | 1416 | 1417 | 1418 | 1419 | 1420 | 1421 | 1422 | 1423 | 1424 | 1428 | 1429 | 1430 | 1431 | 1432 | 1433 | 1434 | 1435 | 1436 | 1439 | --------------------------------------------------------------------------------