├── .nvmrc ├── .eslintignore ├── docs ├── favicon.ico ├── css │ ├── images │ │ ├── overlay.png │ │ ├── pattern-size2.svg │ │ ├── pattern-size1.svg │ │ └── pattern-size3.svg │ └── template.css ├── images │ └── screenshot.jpg └── index.html ├── bin ├── .eslintrc ├── run.js └── build.js ├── chrome-extension ├── images │ ├── airplay16.png │ ├── airplay24.png │ ├── airplay32.png │ ├── airplay64.png │ └── airplay128.png ├── .eslintrc ├── manifest.json ├── popup.html └── src │ ├── background.js │ └── popup.js ├── .eslintrc ├── LICENSE ├── .gitignore ├── package.json ├── webpack.config.js ├── README.md └── lib ├── utils.js ├── request.js ├── verify.js ├── client.js └── pair.js /.nvmrc: -------------------------------------------------------------------------------- 1 | 10.16 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | chrome-extension/dist 2 | build 3 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldiqual/chrome-airplay/HEAD/docs/favicon.ico -------------------------------------------------------------------------------- /bin/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true, 4 | "browser": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /docs/css/images/overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldiqual/chrome-airplay/HEAD/docs/css/images/overlay.png -------------------------------------------------------------------------------- /docs/images/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldiqual/chrome-airplay/HEAD/docs/images/screenshot.jpg -------------------------------------------------------------------------------- /chrome-extension/images/airplay16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldiqual/chrome-airplay/HEAD/chrome-extension/images/airplay16.png -------------------------------------------------------------------------------- /chrome-extension/images/airplay24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldiqual/chrome-airplay/HEAD/chrome-extension/images/airplay24.png -------------------------------------------------------------------------------- /chrome-extension/images/airplay32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldiqual/chrome-airplay/HEAD/chrome-extension/images/airplay32.png -------------------------------------------------------------------------------- /chrome-extension/images/airplay64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldiqual/chrome-airplay/HEAD/chrome-extension/images/airplay64.png -------------------------------------------------------------------------------- /chrome-extension/images/airplay128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldiqual/chrome-airplay/HEAD/chrome-extension/images/airplay128.png -------------------------------------------------------------------------------- /chrome-extension/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | }, 5 | "globals": { 6 | "chrome": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@scoop/eslint-config-scoop", 3 | "parserOptions": { 4 | "ecmaVersion": 2018 5 | }, 6 | "env": { 7 | "browser": false, 8 | "node": false, 9 | "shared-node-browser": true 10 | }, 11 | "globals": { 12 | "require": true, 13 | "module": true, 14 | "Buffer": true, 15 | }, 16 | "rules": { 17 | "no-implicit-globals": "off" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs/css/images/pattern-size2.svg: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/css/images/pattern-size1.svg: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/css/images/pattern-size3.svg: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /chrome-extension/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Chrome Airplay", 3 | "version": "0.1.3", 4 | "description": "Play videos from Chrome to your Apple TV", 5 | "manifest_version": 2, 6 | "icons": { 7 | "16": "images/airplay16.png", 8 | "32": "images/airplay32.png", 9 | "48": "images/airplay64.png", 10 | "128": "images/airplay128.png" 11 | }, 12 | "permissions": [ 13 | "tabs", 14 | "declarativeContent", 15 | "http://*:7000/", 16 | "https://www.youtube.com/" 17 | ], 18 | "background": { 19 | "scripts": ["dist/background.js"], 20 | "persistent": true 21 | }, 22 | "page_action": { 23 | "default_popup": "popup.html", 24 | "default_icon": { 25 | "16": "images/airplay16.png", 26 | "32": "images/airplay32.png", 27 | "48": "images/airplay64.png", 28 | "128": "images/airplay128.png" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018 Lois Di Qual 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | chrome-extension/dist 2 | build/ 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | *.pid.lock 16 | 17 | # Directory for instrumented libs generated by jscoverage/JSCover 18 | lib-cov 19 | 20 | # Coverage directory used by tools like istanbul 21 | coverage 22 | 23 | # nyc test coverage 24 | .nyc_output 25 | 26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 27 | .grunt 28 | 29 | # Bower dependency directory (https://bower.io/) 30 | bower_components 31 | 32 | # node-waf configuration 33 | .lock-wscript 34 | 35 | # Compiled binary addons (https://nodejs.org/api/addons.html) 36 | build/Release 37 | 38 | # Dependency directories 39 | node_modules/ 40 | jspm_packages/ 41 | 42 | # TypeScript v1 declaration files 43 | typings/ 44 | 45 | # Optional npm cache directory 46 | .npm 47 | 48 | # Optional eslint cache 49 | .eslintcache 50 | 51 | # Optional REPL history 52 | .node_repl_history 53 | 54 | # Output of 'npm pack' 55 | *.tgz 56 | 57 | # Yarn Integrity file 58 | .yarn-integrity 59 | 60 | # dotenv environment variables file 61 | .env 62 | 63 | # next.js build output 64 | .next 65 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "lint": "eslint .", 4 | "watch:js:dev": "webpack --watch --mode=development", 5 | "watch:js:prod": "webpack --watch --mode=production", 6 | "build:chrome-extension:prod": "node bin/build.js" 7 | }, 8 | "dependencies": { 9 | "bluebird": "^3.5.1", 10 | "bootstrap": "^4.3.1", 11 | "bplist-creator": "0.0.7", 12 | "bplist-parser": "^0.1.1", 13 | "buffer": "^5.1.0", 14 | "errio": "^1.2.2", 15 | "fast-srp-hap": "^1.0.1", 16 | "inquirer": "^6.5.1", 17 | "joi": "^13.4.0", 18 | "jquery": "^3.4.1", 19 | "lodash": "^4.17.15", 20 | "node-fetch": "^2.1.2", 21 | "p-retry": "^2.0.0", 22 | "plist": "^3.0.1", 23 | "popper.js": "^1.14.3", 24 | "tweetnacl": "^1.0.0", 25 | "ytdl-core": "^0.20.4" 26 | }, 27 | "devDependencies": { 28 | "@scoop/eslint-config-scoop": "^5.0.0", 29 | "acorn": "^7.0.0", 30 | "archiver": "^2.1.1", 31 | "css-loader": "^3.2.0", 32 | "eslint": "^5.16.0", 33 | "eslint-plugin-dependencies": "^2.4.0", 34 | "eslint-plugin-implicit-dependencies": "^1.0.4", 35 | "fs-extra": "^6.0.1", 36 | "style-loader": "^0.21.0", 37 | "uglifyjs-webpack-plugin": "^2.2.0", 38 | "webpack": "^4.12.0", 39 | "webpack-cli": "^3.0.3" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | 'use strict' 4 | 5 | const path = require('path') 6 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin') 7 | 8 | module.exports = { 9 | entry: { 10 | background: './chrome-extension/src/background.js', 11 | popup: './chrome-extension/src/popup.js', 12 | }, 13 | output: { 14 | filename: '[name].js', 15 | path: path.resolve(__dirname, 'chrome-extension/dist') 16 | }, 17 | node: { 18 | fs: 'empty' 19 | }, 20 | devtool: 'cheap-source-map', 21 | module: { 22 | rules: [{ 23 | test: /\.css$/, 24 | use: [ 'style-loader', 'css-loader' ] 25 | }] 26 | }, 27 | optimization: { 28 | minimizer: [ 29 | new UglifyJsPlugin({ 30 | uglifyOptions: { 31 | mangle: { 32 | // To avoid mangling error in `fast-srp-hap` 33 | keep_fnames: true // eslint-disable-line camelcase 34 | }, 35 | compress: { 36 | // To avoid "assignment to const" error due to bad compression 37 | unused: false 38 | } 39 | } 40 | }) 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /bin/run.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | 'use strict' 4 | 5 | const Promise = require('bluebird') 6 | const nacl = require('tweetnacl') 7 | const inquirer = require('inquirer') 8 | 9 | const Client = require('../lib/client') 10 | 11 | async function promptForPin() { 12 | const { pin } = await inquirer.prompt({ 13 | type: 'input', 14 | name: 'pin', 15 | message: 'Enter the PIN showing on your Apple TV' 16 | }) 17 | return pin 18 | } 19 | 20 | async function run() { 21 | 22 | const ipAddress = '192.168.86.30' 23 | const user = 'chrome-airplay' 24 | const keyPair = nacl.sign.keyPair() 25 | const clientPrivateKey = Buffer.from(keyPair.secretKey.slice(0, 32)) 26 | const clientPublicKey = Buffer.from(keyPair.publicKey) 27 | 28 | const airplay = new Client({ ipAddress, user, clientPrivateKey, clientPublicKey }) 29 | 30 | await airplay.startPairing() 31 | 32 | const pin = await promptForPin() 33 | await airplay.enterPin({ pin }) 34 | 35 | await airplay.verify() 36 | 37 | const videoUrl = 'https://media.w3.org/2010/05/sintel/trailer.mp4' 38 | await airplay.play({ videoUrl }) 39 | 40 | await Promise.delay(10000) 41 | } 42 | 43 | run({ promptForPin }).catch(err => { 44 | console.error(err) 45 | process.exit(1) 46 | }) 47 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Chrome Airplay 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 26 | 27 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Chrome Airplay 2 | ============== 3 | 4 | Play videos from Chrome to your Apple TV. 5 | 6 | ![](docs/images/screenshot.jpg) 7 | 8 | Install 9 | ------- 10 | 11 | Install from the Chrome Web Store: 12 | 13 | Supported websites 14 | ------------------ 15 | 16 | - Youtube 17 | 18 | Contribute 19 | ---------- 20 | 21 | ### Clone 22 | 23 | ``` 24 | $ git clone git@github.com:ldiqual/chrome-airplay.git 25 | $ npm install 26 | ``` 27 | 28 | File structure: 29 | 30 | - Chrome extension code is in `chrome-extension/` 31 | - Lib code is in `lib/` 32 | 33 | ### Build/watch JS files 34 | 35 | Watch changes with webpack: 36 | 37 | ``` 38 | $ npm run watch:js:dev 39 | ``` 40 | 41 | ### Load extension in Chrome 42 | 43 | Go to , click `Load unpacked`, and select `chrome-extension/`. 44 | 45 | ### Lint 46 | 47 | Lint the code with: 48 | 49 | ``` 50 | $ npm run lint 51 | ``` 52 | 53 | ### Build for production 54 | 55 | ``` 56 | $ npm run build:chrome-extension:prod 57 | ``` 58 | 59 | This will output to `build/build.zip`. 60 | 61 | Credits 62 | ------- 63 | 64 | - Airplay authentication: 65 | - Airplay video endpoints: 66 | - atv-client: 67 | - Airplay icon: 68 | - Documentation template: 69 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const _ = require('lodash') 4 | 5 | function assertIsBuffer(buffer, description, params) { 6 | if (!Buffer.isBuffer(buffer)) { 7 | throw new Error(`Property ${description} is not a buffer`) 8 | } 9 | 10 | const minLength = params.minLength || 0 11 | if (buffer.length < minLength) { 12 | throw new Error(`Buffer ${description} has length ${buffer.length} (should be at least ${minLength})`) 13 | } 14 | 15 | params = params || {} 16 | if (params.length && buffer.length !== params.length) { 17 | throw new Error(`Buffer ${description} has length ${buffer.length} (should be ${params.length})`) 18 | } 19 | } 20 | 21 | // params: { minLength, length } 22 | function assertIsString(str, description, params) { 23 | if (!_.isString(str)) { 24 | throw new Error(`Property ${description} is not a string`) 25 | } 26 | 27 | params = {} 28 | 29 | const minLength = params.minLength || 0 30 | if (str.length < minLength) { 31 | throw new Error(`String ${description} has length ${str.length} (should be at least ${minLength})`) 32 | } 33 | 34 | if (_.isNumber(params.length) && str.length !== params.length) { 35 | throw new Error(`String ${description} has length ${str.length} (should be ${params.length})`) 36 | } 37 | } 38 | 39 | function assertIsNotNull(param, description) { 40 | if (param === null) { 41 | throw new Error(`Property ${description} is null`) 42 | } 43 | } 44 | 45 | module.exports = { 46 | assertIsBuffer, 47 | assertIsString, 48 | assertIsNotNull 49 | } 50 | -------------------------------------------------------------------------------- /lib/request.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const bplistCreator = require('bplist-creator') 4 | const bplistParser = require('bplist-parser') 5 | const fetch = require('node-fetch') 6 | const http = require('http') 7 | const URL = typeof window !== 'undefined' ? window.URL : require('url').URL // eslint-disable-line no-undef 8 | const _ = require('lodash') 9 | 10 | const appleTvPort = 7000 11 | 12 | const agent = new http.Agent({ 13 | keepAlive: true, 14 | maxSockets: 1 15 | }) 16 | 17 | async function httpRequest({ host, method, path, qs, data, contentType }) { 18 | 19 | const dataBuffer = data ? (new Uint8Array(data)).buffer : null 20 | 21 | const requestUrl = new URL(`http://${host}:${appleTvPort}`) 22 | requestUrl.pathname = `/${path}` 23 | _.forEach(qs, (value, key) => { 24 | requestUrl.searchParams.set(key, value) 25 | }) 26 | 27 | const response = await fetch(requestUrl.toString(), { 28 | method: method, 29 | headers: { 30 | 'Content-Type': contentType, 31 | 'User-Agent': 'AirPlay/320.20', 32 | 'Connection': 'keep-alive' 33 | }, 34 | body: dataBuffer, 35 | encoding: null, 36 | agent: agent 37 | }) 38 | 39 | if (!response.ok) { 40 | const error = new Error(`Airplay request error: ${response.status}`) 41 | error.response = response 42 | throw error 43 | } 44 | 45 | const resArrayBuffer = await response.arrayBuffer() 46 | 47 | return Buffer.from(resArrayBuffer) 48 | } 49 | 50 | async function plistRequest({ host, method, path, qs, params }) { 51 | 52 | const data = params ? bplistCreator(params) : null 53 | 54 | const response = await httpRequest({ 55 | host: host, 56 | method: method, 57 | path: path, 58 | data: data, 59 | qs: qs, 60 | contentType: 'application/x-apple-binary-plist' 61 | }) 62 | 63 | if (response.length === 0) { 64 | return {} 65 | } 66 | 67 | const result = bplistParser.parseBuffer(response) 68 | 69 | return result 70 | } 71 | 72 | module.exports = { 73 | httpRequest, 74 | plistRequest, 75 | } 76 | -------------------------------------------------------------------------------- /bin/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const Promise = require('bluebird') 4 | const fs = require('fs-extra') 5 | const path = require('path') 6 | const webpack = require('webpack') 7 | const _ = require('lodash') 8 | const archiver = require('archiver') 9 | 10 | const webpackConfig = require('../webpack.config.js') 11 | 12 | async function run() { 13 | const outputDir = path.join(__dirname, '..', 'build', 'chrome-extension') 14 | 15 | // Create `build/chrome-extension/` directory 16 | if (!await fs.pathExists(outputDir)) { 17 | await fs.mkdirp(outputDir) 18 | } 19 | 20 | const sourceFilenames = [ 21 | 'images', 22 | 'manifest.json', 23 | 'popup.html', 24 | ] 25 | 26 | // Copy specific files from `chrome-extension/` to `build/chrome-extension/` 27 | await Promise.each(sourceFilenames, async filename => { 28 | const src = path.join(__dirname, '..', 'chrome-extension', filename) 29 | const dst = path.join(outputDir, filename) 30 | console.log(`${src} → ${dst}`) 31 | await fs.copy(src, dst) 32 | }) 33 | 34 | // Create webpack configuration for production mode 35 | // JS files will be compiled to `build/chrome-extension/dist/` 36 | const webpackOutputDir = path.resolve(path.join(outputDir, 'dist')) 37 | const prodWebpackConfig = _.defaultsDeep({ 38 | mode: 'production', 39 | output: { 40 | filename: '[name].js', 41 | path: webpackOutputDir 42 | } 43 | }, webpackConfig) 44 | 45 | // Create webpack instance 46 | const compiler = webpack(prodWebpackConfig) 47 | const run = Promise.promisify(compiler.run, { context: compiler }) 48 | 49 | // Run webpack 50 | console.log(`Webpack destination: ${webpackOutputDir}`) 51 | await run() 52 | 53 | // Zip to `build.zip` 54 | const zipPath = path.join(__dirname, '..', 'build', 'build.zip') 55 | console.log(`Zipping to ${zipPath}`) 56 | await new Promise((fulfill, reject) => { 57 | 58 | const archive = archiver('zip') 59 | const outputStream = fs.createWriteStream(zipPath) 60 | archive.pipe(outputStream) 61 | 62 | archive.on('warning', err => console.warn(err)) 63 | archive.on('error', err => reject(err)) 64 | archive.on('end', () => fulfill()) 65 | 66 | archive.directory(outputDir, false) 67 | archive.finalize() 68 | }) 69 | } 70 | 71 | run().catch(err => { 72 | console.error(err.stack) 73 | process.exit(1) 74 | }) 75 | -------------------------------------------------------------------------------- /lib/verify.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const crypto = require('crypto') 4 | const nacl = require('tweetnacl') 5 | 6 | const request = require('./request') 7 | const utils = require('./utils') 8 | 9 | class Verifier { 10 | 11 | constructor({ ipAddress, clientPrivateKey, clientPublicKey }) { 12 | 13 | // Params 14 | utils.assertIsString(ipAddress, 'ipAddress', { minLength: 8 }) 15 | utils.assertIsBuffer(clientPrivateKey, 'clientPrivateKey', { length: 32 }) 16 | utils.assertIsBuffer(clientPublicKey, 'clientPublicKey', { length: 32 }) 17 | 18 | this.ipAddress = ipAddress 19 | this.clientPrivateKey = clientPrivateKey 20 | this.clientPublicKey = clientPublicKey 21 | 22 | this.clientVerifyPrivate = null 23 | this.clientVerifyPublic = null 24 | this.atvVerifyPublic = null 25 | this.atvVerifyTail = null 26 | } 27 | 28 | async step1() { 29 | 30 | const verifyKeyPair = nacl.box.keyPair.fromSecretKey(this.clientPrivateKey) 31 | const verifyPrivate = Buffer.from(verifyKeyPair.secretKey) 32 | const verifyPublic = Buffer.from(verifyKeyPair.publicKey) 33 | 34 | const data = Buffer.concat([Buffer.from([1, 0, 0, 0]), verifyPublic, this.clientPublicKey]) 35 | 36 | const response = await request.httpRequest({ 37 | host: this.ipAddress, 38 | method: 'POST', 39 | path: 'pair-verify', 40 | contentType: 'application/octet-stream', 41 | data: data 42 | }) 43 | 44 | const pk = response.slice(0, 32) 45 | const tail = response.slice(32) 46 | 47 | utils.assertIsBuffer(verifyPrivate, 'verifyPrivate', { length: 32 }) 48 | utils.assertIsBuffer(verifyPublic, 'verifyPublic', { length: 32 }) 49 | utils.assertIsBuffer(pk, 'pk', { length: 32 }) 50 | utils.assertIsBuffer(tail, 'tail', { minLength: 8 }) 51 | 52 | this.clientVerifyPrivate = verifyPrivate 53 | this.clientVerifyPublic = verifyPublic 54 | this.atvVerifyPublic = pk 55 | this.atvVerifyTail = tail 56 | } 57 | 58 | async step2() { 59 | 60 | // State 61 | utils.assertIsBuffer(this.clientPrivateKey, 'clientPrivateKey', { length: 32 }) 62 | utils.assertIsBuffer(this.clientVerifyPrivate, 'clientVerifyPrivate', { length: 32 }) 63 | utils.assertIsBuffer(this.clientVerifyPublic, 'clientVerifyPublic', { length: 32 }) 64 | utils.assertIsBuffer(this.atvVerifyPublic, 'atvVerifyPublic', { length: 32 }) 65 | utils.assertIsBuffer(this.atvVerifyTail, 'atvVerifyTail', { minLength: 8 }) 66 | 67 | const shared = Buffer.from(nacl.scalarMult(this.clientVerifyPrivate, this.atvVerifyPublic)) 68 | 69 | const aesKey = crypto.createHash('sha512').update('Pair-Verify-AES-Key').update(shared).digest().slice(0, 16) 70 | const aesIV = crypto.createHash('sha512').update('Pair-Verify-AES-IV').update(shared).digest().slice(0, 16) 71 | 72 | const keyPair = nacl.sign.keyPair.fromSeed(this.clientPrivateKey) 73 | const key = Buffer.from(keyPair.secretKey) 74 | const signed = nacl.sign(Buffer.concat([this.clientVerifyPublic, this.atvVerifyPublic]), key) 75 | const signedStripped = Buffer.from(signed).slice(0, 64) 76 | 77 | const cipher = crypto.createCipheriv('aes-128-ctr', aesKey, aesIV) 78 | cipher.update(this.atvVerifyTail) 79 | const signature = cipher.update(signedStripped) 80 | cipher.final() 81 | 82 | const data = Buffer.concat([Buffer.from([0, 0, 0, 0]), signature]) 83 | 84 | await request.httpRequest({ 85 | host: this.ipAddress, 86 | method: 'POST', 87 | path: 'pair-verify', 88 | contentType: 'application/octet-stream', 89 | data: data 90 | }) 91 | } 92 | } 93 | module.exports = Verifier 94 | -------------------------------------------------------------------------------- /chrome-extension/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 51 | 52 | 53 | 54 |
55 | 56 | 57 |
58 | 59 |

Enter the IP address of your Apple TV

60 |

61 | Go to SettingsNetwork and copy the IP Address value here. 62 |

63 | 64 |
65 | 66 |
Invalid IP address, please try again
67 |
68 | 69 | 73 |
74 | 75 | 76 |
77 |
78 | 79 | 80 |
Invalid PIN, please try again
81 | Enter the PIN showing on your Apple TV 82 |
83 | 87 |
88 | 89 | 90 |
91 | 92 |

Select a video format

93 | 94 | 95 | 96 |
97 | 98 |
99 |
100 | 101 | 102 |
103 |
104 |
105 | 106 | 107 |
108 |
109 | 110 |
111 |
112 |
113 | 114 | Unpair 115 | 116 |
117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /lib/client.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const Pairing = require('./pair') 4 | const Verifier = require('./verify') 5 | const request = require('./request') 6 | const plist = require('plist') 7 | 8 | class Client { 9 | 10 | constructor({ ipAddress, user, clientPrivateKey, clientPublicKey }) { 11 | 12 | this.ipAddress = ipAddress 13 | this.user = user 14 | this.clientPrivateKey = clientPrivateKey 15 | this.clientPublicKey = clientPublicKey 16 | 17 | this.pairing = null 18 | } 19 | 20 | async startPairing() { 21 | 22 | this.pairing = new Pairing({ 23 | ipAddress: this.ipAddress, 24 | user: this.user, 25 | clientPrivateKey: this.clientPrivateKey, 26 | clientPublicKey: this.clientPublicKey 27 | }) 28 | 29 | console.log('Start pairing') 30 | await this.pairing.start() 31 | } 32 | 33 | async enterPin({ pin }) { 34 | 35 | console.log('Pair 1') 36 | await this.pairing.step1({ user: this.user }) 37 | 38 | console.log('Pair 2') 39 | await this.pairing.step2({ pin }) 40 | 41 | console.log('Pair 3') 42 | await this.pairing.step3() 43 | } 44 | 45 | async verify() { 46 | const verifier = new Verifier({ 47 | ipAddress: this.ipAddress, 48 | clientPrivateKey: this.clientPrivateKey, 49 | clientPublicKey: this.clientPublicKey 50 | }) 51 | 52 | console.log('Verify 1') 53 | await verifier.step1() 54 | 55 | console.log('Verify 2') 56 | await verifier.step2() 57 | } 58 | 59 | async play({ videoUrl }) { 60 | console.log('Play', videoUrl) 61 | await request.plistRequest({ 62 | host: this.ipAddress, 63 | method: 'POST', 64 | path: 'play', 65 | params: { 66 | 'Content-Location': videoUrl, 67 | 'Start-Position': 0 68 | } 69 | }) 70 | } 71 | 72 | async seek(position) { 73 | console.log('Seek', position) 74 | await request.plistRequest({ 75 | host: this.ipAddress, 76 | method: 'POST', 77 | path: 'scrub', 78 | qs: { 79 | position: position 80 | } 81 | }) 82 | } 83 | 84 | async pause() { 85 | console.log('Pause') 86 | await request.plistRequest({ 87 | host: this.ipAddress, 88 | method: 'POST', 89 | path: 'rate', 90 | qs: { 91 | value: 0 92 | } 93 | }) 94 | } 95 | 96 | async resume() { 97 | console.log('Resume') 98 | await request.plistRequest({ 99 | host: this.ipAddress, 100 | method: 'POST', 101 | path: 'rate', 102 | qs: { 103 | value: 1 104 | } 105 | }) 106 | } 107 | 108 | async stop() { 109 | console.log('Stop') 110 | await request.plistRequest({ 111 | host: this.ipAddress, 112 | method: 'POST', 113 | path: 'stop' 114 | }) 115 | } 116 | 117 | async getPlaybackInfo() { 118 | console.log('Playback info') 119 | 120 | let response 121 | 122 | try { 123 | response = await request.httpRequest({ 124 | host: this.ipAddress, 125 | method: 'GET', 126 | path: 'playback-info' 127 | }) 128 | } catch (err) { 129 | return { 130 | duration: 1, 131 | position: 0, 132 | isPlaying: false, 133 | } 134 | } 135 | 136 | const xml = response.toString('utf8') 137 | const json = plist.parse(xml) 138 | 139 | return { 140 | duration: json.duration, 141 | position: json.position, 142 | isPlaying: json.rate === 1, 143 | } 144 | } 145 | } 146 | 147 | module.exports = Client 148 | -------------------------------------------------------------------------------- /lib/pair.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const crypto = require('crypto') 4 | const srp = require('fast-srp-hap') 5 | 6 | const request = require('./request') 7 | const utils = require('./utils') 8 | 9 | class InvalidPinError extends Error {} 10 | 11 | class Pairing { 12 | 13 | constructor({ ipAddress, user, clientPrivateKey, clientPublicKey }) { 14 | 15 | utils.assertIsString(ipAddress, 'ipAddress', { minLength: 8 }) 16 | utils.assertIsString(user, 'user', { minLength: 4 }) 17 | utils.assertIsBuffer(clientPrivateKey, 'clientPrivateKey', { length: 32 }) 18 | utils.assertIsBuffer(clientPublicKey, 'clientPublicKey', { length: 32 }) 19 | 20 | this.ipAddress = ipAddress 21 | this.user = user 22 | this.clientPrivateKey = clientPrivateKey 23 | this.clientPublicKey = clientPublicKey 24 | 25 | this.srpClient = null 26 | this.atvPublicKey = null 27 | this.atvSalt = null 28 | } 29 | 30 | async start() { 31 | await request.plistRequest({ 32 | host: this.ipAddress, 33 | method: 'POST', 34 | path: 'pair-pin-start', 35 | params: {} 36 | }) 37 | } 38 | 39 | async step1() { 40 | 41 | const result = await request.plistRequest({ 42 | host: this.ipAddress, 43 | method: 'POST', 44 | path: 'pair-setup-pin', 45 | params: { 46 | user: this.user, 47 | method: 'pin' 48 | } 49 | }) 50 | 51 | const { pk, salt } = result[0] 52 | utils.assertIsBuffer(pk, 'pk', { length: 256 }) 53 | utils.assertIsBuffer(salt, 'salt', { length: 16 }) 54 | 55 | this.atvPublicKey = pk 56 | this.atvSalt = salt 57 | } 58 | 59 | async step2({ pin }) { 60 | 61 | // Params 62 | utils.assertIsString(pin, 'pin', { length: 4 }) 63 | 64 | // State 65 | utils.assertIsBuffer(this.atvPublicKey, 'atvPublicKey', { length: 256 }) 66 | utils.assertIsBuffer(this.atvSalt, 'atvSalt', { length: 16 }) 67 | 68 | this.srpClient = getSrpClient({ 69 | user: this.user, 70 | pin, 71 | clientPrivateKey: this.clientPrivateKey, 72 | atvPublicKey: this.atvPublicKey, 73 | atvSalt: this.atvSalt 74 | }) 75 | 76 | await request.plistRequest({ 77 | host: this.ipAddress, 78 | method: 'POST', 79 | path: 'pair-setup-pin', 80 | params: { 81 | pk: this.srpClient.computeA(), 82 | proof: this.srpClient.computeM1() 83 | } 84 | }).catch(err => { 85 | if (err.response && err.response.status) { 86 | throw new InvalidPinError('Invalid pin') 87 | } 88 | throw err 89 | }) 90 | } 91 | 92 | async step3() { 93 | 94 | // State 95 | utils.assertIsNotNull(this.srpClient, 'srpClient') 96 | utils.assertIsBuffer(this.clientPublicKey, 'clientPublicKey', { length: 32 }) 97 | 98 | const sharedSecretHash = this.srpClient.computeK() 99 | const aesKey = crypto.createHash('sha512').update('Pair-Setup-AES-Key').update(sharedSecretHash).digest().slice(0, 16) 100 | const aesIV = crypto.createHash('sha512').update('Pair-Setup-AES-IV').update(sharedSecretHash).digest().slice(0, 16) 101 | aesIV[15]++ 102 | 103 | const cipher = crypto.createCipheriv('aes-128-gcm', aesKey, aesIV) 104 | const epk = cipher.update(this.clientPublicKey) 105 | cipher.final() 106 | const authTag = cipher.getAuthTag() 107 | 108 | await request.plistRequest({ 109 | host: this.ipAddress, 110 | method: 'POST', 111 | path: 'pair-setup-pin', 112 | params: { epk, authTag } 113 | }) 114 | } 115 | } 116 | 117 | Pairing.InvalidPinError = InvalidPinError 118 | 119 | function getSrpClient({ user, pin, clientPrivateKey, atvPublicKey, atvSalt }) { 120 | 121 | // Params 122 | utils.assertIsString(user, 'user', { minLength: 4 }) 123 | utils.assertIsString(pin, 'pin', { length: 4 }) 124 | utils.assertIsBuffer(clientPrivateKey, 'clientPrivateKey', { length: 32 }) 125 | utils.assertIsBuffer(atvPublicKey, 'atvPublicKey', { length: 256 }) 126 | utils.assertIsBuffer(atvSalt, 'atvSalt', { length: 16 }) 127 | 128 | const srpParams = srp.params[2048] 129 | srpParams.hash = 'sha1' 130 | 131 | const client = new srp.Client( 132 | srpParams, 133 | atvSalt, 134 | Buffer.from(user, 'utf8'), 135 | Buffer.from(pin, 'utf8'), 136 | clientPrivateKey 137 | ) 138 | client.setB(atvPublicKey) 139 | 140 | return client 141 | } 142 | 143 | module.exports = Pairing 144 | -------------------------------------------------------------------------------- /chrome-extension/src/background.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const Promise = require('bluebird') 4 | const nacl = require('tweetnacl') 5 | const Errio = require('errio') 6 | 7 | const Client = require('../../lib/client') 8 | const request = require('../../lib/request') 9 | 10 | chrome.runtime.onInstalled.addListener(function() { 11 | chrome.declarativeContent.onPageChanged.removeRules(undefined, function() { 12 | 13 | const rule = { 14 | conditions: [ 15 | new chrome.declarativeContent.PageStateMatcher({ 16 | pageUrl: { 17 | hostEquals: 'www.youtube.com', 18 | pathEquals: '/watch' 19 | } 20 | }) 21 | ], 22 | actions: [ new chrome.declarativeContent.ShowPageAction() ] 23 | } 24 | 25 | chrome.declarativeContent.onPageChanged.addRules([ rule ]) 26 | }) 27 | }) 28 | 29 | function createCredentials() { 30 | const user = 'chrome-airplay' 31 | const keyPair = nacl.sign.keyPair() 32 | const clientPrivateKey = Buffer.from(keyPair.secretKey.slice(0, 32)) 33 | const clientPublicKey = Buffer.from(keyPair.publicKey) 34 | return { user, clientPrivateKey, clientPublicKey } 35 | } 36 | 37 | function saveCredentials({ user, clientPrivateKey, clientPublicKey }) { 38 | const clientPrivateKeyBase64 = clientPrivateKey.toString('base64') 39 | const clientPublicKeyBase64 = clientPublicKey.toString('base64') 40 | const json = JSON.stringify({ 41 | user, 42 | clientPrivateKey: clientPrivateKeyBase64, 43 | clientPublicKey: clientPublicKeyBase64 44 | }) 45 | window.localStorage.setItem('credentials', json) 46 | } 47 | 48 | function removeCredentials() { 49 | window.localStorage.removeItem('credentials') 50 | } 51 | 52 | function getSavedCredentials() { 53 | 54 | const credentialsJSON = window.localStorage.getItem('credentials') 55 | if (!credentialsJSON) { 56 | return null 57 | } 58 | 59 | const credentials = JSON.parse(credentialsJSON) 60 | 61 | const { 62 | user, 63 | clientPrivateKey: clientPrivateKeyBase64, 64 | clientPublicKey: clientPublicKeyBase64 65 | } = credentials 66 | 67 | if (!user || !clientPrivateKeyBase64 || !clientPublicKeyBase64) { 68 | return null 69 | } 70 | 71 | const clientPrivateKey = Buffer.from(clientPrivateKeyBase64, 'base64') 72 | const clientPublicKey = Buffer.from(clientPublicKeyBase64, 'base64') 73 | 74 | return { user, clientPrivateKey, clientPublicKey } 75 | } 76 | 77 | function getNewAirplayInstance({ ipAddress }) { 78 | let credentials = getSavedCredentials() 79 | if (!credentials) { 80 | credentials = createCredentials() 81 | saveCredentials(credentials) 82 | } 83 | return new Client({ ipAddress, ...credentials }) 84 | } 85 | 86 | function getSavedIpAddress() { 87 | return window.localStorage.getItem('ipAddress') || null 88 | } 89 | 90 | function saveIpAddress(ipAddress) { 91 | return window.localStorage.setItem('ipAddress', ipAddress) 92 | } 93 | 94 | function removeIpAddress() { 95 | window.localStorage.removeItem('ipAddress') 96 | } 97 | 98 | let keepAliveInterval = null 99 | function startKeepAliveInterval() { 100 | if (keepAliveInterval) { 101 | return 102 | } 103 | keepAliveInterval = window.setInterval(() => { 104 | const ipAddress = getSavedIpAddress() 105 | if (!ipAddress) { 106 | return 107 | } 108 | console.log('Get server info to maintain connection') 109 | testConnection({ ipAddress }).catch(err => { 110 | console.error("Couldn't get server info", err) 111 | }) 112 | }, 10000) 113 | } 114 | 115 | function stopKeepAliveInterval() { 116 | if (keepAliveInterval) { 117 | window.clearInterval(keepAliveInterval) 118 | } 119 | } 120 | 121 | let airplay = null 122 | const savedIpAddress = getSavedIpAddress() 123 | if (savedIpAddress !== null) { 124 | airplay = getNewAirplayInstance({ ipAddress: savedIpAddress }) 125 | } 126 | 127 | async function testConnection({ ipAddress }) { 128 | const getInfo = request.httpRequest({ 129 | host: ipAddress, 130 | method: 'GET', 131 | path: 'info' 132 | }) 133 | const timeoutError = new Error("Couldn't connect to this Apple TV, please try a different address") 134 | const timeout = Promise.delay(1000).then(() => Promise.reject(timeoutError)) 135 | await Promise.race([ getInfo, timeout ]) 136 | } 137 | 138 | const handlers = { 139 | 'pairing.hasIpAddress': async(req) => { 140 | const hasIpAddress = getSavedIpAddress() !== null 141 | return { hasIpAddress } 142 | }, 143 | 'pairing.setIpAddress': async(req) => { 144 | const ipAddress = req.ipAddress 145 | await testConnection({ ipAddress }) 146 | saveIpAddress(ipAddress) 147 | airplay = getNewAirplayInstance({ ipAddress }) 148 | return {} 149 | }, 150 | 'pairing.start': async(req) => { 151 | await airplay.startPairing() 152 | return {} 153 | }, 154 | 'pairing.enterPin': async(req) => { 155 | const pin = req.pin 156 | await airplay.enterPin({ pin }) 157 | return {} 158 | }, 159 | 'verify': async(req) => { 160 | const timeoutError = new Error("Couldn't connect to this Apple TV, please try a different address") 161 | const timeout = Promise.delay(1000).then(() => Promise.reject(timeoutError)) 162 | await Promise.race([ airplay.verify(), timeout ]) 163 | return {} 164 | }, 165 | 'playback.play': async(req) => { 166 | const { videoUrl } = req 167 | await airplay.play({ videoUrl }) 168 | startKeepAliveInterval() 169 | return {} 170 | }, 171 | 'playback.info': async(req) => { 172 | const playbackInfo = await airplay.getPlaybackInfo() 173 | return { playbackInfo } 174 | }, 175 | 'playback.seek': async(req) => { 176 | const { position } = req 177 | await airplay.seek(position) 178 | return {} 179 | }, 180 | 'playback.pause': async(req) => { 181 | await airplay.pause() 182 | return {} 183 | }, 184 | 'playback.resume': async(req) => { 185 | await airplay.resume() 186 | return {} 187 | }, 188 | 'playback.stop': async(req) => { 189 | await airplay.stop() 190 | stopKeepAliveInterval() 191 | return {} 192 | }, 193 | 'unpair': async(req) => { 194 | await airplay.stop() 195 | stopKeepAliveInterval() 196 | removeIpAddress() 197 | removeCredentials() 198 | airplay = null 199 | return {} 200 | } 201 | } 202 | 203 | chrome.runtime.onMessage.addListener((req, sender, sendResponse) => { 204 | 205 | const action = req.action 206 | if (!action) { 207 | console.error('No action in message payload', req) 208 | return 209 | } 210 | 211 | const handler = handlers[req.action] 212 | if (!handler) { 213 | console.error(`No handler for action ${action}`, req) 214 | return 215 | } 216 | 217 | console.log(`Got message for action ${action}`, req) 218 | 219 | Promise.try(async() => { 220 | const response = await handler(req) 221 | console.log(`Response for ${action}`, response) 222 | sendResponse(response) 223 | }).catch(err => { 224 | console.error(`Error for ${action}`, err) 225 | sendResponse({ error: Errio.toObject(err) }) 226 | }) 227 | 228 | return true 229 | }) 230 | -------------------------------------------------------------------------------- /chrome-extension/src/popup.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const $ = require('jquery') 4 | const Promise = require('bluebird') 5 | const _ = require('lodash') 6 | const ytdl = require('ytdl-core') 7 | const Errio = require('errio') 8 | 9 | require('popper.js') 10 | require('bootstrap') 11 | require('bootstrap/dist/css/bootstrap.min.css') 12 | 13 | const Pairing = require('../../lib/pair') 14 | 15 | // Sections 16 | const pairForm = $('#airplay-pair-form') 17 | const pinForm = $('#airplay-pin-form') 18 | const formatSelector = $('#airplay-format-selector') 19 | const player = $('#airplay-player') 20 | 21 | const pairSubmitButton = $('#airplay-pair-submit') 22 | const unpairLink = $('#airplay-unpair') 23 | 24 | async function run() { 25 | 26 | unpairLink.click(ev => { 27 | Promise.try(async() => { 28 | await performBackgroundAction('unpair') 29 | window.close() 30 | }).catch(err => { 31 | console.log(err) 32 | }) 33 | }) 34 | 35 | try { 36 | const { hasIpAddress } = await performBackgroundAction('pairing.hasIpAddress') 37 | if (!hasIpAddress) { 38 | return showPairForm() 39 | } 40 | await performBackgroundAction('verify') 41 | afterVerify() 42 | } catch (err) { 43 | showPairForm() 44 | } 45 | } 46 | 47 | run().catch(err => { 48 | console.error(err) 49 | }) 50 | 51 | function setIsSubmitting(form, isSubmitting) { 52 | const spinner = $('.spinner', form) 53 | const submitButton = $('button[type=submit]') 54 | if (isSubmitting) { 55 | spinner.show() 56 | submitButton.prop('disabled', true) 57 | } else { 58 | spinner.hide() 59 | submitButton.prop('disabled', false) 60 | } 61 | } 62 | 63 | function setIsPaired() { 64 | unpairLink.show() 65 | } 66 | 67 | function afterVerify() { 68 | setIsPaired() 69 | Promise.try(async() => { 70 | const { playbackInfo } = await performBackgroundAction('playback.info') 71 | if (playbackInfo.isPlaying) { 72 | showPlayer() 73 | } else { 74 | showFormatSelector() 75 | } 76 | }).catch(err => { 77 | console.error(err) 78 | }) 79 | } 80 | 81 | function showPairForm() { 82 | 83 | const pairIpAddressInput = $('#airplay-server-ip-input') 84 | const pairFeedback = $('invalid-feedback', pairForm) 85 | 86 | // Show pair form 87 | pairForm.show() 88 | setIsSubmitting(pairForm, false) 89 | 90 | pairForm.submit(ev => { 91 | ev.preventDefault() 92 | 93 | pairIpAddressInput.removeClass('is-invalid') 94 | pairForm.removeClass('was-validated') 95 | 96 | // Pair 97 | const ipAddress = pairIpAddressInput.val() 98 | pairSubmitButton.prop('disabled', true) 99 | setIsSubmitting(pairForm, true) 100 | 101 | Promise.try(async() => { 102 | await performBackgroundAction('pairing.setIpAddress', { ipAddress: ipAddress }) 103 | await performBackgroundAction('pairing.start') 104 | pairForm.hide() 105 | showPinForm() 106 | }).catch(err => { 107 | 108 | console.error(err) 109 | 110 | pairFeedback.text(err.message) 111 | pairIpAddressInput.addClass('is-invalid') 112 | pairForm.addClass('was-validated') 113 | 114 | pairSubmitButton.prop('disabled', false) 115 | }).finally(() => { 116 | setIsSubmitting(pairForm, false) 117 | }) 118 | }) 119 | } 120 | 121 | function showPinForm() { 122 | 123 | const pinInput = $('#airplay-pin-input') 124 | 125 | // Pin 126 | pinForm.show() 127 | setIsSubmitting(pinForm, false) 128 | pinForm.removeClass('was-validated') 129 | 130 | const enterPin = async() => { 131 | 132 | const pin = await waitForPinSubmit() 133 | setIsSubmitting(pinForm, true) 134 | const promise = performBackgroundAction('pairing.enterPin', { pin }) 135 | 136 | return Promise.resolve(promise) 137 | .catch(Pairing.InvalidPinError, err => { 138 | pinInput.get(0).setCustomValidity('Invalid PIN, please try again') 139 | pinForm.addClass('was-validated') 140 | setIsSubmitting(pinForm, false) 141 | return enterPin() 142 | }) 143 | .catch(err => { 144 | pinInput.get(0).setCustomValidity(err.message) 145 | pinForm.addClass('was-validated') 146 | setIsSubmitting(pinForm, false) 147 | return enterPin() 148 | }) 149 | } 150 | 151 | Promise.try(async() => { 152 | await enterPin() 153 | await performBackgroundAction('verify') 154 | 155 | pinForm.hide() 156 | afterVerify() 157 | }).catch(err => { 158 | console.error(err) 159 | }) 160 | } 161 | 162 | async function getVideoFormats() { 163 | 164 | const currentTab = await getCurrentTab() 165 | const info = await ytdl.getInfo(currentTab.url, { debug: true }) 166 | const formatsFromLowToHigh = _.chain(info.formats) 167 | .filter(format => { 168 | return format.container === 'mp4' 169 | && format.encoding === 'H.264' 170 | && format.audioEncoding === 'aac' 171 | }) 172 | .sortBy(format => { 173 | const resolution = _.replace(format.resolution, 'p', '') 174 | return Number(resolution) 175 | }) 176 | .value() 177 | 178 | console.log(info) 179 | console.log(info.formats) 180 | console.log(formatsFromLowToHigh) 181 | 182 | return formatsFromLowToHigh 183 | } 184 | 185 | async function pauseVideoInActiveTab() { 186 | const currentTab = await getCurrentTab() 187 | chrome.tabs.executeScript(currentTab.id, { 188 | code: "document.querySelector('video').pause()" 189 | }) 190 | } 191 | 192 | function populateFormatSelector(videoFormats) { 193 | const formatList = $('#airplay-format-selector-list') 194 | formatList.html('') 195 | videoFormats.forEach(format => { 196 | const item = $(`${format.resolution}`) 197 | item.click(ev => { 198 | ev.preventDefault() 199 | console.log('Selected format', format) 200 | 201 | Promise.try(async() => { 202 | await performBackgroundAction('playback.play', { videoUrl: format.url }) 203 | await pauseVideoInActiveTab() 204 | formatSelector.hide() 205 | showPlayer() 206 | }).catch(err => { 207 | console.error(err) 208 | }) 209 | }) 210 | formatList.append(item) 211 | }) 212 | } 213 | 214 | function showFormatSelector() { 215 | 216 | formatSelector.show() 217 | 218 | const spinner = $('.spinner', formatSelector) 219 | spinner.show() 220 | 221 | Promise.try(async() => { 222 | const videoFormats = await getVideoFormats() 223 | spinner.hide() 224 | populateFormatSelector(videoFormats) 225 | }).catch(err => { 226 | console.log(err) 227 | }) 228 | } 229 | 230 | function showPlayer() { 231 | 232 | player.show() 233 | const playPauseButton = $('#airplay-player-playpause') 234 | const stopButton = $('#airplay-player-stop') 235 | const slider = $('#airplay-player-slider') 236 | 237 | const setIsPlaying = isPlaying => { 238 | if (isPlaying) { 239 | playPauseButton.removeClass('fa-play') 240 | playPauseButton.addClass('fa-pause') 241 | } else { 242 | playPauseButton.removeClass('fa-pause') 243 | playPauseButton.addClass('fa-play') 244 | } 245 | } 246 | setIsPlaying(true) 247 | 248 | let intervalId = null 249 | const startProgressUpdates = () => { 250 | intervalId = setInterval(() => { 251 | Promise.try(async() => { 252 | const { playbackInfo } = await performBackgroundAction('playback.info') 253 | slider.attr('max', Math.floor(playbackInfo.duration)) 254 | slider.val(Math.floor(playbackInfo.position)) 255 | }).catch(err => { 256 | console.log(err) 257 | }) 258 | }, 1000) 259 | } 260 | slider.val(0) 261 | startProgressUpdates() 262 | 263 | slider.change(ev => { 264 | Promise.try(async() => { 265 | const position = Number(slider.val()) 266 | await performBackgroundAction('playback.seek', { position: position }) 267 | }).catch(err => { 268 | console.log(err) 269 | }) 270 | }) 271 | 272 | playPauseButton.click(ev => { 273 | Promise.try(async() => { 274 | const { playbackInfo } = await performBackgroundAction('playback.info') 275 | if (playbackInfo.isPlaying) { 276 | await performBackgroundAction('playback.pause') 277 | setIsPlaying(false) 278 | clearInterval(intervalId) 279 | } else { 280 | await performBackgroundAction('playback.resume') 281 | setIsPlaying(true) 282 | startProgressUpdates() 283 | } 284 | }).catch(err => { 285 | console.log(err) 286 | }) 287 | }) 288 | 289 | stopButton.click(ev => { 290 | Promise.try(async() => { 291 | await performBackgroundAction('playback.stop') 292 | window.close() 293 | }).catch(err => { 294 | console.log(err) 295 | }) 296 | }) 297 | } 298 | 299 | async function waitForPinSubmit() { 300 | const pinInput = $('#airplay-pin-input') 301 | return new Promise((fulfill, reject) => { 302 | pinForm.submit(ev => { 303 | 304 | ev.preventDefault() 305 | 306 | pinInput.get(0).setCustomValidity('') 307 | const validationResult = pinForm.get(0).checkValidity() 308 | pinForm.addClass('was-validated') 309 | 310 | if (validationResult === false) { 311 | return 312 | } 313 | 314 | const pin = pinInput.val() 315 | fulfill(pin) 316 | }) 317 | }) 318 | } 319 | 320 | async function getCurrentTab() { 321 | return new Promise((fulfill, reject) => { 322 | chrome.tabs.query({ active: true, currentWindow: true }, tabs => { 323 | fulfill(tabs[0] || null) 324 | }) 325 | }) 326 | } 327 | 328 | async function performBackgroundAction(action, params) { 329 | params = params || {} 330 | return new Promise((fulfill, reject) => { 331 | chrome.runtime.sendMessage({ action: action, ...params }, response => { 332 | if (!response) { 333 | const message = _.get(chrome, 'runtime.lastError.message', 'Unknown runtime error') 334 | const err = new Error(message) 335 | return reject(err) 336 | } 337 | if (response.error) { 338 | const err = Errio.fromObject(response.error) 339 | return reject(err) 340 | } 341 | fulfill(response) 342 | }) 343 | }) 344 | } 345 | -------------------------------------------------------------------------------- /docs/css/template.css: -------------------------------------------------------------------------------- 1 | /* 2 | Fractal by HTML5 UP 3 | html5up.net | @ajlkn 4 | Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | */ 6 | 7 | /* Reset */ 8 | 9 | html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { 10 | margin: 0; 11 | padding: 0; 12 | border: 0; 13 | font-size: 100%; 14 | font: inherit; 15 | vertical-align: baseline; 16 | } 17 | 18 | article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { 19 | display: block; 20 | } 21 | 22 | body { 23 | line-height: 1; 24 | } 25 | 26 | ol, ul { 27 | list-style: none; 28 | } 29 | 30 | blockquote, q { 31 | quotes: none; 32 | } 33 | 34 | blockquote:before, blockquote:after, q:before, q:after { 35 | content: ''; 36 | content: none; 37 | } 38 | 39 | table { 40 | border-collapse: collapse; 41 | border-spacing: 0; 42 | } 43 | 44 | body { 45 | -webkit-text-size-adjust: none; 46 | } 47 | 48 | /* Box Model */ 49 | 50 | *, *:before, *:after { 51 | -moz-box-sizing: border-box; 52 | -webkit-box-sizing: border-box; 53 | box-sizing: border-box; 54 | } 55 | 56 | /* Grid */ 57 | 58 | .row { 59 | border-bottom: solid 1px transparent; 60 | -moz-box-sizing: border-box; 61 | -webkit-box-sizing: border-box; 62 | box-sizing: border-box; 63 | } 64 | 65 | .row > * { 66 | float: left; 67 | -moz-box-sizing: border-box; 68 | -webkit-box-sizing: border-box; 69 | box-sizing: border-box; 70 | } 71 | 72 | .row:after, .row:before { 73 | content: ''; 74 | display: block; 75 | clear: both; 76 | height: 0; 77 | } 78 | 79 | .row.uniform > * > :first-child { 80 | margin-top: 0; 81 | } 82 | 83 | .row.uniform > * > :last-child { 84 | margin-bottom: 0; 85 | } 86 | 87 | .row.\30 \25 > * { 88 | padding: 0 0 0 0em; 89 | } 90 | 91 | .row.\30 \25 { 92 | margin: 0 0 -1px 0em; 93 | } 94 | 95 | .row.uniform.\30 \25 > * { 96 | padding: 0em 0 0 0em; 97 | } 98 | 99 | .row.uniform.\30 \25 { 100 | margin: 0em 0 -1px 0em; 101 | } 102 | 103 | .row > * { 104 | padding: 0 0 0 1.5em; 105 | } 106 | 107 | .row { 108 | margin: 0 0 -1px -1.5em; 109 | } 110 | 111 | .row.uniform > * { 112 | padding: 1.5em 0 0 1.5em; 113 | } 114 | 115 | .row.uniform { 116 | margin: -1.5em 0 -1px -1.5em; 117 | } 118 | 119 | .row.\32 00\25 > * { 120 | padding: 0 0 0 3em; 121 | } 122 | 123 | .row.\32 00\25 { 124 | margin: 0 0 -1px -3em; 125 | } 126 | 127 | .row.uniform.\32 00\25 > * { 128 | padding: 3em 0 0 3em; 129 | } 130 | 131 | .row.uniform.\32 00\25 { 132 | margin: -3em 0 -1px -3em; 133 | } 134 | 135 | .row.\31 50\25 > * { 136 | padding: 0 0 0 2.25em; 137 | } 138 | 139 | .row.\31 50\25 { 140 | margin: 0 0 -1px -2.25em; 141 | } 142 | 143 | .row.uniform.\31 50\25 > * { 144 | padding: 2.25em 0 0 2.25em; 145 | } 146 | 147 | .row.uniform.\31 50\25 { 148 | margin: -2.25em 0 -1px -2.25em; 149 | } 150 | 151 | .row.\35 0\25 > * { 152 | padding: 0 0 0 0.75em; 153 | } 154 | 155 | .row.\35 0\25 { 156 | margin: 0 0 -1px -0.75em; 157 | } 158 | 159 | .row.uniform.\35 0\25 > * { 160 | padding: 0.75em 0 0 0.75em; 161 | } 162 | 163 | .row.uniform.\35 0\25 { 164 | margin: -0.75em 0 -1px -0.75em; 165 | } 166 | 167 | .row.\32 5\25 > * { 168 | padding: 0 0 0 0.375em; 169 | } 170 | 171 | .row.\32 5\25 { 172 | margin: 0 0 -1px -0.375em; 173 | } 174 | 175 | .row.uniform.\32 5\25 > * { 176 | padding: 0.375em 0 0 0.375em; 177 | } 178 | 179 | .row.uniform.\32 5\25 { 180 | margin: -0.375em 0 -1px -0.375em; 181 | } 182 | 183 | .\31 2u, .\31 2u\24 { 184 | width: 100%; 185 | clear: none; 186 | margin-left: 0; 187 | } 188 | 189 | .\31 1u, .\31 1u\24 { 190 | width: 91.6666666667%; 191 | clear: none; 192 | margin-left: 0; 193 | } 194 | 195 | .\31 0u, .\31 0u\24 { 196 | width: 83.3333333333%; 197 | clear: none; 198 | margin-left: 0; 199 | } 200 | 201 | .\39 u, .\39 u\24 { 202 | width: 75%; 203 | clear: none; 204 | margin-left: 0; 205 | } 206 | 207 | .\38 u, .\38 u\24 { 208 | width: 66.6666666667%; 209 | clear: none; 210 | margin-left: 0; 211 | } 212 | 213 | .\37 u, .\37 u\24 { 214 | width: 58.3333333333%; 215 | clear: none; 216 | margin-left: 0; 217 | } 218 | 219 | .\36 u, .\36 u\24 { 220 | width: 50%; 221 | clear: none; 222 | margin-left: 0; 223 | } 224 | 225 | .\35 u, .\35 u\24 { 226 | width: 41.6666666667%; 227 | clear: none; 228 | margin-left: 0; 229 | } 230 | 231 | .\34 u, .\34 u\24 { 232 | width: 33.3333333333%; 233 | clear: none; 234 | margin-left: 0; 235 | } 236 | 237 | .\33 u, .\33 u\24 { 238 | width: 25%; 239 | clear: none; 240 | margin-left: 0; 241 | } 242 | 243 | .\32 u, .\32 u\24 { 244 | width: 16.6666666667%; 245 | clear: none; 246 | margin-left: 0; 247 | } 248 | 249 | .\31 u, .\31 u\24 { 250 | width: 8.3333333333%; 251 | clear: none; 252 | margin-left: 0; 253 | } 254 | 255 | .\31 2u\24 + *, 256 | .\31 1u\24 + *, 257 | .\31 0u\24 + *, 258 | .\39 u\24 + *, 259 | .\38 u\24 + *, 260 | .\37 u\24 + *, 261 | .\36 u\24 + *, 262 | .\35 u\24 + *, 263 | .\34 u\24 + *, 264 | .\33 u\24 + *, 265 | .\32 u\24 + *, 266 | .\31 u\24 + * { 267 | clear: left; 268 | } 269 | 270 | .\-11u { 271 | margin-left: 91.66667%; 272 | } 273 | 274 | .\-10u { 275 | margin-left: 83.33333%; 276 | } 277 | 278 | .\-9u { 279 | margin-left: 75%; 280 | } 281 | 282 | .\-8u { 283 | margin-left: 66.66667%; 284 | } 285 | 286 | .\-7u { 287 | margin-left: 58.33333%; 288 | } 289 | 290 | .\-6u { 291 | margin-left: 50%; 292 | } 293 | 294 | .\-5u { 295 | margin-left: 41.66667%; 296 | } 297 | 298 | .\-4u { 299 | margin-left: 33.33333%; 300 | } 301 | 302 | .\-3u { 303 | margin-left: 25%; 304 | } 305 | 306 | .\-2u { 307 | margin-left: 16.66667%; 308 | } 309 | 310 | .\-1u { 311 | margin-left: 8.33333%; 312 | } 313 | 314 | @media screen and (max-width: 1680px) { 315 | 316 | .row > * { 317 | padding: 0 0 0 1.5em; 318 | } 319 | 320 | .row { 321 | margin: 0 0 -1px -1.5em; 322 | } 323 | 324 | .row.uniform > * { 325 | padding: 1.5em 0 0 1.5em; 326 | } 327 | 328 | .row.uniform { 329 | margin: -1.5em 0 -1px -1.5em; 330 | } 331 | 332 | .row.\32 00\25 > * { 333 | padding: 0 0 0 3em; 334 | } 335 | 336 | .row.\32 00\25 { 337 | margin: 0 0 -1px -3em; 338 | } 339 | 340 | .row.uniform.\32 00\25 > * { 341 | padding: 3em 0 0 3em; 342 | } 343 | 344 | .row.uniform.\32 00\25 { 345 | margin: -3em 0 -1px -3em; 346 | } 347 | 348 | .row.\31 50\25 > * { 349 | padding: 0 0 0 2.25em; 350 | } 351 | 352 | .row.\31 50\25 { 353 | margin: 0 0 -1px -2.25em; 354 | } 355 | 356 | .row.uniform.\31 50\25 > * { 357 | padding: 2.25em 0 0 2.25em; 358 | } 359 | 360 | .row.uniform.\31 50\25 { 361 | margin: -2.25em 0 -1px -2.25em; 362 | } 363 | 364 | .row.\35 0\25 > * { 365 | padding: 0 0 0 0.75em; 366 | } 367 | 368 | .row.\35 0\25 { 369 | margin: 0 0 -1px -0.75em; 370 | } 371 | 372 | .row.uniform.\35 0\25 > * { 373 | padding: 0.75em 0 0 0.75em; 374 | } 375 | 376 | .row.uniform.\35 0\25 { 377 | margin: -0.75em 0 -1px -0.75em; 378 | } 379 | 380 | .row.\32 5\25 > * { 381 | padding: 0 0 0 0.375em; 382 | } 383 | 384 | .row.\32 5\25 { 385 | margin: 0 0 -1px -0.375em; 386 | } 387 | 388 | .row.uniform.\32 5\25 > * { 389 | padding: 0.375em 0 0 0.375em; 390 | } 391 | 392 | .row.uniform.\32 5\25 { 393 | margin: -0.375em 0 -1px -0.375em; 394 | } 395 | 396 | .\31 2u\28xlarge\29, .\31 2u\24\28xlarge\29 { 397 | width: 100%; 398 | clear: none; 399 | margin-left: 0; 400 | } 401 | 402 | .\31 1u\28xlarge\29, .\31 1u\24\28xlarge\29 { 403 | width: 91.6666666667%; 404 | clear: none; 405 | margin-left: 0; 406 | } 407 | 408 | .\31 0u\28xlarge\29, .\31 0u\24\28xlarge\29 { 409 | width: 83.3333333333%; 410 | clear: none; 411 | margin-left: 0; 412 | } 413 | 414 | .\39 u\28xlarge\29, .\39 u\24\28xlarge\29 { 415 | width: 75%; 416 | clear: none; 417 | margin-left: 0; 418 | } 419 | 420 | .\38 u\28xlarge\29, .\38 u\24\28xlarge\29 { 421 | width: 66.6666666667%; 422 | clear: none; 423 | margin-left: 0; 424 | } 425 | 426 | .\37 u\28xlarge\29, .\37 u\24\28xlarge\29 { 427 | width: 58.3333333333%; 428 | clear: none; 429 | margin-left: 0; 430 | } 431 | 432 | .\36 u\28xlarge\29, .\36 u\24\28xlarge\29 { 433 | width: 50%; 434 | clear: none; 435 | margin-left: 0; 436 | } 437 | 438 | .\35 u\28xlarge\29, .\35 u\24\28xlarge\29 { 439 | width: 41.6666666667%; 440 | clear: none; 441 | margin-left: 0; 442 | } 443 | 444 | .\34 u\28xlarge\29, .\34 u\24\28xlarge\29 { 445 | width: 33.3333333333%; 446 | clear: none; 447 | margin-left: 0; 448 | } 449 | 450 | .\33 u\28xlarge\29, .\33 u\24\28xlarge\29 { 451 | width: 25%; 452 | clear: none; 453 | margin-left: 0; 454 | } 455 | 456 | .\32 u\28xlarge\29, .\32 u\24\28xlarge\29 { 457 | width: 16.6666666667%; 458 | clear: none; 459 | margin-left: 0; 460 | } 461 | 462 | .\31 u\28xlarge\29, .\31 u\24\28xlarge\29 { 463 | width: 8.3333333333%; 464 | clear: none; 465 | margin-left: 0; 466 | } 467 | 468 | .\31 2u\24\28xlarge\29 + *, 469 | .\31 1u\24\28xlarge\29 + *, 470 | .\31 0u\24\28xlarge\29 + *, 471 | .\39 u\24\28xlarge\29 + *, 472 | .\38 u\24\28xlarge\29 + *, 473 | .\37 u\24\28xlarge\29 + *, 474 | .\36 u\24\28xlarge\29 + *, 475 | .\35 u\24\28xlarge\29 + *, 476 | .\34 u\24\28xlarge\29 + *, 477 | .\33 u\24\28xlarge\29 + *, 478 | .\32 u\24\28xlarge\29 + *, 479 | .\31 u\24\28xlarge\29 + * { 480 | clear: left; 481 | } 482 | 483 | .\-11u\28xlarge\29 { 484 | margin-left: 91.66667%; 485 | } 486 | 487 | .\-10u\28xlarge\29 { 488 | margin-left: 83.33333%; 489 | } 490 | 491 | .\-9u\28xlarge\29 { 492 | margin-left: 75%; 493 | } 494 | 495 | .\-8u\28xlarge\29 { 496 | margin-left: 66.66667%; 497 | } 498 | 499 | .\-7u\28xlarge\29 { 500 | margin-left: 58.33333%; 501 | } 502 | 503 | .\-6u\28xlarge\29 { 504 | margin-left: 50%; 505 | } 506 | 507 | .\-5u\28xlarge\29 { 508 | margin-left: 41.66667%; 509 | } 510 | 511 | .\-4u\28xlarge\29 { 512 | margin-left: 33.33333%; 513 | } 514 | 515 | .\-3u\28xlarge\29 { 516 | margin-left: 25%; 517 | } 518 | 519 | .\-2u\28xlarge\29 { 520 | margin-left: 16.66667%; 521 | } 522 | 523 | .\-1u\28xlarge\29 { 524 | margin-left: 8.33333%; 525 | } 526 | 527 | } 528 | 529 | @media screen and (max-width: 1280px) { 530 | 531 | .row > * { 532 | padding: 0 0 0 1.5em; 533 | } 534 | 535 | .row { 536 | margin: 0 0 -1px -1.5em; 537 | } 538 | 539 | .row.uniform > * { 540 | padding: 1.5em 0 0 1.5em; 541 | } 542 | 543 | .row.uniform { 544 | margin: -1.5em 0 -1px -1.5em; 545 | } 546 | 547 | .row.\32 00\25 > * { 548 | padding: 0 0 0 3em; 549 | } 550 | 551 | .row.\32 00\25 { 552 | margin: 0 0 -1px -3em; 553 | } 554 | 555 | .row.uniform.\32 00\25 > * { 556 | padding: 3em 0 0 3em; 557 | } 558 | 559 | .row.uniform.\32 00\25 { 560 | margin: -3em 0 -1px -3em; 561 | } 562 | 563 | .row.\31 50\25 > * { 564 | padding: 0 0 0 2.25em; 565 | } 566 | 567 | .row.\31 50\25 { 568 | margin: 0 0 -1px -2.25em; 569 | } 570 | 571 | .row.uniform.\31 50\25 > * { 572 | padding: 2.25em 0 0 2.25em; 573 | } 574 | 575 | .row.uniform.\31 50\25 { 576 | margin: -2.25em 0 -1px -2.25em; 577 | } 578 | 579 | .row.\35 0\25 > * { 580 | padding: 0 0 0 0.75em; 581 | } 582 | 583 | .row.\35 0\25 { 584 | margin: 0 0 -1px -0.75em; 585 | } 586 | 587 | .row.uniform.\35 0\25 > * { 588 | padding: 0.75em 0 0 0.75em; 589 | } 590 | 591 | .row.uniform.\35 0\25 { 592 | margin: -0.75em 0 -1px -0.75em; 593 | } 594 | 595 | .row.\32 5\25 > * { 596 | padding: 0 0 0 0.375em; 597 | } 598 | 599 | .row.\32 5\25 { 600 | margin: 0 0 -1px -0.375em; 601 | } 602 | 603 | .row.uniform.\32 5\25 > * { 604 | padding: 0.375em 0 0 0.375em; 605 | } 606 | 607 | .row.uniform.\32 5\25 { 608 | margin: -0.375em 0 -1px -0.375em; 609 | } 610 | 611 | .\31 2u\28large\29, .\31 2u\24\28large\29 { 612 | width: 100%; 613 | clear: none; 614 | margin-left: 0; 615 | } 616 | 617 | .\31 1u\28large\29, .\31 1u\24\28large\29 { 618 | width: 91.6666666667%; 619 | clear: none; 620 | margin-left: 0; 621 | } 622 | 623 | .\31 0u\28large\29, .\31 0u\24\28large\29 { 624 | width: 83.3333333333%; 625 | clear: none; 626 | margin-left: 0; 627 | } 628 | 629 | .\39 u\28large\29, .\39 u\24\28large\29 { 630 | width: 75%; 631 | clear: none; 632 | margin-left: 0; 633 | } 634 | 635 | .\38 u\28large\29, .\38 u\24\28large\29 { 636 | width: 66.6666666667%; 637 | clear: none; 638 | margin-left: 0; 639 | } 640 | 641 | .\37 u\28large\29, .\37 u\24\28large\29 { 642 | width: 58.3333333333%; 643 | clear: none; 644 | margin-left: 0; 645 | } 646 | 647 | .\36 u\28large\29, .\36 u\24\28large\29 { 648 | width: 50%; 649 | clear: none; 650 | margin-left: 0; 651 | } 652 | 653 | .\35 u\28large\29, .\35 u\24\28large\29 { 654 | width: 41.6666666667%; 655 | clear: none; 656 | margin-left: 0; 657 | } 658 | 659 | .\34 u\28large\29, .\34 u\24\28large\29 { 660 | width: 33.3333333333%; 661 | clear: none; 662 | margin-left: 0; 663 | } 664 | 665 | .\33 u\28large\29, .\33 u\24\28large\29 { 666 | width: 25%; 667 | clear: none; 668 | margin-left: 0; 669 | } 670 | 671 | .\32 u\28large\29, .\32 u\24\28large\29 { 672 | width: 16.6666666667%; 673 | clear: none; 674 | margin-left: 0; 675 | } 676 | 677 | .\31 u\28large\29, .\31 u\24\28large\29 { 678 | width: 8.3333333333%; 679 | clear: none; 680 | margin-left: 0; 681 | } 682 | 683 | .\31 2u\24\28large\29 + *, 684 | .\31 1u\24\28large\29 + *, 685 | .\31 0u\24\28large\29 + *, 686 | .\39 u\24\28large\29 + *, 687 | .\38 u\24\28large\29 + *, 688 | .\37 u\24\28large\29 + *, 689 | .\36 u\24\28large\29 + *, 690 | .\35 u\24\28large\29 + *, 691 | .\34 u\24\28large\29 + *, 692 | .\33 u\24\28large\29 + *, 693 | .\32 u\24\28large\29 + *, 694 | .\31 u\24\28large\29 + * { 695 | clear: left; 696 | } 697 | 698 | .\-11u\28large\29 { 699 | margin-left: 91.66667%; 700 | } 701 | 702 | .\-10u\28large\29 { 703 | margin-left: 83.33333%; 704 | } 705 | 706 | .\-9u\28large\29 { 707 | margin-left: 75%; 708 | } 709 | 710 | .\-8u\28large\29 { 711 | margin-left: 66.66667%; 712 | } 713 | 714 | .\-7u\28large\29 { 715 | margin-left: 58.33333%; 716 | } 717 | 718 | .\-6u\28large\29 { 719 | margin-left: 50%; 720 | } 721 | 722 | .\-5u\28large\29 { 723 | margin-left: 41.66667%; 724 | } 725 | 726 | .\-4u\28large\29 { 727 | margin-left: 33.33333%; 728 | } 729 | 730 | .\-3u\28large\29 { 731 | margin-left: 25%; 732 | } 733 | 734 | .\-2u\28large\29 { 735 | margin-left: 16.66667%; 736 | } 737 | 738 | .\-1u\28large\29 { 739 | margin-left: 8.33333%; 740 | } 741 | 742 | } 743 | 744 | @media screen and (max-width: 980px) { 745 | 746 | .row > * { 747 | padding: 0 0 0 1.5em; 748 | } 749 | 750 | .row { 751 | margin: 0 0 -1px -1.5em; 752 | } 753 | 754 | .row.uniform > * { 755 | padding: 1.5em 0 0 1.5em; 756 | } 757 | 758 | .row.uniform { 759 | margin: -1.5em 0 -1px -1.5em; 760 | } 761 | 762 | .row.\32 00\25 > * { 763 | padding: 0 0 0 3em; 764 | } 765 | 766 | .row.\32 00\25 { 767 | margin: 0 0 -1px -3em; 768 | } 769 | 770 | .row.uniform.\32 00\25 > * { 771 | padding: 3em 0 0 3em; 772 | } 773 | 774 | .row.uniform.\32 00\25 { 775 | margin: -3em 0 -1px -3em; 776 | } 777 | 778 | .row.\31 50\25 > * { 779 | padding: 0 0 0 2.25em; 780 | } 781 | 782 | .row.\31 50\25 { 783 | margin: 0 0 -1px -2.25em; 784 | } 785 | 786 | .row.uniform.\31 50\25 > * { 787 | padding: 2.25em 0 0 2.25em; 788 | } 789 | 790 | .row.uniform.\31 50\25 { 791 | margin: -2.25em 0 -1px -2.25em; 792 | } 793 | 794 | .row.\35 0\25 > * { 795 | padding: 0 0 0 0.75em; 796 | } 797 | 798 | .row.\35 0\25 { 799 | margin: 0 0 -1px -0.75em; 800 | } 801 | 802 | .row.uniform.\35 0\25 > * { 803 | padding: 0.75em 0 0 0.75em; 804 | } 805 | 806 | .row.uniform.\35 0\25 { 807 | margin: -0.75em 0 -1px -0.75em; 808 | } 809 | 810 | .row.\32 5\25 > * { 811 | padding: 0 0 0 0.375em; 812 | } 813 | 814 | .row.\32 5\25 { 815 | margin: 0 0 -1px -0.375em; 816 | } 817 | 818 | .row.uniform.\32 5\25 > * { 819 | padding: 0.375em 0 0 0.375em; 820 | } 821 | 822 | .row.uniform.\32 5\25 { 823 | margin: -0.375em 0 -1px -0.375em; 824 | } 825 | 826 | .\31 2u\28medium\29, .\31 2u\24\28medium\29 { 827 | width: 100%; 828 | clear: none; 829 | margin-left: 0; 830 | } 831 | 832 | .\31 1u\28medium\29, .\31 1u\24\28medium\29 { 833 | width: 91.6666666667%; 834 | clear: none; 835 | margin-left: 0; 836 | } 837 | 838 | .\31 0u\28medium\29, .\31 0u\24\28medium\29 { 839 | width: 83.3333333333%; 840 | clear: none; 841 | margin-left: 0; 842 | } 843 | 844 | .\39 u\28medium\29, .\39 u\24\28medium\29 { 845 | width: 75%; 846 | clear: none; 847 | margin-left: 0; 848 | } 849 | 850 | .\38 u\28medium\29, .\38 u\24\28medium\29 { 851 | width: 66.6666666667%; 852 | clear: none; 853 | margin-left: 0; 854 | } 855 | 856 | .\37 u\28medium\29, .\37 u\24\28medium\29 { 857 | width: 58.3333333333%; 858 | clear: none; 859 | margin-left: 0; 860 | } 861 | 862 | .\36 u\28medium\29, .\36 u\24\28medium\29 { 863 | width: 50%; 864 | clear: none; 865 | margin-left: 0; 866 | } 867 | 868 | .\35 u\28medium\29, .\35 u\24\28medium\29 { 869 | width: 41.6666666667%; 870 | clear: none; 871 | margin-left: 0; 872 | } 873 | 874 | .\34 u\28medium\29, .\34 u\24\28medium\29 { 875 | width: 33.3333333333%; 876 | clear: none; 877 | margin-left: 0; 878 | } 879 | 880 | .\33 u\28medium\29, .\33 u\24\28medium\29 { 881 | width: 25%; 882 | clear: none; 883 | margin-left: 0; 884 | } 885 | 886 | .\32 u\28medium\29, .\32 u\24\28medium\29 { 887 | width: 16.6666666667%; 888 | clear: none; 889 | margin-left: 0; 890 | } 891 | 892 | .\31 u\28medium\29, .\31 u\24\28medium\29 { 893 | width: 8.3333333333%; 894 | clear: none; 895 | margin-left: 0; 896 | } 897 | 898 | .\31 2u\24\28medium\29 + *, 899 | .\31 1u\24\28medium\29 + *, 900 | .\31 0u\24\28medium\29 + *, 901 | .\39 u\24\28medium\29 + *, 902 | .\38 u\24\28medium\29 + *, 903 | .\37 u\24\28medium\29 + *, 904 | .\36 u\24\28medium\29 + *, 905 | .\35 u\24\28medium\29 + *, 906 | .\34 u\24\28medium\29 + *, 907 | .\33 u\24\28medium\29 + *, 908 | .\32 u\24\28medium\29 + *, 909 | .\31 u\24\28medium\29 + * { 910 | clear: left; 911 | } 912 | 913 | .\-11u\28medium\29 { 914 | margin-left: 91.66667%; 915 | } 916 | 917 | .\-10u\28medium\29 { 918 | margin-left: 83.33333%; 919 | } 920 | 921 | .\-9u\28medium\29 { 922 | margin-left: 75%; 923 | } 924 | 925 | .\-8u\28medium\29 { 926 | margin-left: 66.66667%; 927 | } 928 | 929 | .\-7u\28medium\29 { 930 | margin-left: 58.33333%; 931 | } 932 | 933 | .\-6u\28medium\29 { 934 | margin-left: 50%; 935 | } 936 | 937 | .\-5u\28medium\29 { 938 | margin-left: 41.66667%; 939 | } 940 | 941 | .\-4u\28medium\29 { 942 | margin-left: 33.33333%; 943 | } 944 | 945 | .\-3u\28medium\29 { 946 | margin-left: 25%; 947 | } 948 | 949 | .\-2u\28medium\29 { 950 | margin-left: 16.66667%; 951 | } 952 | 953 | .\-1u\28medium\29 { 954 | margin-left: 8.33333%; 955 | } 956 | 957 | } 958 | 959 | @media screen and (max-width: 736px) { 960 | 961 | .row > * { 962 | padding: 0 0 0 1.5em; 963 | } 964 | 965 | .row { 966 | margin: 0 0 -1px -1.5em; 967 | } 968 | 969 | .row.uniform > * { 970 | padding: 1.5em 0 0 1.5em; 971 | } 972 | 973 | .row.uniform { 974 | margin: -1.5em 0 -1px -1.5em; 975 | } 976 | 977 | .row.\32 00\25 > * { 978 | padding: 0 0 0 3em; 979 | } 980 | 981 | .row.\32 00\25 { 982 | margin: 0 0 -1px -3em; 983 | } 984 | 985 | .row.uniform.\32 00\25 > * { 986 | padding: 3em 0 0 3em; 987 | } 988 | 989 | .row.uniform.\32 00\25 { 990 | margin: -3em 0 -1px -3em; 991 | } 992 | 993 | .row.\31 50\25 > * { 994 | padding: 0 0 0 2.25em; 995 | } 996 | 997 | .row.\31 50\25 { 998 | margin: 0 0 -1px -2.25em; 999 | } 1000 | 1001 | .row.uniform.\31 50\25 > * { 1002 | padding: 2.25em 0 0 2.25em; 1003 | } 1004 | 1005 | .row.uniform.\31 50\25 { 1006 | margin: -2.25em 0 -1px -2.25em; 1007 | } 1008 | 1009 | .row.\35 0\25 > * { 1010 | padding: 0 0 0 0.75em; 1011 | } 1012 | 1013 | .row.\35 0\25 { 1014 | margin: 0 0 -1px -0.75em; 1015 | } 1016 | 1017 | .row.uniform.\35 0\25 > * { 1018 | padding: 0.75em 0 0 0.75em; 1019 | } 1020 | 1021 | .row.uniform.\35 0\25 { 1022 | margin: -0.75em 0 -1px -0.75em; 1023 | } 1024 | 1025 | .row.\32 5\25 > * { 1026 | padding: 0 0 0 0.375em; 1027 | } 1028 | 1029 | .row.\32 5\25 { 1030 | margin: 0 0 -1px -0.375em; 1031 | } 1032 | 1033 | .row.uniform.\32 5\25 > * { 1034 | padding: 0.375em 0 0 0.375em; 1035 | } 1036 | 1037 | .row.uniform.\32 5\25 { 1038 | margin: -0.375em 0 -1px -0.375em; 1039 | } 1040 | 1041 | .\31 2u\28small\29, .\31 2u\24\28small\29 { 1042 | width: 100%; 1043 | clear: none; 1044 | margin-left: 0; 1045 | } 1046 | 1047 | .\31 1u\28small\29, .\31 1u\24\28small\29 { 1048 | width: 91.6666666667%; 1049 | clear: none; 1050 | margin-left: 0; 1051 | } 1052 | 1053 | .\31 0u\28small\29, .\31 0u\24\28small\29 { 1054 | width: 83.3333333333%; 1055 | clear: none; 1056 | margin-left: 0; 1057 | } 1058 | 1059 | .\39 u\28small\29, .\39 u\24\28small\29 { 1060 | width: 75%; 1061 | clear: none; 1062 | margin-left: 0; 1063 | } 1064 | 1065 | .\38 u\28small\29, .\38 u\24\28small\29 { 1066 | width: 66.6666666667%; 1067 | clear: none; 1068 | margin-left: 0; 1069 | } 1070 | 1071 | .\37 u\28small\29, .\37 u\24\28small\29 { 1072 | width: 58.3333333333%; 1073 | clear: none; 1074 | margin-left: 0; 1075 | } 1076 | 1077 | .\36 u\28small\29, .\36 u\24\28small\29 { 1078 | width: 50%; 1079 | clear: none; 1080 | margin-left: 0; 1081 | } 1082 | 1083 | .\35 u\28small\29, .\35 u\24\28small\29 { 1084 | width: 41.6666666667%; 1085 | clear: none; 1086 | margin-left: 0; 1087 | } 1088 | 1089 | .\34 u\28small\29, .\34 u\24\28small\29 { 1090 | width: 33.3333333333%; 1091 | clear: none; 1092 | margin-left: 0; 1093 | } 1094 | 1095 | .\33 u\28small\29, .\33 u\24\28small\29 { 1096 | width: 25%; 1097 | clear: none; 1098 | margin-left: 0; 1099 | } 1100 | 1101 | .\32 u\28small\29, .\32 u\24\28small\29 { 1102 | width: 16.6666666667%; 1103 | clear: none; 1104 | margin-left: 0; 1105 | } 1106 | 1107 | .\31 u\28small\29, .\31 u\24\28small\29 { 1108 | width: 8.3333333333%; 1109 | clear: none; 1110 | margin-left: 0; 1111 | } 1112 | 1113 | .\31 2u\24\28small\29 + *, 1114 | .\31 1u\24\28small\29 + *, 1115 | .\31 0u\24\28small\29 + *, 1116 | .\39 u\24\28small\29 + *, 1117 | .\38 u\24\28small\29 + *, 1118 | .\37 u\24\28small\29 + *, 1119 | .\36 u\24\28small\29 + *, 1120 | .\35 u\24\28small\29 + *, 1121 | .\34 u\24\28small\29 + *, 1122 | .\33 u\24\28small\29 + *, 1123 | .\32 u\24\28small\29 + *, 1124 | .\31 u\24\28small\29 + * { 1125 | clear: left; 1126 | } 1127 | 1128 | .\-11u\28small\29 { 1129 | margin-left: 91.66667%; 1130 | } 1131 | 1132 | .\-10u\28small\29 { 1133 | margin-left: 83.33333%; 1134 | } 1135 | 1136 | .\-9u\28small\29 { 1137 | margin-left: 75%; 1138 | } 1139 | 1140 | .\-8u\28small\29 { 1141 | margin-left: 66.66667%; 1142 | } 1143 | 1144 | .\-7u\28small\29 { 1145 | margin-left: 58.33333%; 1146 | } 1147 | 1148 | .\-6u\28small\29 { 1149 | margin-left: 50%; 1150 | } 1151 | 1152 | .\-5u\28small\29 { 1153 | margin-left: 41.66667%; 1154 | } 1155 | 1156 | .\-4u\28small\29 { 1157 | margin-left: 33.33333%; 1158 | } 1159 | 1160 | .\-3u\28small\29 { 1161 | margin-left: 25%; 1162 | } 1163 | 1164 | .\-2u\28small\29 { 1165 | margin-left: 16.66667%; 1166 | } 1167 | 1168 | .\-1u\28small\29 { 1169 | margin-left: 8.33333%; 1170 | } 1171 | 1172 | } 1173 | 1174 | @media screen and (max-width: 480px) { 1175 | 1176 | .row > * { 1177 | padding: 0 0 0 1.5em; 1178 | } 1179 | 1180 | .row { 1181 | margin: 0 0 -1px -1.5em; 1182 | } 1183 | 1184 | .row.uniform > * { 1185 | padding: 1.5em 0 0 1.5em; 1186 | } 1187 | 1188 | .row.uniform { 1189 | margin: -1.5em 0 -1px -1.5em; 1190 | } 1191 | 1192 | .row.\32 00\25 > * { 1193 | padding: 0 0 0 3em; 1194 | } 1195 | 1196 | .row.\32 00\25 { 1197 | margin: 0 0 -1px -3em; 1198 | } 1199 | 1200 | .row.uniform.\32 00\25 > * { 1201 | padding: 3em 0 0 3em; 1202 | } 1203 | 1204 | .row.uniform.\32 00\25 { 1205 | margin: -3em 0 -1px -3em; 1206 | } 1207 | 1208 | .row.\31 50\25 > * { 1209 | padding: 0 0 0 2.25em; 1210 | } 1211 | 1212 | .row.\31 50\25 { 1213 | margin: 0 0 -1px -2.25em; 1214 | } 1215 | 1216 | .row.uniform.\31 50\25 > * { 1217 | padding: 2.25em 0 0 2.25em; 1218 | } 1219 | 1220 | .row.uniform.\31 50\25 { 1221 | margin: -2.25em 0 -1px -2.25em; 1222 | } 1223 | 1224 | .row.\35 0\25 > * { 1225 | padding: 0 0 0 0.75em; 1226 | } 1227 | 1228 | .row.\35 0\25 { 1229 | margin: 0 0 -1px -0.75em; 1230 | } 1231 | 1232 | .row.uniform.\35 0\25 > * { 1233 | padding: 0.75em 0 0 0.75em; 1234 | } 1235 | 1236 | .row.uniform.\35 0\25 { 1237 | margin: -0.75em 0 -1px -0.75em; 1238 | } 1239 | 1240 | .row.\32 5\25 > * { 1241 | padding: 0 0 0 0.375em; 1242 | } 1243 | 1244 | .row.\32 5\25 { 1245 | margin: 0 0 -1px -0.375em; 1246 | } 1247 | 1248 | .row.uniform.\32 5\25 > * { 1249 | padding: 0.375em 0 0 0.375em; 1250 | } 1251 | 1252 | .row.uniform.\32 5\25 { 1253 | margin: -0.375em 0 -1px -0.375em; 1254 | } 1255 | 1256 | .\31 2u\28xsmall\29, .\31 2u\24\28xsmall\29 { 1257 | width: 100%; 1258 | clear: none; 1259 | margin-left: 0; 1260 | } 1261 | 1262 | .\31 1u\28xsmall\29, .\31 1u\24\28xsmall\29 { 1263 | width: 91.6666666667%; 1264 | clear: none; 1265 | margin-left: 0; 1266 | } 1267 | 1268 | .\31 0u\28xsmall\29, .\31 0u\24\28xsmall\29 { 1269 | width: 83.3333333333%; 1270 | clear: none; 1271 | margin-left: 0; 1272 | } 1273 | 1274 | .\39 u\28xsmall\29, .\39 u\24\28xsmall\29 { 1275 | width: 75%; 1276 | clear: none; 1277 | margin-left: 0; 1278 | } 1279 | 1280 | .\38 u\28xsmall\29, .\38 u\24\28xsmall\29 { 1281 | width: 66.6666666667%; 1282 | clear: none; 1283 | margin-left: 0; 1284 | } 1285 | 1286 | .\37 u\28xsmall\29, .\37 u\24\28xsmall\29 { 1287 | width: 58.3333333333%; 1288 | clear: none; 1289 | margin-left: 0; 1290 | } 1291 | 1292 | .\36 u\28xsmall\29, .\36 u\24\28xsmall\29 { 1293 | width: 50%; 1294 | clear: none; 1295 | margin-left: 0; 1296 | } 1297 | 1298 | .\35 u\28xsmall\29, .\35 u\24\28xsmall\29 { 1299 | width: 41.6666666667%; 1300 | clear: none; 1301 | margin-left: 0; 1302 | } 1303 | 1304 | .\34 u\28xsmall\29, .\34 u\24\28xsmall\29 { 1305 | width: 33.3333333333%; 1306 | clear: none; 1307 | margin-left: 0; 1308 | } 1309 | 1310 | .\33 u\28xsmall\29, .\33 u\24\28xsmall\29 { 1311 | width: 25%; 1312 | clear: none; 1313 | margin-left: 0; 1314 | } 1315 | 1316 | .\32 u\28xsmall\29, .\32 u\24\28xsmall\29 { 1317 | width: 16.6666666667%; 1318 | clear: none; 1319 | margin-left: 0; 1320 | } 1321 | 1322 | .\31 u\28xsmall\29, .\31 u\24\28xsmall\29 { 1323 | width: 8.3333333333%; 1324 | clear: none; 1325 | margin-left: 0; 1326 | } 1327 | 1328 | .\31 2u\24\28xsmall\29 + *, 1329 | .\31 1u\24\28xsmall\29 + *, 1330 | .\31 0u\24\28xsmall\29 + *, 1331 | .\39 u\24\28xsmall\29 + *, 1332 | .\38 u\24\28xsmall\29 + *, 1333 | .\37 u\24\28xsmall\29 + *, 1334 | .\36 u\24\28xsmall\29 + *, 1335 | .\35 u\24\28xsmall\29 + *, 1336 | .\34 u\24\28xsmall\29 + *, 1337 | .\33 u\24\28xsmall\29 + *, 1338 | .\32 u\24\28xsmall\29 + *, 1339 | .\31 u\24\28xsmall\29 + * { 1340 | clear: left; 1341 | } 1342 | 1343 | .\-11u\28xsmall\29 { 1344 | margin-left: 91.66667%; 1345 | } 1346 | 1347 | .\-10u\28xsmall\29 { 1348 | margin-left: 83.33333%; 1349 | } 1350 | 1351 | .\-9u\28xsmall\29 { 1352 | margin-left: 75%; 1353 | } 1354 | 1355 | .\-8u\28xsmall\29 { 1356 | margin-left: 66.66667%; 1357 | } 1358 | 1359 | .\-7u\28xsmall\29 { 1360 | margin-left: 58.33333%; 1361 | } 1362 | 1363 | .\-6u\28xsmall\29 { 1364 | margin-left: 50%; 1365 | } 1366 | 1367 | .\-5u\28xsmall\29 { 1368 | margin-left: 41.66667%; 1369 | } 1370 | 1371 | .\-4u\28xsmall\29 { 1372 | margin-left: 33.33333%; 1373 | } 1374 | 1375 | .\-3u\28xsmall\29 { 1376 | margin-left: 25%; 1377 | } 1378 | 1379 | .\-2u\28xsmall\29 { 1380 | margin-left: 16.66667%; 1381 | } 1382 | 1383 | .\-1u\28xsmall\29 { 1384 | margin-left: 8.33333%; 1385 | } 1386 | 1387 | } 1388 | 1389 | @media screen and (max-width: 360px) { 1390 | 1391 | .row > * { 1392 | padding: 0 0 0 1.5em; 1393 | } 1394 | 1395 | .row { 1396 | margin: 0 0 -1px -1.5em; 1397 | } 1398 | 1399 | .row.uniform > * { 1400 | padding: 1.5em 0 0 1.5em; 1401 | } 1402 | 1403 | .row.uniform { 1404 | margin: -1.5em 0 -1px -1.5em; 1405 | } 1406 | 1407 | .row.\32 00\25 > * { 1408 | padding: 0 0 0 3em; 1409 | } 1410 | 1411 | .row.\32 00\25 { 1412 | margin: 0 0 -1px -3em; 1413 | } 1414 | 1415 | .row.uniform.\32 00\25 > * { 1416 | padding: 3em 0 0 3em; 1417 | } 1418 | 1419 | .row.uniform.\32 00\25 { 1420 | margin: -3em 0 -1px -3em; 1421 | } 1422 | 1423 | .row.\31 50\25 > * { 1424 | padding: 0 0 0 2.25em; 1425 | } 1426 | 1427 | .row.\31 50\25 { 1428 | margin: 0 0 -1px -2.25em; 1429 | } 1430 | 1431 | .row.uniform.\31 50\25 > * { 1432 | padding: 2.25em 0 0 2.25em; 1433 | } 1434 | 1435 | .row.uniform.\31 50\25 { 1436 | margin: -2.25em 0 -1px -2.25em; 1437 | } 1438 | 1439 | .row.\35 0\25 > * { 1440 | padding: 0 0 0 0.75em; 1441 | } 1442 | 1443 | .row.\35 0\25 { 1444 | margin: 0 0 -1px -0.75em; 1445 | } 1446 | 1447 | .row.uniform.\35 0\25 > * { 1448 | padding: 0.75em 0 0 0.75em; 1449 | } 1450 | 1451 | .row.uniform.\35 0\25 { 1452 | margin: -0.75em 0 -1px -0.75em; 1453 | } 1454 | 1455 | .row.\32 5\25 > * { 1456 | padding: 0 0 0 0.375em; 1457 | } 1458 | 1459 | .row.\32 5\25 { 1460 | margin: 0 0 -1px -0.375em; 1461 | } 1462 | 1463 | .row.uniform.\32 5\25 > * { 1464 | padding: 0.375em 0 0 0.375em; 1465 | } 1466 | 1467 | .row.uniform.\32 5\25 { 1468 | margin: -0.375em 0 -1px -0.375em; 1469 | } 1470 | 1471 | .\31 2u\28xxsmall\29, .\31 2u\24\28xxsmall\29 { 1472 | width: 100%; 1473 | clear: none; 1474 | margin-left: 0; 1475 | } 1476 | 1477 | .\31 1u\28xxsmall\29, .\31 1u\24\28xxsmall\29 { 1478 | width: 91.6666666667%; 1479 | clear: none; 1480 | margin-left: 0; 1481 | } 1482 | 1483 | .\31 0u\28xxsmall\29, .\31 0u\24\28xxsmall\29 { 1484 | width: 83.3333333333%; 1485 | clear: none; 1486 | margin-left: 0; 1487 | } 1488 | 1489 | .\39 u\28xxsmall\29, .\39 u\24\28xxsmall\29 { 1490 | width: 75%; 1491 | clear: none; 1492 | margin-left: 0; 1493 | } 1494 | 1495 | .\38 u\28xxsmall\29, .\38 u\24\28xxsmall\29 { 1496 | width: 66.6666666667%; 1497 | clear: none; 1498 | margin-left: 0; 1499 | } 1500 | 1501 | .\37 u\28xxsmall\29, .\37 u\24\28xxsmall\29 { 1502 | width: 58.3333333333%; 1503 | clear: none; 1504 | margin-left: 0; 1505 | } 1506 | 1507 | .\36 u\28xxsmall\29, .\36 u\24\28xxsmall\29 { 1508 | width: 50%; 1509 | clear: none; 1510 | margin-left: 0; 1511 | } 1512 | 1513 | .\35 u\28xxsmall\29, .\35 u\24\28xxsmall\29 { 1514 | width: 41.6666666667%; 1515 | clear: none; 1516 | margin-left: 0; 1517 | } 1518 | 1519 | .\34 u\28xxsmall\29, .\34 u\24\28xxsmall\29 { 1520 | width: 33.3333333333%; 1521 | clear: none; 1522 | margin-left: 0; 1523 | } 1524 | 1525 | .\33 u\28xxsmall\29, .\33 u\24\28xxsmall\29 { 1526 | width: 25%; 1527 | clear: none; 1528 | margin-left: 0; 1529 | } 1530 | 1531 | .\32 u\28xxsmall\29, .\32 u\24\28xxsmall\29 { 1532 | width: 16.6666666667%; 1533 | clear: none; 1534 | margin-left: 0; 1535 | } 1536 | 1537 | .\31 u\28xxsmall\29, .\31 u\24\28xxsmall\29 { 1538 | width: 8.3333333333%; 1539 | clear: none; 1540 | margin-left: 0; 1541 | } 1542 | 1543 | .\31 2u\24\28xxsmall\29 + *, 1544 | .\31 1u\24\28xxsmall\29 + *, 1545 | .\31 0u\24\28xxsmall\29 + *, 1546 | .\39 u\24\28xxsmall\29 + *, 1547 | .\38 u\24\28xxsmall\29 + *, 1548 | .\37 u\24\28xxsmall\29 + *, 1549 | .\36 u\24\28xxsmall\29 + *, 1550 | .\35 u\24\28xxsmall\29 + *, 1551 | .\34 u\24\28xxsmall\29 + *, 1552 | .\33 u\24\28xxsmall\29 + *, 1553 | .\32 u\24\28xxsmall\29 + *, 1554 | .\31 u\24\28xxsmall\29 + * { 1555 | clear: left; 1556 | } 1557 | 1558 | .\-11u\28xxsmall\29 { 1559 | margin-left: 91.66667%; 1560 | } 1561 | 1562 | .\-10u\28xxsmall\29 { 1563 | margin-left: 83.33333%; 1564 | } 1565 | 1566 | .\-9u\28xxsmall\29 { 1567 | margin-left: 75%; 1568 | } 1569 | 1570 | .\-8u\28xxsmall\29 { 1571 | margin-left: 66.66667%; 1572 | } 1573 | 1574 | .\-7u\28xxsmall\29 { 1575 | margin-left: 58.33333%; 1576 | } 1577 | 1578 | .\-6u\28xxsmall\29 { 1579 | margin-left: 50%; 1580 | } 1581 | 1582 | .\-5u\28xxsmall\29 { 1583 | margin-left: 41.66667%; 1584 | } 1585 | 1586 | .\-4u\28xxsmall\29 { 1587 | margin-left: 33.33333%; 1588 | } 1589 | 1590 | .\-3u\28xxsmall\29 { 1591 | margin-left: 25%; 1592 | } 1593 | 1594 | .\-2u\28xxsmall\29 { 1595 | margin-left: 16.66667%; 1596 | } 1597 | 1598 | .\-1u\28xxsmall\29 { 1599 | margin-left: 8.33333%; 1600 | } 1601 | 1602 | } 1603 | 1604 | /* Basic */ 1605 | 1606 | @-ms-viewport { 1607 | width: device-width; 1608 | } 1609 | 1610 | body { 1611 | -ms-overflow-style: scrollbar; 1612 | } 1613 | 1614 | @media screen and (max-width: 360px) { 1615 | 1616 | html, body { 1617 | min-width: 320px; 1618 | } 1619 | 1620 | } 1621 | 1622 | body { 1623 | background: #ffffff; 1624 | } 1625 | 1626 | body.is-loading *, body.is-loading *:before, body.is-loading *:after { 1627 | -moz-animation: none !important; 1628 | -webkit-animation: none !important; 1629 | -ms-animation: none !important; 1630 | animation: none !important; 1631 | -moz-transition: none !important; 1632 | -webkit-transition: none !important; 1633 | -ms-transition: none !important; 1634 | transition: none !important; 1635 | } 1636 | 1637 | /* Type */ 1638 | 1639 | body { 1640 | color: #999999; 1641 | } 1642 | 1643 | html, input, select, textarea { 1644 | font-size: 16pt; 1645 | } 1646 | 1647 | @media screen and (max-width: 1680px) { 1648 | 1649 | html, input, select, textarea { 1650 | font-size: 13pt; 1651 | } 1652 | 1653 | } 1654 | 1655 | @media screen and (max-width: 1280px) { 1656 | 1657 | html, input, select, textarea { 1658 | font-size: 12pt; 1659 | } 1660 | 1661 | } 1662 | 1663 | @media screen and (max-width: 360px) { 1664 | 1665 | html, input, select, textarea { 1666 | font-size: 11pt; 1667 | } 1668 | 1669 | } 1670 | 1671 | body, input, select, textarea { 1672 | font-family: Arial, Helvetica, sans-serif; 1673 | font-weight: normal; 1674 | line-height: 1.5em; 1675 | letter-spacing: -0.015em; 1676 | } 1677 | 1678 | a { 1679 | -moz-transition: color 0.2s ease-in-out, border-bottom-color 0.2s ease-in-out; 1680 | -webkit-transition: color 0.2s ease-in-out, border-bottom-color 0.2s ease-in-out; 1681 | -ms-transition: color 0.2s ease-in-out, border-bottom-color 0.2s ease-in-out; 1682 | transition: color 0.2s ease-in-out, border-bottom-color 0.2s ease-in-out; 1683 | text-decoration: none; 1684 | border-bottom: dotted 1px; 1685 | } 1686 | 1687 | a:hover { 1688 | border-bottom-color: transparent !important; 1689 | } 1690 | 1691 | strong, b { 1692 | font-weight: bold; 1693 | } 1694 | 1695 | em, i { 1696 | font-style: italic; 1697 | } 1698 | 1699 | p { 1700 | margin: 0 0 2em 0; 1701 | } 1702 | 1703 | h1, h2, h3, h4, h5, h6 { 1704 | font-weight: normal; 1705 | line-height: 1em; 1706 | margin: 0 0 1em 0; 1707 | letter-spacing: -0.0125em; 1708 | } 1709 | 1710 | h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { 1711 | color: inherit; 1712 | text-decoration: none; 1713 | border-bottom: none; 1714 | } 1715 | 1716 | @media screen and (max-width: 980px) { 1717 | 1718 | h1 br, h2 br, h3 br, h4 br, h5 br, h6 br { 1719 | display: none; 1720 | } 1721 | 1722 | } 1723 | 1724 | h2 { 1725 | font-size: 1.75em; 1726 | line-height: 1.5em; 1727 | } 1728 | 1729 | h3 { 1730 | font-size: 1.5em; 1731 | line-height: 1.5em; 1732 | } 1733 | 1734 | h4 { 1735 | font-size: 1.1em; 1736 | line-height: 1.5em; 1737 | } 1738 | 1739 | h5 { 1740 | font-size: 0.9em; 1741 | line-height: 1.5em; 1742 | } 1743 | 1744 | h6 { 1745 | font-size: 0.7em; 1746 | line-height: 1.5em; 1747 | } 1748 | 1749 | @media screen and (max-width: 736px) { 1750 | 1751 | h2 { 1752 | font-size: 1.25em; 1753 | } 1754 | 1755 | h3 { 1756 | font-size: 1.2em; 1757 | } 1758 | 1759 | h4 { 1760 | font-size: 1em; 1761 | } 1762 | 1763 | } 1764 | 1765 | sub { 1766 | font-size: 0.8em; 1767 | position: relative; 1768 | top: 0.5em; 1769 | } 1770 | 1771 | sup { 1772 | font-size: 0.8em; 1773 | position: relative; 1774 | top: -0.5em; 1775 | } 1776 | 1777 | blockquote { 1778 | border-left-style: solid; 1779 | border-left-width: 4px; 1780 | font-style: italic; 1781 | margin: 0 0 2em 0; 1782 | padding: 0.5em 0 0.5em 2em; 1783 | } 1784 | 1785 | code { 1786 | border-radius: 6px; 1787 | border-style: solid; 1788 | border-width: 1px; 1789 | font-family: "Courier New", monospace; 1790 | font-size: 0.9em; 1791 | margin: 0 0.25em; 1792 | padding: 0.25em 0.65em; 1793 | } 1794 | 1795 | pre { 1796 | -webkit-overflow-scrolling: touch; 1797 | font-family: "Courier New", monospace; 1798 | font-size: 0.9em; 1799 | margin: 0 0 2em 0; 1800 | } 1801 | 1802 | pre code { 1803 | display: block; 1804 | line-height: 1.75em; 1805 | padding: 1em 1.5em; 1806 | overflow-x: auto; 1807 | } 1808 | 1809 | hr { 1810 | border: 0; 1811 | border-bottom-style: solid; 1812 | border-bottom-width: 1px; 1813 | margin: 2em 0; 1814 | } 1815 | 1816 | hr.major { 1817 | margin: 3em 0; 1818 | } 1819 | 1820 | .align-left { 1821 | text-align: left; 1822 | } 1823 | 1824 | .align-center { 1825 | text-align: center; 1826 | } 1827 | 1828 | .align-right { 1829 | text-align: right; 1830 | } 1831 | 1832 | input, select, textarea { 1833 | color: #999999; 1834 | } 1835 | 1836 | a { 1837 | color: inherit; 1838 | border-bottom-color: #d6d6d6; 1839 | } 1840 | 1841 | a:hover { 1842 | color: #4696e5; 1843 | } 1844 | 1845 | strong, b { 1846 | color: #828282; 1847 | } 1848 | 1849 | h1, h2, h3, h4, h5, h6 { 1850 | color: #828282; 1851 | } 1852 | 1853 | blockquote { 1854 | border-left-color: #e6e6e6; 1855 | } 1856 | 1857 | code { 1858 | background: rgba(144, 144, 144, 0.075); 1859 | border-color: #e6e6e6; 1860 | } 1861 | 1862 | hr { 1863 | border-bottom-color: #e6e6e6; 1864 | } 1865 | 1866 | /* Box */ 1867 | 1868 | .box { 1869 | border-radius: 6px; 1870 | border: solid 1px #e6e6e6; 1871 | margin-bottom: 2em; 1872 | padding: 1.5em; 1873 | } 1874 | 1875 | .box > :last-child, 1876 | .box > :last-child > :last-child, 1877 | .box > :last-child > :last-child > :last-child { 1878 | margin-bottom: 0; 1879 | } 1880 | 1881 | .box.alt { 1882 | border: 0; 1883 | border-radius: 0; 1884 | padding: 0; 1885 | } 1886 | 1887 | /* Button */ 1888 | 1889 | input[type="submit"], 1890 | input[type="reset"], 1891 | input[type="button"], 1892 | button, 1893 | .button { 1894 | -moz-appearance: none; 1895 | -webkit-appearance: none; 1896 | -ms-appearance: none; 1897 | appearance: none; 1898 | -moz-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; 1899 | -webkit-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; 1900 | -ms-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; 1901 | transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; 1902 | border-radius: 6px; 1903 | border: 0; 1904 | cursor: pointer; 1905 | display: inline-block; 1906 | font-weight: bold; 1907 | height: 2.85em; 1908 | line-height: 2.95em; 1909 | padding: 0 1.75em; 1910 | text-align: center; 1911 | text-decoration: none; 1912 | white-space: nowrap; 1913 | } 1914 | 1915 | input[type="submit"].icon, 1916 | input[type="reset"].icon, 1917 | input[type="button"].icon, 1918 | button.icon, 1919 | .button.icon { 1920 | padding-left: 1.35em; 1921 | } 1922 | 1923 | input[type="submit"].icon:before, 1924 | input[type="reset"].icon:before, 1925 | input[type="button"].icon:before, 1926 | button.icon:before, 1927 | .button.icon:before { 1928 | margin-right: 0.5em; 1929 | } 1930 | 1931 | input[type="submit"].fit, 1932 | input[type="reset"].fit, 1933 | input[type="button"].fit, 1934 | button.fit, 1935 | .button.fit { 1936 | display: block; 1937 | margin: 0 0 1em 0; 1938 | width: 100%; 1939 | } 1940 | 1941 | input[type="submit"].small, 1942 | input[type="reset"].small, 1943 | input[type="button"].small, 1944 | button.small, 1945 | .button.small { 1946 | font-size: 0.8em; 1947 | } 1948 | 1949 | input[type="submit"].big, 1950 | input[type="reset"].big, 1951 | input[type="button"].big, 1952 | button.big, 1953 | .button.big { 1954 | font-size: 1.35em; 1955 | } 1956 | 1957 | input[type="submit"].disabled, input[type="submit"]:disabled, 1958 | input[type="reset"].disabled, 1959 | input[type="reset"]:disabled, 1960 | input[type="button"].disabled, 1961 | input[type="button"]:disabled, 1962 | button.disabled, 1963 | button:disabled, 1964 | .button.disabled, 1965 | .button:disabled { 1966 | -moz-pointer-events: none; 1967 | -webkit-pointer-events: none; 1968 | -ms-pointer-events: none; 1969 | pointer-events: none; 1970 | cursor: default; 1971 | opacity: 0.25; 1972 | } 1973 | 1974 | @media screen and (max-width: 480px) and (orientation: portrait) { 1975 | 1976 | input[type="submit"], 1977 | input[type="reset"], 1978 | input[type="button"], 1979 | button, 1980 | .button { 1981 | padding: 0; 1982 | } 1983 | 1984 | } 1985 | 1986 | input[type="submit"], 1987 | input[type="reset"], 1988 | input[type="button"], 1989 | button, 1990 | .button { 1991 | background-color: transparent; 1992 | color: #828282 !important; 1993 | box-shadow: inset 0 0 0 2px #e6e6e6; 1994 | } 1995 | 1996 | input[type="submit"]:hover, 1997 | input[type="reset"]:hover, 1998 | input[type="button"]:hover, 1999 | button:hover, 2000 | .button:hover { 2001 | background-color: rgba(144, 144, 144, 0.075); 2002 | } 2003 | 2004 | input[type="submit"]:active, 2005 | input[type="reset"]:active, 2006 | input[type="button"]:active, 2007 | button:active, 2008 | .button:active { 2009 | background-color: rgba(144, 144, 144, 0.15); 2010 | } 2011 | 2012 | input[type="submit"].special, 2013 | input[type="reset"].special, 2014 | input[type="button"].special, 2015 | button.special, 2016 | .button.special { 2017 | box-shadow: none; 2018 | background-color: #4696e5; 2019 | color: #ffffff !important; 2020 | } 2021 | 2022 | input[type="submit"].special:hover, 2023 | input[type="reset"].special:hover, 2024 | input[type="button"].special:hover, 2025 | button.special:hover, 2026 | .button.special:hover { 2027 | background-color: #5ca3e8; 2028 | } 2029 | 2030 | input[type="submit"].special:active, 2031 | input[type="reset"].special:active, 2032 | input[type="button"].special:active, 2033 | button.special:active, 2034 | .button.special:active { 2035 | background-color: #3089e2; 2036 | } 2037 | 2038 | /* Form */ 2039 | 2040 | form { 2041 | margin: 0 0 2em 0; 2042 | } 2043 | 2044 | label { 2045 | display: block; 2046 | font-size: 0.9em; 2047 | font-weight: bold; 2048 | margin: 0 0 1em 0; 2049 | } 2050 | 2051 | input[type="text"], 2052 | input[type="password"], 2053 | input[type="email"], 2054 | select, 2055 | textarea { 2056 | -moz-appearance: none; 2057 | -webkit-appearance: none; 2058 | -ms-appearance: none; 2059 | appearance: none; 2060 | border-radius: 6px; 2061 | border: none; 2062 | border-style: solid; 2063 | border-width: 1px; 2064 | color: inherit; 2065 | display: block; 2066 | outline: 0; 2067 | padding: 0 1em; 2068 | text-decoration: none; 2069 | width: 100%; 2070 | } 2071 | 2072 | input[type="text"]:invalid, 2073 | input[type="password"]:invalid, 2074 | input[type="email"]:invalid, 2075 | select:invalid, 2076 | textarea:invalid { 2077 | box-shadow: none; 2078 | } 2079 | 2080 | .select-wrapper { 2081 | text-decoration: none; 2082 | display: block; 2083 | position: relative; 2084 | } 2085 | 2086 | .select-wrapper:before { 2087 | -moz-osx-font-smoothing: grayscale; 2088 | -webkit-font-smoothing: antialiased; 2089 | font-family: FontAwesome; 2090 | font-style: normal; 2091 | font-weight: normal; 2092 | text-transform: none !important; 2093 | } 2094 | 2095 | .select-wrapper:before { 2096 | content: '\f078'; 2097 | display: block; 2098 | height: 2.75em; 2099 | line-height: 2.75em; 2100 | pointer-events: none; 2101 | position: absolute; 2102 | right: 0; 2103 | text-align: center; 2104 | top: 0; 2105 | width: 2.75em; 2106 | } 2107 | 2108 | .select-wrapper select::-ms-expand { 2109 | display: none; 2110 | } 2111 | 2112 | input[type="text"], 2113 | input[type="password"], 2114 | input[type="email"], 2115 | select { 2116 | height: 2.75em; 2117 | } 2118 | 2119 | textarea { 2120 | padding: 0.75em 1em; 2121 | } 2122 | 2123 | input[type="checkbox"], 2124 | input[type="radio"] { 2125 | -moz-appearance: none; 2126 | -webkit-appearance: none; 2127 | -ms-appearance: none; 2128 | appearance: none; 2129 | display: block; 2130 | float: left; 2131 | margin-right: -2em; 2132 | opacity: 0; 2133 | width: 1em; 2134 | z-index: -1; 2135 | } 2136 | 2137 | input[type="checkbox"] + label, 2138 | input[type="radio"] + label { 2139 | text-decoration: none; 2140 | cursor: pointer; 2141 | display: inline-block; 2142 | font-size: 1em; 2143 | font-weight: normal; 2144 | padding-left: 2.4em; 2145 | padding-right: 0.75em; 2146 | position: relative; 2147 | } 2148 | 2149 | input[type="checkbox"] + label:before, 2150 | input[type="radio"] + label:before { 2151 | -moz-osx-font-smoothing: grayscale; 2152 | -webkit-font-smoothing: antialiased; 2153 | font-family: FontAwesome; 2154 | font-style: normal; 2155 | font-weight: normal; 2156 | text-transform: none !important; 2157 | } 2158 | 2159 | input[type="checkbox"] + label:before, 2160 | input[type="radio"] + label:before { 2161 | border-radius: 6px; 2162 | border-style: solid; 2163 | border-width: 1px; 2164 | content: ''; 2165 | display: inline-block; 2166 | height: 1.65em; 2167 | left: 0; 2168 | line-height: 1.58125em; 2169 | position: absolute; 2170 | text-align: center; 2171 | top: 0; 2172 | width: 1.65em; 2173 | } 2174 | 2175 | input[type="checkbox"]:checked + label:before, 2176 | input[type="radio"]:checked + label:before { 2177 | content: '\f00c'; 2178 | } 2179 | 2180 | input[type="checkbox"] + label:before { 2181 | border-radius: 6px; 2182 | } 2183 | 2184 | input[type="radio"] + label:before { 2185 | border-radius: 100%; 2186 | } 2187 | 2188 | ::-webkit-input-placeholder { 2189 | opacity: 1.0; 2190 | } 2191 | 2192 | :-moz-placeholder { 2193 | opacity: 1.0; 2194 | } 2195 | 2196 | ::-moz-placeholder { 2197 | opacity: 1.0; 2198 | } 2199 | 2200 | :-ms-input-placeholder { 2201 | opacity: 1.0; 2202 | } 2203 | 2204 | .formerize-placeholder { 2205 | opacity: 1.0; 2206 | } 2207 | 2208 | label { 2209 | color: #828282; 2210 | } 2211 | 2212 | input[type="text"], 2213 | input[type="password"], 2214 | input[type="email"], 2215 | select, 2216 | textarea { 2217 | color: inherit; 2218 | background-color: rgba(144, 144, 144, 0.075); 2219 | border-color: #e6e6e6; 2220 | } 2221 | 2222 | input[type="text"]:focus, 2223 | input[type="password"]:focus, 2224 | input[type="email"]:focus, 2225 | select:focus, 2226 | textarea:focus { 2227 | border-color: #4696e5; 2228 | box-shadow: 0 0 0 1px #4696e5; 2229 | } 2230 | 2231 | .select-wrapper:before { 2232 | color: #e6e6e6; 2233 | } 2234 | 2235 | input[type="checkbox"] + label, 2236 | input[type="radio"] + label { 2237 | color: #999999; 2238 | } 2239 | 2240 | input[type="checkbox"] + label:before, 2241 | input[type="radio"] + label:before { 2242 | background-color: rgba(144, 144, 144, 0.075); 2243 | border-color: #e6e6e6; 2244 | } 2245 | 2246 | input[type="checkbox"]:checked + label:before, 2247 | input[type="radio"]:checked + label:before { 2248 | background-color: #4696e5; 2249 | border-color: #4696e5; 2250 | color: #ffffff; 2251 | } 2252 | 2253 | input[type="checkbox"]:focus + label:before, 2254 | input[type="radio"]:focus + label:before { 2255 | border-color: #4696e5; 2256 | box-shadow: 0 0 0 1px #4696e5; 2257 | } 2258 | 2259 | ::-webkit-input-placeholder { 2260 | color: #e0e0e0 !important; 2261 | } 2262 | 2263 | :-moz-placeholder { 2264 | color: #e0e0e0 !important; 2265 | } 2266 | 2267 | ::-moz-placeholder { 2268 | color: #e0e0e0 !important; 2269 | } 2270 | 2271 | :-ms-input-placeholder { 2272 | color: #e0e0e0 !important; 2273 | } 2274 | 2275 | .formerize-placeholder { 2276 | color: #e0e0e0 !important; 2277 | } 2278 | 2279 | /* Icon */ 2280 | 2281 | .icon { 2282 | text-decoration: none; 2283 | border-bottom: none; 2284 | position: relative; 2285 | } 2286 | 2287 | .icon:before { 2288 | -moz-osx-font-smoothing: grayscale; 2289 | -webkit-font-smoothing: antialiased; 2290 | font-family: FontAwesome; 2291 | font-style: normal; 2292 | font-weight: normal; 2293 | text-transform: none !important; 2294 | } 2295 | 2296 | .icon > .label { 2297 | display: none; 2298 | } 2299 | 2300 | .icon { 2301 | color: #e0e0e0; 2302 | } 2303 | 2304 | /* Image */ 2305 | 2306 | .image { 2307 | border-radius: 6px; 2308 | border: 0; 2309 | display: inline-block; 2310 | position: relative; 2311 | overflow: hidden; 2312 | } 2313 | 2314 | .image img { 2315 | border-radius: 6px; 2316 | display: block; 2317 | } 2318 | 2319 | .image.left, .image.right { 2320 | max-width: 40%; 2321 | } 2322 | 2323 | .image.left img, .image.right img { 2324 | width: 100%; 2325 | } 2326 | 2327 | .image.left { 2328 | float: left; 2329 | margin: 0 1.5em 1em 0; 2330 | top: 0.25em; 2331 | } 2332 | 2333 | .image.right { 2334 | float: right; 2335 | margin: 0 0 1em 1.5em; 2336 | top: 0.25em; 2337 | } 2338 | 2339 | .image.fit { 2340 | display: block; 2341 | margin: 0 0 2em 0; 2342 | width: 100%; 2343 | } 2344 | 2345 | .image.fit img { 2346 | width: 100%; 2347 | } 2348 | 2349 | .image.main { 2350 | display: block; 2351 | margin: 0 0 3em 0; 2352 | width: 100%; 2353 | } 2354 | 2355 | .image.main img { 2356 | width: 100%; 2357 | } 2358 | 2359 | .image.phone { 2360 | box-shadow: none; 2361 | border-radius: 0; 2362 | margin: 0 0 3em 0; 2363 | width: 13em; 2364 | } 2365 | 2366 | .image.phone img { 2367 | border-radius: 0; 2368 | display: block; 2369 | position: relative; 2370 | width: 100%; 2371 | } 2372 | 2373 | .image.phone .inner, .image.phone:before, .image.phone:after { 2374 | display: block; 2375 | border: solid 2px rgba(255, 255, 255, 0.25); 2376 | } 2377 | 2378 | .image.phone .inner { 2379 | position: relative; 2380 | } 2381 | 2382 | .image.phone .inner:before, .image.phone .inner:after { 2383 | content: ''; 2384 | position: absolute; 2385 | left: 50%; 2386 | } 2387 | 2388 | .image.phone .inner:before { 2389 | top: -1.375em; 2390 | margin-left: -1em; 2391 | width: 2em; 2392 | height: 0.25em; 2393 | border-radius: 0.5em; 2394 | background: rgba(255, 255, 255, 0.25); 2395 | } 2396 | 2397 | .image.phone .inner:after { 2398 | bottom: -2.75em; 2399 | margin-left: -1em; 2400 | width: 2em; 2401 | height: 2em; 2402 | border-radius: 100%; 2403 | border: solid 2px rgba(255, 255, 255, 0.25); 2404 | } 2405 | 2406 | .image.phone:before, .image.phone:after { 2407 | content: ''; 2408 | } 2409 | 2410 | .image.phone:before { 2411 | height: 2.5em; 2412 | border-radius: 1em 1em 0 0; 2413 | border-bottom: 0; 2414 | } 2415 | 2416 | .image.phone:after { 2417 | height: 3.5em; 2418 | border-radius: 0 0 1em 1em; 2419 | border-top: 0; 2420 | } 2421 | 2422 | .image { 2423 | box-shadow: 0 0 0 4px #ffffff, 0 0 0 5px #e6e6e6; 2424 | } 2425 | 2426 | .image.phone { 2427 | box-shadow: none; 2428 | } 2429 | 2430 | .image.phone .inner, .image.phone:before, .image.phone:after { 2431 | border-color: #e6e6e6; 2432 | } 2433 | 2434 | .image.phone .inner:before { 2435 | background: #e6e6e6; 2436 | } 2437 | 2438 | .image.phone .inner:after { 2439 | border-color: #e6e6e6; 2440 | } 2441 | 2442 | /* List */ 2443 | 2444 | ol { 2445 | list-style: decimal; 2446 | margin: 0 0 2em 0; 2447 | padding-left: 1.25em; 2448 | } 2449 | 2450 | ol li { 2451 | padding-left: 0.25em; 2452 | } 2453 | 2454 | ul { 2455 | list-style: disc; 2456 | margin: 0 0 2em 0; 2457 | padding-left: 1em; 2458 | } 2459 | 2460 | ul li { 2461 | padding-left: 0.5em; 2462 | } 2463 | 2464 | ul.alt { 2465 | list-style: none; 2466 | padding-left: 0; 2467 | } 2468 | 2469 | ul.alt li { 2470 | border-top-style: solid; 2471 | border-top-width: 1px; 2472 | padding: 0.5em 0; 2473 | } 2474 | 2475 | ul.alt li:first-child { 2476 | border-top: 0; 2477 | padding-top: 0; 2478 | } 2479 | 2480 | ul.icons { 2481 | cursor: default; 2482 | list-style: none; 2483 | padding-left: 0; 2484 | } 2485 | 2486 | ul.icons li { 2487 | display: inline-block; 2488 | padding: 0 1.5em 0 0; 2489 | } 2490 | 2491 | ul.icons li:last-child { 2492 | padding-right: 0 !important; 2493 | } 2494 | 2495 | ul.icons li .icon:before { 2496 | font-size: 1.75rem; 2497 | } 2498 | 2499 | ul.icons.major li { 2500 | padding: 0 2.5em 0 0; 2501 | } 2502 | 2503 | ul.icons.major li .icon:before { 2504 | font-size: 2.75rem; 2505 | } 2506 | 2507 | @media screen and (max-width: 736px) { 2508 | 2509 | ul.icons.major li { 2510 | padding: 0 1.25em 0 0; 2511 | } 2512 | 2513 | ul.icons.major li .icon:before { 2514 | font-size: 1.75rem; 2515 | } 2516 | 2517 | } 2518 | 2519 | ul.icons.labeled li { 2520 | margin: 1em 0; 2521 | padding: 0 2em 0 0; 2522 | } 2523 | 2524 | ul.icons.labeled li .icon:before { 2525 | vertical-align: middle; 2526 | font-size: 2.25rem; 2527 | margin-right: 0.5em; 2528 | } 2529 | 2530 | ul.icons.labeled li .icon .label { 2531 | display: inline-block; 2532 | vertical-align: middle; 2533 | color: #999999; 2534 | } 2535 | 2536 | @media screen and (max-width: 736px) and (orientation: portrait) { 2537 | 2538 | ul.icons.labeled { 2539 | text-align: left; 2540 | margin-right: auto; 2541 | margin-left: auto; 2542 | display: inline-block; 2543 | white-space: nowrap; 2544 | } 2545 | 2546 | ul.icons.labeled li { 2547 | display: block; 2548 | padding: 0; 2549 | margin: 1.5em 0 0 0; 2550 | } 2551 | 2552 | ul.icons.labeled li .icon:before { 2553 | width: 1.5em; 2554 | display: block; 2555 | float: left; 2556 | margin-right: 0; 2557 | } 2558 | 2559 | ul.icons.labeled li .icon:after { 2560 | content: ''; 2561 | display: block; 2562 | clear: both; 2563 | } 2564 | 2565 | ul.icons.labeled li:first-child { 2566 | margin-top: 0; 2567 | } 2568 | 2569 | } 2570 | 2571 | ul.actions { 2572 | cursor: default; 2573 | list-style: none; 2574 | padding-left: 0; 2575 | } 2576 | 2577 | ul.actions li { 2578 | display: inline-block; 2579 | padding: 0 1em 0 0; 2580 | vertical-align: middle; 2581 | } 2582 | 2583 | ul.actions li:last-child { 2584 | padding-right: 0; 2585 | } 2586 | 2587 | ul.actions.small li { 2588 | padding: 0 0.5em 0 0; 2589 | } 2590 | 2591 | ul.actions.vertical li { 2592 | display: block; 2593 | padding: 1em 0 0 0; 2594 | } 2595 | 2596 | ul.actions.vertical li:first-child { 2597 | padding-top: 0; 2598 | } 2599 | 2600 | ul.actions.vertical li > * { 2601 | margin-bottom: 0; 2602 | } 2603 | 2604 | ul.actions.vertical.small li { 2605 | padding: 0.5em 0 0 0; 2606 | } 2607 | 2608 | ul.actions.vertical.small li:first-child { 2609 | padding-top: 0; 2610 | } 2611 | 2612 | ul.actions.fit { 2613 | display: table; 2614 | margin-left: -1em; 2615 | padding: 0; 2616 | table-layout: fixed; 2617 | width: calc(100% + 1em); 2618 | } 2619 | 2620 | ul.actions.fit li { 2621 | display: table-cell; 2622 | padding: 0 0 0 1em; 2623 | } 2624 | 2625 | ul.actions.fit li > * { 2626 | margin-bottom: 0; 2627 | } 2628 | 2629 | ul.actions.fit.small { 2630 | margin-left: -0.5em; 2631 | width: calc(100% + 0.5em); 2632 | } 2633 | 2634 | ul.actions.fit.small li { 2635 | padding: 0 0 0 0.5em; 2636 | } 2637 | 2638 | @media screen and (max-width: 480px) and (orientation: portrait) { 2639 | 2640 | ul.actions { 2641 | margin: 0 0 2em 0; 2642 | } 2643 | 2644 | ul.actions li { 2645 | padding: 1em 0 0 0; 2646 | display: block; 2647 | text-align: center; 2648 | width: 100%; 2649 | } 2650 | 2651 | ul.actions li:first-child { 2652 | padding-top: 0; 2653 | } 2654 | 2655 | ul.actions li > * { 2656 | width: 100%; 2657 | margin: 0 !important; 2658 | } 2659 | 2660 | ul.actions li > *.icon:before { 2661 | margin-left: -2em; 2662 | } 2663 | 2664 | ul.actions.small li { 2665 | padding: 0.5em 0 0 0; 2666 | } 2667 | 2668 | ul.actions.small li:first-child { 2669 | padding-top: 0; 2670 | } 2671 | 2672 | } 2673 | 2674 | dl { 2675 | margin: 0 0 2em 0; 2676 | } 2677 | 2678 | dl dt { 2679 | display: block; 2680 | font-weight: bold; 2681 | margin: 0 0 1em 0; 2682 | } 2683 | 2684 | dl dd { 2685 | margin-left: 2em; 2686 | } 2687 | 2688 | ul.alt > li { 2689 | border-top-color: #e6e6e6; 2690 | } 2691 | 2692 | /* Section/Article */ 2693 | 2694 | section.special, article.special { 2695 | text-align: center; 2696 | } 2697 | 2698 | header p { 2699 | position: relative; 2700 | margin: 0 0 1.5em 0; 2701 | } 2702 | 2703 | @media screen and (max-width: 736px) { 2704 | 2705 | header p br { 2706 | display: none; 2707 | } 2708 | 2709 | } 2710 | 2711 | header h2 + p { 2712 | font-size: 1.25em; 2713 | margin-top: -0.5em; 2714 | line-height: 1.5em; 2715 | } 2716 | 2717 | header h3 + p { 2718 | font-size: 1.1em; 2719 | margin-top: -0.25em; 2720 | line-height: 1.5em; 2721 | } 2722 | 2723 | header h4 + p, 2724 | header h5 + p, 2725 | header h6 + p { 2726 | font-size: 0.9em; 2727 | margin-top: -0.6em; 2728 | line-height: 1.5em; 2729 | } 2730 | 2731 | header.major { 2732 | margin: 0 0 2.5em 0; 2733 | text-align: center; 2734 | } 2735 | 2736 | header.major:after { 2737 | content: ''; 2738 | border-bottom: solid 2px #e6e6e6; 2739 | display: block; 2740 | width: 4em; 2741 | margin: 2em auto 0 auto; 2742 | } 2743 | 2744 | @media screen and (max-width: 736px) { 2745 | 2746 | header.major { 2747 | margin: 0 0 2em 0; 2748 | } 2749 | 2750 | header.major p { 2751 | font-size: 1em; 2752 | } 2753 | 2754 | } 2755 | 2756 | /* Spotlight */ 2757 | 2758 | .spotlight { 2759 | display: -moz-flex; 2760 | display: -webkit-flex; 2761 | display: -ms-flex; 2762 | display: flex; 2763 | -moz-align-items: center; 2764 | -webkit-align-items: center; 2765 | -ms-align-items: center; 2766 | align-items: center; 2767 | margin: 0 0 2em 0; 2768 | } 2769 | 2770 | .spotlight .image { 2771 | width: 30%; 2772 | border-radius: 100%; 2773 | margin: 0 3em 0 0; 2774 | display: block; 2775 | } 2776 | 2777 | .spotlight .image img { 2778 | display: block; 2779 | border-radius: 100%; 2780 | width: 100%; 2781 | } 2782 | 2783 | .spotlight .content { 2784 | width: 70%; 2785 | } 2786 | 2787 | .spotlight .content > :last-child { 2788 | margin-bottom: 0; 2789 | } 2790 | 2791 | .spotlight:nth-child(2n) { 2792 | -moz-flex-direction: row-reverse; 2793 | -webkit-flex-direction: row-reverse; 2794 | -ms-flex-direction: row-reverse; 2795 | flex-direction: row-reverse; 2796 | } 2797 | 2798 | .spotlight:nth-child(2n) .image { 2799 | margin: 0 0 0 3em; 2800 | } 2801 | 2802 | .spotlight:nth-child(2n) .content { 2803 | text-align: right; 2804 | } 2805 | 2806 | @media screen and (max-width: 736px) and (orientation: landscape) { 2807 | 2808 | .spotlight .image { 2809 | margin: 0 2em 0 0; 2810 | } 2811 | 2812 | .spotlight:nth-child(2n) .image { 2813 | margin: 0 0 0 2em; 2814 | } 2815 | 2816 | } 2817 | 2818 | @media screen and (max-width: 736px) and (orientation: portrait) { 2819 | 2820 | .spotlight { 2821 | -moz-flex-direction: column !important; 2822 | -webkit-flex-direction: column !important; 2823 | -ms-flex-direction: column !important; 2824 | flex-direction: column !important; 2825 | } 2826 | 2827 | .spotlight .image { 2828 | width: 100%; 2829 | max-width: 60%; 2830 | margin: 0 0 2em 0 !important; 2831 | } 2832 | 2833 | .spotlight .content { 2834 | width: 100%; 2835 | text-align: center !important; 2836 | } 2837 | 2838 | } 2839 | 2840 | /* Table */ 2841 | 2842 | .table-wrapper { 2843 | -webkit-overflow-scrolling: touch; 2844 | overflow-x: auto; 2845 | } 2846 | 2847 | table { 2848 | margin: 0 0 2em 0; 2849 | width: 100%; 2850 | } 2851 | 2852 | table tbody tr { 2853 | border-style: solid; 2854 | border-width: 1px; 2855 | border-left: 0; 2856 | border-right: 0; 2857 | } 2858 | 2859 | table td { 2860 | padding: 0.75em 0.75em; 2861 | } 2862 | 2863 | table th { 2864 | font-size: 0.9em; 2865 | font-weight: bold; 2866 | padding: 0 0.75em 0.75em 0.75em; 2867 | text-align: left; 2868 | } 2869 | 2870 | table thead { 2871 | border-bottom-style: solid; 2872 | border-bottom-width: 2px; 2873 | } 2874 | 2875 | table tfoot { 2876 | border-top-style: solid; 2877 | border-top-width: 2px; 2878 | } 2879 | 2880 | table.alt { 2881 | border-collapse: separate; 2882 | } 2883 | 2884 | table.alt tbody tr td { 2885 | border-style: solid; 2886 | border-width: 1px; 2887 | border-left-width: 0; 2888 | border-top-width: 0; 2889 | } 2890 | 2891 | table.alt tbody tr td:first-child { 2892 | border-left-width: 1px; 2893 | } 2894 | 2895 | table.alt tbody tr:first-child td { 2896 | border-top-width: 1px; 2897 | } 2898 | 2899 | table.alt thead { 2900 | border-bottom: 0; 2901 | } 2902 | 2903 | table.alt tfoot { 2904 | border-top: 0; 2905 | } 2906 | 2907 | table tbody tr { 2908 | border-color: #e6e6e6; 2909 | } 2910 | 2911 | table tbody tr:nth-child(2n + 1) { 2912 | background-color: rgba(144, 144, 144, 0.075); 2913 | } 2914 | 2915 | table th { 2916 | color: #828282; 2917 | } 2918 | 2919 | table thead { 2920 | border-bottom-color: #e6e6e6; 2921 | } 2922 | 2923 | table tfoot { 2924 | border-top-color: #e6e6e6; 2925 | } 2926 | 2927 | table.alt tbody tr td { 2928 | border-color: #e6e6e6; 2929 | } 2930 | 2931 | /* Wrapper */ 2932 | 2933 | .wrapper { 2934 | padding: 4.5em 0 2.5em 0 ; 2935 | background-color: #ffffff; 2936 | border-bottom: solid 2px #eeeeee; 2937 | } 2938 | 2939 | .wrapper > .inner { 2940 | margin-left: auto; 2941 | margin-right: auto; 2942 | width: 50em; 2943 | } 2944 | 2945 | .wrapper > .inner.alt > * { 2946 | border-top: solid 2px #eeeeee; 2947 | margin-bottom: 0; 2948 | margin-top: 3em; 2949 | padding-top: 3em; 2950 | } 2951 | 2952 | .wrapper > .inner.alt > *:first-child { 2953 | border-top: 0; 2954 | margin-top: 0; 2955 | padding-top: 0; 2956 | } 2957 | 2958 | .wrapper.style1 { 2959 | background-color: #4696e5; 2960 | color: #d0e4f8; 2961 | } 2962 | 2963 | .wrapper.style1 input[type="submit"], 2964 | .wrapper.style1 input[type="reset"], 2965 | .wrapper.style1 input[type="button"], 2966 | .wrapper.style1 button, 2967 | .wrapper.style1 .button { 2968 | background-color: transparent; 2969 | color: #ffffff !important; 2970 | box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.25); 2971 | } 2972 | 2973 | .wrapper.style1 input[type="submit"]:hover, 2974 | .wrapper.style1 input[type="reset"]:hover, 2975 | .wrapper.style1 input[type="button"]:hover, 2976 | .wrapper.style1 button:hover, 2977 | .wrapper.style1 .button:hover { 2978 | background-color: rgba(255, 255, 255, 0.075); 2979 | } 2980 | 2981 | .wrapper.style1 input[type="submit"]:active, 2982 | .wrapper.style1 input[type="reset"]:active, 2983 | .wrapper.style1 input[type="button"]:active, 2984 | .wrapper.style1 button:active, 2985 | .wrapper.style1 .button:active { 2986 | background-color: rgba(255, 255, 255, 0.2); 2987 | } 2988 | 2989 | .wrapper.style1 input[type="submit"].special, 2990 | .wrapper.style1 input[type="reset"].special, 2991 | .wrapper.style1 input[type="button"].special, 2992 | .wrapper.style1 button.special, 2993 | .wrapper.style1 .button.special { 2994 | box-shadow: none; 2995 | background-color: #ffffff; 2996 | color: #4696e5 !important; 2997 | } 2998 | 2999 | .wrapper.style1 label { 3000 | color: #ffffff; 3001 | } 3002 | 3003 | .wrapper.style1 input[type="text"], 3004 | .wrapper.style1 input[type="password"], 3005 | .wrapper.style1 input[type="email"], 3006 | .wrapper.style1 select, 3007 | .wrapper.style1 textarea { 3008 | color: inherit; 3009 | background-color: rgba(255, 255, 255, 0.075); 3010 | border-color: rgba(255, 255, 255, 0.25); 3011 | } 3012 | 3013 | .wrapper.style1 input[type="text"]:focus, 3014 | .wrapper.style1 input[type="password"]:focus, 3015 | .wrapper.style1 input[type="email"]:focus, 3016 | .wrapper.style1 select:focus, 3017 | .wrapper.style1 textarea:focus { 3018 | border-color: #ffffff; 3019 | box-shadow: 0 0 0 1px #ffffff; 3020 | } 3021 | 3022 | .wrapper.style1 .select-wrapper:before { 3023 | color: rgba(255, 255, 255, 0.25); 3024 | } 3025 | 3026 | .wrapper.style1 input[type="checkbox"] + label, 3027 | .wrapper.style1 input[type="radio"] + label { 3028 | color: #d0e4f8; 3029 | } 3030 | 3031 | .wrapper.style1 input[type="checkbox"] + label:before, 3032 | .wrapper.style1 input[type="radio"] + label:before { 3033 | background-color: rgba(255, 255, 255, 0.075); 3034 | border-color: rgba(255, 255, 255, 0.25); 3035 | } 3036 | 3037 | .wrapper.style1 input[type="checkbox"]:checked + label:before, 3038 | .wrapper.style1 input[type="radio"]:checked + label:before { 3039 | background-color: #ffffff; 3040 | border-color: #ffffff; 3041 | color: #4696e5; 3042 | } 3043 | 3044 | .wrapper.style1 input[type="checkbox"]:focus + label:before, 3045 | .wrapper.style1 input[type="radio"]:focus + label:before { 3046 | border-color: #ffffff; 3047 | box-shadow: 0 0 0 1px #ffffff; 3048 | } 3049 | 3050 | .wrapper.style1 ::-webkit-input-placeholder { 3051 | color: #b5d5f4 !important; 3052 | } 3053 | 3054 | .wrapper.style1 :-moz-placeholder { 3055 | color: #b5d5f4 !important; 3056 | } 3057 | 3058 | .wrapper.style1 ::-moz-placeholder { 3059 | color: #b5d5f4 !important; 3060 | } 3061 | 3062 | .wrapper.style1 :-ms-input-placeholder { 3063 | color: #b5d5f4 !important; 3064 | } 3065 | 3066 | .wrapper.style1 .formerize-placeholder { 3067 | color: #b5d5f4 !important; 3068 | } 3069 | 3070 | .wrapper.style1 .icon { 3071 | color: #b5d5f4; 3072 | } 3073 | 3074 | .wrapper.style1 .image { 3075 | box-shadow: 0 0 0 4px #4696e5, 0 0 0 5px rgba(255, 255, 255, 0.25); 3076 | } 3077 | 3078 | .wrapper.style1 .image.phone { 3079 | box-shadow: none; 3080 | } 3081 | 3082 | .wrapper.style1 .image.phone .inner, .wrapper.style1 .image.phone:before, .wrapper.style1 .image.phone:after { 3083 | border-color: rgba(255, 255, 255, 0.25); 3084 | } 3085 | 3086 | .wrapper.style1 .image.phone .inner:before { 3087 | background: rgba(255, 255, 255, 0.25); 3088 | } 3089 | 3090 | .wrapper.style1 .image.phone .inner:after { 3091 | border-color: rgba(255, 255, 255, 0.25); 3092 | } 3093 | 3094 | .wrapper.style1 ul.alt > li { 3095 | border-top-color: rgba(255, 255, 255, 0.25); 3096 | } 3097 | 3098 | .wrapper.style1 table tbody tr { 3099 | border-color: rgba(255, 255, 255, 0.25); 3100 | } 3101 | 3102 | .wrapper.style1 table tbody tr:nth-child(2n + 1) { 3103 | background-color: rgba(255, 255, 255, 0.075); 3104 | } 3105 | 3106 | .wrapper.style1 table th { 3107 | color: #ffffff; 3108 | } 3109 | 3110 | .wrapper.style1 table thead { 3111 | border-bottom-color: rgba(255, 255, 255, 0.25); 3112 | } 3113 | 3114 | .wrapper.style1 table tfoot { 3115 | border-top-color: rgba(255, 255, 255, 0.25); 3116 | } 3117 | 3118 | .wrapper.style1 table.alt tbody tr td { 3119 | border-color: rgba(255, 255, 255, 0.25); 3120 | } 3121 | 3122 | .wrapper.style1 input, .wrapper.style1 select, .wrapper.style1 textarea { 3123 | color: #d0e4f8; 3124 | } 3125 | 3126 | .wrapper.style1 a { 3127 | color: inherit; 3128 | border-bottom-color: rgba(255, 255, 255, 0.5); 3129 | color: #ffffff; 3130 | } 3131 | 3132 | .wrapper.style1 strong, .wrapper.style1 b { 3133 | color: #ffffff; 3134 | } 3135 | 3136 | .wrapper.style1 h1, .wrapper.style1 h2, .wrapper.style1 h3, .wrapper.style1 h4, .wrapper.style1 h5, .wrapper.style1 h6 { 3137 | color: #ffffff; 3138 | } 3139 | 3140 | .wrapper.style1 blockquote { 3141 | border-left-color: rgba(255, 255, 255, 0.25); 3142 | } 3143 | 3144 | .wrapper.style1 code { 3145 | background: rgba(255, 255, 255, 0.075); 3146 | border-color: rgba(255, 255, 255, 0.25); 3147 | } 3148 | 3149 | .wrapper.style1 hr { 3150 | border-bottom-color: rgba(255, 255, 255, 0.25); 3151 | } 3152 | 3153 | .wrapper.style2 { 3154 | background-color: #fbfbfb; 3155 | color: #999999; 3156 | } 3157 | 3158 | .wrapper.style2 input[type="submit"], 3159 | .wrapper.style2 input[type="reset"], 3160 | .wrapper.style2 input[type="button"], 3161 | .wrapper.style2 button, 3162 | .wrapper.style2 .button { 3163 | background-color: transparent; 3164 | color: #828282 !important; 3165 | box-shadow: inset 0 0 0 2px #e6e6e6; 3166 | } 3167 | 3168 | .wrapper.style2 input[type="submit"]:hover, 3169 | .wrapper.style2 input[type="reset"]:hover, 3170 | .wrapper.style2 input[type="button"]:hover, 3171 | .wrapper.style2 button:hover, 3172 | .wrapper.style2 .button:hover { 3173 | background-color: rgba(144, 144, 144, 0.075); 3174 | } 3175 | 3176 | .wrapper.style2 input[type="submit"]:active, 3177 | .wrapper.style2 input[type="reset"]:active, 3178 | .wrapper.style2 input[type="button"]:active, 3179 | .wrapper.style2 button:active, 3180 | .wrapper.style2 .button:active { 3181 | background-color: rgba(144, 144, 144, 0.15); 3182 | } 3183 | 3184 | .wrapper.style2 input[type="submit"].special, 3185 | .wrapper.style2 input[type="reset"].special, 3186 | .wrapper.style2 input[type="button"].special, 3187 | .wrapper.style2 button.special, 3188 | .wrapper.style2 .button.special { 3189 | box-shadow: none; 3190 | background-color: #4696e5; 3191 | color: #ffffff !important; 3192 | } 3193 | 3194 | .wrapper.style2 input[type="submit"].special:hover, 3195 | .wrapper.style2 input[type="reset"].special:hover, 3196 | .wrapper.style2 input[type="button"].special:hover, 3197 | .wrapper.style2 button.special:hover, 3198 | .wrapper.style2 .button.special:hover { 3199 | background-color: #5ca3e8; 3200 | } 3201 | 3202 | .wrapper.style2 input[type="submit"].special:active, 3203 | .wrapper.style2 input[type="reset"].special:active, 3204 | .wrapper.style2 input[type="button"].special:active, 3205 | .wrapper.style2 button.special:active, 3206 | .wrapper.style2 .button.special:active { 3207 | background-color: #3089e2; 3208 | } 3209 | 3210 | .wrapper.style2 label { 3211 | color: #828282; 3212 | } 3213 | 3214 | .wrapper.style2 input[type="text"], 3215 | .wrapper.style2 input[type="password"], 3216 | .wrapper.style2 input[type="email"], 3217 | .wrapper.style2 select, 3218 | .wrapper.style2 textarea { 3219 | color: inherit; 3220 | background-color: rgba(144, 144, 144, 0.075); 3221 | border-color: #e6e6e6; 3222 | } 3223 | 3224 | .wrapper.style2 input[type="text"]:focus, 3225 | .wrapper.style2 input[type="password"]:focus, 3226 | .wrapper.style2 input[type="email"]:focus, 3227 | .wrapper.style2 select:focus, 3228 | .wrapper.style2 textarea:focus { 3229 | border-color: #4696e5; 3230 | box-shadow: 0 0 0 1px #4696e5; 3231 | } 3232 | 3233 | .wrapper.style2 .select-wrapper:before { 3234 | color: #e6e6e6; 3235 | } 3236 | 3237 | .wrapper.style2 input[type="checkbox"] + label, 3238 | .wrapper.style2 input[type="radio"] + label { 3239 | color: #999999; 3240 | } 3241 | 3242 | .wrapper.style2 input[type="checkbox"] + label:before, 3243 | .wrapper.style2 input[type="radio"] + label:before { 3244 | background-color: rgba(144, 144, 144, 0.075); 3245 | border-color: #e6e6e6; 3246 | } 3247 | 3248 | .wrapper.style2 input[type="checkbox"]:checked + label:before, 3249 | .wrapper.style2 input[type="radio"]:checked + label:before { 3250 | background-color: #4696e5; 3251 | border-color: #4696e5; 3252 | color: #ffffff; 3253 | } 3254 | 3255 | .wrapper.style2 input[type="checkbox"]:focus + label:before, 3256 | .wrapper.style2 input[type="radio"]:focus + label:before { 3257 | border-color: #4696e5; 3258 | box-shadow: 0 0 0 1px #4696e5; 3259 | } 3260 | 3261 | .wrapper.style2 ::-webkit-input-placeholder { 3262 | color: #e0e0e0 !important; 3263 | } 3264 | 3265 | .wrapper.style2 :-moz-placeholder { 3266 | color: #e0e0e0 !important; 3267 | } 3268 | 3269 | .wrapper.style2 ::-moz-placeholder { 3270 | color: #e0e0e0 !important; 3271 | } 3272 | 3273 | .wrapper.style2 :-ms-input-placeholder { 3274 | color: #e0e0e0 !important; 3275 | } 3276 | 3277 | .wrapper.style2 .formerize-placeholder { 3278 | color: #e0e0e0 !important; 3279 | } 3280 | 3281 | .wrapper.style2 .icon { 3282 | color: #e0e0e0; 3283 | } 3284 | 3285 | .wrapper.style2 .image { 3286 | box-shadow: 0 0 0 4px #fbfbfb, 0 0 0 5px #e6e6e6; 3287 | } 3288 | 3289 | .wrapper.style2 .image.phone { 3290 | box-shadow: none; 3291 | } 3292 | 3293 | .wrapper.style2 .image.phone .inner, .wrapper.style2 .image.phone:before, .wrapper.style2 .image.phone:after { 3294 | border-color: #e6e6e6; 3295 | } 3296 | 3297 | .wrapper.style2 .image.phone .inner:before { 3298 | background: #e6e6e6; 3299 | } 3300 | 3301 | .wrapper.style2 .image.phone .inner:after { 3302 | border-color: #e6e6e6; 3303 | } 3304 | 3305 | .wrapper.style2 ul.alt > li { 3306 | border-top-color: #e6e6e6; 3307 | } 3308 | 3309 | .wrapper.style2 table tbody tr { 3310 | border-color: #e6e6e6; 3311 | } 3312 | 3313 | .wrapper.style2 table tbody tr:nth-child(2n + 1) { 3314 | background-color: rgba(144, 144, 144, 0.075); 3315 | } 3316 | 3317 | .wrapper.style2 table th { 3318 | color: #828282; 3319 | } 3320 | 3321 | .wrapper.style2 table thead { 3322 | border-bottom-color: #e6e6e6; 3323 | } 3324 | 3325 | .wrapper.style2 table tfoot { 3326 | border-top-color: #e6e6e6; 3327 | } 3328 | 3329 | .wrapper.style2 table.alt tbody tr td { 3330 | border-color: #e6e6e6; 3331 | } 3332 | 3333 | .wrapper.style2 input, .wrapper.style2 select, .wrapper.style2 textarea { 3334 | color: #999999; 3335 | } 3336 | 3337 | .wrapper.style2 a { 3338 | color: inherit; 3339 | border-bottom-color: #d6d6d6; 3340 | } 3341 | 3342 | .wrapper.style2 a:hover { 3343 | color: #4696e5; 3344 | } 3345 | 3346 | .wrapper.style2 strong, .wrapper.style2 b { 3347 | color: #828282; 3348 | } 3349 | 3350 | .wrapper.style2 h1, .wrapper.style2 h2, .wrapper.style2 h3, .wrapper.style2 h4, .wrapper.style2 h5, .wrapper.style2 h6 { 3351 | color: #828282; 3352 | } 3353 | 3354 | .wrapper.style2 blockquote { 3355 | border-left-color: #e6e6e6; 3356 | } 3357 | 3358 | .wrapper.style2 code { 3359 | background: rgba(144, 144, 144, 0.075); 3360 | border-color: #e6e6e6; 3361 | } 3362 | 3363 | .wrapper.style2 hr { 3364 | border-bottom-color: #e6e6e6; 3365 | } 3366 | 3367 | .wrapper.style3 { 3368 | background-color: #f7f7f7; 3369 | color: #999999; 3370 | } 3371 | 3372 | .wrapper.style3 input[type="submit"], 3373 | .wrapper.style3 input[type="reset"], 3374 | .wrapper.style3 input[type="button"], 3375 | .wrapper.style3 button, 3376 | .wrapper.style3 .button { 3377 | background-color: transparent; 3378 | color: #828282 !important; 3379 | box-shadow: inset 0 0 0 2px #d6d6d6; 3380 | } 3381 | 3382 | .wrapper.style3 input[type="submit"]:hover, 3383 | .wrapper.style3 input[type="reset"]:hover, 3384 | .wrapper.style3 input[type="button"]:hover, 3385 | .wrapper.style3 button:hover, 3386 | .wrapper.style3 .button:hover { 3387 | background-color: rgba(144, 144, 144, 0.075); 3388 | } 3389 | 3390 | .wrapper.style3 input[type="submit"]:active, 3391 | .wrapper.style3 input[type="reset"]:active, 3392 | .wrapper.style3 input[type="button"]:active, 3393 | .wrapper.style3 button:active, 3394 | .wrapper.style3 .button:active { 3395 | background-color: rgba(144, 144, 144, 0.15); 3396 | } 3397 | 3398 | .wrapper.style3 input[type="submit"].special, 3399 | .wrapper.style3 input[type="reset"].special, 3400 | .wrapper.style3 input[type="button"].special, 3401 | .wrapper.style3 button.special, 3402 | .wrapper.style3 .button.special { 3403 | box-shadow: none; 3404 | background-color: #4696e5; 3405 | color: #ffffff !important; 3406 | } 3407 | 3408 | .wrapper.style3 input[type="submit"].special:hover, 3409 | .wrapper.style3 input[type="reset"].special:hover, 3410 | .wrapper.style3 input[type="button"].special:hover, 3411 | .wrapper.style3 button.special:hover, 3412 | .wrapper.style3 .button.special:hover { 3413 | background-color: #5ca3e8; 3414 | } 3415 | 3416 | .wrapper.style3 input[type="submit"].special:active, 3417 | .wrapper.style3 input[type="reset"].special:active, 3418 | .wrapper.style3 input[type="button"].special:active, 3419 | .wrapper.style3 button.special:active, 3420 | .wrapper.style3 .button.special:active { 3421 | background-color: #3089e2; 3422 | } 3423 | 3424 | .wrapper.style3 label { 3425 | color: #828282; 3426 | } 3427 | 3428 | .wrapper.style3 input[type="text"], 3429 | .wrapper.style3 input[type="password"], 3430 | .wrapper.style3 input[type="email"], 3431 | .wrapper.style3 select, 3432 | .wrapper.style3 textarea { 3433 | color: inherit; 3434 | background-color: rgba(144, 144, 144, 0.075); 3435 | border-color: #d6d6d6; 3436 | } 3437 | 3438 | .wrapper.style3 input[type="text"]:focus, 3439 | .wrapper.style3 input[type="password"]:focus, 3440 | .wrapper.style3 input[type="email"]:focus, 3441 | .wrapper.style3 select:focus, 3442 | .wrapper.style3 textarea:focus { 3443 | border-color: #4696e5; 3444 | box-shadow: 0 0 0 1px #4696e5; 3445 | } 3446 | 3447 | .wrapper.style3 .select-wrapper:before { 3448 | color: #d6d6d6; 3449 | } 3450 | 3451 | .wrapper.style3 input[type="checkbox"] + label, 3452 | .wrapper.style3 input[type="radio"] + label { 3453 | color: #999999; 3454 | } 3455 | 3456 | .wrapper.style3 input[type="checkbox"] + label:before, 3457 | .wrapper.style3 input[type="radio"] + label:before { 3458 | background-color: rgba(144, 144, 144, 0.075); 3459 | border-color: #d6d6d6; 3460 | } 3461 | 3462 | .wrapper.style3 input[type="checkbox"]:checked + label:before, 3463 | .wrapper.style3 input[type="radio"]:checked + label:before { 3464 | background-color: #4696e5; 3465 | border-color: #4696e5; 3466 | color: #ffffff; 3467 | } 3468 | 3469 | .wrapper.style3 input[type="checkbox"]:focus + label:before, 3470 | .wrapper.style3 input[type="radio"]:focus + label:before { 3471 | border-color: #4696e5; 3472 | box-shadow: 0 0 0 1px #4696e5; 3473 | } 3474 | 3475 | .wrapper.style3 ::-webkit-input-placeholder { 3476 | color: #b0b0b0 !important; 3477 | } 3478 | 3479 | .wrapper.style3 :-moz-placeholder { 3480 | color: #b0b0b0 !important; 3481 | } 3482 | 3483 | .wrapper.style3 ::-moz-placeholder { 3484 | color: #b0b0b0 !important; 3485 | } 3486 | 3487 | .wrapper.style3 :-ms-input-placeholder { 3488 | color: #b0b0b0 !important; 3489 | } 3490 | 3491 | .wrapper.style3 .formerize-placeholder { 3492 | color: #b0b0b0 !important; 3493 | } 3494 | 3495 | .wrapper.style3 .icon { 3496 | color: #b0b0b0; 3497 | } 3498 | 3499 | .wrapper.style3 .image { 3500 | box-shadow: 0 0 0 4px #f7f7f7, 0 0 0 5px #d6d6d6; 3501 | } 3502 | 3503 | .wrapper.style3 .image.phone { 3504 | box-shadow: none; 3505 | } 3506 | 3507 | .wrapper.style3 .image.phone .inner, .wrapper.style3 .image.phone:before, .wrapper.style3 .image.phone:after { 3508 | border-color: #d6d6d6; 3509 | } 3510 | 3511 | .wrapper.style3 .image.phone .inner:before { 3512 | background: #d6d6d6; 3513 | } 3514 | 3515 | .wrapper.style3 .image.phone .inner:after { 3516 | border-color: #d6d6d6; 3517 | } 3518 | 3519 | .wrapper.style3 ul.alt > li { 3520 | border-top-color: #d6d6d6; 3521 | } 3522 | 3523 | .wrapper.style3 table tbody tr { 3524 | border-color: #d6d6d6; 3525 | } 3526 | 3527 | .wrapper.style3 table tbody tr:nth-child(2n + 1) { 3528 | background-color: rgba(144, 144, 144, 0.075); 3529 | } 3530 | 3531 | .wrapper.style3 table th { 3532 | color: #828282; 3533 | } 3534 | 3535 | .wrapper.style3 table thead { 3536 | border-bottom-color: #d6d6d6; 3537 | } 3538 | 3539 | .wrapper.style3 table tfoot { 3540 | border-top-color: #d6d6d6; 3541 | } 3542 | 3543 | .wrapper.style3 table.alt tbody tr td { 3544 | border-color: #d6d6d6; 3545 | } 3546 | 3547 | .wrapper.style3 input, .wrapper.style3 select, .wrapper.style3 textarea { 3548 | color: #999999; 3549 | } 3550 | 3551 | .wrapper.style3 a { 3552 | color: inherit; 3553 | border-bottom-color: #c6c6c6; 3554 | } 3555 | 3556 | .wrapper.style3 a:hover { 3557 | color: #4696e5; 3558 | } 3559 | 3560 | .wrapper.style3 strong, .wrapper.style3 b { 3561 | color: #828282; 3562 | } 3563 | 3564 | .wrapper.style3 h1, .wrapper.style3 h2, .wrapper.style3 h3, .wrapper.style3 h4, .wrapper.style3 h5, .wrapper.style3 h6 { 3565 | color: #828282; 3566 | } 3567 | 3568 | .wrapper.style3 blockquote { 3569 | border-left-color: #d6d6d6; 3570 | } 3571 | 3572 | .wrapper.style3 code { 3573 | background: rgba(144, 144, 144, 0.075); 3574 | border-color: #d6d6d6; 3575 | } 3576 | 3577 | .wrapper.style3 hr { 3578 | border-bottom-color: #d6d6d6; 3579 | } 3580 | 3581 | @media screen and (max-width: 980px) { 3582 | 3583 | .wrapper { 3584 | padding: 4em 4em 2em 4em ; 3585 | } 3586 | 3587 | .wrapper > .inner { 3588 | width: 100%; 3589 | } 3590 | 3591 | } 3592 | 3593 | @media screen and (max-width: 736px) and (orientation: landscape) { 3594 | 3595 | .wrapper { 3596 | padding: 3em 3em 1em 3em ; 3597 | } 3598 | 3599 | } 3600 | 3601 | @media screen and (max-width: 736px) and (orientation: portrait) { 3602 | 3603 | .wrapper { 3604 | padding: 3em 1.5em 1em 1.5em ; 3605 | } 3606 | 3607 | } 3608 | 3609 | @media screen and (max-width: 480px) and (orientation: landscape) { 3610 | 3611 | .wrapper { 3612 | padding: 2em 1.5em 0.1em 1.5em ; 3613 | } 3614 | 3615 | } 3616 | 3617 | @media screen and (max-width: 480px) and (orientation: portrait) { 3618 | 3619 | .wrapper { 3620 | padding: 2em 1em 0.1em 1em ; 3621 | } 3622 | 3623 | } 3624 | 3625 | /* Header */ 3626 | 3627 | #header { 3628 | background-color: #4696e5; 3629 | color: #d0e4f8; 3630 | padding: 4.5em 0 2.5em 0 ; 3631 | -moz-align-items: center; 3632 | -webkit-align-items: center; 3633 | -ms-align-items: center; 3634 | align-items: center; 3635 | display: -moz-flex; 3636 | display: -webkit-flex; 3637 | display: -ms-flex; 3638 | display: flex; 3639 | -moz-justify-content: center; 3640 | -webkit-justify-content: center; 3641 | -ms-justify-content: center; 3642 | justify-content: center; 3643 | background-image: url("images/overlay.png"), url("images/pattern-size1.svg"); 3644 | background-position: top left, center center; 3645 | background-attachment: fixed, fixed; 3646 | background-size: auto, cover; 3647 | height: 100vh; 3648 | min-height: 35em; 3649 | } 3650 | 3651 | #header input[type="submit"], 3652 | #header input[type="reset"], 3653 | #header input[type="button"], 3654 | #header button, 3655 | #header .button { 3656 | background-color: transparent; 3657 | color: #ffffff !important; 3658 | box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.25); 3659 | } 3660 | 3661 | #header input[type="submit"]:hover, 3662 | #header input[type="reset"]:hover, 3663 | #header input[type="button"]:hover, 3664 | #header button:hover, 3665 | #header .button:hover { 3666 | background-color: rgba(255, 255, 255, 0.075); 3667 | } 3668 | 3669 | #header input[type="submit"]:active, 3670 | #header input[type="reset"]:active, 3671 | #header input[type="button"]:active, 3672 | #header button:active, 3673 | #header .button:active { 3674 | background-color: rgba(255, 255, 255, 0.2); 3675 | } 3676 | 3677 | #header input[type="submit"].special, 3678 | #header input[type="reset"].special, 3679 | #header input[type="button"].special, 3680 | #header button.special, 3681 | #header .button.special { 3682 | box-shadow: none; 3683 | background-color: #ffffff; 3684 | color: #4696e5 !important; 3685 | } 3686 | 3687 | #header label { 3688 | color: #ffffff; 3689 | } 3690 | 3691 | #header input[type="text"], 3692 | #header input[type="password"], 3693 | #header input[type="email"], 3694 | #header select, 3695 | #header textarea { 3696 | color: inherit; 3697 | background-color: rgba(255, 255, 255, 0.075); 3698 | border-color: rgba(255, 255, 255, 0.25); 3699 | } 3700 | 3701 | #header input[type="text"]:focus, 3702 | #header input[type="password"]:focus, 3703 | #header input[type="email"]:focus, 3704 | #header select:focus, 3705 | #header textarea:focus { 3706 | border-color: #ffffff; 3707 | box-shadow: 0 0 0 1px #ffffff; 3708 | } 3709 | 3710 | #header .select-wrapper:before { 3711 | color: rgba(255, 255, 255, 0.25); 3712 | } 3713 | 3714 | #header input[type="checkbox"] + label, 3715 | #header input[type="radio"] + label { 3716 | color: #d0e4f8; 3717 | } 3718 | 3719 | #header input[type="checkbox"] + label:before, 3720 | #header input[type="radio"] + label:before { 3721 | background-color: rgba(255, 255, 255, 0.075); 3722 | border-color: rgba(255, 255, 255, 0.25); 3723 | } 3724 | 3725 | #header input[type="checkbox"]:checked + label:before, 3726 | #header input[type="radio"]:checked + label:before { 3727 | background-color: #ffffff; 3728 | border-color: #ffffff; 3729 | color: #4696e5; 3730 | } 3731 | 3732 | #header input[type="checkbox"]:focus + label:before, 3733 | #header input[type="radio"]:focus + label:before { 3734 | border-color: #ffffff; 3735 | box-shadow: 0 0 0 1px #ffffff; 3736 | } 3737 | 3738 | #header ::-webkit-input-placeholder { 3739 | color: #b5d5f4 !important; 3740 | } 3741 | 3742 | #header :-moz-placeholder { 3743 | color: #b5d5f4 !important; 3744 | } 3745 | 3746 | #header ::-moz-placeholder { 3747 | color: #b5d5f4 !important; 3748 | } 3749 | 3750 | #header :-ms-input-placeholder { 3751 | color: #b5d5f4 !important; 3752 | } 3753 | 3754 | #header .formerize-placeholder { 3755 | color: #b5d5f4 !important; 3756 | } 3757 | 3758 | #header .icon { 3759 | color: #b5d5f4; 3760 | } 3761 | 3762 | #header .image { 3763 | box-shadow: 0 0 0 4px #4696e5, 0 0 0 5px rgba(255, 255, 255, 0.25); 3764 | } 3765 | 3766 | #header .image.phone { 3767 | box-shadow: none; 3768 | } 3769 | 3770 | #header .image.phone .inner, #header .image.phone:before, #header .image.phone:after { 3771 | border-color: rgba(255, 255, 255, 0.25); 3772 | } 3773 | 3774 | #header .image.phone .inner:before { 3775 | background: rgba(255, 255, 255, 0.25); 3776 | } 3777 | 3778 | #header .image.phone .inner:after { 3779 | border-color: rgba(255, 255, 255, 0.25); 3780 | } 3781 | 3782 | #header ul.alt > li { 3783 | border-top-color: rgba(255, 255, 255, 0.25); 3784 | } 3785 | 3786 | #header table tbody tr { 3787 | border-color: rgba(255, 255, 255, 0.25); 3788 | } 3789 | 3790 | #header table tbody tr:nth-child(2n + 1) { 3791 | background-color: rgba(255, 255, 255, 0.075); 3792 | } 3793 | 3794 | #header table th { 3795 | color: #ffffff; 3796 | } 3797 | 3798 | #header table thead { 3799 | border-bottom-color: rgba(255, 255, 255, 0.25); 3800 | } 3801 | 3802 | #header table tfoot { 3803 | border-top-color: rgba(255, 255, 255, 0.25); 3804 | } 3805 | 3806 | #header table.alt tbody tr td { 3807 | border-color: rgba(255, 255, 255, 0.25); 3808 | } 3809 | 3810 | #header input, #header select, #header textarea { 3811 | color: #d0e4f8; 3812 | } 3813 | 3814 | #header a { 3815 | color: inherit; 3816 | border-bottom-color: rgba(255, 255, 255, 0.5); 3817 | color: #ffffff; 3818 | } 3819 | 3820 | #header strong, #header b { 3821 | color: #ffffff; 3822 | } 3823 | 3824 | #header h1, #header h2, #header h3, #header h4, #header h5, #header h6 { 3825 | color: #ffffff; 3826 | } 3827 | 3828 | #header blockquote { 3829 | border-left-color: rgba(255, 255, 255, 0.25); 3830 | } 3831 | 3832 | #header code { 3833 | background: rgba(255, 255, 255, 0.075); 3834 | border-color: rgba(255, 255, 255, 0.25); 3835 | } 3836 | 3837 | #header hr { 3838 | border-bottom-color: rgba(255, 255, 255, 0.25); 3839 | } 3840 | 3841 | #header h1 { 3842 | font-size: 3.25em; 3843 | font-weight: bold; 3844 | margin-bottom: 0.5em; 3845 | } 3846 | 3847 | #header p { 3848 | font-size: 1.5em; 3849 | line-height: 1.35em; 3850 | } 3851 | 3852 | #header p br { 3853 | display: inline; 3854 | } 3855 | 3856 | #header .content { 3857 | -moz-transition: opacity 0.5s ease, -moz-transform 1s ease; 3858 | -webkit-transition: opacity 0.5s ease, -webkit-transform 1s ease; 3859 | -ms-transition: opacity 0.5s ease, -ms-transform 1s ease; 3860 | transition: opacity 0.5s ease, transform 1s ease; 3861 | -moz-transform: translateX(0); 3862 | -webkit-transform: translateX(0); 3863 | -ms-transform: translateX(0); 3864 | transform: translateX(0); 3865 | opacity: 1; 3866 | text-align: right; 3867 | margin: -3.5em 4em 0 0; 3868 | } 3869 | 3870 | #header .content > :last-child { 3871 | margin-bottom: 0; 3872 | } 3873 | 3874 | #header .image { 3875 | -moz-transition: opacity 1s ease, -moz-transform 1s ease; 3876 | -webkit-transition: opacity 1s ease, -webkit-transform 1s ease; 3877 | -ms-transition: opacity 1s ease, -ms-transform 1s ease; 3878 | transition: opacity 1s ease, transform 1s ease; 3879 | -moz-transform: translateY(0); 3880 | -webkit-transform: translateY(0); 3881 | -ms-transform: translateY(0); 3882 | transform: translateY(0); 3883 | opacity: 1; 3884 | } 3885 | 3886 | #header .image img { 3887 | -moz-transition: opacity 0.75s ease; 3888 | -webkit-transition: opacity 0.75s ease; 3889 | -ms-transition: opacity 0.75s ease; 3890 | transition: opacity 0.75s ease; 3891 | -moz-transition-delay: 0.75s; 3892 | -webkit-transition-delay: 0.75s; 3893 | -ms-transition-delay: 0.75s; 3894 | transition-delay: 0.75s; 3895 | opacity: 1; 3896 | } 3897 | 3898 | @media screen and (max-width: 1280px) { 3899 | 3900 | #header { 3901 | background-image: url("images/overlay.png"), url("images/pattern-size2.svg"); 3902 | } 3903 | 3904 | } 3905 | 3906 | @media screen and (max-width: 980px) { 3907 | 3908 | #header { 3909 | height: auto; 3910 | min-height: 0; 3911 | } 3912 | 3913 | #header .content { 3914 | margin: -2em 4em 0 0; 3915 | } 3916 | 3917 | } 3918 | 3919 | @media screen and (max-width: 980px) and (orientation: portrait) { 3920 | 3921 | #header { 3922 | padding: 6em 3em 4em 3em ; 3923 | -moz-flex-direction: column-reverse; 3924 | -webkit-flex-direction: column-reverse; 3925 | -ms-flex-direction: column-reverse; 3926 | flex-direction: column-reverse; 3927 | } 3928 | 3929 | #header .content { 3930 | display: block; 3931 | width: 100%; 3932 | text-align: center; 3933 | margin: 0 0 2em 0; 3934 | } 3935 | 3936 | #header .image { 3937 | overflow: hidden; 3938 | } 3939 | 3940 | } 3941 | 3942 | @media screen and (max-width: 736px) { 3943 | 3944 | #header { 3945 | background-image: url("images/overlay.png"), url("images/pattern-size3.svg"); 3946 | } 3947 | 3948 | #header h1 { 3949 | font-size: 2em; 3950 | } 3951 | 3952 | #header p { 3953 | font-size: 1em; 3954 | line-height: inherit; 3955 | } 3956 | 3957 | } 3958 | 3959 | @media screen and (max-width: 736px) and (orientation: landscape) { 3960 | 3961 | #header { 3962 | padding: 2em 2em 0.1em 2em ; 3963 | } 3964 | 3965 | #header .content { 3966 | margin: 0 2em 2em 0; 3967 | } 3968 | 3969 | #header .image { 3970 | font-size: 0.8em; 3971 | width: 15em; 3972 | max-width: 20vw; 3973 | } 3974 | 3975 | #header .image .inner, #header .image:before, #header .image:after { 3976 | font-size: 0.8em; 3977 | } 3978 | 3979 | } 3980 | 3981 | @media screen and (max-width: 736px) and (orientation: portrait) { 3982 | 3983 | #header { 3984 | padding: 3em 1.5em 1em 1.5em ; 3985 | } 3986 | 3987 | #header .image { 3988 | font-size: 0.6em; 3989 | max-width: 60vw; 3990 | } 3991 | 3992 | } 3993 | 3994 | @media screen and (max-width: 480px) and (orientation: landscape) { 3995 | 3996 | #header { 3997 | padding: 2em 1.5em 0.1em 1.5em ; 3998 | } 3999 | 4000 | #header .image { 4001 | font-size: 0.7em; 4002 | } 4003 | 4004 | #header .actions { 4005 | font-size: 0.8em; 4006 | } 4007 | 4008 | } 4009 | 4010 | @media screen and (max-width: 480px) and (orientation: portrait) { 4011 | 4012 | #header { 4013 | padding: 2em 1em 0.1em 1em ; 4014 | } 4015 | 4016 | } 4017 | 4018 | body.is-mobile #header { 4019 | background-attachment: scroll, scroll; 4020 | } 4021 | 4022 | body.is-loading #header .content { 4023 | -moz-transform: translateX(2em); 4024 | -webkit-transform: translateX(2em); 4025 | -ms-transform: translateX(2em); 4026 | transform: translateX(2em); 4027 | opacity: 0; 4028 | } 4029 | 4030 | body.is-loading #header .image { 4031 | -moz-transform: translateY(4em); 4032 | -webkit-transform: translateY(4em); 4033 | -ms-transform: translateY(4em); 4034 | transform: translateY(4em); 4035 | opacity: 0; 4036 | } 4037 | 4038 | body.is-loading #header .image img { 4039 | opacity: 0; 4040 | } 4041 | 4042 | @media screen and (max-width: 980px) and (orientation: portrait) { 4043 | 4044 | body.is-loading #header .content { 4045 | -moz-transform: none; 4046 | -webkit-transform: none; 4047 | -ms-transform: none; 4048 | transform: none; 4049 | opacity: 1; 4050 | } 4051 | 4052 | body.is-loading #header .image { 4053 | -moz-transform: translateY(2em); 4054 | -webkit-transform: translateY(2em); 4055 | -ms-transform: translateY(2em); 4056 | transform: translateY(2em); 4057 | } 4058 | 4059 | } 4060 | 4061 | /* Main */ 4062 | 4063 | #main { 4064 | padding: 4em 0 2em 0 ; 4065 | } 4066 | 4067 | @media screen and (max-width: 736px) { 4068 | 4069 | #main { 4070 | padding: 3em 0 1em 0 ; 4071 | } 4072 | 4073 | } 4074 | 4075 | /* Footer */ 4076 | 4077 | #footer { 4078 | background-color: #f7f7f7; 4079 | color: #999999; 4080 | padding: 4.5em 0 2.5em 0 ; 4081 | color: #b0b0b0; 4082 | text-align: center; 4083 | } 4084 | 4085 | #footer input, #footer select, #footer textarea { 4086 | color: #999999; 4087 | } 4088 | 4089 | #footer a { 4090 | color: inherit; 4091 | border-bottom-color: #c6c6c6; 4092 | } 4093 | 4094 | #footer a:hover { 4095 | color: #4696e5; 4096 | } 4097 | 4098 | #footer strong, #footer b { 4099 | color: #828282; 4100 | } 4101 | 4102 | #footer h1, #footer h2, #footer h3, #footer h4, #footer h5, #footer h6 { 4103 | color: #828282; 4104 | } 4105 | 4106 | #footer blockquote { 4107 | border-left-color: #d6d6d6; 4108 | } 4109 | 4110 | #footer code { 4111 | background: rgba(144, 144, 144, 0.075); 4112 | border-color: #d6d6d6; 4113 | } 4114 | 4115 | #footer hr { 4116 | border-bottom-color: #d6d6d6; 4117 | } 4118 | 4119 | #footer a { 4120 | color: inherit; 4121 | } 4122 | 4123 | #footer .copyright { 4124 | font-size: 0.8em; 4125 | } 4126 | 4127 | @media screen and (max-width: 980px) { 4128 | 4129 | #footer { 4130 | padding: 4em 4em 2em 4em ; 4131 | } 4132 | 4133 | } 4134 | 4135 | @media screen and (max-width: 736px) and (orientation: landscape) { 4136 | 4137 | #footer { 4138 | padding: 3em 3em 1em 3em ; 4139 | } 4140 | 4141 | } 4142 | 4143 | @media screen and (max-width: 736px) and (orientation: portrait) { 4144 | 4145 | #footer { 4146 | padding: 3em 1.5em 1em 1.5em ; 4147 | } 4148 | 4149 | } 4150 | --------------------------------------------------------------------------------