First commit
This commit is contained in:
commit
77d2c29e38
77
app/base/BaseController.php
Normal file
77
app/base/BaseController.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
class BaseController {
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function login()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function logout()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function search()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Output a template to HTML, using the provided data
|
||||
*
|
||||
* @param string $template
|
||||
* @param array/object $data
|
||||
* @return void
|
||||
*/
|
||||
public function outputHTML($template, $data=[])
|
||||
{
|
||||
global $router;
|
||||
$route = $router->get_route();
|
||||
$data['route_path'] = ($route) ? $router->get_route()->path : "";
|
||||
|
||||
$path = realpath(__DIR__ . "/../views/{$template}.php");
|
||||
|
||||
if ( ! is_file($path))
|
||||
{
|
||||
throw new Exception("Invalid template : {$path}");
|
||||
}
|
||||
|
||||
ob_start();
|
||||
extract($data);
|
||||
include $path;
|
||||
$buffer = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
header("Content-type: text/html;charset=utf-8");
|
||||
echo $buffer;
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output json with the proper content type
|
||||
*
|
||||
* @param mixed data
|
||||
* @return void
|
||||
*/
|
||||
public function outputJSON($data)
|
||||
{
|
||||
if ( ! is_string($data))
|
||||
{
|
||||
$data = json_encode($data);
|
||||
}
|
||||
|
||||
header("Content-type: application/json");
|
||||
echo $data;
|
||||
}
|
||||
}
|
39
app/base/BaseModel.php
Normal file
39
app/base/BaseModel.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
use \GuzzleHttp\Client;
|
||||
use \GuzzleHttp\Cookie\CookieJar;
|
||||
|
||||
class BaseModel {
|
||||
|
||||
protected $client;
|
||||
protected $cookieJar;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->cookieJar = new CookieJar();
|
||||
$this->client = new Client([
|
||||
'base_url' => $this->base_url,
|
||||
'defaults' => [
|
||||
'cookies' => $this->cookieJar,
|
||||
'headers' => [
|
||||
'User-Agent' => $_SERVER['HTTP_USER_AGENT'],
|
||||
'Accept-Encoding' => 'application/json'
|
||||
],
|
||||
'timeout' => 5,
|
||||
'connect_timeout' => 5
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full url path, since the base_url in Guzzle doesn't work correctly
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
protected function _url($path)
|
||||
{
|
||||
return "{$this->base_url}{$path}";
|
||||
}
|
||||
}
|
||||
// End of BaseModel.php
|
88
app/base/Router.php
Normal file
88
app/base/Router.php
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
use Aura\Router\RouterFactory;
|
||||
|
||||
class Router {
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$router_factory = new RouterFactory();
|
||||
$router = $router_factory->newInstance();
|
||||
$this->router = $router_factory->newInstance();
|
||||
|
||||
$this->_setup_routes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current route object, if one matches
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function get_route()
|
||||
{
|
||||
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
||||
$route = $this->router->match($path, $_SERVER);
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the current route
|
||||
*
|
||||
* @param [object] $route
|
||||
* @return void
|
||||
*/
|
||||
public function dispatch($route = NULL)
|
||||
{
|
||||
if (is_null($route))
|
||||
{
|
||||
$route = $this->get_route();
|
||||
}
|
||||
|
||||
if ( ! $route)
|
||||
{
|
||||
$controller_name = 'BaseController';
|
||||
$action_method = 'outputHTML';
|
||||
$params = [
|
||||
'template' => '404',
|
||||
'data' => [
|
||||
'title' => 'Page Not Found'
|
||||
]
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
$controller_name = $route->params['controller'];
|
||||
$action_method = $route->params['action'];
|
||||
$params = (isset($route->params['params'])) ? $route->params['params'] : [];
|
||||
}
|
||||
|
||||
$controller = new $controller_name();
|
||||
|
||||
// Run the appropriate controller method
|
||||
call_user_func_array([$controller, $action_method], $params);
|
||||
}
|
||||
|
||||
private function _setup_routes()
|
||||
{
|
||||
$host = $_SERVER['HTTP_HOST'];
|
||||
$controller_class = ($host == "anime.timshomepage.net") ? "AnimeController" : "MangaController";
|
||||
|
||||
$routes = require __DIR__ . '/../config/routes.php';
|
||||
|
||||
// Add the default route
|
||||
$this->router->add('home', '/')->addValues([
|
||||
'controller' => $controller_class,
|
||||
'action' => 'index'
|
||||
]);
|
||||
|
||||
// Add routes by the configuration file
|
||||
foreach($routes as $name => $route)
|
||||
{
|
||||
$path = $route['path'];
|
||||
unset($route['path']);
|
||||
$this->router->add($name, $path)->addValues($route);
|
||||
}
|
||||
}
|
||||
}
|
||||
// End of Router.php
|
17
app/base/autoloader.php
Normal file
17
app/base/autoloader.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
function anime_autoloader($class) {
|
||||
$dirs = ["base", "controllers", "models"];
|
||||
|
||||
foreach($dirs as $dir)
|
||||
{
|
||||
$file = realpath(__DIR__ . "/../{$dir}/{$class}.php");
|
||||
if (file_exists($file))
|
||||
{
|
||||
require_once $file;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spl_autoload_register('anime_autoloader');
|
42
app/config/routes.php
Normal file
42
app/config/routes.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'anime_all' => [
|
||||
'path' => '/all',
|
||||
'controller' => 'AnimeController',
|
||||
'action' => 'all',
|
||||
'params' => []
|
||||
],
|
||||
'anime_plan_to_watch' => [
|
||||
'path' => '/plan_to_watch',
|
||||
'controller' => 'AnimeController',
|
||||
'action' => 'anime_list',
|
||||
'params' => [
|
||||
'type' => 'plan-to-watch'
|
||||
]
|
||||
],
|
||||
'anime_on_hold' => [
|
||||
'path' => '/on_hold',
|
||||
'controller' => 'AnimeController',
|
||||
'action' => 'anime_list',
|
||||
'params' => [
|
||||
'type' => 'on-hold'
|
||||
]
|
||||
],
|
||||
'anime_dropped' => [
|
||||
'path' => '/dropped',
|
||||
'controller' => 'AnimeController',
|
||||
'action' => 'anime_list',
|
||||
'params' => [
|
||||
'type' => 'dropped'
|
||||
]
|
||||
],
|
||||
'anime_completed' => [
|
||||
'path' => '/completed',
|
||||
'controller' => 'AnimeController',
|
||||
'action' => 'anime_list',
|
||||
'params' => [
|
||||
'type' => 'completed'
|
||||
]
|
||||
]
|
||||
];
|
41
app/controllers/AnimeController.php
Normal file
41
app/controllers/AnimeController.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
class AnimeController extends BaseController {
|
||||
|
||||
private $model;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->model = new AnimeModel();
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
parent::__destruct();
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$this->anime_list('currently-watching');
|
||||
}
|
||||
|
||||
public function all()
|
||||
{
|
||||
$data = $this->model->get_all_lists();
|
||||
$this->outputHTML('anime_list', [
|
||||
'title' => "Tim's Anime List · All",
|
||||
'sections' => $data
|
||||
]);
|
||||
}
|
||||
|
||||
public function anime_list($type, $title="Tim's Anime List")
|
||||
{
|
||||
$data = $this->model->get_list($type);
|
||||
$this->outputHTML('anime_list', [
|
||||
'title' => $title,
|
||||
'sections' => $data
|
||||
]);
|
||||
}
|
||||
}
|
||||
// End of AnimeController.php
|
134
app/models/AnimeModel.php
Normal file
134
app/models/AnimeModel.php
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Model for handling requests dealing with the anime list
|
||||
*/
|
||||
class AnimeModel extends BaseModel {
|
||||
|
||||
protected $client;
|
||||
protected $cookieJar;
|
||||
protected $base_url = "https://hummingbird.me/api/v1";
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full set of anime lists
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_all_lists()
|
||||
{
|
||||
$output = [
|
||||
'Watching' => [],
|
||||
'Completed' => [],
|
||||
'Plan to Watch' => [],
|
||||
'On Hold' => [],
|
||||
'Dropped' => []
|
||||
];
|
||||
|
||||
$data = $this->_get_list();
|
||||
|
||||
foreach($data as $datum)
|
||||
{
|
||||
switch($datum['status'])
|
||||
{
|
||||
case "completed":
|
||||
$output['Completed'][] = $datum;
|
||||
break;
|
||||
|
||||
case "plan-to-watch":
|
||||
$output['Plan to Watch'][] = $datum;
|
||||
break;
|
||||
|
||||
case "dropped":
|
||||
$output['Dropped'][] = $datum;
|
||||
break;
|
||||
|
||||
case "on-hold":
|
||||
$output['On Hold'][] = $datum;
|
||||
break;
|
||||
|
||||
case "currently-watching":
|
||||
$output['Watching'][] = $datum;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort anime by name
|
||||
foreach($output as &$status_list)
|
||||
{
|
||||
$this->sort_by_name($status_list);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a category out of the full list
|
||||
*
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
public function get_list($type)
|
||||
{
|
||||
$map = [
|
||||
'currently-watching' => 'Watching',
|
||||
'completed' => 'Completed',
|
||||
'plan-to-watch' => 'Plan to Watch',
|
||||
'on-hold' => 'On Hold',
|
||||
'dropped' => 'Dropped'
|
||||
];
|
||||
|
||||
$data = $this->_get_list($type);
|
||||
$this->sort_by_name($data);
|
||||
|
||||
$output = [];
|
||||
$output[$map[$type]] = $data;
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function _get_list($type="all")
|
||||
{
|
||||
global $defaultHandler;
|
||||
|
||||
$config = [
|
||||
'query' => [
|
||||
'username' => 'timw4mail',
|
||||
],
|
||||
'allow_redirects' => false
|
||||
];
|
||||
|
||||
if ($type != "all")
|
||||
{
|
||||
$config['query']['status'] = $type;
|
||||
}
|
||||
|
||||
$response = $this->client->get($this->_url('/users/timw4mail/library'), $config);
|
||||
|
||||
$defaultHandler->addDataTable('response', (array)$response);
|
||||
|
||||
if ($response->getStatusCode() != 200)
|
||||
{
|
||||
throw new Exception($response->getEffectiveUrl());
|
||||
}
|
||||
|
||||
return $response->json();
|
||||
}
|
||||
|
||||
private function sort_by_name(&$array)
|
||||
{
|
||||
$sort = array();
|
||||
|
||||
foreach($array as $key => $item)
|
||||
{
|
||||
$sort[$key] = $item['anime']['title'];
|
||||
}
|
||||
|
||||
array_multisort($sort, SORT_ASC, $array);
|
||||
}
|
||||
}
|
||||
// End of AnimeModel.php
|
8
app/views/404.php
Normal file
8
app/views/404.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php include 'header.php'; ?>
|
||||
<body>
|
||||
<main>
|
||||
<h1>404</h1>
|
||||
<h2>Page Not Found</h2>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
39
app/views/anime_list.php
Normal file
39
app/views/anime_list.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php include 'header.php' ?>
|
||||
<body>
|
||||
<h1>Tim's Anime List</h1>
|
||||
<nav>
|
||||
<ul>
|
||||
<li class="<?= is_selected('/all', $route_path) ?>"><a href="/all">All</a></li>
|
||||
<li class="<?= is_selected('/', $route_path) ?>"><a href="/">Watching</a></li>
|
||||
<li class="<?= is_selected('/plan_to_watch', $route_path) ?>"><a href="/plan_to_watch">Plan to Watch</a></li>
|
||||
<li class="<?= is_selected('/on_hold', $route_path) ?>"><a href="/on_hold">On Hold</a></li>
|
||||
<li class="<?= is_selected('/dropped', $route_path) ?>"><a href="/dropped">Dropped</a></li>
|
||||
<li class="<?= is_selected('/completed', $route_path) ?>"><a href="/completed">Completed</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<main>
|
||||
<?php foreach ($sections as $name => $items): ?>
|
||||
<section class="status">
|
||||
<h2><?= $name ?></h2>
|
||||
<section class="media-wrap">
|
||||
<?php foreach($items as $item): ?>
|
||||
<article class="media" id="a-<?= $item['anime']['id'] ?>">
|
||||
<img src="<?= $item['anime']['cover_image'] ?>" />
|
||||
<div class="name"><a href="<?= $item['anime']['url'] ?>">
|
||||
<?= $item['anime']['title'] ?>
|
||||
<?= ($item['anime']['alternate_title'] != "") ? "<br />({$item['anime']['alternate_title']})" : ""; ?>
|
||||
</a></div>
|
||||
<div class="media_metadata">
|
||||
<div class="media_type"><?= $item['anime']['show_type'] ?></div>
|
||||
<div class="airing_status"><?= $item['anime']['status'] ?></div>
|
||||
<div class="user_rating"><?= (int)($item['rating']['value'] * 2) ?> / 10</div>
|
||||
<div class="completion"><?= $item['episodes_watched'] ?> / <?= $item['anime']['episode_count'] ?></div>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach ?>
|
||||
</section>
|
||||
</section>
|
||||
<?php endforeach ?>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
0
app/views/footer.php
Normal file
0
app/views/footer.php
Normal file
7
app/views/header.php
Normal file
7
app/views/header.php
Normal file
@ -0,0 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><?= $title ?></title>
|
||||
<link rel="stylesheet" href="/public/css/marx.css" />
|
||||
<link rel="stylesheet" href="/public/css/base.css" />
|
||||
</head>
|
7
composer.json
Normal file
7
composer.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "5.3.*",
|
||||
"filp/whoops": "1.1.*",
|
||||
"aura/router": "2.2.*"
|
||||
}
|
||||
}
|
38
index.php
Normal file
38
index.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
require __DIR__ . '/app/base/autoloader.php';
|
||||
|
||||
use \Whoops\Handler\PrettyPageHandler;
|
||||
use \Whoops\Handler\JsonResponseHandler;
|
||||
|
||||
function is_selected($a, $b)
|
||||
{
|
||||
return ($a === $b) ? 'selected' : '';
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Setup error handling
|
||||
// -----------------------------------------------------------------------------
|
||||
$whoops = new \Whoops\Run();
|
||||
|
||||
// Set up default handler for general errors
|
||||
$defaultHandler = new PrettyPageHandler();
|
||||
$whoops->pushHandler($defaultHandler);
|
||||
|
||||
// Set up json handler for ajax errors
|
||||
$jsonHandler = new JsonResponseHandler();
|
||||
$jsonHandler->onlyForAjaxRequests(true);
|
||||
$whoops->pushHandler($jsonHandler);
|
||||
|
||||
$whoops->register();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Router
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
$router = new Router();
|
||||
$defaultHandler->addDataTable('route', (array)$router->get_route());
|
||||
$router->dispatch();
|
||||
|
||||
// End of index.php
|
66
public/css/base.css
Normal file
66
public/css/base.css
Normal file
@ -0,0 +1,66 @@
|
||||
.media-wrap {
|
||||
text-align:center;
|
||||
margin:0 auto;
|
||||
}
|
||||
|
||||
.media {
|
||||
position:relative;
|
||||
vertical-align:top;
|
||||
display:inline-block;
|
||||
text-align:center;
|
||||
width:220px;
|
||||
height:319px;
|
||||
margin:0.25em;
|
||||
}
|
||||
.media > img {
|
||||
border-radius:0.25em;
|
||||
}
|
||||
|
||||
.name, .media_type, .airing_status, .user_rating, .completion {
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
color: #fff;
|
||||
padding:0.25em;
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
.media > .media_metadata {
|
||||
position:absolute;
|
||||
bottom:0;
|
||||
right:0;
|
||||
}
|
||||
|
||||
.media > .media_metadata > .media_type {
|
||||
border-top-left-radius: 0.25em;
|
||||
border-top-right-radius: 0.25em;
|
||||
}
|
||||
|
||||
.media > .media_metadata > .completion {
|
||||
border-bottom-left-radius: 0.25em;
|
||||
border-bottom-right-radius: 0.25em;
|
||||
}
|
||||
|
||||
.media > .name {
|
||||
border-radius:0.25em;
|
||||
position:absolute;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.media > .name:hover {
|
||||
background:rgba(0,0,0,0.9);
|
||||
}
|
||||
|
||||
.media > .name > a {
|
||||
text-align:justify;
|
||||
background:none;
|
||||
color:#fff;
|
||||
text-shadow: 1px 2px 1px rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
|
||||
.user_rating::before {
|
||||
content: "Rating: ";
|
||||
}
|
||||
|
||||
.completion::before {
|
||||
content: "Episodes: ";
|
||||
}
|
||||
|
436
public/css/marx.css
Normal file
436
public/css/marx.css
Normal file
@ -0,0 +1,436 @@
|
||||
:root {
|
||||
box-sizing: border-box;
|
||||
cursor: default;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Helvetica, 'Lucida Grande', sans-serif;
|
||||
line-height: 1.4;
|
||||
overflow-y: scroll;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%;
|
||||
text-size-adjust: 100%; }
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none; }
|
||||
|
||||
details {
|
||||
display: block; }
|
||||
|
||||
input[type="number"] {
|
||||
width: auto; }
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield; }
|
||||
input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none; }
|
||||
|
||||
main {
|
||||
display: block; }
|
||||
|
||||
summary {
|
||||
display: block; }
|
||||
|
||||
pre {
|
||||
overflow: auto; }
|
||||
|
||||
progress {
|
||||
display: inline-block; }
|
||||
|
||||
small {
|
||||
font-size: 75%; }
|
||||
|
||||
big {
|
||||
font-size: 125%; }
|
||||
|
||||
template {
|
||||
display: none; }
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
resize: vertical; }
|
||||
|
||||
[hidden] {
|
||||
display: none; }
|
||||
|
||||
[unselectable] {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none; }
|
||||
|
||||
*, ::before, ::after {
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
box-sizing: inherit; }
|
||||
|
||||
* {
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
::before, ::after {
|
||||
text-decoration: inherit;
|
||||
vertical-align: inherit; }
|
||||
|
||||
a {
|
||||
text-decoration: none; }
|
||||
|
||||
audio, canvas, iframe, img, svg, video {
|
||||
vertical-align: middle; }
|
||||
|
||||
button, input, select, textarea {
|
||||
background-color: transparent;
|
||||
border: .1rem solid #ccc;
|
||||
color: inherit;
|
||||
font-family: inherit;
|
||||
font-style: inherit;
|
||||
font-weight: inherit;
|
||||
min-height: 1.4em; }
|
||||
|
||||
code, kbd, pre, samp {
|
||||
font-family: Menlo, Monaco, Consolas, 'Courier New', monospace, monospace; }
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0; }
|
||||
|
||||
::-moz-selection {
|
||||
background-color: #b3d4fc;
|
||||
text-shadow: none; }
|
||||
|
||||
::selection {
|
||||
background-color: #b3d4fc;
|
||||
text-shadow: none; }
|
||||
|
||||
button::-moz-focus-inner {
|
||||
border: 0; }
|
||||
|
||||
@media screen {
|
||||
[hidden~="screen"] {
|
||||
display: inherit; }
|
||||
[hidden~="screen"]:not(:active):not(:focus):not(:target) {
|
||||
clip: rect(0 0 0 0) !important;
|
||||
position: absolute !important; } }
|
||||
|
||||
body {
|
||||
color: #444;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Helvetica, 'Lucida Grande', sans-serif;
|
||||
font-size: 1.6rem;
|
||||
font-style: normal;
|
||||
font-weight: 400; }
|
||||
|
||||
p {
|
||||
margin: 0 0 1.6rem; }
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: 'Lato', 'Open Sans', 'Helvetica Neue', Helvetica, 'Lucida Grande', sans-serif;
|
||||
margin: 2rem 0 1.6rem; }
|
||||
|
||||
h1 {
|
||||
border-bottom: .1rem solid rgba(0, 0, 0, 0.2);
|
||||
font-size: 3.6rem;
|
||||
font-style: normal;
|
||||
font-weight: 500; }
|
||||
|
||||
h2 {
|
||||
font-size: 3rem;
|
||||
font-style: normal;
|
||||
font-weight: 500; }
|
||||
|
||||
h3 {
|
||||
font-size: 2.4rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
margin: 1.6rem 0 0.4rem; }
|
||||
|
||||
h4 {
|
||||
font-size: 1.8rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
margin: 1.6rem 0 0.4rem; }
|
||||
|
||||
h5 {
|
||||
font-size: 1.6rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
margin: 1.6rem 0 0.4rem; }
|
||||
|
||||
h6 {
|
||||
color: #777;
|
||||
font-size: 1.4rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
margin: 1.6rem 0 0.4rem; }
|
||||
|
||||
small {
|
||||
color: #777; }
|
||||
|
||||
pre {
|
||||
background: #efefef;
|
||||
color: #444;
|
||||
display: block;
|
||||
font-family: Menlo, Monaco, Consolas, 'Courier New', monospace;
|
||||
font-size: 1.4rem;
|
||||
margin: 1.6rem 0;
|
||||
padding: 1.6rem;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word; }
|
||||
|
||||
code {
|
||||
background: #efefef;
|
||||
color: #444;
|
||||
font-family: Menlo, Monaco, Consolas, 'Courier New', monospace;
|
||||
font-size: 1.4rem;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word; }
|
||||
|
||||
a {
|
||||
color: #1271db;
|
||||
-webkit-transition: .25s ease;
|
||||
transition: .25s ease; }
|
||||
a:hover, a:focus {
|
||||
text-decoration: none; }
|
||||
|
||||
dl {
|
||||
margin-bottom: 1.6rem; }
|
||||
|
||||
dd {
|
||||
margin-left: 4rem; }
|
||||
|
||||
ul, ol {
|
||||
margin-bottom: 0.8rem;
|
||||
padding-left: 2rem; }
|
||||
|
||||
blockquote {
|
||||
border-left: .2rem solid #1271db;
|
||||
font-family: Georgia, Times, 'Times New Roman', serif;
|
||||
font-style: italic;
|
||||
margin: 1.6rem 0;
|
||||
padding-left: 1.6rem; }
|
||||
|
||||
figcaption {
|
||||
font-family: Georgia, Times, 'Times New Roman', serif; }
|
||||
|
||||
html {
|
||||
font-size: 62.5%; }
|
||||
|
||||
body {
|
||||
padding: 0; }
|
||||
|
||||
main, header, footer, article, section, aside, details, summary {
|
||||
display: block;
|
||||
height: auto;
|
||||
margin: 0 auto;
|
||||
width: 100%; }
|
||||
|
||||
main {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.6rem 1.6rem; }
|
||||
|
||||
footer {
|
||||
border-top: .1rem solid rgba(0, 0, 0, 0.2);
|
||||
clear: both;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
max-width: 100%;
|
||||
padding: 1rem 0;
|
||||
text-align: center; }
|
||||
|
||||
hr {
|
||||
border-top: .1rem solid rgba(0, 0, 0, 0.2);
|
||||
display: block;
|
||||
margin-bottom: 1.6rem;
|
||||
width: 100%; }
|
||||
|
||||
img {
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
vertical-align: baseline; }
|
||||
|
||||
@media screen and (max-width: 40rem) {
|
||||
article, section, aside {
|
||||
clear: both;
|
||||
display: block;
|
||||
max-width: 100%; }
|
||||
img {
|
||||
margin-right: 1.6rem; } }
|
||||
|
||||
input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="date"], input[type="month"], input[type="time"], input[type="datetime"], input[type="datetime-local"], input[type="week"], input[type="number"], input[type="search"], input[type="tel"], input[type="color"], select {
|
||||
border: .1rem solid #ccc;
|
||||
border-radius: 0;
|
||||
display: inline-block;
|
||||
padding: 0.8rem;
|
||||
vertical-align: middle; }
|
||||
|
||||
input:not([type]) {
|
||||
-webkit-appearance: none;
|
||||
background-clip: padding-box;
|
||||
background-color: #fff;
|
||||
border: .1rem solid #ccc;
|
||||
border-radius: 0;
|
||||
color: #444;
|
||||
display: inline-block;
|
||||
padding: 0.8rem;
|
||||
text-align: left; }
|
||||
|
||||
input[type="color"] {
|
||||
padding: 0.8rem 1.6rem; }
|
||||
|
||||
input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus, input[type="url"]:focus, input[type="date"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="week"]:focus, input[type="number"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="color"]:focus, select:focus, textarea:focus {
|
||||
border-color: #b3d4fc; }
|
||||
|
||||
input:not([type]):focus {
|
||||
border-color: #b3d4fc; }
|
||||
|
||||
input[type="radio"], input[type="checkbox"] {
|
||||
vertical-align: middle; }
|
||||
|
||||
input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus {
|
||||
outline: .1rem solid thin #444; }
|
||||
|
||||
input[type="text"][disabled], input[type="password"][disabled], input[type="email"][disabled], input[type="url"][disabled], input[type="date"][disabled], input[type="month"][disabled], input[type="time"][disabled], input[type="datetime"][disabled], input[type="datetime-local"][disabled], input[type="week"][disabled], input[type="number"][disabled], input[type="search"][disabled], input[type="tel"][disabled], input[type="color"][disabled], select[disabled], textarea[disabled] {
|
||||
background-color: #efefef;
|
||||
color: #777;
|
||||
cursor: not-allowed; }
|
||||
|
||||
input:not([type])[disabled] {
|
||||
background-color: #efefef;
|
||||
color: #777;
|
||||
cursor: not-allowed; }
|
||||
|
||||
input[readonly], select[readonly], textarea[readonly] {
|
||||
background-color: #efefef;
|
||||
border-color: #ccc;
|
||||
color: #777; }
|
||||
|
||||
input:focus:invalid, textarea:focus:invalid, select:focus:invalid {
|
||||
border-color: #e9322d;
|
||||
color: #b94a48; }
|
||||
|
||||
input[type="file"]:focus:invalid:focus, input[type="radio"]:focus:invalid:focus, input[type="checkbox"]:focus:invalid:focus {
|
||||
outline-color: #ff4136; }
|
||||
|
||||
select {
|
||||
background-color: #fff;
|
||||
border: .1rem solid #ccc; }
|
||||
|
||||
select[multiple] {
|
||||
height: auto; }
|
||||
|
||||
label {
|
||||
line-height: 2; }
|
||||
|
||||
fieldset {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0.8rem 0; }
|
||||
|
||||
legend {
|
||||
border-bottom: .1rem solid #ccc;
|
||||
color: #444;
|
||||
display: block;
|
||||
margin-bottom: 0.8rem;
|
||||
padding: 0.8rem 0;
|
||||
width: 100%; }
|
||||
|
||||
textarea {
|
||||
border: .1rem solid #ccc;
|
||||
border-radius: 0;
|
||||
display: block;
|
||||
margin-bottom: 0.8rem;
|
||||
padding: 0.8rem;
|
||||
vertical-align: middle; }
|
||||
|
||||
input[type=submit], button {
|
||||
background-color: transparent;
|
||||
border: .2rem solid #444;
|
||||
border-radius: 0;
|
||||
color: #444;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
margin-bottom: 0.8rem;
|
||||
margin-right: 0.4rem;
|
||||
padding: 0.8rem 1.6rem;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
-webkit-transition: .25s ease;
|
||||
transition: .25s ease;
|
||||
-webkit-user-drag: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
vertical-align: baseline; }
|
||||
input[type=submit] a, button a {
|
||||
color: #444; }
|
||||
|
||||
input[type=submit]::-moz-focus-inner, button::-moz-focus-inner {
|
||||
padding: 0; }
|
||||
|
||||
input[type=submit]:hover, button:hover {
|
||||
background: #444;
|
||||
border-color: #444;
|
||||
color: #fff; }
|
||||
input[type=submit]:hover a, button:hover a {
|
||||
color: #fff; }
|
||||
|
||||
input[type=submit]:active, button:active {
|
||||
background: #6a6a6a;
|
||||
border-color: #6a6a6a;
|
||||
color: #fff; }
|
||||
input[type=submit]:active a, button:active a {
|
||||
color: #fff; }
|
||||
|
||||
input[type=submit]:disabled, button:disabled {
|
||||
box-shadow: none;
|
||||
cursor: not-allowed;
|
||||
opacity: .40; }
|
||||
|
||||
nav ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-top: 1.6rem;
|
||||
text-align: center; }
|
||||
nav ul li {
|
||||
display: inline; }
|
||||
nav a {
|
||||
border-bottom: .2rem solid transparent;
|
||||
color: #444;
|
||||
padding: 0.8rem 1.6rem;
|
||||
text-decoration: none;
|
||||
-webkit-transition: .25s ease;
|
||||
transition: .25s ease; }
|
||||
nav a:hover, nav li.selected a {
|
||||
border-color: rgba(0, 0, 0, 0.2); }
|
||||
nav a:active {
|
||||
border-color: rgba(0, 0, 0, 0.56); }
|
||||
|
||||
table {
|
||||
margin-bottom: 1.6rem; }
|
||||
|
||||
caption {
|
||||
padding: 0.8rem 0; }
|
||||
|
||||
thead th {
|
||||
background: #efefef;
|
||||
color: #444; }
|
||||
|
||||
tr {
|
||||
background: #fff;
|
||||
margin-bottom: 0.8rem; }
|
||||
|
||||
th, td {
|
||||
border: .1rem solid #ccc;
|
||||
padding: 0.8rem 1.6rem;
|
||||
text-align: center;
|
||||
vertical-align: inherit; }
|
||||
|
||||
tfoot tr {
|
||||
background: none; }
|
||||
|
||||
tfoot td {
|
||||
color: #efefef;
|
||||
font-size: 0.8rem;
|
||||
font-style: italic;
|
||||
padding: 1.6rem 0.4rem; }
|
Loading…
Reference in New Issue
Block a user