Sebas 5 anos atrás
commit
e485331431
73 arquivos alterados com 4774 adições e 0 exclusões
  1. 5 0
      .gitignore
  2. 16 0
      README.md
  3. 1 0
      __init__.py
  4. 19 0
      __openerp__.py
  5. 45 0
      gulpfile.js
  6. 19 0
      package.json
  7. 5 0
      sonar-project.properties
  8. BIN
      static/description/icon.png
  9. 1 0
      static/src/coffee/login.coffee
  10. 628 0
      static/src/css/backend/theme.css
  11. 100 0
      static/src/css/login/theme.css
  12. BIN
      static/src/favicons/android-icon-144x144.png
  13. BIN
      static/src/favicons/android-icon-192x192.png
  14. BIN
      static/src/favicons/android-icon-36x36.png
  15. BIN
      static/src/favicons/android-icon-48x48.png
  16. BIN
      static/src/favicons/android-icon-72x72.png
  17. BIN
      static/src/favicons/android-icon-96x96.png
  18. BIN
      static/src/favicons/apple-icon-114x114.png
  19. BIN
      static/src/favicons/apple-icon-120x120.png
  20. BIN
      static/src/favicons/apple-icon-144x144.png
  21. BIN
      static/src/favicons/apple-icon-152x152.png
  22. BIN
      static/src/favicons/apple-icon-180x180.png
  23. BIN
      static/src/favicons/apple-icon-57x57.png
  24. BIN
      static/src/favicons/apple-icon-60x60.png
  25. BIN
      static/src/favicons/apple-icon-72x72.png
  26. BIN
      static/src/favicons/apple-icon-76x76.png
  27. BIN
      static/src/favicons/apple-icon-precomposed.png
  28. BIN
      static/src/favicons/apple-icon.png
  29. 2 0
      static/src/favicons/browserconfig.xml
  30. BIN
      static/src/favicons/favicon-16x16.png
  31. BIN
      static/src/favicons/favicon-32x32.png
  32. BIN
      static/src/favicons/favicon-96x96.png
  33. BIN
      static/src/favicons/favicon.ico
  34. 41 0
      static/src/favicons/manifest.json
  35. BIN
      static/src/favicons/ms-icon-144x144.png
  36. BIN
      static/src/favicons/ms-icon-150x150.png
  37. BIN
      static/src/favicons/ms-icon-310x310.png
  38. BIN
      static/src/favicons/ms-icon-70x70.png
  39. BIN
      static/src/img/background.jpg
  40. BIN
      static/src/img/company.png
  41. BIN
      static/src/img/logo.png
  42. 4 0
      static/src/js/login.js
  43. 110 0
      static/src/json/particles.json
  44. 1579 0
      static/src/lib/animate.css
  45. 1541 0
      static/src/lib/particles.js
  46. 14 0
      static/src/sass/_body.sass
  47. 17 0
      static/src/sass/_variables.sass
  48. 3 0
      static/src/sass/backend/_application.sass
  49. 31 0
      static/src/sass/backend/_buttons.sass
  50. 28 0
      static/src/sass/backend/_dashboard.sass
  51. 67 0
      static/src/sass/backend/_forms.sass
  52. 42 0
      static/src/sass/backend/_header.sass
  53. 19 0
      static/src/sass/backend/_kanbans.sass
  54. 2 0
      static/src/sass/backend/_loading.sass
  55. 3 0
      static/src/sass/backend/_main.sass
  56. 58 0
      static/src/sass/backend/_menubar.sass
  57. 24 0
      static/src/sass/backend/_messages.sass
  58. 15 0
      static/src/sass/backend/_modals.sass
  59. 53 0
      static/src/sass/backend/_pos.sass
  60. 28 0
      static/src/sass/backend/_reporting.sass
  61. 9 0
      static/src/sass/backend/_searcher.sass
  62. 38 0
      static/src/sass/backend/_sidebar.sass
  63. 11 0
      static/src/sass/backend/_toggler.sass
  64. 14 0
      static/src/sass/backend/_trees.sass
  65. 19 0
      static/src/sass/backend/theme.sass
  66. 19 0
      static/src/sass/login/_brand.sass
  67. 41 0
      static/src/sass/login/_form.sass
  68. 4 0
      static/src/sass/login/theme.sass
  69. 10 0
      views/eiru_assets_backend.xml
  70. 34 0
      views/eiru_web_layout.xml
  71. 21 0
      views/eiru_web_login.xml
  72. 25 0
      views/eiru_web_login_layout.xml
  73. 9 0
      views/eiru_web_menu_secondary.xml

+ 5 - 0
.gitignore

@@ -0,0 +1,5 @@
+*.pyc
+node_modules
+package-lock.json
+yarn.lock
+.scannerwork

+ 16 - 0
README.md

@@ -0,0 +1,16 @@
+# Eiru Theme
+Como usar?
+
+## Pasos
+1. Instalar Node.js en su última versión
+2. Instalar gulp de manera global
+ 
+    `npm install -g gulp`
+    
+3. En la raíz del proyecto instalar las dependencias
+
+     `npm install`
+     
+4. Transpilar el proyecto
+
+    `gulp default`

+ 1 - 0
__init__.py

@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-

+ 19 - 0
__openerp__.py

@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+{
+    'name': "Eiru Theme",
+    'author': "Robert Gauto",
+    'website': "http://www.eiru.com.py",
+    'category': 'Theme',
+    'version': '0.1',
+    'depends': ['base'],
+    'data': [
+        'views/eiru_assets_backend.xml',
+        'views/eiru_web_layout.xml',
+        'views/eiru_web_login_layout.xml',
+        'views/eiru_web_login.xml',
+        'views/eiru_web_menu_secondary.xml'
+    ],
+    'qweb': [
+        'static/src/xml/*.xml'
+    ]
+}

+ 45 - 0
gulpfile.js

@@ -0,0 +1,45 @@
+"use strict";
+
+var del = require('del')
+var gulp = require("gulp");
+var coffee = require("gulp-coffee");
+var sass = require("gulp-sass");
+
+
+// clean task
+gulp.task("clean", function () {
+    return del(["src/static/coffee/**/*.coffee", "src/static/js/**/*.js"]);
+});
+
+// coffee task
+gulp.task("coffee", function () {
+    return gulp.src("./static/src/coffee/*.coffee")
+        .pipe(coffee())
+        .pipe(gulp.dest("./static/src/js"));
+});
+
+// coffee watch task
+gulp.task("coffee:watch", function () {
+    return gulp.watch("./static/src/coffee/*.coffee", ["clean", "coffee"]);
+});
+
+// sass task
+gulp.task("sass", function () {
+    return gulp.src("./static/src/sass/**/*.sass")
+        .pipe(sass({
+            indentedSyntax: true,
+            indentType: "tab",
+            indentWidth: 1,
+            outputStyle: "expanded"
+        }).on("error", sass.logError))
+        .pipe(gulp.dest("./static/src/css"));
+});
+
+// sass watch task
+gulp.task("sass:watch", function () {
+    return gulp.watch("./static/src/sass/**/*.sass", ["clean", "sass"]);
+});
+
+// sass default tasks
+gulp.task("default", ["coffee", "sass"]);
+gulp.task("default:watch", ["coffee:watch", "sass:watch"]);

+ 19 - 0
package.json

@@ -0,0 +1,19 @@
+{
+  "name": "eiru-theme",
+  "version": "1.0.0",
+  "private": true,
+  "main": "index.js",
+  "repository": "http://127.0.0.1:3000/robert/eiru_theme.git",
+  "author": "robert2206 <robert.gauto@gmail.com>",
+  "license": "MIT",
+  "scripts": {
+    "start": "gulp default:watch",
+    "build": "gulp default"
+  },
+  "devDependencies": {
+    "del": "^3.0.0",
+    "gulp": "^3.9.1",
+    "gulp-coffee": "^2.3.4",
+    "gulp-sass": "^3.1.0"
+  }
+}

+ 5 - 0
sonar-project.properties

@@ -0,0 +1,5 @@
+sonar.projectKey=theme
+sonar.projectName=eiru_theme
+sonar.projectVersion=1.0
+sonar.sources=static/src
+sonar.javascript.globals=openerp,$

BIN
static/description/icon.png


+ 1 - 0
static/src/coffee/login.coffee

@@ -0,0 +1 @@
+particlesJS.load "particles-js", "/eiru_theme/static/src/json/particles.json"

+ 628 - 0
static/src/css/backend/theme.css

@@ -0,0 +1,628 @@
+@import url("https://fonts.googleapis.com/css?family=Roboto");
+html, body, .openerp {
+	background: #fff;
+	font-family: 'Roboto', sans-serif;
+}
+
+body {
+	font-size: 14pt;
+}
+
+body .oe_user_menu_placeholder .dropdown-menu li:nth-child(2), body .oe_user_menu_placeholder .dropdown-menu li:nth-child(3), body .oe_user_menu_placeholder .dropdown-menu li:nth-child(4) {
+	display: none;
+}
+
+.oe_view_manager_header button {
+	border: 1px solid transparent !important;
+	border-radius: 0 !important;
+	box-shadow: none !important;
+}
+
+.oe_view_manager_header .oe_highlight {
+	width: 85px !important;
+	height: 30px !important;
+	background: #d32f2f !important;
+}
+
+.oe_view_manager_header .oe_form_button_edit {
+	width: 85px !important;
+	height: 30px !important;
+	color: #fff !important;
+	background: #d32f2f !important;
+}
+
+.oe_view_manager_header .oe_form_button_create {
+	width: 85px !important;
+	height: 30px !important;
+	color: #fff !important;
+	background: #4caf50 !important;
+}
+
+.oe_view_manager_header .oe_dropdown_toggle {
+	width: 85px !important;
+	height: 30px !important;
+	color: #fff !important;
+	background: #0288d1 !important;
+}
+
+.oe_view_manager_header .oe_list_discard, .oe_view_manager_header .oe_form_button_cancel, .oe_view_manager_header .oe_list_button_import {
+	color: #007dc1 !important;
+}
+
+#oe_main_menu_navbar {
+	height: 45px;
+	background-color: #0288d1 !important;
+	border: 0;
+}
+
+#oe_main_menu_placeholder {
+	height: 45px;
+	background-color: #0288d1 !important;
+	box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26);
+}
+
+.oe_application_menu_placeholder {
+	height: 45px;
+	background-color: #0288d1 !important;
+}
+
+.oe_application_menu_placeholder li {
+	height: 45px;
+}
+
+.oe_application_menu_placeholder li.active {
+	background-color: #007dc1;
+	border-bottom: 2px solid #fff;
+}
+
+.oe_application_menu_placeholder li .oe_menu_toggler, .oe_application_menu_placeholder li .oe_menu_leaf {
+	height: 45px;
+	margin-top: 0 !important;
+	line-height: 23px !important;
+	padding: 12px 10px !important;
+	color: #fff !important;
+	background-color: transparent !important;
+}
+
+.oe_user_menu_placeholder {
+	height: 45px;
+	background-color: #0288d1 !important;
+}
+
+.oe_user_menu_placeholder li {
+	height: 45px;
+}
+
+.oe_user_menu_placeholder li.open {
+	background-color: #007dc1;
+}
+
+.oe_user_menu_placeholder li .dropdown-toggle {
+	height: 45px;
+	padding-top: 12px !important;
+	margin: 0 !important;
+	color: #fff !important;
+	background-color: transparent !important;
+}
+
+.oe_user_menu_placeholder li .dropdown-menu li a {
+	height: 45px;
+	line-height: 34px;
+	transition-duration: 0.3s;
+}
+
+.oe_user_menu_placeholder li .dropdown-menu li a:hover {
+	color: #fff;
+	background-color: #007dc1;
+}
+
+.oe_systray {
+	height: 45px;
+	background-color: #0288d1 !important;
+}
+
+.oe_systray li {
+	height: 45px;
+}
+
+.oe_systray li a {
+	line-height: 34px;
+}
+
+.oe_systray li a i {
+	color: #fff;
+}
+
+.oe_leftbar {
+	width: 250px !important;
+	background: #f5f5f5 !important;
+	border-right: 1px solid #eeeeee !important;
+}
+
+.oe_leftbar > div {
+	width: 250px !important;
+}
+
+.oe_leftbar > div .oe_logo {
+	width: 100%;
+	height: 120px;
+}
+
+.oe_leftbar > div .oe_secondary_menus_container {
+	padding-top: 20px;
+}
+
+.oe_leftbar > div .oe_secondary_menus_container .oe_secondary_menu .oe_secondary_menu_section {
+	color: #616161;
+}
+
+.oe_leftbar > div .oe_secondary_menus_container .oe_secondary_menu .oe_secondary_submenu li {
+	width: 100%;
+	margin: 0 !important;
+}
+
+.oe_leftbar > div .oe_secondary_menus_container .oe_secondary_menu .oe_secondary_submenu li.active {
+	background-color: #0288d1 !important;
+}
+
+.oe_leftbar > div .oe_secondary_menus_container .oe_secondary_menu .oe_secondary_submenu li.active a .badge {
+	background-color: #fff !important;
+}
+
+.oe_leftbar > div .oe_secondary_menus_container .oe_secondary_menu .oe_secondary_submenu li:hover {
+	background-color: #eeeeee;
+}
+
+.oe_leftbar > div .oe_secondary_menus_container .oe_secondary_menu .oe_secondary_submenu li a {
+	width: inherit;
+	height: inherit;
+	line-height: 23px;
+	background-color: transparent !important;
+}
+
+.oe_leftbar > div .oe_secondary_menus_container .oe_secondary_menu .oe_secondary_submenu li a .badge {
+	background-color: #0288d1;
+}
+
+.oe_leftbar > div .oe_footer {
+	background: #fff !important;
+	font-size: 7.5pt;
+}
+
+.oe_leftbar > div .oe_footer a span {
+	color: #0288d1 !important;
+}
+
+.eiru-toggler {
+	width: 45px;
+	height: 45px;
+	text-align: center;
+	line-height: 45px;
+}
+
+.eiru-toggler:hover {
+	cursor: pointer;
+	-webkit-cursor: pointer;
+	-moz-cursor: pointer;
+}
+
+.eiru-toggler i {
+	color: #fff;
+}
+
+.pos .wizard-progress-bar {
+	background: #0288d1;
+}
+
+.oe_view_manager_header {
+	background: #fff !important;
+	border-bottom: 1px solid #eeeeee !important;
+}
+
+.oe_view_manager_header .oe_view_title {
+	color: #616161;
+}
+
+.oe_view_manager_header .oe_view_title a {
+	color: #007dc1 !important;
+}
+
+.oe_view_manager_header .oe_searchview {
+	box-shadow: none !important;
+	width: 450px;
+	border-top: none;
+	border-left: none;
+	border-right: none;
+	border-bottom: 1px solid #d3d3d3;
+	border-radius: 0;
+}
+
+.oe_view_manager_header .oe_searchview.oe_focused {
+	border-bottom: 1px solid #0288d1;
+}
+
+.oe_view_manager_header .oe_searchview .oe_searchview_facet {
+	border-radius: 0;
+	border: 1px solid #d3d3d3 !important;
+	background: #0288d1 !important;
+}
+
+.oe_view_manager_header .oe_searchview .oe_searchview_facet:focus {
+	border-color: #0288d1 !important;
+}
+
+.oe_view_manager_header .oe_searchview .oe_searchview_facet .oe_facet_category {
+	background: #0288d1;
+}
+
+.oe_view_manager_header .oe_searchview .oe_searchview_facet .oe_facet_remove {
+	color: #0288d1 !important;
+}
+
+.oe_view_manager_header .oe_searchview .oe_searchview_facet .oe_facet_remove:hover {
+	color: #fff !important;
+	background: #0288d1 !important;
+}
+
+.oe_view_manager_header .oe_searchview .oe-autocomplete {
+	border-radius: 0 !important;
+}
+
+.oe_view_manager_header .oe_searchview .oe-autocomplete li {
+	height: 28px !important;
+	line-height: 25px !important;
+}
+
+.oe_view_manager_header .oe_searchview .oe-autocomplete li.oe-selection-focus {
+	background: #0288d1 !important;
+}
+
+.oe_view_manager_header .oe_view_manager_switch {
+	border-radius: 0 !important;
+}
+
+.oe_searchview_drawer dt {
+	color: #0288d1 !important;
+}
+
+.oe_searchview_drawer dd .badge {
+	background: #0288d1 !important;
+}
+
+.oe_searchview_drawer dd .oe_searchview_custom_delete:hover {
+	background: #0288d1 !important;
+}
+
+.oe_view_manager_body {
+	margin: 15px;
+	box-shadow: 2px 2px 5px #d3d3d3, -2px -2px 5px #d3d3d3;
+}
+
+.oe_list_content thead tr {
+	width: 100%;
+	height: 47px !important;
+	color: #616161;
+	background: #fff !important;
+}
+
+.oe_list_content thead tr th {
+	border: none !important;
+}
+
+.oe_list_content thead tr th input[type="checkbox"] {
+	outline: 0;
+}
+
+.oe_list_content thead tr th input[type="checkbox"]::after {
+	border: 2px solid #616161;
+	border-radius: 2px;
+}
+
+.oe_form header {
+	height: 35px;
+	background: #fff !important;
+	border: none !important;
+	box-shadow: 1px 0 3px #d3d3d3;
+}
+
+.oe_form header button {
+	height: 30px;
+	padding-left: 5px !important;
+	padding-right: 5px !important;
+	border-radius: 0 !important;
+	border: 1px solid #d3d3d3 !important;
+	color: #616161 !important;
+	background: #fff !important;
+}
+
+.oe_form header ul {
+	height: 35px;
+}
+
+.oe_form header ul li {
+	height: 35px;
+}
+
+.oe_form header ul li .label {
+	height: 35px;
+	padding-top: 9px !important;
+}
+
+.oe_form header ul li .arrow {
+	width: 21px !important;
+	height: 35px !important;
+}
+
+.oe_form header ul li .arrow span {
+	width: 26px !important;
+	height: 26px !important;
+	margin-left: -10 !important;
+	margin-top: 4px !important;
+}
+
+.oe_form .oe_form_sheetbg {
+	background: none !important;
+	border: none !important;
+	padding: 15px !important;
+	z-index: 0 !important;
+	overflow-x: hidden;
+}
+
+.oe_form .oe_form_sheetbg .oe_form_sheet {
+	width: 100%;
+	max-width: none;
+	border: none !important;
+	padding: 0 !important;
+	box-shadow: none !important;
+}
+
+.oe_form .oe_form_sheetbg .oe_stat_button {
+	color: #616161;
+}
+
+.oe_form .oe_form_sheetbg .oe_stat_button .stat_button_icon {
+	color: #0288d1;
+}
+
+.oe_form .oe_form_sheetbg .oe_stat_button:hover {
+	color: #fff;
+	background: #0288d1;
+}
+
+.oe_form .oe_form_sheetbg .oe_stat_button:hover .stat_button_icon {
+	color: #fff;
+}
+
+.oe_form .oe_form_sheetbg .oe_form_button {
+	width: 85px !important;
+	height: 30px !important;
+	box-shadow: none !important;
+	border-radius: 0 !important;
+	background: #fff;
+}
+
+.oe_form .oe_form_sheetbg .oe_form_button.oe_highlight {
+	border: none !important;
+	background-color: #d32f2f !important;
+}
+
+.oe_form .oe_form_sheetbg .oe_msg a {
+	color: #0288d1 !important;
+}
+
+.oe_form .oe_chatter {
+	width: 100% !important;
+	max-width: none !important;
+}
+
+.oe_form .oe_chatter a {
+	color: #007dc1 !important;
+}
+
+.modal-dialog .modal-content {
+	border-radius: 0 !important;
+}
+
+.modal-dialog .modal-footer footer .oe_highlight {
+	width: 120px !important;
+	height: 30px !important;
+	border: none !important;
+	border-radius: 0 !important;
+	box-shadow: none !important;
+	background: #d32f2f !important;
+}
+
+.modal-dialog .modal-footer footer .oe_link span {
+	color: #0288d1 !important;
+}
+
+.oe_kanban_view .oe_kanban_column_cards {
+	padding: 15px;
+}
+
+.oe_kanban_view .oe_kanban_image {
+	width: 75px !important;
+	height: 75px !important;
+	border-radius: 50% !important;
+}
+
+.oe_kanban_view .oe_kanban_details a {
+	color: #0288d1 !important;
+}
+
+.oe_kanban_view .oe_kanban_action_a {
+	color: #0288d1 !important;
+}
+
+.oe_kanban_view .oe_kanban_action_button {
+	width: 85px !important;
+	height: 30px !important;
+	border: 1px solid #d3d3d3 !important;
+	border-radius: 0 !important;
+	box-shadow: none !important;
+	background: #fff !important;
+}
+
+.oe_mail .oe_msg_left a img {
+	border-radius: 50% !important;
+}
+
+.oe_mail .oe_msg_center .oe_msg_title a {
+	color: #0288d1 !important;
+}
+
+.oe_mail .oe_msg_center .oe_msg_body .oe_msg_body_short p b a {
+	color: #0288d1 !important;
+}
+
+.oe_mail .oe_msg_center .oe_msg_body .oe_msg_body_short span a {
+	color: #0288d1 !important;
+}
+
+.oe_mail .oe_msg_center .oe_msg_footer .oe_mail_action_author {
+	color: #0288d1 !important;
+}
+
+.oe_mail .oe_msg_center .oe_msg_footer .oe_msg_vote {
+	color: #0288d1 !important;
+}
+
+.grid-stack-item-content.dashboard {
+	border: 1px solid #eeeeee;
+	border-bottom: 3px solid #0288d1;
+	background-color: #fff;
+}
+
+.grid-stack-item-content.dashboard .widget-title {
+	color: #616161;
+}
+
+.grid-stack-item-content.dashboard .widget-content a {
+	font-size: 18pt !important;
+	color: #0288d1;
+}
+
+.grid-stack-item-content.dashboard .widget-footer {
+	text-align: center;
+	font-size: 11pt;
+	color: #616161;
+}
+
+.dashboard-sale-wrapper {
+	background: #fff;
+	padding: 15px;
+}
+
+.dashboard-sale-wrapper .dashboard-sale-actions img {
+	filter: contrast(250%);
+}
+
+.dashboard-sale-wrapper .dashboard-sale-actions .new-sale, .dashboard-sale-wrapper .dashboard-sale-actions .new-budget {
+	background: #0288d1;
+}
+
+.dashboard-sale-wrapper .dashboard-sale-actions .new-sale::before, .dashboard-sale-wrapper .dashboard-sale-actions .new-budget::before {
+	background: #0288d1;
+}
+
+.dashboard-sale-wrapper .dashboard-sale-welcome i {
+	color: #0288d1;
+}
+
+.reporting_view_header {
+	background: #fff !important;
+	border-bottom: 1px solid #eeeeee !important;
+}
+
+.reporting_view_header h2 {
+	color: #616161;
+}
+
+.report_view {
+	padding: 15px;
+	box-shadow: 2px 2px 5px #d3d3d3, -2px -2px 5px #d3d3d3;
+}
+
+.report_view .reporting_page_header h1 {
+	font-size: 16pt;
+}
+
+.report_view .report_item {
+	border-radius: 0;
+	box-shadow: none;
+}
+
+.report_view .report_item .report_title h1 {
+	font-size: 14pt;
+}
+
+.report_view .report_item .report_action button {
+	width: 100% !important;
+	height: 30px;
+	background: #d32f2f;
+	border-radius: 0;
+	border: none;
+}
+
+.report_view .report_item:hover {
+	transform: none;
+	box-shadow: none;
+}
+
+.oe_loading {
+	border-radius: 0 !important;
+}
+
+.pos .wizard-progress-bar, .purchases .wizard-progress-bar {
+	background-color: #0288d1 !important;
+	color: #0288d1 !important;
+}
+
+.pos .wizard-icon-circle.checked, .purchases .wizard-icon-circle.checked {
+	border-color: #0288d1 !important;
+}
+
+.pos .wizard-icon-circle .wizard-icon-container, .purchases .wizard-icon-circle .wizard-icon-container {
+	background: #0288d1 !important;
+}
+
+.pos .stepTitle.active, .purchases .stepTitle.active {
+	color: #0288d1 !important;
+}
+
+.pos .pos-step .spinner .spinner-rect, .pos .purchase-step .spinner .spinner-rect, .purchases .pos-step .spinner .spinner-rect, .purchases .purchase-step .spinner .spinner-rect {
+	background: #0288d1 !important;
+}
+
+.pos .pos-step .card-grid .add-card i, .pos .purchase-step .card-grid .add-card i, .purchases .pos-step .card-grid .add-card i, .purchases .purchase-step .card-grid .add-card i {
+	color: #0288d1 !important;
+}
+
+.pos .pos-step .card-grid .card.selected-card, .pos .purchase-step .card-grid .card.selected-card, .purchases .pos-step .card-grid .card.selected-card, .purchases .purchase-step .card-grid .card.selected-card {
+	border-bottom: 3px solid #0288d1 !important;
+}
+
+.pos .pos-step .card-grid .card .card-details, .pos .purchase-step .card-grid .card .card-details, .purchases .pos-step .card-grid .card .card-details, .purchases .purchase-step .card-grid .card .card-details {
+	background: #0288d1 !important;
+}
+
+.pos .pos-step .cart .cart-item:hover, .pos .purchase-step .cart .cart-item:hover, .purchases .pos-step .cart .cart-item:hover, .purchases .purchase-step .cart .cart-item:hover {
+	border-bottom: 2px solid #0288d1;
+}
+
+.pos .pos-step form .form-actions .form-action, .pos .purchase-step form .form-actions .form-action, .purchases .pos-step form .form-actions .form-action, .purchases .purchase-step form .form-actions .form-action {
+	background: #0288d1;
+}
+
+.pos .pos-step form .discount-options .discount-button, .pos .purchase-step form .discount-options .discount-button, .purchases .pos-step form .discount-options .discount-button, .purchases .purchase-step form .discount-options .discount-button {
+	background: #0288d1;
+}
+
+.pos .pos-step .product-variants .variant-details:hover, .pos .purchase-step .product-variants .variant-details:hover, .purchases .pos-step .product-variants .variant-details:hover, .purchases .purchase-step .product-variants .variant-details:hover {
+	border-bottom: 2px solid #0288d1;
+}
+
+.pos .wizard-card-footer .wizard-btn, .purchases .wizard-card-footer .wizard-btn {
+	background: #0288d1 !important;
+	border-color: none !important;
+}

+ 100 - 0
static/src/css/login/theme.css

@@ -0,0 +1,100 @@
+@import url("https://fonts.googleapis.com/css?family=Roboto");
+html, body, .openerp {
+	background: #fff;
+	font-family: 'Roboto', sans-serif;
+}
+
+body {
+	font-size: 14pt;
+}
+
+body .oe_user_menu_placeholder .dropdown-menu li:nth-child(2), body .oe_user_menu_placeholder .dropdown-menu li:nth-child(3), body .oe_user_menu_placeholder .dropdown-menu li:nth-child(4) {
+	display: none;
+}
+
+.oe_single_form {
+	background: #0288d1 url(/eiru_theme/static/src/img/background.jpg) right bottom !important;
+}
+
+.oe_single_form::before {
+	content: '';
+	position: fixed;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	background: #0288d1;
+	opacity: 0.3;
+}
+
+.oe_single_form .oe_single_form_container {
+	box-shadow: none !important;
+	border: none !important;
+}
+
+.oe_single_form .oe_single_form_container.modal-content {
+	padding: 20px !important;
+	border-radius: 0 !important;
+}
+
+.oe_single_form .oe_single_form_container.modal-content .oe_single_form_footer {
+	font-size: 9pt !important;
+	color: #fff !important;
+}
+
+.oe_single_form .oe_single_form_container.modal-content .oe_login_manage_db, .oe_single_form .oe_single_form_container.modal-content .oe_footer_seperator {
+	display: none;
+}
+
+.oe_login_form .control-label {
+	font-size: 10pt;
+	color: #616161;
+}
+
+.oe_login_form .form-control {
+	border-radius: 0 !important;
+}
+
+.oe_login_form .alert-danger {
+	border-radius: 0 !important;
+	text-align: center;
+}
+
+.oe_login_form button {
+	width: 100%;
+	border-radius: 0 !important;
+	background-color: #0288d1;
+	border-color: transparent;
+}
+
+.oe_login_form button:hover {
+	border-color: transparent !important;
+	background-color: #0288d1 !important;
+}
+
+.eiru-brand-login {
+	width: 200px;
+	height: 100px;
+	position: absolute;
+	bottom: 0;
+	right: 0;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.eiru-brand-login img {
+	width: 50px;
+	height: 45px;
+	filter: contrast(150%);
+}
+
+.eiru-brand-login div {
+	color: #fff;
+	padding-left: 5px;
+}
+
+.eiru-brand-login div h2 {
+	font-size: 20pt;
+	margin: 0;
+}

BIN
static/src/favicons/android-icon-144x144.png


BIN
static/src/favicons/android-icon-192x192.png


BIN
static/src/favicons/android-icon-36x36.png


BIN
static/src/favicons/android-icon-48x48.png


BIN
static/src/favicons/android-icon-72x72.png


BIN
static/src/favicons/android-icon-96x96.png


BIN
static/src/favicons/apple-icon-114x114.png


BIN
static/src/favicons/apple-icon-120x120.png


BIN
static/src/favicons/apple-icon-144x144.png


BIN
static/src/favicons/apple-icon-152x152.png


BIN
static/src/favicons/apple-icon-180x180.png


BIN
static/src/favicons/apple-icon-57x57.png


BIN
static/src/favicons/apple-icon-60x60.png


BIN
static/src/favicons/apple-icon-72x72.png


BIN
static/src/favicons/apple-icon-76x76.png


BIN
static/src/favicons/apple-icon-precomposed.png


BIN
static/src/favicons/apple-icon.png


+ 2 - 0
static/src/favicons/browserconfig.xml

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>

BIN
static/src/favicons/favicon-16x16.png


BIN
static/src/favicons/favicon-32x32.png


BIN
static/src/favicons/favicon-96x96.png


BIN
static/src/favicons/favicon.ico


+ 41 - 0
static/src/favicons/manifest.json

@@ -0,0 +1,41 @@
+{
+ "name": "App",
+ "icons": [
+  {
+   "src": "\/android-icon-36x36.png",
+   "sizes": "36x36",
+   "type": "image\/png",
+   "density": "0.75"
+  },
+  {
+   "src": "\/android-icon-48x48.png",
+   "sizes": "48x48",
+   "type": "image\/png",
+   "density": "1.0"
+  },
+  {
+   "src": "\/android-icon-72x72.png",
+   "sizes": "72x72",
+   "type": "image\/png",
+   "density": "1.5"
+  },
+  {
+   "src": "\/android-icon-96x96.png",
+   "sizes": "96x96",
+   "type": "image\/png",
+   "density": "2.0"
+  },
+  {
+   "src": "\/android-icon-144x144.png",
+   "sizes": "144x144",
+   "type": "image\/png",
+   "density": "3.0"
+  },
+  {
+   "src": "\/android-icon-192x192.png",
+   "sizes": "192x192",
+   "type": "image\/png",
+   "density": "4.0"
+  }
+ ]
+}

BIN
static/src/favicons/ms-icon-144x144.png


BIN
static/src/favicons/ms-icon-150x150.png


BIN
static/src/favicons/ms-icon-310x310.png


BIN
static/src/favicons/ms-icon-70x70.png


BIN
static/src/img/background.jpg


BIN
static/src/img/company.png


BIN
static/src/img/logo.png


+ 4 - 0
static/src/js/login.js

@@ -0,0 +1,4 @@
+(function() {
+  particlesJS.load("particles-js", "/eiru_theme/static/src/json/particles.json");
+
+}).call(this);

+ 110 - 0
static/src/json/particles.json

@@ -0,0 +1,110 @@
+{
+    "particles": {
+        "number": {
+            "value": 80,
+            "density": {
+                "enable": true,
+                "value_area": 800
+            }
+        },
+        "color": {
+            "value": "#fff"
+        },
+        "shape": {
+            "type": "circle",
+            "stroke": {
+                "width": 0,
+                "color": "#000000"
+            },
+            "polygon": {
+                "nb_sides": 5
+            },
+            "image": {
+                "src": "img/github.svg",
+                "width": 100,
+                "height": 100
+            }
+        },
+        "opacity": {
+            "value": 1,
+            "random": false,
+            "anim": {
+                "enable": false,
+                "speed": 1,
+                "opacity_min": 0.1,
+                "sync": false
+            }
+        },
+        "size": {
+            "value": 3,
+            "random": true,
+            "anim": {
+                "enable": false,
+                "speed": 40,
+                "size_min": 0.1,
+                "sync": false
+            }
+        },
+        "line_linked": {
+            "enable": true,
+            "distance": 150,
+            "color": "#fff",
+            "opacity": 0.4,
+            "width": 1
+        },
+        "move": {
+            "enable": true,
+            "speed": 3,
+            "direction": "none",
+            "random": false,
+            "straight": false,
+            "out_mode": "out",
+            "bounce": false,
+            "attract": {
+                "enable": false,
+                "rotateX": 600,
+                "rotateY": 1200
+            }
+        }
+    },
+    "interactivity": {
+        "detect_on": "canvas",
+        "events": {
+            "onhover": {
+                "enable": true,
+                "mode": "repulse"
+            },
+            "onclick": {
+                "enable": true,
+                "mode": "push"
+            },
+            "resize": true
+        },
+        "modes": {
+            "grab": {
+                "distance": 400,
+                "line_linked": {
+                    "opacity": 1
+                }
+            },
+            "bubble": {
+                "distance": 400,
+                "size": 40,
+                "duration": 2,
+                "opacity": 8,
+                "speed": 3
+            },
+            "repulse": {
+                "distance": 200,
+                "duration": 0.4
+            },
+            "push": {
+                "particles_nb": 4
+            },
+            "remove": {
+                "particles_nb": 2
+            }
+        }
+    },
+    "retina_detect": true
+}

+ 1579 - 0
static/src/lib/animate.css

@@ -0,0 +1,1579 @@
+@charset "UTF-8";
+
+/*!
+ * animate.css -http://daneden.me/animate
+ * Version - 3.5.2
+ * Licensed under the MIT license - http://opensource.org/licenses/MIT
+ *
+ * Copyright (c) 2017 Daniel Eden
+ */
+
+.animated {
+  animation-duration: 1s;
+  animation-fill-mode: both;
+}
+
+.animated.infinite {
+  animation-iteration-count: infinite;
+}
+
+.animated.hinge {
+  animation-duration: 2s;
+}
+
+.animated.flipOutX,
+.animated.flipOutY,
+.animated.bounceIn,
+.animated.bounceOut {
+  animation-duration: .75s;
+}
+
+@keyframes bounce {
+  from, 20%, 53%, 80%, to {
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    transform: translate3d(0,0,0);
+  }
+
+  40%, 43% {
+    animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
+    transform: translate3d(0, -30px, 0);
+  }
+
+  70% {
+    animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
+    transform: translate3d(0, -15px, 0);
+  }
+
+  90% {
+    transform: translate3d(0,-4px,0);
+  }
+}
+
+.bounce {
+  animation-name: bounce;
+  transform-origin: center bottom;
+}
+
+@keyframes flash {
+  from, 50%, to {
+    opacity: 1;
+  }
+
+  25%, 75% {
+    opacity: 0;
+  }
+}
+
+.flash {
+  animation-name: flash;
+}
+
+/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
+
+@keyframes pulse {
+  from {
+    transform: scale3d(1, 1, 1);
+  }
+
+  50% {
+    transform: scale3d(1.05, 1.05, 1.05);
+  }
+
+  to {
+    transform: scale3d(1, 1, 1);
+  }
+}
+
+.pulse {
+  animation-name: pulse;
+}
+
+@keyframes rubberBand {
+  from {
+    transform: scale3d(1, 1, 1);
+  }
+
+  30% {
+    transform: scale3d(1.25, 0.75, 1);
+  }
+
+  40% {
+    transform: scale3d(0.75, 1.25, 1);
+  }
+
+  50% {
+    transform: scale3d(1.15, 0.85, 1);
+  }
+
+  65% {
+    transform: scale3d(.95, 1.05, 1);
+  }
+
+  75% {
+    transform: scale3d(1.05, .95, 1);
+  }
+
+  to {
+    transform: scale3d(1, 1, 1);
+  }
+}
+
+.rubberBand {
+  animation-name: rubberBand;
+}
+
+@keyframes shake {
+  from, to {
+    transform: translate3d(0, 0, 0);
+  }
+
+  10%, 30%, 50%, 70%, 90% {
+    transform: translate3d(-10px, 0, 0);
+  }
+
+  20%, 40%, 60%, 80% {
+    transform: translate3d(10px, 0, 0);
+  }
+}
+
+.shake {
+  animation-name: shake;
+}
+
+@keyframes headShake {
+  0% {
+    transform: translateX(0);
+  }
+
+  6.5% {
+    transform: translateX(-6px) rotateY(-9deg);
+  }
+
+  18.5% {
+    transform: translateX(5px) rotateY(7deg);
+  }
+
+  31.5% {
+    transform: translateX(-3px) rotateY(-5deg);
+  }
+
+  43.5% {
+    transform: translateX(2px) rotateY(3deg);
+  }
+
+  50% {
+    transform: translateX(0);
+  }
+}
+
+.headShake {
+  animation-timing-function: ease-in-out;
+  animation-name: headShake;
+}
+
+@keyframes swing {
+  20% {
+    transform: rotate3d(0, 0, 1, 15deg);
+  }
+
+  40% {
+    transform: rotate3d(0, 0, 1, -10deg);
+  }
+
+  60% {
+    transform: rotate3d(0, 0, 1, 5deg);
+  }
+
+  80% {
+    transform: rotate3d(0, 0, 1, -5deg);
+  }
+
+  to {
+    transform: rotate3d(0, 0, 1, 0deg);
+  }
+}
+
+.swing {
+  transform-origin: top center;
+  animation-name: swing;
+}
+
+@keyframes tada {
+  from {
+    transform: scale3d(1, 1, 1);
+  }
+
+  10%, 20% {
+    transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
+  }
+
+  30%, 50%, 70%, 90% {
+    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
+  }
+
+  40%, 60%, 80% {
+    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
+  }
+
+  to {
+    transform: scale3d(1, 1, 1);
+  }
+}
+
+.tada {
+  animation-name: tada;
+}
+
+/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
+
+@keyframes wobble {
+  from {
+    transform: none;
+  }
+
+  15% {
+    transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
+  }
+
+  30% {
+    transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
+  }
+
+  45% {
+    transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
+  }
+
+  60% {
+    transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
+  }
+
+  75% {
+    transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
+  }
+
+  to {
+    transform: none;
+  }
+}
+
+.wobble {
+  animation-name: wobble;
+}
+
+@keyframes jello {
+  from, 11.1%, to {
+    transform: none;
+  }
+
+  22.2% {
+    transform: skewX(-12.5deg) skewY(-12.5deg);
+  }
+
+  33.3% {
+    transform: skewX(6.25deg) skewY(6.25deg);
+  }
+
+  44.4% {
+    transform: skewX(-3.125deg) skewY(-3.125deg);
+  }
+
+  55.5% {
+    transform: skewX(1.5625deg) skewY(1.5625deg);
+  }
+
+  66.6% {
+    transform: skewX(-0.78125deg) skewY(-0.78125deg);
+  }
+
+  77.7% {
+    transform: skewX(0.390625deg) skewY(0.390625deg);
+  }
+
+  88.8% {
+    transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
+  }
+}
+
+.jello {
+  animation-name: jello;
+  transform-origin: center;
+}
+
+@keyframes bounceIn {
+  from, 20%, 40%, 60%, 80%, to {
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  0% {
+    opacity: 0;
+    transform: scale3d(.3, .3, .3);
+  }
+
+  20% {
+    transform: scale3d(1.1, 1.1, 1.1);
+  }
+
+  40% {
+    transform: scale3d(.9, .9, .9);
+  }
+
+  60% {
+    opacity: 1;
+    transform: scale3d(1.03, 1.03, 1.03);
+  }
+
+  80% {
+    transform: scale3d(.97, .97, .97);
+  }
+
+  to {
+    opacity: 1;
+    transform: scale3d(1, 1, 1);
+  }
+}
+
+.bounceIn {
+  animation-name: bounceIn;
+}
+
+@keyframes bounceInDown {
+  from, 60%, 75%, 90%, to {
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  0% {
+    opacity: 0;
+    transform: translate3d(0, -3000px, 0);
+  }
+
+  60% {
+    opacity: 1;
+    transform: translate3d(0, 25px, 0);
+  }
+
+  75% {
+    transform: translate3d(0, -10px, 0);
+  }
+
+  90% {
+    transform: translate3d(0, 5px, 0);
+  }
+
+  to {
+    transform: none;
+  }
+}
+
+.bounceInDown {
+  animation-name: bounceInDown;
+}
+
+@keyframes bounceInLeft {
+  from, 60%, 75%, 90%, to {
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  0% {
+    opacity: 0;
+    transform: translate3d(-3000px, 0, 0);
+  }
+
+  60% {
+    opacity: 1;
+    transform: translate3d(25px, 0, 0);
+  }
+
+  75% {
+    transform: translate3d(-10px, 0, 0);
+  }
+
+  90% {
+    transform: translate3d(5px, 0, 0);
+  }
+
+  to {
+    transform: none;
+  }
+}
+
+.bounceInLeft {
+  animation-name: bounceInLeft;
+}
+
+@keyframes bounceInRight {
+  from, 60%, 75%, 90%, to {
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  from {
+    opacity: 0;
+    transform: translate3d(3000px, 0, 0);
+  }
+
+  60% {
+    opacity: 1;
+    transform: translate3d(-25px, 0, 0);
+  }
+
+  75% {
+    transform: translate3d(10px, 0, 0);
+  }
+
+  90% {
+    transform: translate3d(-5px, 0, 0);
+  }
+
+  to {
+    transform: none;
+  }
+}
+
+.bounceInRight {
+  animation-name: bounceInRight;
+}
+
+@keyframes bounceInUp {
+  from, 60%, 75%, 90%, to {
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  from {
+    opacity: 0;
+    transform: translate3d(0, 3000px, 0);
+  }
+
+  60% {
+    opacity: 1;
+    transform: translate3d(0, -20px, 0);
+  }
+
+  75% {
+    transform: translate3d(0, 10px, 0);
+  }
+
+  90% {
+    transform: translate3d(0, -5px, 0);
+  }
+
+  to {
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+.bounceInUp {
+  animation-name: bounceInUp;
+}
+
+@keyframes bounceOut {
+  20% {
+    transform: scale3d(.9, .9, .9);
+  }
+
+  50%, 55% {
+    opacity: 1;
+    transform: scale3d(1.1, 1.1, 1.1);
+  }
+
+  to {
+    opacity: 0;
+    transform: scale3d(.3, .3, .3);
+  }
+}
+
+.bounceOut {
+  animation-name: bounceOut;
+}
+
+@keyframes bounceOutDown {
+  20% {
+    transform: translate3d(0, 10px, 0);
+  }
+
+  40%, 45% {
+    opacity: 1;
+    transform: translate3d(0, -20px, 0);
+  }
+
+  to {
+    opacity: 0;
+    transform: translate3d(0, 2000px, 0);
+  }
+}
+
+.bounceOutDown {
+  animation-name: bounceOutDown;
+}
+
+@keyframes bounceOutLeft {
+  20% {
+    opacity: 1;
+    transform: translate3d(20px, 0, 0);
+  }
+
+  to {
+    opacity: 0;
+    transform: translate3d(-2000px, 0, 0);
+  }
+}
+
+.bounceOutLeft {
+  animation-name: bounceOutLeft;
+}
+
+@keyframes bounceOutRight {
+  20% {
+    opacity: 1;
+    transform: translate3d(-20px, 0, 0);
+  }
+
+  to {
+    opacity: 0;
+    transform: translate3d(2000px, 0, 0);
+  }
+}
+
+.bounceOutRight {
+  animation-name: bounceOutRight;
+}
+
+@keyframes bounceOutUp {
+  20% {
+    transform: translate3d(0, -10px, 0);
+  }
+
+  40%, 45% {
+    opacity: 1;
+    transform: translate3d(0, 20px, 0);
+  }
+
+  to {
+    opacity: 0;
+    transform: translate3d(0, -2000px, 0);
+  }
+}
+
+.bounceOutUp {
+  animation-name: bounceOutUp;
+}
+
+@keyframes fadeIn {
+  from {
+    opacity: 0;
+  }
+
+  to {
+    opacity: 1;
+  }
+}
+
+.fadeIn {
+  animation-name: fadeIn;
+}
+
+@keyframes fadeInDown {
+  from {
+    opacity: 0;
+    transform: translate3d(0, -100%, 0);
+  }
+
+  to {
+    opacity: 1;
+    transform: none;
+  }
+}
+
+.fadeInDown {
+  animation-name: fadeInDown;
+}
+
+@keyframes fadeInDownBig {
+  from {
+    opacity: 0;
+    transform: translate3d(0, -2000px, 0);
+  }
+
+  to {
+    opacity: 1;
+    transform: none;
+  }
+}
+
+.fadeInDownBig {
+  animation-name: fadeInDownBig;
+}
+
+@keyframes fadeInLeft {
+  from {
+    opacity: 0;
+    transform: translate3d(-100%, 0, 0);
+  }
+
+  to {
+    opacity: 1;
+    transform: none;
+  }
+}
+
+.fadeInLeft {
+  animation-name: fadeInLeft;
+}
+
+@keyframes fadeInLeftBig {
+  from {
+    opacity: 0;
+    transform: translate3d(-2000px, 0, 0);
+  }
+
+  to {
+    opacity: 1;
+    transform: none;
+  }
+}
+
+.fadeInLeftBig {
+  animation-name: fadeInLeftBig;
+}
+
+@keyframes fadeInRight {
+  from {
+    opacity: 0;
+    transform: translate3d(100%, 0, 0);
+  }
+
+  to {
+    opacity: 1;
+    transform: none;
+  }
+}
+
+.fadeInRight {
+  animation-name: fadeInRight;
+}
+
+@keyframes fadeInRightBig {
+  from {
+    opacity: 0;
+    transform: translate3d(2000px, 0, 0);
+  }
+
+  to {
+    opacity: 1;
+    transform: none;
+  }
+}
+
+.fadeInRightBig {
+  animation-name: fadeInRightBig;
+}
+
+@keyframes fadeInUp {
+  from {
+    opacity: 0;
+    transform: translate3d(0, 100%, 0);
+  }
+
+  to {
+    opacity: 1;
+    transform: none;
+  }
+}
+
+.fadeInUp {
+  animation-name: fadeInUp;
+}
+
+@keyframes fadeInUpBig {
+  from {
+    opacity: 0;
+    transform: translate3d(0, 2000px, 0);
+  }
+
+  to {
+    opacity: 1;
+    transform: none;
+  }
+}
+
+.fadeInUpBig {
+  animation-name: fadeInUpBig;
+}
+
+@keyframes fadeOut {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+  }
+}
+
+.fadeOut {
+  animation-name: fadeOut;
+}
+
+@keyframes fadeOutDown {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    transform: translate3d(0, 100%, 0);
+  }
+}
+
+.fadeOutDown {
+  animation-name: fadeOutDown;
+}
+
+@keyframes fadeOutDownBig {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    transform: translate3d(0, 2000px, 0);
+  }
+}
+
+.fadeOutDownBig {
+  animation-name: fadeOutDownBig;
+}
+
+@keyframes fadeOutLeft {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    transform: translate3d(-100%, 0, 0);
+  }
+}
+
+.fadeOutLeft {
+  animation-name: fadeOutLeft;
+}
+
+@keyframes fadeOutLeftBig {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    transform: translate3d(-2000px, 0, 0);
+  }
+}
+
+.fadeOutLeftBig {
+  animation-name: fadeOutLeftBig;
+}
+
+@keyframes fadeOutRight {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    transform: translate3d(100%, 0, 0);
+  }
+}
+
+.fadeOutRight {
+  animation-name: fadeOutRight;
+}
+
+@keyframes fadeOutRightBig {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    transform: translate3d(2000px, 0, 0);
+  }
+}
+
+.fadeOutRightBig {
+  animation-name: fadeOutRightBig;
+}
+
+@keyframes fadeOutUp {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    transform: translate3d(0, -100%, 0);
+  }
+}
+
+.fadeOutUp {
+  animation-name: fadeOutUp;
+}
+
+@keyframes fadeOutUpBig {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    transform: translate3d(0, -2000px, 0);
+  }
+}
+
+.fadeOutUpBig {
+  animation-name: fadeOutUpBig;
+}
+
+@keyframes flip {
+  from {
+    transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
+    animation-timing-function: ease-out;
+  }
+
+  40% {
+    transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
+    animation-timing-function: ease-out;
+  }
+
+  50% {
+    transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
+    animation-timing-function: ease-in;
+  }
+
+  80% {
+    transform: perspective(400px) scale3d(.95, .95, .95);
+    animation-timing-function: ease-in;
+  }
+
+  to {
+    transform: perspective(400px);
+    animation-timing-function: ease-in;
+  }
+}
+
+.animated.flip {
+  -webkit-backface-visibility: visible;
+  backface-visibility: visible;
+  animation-name: flip;
+}
+
+@keyframes flipInX {
+  from {
+    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+    animation-timing-function: ease-in;
+    opacity: 0;
+  }
+
+  40% {
+    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+    animation-timing-function: ease-in;
+  }
+
+  60% {
+    transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
+    opacity: 1;
+  }
+
+  80% {
+    transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
+  }
+
+  to {
+    transform: perspective(400px);
+  }
+}
+
+.flipInX {
+  -webkit-backface-visibility: visible !important;
+  backface-visibility: visible !important;
+  animation-name: flipInX;
+}
+
+@keyframes flipInY {
+  from {
+    transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+    animation-timing-function: ease-in;
+    opacity: 0;
+  }
+
+  40% {
+    transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
+    animation-timing-function: ease-in;
+  }
+
+  60% {
+    transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
+    opacity: 1;
+  }
+
+  80% {
+    transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
+  }
+
+  to {
+    transform: perspective(400px);
+  }
+}
+
+.flipInY {
+  -webkit-backface-visibility: visible !important;
+  backface-visibility: visible !important;
+  animation-name: flipInY;
+}
+
+@keyframes flipOutX {
+  from {
+    transform: perspective(400px);
+  }
+
+  30% {
+    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+    opacity: 1;
+  }
+
+  to {
+    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+    opacity: 0;
+  }
+}
+
+.flipOutX {
+  animation-name: flipOutX;
+  -webkit-backface-visibility: visible !important;
+  backface-visibility: visible !important;
+}
+
+@keyframes flipOutY {
+  from {
+    transform: perspective(400px);
+  }
+
+  30% {
+    transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
+    opacity: 1;
+  }
+
+  to {
+    transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+    opacity: 0;
+  }
+}
+
+.flipOutY {
+  -webkit-backface-visibility: visible !important;
+  backface-visibility: visible !important;
+  animation-name: flipOutY;
+}
+
+@keyframes lightSpeedIn {
+  from {
+    transform: translate3d(100%, 0, 0) skewX(-30deg);
+    opacity: 0;
+  }
+
+  60% {
+    transform: skewX(20deg);
+    opacity: 1;
+  }
+
+  80% {
+    transform: skewX(-5deg);
+    opacity: 1;
+  }
+
+  to {
+    transform: none;
+    opacity: 1;
+  }
+}
+
+.lightSpeedIn {
+  animation-name: lightSpeedIn;
+  animation-timing-function: ease-out;
+}
+
+@keyframes lightSpeedOut {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    transform: translate3d(100%, 0, 0) skewX(30deg);
+    opacity: 0;
+  }
+}
+
+.lightSpeedOut {
+  animation-name: lightSpeedOut;
+  animation-timing-function: ease-in;
+}
+
+@keyframes rotateIn {
+  from {
+    transform-origin: center;
+    transform: rotate3d(0, 0, 1, -200deg);
+    opacity: 0;
+  }
+
+  to {
+    transform-origin: center;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+.rotateIn {
+  animation-name: rotateIn;
+}
+
+@keyframes rotateInDownLeft {
+  from {
+    transform-origin: left bottom;
+    transform: rotate3d(0, 0, 1, -45deg);
+    opacity: 0;
+  }
+
+  to {
+    transform-origin: left bottom;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+.rotateInDownLeft {
+  animation-name: rotateInDownLeft;
+}
+
+@keyframes rotateInDownRight {
+  from {
+    transform-origin: right bottom;
+    transform: rotate3d(0, 0, 1, 45deg);
+    opacity: 0;
+  }
+
+  to {
+    transform-origin: right bottom;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+.rotateInDownRight {
+  animation-name: rotateInDownRight;
+}
+
+@keyframes rotateInUpLeft {
+  from {
+    transform-origin: left bottom;
+    transform: rotate3d(0, 0, 1, 45deg);
+    opacity: 0;
+  }
+
+  to {
+    transform-origin: left bottom;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+.rotateInUpLeft {
+  animation-name: rotateInUpLeft;
+}
+
+@keyframes rotateInUpRight {
+  from {
+    transform-origin: right bottom;
+    transform: rotate3d(0, 0, 1, -90deg);
+    opacity: 0;
+  }
+
+  to {
+    transform-origin: right bottom;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+.rotateInUpRight {
+  animation-name: rotateInUpRight;
+}
+
+@keyframes rotateOut {
+  from {
+    transform-origin: center;
+    opacity: 1;
+  }
+
+  to {
+    transform-origin: center;
+    transform: rotate3d(0, 0, 1, 200deg);
+    opacity: 0;
+  }
+}
+
+.rotateOut {
+  animation-name: rotateOut;
+}
+
+@keyframes rotateOutDownLeft {
+  from {
+    transform-origin: left bottom;
+    opacity: 1;
+  }
+
+  to {
+    transform-origin: left bottom;
+    transform: rotate3d(0, 0, 1, 45deg);
+    opacity: 0;
+  }
+}
+
+.rotateOutDownLeft {
+  animation-name: rotateOutDownLeft;
+}
+
+@keyframes rotateOutDownRight {
+  from {
+    transform-origin: right bottom;
+    opacity: 1;
+  }
+
+  to {
+    transform-origin: right bottom;
+    transform: rotate3d(0, 0, 1, -45deg);
+    opacity: 0;
+  }
+}
+
+.rotateOutDownRight {
+  animation-name: rotateOutDownRight;
+}
+
+@keyframes rotateOutUpLeft {
+  from {
+    transform-origin: left bottom;
+    opacity: 1;
+  }
+
+  to {
+    transform-origin: left bottom;
+    transform: rotate3d(0, 0, 1, -45deg);
+    opacity: 0;
+  }
+}
+
+.rotateOutUpLeft {
+  animation-name: rotateOutUpLeft;
+}
+
+@keyframes rotateOutUpRight {
+  from {
+    transform-origin: right bottom;
+    opacity: 1;
+  }
+
+  to {
+    transform-origin: right bottom;
+    transform: rotate3d(0, 0, 1, 90deg);
+    opacity: 0;
+  }
+}
+
+.rotateOutUpRight {
+  animation-name: rotateOutUpRight;
+}
+
+@keyframes hinge {
+  0% {
+    transform-origin: top left;
+    animation-timing-function: ease-in-out;
+  }
+
+  20%, 60% {
+    transform: rotate3d(0, 0, 1, 80deg);
+    transform-origin: top left;
+    animation-timing-function: ease-in-out;
+  }
+
+  40%, 80% {
+    transform: rotate3d(0, 0, 1, 60deg);
+    transform-origin: top left;
+    animation-timing-function: ease-in-out;
+    opacity: 1;
+  }
+
+  to {
+    transform: translate3d(0, 700px, 0);
+    opacity: 0;
+  }
+}
+
+.hinge {
+  animation-name: hinge;
+}
+
+@keyframes jackInTheBox {
+  from {
+    opacity: 0;
+    transform: scale(0.1) rotate(30deg);
+    transform-origin: center bottom;
+  }
+
+  50% {
+    transform: rotate(-10deg);
+  }
+
+  70% {
+    transform: rotate(3deg);
+  }
+
+  to {
+    opacity: 1;
+    transform: scale(1);
+  }
+}
+
+.jackInTheBox {
+  animation-name: jackInTheBox;
+}
+
+/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
+
+@keyframes rollIn {
+  from {
+    opacity: 0;
+    transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
+  }
+
+  to {
+    opacity: 1;
+    transform: none;
+  }
+}
+
+.rollIn {
+  animation-name: rollIn;
+}
+
+/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
+
+@keyframes rollOut {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
+  }
+}
+
+.rollOut {
+  animation-name: rollOut;
+}
+
+@keyframes zoomIn {
+  from {
+    opacity: 0;
+    transform: scale3d(.3, .3, .3);
+  }
+
+  50% {
+    opacity: 1;
+  }
+}
+
+.zoomIn {
+  animation-name: zoomIn;
+}
+
+@keyframes zoomInDown {
+  from {
+    opacity: 0;
+    transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  60% {
+    opacity: 1;
+    transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+.zoomInDown {
+  animation-name: zoomInDown;
+}
+
+@keyframes zoomInLeft {
+  from {
+    opacity: 0;
+    transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  60% {
+    opacity: 1;
+    transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+.zoomInLeft {
+  animation-name: zoomInLeft;
+}
+
+@keyframes zoomInRight {
+  from {
+    opacity: 0;
+    transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  60% {
+    opacity: 1;
+    transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+.zoomInRight {
+  animation-name: zoomInRight;
+}
+
+@keyframes zoomInUp {
+  from {
+    opacity: 0;
+    transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  60% {
+    opacity: 1;
+    transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+.zoomInUp {
+  animation-name: zoomInUp;
+}
+
+@keyframes zoomOut {
+  from {
+    opacity: 1;
+  }
+
+  50% {
+    opacity: 0;
+    transform: scale3d(.3, .3, .3);
+  }
+
+  to {
+    opacity: 0;
+  }
+}
+
+.zoomOut {
+  animation-name: zoomOut;
+}
+
+@keyframes zoomOutDown {
+  40% {
+    opacity: 1;
+    transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  to {
+    opacity: 0;
+    transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
+    transform-origin: center bottom;
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+.zoomOutDown {
+  animation-name: zoomOutDown;
+}
+
+@keyframes zoomOutLeft {
+  40% {
+    opacity: 1;
+    transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);
+  }
+
+  to {
+    opacity: 0;
+    transform: scale(.1) translate3d(-2000px, 0, 0);
+    transform-origin: left center;
+  }
+}
+
+.zoomOutLeft {
+  animation-name: zoomOutLeft;
+}
+
+@keyframes zoomOutRight {
+  40% {
+    opacity: 1;
+    transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);
+  }
+
+  to {
+    opacity: 0;
+    transform: scale(.1) translate3d(2000px, 0, 0);
+    transform-origin: right center;
+  }
+}
+
+.zoomOutRight {
+  animation-name: zoomOutRight;
+}
+
+@keyframes zoomOutUp {
+  40% {
+    opacity: 1;
+    transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  to {
+    opacity: 0;
+    transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
+    transform-origin: center bottom;
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+.zoomOutUp {
+  animation-name: zoomOutUp;
+}
+
+@keyframes slideInDown {
+  from {
+    transform: translate3d(0, -100%, 0);
+    visibility: visible;
+  }
+
+  to {
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+.slideInDown {
+  animation-name: slideInDown;
+}
+
+@keyframes slideInLeft {
+  from {
+    transform: translate3d(-100%, 0, 0);
+    visibility: visible;
+  }
+
+  to {
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+.slideInLeft {
+  animation-name: slideInLeft;
+}
+
+@keyframes slideInRight {
+  from {
+    transform: translate3d(100%, 0, 0);
+    visibility: visible;
+  }
+
+  to {
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+.slideInRight {
+  animation-name: slideInRight;
+}
+
+@keyframes slideInUp {
+  from {
+    transform: translate3d(0, 100%, 0);
+    visibility: visible;
+  }
+
+  to {
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+.slideInUp {
+  animation-name: slideInUp;
+}
+
+@keyframes slideOutDown {
+  from {
+    transform: translate3d(0, 0, 0);
+  }
+
+  to {
+    visibility: hidden;
+    transform: translate3d(0, 100%, 0);
+  }
+}
+
+.slideOutDown {
+  animation-name: slideOutDown;
+}
+
+@keyframes slideOutLeft {
+  from {
+    transform: translate3d(0, 0, 0);
+  }
+
+  to {
+    visibility: hidden;
+    transform: translate3d(-100%, 0, 0);
+  }
+}
+
+.slideOutLeft {
+  animation-name: slideOutLeft;
+}
+
+@keyframes slideOutRight {
+  from {
+    transform: translate3d(0, 0, 0);
+  }
+
+  to {
+    visibility: hidden;
+    transform: translate3d(100%, 0, 0);
+  }
+}
+
+.slideOutRight {
+  animation-name: slideOutRight;
+}
+
+@keyframes slideOutUp {
+  from {
+    transform: translate3d(0, 0, 0);
+  }
+
+  to {
+    visibility: hidden;
+    transform: translate3d(0, -100%, 0);
+  }
+}
+
+.slideOutUp {
+  animation-name: slideOutUp;
+}

+ 1541 - 0
static/src/lib/particles.js

@@ -0,0 +1,1541 @@
+/* -----------------------------------------------
+/* Author : Vincent Garreau  - vincentgarreau.com
+/* MIT license: http://opensource.org/licenses/MIT
+/* Demo / Generator : vincentgarreau.com/particles.js
+/* GitHub : github.com/VincentGarreau/particles.js
+/* How to use? : Check the GitHub README
+/* v2.0.0
+/* ----------------------------------------------- */
+
+var pJS = function(tag_id, params){
+
+  var canvas_el = document.querySelector('#'+tag_id+' > .particles-js-canvas-el');
+
+  /* particles.js variables with default values */
+  this.pJS = {
+    canvas: {
+      el: canvas_el,
+      w: canvas_el.offsetWidth,
+      h: canvas_el.offsetHeight
+    },
+    particles: {
+      number: {
+        value: 400,
+        density: {
+          enable: true,
+          value_area: 800
+        }
+      },
+      color: {
+        value: '#fff'
+      },
+      shape: {
+        type: 'circle',
+        stroke: {
+          width: 0,
+          color: '#ff0000'
+        },
+        polygon: {
+          nb_sides: 5
+        },
+        image: {
+          src: '',
+          width: 100,
+          height: 100
+        }
+      },
+      opacity: {
+        value: 1,
+        random: false,
+        anim: {
+          enable: false,
+          speed: 2,
+          opacity_min: 0,
+          sync: false
+        }
+      },
+      size: {
+        value: 20,
+        random: false,
+        anim: {
+          enable: false,
+          speed: 20,
+          size_min: 0,
+          sync: false
+        }
+      },
+      line_linked: {
+        enable: true,
+        distance: 100,
+        color: '#fff',
+        opacity: 1,
+        width: 1
+      },
+      move: {
+        enable: true,
+        speed: 2,
+        direction: 'none',
+        random: false,
+        straight: false,
+        out_mode: 'out',
+        bounce: false,
+        attract: {
+          enable: false,
+          rotateX: 3000,
+          rotateY: 3000
+        }
+      },
+      array: []
+    },
+    interactivity: {
+      detect_on: 'canvas',
+      events: {
+        onhover: {
+          enable: true,
+          mode: 'grab'
+        },
+        onclick: {
+          enable: true,
+          mode: 'push'
+        },
+        resize: true
+      },
+      modes: {
+        grab:{
+          distance: 100,
+          line_linked:{
+            opacity: 1
+          }
+        },
+        bubble:{
+          distance: 200,
+          size: 80,
+          duration: 0.4
+        },
+        repulse:{
+          distance: 200,
+          duration: 0.4
+        },
+        push:{
+          particles_nb: 4
+        },
+        remove:{
+          particles_nb: 2
+        }
+      },
+      mouse:{}
+    },
+    retina_detect: false,
+    fn: {
+      interact: {},
+      modes: {},
+      vendors:{}
+    },
+    tmp: {}
+  };
+
+  var pJS = this.pJS;
+
+  /* params settings */
+  if(params){
+    Object.deepExtend(pJS, params);
+  }
+
+  pJS.tmp.obj = {
+    size_value: pJS.particles.size.value,
+    size_anim_speed: pJS.particles.size.anim.speed,
+    move_speed: pJS.particles.move.speed,
+    line_linked_distance: pJS.particles.line_linked.distance,
+    line_linked_width: pJS.particles.line_linked.width,
+    mode_grab_distance: pJS.interactivity.modes.grab.distance,
+    mode_bubble_distance: pJS.interactivity.modes.bubble.distance,
+    mode_bubble_size: pJS.interactivity.modes.bubble.size,
+    mode_repulse_distance: pJS.interactivity.modes.repulse.distance
+  };
+
+
+  pJS.fn.retinaInit = function(){
+
+    if(pJS.retina_detect && window.devicePixelRatio > 1){
+      pJS.canvas.pxratio = window.devicePixelRatio; 
+      pJS.tmp.retina = true;
+    } 
+    else{
+      pJS.canvas.pxratio = 1;
+      pJS.tmp.retina = false;
+    }
+
+    pJS.canvas.w = pJS.canvas.el.offsetWidth * pJS.canvas.pxratio;
+    pJS.canvas.h = pJS.canvas.el.offsetHeight * pJS.canvas.pxratio;
+
+    pJS.particles.size.value = pJS.tmp.obj.size_value * pJS.canvas.pxratio;
+    pJS.particles.size.anim.speed = pJS.tmp.obj.size_anim_speed * pJS.canvas.pxratio;
+    pJS.particles.move.speed = pJS.tmp.obj.move_speed * pJS.canvas.pxratio;
+    pJS.particles.line_linked.distance = pJS.tmp.obj.line_linked_distance * pJS.canvas.pxratio;
+    pJS.interactivity.modes.grab.distance = pJS.tmp.obj.mode_grab_distance * pJS.canvas.pxratio;
+    pJS.interactivity.modes.bubble.distance = pJS.tmp.obj.mode_bubble_distance * pJS.canvas.pxratio;
+    pJS.particles.line_linked.width = pJS.tmp.obj.line_linked_width * pJS.canvas.pxratio;
+    pJS.interactivity.modes.bubble.size = pJS.tmp.obj.mode_bubble_size * pJS.canvas.pxratio;
+    pJS.interactivity.modes.repulse.distance = pJS.tmp.obj.mode_repulse_distance * pJS.canvas.pxratio;
+
+  };
+
+
+
+  /* ---------- pJS functions - canvas ------------ */
+
+  pJS.fn.canvasInit = function(){
+    pJS.canvas.ctx = pJS.canvas.el.getContext('2d');
+  };
+
+  pJS.fn.canvasSize = function(){
+
+    pJS.canvas.el.width = pJS.canvas.w;
+    pJS.canvas.el.height = pJS.canvas.h;
+
+    if(pJS && pJS.interactivity.events.resize){
+
+      window.addEventListener('resize', function(){
+
+          pJS.canvas.w = pJS.canvas.el.offsetWidth;
+          pJS.canvas.h = pJS.canvas.el.offsetHeight;
+
+          /* resize canvas */
+          if(pJS.tmp.retina){
+            pJS.canvas.w *= pJS.canvas.pxratio;
+            pJS.canvas.h *= pJS.canvas.pxratio;
+          }
+
+          pJS.canvas.el.width = pJS.canvas.w;
+          pJS.canvas.el.height = pJS.canvas.h;
+
+          /* repaint canvas on anim disabled */
+          if(!pJS.particles.move.enable){
+            pJS.fn.particlesEmpty();
+            pJS.fn.particlesCreate();
+            pJS.fn.particlesDraw();
+            pJS.fn.vendors.densityAutoParticles();
+          }
+
+        /* density particles enabled */
+        pJS.fn.vendors.densityAutoParticles();
+
+      });
+
+    }
+
+  };
+
+
+  pJS.fn.canvasPaint = function(){
+    pJS.canvas.ctx.fillRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+  };
+
+  pJS.fn.canvasClear = function(){
+    pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+  };
+
+
+  /* --------- pJS functions - particles ----------- */
+
+  pJS.fn.particle = function(color, opacity, position){
+
+    /* size */
+    this.radius = (pJS.particles.size.random ? Math.random() : 1) * pJS.particles.size.value;
+    if(pJS.particles.size.anim.enable){
+      this.size_status = false;
+      this.vs = pJS.particles.size.anim.speed / 100;
+      if(!pJS.particles.size.anim.sync){
+        this.vs = this.vs * Math.random();
+      }
+    }
+
+    /* position */
+    this.x = position ? position.x : Math.random() * pJS.canvas.w;
+    this.y = position ? position.y : Math.random() * pJS.canvas.h;
+
+    /* check position  - into the canvas */
+    if(this.x > pJS.canvas.w - this.radius*2) this.x = this.x - this.radius;
+    else if(this.x < this.radius*2) this.x = this.x + this.radius;
+    if(this.y > pJS.canvas.h - this.radius*2) this.y = this.y - this.radius;
+    else if(this.y < this.radius*2) this.y = this.y + this.radius;
+
+    /* check position - avoid overlap */
+    if(pJS.particles.move.bounce){
+      pJS.fn.vendors.checkOverlap(this, position);
+    }
+
+    /* color */
+    this.color = {};
+    if(typeof(color.value) == 'object'){
+
+      if(color.value instanceof Array){
+        var color_selected = color.value[Math.floor(Math.random() * pJS.particles.color.value.length)];
+        this.color.rgb = hexToRgb(color_selected);
+      }else{
+        if(color.value.r != undefined && color.value.g != undefined && color.value.b != undefined){
+          this.color.rgb = {
+            r: color.value.r,
+            g: color.value.g,
+            b: color.value.b
+          }
+        }
+        if(color.value.h != undefined && color.value.s != undefined && color.value.l != undefined){
+          this.color.hsl = {
+            h: color.value.h,
+            s: color.value.s,
+            l: color.value.l
+          }
+        }
+      }
+
+    }
+    else if(color.value == 'random'){
+      this.color.rgb = {
+        r: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),
+        g: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),
+        b: (Math.floor(Math.random() * (255 - 0 + 1)) + 0)
+      }
+    }
+    else if(typeof(color.value) == 'string'){
+      this.color = color;
+      this.color.rgb = hexToRgb(this.color.value);
+    }
+
+    /* opacity */
+    this.opacity = (pJS.particles.opacity.random ? Math.random() : 1) * pJS.particles.opacity.value;
+    if(pJS.particles.opacity.anim.enable){
+      this.opacity_status = false;
+      this.vo = pJS.particles.opacity.anim.speed / 100;
+      if(!pJS.particles.opacity.anim.sync){
+        this.vo = this.vo * Math.random();
+      }
+    }
+
+    /* animation - velocity for speed */
+    var velbase = {}
+    switch(pJS.particles.move.direction){
+      case 'top':
+        velbase = { x:0, y:-1 };
+      break;
+      case 'top-right':
+        velbase = { x:0.5, y:-0.5 };
+      break;
+      case 'right':
+        velbase = { x:1, y:-0 };
+      break;
+      case 'bottom-right':
+        velbase = { x:0.5, y:0.5 };
+      break;
+      case 'bottom':
+        velbase = { x:0, y:1 };
+      break;
+      case 'bottom-left':
+        velbase = { x:-0.5, y:1 };
+      break;
+      case 'left':
+        velbase = { x:-1, y:0 };
+      break;
+      case 'top-left':
+        velbase = { x:-0.5, y:-0.5 };
+      break;
+      default:
+        velbase = { x:0, y:0 };
+      break;
+    }
+
+    if(pJS.particles.move.straight){
+      this.vx = velbase.x;
+      this.vy = velbase.y;
+      if(pJS.particles.move.random){
+        this.vx = this.vx * (Math.random());
+        this.vy = this.vy * (Math.random());
+      }
+    }else{
+      this.vx = velbase.x + Math.random()-0.5;
+      this.vy = velbase.y + Math.random()-0.5;
+    }
+
+    // var theta = 2.0 * Math.PI * Math.random();
+    // this.vx = Math.cos(theta);
+    // this.vy = Math.sin(theta);
+
+    this.vx_i = this.vx;
+    this.vy_i = this.vy;
+
+    
+
+    /* if shape is image */
+
+    var shape_type = pJS.particles.shape.type;
+    if(typeof(shape_type) == 'object'){
+      if(shape_type instanceof Array){
+        var shape_selected = shape_type[Math.floor(Math.random() * shape_type.length)];
+        this.shape = shape_selected;
+      }
+    }else{
+      this.shape = shape_type;
+    }
+
+    if(this.shape == 'image'){
+      var sh = pJS.particles.shape;
+      this.img = {
+        src: sh.image.src,
+        ratio: sh.image.width / sh.image.height
+      }
+      if(!this.img.ratio) this.img.ratio = 1;
+      if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg != undefined){
+        pJS.fn.vendors.createSvgImg(this);
+        if(pJS.tmp.pushing){
+          this.img.loaded = false;
+        }
+      }
+    }
+
+    
+
+  };
+
+
+  pJS.fn.particle.prototype.draw = function() {
+
+    var p = this;
+
+    if(p.radius_bubble != undefined){
+      var radius = p.radius_bubble; 
+    }else{
+      var radius = p.radius;
+    }
+
+    if(p.opacity_bubble != undefined){
+      var opacity = p.opacity_bubble;
+    }else{
+      var opacity = p.opacity;
+    }
+
+    if(p.color.rgb){
+      var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+opacity+')';
+    }else{
+      var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+opacity+')';
+    }
+
+    pJS.canvas.ctx.fillStyle = color_value;
+    pJS.canvas.ctx.beginPath();
+
+    switch(p.shape){
+
+      case 'circle':
+        pJS.canvas.ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false);
+      break;
+
+      case 'edge':
+        pJS.canvas.ctx.rect(p.x-radius, p.y-radius, radius*2, radius*2);
+      break;
+
+      case 'triangle':
+        pJS.fn.vendors.drawShape(pJS.canvas.ctx, p.x-radius, p.y+radius / 1.66, radius*2, 3, 2);
+      break;
+
+      case 'polygon':
+        pJS.fn.vendors.drawShape(
+          pJS.canvas.ctx,
+          p.x - radius / (pJS.particles.shape.polygon.nb_sides/3.5), // startX
+          p.y - radius / (2.66/3.5), // startY
+          radius*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength
+          pJS.particles.shape.polygon.nb_sides, // sideCountNumerator
+          1 // sideCountDenominator
+        );
+      break;
+
+      case 'star':
+        pJS.fn.vendors.drawShape(
+          pJS.canvas.ctx,
+          p.x - radius*2 / (pJS.particles.shape.polygon.nb_sides/4), // startX
+          p.y - radius / (2*2.66/3.5), // startY
+          radius*2*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength
+          pJS.particles.shape.polygon.nb_sides, // sideCountNumerator
+          2 // sideCountDenominator
+        );
+      break;
+
+      case 'image':
+
+        function draw(){
+          pJS.canvas.ctx.drawImage(
+            img_obj,
+            p.x-radius,
+            p.y-radius,
+            radius*2,
+            radius*2 / p.img.ratio
+          );
+        }
+
+        if(pJS.tmp.img_type == 'svg'){
+          var img_obj = p.img.obj;
+        }else{
+          var img_obj = pJS.tmp.img_obj;
+        }
+
+        if(img_obj){
+          draw();
+        }
+
+      break;
+
+    }
+
+    pJS.canvas.ctx.closePath();
+
+    if(pJS.particles.shape.stroke.width > 0){
+      pJS.canvas.ctx.strokeStyle = pJS.particles.shape.stroke.color;
+      pJS.canvas.ctx.lineWidth = pJS.particles.shape.stroke.width;
+      pJS.canvas.ctx.stroke();
+    }
+    
+    pJS.canvas.ctx.fill();
+    
+  };
+
+
+  pJS.fn.particlesCreate = function(){
+    for(var i = 0; i < pJS.particles.number.value; i++) {
+      pJS.particles.array.push(new pJS.fn.particle(pJS.particles.color, pJS.particles.opacity.value));
+    }
+  };
+
+  pJS.fn.particlesUpdate = function(){
+
+    for(var i = 0; i < pJS.particles.array.length; i++){
+
+      /* the particle */
+      var p = pJS.particles.array[i];
+
+      // var d = ( dx = pJS.interactivity.mouse.click_pos_x - p.x ) * dx + ( dy = pJS.interactivity.mouse.click_pos_y - p.y ) * dy;
+      // var f = -BANG_SIZE / d;
+      // if ( d < BANG_SIZE ) {
+      //     var t = Math.atan2( dy, dx );
+      //     p.vx = f * Math.cos(t);
+      //     p.vy = f * Math.sin(t);
+      // }
+
+      /* move the particle */
+      if(pJS.particles.move.enable){
+        var ms = pJS.particles.move.speed/2;
+        p.x += p.vx * ms;
+        p.y += p.vy * ms;
+      }
+
+      /* change opacity status */
+      if(pJS.particles.opacity.anim.enable) {
+        if(p.opacity_status == true) {
+          if(p.opacity >= pJS.particles.opacity.value) p.opacity_status = false;
+          p.opacity += p.vo;
+        }else {
+          if(p.opacity <= pJS.particles.opacity.anim.opacity_min) p.opacity_status = true;
+          p.opacity -= p.vo;
+        }
+        if(p.opacity < 0) p.opacity = 0;
+      }
+
+      /* change size */
+      if(pJS.particles.size.anim.enable){
+        if(p.size_status == true){
+          if(p.radius >= pJS.particles.size.value) p.size_status = false;
+          p.radius += p.vs;
+        }else{
+          if(p.radius <= pJS.particles.size.anim.size_min) p.size_status = true;
+          p.radius -= p.vs;
+        }
+        if(p.radius < 0) p.radius = 0;
+      }
+
+      /* change particle position if it is out of canvas */
+      if(pJS.particles.move.out_mode == 'bounce'){
+        var new_pos = {
+          x_left: p.radius,
+          x_right:  pJS.canvas.w,
+          y_top: p.radius,
+          y_bottom: pJS.canvas.h
+        }
+      }else{
+        var new_pos = {
+          x_left: -p.radius,
+          x_right: pJS.canvas.w + p.radius,
+          y_top: -p.radius,
+          y_bottom: pJS.canvas.h + p.radius
+        }
+      }
+
+      if(p.x - p.radius > pJS.canvas.w){
+        p.x = new_pos.x_left;
+        p.y = Math.random() * pJS.canvas.h;
+      }
+      else if(p.x + p.radius < 0){
+        p.x = new_pos.x_right;
+        p.y = Math.random() * pJS.canvas.h;
+      }
+      if(p.y - p.radius > pJS.canvas.h){
+        p.y = new_pos.y_top;
+        p.x = Math.random() * pJS.canvas.w;
+      }
+      else if(p.y + p.radius < 0){
+        p.y = new_pos.y_bottom;
+        p.x = Math.random() * pJS.canvas.w;
+      }
+
+      /* out of canvas modes */
+      switch(pJS.particles.move.out_mode){
+        case 'bounce':
+          if (p.x + p.radius > pJS.canvas.w) p.vx = -p.vx;
+          else if (p.x - p.radius < 0) p.vx = -p.vx;
+          if (p.y + p.radius > pJS.canvas.h) p.vy = -p.vy;
+          else if (p.y - p.radius < 0) p.vy = -p.vy;
+        break;
+      }
+
+      /* events */
+      if(isInArray('grab', pJS.interactivity.events.onhover.mode)){
+        pJS.fn.modes.grabParticle(p);
+      }
+
+      if(isInArray('bubble', pJS.interactivity.events.onhover.mode) || isInArray('bubble', pJS.interactivity.events.onclick.mode)){
+        pJS.fn.modes.bubbleParticle(p);
+      }
+
+      if(isInArray('repulse', pJS.interactivity.events.onhover.mode) || isInArray('repulse', pJS.interactivity.events.onclick.mode)){
+        pJS.fn.modes.repulseParticle(p);
+      }
+
+      /* interaction auto between particles */
+      if(pJS.particles.line_linked.enable || pJS.particles.move.attract.enable){
+        for(var j = i + 1; j < pJS.particles.array.length; j++){
+          var p2 = pJS.particles.array[j];
+
+          /* link particles */
+          if(pJS.particles.line_linked.enable){
+            pJS.fn.interact.linkParticles(p,p2);
+          }
+
+          /* attract particles */
+          if(pJS.particles.move.attract.enable){
+            pJS.fn.interact.attractParticles(p,p2);
+          }
+
+          /* bounce particles */
+          if(pJS.particles.move.bounce){
+            pJS.fn.interact.bounceParticles(p,p2);
+          }
+
+        }
+      }
+
+
+    }
+
+  };
+
+  pJS.fn.particlesDraw = function(){
+
+    /* clear canvas */
+    pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+
+    /* update each particles param */
+    pJS.fn.particlesUpdate();
+
+    /* draw each particle */
+    for(var i = 0; i < pJS.particles.array.length; i++){
+      var p = pJS.particles.array[i];
+      p.draw();
+    }
+
+  };
+
+  pJS.fn.particlesEmpty = function(){
+    pJS.particles.array = [];
+  };
+
+  pJS.fn.particlesRefresh = function(){
+
+    /* init all */
+    cancelRequestAnimFrame(pJS.fn.checkAnimFrame);
+    cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+    pJS.tmp.source_svg = undefined;
+    pJS.tmp.img_obj = undefined;
+    pJS.tmp.count_svg = 0;
+    pJS.fn.particlesEmpty();
+    pJS.fn.canvasClear();
+    
+    /* restart */
+    pJS.fn.vendors.start();
+
+  };
+
+
+  /* ---------- pJS functions - particles interaction ------------ */
+
+  pJS.fn.interact.linkParticles = function(p1, p2){
+
+    var dx = p1.x - p2.x,
+        dy = p1.y - p2.y,
+        dist = Math.sqrt(dx*dx + dy*dy);
+
+    /* draw a line between p1 and p2 if the distance between them is under the config distance */
+    if(dist <= pJS.particles.line_linked.distance){
+
+      var opacity_line = pJS.particles.line_linked.opacity - (dist / (1/pJS.particles.line_linked.opacity)) / pJS.particles.line_linked.distance;
+
+      if(opacity_line > 0){        
+        
+        /* style */
+        var color_line = pJS.particles.line_linked.color_rgb_line;
+        pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')';
+        pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;
+        //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */
+        
+        /* path */
+        pJS.canvas.ctx.beginPath();
+        pJS.canvas.ctx.moveTo(p1.x, p1.y);
+        pJS.canvas.ctx.lineTo(p2.x, p2.y);
+        pJS.canvas.ctx.stroke();
+        pJS.canvas.ctx.closePath();
+
+      }
+
+    }
+
+  };
+
+
+  pJS.fn.interact.attractParticles  = function(p1, p2){
+
+    /* condensed particles */
+    var dx = p1.x - p2.x,
+        dy = p1.y - p2.y,
+        dist = Math.sqrt(dx*dx + dy*dy);
+
+    if(dist <= pJS.particles.line_linked.distance){
+
+      var ax = dx/(pJS.particles.move.attract.rotateX*1000),
+          ay = dy/(pJS.particles.move.attract.rotateY*1000);
+
+      p1.vx -= ax;
+      p1.vy -= ay;
+
+      p2.vx += ax;
+      p2.vy += ay;
+
+    }
+    
+
+  }
+
+
+  pJS.fn.interact.bounceParticles = function(p1, p2){
+
+    var dx = p1.x - p2.x,
+        dy = p1.y - p2.y,
+        dist = Math.sqrt(dx*dx + dy*dy),
+        dist_p = p1.radius+p2.radius;
+
+    if(dist <= dist_p){
+      p1.vx = -p1.vx;
+      p1.vy = -p1.vy;
+
+      p2.vx = -p2.vx;
+      p2.vy = -p2.vy;
+    }
+
+  }
+
+
+  /* ---------- pJS functions - modes events ------------ */
+
+  pJS.fn.modes.pushParticles = function(nb, pos){
+
+    pJS.tmp.pushing = true;
+
+    for(var i = 0; i < nb; i++){
+      pJS.particles.array.push(
+        new pJS.fn.particle(
+          pJS.particles.color,
+          pJS.particles.opacity.value,
+          {
+            'x': pos ? pos.pos_x : Math.random() * pJS.canvas.w,
+            'y': pos ? pos.pos_y : Math.random() * pJS.canvas.h
+          }
+        )
+      )
+      if(i == nb-1){
+        if(!pJS.particles.move.enable){
+          pJS.fn.particlesDraw();
+        }
+        pJS.tmp.pushing = false;
+      }
+    }
+
+  };
+
+
+  pJS.fn.modes.removeParticles = function(nb){
+
+    pJS.particles.array.splice(0, nb);
+    if(!pJS.particles.move.enable){
+      pJS.fn.particlesDraw();
+    }
+
+  };
+
+
+  pJS.fn.modes.bubbleParticle = function(p){
+
+    /* on hover event */
+    if(pJS.interactivity.events.onhover.enable && isInArray('bubble', pJS.interactivity.events.onhover.mode)){
+
+      var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+          dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+          dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse),
+          ratio = 1 - dist_mouse / pJS.interactivity.modes.bubble.distance;
+
+      function init(){
+        p.opacity_bubble = p.opacity;
+        p.radius_bubble = p.radius;
+      }
+
+      /* mousemove - check ratio */
+      if(dist_mouse <= pJS.interactivity.modes.bubble.distance){
+
+        if(ratio >= 0 && pJS.interactivity.status == 'mousemove'){
+          
+          /* size */
+          if(pJS.interactivity.modes.bubble.size != pJS.particles.size.value){
+
+            if(pJS.interactivity.modes.bubble.size > pJS.particles.size.value){
+              var size = p.radius + (pJS.interactivity.modes.bubble.size*ratio);
+              if(size >= 0){
+                p.radius_bubble = size;
+              }
+            }else{
+              var dif = p.radius - pJS.interactivity.modes.bubble.size,
+                  size = p.radius - (dif*ratio);
+              if(size > 0){
+                p.radius_bubble = size;
+              }else{
+                p.radius_bubble = 0;
+              }
+            }
+
+          }
+
+          /* opacity */
+          if(pJS.interactivity.modes.bubble.opacity != pJS.particles.opacity.value){
+
+            if(pJS.interactivity.modes.bubble.opacity > pJS.particles.opacity.value){
+              var opacity = pJS.interactivity.modes.bubble.opacity*ratio;
+              if(opacity > p.opacity && opacity <= pJS.interactivity.modes.bubble.opacity){
+                p.opacity_bubble = opacity;
+              }
+            }else{
+              var opacity = p.opacity - (pJS.particles.opacity.value-pJS.interactivity.modes.bubble.opacity)*ratio;
+              if(opacity < p.opacity && opacity >= pJS.interactivity.modes.bubble.opacity){
+                p.opacity_bubble = opacity;
+              }
+            }
+
+          }
+
+        }
+
+      }else{
+        init();
+      }
+
+
+      /* mouseleave */
+      if(pJS.interactivity.status == 'mouseleave'){
+        init();
+      }
+    
+    }
+
+    /* on click event */
+    else if(pJS.interactivity.events.onclick.enable && isInArray('bubble', pJS.interactivity.events.onclick.mode)){
+
+
+      if(pJS.tmp.bubble_clicking){
+        var dx_mouse = p.x - pJS.interactivity.mouse.click_pos_x,
+            dy_mouse = p.y - pJS.interactivity.mouse.click_pos_y,
+            dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse),
+            time_spent = (new Date().getTime() - pJS.interactivity.mouse.click_time)/1000;
+
+        if(time_spent > pJS.interactivity.modes.bubble.duration){
+          pJS.tmp.bubble_duration_end = true;
+        }
+
+        if(time_spent > pJS.interactivity.modes.bubble.duration*2){
+          pJS.tmp.bubble_clicking = false;
+          pJS.tmp.bubble_duration_end = false;
+        }
+      }
+
+
+      function process(bubble_param, particles_param, p_obj_bubble, p_obj, id){
+
+        if(bubble_param != particles_param){
+
+          if(!pJS.tmp.bubble_duration_end){
+            if(dist_mouse <= pJS.interactivity.modes.bubble.distance){
+              if(p_obj_bubble != undefined) var obj = p_obj_bubble;
+              else var obj = p_obj;
+              if(obj != bubble_param){
+                var value = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration);
+                if(id == 'size') p.radius_bubble = value;
+                if(id == 'opacity') p.opacity_bubble = value;
+              }
+            }else{
+              if(id == 'size') p.radius_bubble = undefined;
+              if(id == 'opacity') p.opacity_bubble = undefined;
+            }
+          }else{
+            if(p_obj_bubble != undefined){
+              var value_tmp = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration),
+                  dif = bubble_param - value_tmp;
+                  value = bubble_param + dif;
+              if(id == 'size') p.radius_bubble = value;
+              if(id == 'opacity') p.opacity_bubble = value;
+            }
+          }
+
+        }
+
+      }
+
+      if(pJS.tmp.bubble_clicking){
+        /* size */
+        process(pJS.interactivity.modes.bubble.size, pJS.particles.size.value, p.radius_bubble, p.radius, 'size');
+        /* opacity */
+        process(pJS.interactivity.modes.bubble.opacity, pJS.particles.opacity.value, p.opacity_bubble, p.opacity, 'opacity');
+      }
+
+    }
+
+  };
+
+
+  pJS.fn.modes.repulseParticle = function(p){
+
+    if(pJS.interactivity.events.onhover.enable && isInArray('repulse', pJS.interactivity.events.onhover.mode) && pJS.interactivity.status == 'mousemove') {
+
+      var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+          dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+          dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse);
+
+      var normVec = {x: dx_mouse/dist_mouse, y: dy_mouse/dist_mouse},
+          repulseRadius = pJS.interactivity.modes.repulse.distance,
+          velocity = 100,
+          repulseFactor = clamp((1/repulseRadius)*(-1*Math.pow(dist_mouse/repulseRadius,2)+1)*repulseRadius*velocity, 0, 50);
+      
+      var pos = {
+        x: p.x + normVec.x * repulseFactor,
+        y: p.y + normVec.y * repulseFactor
+      }
+
+      if(pJS.particles.move.out_mode == 'bounce'){
+        if(pos.x - p.radius > 0 && pos.x + p.radius < pJS.canvas.w) p.x = pos.x;
+        if(pos.y - p.radius > 0 && pos.y + p.radius < pJS.canvas.h) p.y = pos.y;
+      }else{
+        p.x = pos.x;
+        p.y = pos.y;
+      }
+    
+    }
+
+
+    else if(pJS.interactivity.events.onclick.enable && isInArray('repulse', pJS.interactivity.events.onclick.mode)) {
+
+      if(!pJS.tmp.repulse_finish){
+        pJS.tmp.repulse_count++;
+        if(pJS.tmp.repulse_count == pJS.particles.array.length){
+          pJS.tmp.repulse_finish = true;
+        }
+      }
+
+      if(pJS.tmp.repulse_clicking){
+
+        var repulseRadius = Math.pow(pJS.interactivity.modes.repulse.distance/6, 3);
+
+        var dx = pJS.interactivity.mouse.click_pos_x - p.x,
+            dy = pJS.interactivity.mouse.click_pos_y - p.y,
+            d = dx*dx + dy*dy;
+
+        var force = -repulseRadius / d * 1;
+
+        function process(){
+
+          var f = Math.atan2(dy,dx);
+          p.vx = force * Math.cos(f);
+          p.vy = force * Math.sin(f);
+
+          if(pJS.particles.move.out_mode == 'bounce'){
+            var pos = {
+              x: p.x + p.vx,
+              y: p.y + p.vy
+            }
+            if (pos.x + p.radius > pJS.canvas.w) p.vx = -p.vx;
+            else if (pos.x - p.radius < 0) p.vx = -p.vx;
+            if (pos.y + p.radius > pJS.canvas.h) p.vy = -p.vy;
+            else if (pos.y - p.radius < 0) p.vy = -p.vy;
+          }
+
+        }
+
+        // default
+        if(d <= repulseRadius){
+          process();
+        }
+
+        // bang - slow motion mode
+        // if(!pJS.tmp.repulse_finish){
+        //   if(d <= repulseRadius){
+        //     process();
+        //   }
+        // }else{
+        //   process();
+        // }
+        
+
+      }else{
+
+        if(pJS.tmp.repulse_clicking == false){
+
+          p.vx = p.vx_i;
+          p.vy = p.vy_i;
+        
+        }
+
+      }
+
+    }
+
+  }
+
+
+  pJS.fn.modes.grabParticle = function(p){
+
+    if(pJS.interactivity.events.onhover.enable && pJS.interactivity.status == 'mousemove'){
+
+      var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+          dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+          dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse);
+
+      /* draw a line between the cursor and the particle if the distance between them is under the config distance */
+      if(dist_mouse <= pJS.interactivity.modes.grab.distance){
+
+        var opacity_line = pJS.interactivity.modes.grab.line_linked.opacity - (dist_mouse / (1/pJS.interactivity.modes.grab.line_linked.opacity)) / pJS.interactivity.modes.grab.distance;
+
+        if(opacity_line > 0){
+
+          /* style */
+          var color_line = pJS.particles.line_linked.color_rgb_line;
+          pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')';
+          pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;
+          //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */
+          
+          /* path */
+          pJS.canvas.ctx.beginPath();
+          pJS.canvas.ctx.moveTo(p.x, p.y);
+          pJS.canvas.ctx.lineTo(pJS.interactivity.mouse.pos_x, pJS.interactivity.mouse.pos_y);
+          pJS.canvas.ctx.stroke();
+          pJS.canvas.ctx.closePath();
+
+        }
+
+      }
+
+    }
+
+  };
+
+
+
+  /* ---------- pJS functions - vendors ------------ */
+
+  pJS.fn.vendors.eventsListeners = function(){
+
+    /* events target element */
+    if(pJS.interactivity.detect_on == 'window'){
+      pJS.interactivity.el = window;
+    }else{
+      pJS.interactivity.el = pJS.canvas.el;
+    }
+
+
+    /* detect mouse pos - on hover / click event */
+    if(pJS.interactivity.events.onhover.enable || pJS.interactivity.events.onclick.enable){
+
+      /* el on mousemove */
+      pJS.interactivity.el.addEventListener('mousemove', function(e){
+
+        if(pJS.interactivity.el == window){
+          var pos_x = e.clientX,
+              pos_y = e.clientY;
+        }
+        else{
+          var pos_x = e.offsetX || e.clientX,
+              pos_y = e.offsetY || e.clientY;
+        }
+
+        pJS.interactivity.mouse.pos_x = pos_x;
+        pJS.interactivity.mouse.pos_y = pos_y;
+
+        if(pJS.tmp.retina){
+          pJS.interactivity.mouse.pos_x *= pJS.canvas.pxratio;
+          pJS.interactivity.mouse.pos_y *= pJS.canvas.pxratio;
+        }
+
+        pJS.interactivity.status = 'mousemove';
+
+      });
+
+      /* el on onmouseleave */
+      pJS.interactivity.el.addEventListener('mouseleave', function(e){
+
+        pJS.interactivity.mouse.pos_x = null;
+        pJS.interactivity.mouse.pos_y = null;
+        pJS.interactivity.status = 'mouseleave';
+
+      });
+
+    }
+
+    /* on click event */
+    if(pJS.interactivity.events.onclick.enable){
+
+      pJS.interactivity.el.addEventListener('click', function(){
+
+        pJS.interactivity.mouse.click_pos_x = pJS.interactivity.mouse.pos_x;
+        pJS.interactivity.mouse.click_pos_y = pJS.interactivity.mouse.pos_y;
+        pJS.interactivity.mouse.click_time = new Date().getTime();
+
+        if(pJS.interactivity.events.onclick.enable){
+
+          switch(pJS.interactivity.events.onclick.mode){
+
+            case 'push':
+              if(pJS.particles.move.enable){
+                pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);
+              }else{
+                if(pJS.interactivity.modes.push.particles_nb == 1){
+                  pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);
+                }
+                else if(pJS.interactivity.modes.push.particles_nb > 1){
+                  pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb);
+                }
+              }
+            break;
+
+            case 'remove':
+              pJS.fn.modes.removeParticles(pJS.interactivity.modes.remove.particles_nb);
+            break;
+
+            case 'bubble':
+              pJS.tmp.bubble_clicking = true;
+            break;
+
+            case 'repulse':
+              pJS.tmp.repulse_clicking = true;
+              pJS.tmp.repulse_count = 0;
+              pJS.tmp.repulse_finish = false;
+              setTimeout(function(){
+                pJS.tmp.repulse_clicking = false;
+              }, pJS.interactivity.modes.repulse.duration*1000)
+            break;
+
+          }
+
+        }
+
+      });
+        
+    }
+
+
+  };
+
+  pJS.fn.vendors.densityAutoParticles = function(){
+
+    if(pJS.particles.number.density.enable){
+
+      /* calc area */
+      var area = pJS.canvas.el.width * pJS.canvas.el.height / 1000;
+      if(pJS.tmp.retina){
+        area = area/(pJS.canvas.pxratio*2);
+      }
+
+      /* calc number of particles based on density area */
+      var nb_particles = area * pJS.particles.number.value / pJS.particles.number.density.value_area;
+
+      /* add or remove X particles */
+      var missing_particles = pJS.particles.array.length - nb_particles;
+      if(missing_particles < 0) pJS.fn.modes.pushParticles(Math.abs(missing_particles));
+      else pJS.fn.modes.removeParticles(missing_particles);
+
+    }
+
+  };
+
+
+  pJS.fn.vendors.checkOverlap = function(p1, position){
+    for(var i = 0; i < pJS.particles.array.length; i++){
+      var p2 = pJS.particles.array[i];
+
+      var dx = p1.x - p2.x,
+          dy = p1.y - p2.y,
+          dist = Math.sqrt(dx*dx + dy*dy);
+
+      if(dist <= p1.radius + p2.radius){
+        p1.x = position ? position.x : Math.random() * pJS.canvas.w;
+        p1.y = position ? position.y : Math.random() * pJS.canvas.h;
+        pJS.fn.vendors.checkOverlap(p1);
+      }
+    }
+  };
+
+
+  pJS.fn.vendors.createSvgImg = function(p){
+
+    /* set color to svg element */
+    var svgXml = pJS.tmp.source_svg,
+        rgbHex = /#([0-9A-F]{3,6})/gi,
+        coloredSvgXml = svgXml.replace(rgbHex, function (m, r, g, b) {
+          if(p.color.rgb){
+            var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+p.opacity+')';
+          }else{
+            var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+p.opacity+')';
+          }
+          return color_value;
+        });
+
+    /* prepare to create img with colored svg */
+    var svg = new Blob([coloredSvgXml], {type: 'image/svg+xml;charset=utf-8'}),
+        DOMURL = window.URL || window.webkitURL || window,
+        url = DOMURL.createObjectURL(svg);
+
+    /* create particle img obj */
+    var img = new Image();
+    img.addEventListener('load', function(){
+      p.img.obj = img;
+      p.img.loaded = true;
+      DOMURL.revokeObjectURL(url);
+      pJS.tmp.count_svg++;
+    });
+    img.src = url;
+
+  };
+
+
+  pJS.fn.vendors.destroypJS = function(){
+    cancelAnimationFrame(pJS.fn.drawAnimFrame);
+    canvas_el.remove();
+    pJSDom = null;
+  };
+
+
+  pJS.fn.vendors.drawShape = function(c, startX, startY, sideLength, sideCountNumerator, sideCountDenominator){
+
+    // By Programming Thomas - https://programmingthomas.wordpress.com/2013/04/03/n-sided-shapes/
+    var sideCount = sideCountNumerator * sideCountDenominator;
+    var decimalSides = sideCountNumerator / sideCountDenominator;
+    var interiorAngleDegrees = (180 * (decimalSides - 2)) / decimalSides;
+    var interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180; // convert to radians
+    c.save();
+    c.beginPath();
+    c.translate(startX, startY);
+    c.moveTo(0,0);
+    for (var i = 0; i < sideCount; i++) {
+      c.lineTo(sideLength,0);
+      c.translate(sideLength,0);
+      c.rotate(interiorAngle);
+    }
+    //c.stroke();
+    c.fill();
+    c.restore();
+
+  };
+
+  pJS.fn.vendors.exportImg = function(){
+    window.open(pJS.canvas.el.toDataURL('image/png'), '_blank');
+  };
+
+
+  pJS.fn.vendors.loadImg = function(type){
+
+    pJS.tmp.img_error = undefined;
+
+    if(pJS.particles.shape.image.src != ''){
+
+      if(type == 'svg'){
+
+        var xhr = new XMLHttpRequest();
+        xhr.open('GET', pJS.particles.shape.image.src);
+        xhr.onreadystatechange = function (data) {
+          if(xhr.readyState == 4){
+            if(xhr.status == 200){
+              pJS.tmp.source_svg = data.currentTarget.response;
+              pJS.fn.vendors.checkBeforeDraw();
+            }else{
+              console.log('Error pJS - Image not found');
+              pJS.tmp.img_error = true;
+            }
+          }
+        }
+        xhr.send();
+
+      }else{
+
+        var img = new Image();
+        img.addEventListener('load', function(){
+          pJS.tmp.img_obj = img;
+          pJS.fn.vendors.checkBeforeDraw();
+        });
+        img.src = pJS.particles.shape.image.src;
+
+      }
+
+    }else{
+      console.log('Error pJS - No image.src');
+      pJS.tmp.img_error = true;
+    }
+
+  };
+
+
+  pJS.fn.vendors.draw = function(){
+
+    if(pJS.particles.shape.type == 'image'){
+
+      if(pJS.tmp.img_type == 'svg'){
+
+        if(pJS.tmp.count_svg >= pJS.particles.number.value){
+          pJS.fn.particlesDraw();
+          if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+          else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+        }else{
+          //console.log('still loading...');
+          if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+        }
+
+      }else{
+
+        if(pJS.tmp.img_obj != undefined){
+          pJS.fn.particlesDraw();
+          if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+          else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+        }else{
+          if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+        }
+
+      }
+
+    }else{
+      pJS.fn.particlesDraw();
+      if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+      else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+    }
+
+  };
+
+
+  pJS.fn.vendors.checkBeforeDraw = function(){
+
+    // if shape is image
+    if(pJS.particles.shape.type == 'image'){
+
+      if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg == undefined){
+        pJS.tmp.checkAnimFrame = requestAnimFrame(check);
+      }else{
+        //console.log('images loaded! cancel check');
+        cancelRequestAnimFrame(pJS.tmp.checkAnimFrame);
+        if(!pJS.tmp.img_error){
+          pJS.fn.vendors.init();
+          pJS.fn.vendors.draw();
+        }
+        
+      }
+
+    }else{
+      pJS.fn.vendors.init();
+      pJS.fn.vendors.draw();
+    }
+
+  };
+
+
+  pJS.fn.vendors.init = function(){
+
+    /* init canvas + particles */
+    pJS.fn.retinaInit();
+    pJS.fn.canvasInit();
+    pJS.fn.canvasSize();
+    pJS.fn.canvasPaint();
+    pJS.fn.particlesCreate();
+    pJS.fn.vendors.densityAutoParticles();
+
+    /* particles.line_linked - convert hex colors to rgb */
+    pJS.particles.line_linked.color_rgb_line = hexToRgb(pJS.particles.line_linked.color);
+
+  };
+
+
+  pJS.fn.vendors.start = function(){
+
+    if(isInArray('image', pJS.particles.shape.type)){
+      pJS.tmp.img_type = pJS.particles.shape.image.src.substr(pJS.particles.shape.image.src.length - 3);
+      pJS.fn.vendors.loadImg(pJS.tmp.img_type);
+    }else{
+      pJS.fn.vendors.checkBeforeDraw();
+    }
+
+  };
+
+
+
+
+  /* ---------- pJS - start ------------ */
+
+
+  pJS.fn.vendors.eventsListeners();
+
+  pJS.fn.vendors.start();
+  
+
+
+};
+
+/* ---------- global functions - vendors ------------ */
+
+Object.deepExtend = function(destination, source) {
+  for (var property in source) {
+    if (source[property] && source[property].constructor &&
+     source[property].constructor === Object) {
+      destination[property] = destination[property] || {};
+      arguments.callee(destination[property], source[property]);
+    } else {
+      destination[property] = source[property];
+    }
+  }
+  return destination;
+};
+
+window.requestAnimFrame = (function(){
+  return  window.requestAnimationFrame ||
+    window.webkitRequestAnimationFrame ||
+    window.mozRequestAnimationFrame    ||
+    window.oRequestAnimationFrame      ||
+    window.msRequestAnimationFrame     ||
+    function(callback){
+      window.setTimeout(callback, 1000 / 60);
+    };
+})();
+
+window.cancelRequestAnimFrame = ( function() {
+  return window.cancelAnimationFrame         ||
+    window.webkitCancelRequestAnimationFrame ||
+    window.mozCancelRequestAnimationFrame    ||
+    window.oCancelRequestAnimationFrame      ||
+    window.msCancelRequestAnimationFrame     ||
+    clearTimeout
+} )();
+
+function hexToRgb(hex){
+  // By Tim Down - http://stackoverflow.com/a/5624139/3493650
+  // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
+  var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
+  hex = hex.replace(shorthandRegex, function(m, r, g, b) {
+     return r + r + g + g + b + b;
+  });
+  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+  return result ? {
+      r: parseInt(result[1], 16),
+      g: parseInt(result[2], 16),
+      b: parseInt(result[3], 16)
+  } : null;
+};
+
+function clamp(number, min, max) {
+  return Math.min(Math.max(number, min), max);
+};
+
+function isInArray(value, array) {
+  return array.indexOf(value) > -1;
+}
+
+
+/* ---------- particles.js functions - start ------------ */
+
+window.pJSDom = [];
+
+window.particlesJS = function(tag_id, params){
+
+  //console.log(params);
+
+  /* no string id? so it's object params, and set the id with default id */
+  if(typeof(tag_id) != 'string'){
+    params = tag_id;
+    tag_id = 'particles-js';
+  }
+
+  /* no id? set the id to default id */
+  if(!tag_id){
+    tag_id = 'particles-js';
+  }
+
+  /* pJS elements */
+  var pJS_tag = document.getElementById(tag_id),
+      pJS_canvas_class = 'particles-js-canvas-el',
+      exist_canvas = pJS_tag.getElementsByClassName(pJS_canvas_class);
+
+  /* remove canvas if exists into the pJS target tag */
+  if(exist_canvas.length){
+    while(exist_canvas.length > 0){
+      pJS_tag.removeChild(exist_canvas[0]);
+    }
+  }
+
+  /* create canvas element */
+  var canvas_el = document.createElement('canvas');
+  canvas_el.className = pJS_canvas_class;
+
+  /* set size canvas */
+  canvas_el.style.width = "100%";
+  canvas_el.style.height = "100%";
+
+  /* append canvas */
+  var canvas = document.getElementById(tag_id).appendChild(canvas_el);
+
+  /* launch particle.js */
+  if(canvas != null){
+    pJSDom.push(new pJS(tag_id, params));
+  }
+
+};
+
+window.particlesJS.load = function(tag_id, path_config_json, callback){
+
+  /* load json config */
+  var xhr = new XMLHttpRequest();
+  xhr.open('GET', path_config_json);
+  xhr.onreadystatechange = function (data) {
+    if(xhr.readyState == 4){
+      if(xhr.status == 200){
+        var params = JSON.parse(data.currentTarget.response);
+        window.particlesJS(tag_id, params);
+        if(callback) callback();
+      }else{
+        console.log('Error pJS - XMLHttpRequest status: '+xhr.status);
+        console.log('Error pJS - File config not found');
+      }
+    }
+  };
+  xhr.send();
+
+};

+ 14 - 0
static/src/sass/_body.sass

@@ -0,0 +1,14 @@
+@import url('https://fonts.googleapis.com/css?family=Roboto')
+
+html, body, .openerp
+    background: $eiru-color-none
+    font-family: 'Roboto', sans-serif
+
+body
+    font-size: $eiru-font-primary
+
+    .oe_user_menu_placeholder
+        .dropdown-menu
+            li
+                &:nth-child(2), &:nth-child(3), &:nth-child(4)
+                    display: none

+ 17 - 0
static/src/sass/_variables.sass

@@ -0,0 +1,17 @@
+// General
+$eiru-font-primary: 14pt
+$eiru-color-primary: #0288d1
+$eiru-color-secondary: #007dc1
+$eiru-color-danger: #d32f2f
+$eiru-color-success: #4caf50
+$eiru-color-light: #eeeeee
+$eiru-color-lighter: #f5f5f5
+$eiru-color-lightdark: #d3d3d3
+$eiru-color-dark: #616161
+$eiru-color-none: #fff
+
+// Navbar
+$eiru-navbar-height: 45px
+
+// Sidebar
+$eiru-sidebar-width: 250px

+ 3 - 0
static/src/sass/backend/_application.sass

@@ -0,0 +1,3 @@
+.pos
+    .wizard-progress-bar
+        background: $eiru-color-primary

+ 31 - 0
static/src/sass/backend/_buttons.sass

@@ -0,0 +1,31 @@
+.oe_view_manager_header
+    button
+        border: 1px solid transparent !important
+        border-radius: 0 !important
+        box-shadow: none !important
+
+    .oe_highlight
+        width: 85px !important
+        height: 30px !important
+        background: $eiru-color-danger !important
+
+    .oe_form_button_edit
+        width: 85px !important
+        height: 30px !important
+        color: $eiru-color-none !important
+        background: $eiru-color-danger !important
+
+    .oe_form_button_create
+        width: 85px !important
+        height: 30px !important
+        color: $eiru-color-none !important
+        background: $eiru-color-success !important
+
+    .oe_dropdown_toggle
+        width: 85px !important
+        height: 30px !important
+        color: $eiru-color-none !important
+        background: $eiru-color-primary !important
+
+    .oe_list_discard, .oe_form_button_cancel, .oe_list_button_import
+        color: $eiru-color-secondary !important

+ 28 - 0
static/src/sass/backend/_dashboard.sass

@@ -0,0 +1,28 @@
+.grid-stack-item-content
+    &.dashboard
+        border: 1px solid $eiru-color-light
+        border-bottom: 3px solid $eiru-color-primary
+        background-color: $eiru-color-none
+        .widget-title
+            color: $eiru-color-dark
+        .widget-content
+            a
+                font-size: 18pt !important
+                color: $eiru-color-primary
+        .widget-footer
+            text-align: center
+            font-size: 11pt
+            color: $eiru-color-dark
+.dashboard-sale-wrapper
+    background: $eiru-color-none
+    padding: 15px
+    .dashboard-sale-actions
+        img
+            filter: contrast(250%)
+        .new-sale, .new-budget
+            background: $eiru-color-primary
+            &::before
+                background: $eiru-color-primary
+    .dashboard-sale-welcome
+        i
+            color: $eiru-color-primary

+ 67 - 0
static/src/sass/backend/_forms.sass

@@ -0,0 +1,67 @@
+.oe_form
+    header
+        height: 35px
+        background: $eiru-color-none !important
+        border: none !important
+        box-shadow: 1px 0 3px $eiru-color-lightdark
+        button
+            height: 30px
+            padding-left: 5px !important
+            padding-right: 5px !important
+            border-radius: 0 !important
+            border: 1px solid $eiru-color-lightdark !important
+            color: $eiru-color-dark !important
+            background: $eiru-color-none !important
+        ul
+            height: 35px
+            li
+                height: 35px
+                .label
+                    height: 35px
+                    padding-top: 9px !important
+                .arrow
+                    width: 21px !important
+                    height: 35px !important
+                    span
+                        width: 26px !important
+                        height: 26px !important
+                        margin-left: -10 !important
+                        margin-top: 4px !important
+    .oe_form_sheetbg
+        background: none !important
+        border: none !important
+        padding: 15px !important
+        z-index: 0 !important
+        overflow-x: hidden
+        .oe_form_sheet
+            width: 100%
+            max-width: none
+            border: none !important
+            padding: 0 !important
+            box-shadow: none !important
+        .oe_stat_button
+            color: $eiru-color-dark
+            .stat_button_icon
+                color: $eiru-color-primary
+            &:hover
+                color: $eiru-color-none
+                background: $eiru-color-primary
+                .stat_button_icon
+                    color: $eiru-color-none
+        .oe_form_button
+            width: 85px !important
+            height: 30px !important
+            box-shadow: none !important
+            border-radius: 0 !important
+            background: $eiru-color-none
+            &.oe_highlight
+                border: none !important
+                background-color: $eiru-color-danger !important
+        .oe_msg
+            a
+                color: $eiru-color-primary !important
+    .oe_chatter
+        width: 100% !important
+        max-width: none !important
+        a
+            color: $eiru-color-secondary !important

+ 42 - 0
static/src/sass/backend/_header.sass

@@ -0,0 +1,42 @@
+.oe_view_manager_header
+    background: $eiru-color-none !important
+    border-bottom: 1px solid $eiru-color-light !important
+    .oe_view_title
+        color: $eiru-color-dark
+        a
+            color: $eiru-color-secondary !important
+    .oe_searchview
+        box-shadow: none !important
+        width: 450px
+        border:
+            top: none
+            left: none
+            right: none
+            bottom: 1px solid $eiru-color-lightdark
+            radius: 0
+        &.oe_focused
+            border-bottom: 1px solid $eiru-color-primary
+        .oe_searchview_facet
+            border-radius: 0
+            border: 1px solid $eiru-color-lightdark !important
+            background: $eiru-color-primary !important
+            &:focus
+                border-color: $eiru-color-primary !important
+            .oe_facet_category
+                background: $eiru-color-primary
+            .oe_facet_remove
+                color: $eiru-color-primary !important
+                &:hover
+                    color: $eiru-color-none !important
+                    background: $eiru-color-primary !important
+        .oe-autocomplete
+            border-radius: 0 !important
+            li
+                height: 28px !important
+                line-height: 25px !important
+                &.oe-selection-focus
+                    background: $eiru-color-primary !important
+
+
+    .oe_view_manager_switch
+        border-radius: 0 !important

+ 19 - 0
static/src/sass/backend/_kanbans.sass

@@ -0,0 +1,19 @@
+.oe_kanban_view
+    .oe_kanban_column_cards
+        padding: 15px
+    .oe_kanban_image
+        width: 75px !important
+        height: 75px !important
+        border-radius: 50% !important
+    .oe_kanban_details
+        a
+            color: $eiru-color-primary !important
+    .oe_kanban_action_a
+        color: $eiru-color-primary !important
+    .oe_kanban_action_button
+        width: 85px !important
+        height: 30px !important
+        border: 1px solid $eiru-color-lightdark !important
+        border-radius: 0 !important
+        box-shadow: none !important
+        background: $eiru-color-none !important

+ 2 - 0
static/src/sass/backend/_loading.sass

@@ -0,0 +1,2 @@
+.oe_loading
+    border-radius: 0 !important

+ 3 - 0
static/src/sass/backend/_main.sass

@@ -0,0 +1,3 @@
+.oe_view_manager_body
+    margin: 15px
+    box-shadow: 2px 2px 5px $eiru-color-lightdark, -2px -2px 5px $eiru-color-lightdark

+ 58 - 0
static/src/sass/backend/_menubar.sass

@@ -0,0 +1,58 @@
+#oe_main_menu_navbar
+    height: $eiru-navbar-height
+    background-color: $eiru-color-primary !important
+    border: 0
+
+#oe_main_menu_placeholder
+    height: $eiru-navbar-height
+    background-color: $eiru-color-primary !important
+    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26)
+
+.oe_application_menu_placeholder
+    height: $eiru-navbar-height
+    background-color: $eiru-color-primary !important
+    li
+        height: $eiru-navbar-height
+        &.active
+            background-color: $eiru-color-secondary
+            border-bottom: 2px solid $eiru-color-none
+        .oe_menu_toggler, .oe_menu_leaf
+            height: $eiru-navbar-height
+            margin-top: 0 !important
+            line-height: 23px !important
+            padding: 12px 10px !important
+            color: $eiru-color-none !important
+            background-color: transparent !important
+
+.oe_user_menu_placeholder
+    height: $eiru-navbar-height
+    background-color: $eiru-color-primary !important
+    li
+        height: $eiru-navbar-height
+        &.open
+            background-color: $eiru-color-secondary
+        .dropdown-toggle
+            height: $eiru-navbar-height
+            padding-top: 12px !important
+            margin: 0 !important
+            color: $eiru-color-none !important
+            background-color: transparent !important
+        .dropdown-menu
+            li
+                a
+                    height: $eiru-navbar-height
+                    line-height: 34px
+                    transition-duration: 0.3s
+                    &:hover
+                        color: $eiru-color-none
+                        background-color: $eiru-color-secondary
+
+.oe_systray
+    height: $eiru-navbar-height
+    background-color: $eiru-color-primary !important
+    li
+        height: $eiru-navbar-height
+        a
+            line-height: 34px
+            i
+                color: $eiru-color-none

+ 24 - 0
static/src/sass/backend/_messages.sass

@@ -0,0 +1,24 @@
+.oe_mail
+    .oe_msg_left
+        a
+            img
+                border-radius: 50% !important
+    .oe_msg_center
+        .oe_msg_title
+            a
+                color: $eiru-color-primary !important
+        .oe_msg_body
+            .oe_msg_body_short
+                p
+                    b
+                        a
+                            color: $eiru-color-primary !important
+                span
+                    a
+                        color: $eiru-color-primary !important
+
+        .oe_msg_footer
+            .oe_mail_action_author
+                color: $eiru-color-primary !important
+            .oe_msg_vote
+                color: $eiru-color-primary !important

+ 15 - 0
static/src/sass/backend/_modals.sass

@@ -0,0 +1,15 @@
+.modal-dialog
+    .modal-content
+        border-radius: 0 !important
+    .modal-footer
+        footer
+            .oe_highlight
+                width: 120px !important
+                height: 30px !important
+                border: none !important
+                border-radius: 0 !important
+                box-shadow: none !important
+                background: $eiru-color-danger !important
+            .oe_link
+                span
+                    color: $eiru-color-primary !important

+ 53 - 0
static/src/sass/backend/_pos.sass

@@ -0,0 +1,53 @@
+.pos, .purchases
+    .wizard-progress-bar
+        background-color: $eiru-color-primary !important
+        color: $eiru-color-primary !important
+    
+    .wizard-icon-circle
+        &.checked
+            border-color: $eiru-color-primary !important
+
+        .wizard-icon-container
+            background: $eiru-color-primary !important
+
+    .stepTitle
+        &.active
+            color: $eiru-color-primary !important
+
+    .pos-step, .purchase-step
+        .spinner
+            .spinner-rect
+                background: $eiru-color-primary !important
+        .card-grid
+            .add-card
+                i
+                    color: $eiru-color-primary !important
+            .card
+                &.selected-card
+                    border-bottom: 3px solid $eiru-color-primary !important
+                .card-details
+                    background: $eiru-color-primary !important
+
+        .cart
+            .cart-item
+                &:hover
+                    border-bottom: 2px solid $eiru-color-primary
+
+        form
+            .form-actions
+                .form-action
+                    background: $eiru-color-primary
+            .discount-options
+                .discount-button
+                    background: $eiru-color-primary
+                
+        .product-variants
+            .variant-details
+                &:hover
+                    border-bottom: 2px solid $eiru-color-primary
+
+    .wizard-card-footer
+        .wizard-btn
+            background: $eiru-color-primary !important
+            border-color: none !important
+

+ 28 - 0
static/src/sass/backend/_reporting.sass

@@ -0,0 +1,28 @@
+.reporting_view_header
+    background: $eiru-color-none !important
+    border-bottom: 1px solid $eiru-color-light !important
+    h2
+        color: $eiru-color-dark
+
+.report_view
+    padding: 15px
+    box-shadow: 2px 2px 5px $eiru-color-lightdark, -2px -2px 5px $eiru-color-lightdark
+    .reporting_page_header
+        h1
+            font-size: 16pt
+    .report_item
+        border-radius: 0
+        box-shadow: none
+        .report_title
+            h1
+                font-size: 14pt
+        .report_action
+            button
+                width: 100% !important
+                height: 30px
+                background: $eiru-color-danger
+                border-radius: 0
+                border: none
+        &:hover
+            transform: none
+            box-shadow: none

+ 9 - 0
static/src/sass/backend/_searcher.sass

@@ -0,0 +1,9 @@
+.oe_searchview_drawer
+    dt
+        color: $eiru-color-primary !important
+    dd
+        .badge
+            background: $eiru-color-primary !important
+        .oe_searchview_custom_delete
+            &:hover
+                background: $eiru-color-primary !important

+ 38 - 0
static/src/sass/backend/_sidebar.sass

@@ -0,0 +1,38 @@
+.oe_leftbar
+    width: $eiru-sidebar-width !important
+    background: $eiru-color-lighter !important
+    border-right: 1px solid $eiru-color-light !important
+    >div
+        width: $eiru-sidebar-width !important
+        .oe_logo
+            width: 100%
+            height: 120px
+        .oe_secondary_menus_container
+            padding-top: 20px
+            .oe_secondary_menu
+                .oe_secondary_menu_section
+                    color: $eiru-color-dark
+                .oe_secondary_submenu
+                    li
+                        width: 100%
+                        margin: 0 !important
+                        &.active
+                            background-color: $eiru-color-primary !important
+                            a
+                                .badge
+                                    background-color: $eiru-color-none !important
+                        &:hover
+                            background-color: $eiru-color-light
+                        a
+                            width: inherit
+                            height: inherit
+                            line-height: 23px
+                            background-color: transparent !important
+                            .badge
+                                background-color: $eiru-color-primary
+        .oe_footer
+            background: $eiru-color-none !important
+            font-size: 7.5pt
+            a
+                span
+                    color: $eiru-color-primary !important

+ 11 - 0
static/src/sass/backend/_toggler.sass

@@ -0,0 +1,11 @@
+.eiru-toggler
+    width: $eiru-navbar-height
+    height: $eiru-navbar-height
+    text-align: center
+    line-height: 45px
+    &:hover
+        cursor: pointer
+        -webkit-cursor: pointer
+        -moz-cursor: pointer
+    i
+        color: $eiru-color-none

+ 14 - 0
static/src/sass/backend/_trees.sass

@@ -0,0 +1,14 @@
+.oe_list_content
+    thead
+        tr
+            width: 100%
+            height: 47px !important
+            color: $eiru-color-dark
+            background: $eiru-color-none !important
+            th
+                border: none !important
+                input[type="checkbox"]
+                    outline: 0
+                    &::after
+                        border: 2px solid #616161
+                        border-radius: 2px

+ 19 - 0
static/src/sass/backend/theme.sass

@@ -0,0 +1,19 @@
+@import "../variables"
+@import "../body"
+@import "buttons"
+@import "menubar"
+@import "sidebar"
+@import "toggler"
+@import "application"
+@import "header"
+@import "searcher"
+@import "main"
+@import "trees"
+@import "forms"
+@import "modals"
+@import "kanbans"
+@import "messages"
+@import "dashboard"
+@import "reporting"
+@import "loading"
+@import "pos"

+ 19 - 0
static/src/sass/login/_brand.sass

@@ -0,0 +1,19 @@
+.eiru-brand-login
+    width: 200px
+    height: 100px
+    position: absolute
+    bottom: 0
+    right: 0
+    display: flex
+    align-items: center
+    justify-content: center
+    img
+        width: 50px
+        height: 45px
+        filter: contrast(150%)
+    div
+        color: $eiru-color-none
+        padding-left: 5px
+        h2
+            font-size: 20pt
+            margin: 0

+ 41 - 0
static/src/sass/login/_form.sass

@@ -0,0 +1,41 @@
+.oe_single_form
+    background: $eiru-color-primary url(/eiru_theme/static/src/img/background.jpg) right bottom !important
+    &::before
+        content: ''
+        position: fixed
+        top: 0
+        left: 0
+        width: 100%
+        height: 100%
+        background: $eiru-color-primary
+        opacity: 0.3
+    .oe_single_form_container
+        // box-shadow: 2px 2px 3px $eiru-color-lightdark, -2px -2px 3px $eiru-color-lightdark !important
+        box-shadow: none !important
+        border: none !important
+        &.modal-content
+            padding: 20px !important
+            border-radius: 0 !important
+            .oe_single_form_footer
+                font-size: 9pt !important
+                color: $eiru-color-none !important
+            .oe_login_manage_db, .oe_footer_seperator
+                display: none
+
+.oe_login_form
+    .control-label
+        font-size: 10pt
+        color: $eiru-color-dark
+    .form-control
+        border-radius: 0 !important
+    .alert-danger
+        border-radius: 0 !important
+        text-align: center
+    button
+        width: 100%
+        border-radius: 0 !important
+        background-color: $eiru-color-primary
+        border-color: transparent
+        &:hover
+            border-color: transparent !important
+            background-color: $eiru-color-primary !important

+ 4 - 0
static/src/sass/login/theme.sass

@@ -0,0 +1,4 @@
+@import "../variables"
+@import "../body"
+@import "form"
+@import "brand"

+ 10 - 0
views/eiru_assets_backend.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data>
+        <template id="eiru_theme.assets_backend" name="Eiru Assets Backend" inherit_id="web.assets_backend">
+            <xpath expr="." position="inside">
+                <link rel="stylesheet" href="/eiru_theme/static/src/css/backend/theme.css" />
+            </xpath>
+        </template>
+    </data>
+</openerp>

+ 34 - 0
views/eiru_web_layout.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data>
+        <template id="eiru_theme.eiru_web_layout" name="Eiru Layout Assets" inherit_id="web.layout">
+            <title position="replace">
+                <title>Eiru Software</title>
+            </title>
+
+            <link rel="shortcut icon" position="replace">
+                <link rel="apple-touch-icon" sizes="57x57" href="/eiru_theme/static/src/favicons/apple-icon-57x57.png" />
+                <link rel="apple-touch-icon" sizes="60x60" href="/eiru_theme/static/src/favicons/apple-icon-60x60.png" />
+                <link rel="apple-touch-icon" sizes="72x72" href="/eiru_theme/static/src/favicons/apple-icon-72x72.png" />
+                <link rel="apple-touch-icon" sizes="76x76" href="/eiru_theme/static/src/favicons/apple-icon-76x76.png" />
+                <link rel="apple-touch-icon" sizes="114x114" href="/eiru_theme/static/src/favicons/apple-icon-114x114.png" />
+                <link rel="apple-touch-icon" sizes="120x120" href="/eiru_theme/static/src/favicons/apple-icon-120x120.png" />
+                <link rel="apple-touch-icon" sizes="144x144" href="/eiru_theme/static/src/favicons/apple-icon-144x144.png" />
+                <link rel="apple-touch-icon" sizes="152x152" href="/eiru_theme/static/src/favicons/apple-icon-152x152.png" />
+                <link rel="apple-touch-icon" sizes="180x180" href="/eiru_theme/static/src/favicons/apple-icon-180x180.png" />
+                <link rel="icon" type="image/png" sizes="192x192"  href="/eiru_theme/static/src/favicons/android-icon-192x192.png" />
+                <link rel="icon" type="image/png" sizes="32x32" href="/eiru_theme/static/src/favicons/favicon-32x32.png" />
+                <link rel="icon" type="image/png" sizes="96x96" href="/eiru_theme/static/src/favicons/favicon-96x96.png" />
+                <link rel="icon" type="image/png" sizes="16x16" href="/eiru_theme/static/src/favicons/favicon-16x16.png" />
+                <link rel="manifest" href="/manifest.json" />
+                <meta name="msapplication-TileColor" content="#ffffff" />
+                <meta name="msapplication-TileImage" content="/ms-icon-144x144.png" />
+                <meta name="theme-color" content="#ffffff" />
+            </link>
+
+            <xpath expr="//body" position="attributes">
+                <attribute name="id">particles-js</attribute>
+            </xpath>
+        </template>
+    </data>
+</openerp>

+ 21 - 0
views/eiru_web_login.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data>
+        <template id="eiru_theme.eiru_web_login" name="Eiru Login Defaults" inherit_id="web.login">
+            <xpath expr="//label[@for='login']" position="replace">
+                <label for="login" class="control-label">Usuario</label>
+            </xpath>
+            <xpath expr="//label[@for='password']" position="replace">
+                <label for="login" class="control-label">Contraseña</label>
+            </xpath>
+            <xpath expr="//button[@type='submit']" position="replace">
+                <button type="submit" class="btn btn-primary">Iniciar Sesión</button>
+            </xpath>
+            <xpath expr="//p[@class='alert alert-danger']" position="replace">
+                <p class="alert alert-danger" t-if="error">
+                    Credenciales no válidas
+                </p>
+            </xpath>
+        </template>
+    </data>
+</openerp>

+ 25 - 0
views/eiru_web_login_layout.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data>
+        <template id="eiru_theme.eiru_web_login_layout" name="Eiru Login Assets" inherit_id="web.login_layout">
+            <xpath expr="//link[last()]" position="after">
+                <link rel="stylesheet" href="/eiru_theme/static/src/css/login/theme.css" />
+            </xpath>
+            <xpath expr="." position="inside">
+                <div class="eiru-brand-login">
+                    <img class="animated bounceInLeft" src="/eiru_theme/static/src/img/logo.png" />
+                    <div class="animated bounceInDown">
+                        <h2>EIRU</h2>
+                    </div>
+                </div>
+                <script src="/eiru_theme/static/src/lib/particles.js" />
+                <script src="/eiru_theme/static/src/js/login.js" />
+            </xpath>
+            <xpath expr="//div[@class='oe_single_form_container modal-content']" position="attributes">
+                <attribute name="class">oe_single_form_container modal-content animated bounce</attribute>
+            </xpath>
+            <xpath expr="//div[@class='oe_single_form_footer']/a" position="replace">
+            </xpath>
+        </template>
+    </data>
+</openerp>

+ 9 - 0
views/eiru_web_menu_secondary.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data>
+        <template id="eiru_theme.eiru_web_menu_secondary" name="Eiru Web Secondary" inherit_id="web.menu_secondary">
+            <xpath expr="//div[@class='oe_footer']" position="replace">
+            </xpath>
+        </template>
+    </data>
+</openerp>