├── public ├── favicon.png ├── style │ ├── icon │ │ ├── todos.eot │ │ ├── todos.ttf │ │ ├── todos.woff │ │ └── todos.svg │ ├── font │ │ ├── OpenSans-Light-webfont.eot │ │ ├── OpenSans-Light-webfont.ttf │ │ ├── OpenSans-Light-webfont.woff │ │ ├── OpenSans-Regular-webfont.eot │ │ ├── OpenSans-Regular-webfont.ttf │ │ ├── OpenSans-Regular-webfont.woff │ │ └── OpenSans-Light-webfont.svg │ ├── main.css │ └── reset.css ├── apple-touch-icon-precomposed.png ├── index.html └── img │ └── logo-todos.svg ├── .gitignore ├── README.md ├── lib ├── util.js ├── constants.js └── store.js ├── server.js ├── webpack.config.js ├── client ├── views │ ├── Notifications.jsx │ ├── App.jsx │ ├── User.jsx │ ├── list │ │ ├── TaskItems.jsx │ │ ├── Tasks.jsx │ │ └── ListName.jsx │ ├── ListTodos.jsx │ ├── SignIn.jsx │ └── Join.jsx ├── index.jsx └── transfer.js ├── package.json └── server ├── data.js ├── transfer.js └── db.js /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobiblazeski/rio/HEAD/public/favicon.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | node_modules/ 3 | .brackets.json 4 | public/bundle.js 5 | rethinkdb_data/ -------------------------------------------------------------------------------- /public/style/icon/todos.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobiblazeski/rio/HEAD/public/style/icon/todos.eot -------------------------------------------------------------------------------- /public/style/icon/todos.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobiblazeski/rio/HEAD/public/style/icon/todos.ttf -------------------------------------------------------------------------------- /public/style/icon/todos.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobiblazeski/rio/HEAD/public/style/icon/todos.woff -------------------------------------------------------------------------------- /public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobiblazeski/rio/HEAD/public/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /public/style/font/OpenSans-Light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobiblazeski/rio/HEAD/public/style/font/OpenSans-Light-webfont.eot -------------------------------------------------------------------------------- /public/style/font/OpenSans-Light-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobiblazeski/rio/HEAD/public/style/font/OpenSans-Light-webfont.ttf -------------------------------------------------------------------------------- /public/style/font/OpenSans-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobiblazeski/rio/HEAD/public/style/font/OpenSans-Light-webfont.woff -------------------------------------------------------------------------------- /public/style/font/OpenSans-Regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobiblazeski/rio/HEAD/public/style/font/OpenSans-Regular-webfont.eot -------------------------------------------------------------------------------- /public/style/font/OpenSans-Regular-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobiblazeski/rio/HEAD/public/style/font/OpenSans-Regular-webfont.ttf -------------------------------------------------------------------------------- /public/style/font/OpenSans-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobiblazeski/rio/HEAD/public/style/font/OpenSans-Regular-webfont.woff -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rio 2 | Port of meteor realtime todos application using RethinkDB, Rxjs, Socket.io & React 3 | 4 | Story https://medium.com/@bobiblazeski/of-pipes-and-feeds-6b443b9713e0 5 | -------------------------------------------------------------------------------- /lib/util.js: -------------------------------------------------------------------------------- 1 | var Util = module.exports = {}; 2 | 3 | var re = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i; 4 | 5 | Util.validateEmail = function validateEmail(email) { 6 | return re.test(email); 7 | }; 8 | 9 | Util.validatePassword = function validatePassword(password) { 10 | return R.is(String,password) && password.length > 3; 11 | }; 12 | 13 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var app = require('koa')(), 2 | http= require('http'), 3 | serve= require('koa-static'); 4 | 5 | 6 | app.use(serve(__dirname+'/public')); 7 | 8 | // This must come after last app.use() 9 | var server = http.Server(app.callback()); 10 | 11 | var transfer = require('./server/transfer'); 12 | transfer.setup(server); 13 | 14 | 15 | server.listen(4000); 16 | console.info('Now running on localhost:4000'); -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: './client/index.jsx', 3 | output: { 4 | path:__dirname+'/public', 5 | filename: "bundle.js" 6 | }, 7 | module: { 8 | loaders: [ 9 | { 10 | test: /\.jsx$/, 11 | loader: 'babel-loader' 12 | } 13 | ] 14 | }, 15 | externals: { 16 | 'react': 'React', 17 | 'rx':'Rx', 18 | 'ramda':'R', 19 | 'immutable':'Immutable' 20 | }, 21 | resolve: { 22 | extensions: ['','.js','.jsx'] 23 | } 24 | }; -------------------------------------------------------------------------------- /client/views/Notifications.jsx: -------------------------------------------------------------------------------- 1 | var Notifications = module.exports = React.createClass({ 2 | render : function(){ 3 | return ( 4 |
5 |
6 | 7 |
8 |
Trying to connect
9 |
There seems to be a connection issue
10 |
11 |
12 |
13 | ); 14 | } 15 | }); -------------------------------------------------------------------------------- /lib/constants.js: -------------------------------------------------------------------------------- 1 | var Constants = module.exports = { 2 | sendAll: 'send all', 3 | 4 | taskChange: 'task change', 5 | taskCreate: 'task create', 6 | taskUpdate: 'task update', 7 | taskDelete: 'task delete', 8 | 9 | listChange: 'list change', 10 | listCreate: 'list create', 11 | listUpdate: 'list update', 12 | listDelete: 'list delete', 13 | 14 | signInRequest: 'signin request', 15 | signInResult: 'signin result', 16 | joinRequest: 'signup request', 17 | joinResult: 'signup result', 18 | clearAll: 'clear all', 19 | user: { email: '', id: '00000000-0000-0000-0000-000000000000'} 20 | }; 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rio", 3 | "version": "0.0.1", 4 | "scripts": { 5 | "start": "node server.js" 6 | }, 7 | "dependencies": { 8 | "async": "^1.0.0", 9 | "immutable": "^3.7.3", 10 | "koa": "^0.20.0", 11 | "koa-static": "^1.4.9", 12 | "ramda": "^0.14.0", 13 | "react": "^0.13.3", 14 | "react-router": "^0.13.3", 15 | "rethinkdbdash": "^2.0.11", 16 | "rx": "^2.5.2", 17 | "socket.io": "^1.3.5" 18 | }, 19 | "devDependencies": { 20 | "babel-core": "^5.4.7", 21 | "babel-loader": "^5.1.3", 22 | "node-libs-browser": "^0.5.2", 23 | "nodemon": "^1.3.7", 24 | "webpack": "^1.9.8" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Todos 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /client/views/App.jsx: -------------------------------------------------------------------------------- 1 | var { RouteHandler} = require('react-router'); 2 | 3 | var Notifications = require('./Notifications'); 4 | var ListTodos = require('./ListTodos'); 5 | var User = require('./User'); 6 | 7 | var App = module.exports = React.createClass({ 8 | render: function () { 9 | return ( 10 |
11 | 15 |
16 | 17 |
18 | 19 |
20 |
21 | ); 22 | } 23 | }); 24 | //Below
25 | // -------------------------------------------------------------------------------- /client/index.jsx: -------------------------------------------------------------------------------- 1 | var Router = require('react-router'); 2 | var { Route, Redirect, RouteHandler, DefaultRoute, Link} = Router; 3 | 4 | var App = require('./views/App'); 5 | var SignIn = require('./views/SignIn'); 6 | var Join = require('./views/Join'); 7 | var Tasks = require('./views/list/Tasks'); 8 | var Transfer = require('./transfer'); 9 | 10 | 11 | var routes = ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | 20 | Router.run(routes, Router.HistoryLocation, function(Handler){ 21 | React.render(, document.body) 22 | }); 23 | 24 | // -------------------------------------------------------------------------------- /lib/store.js: -------------------------------------------------------------------------------- 1 | var Rx = require('rx'); 2 | var Immutable = require('immutable'); 3 | var Constants = require('./constants'); 4 | 5 | var Store = module.exports = { 6 | user : new Rx.BehaviorSubject(Constants.user), // Client only 7 | allLists : new Rx.BehaviorSubject(Immutable.Map({})),// Client only 8 | allTasks : new Rx.BehaviorSubject(Immutable.Map({})),// Client only 9 | sendAll: new Rx.BehaviorSubject(), 10 | 11 | signInRequest : new Rx.BehaviorSubject(), 12 | signInResult : new Rx.BehaviorSubject(), 13 | joinRequest : new Rx.BehaviorSubject(), 14 | joinResult : new Rx.BehaviorSubject(), 15 | listChange : new Rx.BehaviorSubject(), 16 | listCreate : new Rx.BehaviorSubject(), 17 | listUpdate : new Rx.BehaviorSubject(), 18 | listDelete : new Rx.BehaviorSubject(), 19 | taskChange : new Rx.BehaviorSubject(), 20 | taskCreate : new Rx.BehaviorSubject(), 21 | taskUpdate : new Rx.BehaviorSubject(), 22 | taskDelete : new Rx.BehaviorSubject() 23 | }; -------------------------------------------------------------------------------- /client/views/User.jsx: -------------------------------------------------------------------------------- 1 | var { Link} = require('react-router'); 2 | 3 | var Store = require('../../lib/store'); 4 | var Constants = require('../../lib/constants'); 5 | 6 | var User = module.exports = React.createClass({ 7 | getInitialState: function () { 8 | return Store.user.value; 9 | }, 10 | componentWillMount: function () { 11 | 12 | this.onLogout = function(){ 13 | Store.user.onNext(Constants.user); 14 | } 15 | }, 16 | render: function () { 17 | return this.state.email === '' ? 18 | (
19 | Sign In 20 | Join 21 |
) : 22 | (); 29 | }, 30 | componentDidMount: function(){ 31 | Store.user.skip(1).subscribe(function(user){ 32 | console.log('User componentWillMount',user); 33 | this.setState(user); 34 | }.bind(this)); 35 | } 36 | 37 | }); 38 | 39 | -------------------------------------------------------------------------------- /client/views/list/TaskItems.jsx: -------------------------------------------------------------------------------- 1 | var Store = require('../../../lib/store'); 2 | 3 | var TaskItems = module.exports = React.createClass({ 4 | componentWillMount: function(){ 5 | this.onChecked = function(user,taskId,event) { 6 | Store.taskUpdate.onNext({ 7 | id: taskId, 8 | user: user, 9 | done: event.target.value 10 | }) 11 | }.bind(this); 12 | }, 13 | render: function(){ 14 | var items = this.props.tasks.map(function (d) { 15 | var key = d.user+':'+d.list+':'+d.item; 16 | return ( 17 |
18 | 25 | 26 | 27 | 28 | 29 |
30 | ); 31 | }.bind(this)); 32 | return ( 33 |
34 | {items} 35 |
36 | ); 37 | } 38 | }); -------------------------------------------------------------------------------- /client/views/list/Tasks.jsx: -------------------------------------------------------------------------------- 1 | var Store = require('../../../lib/store'); 2 | var TaskItems = require('./TaskItems.jsx'); 3 | var ListName = require('./ListName.jsx'); 4 | 5 | var Tasks = module.exports = React.createClass({ 6 | contextTypes: { 7 | router: React.PropTypes.func 8 | }, 9 | getInitialState: function () { 10 | return { 11 | lists: Store.allLists.value, 12 | tasks: Store.allTasks.value 13 | } 14 | }, 15 | componentWillMount: function () { 16 | Store.allLists.subscribe(function (lists) { 17 | this.setState({lists: lists}); 18 | }.bind(this)); 19 | Store.allTasks.subscribe(function (tasks) { 20 | this.setState({tasks: tasks}); 21 | }.bind(this)); 22 | }, 23 | render: function () { 24 | var nameParam = this.context.router.getCurrentParams().name; 25 | if (!nameParam && this.state.lists.count() > 0) { 26 | nameParam = this.state.lists.first().id; 27 | } 28 | var list = this.state.lists.get(nameParam) || {id: '', name: 'unknown'}; 29 | var tasksGrouped = R.groupBy(R.prop('list'), this.state.tasks.toArray()); 30 | var tasks = tasksGrouped.hasOwnProperty(nameParam) ? 31 | tasksGrouped[nameParam] : []; 32 | return ( 33 |
34 | 35 | 36 |
37 | ); 38 | } 39 | }); -------------------------------------------------------------------------------- /server/data.js: -------------------------------------------------------------------------------- 1 | var R = require('ramda'); 2 | var Constants = require('../lib/constants'); 3 | 4 | 5 | var lists = [ 6 | { 7 | user:Constants.user.id, 8 | name: "Meteor Principles", 9 | items: ["Data on the Wire", 10 | "One Language", 11 | "Database Everywhere", 12 | "Latency Compensation", 13 | "Full Stack Reactivity", 14 | "Embrace the Ecosystem", 15 | "Simplicity Equals Productivity" 16 | ] 17 | }, 18 | { 19 | user:Constants.user.id, 20 | name: "Languages", 21 | items: ["Lisp", 22 | "C", 23 | "C++", 24 | "Python", 25 | "Ruby", 26 | "JavaScript", 27 | "Scala", 28 | "Erlang", 29 | "6502 Assembly" 30 | ] 31 | }, 32 | { 33 | user:Constants.user.id, 34 | name: "Favorite Scientists", 35 | items: ["Ada Lovelace", 36 | "Grace Hopper", 37 | "Marie Curie", 38 | "Carl Friedrich Gauss", 39 | "Nikola Tesla", 40 | "Claude Shannon" 41 | ] 42 | } 43 | ]; 44 | 45 | exports.lists = R.map(R.pick(['name','user']),lists); 46 | 47 | exports.tasks = function (dbLists) { 48 | console.log(dbLists); 49 | return R.reduce(function(acc,d) { 50 | return acc.concat(R.map(function (e) { 51 | var dbList = R.find(function(dbEntry){ 52 | return dbEntry.name == d.name; 53 | },dbLists); 54 | return { 55 | user: Constants.user.id, 56 | list: dbList.id, 57 | item: e, 58 | done: false 59 | } 60 | }, d.items)); 61 | },[],lists); 62 | }; 63 | 64 | 65 | -------------------------------------------------------------------------------- /client/views/ListTodos.jsx: -------------------------------------------------------------------------------- 1 | var Link = require('react-router').Link; 2 | var Store = require('../../lib/store'); 3 | 4 | 5 | var ListTodos = module.exports = React.createClass({ 6 | getInitialState: function(){ 7 | return { 8 | lists: Immutable.Map({}), 9 | tasks: Immutable.Map({}) 10 | } 11 | }, 12 | componentWillMount : function(){ 13 | Store.allLists.subscribe(function(lists){ 14 | this.setState({ lists: lists }); 15 | }.bind(this)); 16 | Store.allTasks.subscribe(function(tasks){ 17 | this.setState({ tasks: tasks }); 18 | }.bind(this)); 19 | this.onCreateList = function(){ 20 | Store.listCreate.onNext({ 21 | user: '', 22 | name: 'List '+Math.random().toFixed(3).toString() 23 | }); 24 | } 25 | }, 26 | render: function () { 27 | var pairs=R.toPairs( R.groupBy(R.prop('id'),this.state.lists.toArray())); 28 | var tasksGrouped=R.groupBy(R.prop('list'),this.state.tasks.toArray()); 29 | var items = pairs.map(function(pair){ 30 | var key = pair[0]; 31 | var count = tasksGrouped.hasOwnProperty(key) ? 32 | R.reject(R.prop('done'), tasksGrouped[key]).length : 0; 33 | return ( 34 | 38 | {count} 39 | {pair[1][0].name} 40 | 41 | ); 42 | }); 43 | return ( 44 |
45 | 46 | New List 47 | {items} 48 |
49 | ); 50 | } 51 | }); -------------------------------------------------------------------------------- /client/views/SignIn.jsx: -------------------------------------------------------------------------------- 1 | var Link = require('react-router').Link; 2 | var Store = require('../../lib/store'); 3 | 4 | var SignIn = module.exports = React.createClass({ 5 | contextTypes: { 6 | router: React.PropTypes.func 7 | }, 8 | getInitialState: function () { 9 | return { 10 | enabled : false, 11 | errors: [] 12 | } 13 | }, 14 | componentWillMount: function () { 15 | this.onSignIn = function(e){ 16 | e.preventDefault(); 17 | var email = React.findDOMNode(this.refs.email).value; 18 | var password = React.findDOMNode(this.refs.password).value; 19 | Store.signInRequest.onNext({ 20 | email: email, 21 | password: password 22 | }); 23 | }.bind(this); 24 | }, 25 | render: function () { 26 | return ( 27 |
28 | 35 |
36 |
37 |

Sign In.

38 |

Signing in allows you to view private lists

39 |
40 |
41 |
42 |
43 |
44 | 45 | 46 |
47 |
48 | 49 | 50 |
51 | 52 |
53 |
54 | Need an account? Join Now. 55 |
56 |
57 | ); 58 | } 59 | }); -------------------------------------------------------------------------------- /client/transfer.js: -------------------------------------------------------------------------------- 1 | var Store= require('../lib/store'); 2 | var Ramda = require('ramda'); 3 | var Constants = require('../lib/constants'); 4 | 5 | var socket = io(); 6 | 7 | var Transfer = module.exports = {}; 8 | 9 | Transfer.setup = function setup(socket){ 10 | socket.on(Constants.listChange,function(change){ 11 | Store.listChange.onNext(change); 12 | }); 13 | socket.on(Constants.taskChange,function(change){ 14 | Store.taskChange.onNext(change); 15 | }); 16 | function emit(address, data){ 17 | console.log(address,data); 18 | socket.emit(address, R.merge(data,{ user: Store.user.value.id})); 19 | console.log('after emit',address,data); 20 | } 21 | 22 | Store.taskCreate.skip(1).subscribe(R.partial(emit,Constants.taskCreate)); 23 | Store.taskUpdate.skip(1).subscribe(R.partial(emit,Constants.taskUpdate)); 24 | Store.taskDelete.skip(1).subscribe(R.partial(emit,Constants.taskDelete)); 25 | 26 | Store.listCreate.skip(1).subscribe(R.partial(emit,Constants.listCreate)); 27 | Store.listUpdate.skip(1).subscribe(R.partial(emit,Constants.listUpdate)); 28 | Store.listDelete.skip(1).subscribe(R.partial(emit,Constants.listDelete)); 29 | // User management 30 | Store.signInRequest.skip(1).subscribe(R.partial(emit,Constants.signInRequest)); 31 | socket.on(Constants.signInResult,function(result){ 32 | Store.signInResult.onNext(result); 33 | }); 34 | Store.joinRequest.skip(1).subscribe(R.partial(emit,Constants.joinRequest)); 35 | socket.on(Constants.joinResult, function(result){ 36 | console.log(Constants.joinResult,result); 37 | Store.joinResult.onNext(result); 38 | console.log('after',Constants.joinResult,result); 39 | }); 40 | Store.user.subscribe(function(user){ 41 | Store.allLists.onNext(filtered(Store.allLists.value,user.id)); 42 | Store.allTasks.onNext(filtered(Store.allTasks.value,user.id)); 43 | emit(Constants.sendAll,user); 44 | }); 45 | }; 46 | 47 | Transfer.setup(socket); 48 | 49 | Store.listChange.skip(1).subscribe(function(change){ 50 | if(!change.new_val) { // DELETE 51 | Store.allLists.onNext(Store.allLists.value.delete(change.old_val.id)); 52 | } else { // READ, UPDATE 53 | Store.allLists.onNext(Store.allLists.value.set(change.new_val.id, change.new_val)); 54 | } 55 | }); 56 | 57 | Store.taskChange.skip(1).subscribe(function(change){ 58 | if(!change.new_val) { // DELETE 59 | Store.allTasks.onNext(Store.allTasks.value.delete(change.old_val.id)); 60 | } else { // READ, UPDATE 61 | Store.allTasks.onNext(Store.allTasks.value.set(change.new_val.id, change.new_val)); 62 | } 63 | }); 64 | 65 | Store.signInResult.skip(1).subscribe(function(d){ 66 | Store.user.onNext(d); 67 | }); 68 | 69 | function filtered(map,user){ 70 | return map.filter(function(d){ 71 | return d.user == user; 72 | }); 73 | } 74 | -------------------------------------------------------------------------------- /server/transfer.js: -------------------------------------------------------------------------------- 1 | var socketIo = require('socket.io'); 2 | var R = require('ramda'); 3 | var Data = require('./data'); 4 | var Db = require('./db'); 5 | var Store = require('../lib/store'); 6 | var Constants = require('../lib/constants'); 7 | 8 | var Transfer = module.exports = {}; 9 | 10 | 11 | Transfer.setup = function setup(server) { 12 | var io = socketIo(server); 13 | io.on('connection', function (socket) { 14 | Db.setup(function (err) { 15 | if (!err) { 16 | Db.changes(Store.listChange,'list'); 17 | Db.changes(Store.taskChange,'task'); 18 | listen(socket); 19 | } 20 | console.log('Database setup err:', err); 21 | }); 22 | }); 23 | }; 24 | 25 | Store.joinRequest.skip(1).subscribe(function (val) { 26 | Db.join(val, function (res) { 27 | Store.joinResult.onNext(res); 28 | }); 29 | }); 30 | 31 | Store.signInRequest.skip(1).subscribe(function (val) { 32 | Db.signIn(val, function (res) { 33 | Store.signInResult.onNext(res); 34 | }); 35 | }); 36 | 37 | 38 | Store.taskCreate.skip(1).subscribe(R.partial(Db.createEntry,'task')); 39 | Store.taskUpdate.skip(1).subscribe(Db.taskUpdate); 40 | Store.taskDelete.skip(1).subscribe(Db.taskDelete); 41 | 42 | Store.listCreate.skip(1).subscribe(R.partial(Db.createEntry,'list')); 43 | Store.listUpdate.skip(1).subscribe(Db.listUpdate); 44 | Store.listDelete.skip(1).subscribe(Db.listDelete); 45 | 46 | var toChange = R.map(function (entry) { 47 | return entry.hasOwnProperty('old_val') ? entry 48 | : {old_val: null, new_val: entry}; 49 | }); 50 | 51 | function listen(socket) { 52 | function emit(address, change) { 53 | socket.emit(address, change); 54 | } 55 | 56 | socket.on(Constants.sendAll, function sendAll(user) { 57 | Db.allLists(user.id, function (err, res) { 58 | toChange(err ? [] : res).forEach(function (d) { 59 | emit(Constants.listChange, d); 60 | }); 61 | }); 62 | Db.allTasks(user.id, function (err, res) { 63 | toChange(err ? [] : res).forEach(function (d) { 64 | emit(Constants.taskChange, d); 65 | }); 66 | }); 67 | }); 68 | 69 | Store.listChange.skip(1).subscribe(R.partial(emit, Constants.listChange)); 70 | Store.taskChange.skip(1).subscribe(R.partial(emit, Constants.taskChange)); 71 | Store.signInRequest.skip(1).subscribe(function (data) { 72 | socket.emit('signin', data); 73 | }); 74 | function onNext(subject, data) { 75 | console.log(data); 76 | subject.onNext(data); 77 | } 78 | 79 | socket.on(Constants.taskCreate, R.partial(onNext, Store.taskCreate)); 80 | socket.on(Constants.taskUpdate, R.partial(onNext, Store.taskUpdate)); 81 | socket.on(Constants.taskDelete, R.partial(onNext, Store.taskDelete)); 82 | socket.on(Constants.listCreate, R.partial(onNext, Store.listCreate)); 83 | socket.on(Constants.listUpdate, R.partial(onNext, Store.listUpdate)); 84 | socket.on(Constants.listDelete, R.partial(onNext, Store.listDelete)); 85 | socket.on(Constants.joinRequest, R.partial(onNext, Store.joinRequest)); 86 | socket.on(Constants.signInRequest, R.partial(onNext, Store.signInRequest)); 87 | 88 | Store.joinResult.skip(1).subscribe(function (data) { 89 | socket.emit(Constants.joinResult, data); 90 | }); 91 | Store.signInResult.skip(1).subscribe(function (data) { 92 | socket.emit(Constants.signInResult, data); 93 | }); 94 | } 95 | -------------------------------------------------------------------------------- /client/views/Join.jsx: -------------------------------------------------------------------------------- 1 | var Link = require('react-router').Link; 2 | var Util = require('../../lib/util'); 3 | var Store = require('../../lib/store'); 4 | 5 | var Join = module.exports = React.createClass({ 6 | contextTypes: { 7 | router: React.PropTypes.func 8 | }, 9 | getInitialState: function(){ 10 | return { errors: []}; 11 | }, 12 | componentWillMount: function(){ 13 | Store.joinResult.skip(1).subscribe(function(res){ 14 | if(res.hasOwnProperty('errors')){ 15 | this.setState({ errors: res.errors }); 16 | } else { 17 | Store.user.onNext(res); 18 | this.context.router.transitionTo('/'); 19 | } 20 | }.bind(this)); 21 | this.onJoin = function(e){ 22 | e.preventDefault(); 23 | var errors = validateJoin(this.refs.email.value, 24 | this.refs.password.value, this.refs.confirm.value); 25 | if(errors.length) { 26 | this.setState({errors: errors}); 27 | } else { 28 | var email = React.findDOMNode(this.refs.email).value; 29 | var password = React.findDOMNode(this.refs.password).value; 30 | console.log('onJoin',email,password); 31 | Store.joinRequest.onNext({ 32 | email: email, 33 | password: password 34 | }); 35 | } 36 | }.bind(this); 37 | }, 38 | 39 | render: function () { 40 | return ( 41 |
42 | 49 |
50 |
51 |

Join.

52 |

Joining allows you to make private lists

53 |
54 |
55 | 56 | 57 |
58 |
59 | 61 | 62 |
63 |
64 | 66 | 67 |
68 | 69 |
70 |
71 | Have an account? Sign in 72 |
73 |
74 | ); 75 | } 76 | }); 77 | 78 | function validateJoin(email,password,confirm) { 79 | var errors = []; 80 | if(Util.validateEmail(email)) { 81 | errors.push('Invalid email'); 82 | } 83 | if(Util.validatePassword(password)) { 84 | errors.push('Invalid password'); 85 | } 86 | if(password !== confirm) { 87 | errors.push('Passwords do not match'); 88 | } 89 | return errors; 90 | } -------------------------------------------------------------------------------- /client/views/list/ListName.jsx: -------------------------------------------------------------------------------- 1 | var Store = require('../../../lib/store'); 2 | 3 | var TaskName = module.exports = React.createClass({ 4 | contextTypes: { 5 | router: React.PropTypes.func 6 | }, 7 | getInitialState: function () { 8 | return { edit: false } 9 | }, 10 | componentWillMount: function () { 11 | this.onDeleteList = function () { 12 | Store.listDelete.onNext({ id: this.props.listId }); 13 | this.context.router.transitionTo('/'); 14 | }.bind(this); 15 | this.onEditList = function(){ 16 | this.setState({edit:true}); 17 | }.bind(this); 18 | this.onUpdateListName = function(e){ 19 | e.preventDefault(); 20 | var listName = React.findDOMNode(this.refs.listName).value.trim(); 21 | if(listName && listName != '') { 22 | Store.listUpdate.onNext({ 23 | id: this.props.listId, 24 | name: listName 25 | }); 26 | this.setState({ edit:false }, function(){ 27 | React.findDOMNode(this.refs.theInput).value 28 | }.bind(this)); 29 | } 30 | }.bind(this); 31 | this.onCreateTask = function(e){ 32 | e.preventDefault(); 33 | var taskName = React.findDOMNode(this.refs.taskName).value.trim(); 34 | if(taskName && taskName != '') { 35 | Store.taskCreate.onNext({ 36 | done: false, 37 | item: taskName, 38 | list: this.props.listId 39 | }); 40 | this.setState({ edit:false },function(){ 41 | React.findDOMNode(this.refs.taskName).value = ''; 42 | }.bind(this)); 43 | } 44 | 45 | }.bind(this); 46 | }, 47 | render: function () { 48 | var listName = this.state.edit ? 49 | (
50 | 54 |
55 | 56 | 57 | 58 |
59 |
) : 60 | (
61 |
62 | 63 | 64 | 65 |
66 |

67 | {this.props.listName} 68 | {this.props.tasks.length} 69 |

70 |
71 | 80 |
81 |
); 82 | return ( 83 | 90 | ); 91 | } 92 | }); -------------------------------------------------------------------------------- /public/img/logo-todos.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 36 | 42 | 48 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /server/db.js: -------------------------------------------------------------------------------- 1 | var async = require('async'); 2 | var R = require('ramda'); 3 | var data = require('./data'); 4 | var Constants = require('../lib/constants'); 5 | 6 | 7 | var r = require('rethinkdbdash')({ 8 | host: 'localhost', 9 | port: 28015, 10 | db: 'test' 11 | }); 12 | 13 | var Db = module.exports = {}; 14 | 15 | 16 | Db.allTasks = function (userId, cb) { 17 | r.db('rio').table('task').filter({user: userId}).run(cb); 18 | }; 19 | 20 | Db.allLists = function (userId, cb) { 21 | r.db('rio').table('list').filter({user: userId}).run(cb); 22 | }; 23 | 24 | 25 | function logError(err) { 26 | if (err) console.log(err); 27 | } 28 | Db.changes = function (subject,table) { 29 | r.db('rio').table(table).changes().run(function iterateCursor(err, cursor) { 30 | cursor.each(function (res, change) { 31 | subject.onNext(change); 32 | }); 33 | }); 34 | }; 35 | 36 | Db.createEntry = function (table,data) { 37 | r.db('rio').table(table).insert(data).run(logError); 38 | }; 39 | 40 | 41 | Db.taskUpdate = function (task) { 42 | r.db('rio').table('task').get(task.id).update(task).run(logError); 43 | }; 44 | 45 | Db.taskDelete = function (task) { 46 | r.db('rio').table('task').get(task.id).delete().run(logError); 47 | }; 48 | 49 | Db.listUpdate = function (info) { 50 | r.db('rio').table('list').get(info.id).update({name: info.name}).run(logError); 51 | }; 52 | 53 | Db.listDelete = function (data) { 54 | r.db('rio').table('list').get(data.id).delete().run(logError); 55 | }; 56 | 57 | Db.signIn = function signIn(info, cb) { 58 | r.db('rio').table('user').filter(R.pick(['email', 'password'], info)) 59 | .run(function (err, res) { 60 | cb(err || res.length == 0 ? Constants.user : res[0]) 61 | }); 62 | }; 63 | 64 | Db.join = function join(info, cb) { 65 | r.db('rio').table('user') 66 | .filter({email: info.email}) 67 | .run(function (err, res) { 68 | if (err) { 69 | cb({errors: [err]}); 70 | } else { 71 | r.db('rio').table('user') 72 | .insert(R.omit(['id'], info)) 73 | .run(function (err, res) { 74 | cb(!err && res.inserted ? { 75 | email: info.email, 76 | id: res.generated_keys[0] 77 | } : {errors: ['server error']}); 78 | }); 79 | } 80 | }); 81 | }; 82 | 83 | Db.setup = function setup(mainCallback) { 84 | async.waterfall([ 85 | function (callback) { 86 | r.dbList().run(function (err, res) { 87 | callback(err, res); 88 | }); 89 | }, 90 | function (databases, callback) { 91 | if (databases.indexOf('rio') == -1) { 92 | r.dbCreate('rio').run(function (err) { 93 | callback(err, true); 94 | }); 95 | } else { 96 | callback(null, false); 97 | } 98 | }, 99 | function (create, callback) { 100 | if (create) { 101 | r.db('rio').tableCreate('user') 102 | .run(function (err, res) { 103 | callback(err, create); 104 | }); 105 | } else { 106 | callback(null, create); 107 | } 108 | 109 | }, 110 | function (create, callback) { 111 | if (create) { 112 | r.db('rio').tableCreate('list') 113 | .run(function (err, res) { 114 | callback(err, create); 115 | }); 116 | } else { 117 | callback(null, create); 118 | } 119 | }, 120 | function (create, callback) { 121 | if (create) { 122 | r.db('rio').tableCreate('task') 123 | .run(function (err, res) { 124 | callback(err, create); 125 | }); 126 | } else { 127 | callback(null, create); 128 | } 129 | }, 130 | function (create, callback) { 131 | if (create) { 132 | r.db('rio').table('list').insert(data.lists) 133 | .run(function (err, res) { 134 | callback(err, res); 135 | }); 136 | } else { 137 | callback(null, create); 138 | } 139 | }, 140 | function (create, callback) { 141 | if (create) { 142 | r.db('rio').table('list') 143 | .run(function (err, res) { 144 | if (err) { 145 | callback(err, res); 146 | } else { 147 | r.db('rio').table('task').insert(data.tasks(res)) 148 | .run(function (err, res) { 149 | callback(err, res); 150 | }); 151 | } 152 | }); 153 | } else { 154 | callback(null); 155 | } 156 | } 157 | ], function (err, res) { 158 | mainCallback(err, res); 159 | }) 160 | }; 161 | 162 | -------------------------------------------------------------------------------- /public/style/icon/todos.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /public/style/main.css: -------------------------------------------------------------------------------- 1 | /* Reset.less 2 | * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc). 3 | * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */ 4 | html, 5 | body { 6 | margin: 0; 7 | padding: 0; 8 | } 9 | h1, 10 | h2, 11 | h3, 12 | h4, 13 | h5, 14 | h6, 15 | p, 16 | blockquote, 17 | pre, 18 | a, 19 | abbr, 20 | acronym, 21 | address, 22 | cite, 23 | code, 24 | del, 25 | dfn, 26 | em, 27 | img, 28 | q, 29 | s, 30 | samp, 31 | small, 32 | strike, 33 | strong, 34 | sub, 35 | sup, 36 | tt, 37 | var, 38 | dd, 39 | dl, 40 | dt, 41 | li, 42 | ol, 43 | ul, 44 | fieldset, 45 | form, 46 | label, 47 | legend, 48 | button, 49 | table, 50 | caption, 51 | tbody, 52 | tfoot, 53 | thead, 54 | tr, 55 | th, 56 | td { 57 | margin: 0; 58 | padding: 0; 59 | border: 0; 60 | font-weight: normal; 61 | font-style: normal; 62 | font-size: 100%; 63 | line-height: 1; 64 | font-family: inherit; 65 | } 66 | table { 67 | border-collapse: collapse; 68 | border-spacing: 0; 69 | } 70 | ol, 71 | ul { 72 | list-style: none; 73 | } 74 | q:before, 75 | q:after, 76 | blockquote:before, 77 | blockquote:after { 78 | content: ""; 79 | } 80 | html { 81 | font-size: 100%; 82 | -webkit-text-size-adjust: 100%; 83 | -ms-text-size-adjust: 100%; 84 | } 85 | a:focus { 86 | outline: thin dotted; 87 | } 88 | a:hover, 89 | a:active { 90 | outline: 0; 91 | } 92 | article, 93 | aside, 94 | details, 95 | figcaption, 96 | figure, 97 | footer, 98 | header, 99 | hgroup, 100 | nav, 101 | section { 102 | display: block; 103 | } 104 | audio, 105 | canvas, 106 | video { 107 | display: inline-block; 108 | *display: inline; 109 | *zoom: 1; 110 | } 111 | audio:not([controls]) { 112 | display: none; 113 | } 114 | sub, 115 | sup { 116 | font-size: 75%; 117 | line-height: 0; 118 | position: relative; 119 | vertical-align: baseline; 120 | } 121 | sup { 122 | top: -0.5em; 123 | } 124 | sub { 125 | bottom: -0.25em; 126 | } 127 | img { 128 | border: 0; 129 | -ms-interpolation-mode: bicubic; 130 | } 131 | button, 132 | input, 133 | select, 134 | textarea { 135 | font-size: 100%; 136 | margin: 0; 137 | vertical-align: baseline; 138 | *vertical-align: middle; 139 | } 140 | button, 141 | input { 142 | line-height: normal; 143 | *overflow: visible; 144 | } 145 | button::-moz-focus-inner, 146 | input::-moz-focus-inner { 147 | border: 0; 148 | padding: 0; 149 | } 150 | button, 151 | input[type="button"], 152 | input[type="reset"], 153 | input[type="submit"] { 154 | cursor: pointer; 155 | -webkit-appearance: button; 156 | } 157 | input[type="search"] { 158 | -webkit-appearance: textfield; 159 | -webkit-box-sizing: content-box; 160 | -moz-box-sizing: content-box; 161 | box-sizing: content-box; 162 | } 163 | input[type="search"]::-webkit-search-decoration { 164 | -webkit-appearance: none; 165 | } 166 | textarea { 167 | overflow: auto; 168 | vertical-align: top; 169 | } 170 | @font-face { 171 | font-family: 'Open Sans'; 172 | src: url('font/OpenSans-Light-webfont.eot'); 173 | src: url('font/OpenSans-Light-webfont.eot?#iefix') format('embedded-opentype'), url('font/OpenSans-Light-webfont.woff') format('woff'), url('font/OpenSans-Light-webfont.ttf') format('truetype'), url('font/OpenSans-Light-webfont.svg#OpenSansLight') format('svg'); 174 | font-weight: 200; 175 | font-style: normal; 176 | } 177 | @font-face { 178 | font-family: 'Open Sans'; 179 | src: url('font/OpenSans-Regular-webfont.eot'); 180 | src: url('font/OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'), url('font/OpenSans-Regular-webfont.woff') format('woff'), url('font/OpenSans-Regular-webfont.ttf') format('truetype'), url('font/OpenSans-Regular-webfont.svg#OpenSansRegular') format('svg'); 181 | font-weight: normal; 182 | font-weight: 400; 183 | font-style: normal; 184 | } 185 | .force-wrap { 186 | word-wrap: break-word; 187 | word-break: break-all; 188 | -ms-word-break: break-all; 189 | word-break: break-word; 190 | -webkit-hyphens: auto; 191 | -moz-hyphens: auto; 192 | -ms-hyphens: auto; 193 | hyphens: auto; 194 | } 195 | .type-light { 196 | font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 197 | font-weight: 300; 198 | } 199 | * { 200 | -webkit-box-sizing: border-box; 201 | -moz-box-sizing: border-box; 202 | box-sizing: border-box; 203 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 204 | -webkit-tap-highlight-color: transparent; 205 | } 206 | html, 207 | button, 208 | input, 209 | textarea, 210 | select { 211 | outline: none; 212 | -webkit-font-smoothing: antialiased; 213 | -moz-osx-font-smoothing: grayscale; 214 | } 215 | body { 216 | font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 217 | font-style: 400; 218 | color: #333333; 219 | font-size: 16px; 220 | } 221 | h1, 222 | h2, 223 | h3, 224 | h4, 225 | h5, 226 | h6 { 227 | font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 228 | font-style: 400; 229 | margin: 0; 230 | padding: 0; 231 | } 232 | h1 { 233 | font-size: 40px; 234 | line-height: 48px; 235 | } 236 | h2 { 237 | font-size: 28px; 238 | line-height: 32px; 239 | } 240 | h3 { 241 | font-size: 24px; 242 | line-height: 28px; 243 | } 244 | h4 { 245 | font-size: 20px; 246 | line-height: 24px; 247 | } 248 | h5 { 249 | font-size: 14px; 250 | line-height: 20px; 251 | color: #cccccc; 252 | text-transform: uppercase; 253 | } 254 | h6 { 255 | color: #aaaaaa; 256 | } 257 | p { 258 | font-size: 16px; 259 | line-height: 24px; 260 | } 261 | sub, 262 | sup { 263 | font-size: .8em; 264 | } 265 | sub { 266 | bottom: -0.2em; 267 | } 268 | sup { 269 | top: -0.2em; 270 | } 271 | b { 272 | font-weight: bold; 273 | } 274 | em { 275 | font-style: italic; 276 | } 277 | [class^="btn-"], 278 | [class*=" btn-"] { 279 | font-size: 14px; 280 | line-height: 20px; 281 | line-height: 20px !important; 282 | padding: 1em 1.25em; 283 | letter-spacing: .3em; 284 | text-indent: .3em; 285 | text-transform: uppercase; 286 | -webkit-transition: all 200ms ease-in; 287 | -moz-transition: all 200ms ease-in; 288 | -o-transition: all 200ms ease-in; 289 | transition: all 200ms ease-in; 290 | color: #ffffff; 291 | display: inline-block; 292 | position: relative; 293 | text-align: center; 294 | text-decoration: none !important; 295 | vertical-align: middle; 296 | white-space: nowrap; 297 | } 298 | [class^="btn-"][class*="primary"], 299 | [class*=" btn-"][class*="primary"] { 300 | background-color: #2cc5d2; 301 | color: #ffffff; 302 | } 303 | [class^="btn-"][class*="primary"]:hover, 304 | [class*=" btn-"][class*="primary"]:hover { 305 | background-color: #28b1bd; 306 | } 307 | [class^="btn-"][class*="primary"]:active, 308 | [class*=" btn-"][class*="primary"]:active { 309 | box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px 0 inset; 310 | } 311 | [class^="btn-"][class*="secondary"], 312 | [class*=" btn-"][class*="secondary"] { 313 | -webkit-transition: all 300ms ease-in; 314 | -moz-transition: all 300ms ease-in; 315 | -o-transition: all 300ms ease-in; 316 | transition: all 300ms ease-in; 317 | box-shadow: #5a7ca6 0 0 0 1px inset; 318 | color: #ffffff; 319 | } 320 | [class^="btn-"][class*="secondary"]:hover, 321 | [class*=" btn-"][class*="secondary"]:hover { 322 | color: #eeeeee; 323 | } 324 | [class^="btn-"][class*="secondary"]:active, 325 | [class*=" btn-"][class*="secondary"]:active, 326 | [class^="btn-"][class*="secondary"].active, 327 | [class*=" btn-"][class*="secondary"].active { 328 | box-shadow: #9db1ca 0 0 0 1px inset; 329 | } 330 | [class^="btn-"][disabled], 331 | [class*=" btn-"][disabled] { 332 | opacity: .5; 333 | } 334 | .btns-group { 335 | display: -webkit-box; 336 | display: -moz-box; 337 | display: -webkit-flex; 338 | display: -ms-flexbox; 339 | display: flex; 340 | -webkit-flex-wrap: wrap; 341 | -ms-flex-wrap: wrap; 342 | flex-wrap: wrap; 343 | width: 100%; 344 | } 345 | .btns-group [class*="btn-"] { 346 | overflow: hidden; 347 | text-overflow: ellipsis; 348 | white-space: nowrap; 349 | -webkit-box-flex: 1; 350 | -moz-box-flex: 1; 351 | -webkit-flex: 1; 352 | -ms-flex: 1; 353 | flex: 1; 354 | } 355 | .btns-group [class*="btn-"] + [class*="btn-"] { 356 | margin-left: -1px; 357 | } 358 | input[type="text"], 359 | input[type="email"], 360 | input[type="password"], 361 | textarea { 362 | font-size: 14px; 363 | line-height: 20px; 364 | font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 365 | font-style: 400; 366 | padding: .75rem 0; 367 | line-height: 1.5rem !important; 368 | border: none; 369 | border-radius: 0; 370 | box-sizing: border-box; 371 | color: #333333; 372 | outline: none; 373 | } 374 | input[type="text"]::-webkit-input-placeholder, 375 | input[type="email"]::-webkit-input-placeholder, 376 | input[type="password"]::-webkit-input-placeholder, 377 | textarea::-webkit-input-placeholder { 378 | color: #778b91; 379 | } 380 | input[type="text"]:-moz-placeholder, 381 | input[type="email"]:-moz-placeholder, 382 | input[type="password"]:-moz-placeholder, 383 | textarea:-moz-placeholder { 384 | color: #778b91; 385 | } 386 | input[type="text"]::-moz-placeholder, 387 | input[type="email"]::-moz-placeholder, 388 | input[type="password"]::-moz-placeholder, 389 | textarea::-moz-placeholder { 390 | color: #778b91; 391 | } 392 | input[type="text"]:-ms-input-placeholder, 393 | input[type="email"]:-ms-input-placeholder, 394 | input[type="password"]:-ms-input-placeholder, 395 | textarea:-ms-input-placeholder { 396 | color: #778b91; 397 | } 398 | input[type="text"][disabled], 399 | input[type="email"][disabled], 400 | input[type="password"][disabled], 401 | textarea[disabled] { 402 | opacity: .5; 403 | } 404 | input:-webkit-autofill { 405 | -webkit-box-shadow: 0 0 0 1000px #ffffff inset; 406 | } 407 | .checkbox { 408 | display: inline-block; 409 | height: 3rem; 410 | position: relative; 411 | vertical-align: middle; 412 | width: 44px; 413 | } 414 | .checkbox input[type="checkbox"] { 415 | font-size: 1em; 416 | visibility: hidden; 417 | } 418 | .checkbox input[type="checkbox"] + span:before { 419 | position: absolute; 420 | top: 50%; 421 | right: auto; 422 | bottom: auto; 423 | left: 50%; 424 | width: 0.85em; 425 | height: 0.85em; 426 | -webkit-transform: translate3d(-50%, -50%, 0); 427 | -moz-transform: translate3d(-50%, -50%, 0); 428 | -ms-transform: translate3d(-50%, -50%, 0); 429 | -o-transform: translate3d(-50%, -50%, 0); 430 | transform: translate3d(-50%, -50%, 0); 431 | background: transparent; 432 | box-shadow: #abdfe3 0 0 0 1px inset; 433 | content: ''; 434 | display: block; 435 | } 436 | .checkbox input[type="checkbox"]:checked + span:before { 437 | box-shadow: none; 438 | color: #cccccc; 439 | font-family: 'todos'; 440 | speak: none; 441 | font-style: normal; 442 | font-weight: normal; 443 | font-variant: normal; 444 | text-transform: none; 445 | line-height: 1; 446 | -webkit-font-smoothing: antialiased; 447 | -moz-osx-font-smoothing: grayscale; 448 | content: "\e612"; 449 | } 450 | .input-symbol { 451 | display: inline-block; 452 | position: relative; 453 | } 454 | .input-symbol.error [class^="icon-"], 455 | .input-symbol.error [class*=" icon-"] { 456 | color: #ff4400; 457 | } 458 | .input-symbol [class^="icon-"], 459 | .input-symbol [class*=" icon-"] { 460 | left: 1em; 461 | } 462 | .input-symbol input { 463 | padding-left: 3em; 464 | } 465 | .input-symbol input { 466 | width: 100%; 467 | } 468 | .input-symbol input:focus + [class^="icon-"], 469 | .input-symbol input:focus + [class*=" icon-"] { 470 | color: #2cc5d2; 471 | } 472 | .input-symbol [class^="icon-"], 473 | .input-symbol [class*=" icon-"] { 474 | -webkit-transition: all 300ms ease-in; 475 | -moz-transition: all 300ms ease-in; 476 | -o-transition: all 300ms ease-in; 477 | transition: all 300ms ease-in; 478 | -webkit-transform: translate3d(0, -50%, 0); 479 | -moz-transform: translate3d(0, -50%, 0); 480 | -ms-transform: translate3d(0, -50%, 0); 481 | -o-transform: translate3d(0, -50%, 0); 482 | transform: translate3d(0, -50%, 0); 483 | background: transparent; 484 | color: #aaaaaa; 485 | font-size: 1em; 486 | height: 1em; 487 | position: absolute; 488 | top: 50%; 489 | width: 1em; 490 | } 491 | @font-face { 492 | font-family: 'todos'; 493 | src: url('icon/todos.eot?-5w3um4'); 494 | src: url('icon/todos.eot?#iefix5w3um4') format('embedded-opentype'), url('icon/todos.woff?5w3um4') format('woff'), url('icon/todos.ttf?5w3um4') format('truetype'), url('icon/todos.svg?5w3um4#todos') format('svg'); 495 | font-weight: normal; 496 | font-style: normal; 497 | } 498 | [class^="icon-"], 499 | [class*=" icon-"] { 500 | font-family: 'todos'; 501 | speak: none; 502 | font-style: normal; 503 | font-weight: normal; 504 | font-variant: normal; 505 | text-transform: none; 506 | line-height: 1; 507 | -webkit-font-smoothing: antialiased; 508 | -moz-osx-font-smoothing: grayscale; 509 | } 510 | .icon-unlock:before { 511 | content: "\e600"; 512 | } 513 | .icon-user-add:before { 514 | content: "\e604"; 515 | } 516 | .icon-cog:before { 517 | content: "\e606"; 518 | } 519 | .icon-trash:before { 520 | content: "\e607"; 521 | } 522 | .icon-edit:before { 523 | content: "\e608"; 524 | } 525 | .icon-add:before { 526 | content: "\e60a"; 527 | } 528 | .icon-plus:before { 529 | content: "\e60b"; 530 | } 531 | .icon-close:before { 532 | content: "\e60c"; 533 | } 534 | .icon-cross:before { 535 | content: "\e60d"; 536 | } 537 | .icon-sync:before { 538 | content: "\e60e"; 539 | } 540 | .icon-lock:before { 541 | content: "\e610"; 542 | } 543 | .icon-check:before { 544 | content: "\e612"; 545 | } 546 | .icon-share:before { 547 | content: "\e617"; 548 | } 549 | .icon-email:before { 550 | content: "\e619"; 551 | } 552 | .icon-arrow-up:before { 553 | content: "\e623"; 554 | } 555 | .icon-arrow-down:before { 556 | content: "\e626"; 557 | } 558 | .icon-list-unordered:before { 559 | content: "\e634"; 560 | } 561 | body { 562 | position: absolute; 563 | top: 0; 564 | right: 0; 565 | bottom: 0; 566 | left: 0; 567 | width: auto; 568 | height: auto; 569 | background-color: #315481; 570 | background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMSAxIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIj48bGluZWFyR3JhZGllbnQgaWQ9Imxlc3NoYXQtZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiMzMTU0ODEiIHN0b3Atb3BhY2l0eT0iMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzkxOGU4MiIgc3RvcC1vcGFjaXR5PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2xlc3NoYXQtZ2VuZXJhdGVkKSIgLz48L3N2Zz4=); 571 | background-image: -webkit-linear-gradient(top, #315481, #918e82 100%); 572 | background-image: -moz-linear-gradient(top, #315481, #918e82 100%); 573 | background-image: -o-linear-gradient(top, #315481, #918e82 100%); 574 | background-image: linear-gradient(to bottom, #315481, #918e82 100%); 575 | background-repeat: no-repeat; 576 | background-attachment: fixed; 577 | } 578 | #container { 579 | position: absolute; 580 | top: 0; 581 | right: 0; 582 | bottom: 0; 583 | left: 0; 584 | width: auto; 585 | height: auto; 586 | overflow: hidden; 587 | } 588 | @media screen and (min-width: 60em) { 589 | #container { 590 | left: 5.55555%; 591 | right: 5.55555%; 592 | } 593 | } 594 | @media screen and (min-width: 80em) { 595 | #container { 596 | left: 11.1111%; 597 | right: 11.1111%; 598 | } 599 | } 600 | #menu { 601 | position: absolute; 602 | top: 0; 603 | right: 0; 604 | bottom: 0; 605 | left: 0; 606 | width: 270px; 607 | height: auto; 608 | } 609 | #content-container { 610 | position: absolute; 611 | top: 0; 612 | right: 0; 613 | bottom: 0; 614 | left: 0; 615 | width: auto; 616 | height: auto; 617 | -webkit-transition: all 200ms ease-out; 618 | -moz-transition: all 200ms ease-out; 619 | -o-transition: all 200ms ease-out; 620 | transition: all 200ms ease-out; 621 | -webkit-transform: translate3d(0, 0, 0); 622 | -moz-transform: translate3d(0, 0, 0); 623 | -ms-transform: translate3d(0, 0, 0); 624 | -o-transform: translate3d(0, 0, 0); 625 | transform: translate3d(0, 0, 0); 626 | background: #d2edf4; 627 | opacity: 1; 628 | } 629 | @media screen and (min-width: 40em) { 630 | #content-container { 631 | left: 270px; 632 | } 633 | } 634 | #content-container .content-scrollable { 635 | position: absolute; 636 | top: 0; 637 | right: 0; 638 | bottom: 0; 639 | left: 0; 640 | width: auto; 641 | height: auto; 642 | -webkit-transform: translate3d(0, 0, 0); 643 | -moz-transform: translate3d(0, 0, 0); 644 | -ms-transform: translate3d(0, 0, 0); 645 | -o-transform: translate3d(0, 0, 0); 646 | transform: translate3d(0, 0, 0); 647 | overflow-y: auto; 648 | -webkit-overflow-scrolling: touch; 649 | } 650 | .menu-open #content-container { 651 | -webkit-transform: translate3d(270px, 0, 0); 652 | -moz-transform: translate3d(270px, 0, 0); 653 | -ms-transform: translate3d(270px, 0, 0); 654 | -o-transform: translate3d(270px, 0, 0); 655 | transform: translate3d(270px, 0, 0); 656 | opacity: .85; 657 | left: 0; 658 | } 659 | @media screen and (min-width: 40em) { 660 | .menu-open #content-container { 661 | -webkit-transform: translate3d(0, 0, 0); 662 | -moz-transform: translate3d(0, 0, 0); 663 | -ms-transform: translate3d(0, 0, 0); 664 | -o-transform: translate3d(0, 0, 0); 665 | transform: translate3d(0, 0, 0); 666 | opacity: 1; 667 | left: 270px; 668 | } 669 | } 670 | .content-overlay { 671 | position: absolute; 672 | top: 0; 673 | right: 0; 674 | bottom: 0; 675 | left: 0; 676 | width: auto; 677 | height: auto; 678 | cursor: pointer; 679 | } 680 | .menu-open .content-overlay { 681 | -webkit-transform: translate3d(270px, 0, 0); 682 | -moz-transform: translate3d(270px, 0, 0); 683 | -ms-transform: translate3d(270px, 0, 0); 684 | -o-transform: translate3d(270px, 0, 0); 685 | transform: translate3d(270px, 0, 0); 686 | z-index: 1; 687 | } 688 | @media screen and (min-width: 40em) { 689 | .content-overlay { 690 | display: none; 691 | } 692 | } 693 | a { 694 | -webkit-transition: all 200ms ease-in; 695 | -moz-transition: all 200ms ease-in; 696 | -o-transition: all 200ms ease-in; 697 | transition: all 200ms ease-in; 698 | color: #5db9ff; 699 | cursor: pointer; 700 | text-decoration: none; 701 | } 702 | a:hover { 703 | color: #239da8; 704 | } 705 | a:active { 706 | color: #555555; 707 | } 708 | a:focus { 709 | outline: none; 710 | } 711 | #menu { 712 | overflow-y: auto; 713 | -webkit-overflow-scrolling: touch; 714 | } 715 | #menu .btns-group, 716 | #menu .btns-group-vertical { 717 | margin: 2em auto 2em; 718 | width: 80%; 719 | } 720 | #menu .btns-group .btn-secondary, 721 | #menu .btns-group-vertical .btn-secondary { 722 | font-size: 12px; 723 | line-height: 16px; 724 | padding-top: .5em; 725 | padding-bottom: .5em; 726 | } 727 | #menu .btns-group-vertical .btn-secondary { 728 | word-wrap: break-word; 729 | word-break: break-all; 730 | -ms-word-break: break-all; 731 | word-break: break-word; 732 | -webkit-hyphens: auto; 733 | -moz-hyphens: auto; 734 | -ms-hyphens: auto; 735 | hyphens: auto; 736 | padding-right: 2.5em; 737 | text-align: left; 738 | text-indent: 0; 739 | white-space: normal; 740 | width: 100%; 741 | } 742 | #menu .btns-group-vertical .btn-secondary + .btn-secondary { 743 | margin-top: .5rem; 744 | } 745 | #menu .btns-group-vertical .btn-secondary + .btn-secondary:before { 746 | position: absolute; 747 | top: -0.5rem; 748 | right: 50%; 749 | bottom: auto; 750 | left: auto; 751 | width: 1px; 752 | height: 0.5rem; 753 | background: #5a7ca6; 754 | content: ''; 755 | } 756 | #menu .btns-group-vertical .btn-secondary [class^="icon-"], 757 | #menu .btns-group-vertical .btn-secondary [class*=" icon-"] { 758 | position: absolute; 759 | top: 0.5em; 760 | right: 0.5em; 761 | bottom: auto; 762 | left: auto; 763 | width: auto; 764 | height: auto; 765 | line-height: 20px; 766 | } 767 | #menu .list-todos a { 768 | box-shadow: rgba(255, 255, 255, 0.15) 0 1px 0 0; 769 | display: block; 770 | line-height: 1.5em; 771 | padding: .75em 2.5em; 772 | position: relative; 773 | } 774 | #menu .list-todos .count-list { 775 | -webkit-transition: all 200ms ease-in; 776 | -moz-transition: all 200ms ease-in; 777 | -o-transition: all 200ms ease-in; 778 | transition: all 200ms ease-in; 779 | background: rgba(255, 255, 255, 0.1); 780 | border-radius: 1em; 781 | float: right; 782 | font-size: .7rem; 783 | line-height: 1; 784 | margin-top: .25rem; 785 | margin-right: -1.5em; 786 | padding: .3em .5em; 787 | } 788 | #menu .list-todos [class^="icon-"], 789 | #menu .list-todos [class*=" icon-"] { 790 | font-size: 14px; 791 | line-height: 20px; 792 | float: left; 793 | margin-left: -1.5rem; 794 | margin-right: .5rem; 795 | margin-top: .1rem; 796 | width: 1em; 797 | } 798 | #menu .list-todos .icon-lock { 799 | font-size: 12px; 800 | line-height: 16px; 801 | margin-top: .2rem; 802 | opacity: .8; 803 | } 804 | #menu .list-todos .list-todo { 805 | color: rgba(255, 255, 255, 0.4); 806 | } 807 | #menu .list-todos .list-todo:hover, 808 | #menu .list-todos .list-todo:active, 809 | #menu .list-todos .list-todo.active { 810 | color: #ffffff; 811 | } 812 | #menu .list-todos .list-todo:hover .count-list, 813 | #menu .list-todos .list-todo:active .count-list, 814 | #menu .list-todos .list-todo.active .count-list { 815 | background: #2cc5d2; 816 | } 817 | .cordova #menu .list-todos .list-todo:hover { 818 | color: rgba(255, 255, 255, 0.4); 819 | } 820 | nav { 821 | position: absolute; 822 | top: 0; 823 | right: 0; 824 | bottom: auto; 825 | left: 0; 826 | width: auto; 827 | height: auto; 828 | -webkit-transform: translate3d(0, 0, 0); 829 | -moz-transform: translate3d(0, 0, 0); 830 | -ms-transform: translate3d(0, 0, 0); 831 | -o-transform: translate3d(0, 0, 0); 832 | transform: translate3d(0, 0, 0); 833 | -webkit-transition: all 200ms ease-out; 834 | -moz-transition: all 200ms ease-out; 835 | -o-transition: all 200ms ease-out; 836 | transition: all 200ms ease-out; 837 | z-index: 10; 838 | } 839 | nav .nav-item { 840 | font-size: 20px; 841 | line-height: 24px; 842 | color: #1c3f53; 843 | display: inline-block; 844 | height: 3rem; 845 | text-align: center; 846 | width: 3rem; 847 | } 848 | nav .nav-item:active { 849 | opacity: .5; 850 | } 851 | nav .nav-item [class^="icon-"], 852 | nav .nav-item [class*=" icon-"] { 853 | line-height: 3rem; 854 | vertical-align: middle; 855 | } 856 | nav .nav-group { 857 | position: absolute; 858 | top: 0; 859 | right: auto; 860 | bottom: auto; 861 | left: 0; 862 | width: auto; 863 | height: auto; 864 | z-index: 1; 865 | } 866 | nav .nav-group.right { 867 | left: auto; 868 | right: 0; 869 | } 870 | .page.lists-show nav { 871 | background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMSAxIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIj48bGluZWFyR3JhZGllbnQgaWQ9Imxlc3NoYXQtZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiNkMGVkZjUiIHN0b3Atb3BhY2l0eT0iMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2UxZTVmMCIgc3RvcC1vcGFjaXR5PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2xlc3NoYXQtZ2VuZXJhdGVkKSIgLz48L3N2Zz4=); 872 | background-image: -webkit-linear-gradient(top, #d0edf5, #e1e5f0 100%); 873 | background-image: -moz-linear-gradient(top, #d0edf5, #e1e5f0 100%); 874 | background-image: -o-linear-gradient(top, #d0edf5, #e1e5f0 100%); 875 | background-image: linear-gradient(to bottom, #d0edf5, #e1e5f0 100%); 876 | height: 5em; 877 | text-align: center; 878 | } 879 | @media screen and (min-width: 40em) { 880 | .page.lists-show nav { 881 | text-align: left; 882 | } 883 | } 884 | .page.lists-show nav .title-page { 885 | position: absolute; 886 | top: 0; 887 | right: 3rem; 888 | bottom: auto; 889 | left: 3rem; 890 | width: auto; 891 | height: auto; 892 | cursor: pointer; 893 | font-size: 1.125em; 894 | white-space: nowrap; 895 | } 896 | @media screen and (min-width: 40em) { 897 | .page.lists-show nav .title-page { 898 | left: 1rem; 899 | right: 6rem; 900 | } 901 | } 902 | .page.lists-show nav .title-page .title-wrapper { 903 | overflow: hidden; 904 | text-overflow: ellipsis; 905 | white-space: nowrap; 906 | color: #1c3f53; 907 | display: inline-block; 908 | padding-right: 1.5rem; 909 | vertical-align: top; 910 | max-width: 100%; 911 | } 912 | .page.lists-show nav .title-page .count-list { 913 | background: #2cc5d2; 914 | border-radius: 1em; 915 | color: #ffffff; 916 | display: inline-block; 917 | font-size: .7rem; 918 | line-height: 1; 919 | margin-left: -1.25rem; 920 | margin-top: -4px; 921 | padding: .3em .5em; 922 | vertical-align: middle; 923 | } 924 | .page.lists-show nav form.todo-new { 925 | position: absolute; 926 | top: 3em; 927 | right: 0; 928 | bottom: auto; 929 | left: 0; 930 | width: auto; 931 | height: auto; 932 | } 933 | .page.lists-show nav form.todo-new input[type="text"] { 934 | background: transparent; 935 | padding-bottom: .25em; 936 | padding-left: 44px !important; 937 | padding-top: .25em; 938 | } 939 | .page.lists-show nav form.list-edit-form { 940 | position: relative; 941 | } 942 | .page.lists-show nav form.list-edit-form input[type="text"] { 943 | background: transparent; 944 | font-size: 1.125em; 945 | width: 100%; 946 | padding-right: 3em; 947 | padding-left: 1rem; 948 | } 949 | .page.lists-show nav select.list-edit { 950 | font-size: 14px; 951 | line-height: 20px; 952 | position: absolute; 953 | top: 0; 954 | right: 0; 955 | bottom: 0; 956 | left: 0; 957 | width: auto; 958 | height: auto; 959 | background: transparent; 960 | opacity: 0; 961 | } 962 | .page.lists-show nav .options-web { 963 | display: none; 964 | } 965 | .page.lists-show nav .options-web .nav-item { 966 | font-size: 16px; 967 | line-height: 24px; 968 | width: 2rem; 969 | } 970 | .page.lists-show nav .options-web .nav-item:last-child { 971 | margin-right: .5rem; 972 | } 973 | @media screen and (min-width: 40em) { 974 | .page.lists-show nav .nav-group:not(.right) { 975 | display: none !important; 976 | } 977 | .page.lists-show nav .options-mobile { 978 | display: none; 979 | } 980 | .page.lists-show nav .options-web { 981 | display: block; 982 | } 983 | } 984 | @media screen and (min-width: 40em) { 985 | .page.auth .nav-group { 986 | display: none; 987 | } 988 | .page.not-found .nav-group { 989 | display: none; 990 | } 991 | } 992 | .list-items .list-item { 993 | font-size: 14px; 994 | line-height: 20px; 995 | display: -webkit-box; 996 | display: -moz-box; 997 | display: -webkit-flex; 998 | display: -ms-flexbox; 999 | display: flex; 1000 | -webkit-flex-wrap: wrap; 1001 | -ms-flex-wrap: wrap; 1002 | flex-wrap: wrap; 1003 | height: 3rem; 1004 | width: 100%; 1005 | } 1006 | .list-items .list-item .checkbox { 1007 | -webkit-box-flex: 0; 1008 | -moz-box-flex: 0; 1009 | -webkit-flex: 0 0 44px; 1010 | -ms-flex: 0 0 44px; 1011 | flex: 0 0 44px; 1012 | cursor: pointer; 1013 | } 1014 | .list-items .list-item input[type="text"] { 1015 | -webkit-box-flex: 1; 1016 | -moz-box-flex: 1; 1017 | -webkit-flex: 1; 1018 | -ms-flex: 1; 1019 | flex: 1; 1020 | } 1021 | .list-items .list-item .delete-item { 1022 | -webkit-box-flex: 0; 1023 | -moz-box-flex: 0; 1024 | -webkit-flex: 0 0 3rem; 1025 | -ms-flex: 0 0 3rem; 1026 | flex: 0 0 3rem; 1027 | } 1028 | .list-items .list-item input[type="text"] { 1029 | background: transparent; 1030 | cursor: pointer; 1031 | } 1032 | .list-items .list-item input[type="text"]:focus { 1033 | cursor: text; 1034 | } 1035 | .list-items .list-item .delete-item { 1036 | color: #cccccc; 1037 | line-height: 3rem; 1038 | text-align: center; 1039 | } 1040 | .list-items .list-item .delete-item:hover { 1041 | color: #2cc5d2; 1042 | } 1043 | .list-items .list-item .delete-item:active { 1044 | color: #555555; 1045 | } 1046 | .list-items .list-item .delete-item .icon-trash { 1047 | font-size: 1.1em; 1048 | } 1049 | .list-items .list-item + .list-item { 1050 | border-top: 1px solid #f0f9fb; 1051 | } 1052 | .list-items .list-item.checked input[type="text"] { 1053 | color: #cccccc; 1054 | text-decoration: line-through; 1055 | } 1056 | .list-items .list-item.checked .delete-item { 1057 | display: inline-block; 1058 | } 1059 | .list-items .list-item .delete-item { 1060 | display: none; 1061 | } 1062 | .list-items .list-item.editing .delete-item { 1063 | display: inline-block; 1064 | } 1065 | .wrapper-message { 1066 | position: absolute; 1067 | top: 45%; 1068 | right: 0; 1069 | bottom: auto; 1070 | left: 0; 1071 | width: auto; 1072 | height: auto; 1073 | -webkit-transform: translate3d(0, -50%, 0); 1074 | -moz-transform: translate3d(0, -50%, 0); 1075 | -ms-transform: translate3d(0, -50%, 0); 1076 | -o-transform: translate3d(0, -50%, 0); 1077 | transform: translate3d(0, -50%, 0); 1078 | text-align: center; 1079 | } 1080 | .wrapper-message .title-message { 1081 | font-size: 24px; 1082 | line-height: 28px; 1083 | font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 1084 | font-weight: 300; 1085 | color: #1c3f53; 1086 | margin-bottom: .5em; 1087 | } 1088 | .wrapper-message .subtitle-message { 1089 | font-size: 14px; 1090 | line-height: 20px; 1091 | color: #aaaaaa; 1092 | } 1093 | @-webkit-keyframes spin { 1094 | 0% { 1095 | -webkit-transform: rotate(0deg); 1096 | -moz-transform: rotate(0deg); 1097 | -ms-transform: rotate(0deg); 1098 | -o-transform: rotate(0deg); 1099 | transform: rotate(0deg); 1100 | } 1101 | 100% { 1102 | -webkit-transform: rotate(359deg); 1103 | -moz-transform: rotate(359deg); 1104 | -ms-transform: rotate(359deg); 1105 | -o-transform: rotate(359deg); 1106 | transform: rotate(359deg); 1107 | } 1108 | } 1109 | @keyframes spin { 1110 | 0% { 1111 | -webkit-transform: rotate(0deg); 1112 | -moz-transform: rotate(0deg); 1113 | -ms-transform: rotate(0deg); 1114 | -o-transform: rotate(0deg); 1115 | transform: rotate(0deg); 1116 | } 1117 | 100% { 1118 | -webkit-transform: rotate(359deg); 1119 | -moz-transform: rotate(359deg); 1120 | -ms-transform: rotate(359deg); 1121 | -o-transform: rotate(359deg); 1122 | transform: rotate(359deg); 1123 | } 1124 | } 1125 | .notifications { 1126 | position: absolute; 1127 | top: auto; 1128 | right: auto; 1129 | bottom: 10px; 1130 | left: 50%; 1131 | width: 280px; 1132 | height: auto; 1133 | -webkit-transform: translate3d(-50%, 0, 0); 1134 | -moz-transform: translate3d(-50%, 0, 0); 1135 | -ms-transform: translate3d(-50%, 0, 0); 1136 | -o-transform: translate3d(-50%, 0, 0); 1137 | transform: translate3d(-50%, 0, 0); 1138 | z-index: 1; 1139 | } 1140 | @media screen and (min-width: 40em) { 1141 | .notifications { 1142 | -webkit-transform: translate3d(0, 0, 0); 1143 | -moz-transform: translate3d(0, 0, 0); 1144 | -ms-transform: translate3d(0, 0, 0); 1145 | -o-transform: translate3d(0, 0, 0); 1146 | transform: translate3d(0, 0, 0); 1147 | bottom: auto; 1148 | right: 1rem; 1149 | top: 1rem; 1150 | left: auto; 1151 | } 1152 | } 1153 | .notifications .notification { 1154 | font-size: 12px; 1155 | line-height: 16px; 1156 | background: rgba(51, 51, 51, 0.85); 1157 | color: #ffffff; 1158 | margin-bottom: .25rem; 1159 | padding: .5rem .75rem; 1160 | position: relative; 1161 | width: 100%; 1162 | } 1163 | .notifications .notification .icon-sync { 1164 | position: absolute; 1165 | top: 30%; 1166 | right: auto; 1167 | bottom: auto; 1168 | left: 1rem; 1169 | width: auto; 1170 | height: auto; 1171 | -webkit-animation: spin 2s infinite linear; 1172 | -moz-animation: spin 2s infinite linear; 1173 | -o-animation: spin 2s infinite linear; 1174 | animation: spin 2s infinite linear; 1175 | color: #ffffff; 1176 | font-size: 1.5em; 1177 | } 1178 | .notifications .notification .meta { 1179 | overflow: hidden; 1180 | padding-left: 3em; 1181 | } 1182 | .notifications .notification .meta .title-notification { 1183 | letter-spacing: .3em; 1184 | text-indent: .3em; 1185 | text-transform: uppercase; 1186 | display: block; 1187 | } 1188 | .notifications .notification .meta .description { 1189 | display: block; 1190 | } 1191 | .page.lists-show .content-scrollable { 1192 | background: #ffffff; 1193 | top: 5em !important; 1194 | } 1195 | .page.auth { 1196 | text-align: center; 1197 | } 1198 | .page.auth .content-scrollable { 1199 | background: #d2edf4; 1200 | } 1201 | .page.auth .wrapper-auth { 1202 | padding-top: 4em; 1203 | } 1204 | @media screen and (min-width: 40em) { 1205 | .page.auth .wrapper-auth { 1206 | margin: 0 auto; 1207 | max-width: 480px; 1208 | width: 80%; 1209 | } 1210 | } 1211 | .page.auth .wrapper-auth .title-auth { 1212 | font-size: 40px; 1213 | line-height: 48px; 1214 | font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 1215 | font-weight: 300; 1216 | color: #1c3f53; 1217 | margin-bottom: .75rem; 1218 | } 1219 | .page.auth .wrapper-auth .subtitle-auth { 1220 | color: #666666; 1221 | margin: 0 15% 3rem; 1222 | } 1223 | .page.auth .wrapper-auth form .input-symbol { 1224 | margin-bottom: 1px; 1225 | width: 100%; 1226 | } 1227 | .page.auth .wrapper-auth form .btn-primary { 1228 | margin: 1em 5% 0; 1229 | width: 90%; 1230 | } 1231 | @media screen and (min-width: 40em) { 1232 | .page.auth .wrapper-auth form .btn-primary { 1233 | margin-left: 0; 1234 | margin-right: 0; 1235 | width: 100%; 1236 | } 1237 | } 1238 | .page.auth .wrapper-auth .list-errors { 1239 | margin-top: -2rem; 1240 | } 1241 | .page.auth .wrapper-auth .list-errors .list-item { 1242 | letter-spacing: .3em; 1243 | text-indent: .3em; 1244 | text-transform: uppercase; 1245 | background: #f6fccf; 1246 | color: #ff4400; 1247 | font-size: .625em; 1248 | margin-bottom: 1px; 1249 | padding: .7rem 0; 1250 | } 1251 | .page.auth .link-auth-alt { 1252 | font-size: 12px; 1253 | line-height: 16px; 1254 | position: absolute; 1255 | top: auto; 1256 | right: 0; 1257 | bottom: 1em; 1258 | left: 0; 1259 | width: auto; 1260 | height: auto; 1261 | color: #aaaaaa; 1262 | display: inline-block; 1263 | } 1264 | @media screen and (min-width: 40em) { 1265 | .page.auth .link-auth-alt { 1266 | bottom: 0; 1267 | margin-top: 1rem; 1268 | position: relative; 1269 | } 1270 | } 1271 | .page.not-found .content-scrollable { 1272 | background: #d2edf4; 1273 | } 1274 | .loading-app { 1275 | position: absolute; 1276 | top: 50%; 1277 | right: 50%; 1278 | bottom: auto; 1279 | left: auto; 1280 | width: 50%; 1281 | height: auto; 1282 | -webkit-transform: translate3d(50%, -50%, 0); 1283 | -moz-transform: translate3d(50%, -50%, 0); 1284 | -ms-transform: translate3d(50%, -50%, 0); 1285 | -o-transform: translate3d(50%, -50%, 0); 1286 | transform: translate3d(50%, -50%, 0); 1287 | min-width: 160px; 1288 | max-width: 320px; 1289 | } 1290 | -------------------------------------------------------------------------------- /public/style/reset.css: -------------------------------------------------------------------------------- 1 | /* Reset.less 2 | * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc). 3 | * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */ 4 | 5 | html, 6 | body { 7 | margin: 0; 8 | padding: 0; 9 | } 10 | 11 | h1, 12 | h2, 13 | h3, 14 | h4, 15 | h5, 16 | h6, 17 | p, 18 | blockquote, 19 | pre, 20 | a, 21 | abbr, 22 | acronym, 23 | address, 24 | cite, 25 | code, 26 | del, 27 | dfn, 28 | em, 29 | img, 30 | q, 31 | s, 32 | samp, 33 | small, 34 | strike, 35 | strong, 36 | sub, 37 | sup, 38 | tt, 39 | var, 40 | dd, 41 | dl, 42 | dt, 43 | li, 44 | ol, 45 | ul, 46 | fieldset, 47 | form, 48 | label, 49 | legend, 50 | button, 51 | table, 52 | caption, 53 | tbody, 54 | tfoot, 55 | thead, 56 | tr, 57 | th, 58 | td { 59 | margin: 0; 60 | padding: 0; 61 | border: 0; 62 | font-weight: normal; 63 | font-style: normal; 64 | font-size: 100%; 65 | line-height: 1; 66 | font-family: inherit; 67 | } 68 | 69 | table { 70 | border-collapse: collapse; 71 | border-spacing: 0; 72 | } 73 | 74 | ol, 75 | ul { 76 | list-style: none; 77 | } 78 | 79 | q:before, 80 | q:after, 81 | blockquote:before, 82 | blockquote:after { 83 | content: ""; 84 | } 85 | 86 | html { 87 | font-size: 100%; 88 | -webkit-text-size-adjust: 100%; 89 | -ms-text-size-adjust: 100%; 90 | } 91 | 92 | a:focus { 93 | outline: thin dotted; 94 | } 95 | 96 | a:hover, 97 | a:active { 98 | outline: 0; 99 | } 100 | 101 | article, 102 | aside, 103 | details, 104 | figcaption, 105 | figure, 106 | footer, 107 | header, 108 | hgroup, 109 | nav, 110 | section { 111 | display: block; 112 | } 113 | 114 | audio, 115 | canvas, 116 | video { 117 | display: inline-block; 118 | *display: inline; 119 | *zoom: 1; 120 | } 121 | 122 | audio:not([controls]) { 123 | display: none; 124 | } 125 | 126 | sub, 127 | sup { 128 | font-size: 75%; 129 | line-height: 0; 130 | position: relative; 131 | vertical-align: baseline; 132 | } 133 | 134 | sup { 135 | top: -0.5em; 136 | } 137 | 138 | sub { 139 | bottom: -0.25em; 140 | } 141 | 142 | img { 143 | border: 0; 144 | -ms-interpolation-mode: bicubic; 145 | } 146 | 147 | button, 148 | input, 149 | select, 150 | textarea { 151 | font-size: 100%; 152 | margin: 0; 153 | vertical-align: baseline; 154 | *vertical-align: middle; 155 | } 156 | 157 | button, 158 | input { 159 | line-height: normal; 160 | *overflow: visible; 161 | } 162 | 163 | button::-moz-focus-inner, 164 | input::-moz-focus-inner { 165 | border: 0; 166 | padding: 0; 167 | } 168 | 169 | button, 170 | input[type="button"], 171 | input[type="reset"], 172 | input[type="submit"] { 173 | cursor: pointer; 174 | -webkit-appearance: button; 175 | } 176 | 177 | input[type="search"] { 178 | -webkit-appearance: textfield; 179 | -webkit-box-sizing: content-box; 180 | -moz-box-sizing: content-box; 181 | box-sizing: content-box; 182 | } 183 | 184 | input[type="search"]::-webkit-search-decoration { 185 | -webkit-appearance: none; 186 | } 187 | 188 | textarea { 189 | overflow: auto; 190 | vertical-align: top; 191 | } 192 | 193 | @font-face { 194 | font-family: 'Open Sans'; 195 | src: url('/font/OpenSans-Light-webfont.eot'); 196 | src: url('/font/OpenSans-Light-webfont.eot?') format('embedded-opentype'), url('/font/OpenSans-Light-webfont.woff') format('woff'), url('/font/OpenSans-Light-webfont.ttf') format('truetype'), url('/font/OpenSans-Light-webfont.svg') format('svg'); 197 | font-weight: 200; 198 | font-style: normal; 199 | } 200 | 201 | @font-face { 202 | font-family: 'Open Sans'; 203 | src: url('/font/OpenSans-Regular-webfont.eot'); 204 | src: url('/font/OpenSans-Regular-webfont.eot?') format('embedded-opentype'), url('/font/OpenSans-Regular-webfont.woff') format('woff'), url('/font/OpenSans-Regular-webfont.ttf') format('truetype'), url('/font/OpenSans-Regular-webfont.svg') format('svg'); 205 | font-weight: normal; 206 | font-weight: 400; 207 | font-style: normal; 208 | } 209 | 210 | .force-wrap { 211 | word-wrap: break-word; 212 | word-break: break-all; 213 | -ms-word-break: break-all; 214 | word-break: break-word; 215 | -webkit-hyphens: auto; 216 | -moz-hyphens: auto; 217 | -ms-hyphens: auto; 218 | hyphens: auto; 219 | } 220 | 221 | .type-light { 222 | font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 223 | font-weight: 300; 224 | } 225 | 226 | * { 227 | -webkit-box-sizing: border-box; 228 | -moz-box-sizing: border-box; 229 | box-sizing: border-box; 230 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 231 | -webkit-tap-highlight-color: transparent; 232 | } 233 | 234 | html, 235 | button, 236 | input, 237 | textarea, 238 | select { 239 | outline: none; 240 | -webkit-font-smoothing: antialiased; 241 | -moz-osx-font-smoothing: grayscale; 242 | } 243 | 244 | body { 245 | font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 246 | font-style: 400; 247 | color: #333333; 248 | font-size: 16px; 249 | } 250 | 251 | h1, 252 | h2, 253 | h3, 254 | h4, 255 | h5, 256 | h6 { 257 | font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 258 | font-style: 400; 259 | margin: 0; 260 | padding: 0; 261 | } 262 | 263 | h1 { 264 | font-size: 40px; 265 | line-height: 48px; 266 | } 267 | 268 | h2 { 269 | font-size: 28px; 270 | line-height: 32px; 271 | } 272 | 273 | h3 { 274 | font-size: 24px; 275 | line-height: 28px; 276 | } 277 | 278 | h4 { 279 | font-size: 20px; 280 | line-height: 24px; 281 | } 282 | 283 | h5 { 284 | font-size: 14px; 285 | line-height: 20px; 286 | color: #cccccc; 287 | text-transform: uppercase; 288 | } 289 | 290 | h6 { 291 | color: #aaaaaa; 292 | } 293 | 294 | p { 295 | font-size: 16px; 296 | line-height: 24px; 297 | } 298 | 299 | sub, 300 | sup { 301 | font-size: .8em; 302 | } 303 | 304 | sub { 305 | bottom: -0.2em; 306 | } 307 | 308 | sup { 309 | top: -0.2em; 310 | } 311 | 312 | b { 313 | font-weight: bold; 314 | } 315 | 316 | em { 317 | font-style: italic; 318 | } 319 | 320 | [class^="btn-"], 321 | [class*=" btn-"] { 322 | font-size: 14px; 323 | line-height: 20px; 324 | line-height: 20px !important; 325 | padding: 1em 1.25em; 326 | letter-spacing: .3em; 327 | text-indent: .3em; 328 | text-transform: uppercase; 329 | -webkit-transition: all 200ms ease-in; 330 | -moz-transition: all 200ms ease-in; 331 | -o-transition: all 200ms ease-in; 332 | transition: all 200ms ease-in; 333 | color: #ffffff; 334 | display: inline-block; 335 | position: relative; 336 | text-align: center; 337 | text-decoration: none !important; 338 | vertical-align: middle; 339 | white-space: nowrap; 340 | } 341 | 342 | [class^="btn-"][class*="primary"], 343 | [class*=" btn-"][class*="primary"] { 344 | background-color: #2cc5d2; 345 | color: #ffffff; 346 | } 347 | 348 | [class^="btn-"][class*="primary"]:hover, 349 | [class*=" btn-"][class*="primary"]:hover { 350 | background-color: #28b1bd; 351 | } 352 | 353 | [class^="btn-"][class*="primary"]:active, 354 | [class*=" btn-"][class*="primary"]:active { 355 | box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px 0 inset; 356 | } 357 | 358 | [class^="btn-"][class*="secondary"], 359 | [class*=" btn-"][class*="secondary"] { 360 | -webkit-transition: all 300ms ease-in; 361 | -moz-transition: all 300ms ease-in; 362 | -o-transition: all 300ms ease-in; 363 | transition: all 300ms ease-in; 364 | box-shadow: #5a7ca6 0 0 0 1px inset; 365 | color: #ffffff; 366 | } 367 | 368 | [class^="btn-"][class*="secondary"]:hover, 369 | [class*=" btn-"][class*="secondary"]:hover { 370 | color: #eeeeee; 371 | } 372 | 373 | [class^="btn-"][class*="secondary"]:active, 374 | [class*=" btn-"][class*="secondary"]:active, 375 | [class^="btn-"][class*="secondary"].active, 376 | [class*=" btn-"][class*="secondary"].active { 377 | box-shadow: #9db1ca 0 0 0 1px inset; 378 | } 379 | 380 | [class^="btn-"][disabled], 381 | [class*=" btn-"][disabled] { 382 | opacity: .5; 383 | } 384 | 385 | .btns-group { 386 | display: -webkit-box; 387 | display: -moz-box; 388 | display: -webkit-flex; 389 | display: -ms-flexbox; 390 | display: flex; 391 | -webkit-flex-wrap: wrap; 392 | -ms-flex-wrap: wrap; 393 | flex-wrap: wrap; 394 | width: 100%; 395 | } 396 | 397 | .btns-group [class*="btn-"] { 398 | overflow: hidden; 399 | text-overflow: ellipsis; 400 | white-space: nowrap; 401 | -webkit-box-flex: 1; 402 | -moz-box-flex: 1; 403 | -webkit-flex: 1; 404 | -ms-flex: 1; 405 | flex: 1; 406 | } 407 | 408 | .btns-group [class*="btn-"] + [class*="btn-"] { 409 | margin-left: -1px; 410 | } 411 | 412 | input[type="text"], 413 | input[type="email"], 414 | input[type="password"], 415 | textarea { 416 | font-size: 14px; 417 | line-height: 20px; 418 | font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 419 | font-style: 400; 420 | padding: .75rem 0; 421 | line-height: 1.5rem !important; 422 | border: none; 423 | border-radius: 0; 424 | box-sizing: border-box; 425 | color: #333333; 426 | outline: none; 427 | } 428 | 429 | input[type="text"]::-webkit-input-placeholder, 430 | input[type="email"]::-webkit-input-placeholder, 431 | input[type="password"]::-webkit-input-placeholder, 432 | textarea::-webkit-input-placeholder { 433 | color: #778b91; 434 | } 435 | 436 | input[type="text"]:-moz-placeholder, 437 | input[type="email"]:-moz-placeholder, 438 | input[type="password"]:-moz-placeholder, 439 | textarea:-moz-placeholder { 440 | color: #778b91; 441 | } 442 | 443 | input[type="text"]::-moz-placeholder, 444 | input[type="email"]::-moz-placeholder, 445 | input[type="password"]::-moz-placeholder, 446 | textarea::-moz-placeholder { 447 | color: #778b91; 448 | } 449 | 450 | input[type="text"]:-ms-input-placeholder, 451 | input[type="email"]:-ms-input-placeholder, 452 | input[type="password"]:-ms-input-placeholder, 453 | textarea:-ms-input-placeholder { 454 | color: #778b91; 455 | } 456 | 457 | input[type="text"][disabled], 458 | input[type="email"][disabled], 459 | input[type="password"][disabled], 460 | textarea[disabled] { 461 | opacity: .5; 462 | } 463 | 464 | input:-webkit-autofill { 465 | -webkit-box-shadow: 0 0 0 1000px #ffffff inset; 466 | } 467 | 468 | .checkbox { 469 | display: inline-block; 470 | height: 3rem; 471 | position: relative; 472 | vertical-align: middle; 473 | width: 44px; 474 | } 475 | 476 | .checkbox input[type="checkbox"] { 477 | font-size: 1em; 478 | visibility: hidden; 479 | } 480 | 481 | .checkbox input[type="checkbox"] + span:before { 482 | position: absolute; 483 | top: 50%; 484 | right: auto; 485 | bottom: auto; 486 | left: 50%; 487 | width: 0.85em; 488 | height: 0.85em; 489 | -webkit-transform: translate3d(-50%, -50%, 0); 490 | -moz-transform: translate3d(-50%, -50%, 0); 491 | -ms-transform: translate3d(-50%, -50%, 0); 492 | -o-transform: translate3d(-50%, -50%, 0); 493 | transform: translate3d(-50%, -50%, 0); 494 | background: transparent; 495 | box-shadow: #abdfe3 0 0 0 1px inset; 496 | content: ''; 497 | display: block; 498 | } 499 | 500 | .checkbox input[type="checkbox"]:checked + span:before { 501 | box-shadow: none; 502 | color: #cccccc; 503 | font-family: 'todos'; 504 | speak: none; 505 | font-style: normal; 506 | font-weight: normal; 507 | font-variant: normal; 508 | text-transform: none; 509 | line-height: 1; 510 | -webkit-font-smoothing: antialiased; 511 | -moz-osx-font-smoothing: grayscale; 512 | content: "\e612"; 513 | } 514 | 515 | .input-symbol { 516 | display: inline-block; 517 | position: relative; 518 | } 519 | 520 | .input-symbol.error [class^="icon-"], 521 | .input-symbol.error [class*=" icon-"] { 522 | color: #ff4400; 523 | } 524 | 525 | .input-symbol [class^="icon-"], 526 | .input-symbol [class*=" icon-"] { 527 | left: 1em; 528 | } 529 | 530 | .input-symbol input { 531 | padding-left: 3em; 532 | } 533 | 534 | .input-symbol input { 535 | width: 100%; 536 | } 537 | 538 | .input-symbol input:focus + [class^="icon-"], 539 | .input-symbol input:focus + [class*=" icon-"] { 540 | color: #2cc5d2; 541 | } 542 | 543 | .input-symbol [class^="icon-"], 544 | .input-symbol [class*=" icon-"] { 545 | -webkit-transition: all 300ms ease-in; 546 | -moz-transition: all 300ms ease-in; 547 | -o-transition: all 300ms ease-in; 548 | transition: all 300ms ease-in; 549 | -webkit-transform: translate3d(0, -50%, 0); 550 | -moz-transform: translate3d(0, -50%, 0); 551 | -ms-transform: translate3d(0, -50%, 0); 552 | -o-transform: translate3d(0, -50%, 0); 553 | transform: translate3d(0, -50%, 0); 554 | background: transparent; 555 | color: #aaaaaa; 556 | font-size: 1em; 557 | height: 1em; 558 | position: absolute; 559 | top: 50%; 560 | width: 1em; 561 | } 562 | 563 | @font-face { 564 | font-family: 'todos'; 565 | src: url('/icon/todos.eot?-5w3um4'); 566 | src: url('/icon/todos.eot?') format('embedded-opentype'), url('/icon/todos.woff?5w3um4') format('woff'), url('/icon/todos.ttf?5w3um4') format('truetype'), url('/icon/todos.svg?5w3um4') format('svg'); 567 | font-weight: normal; 568 | font-style: normal; 569 | } 570 | 571 | [class^="icon-"], 572 | [class*=" icon-"] { 573 | font-family: 'todos'; 574 | speak: none; 575 | font-style: normal; 576 | font-weight: normal; 577 | font-variant: normal; 578 | text-transform: none; 579 | line-height: 1; 580 | -webkit-font-smoothing: antialiased; 581 | -moz-osx-font-smoothing: grayscale; 582 | } 583 | 584 | .icon-unlock:before { 585 | content: "\e600"; 586 | } 587 | 588 | .icon-user-add:before { 589 | content: "\e604"; 590 | } 591 | 592 | .icon-cog:before { 593 | content: "\e606"; 594 | } 595 | 596 | .icon-trash:before { 597 | content: "\e607"; 598 | } 599 | 600 | .icon-edit:before { 601 | content: "\e608"; 602 | } 603 | 604 | .icon-add:before { 605 | content: "\e60a"; 606 | } 607 | 608 | .icon-plus:before { 609 | content: "\e60b"; 610 | } 611 | 612 | .icon-close:before { 613 | content: "\e60c"; 614 | } 615 | 616 | .icon-cross:before { 617 | content: "\e60d"; 618 | } 619 | 620 | .icon-sync:before { 621 | content: "\e60e"; 622 | } 623 | 624 | .icon-lock:before { 625 | content: "\e610"; 626 | } 627 | 628 | .icon-check:before { 629 | content: "\e612"; 630 | } 631 | 632 | .icon-share:before { 633 | content: "\e617"; 634 | } 635 | 636 | .icon-email:before { 637 | content: "\e619"; 638 | } 639 | 640 | .icon-arrow-up:before { 641 | content: "\e623"; 642 | } 643 | 644 | .icon-arrow-down:before { 645 | content: "\e626"; 646 | } 647 | 648 | .icon-list-unordered:before { 649 | content: "\e634"; 650 | } 651 | 652 | body { 653 | position: absolute; 654 | top: 0; 655 | right: 0; 656 | bottom: 0; 657 | left: 0; 658 | width: auto; 659 | height: auto; 660 | background-color: #315481; 661 | background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMSAxIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIj48bGluZWFyR3JhZGllbnQgaWQ9Imxlc3NoYXQtZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiMzMTU0ODEiIHN0b3Atb3BhY2l0eT0iMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzkxOGU4MiIgc3RvcC1vcGFjaXR5PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2xlc3NoYXQtZ2VuZXJhdGVkKSIgLz48L3N2Zz4=); 662 | background-image: -webkit-linear-gradient(top, #315481, #918e82 100%); 663 | background-image: -moz-linear-gradient(top, #315481, #918e82 100%); 664 | background-image: -o-linear-gradient(top, #315481, #918e82 100%); 665 | background-image: linear-gradient(to bottom, #315481, #918e82 100%); 666 | background-repeat: no-repeat; 667 | background-attachment: fixed; 668 | } 669 | 670 | #container { 671 | position: absolute; 672 | top: 0; 673 | right: 0; 674 | bottom: 0; 675 | left: 0; 676 | width: auto; 677 | height: auto; 678 | overflow: hidden; 679 | } 680 | 681 | @media screen and (min-width: 60em) { 682 | #container { 683 | left: 5.55555%; 684 | right: 5.55555%; 685 | } 686 | } 687 | 688 | @media screen and (min-width: 80em) { 689 | #container { 690 | left: 11.1111%; 691 | right: 11.1111%; 692 | } 693 | } 694 | 695 | #menu { 696 | position: absolute; 697 | top: 0; 698 | right: 0; 699 | bottom: 0; 700 | left: 0; 701 | width: 270px; 702 | height: auto; 703 | } 704 | 705 | #content-container { 706 | position: absolute; 707 | top: 0; 708 | right: 0; 709 | bottom: 0; 710 | left: 0; 711 | width: auto; 712 | height: auto; 713 | -webkit-transition: all 200ms ease-out; 714 | -moz-transition: all 200ms ease-out; 715 | -o-transition: all 200ms ease-out; 716 | transition: all 200ms ease-out; 717 | -webkit-transform: translate3d(0, 0, 0); 718 | -moz-transform: translate3d(0, 0, 0); 719 | -ms-transform: translate3d(0, 0, 0); 720 | -o-transform: translate3d(0, 0, 0); 721 | transform: translate3d(0, 0, 0); 722 | background: #d2edf4; 723 | opacity: 1; 724 | } 725 | 726 | @media screen and (min-width: 40em) { 727 | #content-container { 728 | left: 270px; 729 | } 730 | } 731 | 732 | #content-container .content-scrollable { 733 | position: absolute; 734 | top: 0; 735 | right: 0; 736 | bottom: 0; 737 | left: 0; 738 | width: auto; 739 | height: auto; 740 | -webkit-transform: translate3d(0, 0, 0); 741 | -moz-transform: translate3d(0, 0, 0); 742 | -ms-transform: translate3d(0, 0, 0); 743 | -o-transform: translate3d(0, 0, 0); 744 | transform: translate3d(0, 0, 0); 745 | overflow-y: auto; 746 | -webkit-overflow-scrolling: touch; 747 | } 748 | 749 | .menu-open #content-container { 750 | -webkit-transform: translate3d(270px, 0, 0); 751 | -moz-transform: translate3d(270px, 0, 0); 752 | -ms-transform: translate3d(270px, 0, 0); 753 | -o-transform: translate3d(270px, 0, 0); 754 | transform: translate3d(270px, 0, 0); 755 | opacity: .85; 756 | left: 0; 757 | } 758 | 759 | @media screen and (min-width: 40em) { 760 | .menu-open #content-container { 761 | -webkit-transform: translate3d(0, 0, 0); 762 | -moz-transform: translate3d(0, 0, 0); 763 | -ms-transform: translate3d(0, 0, 0); 764 | -o-transform: translate3d(0, 0, 0); 765 | transform: translate3d(0, 0, 0); 766 | opacity: 1; 767 | left: 270px; 768 | } 769 | } 770 | 771 | .content-overlay { 772 | position: absolute; 773 | top: 0; 774 | right: 0; 775 | bottom: 0; 776 | left: 0; 777 | width: auto; 778 | height: auto; 779 | cursor: pointer; 780 | } 781 | 782 | .menu-open .content-overlay { 783 | -webkit-transform: translate3d(270px, 0, 0); 784 | -moz-transform: translate3d(270px, 0, 0); 785 | -ms-transform: translate3d(270px, 0, 0); 786 | -o-transform: translate3d(270px, 0, 0); 787 | transform: translate3d(270px, 0, 0); 788 | z-index: 1; 789 | } 790 | 791 | @media screen and (min-width: 40em) { 792 | .content-overlay { 793 | display: none; 794 | } 795 | } 796 | 797 | a { 798 | -webkit-transition: all 200ms ease-in; 799 | -moz-transition: all 200ms ease-in; 800 | -o-transition: all 200ms ease-in; 801 | transition: all 200ms ease-in; 802 | color: #5db9ff; 803 | cursor: pointer; 804 | text-decoration: none; 805 | } 806 | 807 | a:hover { 808 | color: #239da8; 809 | } 810 | 811 | a:active { 812 | color: #555555; 813 | } 814 | 815 | a:focus { 816 | outline: none; 817 | } 818 | 819 | #menu { 820 | overflow-y: auto; 821 | -webkit-overflow-scrolling: touch; 822 | } 823 | 824 | #menu .btns-group, 825 | #menu .btns-group-vertical { 826 | margin: 2em auto 2em; 827 | width: 80%; 828 | } 829 | 830 | #menu .btns-group .btn-secondary, 831 | #menu .btns-group-vertical .btn-secondary { 832 | font-size: 12px; 833 | line-height: 16px; 834 | padding-top: .5em; 835 | padding-bottom: .5em; 836 | } 837 | 838 | #menu .btns-group-vertical .btn-secondary { 839 | word-wrap: break-word; 840 | word-break: break-all; 841 | -ms-word-break: break-all; 842 | word-break: break-word; 843 | -webkit-hyphens: auto; 844 | -moz-hyphens: auto; 845 | -ms-hyphens: auto; 846 | hyphens: auto; 847 | padding-right: 2.5em; 848 | text-align: left; 849 | text-indent: 0; 850 | white-space: normal; 851 | width: 100%; 852 | } 853 | 854 | #menu .btns-group-vertical .btn-secondary + .btn-secondary { 855 | margin-top: .5rem; 856 | } 857 | 858 | #menu .btns-group-vertical .btn-secondary + .btn-secondary:before { 859 | position: absolute; 860 | top: -0.5rem; 861 | right: 50%; 862 | bottom: auto; 863 | left: auto; 864 | width: 1px; 865 | height: 0.5rem; 866 | background: #5a7ca6; 867 | content: ''; 868 | } 869 | 870 | #menu .btns-group-vertical .btn-secondary [class^="icon-"], 871 | #menu .btns-group-vertical .btn-secondary [class*=" icon-"] { 872 | position: absolute; 873 | top: 0.5em; 874 | right: 0.5em; 875 | bottom: auto; 876 | left: auto; 877 | width: auto; 878 | height: auto; 879 | line-height: 20px; 880 | } 881 | 882 | #menu .list-todos a { 883 | box-shadow: rgba(255, 255, 255, 0.15) 0 1px 0 0; 884 | display: block; 885 | line-height: 1.5em; 886 | padding: .75em 2.5em; 887 | position: relative; 888 | } 889 | 890 | #menu .list-todos .count-list { 891 | -webkit-transition: all 200ms ease-in; 892 | -moz-transition: all 200ms ease-in; 893 | -o-transition: all 200ms ease-in; 894 | transition: all 200ms ease-in; 895 | background: rgba(255, 255, 255, 0.1); 896 | border-radius: 1em; 897 | float: right; 898 | font-size: .7rem; 899 | line-height: 1; 900 | margin-top: .25rem; 901 | margin-right: -1.5em; 902 | padding: .3em .5em; 903 | } 904 | 905 | #menu .list-todos [class^="icon-"], 906 | #menu .list-todos [class*=" icon-"] { 907 | font-size: 14px; 908 | line-height: 20px; 909 | float: left; 910 | margin-left: -1.5rem; 911 | margin-right: .5rem; 912 | margin-top: .1rem; 913 | width: 1em; 914 | } 915 | 916 | #menu .list-todos .icon-lock { 917 | font-size: 12px; 918 | line-height: 16px; 919 | margin-top: .2rem; 920 | opacity: .8; 921 | } 922 | 923 | #menu .list-todos .list-todo { 924 | color: rgba(255, 255, 255, 0.4); 925 | } 926 | 927 | #menu .list-todos .list-todo:hover, 928 | #menu .list-todos .list-todo:active, 929 | #menu .list-todos .list-todo.active { 930 | color: #ffffff; 931 | } 932 | 933 | #menu .list-todos .list-todo:hover .count-list, 934 | #menu .list-todos .list-todo:active .count-list, 935 | #menu .list-todos .list-todo.active .count-list { 936 | background: #2cc5d2; 937 | } 938 | 939 | .cordova #menu .list-todos .list-todo:hover { 940 | color: rgba(255, 255, 255, 0.4); 941 | } 942 | 943 | nav { 944 | position: absolute; 945 | top: 0; 946 | right: 0; 947 | bottom: auto; 948 | left: 0; 949 | width: auto; 950 | height: auto; 951 | -webkit-transform: translate3d(0, 0, 0); 952 | -moz-transform: translate3d(0, 0, 0); 953 | -ms-transform: translate3d(0, 0, 0); 954 | -o-transform: translate3d(0, 0, 0); 955 | transform: translate3d(0, 0, 0); 956 | -webkit-transition: all 200ms ease-out; 957 | -moz-transition: all 200ms ease-out; 958 | -o-transition: all 200ms ease-out; 959 | transition: all 200ms ease-out; 960 | z-index: 10; 961 | } 962 | 963 | nav .nav-item { 964 | font-size: 20px; 965 | line-height: 24px; 966 | color: #1c3f53; 967 | display: inline-block; 968 | height: 3rem; 969 | text-align: center; 970 | width: 3rem; 971 | } 972 | 973 | nav .nav-item:active { 974 | opacity: .5; 975 | } 976 | 977 | nav .nav-item [class^="icon-"], 978 | nav .nav-item [class*=" icon-"] { 979 | line-height: 3rem; 980 | vertical-align: middle; 981 | } 982 | 983 | nav .nav-group { 984 | position: absolute; 985 | top: 0; 986 | right: auto; 987 | bottom: auto; 988 | left: 0; 989 | width: auto; 990 | height: auto; 991 | z-index: 1; 992 | } 993 | 994 | nav .nav-group.right { 995 | left: auto; 996 | right: 0; 997 | } 998 | 999 | .page.lists-show nav { 1000 | background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMSAxIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIj48bGluZWFyR3JhZGllbnQgaWQ9Imxlc3NoYXQtZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiNkMGVkZjUiIHN0b3Atb3BhY2l0eT0iMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2UxZTVmMCIgc3RvcC1vcGFjaXR5PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2xlc3NoYXQtZ2VuZXJhdGVkKSIgLz48L3N2Zz4=); 1001 | background-image: -webkit-linear-gradient(top, #d0edf5, #e1e5f0 100%); 1002 | background-image: -moz-linear-gradient(top, #d0edf5, #e1e5f0 100%); 1003 | background-image: -o-linear-gradient(top, #d0edf5, #e1e5f0 100%); 1004 | background-image: linear-gradient(to bottom, #d0edf5, #e1e5f0 100%); 1005 | height: 5em; 1006 | text-align: center; 1007 | } 1008 | 1009 | @media screen and (min-width: 40em) { 1010 | .page.lists-show nav { 1011 | text-align: left; 1012 | } 1013 | } 1014 | 1015 | .page.lists-show nav .title-page { 1016 | position: absolute; 1017 | top: 0; 1018 | right: 3rem; 1019 | bottom: auto; 1020 | left: 3rem; 1021 | width: auto; 1022 | height: auto; 1023 | cursor: pointer; 1024 | font-size: 1.125em; 1025 | white-space: nowrap; 1026 | } 1027 | 1028 | @media screen and (min-width: 40em) { 1029 | .page.lists-show nav .title-page { 1030 | left: 1rem; 1031 | right: 6rem; 1032 | } 1033 | } 1034 | 1035 | .page.lists-show nav .title-page .title-wrapper { 1036 | overflow: hidden; 1037 | text-overflow: ellipsis; 1038 | white-space: nowrap; 1039 | color: #1c3f53; 1040 | display: inline-block; 1041 | padding-right: 1.5rem; 1042 | vertical-align: top; 1043 | max-width: 100%; 1044 | } 1045 | 1046 | .page.lists-show nav .title-page .count-list { 1047 | background: #2cc5d2; 1048 | border-radius: 1em; 1049 | color: #ffffff; 1050 | display: inline-block; 1051 | font-size: .7rem; 1052 | line-height: 1; 1053 | margin-left: -1.25rem; 1054 | margin-top: -4px; 1055 | padding: .3em .5em; 1056 | vertical-align: middle; 1057 | } 1058 | 1059 | .page.lists-show nav form.todo-new { 1060 | position: absolute; 1061 | top: 3em; 1062 | right: 0; 1063 | bottom: auto; 1064 | left: 0; 1065 | width: auto; 1066 | height: auto; 1067 | } 1068 | 1069 | .page.lists-show nav form.todo-new input[type="text"] { 1070 | background: transparent; 1071 | padding-bottom: .25em; 1072 | padding-left: 44px !important; 1073 | padding-top: .25em; 1074 | } 1075 | 1076 | .page.lists-show nav form.list-edit-form { 1077 | position: relative; 1078 | } 1079 | 1080 | .page.lists-show nav form.list-edit-form input[type="text"] { 1081 | background: transparent; 1082 | font-size: 1.125em; 1083 | width: 100%; 1084 | padding-right: 3em; 1085 | padding-left: 1rem; 1086 | } 1087 | 1088 | .page.lists-show nav select.list-edit { 1089 | font-size: 14px; 1090 | line-height: 20px; 1091 | position: absolute; 1092 | top: 0; 1093 | right: 0; 1094 | bottom: 0; 1095 | left: 0; 1096 | width: auto; 1097 | height: auto; 1098 | background: transparent; 1099 | opacity: 0; 1100 | } 1101 | 1102 | .page.lists-show nav .options-web { 1103 | display: none; 1104 | } 1105 | 1106 | .page.lists-show nav .options-web .nav-item { 1107 | font-size: 16px; 1108 | line-height: 24px; 1109 | width: 2rem; 1110 | } 1111 | 1112 | .page.lists-show nav .options-web .nav-item:last-child { 1113 | margin-right: .5rem; 1114 | } 1115 | 1116 | @media screen and (min-width: 40em) { 1117 | .page.lists-show nav .nav-group:not(.right) { 1118 | display: none !important; 1119 | } 1120 | 1121 | .page.lists-show nav .options-mobile { 1122 | display: none; 1123 | } 1124 | 1125 | .page.lists-show nav .options-web { 1126 | display: block; 1127 | } 1128 | } 1129 | 1130 | @media screen and (min-width: 40em) { 1131 | .page.auth .nav-group { 1132 | display: none; 1133 | } 1134 | 1135 | .page.not-found .nav-group { 1136 | display: none; 1137 | } 1138 | } 1139 | 1140 | .list-items .list-item { 1141 | font-size: 14px; 1142 | line-height: 20px; 1143 | display: -webkit-box; 1144 | display: -moz-box; 1145 | display: -webkit-flex; 1146 | display: -ms-flexbox; 1147 | display: flex; 1148 | -webkit-flex-wrap: wrap; 1149 | -ms-flex-wrap: wrap; 1150 | flex-wrap: wrap; 1151 | height: 3rem; 1152 | width: 100%; 1153 | } 1154 | 1155 | .list-items .list-item .checkbox { 1156 | -webkit-box-flex: 0; 1157 | -moz-box-flex: 0; 1158 | -webkit-flex: 0 0 44px; 1159 | -ms-flex: 0 0 44px; 1160 | flex: 0 0 44px; 1161 | cursor: pointer; 1162 | } 1163 | 1164 | .list-items .list-item input[type="text"] { 1165 | -webkit-box-flex: 1; 1166 | -moz-box-flex: 1; 1167 | -webkit-flex: 1; 1168 | -ms-flex: 1; 1169 | flex: 1; 1170 | } 1171 | 1172 | .list-items .list-item .delete-item { 1173 | -webkit-box-flex: 0; 1174 | -moz-box-flex: 0; 1175 | -webkit-flex: 0 0 3rem; 1176 | -ms-flex: 0 0 3rem; 1177 | flex: 0 0 3rem; 1178 | } 1179 | 1180 | .list-items .list-item input[type="text"] { 1181 | background: transparent; 1182 | cursor: pointer; 1183 | } 1184 | 1185 | .list-items .list-item input[type="text"]:focus { 1186 | cursor: text; 1187 | } 1188 | 1189 | .list-items .list-item .delete-item { 1190 | color: #cccccc; 1191 | line-height: 3rem; 1192 | text-align: center; 1193 | } 1194 | 1195 | .list-items .list-item .delete-item:hover { 1196 | color: #2cc5d2; 1197 | } 1198 | 1199 | .list-items .list-item .delete-item:active { 1200 | color: #555555; 1201 | } 1202 | 1203 | .list-items .list-item .delete-item .icon-trash { 1204 | font-size: 1.1em; 1205 | } 1206 | 1207 | .list-items .list-item + .list-item { 1208 | border-top: 1px solid #f0f9fb; 1209 | } 1210 | 1211 | .list-items .list-item.checked input[type="text"] { 1212 | color: #cccccc; 1213 | text-decoration: line-through; 1214 | } 1215 | 1216 | .list-items .list-item.checked .delete-item { 1217 | display: inline-block; 1218 | } 1219 | 1220 | .list-items .list-item .delete-item { 1221 | display: none; 1222 | } 1223 | 1224 | .list-items .list-item.editing .delete-item { 1225 | display: inline-block; 1226 | } 1227 | 1228 | .wrapper-message { 1229 | position: absolute; 1230 | top: 45%; 1231 | right: 0; 1232 | bottom: auto; 1233 | left: 0; 1234 | width: auto; 1235 | height: auto; 1236 | -webkit-transform: translate3d(0, -50%, 0); 1237 | -moz-transform: translate3d(0, -50%, 0); 1238 | -ms-transform: translate3d(0, -50%, 0); 1239 | -o-transform: translate3d(0, -50%, 0); 1240 | transform: translate3d(0, -50%, 0); 1241 | text-align: center; 1242 | } 1243 | 1244 | .wrapper-message .title-message { 1245 | font-size: 24px; 1246 | line-height: 28px; 1247 | font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 1248 | font-weight: 300; 1249 | color: #1c3f53; 1250 | margin-bottom: .5em; 1251 | } 1252 | 1253 | .wrapper-message .subtitle-message { 1254 | font-size: 14px; 1255 | line-height: 20px; 1256 | color: #aaaaaa; 1257 | } 1258 | 1259 | @-webkit-keyframes spin { 1260 | 0% { 1261 | -webkit-transform: rotate(0deg); 1262 | -moz-transform: rotate(0deg); 1263 | -ms-transform: rotate(0deg); 1264 | -o-transform: rotate(0deg); 1265 | transform: rotate(0deg); 1266 | } 1267 | 1268 | 100% { 1269 | -webkit-transform: rotate(359deg); 1270 | -moz-transform: rotate(359deg); 1271 | -ms-transform: rotate(359deg); 1272 | -o-transform: rotate(359deg); 1273 | transform: rotate(359deg); 1274 | } 1275 | } 1276 | 1277 | @keyframes spin { 1278 | 0% { 1279 | -webkit-transform: rotate(0deg); 1280 | -moz-transform: rotate(0deg); 1281 | -ms-transform: rotate(0deg); 1282 | -o-transform: rotate(0deg); 1283 | transform: rotate(0deg); 1284 | } 1285 | 1286 | 100% { 1287 | -webkit-transform: rotate(359deg); 1288 | -moz-transform: rotate(359deg); 1289 | -ms-transform: rotate(359deg); 1290 | -o-transform: rotate(359deg); 1291 | transform: rotate(359deg); 1292 | } 1293 | } 1294 | 1295 | .notifications { 1296 | position: absolute; 1297 | top: auto; 1298 | right: auto; 1299 | bottom: 10px; 1300 | left: 50%; 1301 | width: 280px; 1302 | height: auto; 1303 | -webkit-transform: translate3d(-50%, 0, 0); 1304 | -moz-transform: translate3d(-50%, 0, 0); 1305 | -ms-transform: translate3d(-50%, 0, 0); 1306 | -o-transform: translate3d(-50%, 0, 0); 1307 | transform: translate3d(-50%, 0, 0); 1308 | z-index: 1; 1309 | } 1310 | 1311 | @media screen and (min-width: 40em) { 1312 | .notifications { 1313 | -webkit-transform: translate3d(0, 0, 0); 1314 | -moz-transform: translate3d(0, 0, 0); 1315 | -ms-transform: translate3d(0, 0, 0); 1316 | -o-transform: translate3d(0, 0, 0); 1317 | transform: translate3d(0, 0, 0); 1318 | bottom: auto; 1319 | right: 1rem; 1320 | top: 1rem; 1321 | left: auto; 1322 | } 1323 | } 1324 | 1325 | .notifications .notification { 1326 | font-size: 12px; 1327 | line-height: 16px; 1328 | background: rgba(51, 51, 51, 0.85); 1329 | color: #ffffff; 1330 | margin-bottom: .25rem; 1331 | padding: .5rem .75rem; 1332 | position: relative; 1333 | width: 100%; 1334 | } 1335 | 1336 | .notifications .notification .icon-sync { 1337 | position: absolute; 1338 | top: 30%; 1339 | right: auto; 1340 | bottom: auto; 1341 | left: 1rem; 1342 | width: auto; 1343 | height: auto; 1344 | -webkit-animation: spin 2s infinite linear; 1345 | -moz-animation: spin 2s infinite linear; 1346 | -o-animation: spin 2s infinite linear; 1347 | animation: spin 2s infinite linear; 1348 | color: #ffffff; 1349 | font-size: 1.5em; 1350 | } 1351 | 1352 | .notifications .notification .meta { 1353 | overflow: hidden; 1354 | padding-left: 3em; 1355 | } 1356 | 1357 | .notifications .notification .meta .title-notification { 1358 | letter-spacing: .3em; 1359 | text-indent: .3em; 1360 | text-transform: uppercase; 1361 | display: block; 1362 | } 1363 | 1364 | .notifications .notification .meta .description { 1365 | display: block; 1366 | } 1367 | 1368 | .page.lists-show .content-scrollable { 1369 | background: #ffffff; 1370 | top: 5em !important; 1371 | } 1372 | 1373 | .page.auth { 1374 | text-align: center; 1375 | } 1376 | 1377 | .page.auth .content-scrollable { 1378 | background: #d2edf4; 1379 | } 1380 | 1381 | .page.auth .wrapper-auth { 1382 | padding-top: 4em; 1383 | } 1384 | 1385 | @media screen and (min-width: 40em) { 1386 | .page.auth .wrapper-auth { 1387 | margin: 0 auto; 1388 | max-width: 480px; 1389 | width: 80%; 1390 | } 1391 | } 1392 | 1393 | .page.auth .wrapper-auth .title-auth { 1394 | font-size: 40px; 1395 | line-height: 48px; 1396 | font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 1397 | font-weight: 300; 1398 | color: #1c3f53; 1399 | margin-bottom: .75rem; 1400 | } 1401 | 1402 | .page.auth .wrapper-auth .subtitle-auth { 1403 | color: #666666; 1404 | margin: 0 15% 3rem; 1405 | } 1406 | 1407 | .page.auth .wrapper-auth form .input-symbol { 1408 | margin-bottom: 1px; 1409 | width: 100%; 1410 | } 1411 | 1412 | .page.auth .wrapper-auth form .btn-primary { 1413 | margin: 1em 5% 0; 1414 | width: 90%; 1415 | } 1416 | 1417 | @media screen and (min-width: 40em) { 1418 | .page.auth .wrapper-auth form .btn-primary { 1419 | margin-left: 0; 1420 | margin-right: 0; 1421 | width: 100%; 1422 | } 1423 | } 1424 | 1425 | .page.auth .wrapper-auth .list-errors { 1426 | margin-top: -2rem; 1427 | } 1428 | 1429 | .page.auth .wrapper-auth .list-errors .list-item { 1430 | letter-spacing: .3em; 1431 | text-indent: .3em; 1432 | text-transform: uppercase; 1433 | background: #f6fccf; 1434 | color: #ff4400; 1435 | font-size: .625em; 1436 | margin-bottom: 1px; 1437 | padding: .7rem 0; 1438 | } 1439 | 1440 | .page.auth .link-auth-alt { 1441 | font-size: 12px; 1442 | line-height: 16px; 1443 | position: absolute; 1444 | top: auto; 1445 | right: 0; 1446 | bottom: 1em; 1447 | left: 0; 1448 | width: auto; 1449 | height: auto; 1450 | color: #aaaaaa; 1451 | display: inline-block; 1452 | } 1453 | 1454 | @media screen and (min-width: 40em) { 1455 | .page.auth .link-auth-alt { 1456 | bottom: 0; 1457 | margin-top: 1rem; 1458 | position: relative; 1459 | } 1460 | } 1461 | 1462 | .page.not-found .content-scrollable { 1463 | background: #d2edf4; 1464 | } 1465 | 1466 | .loading-app { 1467 | position: absolute; 1468 | top: 50%; 1469 | right: 50%; 1470 | bottom: auto; 1471 | left: auto; 1472 | width: 50%; 1473 | height: auto; 1474 | -webkit-transform: translate3d(50%, -50%, 0); 1475 | -moz-transform: translate3d(50%, -50%, 0); 1476 | -ms-transform: translate3d(50%, -50%, 0); 1477 | -o-transform: translate3d(50%, -50%, 0); 1478 | transform: translate3d(50%, -50%, 0); 1479 | min-width: 160px; 1480 | max-width: 320px; 1481 | } -------------------------------------------------------------------------------- /public/style/font/OpenSans-Light-webfont.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This is a custom SVG webfont generated by Font Squirrel. 6 | Copyright : Digitized data copyright 20102011 Google Corporation 7 | Foundry : Ascender Corporation 8 | Foundry URL : httpwwwascendercorpcom 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | --------------------------------------------------------------------------------