diff options
| author | Jules Laplace <jules@okfoc.us> | 2016-10-28 18:07:56 -0400 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2016-10-28 18:07:56 -0400 |
| commit | a9c9d6adf470d0966e6c6bef0803e298fd2d4117 (patch) | |
| tree | 6ccec2a448992a5f43226532051a6df09afbc203 | |
| parent | 343b0b3dc5bb7dbe762182a486e63a4aff6ef8fc (diff) | |
| parent | 9e7bacd46c1e5d0e1c24433690d421ab3f3a11f2 (diff) | |
merge
213 files changed, 12021 insertions, 2283 deletions
@@ -34,3 +34,6 @@ config.json app.concat.js app.min.js +static.concat.js +static.min.js + diff --git a/Gruntfile.js b/Gruntfile.js index f62cc82..988d040 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -8,16 +8,192 @@ module.exports = function(grunt) { }, js: { src: [ + "/assets/javascripts/vendor/bower_components/jquery/dist/jquery.min.js" + "/assets/javascripts/vendor/bower_components/lodash/lodash.min.js", + "/assets/javascripts/vendor/bower_components/momentjs/min/moment.min.js", + "/assets/javascripts/vendor/bower_components/fiber/src/fiber.min.js", + "/assets/javascripts/vendor/bower_components/hidpi-canvas/dist/hidpi-canvas.js", + "/assets/javascripts/vendor/bower_components/marked/lib/marked.js", + "/assets/javascripts/vendor/tube.js", + "/assets/javascripts/vendor/loader.js", + "/assets/javascripts/vendor/polyfill.js", + "/assets/javascripts/vendor/sha1.js", + "/assets/javascripts/vendor/dataUriToBlob.js", + "/assets/javascripts/vendor/froogaloop.js", + "/assets/javascripts/util.js", + + "/assets/javascripts/mx/mx.js", + + "/assets/javascripts/mx/extensions/mx.scene.js", + "/assets/javascripts/mx/extensions/mx.movements.js", + "/assets/javascripts/mx/extensions/mx.movementsMobile.js", + "/assets/javascripts/mx/extensions/mx.orbitCamera.js", + + "/assets/javascripts/mx/primitives/mx.image.js", + "/assets/javascripts/mx/primitives/mx.text.js", + "/assets/javascripts/mx/primitives/mx.video.js", + "/assets/javascripts/mx/primitives/mx.youtube.js", + "/assets/javascripts/mx/primitives/mx.vimeo.js", + "/assets/javascripts/mx/primitives/mx.soundcloud.js", + "/assets/javascripts/mx/primitives/mx.grid.js", + "/assets/javascripts/mx/primitives/mx.point.js", + "/assets/javascripts/mx/primitives/mx.polyline.js", + + "/assets/javascripts/rectangles/_env.js", + + "/assets/javascripts/rectangles/util/constants.js", + "/assets/javascripts/rectangles/util/colors.js", + "/assets/javascripts/rectangles/util/coords.js", + "/assets/javascripts/rectangles/util/debug.js", + "/assets/javascripts/rectangles/util/keys.js", + "/assets/javascripts/rectangles/util/measurement.js", + "/assets/javascripts/rectangles/util/minotaur.js", + "/assets/javascripts/rectangles/util/mouse.js", + "/assets/javascripts/rectangles/util/permissions.js", + "/assets/javascripts/rectangles/util/sort.js", + "/assets/javascripts/rectangles/util/uid.js", + "/assets/javascripts/rectangles/util/undostack.js", + "/assets/javascripts/rectangles/util/wheel.js", + + "/assets/javascripts/rectangles/models/vec2.js", + "/assets/javascripts/rectangles/models/vec3.js", + "/assets/javascripts/rectangles/models/rect.js", + "/assets/javascripts/rectangles/models/surface.js", + "/assets/javascripts/rectangles/models/tree.js", + "/assets/javascripts/rectangles/models/room.js", + "/assets/javascripts/rectangles/models/wall.js", + "/assets/javascripts/rectangles/models/floor.js", + + "/assets/javascripts/rectangles/engine/rooms/_rooms.js", + "/assets/javascripts/rectangles/engine/rooms/_walls.js", + "/assets/javascripts/rectangles/engine/rooms/builder.js", + "/assets/javascripts/rectangles/engine/rooms/clipper.js", + "/assets/javascripts/rectangles/engine/rooms/grouper.js", + "/assets/javascripts/rectangles/engine/rooms/mover.js", + + "/assets/javascripts/rectangles/engine/scenery/_scenery.js", + "/assets/javascripts/rectangles/engine/scenery/move.js", + "/assets/javascripts/rectangles/engine/scenery/resize.js", + "/assets/javascripts/rectangles/engine/scenery/randomize.js", + "/assets/javascripts/rectangles/engine/scenery/sound.js", + "/assets/javascripts/rectangles/engine/scenery/undo.js", + "/assets/javascripts/rectangles/engine/scenery/types/_object.js", + "/assets/javascripts/rectangles/engine/scenery/types/audio.js", + "/assets/javascripts/rectangles/engine/scenery/types/image.js", + "/assets/javascripts/rectangles/engine/scenery/types/text.js", + "/assets/javascripts/rectangles/engine/scenery/types/video.js", + + "/assets/javascripts/rectangles/engine/sculpture/_sculpture.js", + "/assets/javascripts/rectangles/engine/sculpture/move.js", + "/assets/javascripts/rectangles/engine/sculpture/resize.js", + "/assets/javascripts/rectangles/engine/sculpture/types/_object.js", + "/assets/javascripts/rectangles/engine/sculpture/types/image.js", + + "/assets/javascripts/rectangles/engine/shapes/polyline.js", + "/assets/javascripts/rectangles/engine/shapes/ortho.js", + "/assets/javascripts/rectangles/engine/shapes/shapelist.js", + "/assets/javascripts/rectangles/engine/shapes/regionlist.js", + + "/assets/javascripts/rectangles/engine/map/_map.js", + "/assets/javascripts/rectangles/engine/map/draw.js", + "/assets/javascripts/rectangles/engine/map/ui/editor.js", + "/assets/javascripts/rectangles/engine/map/ui/minimap.js", + "/assets/javascripts/rectangles/engine/map/ui/ortho.js", + "/assets/javascripts/rectangles/engine/map/tools/_base.js", + "/assets/javascripts/rectangles/engine/map/tools/arrow.js", + "/assets/javascripts/rectangles/engine/map/tools/line.js", + "/assets/javascripts/rectangles/engine/map/tools/eraser.js", + "/assets/javascripts/rectangles/engine/map/tools/ortho.js", + "/assets/javascripts/rectangles/engine/map/tools/polyline.js", + "/assets/javascripts/rectangles/engine/map/tools/position.js", + "/assets/javascripts/rectangles/engine/map/tools/start.js", + + "/assets/javascripts/ui/lib/View.js", + "/assets/javascripts/ui/lib/Router.js", + "/assets/javascripts/ui/lib/ModalView.js", + "/assets/javascripts/ui/lib/FormView.js", + "/assets/javascripts/ui/lib/UploadView.js", + "/assets/javascripts/ui/lib/AnimatedView.js", + "/assets/javascripts/ui/lib/ToggleableView.js", + "/assets/javascripts/ui/lib/AlertModal.js", + "/assets/javascripts/ui/lib/ConfirmModal.js", + "/assets/javascripts/ui/lib/ErrorModal.js", + "/assets/javascripts/ui/lib/Parser.js", + "/assets/javascripts/ui/lib/LabColorPicker.js", + + "/assets/javascripts/ui/site/SignInModal.js", + "/assets/javascripts/ui/site/SignUpModal.js", + "/assets/javascripts/ui/site/UsernameTaken.js", + "/assets/javascripts/ui/site/PasswordForgot.js", + "/assets/javascripts/ui/site/PasswordReset.js", + "/assets/javascripts/ui/site/LayoutsIndex.js", + "/assets/javascripts/ui/site/LayoutsModal.js", + "/assets/javascripts/ui/site/NewProjectModal.js", + "/assets/javascripts/ui/site/EditProjectModal.js", + "/assets/javascripts/ui/site/EditProfileModal.js", + "/assets/javascripts/ui/site/EditSubscriptionModal.js", + "/assets/javascripts/ui/site/DocumentModal.js", + + "/assets/javascripts/ui/site/HomeView.js", + "/assets/javascripts/ui/site/ProfileView.js", + "/assets/javascripts/ui/site/ProjectList.js", + + "/assets/javascripts/ui/builder/BuilderView.js", + "/assets/javascripts/ui/builder/BuilderSettings.js", + "/assets/javascripts/ui/builder/BuilderToolbar.js", + "/assets/javascripts/ui/builder/BuilderInfo.js", + + "/assets/javascripts/ui/blueprint/BlueprintView.js", + "/assets/javascripts/ui/blueprint/BlueprintInfo.js", + "/assets/javascripts/ui/blueprint/BlueprintSettings.js", + "/assets/javascripts/ui/blueprint/BlueprintEditor.js", + "/assets/javascripts/ui/blueprint/BlueprintScaler.js", + "/assets/javascripts/ui/blueprint/BlueprintToolbar.js", + "/assets/javascripts/ui/blueprint/BlueprintUploader.js", + "/assets/javascripts/ui/blueprint/BlueprintNotice.js", + + "/assets/javascripts/ui/editor/EditorView.js", + "/assets/javascripts/ui/editor/EditorSettings.js", + "/assets/javascripts/ui/editor/EditorToolbar.js", + "/assets/javascripts/ui/editor/HelpCursor.js", + "/assets/javascripts/ui/editor/ColorControl.js", + "/assets/javascripts/ui/editor/Collaborators.js", + "/assets/javascripts/ui/editor/MediaEditor.js", + "/assets/javascripts/ui/editor/MediaTumblr.js", + "/assets/javascripts/ui/editor/MediaUpload.js", + "/assets/javascripts/ui/editor/MediaViewer.js", + "/assets/javascripts/ui/editor/Presets.js", + "/assets/javascripts/ui/editor/SculptureEditor.js", + "/assets/javascripts/ui/editor/TextEditor.js", + "/assets/javascripts/ui/editor/WallpaperPicker.js", + + "/assets/javascripts/ui/reader/ReaderView.js", + "/assets/javascripts/ui/reader/ShareView.js", + "/assets/javascripts/ui/reader/EmbedView.js", + "/assets/javascripts/ui/reader/MediaPlayer.js", + "/assets/javascripts/ui/reader/Tracker.js", + + "/assets/javascripts/ui/_router.js", + + "/assets/javascripts/app.js", + "/assets/javascripts/defaults.js", + ], + dest: 'public/assets/javascripts/app.concat.js', + }, + + // this builds a static version of the vvalls code, suitable for embedding + // in another website. see assets/test/static.html + 'static': { + src: [ "public/assets/javascripts/vendor/bower_components/jquery/dist/jquery.min.js", - "public/assets/javascripts/vendor/bower_components/lodash/dist/lodash.min.js", + "public/assets/javascripts/vendor/bower_components/lodash/lodash.min.js", "public/assets/javascripts/vendor/bower_components/momentjs/min/moment.min.js", "public/assets/javascripts/vendor/bower_components/fiber/src/fiber.min.js", "public/assets/javascripts/vendor/bower_components/marked/lib/marked.js", + "public/assets/javascripts/vendor/bower_components/hidpi-canvas/dist/hidpi-canvas.js", "public/assets/javascripts/vendor/tube.js", "public/assets/javascripts/vendor/loader.js", "public/assets/javascripts/vendor/polyfill.js", - "public/assets/javascripts/vendor/sha1.js", - "public/assets/javascripts/vendor/dataUriToBlob.js", "public/assets/javascripts/vendor/froogaloop.js", "public/assets/javascripts/util.js", @@ -31,6 +207,7 @@ module.exports = function(grunt) { "public/assets/javascripts/mx/primitives/mx.youtube.js", "public/assets/javascripts/mx/primitives/mx.vimeo.js", "public/assets/javascripts/mx/primitives/mx.soundcloud.js", + "public/assets/javascripts/mx/primitives/mx.grid.js", "public/assets/javascripts/rectangles/_env.js", @@ -68,6 +245,7 @@ module.exports = function(grunt) { "public/assets/javascripts/rectangles/engine/scenery/move.js", "public/assets/javascripts/rectangles/engine/scenery/resize.js", "public/assets/javascripts/rectangles/engine/scenery/randomize.js", + "public/assets/javascripts/rectangles/engine/scenery/sound.js", "public/assets/javascripts/rectangles/engine/scenery/undo.js", "public/assets/javascripts/rectangles/engine/scenery/types/_object.js", "public/assets/javascripts/rectangles/engine/scenery/types/image.js", @@ -75,54 +253,20 @@ module.exports = function(grunt) { "public/assets/javascripts/rectangles/engine/scenery/types/video.js", "public/assets/javascripts/rectangles/engine/scenery/types/audio.js", + "public/assets/javascripts/rectangles/engine/sculpture/_sculpture.js", + "public/assets/javascripts/rectangles/engine/sculpture/move.js", + "public/assets/javascripts/rectangles/engine/sculpture/resize.js", + "public/assets/javascripts/rectangles/engine/sculpture/types/_object.js", + "public/assets/javascripts/rectangles/engine/sculpture/types/image.js", + "public/assets/javascripts/rectangles/engine/map/_map.js", - "public/assets/javascripts/rectangles/engine/map/ui_editor.js", - "public/assets/javascripts/rectangles/engine/map/ui_minimap.js", + "public/assets/javascripts/rectangles/engine/map/ui/editor.js", + "public/assets/javascripts/rectangles/engine/map/ui/minimap.js", "public/assets/javascripts/rectangles/engine/map/draw.js", "public/assets/javascripts/ui/lib/View.js", "public/assets/javascripts/ui/lib/Router.js", "public/assets/javascripts/ui/lib/ModalView.js", - "public/assets/javascripts/ui/lib/FormView.js", - "public/assets/javascripts/ui/lib/UploadView.js", - "public/assets/javascripts/ui/lib/AlertModal.js", - "public/assets/javascripts/ui/lib/ConfirmModal.js", - "public/assets/javascripts/ui/lib/ErrorModal.js", - "public/assets/javascripts/ui/lib/Parser.js", - "public/assets/javascripts/ui/lib/LabColorPicker.js", - - "public/assets/javascripts/ui/site/SignInModal.js", - "public/assets/javascripts/ui/site/SignUpModal.js", - "public/assets/javascripts/ui/site/UsernameTaken.js", - "public/assets/javascripts/ui/site/PasswordForgot.js", - "public/assets/javascripts/ui/site/PasswordReset.js", - "public/assets/javascripts/ui/site/LayoutsModal.js", - "public/assets/javascripts/ui/site/EditProjectModal.js", - "public/assets/javascripts/ui/site/EditProfileModal.js", - "public/assets/javascripts/ui/site/DocumentModal.js", - - "public/assets/javascripts/ui/site/HomeView.js", - "public/assets/javascripts/ui/site/ProfileView.js", - "public/assets/javascripts/ui/site/ProjectList.js", - - "public/assets/javascripts/ui/builder/BuilderView.js", - "public/assets/javascripts/ui/builder/BuilderSettings.js", - "public/assets/javascripts/ui/builder/BuilderToolbar.js", - "public/assets/javascripts/ui/builder/BuilderInfo.js", - - "public/assets/javascripts/ui/editor/EditorView.js", - "public/assets/javascripts/ui/editor/EditorSettings.js", - "public/assets/javascripts/ui/editor/EditorToolbar.js", - "public/assets/javascripts/ui/editor/HelpCursor.js", - "public/assets/javascripts/ui/editor/ColorControl.js", - "public/assets/javascripts/ui/editor/Collaborators.js", - "public/assets/javascripts/ui/editor/MediaEditor.js", - "public/assets/javascripts/ui/editor/MediaTumblr.js", - "public/assets/javascripts/ui/editor/MediaUpload.js", - "public/assets/javascripts/ui/editor/MediaViewer.js", - "public/assets/javascripts/ui/editor/Presets.js", - "public/assets/javascripts/ui/editor/TextEditor.js", - "public/assets/javascripts/ui/editor/WallpaperPicker.js", "public/assets/javascripts/ui/reader/ReaderView.js", "public/assets/javascripts/ui/reader/ShareView.js", @@ -130,35 +274,66 @@ module.exports = function(grunt) { "public/assets/javascripts/ui/reader/MediaPlayer.js", "public/assets/javascripts/ui/reader/Tracker.js", - "public/assets/javascripts/ui/_router.js", + "public/assets/javascripts/ui/reader/_router.js", "public/assets/javascripts/app.js", "public/assets/javascripts/defaults.js", ], - dest: 'public/assets/javascripts/app.concat.js', + dest: 'public/assets/javascripts/static.concat.js', } + + }, + copy: { + concat: { + files: [ + { + src: 'public/assets/javascripts/app.concat.js', + dest: 'public/assets/javascripts/app.min.js', + }, + ] + }, + 'static': { + files: [ + { + src: 'public/assets/javascripts/static.concat.js', + dest: 'public/assets/javascripts/static.min.js', + }, + ] + }, + }, uglify: { options: { - banner: '/* vvalls by okfocus 2015 */\n' + banner: '/* vvalls by okfocus 2016 */\n' }, js: { src: 'public/assets/javascripts/app.concat.js', dest: 'public/assets/javascripts/app.min.js', + }, + 'static': { + src: 'public/assets/javascripts/static.concat.js', + dest: 'public/assets/javascripts/static.min.js', } }, clean: { - release: ["public/assets/javascripts/app.concat.js"], + release: [ + "public/assets/javascripts/static.concat.js", + "public/assets/javascripts/app.concat.js", + ], } }); // Load tasks that we'll be using grunt.loadNpmTasks('grunt-contrib-concat'); + grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-clean'); // Default task(s). - grunt.registerTask('js', ['concat:js', 'uglify:js', 'clean:release']); - grunt.registerTask('default', ['js']); + grunt.registerTask('js', ['concat:js', 'uglify:js', 'clean:release']); + grunt.registerTask('js-test', ['concat:js', 'copy:concat']); + grunt.registerTask('static', ['concat:static', 'uglify:static', 'clean:release']); + grunt.registerTask('static-test', ['concat:static', 'copy:static']); + grunt.registerTask('default', ['js']); }; @@ -1 +1,2 @@ -web: node server
\ No newline at end of file +web: node server +webhook: node server/lib/webhook
\ No newline at end of file @@ -19,3 +19,20 @@ vvalls | | .' | |/ | | \| | `. | | +------+' +------+ +------+ +------+ `+------+ ``` + +Installing VValls +================= + +1) Install mongodb, nodejs, npm (probably comes with node) and bower +2) `git clone git@github.com:okfocus/vvalls.git` +3) `cd vvalls ; git checkout subscriptions` +4) `npm install` +5) `bower install` +6) `cp config.json.example config.json` +7) Start the mongod server (if it isn't running already) +8) `node server` + +Server will be running on http://lvh.me:3000/ + +To give yourself superuser access, visit http://lvh.me:3000/staff/authorize (development mode only) + @@ -9,6 +9,7 @@ "fiber": "", "jquery-jsonview": "1.2.0", "prefixfree": "", - "marked": "0.3.2" + "marked": "0.3.2", + "hidpi-canvas": "git://github.com/julescarbon/hidpi-canvas-polyfill.git#master" } } diff --git a/config.json.example b/config.json.example index 6028021..df4b86e 100644 --- a/config.json.example +++ b/config.json.example @@ -1,9 +1,10 @@ { - "host": "lvh.me:3000", - "hostName": "lvh.me", - "port": 3000, - "socketPort": 1337, + "host": "lvh.me:3000", + "hostName": "lvh.me", + "port": 3000, + "socketPort": 1337, + "webhookPort": 5000, "databaseHost": "lvh.me", - "pageSize": 10, - "env": { "development": 1 } + "env": { "development": 1 }, + "basicAuth": { "user": "vv", "pass": "ok" } } diff --git a/package.json b/package.json index adefb82..b055b9e 100644 --- a/package.json +++ b/package.json @@ -6,41 +6,45 @@ "url": "git://github.com/okfocus/vvalls.git" }, "dependencies": { - "express": "~3.4.8", - "monk": "~0.7.1", - "socket.io": "~0.9.16", + "body-parser": "1.3.0", "connect-mongo": "~0.4.1", - "passport": "~0.2.0", - "passport-local": "~1.0.0", - "passport-twitter": "~1.0.2", - "passport-facebook": "~1.0.3", - "passport.socketio": "~3.0.1", - "node-restful": "~0.1.14", "ejs": "^0.8.8", - "useful-string": "0.0.1", + "emailjs": "~0.3.6", + "express": "^3.4.8", "express-subdomain-handler": "~0.1.0", "express-subdomains": "0.0.5", - "lodash": "~2.4.1", - "mongoose": "~3.8.8", - "mongoose-unique-validator": "~0.3.0", - "mongoose-lifecycle": "~1.0.0", + "express-xml-bodyparser": "0.0.6", + "html-entities": "~1.0.10", + "inspect": "0.0.2", + "intro.js": "^0.9.0", + "js2xml": "", "knox": "~0.8.10", + "lodash": "~2.4.1", + "marked": "~0.3.2", + "method-override": "^2.3.6", "moment": "~2.6.0", - "html-entities": "~1.0.10", + "mongoose": "^4.2.8", + "mongoose-lifecycle": "", + "mongoose-unique-validator": "", "multer": "~0.1.0", - "body-parser": "1.3.0", - "marked": "~0.3.2", - "emailjs": "~0.3.6", - "intro.js": "^0.9.0" + "node-recurly": "julescarbon/node-recurly", + "passport": "~0.2.0", + "passport-facebook": "~1.0.3", + "passport-local": "~1.0.0", + "passport-twitter": "~1.0.2", + "passport.socketio": "~3.0.1", + "socket.io": "~0.9.16", + "useful-string": "0.0.1", + "xml2js": "" }, "devDependencies": { - "grunt": "~0.4.1", - "grunt-contrib-concat": "~0.3.0", - "grunt-contrib-uglify": "~0.2.5", - "grunt-contrib-watch": "~0.5.3", - "grunt-contrib-clean": "~0.5.0", - "grunt-contrib-copy": "~0.5.0", - "grunt-dentist": "~0.3.4", - "mocha": "~1.20.1" + "grunt": "", + "grunt-contrib-concat": "", + "grunt-contrib-uglify": "", + "grunt-contrib-watch": "", + "grunt-contrib-clean": "", + "grunt-contrib-copy": "", + "grunt-dentist": "", + "mocha": "" } } diff --git a/public/assets/fonts/ionicons.eot b/public/assets/fonts/ionicons.eot Binary files differindex 52b1e57..92a3f20 100755 --- a/public/assets/fonts/ionicons.eot +++ b/public/assets/fonts/ionicons.eot diff --git a/public/assets/fonts/ionicons.svg b/public/assets/fonts/ionicons.svg index 5c8c909..49fc8f3 100755 --- a/public/assets/fonts/ionicons.svg +++ b/public/assets/fonts/ionicons.svg @@ -1,11 +1,11 @@ <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > <!-- -2014-6-16: Created. +2014-12-4: Created. --> <svg xmlns="http://www.w3.org/2000/svg"> <metadata> -Created by FontForge 20120731 at Mon Jun 16 14:44:31 2014 +Created by FontForge 20120731 at Thu Dec 4 09:51:48 2014 By Adam Bradley Created by Adam Bradley with FontForge 2.0 (http://fontforge.sf.net) </metadata> @@ -19,189 +19,307 @@ Created by Adam Bradley with FontForge 2.0 (http://fontforge.sf.net) panose-1="2 0 6 3 0 0 0 0 0 0" ascent="448" descent="-64" - bbox="-0.5 -64.0026 512.487 448" + bbox="-0.54049 -64 512.487 448" underline-thickness="25.6" underline-position="-51.2" - unicode-range="U+F100-F358" + unicode-range="U+F100-F4F7" /> <missing-glyph /> <glyph glyph-name="ion-alert-circled" unicode="" d="M445 26c3 -5 5 -13 2 -18s-8 -8 -14 -8h-418c-6 0 -11 3 -14 8s-1 13 2 18l207 349c3 5 8 9 14 9s11 -4 14 -9zM256 48v48h-64v-48h64zM256 128v144h-64v-144h64z" /> <glyph glyph-name="ion-alert" unicode="" horiz-adv-x="128" d="M128 -32h-128v96h128v-96zM112 128h-96l-16 288h128z" /> - <glyph glyph-name="ion-android-add-contact" unicode="" horiz-adv-x="512" -d="M258 174c59 -18 95 -58 108 -110h-366c13 52 49 92 108 110c22 -13 48 -20 75 -20s53 7 75 20zM183 184c-73 0 -132 59 -132 132s59 132 132 132s132 -59 132 -132s-59 -132 -132 -132zM276 280h-185c14 -37 50 -63 92 -63s79 26 93 63zM512 48v-32h-80v-80h-32v80h-80 -v32h80v80h32v-80h80z" /> - <glyph glyph-name="ion-android-add" unicode="" horiz-adv-x="512" -d="M512 224v-64h-224v-224h-64v224h-224v64h224v224h64v-224h224z" /> - <glyph glyph-name="ion-android-alarm" unicode="" horiz-adv-x="512" -d="M256 400c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM392 40c36 36 56 85 56 136s-20 100 -56 136s-85 56 -136 56s-100 -20 -136 -56s-56 -85 -56 -136s20 -100 56 -136s85 -56 136 -56s100 20 136 56zM224 160l16 176h24l8 -160 -l80 -96l-16 -16zM388 432c53 -27 97 -71 124 -124l-28 -15c-12 24 -28 45 -47 64s-40 35 -64 47l15 28v0zM124 432v0l15 -28c-24 -12 -45 -28 -64 -47s-35 -40 -47 -64l-28 15c27 53 71 97 124 124z" /> - <glyph glyph-name="ion-android-archive" unicode="" horiz-adv-x="512" -d="M432 400l80 -64v-352h-512v352l80 64h352zM256 64l112 128h-56v56h-112v-56h-56zM36 336h440l-60 48h-320z" /> - <glyph glyph-name="ion-android-arrow-back" unicode="" horiz-adv-x="256" -d="M256 448l-144 -256l144 -256h-112l-144 256l144 256h112z" /> - <glyph glyph-name="ion-android-arrow-down-left" unicode="" horiz-adv-x="480" -d="M0 256h80v-167l343 343l57 -57l-343 -343h167v-80h-304v304z" /> - <glyph glyph-name="ion-android-arrow-down-right" unicode="" horiz-adv-x="480" -d="M480 256v-304h-304v80h167l-343 343l57 57l343 -343v167h80z" /> - <glyph glyph-name="ion-android-arrow-forward" unicode="" horiz-adv-x="256" -d="M0 448h112l144 -256l-144 -256h-112l144 256z" /> - <glyph glyph-name="ion-android-arrow-up-left" unicode="" horiz-adv-x="480" -d="M304 432v-80h-167l343 -343l-57 -57l-343 343v-167h-80v304h304z" /> - <glyph glyph-name="ion-android-arrow-up-right" unicode="" horiz-adv-x="480" -d="M176 432h304v-304h-80v167l-343 -343l-57 57l343 343h-167v80z" /> - <glyph glyph-name="ion-android-battery" unicode="" horiz-adv-x="256" -d="M192 352h64v-32v-352h-256v352v32h64v32v32h128v-32v-32zM224 224v96h-64v64h-64v-64h-64v-96h192z" /> - <glyph glyph-name="ion-android-book" unicode="" horiz-adv-x="512" -d="M0 448l176 -112v-384l-176 144v352zM512 448v-352l-176 -144v384zM208 -64v384h96v-384h-96zM426 442c17 0 38 -2 38 -2l-160 -96h-48h-48l-160 96s21 2 38 2s54 1 106 -26s64 -44 64 -44s12 17 64 44s89 26 106 26z" /> - <glyph glyph-name="ion-android-calendar" unicode="" horiz-adv-x="512" -d="M502 416c6 0 10 -4 10 -10v-460c0 -6 -4 -10 -10 -10h-492c-6 0 -10 4 -10 10v460c0 6 4 10 10 10h102v32h64v-32h160v32h64v-32h102zM480 -32v416h-80v-32h-64v32h-160v-32h-64v32h-80v-416h448z" /> - <glyph glyph-name="ion-android-call" unicode="" horiz-adv-x="512" -d="M451 98c38 -28 56 -46 60 -62c4 -19 -7 -26 -40 -64c-32 -37 -61 -36 -84 -36s-61 12 -121 48c-22 14 -49 33 -74 54c-15 12 -35 30 -52 48c-12 12 -24 25 -32 35c-21 25 -40 52 -54 74c-36 60 -54 105 -54 128s-1 52 36 84c38 33 45 44 64 40c16 -4 34 -23 62 -60 -s46 -64 40 -76c-8 -15 -25 -23 -56 -39c-11 -6 -32 -18 -28 -28c5 -13 28 -55 81 -109l13 -13v0c48 -44 84 -63 96 -68c10 -4 22 17 28 28c16 31 24 48 39 56c12 6 39 -12 76 -40zM417 353c-31 31 -71 49 -113 52v43c112 -7 201 -96 208 -208h-43c-3 42 -21 82 -52 113z -M304 358c57 -14 103 -61 117 -118h-44c-12 34 -39 61 -73 73v45z" /> - <glyph glyph-name="ion-android-camera" unicode="" horiz-adv-x="512" -d="M96 368l-80 -32v48h80v-16zM336 352h176v-352h-512v304l128 48h48v48h32h96h32v-48zM256 48c71 0 128 57 128 128s-57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128zM156 176c0 67 33 100 100 100s100 -33 100 -100s-33 -100 -100 -100s-100 33 -100 100z" /> - <glyph glyph-name="ion-android-chat" unicode="" horiz-adv-x="480" -d="M224 448c141 0 256 -115 256 -256s-115 -256 -256 -256v64c-124 0 -224 100 -224 224s100 224 224 224v0zM208 246v48c0 6 -4 10 -10 10h-92c-6 0 -10 -4 -10 -10v-108c0 -6 4 -10 10 -10h70v-16c0 -9 -7 -16 -16 -16v-32c26 0 48 22 48 48v26v60zM384 246v48 -c0 6 -4 10 -10 10h-92c-6 0 -10 -4 -10 -10v-108c0 -6 4 -10 10 -10h70v-16c0 -9 -7 -16 -16 -16v-32c26 0 48 22 48 48v26v60z" /> - <glyph glyph-name="ion-android-checkmark" unicode="" horiz-adv-x="512" -d="M176 -16l-176 176l80 83l112 -107l248 248l72 -72z" /> - <glyph glyph-name="ion-android-clock" unicode="" -d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM360 56c36 36 56 85 56 136s-20 100 -56 136s-85 56 -136 56s-100 -20 -136 -56s-56 -85 -56 -136s20 -100 56 -136s85 -56 136 -56s100 20 136 56zM192 176l16 176h24l8 -160 -l80 -96l-16 -16z" /> - <glyph glyph-name="ion-android-close" unicode="" horiz-adv-x="407" -d="M407 350l-158 -158l158 -158l-45 -46l-158 159l-159 -159l-45 46l158 158l-158 158l45 46l159 -159l158 159z" /> - <glyph glyph-name="ion-android-contact" unicode="" horiz-adv-x="488" -d="M344 82c78 -24 126 -77 144 -146h-488c18 69 66 122 144 146c30 -17 64 -26 100 -26s70 9 100 26zM244 448c97 0 176 -79 176 -176s-79 -176 -176 -176s-176 79 -176 176s79 176 176 176zM244 140c56 0 104 35 123 84h-246c19 -49 67 -84 123 -84z" /> - <glyph glyph-name="ion-android-contacts" unicode="" horiz-adv-x="512" -d="M237 85c54 -16 87 -53 99 -101h-336c12 47 45 85 99 101c20 -12 44 -19 69 -19s49 7 69 19zM168 336c67 0 121 -54 121 -121s-54 -121 -121 -121s-121 54 -121 121s54 121 121 121zM168 123c38 0 71 26 84 58h-169c13 -32 47 -58 85 -58zM332 48c-15 23 -38 42 -68 54 -c13 11 24 23 32 37c15 -6 31 -9 48 -9c25 0 49 7 69 19c54 -16 87 -53 99 -101h-180zM314 245c-9 42 -36 78 -72 99c22 34 59 56 102 56c67 0 121 -54 121 -121s-54 -121 -121 -121c-13 0 -25 2 -37 6c3 9 6 18 8 28c9 -3 19 -5 29 -5c38 0 71 26 84 58h-114z" /> - <glyph glyph-name="ion-android-data" unicode="" -d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM88 56v0v0v0zM240 1c40 3 77 18 108 44l-124 147v144l-16 47c-40 -3 -77 -18 -108 -44l28 -39l-11 -12l-39 28c-26 -31 -42 -68 -45 -108l47 -8v-16l-47 -8 -c3 -40 18 -77 44 -108l39 28l12 -11l-28 -39c31 -26 68 -42 108 -45l8 47h16z" /> - <glyph glyph-name="ion-android-developer" unicode="" horiz-adv-x="512" -d="M140 7c10 0 19 -8 20 -18v-1v-1c0 -10 -10 -19 -20 -19v0v0h-8c-46 0 -79 20 -79 77c0 15 1 31 3 46s2 31 2 45s-1 34 -36 34c-12 0 -22 10 -22 22v0v0c0 12 10 22 22 22c35 0 36 20 36 34s-1 30 -3 45s-3 31 -3 46c0 57 34 77 80 77h8v0v0c10 0 20 -9 20 -19v-1v-1 -c-1 -10 -10 -18 -20 -18h-1c-27 -2 -41 -7 -43 -41c-1 -13 0 -26 1 -40c1 -15 3 -29 4 -43c2 -32 -3 -49 -24 -61v0v0c21 -12 26 -29 24 -61c-1 -14 -3 -28 -4 -43c-1 -14 -2 -26 -1 -40c2 -34 16 -39 43 -41h1zM372 7h1c27 2 41 7 43 41c1 14 0 26 -1 40c-1 15 -3 29 -4 43 -c-2 32 3 49 24 61v0v0c-21 12 -26 29 -24 61c1 14 3 28 4 43c1 14 2 27 1 40c-2 34 -16 39 -43 41h-1c-10 0 -19 8 -20 18v1v1c0 10 10 19 20 19v0v0h7c46 0 80 -20 80 -77c0 -15 -1 -31 -3 -46s-2 -31 -2 -45s1 -34 36 -34c12 0 22 -10 22 -22v0v0c0 -12 -10 -22 -22 -22 -c-35 0 -36 -20 -36 -34s1 -30 2 -45c2 -15 3 -31 3 -46c0 -57 -34 -77 -80 -77h-7v0v0c-10 0 -20 9 -20 19v1v1c1 10 10 18 20 18z" /> - <glyph glyph-name="ion-android-display" unicode="" horiz-adv-x="501" -d="M449 192l52 -53l-74 -29l25 -76l-79 6l-10 -78l-69 40l-44 -66l-44 66l-68 -40l-10 78l-79 -6l25 76l-74 29l52 53l-52 53l74 29l-25 76l79 -6l10 78l68 -40l44 66l44 -66l69 40l10 -78l79 6l-25 -76l74 -29zM250 32c88 0 160 72 160 160s-72 160 -160 160v-320z" /> - <glyph glyph-name="ion-android-download" unicode="" -d="M264 256h88l-128 -128l-128 128h88v175v1h80v-1v-175zM296 404c88 -30 152 -114 152 -212c0 -124 -100 -224 -224 -224s-224 100 -224 224c0 98 64 182 152 212v-34c-24 -10 -46 -24 -64 -42c-36 -36 -56 -85 -56 -136s20 -100 56 -136s85 -56 136 -56s100 20 136 56 -s56 85 56 136s-20 100 -56 136c-19 18 -40 32 -64 42v34zM96 80v16h256v-16h-256z" /> - <glyph glyph-name="ion-android-drawer" unicode="" horiz-adv-x="256" -d="M0 320v64h256v-64h-256zM0 0v64h256v-64h-256zM0 160v64h256v-64h-256z" /> - <glyph glyph-name="ion-android-dropdown" unicode="" horiz-adv-x="288" -d="M0 32l288 288v-288h-288z" /> - <glyph glyph-name="ion-android-earth" unicode="" -d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM32 192c0 -51 20 -100 56 -136c31 -31 71 -49 113 -54c6 16 22 31 8 42c-9 7 -17 14 -25 22c-3 3 -11 21 -9 24c6 9 7 16 9 27c3 13 -4 17 -15 24c-16 10 -31 24 -47 36 -c-8 6 -18 10 -21 20s-4 22 -10 30c-15 22 -13 38 -11 64c0 7 -1 17 -2 26c-30 -35 -46 -79 -46 -125zM360 56c36 36 56 85 56 136s-20 100 -56 136c-30 30 -67 48 -108 54v-9l4 -10l-15 -14l-9 3l-11 11l-11 13l-15 6c-17 -3 -33 -8 -49 -15c0 -2 1 -4 1 -7c8 3 16 5 24 8 -c3 1 14 -7 17 -9c-4 -5 -22 -17 -23 -23c0 -2 7 -7 7 -11v-18c4 3 21 22 23 22c14 4 37 -19 39 -27s-23 -26 -35 -37c-9 -9 -26 -13 -21 -26c2 -4 11 -22 6 -26c-6 -5 -16 10 -19 13c-9 11 -28 7 -41 7c0 -19 -1 -33 16 -46c16 -12 32 -27 51 -35c14 -6 38 8 50 -1 -c17 -12 32 -24 51 -32c8 -4 36 -21 28 -33c-5 -8 -11 -16 -15 -25s-13 -20 -21 -26c-9 -7 -19 -19 -24 -32c38 7 72 25 100 53zM391 262c7 -10 4 -38 4 -50c0 -22 2 -44 -5 -65c-12 9 -23 26 -25 48c-2 23 1 41 -3 61c-3 17 -21 34 -29 50c-7 15 -15 30 -22 45 -c2 -1 6 -2 8 -3c14 -13 27 -26 41 -39c12 -12 21 -33 31 -47z" /> - <glyph glyph-name="ion-android-folder" unicode="" horiz-adv-x="512" -d="M432 16h-432v352h144l48 -64h240v-32h-368l-40 -128l16 -16l40 128h432z" /> - <glyph glyph-name="ion-android-forums" unicode="" horiz-adv-x="512" -d="M422 432c6 0 10 -4 10 -10v-268c0 -6 -4 -10 -10 -10h-230l-112 -112v112h-70c-6 0 -10 4 -10 10v268c0 6 4 10 10 10h412zM502 352c6 0 10 -4 10 -10v-268c0 -6 -4 -10 -10 -10h-70v-112l-112 112h-160l48 48h223c22 0 33 13 33 33v207h38z" /> - <glyph glyph-name="ion-android-friends" unicode="" horiz-adv-x="512" -d="M325 117c54 -16 87 -53 99 -101h-336c12 48 45 85 99 101c20 -12 44 -19 69 -19s49 7 69 19zM256 368c67 0 121 -54 121 -121s-54 -121 -121 -121s-121 54 -121 121s54 121 121 121zM256 155c38 0 71 26 84 58h-169c13 -32 47 -58 85 -58zM412 86c-18 20 -42 36 -72 46 -c8 6 18 11 30 15c12 -7 26 -11 41 -11s29 4 41 11c32 -10 53 -32 60 -61h-100zM411 298c40 0 73 -33 73 -73s-33 -73 -73 -73c-18 0 -34 7 -47 18c3 5 6 10 9 16c10 -9 23 -16 38 -16c23 0 43 15 51 35h-81c4 12 6 25 6 38c0 16 -3 33 -9 47c10 5 21 8 33 8zM172 132 -c-30 -10 -54 -26 -72 -46h-100c7 29 27 51 59 61c12 -7 27 -11 42 -11s29 4 41 11c12 -4 22 -9 30 -15zM101 170c15 0 28 7 38 16c3 -6 5 -11 9 -16c-13 -11 -29 -18 -47 -18c-40 0 -73 33 -73 73s33 73 73 73c12 0 23 -3 33 -8c-6 -14 -9 -31 -9 -47c0 -13 2 -26 6 -38h-81 -c8 -20 28 -35 51 -35z" /> - <glyph glyph-name="ion-android-hand" unicode="" horiz-adv-x="473" -d="M459 172c17 -17 19 -42 2 -59c0 0 -110 -118 -144 -139v0c-32 -24 -73 -38 -113 -38c-63 0 -117 41 -135 97v1v0c0 1 -1 3 -1 4l-66 216c-6 17 2 36 19 42s35 -3 41 -20l38 -102c2 -4 3 -1 3 2l-26 184c-3 17 9 35 26 38s34 -10 37 -27l29 -157c0 -3 2 -2 2 0l1 202 -c0 18 14 32 32 32s32 -14 32 -32l9 -200c0 -5 3 -5 4 -1l27 154c2 18 18 31 36 29s29 -19 27 -37l-24 -196c-2 -13 -4 -34 2 -41c9 -10 24 -10 36 2l48 48c17 17 41 15 58 -2z" /> - <glyph glyph-name="ion-android-image" unicode="" horiz-adv-x="512" -d="M0 448h512v-512h-512v512zM480 -32v448h-448v-448h448zM448 88v-88h-384v136l96 64l112 -96l80 40z" /> - <glyph glyph-name="ion-android-inbox" unicode="" horiz-adv-x="512" -d="M416 416l96 -256v-192h-512v192l96 256h320zM336 160h112l-64 216h-256l-64 -216h112c0 -44 36 -80 80 -80s80 36 80 80z" /> - <glyph glyph-name="ion-android-information" unicode="" -d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM256 67v157h-64v-157h64zM224 272c22 0 40 18 40 40s-18 40 -40 40s-40 -18 -40 -40s18 -40 40 -40z" /> - <glyph glyph-name="ion-android-keypad" unicode="" horiz-adv-x="384" -d="M96 362c0 -6 -4 -10 -10 -10h-76c-6 0 -10 4 -10 10v76c0 6 4 10 10 10h76c6 0 10 -4 10 -10v-76zM243 362c0 -6 -4 -10 -10 -10h-76c-6 0 -10 4 -10 10v76c0 6 4 10 10 10h76c6 0 10 -4 10 -10v-76zM384 362c0 -6 -4 -10 -10 -10h-76c-6 0 -10 4 -10 10v76 -c0 6 4 10 10 10h76c6 0 10 -4 10 -10v-76zM96 234c0 -6 -4 -10 -10 -10h-76c-6 0 -10 4 -10 10v76c0 6 4 10 10 10h76c6 0 10 -4 10 -10v-76zM243 234c0 -6 -4 -10 -10 -10h-76c-6 0 -10 4 -10 10v76c0 6 4 10 10 10h76c6 0 10 -4 10 -10v-76zM384 234c0 -6 -4 -10 -10 -10 -h-76c-6 0 -10 4 -10 10v76c0 6 4 10 10 10h76c6 0 10 -4 10 -10v-76zM96 106c0 -6 -4 -10 -10 -10h-76c-6 0 -10 4 -10 10v76c0 6 4 10 10 10h76c6 0 10 -4 10 -10v-76zM243 106c0 -6 -4 -10 -10 -10h-76c-6 0 -10 4 -10 10v76c0 6 4 10 10 10h76c6 0 10 -4 10 -10v-76z -M243 -22c0 -6 -4 -10 -10 -10h-76c-6 0 -10 4 -10 10v76c0 6 4 10 10 10h76c6 0 10 -4 10 -10v-76zM384 106c0 -6 -4 -10 -10 -10h-76c-6 0 -10 4 -10 10v76c0 6 4 10 10 10h76c6 0 10 -4 10 -10v-76z" /> - <glyph glyph-name="ion-android-lightbulb" unicode="" horiz-adv-x="352" -d="M176 448c97 0 176 -79 176 -176c0 -62 -24 -117 -72 -148v-156h-32v-32h-144v32h-32v156c-48 31 -72 86 -72 148c0 97 79 176 176 176zM248 0v16h-144v-16h144zM248 48v16h-144v-16h144zM262 151c37 24 58 67 58 121c0 38 -15 75 -42 102s-64 42 -102 42 -s-75 -15 -102 -42s-42 -64 -42 -102c0 -54 21 -97 58 -121l14 -9v-18v-28h144v28v18z" /> - <glyph glyph-name="ion-android-locate" unicode="" horiz-adv-x="512" -d="M160 192c0 64 32 96 96 96s96 -32 96 -96s-32 -96 -96 -96s-96 32 -96 96zM512 208v-32h-65c-4 -47 -22 -87 -55 -120s-73 -51 -120 -55v-65h-32v65c-47 4 -87 22 -120 55s-51 73 -55 120h-65v32h65c1 13 3 26 7 39s9 24 15 35s13 22 21 32s16 18 26 26s21 15 32 21 -s22 11 35 15s26 6 39 7v65h32v-65c47 -4 87 -22 120 -55s51 -73 55 -120h65zM256 49c39 0 73 14 101 42s42 62 42 101s-14 73 -42 101s-62 42 -101 42s-73 -14 -101 -42s-42 -62 -42 -101s14 -73 42 -101s62 -42 101 -42z" /> - <glyph glyph-name="ion-android-location" unicode="" horiz-adv-x="320" -d="M320 288c0 -20 -3 -39 -10 -57v0l-1 -1v-1c-67 -171 -149 -293 -149 -293v0s-82 121 -149 292v2l-1 1v0c-7 18 -10 37 -10 57c0 88 72 160 160 160s160 -72 160 -160zM160 256c26 0 48 22 48 48s-22 48 -48 48s-48 -22 -48 -48s22 -48 48 -48z" /> - <glyph glyph-name="ion-android-mail" unicode="" horiz-adv-x="512" -d="M256 142l256 124v-266h-512v266zM512 310l-256 -123l-256 123v74h512v-74z" /> + <glyph glyph-name="ion-android-add-circle" unicode="" horiz-adv-x="416" +d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM315 171v42h-86v86h-42v-86h-86v-42h86v-86h42v86h86z" /> + <glyph glyph-name="ion-android-add" unicode="" horiz-adv-x="320" +d="M320 171h-139v-139h-42v139h-139v42h139v139h42v-139h139v-42z" /> + <glyph glyph-name="ion-android-alarm-clock" unicode="" horiz-adv-x="428" +d="M428 323l-28 -33l-98 82l28 33zM125 373l-97 -83l-28 33l97 83zM225 275v0v-111l85 -50l-16 -27l-101 61v127h32zM214 360c106 0 193 -86 193 -191s-87 -191 -193 -191c-107 0 -193 86 -193 191s86 191 193 191zM214 20c82 0 150 66 150 149c0 82 -68 149 -150 149 +s-150 -67 -150 -149s68 -149 150 -149z" /> + <glyph glyph-name="ion-android-alert" unicode="" horiz-adv-x="416" +d="M208 400c114 0 208 -94 208 -208s-94 -208 -208 -208s-208 94 -208 208s94 208 208 208zM232 88v40h-48v-40h48zM232 176v128h-48v-128h48z" /> + <glyph glyph-name="ion-android-apps" unicode="" horiz-adv-x="320" +d="M0 272v80h80v-80h-80zM120 32v80h80v-80h-80zM0 32v80h80v-80h-80zM0 152v80h80v-80h-80zM120 152v80h80v-80h-80zM240 352h80v-80h-80v80zM120 272v80h80v-80h-80zM240 152v80h80v-80h-80zM240 32v80h80v-80h-80z" /> + <glyph glyph-name="ion-android-archive" unicode="" horiz-adv-x="416" +d="M406 348c7 -7 10 -17 10 -29v-289c0 -25 -21 -46 -46 -46h-324c-25 0 -46 21 -46 46v289c0 12 3 22 10 29l33 39c6 8 16 13 26 13h278c10 0 20 -5 26 -13zM208 65l127 127h-81v46h-92v-46h-81zM49 354h317l-22 23h-277z" /> + <glyph glyph-name="ion-android-arrow-back" unicode="" horiz-adv-x="342" +d="M342 213v-42h-260l119 -120l-30 -30l-171 171l171 171l31 -30l-120 -120h260z" /> + <glyph glyph-name="ion-android-arrow-down" unicode="" horiz-adv-x="342" +d="M192 363v-260l120 120l30 -31l-171 -171l-171 171l30 30l120 -119v260h42z" /> + <glyph glyph-name="ion-android-arrow-dropdown-circle" unicode="" horiz-adv-x="416" +d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM208 128l96 96h-192z" /> + <glyph glyph-name="ion-android-arrow-dropdown" unicode="" horiz-adv-x="256" +d="M0 256h256l-128 -128z" /> + <glyph glyph-name="ion-android-arrow-dropleft-circle" unicode="" horiz-adv-x="416" +d="M416 192c0 -115 -93 -208 -208 -208s-208 93 -208 208s93 208 208 208s208 -93 208 -208zM144 192l96 -96v192z" /> + <glyph glyph-name="ion-android-arrow-dropleft" unicode="" horiz-adv-x="128" +d="M128 320v-256l-128 128z" /> + <glyph glyph-name="ion-android-arrow-dropright-circle" unicode="" horiz-adv-x="416" +d="M208 -16c-115 0 -208 93 -208 208s93 208 208 208s208 -93 208 -208s-93 -208 -208 -208zM176 96l96 96l-96 96v-192z" /> + <glyph glyph-name="ion-android-arrow-dropright" unicode="" horiz-adv-x="128" +d="M0 320l128 -128l-128 -128v256z" /> + <glyph glyph-name="ion-android-arrow-dropup-circle" unicode="" horiz-adv-x="416" +d="M416 192c0 -115 -93 -208 -208 -208s-208 93 -208 208s93 208 208 208s208 -93 208 -208zM304 160l-96 96l-96 -96h192z" /> + <glyph glyph-name="ion-android-arrow-dropup" unicode="" horiz-adv-x="256" +d="M0 128l128 128l128 -128h-256z" /> + <glyph glyph-name="ion-android-arrow-forward" unicode="" horiz-adv-x="342" +d="M0 171v42h260l-119 120l30 30l171 -171l-171 -171l-31 30l120 120h-260z" /> + <glyph glyph-name="ion-android-arrow-up" unicode="" horiz-adv-x="342" +d="M192 21h-42v260l-120 -119l-30 30l171 171l171 -171l-30 -31l-120 120v-260z" /> + <glyph glyph-name="ion-android-attach" unicode="" horiz-adv-x="235" +d="M203 320h32v-235c0 -65 -53 -117 -118 -117s-117 52 -117 117v246c0 47 38 85 85 85s86 -38 86 -85v-246c0 -30 -24 -53 -54 -53s-53 23 -53 53v203h32v-203c0 -12 9 -21 21 -21s22 9 22 21v246c0 30 -24 53 -54 53s-53 -23 -53 -53v-246c0 -47 38 -85 85 -85 +s86 38 86 85v235z" /> + <glyph glyph-name="ion-android-bar" unicode="" horiz-adv-x="384" +d="M171 171l-171 170v43h384v-43l-171 -170v-131h107v-40h-256v40h107v131zM96 299h192l43 42h-278z" /> + <glyph glyph-name="ion-android-bicycle" unicode="" +d="M299 317c-19 0 -34 14 -34 33s15 34 34 34s33 -15 33 -34s-14 -33 -33 -33zM355 187c51 0 93 -43 93 -94s-42 -93 -93 -93s-94 42 -94 93s43 94 94 94zM355 28c36 0 65 29 65 65s-29 66 -65 66s-66 -30 -66 -66s30 -65 66 -65zM274 224l-30 45l-43 -45l39 -32v-112h-32 +v86l-61 38c-9 6 -19 15 -19 27c0 8 3 17 9 23l72 69c6 6 14 9 22 9c11 0 22 -7 28 -16l34 -60h59v-32h-78zM93 187c51 0 94 -43 94 -94s-43 -93 -94 -93s-93 42 -93 93s42 94 93 94zM93 28c36 0 66 29 66 65s-30 66 -66 66s-65 -30 -65 -66s29 -65 65 -65z" /> + <glyph glyph-name="ion-android-boat" unicode="" +d="M52 35l-51 139c-2 6 -1 12 1 17s8 8 13 10l38 13v98c0 23 20 43 43 43h64l16 53h96l16 -53h64c23 0 43 -20 43 -43v-98l38 -13c5 -2 11 -5 13 -10s3 -12 1 -17l-51 -139h-1c-34 0 -65 20 -86 43c-21 -23 -51 -43 -85 -43s-64 19 -85 42c-21 -23 -52 -42 -86 -42h-1z +M96 312v-84l128 41l128 -41v84h-256zM309 40c0 0 59 -64 107 -64h-21c-30 0 -59 12 -86 26c-53 -28 -117 -28 -170 0c-27 -14 -56 -26 -86 -26h-21c49 0 107 64 107 64c52 -36 118 -36 170 0z" /> + <glyph glyph-name="ion-android-bookmark" unicode="" horiz-adv-x="288" +d="M248 384c22 0 40 -18 40 -40v-344l-144 64l-144 -64v344c0 22 18 40 40 40h208z" /> + <glyph glyph-name="ion-android-bulb" unicode="" +d="M224 278c-25 0 -50 -10 -68 -28s-28 -43 -28 -68c0 -34 18 -66 48 -83l16 -10v-18v-71h64v71v18l16 10c15 8 27 20 35 34c9 15 13 31 13 49c0 25 -10 50 -28 68s-43 28 -68 28zM245 416v0v-64h-42v64h42zM374 362v0l30 -30l-38 -38l-30 30zM74 362v0l38 -38l-30 -30 +l-38 38zM224 310v0c70 0 128 -58 128 -128c0 -48 -26 -89 -64 -111v-103h-128v103c-38 22 -64 64 -64 111c0 70 58 128 128 128zM448 203v0v-42h-64v42h64zM64 203v0v-42h-64v42h64z" /> + <glyph glyph-name="ion-android-bus" unicode="" horiz-adv-x="352" +d="M0 96v204c0 75 82 84 176 84s176 -9 176 -84v-204c0 -18 -14 -24 -27 -36v-39c0 -12 -9 -21 -21 -21h-21c-12 0 -22 9 -22 21v22h-170v-22c0 -12 -10 -21 -22 -21h-21c-12 0 -21 9 -21 21v39c-13 12 -27 17 -27 36zM80 80c18 0 32 14 32 32s-14 32 -32 32 +s-32 -14 -32 -32s14 -32 32 -32zM272 80c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM304 203v106h-256v-106h256z" /> + <glyph glyph-name="ion-android-calendar" unicode="" horiz-adv-x="384" +d="M304 176v-96h-96v96h96zM272 384h48v-32h24c22 0 40 -18 40 -40v-272c0 -22 -18 -40 -40 -40h-304c-22 0 -40 18 -40 40v272c0 22 18 40 40 40h24v32h48v-32h160v32zM344 40v212h-304v-212h304z" /> + <glyph glyph-name="ion-android-call" unicode="" horiz-adv-x="384" +d="M363 117c12 0 21 -9 21 -21v-75c0 -12 -9 -21 -21 -21c-201 0 -363 162 -363 363c0 12 9 21 21 21h75c12 0 21 -9 21 -21c0 -27 4 -52 13 -77c2 -7 0 -16 -5 -21l-47 -47c31 -61 80 -110 141 -141l47 47c5 6 14 7 21 5c23 -7 49 -12 76 -12z" /> + <glyph glyph-name="ion-android-camera" unicode="" +d="M161 168c0 42 21 63 63 63s63 -21 63 -63s-21 -63 -63 -63s-63 21 -63 63zM408 352c11 0 20 -4 28 -12s12 -17 12 -28v-272c0 -11 -4 -20 -12 -28s-17 -12 -28 -12h-368c-11 0 -20 4 -28 12s-12 17 -12 28v272c0 11 4 20 12 28s17 12 28 12h88l32 32h128l32 -32h88z +M224 56c31 0 57 11 79 33s33 48 33 79s-11 57 -33 79s-48 33 -79 33s-57 -11 -79 -33s-33 -48 -33 -79s11 -57 33 -79s48 -33 79 -33z" /> + <glyph glyph-name="ion-android-cancel" unicode="" horiz-adv-x="416" +d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM312 117l-75 75l75 75l-29 29l-75 -75l-75 75l-29 -29l75 -75l-75 -75l29 -29l75 75l75 -75z" /> + <glyph glyph-name="ion-android-car" unicode="" horiz-adv-x="384" +d="M339 331l45 -118v-160c0 -12 -9 -21 -21 -21h-22c-12 0 -21 9 -21 21v11h-256v-11c0 -12 -9 -21 -21 -21h-22c-12 0 -21 9 -21 21v160l45 118c4 13 16 21 30 21h234c14 0 26 -8 30 -21zM75 128c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM309 128 +c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM43 235h298l-32 85h-234z" /> + <glyph glyph-name="ion-android-cart" unicode="" horiz-adv-x="416" +d="M122 70c23 0 41 -18 41 -41s-18 -42 -41 -42s-42 19 -42 42s19 41 42 41zM0 397h68l19 -42h308c11 0 21 -9 21 -20c0 -4 -1 -8 -2 -10l-75 -129c-7 -14 -20 -22 -36 -22h-155l-21 -32s-2 -5 -2 -6c0 -3 2 -5 5 -5h238v-40h-243c-26 0 -45 14 -45 42c0 7 2 15 5 20l31 51 +l-74 151h-42v42zM326 70c23 0 42 -18 42 -41s-19 -42 -42 -42s-41 19 -41 42s18 41 41 41z" /> + <glyph glyph-name="ion-android-chat" unicode="" horiz-adv-x="416" +d="M344 384c4 0 7 -4 7 -8v-214c0 -4 -3 -9 -7 -9h-187l-90 -89v89h-57c-4 0 -10 5 -10 9v214c0 4 6 8 10 8h334zM408 321c4 0 8 -5 8 -9v-214c0 -4 -4 -9 -8 -9h-57v-89l-90 89h-130l39 39h181c18 0 25 10 25 26v167h32z" /> + <glyph glyph-name="ion-android-checkbox-blank" unicode="" horiz-adv-x="384" +d="M341 384c23 0 43 -20 43 -43v-298c0 -23 -20 -43 -43 -43h-298c-23 0 -43 20 -43 43v298c0 23 20 43 43 43h298z" /> + <glyph glyph-name="ion-android-checkbox-outline-blank" unicode="" horiz-adv-x="384" +d="M341 341h-298v-298h298v298zM341 384v0c23 0 43 -20 43 -43v-298c0 -23 -20 -43 -43 -43h-298c-23 0 -43 20 -43 43v298c0 23 20 43 43 43h298z" /> + <glyph glyph-name="ion-android-checkbox-outline" unicode="" horiz-adv-x="384" +d="M105 233l66 -66l183 183l30 -30l-213 -213l-96 96zM341 43v170h43v-170c0 -23 -20 -43 -43 -43h-298c-23 0 -43 20 -43 43v298c0 23 20 43 43 43h213v-43h-213v-298h298z" /> + <glyph glyph-name="ion-android-checkbox" unicode="" horiz-adv-x="384" +d="M341 384c23 0 43 -20 43 -43v-298c0 -23 -20 -43 -43 -43h-298c-23 0 -43 20 -43 43v298c0 23 20 43 43 43h298zM149 85l192 192l-30 30l-162 -162l-76 77l-30 -30z" /> + <glyph glyph-name="ion-android-checkmark-circle" unicode="" horiz-adv-x="416" +d="M123 232l64 -64l179 178l29 -29l-208 -208l-93 93zM374 192h42c0 -114 -94 -208 -208 -208s-208 94 -208 208s94 208 208 208c28 0 54 -6 78 -16l-32 -32c-15 4 -30 6 -46 6c-92 0 -166 -74 -166 -166s74 -166 166 -166s166 74 166 166z" /> + <glyph glyph-name="ion-android-clipboard" unicode="" horiz-adv-x="384" +d="M341 368c23 0 43 -20 43 -43v-314c0 -23 -20 -43 -43 -43h-298c-23 0 -43 20 -43 43v314c0 23 20 43 43 43h87c7 28 32 48 62 48s55 -20 62 -48h87zM192 368c-12 0 -21 -9 -21 -21s9 -22 21 -22s21 10 21 22s-9 21 -21 21zM344 8v320h-40v-72h-224v72h-40v-320h304z" /> + <glyph glyph-name="ion-android-close" unicode="" horiz-adv-x="298" +d="M298 311l-119 -119l119 -119l-30 -30l-119 119l-119 -119l-30 30l119 119l-119 119l30 30l119 -119l119 119z" /> + <glyph glyph-name="ion-android-cloud-circle" unicode="" horiz-adv-x="416" +d="M208 400c114 0 208 -94 208 -208s-94 -208 -208 -208s-208 94 -208 208s94 208 208 208zM302 109c29 0 52 23 52 52s-23 52 -52 52h-11c0 46 -37 83 -83 83c-38 0 -71 -26 -80 -62h-3c-34 0 -63 -29 -63 -63s29 -62 63 -62h177z" /> + <glyph glyph-name="ion-android-cloud-done" unicode="" horiz-adv-x="480" +d="M387 231c52 -3 93 -46 93 -99c0 -55 -45 -100 -100 -100h-260c-66 0 -120 54 -120 120c0 62 47 113 107 119c25 48 75 81 133 81c73 0 133 -52 147 -121zM197 85l141 141l-30 30l-111 -111l-44 45l-30 -30z" /> + <glyph glyph-name="ion-android-cloud-outline" unicode="" horiz-adv-x="480" +d="M387 231c52 -3 93 -46 93 -99c0 -55 -45 -100 -100 -100h-260c-66 0 -120 54 -120 120c0 62 47 113 107 119c25 48 75 81 133 81c73 0 133 -52 147 -121zM380 72c33 0 60 27 60 60s-27 60 -60 60h-30v10c0 61 -49 110 -110 110c-51 0 -93 -34 -106 -80h-14 +c-44 0 -80 -36 -80 -80s36 -80 80 -80h260z" /> + <glyph glyph-name="ion-android-cloud" unicode="" horiz-adv-x="480" +d="M387 231c52 -3 93 -46 93 -99c0 -55 -45 -100 -100 -100h-260c-66 0 -120 54 -120 120c0 62 47 113 107 119c25 48 75 81 133 81c73 0 133 -52 147 -121z" /> + <glyph glyph-name="ion-android-color-palette" unicode="" horiz-adv-x="384" +d="M192 384c106 0 192 -77 192 -171c0 -59 -48 -106 -107 -106h-38c-18 0 -32 -14 -32 -32c0 -9 3 -17 8 -22s9 -12 9 -21c0 -18 -14 -32 -32 -32c-106 0 -192 86 -192 192s86 192 192 192zM75 192c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM139 277 +c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM245 277c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM309 192c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32z" /> + <glyph glyph-name="ion-android-compass" unicode="" +d="M224 217c13 0 25 -12 25 -25s-12 -25 -25 -25s-25 12 -25 25s12 25 25 25zM224 416c123 0 224 -101 224 -224s-101 -224 -224 -224s-224 101 -224 224s101 224 224 224zM273 143l85 183l-183 -85l-85 -183z" /> + <glyph glyph-name="ion-android-contact" unicode="" horiz-adv-x="384" +d="M267 110c59 -18 104 -58 117 -110h-384c13 52 58 92 117 110c22 -13 48 -20 75 -20s53 7 75 20zM192 384c73 0 132 -59 132 -132s-59 -132 -132 -132s-132 59 -132 132s59 132 132 132zM192 153c42 0 78 26 92 63h-184c14 -37 50 -63 92 -63z" /> + <glyph glyph-name="ion-android-contacts" unicode="" +d="M207 104c47 -14 76 -62 87 -104h-294c11 42 40 90 87 104c18 -10 38 -16 60 -16s42 6 60 16zM147 328c58 0 106 -48 106 -106s-48 -106 -106 -106s-106 48 -106 106s48 106 106 106zM147 141c34 0 62 23 74 51h-148c12 -28 40 -51 74 -51zM291 64c-13 20 -34 43 -60 53 +c11 9 21 23 28 35c13 -5 27 -8 42 -8c22 0 42 6 60 16c47 -14 76 -54 87 -96h-157zM275 248c-8 37 -31 69 -63 87c19 29 52 49 89 49c58 0 106 -48 106 -106s-48 -106 -106 -106c-11 0 -22 2 -32 5c3 8 6 16 7 25c8 -3 16 -4 25 -4c34 0 62 22 74 50h-100z" /> + <glyph glyph-name="ion-android-contract" unicode="" horiz-adv-x="384" +d="M0 77v51h128v-128h-51v77h-77zM77 307v77h51v-128h-128v51h77zM256 0v128h128v-51h-77v-77h-51zM307 307h77v-51h-128v128h51v-77z" /> + <glyph glyph-name="ion-android-create" unicode="" horiz-adv-x="384" +d="M0 80l236 236l80 -80l-236 -236h-80v80zM378 298l-40 -40l-80 80l40 40c9 9 20 9 29 0l51 -51c9 -9 9 -20 0 -29z" /> + <glyph glyph-name="ion-android-delete" unicode="" horiz-adv-x="320" +d="M32 43v245h256v-245c0 -23 -20 -43 -43 -43h-170c-23 0 -43 20 -43 43zM320 352v-32h-320v32h80l27 32h106l27 -32h80z" /> + <glyph glyph-name="ion-android-desktop" unicode="" +d="M405 416c23 0 43 -20 43 -43v-282c0 -23 -20 -43 -43 -43h-138l42 -48v-32h-170v32l42 48h-138c-23 0 -43 20 -43 43v282c0 23 20 43 43 43h362zM405 128v245h-362v-245h362z" /> + <glyph glyph-name="ion-android-document" unicode="" horiz-adv-x="320" +d="M192 400l128 -128v-248c0 -22 -18 -40 -40 -40h-240c-22 0 -40 18 -40 40v336c0 22 18 40 40 40h152zM176 256h112l-112 112v-112z" /> + <glyph glyph-name="ion-android-done-all" unicode="" horiz-adv-x="512" +d="M388 308l-140 -139l-31 31l140 139zM481 339l31 -31l-264 -263l-122 123l30 31l92 -91zM0 168l32 31l122 -123l-31 -31z" /> + <glyph glyph-name="ion-android-done" unicode="" horiz-adv-x="384" +d="M122 108l230 230l32 -31l-262 -261l-122 122l32 31z" /> + <glyph glyph-name="ion-android-download" unicode="" horiz-adv-x="480" +d="M387 231c52 -3 93 -46 93 -99c0 -55 -45 -100 -100 -100h-260c-66 0 -120 54 -120 120c0 62 47 113 107 119c25 48 75 81 133 81c73 0 133 -52 147 -121zM208 180h-68l100 -100l100 100h-68v76h-64v-76z" /> + <glyph glyph-name="ion-android-drafts" unicode="" +d="M448 246v-203c0 -23 -20 -43 -43 -43h-362c-23 0 -43 20 -43 43v203c0 15 8 30 20 37l204 101l204 -101c13 -7 20 -22 20 -37zM224 144l171 112l-171 85l-171 -85z" /> + <glyph glyph-name="ion-android-exit" unicode="" horiz-adv-x="384" +d="M151 115l55 56h-206v42h207l-56 56l30 30l107 -107l-107 -107zM341 384c23 0 43 -20 43 -43v-298c0 -23 -20 -43 -43 -43h-298c-23 0 -43 20 -43 43v85h43v-85h298v298h-298v-85h-43v85c0 23 20 43 43 43h298z" /> + <glyph glyph-name="ion-android-expand" unicode="" horiz-adv-x="384" +d="M333 51v77h51v-128h-128v51h77zM333 333h-77v51h128v-128h-51v77zM51 333v-77h-51v128h128v-51h-77zM51 51h77v-51h-128v128h51v-77z" /> + <glyph glyph-name="ion-android-favorite-outline" unicode="" horiz-adv-x="416" +d="M302 384c64 0 114 -50 114 -115c0 -80 -71 -144 -178 -242l-30 -27l-30 27c-107 98 -178 162 -178 242c0 65 50 115 114 115c36 0 71 -17 94 -44c23 27 58 44 94 44zM221 55c50 46 94 86 123 122c28 35 40 63 40 92c0 23 -9 44 -24 59s-35 24 -58 24 +c-26 0 -53 -13 -70 -33l-24 -29l-24 29c-17 20 -44 33 -70 33c-23 0 -43 -9 -58 -24s-24 -36 -24 -59c0 -29 12 -57 40 -92c29 -36 73 -76 123 -122l4 -4l9 -8l9 8z" /> + <glyph glyph-name="ion-android-favorite" unicode="" horiz-adv-x="416" +d="M208 0l-30 27c-107 98 -178 162 -178 242c0 65 50 115 114 115c36 0 71 -17 94 -44c23 27 58 44 94 44c64 0 114 -50 114 -115c0 -80 -71 -144 -178 -242z" /> + <glyph glyph-name="ion-android-film" unicode="" horiz-adv-x="320" +d="M280 384h40v-384h-40v43h-40v-43h-160v43h-40v-43h-40v384h40v-43h40v43h160v-43h40v43zM80 85v43h-40v-43h40zM80 171v42h-40v-42h40zM80 256v43h-40v-43h40zM280 85v43h-40v-43h40zM280 171v42h-40v-42h40zM280 256v43h-40v-43h40z" /> + <glyph glyph-name="ion-android-folder-open" unicode="" +d="M405 304c23 0 43 -20 43 -43v-186c0 -23 -20 -43 -43 -43h-362c-23 0 -43 20 -43 43v234c0 23 20 43 43 43h138l43 -48h181zM416 75v186c0 6 -5 11 -11 11h-373v-197c0 -6 5 -11 11 -11h362c6 0 11 5 11 11z" /> + <glyph glyph-name="ion-android-folder" unicode="" +d="M181 352l43 -48h181c23 0 43 -20 43 -43v-186c0 -23 -20 -43 -43 -43h-362c-23 0 -43 20 -43 43v234c0 23 20 43 43 43h138z" /> + <glyph glyph-name="ion-android-funnel" unicode="" +d="M176 48v48h96v-48h-96zM0 336h448v-48h-448v48zM80 167v50h288v-50h-288z" /> + <glyph glyph-name="ion-android-globe" unicode="" horiz-adv-x="416" +d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM186 15c6 15 21 29 8 39c-8 7 -16 14 -23 21c-2 2 -11 20 -9 23c5 9 6 14 8 24c3 12 -3 16 -13 22c-15 10 -29 23 -43 34c-7 5 -17 10 -20 19s-5 20 -10 28c-14 20 -12 34 -10 58 +c0 7 -1 16 -2 25c-28 -32 -42 -73 -42 -116c0 -48 18 -92 52 -126c29 -29 65 -46 104 -51zM334 66c23 23 39 51 47 82c-8 -1 -19 2 -19 2s-21 24 -23 45c-2 22 0 39 -3 57c-3 16 -20 31 -27 46c-7 14 -13 28 -20 42c2 -1 5 -2 7 -3c5 1 10 2 14 2c-23 16 -49 25 -76 29v-8 +l4 -9l-14 -13l-9 3l-10 10l-10 12l-14 5c-16 -2 -31 -7 -45 -13v-7c7 3 16 5 23 8c3 1 13 -7 16 -9c-4 -5 -21 -15 -22 -21c0 -2 7 -6 7 -10c0 -6 -1 -11 -1 -17c3 3 20 21 22 21c13 3 35 -19 37 -26s-22 -24 -33 -34c-8 -8 -25 -12 -20 -24c2 -4 10 -20 5 -24 +c-6 -5 -14 9 -17 12c-8 10 -26 7 -38 7c0 -17 -1 -31 15 -43c15 -11 30 -25 47 -33c13 -6 36 7 47 -1c16 -11 29 -21 47 -29c8 -3 33 -20 26 -31c-5 -8 -10 -15 -14 -23s-13 -20 -20 -25c-8 -6 -16 -17 -21 -29c35 7 66 23 92 49z" /> + <glyph glyph-name="ion-android-hand" unicode="" horiz-adv-x="414" +d="M401 174c15 -15 18 -36 3 -51c0 0 -96 -103 -126 -121v0c-28 -21 -65 -34 -100 -34c-55 0 -101 36 -117 85v0v1c0 1 -1 2 -1 3l-58 189c-5 15 2 32 17 37s30 -3 35 -18l34 -88c1 -4 2 -2 2 1l-22 161c-3 15 7 30 22 33s30 -8 33 -23l25 -138c0 -2 2 -2 2 0v177 +c0 15 13 28 28 28s28 -13 28 -28l8 -175c0 -5 3 -4 4 -1l23 135c2 15 16 27 31 25s27 -17 25 -32l-21 -172c-1 -12 -3 -30 2 -36c8 -9 20 -9 31 2l42 42c15 15 35 13 50 -2z" /> + <glyph glyph-name="ion-android-hangout" unicode="" horiz-adv-x="352" +d="M176 400c97 0 176 -77 176 -172c0 -91 -76 -196 -176 -244v71c-97 0 -176 78 -176 173s79 172 176 172zM166 217v61h-62v-61h31l-21 -40h31zM248 217v61h-62v-61h31l-20 -40h31z" /> + <glyph glyph-name="ion-android-happy" unicode="" horiz-adv-x="416" +d="M208 400c114 0 208 -94 208 -208s-93 -208 -208 -208s-208 94 -208 208s93 208 208 208zM208 26c92 0 166 74 166 166s-74 166 -166 166s-166 -74 -166 -166s74 -166 166 -166zM281 213c-18 0 -31 13 -31 31s13 31 31 31s31 -13 31 -31s-13 -31 -31 -31zM135 213 +c-18 0 -31 13 -31 31s13 31 31 31s31 -13 31 -31s-13 -31 -31 -31zM208 78c-49 0 -89 29 -106 72h212c-17 -43 -57 -72 -106 -72z" /> + <glyph glyph-name="ion-android-home" unicode="" horiz-adv-x="416" +d="M160 0h-98v192h-62l208 192l208 -192h-62v-192h-98v128h-96v-128z" /> + <glyph glyph-name="ion-android-image" unicode="" horiz-adv-x="384" +d="M384 43c0 -23 -20 -43 -43 -43h-298c-23 0 -43 20 -43 43v298c0 23 20 43 43 43h298c23 0 43 -20 43 -43v-298zM117 160l-74 -96h298l-96 128l-74 -96z" /> + <glyph glyph-name="ion-android-laptop" unicode="" horiz-adv-x="512" +d="M437 32h75c0 -23 -64 -32 -96 -32h-320c-32 0 -96 9 -96 32h75c-23 0 -43 20 -43 43v266c0 23 20 43 43 43h362c23 0 43 -20 43 -43v-266c0 -23 -20 -43 -43 -43zM75 341v-272h362v272h-362zM256 13c12 0 21 10 21 22s-9 21 -21 21s-21 -9 -21 -21s9 -22 21 -22z" /> + <glyph glyph-name="ion-android-list" unicode="" horiz-adv-x="384" +d="M344 384c22 0 40 -18 40 -40v-304c0 -22 -18 -40 -40 -40h-304c-22 0 -40 18 -40 40v304c0 22 18 40 40 40h304zM240 80v48h-160v-48h160zM304 168v48h-224v-48h224zM304 256v48h-224v-48h224z" /> + <glyph glyph-name="ion-android-locate" unicode="" +d="M224 272c44 0 80 -36 80 -80s-36 -80 -80 -80s-80 36 -80 80s36 80 80 80zM415 213h33v-42h-33c-10 -89 -81 -160 -170 -170v-33h-42v33c-89 10 -160 81 -170 170h-33v42h33c10 89 81 160 170 170v33h42v-33c89 -10 160 -81 170 -170zM224 43c82 0 149 67 149 149 +s-67 149 -149 149s-149 -67 -149 -149s67 -149 149 -149z" /> + <glyph glyph-name="ion-android-lock" unicode="" horiz-adv-x="320" +d="M280 262c22 0 40 -18 40 -40v-200c0 -22 -18 -40 -40 -40h-240c-22 0 -40 18 -40 40v200c0 22 18 40 40 40h20v40c0 55 45 100 100 100s100 -45 100 -100v-40h20zM160 80c22 0 40 18 40 40s-18 40 -40 40s-40 -18 -40 -40s18 -40 40 -40zM222 262v40c0 34 -28 62 -62 62 +s-62 -28 -62 -62v-40h124z" /> + <glyph glyph-name="ion-android-mail" unicode="" +d="M405 368c23 0 43 -20 43 -43v-266c0 -23 -20 -43 -43 -43h-362c-23 0 -43 20 -43 43v266c0 23 20 43 43 43h362zM400 277v43l-176 -117l-176 117v-43l176 -117z" /> + <glyph glyph-name="ion-android-map" unicode="" horiz-adv-x="384" +d="M373 384c6 0 11 -5 11 -11v-322c0 -5 -3 -9 -7 -10l-121 -41l-128 45s-105 -41 -108 -42s-7 -3 -9 -3c-6 0 -11 5 -11 11v322c0 5 3 9 7 10l121 41l128 -45s103 40 108 42s7 3 9 3zM256 43v254l-128 44v-254z" /> + <glyph glyph-name="ion-android-menu" unicode="" horiz-adv-x="384" +d="M0 64v43h384v-43h-384zM0 171v42h384v-42h-384zM0 320h384v-43h-384v43z" /> + <glyph glyph-name="ion-android-microphone-off" unicode="" horiz-adv-x="408" +d="M316 93l58 -58l-58 58l58 -58l34 -33l-24 -24l-95 95c-19 -11 -40 -20 -62 -23v-82h-46v82c-75 10 -137 76 -137 153h39c0 -68 58 -117 121 -117c20 0 40 5 57 14l-32 33c-8 -3 -16 -5 -25 -5c-38 0 -69 31 -69 69v29l-135 134l24 24l111 -110v0l140 -140l5 -5l9 -9z +M273 197c0 -4 0 -8 -1 -12l-137 137v25c0 38 31 69 69 69s69 -31 69 -69v-150zM365 203c0 -31 -10 -60 -27 -84l-27 28c9 17 15 36 15 56h39zM408 2v0l-34 33z" /> <glyph glyph-name="ion-android-microphone" unicode="" horiz-adv-x="320" -d="M225 192c0 -35 -29 -64 -64 -64v0c-35 0 -64 29 -64 64v160c0 35 29 64 64 64v0c35 0 64 -29 64 -64v-160zM272 208h48v-8c0 -80 -59 -147 -135 -159v-73h-48v73c-78 11 -137 78 -137 159v8h48v-8c0 -30 12 -59 33 -80s49 -32 79 -32s58 11 79 32s33 50 33 80v8z" /> - <glyph glyph-name="ion-android-mixer" unicode="" horiz-adv-x="512" -d="M0 335v32h304v-32h-304zM432 335v32h80v-32h-80zM0 176v32h80v-32h-80zM208 176v32h304v-32h-304zM0 14v32h304v-32h-304zM432 14v32h80v-32h-80zM192 136c0 -22 -22 -40 -48 -40v0c-26 0 -48 18 -48 40v112c0 22 22 40 48 40v0c26 0 48 -18 48 -40v-112zM416 296 -c0 -22 -22 -40 -48 -40v0c-26 0 -48 18 -48 40v112c0 22 22 40 48 40v0c26 0 48 -18 48 -40v-112zM416 -24c0 -22 -22 -40 -48 -40v0c-26 0 -48 18 -48 40v112c0 22 22 40 48 40v0c26 0 48 -18 48 -40v-112z" /> - <glyph glyph-name="ion-android-more" unicode="" horiz-adv-x="128" -d="M0 128v128h128v-128h-128zM0 320v128h128v-128h-128zM0 -64v128h128v-128h-128z" /> - <glyph glyph-name="ion-android-note" unicode="" horiz-adv-x="464" -d="M0 448h464v-512h-464v512zM40 384v-64h256v64h-256zM424 32v48h-384v-48h384zM424 128v48h-384v-48h384zM424 224v48h-384v-48h384z" /> - <glyph glyph-name="ion-android-playstore" unicode="" horiz-adv-x="512" -d="M512 320c-23 -265 -16 -384 -16 -384h-480s7 116 -16 384h128c0 71 57 128 128 128s128 -57 128 -128h128zM256 416c-53 0 -96 -43 -96 -96h192c0 53 -43 96 -96 96zM192 16l176 104l-176 104v-208z" /> - <glyph glyph-name="ion-android-printer" unicode="" horiz-adv-x="512" -d="M96 320v96h320v-96h-320zM512 229v0v-165h-96v-96h-320v96h-96v165v0c0 33 27 59 60 59h392c33 0 60 -26 60 -59zM352 32v128h-192v-128h192zM416 200c13 0 24 11 24 24s-11 24 -24 24s-24 -11 -24 -24s11 -24 24 -24z" /> - <glyph glyph-name="ion-android-promotion" unicode="" horiz-adv-x="384" -d="M384 256l-192 -192l-192 192v192h192v0zM96 304c26 0 48 22 48 48s-22 48 -48 48s-48 -22 -48 -48s22 -48 48 -48zM384 192v-64l-192 -192l-192 192v64l192 -192z" /> - <glyph glyph-name="ion-android-reminder" unicode="" horiz-adv-x="416" -d="M0 48l64 160v96c0 80 64 144 144 144v0c80 0 144 -64 144 -144v-96l64 -160zM208 -64c-54 0 -100 33 -119 80h238c-19 -47 -65 -80 -119 -80z" /> - <glyph glyph-name="ion-android-remove" unicode="" horiz-adv-x="512" -d="M0 160v64h512v-64h-512z" /> - <glyph glyph-name="ion-android-search" unicode="" horiz-adv-x="512" -d="M510 6c6 -6 -3 -27 -22 -46s-40 -28 -46 -22l-113 113c-4 4 -1 15 8 28l-40 40c-31 -24 -70 -39 -113 -39c-102 0 -184 82 -184 184s82 184 184 184s184 -82 184 -184c0 -43 -15 -82 -39 -113l40 -40c13 9 24 12 28 8zM184 120c38 0 75 15 102 42s42 64 42 102 -s-15 75 -42 102s-64 42 -102 42s-75 -15 -102 -42s-42 -64 -42 -102s15 -75 42 -102s64 -42 102 -42z" /> - <glyph glyph-name="ion-android-send" unicode="" horiz-adv-x="512" -d="M0 448l512 -256l-512 -256l43 235l426 21l-426 21z" /> - <glyph glyph-name="ion-android-settings" unicode="" horiz-adv-x="491" -d="M438 192c0 -14 -2 -28 -5 -42l58 -44l-48 -84l-67 29c-21 -19 -45 -33 -73 -42l-9 -73h-96l-9 73c-28 9 -52 23 -73 42l-68 -29l-48 84l58 44c-3 14 -4 28 -4 42s1 28 4 42l-58 44l48 84l68 -29c21 19 45 33 73 42l9 73h96l9 -73c28 -9 52 -23 73 -42l67 29l48 -84 -l-58 -44c3 -14 5 -28 5 -42zM246 128c35 0 64 29 64 64s-29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64z" /> - <glyph glyph-name="ion-android-share" unicode="" horiz-adv-x="480" -d="M400 96c44 0 80 -36 80 -80s-36 -80 -80 -80s-80 36 -80 80c0 5 0 10 1 14l-186 104c-14 -13 -34 -22 -55 -22c-44 0 -80 36 -80 80s36 80 80 80c21 0 41 -9 55 -22l186 104c-1 5 -1 9 -1 14c0 44 36 80 80 80s80 -36 80 -80s-36 -80 -80 -80c-22 0 -42 9 -56 23 -l-186 -102c1 -5 2 -11 2 -17s-1 -12 -2 -17l185 -102c14 14 35 23 57 23z" /> - <glyph glyph-name="ion-android-social-user" unicode="" horiz-adv-x="512" -d="M142 334c0 76 38 114 114 114s114 -38 114 -114s-38 -114 -114 -114s-114 38 -114 114zM502 50c7 -7 10 -14 10 -22v-92h-512v92c0 8 3 15 10 22c61 61 143 91 246 91s185 -30 246 -91z" /> - <glyph glyph-name="ion-android-social" unicode="" horiz-adv-x="512" -d="M256 280c0 53 27 80 80 80s80 -27 80 -80s-27 -80 -80 -80s-80 27 -80 80zM73 213c0 41 20 61 61 61s61 -20 61 -61s-20 -61 -61 -61s-61 20 -61 61zM136 112c7 0 15 -1 24 -2v0v0c-21 -17 -31 -30 -32 -38v-72h-128v50c0 2 1 5 2 7s1 3 3 5c33 33 76 50 131 50zM505 80 -c5 -5 7 -10 7 -15v-65h-352v65c0 5 2 10 7 15c42 43 98 64 169 64s127 -21 169 -64z" /> - <glyph glyph-name="ion-android-sort" unicode="" horiz-adv-x="512" -d="M0 288v64h512v-64h-512zM0 160v64h352v-64h-352zM0 32v64h192v-64h-192z" /> - <glyph glyph-name="ion-android-stair-drawer" unicode="" horiz-adv-x="512" -d="M0 0v96h256v-96h-256zM128 144v96h256v-96h-256zM256 288v96h256v-96h-256z" /> - <glyph glyph-name="ion-android-star" unicode="" horiz-adv-x="512" -d="M512 246l-136 -121l40 -178l-160 85l-160 -85l40 178l-136 121l182 17l74 174l74 -174z" /> - <glyph glyph-name="ion-android-stopwatch" unicode="" -d="M240 383c116 -8 208 -105 208 -223c0 -124 -100 -224 -224 -224s-224 100 -224 224c0 118 92 215 208 223v17h-32v48h96v-48h-32v-17zM360 24c36 36 56 85 56 136s-20 100 -56 136s-85 56 -136 56s-100 -20 -136 -56s-56 -85 -56 -136s20 -100 56 -136s85 -56 136 -56 -s100 20 136 56zM337 273c3 -3 3 -8 0 -11l-74 -74c6 -8 9 -18 9 -28c0 -26 -22 -48 -48 -48s-48 22 -48 48s22 48 48 48c10 0 20 -3 28 -9l74 74c3 3 8 3 11 0zM224 128c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32z" /> - <glyph glyph-name="ion-android-storage" unicode="" -d="M0 256h448v-128h-448v128zM128 160v32h-96v-32h96zM0 416h448v-128h-448v128zM128 320v32h-96v-32h96zM0 96h448v-128h-448v128zM128 0v32h-96v-32h96z" /> - <glyph glyph-name="ion-android-system-back" unicode="" horiz-adv-x="512" -d="M416 256c53 0 96 -43 96 -96s-43 -96 -96 -96h-192v32h192c35 0 64 29 64 64s-29 64 -64 64v0h-361l67 -80h-42l-80 96l80 96h42l-67 -80h361z" /> - <glyph glyph-name="ion-android-system-home" unicode="" horiz-adv-x="512" -d="M256 303l-224 -84v-123h448v123zM256 338v0l256 -96v-178h-512v178z" /> - <glyph glyph-name="ion-android-system-windows" unicode="" horiz-adv-x="512" -d="M0 256h416v-192h-416v192zM384 96v128h-352v-128h352zM128 320h384v-192h-32v160h-352v32z" /> - <glyph glyph-name="ion-android-timer" unicode="" horiz-adv-x="320" -d="M210 202c87 -46 110 -206 110 -234h-320c0 27 23 188 110 234c-87 41 -110 187 -110 214h320c0 -26 -23 -172 -110 -214zM61 304c12 -25 25 -44 41 -58c17 -15 36 -22 58 -22s41 7 58 22c16 14 29 34 41 59c12 26 19 52 23 69c1 3 2 10 2 10h-248c4 -21 12 -52 25 -80z -M284 0c-4 25 -12 58 -26 91c-12 29 -25 51 -41 67c-17 17 -36 25 -57 25s-39 -8 -56 -25c-16 -16 -30 -38 -42 -67c-14 -33 -22 -66 -26 -91h248z" /> - <glyph glyph-name="ion-android-trash" unicode="" horiz-adv-x="352" -d="M16 249c39 -10 68 -21 160 -21s121 12 160 21c-2 -54 -10 -224 -11 -266c-1 -25 -66 -46 -147 -46s-145 21 -146 46c-2 34 -13 212 -16 266zM256 374c81 -10 96 -10 96 -53s-68 -59 -176 -59s-176 16 -176 58s17 44 96 54v66c0 6 5 8 11 8h140c6 0 9 -2 9 -8v-66z -M128 416v-39c15 1 31 1 48 1s34 0 48 -1v39h-96z" /> - <glyph glyph-name="ion-android-user-menu" unicode="" -d="M144 232c-28 0 -52 17 -62 42h124c-10 -25 -34 -42 -62 -42zM0 416h288v-288h-21c-9 35 -32 62 -72 74c-15 -8 -33 -13 -51 -13s-36 5 -51 13c-40 -12 -63 -39 -72 -74h-21v288zM144 209c49 0 89 40 89 89s-40 89 -89 89s-89 -40 -89 -89s40 -89 89 -89zM320 288v128h128 -v-128h-128zM320 128v128h128v-128h-128zM320 -32v128h128v-128h-128zM160 -32v128h128v-128h-128zM0 -32v128h128v-128h-128z" /> - <glyph glyph-name="ion-android-volume" unicode="" horiz-adv-x="512" -d="M234 448c54 0 70 -115 70 -256s-16 -256 -70 -256c-42 0 -74 64 -138 160h-64c-18 0 -32 43 -32 96s14 96 32 96h64c64 96 96 160 138 160zM240 -14c24 0 34 82 34 206s-10 206 -34 206c-18 0 -24 -78 -27 -144c28 -7 43 -32 43 -62s-15 -55 -43 -62 -c3 -66 9 -144 27 -144zM466 370c30 -52 46 -113 46 -178s-17 -126 -47 -178l-23 24c4 8 8 16 12 25c17 41 26 84 26 129s-9 88 -26 129c-4 9 -8 17 -12 25zM411 295c23 -28 37 -64 37 -103s-14 -75 -37 -103l-22 23c18 23 27 51 27 80c0 30 -9 57 -27 80zM375 229 -c6 -11 9 -24 9 -37s-3 -27 -9 -38l-30 12c4 8 7 17 7 26s-3 18 -7 26z" /> - <glyph glyph-name="ion-android-wifi" unicode="" horiz-adv-x="512" -d="M333 181c20 -8 38 -20 54 -34l-54 -61c-21 16 -48 26 -77 26s-56 -10 -77 -26l-54 61c16 14 34 26 54 34c24 10 50 16 77 16s53 -6 77 -16zM256 96c24 0 47 -8 66 -22l-66 -74l-66 74c19 14 42 22 66 22zM372 269c29 -12 56 -28 80 -49l-55 -61c-38 34 -87 54 -141 54 -s-103 -21 -141 -54l-55 61c24 21 51 37 80 49c37 16 76 24 116 24s79 -8 116 -24zM256 384c98 0 188 -36 256 -96l-50 -56c-55 48 -127 77 -206 77s-151 -29 -206 -77l-50 56c68 60 158 96 256 96z" /> +d="M160 128c-38 0 -69 31 -69 69v150c0 38 31 69 69 69s69 -31 69 -69v-150c0 -38 -31 -69 -69 -69zM281 203h39c0 -78 -62 -142 -137 -153v-82h-46v82c-75 10 -137 75 -137 153h39c0 -69 58 -116 121 -116s121 47 121 116z" /> + <glyph glyph-name="ion-android-more-horizontal" unicode="" horiz-adv-x="320" +d="M40 232c22 0 40 -18 40 -40s-18 -40 -40 -40s-40 18 -40 40s18 40 40 40zM280 232c22 0 40 -18 40 -40s-18 -40 -40 -40s-40 18 -40 40s18 40 40 40zM160 232c22 0 40 -18 40 -40s-18 -40 -40 -40s-40 18 -40 40s18 40 40 40z" /> + <glyph glyph-name="ion-android-more-vertical" unicode="" horiz-adv-x="80" +d="M80 312c0 -22 -18 -40 -40 -40s-40 18 -40 40s18 40 40 40s40 -18 40 -40zM80 72c0 -22 -18 -40 -40 -40s-40 18 -40 40s18 40 40 40s40 -18 40 -40zM80 192c0 -22 -18 -40 -40 -40s-40 18 -40 40s18 40 40 40s40 -18 40 -40z" /> + <glyph glyph-name="ion-android-navigate" unicode="" horiz-adv-x="320" +d="M160 384l160 -369l-15 -15l-145 64l-145 -64l-15 15z" /> + <glyph glyph-name="ion-android-notifications-none" unicode="" horiz-adv-x="352" +d="M177 328h-2c-6 0 -24 -5 -24 -5c-46 -10 -78 -53 -78 -100v-114v-13l-9 -10l-8 -8h240l-8 8l-9 10v13v114c0 47 -32 90 -78 100c0 0 -17 5 -24 5zM176 400v0c18 0 31 -13 31 -31v-15c59 -14 104 -68 104 -131v-114l41 -42v-21h-352v21l41 42v114c0 63 45 117 104 131v15 +c0 18 13 31 31 31zM217 26v0c0 -23 -18 -42 -41 -42s-41 19 -41 42h82z" /> + <glyph glyph-name="ion-android-notifications-off" unicode="" horiz-adv-x="364" +d="M182 -16c-23 0 -41 19 -41 42h82c0 -23 -18 -42 -41 -42zM57 341l295 -295v0l12 -12l-24 -24l-36 36h-298v21l41 41v115c0 23 6 44 16 63l-63 64l24 24l33 -33v0zM317 223v-94l-208 207c13 8 27 15 42 18v15c0 18 13 31 31 31s31 -13 31 -31v-15c59 -14 104 -67 104 -131 +z" /> + <glyph glyph-name="ion-android-notifications" unicode="" horiz-adv-x="352" +d="M176 -16c-23 0 -41 19 -41 42h82c0 -23 -18 -42 -41 -42zM311 109l41 -42v-21h-352v21l41 42v114c0 63 45 117 104 131v15c0 18 13 31 31 31s31 -13 31 -31v-15c59 -14 104 -68 104 -131v-114z" /> + <glyph glyph-name="ion-android-open" unicode="" horiz-adv-x="384" +d="M341 43v133h43v-133c0 -23 -20 -43 -43 -43h-298c-23 0 -43 20 -43 43v298c0 23 20 43 43 43h133v-43h-133v-298h298zM224 384h160v-160h-43v87l-215 -215l-30 30l215 215h-87v43z" /> + <glyph glyph-name="ion-android-options" unicode="" +d="M0 32v32h272v-32h-272zM368 32v32h80v-32h-80zM352 0c0 -18 -14 -32 -32 -32v0c-18 0 -32 14 -32 32v96c0 18 14 32 32 32v0c18 0 32 -14 32 -32v-96zM0 176v32h80v-32h-80zM176 176v32h272v-32h-272zM160 144c0 -18 -14 -32 -32 -32v0c-18 0 -32 14 -32 32v96 +c0 18 14 32 32 32v0c18 0 32 -14 32 -32v-96zM0 320v32h272v-32h-272zM368 320v32h80v-32h-80zM352 288c0 -18 -14 -32 -32 -32v0c-18 0 -32 14 -32 32v96c0 18 14 32 32 32v0c18 0 32 -14 32 -32v-96z" /> + <glyph glyph-name="ion-android-people" unicode="" +d="M305 216c-34 0 -61 27 -61 60s27 60 61 60s62 -27 62 -60s-28 -60 -62 -60zM143 216c-34 0 -62 27 -62 60s28 60 62 60s61 -27 61 -60s-27 -60 -61 -60zM143 172c48 0 145 -23 145 -70v-54h-288v54c0 47 95 70 143 70zM305 161c48 0 143 -12 143 -59v-54h-128v54 +c0 30 -9 41 -32 58c7 1 11 1 17 1z" /> + <glyph glyph-name="ion-android-person-add" unicode="" horiz-adv-x="480" +d="M288 192c-53 0 -96 43 -96 96s43 96 96 96s96 -43 96 -96s-43 -96 -96 -96zM288 144c64 0 192 -32 192 -96v-48h-384v48c0 64 128 96 192 96zM96 224h64v-32h-64v-64h-32v64h-64v32h64v64h32v-64z" /> + <glyph glyph-name="ion-android-person" unicode="" horiz-adv-x="384" +d="M192 192c-53 0 -96 43 -96 96s43 96 96 96s96 -43 96 -96s-43 -96 -96 -96zM192 144c64 0 192 -32 192 -96v-48h-384v48c0 64 128 96 192 96z" /> + <glyph glyph-name="ion-android-phone-landscape" unicode="" +d="M448 89c0 -23 -19 -41 -41 -41h-366c-22 0 -41 18 -41 41v206c0 23 19 41 41 41h366c22 0 41 -18 41 -41v-206zM80 84h288v216h-288v-216z" /> + <glyph glyph-name="ion-android-phone-portrait" unicode="" horiz-adv-x="288" +d="M247 416c23 0 41 -19 41 -41v-366c0 -22 -18 -41 -41 -41h-206c-23 0 -41 19 -41 41v366c0 22 18 41 41 41h206zM252 48v288h-216v-288h216z" /> + <glyph glyph-name="ion-android-pin" unicode="" horiz-adv-x="320" +d="M160 416c88 0 160 -71 160 -157c0 -118 -160 -291 -160 -291s-160 173 -160 291c0 86 72 157 160 157zM160 203c32 0 57 25 57 56s-25 56 -57 56s-57 -25 -57 -56s25 -56 57 -56z" /> + <glyph glyph-name="ion-android-plane" unicode="" horiz-adv-x="384" +d="M384 112l-160 48v-114l48 -31v-31l-80 16l-80 -16v31l48 31v114l-160 -48v40l160 104v113c0 18 15 31 32 31s32 -13 32 -31v-113l160 -104v-40z" /> + <glyph glyph-name="ion-android-playstore" unicode="" horiz-adv-x="416" +d="M416 296c-19 -214 -13 -312 -13 -312h-390s6 96 -13 312h104c0 57 47 104 104 104s104 -47 104 -104h104zM208 374c-43 0 -78 -35 -78 -78h156c0 43 -35 78 -78 78zM156 50l143 85l-143 84v-169z" /> + <glyph glyph-name="ion-android-print" unicode="" horiz-adv-x="416" +d="M352 288c35 0 64 -29 64 -64v-139h-80v-85h-256v85h-80v139c0 35 29 64 64 64h288zM304 32v128h-192v-128h192zM336 384v0v-80h-256v80h256z" /> + <glyph glyph-name="ion-android-radio-button-off" unicode="" horiz-adv-x="416" +d="M208 400c114 0 208 -94 208 -208s-94 -208 -208 -208s-208 94 -208 208s94 208 208 208zM208 26c92 0 166 74 166 166s-74 166 -166 166s-166 -74 -166 -166s74 -166 166 -166z" /> + <glyph glyph-name="ion-android-radio-button-on" unicode="" horiz-adv-x="416" +d="M208 296c57 0 104 -47 104 -104s-47 -104 -104 -104s-104 47 -104 104s47 104 104 104zM208 400c114 0 208 -94 208 -208s-94 -208 -208 -208s-208 94 -208 208s94 208 208 208zM208 26c92 0 166 74 166 166s-74 166 -166 166s-166 -74 -166 -166s74 -166 166 -166z" /> + <glyph glyph-name="ion-android-refresh" unicode="" horiz-adv-x="352" +d="M176 60c56 0 104 34 123 84h46c-21 -74 -88 -128 -169 -128c-98 0 -176 79 -176 176s79 176 176 176c48 0 92 -20 124 -52l52 52v-154h-154l70 70c-23 24 -56 40 -92 40c-73 0 -132 -59 -132 -132s59 -132 132 -132z" /> + <glyph glyph-name="ion-android-remove-circle" unicode="" horiz-adv-x="416" +d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM315 171v42h-214v-42h214z" /> + <glyph glyph-name="ion-android-remove" unicode="" horiz-adv-x="320" +d="M0 171v42h320v-42h-320z" /> + <glyph glyph-name="ion-android-restaurant" unicode="" horiz-adv-x="415" +d="M116 168l-91 89c-34 33 -34 86 0 119l153 -148zM264 206l-33 -31l150 -145l-30 -30l-150 146l-150 -146l-30 30s163 159 211 207c-15 32 -4 77 31 111c41 40 101 49 132 17c33 -31 24 -89 -17 -129c-34 -34 -80 -45 -114 -30z" /> + <glyph glyph-name="ion-android-sad" unicode="" horiz-adv-x="416" +d="M208 160c45 0 83 -26 102 -64h-204c19 38 57 64 102 64zM208 400c114 0 208 -94 208 -208s-93 -208 -208 -208s-208 94 -208 208s93 208 208 208zM208 26c92 0 166 74 166 166s-74 166 -166 166s-166 -74 -166 -166s74 -166 166 -166zM281 213c-18 0 -31 13 -31 31 +s13 31 31 31s31 -13 31 -31s-13 -31 -31 -31zM135 213c-18 0 -31 13 -31 31s13 31 31 31s31 -13 31 -31s-13 -31 -31 -31z" /> + <glyph glyph-name="ion-android-search" unicode="" horiz-adv-x="384" +d="M274 143l110 -110l-33 -33l-109 110v17l-7 6c-25 -21 -58 -34 -93 -34c-79 0 -142 63 -142 142s63 143 141 143c79 0 142 -64 142 -143c0 -36 -13 -68 -34 -93l7 -5h18zM142 143c55 0 99 43 99 98s-44 99 -99 99s-98 -44 -98 -99s43 -98 98 -98z" /> + <glyph glyph-name="ion-android-send" unicode="" horiz-adv-x="416" +d="M0 0v149l298 43l-298 43v149l416 -192z" /> + <glyph glyph-name="ion-android-settings" unicode="" horiz-adv-x="416" +d="M366 171l47 -34c3 -3 4 -10 2 -14l-43 -71c-2 -4 -7 -7 -12 -5l-54 21c-12 -8 -23 -16 -36 -21l-8 -55c-1 -4 -6 -8 -11 -8h-85c-5 0 -10 3 -11 8l-8 55c-13 5 -25 13 -36 21l-54 -21c-4 -2 -10 1 -12 5l-43 71c-3 5 -2 11 2 14l45 34c0 7 -1 14 -1 21s1 14 1 21l-46 34 +c-3 3 -4 10 -2 14l43 71c2 4 7 7 12 5l54 -21c12 8 23 16 36 21l8 55c1 4 6 8 11 8h85c5 0 10 -4 11 -8l7 -55c13 -5 25 -13 36 -21l53 21c4 2 11 -1 13 -5l43 -71c3 -5 2 -11 -2 -14l-45 -34c0 -7 1 -14 1 -21s0 -15 -1 -21zM207 119c41 0 75 32 75 73s-34 73 -75 73 +s-74 -32 -74 -73s33 -73 74 -73z" /> + <glyph glyph-name="ion-android-share-alt" unicode="" horiz-adv-x="384" +d="M320 104c34 0 62 -28 62 -62s-28 -62 -62 -62s-62 28 -62 62c0 5 1 10 2 14l-152 88c-12 -11 -27 -17 -44 -17c-35 0 -64 29 -64 64s28 64 63 64c17 0 32 -6 44 -17l151 87c-1 5 -2 10 -2 15c0 35 29 64 64 64s64 -29 64 -64s-29 -64 -64 -64c-17 0 -32 6 -44 17 +l-151 -87c1 -5 2 -10 2 -15s-1 -10 -2 -15l153 -88c11 11 26 16 42 16z" /> + <glyph glyph-name="ion-android-share" unicode="" horiz-adv-x="384" +d="M384 200l-160 -147v88c-107 0 -171 -34 -224 -109c21 107 75 214 224 235v85z" /> + <glyph glyph-name="ion-android-star-half" unicode="" horiz-adv-x="404" +d="M404 238l-110 -96l33 -142l-125 75l-125 -75l33 142l-110 96l145 12l57 134l57 -134zM219 103l60 -36l-16 68l-5 19l15 12l53 46l-70 6l-19 2l-8 18l-27 64v-189z" /> + <glyph glyph-name="ion-android-star-outline" unicode="" horiz-adv-x="404" +d="M404 238l-110 -96l33 -142l-125 75l-125 -75l33 142l-110 96l145 12l57 134l57 -134zM219 103l60 -36l-16 68l-5 19l15 12l53 46l-70 6l-19 2l-8 18l-27 64l-27 -64l-8 -18l-19 -2l-70 -6l53 -46l15 -12l-5 -19l-16 -68l60 36l17 10z" /> + <glyph glyph-name="ion-android-star" unicode="" horiz-adv-x="404" +d="M202 75l-125 -75l33 142l-110 96l145 12l57 134l57 -134l145 -12l-110 -96l33 -142z" /> + <glyph glyph-name="ion-android-stopwatch" unicode="" horiz-adv-x="384" +d="M168 141v131h48v-131h-48zM344 278c25 -33 40 -74 40 -118c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192c44 0 85 -15 118 -40l31 30l33 -33zM298 54c28 28 44 66 44 106s-16 78 -44 106s-66 44 -106 44s-78 -16 -106 -44s-44 -66 -44 -106 +s16 -78 44 -106s66 -44 106 -44s78 16 106 44zM128 368v48h128v-48h-128z" /> + <glyph glyph-name="ion-android-subway" unicode="" horiz-adv-x="352" +d="M176 400c94 0 176 -10 176 -85v-214c0 -42 -33 -74 -75 -74l27 -27v-16h-256v16l27 27c-42 0 -75 32 -75 74v214c0 75 82 85 176 85zM80 64c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM160 208v96h-112v-96h112zM272 64c18 0 32 14 32 32 +s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM304 208v96h-112v-96h112z" /> + <glyph glyph-name="ion-android-sunny" unicode="" +d="M224 288c-25 0 -50 -10 -68 -28s-28 -43 -28 -68s10 -50 28 -68s43 -28 68 -28s50 10 68 28s28 43 28 68s-10 50 -28 68s-43 28 -68 28zM245 416v0v-64h-42v64h42zM374 372v0l30 -30l-38 -38l-30 30zM74 372v0l38 -38l-30 -30l-38 38zM224 320v0c70 0 128 -58 128 -128 +s-58 -128 -128 -128s-128 58 -128 128s58 128 128 128zM448 213v0v-42h-64v42h64zM64 213v0v-42h-64v42h64zM366 80v0l38 -38l-30 -30l-38 38zM82 80v0l30 -30l-38 -38l-30 30zM245 32v0v-64h-42v64h42z" /> + <glyph glyph-name="ion-android-sync" unicode="" horiz-adv-x="320" +d="M160 355c88 0 160 -73 160 -163c0 -32 -9 -62 -25 -87l-29 30c9 17 14 37 14 57c0 67 -54 122 -120 122v-61l-80 82l80 81v-61zM160 70v61l80 -82l-80 -81v61c-88 0 -160 73 -160 163c0 32 9 63 25 87l29 -30c-9 -17 -14 -37 -14 -57c0 -67 54 -122 120 -122z" /> + <glyph glyph-name="ion-android-textsms" unicode="" horiz-adv-x="384" +d="M344 384c22 0 40 -18 40 -40v-240c0 -22 -18 -40 -40 -40h-280l-64 -64v344c0 22 10 40 32 40h312zM134 206v40h-38v-40h38zM211 206v40h-38v-40h38zM288 206v40h-38v-40h38z" /> + <glyph glyph-name="ion-android-time" unicode="" horiz-adv-x="426" +d="M213 405c117 0 213 -96 213 -213s-95 -213 -213 -213s-213 96 -213 213s95 213 213 213zM213 22c94 0 170 76 170 170s-76 170 -170 170s-170 -76 -170 -170s76 -170 170 -170zM224 298v-111l96 -57l-16 -26l-112 67v127h32z" /> + <glyph glyph-name="ion-android-train" unicode="" horiz-adv-x="352" +d="M0 101v214c0 75 82 85 176 85s176 -10 176 -85v-214c0 -42 -33 -74 -75 -74l27 -27v-16h-256v16l27 27c-42 0 -75 32 -75 74zM176 72c22 0 40 18 40 40s-18 40 -40 40s-40 -18 -40 -40s18 -40 40 -40zM304 224v96h-256v-96h256z" /> + <glyph glyph-name="ion-android-unlock" unicode="" horiz-adv-x="320" +d="M280 262c22 0 40 -18 40 -40v-200c0 -22 -18 -40 -40 -40h-240c-22 0 -40 18 -40 40v200c0 22 18 40 40 40h182v40v0c0 34 -28 62 -62 62s-62 -28 -62 -62h-38c0 55 45 100 100 100s100 -45 100 -100v-40h20zM160 80c22 0 40 18 40 40s-18 40 -40 40s-40 -18 -40 -40 +s18 -40 40 -40z" /> + <glyph glyph-name="ion-android-upload" unicode="" horiz-adv-x="480" +d="M387 231c52 -3 93 -46 93 -99c0 -55 -45 -100 -100 -100h-260c-66 0 -120 54 -120 120c0 62 47 113 107 119c25 48 75 81 133 81c73 0 133 -52 147 -121zM272 172h68l-100 100l-100 -100h68v-76h64v76z" /> + <glyph glyph-name="ion-android-volume-down" unicode="" horiz-adv-x="288" +d="M0 256h85l107 112v-352l-107 112h-85v128zM288 192c0 -38 -21 -73 -53 -88v177c32 -16 53 -51 53 -89z" /> + <glyph glyph-name="ion-android-volume-mute" unicode="" horiz-adv-x="192" +d="M0 256h85l107 112v-352l-107 112h-85v128z" /> + <glyph glyph-name="ion-android-volume-off" unicode="" horiz-adv-x="384" +d="M342 192c0 69 -45 128 -107 147v45c85 -20 149 -99 149 -192c0 -35 -8 -68 -24 -96l-32 32c9 19 14 41 14 64zM192 368v-104l-51 51zM357 51v0l24 -24l-24 -24l-40 40c-23 -21 -51 -36 -82 -43v45c19 6 37 15 52 28l-95 95v-152l-107 112h-85v128h85l9 10l-91 91l24 24z +M288 192c0 -7 0 -15 -2 -22l-51 51v60c32 -16 53 -51 53 -89z" /> + <glyph glyph-name="ion-android-volume-up" unicode="" horiz-adv-x="384" +d="M0 256h85l107 112v-352l-107 112h-85v128zM288 192c0 -38 -21 -73 -53 -88v177c32 -16 53 -51 53 -89zM235 384c85 -20 149 -99 149 -192s-64 -172 -149 -192v45c62 19 106 78 106 147s-44 128 -106 147v45z" /> + <glyph glyph-name="ion-android-walk" unicode="" horiz-adv-x="272" +d="M168 336c-22 0 -40 18 -40 40s18 40 40 40s40 -18 40 -40s-18 -40 -40 -40zM168 216l-20 38l-20 -62l57 -96v-128h-38v96l-50 68l-57 -164h-40l81 320l-41 -16v-80h-40v112l111 38c4 1 10 1 13 1c13 0 23 -6 31 -18l45 -69h72v-40h-104z" /> + <glyph glyph-name="ion-android-warning" unicode="" +d="M0 -16l224 416l224 -416h-448zM248 48v48h-48v-48h48zM248 128v96h-48v-96h48z" /> + <glyph glyph-name="ion-android-watch" unicode="" horiz-adv-x="320" +d="M320 192c0 -51 -24 -96 -61 -125l-19 -115h-160l-19 115c-37 29 -61 74 -61 125s24 96 61 125l19 115h160l19 -115c37 -29 61 -74 61 -125zM40 192c0 -66 54 -120 120 -120s120 54 120 120s-54 120 -120 120s-120 -54 -120 -120z" /> + <glyph glyph-name="ion-android-wifi" unicode="" horiz-adv-x="416" +d="M208 219c23 0 42 -18 42 -41s-19 -41 -42 -41s-42 18 -42 41s19 41 42 41zM333 178c0 -45 -26 -85 -63 -107l-20 36c25 14 41 40 41 71c0 45 -37 82 -83 82s-83 -37 -83 -82c0 -31 16 -57 41 -71l-20 -36c-37 22 -63 62 -63 107c0 68 56 124 125 124s125 -56 125 -124z +M208 384c114 0 208 -93 208 -206c0 -76 -42 -142 -104 -178l-21 36c50 28 83 81 83 142c0 91 -74 165 -166 165s-166 -74 -166 -165c0 -61 33 -113 83 -142l-21 -36c-62 36 -104 102 -104 178c0 113 94 206 208 206z" /> <glyph glyph-name="ion-aperture" unicode="" d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM360 56c36 36 56 85 56 136s-20 100 -56 136s-85 56 -136 56s-100 -20 -136 -56s-56 -85 -56 -136s20 -100 56 -136s85 -56 136 -56s100 20 136 56zM168 342l56 -86h-147 c17 40 50 71 91 86zM381 160h-102l72 129c21 -27 33 -60 33 -97c0 -11 -1 -22 -3 -32zM328 314l-49 -90l-78 126c8 1 15 2 23 2c40 0 76 -14 104 -38zM67 224h102l-72 -129c-21 27 -33 60 -33 97c0 11 1 22 3 32zM280 42l-56 86h147c-17 -40 -50 -71 -91 -86zM120 70l49 90 @@ -262,6 +380,13 @@ s-16 -34 -27 -46s-24 -22 -38 -28s-29 -10 -45 -10s-29 4 -39 12s-15 17 -15 29h-3c- l-24 -113c-1 -6 -2 -12 -3 -19s-2 -13 -2 -19c0 -7 1 -13 4 -18s7 -7 15 -7c16 0 29 9 39 26s16 40 16 68c0 24 -4 45 -12 64s-20 34 -34 47s-32 23 -52 29s-41 9 -65 9c-26 0 -49 -4 -70 -13s-39 -22 -54 -38s-27 -34 -35 -56c-8 -21 -13 -44 -13 -69c0 -26 4 -51 13 -72 s21 -39 37 -54s35 -27 57 -35s46 -12 72 -12c33 0 61 6 85 16s45 25 65 43zM231 260c-10 0 -18 -2 -25 -8s-14 -13 -19 -22s-8 -18 -11 -28s-4 -20 -4 -30c0 -5 0 -10 1 -16c1 -5 3 -10 6 -15s7 -8 12 -11s11 -5 19 -5c11 0 20 3 28 8s14 13 19 21s9 16 11 26s3 19 3 27 c0 6 0 13 -1 19s-4 12 -7 17s-7 9 -12 12s-12 5 -20 5z" /> + <glyph glyph-name="ion-backspace-outline" unicode="" horiz-adv-x="512" +d="M413 116c2 -2 3 -4 3 -6s-1 -4 -3 -6l-21 -22c-2 -2 -4 -2 -6 -2s-4 0 -6 2l-76 77l-76 -77c-2 -2 -4 -2 -6 -2s-4 0 -6 2l-21 22c-2 2 -3 4 -3 6s1 4 3 6l76 76l-77 76c-3 3 -3 9 0 12l22 22c2 2 4 2 6 2s4 0 6 -2l76 -76l76 76c2 2 4 2 6 2s4 0 6 -2l22 -22 +c3 -3 3 -9 0 -12l-77 -76zM499 354c9 -9 13 -20 13 -33v-256c0 -27 -20 -49 -46 -49h-298c-13 0 -24 3 -34 9c-9 5 -16 11 -23 20v0l-1 1l-110 146l110 148c14 19 34 28 58 28h298c13 0 24 -5 33 -14zM480 65v256c0 9 -5 15 -14 15h-298c-11 0 -22 -3 -32 -16l-96 -128 +l96 -128c8 -10 17 -16 32 -16h298c9 0 14 8 14 17z" /> + <glyph glyph-name="ion-backspace" unicode="" horiz-adv-x="512" +d="M499 354c9 -9 13 -20 13 -33v-256c0 -27 -20 -49 -46 -49h-298c-13 0 -24 3 -34 9c-9 5 -16 11 -23 20v0l-1 1l-110 146l110 148c14 19 34 28 58 28h298c13 0 24 -5 33 -14zM413 116l-76 76l77 76c3 3 3 9 0 12l-22 22c-2 2 -4 2 -6 2s-4 0 -6 -2l-76 -76l-76 76 +c-2 2 -4 2 -6 2s-4 0 -6 -2l-22 -22c-3 -3 -3 -9 0 -12l77 -76l-76 -76c-2 -2 -3 -4 -3 -6s1 -4 3 -6l21 -22c2 -2 4 -2 6 -2s4 0 6 2l76 77l76 -77c2 -2 4 -2 6 -2s4 0 6 2l21 22c2 2 3 4 3 6s-1 4 -3 6z" /> <glyph glyph-name="ion-bag" unicode="" d="M416 288l32 -320h-448l32 320h64v4c0 68 56 124 124 124h8c68 0 124 -56 124 -124v-4h64zM128 292v-4h192v4c0 51 -41 92 -92 92v0h-8c-51 0 -92 -41 -92 -92zM36 0h376l-25 256h-35v-36c10 -6 16 -16 16 -28c0 -18 -14 -32 -32 -32s-32 14 -32 32c0 12 6 22 16 28v36 h-192v-36c10 -6 16 -16 16 -28c0 -18 -14 -32 -32 -32s-32 14 -32 32c0 12 6 22 16 28v36h-35z" /> @@ -276,10 +401,8 @@ d="M438 256c6 0 10 -4 10 -10v-108c0 -6 -4 -10 -10 -10h-37v-54c0 -6 -4 -10 -10 -1 <glyph glyph-name="ion-battery-low" unicode="" d="M10 64c-6 0 -10 4 -10 10v236c0 6 4 10 10 10h381c6 0 10 -4 10 -10v-54h37c6 0 10 -4 10 -10v-108c0 -6 -4 -10 -10 -10h-37v-54c0 -6 -4 -10 -10 -10h-381zM369 288h-209l32 -192h177v32v32h32h15v64h-15h-32v32v32z" /> <glyph glyph-name="ion-beaker" unicode="" horiz-adv-x="384" -d="M375 52c6 -9 9 -20 9 -32c0 -28 -16 -52 -63 -52h-258c-47 0 -63 24 -63 52c0 12 3 23 9 32l49 73l48 73l2 3c13 20 20 45 20 71v92s-15 30 -15 39s6 13 15 13h127c9 0 16 -3 16 -12s-15 -20 -15 -40v-92c0 -26 6 -51 19 -71l3 -4l48 -72zM345 7c3 3 7 8 7 14 -c0 5 -2 10 -4 14l-49 72v0v1l-48 72s-2 3 -3 5c-16 26 -24 56 -24 87v74c0 7 0 18 1 22c5 18 0 16 -9 16h-47c-9 0 -15 2 -10 -16c1 -4 1 -16 1 -22v-75c0 -32 -9 -61 -25 -86l-3 -5l-47 -73v0v0l-49 -73c-2 -4 -4 -9 -4 -14c0 -6 3 -10 6 -13c4 -4 12 -7 25 -7h258 -c13 0 20 3 24 7zM327 37l1 -1c1 -2 2 -5 2 -7c0 -7 -6 -13 -14 -13v0h-16h-30h-157h-29h-16v0c-7 0 -14 5 -14 13c0 3 1 6 3 8l8 13l1 1v0v1l16 23l42 66l1 1v0v0l12 18h109l14 -20v0l1 -1l1 -2l40 -62l12 -18zM238 106c2 -1 4 -2 6 -2s3 0 5 2c1 2 3 4 3 6s-1 4 -3 6 -c-1 2 -3 2 -5 2s-4 0 -6 -2c-1 -2 -2 -4 -2 -6s0 -4 2 -6zM274 50c2 -2 5 -4 7 -4c1 0 3 0 4 1c4 2 4 7 2 11l-23 36c-1 2 -4 4 -7 4c-2 0 -3 0 -4 -1c-4 -2 -5 -7 -3 -11zM124 141v0c-4 -5 0 0 0 0z" /> +d="M80 256h240v-224c0 -9 -7 -16 -16 -16h-208c-9 0 -16 7 -16 16v224zM296 104v48c0 4 -4 8 -8 8s-8 -4 -8 -8v-48c0 -4 4 -8 8 -8s8 4 8 8zM288 176c4 0 8 4 8 8s-4 8 -8 8s-8 -4 -8 -8s4 -8 8 -8zM381 416c3 0 3 -2 3 -3s-2 -3 -3 -5s-13 -20 -13 -40v-336 +c0 -35 -29 -64 -64 -64h-208c-35 0 -64 29 -64 64v307c0 32 -2 33 -32 37c0 12 11 40 65 40h316zM336 368c0 5 0 16 1 16h-273c-1 0 -3 0 -4 -1c5 -7 4 -32 4 -44v-307c0 -18 14 -32 32 -32h210c17 0 30 14 30 32v336z" /> <glyph glyph-name="ion-beer" unicode="" d="M384 288c35 0 64 -29 64 -64v-96c0 -35 -29 -64 -64 -64h-32v-80c0 -9 -7 -16 -16 -16h-256c-9 0 -16 7 -16 16v223c-26 0 -48 22 -48 48v54v1c-10 11 -16 26 -16 42c0 35 29 64 64 64c18 0 34 -8 46 -20c10 12 26 20 43 20c14 0 27 -6 37 -14c12 9 26 14 42 14 c17 0 34 -6 46 -16c11 10 26 16 42 16c35 0 64 -29 64 -64c0 -24 -18 -44 -32 -48v-16h32zM296 144c4 0 8 3 8 8v0v48c0 4 -4 8 -8 8s-8 -4 -8 -8v-48c0 -3 2 -6 4 -7c1 -1 2 -1 4 -1zM303 220c1 2 1 4 1 6s-1 4 -3 5s-4 1 -6 1s-4 -2 -5 -4s-2 -4 -2 -6s2 -4 4 -5 @@ -299,6 +422,10 @@ c-10 -10 -25 -10 -35 0s-10 25 0 35c2 2 3 3 5 4zM288 320c0 -32 -9 -58 -50 -86c-37 c21 14 38 31 47 49c5 -15 5 -48 0 -64zM88 288c-6 4 -9 14 -8 27c2 22 34 39 32 69c14 2 31 -3 42 -24c-5 -11 -15 -21 -28 -34s-26 -22 -38 -38z" /> <glyph glyph-name="ion-bookmark" unicode="" horiz-adv-x="192" d="M184 384c4 0 8 -4 8 -8v-56h-192v56c0 4 4 8 8 8h176zM0 0v304h192v-304l-96 96z" /> + <glyph glyph-name="ion-bowtie" unicode="" +d="M192 236c0 0 8 5 20 7c21 4 39 5 47 -9c10 -17 19 -53 17 -85c-1 -17 -5 -22 -5 -22s-15 -10 -47 -7c-35 3 -40 15 -40 15s5 12 8 43s0 58 0 58zM152 163c-17 -4 -38 -10 -38 -10s45 4 64 9c-4 -21 -10 -34 -10 -34s-83 -80 -116 -80c-28 0 -52 68 -52 144s26 144 52 144 +c35 0 106 -57 128 -97c0 0 3 -16 2 -32c-10 5 -24 10 -44 14c-28 6 -42 3 -42 3s18 -4 57 -17c15 -5 22 -8 29 -10c0 -3 -1 -7 -1 -10c0 -5 0 -10 -1 -15c-5 -2 -15 -6 -28 -9zM396 336c26 0 52 -68 52 -144s-24 -144 -52 -144c-37 0 -104 68 -112 79c0 0 4 5 5 22v9 +c16 -7 70 -13 70 -13s-21 6 -40 11c-13 4 -25 8 -30 10c-1 11 -2 23 -4 33c17 11 69 34 69 34s-15 -2 -35 -9c-14 -5 -29 -11 -37 -14c-3 10 -7 18 -10 24c0 1 -1 4 -1 4v1c22 40 89 97 125 97z" /> <glyph glyph-name="ion-briefcase" unicode="" d="M240 176v8h208v-176c0 -4 -4 -8 -8 -8h-432c-4 0 -8 4 -8 8v176h208v-8h32zM440 304c4 0 8 -4 8 -8v-96h-208v8h-32v-8h-208v96c0 4 4 8 8 8h120v31c1 28 22 49 51 49h90c30 0 50 -21 51 -49v-31h120zM288 332v1c0 10 -9 19 -19 19h-90c-10 0 -19 -9 -19 -19v-1v-1v-27 h128v27v1z" /> @@ -324,8 +451,8 @@ h192v-16h-192zM64 96v16h96v-16h-96zM320 96v48h64v-48h-64z" /> d="M0 352h512v-256h-512v256zM193 128c-20 23 -33 58 -33 96s13 73 33 96h-97c0 -35 -29 -64 -64 -64v-80c27 0 48 -21 48 -48h113zM298 187c3 4 4 9 4 15c0 3 0 5 -1 8s-2 6 -4 8s-4 4 -7 6s-6 4 -10 5c-1 0 -4 1 -7 2s-5 0 -8 1v31c2 -1 5 -2 7 -3c4 -3 6 -7 7 -13h20 c0 5 -2 9 -4 13s-5 8 -9 11s-9 5 -14 6c-2 1 -5 2 -7 2v9h-18v-9c-2 0 -4 -1 -6 -2c-5 -1 -10 -2 -14 -5s-7 -6 -9 -10s-4 -9 -4 -14c0 -3 0 -5 1 -8s2 -5 4 -7s5 -5 8 -7s7 -4 12 -5c3 -1 6 0 8 -1v-35c-3 1 -6 2 -9 4s-5 4 -6 7s-2 6 -2 9h-20c0 -5 2 -11 4 -16 c3 -5 6 -8 10 -11s9 -6 15 -7c3 -1 5 -2 8 -2v-9h18v9c3 0 6 1 9 2c5 1 10 2 14 5s7 7 10 11zM480 176v80c-35 0 -64 29 -64 64h-97c20 -23 33 -58 33 -96s-13 -73 -33 -96h113c0 27 22 48 48 48zM64 224c0 21 11 32 32 32s32 -11 32 -32s-11 -32 -32 -32s-32 11 -32 32z -M384 224c0 21 11 32 32 32s32 -11 32 -32s-11 -32 -32 -32s-32 11 -32 32zM273 213c2 -1 4 -2 6 -4s3 -5 3 -9c0 -2 0 -4 -1 -6s-2 -4 -4 -5s-5 -3 -8 -4c-1 0 -2 -1 -4 -1v31c3 -1 6 -1 8 -2zM236 257c1 2 3 3 5 4s4 2 6 2v-26c-4 1 -7 3 -9 5s-4 4 -4 8c0 3 1 5 2 7zM0 64 -v16h512v-16h-512zM0 32v16h512v-16h-512z" /> +M384 224c0 21 11 32 32 32s32 -11 32 -32s-11 -32 -32 -32s-32 11 -32 32zM273 213c2 -1 4 -2 6 -4s3 -5 3 -9c0 -2 0 -4 -1 -6s-2 -4 -4 -5s-5 -3 -8 -4c-1 0 -2 -1 -4 -1v31c3 -1 6 -1 8 -2zM236 257c1 2 3 3 5 4s4 2 6 2v-26c-4 1 -7 3 -9 5s-4 4 -4 8c0 3 1 5 2 7zM0 32 +v32h512v-32h-512z" /> <glyph glyph-name="ion-chatbox-working" unicode="" horiz-adv-x="416" d="M76 48c-42 0 -76 31 -76 71v209c0 40 34 72 76 72h264c42 0 76 -32 76 -72v-209c0 -40 -34 -71 -76 -71h-4v-64s-79 54 -86 59s-7 5 -21 5h-153zM304 256c-18 0 -32 -14 -32 -32s14 -32 32 -32s32 14 32 32s-14 32 -32 32zM208 256c-18 0 -32 -14 -32 -32s14 -32 32 -32 s32 14 32 32s-14 32 -32 32zM112 256c-18 0 -32 -14 -32 -32s14 -32 32 -32s32 14 32 32s-14 32 -32 32z" /> @@ -358,14 +485,13 @@ d="M170 192v0v0l-167 174c-4 4 -4 12 0 16l30 30c4 4 12 5 16 1l204 -213c2 -2 3 -5 <glyph glyph-name="ion-chevron-up" unicode="" d="M224 234l-174 -167c-4 -4 -12 -4 -16 0l-31 30c-4 4 -4 12 0 16l213 204c2 2 5 3 8 3s6 -1 8 -3l213 -204c4 -4 4 -12 0 -16l-31 -30c-4 -4 -12 -4 -16 0l-174 167v0v0z" /> <glyph glyph-name="ion-clipboard" unicode="" horiz-adv-x="352" -d="M80 288c2 20 10 35 28 40l1 1c12 3 21 7 21 20v21c0 26 20 46 46 46s46 -20 46 -46v-21c0 -13 9 -18 21 -21h1c18 -5 26 -20 28 -40h-192zM176 384c-8 0 -14 -6 -14 -14s6 -14 14 -14s14 6 14 14s-6 14 -14 14zM325 385c15 0 27 -13 27 -29v-360c0 -16 -12 -28 -27 -28 -h-149h-149c-15 0 -27 12 -27 28v360c0 16 12 29 27 29h74v-15c0 -11 -9 -18 -19 -18h-37c-7 0 -13 -5 -13 -12v-328c0 -6 6 -12 12 -12h264c6 0 12 6 12 12v328c0 7 -6 12 -13 12h-37c-10 0 -19 7 -19 18v15h74zM64 240v16h112v-16h-112zM64 144v16h160v-16h-160zM64 48v16 -h129v-16h-129zM64 96v16h176v-16h-176zM64 192v16h208v-16h-208z" /> +d="M80 288c2 20 10 35 28 40l1 1c12 3 21 7 21 20v21c0 26 21 46 46 46s46 -20 46 -46v-21c0 -13 9 -18 21 -21h2c18 -5 25 -20 27 -40h-192zM176 384c-8 0 -13 -6 -13 -14s5 -14 13 -14s14 6 14 14s-6 14 -14 14zM325 384c15 0 27 -12 27 -28v-360c0 -16 -12 -28 -27 -28 +h-149h-148c-15 0 -28 12 -28 28v360c0 16 13 28 28 28h73v-13c0 -11 -9 -19 -19 -19h-37c-7 0 -12 -6 -12 -13v-327c0 -6 5 -12 11 -12h265c6 0 11 6 11 12v327c0 7 -5 13 -12 13h-37c-10 0 -20 8 -20 19v13h74zM64 224v32h112v-32h-112zM64 32v32h160v-32h-160zM64 96v32 +h129v-32h-129zM64 160v32h208v-32h-208z" /> <glyph glyph-name="ion-clock" unicode="" -d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM393 283c-2 3 -3 6 -5 9zM324 356c-3 2 -6 3 -9 5zM133 361c-3 -2 -6 -3 -9 -5zM60 292c-2 -3 -3 -6 -5 -9zM55 101c2 -3 3 -6 5 -9zM124 28c3 -2 6 -3 9 -5zM315 23 -c3 2 6 3 9 5zM360 56c10 10 18 21 26 33l-27 16l8 14l27 -16c13 25 21 52 22 81h-32v16h32c-1 29 -9 56 -22 81l-28 -16l-8 14l28 16c-8 12 -16 23 -26 33s-21 18 -33 26l-16 -27l-14 8l16 27c-25 13 -52 21 -81 22v-32h-16v32c-29 -1 -56 -9 -81 -22l16 -28l-14 -8l-16 28 -c-12 -8 -23 -16 -33 -26s-18 -21 -26 -33l27 -16l-8 -14l-27 16c-13 -25 -21 -52 -22 -81h32v-16h-32c1 -29 9 -56 22 -81l28 16l8 -14l-28 -16c8 -12 16 -23 26 -33s21 -18 33 -26l16 27l14 -8l-16 -27c25 -13 52 -21 81 -22v32h16v-32c29 1 56 9 81 22l-16 27l14 8l16 -27 -c12 8 23 16 33 26zM393 101l-5 -9c2 3 3 6 5 9zM368 199v-16h-113c-4 -13 -17 -23 -31 -23c-7 0 -15 3 -20 7l-70 -71l-6 6l71 70c-4 6 -7 13 -7 20c0 12 6 22 16 28v84h32v-84c8 -4 13 -12 15 -21h113z" /> +d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM360 56c10 10 19 21 26 33l-27 16l8 14l27 -16c13 25 21 52 22 81h-32v16h32c-1 29 -9 56 -22 81l-27 -16l-8 14l27 16c-7 12 -16 23 -26 33s-21 19 -33 26l-16 -27l-14 8 +l16 27c-25 13 -52 21 -81 22v-32h-16v32c-29 -1 -56 -9 -81 -22l16 -27l-14 -8l-16 27c-12 -7 -23 -16 -33 -26s-19 -21 -26 -33l27 -16l-8 -14l-27 16c-13 -25 -21 -52 -22 -81h32v-16h-32c1 -29 9 -56 22 -81l27 16l8 -14l-27 -16c7 -12 16 -23 26 -33s21 -19 33 -26 +l16 27l14 -8l-16 -27c25 -13 52 -21 81 -22v32h16v-32c29 1 56 9 81 22l-16 27l14 8l16 -27c12 7 23 16 33 26zM368 207v-32h-117c-6 -9 -16 -15 -27 -15c-18 0 -32 14 -32 32c0 12 6 22 16 28v68h32v-68c5 -3 9 -8 12 -13h116z" /> <glyph glyph-name="ion-close-circled" unicode="" d="M224 415c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM332 116l-75 75l76 75c3 3 3 9 0 12l-22 21c-2 2 -4 3 -6 3s-3 -1 -5 -3l-76 -74l-76 74c-2 2 -3 3 -5 3s-4 -1 -6 -3l-21 -21c-3 -3 -3 -9 0 -12l76 -75l-76 -76 c-2 -1 -2 -3 -2 -5s0 -4 2 -6l21 -22c2 -2 4 -2 6 -2s4 0 6 2l75 76l76 -75c2 -2 3 -3 5 -3s4 1 6 3l21 21c2 1 3 4 3 6s-1 4 -3 6z" /> @@ -406,6 +532,8 @@ s9 5 9 10v150z" /> d="M0 32v64h64v-64h-64zM96 32v128h64v-128h-64zM192 32v224h64v-224h-64zM288 32v320h64v-320h-64z" /> <glyph glyph-name="ion-contrast" unicode="" d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM360 56c36 36 56 85 56 136s-20 100 -56 136s-85 56 -136 56v-384c51 0 100 20 136 56z" /> + <glyph glyph-name="ion-crop" unicode="" +d="M320 -32v48h64v-48h-64zM384 96h64v-64h-384v256h-64v64h64v64h64v-320h192v192h-176v64h240v-256z" /> <glyph glyph-name="ion-cube" unicode="" d="M435 280c7 0 13 -6 13 -12v-183c0 -9 -6 -17 -14 -22v-1l-175 -92v-1c-2 -1 -4 -1 -6 -1c-7 0 -13 6 -13 12v185c0 9 5 17 13 22v0l3 2l172 89l2 1c2 1 3 1 5 1zM422 329c0 0 8 -3 8 -9c0 -7 -8 -11 -8 -11l-183 -97l-2 -1c-4 -2 -8 -3 -13 -3s-9 1 -13 3l-2 1l-183 96 s-8 5 -8 12c0 6 8 9 8 9l181 82s11 5 17 5s17 -5 17 -5zM195 187c8 -5 13 -13 13 -22v-185c0 -6 -6 -12 -13 -12c-2 0 -4 1 -6 2v0l-175 92v1c-8 5 -14 13 -14 22v183c0 6 6 12 13 12c2 0 4 0 5 -1l2 -1l171 -89z" /> @@ -421,33 +549,36 @@ d="M287 279c1 -3 1 -5 1 -9v-244c0 -13 -9 -26 -21 -26h-243c-12 0 -24 13 -24 26v33 <glyph glyph-name="ion-drag" unicode="" horiz-adv-x="512" d="M0 272v32h512v-32h-512zM0 176v32h512v-32h-512zM0 80v32h512v-32h-512z" /> <glyph glyph-name="ion-earth" unicode="" -d="M308 321c-1 0 0 -1 -1 -1s-4 4 -3 5l1 1l1 1l2 1l1 1v1c0 1 -1 2 -1 3v2c1 1 2 1 3 1l1 -1l2 -1l1 -2c0 -1 1 -1 2 -1c2 -1 4 -2 5 -3c3 -3 5 -7 6 -11v-2c-2 -1 -3 -3 -5 -4c-1 -1 -2 -1 -3 -1c-2 0 -4 1 -5 2s-1 2 -1 3c0 2 -1 4 -1 6c0 1 -1 1 -1 1h-2s-1 -1 -2 -1z -M253 351l-1 1c0 1 0 4 1 4h1c4 1 6 3 10 4h1c1 0 2 -1 3 -2c2 -2 2 -3 0 -5v0l-1 -2c0 -1 -1 -2 -1 -3v-1h-1c-3 0 -6 1 -8 2c-2 0 -3 1 -4 2zM134 270h-5c-5 0 -10 1 -14 2h-3s-1 1 -2 1v1s1 2 2 3c1 0 1 1 2 1s2 1 3 1s2 0 3 -1l1 -1l1 -1c2 -1 4 -2 6 -2h5c1 0 1 -1 2 -1 -h1l1 -1c0 -1 0 -2 -1 -2h-2zM144 263c0 0 1 -1 2 -1s1 -1 1 -1v-4h-1v0h-1c-2 1 -5 2 -7 2h-4h-3h-1v1v0c1 0 1 1 2 1l8 4v0l1 -1c1 -1 2 0 3 -1zM224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM88 56c11 -11 24 -20 37 -28 -c-1 1 -3 2 -4 3l-7 7c-3 4 -4 9 -6 13v1c0 2 -1 4 -1 6c0 3 -2 7 -2 10v1c-1 1 -1 2 -1 3s-1 3 -1 4c0 3 1 5 1 8v3c0 3 1 5 1 8v2c-1 1 -1 3 -1 4v5s0 5 1 7c0 1 1 1 1 2v5c0 3 2 7 2 10v1c-2 1 -2 2 -3 3c-2 2 -2 4 -2 7c0 2 0 4 1 6v1h-1c-4 3 -8 6 -11 10 -c-1 2 -2 4 -4 6l-3 3s-2 3 -2 4c-1 2 -1 4 -1 6v2c-1 2 -1 4 -1 6v8s1 4 2 6c0 1 1 1 2 2c2 2 3 5 5 7l3 6c1 1 2 2 2 4c1 2 1 4 1 6v3c0 2 -1 3 -3 4l-1 1c-2 1 -4 3 -6 4v1c-1 4 -2 5 -3 9c0 1 -1 3 -1 3c-2 1 -3 3 -5 4v2v3s1 3 1 4h-1c-3 1 -6 3 -9 5c-2 1 -3 2 -4 4 -c-1 1 -2 3 -3 4c-1 2 -1 3 -1 5c0 3 2 7 2 10v2h-1v1v0c-19 -30 -29 -65 -29 -101c0 -51 20 -100 56 -136zM403 251c0 0 0 -1 1 -1v1c0 2 0 5 -1 7s-2 3 -3 4c0 0 -10 -6 -27 14s-24 16 -24 16s-2 -2 -2 -1h-1v0v-2c0 -1 -1 -2 -1 -4s-1 -6 -1 -8v-1h-1c-3 -1 -6 -1 -9 -2 -c-2 0 -4 -1 -6 0s-3 2 -4 3c-2 2 -3 3 -4 5c-2 3 -4 7 -6 10v1v0c2 1 3 2 4 3h1c1 0 3 1 4 1c2 0 3 1 5 1h3c2 2 5 2 7 4v1c2 2 3 4 5 6l1 1l-1 1l-2 4v2c0 2 1 3 1 5v2c-3 0 -6 1 -9 1c-1 2 -3 5 -4 7h-1c-2 0 -3 1 -5 1h-1c-1 1 -2 2 -2 3c-1 2 -2 3 -2 5c-1 4 0 8 0 12v0 -c3 0 7 1 10 1c-18 11 -38 20 -58 25v-1c-2 -4 -4 -6 -6 -10c-1 -1 -1 -2 -2 -2c-2 0 -4 -1 -6 -1s-2 0 -3 -1v-1c-2 -2 -4 -5 -6 -7c-3 -3 -6 -6 -9 -10v-1h-1v1c-2 1 -4 2 -5 4c-2 2 -3 4 -4 6c-2 4 -3 8 -3 12c0 1 1 1 1 1c1 3 2 7 3 10c0 1 1 1 1 2v1v2v0h-6h-3v0l4 -8 -v-1h-1c-2 -1 -3 -3 -5 -4l-1 -1l-5 -5v0c0 1 -1 1 -2 2s-3 2 -5 3v1h-6l-2 -1c-1 0 -1 -1 -2 -1h-3c-2 0 -2 0 -3 2c0 1 -1 1 -2 1h-1l-2 -1l-3 -3s-2 -1 -3 -2l-1 -1l-6 -3v-1c0 -1 -1 -1 -1 -2v-6c0 -1 1 -2 1 -3c1 -2 1 -2 3 -2h2c1 1 3 1 4 2c2 1 3 2 4 3s3 2 3 4v1 -c0 1 1 0 2 0v0h2c1 -1 3 -1 4 0c1 0 1 0 2 1l2 2s3 2 4 2c2 0 3 1 4 -1v-1l2 -2c1 0 1 -2 2 -2l2 -1c1 -1 1 -1 1 -2s-1 -1 -1 -2s-1 -2 -2 -3c0 -1 -1 -2 -1 -3l-1 -1c0 -1 0 -1 1 -1h1c1 0 2 1 3 1v0v-1c0 -2 -1 -4 -1 -6s-1 -3 -2 -5c0 -1 0 -1 -1 -2s-3 -2 -5 -2 -c-1 0 -2 1 -3 1s-2 1 -2 1c-1 1 -1 1 -2 1h-3h-1c-1 0 -1 -1 -1 -2s-2 -1 -2 -2l-1 -1h-1c-2 0 -3 -1 -5 -1h-8h-1c-3 -1 -7 -2 -10 -3c-1 0 -1 -1 -1 -1c-1 -1 -2 -1 -3 -1c-1 -1 -3 -2 -4 -2h-3h-2l-1 1c-5 -6 -18 -6 -22 -12v-1c0 -2 -1 -3 -1 -5c0 -4 0 -8 -1 -12 -c0 -1 -1 -1 -1 -2l-1 -1h-2l-1 1s-1 0 -1 1s-1 2 -1 3c-1 2 -1 3 -1 5c0 3 -2 4 -4 6c-1 1 -2 2 -3 2c-2 1 -5 1 -7 1c-1 0 -1 1 -2 1c-2 0 -4 -1 -6 -1c-8 -2 -13 -8 -18 -14v-1c-1 -3 -2 -5 -2 -8c0 -2 1 -4 1 -5c1 -2 2 -3 4 -3h5c1 0 2 1 3 1h2c1 0 1 -1 2 -2s0 -3 0 -4 -s-1 -1 -1 -1c-1 -1 -1 -2 -2 -3s-2 -1 -3 -1s-1 -2 -1 -3s-1 -1 0 -2l1 -1s1 -1 2 -1v-2v-1v-10v-2c0 -3 2 -5 5 -7l1 -1c2 -1 3 -3 5 -3h5c2 0 3 1 5 3c1 1 1 2 2 3l1 1c1 1 3 2 4 2s2 0 3 -1l2 -2l2 -1c3 -1 5 -3 8 -4l1 -1c2 0 3 0 5 -1c4 -2 7 -4 10 -8c0 0 1 -1 2 -1 -c7 -2 14 -7 19 -12c3 -3 5 -7 7 -11c0 -1 1 -3 1 -4l1 -1c2 -2 3 -3 4 -5s3 -5 4 -7v0s3 -1 4 -1c5 -1 10 -3 14 -6c4 -2 5 -4 8 -7c1 -1 2 -1 2 -3v-5c-1 -6 -4 -11 -10 -15c0 0 -1 0 -1 -1c-2 -5 -4 -11 -6 -16l-1 -1c-3 -4 -5 -7 -8 -11l-1 -1c-1 0 -1 -2 -2 -2 -c-4 -2 -9 -3 -13 -4c-1 0 -1 -1 -1 -1c-2 -3 -5 -7 -8 -10v0c-1 -1 -2 -3 -3 -4c-2 -3 -3 -6 -5 -9c0 -1 -1 -2 -2 -2c-4 -3 -9 -6 -13 -9h-1l-7 -7c0 0 -1 -1 -1 -2c-1 -2 -2 -3 -3 -5s-1 -4 -2 -6l-1 -2s1 -1 1 -2c1 -6 3 -19 4 -25v-1c28 -15 59 -24 92 -24 -c40 0 77 12 109 34c-1 1 -1 2 -1 3v2c0 2 1 3 2 5c2 3 2 7 4 10c1 3 4 6 5 9c0 1 1 3 1 4v2s-1 3 -1 4c0 2 -1 5 -1 7c-1 3 -1 5 0 8l3 6s2 4 4 6l1 1l4 4c2 2 2 3 3 5c1 3 2 6 1 9c0 2 -1 4 -2 6s-2 3 -2 5c-1 3 -1 7 0 10c0 1 2 3 2 4c1 2 1 3 2 5s1 3 1 5c0 3 0 6 -1 8v2 -s-1 1 -2 1l-1 -1h-2l-1 -1c-1 0 -1 0 -2 1h-1c-1 1 -1 2 -2 2s-2 1 -3 1c-2 0 -5 1 -7 1c-4 0 -7 -1 -11 -1c-3 0 -7 0 -10 1s-5 3 -8 5c-4 2 -7 4 -10 7c-4 3 -7 7 -10 10l-1 1v1c0 2 -1 4 -1 6c0 4 1 7 2 11c1 5 1 10 3 15c1 2 1 3 1 5s1 3 1 5c0 1 -1 2 -1 3v0v2v1 -c0 1 1 1 1 2c3 6 8 10 15 12l1 1c2 3 5 6 7 9c0 0 1 1 2 1c4 1 7 2 11 3c3 1 5 2 8 2s6 -1 8 -1c3 0 6 -1 8 -2h1h9c2 0 3 -1 5 -2c1 0 1 -1 2 -1s1 -1 2 -1c5 -4 9 -7 14 -11h2v0h9c2 0 4 -1 6 -1z" /> +d="M325 322c2 -4 7 -12 3 -15c-3 -2 -10 -2 -13 5s0 11 -5 9s-7 3 -6 4c1 2 3 3 5 4c0 2 -4 8 2 7c4 -1 12 -10 14 -14zM344 277v0v0zM403 251c0 0 -2 0 0 0v0zM224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM141 19l8 -4 +c3 -1 6 -2 10 -3c14 -5 28 -8 43 -10c28 -3 56 -1 83 8c15 5 30 11 43 20c6 4 6 16 10 24c8 16 -2 33 12 47c12 14 4 19 4 34c0 10 8 18 4 29c-1 4 -7 -3 -9 1c-5 7 -21 1 -28 2c-13 2 -24 14 -33 23c-5 5 0 20 1 26c4 15 0 33 19 38c5 1 5 9 10 11c5 1 10 3 15 4 +c9 1 17 -2 26 -2c10 0 14 -5 22 -11c7 -6 13 -3 22 -5c7 0 0 5 -2 8c-3 2 -6 2 -8 2c-16 4 -23 22 -36 30c-6 3 -9 2 -11 0c-1 -1 1 -12 1 -12c-1 -3 -10 -4 -13 -5c-9 -2 -29 17 -15 22c4 1 27 5 24 15c-3 6 2 13 -5 14c-8 1 -7 7 -15 8c-5 1 -5 11 -5 14c0 9 2 6 9 7 +c-17 11 -37 19 -57 24c-1 -3 -5 -12 -8 -12c-5 -1 -6 0 -9 -3c-9 -10 -16 -28 -25 -7c-4 11 5 19 2 28h-6h-3c6 -12 -5 -18 -8 -19c-8 0 -10 5 -17 4c-4 -1 -7 4 -11 2s-13 -8 -14 -12c-3 -12 6 -13 14 -6c6 6 17 12 25 6c6 -5 5 -9 5 -14s-1 -18 -9 -16c-4 1 -7 6 -11 3 +c-8 -7 -18 -6 -29 -9c-10 -2 -16 -6 -25 -9c-8 -3 -11 -4 -12 -12c0 -2 0 -14 -3 -15c-5 -2 -8 22 -22 20c-12 -1 -30 -13 -25 -28c2 -5 28 -3 10 -14c-2 -1 2 -17 2 -20c1 -8 13 -18 21 -10c6 6 6 5 14 2c15 -8 33 -15 45 -27c6 -6 9 -24 17 -28c9 -5 19 -5 26 -14 +c6 -7 -2 -19 -8 -23c-4 -2 -12 -24 -16 -29c-2 -4 -12 -6 -16 -7c-3 0 -7 -9 -9 -11c-7 -7 -8 -13 -17 -19c-18 -12 -22 -23 -18 -44c2 -8 5 -13 11 -16zM100 46l2 -2c7 -6 15 -11 23 -16c-21 21 -23 49 -21 78l3 24c1 3 -4 7 -4 11c0 10 0 5 -8 13c-4 4 -10 11 -12 17 +c-7 16 1 30 10 43c9 14 -7 20 -10 32c-1 6 -7 6 -6 12c1 7 -4 5 -9 9c-12 8 -1 20 -7 26c-43 -70 -36 -162 16 -224c1 -1 0 -1 1 -2h1c3 -4 6 -8 9 -11s7 -6 10 -9z" /> + <glyph glyph-name="ion-easel" unicode="" +d="M48 112v192h352v-192h-352zM432 352c9 0 16 -7 16 -16v-256c0 -9 -7 -16 -16 -16h-416c-9 0 -16 7 -16 16v256c0 9 7 16 16 16h416zM416 96v224h-384v-224h384zM48 -32l29 80h31l-28 -80h-32zM239 416l17 -48h-64l17 48h30zM340 48h31l29 -80h-32zM208 0v48h32v-48h-32z +" /> <glyph glyph-name="ion-edit" unicode="" -d="M381 259l-250 -251l-91 91l251 250zM440 360c12 -12 11 -32 -2 -45l-45 -45l-91 91l45 45c13 13 33 14 45 2zM14 17l18 68l85 -85l-68 -18zM0 -32l9 32l23 -23z" /> +d="M381 259l-250 -251l-91 91l251 250zM440 360c12 -12 11 -32 -2 -45l-45 -45l-91 91l45 45c13 13 33 14 45 2zM32 85l85 -85l-117 -32z" /> <glyph glyph-name="ion-egg" unicode="" horiz-adv-x="320" d="M160 416c64 0 160 -133 160 -257s-64 -191 -160 -191s-160 67 -160 191s96 257 160 257z" /> <glyph glyph-name="ion-eject" unicode="" horiz-adv-x="320" d="M303 128h-286v0c-10 0 -17 7 -17 16c0 3 1 5 3 8l138 191c5 5 11 9 19 9s14 -4 19 -9l138 -190c2 -3 3 -6 3 -9c0 -9 -7 -16 -17 -16v0zM308 96c7 0 12 -5 12 -12v-40c0 -7 -5 -12 -12 -12h-296c-7 0 -12 5 -12 12v40c0 7 5 12 12 12h296z" /> + <glyph glyph-name="ion-email-unread" unicode="" horiz-adv-x="480" +d="M352 288c0 43 21 64 64 64s64 -21 64 -64s-21 -64 -64 -64s-64 21 -64 64zM209 288h127c0 -17 5 -33 15 -47c-6 -3 -14 -8 -22 -12s-16 -8 -23 -12s-14 -8 -22 -12s-15 -8 -21 -11s-11 -6 -16 -9s-9 -5 -12 -7s-4 -3 -5 -3c-6 -3 -13 -4 -21 -4s-15 1 -21 4 +c-1 1 -15 8 -42 23s-54 29 -81 44s-43 23 -46 25c-7 4 -12 8 -13 11c-1 4 -1 6 1 8s6 2 11 2h191zM277 175c18 11 45 30 83 56c16 -15 34 -23 56 -23v-155c0 -2 -1 -4 -2 -7s-3 -5 -5 -7s-4 -4 -7 -5s-6 -2 -8 -2h-185h-185c-5 0 -11 2 -16 7s-8 9 -8 14v205c0 6 3 8 9 5 +c2 -1 11 -7 26 -17s32 -22 53 -36s39 -26 53 -35l-83 -93c-2 -2 -2 -4 -1 -5c2 -1 4 -1 6 1l98 83c16 -10 25 -16 27 -17c6 -3 13 -4 21 -4s15 1 21 4c2 1 11 7 27 17l98 -83c2 -2 5 -2 6 -1s0 3 -2 5z" /> <glyph glyph-name="ion-email" unicode="" horiz-adv-x="416" d="M19 299c-4 2 -11 7 -13 11c-3 8 1 10 12 10h191h191c11 0 15 -2 12 -10c-2 -4 -9 -9 -13 -11c-11 -6 -163 -89 -169 -92s-12 -4 -21 -4s-15 1 -21 4s-158 86 -169 92zM408 295c9 4 8 -1 8 -5v-205c0 -9 -12 -21 -22 -21h-185h-185c-10 0 -24 12 -24 21v205s0 9 9 5 c8 -4 83 -56 132 -88l-83 -93c-2 -2 -2 -4 -1 -5s4 -1 6 1l98 83c15 -10 25 -16 27 -17c8 -4 14 -4 21 -4s13 0 21 4c2 1 12 7 27 17l98 -83c2 -2 5 -2 6 -1s0 3 -2 5l-82 93c49 32 123 84 131 88z" /> + <glyph glyph-name="ion-erlenmeyer-flask-bubbles" unicode="" horiz-adv-x="384" +d="M382 21c2 -4 3 -10 0 -14s-8 -7 -13 -7h-177h-178c-5 0 -9 3 -12 7s-2 10 0 14l118 199v150c0 8 6 14 14 14s15 -6 15 -14v-80c4 3 10 5 16 5c15 0 27 -12 27 -27s-12 -26 -27 -26c-6 0 -12 2 -16 5v-31c0 -2 -1 -4 -2 -6l-35 -59h72c-15 6 -26 20 -26 37 +c0 23 19 42 43 42c15 0 27 -8 35 -19c-1 2 -1 3 -1 5v154c0 8 6 14 14 14s15 -6 15 -14v-150zM218 151h53l-31 54c2 -5 3 -11 3 -17c0 -17 -10 -31 -25 -37zM201 319c-12 0 -22 9 -22 21s10 21 22 21s22 -9 22 -21s-10 -21 -22 -21z" /> + <glyph glyph-name="ion-erlenmeyer-flask" unicode="" horiz-adv-x="384" +d="M375 52c6 -9 9 -20 9 -32c0 -28 -16 -52 -63 -52h-258c-47 0 -63 24 -63 52c0 12 3 23 9 32l49 73l49 77c13 20 21 44 21 70v92s-14 34 -16 43c-2 8 1 9 17 9h126c16 0 18 -1 16 -9c-2 -9 -15 -22 -15 -42v-93c0 -26 6 -50 19 -70zM345 7c3 3 7 8 7 14c0 5 -2 10 -4 14 +l-101 150c-16 26 -23 56 -23 87v112h-64v-112c0 -32 -9 -62 -25 -87l-99 -150c-2 -4 -4 -9 -4 -14c0 -6 3 -11 6 -14c4 -4 12 -7 25 -7h258c13 0 20 3 24 7zM325 37c1 -2 3 -6 3 -8c0 -7 -6 -15 -14 -15h-244c-7 0 -14 6 -14 14c0 3 1 6 3 8l81 124h103l82 -124v1zM238 106 +c2 -1 4 -2 6 -2s3 0 5 2c1 2 3 4 3 6s-1 4 -3 6c-1 2 -3 2 -5 2s-4 0 -6 -2c-1 -2 -2 -4 -2 -6s0 -4 2 -6zM285 47c4 2 4 7 2 11l-23 36c-1 2 -4 4 -7 4c-2 0 -3 0 -4 -1c-4 -2 -4 -7 -2 -11l23 -36c1 -2 5 -4 7 -4c1 0 3 0 4 1z" /> <glyph glyph-name="ion-eye-disabled" unicode="" d="M344 290c41 -27 76 -66 104 -100c-51 -54 -124 -135 -224 -135c-36 0 -65 8 -92 22l-77 -77l-23 23l71 71c-36 25 -68 61 -103 98c78 85 142 137 224 137c34 0 64 -9 92 -23l77 78l23 -23zM134 192c0 -19 6 -36 16 -51l27 27c-4 7 -5 15 -5 24c0 29 23 53 52 53h8 c-5 -6 -8 -13 -8 -21c0 -3 0 -5 1 -8l51 50c-15 11 -33 17 -52 17c-49 0 -90 -41 -90 -91zM224 101c49 0 90 41 90 91c0 19 -6 37 -16 52l-50 -51c3 -1 5 -1 8 -1c8 0 14 3 20 7v-7c0 -29 -23 -53 -52 -53c-9 0 -17 2 -24 6l-28 -27c15 -11 33 -17 52 -17z" /> @@ -475,9 +606,6 @@ c0 -65 36 -121 90 -150c6 -3 13 -7 19 -9c2 -1 3 -1 5 -2c9 -3 19 -5 29 -7c9 -2 18 l53 -52l-36 -41zM178 58l38 113h-85l139 155l-38 -113h85z" /> <glyph glyph-name="ion-flash" unicode="" horiz-adv-x="320" d="M0 160l224 256l-51 -192h147l-224 -256l51 192h-147z" /> - <glyph glyph-name="ion-flask" unicode="" horiz-adv-x="384" -d="M382 21c2 -4 3 -10 0 -14s-8 -7 -13 -7h-177h-178c-5 0 -9 3 -12 7s-2 10 0 14l118 199v150c0 8 6 14 14 14s15 -6 15 -14v-80c4 3 10 5 16 5c15 0 27 -12 27 -27s-12 -26 -27 -26c-6 0 -12 2 -16 5v-31c0 -2 -1 -4 -2 -6l-35 -59h72c-15 6 -26 20 -26 37 -c0 23 19 42 43 42c15 0 27 -8 35 -19c-1 2 -1 3 -1 5v154c0 8 6 14 14 14s15 -6 15 -14v-150zM218 151h53l-31 54c2 -5 3 -11 3 -17c0 -17 -10 -31 -25 -37zM201 319c-12 0 -22 9 -22 21s10 21 22 21s22 -9 22 -21s-10 -21 -22 -21z" /> <glyph glyph-name="ion-folder" unicode="" horiz-adv-x="384" d="M366 256c18 0 19 -7 18 -18l-12 -186c-1 -11 -3 -20 -21 -20h-317c-18 0 -20 9 -21 20l-13 184c-1 11 0 20 18 20h348zM362 305l2 -33h-344c0 6 4 46 6 63c2 18 8 17 25 17h75c28 0 23 0 37 -15c16 -18 19 -17 41 -17h143c11 0 15 -3 15 -15z" /> <glyph glyph-name="ion-fork-repo" unicode="" horiz-adv-x="320" @@ -490,16 +618,8 @@ l9 117h8l10 -117v-1c1 -6 3 -10 9 -10s9 5 9 11v117h8v0c9 -40 24 -91 24 -134z" /> <glyph glyph-name="ion-forward" unicode="" horiz-adv-x="384" d="M224 150c-102 0 -171 -9 -224 -102c0 0 37 208 224 208v80l160 -144l-160 -134v92z" /> <glyph glyph-name="ion-funnel" unicode="" -d="M224 416c124 0 224 -36 224 -80c0 -8 -3 -15 -9 -22v0c-35 -43 -151 -179 -151 -218v-4v-83v0c0 -23 -29 -41 -64 -41s-64 18 -64 41v0v87c0 39 -117 177 -149 216v0c-7 8 -11 16 -11 24c0 44 100 80 224 80zM224 288c106 0 192 25 192 56s-86 56 -192 56 -s-192 -25 -192 -56s86 -56 192 -56z" /> - <glyph glyph-name="ion-game-controller-a" unicode="" -d="M0 193c0 65 50 111 111 111h226c61 0 111 -46 111 -111s-50 -113 -111 -113h-226c-61 0 -111 48 -111 113zM373 215c-11 0 -20 -9 -20 -19s9 -19 20 -19s19 9 19 19s-8 19 -19 19zM330 256c-11 0 -19 -9 -19 -19s8 -19 19 -19s20 9 20 19s-9 19 -20 19zM330 173 -c-11 0 -19 -8 -19 -19c0 -10 8 -19 19 -19s20 9 20 19c0 11 -9 19 -20 19zM288 215c-11 0 -20 -9 -20 -19s9 -19 20 -19s19 9 19 19s-8 19 -19 19zM56 203v-22c0 -3 2 -5 5 -5v0h35v-38v-2c0 -3 2 -4 5 -4h22c3 0 5 2 5 5v0v39h37h1c3 0 5 2 5 5v22c0 3 -2 5 -5 5h-1h-37v38 -v1c0 3 -2 5 -5 5h-22c-3 0 -5 -2 -5 -5v-1v-38h-35h-1c-2 0 -4 -2 -4 -5z" /> - <glyph glyph-name="ion-game-controller-b" unicode="" -d="M346 348c45 -13 67 -61 88 -149s18 -152 -7 -164s-53 15 -80 49c-24 27 -33 28 -123 28s-100 -2 -122 -28c-27 -34 -56 -61 -81 -49s-28 76 -7 164s43 136 88 149s59 -12 122 -12s77 25 122 12zM96 184c22 0 40 18 40 40s-18 40 -40 40s-39 -18 -39 -40s17 -40 39 -40z -M278 204c11 0 19 9 19 20s-8 19 -19 19s-20 -8 -20 -19s9 -20 20 -20zM320 162c11 0 19 8 19 19s-8 20 -19 20s-19 -9 -19 -20s8 -19 19 -19zM320 247c11 0 19 8 19 19s-8 20 -19 20s-19 -9 -19 -20s8 -19 19 -19zM362 204c11 0 20 9 20 20s-9 19 -20 19s-19 -8 -19 -19 -s8 -20 19 -20z" /> +d="M224 416c124 0 224 -36 224 -80c0 -8 -3 -15 -9 -22v0c-35 -43 -151 -179 -151 -218v-4v-83v0c0 -23 -29 -41 -64 -41s-64 18 -64 41v0v87c0 39 -117 177 -149 216v0c-7 8 -11 16 -11 24c0 44 100 80 224 80zM224 288c92 0 176 22 176 48s-83 48 -176 48 +s-176 -22 -176 -48s84 -48 176 -48z" /> <glyph glyph-name="ion-gear-a" unicode="" horiz-adv-x="384" d="M347 192c0 -24 15 -43 37 -56c-4 -13 -10 -26 -16 -38c-25 6 -45 -3 -62 -20s-22 -37 -16 -62c-12 -6 -25 -12 -38 -16c-13 22 -36 37 -60 37s-47 -15 -60 -37c-13 4 -27 10 -39 16c6 25 2 45 -15 62s-37 21 -62 15c-6 12 -12 26 -16 39c22 13 37 36 37 60s-15 43 -37 56 c4 13 9 26 16 38c25 -6 45 3 62 20s21 37 15 62c12 6 26 12 39 16c13 -22 36 -37 60 -37s47 15 60 37c13 -4 27 -10 39 -16c-6 -25 -2 -45 15 -62s37 -26 62 -20c6 -12 12 -25 16 -38c-22 -13 -37 -32 -37 -56zM192 94c54 0 98 44 98 98s-44 98 -98 98s-98 -44 -98 -98 @@ -514,11 +634,15 @@ c0 -4 -3 -7 -7 -7h-50c-4 0 -7 3 -7 7v50c0 4 3 7 7 7h50c4 0 7 -3 7 -7v-50zM192 39 <glyph glyph-name="ion-hammer" unicode="" horiz-adv-x="320" d="M314 416c3 0 6 -3 6 -6v-84c0 -3 -3 -6 -6 -6h-52c-3 0 -6 3 -6 6v14c-6 5 -16 9 -22 7c-7 -2 -23 -13 -30 -25s-6 -28 -6 -66l8 -2c5 -1 7 -6 7 -9v-70c0 -95 11 -201 11 -201c0 -3 -3 -6 -6 -6h-84c-3 0 -6 3 -6 6c0 0 11 106 11 201v70c0 3 3 8 7 9l7 2 c0 43 -5 58 -22 74c-18 16 -41 19 -63 17s-51 -35 -58 -45s-10 2 -10 11c1 16 22 60 72 81s91 22 102 22s27 -1 38 -3s16 -18 26 -18c7 0 14 5 18 9v6c0 3 3 6 6 6h52z" /> - <glyph glyph-name="ion-happy" unicode="" + <glyph glyph-name="ion-happy-outline" unicode="" d="M355 158c8 -4 11 -13 7 -21c-24 -46 -78 -73 -138 -73c-62 0 -118 29 -139 74c-4 8 0 17 8 21c2 1 5 1 7 1c6 0 11 -3 14 -9c16 -34 60 -55 110 -55c49 0 92 21 110 56c3 5 8 8 14 8c3 0 5 -1 7 -2zM381 217c5 -7 4 -17 -4 -22c-3 -2 -6 -3 -10 -3c-5 0 -11 2 -14 6 s-7 10 -17 10s-14 -6 -17 -10s-9 -6 -14 -6c-4 0 -7 1 -10 3c-8 6 -9 15 -3 22c11 14 23 23 44 23s35 -9 45 -23zM157 217c5 -7 4 -17 -4 -22c-3 -2 -6 -3 -10 -3c-5 0 -11 2 -14 6s-7 10 -17 10s-14 -6 -17 -10s-9 -6 -14 -6c-4 0 -7 1 -10 3c-8 6 -9 15 -3 22 c11 14 23 23 44 23s35 -9 45 -23zM224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM360 56c36 36 56 85 56 136s-20 100 -56 136s-85 56 -136 56s-100 -20 -136 -56s-56 -85 -56 -136s20 -100 56 -136s85 -56 136 -56 s100 20 136 56z" /> + <glyph glyph-name="ion-happy" unicode="" +d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM71 195c3 -2 6 -3 10 -3c5 0 11 2 14 6s7 10 17 10s14 -6 17 -10s9 -6 14 -6c4 0 7 1 10 3c8 5 9 15 4 22c-10 14 -24 23 -45 23s-33 -9 -44 -23c-6 -7 -5 -16 3 -22zM362 137 +c4 8 1 17 -7 21c-2 1 -4 2 -7 2c-6 0 -11 -3 -14 -8c-18 -35 -61 -56 -110 -56c-50 0 -94 21 -110 55c-3 6 -8 9 -14 9c-2 0 -5 0 -7 -1c-8 -4 -12 -13 -8 -21c21 -45 77 -74 139 -74c60 0 114 27 138 73zM377 195c8 5 9 15 4 22c-10 14 -24 23 -45 23s-33 -9 -44 -23 +c-6 -7 -5 -16 3 -22c3 -2 6 -3 10 -3c5 0 11 2 14 6s7 10 17 10s14 -6 17 -10s9 -6 14 -6c4 0 7 1 10 3z" /> <glyph glyph-name="ion-headphone" unicode="" horiz-adv-x="384" d="M383 210c3 -51 -3 -130 -13 -162c-20 -67 -40 -80 -72 -80s-58 27 -58 59v106c0 33 23 59 53 59c18 0 34 -9 44 -24c0 0 11 7 13 22s4 34 -5 64s-21 19 -36 38c-2 3 -5 7 -8 10l-10 10c-2 2 -3 3 -5 4c-11 9 -21 17 -34 23c-19 9 -39 13 -60 13s-42 -4 -61 -13 c-13 -6 -22 -14 -33 -23c-2 -1 -3 -2 -5 -4l-10 -10s-6 -7 -8 -10c-15 -19 -27 -8 -36 -38c-9 -31 -7 -49 -5 -64s13 -22 13 -22c10 15 26 24 44 24c30 0 53 -27 53 -59v-106c0 -32 -26 -59 -58 -59s-52 13 -72 80c-10 32 -16 111 -13 162c3 60 22 108 56 145v0 @@ -545,14 +669,6 @@ d="M384 160h-48v-160h-96v128h-96v-128h-96v160h-48l192 224z" /> <glyph glyph-name="ion-icecream" unicode="" horiz-adv-x="320" d="M32 192h256l-128 -224zM307 275c8 -5 13 -13 13 -23c0 -16 -14 -28 -30 -28h-4h-252h-4c-16 0 -30 13 -30 28c0 10 6 18 14 23c1 0 1 2 2 2c4 3 7 7 8 12v1c-2 6 -2 12 -2 18c0 42 34 76 76 76c8 0 16 -2 23 -4c-3 -12 -4 -31 -4 -31c2 15 11 29 11 29c18 23 46 38 77 38 c53 0 96 -43 96 -96c0 -11 -2 -21 -5 -30v-1c0 -4 4 -9 8 -12c1 0 2 -2 3 -2z" /> - <glyph glyph-name="ion-icon-social-google-plus-outline" unicode="" -d="M192 366c12 -10 36 -30 36 -68c0 -37 -21 -55 -43 -72c-7 -7 -15 -13 -15 -24s8 -18 14 -22l18 -14c23 -19 43 -36 43 -71c0 -47 -47 -95 -135 -95c-74 0 -110 35 -110 72c0 18 10 44 40 62c32 19 75 21 98 23c-7 9 -16 18 -16 34c0 9 3 14 5 20c-6 0 -11 -1 -16 -1 -c-54 0 -85 40 -85 79c0 23 10 48 32 67c29 24 64 28 92 28h106l-33 -18h-31zM155 142c-4 0 -7 1 -12 1s-32 -1 -54 -8c-11 -4 -44 -16 -44 -52s36 -62 91 -62c49 0 75 24 75 55c0 26 -17 39 -56 66zM170 238c12 12 13 28 13 37c0 36 -22 92 -65 92c-13 0 -28 -6 -36 -16 -c-9 -11 -11 -24 -11 -37c0 -34 20 -90 64 -90c13 0 27 6 35 14zM448 306v-18h-78v-81h-18v81h-80v18h80v78h18v-78h78z" /> - <glyph glyph-name="ion-icon-social-google-plus" unicode="" -d="M210 172c22 -18 45 -36 45 -73c0 -49 -47 -99 -139 -99c-80 0 -116 39 -116 77c0 10 3 42 42 65c27 16 61 21 85 23c-4 7 -8 15 -8 26c0 4 0 7 1 10h-4c-19 0 -46 4 -67 26c-15 15 -24 36 -24 57c0 26 13 53 35 71v0c32 25 69 29 94 29h134l-60 -33h-13 -c11 -13 23 -31 23 -58c0 -40 -25 -59 -45 -74v-1c-6 -6 -11 -10 -11 -17c0 -6 4 -10 10 -15v0zM85 308c0 -13 4 -33 14 -51c7 -12 21 -27 41 -27c10 0 21 4 28 11c10 10 10 25 10 30c0 18 -6 37 -15 53c-8 13 -20 28 -40 28c-11 0 -23 -5 -29 -13c-6 -7 -9 -18 -9 -31z -M206 80c0 20 -13 31 -50 56c-3 0 -4 1 -8 1c-6 0 -31 -2 -50 -8c-16 -6 -38 -16 -38 -42c0 -31 32 -51 80 -51c41 0 66 17 66 44zM370 306h78v-34h-78v-81h-34v81h-80v34h80v78h34v-78z" /> <glyph glyph-name="ion-image" unicode="" d="M336 224c-26 0 -48 22 -48 48s22 48 48 48s48 -22 48 -48s-22 -48 -48 -48zM420 384c16 0 28 -12 28 -28v-328c0 -16 -12 -28 -28 -28h-392c-16 0 -28 12 -28 28v328c0 16 12 28 28 28h392zM317 186l99 -106v260c0 7 -6 12 -13 12h-358c-7 0 -12 -5 -13 -12v-260l126 152 c4 4 10 8 17 8s13 -2 17 -7l54 -59l4 -4c3 -2 7 -4 11 -4s8 2 12 5l18 16c4 3 8 5 13 5s10 -2 13 -6z" /> @@ -565,463 +681,554 @@ d="M448 195c2 -124 -97 -225 -221 -227s-225 97 -227 221s97 225 221 227s225 -97 22 <glyph glyph-name="ion-information" unicode="" horiz-adv-x="128" d="M96 0h32v-16h-128v16h32v240h-32v16h96v-256zM64 304c-27 0 -48 21 -48 48s21 48 48 48s48 -21 48 -48s-21 -48 -48 -48z" /> <glyph glyph-name="ion-ionic" unicode="" horiz-adv-x="416" -d="M378 313c24 -34 38 -76 38 -121c0 -115 -93 -208 -208 -208s-208 93 -208 208s93 208 208 208c45 0 87 -14 121 -38c6 5 13 7 21 7c19 0 35 -16 35 -35c0 -8 -2 -15 -7 -21zM344 56c18 18 31 38 41 61c10 24 15 49 15 75s-5 51 -15 75c-5 13 -12 25 -20 36 -c-5 -2 -10 -3 -15 -3c-19 0 -35 15 -35 34c0 5 2 11 4 15c-11 8 -23 15 -36 20c-24 10 -49 15 -75 15s-51 -5 -75 -15c-23 -10 -43 -23 -61 -41s-31 -38 -41 -61c-10 -24 -15 -49 -15 -75s5 -51 15 -75c10 -23 23 -43 41 -61s38 -31 61 -41c24 -10 49 -15 75 -15s51 5 75 15 +d="M376 315c25 -34 40 -77 40 -123c0 -115 -93 -208 -208 -208s-208 93 -208 208s93 208 208 208c46 0 89 -15 123 -40c5 3 11 5 18 5c18 0 32 -14 32 -32c0 -7 -2 -13 -5 -18zM344 56c18 18 31 38 41 61c10 24 15 49 15 75s-5 51 -15 75c-6 13 -13 26 -21 38 +c-4 -2 -10 -4 -15 -4c-18 0 -32 14 -32 32c0 5 2 11 4 15c-12 8 -25 15 -38 21c-24 10 -49 15 -75 15s-51 -5 -75 -15c-23 -10 -43 -23 -61 -41s-31 -38 -41 -61c-10 -24 -15 -49 -15 -75s5 -51 15 -75c10 -23 23 -43 41 -61s38 -31 61 -41c24 -10 49 -15 75 -15s51 5 75 15 c23 10 43 23 61 41zM112 192c0 64 32 96 96 96s96 -32 96 -96s-32 -96 -96 -96s-96 32 -96 96z" /> - <glyph glyph-name="ion-ios7-alarm-outline" unicode="" horiz-adv-x="404" + <glyph glyph-name="ion-ios-alarm-outline" unicode="" horiz-adv-x="404" d="M384 256l-54 52l-9 -9c35 -32 57 -79 57 -130c0 -44 -16 -83 -43 -114l36 -45l-12 -10l-35 43c-32 -30 -75 -49 -122 -49v0v0c-47 0 -90 19 -122 49l-35 -43l-12 10l36 45c-27 31 -43 71 -43 115c0 51 22 97 57 129l-9 9l-54 -52c-12 14 -20 32 -20 52c0 44 35 80 80 82 h5c20 0 39 -7 54 -18l-54 -52l11 -11c26 19 56 32 90 35v0c0 8 8 16 16 16s15 -8 15 -16v0c34 -3 65 -16 91 -35l11 11l-54 52c15 11 34 18 54 18h5c45 -2 80 -38 80 -82c0 -20 -8 -38 -20 -52zM22 280l91 89c-9 5 -19 7 -32 6c-37 -2 -65 -32 -65 -67c0 -10 2 -19 6 -28z M362 172c0 88 -72 158 -160 158s-160 -70 -160 -158s72 -158 160 -158s160 70 160 158zM291 369l91 -89c4 9 6 18 6 28c0 35 -28 65 -65 67c-13 1 -23 -1 -32 -6zM202 288h16v-144h-112v16h96v128z" /> - <glyph glyph-name="ion-ios7-alarm" unicode="" horiz-adv-x="404" + <glyph glyph-name="ion-ios-alarm" unicode="" horiz-adv-x="404" d="M385 256l-55 52l-9 -9c35 -32 57 -79 57 -130c0 -44 -16 -83 -43 -114l37 -45l-13 -10l-35 43c-32 -30 -75 -49 -122 -49v0v0c-47 0 -90 19 -122 49l-35 -43l-12 10l36 45c-27 31 -43 70 -43 114c0 51 22 98 57 130l-9 9l-54 -52c-12 14 -20 32 -20 52c0 44 35 80 80 82 h5c20 0 39 -7 54 -18l-54 -53l11 -10c26 19 56 32 90 35v0c0 8 8 16 16 16s15 -8 15 -16v0c34 -3 65 -16 91 -35l11 11l-54 52c15 11 34 18 54 18h5c45 -2 80 -38 80 -82c0 -20 -7 -38 -19 -52zM218 144v144h-16v-128h-96v-16h112z" /> - <glyph glyph-name="ion-ios7-albums-outline" unicode="" + <glyph glyph-name="ion-ios-albums-outline" unicode="" d="M432 304h-416v-288h416v288zM448 320v0v-320h-448v320h448zM40 336v16h368v-16h-368zM72 368v16h304v-16h-304z" /> - <glyph glyph-name="ion-ios7-albums" unicode="" + <glyph glyph-name="ion-ios-albums" unicode="" d="M448 320v0v-320h-448v320h448zM40 336v16h368v-16h-368zM72 368v16h304v-16h-304z" /> - <glyph glyph-name="ion-ios7-americanfootball-outline" unicode="" -d="M356 324c120 -120 88 -352 88 -352s-28 -4 -70 -4c-78 0 -204 14 -282 92c-120 120 -88 352 -88 352s28 4 70 4c78 0 204 -14 282 -92zM364 64l66 -67c2 23 3 61 -1 105l-3 24zM345 313c-33 33 -78 56 -134 71c-11 3 -22 5 -33 7l-71 -71l69 -69l37 37l11 -11l-37 -37 -l21 -21l37 37l11 -11l-37 -37l21 -21l37 37l11 -11l-37 -37l21 -21l37 37l11 -11l-37 -37l70 -69l70 71c-4 24 -10 46 -18 67c-15 40 -34 74 -60 100zM19 282l3 -24l62 62l-66 67c-2 -23 -3 -61 1 -105zM29 398l66 -66l63 62c-27 4 -55 6 -84 6c-18 0 -33 -1 -45 -2zM103 71 -c33 -33 78 -56 134 -71c11 -3 22 -5 33 -7l71 71l-69 69l-37 -37l-11 11l37 37l-21 21l-37 -37l-11 11l37 37l-21 21l-37 -37l-11 11l37 37l-21 21l-37 -37l-11 11l37 37l-69 69l-71 -71c4 -24 10 -46 18 -67c15 -40 34 -74 60 -100zM374 -16c18 0 33 1 45 2l-67 66l-62 -62 -c27 -4 55 -6 84 -6z" /> - <glyph glyph-name="ion-ios7-americanfootball" unicode="" -d="M3 402l81 -82l-76 -76c-12 70 -7 134 -5 158zM272 133l69 -69l-84 -85c-59 12 -120 36 -165 81s-69 106 -81 165l85 84l69 -69l-37 -37l11 -11l37 37l21 -21l-37 -37l11 -11l37 37l21 -21l-37 -37l11 -11l37 37l21 -21l-37 -37l11 -11zM176 251l-69 69l84 85 -c59 -12 120 -36 165 -81s69 -106 81 -165l-84 -84l-70 69l37 37l-11 11l-37 -37l-21 21l37 37l-11 11l-37 -37l-21 21l37 37l-11 11l-37 -37l-21 21l37 37l-11 11zM276 -24l77 76l81 -81c-12 -1 -33 -3 -60 -3c-28 0 -62 2 -98 8zM172 408l-76 -76l-82 81c12 1 33 3 60 3 -c28 0 62 -2 98 -8zM445 -18l-81 82l76 76c12 -70 7 -134 5 -158z" /> - <glyph glyph-name="ion-ios7-analytics-outline" unicode="" + <glyph glyph-name="ion-ios-americanfootball-outline" unicode="" horiz-adv-x="416" +d="M331 315c112 -112 81 -327 81 -327s-26 -4 -65 -4c-73 0 -189 12 -262 85c-112 112 -81 327 -81 327s26 4 65 4c73 0 189 -12 262 -85zM17 383c-2 -19 -5 -60 0 -107c1 -8 2 -16 3 -23l127 127c-25 3 -51 5 -78 5v0v0c-22 0 -41 -1 -52 -2zM96 80c30 -30 72 -53 124 -66 +c10 -3 20 -5 31 -7l142 142c-4 22 -10 44 -17 63c-14 37 -32 68 -56 92c-30 30 -72 53 -124 66c-10 3 -20 5 -31 7l-142 -142c4 -22 10 -44 17 -63c14 -37 32 -68 56 -92zM399 1c2 19 5 60 0 107c-1 8 -2 16 -3 23l-127 -127c25 -3 51 -5 78 -5c22 0 41 1 52 2zM259 130 +l-28 -29l-12 12l29 28l-23 23l-28 -29l-12 12l29 28l-23 23l-28 -29l-12 12l29 28l-23 23l-28 -29l-12 12l29 28l-22 23l-29 -29l-11 12l67 67l12 -11l-29 -29l23 -22l28 29l12 -12l-29 -28l23 -23l28 29l12 -12l-29 -28l23 -23l28 29l12 -12l-29 -28l22 -23l29 29l12 -12 +l-29 -28l22 -23l29 29l11 -12l-67 -67l-12 11l29 29z" /> + <glyph glyph-name="ion-ios-americanfootball" unicode="" horiz-adv-x="416" +d="M331 315c112 -112 81 -327 81 -327s-26 -4 -65 -4c-73 0 -189 12 -262 85c-112 112 -81 327 -81 327s26 4 65 4c73 0 189 -12 262 -85zM20 253l3 -18l142 142l-18 3zM219 113l12 -12l28 29l23 -22l-29 -29l12 -11l67 67l-11 12l-29 -29l-22 23l29 28l-12 12l-28 -29 +l-23 23l29 28l-12 12l-28 -29l-23 23l29 28l-12 12l-28 -29l-23 23l29 28l-12 12l-28 -29l-23 22l29 29l-12 11l-67 -67l11 -12l29 29l22 -23l-29 -28l12 -12l28 29l23 -23l-29 -28l12 -12l28 29l23 -23l-29 -28l12 -12l28 29l23 -23zM269 4l127 127l-3 18l-142 -142z" /> + <glyph glyph-name="ion-ios-analytics-outline" unicode="" d="M224 400c-28 0 -55 -5 -81 -16c-25 -10 -47 -26 -66 -45s-35 -41 -45 -66c-11 -26 -16 -53 -16 -81s5 -55 16 -81c10 -25 26 -47 45 -66s41 -35 66 -45c26 -11 53 -16 81 -16s55 5 81 16c25 10 47 26 66 45s35 41 45 66c11 26 16 53 16 81s-5 55 -16 81 c-10 25 -26 47 -45 66s-41 35 -66 45c-26 11 -53 16 -81 16zM224 416v0c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM76 128c-25 0 -41 18 -42 19c-3 3 -2 9 1 12s8 2 11 -1c1 -1 15 -17 36 -14c12 2 27 26 38 42c4 6 9 12 12 16 c17 21 34 23 45 21c24 -3 45 -28 54 -50c7 -18 18 -28 32 -29c15 -1 31 11 43 30c1 2 3 4 4 7c9 17 24 43 52 43c31 0 52 -35 53 -36c2 -4 1 -9 -3 -11s-9 -1 -11 3c0 0 -5 8 -12 15c-6 6 -16 13 -27 13c-18 0 -29 -19 -38 -35c-1 -3 -3 -5 -4 -7c-15 -25 -36 -40 -58 -38 c-20 1 -36 15 -46 39s-28 39 -41 41c-11 1 -21 -4 -31 -16c-3 -4 -6 -9 -10 -15c-14 -20 -31 -45 -50 -48c-3 0 -5 -1 -8 -1z" /> - <glyph glyph-name="ion-ios7-analytics" unicode="" + <glyph glyph-name="ion-ios-analytics" unicode="" d="M224 416c124 0 224 -100 224 -224c0 -13 -1 -25 -3 -37c-1 -6 -2 -12 -3 -17c-24 -98 -113 -170 -218 -170c-122 0 -221 98 -224 219v5c0 9 1 17 2 26c13 111 107 198 222 198zM431 168c1 8 1 16 1 24c0 28 -5 55 -16 81c-10 25 -26 47 -45 66s-41 35 -66 45 c-26 11 -53 16 -81 16s-55 -5 -81 -16c-25 -10 -47 -26 -66 -45s-35 -41 -45 -66c-11 -26 -16 -53 -16 -81v0c14 -21 29 -34 29 -34h1v-1c1 -1 15 -16 36 -13c12 2 27 26 38 42c4 6 9 12 12 16c17 21 34 23 45 21c24 -3 45 -27 54 -50c7 -18 18 -28 32 -29c15 -1 31 9 43 29 c1 2 3 4 4 7c9 17 24 44 52 44c31 0 52 -35 53 -36c3 -4 9 -12 16 -20z" /> - <glyph glyph-name="ion-ios7-arrow-back" unicode="" horiz-adv-x="192" + <glyph glyph-name="ion-ios-arrow-back" unicode="" horiz-adv-x="192" d="M192 320l-127 -128l127 -128l-32 -32l-160 160v0v0l160 160z" /> - <glyph glyph-name="ion-ios7-arrow-down" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-arrow-down" unicode="" horiz-adv-x="320" d="M301 288l19 -21l-160 -171l-160 171l19 21l141 -150z" /> - <glyph glyph-name="ion-ios7-arrow-forward" unicode="" horiz-adv-x="192" + <glyph glyph-name="ion-ios-arrow-forward" unicode="" horiz-adv-x="192" d="M0 320l32 32l160 -160v0v0l-160 -160l-32 32l127 128z" /> - <glyph glyph-name="ion-ios7-arrow-left" unicode="" horiz-adv-x="192" + <glyph glyph-name="ion-ios-arrow-left" unicode="" horiz-adv-x="192" d="M192 333l-150 -141l150 -141l-21 -19l-171 160l171 160z" /> - <glyph glyph-name="ion-ios7-arrow-right" unicode="" horiz-adv-x="192" + <glyph glyph-name="ion-ios-arrow-right" unicode="" horiz-adv-x="192" d="M0 333l21 19l171 -160l-171 -160l-21 19l150 141z" /> - <glyph glyph-name="ion-ios7-arrow-thin-down" unicode="" horiz-adv-x="192" + <glyph glyph-name="ion-ios-arrow-thin-down" unicode="" horiz-adv-x="192" d="M190 126c2 -2 2 -4 2 -6s0 -4 -2 -6c0 0 -87 -79 -88 -80s-3 -2 -6 -2s-5 1 -6 2s-88 80 -88 80c-3 3 -3 9 0 12s9 3 12 0l74 -67v285c0 4 4 8 8 8s8 -4 8 -8v-285l74 67c3 3 9 3 12 0z" /> - <glyph glyph-name="ion-ios7-arrow-thin-left" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-arrow-thin-left" unicode="" horiz-adv-x="320" d="M94 98c-2 -2 -4 -2 -6 -2s-4 0 -6 2c0 0 -79 87 -80 88s-2 3 -2 6s1 5 2 6s80 88 80 88c3 3 9 3 12 0s3 -9 0 -12l-67 -74h285c4 0 8 -4 8 -8s-4 -8 -8 -8h-285l67 -74c3 -3 3 -9 0 -12z" /> - <glyph glyph-name="ion-ios7-arrow-thin-right" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-arrow-thin-right" unicode="" horiz-adv-x="320" d="M226 98c-3 3 -3 9 0 12l67 74h-285c-4 0 -8 4 -8 8s4 8 8 8h285l-67 74c-3 3 -3 9 0 12s9 3 12 0c0 0 79 -87 80 -88s2 -3 2 -6s-1 -5 -2 -6s-80 -88 -80 -88c-2 -2 -4 -2 -6 -2s-4 0 -6 2z" /> - <glyph glyph-name="ion-ios7-arrow-thin-up" unicode="" horiz-adv-x="192" + <glyph glyph-name="ion-ios-arrow-thin-up" unicode="" horiz-adv-x="192" d="M190 258c-3 -3 -9 -3 -12 0l-74 67v-285c0 -4 -4 -8 -8 -8s-8 4 -8 8v285l-74 -67c-3 -3 -9 -3 -12 0s-3 9 0 12c0 0 87 79 88 80s3 2 6 2s5 -1 6 -2s88 -80 88 -80c2 -2 2 -4 2 -6s0 -4 -2 -6z" /> - <glyph glyph-name="ion-ios7-arrow-up" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-arrow-up" unicode="" horiz-adv-x="320" d="M301 96l-141 150l-141 -150l-19 21l160 171l160 -171z" /> - <glyph glyph-name="ion-ios7-at-outline" unicode="" horiz-adv-x="255" + <glyph glyph-name="ion-ios-at-outline" unicode="" horiz-adv-x="255" d="M236 127v1h19l-3 -6c-3 -6 -13 -19 -22 -27s-18 -14 -28 -20s-21 -10 -32 -13s-23 -5 -34 -5c-16 0 -33 3 -49 8s-30 13 -43 24c-12 11 -26 29 -34 46c-7 16 -10 33 -10 58c0 18 4 38 11 55c7 16 17 30 29 42s27 21 43 28c15 6 33 9 53 9c16 0 32 -3 46 -8 c15 -5 28 -12 39 -22s17 -21 24 -35c6 -13 8 -26 8 -44c0 -14 -2 -28 -7 -40s-9 -20 -17 -30c-8 -9 -13 -15 -23 -21c-11 -6 -20 -9 -29 -9c-8 0 -15 2 -20 7c-3 2 -5 6 -6 9c-6 -6 -11 -10 -17 -12c-10 -3 -18 -4 -26 -4s-15 1 -21 4s-12 7 -17 12s-8 11 -11 18 s-5 14 -5 22c0 12 3 24 7 36v2c4 11 5 16 13 26c8 11 17 19 28 26s24 11 38 11c12 0 21 -3 31 -9c7 -4 12 -10 16 -16l6 17h18l-38 -102c-2 -5 -4 -10 -5 -14s-1 -7 -1 -10c0 -2 1 -4 3 -5s4 -2 8 -2c6 0 11 2 20 7c8 4 12 9 19 17c6 8 10 14 14 25s6 23 6 35 c0 15 -2 25 -7 36c-6 13 -10 22 -19 30s-20 15 -33 20s-27 7 -42 7c-19 0 -35 -3 -48 -9c-15 -6 -27 -14 -37 -24c-11 -10 -19 -23 -25 -37c-6 -15 -10 -32 -10 -48c0 -22 2 -36 8 -49c6 -15 17 -31 28 -41s24 -18 38 -23s30 -7 46 -7c10 0 20 1 30 4s18 6 27 11 s17 11 24 18s14 13 19 21zM147 154c4 5 8 12 11 20l21 57c-2 5 -4 10 -7 13c-3 4 -6 6 -10 8c-1 0 -1 1 -2 1c-3 2 -5 3 -9 4c-5 1 -9 2 -13 2c-10 0 -19 -3 -28 -9s-17 -13 -23 -22c-5 -8 -7 -11 -10 -20c0 -1 -1 -3 -1 -4c-4 -11 -5 -20 -5 -30c0 -6 1 -11 3 -16 s5 -9 8 -13s7 -6 12 -8s9 -3 15 -3c4 0 9 1 14 2c4 1 8 2 12 5s8 7 12 13z" /> - <glyph glyph-name="ion-ios7-at" unicode="" horiz-adv-x="256" + <glyph glyph-name="ion-ios-at" unicode="" horiz-adv-x="256" d="M228 128v0h28c-1 -1 -2 -4 -3 -6c-4 -6 -14 -19 -23 -27s-18 -14 -28 -20s-20 -10 -32 -13c-11 -3 -23 -5 -34 -5c-16 0 -33 3 -49 8s-30 13 -43 24c-12 10 -26 28 -34 46c-7 16 -10 33 -10 58c0 19 4 39 11 55s17 30 29 42s28 21 44 28c15 6 32 9 52 9c16 0 31 -3 46 -8 s28 -12 39 -22s18 -22 25 -36c6 -14 8 -26 8 -44c0 -14 -2 -28 -7 -40c-4 -11 -9 -20 -17 -30c-7 -9 -14 -16 -24 -22c-12 -6 -21 -9 -30 -9s-16 2 -22 8c-2 1 -3 3 -4 5c-4 -4 -9 -6 -14 -8c-10 -3 -18 -5 -27 -5c-8 0 -16 2 -23 5s-12 7 -17 12s-9 12 -12 19s-4 14 -4 22 c0 12 2 25 6 37l1 1c4 10 5 17 13 27c8 11 17 20 28 27c12 7 24 10 38 10c12 0 22 -3 33 -9c5 -3 8 -6 12 -10l5 12h25l-39 -104c-2 -5 -3 -9 -4 -13c-1 -3 -1 -7 -1 -9s0 -3 1 -3c0 0 1 -1 5 -1c5 0 11 2 19 7c7 4 10 8 16 16s9 13 13 23s6 20 6 32c0 14 -1 24 -6 34 c-5 12 -10 21 -18 28c-9 8 -19 14 -31 18s-26 7 -40 7c-18 0 -32 -3 -44 -8c-14 -6 -25 -13 -35 -23s-18 -22 -24 -35c-6 -14 -9 -30 -9 -45c0 -21 3 -34 8 -46c6 -14 16 -30 26 -39s22 -16 35 -21c14 -5 28 -7 43 -7c10 0 20 2 29 4s18 6 26 11s28 20 38 33zM144 157 c4 5 7 12 10 19l20 55c-1 4 -3 7 -5 9c-3 3 -6 6 -9 8h-1h-1v1c-3 2 -5 2 -8 3c-4 1 -8 1 -12 1c-9 0 -17 -2 -25 -7c-10 -6 -17 -14 -21 -21c-5 -8 -6 -11 -9 -19c0 -1 -1 -2 -1 -3c-3 -10 -6 -19 -6 -28c0 -5 1 -10 3 -14s4 -8 7 -11s7 -6 11 -8s8 -2 13 -2c4 0 8 0 12 1 v0c4 1 7 2 11 5c3 2 7 5 11 11z" /> - <glyph glyph-name="ion-ios7-barcode-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-barcode-outline" unicode="" horiz-adv-x="416" d="M0 64v256h80v-16h-64v-224h64v-16h-80zM336 320h80v-256h-80v16h64v224h-64v16zM64 128v128h16v-128h-16zM336 128v128h16v-128h-16zM272 96v192h16v-192h-16zM128 96v192h16v-192h-16zM199 112v160h16v-160h-16z" /> - <glyph glyph-name="ion-ios7-barcode" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-barcode" unicode="" horiz-adv-x="416" d="M0 320h416v-256h-416v256zM80 128v128h-16v-128h16zM144 96v192h-16v-192h16zM215 112v160h-16v-160h16zM288 96v192h-16v-192h16zM352 128v128h-16v-128h16z" /> - <glyph glyph-name="ion-ios7-baseball-outline" unicode="" -d="M378 355c43 -41 70 -99 70 -163s-27 -122 -70 -163c-4 -4 -8 -8 -12 -11c-39 -31 -88 -50 -142 -50c-55 0 -105 19 -144 52c-4 3 -8 7 -12 11c-42 41 -68 98 -68 161s26 120 68 161c4 4 8 8 12 11c39 33 89 52 144 52c54 0 103 -19 142 -50c4 -3 8 -7 12 -11zM77 45l3 -3 -l3 3c9 9 18 19 25 30l-20 10l7 15l22 -11c4 7 8 14 11 22c2 5 3 9 5 14l-23 5l3 16l25 -5c4 14 5 28 6 43h-24v16h24c-1 14 -3 28 -6 42l-25 -5l-3 16l24 4c-2 5 -4 11 -6 16c-3 7 -7 14 -11 21l-22 -11l-7 14l21 11c-7 11 -16 21 -26 31l-3 3l-3 -3 -c-19 -19 -35 -41 -45 -66c-11 -26 -16 -53 -16 -81s5 -55 16 -81c10 -25 26 -47 45 -66zM305 0c17 7 33 17 48 29c-13 12 -23 25 -33 40l-25 -13l-7 14l24 12c-7 13 -13 27 -18 41l-27 -5l-3 16l25 4c-4 15 -5 30 -6 46h-27v16h27c1 15 3 30 6 44l-25 5l3 16l26 -5 -c5 14 11 28 18 41l-23 12l7 14l24 -13c10 15 21 29 34 41c-15 12 -31 22 -48 29c-26 11 -53 16 -81 16s-55 -5 -81 -16c-19 -8 -36 -18 -51 -31c12 -11 22 -24 31 -38l22 12l7 -14l-21 -11c7 -13 13 -27 18 -42l24 5l3 -16l-22 -4c4 -14 5 -30 6 -45h24v-16h-24 -c-1 -16 -3 -31 -7 -46l23 -4l-3 -16l-24 4c-5 -14 -11 -28 -18 -41l21 -11l-7 -14l-23 12c-9 -13 -19 -26 -30 -37c15 -13 32 -23 51 -31c26 -11 53 -16 81 -16s55 5 81 16zM371 45c19 19 35 41 45 66c11 26 16 53 16 81s-5 55 -16 81c-10 25 -26 47 -45 66l-5 5 -c-2 -2 -4 -3 -6 -5c-10 -10 -18 -21 -26 -32l18 -10l-7 -14l-20 10c-4 -7 -7 -13 -10 -20c-2 -5 -4 -11 -6 -16l21 -4l-3 -16l-22 4c-3 -13 -5 -27 -6 -41h21v-16h-21c1 -14 3 -29 6 -43l22 5l3 -16l-20 -4c2 -5 3 -10 5 -15c3 -7 7 -14 11 -21l19 10l7 -15l-18 -9 -c7 -11 16 -21 26 -31c2 -2 4 -3 6 -5z" /> - <glyph glyph-name="ion-ios7-baseball" unicode="" -d="M83 45l-3 -3c-4 -4 -8 -8 -12 -11c-42 41 -68 98 -68 161s26 120 68 161c4 -3 8 -7 12 -11l3 -3c10 -10 19 -20 26 -31l-21 -11l7 -14l22 11c4 -7 8 -14 11 -21c2 -5 4 -11 6 -16l-24 -4l3 -16l25 5c3 -14 5 -28 6 -42h-24v-16h24c-1 -15 -2 -29 -6 -43l-25 5l-3 -16 -l23 -4c-2 -5 -3 -10 -5 -15c-3 -8 -7 -15 -11 -22l-22 11l-7 -15l20 -10c-7 -11 -16 -21 -25 -30zM320 69c10 -15 20 -28 33 -40c4 -4 9 -8 13 -11c-39 -31 -88 -50 -142 -50c-55 0 -105 19 -144 52c4 3 8 7 12 11c11 11 21 24 30 37l23 -12l7 14l-21 11c7 13 13 27 18 41 -l24 -4l3 16l-23 4c4 15 6 30 7 46h24v16h-24c-1 15 -2 31 -6 45l22 4l-3 16l-24 -5c-5 15 -11 29 -18 42l21 11l-7 14l-22 -12c-9 14 -19 27 -31 38c-4 4 -8 8 -12 11c39 33 89 52 144 52c54 0 102 -19 141 -50c-4 -3 -8 -7 -12 -11c-13 -12 -24 -26 -34 -41l-24 13l-7 -14 -l23 -12c-7 -13 -13 -27 -18 -41l-26 5l-3 -16l25 -5c-3 -14 -5 -29 -6 -44h-27v-16h27c1 -16 2 -31 6 -46l-25 -4l3 -16l27 5c5 -14 11 -28 18 -41l-24 -12l7 -14zM448 192c0 -64 -27 -122 -70 -163c-4 3 -8 7 -12 11c-2 2 -4 3 -6 5c-10 10 -19 20 -26 31l18 9l-7 15 -l-19 -10c-4 7 -8 14 -11 21c-2 5 -3 10 -5 15l20 4l-3 16l-22 -5c-3 14 -5 29 -6 43h21v16h-21c1 14 3 28 6 41l22 -4l3 16l-21 4c2 5 4 11 6 16c3 7 6 13 10 20l20 -10l7 14l-18 10c8 11 16 22 26 32c2 2 4 3 6 5c4 4 8 8 12 11c43 -41 70 -99 70 -163zM68 353v0v0v0z -M68 31v0v0zM80 20v0v0v0zM80 364v0v0zM378 29v0v0v0zM378 355v0v0zM366 366v0v0v0zM366 18v0v0z" /> - <glyph glyph-name="ion-ios7-basketball-outline" unicode="" -d="M378 355c43 -41 70 -99 70 -163s-27 -122 -70 -163c-4 -4 -8 -8 -12 -11c-39 -31 -88 -50 -142 -50c-55 0 -105 19 -144 52c-4 3 -8 7 -12 11c-42 41 -68 98 -68 161s26 120 68 161c4 4 8 8 12 11c39 33 89 52 144 52c54 0 103 -19 142 -50c4 -3 8 -7 12 -11zM371 339 -l-5 5c-2 -2 -4 -3 -6 -5c-19 -19 -35 -41 -45 -66c-10 -23 -15 -48 -16 -73h133c-1 25 -6 50 -16 73c-10 25 -26 47 -45 66zM353 355c-15 12 -31 22 -48 29c-23 10 -48 15 -73 16v-200h51c2 61 29 116 70 155zM143 384c-19 -8 -36 -18 -51 -31c40 -39 66 -93 68 -153h56v200 -c-25 -1 -50 -6 -73 -16zM77 339c-19 -19 -35 -41 -45 -66c-10 -23 -15 -48 -16 -73h128c-1 25 -6 50 -16 73c-10 25 -26 47 -45 66l-3 3zM77 45l3 -3l3 3c19 19 35 41 45 66c10 23 15 48 16 73h-128c1 -25 6 -50 16 -73c10 -25 26 -47 45 -66zM92 31c15 -13 32 -23 51 -31 -c23 -10 48 -15 73 -16v200h-56c-2 -60 -28 -114 -68 -153zM305 0c17 7 33 17 48 29c-41 39 -68 94 -70 155h-51v-200c25 1 50 6 73 16zM371 45c19 19 35 41 45 66c10 23 15 48 16 73h-133c1 -25 6 -50 16 -73c10 -25 26 -47 45 -66c2 -2 4 -3 6 -5z" /> - <glyph glyph-name="ion-ios7-basketball" unicode="" -d="M160 200c-2 60 -28 114 -68 153c-4 4 -8 8 -12 11c37 31 84 50 136 52v-216h-56zM283 200h-51v216c51 -2 96 -20 133 -50c-4 -3 -8 -7 -12 -11c-41 -39 -68 -94 -70 -155zM360 339l5 5c4 4 9 8 13 11c41 -39 68 -94 70 -155h-149c1 25 6 50 16 73c10 25 26 47 45 66z -M128 273c10 -23 15 -48 16 -73h-144c2 60 28 114 68 153c4 -3 8 -7 12 -11l3 -3c19 -19 35 -41 45 -66zM283 184c2 -61 29 -116 70 -155c4 -4 8 -8 12 -11c-37 -30 -82 -48 -133 -50v216h51zM83 45l-3 -3c-4 -4 -8 -8 -12 -11c-40 39 -66 93 -68 153h144 -c-1 -25 -6 -50 -16 -73c-10 -25 -26 -47 -45 -66zM315 111c-10 23 -15 48 -16 73h149c-2 -61 -29 -116 -70 -155c-4 3 -9 7 -13 11l-5 5c-19 19 -35 41 -45 66zM160 184h56v-216c-52 2 -99 21 -136 52c4 3 8 7 12 11c40 39 66 93 68 153zM68 31v0v0zM378 29v0v0v0zM68 353v0 -v0v0zM80 20v0v0v0zM365 18v0v0zM80 364v0v0zM365 366v0v0v0zM378 355v0v0z" /> - <glyph glyph-name="ion-ios7-bell-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-baseball-outline" unicode="" horiz-adv-x="416" +d="M415 169v-1v0c-11 -97 -90 -174 -187 -183v0h-2c-2 0 -3 -1 -5 -1h-1h-3h-1h-8c-115 0 -208 93 -208 208v8v1v3v1c0 2 1 3 1 5v2v0c9 97 86 176 183 187v0v0c8 1 16 1 24 1c115 0 208 -93 208 -208c0 -7 0 -14 -1 -20v0v-3zM399 192c0 105 -86 191 -191 191 +c-3 0 -5 -1 -8 -1c0 -11 2 -21 4 -31l20 6l5 -15l-21 -7c2 -7 4 -14 7 -21c2 -5 5 -11 8 -16l17 12l9 -13l-19 -13c7 -12 16 -23 26 -33l14 15l12 -12l-15 -15c11 -10 22 -18 34 -25l12 18l14 -9l-12 -17c5 -2 10 -5 15 -7c7 -3 14 -5 22 -7l7 20l15 -5l-6 -19 +c10 -2 20 -4 30 -4c0 3 1 5 1 8zM17 192c0 -105 86 -191 191 -191h4c-1 9 -1 17 -3 26l-22 -7l-5 16l23 7c-2 8 -5 16 -8 24c-2 5 -4 9 -6 14l-20 -13l-9 13l21 14c-7 12 -16 24 -26 35l-17 -17l-11 11l17 17c-10 10 -22 18 -34 25l-14 -21l-14 9l14 20c-5 2 -10 5 -15 7 +c-7 3 -15 6 -23 8l-8 -24l-15 5l7 23c-9 2 -18 2 -27 3v-4zM228 2c88 9 158 78 169 166c-11 1 -23 3 -34 5l-9 -27l-15 5l8 25c-14 4 -28 10 -41 17l-15 -23l-13 9l14 21c-13 8 -26 17 -37 28l-19 -19l-11 11l19 19c-10 11 -19 23 -27 36l-21 -14l-9 13l22 15 +c-7 13 -12 27 -16 41l-25 -8l-5 16l26 8c-2 12 -4 23 -5 35c-88 -11 -157 -81 -166 -169c10 -1 21 -2 31 -4l8 23l15 -5l-7 -22c14 -4 28 -9 42 -16l13 19l14 -9l-13 -18c13 -8 25 -17 36 -28l17 17l11 -11l-17 -17c11 -12 20 -24 28 -37l19 13l9 -14l-20 -13 +c7 -14 12 -28 16 -42l23 7l5 -15l-24 -8c2 -10 3 -20 4 -30z" /> + <glyph glyph-name="ion-ios-baseball" unicode="" horiz-adv-x="416" +d="M208 400c115 0 208 -93 208 -208c0 -8 0 -16 -1 -24v0v0c-12 -104 -100 -184 -207 -184c-115 0 -208 93 -208 208c0 107 80 195 184 207v0v0c8 1 16 1 24 1zM212 1c5 0 11 0 16 1c-1 10 -2 20 -4 30l24 8l-5 15l-23 -7c-4 14 -9 28 -16 42l20 13l-9 14l-19 -13 +c-8 13 -17 25 -28 37l17 17l-11 11l-17 -17c-11 11 -23 20 -36 28l13 18l-14 9l-13 -19c-14 7 -28 12 -42 16l7 22l-15 5l-8 -23c-10 2 -21 3 -31 4c-1 -5 -1 -11 -1 -16c9 -1 18 -1 27 -3l-7 -23l15 -5l8 24c8 -2 16 -5 23 -8c5 -2 10 -5 15 -7l-14 -20l14 -9l14 21 +c12 -7 24 -15 34 -25l-17 -17l11 -11l17 17c10 -11 19 -23 26 -35l-21 -14l9 -13l20 13c2 -5 4 -9 6 -14c3 -8 6 -16 8 -24l-23 -7l5 -16l22 7c2 -8 2 -17 3 -26zM363 173c11 -2 23 -4 34 -5c1 5 1 11 1 16c-10 1 -20 2 -30 4l6 19l-15 5l-7 -20c-8 2 -15 4 -22 7 +c-5 2 -10 5 -15 7l12 17l-14 9l-12 -18c-12 7 -23 15 -34 25l15 15l-12 12l-15 -15c-10 10 -18 21 -25 33l19 13l-9 13l-17 -12c-3 5 -6 11 -8 16c-3 7 -5 14 -7 21l21 7l-5 15l-20 -6c-2 10 -3 20 -4 31c-5 0 -11 0 -16 -1c1 -12 3 -23 5 -35l-26 -8l5 -16l25 8 +c4 -14 9 -28 16 -41l-22 -15l9 -13l21 14c8 -13 17 -25 27 -36l-19 -19l11 -11l19 19c11 -11 24 -20 37 -28l-14 -21l13 -9l15 23c13 -7 27 -13 41 -17l-8 -25l15 -5z" /> + <glyph glyph-name="ion-ios-basketball-outline" unicode="" horiz-adv-x="416" +d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM399 192c0 55 -24 105 -62 140c-14 -34 -31 -65 -52 -95c15 -12 31 -21 49 -29c21 -9 43 -14 65 -16v0zM325 343c-32 25 -73 40 -117 40v0c2 -22 6 -44 15 -65 +c10 -25 26 -47 45 -66c2 -1 2 -3 4 -4c20 29 38 60 52 93c0 1 1 1 1 2zM192 382c-51 -4 -96 -29 -128 -65c64 -28 121 -69 169 -119c11 12 21 24 30 37c-40 37 -67 89 -71 147zM233 174c-15 -16 -31 -30 -48 -44c28 -35 45 -79 47 -127c33 4 63 17 88 35 +c-22 50 -51 95 -87 136zM214 178l8 8l-10 10c-46 46 -99 82 -158 108c-18 -25 -31 -55 -35 -88c62 -3 116 -31 155 -74c14 11 27 23 40 36zM18 200c0 -3 -1 -5 -1 -8c0 -45 16 -87 43 -120c36 16 71 36 102 60l-7 7c-19 19 -41 35 -66 45c-22 9 -46 15 -71 16zM71 59 +c35 -36 83 -58 137 -58c3 0 5 1 8 1c-1 25 -6 48 -16 71c-7 17 -17 33 -28 47c-31 -24 -65 -45 -101 -61zM333 48c37 32 61 77 65 128c-46 3 -89 21 -123 48c-10 -13 -20 -26 -31 -38c36 -41 67 -87 89 -138z" /> + <glyph glyph-name="ion-ios-basketball" unicode="" horiz-adv-x="416" +d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM333 48c-22 51 -53 97 -89 138c11 12 21 25 31 38c34 -27 77 -45 123 -48c0 5 1 11 1 16c-22 2 -44 7 -65 16c-18 8 -34 17 -49 29c21 30 38 61 52 95c-4 4 -8 8 -12 11 +c0 -1 -1 -1 -1 -2c-14 -33 -32 -64 -52 -93c-2 1 -2 2 -4 4c-19 19 -35 41 -45 66c-9 21 -13 43 -15 65c-5 0 -11 -1 -16 -1c4 -58 31 -110 71 -147c-9 -13 -19 -25 -30 -37c-48 50 -105 91 -169 119c-4 -4 -7 -9 -10 -13c59 -26 112 -62 158 -108l10 -10l-8 -8 +c-13 -13 -26 -25 -40 -36c-39 43 -93 71 -155 74c-1 -5 -1 -11 -1 -16c25 -1 49 -7 71 -16c25 -10 47 -26 66 -45l7 -7c-31 -24 -66 -44 -102 -60c4 -4 7 -9 11 -13c36 16 70 37 101 61c11 -14 21 -30 28 -47c10 -23 15 -46 16 -71c5 0 11 0 16 1c-2 48 -19 92 -47 127 +c17 14 33 28 48 44c36 -41 65 -86 87 -136c4 3 9 6 13 10z" /> + <glyph glyph-name="ion-ios-bell-outline" unicode="" horiz-adv-x="384" d="M318 222c0 -114 28 -126 66 -158h-384c38 32 66 44 66 158c0 98 53 130 102 138v2c0 12 11 22 24 22s24 -10 24 -22v-2c49 -7 102 -40 102 -138zM43 80h298c-25 25 -40 58 -40 142c0 46 -13 80 -37 101c-23 19 -52 23 -72 23s-49 -4 -72 -23c-25 -21 -37 -55 -37 -101 c0 -51 -5 -85 -17 -110c-6 -13 -14 -23 -23 -32zM192 0c-27 0 -49 20 -52 43h104c-3 -23 -25 -43 -52 -43z" /> - <glyph glyph-name="ion-ios7-bell" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-bell" unicode="" horiz-adv-x="384" d="M318 222c0 -114 28 -126 66 -158h-384c38 32 66 44 66 158c0 98 53 130 102 138v2c0 12 11 22 24 22s24 -10 24 -22v-2c49 -7 102 -40 102 -138zM192 0c-27 0 -49 20 -52 43h104c-3 -23 -25 -43 -52 -43z" /> - <glyph glyph-name="ion-ios7-bolt-outline" unicode="" horiz-adv-x="226" + <glyph glyph-name="ion-ios-body-outline" unicode="" horiz-adv-x="384" +d="M192 400c-18 0 -32 -14 -32 -32s14 -32 32 -32s32 14 32 32s-14 32 -32 32zM192 416v0c27 0 48 -21 48 -48s-21 -48 -48 -48s-48 21 -48 48s21 48 48 48zM360 304c13 0 24 -11 24 -24s-11 -24 -24 -24h-100c-5 0 -14 -5 -18 -15c-5 -12 -2 -33 1 -51l4 -21v-1v0l32 -172 +c2 -13 -6 -26 -19 -28h-5c-11 0 -22 8 -24 20l-21 120v0s-5 31 -17 31h-2c-12 0 -19 -31 -19 -31v0l-21 -120c-2 -12 -11 -20 -22 -20h-5c-13 2 -21 15 -19 28l32 172v1l4 21c3 18 6 39 1 51c-4 10 -12 15 -18 15h-100c-13 0 -24 11 -24 24s11 24 24 24h336zM24 272 +c-4 0 -8 4 -8 8s4 8 8 8h336c4 0 8 -4 8 -8s-4 -8 -8 -8h-102c-16 0 -26 -15 -30 -24c-5 -13 -6 -32 -1 -61v0v0l3 -19l1 -3l32 -172c0 -3 0 -5 -1 -6s-2 -2 -5 -3h-2c-4 0 -7 2 -8 6l-21 120v0c0 2 -2 10 -5 19c-2 6 -5 11 -8 15c-7 9 -14 11 -20 11h-2 +c-5 0 -13 -2 -20 -11c-3 -4 -6 -9 -8 -15c-4 -9 -6 -17 -6 -18v-1l-21 -120c-1 -4 -3 -6 -7 -6h-2c-3 0 -4 2 -5 3s-2 3 -1 6l32 172v0v1l4 21v0v0c5 29 5 48 0 61c-4 9 -14 24 -32 24z" /> + <glyph glyph-name="ion-ios-body" unicode="" horiz-adv-x="384" +d="M144 368c0 32 16 48 48 48s48 -16 48 -48s-16 -48 -48 -48s-48 16 -48 48zM360 304c7 0 12 -2 17 -7s7 -10 7 -17s-2 -12 -7 -17s-10 -7 -17 -7h-98c-8 -2 -15 -6 -18 -14c-4 -9 -3 -27 1 -52l4 -21v-1v0l30 -172c1 -7 0 -13 -4 -18s-8 -9 -15 -10s-13 0 -18 4 +s-9 9 -10 16l-21 120v-1l-2 9c-1 5 -3 11 -6 16s-6 8 -10 8h-2c-8 0 -14 -11 -18 -33v1l-21 -120c-1 -7 -5 -12 -10 -16s-11 -5 -18 -4s-11 5 -15 10s-5 11 -4 18l30 172v0v1l4 21c4 25 5 43 1 52c-3 8 -10 12 -18 14h-98c-7 0 -12 2 -17 7s-7 10 -7 17s2 12 7 17s10 7 17 7 +h336z" /> + <glyph glyph-name="ion-ios-bolt-outline" unicode="" horiz-adv-x="226" d="M131 316l-100 -140h65h19l-3 -19l-17 -89l100 140h-65h-19l3 19zM160 384v0l-30 -160h96l-160 -224l30 160h-96z" /> - <glyph glyph-name="ion-ios7-bolt" unicode="" horiz-adv-x="226" + <glyph glyph-name="ion-ios-bolt" unicode="" horiz-adv-x="226" d="M160 384v0l-30 -160h96l-160 -224l30 160h-96z" /> - <glyph glyph-name="ion-ios7-bookmarks-outline" unicode="" horiz-adv-x="418" + <glyph glyph-name="ion-ios-book-outline" unicode="" horiz-adv-x="384" +d="M284 384c55 0 100 -26 100 -79v-1v-4v-261v-17h-6h-11h-5c-17 30 -44 42 -78 42c-40 0 -74 -28 -82 -64h-20c-8 36 -42 64 -82 64c-34 0 -65 -16 -78 -42h-5h-11h-6v9v264v9v1c0 53 45 79 100 79c41 0 78 -14 92 -44c12 30 51 44 92 44zM184 37v254v13v2 +c-1 43 -39 62 -84 62c-44 0 -81 -19 -84 -61v-1v0v-262h1c19 26 48 36 83 36s66 -17 84 -43zM368 300v14v1c-3 42 -40 53 -84 53c-46 0 -84 -20 -84 -64v-1v-266c18 26 49 43 84 43s66 -10 84 -36v256z" /> + <glyph glyph-name="ion-ios-book" unicode="" horiz-adv-x="384" +d="M100 384c35 0 67 -10 84 -31v-353h-2c-8 36 -42 64 -82 64c-34 0 -65 -16 -78 -42h-5h-11h-6v9v264v9v1c0 53 45 79 100 79zM284 384c55 0 100 -26 100 -79v-1v-4v-261v-17h-6h-11h-5c-17 30 -44 42 -78 42c-40 0 -74 -28 -82 -64h-2v353c17 21 50 31 84 31z" /> + <glyph glyph-name="ion-ios-bookmarks-outline" unicode="" horiz-adv-x="418" d="M385 384c19 0 33 -13 33 -32v-286c0 -19 -14 -34 -33 -34h-143s-25 -4 -25 -19v-13h-8h-8v13c0 15 -11 19 -25 19h-143c-19 0 -33 15 -33 34v286c0 19 14 32 33 32h150c10 0 20 -5 26 -12v0v0c6 7 16 12 26 12h150zM201 37v309c0 9 -12 22 -25 22h-143 c-9 0 -16 -7 -16 -16v-286c0 -9 7 -18 16 -18h144c10 0 19 -3 24 -11zM273 368v-100l23 14l9 6l9 -6l23 -14v100h-64zM401 66v286c0 9 -7 16 -16 16h-32v-131l-48 32l-48 -32v131h-15c-13 0 -25 -13 -25 -22v-309c5 9 14 11 24 11h144c9 0 16 9 16 18z" /> - <glyph glyph-name="ion-ios7-bookmarks" unicode="" horiz-adv-x="418" + <glyph glyph-name="ion-ios-bookmarks" unicode="" horiz-adv-x="418" d="M296 283l-23 -15v116h64v-116l-23 15l-9 6zM385 384c19 0 33 -13 33 -32v-286c0 -19 -14 -34 -33 -34h-143s-25 -4 -25 -19v-13h-8h-8v13c0 15 -11 19 -25 19h-143c-19 0 -33 15 -33 34v286c0 19 14 32 33 32h150s18 -8 18 -15v-329l8 -6l8 6v329s10 15 18 15h22v-146 l48 32l48 -32v146h32z" /> - <glyph glyph-name="ion-ios7-box-outline" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-box-outline" unicode="" horiz-adv-x="320" d="M192 208h-1h-63c-9 0 -16 -7 -16 -16s7 -16 16 -16h64c9 0 16 7 16 16s-7 16 -16 16zM192 224v0c18 0 32 -14 32 -32s-14 -32 -32 -32h-64c-18 0 -32 14 -32 32s14 32 32 32h64zM320 336v-80h-16v-208h-288v208h-16v80h320zM288 64v192h-256v-192h256zM304 272v48h-288 v-48h288z" /> - <glyph glyph-name="ion-ios7-box" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-box" unicode="" horiz-adv-x="320" d="M16 48v192h288v-192h-288zM128 208c-9 0 -16 -7 -16 -16s7 -16 16 -16h64c9 0 16 7 16 16s-7 16 -16 16h-64zM0 336h320v-80h-16h-288h-16v80z" /> - <glyph glyph-name="ion-ios7-briefcase-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-briefcase-outline" unicode="" horiz-adv-x="416" d="M368 320h48v-320h-416v320h48v16h32v-16h48v30v2c0 18 10 32 29 32h99c19 0 32 -14 32 -32v-2v-30h48v16h32v-16zM144 320v0h128v0v30c0 10 -7 18 -17 18h-97c-11 0 -14 -8 -14 -18v-30zM400 16v224h-384v-224h384zM400 256v48h-32v-16h-32v16h-256v-16h-32v16h-32v-48 h384z" /> - <glyph glyph-name="ion-ios7-briefcase" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-briefcase" unicode="" horiz-adv-x="416" d="M48 320v16h32v-16h-32zM0 0v240h416v-240h-416zM336 320v16h32v-16h-32zM368 320h48v-64h-416v64h48v-32h32v32h48v30v2c0 18 10 32 29 32h99c19 0 32 -14 32 -32v-2v-30h48v-32h32v32zM272 320v30c0 10 -7 18 -17 18h-97c-11 0 -14 -8 -14 -18v-30v0h128v0z" /> - <glyph glyph-name="ion-ios7-browsers-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-browsers-outline" unicode="" horiz-adv-x="384" d="M0 304h304v-304h-304v304zM288 16v272h-272v-272h272zM384 384v-304h-64v16h48v272h-272v-48h-16v64h304z" /> - <glyph glyph-name="ion-ios7-browsers" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-browsers" unicode="" horiz-adv-x="384" d="M0 304h304v-304h-304v304zM80 384h304v-304h-64v240h-240v64z" /> - <glyph glyph-name="ion-ios7-calculator-outline" unicode="" horiz-adv-x="288" + <glyph glyph-name="ion-ios-calculator-outline" unicode="" horiz-adv-x="288" d="M32 288v64h224v-64h-224zM48 336v-32h192v32h-192zM256 384c18 0 32 -14 32 -32v-320c0 -18 -14 -32 -32 -32h-224c-18 0 -32 14 -32 32v320c0 18 14 32 32 32h224zM272 32v320c0 9 -7 16 -16 16h-224c-9 0 -16 -7 -16 -16v-320c0 -9 7 -16 16 -16h224c9 0 16 7 16 16z M48 208h32h16v-16h-64v64h16v-16v-32zM48 128h32h16v-16h-64v64h16v-16v-32zM48 48h32h16v-16h-64v64h16v-16v-32zM128 208h32h16v-16h-64v64h16v-16v-32zM208 208h32h16v-16h-64v64h16v-16v-32zM128 128h32h16v-16h-64v64h16v-16v-32zM128 48h32h16v-16h-64v64h16v-16v-32z M208 48h32h16v-16h-64v144h16v-96v-32z" /> - <glyph glyph-name="ion-ios7-calculator" unicode="" horiz-adv-x="288" + <glyph glyph-name="ion-ios-calculator" unicode="" horiz-adv-x="288" d="M256 384c18 0 32 -14 32 -32v-320c0 -18 -14 -32 -32 -32h-224c-18 0 -32 14 -32 32v320c0 18 14 32 32 32h224zM248 168h-48v-128h48v128zM248 248h-48v-48h48v48zM168 88h-48v-48h48v48zM168 168h-48v-48h48v48zM168 248h-48v-48h48v48zM88 88h-48v-48h48v48zM88 168 h-48v-48h48v48zM88 248h-48v-48h48v48zM40 296h208v48h-208v-48z" /> - <glyph glyph-name="ion-ios7-calendar-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-calendar-outline" unicode="" horiz-adv-x="384" d="M16 336v-64h352v64zM288 352h96v-352h-384v352h96v32h16v-32h160v32h16v-32zM368 16v240h-352v-240h352zM368 272v64h-80v-32h-16v32h-160v-32h-16v32h-80v-64h352z" /> - <glyph glyph-name="ion-ios7-calendar" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-calendar" unicode="" horiz-adv-x="384" d="M0 0v256h384v-256h-384zM384 352v-80h-384v80h96v-48h16v48h160v-48h16v48h96zM96 352v32h16v-32h-16zM272 352v32h16v-32h-16z" /> - <glyph glyph-name="ion-ios7-camera-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-camera-outline" unicode="" horiz-adv-x="384" d="M354 288c18 0 30 -13 30 -31v-176c0 -18 -12 -33 -30 -33h-320c-18 0 -34 15 -34 33v176c0 18 16 31 34 31h13v16h34v-16h13c32 36 43 48 55 48h88c12 0 23 -12 55 -48h62zM368 81v176c0 9 -5 15 -14 15h-62h-7l-5 3c-3 4 -7 8 -10 11c-12 13 -20 24 -26 30 c-5 5 -7 4 -7 4h-88s-2 0 -7 -4c-6 -5 -14 -14 -25 -27c-3 -4 -7 -10 -11 -14l-5 -3h-7h-60c-9 0 -18 -7 -18 -15v-176c0 -9 9 -17 18 -17h320c8 0 14 8 14 17zM192 258c47 0 86 -38 86 -85s-39 -85 -86 -85s-86 38 -86 85s39 85 86 85zM192 104c38 0 70 31 70 69 s-32 69 -70 69s-70 -31 -70 -69s32 -69 70 -69zM288 239v17h17v-17h-17zM160 173c0 21 11 32 32 32s32 -11 32 -32s-11 -32 -32 -32s-32 11 -32 32z" /> - <glyph glyph-name="ion-ios7-camera" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-camera" unicode="" horiz-adv-x="384" d="M354 288c18 0 30 -13 30 -31v-176c0 -18 -12 -33 -30 -33h-320c-18 0 -34 15 -34 33v176c0 18 16 31 34 31h13v16h34v-16h13c32 36 43 48 55 48h88c12 0 23 -12 55 -48h62zM192 88c47 0 86 38 86 85s-39 85 -86 85s-86 -38 -86 -85s39 -85 86 -85zM305 239v17h-17v-17h17 zM192 242c38 0 70 -31 70 -69s-32 -69 -70 -69s-70 31 -70 69s32 69 70 69zM192 141c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32z" /> - <glyph glyph-name="ion-ios7-cart-outline" unicode="" horiz-adv-x="384" -d="M377 32c0 -14 -11 -25 -25 -25s-25 11 -25 25s11 25 25 25s25 -11 25 -25zM89 32c0 -14 -11 -25 -25 -25s-25 11 -25 25s11 25 25 25s25 -11 25 -25zM64 352h320l-15 -175s-209 -30 -244 -34s-69 -30 -74 -62h333v-17h-352s0 5 2 17c5 35 33 62 65 73l-57 213h-42v17h53z -M352 192l15 143h-297l44 -177c1 0 2 1 3 1z" /> - <glyph glyph-name="ion-ios7-cart" unicode="" horiz-adv-x="384" -d="M377 32c0 -14 -11 -25 -25 -25s-25 11 -25 25s11 25 25 25s25 -11 25 -25zM89 32c0 -14 -11 -25 -25 -25s-25 11 -25 25s11 25 25 25s25 -11 25 -25zM64 352h320l-15 -175s-209 -30 -244 -34s-69 -30 -74 -62h333v-17h-352s0 5 2 17c5 35 33 62 65 73l-57 213h-42v17h53z -" /> - <glyph glyph-name="ion-ios7-chatboxes-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-cart-outline" unicode="" horiz-adv-x="384" +d="M96 48c13 0 24 -11 24 -24s-11 -24 -24 -24s-24 11 -24 24s11 24 24 24zM96 16c4 0 8 4 8 8s-4 8 -8 8s-8 -4 -8 -8s4 -8 8 -8zM320 48c13 0 24 -11 24 -24s-11 -24 -24 -24s-24 11 -24 24s11 24 24 24zM320 16c4 0 8 4 8 8s-4 8 -8 8s-8 -4 -8 -8s4 -8 8 -8zM384 320 +l-16 -128l-271 -48l5 -30c7 -34 21 -34 26 -34h240v-16h-240c-11 0 -21 5 -28 14c-6 8 -11 19 -13 33l-43 234v0c-2 8 -3 12 -7 16c-6 5 -18 7 -37 7v16c23 0 38 -4 47 -11c7 -6 10 -14 12 -21zM355 206l11 99l-304 31l32 -176z" /> + <glyph glyph-name="ion-ios-cart" unicode="" horiz-adv-x="384" +d="M96 48c13 0 24 -11 24 -24s-11 -24 -24 -24s-24 11 -24 24s11 24 24 24zM320 48c13 0 24 -11 24 -24s-11 -24 -24 -24s-24 11 -24 24s11 24 24 24zM384 320l-16 -128l-271 -48l5 -30c7 -34 21 -34 26 -34h240v-16h-240c-11 0 -21 5 -28 14c-6 8 -11 19 -13 33l-43 234v0 +c-2 8 -3 12 -7 16c-6 5 -18 7 -37 7v16c23 0 38 -4 47 -11c7 -6 10 -14 12 -21z" /> + <glyph glyph-name="ion-ios-chatboxes-outline" unicode="" horiz-adv-x="416" d="M16 384v-192h96v-16h-112v224h288v-112h-16v96h-256zM128 272h288v-224h-48v-64h-13l-64 64h-163v224zM400 64v192h-256v-192h153l55 -55v55h48z" /> - <glyph glyph-name="ion-ios7-chatboxes" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-chatboxes" unicode="" horiz-adv-x="416" d="M288 400v-112h-176v-112h-112v224h288zM128 272h288v-224h-48v-64h-13l-64 64h-163v224z" /> - <glyph glyph-name="ion-ios7-chatbubble-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-chatbubble-outline" unicode="" horiz-adv-x="384" d="M192 336c-97 0 -176 -62 -176 -138c0 -26 10 -51 27 -73c0 -1 0 -2 1 -3s2 -1 2 -2c4 -6 6 -13 6 -20c0 -3 1 -3 -13 -47l39 17v0c2 1 10 4 11 4h1v0c5 2 10 3 16 3c5 0 9 -1 14 -2l1 -1h2c19 -6 41 -10 70 -10c48 0 92 15 125 40c32 25 50 58 50 94 c0 76 -79 138 -176 138zM192 352v0c106 0 192 -69 192 -154s-85 -150 -191 -150c-27 0 -52 3 -75 11h-2v0c-3 1 -6 2 -10 2s-9 -1 -12 -2h1h-1c-1 0 -9 -4 -10 -4l-50 -22l-2 -1h-3h-3c-6 1 -8 6 -7 10v0s17 57 17 58c0 4 -1 8 -3 11v0v0v0l1 -1l-4 4c-19 24 -30 53 -30 84 c0 85 86 154 192 154z" /> - <glyph glyph-name="ion-ios7-chatbubble" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-chatbubble" unicode="" horiz-adv-x="384" d="M192 352v0c106 0 192 -69 192 -154s-85 -150 -191 -150c-27 0 -52 3 -75 11h-2v0c-3 1 -6 2 -10 2s-9 -1 -12 -2h1h-1c-1 0 -9 -4 -10 -4l-50 -22l-2 -1h-3h-3c-6 1 -8 6 -7 10v0s17 57 17 58c0 4 -1 8 -3 11v0v0v0l1 -1l-4 4c-19 24 -30 53 -30 84c0 85 86 154 192 154z " /> - <glyph glyph-name="ion-ios7-checkmark-empty" unicode="" horiz-adv-x="207" + <glyph glyph-name="ion-ios-checkmark-empty" unicode="" horiz-adv-x="207" d="M74 118c-2 -2 -6 -4 -9 -4s-7 2 -9 4l-56 56l18 18l47 -47l125 126l17 -18z" /> - <glyph glyph-name="ion-ios7-checkmark-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-checkmark-outline" unicode="" horiz-adv-x="416" d="M292 271l18 -18l-134 -135c-2 -2 -6 -4 -9 -4s-7 2 -9 4l-56 56l18 18l47 -47zM208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM208 1c105 0 191 86 191 191s-86 191 -191 191s-191 -86 -191 -191s86 -191 191 -191z" /> - <glyph glyph-name="ion-ios7-checkmark" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-checkmark" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM176 118l134 135l-18 18l-125 -126l-47 47l-18 -18l56 -56c2 -2 6 -4 9 -4s7 2 9 4z" /> - <glyph glyph-name="ion-ios7-circle-filled" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-circle-filled" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM208 1c105 0 191 86 191 191s-86 191 -191 191s-191 -86 -191 -191s86 -191 191 -191zM208 352c88 0 160 -72 160 -160s-72 -160 -160 -160s-160 72 -160 160s72 160 160 160z" /> - <glyph glyph-name="ion-ios7-circle-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-circle-outline" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM208 1c105 0 191 86 191 191s-86 191 -191 191s-191 -86 -191 -191s86 -191 191 -191z" /> - <glyph glyph-name="ion-ios7-clock-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-clock-outline" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM208 1c105 0 191 86 191 191s-86 191 -191 191s-191 -86 -191 -191s86 -191 191 -191zM208 192v128h17v-145h-113v17h96z" /> - <glyph glyph-name="ion-ios7-clock" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-clock" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM225 175v145h-17v-128h-96v-17h113z" /> - <glyph glyph-name="ion-ios7-close-empty" unicode="" horiz-adv-x="192" + <glyph glyph-name="ion-ios-close-empty" unicode="" horiz-adv-x="192" d="M180 288l12 -12l-84 -84l84 -84l-12 -12l-84 84l-84 -84l-12 12l84 84l-84 84l12 12l84 -84z" /> - <glyph glyph-name="ion-ios7-close-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-close-outline" unicode="" horiz-adv-x="416" d="M355 339c81 -81 81 -213 0 -294s-213 -81 -294 0s-81 213 0 294s213 81 294 0zM343 57c74 74 74 196 0 270s-196 74 -270 0s-74 -196 0 -270s196 -74 270 0zM292 288l12 -12l-84 -84l84 -84l-12 -12l-84 84l-84 -84l-12 12l84 84l-84 84l12 12l84 -84z" /> - <glyph glyph-name="ion-ios7-close" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-close" unicode="" horiz-adv-x="416" d="M355 339c81 -81 81 -213 0 -294s-213 -81 -294 0s-81 213 0 294s213 81 294 0zM304 108l-84 84l84 84l-12 12l-84 -84l-84 84l-12 -12l84 -84l-84 -84l12 -12l84 84l84 -84z" /> - <glyph glyph-name="ion-ios7-cloud-download-outline" unicode="" + <glyph glyph-name="ion-ios-cloud-download-outline" unicode="" d="M161 67l55 -54v242h16v-242l55 54l12 -12l-75 -73l-74 73zM367 284c45 0 81 -37 81 -82s-37 -82 -82 -82v0h-101v16h97h4c37 0 66 30 66 66s-29 67 -66 67h-15v20c0 55 -46 97 -101 97c-38 0 -73 -22 -90 -56l-6 -14l-14 7c-6 3 -13 5 -20 5c-22 0 -40 -18 -44 -39l-1 -9 l-9 -3c-30 -10 -50 -36 -50 -67c0 -40 33 -74 74 -74h91v-16h-91c-50 0 -90 40 -90 89c0 39 26 71 61 83c5 28 29 51 59 51c10 0 18 -2 26 -6c19 39 59 65 105 65c64 0 117 -51 117 -115c0 -1 -1 -2 -1 -3z" /> - <glyph glyph-name="ion-ios7-cloud-download" unicode="" + <glyph glyph-name="ion-ios-cloud-download" unicode="" d="M216 13v107h16v-107l55 54l12 -12l-75 -73l-74 73l11 12zM367 284c45 0 81 -37 81 -82s-37 -82 -82 -82h-134v135h-16v-135h-35h-21h-70c-50 0 -90 40 -90 89c0 39 26 71 61 83c5 28 29 51 59 51c10 0 18 -2 26 -6c19 39 59 65 105 65c64 0 117 -51 117 -115 c0 -1 -1 -2 -1 -3z" /> - <glyph glyph-name="ion-ios7-cloud-outline" unicode="" + <glyph glyph-name="ion-ios-cloud-outline" unicode="" d="M367 215c45 0 81 -37 81 -83c0 -45 -37 -84 -82 -84h-276c-50 0 -90 42 -90 92c0 40 26 71 61 83c5 28 29 52 59 52c10 0 18 -2 26 -6c19 39 59 67 105 67c64 0 117 -53 117 -117c0 -1 -1 -3 -1 -4zM366 64c37 0 66 32 66 69s-29 67 -66 67h-15v21c0 56 -46 99 -101 99 c-38 0 -73 -23 -90 -58l-6 -14l-14 7c-6 3 -13 5 -20 5c-22 0 -40 -17 -44 -39l-1 -9l-9 -3c-30 -10 -50 -37 -50 -69c0 -41 33 -76 74 -76h272h4z" /> - <glyph glyph-name="ion-ios7-cloud-upload-outline" unicode="" + <glyph glyph-name="ion-ios-cloud-upload-outline" unicode="" d="M161 188l-11 11l74 75l75 -75l-12 -11l-55 54v-242h-16v242zM367 264c45 0 81 -39 81 -85s-37 -83 -82 -83v0h-101v16h97h4c37 0 66 30 66 67s-29 70 -66 70l-15 1v20c0 56 -46 99 -101 99c-38 0 -73 -23 -90 -58l-6 -13l-14 6c-6 3 -13 5 -20 5c-22 0 -40 -17 -44 -39 l-1 -9l-9 -3c-30 -10 -50 -39 -50 -71c0 -41 33 -75 74 -75h91v-16h-91c-50 0 -90 40 -90 90c0 40 26 74 61 86c5 28 29 52 59 52c10 0 18 -2 26 -6c19 39 59 66 105 66c64 0 117 -52 117 -116c0 -1 -1 -3 -1 -4z" /> - <glyph glyph-name="ion-ios7-cloud-upload" unicode="" + <glyph glyph-name="ion-ios-cloud-upload" unicode="" d="M216 0v96h16v-96h-16zM367 264c45 0 81 -39 81 -85s-37 -83 -82 -83h-134v146l55 -54l12 11l-75 75l-74 -75l11 -11l55 54v-146h-35h-31h-60c-50 0 -90 40 -90 90c0 40 26 74 61 86c5 28 29 52 59 52c10 0 18 -2 26 -6c19 39 59 66 105 66c64 0 117 -52 117 -116 c0 -1 -1 -3 -1 -4z" /> - <glyph glyph-name="ion-ios7-cloud" unicode="" + <glyph glyph-name="ion-ios-cloud" unicode="" d="M367 215c45 0 81 -37 81 -83c0 -45 -37 -84 -82 -84h-276c-50 0 -90 42 -90 92c0 40 26 71 61 83c5 28 29 52 59 52c10 0 18 -2 26 -6c19 39 59 67 105 67c64 0 117 -53 117 -117c0 -1 -1 -3 -1 -4z" /> - <glyph glyph-name="ion-ios7-cloudy-night-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-cloudy-night-outline" unicode="" horiz-adv-x="384" d="M125 224c-34 0 -63 -28 -63 -62v-12s1 -10 1 -10c-5 0 -12 -1 -14 -1c-19 -3 -33 -18 -33 -37c0 -10 3 -19 10 -26s16 -11 26 -11h157c27 0 49 22 49 49s-22 50 -49 50c-2 0 -4 -1 -6 -1l-14 -2l-3 14c-3 14 -11 26 -22 35s-25 14 -39 14zM125 240v0c37 0 68 -26 76 -61 h8c36 0 65 -29 65 -65s-29 -66 -65 -66h-157c-28 0 -52 24 -52 53c0 27 21 51 47 53v8c0 43 35 78 78 78zM361 142c8 0 15 2 23 4c-4 -7 -9 -14 -14 -20c-21 -24 -50 -41 -84 -45c4 6 6 12 8 19c19 4 36 13 50 25c-18 1 -35 6 -50 13c-23 11 -42 29 -56 51 c-14 21 -22 48 -22 75c0 15 2 30 7 44c-24 -12 -43 -33 -53 -59c-5 2 -12 4 -18 5c14 36 45 65 82 77c8 2 16 4 24 5c-5 -6 -9 -13 -12 -20c-8 -16 -12 -34 -12 -52c0 -32 12 -63 35 -86s54 -36 86 -36h6z" /> - <glyph glyph-name="ion-ios7-cloudy-night" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-cloudy-night" unicode="" horiz-adv-x="384" d="M361 142c8 0 15 2 23 4c-4 -7 -9 -15 -14 -21c-21 -24 -50 -40 -84 -44h-3c4 10 7 21 7 32c0 22 -9 43 -24 58c-14 15 -33 23 -53 24c-6 16 -16 29 -29 40c-10 8 -20 13 -32 17v2c14 36 45 65 82 77c8 2 16 4 24 5c-5 -6 -9 -13 -12 -20c-8 -16 -12 -34 -12 -52 c0 -32 12 -63 35 -86s54 -36 86 -36h6zM125 239v0c37 0 68 -26 76 -61h8c36 0 65 -29 65 -65s-29 -66 -65 -66h-157c-28 0 -52 24 -52 53c0 27 21 51 47 53v7c0 43 35 79 78 79z" /> - <glyph glyph-name="ion-ios7-cloudy-outline" unicode="" horiz-adv-x="274" + <glyph glyph-name="ion-ios-cloudy-outline" unicode="" horiz-adv-x="274" d="M125 272c-34 0 -63 -28 -63 -62v-12s1 -10 1 -10c-6 0 -12 -1 -14 -1c-19 -3 -33 -18 -33 -37c0 -10 3 -19 10 -26s16 -11 26 -11h157c27 0 49 22 49 49s-22 50 -49 50c-2 0 -4 -1 -6 -1l-14 -2l-3 14c-3 14 -11 26 -22 35s-25 14 -39 14zM125 288v0c37 0 68 -26 76 -61 h8c36 0 65 -29 65 -65s-29 -66 -65 -66h-157c-28 0 -52 24 -52 53c0 27 21 51 47 53v8c0 43 35 78 78 78z" /> - <glyph glyph-name="ion-ios7-cloudy" unicode="" horiz-adv-x="274" + <glyph glyph-name="ion-ios-cloudy" unicode="" horiz-adv-x="274" d="M125 288v0c37 0 68 -26 76 -61h8c36 0 65 -29 65 -65s-29 -66 -65 -66h-157c-28 0 -52 24 -52 53c0 27 21 51 47 53v8c0 43 35 78 78 78z" /> - <glyph glyph-name="ion-ios7-cog-outline" unicode="" horiz-adv-x="384" -d="M313 235c4 -12 7 -25 8 -37v-13c-1 -13 -4 -25 -8 -37c-1 -4 -3 -7 -5 -12c-5 -11 -11 -20 -19 -29c0 0 -2 -3 -6 -7s-7 -6 -7 -6c-9 -8 -19 -14 -29 -19c-4 -2 -8 -3 -11 -4c-12 -4 -24 -7 -37 -8h-13c-13 1 -25 4 -37 8c-4 1 -7 3 -11 5c-11 5 -23 12 -32 21l-4 4l-4 4 -c-9 10 -16 20 -21 32c-2 3 -3 7 -4 10c0 0 -1 3 -3 10s-3 10 -3 10c-1 6 -2 13 -2 19v11c1 13 4 26 8 38c1 4 2 7 4 10c5 12 12 22 21 32c1 2 3 4 4 5s3 3 5 4c9 8 20 15 31 20c4 2 7 4 11 5c12 4 25 7 38 8h11c6 0 13 -1 19 -2l8 -2s11 -4 11 -4c3 -1 7 -2 11 -4 -c12 -5 22 -12 32 -21l4 -4l4 -4c9 -9 15 -20 21 -32c2 -4 4 -7 5 -11zM81 186c0 -5 1 -11 2 -16l103 28l28 103c-5 1 -10 2 -16 2h-10c-11 0 -22 -3 -33 -7c-3 -1 -8 -2 -11 -4c-10 -5 -18 -10 -26 -18l-4 -4l-4 -4c-8 -9 -14 -18 -19 -28l-3 -9c-4 -11 -7 -22 -7 -33v-10z -M240 89c9 4 18 10 26 17l-76 76l-103 -28v-1c1 -3 3 -6 4 -9c5 -10 11 -20 19 -28l4 -4s2 -3 3 -4c8 -8 18 -13 28 -18c3 -2 7 -3 10 -4c10 -4 21 -6 32 -7h11c11 0 22 3 32 7c3 1 7 2 10 3zM305 186v11c-1 11 -3 22 -7 32c-1 3 -2 7 -4 10c-5 10 -11 20 -19 28l-3 3l-4 4 -c-8 8 -18 14 -28 19c-3 2 -7 2 -10 3l-1 1l-28 -104l76 -76c7 8 13 16 17 25c2 3 3 7 4 11c4 10 7 22 7 33zM384 175l-33 -8c-1 -5 -2 -10 -3 -14l27 -20l-12 -30l-34 5c-2 -4 -5 -7 -8 -11l17 -29l-22 -23l-30 17c-3 -2 -6 -5 -10 -7l5 -34l-29 -12l-21 27 -c-4 -1 -9 -2 -14 -3l-8 -33h-32l-9 33c-4 1 -9 2 -13 3l-21 -28l-29 12l4 34c-4 2 -7 5 -11 8l-30 -18l-23 22l18 31c-3 4 -5 7 -7 11l-35 -5l-12 29l28 22c-1 4 -1 8 -2 12l-35 9v32l35 9c1 4 1 8 2 12l-29 22l12 30l36 -5c2 4 5 7 7 10l-19 32l22 22l32 -19c4 3 8 6 12 8 -l-5 35l29 13l22 -29c4 1 8 1 12 2l9 35h32l9 -35c4 -1 8 -1 12 -2l22 28l29 -12l-5 -35c4 -2 7 -5 11 -8l30 18l22 -23l-17 -29c3 -4 5 -7 7 -11l35 5l12 -30l-28 -21c1 -4 2 -9 3 -13l33 -9v-32zM338 140l-8 7l2 10l3 12l1 11l10 2l22 6v7l-22 6l-10 2l-1 11l-3 12l-2 10 -l8 6l18 13l-3 7l-22 -3l-10 -1l-6 8c-2 3 -3 6 -6 10l-7 8l6 10l11 18l-5 6l-20 -12l-8 -5l-9 7l-9 6l-10 6l2 10l4 23l-7 2l-14 -18l-6 -8l-10 2c-4 1 -7 1 -11 2l-11 2l-3 10l-5 23h-7l-6 -23l-3 -10l-11 -2c-4 0 -6 -1 -10 -2l-11 -2l-6 8l-14 19l-7 -3l3 -23l2 -11 -l-9 -5l-2 -1c-3 -2 -5 -4 -8 -6l-9 -6l-9 6l-21 12l-5 -5l12 -21l6 -9l-6 -8c-2 -3 -4 -7 -6 -10l-6 -9l-10 2l-23 3l-3 -7l19 -14l8 -6l-2 -10c-1 -4 -1 -7 -2 -11l-2 -11l-10 -2l-23 -6v-7l23 -6l10 -3l1 -10c1 -4 2 -7 3 -11l2 -11l-8 -6l-19 -14l3 -6l23 3l10 1l6 -9 -c2 -4 4 -7 6 -10l6 -8l-5 -9l-12 -20l5 -5l20 11l9 6l9 -6c3 -2 6 -5 10 -7l9 -5l-2 -11l-3 -22l7 -3l13 18l6 9l11 -3c4 -1 8 -1 12 -2l10 -2l3 -10l5 -21h8l5 21l2 10l11 2c4 1 8 1 12 2l10 3l7 -9l13 -17l7 3l-4 21l-1 11l9 5c2 2 4 4 7 6c0 0 1 1 2 1l8 6l9 -5l19 -11 -l5 5l-11 18l-5 9l6 9c2 3 6 6 8 10l5 9l11 -1l21 -3l3 6z" /> - <glyph glyph-name="ion-ios7-cog" unicode="" horiz-adv-x="384" -d="M384 175l-33 -8c-1 -5 -2 -10 -3 -14l27 -20l-12 -30l-34 5c-2 -4 -5 -7 -8 -11l17 -29l-22 -23l-30 17c-3 -2 -6 -5 -10 -7l5 -34l-29 -12l-21 27c-4 -1 -9 -2 -14 -3l-8 -33h-32l-9 33c-4 1 -9 2 -13 3l-21 -28l-29 12l4 34c-4 2 -7 5 -11 8l-30 -18l-23 22l18 31 -c-3 4 -5 7 -7 11l-35 -5l-12 29l28 22c-1 4 -1 8 -2 12l-35 9v32l35 9c1 4 1 8 2 12l-29 22l12 30l36 -5c2 4 5 7 7 10l-19 32l22 22l32 -19c4 3 8 6 12 8l-5 35l29 13l22 -29c4 1 8 1 12 2l9 35h32l9 -35c4 -1 8 -1 12 -2l22 28l29 -12l-5 -35c4 -2 7 -5 11 -8l30 18 -l22 -23l-17 -29c3 -4 5 -7 7 -11l35 5l12 -30l-28 -21c1 -4 2 -9 3 -13l33 -9v-32zM321 185c0 4 -1 8 -1 12c-1 13 -3 25 -7 37c-1 4 -3 8 -5 12c-5 11 -12 22 -21 31l-4 4l-5 5c-10 9 -19 16 -31 21c-4 2 -8 3 -11 4c0 0 -7 2 -11 3l-8 2c-6 1 -13 3 -19 3h-11 -c-13 -1 -26 -4 -38 -8c-4 -1 -7 -3 -11 -5c-11 -5 -22 -12 -31 -20c-2 -1 -4 -4 -5 -5s-3 -2 -4 -4c-9 -10 -16 -20 -21 -32c-2 -3 -4 -7 -5 -11c-4 -12 -6 -24 -7 -37v-12c0 -6 1 -12 2 -18c0 0 1 -3 3 -10s3 -10 3 -10c1 -3 3 -7 4 -10c5 -12 12 -22 21 -32 -c2 -2 2 -3 4 -5c1 -1 3 -2 4 -3c9 -9 20 -16 32 -22c4 -2 7 -3 11 -4c12 -4 24 -7 37 -8h13c12 1 25 3 37 7c3 1 7 3 11 5c10 5 20 11 29 19c0 0 3 2 7 6s6 7 6 7c8 9 14 18 19 29c2 5 4 8 5 12c4 12 7 24 8 37zM214 301l-28 -103l-103 -28c-1 5 -2 11 -2 16v10 -c0 11 3 22 7 33l3 9c5 10 11 19 19 28l4 4l4 4c8 8 17 13 27 18c3 2 7 3 10 4c11 4 22 7 33 7h10c5 0 11 -1 16 -2zM87 154l103 28l76 -76c-8 -6 -17 -13 -26 -17c-3 -1 -7 -2 -10 -3c-10 -4 -21 -7 -32 -7h-11c-11 0 -22 3 -32 7c-3 1 -8 2 -11 4c-10 5 -19 10 -27 18 -c-1 1 -2 3 -3 4l-4 4c-8 8 -14 18 -19 28c-2 3 -3 6 -4 9v1zM298 229c4 -10 6 -21 7 -32v-11c-1 -11 -3 -23 -7 -33c-1 -4 -2 -7 -4 -11c-4 -9 -10 -17 -17 -25l-76 76l28 104l1 -1c3 -1 7 -2 10 -3c10 -5 20 -11 28 -19l4 -4l3 -3c8 -8 14 -18 19 -28c2 -3 3 -7 4 -10z" /> - <glyph glyph-name="ion-ios7-compose-outline" unicode="" horiz-adv-x="368" -d="M288 48v192l16 16v-224h-304v288h240l-16 -16h-208v-256h272zM158 164l171 171l11 -11l-180 -180h-32v32l180 180l11 -11l-171 -171zM364 368c2 -3 4 -6 4 -10s-2 -7 -4 -10l-12 -12l-21 21l-11 11v0l12 12c3 2 6 4 10 4s7 -2 10 -4z" /> - <glyph glyph-name="ion-ios7-compose" unicode="" horiz-adv-x="368" -d="M128 176l180 180l32 -32l-180 -180h-32v32zM364 368c2 -3 4 -6 4 -10s-2 -7 -4 -10l-12 -12l-21 21l-11 11v0l12 12c3 2 6 4 10 4s7 -2 10 -4zM176 128l128 129v-3v-222h-304v288h240v0v0l-128 -128v-64h64z" /> - <glyph glyph-name="ion-ios7-contact-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-cog-outline" unicode="" horiz-adv-x="384" +d="M384 175l-33 -8l-3 -14l27 -20l-12 -30l-34 5l-8 -11l17 -29l-23 -23l-29 17l-10 -7l5 -34l-29 -12l-21 27l-14 -3l-8 -33h-32l-9 33l-13 3l-21 -28l-29 12l4 34l-11 8l-30 -19l-23 23l18 31l-7 11l-35 -5l-12 29l28 22l-2 12l-35 9v32l35 9l2 12l-29 22l12 30l36 -5 +l7 10l-19 32l22 22l32 -19l11 8l-4 35l29 13l22 -29l12 2l9 35h32l9 -35l12 -2l22 28l29 -12l-5 -35l11 -8l30 18l22 -23l-17 -30l7 -10l35 5l12 -30l-28 -21l3 -13l33 -9v-32zM356 127l-26 20l6 33l32 8v7l-32 8l-6 33l26 19l-3 7l-32 -5l-19 27l17 28l-5 6l-28 -17l-28 18 +l5 34l-6 2l-20 -26l-32 6l-8 33h-7l-9 -33l-32 -6l-20 27l-7 -3l5 -34l-28 -18l-9 6l-21 12l-5 -5l18 -30l-18 -27l-33 5l-3 -7l27 -20l-6 -32l-33 -8v-7l33 -9l6 -32l-27 -20l3 -6l33 4l18 -27l-17 -29l5 -6l29 18l28 -18l-5 -33l7 -3l19 27l33 -7l8 -31h8l7 31l33 7 +l20 -26l7 3l-5 32l26 18l28 -16l5 5l-16 27l19 28l32 -4zM192 320c71 0 128 -57 128 -128s-57 -128 -128 -128s-128 57 -128 128s57 128 128 128zM80 192c0 -7 1 -15 2 -22l104 28l28 104c-7 1 -15 2 -22 2c-30 0 -58 -12 -79 -33s-33 -49 -33 -79zM192 80c27 0 53 10 73 27 +l-75 75l-104 -28c6 -15 15 -29 27 -41c21 -21 49 -33 79 -33zM276 118c18 20 28 47 28 74c0 30 -12 58 -33 79c-12 12 -26 22 -42 27l-28 -105z" /> + <glyph glyph-name="ion-ios-cog" unicode="" horiz-adv-x="384" +d="M229 298c16 -5 30 -15 42 -27c21 -21 33 -49 33 -79c0 -27 -10 -54 -28 -74l-75 75zM214 302l-28 -104l-104 -28c-1 7 -2 15 -2 22c0 30 12 58 33 79s49 33 79 33c7 0 15 -1 22 -2zM86 154l104 28l75 -75c-20 -17 -46 -27 -73 -27c-30 0 -58 12 -79 33 +c-12 12 -21 26 -27 41zM384 175l-33 -8l-3 -14l27 -20l-12 -30l-34 5l-8 -11l17 -29l-23 -23l-29 17l-10 -7l5 -34l-29 -12l-21 27l-14 -3l-8 -33h-32l-9 33l-13 3l-21 -28l-29 12l4 34l-11 8l-30 -19l-23 23l18 31l-7 11l-35 -5l-12 29l28 22l-2 12l-35 9v32l35 9l2 12 +l-29 22l12 30l36 -5l7 10l-19 32l22 22l32 -19l11 8l-4 35l29 13l22 -29l12 2l9 35h32l9 -35l12 -2l22 28l29 -12l-5 -35l11 -8l30 18l22 -23l-17 -30l7 -10l35 5l12 -30l-28 -21l3 -13l33 -9v-32zM192 64c71 0 128 57 128 128s-57 128 -128 128s-128 -57 -128 -128 +s57 -128 128 -128z" /> + <glyph glyph-name="ion-ios-color-filter-outline" unicode="" horiz-adv-x="384" +d="M302 236c47 -13 82 -57 82 -108c0 -62 -50 -112 -112 -112c-31 0 -60 13 -80 34c-20 -21 -49 -34 -80 -34c-62 0 -112 50 -112 112c0 51 35 95 82 108c-1 7 -2 13 -2 20c0 62 50 112 112 112s112 -50 112 -112c0 -7 -1 -13 -2 -20zM96 256c0 -6 0 -12 1 -17 +c5 1 10 1 15 1c31 0 60 -13 80 -34c20 21 49 34 80 34c5 0 10 0 15 -1c1 5 1 11 1 17c0 53 -43 96 -96 96s-96 -43 -96 -96zM208 128c0 6 0 12 -1 17c-5 -1 -10 -1 -15 -1s-10 0 -15 1c-1 -5 -1 -11 -1 -17c0 -20 6 -38 16 -53c10 15 16 33 16 53zM192 160c3 0 7 1 10 1 +c-3 7 -6 14 -10 20c-4 -6 -7 -13 -10 -20c3 0 7 -1 10 -1zM166 164c4 11 9 21 16 30c-18 18 -43 30 -70 30c-3 0 -7 -1 -10 -1c10 -29 34 -51 64 -59zM202 194c7 -9 12 -19 16 -30c30 8 54 30 64 59c-3 0 -7 1 -10 1c-27 0 -52 -12 -70 -30zM112 32c27 0 52 12 70 30 +c-14 19 -22 41 -22 66c0 7 1 13 2 20c-36 10 -64 37 -76 72c-40 -11 -70 -48 -70 -92c0 -53 43 -96 96 -96zM272 32c53 0 96 43 96 96c0 44 -30 81 -70 92c-12 -35 -40 -62 -76 -72c1 -7 2 -13 2 -20c0 -25 -8 -47 -22 -66c18 -18 43 -30 70 -30z" /> + <glyph glyph-name="ion-ios-color-filter" unicode="" horiz-adv-x="384" +d="M302 236c47 -13 82 -57 82 -108c0 -62 -50 -112 -112 -112c-31 0 -60 13 -80 34c-20 -21 -49 -34 -80 -34c-62 0 -112 50 -112 112c0 51 35 95 82 108c-1 7 -2 13 -2 20c0 62 50 112 112 112s112 -50 112 -112c0 -7 -1 -13 -2 -20zM192 53l1 -2c3 3 6 7 9 11 +c14 19 22 41 22 66c0 7 -1 13 -2 20c36 10 64 37 76 72c2 5 3 10 4 15c-1 0 -2 1 -3 1v1c-4 1 -8 1 -12 2c-5 1 -10 1 -15 1c-31 0 -60 -13 -80 -34c-20 21 -49 34 -80 34c-5 0 -10 0 -15 -1c-4 -1 -8 -1 -12 -2v-1c-1 0 -2 -1 -3 -1c1 -5 2 -10 4 -15c12 -35 40 -62 76 -72 +c-1 -7 -2 -13 -2 -20c0 -25 8 -47 22 -66c3 -4 6 -8 9 -11zM207 145c1 -5 1 -11 1 -17c0 -20 -6 -38 -16 -53c-10 15 -16 33 -16 53c0 6 0 12 1 17c5 -1 10 -1 15 -1s10 0 15 1zM282 223c-10 -29 -34 -51 -64 -59c-4 11 -9 21 -16 30c18 18 43 30 70 30c3 0 7 -1 10 -1z +M202 161c-3 0 -7 -1 -10 -1s-7 1 -10 1c3 7 6 14 10 20c4 -6 7 -13 10 -20zM112 224c27 0 52 -12 70 -30c-7 -9 -12 -19 -16 -30c-30 8 -54 30 -64 59c3 0 7 1 10 1z" /> + <glyph glyph-name="ion-ios-color-wand-outline" unicode="" horiz-adv-x="384" +d="M128 298l256 -256l-34 -34l-256 256zM149 232l201 -201l11 11l-201 202zM120 344v40h16v-40h-16zM120 140v40h16v-40h-16zM216 256v16h40v-16h-40zM0 256v16h40v-16h-40zM47 354l29 -29l-12 -11l-28 28zM76 198l-29 -28l-11 11l28 28zM220 342l-28 -28l-12 11l29 29z" /> + <glyph glyph-name="ion-ios-color-wand" unicode="" horiz-adv-x="396" +d="M140 289l256 -257l-34 -34l-256 257zM124 322v64h32v-64h-32zM124 118v64h32v-64h-32zM216 238v32h64v-32h-64zM246 336l-45 -45l-23 22l45 46zM34 336l23 23l45 -46l-23 -22zM34 169l45 45l23 -22l-45 -46zM0 238v32h64v-32h-64z" /> + <glyph glyph-name="ion-ios-compose-outline" unicode="" horiz-adv-x="384" +d="M304 32v208l16 16v-240h-320v304h256l-16 -16h-224v-272h288zM174 164l171 171l11 -11l-180 -180h-32v32l180 180l11 -11l-171 -171zM380 368c2 -3 4 -6 4 -10s-2 -7 -4 -10l-12 -12l-21 21l-11 11v0l12 12c3 2 6 4 10 4s7 -2 10 -4z" /> + <glyph glyph-name="ion-ios-compose" unicode="" horiz-adv-x="384" +d="M192 128l128 128v-240h-320v304h256l-128 -128v-64h64zM324 356l32 -32l-180 -180h-32v32zM380 368c2 -3 4 -6 4 -10s-2 -7 -4 -10l-12 -12l-21 21l-11 11v0l12 12c3 2 6 4 10 4s7 -2 10 -4z" /> + <glyph glyph-name="ion-ios-contact-outline" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM208 383c-105 0 -191 -86 -191 -191c0 -47 17 -89 45 -122c18 8 62 24 90 32c2 1 3 0 3 10c0 11 -1 18 -4 24c-4 8 -7 20 -9 31c-4 5 -10 15 -14 33c-3 16 -1 22 1 28v2 c1 4 0 23 -3 38c-2 10 1 34 15 52c9 12 27 26 58 28h18c32 -2 49 -16 58 -28c14 -18 17 -42 15 -52c-3 -15 -4 -34 -3 -38c0 0 1 -1 1 -2c2 -6 3 -12 0 -28c-4 -18 -10 -27 -14 -32c-2 -11 -5 -24 -9 -32c-3 -7 -6 -15 -6 -23c0 -10 0 -10 2 -11c27 -8 73 -24 93 -32 c28 33 45 76 45 122c0 105 -86 191 -191 191z" /> - <glyph glyph-name="ion-ios7-contact" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-contact" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM208 1c59 0 111 27 146 69c-20 8 -66 24 -93 32c-2 1 -3 1 -3 11c0 8 4 16 7 23c4 8 7 21 9 32c4 5 10 14 14 32c3 16 2 22 0 28c0 0 -1 1 -1 2c-1 4 0 23 3 38c2 10 -1 34 -15 52 c-9 12 -26 26 -58 28h-18c-31 -2 -49 -16 -58 -28c-14 -18 -17 -42 -15 -52c3 -15 4 -34 3 -38v-2c-2 -6 -4 -12 -1 -28c4 -18 10 -28 14 -33c2 -11 5 -23 9 -31c3 -6 4 -13 4 -24c0 -10 -1 -9 -3 -10c-28 -8 -72 -24 -90 -32c35 -42 87 -69 146 -69z" /> - <glyph glyph-name="ion-ios7-copy-outline" unicode="" horiz-adv-x="288" + <glyph glyph-name="ion-ios-copy-outline" unicode="" horiz-adv-x="288" d="M192 352v-64h64v-16h-80v80h16zM213 384l75 -75v-261h-48v-48h-240v336h48v48h165zM224 16v32h-176v272h-32v-304h208zM272 64v238l-65 66h-143v-304h208z" /> - <glyph glyph-name="ion-ios7-copy" unicode="" horiz-adv-x="288" + <glyph glyph-name="ion-ios-copy" unicode="" horiz-adv-x="288" d="M32 32h16h192v-32h-240v336h32v-288v-16zM213 384l75 -75v-261h-48h-192v288v48h165zM256 272v16h-64v64h-16v-80h80z" /> - <glyph glyph-name="ion-ios7-download-outline" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-crop-strong" unicode="" horiz-adv-x="384" +d="M64 336v48h32v-48h-32zM96 96h176v-32h-208v208h32v-176zM336 64v32h48v-32h-48zM0 320h320v-320h-32v288h-288v32z" /> + <glyph glyph-name="ion-ios-crop" unicode="" horiz-adv-x="384" +d="M64 336v48h16v-48h-16zM80 80h208v-16h-224v224h16v-208zM336 64v16h48v-16h-48zM0 320h320v-320h-16v304h-304v16z" /> + <glyph glyph-name="ion-ios-download-outline" unicode="" horiz-adv-x="320" d="M192 304h128v-304h-320v304h128v-16h-112v-272h288v272h-112v16zM97 196l55 -55v243h16v-243l55 55l11 -12l-74 -74l-74 74z" /> - <glyph glyph-name="ion-ios7-download" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-download" unicode="" horiz-adv-x="320" d="M168 304h152v-304h-320v304h152v-163l-55 55l-11 -12l74 -74l74 74l-11 12l-55 -55v163zM152 304v80h16v-80h-16z" /> - <glyph glyph-name="ion-ios7-drag" unicode="" horiz-adv-x="352" + <glyph glyph-name="ion-ios-drag" unicode="" horiz-adv-x="352" d="M0 128v16h352v-16h-352zM0 184v16h352v-16h-352zM0 240v16h352v-16h-352z" /> - <glyph glyph-name="ion-ios7-email-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-email-outline" unicode="" horiz-adv-x="384" d="M0 320h384v-256h-384v256zM192 180l163 124h-326zM16 80h352v214l-115 -88l68 -77l-2 -2l-79 70l-48 -37l-48 37l-79 -70l-2 2l68 77l-115 88v-214z" /> - <glyph glyph-name="ion-ios7-email" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-email" unicode="" horiz-adv-x="384" d="M384 64h-384v242l131 -100l-68 -77l2 -2l79 70l48 -37l48 37l79 -70l2 2l-68 77l131 100v-242zM376 320l-184 -140l-184 140h368z" /> - <glyph glyph-name="ion-ios7-expand" unicode="" horiz-adv-x="364" -d="M214 152l8 8l92 -92l50 50v-108h-108l50 50zM150 232l-8 -8l-92 92l-50 -50v108h108l-50 -50z" /> - <glyph glyph-name="ion-ios7-eye-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-eye-outline" unicode="" horiz-adv-x="384" d="M383 192l1 -1l-6 -6c-21 -21 -47 -48 -78 -69c-36 -24 -72 -36 -108 -36c-83 0 -130 49 -185 105l-7 7l1 1c39 40 67 64 94 81c32 20 63 30 97 30c83 0 146 -60 191 -112zM192 288c-62 0 -111 -36 -170 -96c24 -24 48 -50 76 -68c30 -20 60 -28 94 -28 c75 0 133 56 171 95c-26 29 -50 50 -74 66c-32 21 -64 31 -97 31zM192 112c-44 0 -80 36 -80 80s36 80 80 80s80 -36 80 -80s-36 -80 -80 -80zM192 256c-35 0 -64 -29 -64 -64s29 -64 64 -64s64 29 64 64s-29 64 -64 64zM224 192h16v0c0 -26 -22 -48 -48 -48s-48 21 -48 48 s22 48 48 48v-16c-16 0 -32 -13 -32 -31s15 -33 32 -33s32 14 32 32v0z" /> - <glyph glyph-name="ion-ios7-eye" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-eye" unicode="" horiz-adv-x="384" d="M383 192l1 -1l-6 -6c-21 -21 -47 -48 -78 -69c-36 -24 -72 -36 -108 -36c-83 0 -130 49 -185 105l-7 7l1 1c39 40 67 64 94 81c32 20 63 30 97 30c83 0 146 -60 191 -112zM192 112c44 0 80 36 80 80s-36 80 -80 80s-80 -36 -80 -80s36 -80 80 -80zM186 221 c0 -19 16 -35 35 -35c7 0 14 2 19 6v0c0 -27 -22 -48 -48 -48s-48 21 -48 48s22 48 48 48c-4 -5 -6 -12 -6 -19z" /> - <glyph glyph-name="ion-ios7-fastforward-outline" unicode="" + <glyph glyph-name="ion-ios-fastforward-outline" unicode="" d="M16 293v-202l184 101zM240 292v0v-78v-27v-95l176 100zM224 320v0l224 -128l-224 -128v123l-224 -123v256l224 -123v123z" /> - <glyph glyph-name="ion-ios7-fastforward" unicode="" + <glyph glyph-name="ion-ios-fastforward" unicode="" d="M224 320v0l224 -128l-224 -128v123l-224 -123v256l224 -123v123z" /> - <glyph glyph-name="ion-ios7-filing-outline" unicode="" horiz-adv-x="352" + <glyph glyph-name="ion-ios-filing-outline" unicode="" horiz-adv-x="352" d="M288 320l64 -96v-160h-176h-176v160l64 96h224zM333 224l-45 68v-68h45zM80 304v-80h48c0 -26 22 -48 48 -48s48 22 48 48h48v80h-192zM64 292l-45 -68h45v68zM336 80v128h-98c-7 -28 -32 -48 -62 -48s-55 20 -62 48h-98v-128h160h160z" /> - <glyph glyph-name="ion-ios7-filing" unicode="" horiz-adv-x="352" + <glyph glyph-name="ion-ios-filing" unicode="" horiz-adv-x="352" d="M176 160c30 0 55 20 62 48h114v-144h-176h-176v144h114c7 -28 32 -48 62 -48zM64 224h-7h-57l64 96v0v-80h16v80h192v-80h16v80v0l64 -96h-56h-8h-16h-8h-40c0 -26 -22 -48 -48 -48s-48 22 -48 48h-39h-9h-16z" /> - <glyph glyph-name="ion-ios7-film-outline" unicode="" horiz-adv-x="384" -d="M0 349v35h32v-35h-32zM303 366h-222v-142h222v142zM320 384v0v-177h-256v177h256zM303 160h-222v-143h222v143zM320 178v0v-178h-256v178h256zM0 279v35h32v-35h-32zM0 210v34h32v-34h-32zM0 140v34h32v-34h-32zM0 70v35h32v-35h-32zM0 0v35h32v-35h-32zM352 349v35h32 -v-35h-32zM352 279v35h32v-35h-32zM352 210v34h32v-34h-32zM352 140v34h32v-34h-32zM352 70v35h32v-35h-32zM352 0v35h32v-35h-32z" /> - <glyph glyph-name="ion-ios7-film" unicode="" horiz-adv-x="384" -d="M0 349v35h32v-35h-32zM320 384v0v-177h-256v177h256zM320 178v0v-178h-256v178h256zM0 279v35h32v-35h-32zM0 210v34h32v-34h-32zM0 140v34h32v-34h-32zM0 70v35h32v-35h-32zM0 0v35h32v-35h-32zM352 349v35h32v-35h-32zM352 279v35h32v-35h-32zM352 210v34h32v-34h-32z -M352 140v34h32v-34h-32zM352 70v35h32v-35h-32zM352 0v35h32v-35h-32z" /> - <glyph glyph-name="ion-ios7-flag-outline" unicode="" horiz-adv-x="256" + <glyph glyph-name="ion-ios-film-outline" unicode="" horiz-adv-x="400" +d="M0 360h400v-336h-400v336zM72 40v48h-56v-48h56zM72 104v48h-56v-48h56zM72 168v48h-56v-48h56zM72 232v48h-56v-48h56zM72 296v48h-56v-48h56zM312 40v144h-224v-144h224zM312 200v144h-224v-144h224zM384 40v48h-56v-48h56zM384 104v48h-56v-48h56zM384 168v48h-56v-48 +h56zM384 232v48h-56v-48h56zM384 296v48h-56v-48h56z" /> + <glyph glyph-name="ion-ios-film" unicode="" horiz-adv-x="400" +d="M0 360h400v-336h-400v336zM72 40v48h-56v-48h56zM72 104v48h-56v-48h56zM72 168v48h-56v-48h56zM72 232v48h-56v-48h56zM72 296v48h-56v-48h56zM312 184v16h-224v-16h224zM384 40v48h-56v-48h56zM384 104v48h-56v-48h56zM384 168v48h-56v-48h56zM384 232v48h-56v-48h56z +M384 296v48h-56v-48h56z" /> + <glyph glyph-name="ion-ios-flag-outline" unicode="" horiz-adv-x="256" d="M240 336c6 1 11 1 16 2v-16v-157c-5 -1 -10 -1 -16 -2c-11 -1 -24 -3 -39 -3c-25 0 -47 4 -69 9s-42 13 -64 13c-30 0 -46 -5 -52 -7v-143h-16v142v162v2l3 3c2 1 18 11 65 11c24 0 45 -4 67 -9c21 -4 42 -11 65 -11c15 0 29 3 40 4zM240 179v0v141c-11 -1 -25 -4 -40 -4 c-25 0 -46 6 -68 11s-42 9 -64 9c-30 0 -46 -5 -52 -7v-137c10 3 26 6 52 6c24 0 45 -8 67 -13c21 -4 43 -9 66 -9c15 0 28 2 39 3z" /> - <glyph glyph-name="ion-ios7-flag" unicode="" horiz-adv-x="256" + <glyph glyph-name="ion-ios-flag" unicode="" horiz-adv-x="256" d="M240 336c6 1 11 1 16 2v-16v-157c-5 -1 -10 -1 -16 -2c-11 -1 -24 -3 -39 -3c-25 0 -47 4 -69 9s-42 13 -64 13c-30 0 -46 -5 -52 -7v-143h-16v142v162v2l3 3c2 1 18 11 65 11c24 0 45 -4 67 -9c21 -4 42 -11 65 -11c15 0 29 3 40 4z" /> - <glyph glyph-name="ion-ios7-folder-outline" unicode="" horiz-adv-x="320" -d="M294 304c16 0 26 -9 26 -25v-202c0 -16 -10 -29 -26 -29h-266c-16 0 -28 13 -28 29v235c0 15 12 24 28 24h60c6 0 14 -5 21 -13c8 -9 14 -19 19 -19h166zM28 320c-2 0 -12 1 -12 -8v-56h288v23c0 7 -3 9 -10 9h-166c-14 0 -18 10 -30 24c-6 7 -11 8 -15 8h-11h-44z -M294 64c7 0 10 7 10 13v163h-288v-163c0 -7 6 -13 12 -13h266z" /> - <glyph glyph-name="ion-ios7-folder" unicode="" horiz-adv-x="320" -d="M0 77v163h320v-163c0 -16 -10 -29 -26 -29h-266c-16 0 -28 13 -28 29zM320 279v-23h-320v56c0 15 12 24 28 24h60c6 0 14 -5 21 -13c8 -9 14 -19 19 -19h166c16 0 26 -9 26 -25z" /> - <glyph glyph-name="ion-ios7-football-outline" unicode="" -d="M152 208l72 48l72 -48l-24 -80h-96zM224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM388 64c11 14 21 30 28 47c9 22 15 46 16 70l-13 -10l-42 59v78l21 -3c-8 12 -17 24 -27 34c-19 19 -41 35 -66 45c-7 3 -13 5 -20 7 -l10 -25l-71 -22l-71 22l10 25c-7 -2 -13 -4 -20 -7c-25 -10 -47 -26 -66 -45c-10 -10 -19 -22 -27 -34l21 3v-78l-42 -59l-13 10c1 -24 7 -48 16 -70c7 -17 17 -33 28 -47l1 13l69 -24l44 -61l-2 -2c17 -4 34 -6 52 -6s35 2 52 6l-2 2l44 61l69 24z" /> - <glyph glyph-name="ion-ios7-football" unicode="" -d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM432 181v11c0 28 -5 55 -16 81c-5 11 -11 22 -18 32l-21 3v-78l42 -59zM176 128h96l24 80l-72 48l-72 -48zM285 391c-20 6 -40 9 -61 9s-41 -3 -61 -9l-10 -25l71 -22l71 22z -M32 273c-11 -26 -16 -53 -16 -81v-11l13 -10l42 59v78l-21 -3c-7 -10 -13 -21 -18 -32zM77 45c19 -19 41 -35 66 -45c10 -4 19 -7 29 -10l2 2l-44 61l-69 24l-1 -13c5 -7 11 -13 17 -19zM371 45c6 6 12 12 17 19l-1 13l-69 -24l-44 -61l2 -2c10 3 19 6 29 10 -c25 10 47 26 66 45z" /> - <glyph glyph-name="ion-ios7-gear-outline" unicode="" horiz-adv-x="384" -d="M193 288c26 0 50 -10 68 -28s28 -42 28 -68s-10 -50 -28 -68s-42 -28 -68 -28s-50 10 -68 28s-28 42 -28 68s10 50 28 68s42 28 68 28zM193 112c44 0 80 36 80 80s-36 80 -80 80s-80 -36 -80 -80s36 -80 80 -80zM360 232c14 0 24 -11 24 -25v-15v-15 -c0 -14 -10 -24 -24 -24h-15c-12 0 -23 -11 -23 -24c0 -6 3 -13 8 -17l10 -9c10 -10 10 -25 0 -35l-22 -22c-4 -4 -11 -7 -18 -7s-14 3 -18 7l-9 9c-5 5 -11 8 -17 8c-13 0 -23 -11 -23 -23v-15c0 -14 -11 -25 -25 -25h-30c-14 0 -25 11 -25 25v15c0 12 -10 23 -23 23 -c-6 0 -13 -3 -17 -8l-10 -9c-4 -4 -10 -7 -17 -7s-14 3 -18 7l-22 22c-10 10 -10 25 0 35l9 9c5 4 8 11 8 17c0 13 -11 23 -23 23h-15c-14 0 -25 11 -25 25v15v15c0 14 11 25 25 25h15c12 0 23 10 23 23c0 6 -3 13 -8 17l-9 9c-10 10 -10 25 0 35l22 22c4 4 11 7 18 7 -s13 -3 17 -7l10 -10c4 -5 11 -7 17 -7c13 0 23 11 23 23v15c0 14 11 25 25 25h30c14 0 24 -11 24 -25v-15c0 -12 11 -23 24 -23c6 0 13 3 17 8l9 9c4 4 11 7 18 7s14 -3 18 -7l22 -22c10 -10 10 -25 0 -35l-10 -9c-5 -4 -8 -11 -8 -17c0 -13 11 -23 23 -23h15zM368 192v15 -c0 4 -3 9 -8 9h-15c-10 0 -20 4 -27 12s-12 17 -12 27c0 11 5 21 13 28l9 9c2 2 3 5 3 7s-1 4 -3 6l-22 22c-2 1 -4 2 -6 2s-4 0 -6 -2l-10 -9c-8 -8 -17 -13 -28 -13c-10 0 -20 4 -28 11s-12 18 -12 28v15c0 5 -4 9 -8 9h-30c-4 0 -9 -4 -9 -9v-15c0 -10 -4 -21 -12 -28 -s-17 -11 -27 -11c-11 0 -21 4 -28 12l-10 10v0v0c-1 1 -4 2 -6 2s-4 0 -6 -2l-23 -22c-2 -2 -2 -5 -2 -6s0 -5 2 -7l9 -9c8 -8 13 -17 13 -28c0 -10 -4 -19 -11 -27s-18 -12 -28 -12h-15c-5 0 -9 -5 -9 -9v-15v-15c0 -4 4 -9 9 -9h15c10 0 21 -4 28 -12s11 -17 11 -27 -c0 -11 -4 -21 -12 -29l-9 -8c-3 -3 -3 -10 0 -13l22 -22v0v0c1 -1 4 -2 6 -2s4 0 6 2l10 9c7 8 17 13 28 13c10 0 19 -4 27 -11s12 -18 12 -28v-15c0 -5 4 -9 9 -9h30c5 0 9 4 9 9v15c0 10 4 21 12 28s17 11 27 11c11 0 21 -5 29 -13l9 -9c2 -2 4 -2 6 -2s4 0 6 2l23 22 -c3 3 3 10 0 13l-10 9c-8 7 -12 17 -12 28c0 10 4 20 11 28s18 12 28 12h15c5 0 7 4 7 8v15z" /> - <glyph glyph-name="ion-ios7-gear" unicode="" horiz-adv-x="384" -d="M360 232c14 0 24 -11 24 -25v-15v-15c0 -14 -10 -25 -24 -25h-15c-12 0 -23 -10 -23 -23c0 -6 3 -13 8 -17l10 -9c10 -10 10 -25 0 -35l-23 -22c-4 -4 -10 -7 -17 -7s-14 3 -18 7l-9 9c-5 5 -11 8 -17 8c-13 0 -24 -11 -24 -23v-15c0 -14 -10 -25 -24 -25h-30 -c-14 0 -25 11 -25 25v15c0 12 -10 23 -23 23c-6 0 -13 -2 -17 -7l-10 -10c-4 -4 -10 -7 -17 -7s-14 3 -18 7l-22 22c-10 10 -10 25 0 35l9 9c5 4 8 11 8 17c0 13 -11 23 -23 23h-15c-14 0 -25 11 -25 25v15v15c0 14 11 25 25 25h15c12 0 23 10 23 23c0 6 -3 13 -8 17l-9 9 -c-10 10 -10 25 0 35l22 22c4 4 11 7 18 7s14 -3 18 -7l9 -10c4 -5 11 -7 17 -7c13 0 23 11 23 23v15c0 14 11 25 25 25h30c14 0 25 -11 25 -25v-15c0 -12 10 -23 23 -23c6 0 13 3 17 8l9 9c4 4 11 7 18 7s14 -3 18 -7l22 -22c10 -10 10 -25 0 -35l-10 -10 -c-5 -4 -8 -10 -8 -16c0 -13 11 -23 23 -23h15zM273 192v0c0 44 -36 80 -80 80s-80 -36 -80 -80v0v0c0 -44 36 -80 80 -80s80 36 80 80v0z" /> - <glyph glyph-name="ion-ios7-glasses-outline" unicode="" + <glyph glyph-name="ion-ios-flame-outline" unicode="" horiz-adv-x="256" +d="M96 416c87 -64 170 -179 159 -288c-13 -134 -104 -160 -127 -160s-127 40 -128 160c-1 146 122 143 96 288zM128 -24c0 0 40 36 40 80s-40 80 -40 80s-41 -36 -41 -80s41 -80 41 -80zM239 130c5 47 -10 99 -41 151c-22 36 -50 70 -83 99c0 -57 -24 -91 -49 -123 +c-26 -34 -50 -65 -50 -129c0 -25 5 -48 15 -68c8 -17 20 -32 35 -45c8 -7 16 -12 23 -16c-9 16 -18 35 -18 57c0 51 44 90 46 92l11 9l11 -9c2 -2 45 -41 45 -92c0 -23 -9 -44 -19 -60c7 4 13 8 20 14c14 12 25 27 34 44c11 21 17 47 20 76z" /> + <glyph glyph-name="ion-ios-flame" unicode="" horiz-adv-x="256" +d="M96 416c87 -64 170 -179 159 -288c-13 -134 -104 -160 -127 -160s-127 40 -128 160c-1 146 122 143 96 288zM128 -24c0 0 40 36 40 80s-40 80 -40 80s-41 -36 -41 -80s41 -80 41 -80z" /> + <glyph glyph-name="ion-ios-flask-outline" unicode="" horiz-adv-x="384" +d="M373 78c8 -16 11 -32 11 -46c-1 -36 -27 -64 -63 -64h-256c-36 0 -64 27 -65 64c0 14 4 30 12 46l116 195v127h-16v16h16h16v-16v-16h48v-16h-48v-32h32v-16h-32v-32h48v-16h-48v-3l-2 -4l-15 -25h49v-16h-58l-92 -154c-13 -25 -14 -43 -2 -63c9 -14 23 -23 41 -23h256 +c17 0 33 8 41 22c5 8 6 17 6 26c0 12 -2 25 -9 38l-116 195l-3 4v131v16h16h16v-16h-16v-127zM44 73l72 119h153l72 -119c7 -11 10 -24 10 -33c-1 -24 -16 -40 -46 -40h-226c-30 0 -46 12 -46 40c0 9 4 22 11 33zM260 176h-135l-67 -111v0v0c-5 -8 -9 -19 -9 -25 +c0 -13 5 -17 6 -18c4 -4 13 -6 24 -6h226c10 0 18 3 23 7c4 4 7 10 7 18c0 6 -3 16 -8 24v0v0z" /> + <glyph glyph-name="ion-ios-flask" unicode="" horiz-adv-x="384" +d="M327 65v0c5 -8 8 -18 8 -24c0 -8 -3 -14 -7 -18c-5 -4 -13 -7 -23 -7h-226c-11 0 -20 2 -24 6c-1 1 -6 5 -6 18c0 6 4 17 9 25v0v0l67 111h135l67 -111v0zM373 78c8 -16 11 -32 11 -46c-1 -36 -27 -64 -63 -64h-256c-36 0 -64 27 -65 64c0 14 4 30 12 46l116 195v127h-16 +v16h160v-16h-16v-127zM144 384v-16h48v16h-48zM144 336v-16h32v16h-32zM144 288v-16h48v16h-48zM127 240l-9 -16h58v16h-49zM351 40c0 9 -3 22 -10 33l-72 119h-154l-71 -119c-7 -11 -11 -24 -11 -33c0 -28 16 -40 46 -40h226c30 0 45 16 46 40z" /> + <glyph glyph-name="ion-ios-flower-outline" unicode="" +d="M363 164c-29 0 -65 7 -93 14c-1 -3 -2 -6 -4 -9c25 -15 56 -36 76 -56c40 -40 53 -68 41 -80c-3 -3 -7 -4 -12 -4c-15 0 -38 15 -68 45c-20 20 -41 51 -56 76c-3 -2 -7 -3 -10 -4c7 -28 15 -64 15 -93c0 -56 -12 -85 -28 -85s-28 29 -28 85c0 29 8 65 15 93 +c-3 1 -7 2 -10 4c-15 -25 -36 -56 -56 -76c-30 -30 -53 -45 -68 -45c-5 0 -9 1 -12 4c-12 12 1 40 41 80c20 20 51 41 76 56c-2 3 -3 6 -4 9c-28 -7 -64 -14 -93 -14c-56 0 -85 12 -85 28s29 28 85 28c29 0 65 -8 93 -15c1 3 2 7 4 10c-25 15 -56 35 -76 55 +c-40 40 -53 68 -41 80c3 3 7 4 12 4c15 0 38 -14 68 -44c20 -20 41 -51 56 -76c3 2 7 3 10 4c-7 28 -15 64 -15 93c0 56 12 85 28 85s28 -29 28 -85c0 -29 -8 -65 -15 -93c3 -1 7 -2 10 -4c15 25 36 56 56 76c30 30 53 44 68 44c5 0 9 -1 12 -4c12 -12 -1 -40 -41 -80 +c-20 -20 -51 -40 -76 -55c2 -3 3 -7 4 -10c28 7 64 15 93 15c56 0 85 -12 85 -28s-29 -28 -85 -28zM288 193v-3c30 -7 56 -10 75 -10c21 0 39 2 52 5c10 3 14 6 16 7c-2 1 -6 4 -16 7c-13 3 -31 5 -52 5c-19 0 -45 -4 -75 -11zM314 299c-14 -14 -30 -35 -46 -61l2 -2 +c26 16 47 32 61 46c15 15 26 28 33 40c5 9 7 14 7 16c-4 0 -22 -4 -57 -39zM178 236l2 2c-16 26 -32 47 -46 61c-35 35 -53 39 -57 39c0 -2 2 -7 7 -16c7 -12 18 -25 33 -40c14 -14 35 -30 61 -46zM85 180c19 0 45 3 75 10v3c-30 7 -56 11 -75 11c-21 0 -39 -2 -52 -5 +c-10 -3 -14 -6 -16 -7c2 -1 5 -4 15 -7c13 -3 32 -5 53 -5zM134 85c14 14 30 35 46 61l-2 2c-26 -16 -47 -32 -61 -46c-15 -15 -26 -29 -33 -41c-5 -9 -7 -14 -7 -16c4 0 22 5 57 40zM270 148l-2 -2c16 -26 32 -47 46 -61c35 -35 53 -40 57 -40c0 2 -2 7 -7 16 +c-7 12 -18 26 -33 41c-14 14 -35 30 -61 46zM217 383c-3 -13 -5 -31 -5 -52c0 -19 4 -45 11 -75h2c7 30 11 56 11 75c0 21 -2 39 -5 52c-3 10 -6 14 -7 16c-1 -2 -4 -6 -7 -16zM231 0c3 13 5 32 5 53c0 19 -4 45 -11 75h-2c-7 -30 -11 -56 -11 -75c0 -21 2 -40 5 -53 +c3 -10 6 -13 7 -15c1 2 4 5 7 15zM224 160c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM313 42c10 -34 7 -53 -5 -58c-2 -1 -3 -1 -5 -1c-11 0 -25 13 -37 35c5 35 -2 76 -2 76s24 -34 49 -52zM302 -1c1 4 2 14 -3 34c-5 4 -10 9 -15 14 +c0 -9 0 -17 -1 -25c10 -16 16 -22 19 -23zM182 365c-6 -35 1 -75 1 -75s-27 35 -48 51c-10 35 -7 54 5 59c2 1 3 1 5 1c11 0 24 -12 37 -36zM164 337c0 9 0 17 1 25c-10 16 -16 21 -19 22c-1 -4 -2 -14 3 -34c5 -4 10 -8 15 -13zM50 149c35 -4 76 2 76 2s-34 -24 -51 -48 +c-12 -4 -26 -6 -35 -6c-13 0 -21 4 -24 11c-5 11 7 25 34 41zM66 117c4 5 8 10 13 15c-9 0 -17 0 -25 1c-16 -10 -21 -16 -22 -19c1 0 4 -1 8 -1c7 0 16 1 26 4zM432 276c5 -11 -7 -26 -34 -42c-35 5 -76 -2 -76 -2s33 25 51 49c13 4 26 5 35 5c13 0 21 -3 24 -10zM394 250 +c16 10 21 16 22 19c-1 0 -4 1 -8 1c-7 0 -16 -1 -26 -4c-4 -5 -8 -9 -13 -14c9 0 17 -1 25 -2zM131 39c31 24 53 55 53 55s-7 -39 -3 -71c-15 -26 -28 -39 -39 -39c-2 0 -4 0 -6 1c-11 5 -13 24 -5 54zM143 1c4 2 12 8 22 26c0 6 -1 13 -1 20c-6 -6 -13 -12 -19 -17 +c-4 -18 -3 -26 -2 -29zM312 398c11 -5 13 -22 5 -54c-29 -21 -53 -55 -53 -55s8 48 3 71c13 25 28 39 39 39c2 0 4 0 6 -1zM303 353c5 18 3 27 2 30c-4 -2 -12 -8 -22 -26c0 -6 1 -14 1 -21c6 6 13 12 19 17zM71 285c18 -24 55 -53 55 -53s-40 7 -70 3c-28 15 -43 32 -38 44 +c3 7 10 11 22 11c8 0 21 -1 31 -5zM33 273c2 -4 8 -12 26 -22c6 0 13 1 20 1c-6 6 -12 12 -17 18c-8 2 -16 4 -22 4c-4 0 -6 -1 -7 -1zM392 149c30 -17 43 -33 38 -45c-3 -7 -10 -10 -22 -10c-8 0 -19 1 -31 5c-20 27 -55 52 -55 52s45 -8 70 -2zM408 110c4 0 6 1 7 1 +c-2 4 -8 12 -26 22c-6 0 -13 -1 -20 -1c6 -6 12 -13 17 -19c8 -2 16 -3 22 -3z" /> + <glyph glyph-name="ion-ios-flower" unicode="" +d="M363 220c56 0 85 -12 85 -28s-29 -28 -85 -28c-29 0 -65 7 -93 14c-1 -3 -2 -6 -4 -9c25 -15 56 -36 76 -56c40 -40 53 -68 41 -80s-40 1 -80 41c-20 20 -41 51 -56 76c-3 -2 -7 -3 -10 -4c7 -28 15 -64 15 -93c0 -56 -12 -85 -28 -85s-28 29 -28 85c0 29 8 65 15 93 +c-3 1 -7 2 -10 4c-15 -25 -36 -56 -56 -76c-40 -40 -68 -53 -80 -41s1 40 41 80c20 20 51 41 76 56c-2 3 -3 6 -4 9c-28 -7 -64 -14 -93 -14c-56 0 -85 12 -85 28s29 28 85 28c29 0 65 -8 93 -15c1 3 2 7 4 10c-25 15 -56 35 -76 55c-40 40 -53 68 -41 80s40 0 80 -40 +c20 -20 41 -51 56 -76c3 2 6 3 9 4c-7 28 -14 64 -14 93c0 56 12 85 28 85s28 -29 28 -85c0 -29 -7 -65 -14 -93c3 -1 6 -2 9 -4c15 25 36 56 56 76c40 40 68 52 80 40s-1 -40 -41 -80c-20 -20 -51 -40 -76 -55c2 -3 3 -7 4 -10c28 7 64 15 93 15zM264 94c0 0 24 -34 49 -52 +c10 -34 7 -53 -5 -58c-2 -1 -3 -1 -5 -1c-11 0 -25 13 -37 35c5 35 -2 76 -2 76zM183 290c0 0 -27 35 -48 51c-10 35 -7 54 5 59c2 1 3 1 5 1c11 0 24 -12 37 -36c-6 -35 1 -75 1 -75zM126 151c0 0 -34 -24 -51 -48c-12 -4 -26 -6 -35 -6c-13 0 -21 4 -24 11 +c-5 11 7 25 34 41c35 -4 76 2 76 2zM322 232c0 0 33 25 51 49c13 4 26 5 35 5c13 0 21 -3 24 -10c5 -11 -7 -26 -34 -42c-35 5 -76 -2 -76 -2zM131 39c31 24 53 55 53 55s-7 -39 -3 -71c-15 -26 -28 -39 -39 -39c-2 0 -4 0 -6 1c-11 5 -13 24 -5 54zM317 344 +c-29 -21 -53 -55 -53 -55s8 48 3 71c13 25 28 39 39 39c2 0 4 0 6 -1c11 -5 13 -22 5 -54zM56 235c-28 15 -43 32 -38 44c3 7 10 11 22 11c8 0 21 -1 31 -5c18 -24 55 -53 55 -53s-40 7 -70 3zM392 149c30 -17 43 -33 38 -45c-3 -7 -10 -10 -22 -10c-8 0 -19 1 -31 5 +c-20 27 -55 52 -55 52s45 -8 70 -2z" /> + <glyph glyph-name="ion-ios-folder-outline" unicode="" +d="M425 352c13 0 23 -10 23 -23v-304c0 -14 -10 -25 -23 -25h-400c-13 0 -25 12 -25 25v336c0 13 11 23 25 23h112c8 0 12 -2 17 -7v0l23 -23c2 -2 3 -2 6 -2h242zM25 368c-4 0 -9 -3 -9 -7v-74c3 1 5 1 8 1h400c3 0 5 0 8 -1v42c0 4 -3 7 -7 7h-242c-7 0 -12 2 -17 7 +l-23 23c-2 2 -3 2 -6 2h-112zM432 25v239c0 4 -4 8 -8 8h-400c-4 0 -8 -4 -8 -8v-239c0 -4 5 -9 9 -9h400c4 0 7 5 7 9z" /> + <glyph glyph-name="ion-ios-folder" unicode="" +d="M440 272c4 0 8 -4 8 -8v-239c0 -14 -10 -25 -23 -25h-400c-13 0 -25 12 -25 25v239c0 4 4 8 8 8h432zM425 352c13 0 23 -10 23 -23v-42c-3 1 -5 1 -8 1h-432c-3 0 -5 0 -8 -1v74c0 13 11 23 25 23h112c8 0 12 -2 17 -7v0l23 -23c2 -2 3 -2 6 -2h242z" /> + <glyph glyph-name="ion-ios-football-outline" unicode="" horiz-adv-x="416" +d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM249 6c3 1 5 1 8 2l24 64l-20 39v1h-106l-20 -39l25 -65c2 -1 5 -1 7 -2c12 -3 25 -5 38 -5c14 0 30 2 44 5zM41 284c-15 -27 -23 -57 -24 -89l43 37v0zM142 371 +c-36 -14 -68 -38 -90 -69l22 -64l5 -2l49 -23l71 60v58zM277 201l-70 58l-69 -58v-1l18 -72h104l18 72zM399 195c-1 32 -9 63 -24 90l-19 -53v0zM364 302c-22 31 -54 56 -90 69l-58 -40v-58l71 -60l54 24zM18 175c3 -34 15 -66 33 -92l70 -1l21 39l-20 77l-1 1l-49 22z +M295 82l70 1c18 26 30 58 33 92l-54 46l-50 -23l-20 -77zM207 345l47 32c-15 4 -30 6 -46 6s-32 -2 -47 -6zM118 66l-54 1c20 -23 46 -42 75 -53l-20 50zM277 14c29 11 55 30 75 53l-56 -1l-2 -3z" /> + <glyph glyph-name="ion-ios-football" unicode="" horiz-adv-x="416" +d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM249 6c3 1 5 1 8 2l24 64l-20 39v1h-106l-20 -39l25 -65c2 -1 5 -1 7 -2c12 -3 25 -5 38 -5c14 0 30 2 44 5zM142 371c-36 -14 -68 -38 -90 -69l22 -64l5 -2l49 -23l71 60v58z +M364 302c-22 31 -54 56 -90 69l-58 -40v-58l71 -60l54 24zM18 175c3 -34 15 -66 33 -92l70 -1l21 39l-20 77l-1 1l-49 22zM295 82l70 1c18 26 30 58 33 92l-54 46l-50 -23l-20 -77z" /> + <glyph glyph-name="ion-ios-game-controller-a-outline" unicode="" +d="M163 208c3 0 5 -2 5 -5v-22c0 -3 -2 -5 -5 -5h-35v-35c0 -3 -3 -5 -6 -5h-21c-3 0 -5 2 -5 5v35h-35c-3 0 -5 3 -5 6v21c0 3 2 5 5 5h35v35c0 3 2 5 5 5h22c3 0 5 -2 5 -5v-35h35zM330 169c11 0 20 -8 20 -19s-9 -19 -20 -19s-19 8 -19 19s8 19 19 19zM288 211 +c11 0 19 -8 19 -19s-8 -19 -19 -19s-20 8 -20 19s9 19 20 19zM373 211c11 0 19 -8 19 -19s-8 -19 -19 -19s-20 8 -20 19s9 19 20 19zM330 253c11 0 20 -8 20 -19s-9 -20 -20 -20s-19 9 -19 20s8 19 19 19zM337 286h-226c-26 0 -49 -9 -67 -26s-28 -41 -28 -67s10 -51 28 -68 +s41 -27 67 -27h226c26 0 49 10 67 27s28 42 28 68s-10 50 -28 67s-41 26 -67 26zM337 302v0c61 0 111 -45 111 -109s-50 -111 -111 -111h-226c-61 0 -111 47 -111 111s50 109 111 109h226z" /> + <glyph glyph-name="ion-ios-game-controller-a" unicode="" +d="M337 302c61 0 111 -45 111 -109s-50 -111 -111 -111h-226c-61 0 -111 47 -111 111s50 109 111 109h226zM168 181v0v22c0 3 -2 5 -5 5h-35v35c0 3 -2 5 -5 5h-22c-3 0 -5 -2 -5 -5v-35h-35c-3 0 -5 -2 -5 -5v-21c0 -3 2 -6 5 -6h35v-35c0 -3 2 -5 5 -5h21c3 0 6 2 6 5v35 +h35c3 0 5 2 5 5zM288 173c11 0 19 8 19 19s-8 19 -19 19s-20 -8 -20 -19s9 -19 20 -19zM330 131c11 0 20 8 20 19s-9 19 -20 19s-19 -8 -19 -19s8 -19 19 -19zM330 214c11 0 20 9 20 20s-9 19 -20 19s-19 -8 -19 -19s8 -20 19 -20zM373 173c11 0 19 8 19 19s-8 19 -19 19 +s-20 -8 -20 -19s9 -19 20 -19z" /> + <glyph glyph-name="ion-ios-game-controller-b-outline" unicode="" +d="M276 244c11 0 20 -9 20 -20s-9 -20 -20 -20s-20 9 -20 20s9 20 20 20zM320 200c11 0 20 -9 20 -20s-9 -20 -20 -20s-20 9 -20 20s9 20 20 20zM103 264c22 0 39 -18 39 -40s-17 -40 -39 -40s-39 18 -39 40s17 40 39 40zM103 205c11 0 19 8 19 19s-8 19 -19 19 +s-19 -8 -19 -19s8 -19 19 -19zM320 288c11 0 20 -9 20 -20s-9 -20 -20 -20s-20 9 -20 20s9 20 20 20zM364 244c11 0 20 -9 20 -20s-9 -20 -20 -20s-20 9 -20 20s9 20 20 20zM434 199c21 -88 18 -152 -7 -164c-4 -2 -9 -3 -13 -3c-22 0 -45 24 -68 52c-26 32 -32 33 -110 33 +h-24c-78 0 -84 -1 -110 -33c-23 -28 -46 -52 -68 -52c-4 0 -9 1 -13 3c-25 12 -28 76 -7 164s43 136 88 149c10 3 18 4 26 4c28 0 47 -15 96 -15s68 15 96 15c8 0 16 -1 26 -4c45 -13 67 -61 88 -149zM420 49c10 5 23 48 -1 146c-21 90 -43 128 -78 138c-8 2 -14 3 -21 3 +c-10 0 -19 -2 -30 -5c-16 -4 -36 -10 -66 -10s-50 6 -66 10c-11 3 -20 5 -30 5c-7 0 -13 -1 -21 -3c-35 -10 -57 -48 -78 -138c-24 -98 -11 -141 -1 -146c2 -1 4 -1 6 -1c6 0 14 4 23 12s19 18 32 34s24 28 44 34c17 5 38 5 79 5h24c41 0 62 0 79 -5c20 -6 31 -18 44 -34 +s23 -26 32 -34s17 -12 23 -12c2 0 4 0 6 1z" /> + <glyph glyph-name="ion-ios-game-controller-b" unicode="" +d="M103 243c11 0 19 -8 19 -19s-8 -19 -19 -19s-19 8 -19 19s8 19 19 19zM434 199c21 -88 18 -152 -7 -164c-4 -2 -9 -3 -13 -3c-22 0 -45 24 -68 52c-26 32 -32 33 -110 33h-24c-78 0 -84 -1 -110 -33c-23 -28 -46 -52 -68 -52c-4 0 -9 1 -13 3c-25 12 -28 76 -7 164 +s43 136 88 149c10 3 18 4 26 4c28 0 47 -15 96 -15s68 15 96 15c8 0 16 -1 26 -4c45 -13 67 -61 88 -149zM103 184c22 0 39 18 39 40s-17 40 -39 40s-39 -18 -39 -40s17 -40 39 -40zM276 204c11 0 20 9 20 20s-9 20 -20 20s-20 -9 -20 -20s9 -20 20 -20zM320 160 +c11 0 20 9 20 20s-9 20 -20 20s-20 -9 -20 -20s9 -20 20 -20zM320 248c11 0 20 9 20 20s-9 20 -20 20s-20 -9 -20 -20s9 -20 20 -20zM364 204c11 0 20 9 20 20s-9 20 -20 20s-20 -9 -20 -20s9 -20 20 -20z" /> + <glyph glyph-name="ion-ios-gear-outline" unicode="" horiz-adv-x="384" +d="M193 288c26 0 50 -10 68 -28s28 -42 28 -68s-10 -50 -28 -68s-42 -28 -68 -28s-50 10 -68 28s-28 42 -28 68s10 50 28 68s42 28 68 28zM193 112c44 0 80 36 80 80s-36 80 -80 80s-80 -36 -80 -80s36 -80 80 -80zM138 365c-10 -3 -20 -7 -30 -12c2 -8 1 -16 0 -24 +c-2 -13 -8 -25 -18 -35c-12 -12 -29 -19 -46 -19c-4 0 -9 0 -13 1c-5 -10 -9 -20 -12 -30c7 -4 12 -10 17 -17c8 -11 12 -24 12 -37s-4 -26 -12 -37c-5 -7 -10 -13 -17 -17c3 -10 7 -20 12 -30c4 1 9 1 13 1c17 0 34 -7 46 -19c10 -10 16 -22 18 -35c1 -8 2 -16 0 -24 +c10 -5 20 -9 30 -12c4 7 10 12 17 17c11 8 24 12 37 12s26 -4 37 -12c7 -5 13 -10 17 -17c10 3 20 7 30 12c-2 8 -1 16 0 24c2 13 8 25 18 35c12 12 29 19 46 19c4 0 9 0 13 -1c5 10 9 20 12 30c-7 4 -12 10 -17 17c-8 11 -12 24 -12 37s4 26 12 37c5 7 10 13 17 17 +c-3 10 -7 20 -12 30c-4 -1 -9 -1 -13 -1c-17 0 -34 7 -46 19c-10 10 -16 22 -18 35c-1 8 -2 16 0 24c-10 5 -20 9 -30 12c-4 -7 -10 -12 -17 -17c-11 -8 -24 -12 -37 -12s-26 4 -37 12c-7 5 -13 10 -17 17zM238 384v0c20 -5 40 -13 57 -24c-8 -18 -5 -40 10 -55 +c10 -10 22 -14 35 -14c7 0 14 1 20 4c11 -17 19 -37 24 -57c-19 -7 -32 -25 -32 -46s14 -39 32 -46c-5 -20 -13 -40 -24 -57c-6 3 -13 4 -20 4c-13 0 -25 -4 -35 -14c-15 -15 -18 -37 -10 -55c-17 -11 -37 -19 -57 -24c-7 18 -25 32 -46 32s-39 -14 -46 -32 +c-20 5 -40 13 -57 24c8 18 5 40 -10 55c-10 10 -22 14 -35 14c-7 0 -14 -1 -20 -4c-11 17 -19 37 -24 57c18 7 32 25 32 46s-13 39 -32 46c5 20 13 40 24 57c6 -3 13 -4 20 -4c13 0 25 4 35 14c15 15 18 37 10 55c17 11 37 19 57 24c7 -19 25 -32 46 -32s39 13 46 32z" /> + <glyph glyph-name="ion-ios-gear" unicode="" horiz-adv-x="384" +d="M352 192c0 -21 14 -39 32 -46c-5 -20 -13 -40 -24 -57c-6 3 -13 4 -20 4c-13 0 -25 -4 -35 -14c-15 -15 -18 -37 -10 -55c-17 -11 -37 -19 -57 -24c-7 18 -25 32 -46 32s-39 -14 -46 -32c-20 5 -40 13 -57 24c8 18 5 40 -10 55c-10 10 -22 14 -35 14c-7 0 -14 -1 -20 -4 +c-11 17 -19 37 -24 57c18 7 32 25 32 46s-13 39 -32 46c5 20 13 40 24 57c6 -3 13 -4 20 -4c13 0 25 4 35 14c15 15 18 37 10 55c17 11 37 19 57 24c7 -19 25 -32 46 -32s39 13 46 32c20 -5 40 -13 57 -24c-8 -18 -5 -40 10 -55c10 -10 22 -14 35 -14c7 0 14 1 20 4 +c11 -17 19 -37 24 -57c-19 -7 -32 -25 -32 -46zM193 112c44 0 80 36 80 80s-36 80 -80 80s-80 -36 -80 -80s36 -80 80 -80z" /> + <glyph glyph-name="ion-ios-glasses-outline" unicode="" d="M433 201v0h15v-18h-15c-2 -22 -13 -43 -29 -58c-17 -16 -39 -25 -62 -25c-51 0 -92 41 -92 92v0v0c0 10 -12 22 -26 22s-26 -12 -26 -22v0v0c0 -51 -41 -92 -92 -92c-23 0 -45 9 -62 25c-16 15 -27 36 -29 58h-15v18h15c2 22 13 43 29 59c17 16 39 24 62 24 c42 0 78 -27 89 -67c7 7 18 12 29 12s22 -5 29 -12c11 40 47 67 89 67c23 0 45 -9 62 -25c16 -15 27 -36 29 -58zM342 115c42 0 77 35 77 77s-35 77 -77 77s-77 -35 -77 -77s35 -77 77 -77zM106 115c42 0 77 35 77 77s-35 77 -77 77s-77 -35 -77 -77s35 -77 77 -77z" /> - <glyph glyph-name="ion-ios7-glasses" unicode="" + <glyph glyph-name="ion-ios-glasses" unicode="" d="M433 201v0h15v-18h-15c-2 -22 -13 -43 -29 -58c-17 -16 -39 -25 -62 -25c-51 0 -92 41 -92 92v0v0c0 10 -12 22 -26 22s-26 -12 -26 -22v0v0c0 -51 -41 -92 -92 -92c-23 0 -45 9 -62 25c-16 15 -27 36 -29 58h-15v18h15c2 22 13 43 29 59c17 16 39 24 62 24 c42 0 78 -27 89 -67c7 7 18 12 29 12s22 -5 29 -12c11 40 47 67 89 67c23 0 45 -9 62 -25c16 -15 27 -36 29 -58z" /> - <glyph glyph-name="ion-ios7-heart-outline" unicode="" horiz-adv-x="384" -d="M277 350c-38 0 -71 -24 -85 -57c-14 33 -47 57 -85 57c-51 0 -92 -42 -92 -93c0 -25 10 -47 26 -64l151 -152l148 150c17 17 29 40 29 66c0 51 -41 93 -92 93zM277 365v0c59 0 107 -49 107 -108c0 -30 -12 -57 -33 -77l-148 -150l-11 -11l-11 11l-151 153 -c-19 20 -30 46 -30 74c0 59 48 108 107 108c34 0 65 -16 85 -42c20 26 51 42 85 42z" /> - <glyph glyph-name="ion-ios7-heart" unicode="" horiz-adv-x="384" -d="M277 365v0c59 0 107 -49 107 -108c0 -30 -12 -57 -33 -77l-148 -150l-11 -11l-11 11l-151 153c-19 20 -30 46 -30 74c0 59 48 108 107 108c34 0 65 -16 85 -42c20 26 51 42 85 42z" /> - <glyph glyph-name="ion-ios7-help-empty" unicode="" horiz-adv-x="128" + <glyph glyph-name="ion-ios-grid-view-outline" unicode="" horiz-adv-x="384" +d="M384 256h-112v-128h112v-16h-112v-112h-16v112h-128v-112h-16v112h-112v16h112v128h-112v16h112v112h16v-112h128v112h16v-112h112v-16zM256 128v128h-128v-128h128z" /> + <glyph glyph-name="ion-ios-grid-view" unicode="" horiz-adv-x="384" +d="M128 128v128h128v-128h-128zM0 384h384v-384h-384v384zM352 256v16h-80v80h-16v-80h-128v80h-16v-80h-80v-16h80v-128h-80v-16h80v-80h16v80h128v-80h16v80h80v16h-80v128h80z" /> + <glyph glyph-name="ion-ios-heart-outline" unicode="" +d="M327 368c69 0 121 -43 121 -116c0 -31 -13 -71 -41 -105s-45 -52 -100 -88s-83 -43 -83 -43s-28 7 -83 43s-72 54 -100 88s-41 74 -41 105c0 73 52 116 121 116c39 0 82 -18 103 -53c21 35 64 53 103 53zM395 157c12 14 22 31 28 49c6 16 9 31 9 46c0 30 -10 56 -29 74 +c-9 8 -20 15 -33 19c-13 5 -28 7 -43 7c-38 0 -73 -18 -89 -45l-14 -23l-14 23c-16 27 -51 45 -89 45c-15 0 -30 -2 -43 -7c-13 -4 -24 -11 -33 -19c-19 -18 -29 -44 -29 -74c0 -15 3 -30 9 -46c6 -18 16 -35 28 -49c27 -32 42 -49 97 -85c40 -27 65 -36 74 -39 +c9 3 34 12 74 39c55 36 70 53 97 85z" /> + <glyph glyph-name="ion-ios-heart" unicode="" +d="M327 368c69 0 121 -43 121 -116c0 -31 -13 -71 -41 -105s-45 -52 -100 -88s-83 -43 -83 -43s-28 7 -83 43s-72 54 -100 88s-41 74 -41 105c0 73 52 116 121 116c39 0 82 -18 103 -53c21 35 64 53 103 53z" /> + <glyph glyph-name="ion-ios-help-empty" unicode="" horiz-adv-x="128" d="M68 82c-9 0 -17 8 -17 17s8 17 17 17s17 -8 17 -17s-8 -17 -17 -17zM102 197c-23 -22 -22 -27 -23 -53h-19c1 28 7 43 30 64c11 10 19 24 19 39c0 24 -19 39 -42 39c-32 0 -49 -16 -48 -46h-19c0 42 25 62 68 62c33 0 60 -20 60 -54c0 -22 -11 -37 -26 -51z" /> - <glyph glyph-name="ion-ios7-help-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-help-outline" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM208 1c105 0 191 86 191 191s-86 191 -191 191s-191 -86 -191 -191s86 -191 191 -191zM212 302c33 0 60 -21 60 -55c0 -22 -11 -36 -26 -50c-23 -23 -22 -27 -23 -53h-19 c1 28 7 43 30 64c11 10 19 23 19 38c0 24 -19 40 -42 40c-32 0 -49 -16 -48 -46h-19c0 42 25 62 68 62zM212 116c9 0 17 -8 17 -17s-8 -17 -17 -17s-17 8 -17 17s8 17 17 17z" /> - <glyph glyph-name="ion-ios7-help" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-help" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM212 82c9 0 17 8 17 17s-8 17 -17 17s-17 -8 -17 -17s8 -17 17 -17zM246 197c15 14 26 29 26 51c0 34 -27 54 -60 54c-43 0 -68 -20 -68 -62h19c-1 30 16 46 48 46 c23 0 42 -15 42 -39c0 -15 -8 -29 -19 -39c-23 -21 -29 -36 -30 -64h19c1 26 0 31 23 53z" /> - <glyph glyph-name="ion-ios7-home-outline" unicode="" horiz-adv-x="384" -d="M192 336l160 -128v-208h-112v128h-96v-128h-112v208zM336 16v184l-144 116l-144 -116v-184h80v128h128v-128h80zM192 384l192 -154v-20l-192 154l-192 -154v20l32 26v96h64v-45zM80 294v42h-32v-67z" /> - <glyph glyph-name="ion-ios7-home" unicode="" horiz-adv-x="384" -d="M192 336l160 -128v-208h-112v128h-96v-128h-112v208zM192 384l192 -154v-20l-192 154l-192 -154v20l32 26v96h64v-45z" /> - <glyph glyph-name="ion-ios7-infinite-outline" unicode="" horiz-adv-x="384" -d="M359 249c33 -31 33 -82 0 -113c-16 -15 -36 -24 -59 -24c-22 0 -44 9 -60 24l-108 102c-13 12 -30 18 -48 18s-35 -6 -48 -18c-26 -25 -26 -66 0 -91c13 -12 30 -19 48 -19s35 7 48 19l36 34l12 -11l-36 -34c-16 -15 -37 -24 -60 -24s-43 9 -59 24c-33 31 -33 82 0 113 -c16 15 36 23 59 23c22 0 44 -8 60 -23l108 -102c13 -12 30 -19 48 -19s34 7 47 19c26 25 26 66 0 91c-13 12 -29 18 -47 18s-35 -6 -48 -18l-37 -35l-11 11l36 35c16 15 37 23 60 23s43 -8 59 -23z" /> - <glyph glyph-name="ion-ios7-infinite" unicode="" horiz-adv-x="384" -d="M358 249c17 -15 26 -36 26 -57c0 -22 -9 -42 -26 -57s-39 -23 -63 -23s-45 8 -62 23l-103 93c-11 10 -26 15 -41 15s-30 -5 -41 -15s-16 -22 -16 -36s5 -26 16 -36s26 -15 41 -15s30 5 41 15l30 28l23 -20l-32 -29c-17 -15 -38 -23 -62 -23s-46 8 -63 23s-26 35 -26 57 -s9 42 26 57s39 23 63 23s45 -8 62 -23l104 -93c11 -10 25 -15 40 -15s30 5 41 15s17 22 17 36s-6 26 -17 36s-26 15 -41 15s-29 -5 -40 -15l-31 -28l-23 20l32 29c17 15 38 23 62 23s46 -8 63 -23z" /> - <glyph glyph-name="ion-ios7-information-empty" unicode="" horiz-adv-x="64" + <glyph glyph-name="ion-ios-home-outline" unicode="" horiz-adv-x="384" +d="M192 336l160 -128v-208h-112v128h-96v-128h-112v208zM336 16v184l-144 116l-144 -116v-184h80v128h128v-128h80zM192 384l192 -153l-12 -12l-180 145l-180 -145l-12 12l32 25v96h64v-45zM80 294v42h-32v-67z" /> + <glyph glyph-name="ion-ios-home" unicode="" horiz-adv-x="384" +d="M192 336l160 -128v-208h-112v128h-96v-128h-112v208zM192 384l192 -153l-12 -12l-180 145l-180 -145l-12 12l32 25v96h64v-45z" /> + <glyph glyph-name="ion-ios-infinite-outline" unicode="" +d="M419 260c19 -19 29 -43 29 -68s-10 -49 -29 -68c-19 -18 -44 -28 -70 -28s-50 10 -69 28l-126 123c-15 15 -35 22 -56 22s-40 -7 -55 -22c-31 -30 -31 -80 0 -110c15 -15 34 -22 55 -22s41 7 56 22l43 42l13 -14l-42 -41c-19 -18 -44 -28 -70 -28s-50 10 -69 28 +c-19 19 -29 43 -29 68s10 49 29 68c19 18 43 28 69 28s51 -10 70 -28l126 -123c15 -15 34 -22 55 -22s41 7 56 22c31 30 31 80 0 110c-15 15 -35 22 -56 22s-40 -7 -55 -22l-43 -42l-13 14l42 41c19 18 44 28 70 28s50 -10 69 -28z" /> + <glyph glyph-name="ion-ios-infinite" unicode="" horiz-adv-x="464" +d="M433 266c20 -20 31 -46 31 -74s-11 -54 -31 -74s-48 -30 -76 -30s-55 10 -75 30l-125 123c-13 13 -32 20 -51 20s-37 -7 -50 -20s-21 -31 -21 -49c0 -19 8 -36 21 -49s31 -20 50 -20s38 7 51 20l39 38l25 -25l-39 -38c-20 -20 -48 -30 -76 -30s-55 10 -75 30 +s-31 46 -31 74s11 54 31 74s47 30 75 30s56 -10 76 -30l125 -123c13 -13 31 -20 50 -20s38 7 51 20s20 31 20 49c0 19 -7 36 -20 49s-32 20 -51 20s-37 -7 -50 -20l-39 -38l-25 25l39 38c20 20 48 30 76 30s55 -10 75 -30z" /> + <glyph glyph-name="ion-ios-information-empty" unicode="" horiz-adv-x="64" d="M8 276c0 13 7 20 20 20s20 -7 20 -20s-7 -20 -20 -20s-20 7 -20 20zM48 104h16v-8h-64v8h16v120h-16v8h48v-128z" /> - <glyph glyph-name="ion-ios7-information-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-information-outline" unicode="" horiz-adv-x="416" d="M184 276c0 13 7 20 20 20s20 -7 20 -20s-7 -20 -20 -20s-20 7 -20 20zM224 104h16v-8h-64v8h16v120h-16v8h48v-128zM208 400c57 0 106 -20 147 -61s61 -90 61 -147s-20 -106 -61 -147s-90 -61 -147 -61s-106 20 -147 61s-61 90 -61 147s20 106 61 147s90 61 147 61z M208 1c53 0 98 19 135 56s56 82 56 135s-19 98 -56 135s-82 56 -135 56s-98 -19 -135 -56s-56 -82 -56 -135s19 -98 56 -135s82 -56 135 -56z" /> - <glyph glyph-name="ion-ios7-information" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-information" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM204 296c-11 0 -20 -9 -20 -20s9 -20 20 -20s20 9 20 20s-9 20 -20 20zM240 96v8h-16v128h-48v-8h16v-120h-16v-8h64z" /> - <glyph glyph-name="ion-ios7-ionic-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-ionic-outline" unicode="" horiz-adv-x="416" d="M378 313c24 -34 38 -76 38 -121c0 -115 -92 -208 -207 -208s-209 93 -209 208s94 208 209 208c45 0 86 -14 120 -38c6 5 13 8 21 8c19 0 35 -16 35 -35c0 -8 -2 -16 -7 -22zM350 357c-12 0 -22 -10 -22 -22s10 -22 22 -22s22 10 22 22s-10 22 -22 22zM344 56 c18 18 31 39 41 62c10 24 15 48 15 74s-5 51 -15 75c-5 13 -12 25 -20 36c-5 -2 -10 -3 -15 -3c-19 0 -35 16 -35 35c0 5 2 11 4 15c-11 8 -23 15 -36 20c-24 10 -49 14 -75 14s-51 -4 -75 -14c-23 -10 -43 -24 -61 -42s-31 -38 -41 -61c-10 -24 -15 -49 -15 -75 s5 -50 15 -74c10 -23 23 -44 41 -62s38 -31 61 -41c24 -10 49 -15 75 -15s51 5 75 15c23 10 43 23 61 41zM208 288c53 0 96 -43 96 -96s-43 -96 -96 -96s-96 43 -96 96s43 96 96 96zM208 112c44 0 80 36 80 80s-36 80 -80 80s-79 -36 -79 -80s35 -80 79 -80z" /> - <glyph glyph-name="ion-ios7-keypad-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-keypad-outline" unicode="" horiz-adv-x="384" d="M331 107c30 0 53 -24 53 -54s-23 -53 -53 -53s-54 23 -54 53s24 54 54 54zM331 16c21 0 37 16 37 37s-16 38 -37 38s-38 -17 -38 -38s17 -37 38 -37zM192 107c30 0 53 -24 53 -54s-23 -53 -53 -53s-53 23 -53 53s23 54 53 54zM192 16c21 0 37 16 37 37s-16 38 -37 38 s-37 -17 -37 -38s16 -37 37 -37zM53 107c30 0 54 -24 54 -54s-24 -53 -54 -53s-53 23 -53 53s23 54 53 54zM53 16c21 0 38 16 38 37s-17 38 -38 38s-37 -17 -37 -38s16 -37 37 -37zM331 245c30 0 53 -23 53 -53s-23 -53 -53 -53s-54 23 -54 53s24 53 54 53zM331 155 c21 0 37 16 37 37s-16 37 -37 37s-38 -16 -38 -37s17 -37 38 -37zM192 245c30 0 53 -23 53 -53s-23 -53 -53 -53s-53 23 -53 53s23 53 53 53zM192 155c21 0 37 16 37 37s-16 37 -37 37s-37 -16 -37 -37s16 -37 37 -37zM53 245c30 0 54 -23 54 -53s-24 -53 -54 -53 s-53 23 -53 53s23 53 53 53zM53 155c21 0 38 16 38 37s-17 37 -38 37s-37 -16 -37 -37s16 -37 37 -37zM331 277c-30 0 -54 24 -54 54s24 53 54 53s53 -23 53 -53s-23 -54 -53 -54zM331 368c-21 0 -38 -16 -38 -37s17 -38 38 -38s37 17 37 38s-16 37 -37 37zM192 384 c30 0 53 -23 53 -53s-23 -54 -53 -54s-53 24 -53 54s23 53 53 53zM192 293c21 0 37 17 37 38s-16 37 -37 37s-37 -16 -37 -37s16 -38 37 -38zM53 384c30 0 54 -23 54 -53s-24 -54 -54 -54s-53 24 -53 54s23 53 53 53zM53 293c21 0 38 17 38 38s-17 37 -38 37 s-37 -16 -37 -37s16 -38 37 -38z" /> - <glyph glyph-name="ion-ios7-keypad" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-keypad" unicode="" horiz-adv-x="384" d="M331 107c30 0 53 -24 53 -54s-23 -53 -53 -53s-54 23 -54 53s24 54 54 54zM192 107c30 0 53 -24 53 -54s-23 -53 -53 -53s-53 23 -53 53s23 54 53 54zM53 107c30 0 54 -24 54 -54s-24 -53 -54 -53s-53 23 -53 53s23 54 53 54zM331 245c30 0 53 -23 53 -53 s-23 -53 -53 -53s-54 23 -54 53s24 53 54 53zM192 245c30 0 53 -23 53 -53s-23 -53 -53 -53s-53 23 -53 53s23 53 53 53zM53 245c30 0 54 -23 54 -53s-24 -53 -54 -53s-53 23 -53 53s23 53 53 53zM331 277c-30 0 -54 24 -54 54s24 53 54 53s53 -23 53 -53s-23 -54 -53 -54z M192 384c30 0 53 -23 53 -53s-23 -54 -53 -54s-53 24 -53 54s23 53 53 53zM53 384c30 0 54 -23 54 -53s-24 -54 -54 -54s-53 24 -53 54s23 53 53 53z" /> - <glyph glyph-name="ion-ios7-lightbulb-outline" unicode="" horiz-adv-x="288" + <glyph glyph-name="ion-ios-lightbulb-outline" unicode="" horiz-adv-x="288" d="M288 275c0 -31 -13 -59 -30 -83v0c-11 -15 -22 -28 -32 -45c-22 -38 -18 -73 -18 -82v-1h-128v1c0 7 3 44 -19 82c-10 17 -20 30 -31 45v0c-17 24 -30 52 -30 83c0 78 66 141 144 141s144 -63 144 -141zM239 194l6 8c16 22 27 47 27 73c0 33 -16 65 -40 89s-55 36 -88 36 s-64 -12 -88 -36s-40 -56 -40 -89c0 -26 11 -51 27 -73l19 -26v0c5 -6 9 -13 13 -21c17 -29 21 -58 21 -75h16v112l-32 64h17l31 -64v-112h32v112l31 64h17l-32 -64v-112h16c0 17 4 45 21 75c8 14 16 25 24 36c1 1 1 2 2 3zM112 -32v16h64v-16h-64zM96 0v16h96v-16h-96z M96 32v16h96v-16h-96z" /> - <glyph glyph-name="ion-ios7-lightbulb" unicode="" horiz-adv-x="288" + <glyph glyph-name="ion-ios-lightbulb" unicode="" horiz-adv-x="288" d="M288 275c0 -31 -13 -59 -30 -83v0c-11 -15 -22 -28 -32 -45c-22 -38 -18 -73 -18 -82v-1h-32v128l32 64h-16l-32 -64v-128h-32v128l-31 64h-17l32 -64v-128h-32v1c0 7 3 44 -19 82c-10 17 -20 30 -31 45v0c-17 24 -30 52 -30 83c0 78 66 141 144 141s144 -63 144 -141z M112 -32v16h64v-16h-64zM96 0v16h96v-16h-96zM96 32v16h96v-16h-96z" /> - <glyph glyph-name="ion-ios7-location-outline" unicode="" horiz-adv-x="268" -d="M134 416c74 0 134 -59 134 -133c0 -17 -3 -34 -9 -50l-1 -1c0 -1 -1 -3 -1 -4l-1 -1l-122 -259l-122 260c0 1 -2 3 -2 4v0v1v0c-6 16 -10 34 -10 50c0 74 60 133 134 133zM243 239c6 14 9 29 9 44c0 65 -53 117 -118 117s-118 -52 -118 -117c0 -15 3 -31 9 -45 -c0 -1 1 -1 1 -2l1 -2l107 -227l107 227l1 2c0 1 1 1 1 2v1zM134 352c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM134 241c26 0 47 21 47 47s-21 47 -47 47s-47 -21 -47 -47s21 -47 47 -47z" /> - <glyph glyph-name="ion-ios7-location" unicode="" horiz-adv-x="268" -d="M134 416c74 0 134 -59 134 -133c0 -17 -3 -34 -9 -50l-1 -1c0 -1 -1 -3 -1 -4l-1 -1l-122 -259l-122 260c0 1 -2 3 -2 4v1v0c-6 16 -10 34 -10 50c0 74 60 133 134 133zM134 241c26 0 47 21 47 47s-21 47 -47 47s-47 -21 -47 -47s21 -47 47 -47z" /> - <glyph glyph-name="ion-ios7-locked-outline" unicode="" horiz-adv-x="320" -d="M264 224h56v-240h-320v240h56v72c0 57 46 104 104 104c57 0 104 -47 104 -104v-72zM72 296v-72h176v72c0 48 -40 88 -88 88s-88 -40 -88 -88zM304 0v208h-288v-208h288zM192 128c0 -15 -10 -27 -24 -31v-41c0 -4 -4 -8 -8 -8s-8 4 -8 8v41c-14 4 -24 16 -24 31 -c0 18 14 32 32 32s32 -14 32 -32zM160 112c9 0 16 7 16 16s-7 16 -16 16s-16 -7 -16 -16s7 -16 16 -16z" /> - <glyph glyph-name="ion-ios7-locked" unicode="" horiz-adv-x="320" -d="M160 144c9 0 16 -7 16 -16s-7 -16 -16 -16s-16 7 -16 16s7 16 16 16zM264 224h56v-240h-320v240h56v72c0 57 46 104 104 104c57 0 104 -47 104 -104v-72zM168 97c14 4 24 16 24 31c0 18 -14 32 -32 32s-32 -14 -32 -32c0 -15 10 -27 24 -31v-41c0 -4 4 -8 8 -8s8 4 8 8 -v41zM248 224v72c0 48 -40 88 -88 88s-88 -40 -88 -88v-72h176z" /> - <glyph glyph-name="ion-ios7-loop-strong" unicode="" horiz-adv-x="512" + <glyph glyph-name="ion-ios-list-outline" unicode="" horiz-adv-x="384" +d="M368 368h-352v-352h352v352zM384 384v0v-384h-384v384h384zM128 280v16h192v-16h-192zM128 184v16h192v-16h-192zM128 88v16h192v-16h-192zM64 288c0 11 5 16 16 16s16 -5 16 -16s-5 -16 -16 -16s-16 5 -16 16zM64 192c0 11 5 16 16 16s16 -5 16 -16s-5 -16 -16 -16 +s-16 5 -16 16zM64 96c0 11 5 16 16 16s16 -5 16 -16s-5 -16 -16 -16s-16 5 -16 16z" /> + <glyph glyph-name="ion-ios-list" unicode="" horiz-adv-x="384" +d="M0 384h384v-384h-384v384zM80 80c9 0 16 7 16 16s-7 16 -16 16s-16 -7 -16 -16s7 -16 16 -16zM80 176c9 0 16 7 16 16s-7 16 -16 16s-16 -7 -16 -16s7 -16 16 -16zM80 272c9 0 16 7 16 16s-7 16 -16 16s-16 -7 -16 -16s7 -16 16 -16zM320 88v16h-192v-16h192zM320 184v16 +h-192v-16h192zM320 280v16h-192v-16h192z" /> + <glyph glyph-name="ion-ios-location-outline" unicode="" horiz-adv-x="288" +d="M144 400c-34 0 -67 -13 -91 -37s-37 -57 -37 -91c0 -43 24 -107 70 -186c22 -38 44 -72 58 -91c14 19 36 53 58 91c46 79 70 143 70 186c0 34 -13 67 -37 91s-57 37 -91 37zM144 416v0c80 0 144 -64 144 -144c0 -112 -144 -304 -144 -304s-144 192 -144 304 +c0 80 64 144 144 144zM144 336c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM144 225c26 0 47 21 47 47s-21 47 -47 47s-47 -21 -47 -47s21 -47 47 -47z" /> + <glyph glyph-name="ion-ios-location" unicode="" horiz-adv-x="288" +d="M144 416c80 0 144 -64 144 -144c0 -112 -144 -304 -144 -304s-144 192 -144 304c0 80 64 144 144 144zM144 225c26 0 47 21 47 47s-21 47 -47 47s-47 -21 -47 -47s21 -47 47 -47z" /> + <glyph glyph-name="ion-ios-locked-outline" unicode="" horiz-adv-x="320" +d="M264 224h56v-240h-320v240h56v72c0 57 47 104 104 104s104 -47 104 -104v-72zM72 296v-72h176v72c0 49 -39 88 -88 88s-88 -39 -88 -88zM304 0v208h-288v-208h288zM160 160c18 0 32 -14 32 -32c0 -15 -10 -27 -24 -31v-33h-16v33c-14 4 -24 16 -24 31c0 18 14 32 32 32z +M160 112c9 0 16 7 16 16s-7 16 -16 16s-16 -7 -16 -16s7 -16 16 -16z" /> + <glyph glyph-name="ion-ios-locked" unicode="" horiz-adv-x="320" +d="M264 224h56v-240h-320v240h56v72c0 57 47 104 104 104s104 -47 104 -104v-72zM168 97c14 4 24 16 24 31c0 18 -14 32 -32 32s-32 -14 -32 -32c0 -15 10 -27 24 -31v-33h16v33zM248 224v72c0 49 -39 88 -88 88s-88 -39 -88 -88v-72h176zM160 144c9 0 16 -7 16 -16 +s-7 -16 -16 -16s-16 7 -16 16s7 16 16 16z" /> + <glyph glyph-name="ion-ios-loop-strong" unicode="" horiz-adv-x="512" d="M256 400c115 0 208 -93 208 -208c0 -14 -1 -28 -4 -42l-1 -4l-24 5l1 4c2 12 4 24 4 37c0 101 -83 184 -184 184c-66 0 -127 -36 -160 -94l-2 -3l-21 11l2 4c37 65 106 106 181 106zM416 102l2 3l21 -11l-2 -4c-37 -65 -106 -106 -181 -106c-115 0 -208 93 -208 208 c0 14 1 28 4 42l1 4l24 -5l-1 -4c-2 -12 -4 -24 -4 -37c0 -101 83 -184 184 -184c66 0 127 36 160 94zM384 192h128l-64 -64zM0 192l64 64l64 -64h-128z" /> - <glyph glyph-name="ion-ios7-loop" unicode="" horiz-adv-x="489" + <glyph glyph-name="ion-ios-loop" unicode="" horiz-adv-x="489" d="M478 192l11 -11l-52 -53l-53 53l10 11l43 -41zM449 192v0v0c0 -7 0 -14 -1 -21l-16 1c1 7 1 14 1 21c-1 103 -85 187 -188 187c-68 0 -131 -37 -164 -96l-14 8c36 64 104 104 178 104c112 0 203 -91 204 -202v0v-2zM409 100l14 -8c-36 -64 -104 -104 -178 -104 c-111 0 -202 90 -204 200v0v3v1v0c0 7 0 14 1 21l16 -1c-1 -7 -1 -14 -1 -21c0 -103 85 -187 188 -187c68 0 131 37 164 96zM53 256l52 -53l-11 -11l-41 41l-42 -41l-11 11z" /> - <glyph glyph-name="ion-ios7-medkit-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-medical-outline" unicode="" horiz-adv-x="364" +d="M364 260l-118 -68l118 -68l-32 -56l-118 69v-137h-64v137l-118 -69l-32 56l118 68l-118 68l32 56l118 -69v137h64v-137l118 69zM342 118l-128 74l128 74l-16 28l-128 -74v148h-32v-148l-128 74l-16 -28l128 -74l-128 -74l16 -28l128 74v-148h32v148l128 -74z" /> + <glyph glyph-name="ion-ios-medical" unicode="" horiz-adv-x="364" +d="M364 260l-118 -68l118 -68l-32 -56l-118 69v-137h-64v137l-118 -69l-32 56l118 68l-118 68l32 56l118 -69v137h64v-137l118 69z" /> + <glyph glyph-name="ion-ios-medkit-outline" unicode="" horiz-adv-x="416" d="M224 240h-32v-48v-16h-16h-48v-32h48h16v-16v-48h32v48v16h16h48v32h-48h-16v16v48zM240 256v0v-64h64v-64h-64v-64h-64v64h-64v64h64v64h64zM288 320h128v-320h-416v320h128v32c0 18 10 32 29 32h99c19 0 32 -14 32 -32v-32zM144 350v-30h128v30c0 10 -7 18 -17 18h-97 c-11 0 -14 -8 -14 -18zM400 16v288h-384v-288h384z" /> - <glyph glyph-name="ion-ios7-medkit" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-medkit" unicode="" horiz-adv-x="416" d="M224 176h16h48v-32h-48h-16v-16v-48h-32v48v16h-16h-48v32h48h16v16v48h32v-48v-16zM288 320h128v-320h-416v320h128v32c0 18 10 32 29 32h99c19 0 32 -14 32 -32v-32zM144 350v-30h128v30c0 10 -7 18 -17 18h-97c-11 0 -14 -8 -14 -18zM304 128v64h-64v64h-64v-64h-64 v-64h64v-64h64v64h64z" /> - <glyph glyph-name="ion-ios7-mic-off" unicode="" horiz-adv-x="280" + <glyph glyph-name="ion-ios-mic-off" unicode="" horiz-adv-x="280" d="M266 -32l-258 440l14 8l258 -440zM128 95c-44 0 -79 37 -79 83v118l113 -193c-10 -5 -22 -8 -34 -8zM207 178c0 -10 -2 -19 -5 -28l-136 234c14 20 37 32 62 32c44 0 79 -38 79 -84v-154zM256 176c0 -28 -9 -54 -24 -75l-10 17c11 17 17 36 17 58v80h17v-80zM139 49v0 v-63h69v-18h-161v18h73v63c-67 5 -120 60 -120 127v80h19v-80c0 -60 50 -109 110 -109c17 0 34 4 48 11l9 -16c-14 -7 -30 -12 -47 -13z" /> - <glyph glyph-name="ion-ios7-mic-outline" unicode="" horiz-adv-x="256" + <glyph glyph-name="ion-ios-mic-outline" unicode="" horiz-adv-x="256" d="M128 416c44 0 79 -38 79 -84v-154c0 -46 -35 -84 -79 -84s-79 38 -79 84v154c0 46 35 84 79 84zM191 178v154c0 37 -28 68 -63 68s-63 -31 -63 -68v-154c0 -37 28 -68 63 -68s63 31 63 68zM239 256h17v-80c0 -67 -51 -122 -117 -127v-63h69v-18h-161v18h73v63 c-67 5 -120 60 -120 127v80h19v-80c0 -60 50 -109 110 -109s110 49 110 109v80z" /> - <glyph glyph-name="ion-ios7-mic" unicode="" horiz-adv-x="256" + <glyph glyph-name="ion-ios-mic" unicode="" horiz-adv-x="256" d="M128 94c-44 0 -79 38 -79 84v154c0 46 35 84 79 84s79 -38 79 -84v-154c0 -46 -35 -84 -79 -84zM239 256h17v-80c0 -67 -51 -122 -117 -127v-63h69v-18h-161v18h73v63c-67 5 -120 60 -120 127v80h19v-80c0 -60 50 -109 110 -109s110 49 110 109v80z" /> - <glyph glyph-name="ion-ios7-minus-empty" unicode="" horiz-adv-x="256" + <glyph glyph-name="ion-ios-minus-empty" unicode="" horiz-adv-x="256" d="M256 183h-256v17h256v-17z" /> - <glyph glyph-name="ion-ios7-minus-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-minus-outline" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM208 1c105 0 191 86 191 191s-86 191 -191 191s-191 -86 -191 -191s86 -191 191 -191zM80 183v17h256v-17h-256z" /> - <glyph glyph-name="ion-ios7-minus" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-minus" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM336 183v17h-256v-17h256z" /> - <glyph glyph-name="ion-ios7-monitor-outline" unicode="" horiz-adv-x="480" + <glyph glyph-name="ion-ios-monitor-outline" unicode="" horiz-adv-x="480" d="M480 64h-176v-16h64v-16h-257v16h64v16h-175v288h480v-288zM16 336v-256h448v256h-448z" /> - <glyph glyph-name="ion-ios7-monitor" unicode="" horiz-adv-x="480" + <glyph glyph-name="ion-ios-monitor" unicode="" horiz-adv-x="480" d="M480 64h-176v-16h64v-16h-257v16h64v16h-175v288h480v-288zM16 336v-256h448v256h-448zM32 96v224h416v-224h-416z" /> - <glyph glyph-name="ion-ios7-moon-outline" unicode="" horiz-adv-x="216" + <glyph glyph-name="ion-ios-moon-outline" unicode="" horiz-adv-x="216" d="M195 133c7 0 14 1 21 3c-4 -7 -7 -12 -12 -18c-21 -25 -53 -41 -88 -41c-64 0 -116 51 -116 115c0 52 34 96 81 111c7 2 14 3 22 4c-4 -6 -8 -12 -11 -18c-7 -14 -11 -30 -11 -47c0 -29 11 -56 32 -77s48 -32 77 -32h5zM116 93c25 0 48 9 65 24c-65 5 -116 59 -116 125 c0 14 2 28 6 40c-33 -16 -55 -51 -55 -90c0 -55 45 -99 100 -99z" /> - <glyph glyph-name="ion-ios7-moon" unicode="" horiz-adv-x="216" + <glyph glyph-name="ion-ios-moon" unicode="" horiz-adv-x="216" d="M195 133c7 0 14 1 21 3c-4 -7 -7 -12 -12 -18c-21 -25 -53 -41 -88 -41c-64 0 -116 51 -116 115c0 52 34 96 81 111c7 2 14 3 22 4c-4 -6 -8 -12 -11 -18c-7 -14 -11 -30 -11 -47c0 -29 11 -56 32 -77s48 -32 77 -32h5z" /> - <glyph glyph-name="ion-ios7-more-outline" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-more-outline" unicode="" horiz-adv-x="320" d="M160 210c-10 0 -18 -8 -18 -18s8 -18 18 -18s18 8 18 18s-8 18 -18 18zM160 224v0c18 0 32 -14 32 -32s-14 -32 -32 -32s-32 14 -32 32s14 32 32 32zM32 210c-10 0 -18 -8 -18 -18s8 -18 18 -18s18 8 18 18s-8 18 -18 18zM32 224v0c18 0 32 -14 32 -32s-14 -32 -32 -32 s-32 14 -32 32s14 32 32 32zM288 210c-10 0 -18 -8 -18 -18s8 -18 18 -18s18 8 18 18s-8 18 -18 18zM288 224v0c18 0 32 -14 32 -32s-14 -32 -32 -32s-32 14 -32 32s14 32 32 32z" /> - <glyph glyph-name="ion-ios7-more" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-more" unicode="" horiz-adv-x="320" d="M160 224v0c18 0 32 -14 32 -32s-14 -32 -32 -32s-32 14 -32 32s14 32 32 32zM32 224v0c18 0 32 -14 32 -32s-14 -32 -32 -32s-32 14 -32 32s14 32 32 32zM288 224v0c18 0 32 -14 32 -32s-14 -32 -32 -32s-32 14 -32 32s14 32 32 32z" /> - <glyph glyph-name="ion-ios7-musical-note" unicode="" horiz-adv-x="192" + <glyph glyph-name="ion-ios-musical-note" unicode="" horiz-adv-x="192" d="M192 346v-1v-65c0 -3 -3 -6 -6 -5v0l-73 13v-192c0 -33 1 -80 -51 -82c-48 -2 -62 16 -62 41c0 19 9 39 51 41c22 1 37 1 45 1v273l90 -19l2 -1c2 0 3 -1 4 -3v0v-1v0z" /> - <glyph glyph-name="ion-ios7-musical-notes" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-musical-notes" unicode="" horiz-adv-x="320" d="M320 128c0 -34 4 -80 -49 -82c-49 -2 -62 16 -62 41c0 20 9 39 52 41c23 1 34 2 43 2v160l-191 -32v-161c0 -34 3 -81 -50 -83c-49 -2 -63 17 -63 42c0 20 9 39 52 41c23 1 35 1 44 1v237l224 35v-242z" /> - <glyph glyph-name="ion-ios7-navigate-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-navigate-outline" unicode="" horiz-adv-x="416" d="M208 384c-51 0 -99 -21 -135 -57s-57 -84 -57 -135s21 -99 57 -135s84 -57 135 -57s99 21 135 57s57 84 57 135s-21 99 -57 135s-84 57 -135 57zM208 400v0c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM304 288l-96 -224v128h-128z" /> - <glyph glyph-name="ion-ios7-navigate" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-navigate" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM208 64l96 224l-224 -96h128v-128z" /> - <glyph glyph-name="ion-ios7-paper-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-nutrition-outline" unicode="" horiz-adv-x="384" +d="M294 214v0c6 -6 10 -14 10 -23c0 -11 -5 -20 -13 -26v0s-51 -37 -106 -77l-38 31c-2 2 -4 3 -6 3c-1 0 -2 0 -3 -1v0c-2 -2 -2 -6 1 -10l29 -35l-115 -84c-6 -4 -13 -8 -21 -8c-18 0 -32 14 -32 32c0 7 1 13 4 18v0c2 2 17 25 37 57l21 -17c2 -2 4 -2 6 -2c1 0 3 0 4 1v0 +c2 2 1 6 -2 10l-19 23c27 43 60 96 84 134l36 -30c2 -2 4 -3 6 -3c1 0 2 1 3 2v0c2 2 2 5 -1 9l-33 40c11 18 19 29 19 29v0c6 10 15 16 27 16c9 0 18 -4 24 -10v0l78 -79v0v0zM282 178c4 3 6 8 6 13c0 4 -2 9 -5 12l-5 4v1l-69 69v0l-5 5c-3 3 -8 5 -12 5 +c-6 0 -10 -3 -13 -8l-5 -8c-2 -3 -5 -7 -8 -12l25 -30v0l1 -1c8 -10 8 -22 0 -30l-1 -1l-1 -1c-4 -3 -8 -5 -13 -5s-11 2 -16 6v1h-1l-21 18l-24 -39l-44 -70l12 -14v0v0c8 -10 8 -23 0 -31v0c-4 -4 -9 -6 -15 -6c-5 0 -11 2 -16 6v0v0l-7 5c-3 -5 -5 -9 -8 -13 +c-12 -19 -16 -26 -18 -29c-1 -3 -2 -6 -2 -9c0 -9 7 -16 16 -16c3 0 6 2 11 5l101 74l-18 22h-1v0c-8 10 -8 23 0 31v0v0v0c4 4 10 6 15 6s11 -2 16 -6v0h1l28 -24c49 36 93 68 96 70zM376 333l8 -14l-5 -3l-103 -60l-17 17l71 123l2 4l14 -8l-3 -4l-63 -111l91 53z" /> + <glyph glyph-name="ion-ios-nutrition" unicode="" horiz-adv-x="384" +d="M295 214v0c6 -6 9 -13 9 -22c0 -11 -5 -20 -13 -26v0s-51 -38 -106 -78l-38 32c-4 3 -8 3 -10 1v0c-2 -2 -2 -6 1 -10l29 -35l-114 -84c-6 -4 -13 -8 -21 -8c-18 0 -32 14 -32 32c0 7 2 13 5 18v0c1 2 16 25 36 57l20 -17c4 -3 8 -3 10 -1v0c2 2 2 6 -1 10l-20 23 +c27 43 60 96 84 134l36 -30c4 -3 8 -3 10 -1v0c2 2 2 6 -1 10l-33 40c11 18 18 29 18 29v0c6 10 16 16 28 16c9 0 18 -4 24 -10v0l78 -79l1 -1v0zM384 309l-103 -59l-28 29l70 121l28 -16l-50 -85l67 38z" /> + <glyph glyph-name="ion-ios-paper-outline" unicode="" horiz-adv-x="384" d="M48 384h336v-353c0 -17 -14 -31 -31 -31h-322c-17 0 -31 14 -31 31v305h32v-16h-16v-289c0 -8 7 -15 15 -15h322c8 0 15 7 15 15v337h-304v-320h-16v320v16zM96 320v16h128v-16h-128zM96 240v16h240v-16h-240zM96 160v16h192v-16h-192zM96 80v16h240v-16h-240z" /> - <glyph glyph-name="ion-ios7-paper" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-paper" unicode="" horiz-adv-x="384" d="M48 384h336v-353c0 -17 -14 -31 -31 -31h-322c-17 0 -31 14 -31 31v305h32v-288h16v288v32v16zM96 336v-16h128v16h-128zM96 176v-16h192v16h-192zM336 80v16h-240v-16h240zM336 240v16h-240v-16h240z" /> - <glyph glyph-name="ion-ios7-paperplane-outline" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-paperplane-outline" unicode="" horiz-adv-x="320" d="M0 198l320 154l-146 -320l-57 115zM132 152l41 -83l115 249zM286 320l-248 -121l83 -36z" /> - <glyph glyph-name="ion-ios7-paperplane" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-paperplane" unicode="" horiz-adv-x="320" d="M0 198l320 154l-214 -200zM320 352l-146 -320l-52 104z" /> - <glyph glyph-name="ion-ios7-partlysunny-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-partlysunny-outline" unicode="" horiz-adv-x="384" d="M144 298v54h16v-54h-16zM0 192v16h55v-16h-55zM44 299l10 11l32 -32l-11 -11zM223 268l-11 11l32 32l11 -11zM56 96l-10 11l31 31l11 -11zM129 153c-4 -3 -8 -7 -12 -12c-23 12 -39 36 -39 63c0 39 32 71 71 71c21 0 40 -10 53 -25c-4 -2 -9 -4 -14 -8 c-10 11 -23 17 -39 17c-30 0 -55 -25 -55 -55c0 -23 15 -43 35 -51zM235 208c-34 0 -63 -28 -63 -62v-12s1 -10 1 -10c-5 0 -12 -1 -14 -1c-19 -3 -33 -18 -33 -37c0 -10 3 -19 10 -26s16 -11 26 -11h157c27 0 49 22 49 49s-22 50 -49 50c-2 0 -4 -1 -6 -1l-14 -2l-3 14 c-3 14 -11 26 -22 35s-25 14 -39 14zM235 224v0c37 0 68 -26 76 -61h8c36 0 65 -29 65 -65s-29 -66 -65 -66h-157c-28 0 -52 24 -52 53c0 27 21 51 47 53v8c0 43 35 78 78 78z" /> - <glyph glyph-name="ion-ios7-partlysunny" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-partlysunny" unicode="" horiz-adv-x="384" d="M144 298v54h16v-54h-16zM0 192v16h55v-16h-55zM44 299l10 11l32 -32l-11 -11zM223 268l-11 11l32 32l11 -11zM56 96l-10 11l31 31l11 -11zM235 224v0c37 0 68 -26 76 -61h8c36 0 65 -29 65 -65s-29 -66 -65 -66h-157c-28 0 -52 24 -52 53c0 27 21 51 47 53v8 c0 43 35 78 78 78zM201 252l1 -2v0c-31 -5 -62 -43 -62 -75c0 -2 1 -5 1 -7l-1 -1h-1c-11 -6 -18 -14 -22 -26v1v-1c-23 12 -39 36 -39 63c0 39 32 71 71 71c21 0 39 -9 52 -23z" /> - <glyph glyph-name="ion-ios7-pause-outline" unicode="" horiz-adv-x="256" + <glyph glyph-name="ion-ios-pause-outline" unicode="" horiz-adv-x="256" d="M63 336h-47v-288h47v288zM79 352v0v-320h-79v320h79zM240 336h-47v-288h47v288zM256 352v0v-320h-79v320h79z" /> - <glyph glyph-name="ion-ios7-pause" unicode="" horiz-adv-x="256" + <glyph glyph-name="ion-ios-pause" unicode="" horiz-adv-x="256" d="M0 32v320h79v-320h-79zM177 32v320h79v-320h-79z" /> - <glyph glyph-name="ion-ios7-paw-outline" unicode="" horiz-adv-x="416" -d="M262 238c-11 2 -20 7 -27 17c-12 16 -15 41 -11 65c6 37 27 64 54 64h6c12 -2 22 -8 30 -19c12 -16 16 -39 13 -61c-6 -37 -31 -66 -59 -66h-6zM278 368c-18 0 -34 -21 -38 -50c-3 -20 -1 -41 8 -53c5 -6 11 -10 17 -11h3c19 0 39 23 43 52c3 18 -2 37 -11 49 -c-4 5 -10 12 -19 13h-3zM412 244c6 -17 5 -38 -3 -57c-10 -25 -31 -43 -51 -43c-5 0 -10 1 -15 3c-22 10 -30 45 -17 79c10 28 31 46 51 46c5 0 10 -1 14 -3c10 -4 17 -13 21 -25zM357 162c14 0 29 13 37 32c6 15 7 31 2 44c-2 5 -5 12 -12 15c-2 1 -4 2 -7 2 -c-13 0 -28 -15 -36 -36c-9 -25 -6 -50 8 -56c2 -1 5 -1 8 -1zM7 187c-8 19 -9 40 -3 57c4 12 11 21 21 25c4 2 9 3 14 3c20 0 41 -18 51 -46c13 -34 5 -69 -17 -79c-5 -2 -10 -3 -15 -3c-20 0 -41 18 -51 43zM22 194c8 -19 23 -32 37 -32c3 0 6 0 8 1c14 6 17 31 8 56 -c-8 21 -23 36 -36 36c-3 0 -5 -1 -7 -2c-7 -3 -10 -10 -12 -15c-5 -13 -4 -29 2 -44zM149 238c-28 0 -53 29 -59 66c-3 22 1 45 13 61c8 11 18 17 30 19h6c27 0 47 -28 53 -65c4 -24 2 -48 -10 -64c-7 -10 -17 -15 -28 -17h-5zM139 368h-4c-9 -1 -15 -8 -19 -13 -c-9 -12 -13 -31 -10 -49c4 -29 24 -52 43 -52h3c6 1 11 5 16 11c9 12 11 32 8 52c-4 29 -19 51 -37 51zM208 192c64 0 128 -71 128 -138c0 -20 -11 -36 -22 -43c-13 -8 -23 -11 -42 -11c-23 0 -29 7 -40 14c-8 5 -14 9 -24 9s-16 -4 -24 -9c-11 -7 -17 -14 -40 -14 -c-19 0 -29 3 -42 11c-11 7 -22 23 -22 43c0 67 64 138 128 138zM306 25c6 3 14 14 14 29c0 28 -14 59 -36 83c-11 12 -23 22 -36 29s-27 10 -40 10s-27 -3 -40 -10s-25 -17 -36 -29c-22 -24 -36 -55 -36 -83c0 -15 8 -26 14 -29c11 -7 18 -9 34 -9c14 0 19 3 26 8 -c2 1 4 3 6 4c9 5 18 11 32 11s23 -6 32 -11c2 -1 4 -3 6 -4c7 -5 12 -8 26 -8c16 0 23 2 34 9z" /> - <glyph glyph-name="ion-ios7-paw" unicode="" horiz-adv-x="416" -d="M262 238c-11 2 -20 7 -27 17c-12 16 -15 41 -11 65c6 37 27 64 54 64h6c12 -2 22 -8 30 -19c12 -16 16 -39 13 -61c-6 -37 -31 -66 -59 -66h-6zM412 244c6 -17 5 -38 -3 -57c-10 -25 -31 -43 -51 -43c-5 0 -10 1 -15 3c-22 10 -30 45 -17 79c10 28 31 46 51 46 -c5 0 10 -1 14 -3c10 -4 17 -13 21 -25zM7 187c-8 19 -9 40 -3 57c4 12 11 21 21 25c4 2 9 3 14 3c20 0 41 -18 51 -46c13 -34 5 -69 -17 -79c-5 -2 -10 -3 -15 -3c-20 0 -41 18 -51 43zM149 238c-28 0 -53 29 -59 66c-3 22 1 45 13 61c8 11 18 17 30 19h6 -c27 0 47 -28 53 -65c4 -24 2 -48 -10 -64c-7 -10 -17 -15 -28 -17h-5zM208 192c64 0 128 -71 128 -138c0 -20 -11 -36 -22 -43c-13 -8 -23 -11 -42 -11c-23 0 -29 7 -40 14c-8 5 -14 9 -24 9s-16 -4 -24 -9c-11 -7 -17 -14 -40 -14c-19 0 -29 3 -42 11c-11 7 -22 23 -22 43 -c0 67 64 138 128 138z" /> - <glyph glyph-name="ion-ios7-people-outline" unicode="" + <glyph glyph-name="ion-ios-paw-outline" unicode="" horiz-adv-x="384" +d="M380 252c6 -17 5 -38 -3 -57c-10 -25 -31 -43 -51 -43c-5 0 -10 1 -15 3c-22 10 -30 45 -17 79c10 28 31 46 51 46c5 0 10 -1 14 -3c10 -4 17 -13 21 -25zM362 202c6 15 7 31 2 44c-2 5 -5 12 -12 15c-2 1 -4 2 -7 2c-13 0 -28 -15 -36 -36c-9 -25 -6 -50 8 -56 +c2 -1 5 -1 8 -1c14 0 29 13 37 32zM90 234c13 -34 5 -69 -17 -79c-5 -2 -10 -3 -15 -3c-20 0 -41 18 -51 43c-8 19 -9 40 -3 57c4 12 11 21 21 25c4 2 9 3 14 3c20 0 41 -18 51 -46zM67 171c14 6 17 31 8 56c-8 21 -23 36 -36 36c-3 0 -5 -1 -7 -2c-7 -3 -10 -10 -12 -15 +c-5 -13 -4 -29 2 -44c8 -19 23 -32 37 -32c3 0 6 0 8 1zM134 237c-28 1 -52 32 -56 69c-2 23 4 45 16 60c8 10 19 17 31 18h6c27 -1 46 -29 50 -67c3 -24 -1 -48 -13 -63c-8 -9 -17 -15 -28 -16c-2 0 -4 -1 -6 -1zM107 356c-10 -12 -14 -29 -12 -48c3 -29 21 -53 40 -54h3 +c6 1 12 4 17 10c10 12 12 31 10 51c-3 29 -17 52 -35 53h-3c-9 -1 -16 -7 -20 -12zM192 208c64 0 128 -76 128 -149c0 -22 -11 -40 -22 -47c-13 -9 -23 -12 -42 -12c-23 0 -29 8 -40 15c-8 5 -14 10 -24 10s-16 -5 -24 -10c-11 -7 -17 -15 -40 -15c-19 0 -29 3 -42 12 +c-11 7 -22 25 -22 47c0 73 64 149 128 149zM290 27c6 4 14 16 14 32c0 30 -14 64 -36 91c-11 13 -23 24 -36 31c-13 8 -27 11 -40 11s-27 -3 -40 -11c-13 -7 -25 -18 -36 -31c-22 -27 -36 -61 -36 -91c0 -16 8 -28 14 -32c11 -7 18 -10 34 -10c14 0 19 4 26 9c2 1 4 3 6 4 +c9 6 18 12 32 12s23 -6 32 -12c2 -1 4 -3 6 -4c7 -5 12 -9 26 -9c16 0 23 3 34 10zM244 238c-11 1 -20 7 -28 16c-12 15 -16 39 -13 63c4 38 23 66 50 67h7c12 -1 22 -8 30 -18c12 -15 18 -37 16 -60c-4 -37 -28 -67 -56 -68h-6zM219 315c-2 -20 0 -39 10 -51 +c5 -6 11 -9 17 -10h3c19 1 38 25 41 54c2 19 -3 36 -13 48c-4 5 -10 11 -19 12h-4c-18 -1 -32 -24 -35 -53z" /> + <glyph glyph-name="ion-ios-paw" unicode="" horiz-adv-x="384" +d="M380 252c6 -17 5 -38 -3 -57c-10 -25 -31 -43 -51 -43c-5 0 -10 1 -15 3c-22 10 -30 45 -17 79c10 28 31 46 51 46c5 0 10 -1 14 -3c10 -4 17 -13 21 -25zM90 234c13 -34 5 -69 -17 -79c-5 -2 -10 -3 -15 -3c-20 0 -41 18 -51 43c-8 19 -9 40 -3 57c4 12 11 21 21 25 +c4 2 9 3 14 3c20 0 41 -18 51 -46zM134 237c-28 1 -52 32 -56 69c-2 23 4 45 16 60c8 10 19 17 31 18h6c27 -1 46 -29 50 -67c3 -24 -1 -48 -13 -63c-8 -9 -17 -15 -28 -16c-2 0 -4 -1 -6 -1zM192 208c64 0 128 -76 128 -149c0 -22 -11 -40 -22 -47c-13 -9 -23 -12 -42 -12 +c-23 0 -29 8 -40 15c-8 5 -14 10 -24 10s-16 -5 -24 -10c-11 -7 -17 -15 -40 -15c-19 0 -29 3 -42 12c-11 7 -22 25 -22 47c0 73 64 149 128 149zM244 238c-11 1 -20 7 -28 16c-12 15 -16 39 -13 63c4 38 23 66 50 67h7c12 -1 22 -8 30 -18c12 -15 18 -37 16 -60 +c-4 -37 -28 -67 -56 -68h-6z" /> + <glyph glyph-name="ion-ios-people-outline" unicode="" d="M224 336v0v0zM317 113c11 -4 -11 4 0 0c28 -10 46 -35 46 -65h-28h-250c0 22 9 42 27 55c15 11 31 12 49 16c7 1 24 5 26 13s1 15 1 23c0 3 0 3 -2 5c-4 4 -6 9 -8 14c-2 8 -3 16 -4 24c-9 -2 -10 16 -12 21c-1 4 -7 24 3 21c-3 5 -4 13 -5 19c-2 13 -2 26 3 39 c10 26 37 39 64 38c26 -1 51 -16 59 -42c4 -12 3 -26 1 -39c-1 -5 -2 -11 -4 -15c10 3 4 -20 3 -23c-2 -5 -3 -21 -12 -19c-1 -10 -2 -22 -7 -31c-1 -2 -7 -8 -7 -10v-11c0 -5 0 -10 2 -15s10 -7 14 -8c14 -5 27 -5 41 -10zM115 84c-6 -6 9 10 0 0c-6 -6 -10 -12 -12 -20h4 h238c-4 15 -17 27 -30 33s-28 4 -41 9s-25 9 -28 25c-2 11 -2 22 -2 33c0 2 7 7 8 9c3 5 4 11 5 17c1 5 0 12 4 15c5 4 7 7 9 13c2 8 3 12 -1 19c-3 5 0 8 1 13c3 11 4 24 2 36c-8 37 -62 45 -86 19c-12 -13 -12 -31 -9 -47c1 -6 6 -14 3 -19c-1 -3 -5 -6 -4 -10 @@ -1031,254 +1238,271 @@ c6 -2 19 -3 23 -8c2 -3 1 -5 -2 -5c-8 -1 -15 -1 -22 -5zM71 112c6 10 16 18 26 24c- c-1 -12 -8 -18 -19 -22c-12 -4 -29 -3 -36 -15h49zM368 96c-2 8 -10 14 -16 19c-8 6 -18 13 -28 15c-3 1 -16 -1 -13 5c2 4 9 5 13 6s15 2 16 7c0 1 1 14 0 14c-6 0 -12 1 -18 2c-4 1 -7 2 -11 4c-6 3 -2 6 0 11c14 32 -10 88 32 105c15 6 34 5 48 -3c15 -9 20 -27 20 -44 c0 -20 -4 -44 7 -62c2 -3 4 -4 0 -6c-2 -1 -4 -1 -6 -2l-12 -3s-9 -1 -13 -1c0 -4 -2 -13 1 -17c6 -7 21 -7 29 -10c18 -6 31 -20 31 -40h-80zM367 123c4 -4 -5 5 0 0s8 -11 15 -11h16h28c-7 12 -26 11 -38 16c-11 4 -16 12 -17 24c0 2 -1 27 1 27c9 0 18 0 26 1 c-7 23 1 47 -4 70c-3 15 -15 23 -30 23c-17 0 -28 -8 -31 -25c-4 -23 2 -46 -5 -68c6 -2 12 -2 18 -2s8 1 9 -5c1 -11 5 -28 -4 -37c6 -4 11 -8 16 -13z" /> - <glyph glyph-name="ion-ios7-people" unicode="" + <glyph glyph-name="ion-ios-people" unicode="" d="M317 113c11 -4 -11 4 0 0v0zM317 113c28 -10 46 -35 46 -65h-28h-250c0 22 9 42 27 55c15 11 31 12 49 16c7 1 24 5 26 13s1 15 1 23c0 3 0 3 -2 5c-4 4 -6 9 -8 14c-2 8 -3 16 -4 24c-9 -2 -10 16 -12 21c-1 4 -7 24 3 21c-3 5 -4 13 -5 19c-2 13 -2 26 3 39 c10 26 37 39 64 38c26 -1 51 -16 59 -42c4 -12 3 -26 1 -39c-1 -5 -2 -11 -4 -15c10 3 4 -20 3 -23c-2 -5 -3 -21 -12 -19c-1 -10 -2 -22 -7 -31c-1 -2 -7 -8 -7 -10v-11c0 -5 0 -10 2 -15s10 -7 14 -8c14 -5 27 -5 41 -10zM111 126h2h-1h-1zM111 126c-9 -5 -17 -11 -24 -19 c-1 -2 -6 -11 -7 -11h-25h-55c0 20 12 34 30 40c6 2 27 4 30 11c2 5 1 11 1 16c-10 -1 -24 1 -32 7c-2 2 3 9 4 12c1 4 2 7 3 11c1 9 1 19 1 28c0 16 -1 35 8 49c8 13 23 18 38 18c24 0 43 -13 47 -37c3 -16 1 -32 2 -48c0 -8 2 -16 5 -24c1 -2 5 -7 3 -9l-6 -3 c-5 -2 -11 -3 -17 -4c-1 0 -8 0 -9 -1s0 -9 0 -11c0 -4 1 -6 5 -7c6 -2 19 -3 23 -8c2 -3 1 -5 -2 -5c-7 -1 -14 -2 -21 -5c2 1 2 2 -1 0c-8 -4 -4 -2 -1 0zM417 136c18 -6 31 -20 31 -40h-80c-2 8 -10 14 -16 19c-8 6 -18 13 -28 15c-3 1 -16 -1 -13 5c2 4 9 5 13 6 s15 2 16 7c0 1 1 14 0 14c-6 0 -12 1 -18 2c-4 1 -7 2 -11 4c-6 3 -2 6 0 11c14 32 -10 88 32 105c15 6 34 5 48 -3c15 -9 20 -27 20 -44c0 -20 -4 -44 7 -62c2 -3 4 -4 0 -6c-2 -1 -4 -1 -6 -2l-12 -3s-9 -1 -13 -1c0 -4 -2 -13 1 -17c6 -7 21 -7 29 -10z" /> - <glyph glyph-name="ion-ios7-person-outline" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-person-outline" unicode="" horiz-adv-x="320" d="M106 246v0v0zM267 84c13 -5 53 -20 53 -52h-160h-160c0 32 40 47 53 52s31 6 43 9c7 2 17 5 20 9s1 41 1 41s-6 10 -9 18s-7 32 -7 32s-7 0 -9 12c-2 13 -6 17 -6 27c0 9 5 10 5 10v0s-4 13 -5 42c-1 34 25 68 74 68s75 -34 74 -68c-1 -29 -5 -42 -5 -42v0s5 -1 5 -10 c0 -10 -3 -15 -6 -28c-2 -12 -9 -12 -9 -12s-4 -23 -7 -31s-9 -18 -9 -18s-2 -37 1 -41s13 -7 20 -9c12 -3 30 -4 43 -9zM160 48v0h137c-2 3 -4 6 -8 8c-7 5 -16 9 -27 13c-7 2 -17 4 -26 5c-6 1 -10 2 -15 3c-3 1 -21 5 -29 15c-4 5 -6 12 -6 32c0 10 1 20 1 20v4l2 4 c1 2 6 9 8 15c2 5 5 19 6 28c0 0 0 -1 1 4s8 4 9 8s3 7 5 18s-5 12 -5 17c0 4 1 5 1 5v0c0 1 4 14 4 38c0 13 -5 26 -14 35c-11 11 -25 16 -44 16c-18 0 -34 -5 -45 -16c-9 -9 -13 -22 -13 -35c1 -24 4 -37 4 -38v0s1 -3 0 -6c-1 -5 -6 -5 -4 -16s4 -14 5 -18s8 -3 9 -8 s1 -4 1 -4c1 -9 4 -23 6 -28c2 -6 6 -13 8 -15l2 -4v-4s1 -10 1 -20c0 -20 -2 -27 -6 -32c-8 -10 -26 -14 -29 -15c-5 -1 -10 -2 -16 -3c-9 -1 -18 -3 -25 -5c-11 -4 -20 -8 -27 -13c-4 -2 -6 -5 -8 -8h137z" /> - <glyph glyph-name="ion-ios7-person" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-person" unicode="" horiz-adv-x="320" d="M267 84c13 -5 53 -20 53 -52h-160h-160c0 32 40 47 53 52s31 6 43 9c7 2 17 5 20 9s1 41 1 41s-6 10 -9 18s-7 32 -7 32s-7 0 -9 12c-2 13 -6 17 -6 27c0 9 5 10 5 10v0s-4 13 -5 42c-1 34 25 68 74 68s75 -34 74 -68c-1 -29 -5 -42 -5 -42v0s5 -1 5 -10 c0 -10 -3 -15 -6 -28c-2 -12 -9 -12 -9 -12s-4 -23 -7 -31s-9 -18 -9 -18s-2 -37 1 -41s13 -7 20 -9c12 -3 30 -4 43 -9z" /> - <glyph glyph-name="ion-ios7-personadd-outline" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-personadd-outline" unicode="" horiz-adv-x="320" d="M320 295v-14h-25v-25h-14v25h-25v14h25v25h14v-25h25zM106 246v0v0zM267 84c13 -5 53 -20 53 -52h-160h-160c0 32 40 47 53 52s31 6 43 9c7 2 17 5 20 9s1 41 1 41s-6 10 -9 18s-7 32 -7 32s-7 0 -9 12c-2 13 -6 17 -6 27c0 9 5 10 5 10v0s-4 13 -5 42c-1 34 25 68 74 68 s75 -34 74 -68c-1 -29 -5 -42 -5 -42v0s5 -1 5 -10c0 -10 -3 -15 -6 -28c-2 -12 -9 -12 -9 -12s-4 -23 -7 -31s-9 -18 -9 -18s-2 -37 1 -41s13 -7 20 -9c12 -3 30 -4 43 -9zM160 48v0h137c-2 3 -4 6 -8 8c-7 5 -16 9 -27 13c-7 2 -17 4 -26 5c-6 1 -10 2 -15 3 c-3 1 -21 5 -29 15c-4 5 -6 12 -6 32c0 10 1 20 1 20v4l2 4c1 2 6 9 8 15c2 5 5 19 6 28c0 0 0 -1 1 4s8 4 9 8s3 7 5 18s-5 12 -5 17c0 4 1 5 1 5v0c0 1 4 14 4 38c0 13 -5 26 -14 35c-11 11 -25 16 -44 16c-18 0 -34 -5 -45 -16c-9 -9 -13 -22 -13 -35c1 -24 4 -37 4 -38 v0s1 -3 0 -6c-1 -5 -6 -5 -4 -16s4 -14 5 -18s8 -3 9 -8s1 -4 1 -4c1 -9 4 -23 6 -28c2 -6 6 -13 8 -15l2 -4v-4s1 -10 1 -20c0 -20 -2 -27 -6 -32c-8 -10 -26 -14 -29 -15c-5 -1 -10 -2 -16 -3c-9 -1 -18 -3 -25 -5c-11 -4 -20 -8 -27 -13c-4 -2 -6 -5 -8 -8h137z" /> - <glyph glyph-name="ion-ios7-personadd" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-personadd" unicode="" horiz-adv-x="320" d="M320 295v-14h-25v-25h-14v25h-25v14h25v25h14v-25h25zM267 84c13 -5 53 -20 53 -52h-160h-160c0 32 40 47 53 52s31 6 43 9c7 2 17 5 20 9s1 41 1 41s-6 10 -9 18s-7 32 -7 32s-7 0 -9 12c-2 13 -6 17 -6 27c0 9 5 10 5 10v0s-4 13 -5 42c-1 34 25 68 74 68 s75 -34 74 -68c-1 -29 -5 -42 -5 -42v0s5 -1 5 -10c0 -10 -3 -15 -6 -28c-2 -12 -9 -12 -9 -12s-4 -23 -7 -31s-9 -18 -9 -18s-2 -37 1 -41s13 -7 20 -9c12 -3 30 -4 43 -9z" /> - <glyph glyph-name="ion-ios7-photos-outline" unicode="" + <glyph glyph-name="ion-ios-photos-outline" unicode="" d="M64 320h384v-320h-384v320zM432 16v288h-352v-288h352zM0 384h384v-48h-16v32h-352v-288h32v-16h-48v320z" /> - <glyph glyph-name="ion-ios7-photos" unicode="" + <glyph glyph-name="ion-ios-photos" unicode="" d="M64 320h384v-320h-384v320zM384 384v-48h-336v-272h-48v320h384z" /> - <glyph glyph-name="ion-ios7-pie-outline" unicode="" -d="M32 176h208v208c5 0 11 -1 16 -1c17 -1 33 -4 49 -9c24 -8 46 -21 65 -36c47 -38 78 -96 78 -162c0 -115 -93 -208 -208 -208c-66 0 -124 31 -162 78c-15 19 -28 41 -36 65c-5 16 -8 32 -9 49c0 5 -1 11 -1 16zM49 160c2 -20 6 -40 14 -59c7 -16 15 -30 26 -44 -c5 -6 10 -12 15 -17c12 -12 24 -22 38 -30c7 -4 15 -8 23 -11c24 -10 49 -15 75 -15s51 5 75 15c23 10 43 23 61 41s31 38 41 61c10 24 15 49 15 75s-5 51 -15 75c-3 8 -8 15 -12 22c-8 14 -17 27 -29 39c-5 5 -11 10 -17 15c-14 11 -28 19 -44 26c-19 8 -39 12 -59 14v-191 -v-16h-16h-191zM0 208c0 115 93 208 208 208c5 0 11 -1 16 -1v-207v-16h-16h-207c0 5 -1 11 -1 16zM16 208h192v192c-26 0 -51 -5 -75 -15c-23 -10 -43 -23 -61 -41s-31 -38 -41 -61c-10 -24 -15 -49 -15 -75z" /> - <glyph glyph-name="ion-ios7-pie" unicode="" -d="M32 176h208v208c5 0 11 -1 16 -1c17 -1 33 -4 49 -9c24 -8 46 -21 65 -36c47 -38 78 -96 78 -162c0 -115 -93 -208 -208 -208c-66 0 -124 31 -162 78c-15 19 -28 41 -36 65c-5 16 -8 32 -9 49c0 5 -1 11 -1 16zM0 208c0 115 93 208 208 208c5 0 11 -1 16 -1v-207v-16h-16 -h-207c0 5 -1 11 -1 16z" /> - <glyph glyph-name="ion-ios7-play-outline" unicode="" horiz-adv-x="256" + <glyph glyph-name="ion-ios-pie-outline" unicode="" +d="M256 367v0v-207v-12l-12 -4l-180 -45c6 -13 13 -25 21 -36c12 -16 25 -30 41 -42c33 -24 73 -37 114 -37c26 0 51 5 75 15c23 10 43 23 61 41s31 38 41 61c10 24 15 49 15 75c0 51 -20 100 -56 136c-32 32 -75 51 -120 55zM240 384v0c115 0 208 -93 208 -208 +s-93 -208 -208 -208c-92 0 -171 60 -198 143l198 49v224zM208 400c-31 -1 -60 -7 -85 -18c-24 -11 -44 -26 -61 -46c-29 -34 -46 -80 -46 -127v0v0c0 -13 3 -46 12 -70l180 46v215zM224 416v0v-244l-205 -52c-19 32 -19 89 -19 89c0 91 58 207 218 207h6z" /> + <glyph glyph-name="ion-ios-pie" unicode="" +d="M240 384v0c115 0 208 -93 208 -208s-93 -208 -208 -208c-92 0 -171 60 -198 143l198 49v224zM224 416v0v-244l-205 -52c-19 32 -19 89 -19 89c0 91 58 207 218 207h6z" /> + <glyph glyph-name="ion-ios-pint-outline" unicode="" horiz-adv-x="224" +d="M224 278c0 -98 -32 -101 -32 -181c0 -40 16 -71 16 -99c0 -27 -9 -30 -32 -30h-128c-23 0 -32 2 -32 29c0 28 16 60 16 100c0 80 -32 83 -32 181c0 21 1 89 19 125c4 9 13 13 32 13h122c19 0 28 -4 32 -13c18 -36 19 -104 19 -125zM34 396c-8 -16 -14 -43 -17 -76h190 +c-3 33 -9 60 -17 76c-1 2 -1 1 -2 2c-2 1 -6 2 -15 2h-122c-9 0 -13 -1 -15 -2c-1 -1 -1 0 -2 -2zM191 -15c0 1 1 5 1 13c0 11 -4 23 -7 37c-4 18 -9 39 -9 62c0 41 8 64 16 86c8 23 16 46 16 95c0 9 -1 18 -1 26h-190c0 -8 -1 -17 -1 -26c0 -49 8 -72 16 -95 +c8 -22 16 -45 16 -86c0 -23 -5 -44 -9 -62c-3 -14 -7 -26 -7 -37c0 -8 1 -12 1 -13c2 -1 7 -1 15 -1h128c8 0 13 0 15 1z" /> + <glyph glyph-name="ion-ios-pint" unicode="" horiz-adv-x="224" +d="M224 278c0 -98 -32 -101 -32 -181c0 -40 16 -71 16 -99c0 -27 -9 -30 -32 -30h-128c-23 0 -32 2 -32 29c0 28 16 60 16 100c0 80 -32 83 -32 181c0 21 1 89 19 125c4 9 13 13 32 13h122c19 0 28 -4 32 -13c18 -36 19 -104 19 -125zM34 396c-8 -16 -14 -43 -17 -76h190 +c-3 33 -9 60 -17 76c-1 2 -1 1 -2 2c-2 1 -6 2 -15 2h-122c-9 0 -13 -1 -15 -2c-1 -1 -1 0 -2 -2z" /> + <glyph glyph-name="ion-ios-play-outline" unicode="" horiz-adv-x="256" d="M16 323v-262l210 131zM0 352v0l256 -160l-256 -160v320z" /> - <glyph glyph-name="ion-ios7-play" unicode="" horiz-adv-x="256" + <glyph glyph-name="ion-ios-play" unicode="" horiz-adv-x="256" d="M0 352v0l256 -160l-256 -160v320z" /> - <glyph glyph-name="ion-ios7-plus-empty" unicode="" horiz-adv-x="256" + <glyph glyph-name="ion-ios-plus-empty" unicode="" horiz-adv-x="256" d="M256 183h-120v-119h-17v119h-119v17h119v120h17v-120h120v-17z" /> - <glyph glyph-name="ion-ios7-plus-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-plus-outline" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM208 1c105 0 191 86 191 191s-86 191 -191 191s-191 -86 -191 -191s86 -191 191 -191zM216 320v-120h120v-17h-120v-119h-17v119h-119v17h119v120h17z" /> - <glyph glyph-name="ion-ios7-plus" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-plus" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM336 183v17h-120v120h-17v-120h-119v-17h119v-119h17v119h120z" /> - <glyph glyph-name="ion-ios7-pricetag-outline" unicode="" horiz-adv-x="384" -d="M143 368h-111c-9 0 -16 -7 -16 -16v-108c0 -6 3 -12 7 -16l213 -207h1v-1c3 -3 7 -4 11 -4s8 1 11 4l104 105c3 3 5 7 5 11s-2 8 -5 11v1v0l-204 213c-4 4 -10 7 -16 7zM143 384v0c10 0 20 -4 28 -12l204 -213c6 -6 9 -15 9 -23s-3 -16 -9 -22l-105 -105 -c-6 -6 -14 -9 -22 -9s-17 3 -23 9l-214 207c-7 7 -11 17 -11 28v108c0 18 14 32 32 32h111zM96 320c-18 0 -32 -14 -32 -32s14 -32 32 -32s32 14 32 32s-14 32 -32 32zM96 336v0c26 0 48 -22 48 -48s-22 -48 -48 -48s-48 22 -48 48s22 48 48 48z" /> - <glyph glyph-name="ion-ios7-pricetag" unicode="" horiz-adv-x="384" -d="M64 288c0 21 11 32 32 32s32 -11 32 -32s-11 -32 -32 -32s-32 11 -32 32zM375 159c6 -6 9 -14 9 -23s-3 -16 -9 -22l-105 -105c-6 -6 -13 -9 -22 -9s-17 3 -23 9l-214 207c-8 8 -11 17 -11 28v108c0 9 3 17 9 23s14 9 23 9h111c11 0 20 -4 28 -12zM96 240 -c13 0 25 5 34 14s14 21 14 34s-5 25 -14 34s-21 14 -34 14s-25 -5 -34 -14s-14 -21 -14 -34s5 -25 14 -34s21 -14 34 -14z" /> - <glyph glyph-name="ion-ios7-pricetags-outline" unicode="" + <glyph glyph-name="ion-ios-pricetag-outline" unicode="" horiz-adv-x="416" +d="M416 416v-160l-256 -288l-160 160l256 288h160zM400 264v136h-136l-240 -272l136 -136zM320 288c-18 0 -32 14 -32 32s14 32 32 32s32 -14 32 -32s-14 -32 -32 -32zM320 336c-9 0 -16 -7 -16 -16s7 -16 16 -16s16 7 16 16s-7 16 -16 16z" /> + <glyph glyph-name="ion-ios-pricetag" unicode="" horiz-adv-x="416" +d="M304 320c0 11 5 16 16 16s16 -5 16 -16s-5 -16 -16 -16s-16 5 -16 16zM256 416h160v-160l-256 -288l-160 160zM320 288c9 0 16 4 22 10s10 13 10 22s-4 16 -10 22s-13 10 -22 10s-16 -4 -22 -10s-10 -13 -10 -22s4 -16 10 -22s13 -10 22 -10z" /> + <glyph glyph-name="ion-ios-pricetags-outline" unicode="" d="M416 384h32v-144l-240 -272l-25 24l-23 -24l-160 160l256 288h160v-32zM160 -9l12 12l11 12l217 248v105v16v16h-137l-241 -272zM432 247v121h-16v-112l-221 -253l13 -12zM320 288c-18 0 -32 14 -32 32s14 32 32 32s32 -14 32 -32s-14 -32 -32 -32zM320 336 c-9 0 -16 -7 -16 -16s7 -16 16 -16s16 7 16 16s-7 16 -16 16z" /> - <glyph glyph-name="ion-ios7-pricetags" unicode="" + <glyph glyph-name="ion-ios-pricetags" unicode="" d="M432 384h16v-144l-240 -272l-13 13l237 266v137zM256 416h160v-32v-16v-112l-221 -253l-12 -11l-23 -24l-160 160zM320 288c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM304 320c0 11 5 16 16 16s16 -5 16 -16s-5 -16 -16 -16s-16 5 -16 16z" /> - <glyph glyph-name="ion-ios7-printer-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-printer-outline" unicode="" horiz-adv-x="416" d="M384 336c18 0 32 -13 32 -31v-159c0 -18 -14 -32 -32 -32h-48v-114h-256v114h-48c-18 0 -32 14 -32 32v159c0 18 14 31 32 31h32v48h288v-48h32zM80 368v-32h256v32h-256zM320 16v192h-224v-192h224zM400 146v159c0 9 -7 15 -16 15v0h-352c-9 0 -16 -6 -16 -15v-159 c0 -9 7 -16 16 -16h48v94h256v-94h48c9 0 16 7 16 16z" /> - <glyph glyph-name="ion-ios7-printer" unicode="" horiz-adv-x="416" -d="M384 336c18 0 32 -13 32 -31v-159c0 -18 -14 -32 -32 -32h-32v126h-288v-126h-32c-18 0 -32 14 -32 32v159c0 18 14 31 32 31h32v48h288v-48h32zM80 0v224h256v-224h-256z" /> - <glyph glyph-name="ion-ios7-pulse-strong" unicode="" horiz-adv-x="480" + <glyph glyph-name="ion-ios-printer" unicode="" horiz-adv-x="416" +d="M80 0v224h256v-224h-256zM80 -0v224h256v-224h-256zM64 352v32h288v-32h-288zM385 336c18 0 31 -14 31 -31v-158c0 -17 -13 -34 -31 -34h-33v126h-288v-126h-31c-18 0 -33 17 -33 34v158c0 17 15 31 33 31h352z" /> + <glyph glyph-name="ion-ios-pulse-strong" unicode="" horiz-adv-x="480" d="M432 175c27 0 48 -20 48 -47s-21 -49 -48 -49c-21 0 -38 13 -45 31h-51c-7 0 -13 4 -15 11l-16 47l-50 -173c-2 -7 -8 -11 -15 -11h-1c-7 0 -14 5 -15 12l-51 308l-45 -182c-2 -7 -9 -12 -16 -12h-112v32h99l61 245c2 7 8 13 16 13s15 -7 16 -14l52 -314l45 155 c2 7 8 11 15 11v0c7 0 13 -4 15 -11l29 -85h38c6 19 25 33 46 33z" /> - <glyph glyph-name="ion-ios7-pulse" unicode="" + <glyph glyph-name="ion-ios-pulse" unicode="" d="M416 160c18 0 32 -14 32 -32s-14 -32 -32 -32c-15 0 -27 10 -31 23h-65c-3 0 -7 2 -8 5l-23 72l-57 -198c-1 -3 -4 -6 -8 -6v0c-4 0 -7 3 -8 7l-58 346l-54 -220c-1 -4 -4 -6 -8 -6h-96v16h90l62 251c1 4 4 6 8 6s7 -3 8 -7l58 -349l54 190c1 3 4 5 8 5s7 -2 8 -5l30 -91 h59c3 14 16 25 31 25z" /> - <glyph glyph-name="ion-ios7-rainy-outline" unicode="" horiz-adv-x="288" + <glyph glyph-name="ion-ios-rainy-outline" unicode="" horiz-adv-x="288" d="M220 269c38 0 68 -33 68 -71c0 -29 -19 -56 -45 -66l-55 -80c-2 -2 -5 -4 -8 -4c-5 0 -8 3 -8 8c0 2 1 4 2 6l46 66v0h-35l-31 -44c-2 -2 -4 -4 -7 -4c-5 0 -9 3 -9 8c0 2 1 3 2 5l25 35h-37l-53 -76c-2 -2 -4 -4 -7 -4c-5 0 -9 3 -9 8c0 2 2 4 3 6l46 66h-36l-32 -44 c-2 -2 -4 -4 -7 -4c-5 0 -8 3 -8 8c0 2 1 4 2 6l25 34c-29 2 -52 27 -52 56c0 28 22 58 50 60c0 3 -1 5 -1 8c0 46 31 84 82 84c45 0 73 -31 81 -68c3 0 5 1 8 1zM220 146c28 0 52 24 52 52s-24 54 -52 54h-6l-15 -2l-3 15c-3 14 -11 31 -23 40c-12 10 -26 14 -41 14 c-36 0 -66 -31 -66 -67v-12v-10c-6 0 -12 -2 -14 -2c-20 -3 -35 -23 -35 -43c0 -10 4 -20 11 -27s16 -12 26 -12h124v0v0h42z" /> - <glyph glyph-name="ion-ios7-rainy" unicode="" horiz-adv-x="288" + <glyph glyph-name="ion-ios-rainy" unicode="" horiz-adv-x="288" d="M220 269c38 0 68 -33 68 -71c0 -29 -19 -56 -45 -66l-55 -80c-2 -2 -5 -4 -8 -4c-5 0 -8 3 -8 8c0 2 1 4 2 6l46 66v0h-35l-31 -44c-2 -2 -4 -4 -7 -4c-5 0 -9 3 -9 8c0 2 1 3 2 5l25 35h-37l-53 -76c-2 -2 -4 -4 -7 -4c-5 0 -9 3 -9 8c0 2 2 4 3 6l46 66h-36l-32 -44 c-2 -2 -4 -4 -7 -4c-5 0 -8 3 -8 8c0 2 1 4 2 6l25 34c-29 2 -52 27 -52 56c0 28 22 58 50 60c0 3 -1 5 -1 8c0 46 31 84 82 84c45 0 73 -31 81 -68c3 0 5 1 8 1z" /> - <glyph glyph-name="ion-ios7-recording-outline" unicode="" horiz-adv-x="480" + <glyph glyph-name="ion-ios-recording-outline" unicode="" horiz-adv-x="480" d="M370 304c61 0 110 -50 110 -112s-49 -112 -110 -112h-260c-61 0 -110 50 -110 112s49 112 110 112s110 -50 110 -112c0 -40 -21 -75 -53 -95h146c-32 20 -53 55 -53 95c0 62 49 112 110 112zM16 192c0 -53 42 -95 94 -95s93 42 93 95s-41 95 -93 95s-94 -42 -94 -95z M370 97c52 0 94 42 94 95s-42 95 -94 95s-93 -42 -93 -95s41 -95 93 -95zM368 240c-26 0 -48 -22 -48 -48s22 -48 48 -48s48 22 48 48s-22 48 -48 48zM368 256v0c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM112 240c-26 0 -48 -22 -48 -48 s22 -48 48 -48s48 22 48 48s-22 48 -48 48zM112 256v0c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64z" /> - <glyph glyph-name="ion-ios7-recording" unicode="" horiz-adv-x="480" + <glyph glyph-name="ion-ios-recording" unicode="" horiz-adv-x="480" d="M370 304c61 0 110 -50 110 -112s-49 -112 -110 -112h-260c-61 0 -110 50 -110 112s49 112 110 112s110 -50 110 -112c0 -40 -21 -76 -53 -95h146c-32 19 -53 55 -53 95c0 62 49 112 110 112zM112 128c35 0 64 29 64 64s-29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64z M368 128c35 0 64 29 64 64s-29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64zM368 240c26 0 48 -22 48 -48s-22 -48 -48 -48s-48 22 -48 48s22 48 48 48zM112 240c26 0 48 -22 48 -48s-22 -48 -48 -48s-48 22 -48 48s22 48 48 48z" /> - <glyph glyph-name="ion-ios7-redo-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-redo-outline" unicode="" horiz-adv-x="384" d="M0 48v32c0 17 -3 83 49 136c35 36 80 53 143 56v80l192 -128l-192 -128v80c-40 -1 -63 -9 -87 -20c-31 -14 -55 -44 -75 -77l-20 -31h-10zM208 256c-201 0 -192 -169 -192 -169c48 81 101 105 192 105v-65l148 97l-148 97v-65z" /> - <glyph glyph-name="ion-ios7-redo" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-redo" unicode="" horiz-adv-x="384" d="M0 48v32c0 17 -3 83 49 136c35 36 80 53 143 56v80l192 -128l-192 -128v80c-40 -1 -63 -9 -87 -20c-31 -14 -55 -44 -75 -77l-20 -31h-10z" /> - <glyph glyph-name="ion-ios7-refresh-empty" unicode="" horiz-adv-x="256" + <glyph glyph-name="ion-ios-refresh-empty" unicode="" horiz-adv-x="256" d="M128 64c-71 0 -128 57 -128 128s57 128 128 128v44l96 -64l-96 -56v56c-60 0 -108 -48 -108 -108s48 -108 108 -108s108 48 108 108h20c0 -71 -57 -128 -128 -128z" /> - <glyph glyph-name="ion-ios7-refresh-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-refresh-outline" unicode="" horiz-adv-x="416" d="M316 192v0h20c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128v44l96 -64l-96 -56v56c-60 0 -108 -48 -108 -108s48 -108 108 -108s108 48 108 108zM208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM208 1 c105 0 191 86 191 191s-86 191 -191 191s-191 -86 -191 -191s86 -191 191 -191z" /> - <glyph glyph-name="ion-ios7-refresh" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-refresh" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM208 64c71 0 128 57 128 128h-20c0 -60 -48 -108 -108 -108s-108 48 -108 108s48 108 108 108v-56l96 56l-96 64v-44c-71 0 -128 -57 -128 -128s57 -128 128 -128z" /> - <glyph glyph-name="ion-ios7-reload" unicode="" horiz-adv-x="512" -d="M256 384c105.9 0 191.7 -85.7002 191.9 -191.5l55 52.5l9 -9.09961l-70.3008 -67.9004l-66.5996 67.9004l9 9.09961l51.0996 -52.4004c-0.299805 98.5 -80.5 178.601 -179.1 178.601c-98.7998 0 -179.2 -80.4004 -179.2 -179.2s80.4004 -179.2 179.2 -179.2 -c78.5996 0 145.5 51 169.5 121.601l12.4004 -3.5c-25.6006 -76.1006 -97.3008 -130.9 -181.9 -130.9c-106 0 -192 86 -192 192s86 192 192 192z" /> - <glyph glyph-name="ion-ios7-reverse-camera-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-reload" unicode="" +d="M192 384c106 0 192 -86 192 -192l55 53l9 -9l-70 -68l-67 68l9 9l51 -52c0 98 -80 178 -179 178s-179 -80 -179 -179s80 -179 179 -179c79 0 146 50 170 121l12 -3c-26 -76 -97 -131 -182 -131c-106 0 -192 86 -192 192s86 192 192 192z" /> + <glyph glyph-name="ion-ios-reverse-camera-outline" unicode="" horiz-adv-x="384" d="M238 129l2 2l11 -12l-2 -2c-16 -14 -36 -21 -57 -21c-45 0 -82 36 -87 78h-30l38 50l39 -50h-31c5 -33 35 -62 71 -62c17 0 33 6 46 17zM252 249c16 -14 25 -37 27 -57h30l-38 -51l-39 51h31c-5 35 -35 64 -71 64c-17 0 -33 -6 -46 -17l-2 -2l-11 12l2 2 c16 14 36 21 57 21c22 0 44 -8 60 -23zM354 288c18 0 30 -14 30 -31v-176c0 -17 -12 -33 -30 -33h-320c-18 0 -34 16 -34 33v176c0 17 16 31 34 31h13v16h34v-16h13c32 36 43 48 55 48h88c12 0 23 -12 55 -48h62zM368 81v176c0 9 -5 15 -14 15h-62h-6s-4 1 -6 3s-6 8 -9 11 c-12 13 -21 24 -27 30c-5 5 -7 4 -7 4h-88s-1 0 -6 -4c-6 -5 -15 -14 -26 -27c-3 -4 -8 -11 -11 -14s-4 -3 -6 -3h-6h-60c-9 0 -18 -7 -18 -15v-176c0 -9 9 -17 18 -17h320c8 0 14 8 14 17z" /> - <glyph glyph-name="ion-ios7-reverse-camera" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-reverse-camera" unicode="" horiz-adv-x="384" d="M354 288c18 0 30 -14 30 -31v-176c0 -17 -12 -33 -30 -33h-320c-18 0 -34 16 -34 33v176c0 17 16 31 34 31h13v16h34v-16h13c32 36 43 48 55 48h88c12 0 23 -12 55 -48h62zM249 117l2 2l-11 12l-2 -2c-13 -11 -29 -17 -46 -17c-36 0 -66 29 -71 62h31l-39 50l-38 -50h30 c5 -42 42 -78 87 -78c21 0 41 7 57 21zM271 141l38 51h-30c-2 20 -11 43 -27 57c-16 15 -38 23 -60 23c-21 0 -41 -7 -57 -21l-2 -2l11 -12l2 2c13 11 29 17 46 17c36 0 66 -29 71 -64h-31z" /> - <glyph glyph-name="ion-ios7-rewind-outline" unicode="" + <glyph glyph-name="ion-ios-rewind-outline" unicode="" d="M432 293l-184 -101l184 -101v202zM208 292v0l-176 -100l176 -100v95v27v78zM224 320v0v-123l224 123v-256l-224 123v-123l-224 128z" /> - <glyph glyph-name="ion-ios7-rewind" unicode="" + <glyph glyph-name="ion-ios-rewind" unicode="" d="M224 320v0v-123l224 123v-256l-224 123v-123l-224 128z" /> - <glyph glyph-name="ion-ios7-search-strong" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-rose-outline" unicode="" horiz-adv-x="320" +d="M284 295c-4 -1 -9 -3 -13 -4c-37 -11 -71 -24 -103 -39c-17 -8 -24 -12 -44 -24l-7 -4c-31 -18 -50 -33 -63 -51c-15 -21 -22 -45 -22 -77c0 -16 3 -30 9 -44c6 -13 14 -26 25 -36c23 -21 55 -32 94 -32s71 11 94 32c11 10 19 23 25 36c6 14 9 28 9 44c0 20 -5 40 -11 60 +c-11 40 -23 83 7 139zM320 320v0c-77 -96 -16 -151 -16 -224s-56 -128 -144 -128s-144 55 -144 128s35 109 93 142c25 14 33 19 52 28c30 14 65 28 105 40c17 5 35 10 54 14zM38 325c14 -28 18 -57 19 -83c9 7 20 13 30 20c7 4 14 9 21 13c5 3 10 6 16 9c-5 4 -11 7 -17 11 +c-22 13 -48 23 -69 30zM0 352v0s66 -15 115 -43c15 -8 28 -18 37 -29c-12 -6 -24 -12 -36 -19c-7 -4 -14 -8 -20 -12c-25 -16 -44 -31 -57 -42c5 41 2 98 -39 145zM249 367c-8 -1 -20 -2 -35 -7c-25 -8 -47 -20 -64 -36c8 -6 15 -12 21 -18c29 12 65 26 95 34 +c-5 10 -12 20 -17 27zM256 384v0s26 -32 32 -55c-33 -8 -84 -25 -121 -42l-3 3c-9 11 -22 22 -39 32c52 60 131 62 131 62zM85 394c-6 -10 -10 -20 -14 -28c12 -4 22 -10 36 -17c4 5 9 10 14 14c-13 15 -27 25 -36 31zM80 416v0s35 -16 64 -56c-12 -9 -23 -20 -33 -31 +c-26 13 -40 21 -61 27c5 15 15 38 30 60z" /> + <glyph glyph-name="ion-ios-rose" unicode="" horiz-adv-x="320" +d="M320 320v0c-77 -96 -16 -151 -16 -224s-56 -128 -144 -128s-144 55 -144 128s35 109 93 142c25 14 33 19 52 28c30 14 65 28 105 40c17 5 35 10 54 14zM0 352v0s66 -15 115 -43c15 -8 28 -18 37 -29c-12 -6 -24 -12 -36 -19c-7 -4 -14 -8 -20 -12 +c-25 -16 -44 -31 -57 -42c5 41 2 98 -39 145zM256 384v0s26 -32 32 -55c-33 -8 -84 -25 -121 -42l-3 3c-9 11 -22 22 -39 32c52 60 131 62 131 62zM80 416v0s35 -16 64 -56c-12 -9 -23 -20 -33 -31c-26 13 -40 21 -61 27c5 15 15 38 30 60z" /> + <glyph glyph-name="ion-ios-search-strong" unicode="" horiz-adv-x="384" d="M280 150l-4 -7l108 -109l-34 -34l-108 109l-7 -5c-24 -15 -53 -25 -83 -25c-84 0 -152 69 -152 153s68 152 152 152s152 -68 152 -152c0 -30 -9 -58 -24 -82zM237 317c-23 23 -53 35 -85 35s-62 -12 -85 -35s-35 -53 -35 -85s12 -62 35 -85s53 -35 85 -35s62 12 85 35 s36 53 36 85s-13 62 -36 85z" /> - <glyph glyph-name="ion-ios7-search" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-search" unicode="" horiz-adv-x="384" d="M384 23l-23 -23l-113 113c-26 -21 -60 -33 -96 -33c-84 0 -152 68 -152 152s68 152 152 152s152 -68 152 -152c0 -36 -12 -69 -33 -95zM56 135c26 -26 60 -39 96 -39s70 14 96 40s40 60 40 96s-14 70 -40 96s-60 40 -96 40s-70 -14 -96 -40s-40 -60 -40 -96 s14 -71 40 -97z" /> - <glyph glyph-name="ion-ios7-settings-strong" unicode="" + <glyph glyph-name="ion-ios-settings-strong" unicode="" d="M0 72h283c6 14 21 24 37 24s31 -10 37 -24h91v-32h-91c-6 -14 -21 -24 -37 -24s-31 10 -37 24h-283zM0 208h91c6 14 21 24 37 24s31 -10 37 -24h283v-32h-283c-6 -14 -21 -24 -37 -24s-31 10 -37 24h-91zM0 344h283c6 14 21 24 37 24s31 -10 37 -24h91v-32h-91 c-6 -14 -21 -24 -37 -24s-31 10 -37 24h-283z" /> - <glyph glyph-name="ion-ios7-settings" unicode="" + <glyph glyph-name="ion-ios-settings" unicode="" d="M320 344c-9 0 -16 -7 -16 -16s7 -16 16 -16s16 7 16 16s-7 16 -16 16zM320 360v0c18 0 32 -14 32 -32s-14 -32 -32 -32s-32 14 -32 32s14 32 32 32zM320 72c-9 0 -16 -7 -16 -16s7 -16 16 -16s16 7 16 16s-7 16 -16 16zM320 88v0c18 0 32 -14 32 -32s-14 -32 -32 -32 s-32 14 -32 32s14 32 32 32zM128 208c-9 0 -16 -7 -16 -16s7 -16 16 -16s16 7 16 16s-7 16 -16 16zM128 224v0c18 0 32 -14 32 -32s-14 -32 -32 -32s-32 14 -32 32s14 32 32 32zM175 200h273v-16h-273c0 3 1 5 1 8s-1 5 -1 8zM80 192c0 -3 1 -5 1 -8h-81v16h81 c0 -3 -1 -5 -1 -8zM367 64h81v-16h-81c0 3 1 5 1 8s-1 5 -1 8zM272 56c0 -3 1 -5 1 -8h-273v16h273c0 -3 -1 -5 -1 -8zM367 336h81v-16h-81c0 3 1 5 1 8s-1 5 -1 8zM273 336c0 -3 -1 -5 -1 -8s1 -5 1 -8h-273v16h273z" /> - <glyph glyph-name="ion-ios7-shrink" unicode="" horiz-adv-x="364" -d="M364 18l-8 -8l-92 92l-50 -50v108h108l-50 -50zM0 366l8 8l92 -92l50 50v-108h-108l50 50z" /> - <glyph glyph-name="ion-ios7-skipbackward-outline" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-shuffle-strong" unicode="" horiz-adv-x="384" +d="M301 296c-85 0 -119 -64 -152 -126c-1 -3 -3 -5 -4 -8l-1 -1c-2 -3 -2 -5 -4 -8c-21 -38 -43 -68 -68 -83c-15 -9 -34 -18 -72 -18v32c45 0 76 18 112 84c2 3 2 6 4 9h1c1 2 3 4 4 7c34 64 76 144 180 144h15l-52 43l21 25l99 -84l-99 -82l-21 24l51 42h-14zM285 154 +l99 -82l-99 -84l-21 25l52 43h-15c-78 0 -122 45 -153 95l18 33c29 -51 64 -96 135 -96h14l-51 42zM112 216c-36 66 -67 84 -112 84v32c38 0 57 -9 72 -18c25 -15 47 -44 67 -81c-7 -11 -13 -22 -19 -33c-1 2 -2 5 -3 7h-1c-2 3 -2 6 -4 9z" /> + <glyph glyph-name="ion-ios-shuffle" unicode="" horiz-adv-x="384" +d="M298 241l-10 12l62 51h-46c-93 0 -129 -75 -164 -139c-2 -3 -3 -6 -5 -9c-20 -37 -41 -61 -65 -75c-14 -8 -33 -17 -70 -17v16c48 0 83 14 121 84c2 3 3 6 5 9c35 65 75 147 178 147h46l-62 52l10 12l86 -72zM135 228c0 -1 1 -2 1 -3c-3 -5 -6 -11 -9 -16c0 1 -1 1 -1 2 +c-2 3 -3 6 -5 9c-38 70 -73 84 -121 84v16c37 0 56 -9 70 -17c24 -14 45 -38 65 -75zM298 143l86 -71l-86 -72l-10 12l62 52h-46c-76 0 -118 45 -149 95c1 2 2 5 3 7c2 3 4 7 6 10c30 -50 67 -96 140 -96h46l-62 51z" /> + <glyph glyph-name="ion-ios-skipbackward-outline" unicode="" horiz-adv-x="320" d="M0 352h79v-142l241 142v-320l-241 142v-142h-79v320zM80 192l7 -4l217 -128v264v0l-217 -128zM16 336v-288h47v126v8v28v126h-47z" /> - <glyph glyph-name="ion-ios7-skipbackward" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-skipbackward" unicode="" horiz-adv-x="320" d="M0 352h79v-142l241 142v-320l-241 142v-142h-79v320z" /> - <glyph glyph-name="ion-ios7-skipforward-outline" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-skipforward-outline" unicode="" horiz-adv-x="320" d="M241 352h79v-320h-79v142l-241 -142v320l241 -142v142zM233 188l7 4l-7 4l-217 128v0v-264zM304 48v288h-47v-126v-28v-8v-126h47z" /> - <glyph glyph-name="ion-ios7-skipforward" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-skipforward" unicode="" horiz-adv-x="320" d="M241 352h79v-320h-79v142l-241 -142v320l241 -142v142z" /> - <glyph glyph-name="ion-ios7-snowy" unicode="" horiz-adv-x="256" + <glyph glyph-name="ion-ios-snowy" unicode="" horiz-adv-x="256" d="M252 131c4 -2 5 -7 3 -11s-7 -5 -11 -3l-29 17c-2 -8 -2 -16 0 -24c1 -4 -3 -9 -7 -10s-8 2 -9 6c-2 12 -3 24 1 36l-64 36v-73c11 -3 22 -8 31 -16c3 -3 4 -8 1 -11s-8 -4 -11 -1c-6 5 -13 10 -21 12v-33c0 -4 -4 -8 -8 -8s-8 4 -8 8v33c-8 -2 -15 -7 -21 -12 c-3 -3 -8 -2 -11 1s-3 8 0 11c9 8 20 13 32 16v73l-65 -36c4 -12 4 -23 2 -35c-1 -4 -5 -8 -9 -7s-8 6 -7 10c2 8 2 16 0 24l-29 -17c-4 -2 -9 -1 -11 3s-1 9 3 11l29 16c-6 6 -13 10 -21 13c-4 1 -6 6 -5 10c2 4 6 6 10 5c12 -4 22 -11 30 -19l65 36l-65 37 c-8 -9 -18 -15 -30 -19c-4 -1 -9 0 -10 4s1 10 5 11c8 3 15 6 21 12l-29 16c-4 2 -5 7 -3 11s7 5 11 3l29 -16c2 8 2 15 0 23c-1 4 3 9 7 10s8 -2 9 -6c2 -12 1 -25 -2 -36l65 -36v73c-12 3 -23 8 -32 16c-3 3 -3 8 0 11s8 4 11 1c6 -5 13 -10 21 -12v33c0 4 4 8 8 8 s8 -4 8 -8v-33c8 2 15 7 21 12c3 3 8 2 11 -1s2 -8 -1 -11c-9 -8 -20 -13 -31 -16v-73l64 36c-3 11 -4 24 -2 36c1 4 6 7 10 6s7 -6 6 -10c-2 -8 -1 -15 1 -23l29 16c4 2 9 1 11 -3s1 -9 -3 -11l-29 -16c6 -6 13 -10 21 -13c4 -1 6 -6 5 -10s-6 -6 -10 -5 c-12 4 -23 10 -31 19l-64 -36l64 -36c8 8 19 15 31 19c4 1 9 -1 10 -5s-1 -9 -5 -10c-8 -3 -15 -7 -21 -13z" /> - <glyph glyph-name="ion-ios7-speedometer-outline" unicode="" -d="M448 163v0v0c0 -63 -27 -120 -70 -160l-2 -3l-37 37l11 11l26 -25c16 17 28 36 38 57c10 23 17 47 18 72h-32v16h32c-1 26 -6 51 -16 75c-9 22 -22 42 -38 59l-28 -28l-6 6l-5 5v0h-1l28 28c-18 17 -38 30 -61 40s-48 14 -73 15v-37h-16v37c-25 -1 -50 -5 -73 -15 -s-43 -23 -61 -40l27 -28v0v0l-5 -5l-6 -6l-28 28c-16 -17 -29 -37 -38 -59c-10 -24 -15 -49 -16 -75h32v-16h-32c1 -25 8 -49 18 -72c9 -21 22 -40 38 -57l25 25l12 -11l-37 -37v1c-44 40 -72 97 -72 161v1v0c0 122 100 221 224 221v0v0h1c124 0 223 -99 223 -221zM208 193 -l110 68l10 -11l-82 -94l-1 -1c-5 -6 -13 -10 -21 -10c-15 0 -27 11 -27 26c0 8 4 15 9 20z" /> - <glyph glyph-name="ion-ios7-speedometer" unicode="" -d="M224 384c124 0 224 -99 224 -221c0 -64 -28 -122 -72 -163h-304c-44 41 -72 99 -72 163c0 122 100 221 224 221zM246 156l82 94l-10 11l-110 -68l-2 -2c-5 -5 -9 -12 -9 -20c0 -15 12 -26 27 -26c8 0 16 4 21 10zM372 18c35 35 60 87 60 145v0v1c0 84 -52 157 -125 188 -c-25 11 -54 16 -83 16v0v0v0c-29 0 -57 -5 -82 -16c-72 -30 -126 -104 -126 -188v0v-1c0 -50 21 -109 62 -146l1 -1l15 15l19 19l-11 10l-23 -23c-15 16 -23 31 -32 50c-10 21 -15 43 -16 67h29v15h-29c0 23 5 47 15 69c9 20 20 38 35 54l26 -26l5 5l5 5v0v0l-25 26 -c17 16 36 28 57 37c22 9 44 13 68 14v-35h14v35c24 -1 46 -5 68 -14c21 -9 40 -21 57 -37l-26 -26h1v0l5 -5l5 -5l26 26c15 -16 26 -34 35 -54c10 -22 14 -46 15 -69h-29v-15h29c-1 -24 -6 -46 -16 -67c-9 -19 -17 -34 -32 -50l-23 24l-11 -11l19 -19l15 -15z" /> - <glyph glyph-name="ion-ios7-star-half" unicode="" + <glyph glyph-name="ion-ios-speedometer-outline" unicode="" +d="M224 384c124 0 224 -100 224 -224c0 -57 -21 -108 -56 -148c-4 -4 -7 -8 -11 -12l-10 10l-1 2c-19 18 -41 33 -65 43c-26 11 -53 16 -81 16s-55 -5 -81 -16c-24 -10 -46 -25 -65 -43l-1 -2l-10 -10c-4 4 -7 8 -11 12c-35 40 -56 91 -56 148c0 124 100 224 224 224z +M416 79c10 23 15 48 16 73h-32v16h32c-1 25 -6 50 -16 73c-9 22 -23 42 -39 60l-27 -27l-6 6l-5 5v0h-1l27 27c-18 17 -38 31 -60 40c-23 10 -48 15 -74 16v-38h-16v38c-25 -1 -49 -6 -72 -16c-22 -10 -43 -23 -61 -40l27 -27v0v0l-6 -6l-5 -5l-27 27 +c-16 -18 -30 -38 -39 -60c-10 -23 -15 -49 -16 -74h32v-16h-32c1 -25 6 -49 16 -72c9 -20 20 -39 35 -56c40 40 96 64 157 64s117 -24 157 -64c15 17 26 36 35 56zM336 273l2 -1l-75 -84c6 -8 9 -18 9 -28c0 -26 -22 -48 -48 -48c-10 0 -19 4 -27 9l-13 -12l-11 11l12 12 +c-6 8 -9 18 -9 28c0 26 22 48 48 48c10 0 19 -3 27 -8zM224 128c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32z" /> + <glyph glyph-name="ion-ios-speedometer" unicode="" +d="M385 169v-15h30c-1 -22 -6 -44 -15 -65c-8 -18 -19 -35 -32 -50c-39 37 -90 58 -144 58s-105 -21 -144 -58c-13 15 -24 32 -32 50c-9 21 -14 43 -15 65h28h1v16h-29c1 23 6 45 15 66c9 20 20 38 35 54l25 -24l10 10l1 1v0v0l-25 25c16 15 36 26 56 35c21 9 43 14 66 15 +v-34h14h1v34c23 -1 46 -6 67 -15s39 -20 55 -35l-24 -25l11 -11l25 25c15 -16 26 -35 35 -55c9 -21 14 -43 15 -66h-30v-1zM272 160c0 10 -3 20 -9 28l63 76l-2 1l-73 -65c-8 5 -17 8 -27 8c-26 0 -48 -22 -48 -48c0 -10 3 -20 9 -28l-12 -12l11 -11l13 12c8 -5 17 -9 27 -9 +c26 0 48 22 48 48zM224 384c124 0 224 -100 224 -224c0 -57 -21 -108 -56 -148c-4 -4 -7 -8 -11 -12h-23c-32 39 -80 64 -134 64s-102 -25 -134 -64h-23c-4 4 -7 8 -11 12c-35 40 -56 91 -56 148c0 124 100 224 224 224zM379 27c34 37 52 86 52 136c0 55 -22 106 -61 145 +s-91 60 -146 60s-107 -21 -146 -60s-61 -90 -61 -145c0 -50 18 -99 52 -136l10 -10l1 -1v1l9 9l1 1v0c17 17 38 30 60 39c24 10 48 15 74 15s50 -5 74 -15c22 -9 43 -22 60 -39v0l1 -1l9 -9v-1l1 1zM192 160c0 21 11 32 32 32s32 -11 32 -32s-11 -32 -32 -32s-32 11 -32 32z +" /> + <glyph glyph-name="ion-ios-star-half" unicode="" d="M140 143l-140 98h171l53 159l53 -159h171l-140 -98l54 -159l-138 99l-138 -99zM224 347v-244l107 -76l-43 122l108 75h-131z" /> - <glyph glyph-name="ion-ios7-star-outline" unicode="" + <glyph glyph-name="ion-ios-star-outline" unicode="" d="M448 241l-140 -98l54 -159l-138 99l-138 -99l54 159l-140 98h171l53 159l53 -159h171zM331 27l-43 122l108 75h-131l-41 123l-41 -123h-131l108 -75l-43 -122l107 76z" /> - <glyph glyph-name="ion-ios7-star" unicode="" + <glyph glyph-name="ion-ios-star" unicode="" d="M448 241l-140 -98l54 -159l-138 99l-138 -99l54 159l-140 98h171l53 159l53 -159h171z" /> - <glyph glyph-name="ion-ios7-stopwatch-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-stopwatch-outline" unicode="" horiz-adv-x="384" d="M334 301c32 -35 50 -80 50 -128c0 -104 -86 -189 -192 -189s-192 85 -192 189c0 48 18 94 51 129l1 1h-18l-8 -8l-23 23l41 40l23 -22l-9 -9v-18c31 30 72 50 116 53h2v38h32v-38c43 -4 82 -21 113 -49l5 -5v19l-9 9l23 22l41 -40l-22 -23l-9 8h-18zM192 2 c96 0 173 77 173 171s-77 171 -173 171c-95 0 -173 -77 -173 -171s77 -171 173 -171zM200 191c14 -4 24 -17 24 -31c0 -15 -10 -26 -24 -30l-8 -18v0l-8 18c-14 4 -24 15 -24 30c0 14 12 27 24 31v129h16v-129z" /> - <glyph glyph-name="ion-ios7-stopwatch" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-stopwatch" unicode="" horiz-adv-x="384" d="M334 301c32 -35 50 -80 50 -128c0 -104 -86 -189 -192 -189s-192 85 -192 189c0 48 18 94 51 129l1 1h-18l-8 -8l-23 23l41 40l23 -22l-9 -9v-18c31 30 72 50 116 53h2v38h32v-38c43 -4 82 -21 113 -49l5 -5v19l-9 9l23 22l41 -40l-22 -23l-9 8h-18zM200 130 c14 4 24 15 24 30c0 14 -10 27 -24 31v129h-16v-129c-12 -4 -24 -17 -24 -31c0 -15 10 -26 24 -30l8 -18z" /> - <glyph glyph-name="ion-ios7-sunny-outline" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-sunny-outline" unicode="" horiz-adv-x="320" d="M151 296v56h18v-56h-18zM151 32v60h18v-60h-18zM264 183v18h56v-18h-56zM0 183v18h60v-18h-60zM240 130l34 -34l-12 -12l-33 34zM64 306l34 -33l-12 -12l-34 34zM229 272l33 34l12 -12l-34 -33zM52 96l34 34l11 -12l-33 -34zM160 116c-42 0 -76 34 -76 76s34 76 76 76 s76 -34 76 -76s-34 -76 -76 -76zM160 251c-32 0 -59 -27 -59 -59s27 -59 59 -59s59 27 59 59s-27 59 -59 59z" /> - <glyph glyph-name="ion-ios7-sunny" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-sunny" unicode="" horiz-adv-x="320" d="M151 296v56h18v-56h-18zM151 32v60h18v-60h-18zM264 183v18h56v-18h-56zM0 183v18h60v-18h-60zM240 130l34 -34l-12 -12l-33 34zM64 306l34 -33l-12 -12l-34 34zM229 272l33 34l12 -12l-34 -33zM52 96l34 34l11 -12l-33 -34zM160 116c-42 0 -76 34 -76 76s34 76 76 76 s76 -34 76 -76s-34 -76 -76 -76z" /> - <glyph glyph-name="ion-ios7-telephone-outline" unicode="" horiz-adv-x="352" + <glyph glyph-name="ion-ios-telephone-outline" unicode="" horiz-adv-x="352" d="M336 112c16 -16 26 -35 0 -66c-25 -30 -42 -30 -64 -30c-24 0 -58 14 -93 40c-32 23 -46 34 -78 67c-34 35 -55 64 -79 107c-27 50 -24 74 -18 92c4 12 14 24 28 33l1 1c6 4 18 12 32 12c13 0 24 -6 34 -18l1 -1c11 -14 24 -31 32 -47c10 -21 10 -38 -1 -53 c-9 -12 -12 -19 -12 -23s5 -9 13 -18l1 -1c16 -18 20 -23 26 -29c1 -1 3 -2 4 -3l2 -2c7 -7 11 -12 29 -28l1 -1c7 -6 9 -8 12 -8c5 0 16 7 29 15c4 3 11 5 17 5c27 0 68 -29 83 -44zM324 57c19 22 13 31 1 43c-13 14 -50 39 -72 39c-3 0 -6 -1 -8 -2 c-19 -12 -28 -18 -37 -18s-15 6 -23 13h-1c-19 16 -23 21 -30 29l-2 2c-1 1 -3 2 -4 3c-6 6 -11 12 -27 30v1c-10 11 -17 18 -18 28s5 20 16 34c15 20 -5 48 -31 79l-1 1c-7 8 -14 12 -22 12c-10 0 -18 -6 -23 -9c-1 0 -2 -1 -2 -1c-11 -7 -18 -16 -21 -24 c-5 -16 -7 -35 17 -79c23 -42 43 -70 76 -104c31 -32 45 -42 76 -64c32 -23 64 -38 84 -38c21 0 32 1 52 25z" /> - <glyph glyph-name="ion-ios7-telephone" unicode="" horiz-adv-x="352" + <glyph glyph-name="ion-ios-telephone" unicode="" horiz-adv-x="352" d="M336 112c16 -16 26 -35 0 -66c-25 -30 -42 -30 -64 -30c-24 0 -58 14 -93 40c-32 23 -46 34 -78 67c-34 35 -55 64 -79 107c-27 50 -24 74 -18 92c4 12 14 24 28 33l1 1c6 4 18 12 32 12c13 0 24 -6 34 -18l1 -1c11 -14 24 -31 32 -47c10 -21 10 -38 -1 -53 c-9 -12 -12 -19 -12 -23s5 -9 13 -18l1 -1c16 -18 20 -23 26 -29c1 -1 3 -2 4 -3l2 -2c7 -7 11 -12 29 -28l1 -1c7 -6 9 -8 12 -8c5 0 16 7 29 15c4 3 11 5 17 5c27 0 68 -29 83 -44z" /> - <glyph glyph-name="ion-ios7-tennisball-outline" unicode="" -d="M378 355c43 -41 70 -99 70 -163s-27 -122 -70 -163c-4 -4 -8 -8 -12 -11c-39 -31 -88 -50 -142 -50c-55 0 -105 19 -144 52c-4 3 -8 7 -12 11c-42 41 -68 98 -68 161s26 120 68 161c4 4 8 8 12 11c39 33 89 52 144 52c54 0 103 -19 142 -50c4 -3 8 -7 12 -11zM77 45l3 -3 -l3 3c19 19 35 41 45 66c11 26 16 53 16 81s-5 55 -16 81c-10 25 -26 47 -45 66l-3 3l-3 -3c-19 -19 -35 -41 -45 -66c-11 -26 -16 -53 -16 -81s5 -55 16 -81c10 -25 26 -47 45 -66zM305 0c17 7 33 17 48 29c-43 41 -70 99 -70 163s27 122 70 163c-15 12 -31 22 -48 29 -c-26 11 -53 16 -81 16s-55 -5 -81 -16c-19 -8 -36 -18 -51 -31c42 -41 68 -98 68 -161s-26 -120 -68 -161c15 -13 32 -23 51 -31c26 -11 53 -16 81 -16s55 5 81 16zM371 45c19 19 35 41 45 66c11 26 16 53 16 81s-5 55 -16 81c-10 25 -26 47 -45 66l-5 5c-2 -2 -4 -3 -6 -5 -c-19 -19 -35 -41 -45 -66c-11 -26 -16 -53 -16 -81s5 -55 16 -81c10 -25 26 -47 45 -66c2 -2 4 -3 6 -5z" /> - <glyph glyph-name="ion-ios7-tennisball" unicode="" -d="M283 192c0 -64 27 -122 70 -163c4 -4 9 -8 13 -11c-39 -31 -88 -50 -142 -50c-55 0 -105 19 -144 52c4 3 8 7 12 11c42 41 68 98 68 161s-26 120 -68 161c-4 4 -8 8 -12 11c39 33 89 52 144 52c54 0 103 -19 142 -50c-4 -3 -9 -7 -13 -11c-43 -41 -70 -99 -70 -163z -M448 192c0 -64 -27 -122 -70 -163c-4 3 -8 7 -12 11c-2 2 -4 3 -6 5c-19 19 -35 41 -45 66c-11 26 -16 53 -16 81s5 55 16 81c10 25 26 47 45 66c2 2 4 3 6 5c4 4 8 8 12 11c43 -41 70 -99 70 -163zM83 45l-3 -3c-4 -4 -8 -8 -12 -11c-42 41 -68 98 -68 161s26 120 68 161 -c4 -3 8 -7 12 -11l3 -3c19 -19 35 -41 45 -66c11 -26 16 -53 16 -81s-5 -55 -16 -81c-10 -25 -26 -47 -45 -66zM68 353v0v0v0zM80 20v0v0v0zM68 31v0v0zM80 364v0v0zM378 29v0v0v0zM366 18v0v0zM378 355v0v0zM366 366v0v0v0z" /> - <glyph glyph-name="ion-ios7-thunderstorm-outline" unicode="" horiz-adv-x="274" + <glyph glyph-name="ion-ios-tennisball-outline" unicode="" horiz-adv-x="416" +d="M416 192v-8v0c0 -5 0 -11 -1 -16v0c-11 -97 -90 -174 -187 -183v0h-4h-2s-1 -1 -2 -1h-3h-1h-8c-115 0 -208 93 -208 208s93 208 208 208s208 -93 208 -208zM399 192c0 105 -86 191 -191 191c-3 0 -5 -1 -8 -1c1 -24 6 -46 15 -68c10 -26 26 -49 46 -69s43 -36 69 -46 +c22 -9 44 -14 68 -15c0 3 1 5 1 8zM17 192c0 -105 86 -191 191 -191h4c-1 22 -7 45 -15 66c-10 26 -26 48 -46 68s-42 36 -68 46c-21 8 -44 14 -66 15v-4zM228 2c88 9 158 78 169 166c-54 3 -106 25 -147 66s-63 93 -66 147c-88 -11 -157 -81 -166 -169 +c53 -3 105 -25 145 -65s62 -92 65 -145z" /> + <glyph glyph-name="ion-ios-tennisball" unicode="" horiz-adv-x="416" +d="M0 196v0v0v0zM212 -16h1h-1v0zM208 400c115 0 208 -93 208 -208c0 -8 0 -16 -1 -24v0v0c-11 -97 -90 -174 -187 -183v0v0c-6 -1 -13 -1 -20 -1c-115 0 -208 93 -208 208v4v0v0c0 6 0 11 1 16v0v0c9 97 86 176 183 187v0v0c6 1 11 1 16 1v0v0h8zM83 181 +c26 -10 48 -26 68 -46s36 -42 46 -68c8 -21 14 -44 15 -66c5 0 11 0 16 1c-3 53 -25 105 -65 145s-92 62 -145 65c-1 -5 -1 -11 -1 -16c22 -1 45 -7 66 -15zM250 234c41 -41 93 -63 147 -66c1 5 1 11 1 16c-24 1 -46 6 -68 15c-26 10 -49 26 -69 46s-36 43 -46 69 +c-9 22 -14 44 -15 68c-5 0 -11 0 -16 -1c3 -54 25 -106 66 -147z" /> + <glyph glyph-name="ion-ios-thunderstorm-outline" unicode="" horiz-adv-x="274" d="M193 176l-88 -128l29 96h-52l15 80h72l-16 -48h40zM209 275c36 0 65 -29 65 -65s-29 -66 -65 -66h-8v17h8c27 0 49 22 49 49s-22 50 -49 50h-6l-14 -2l-3 14c-3 14 -11 26 -22 35s-25 13 -39 13c-34 0 -63 -27 -63 -62v-12s1 -9 1 -9c-5 0 -12 -2 -14 -2 c-19 -3 -33 -18 -33 -37c0 -10 3 -19 10 -26s16 -11 26 -11h11v-17h-11c-28 0 -52 24 -52 53c0 27 21 51 47 53v8c0 43 35 78 78 78c37 0 68 -26 76 -61h8z" /> - <glyph glyph-name="ion-ios7-thunderstorm" unicode="" horiz-adv-x="274" + <glyph glyph-name="ion-ios-thunderstorm" unicode="" horiz-adv-x="274" d="M153 176h40l-22 -32l-66 -96l29 96h-52l15 80h72zM84 240h107l-16 -48h18h30l-33 -48h19c36 0 65 30 65 66s-29 65 -65 65h-8c-8 35 -39 61 -76 61c-43 0 -78 -35 -78 -78v-8c-26 -2 -47 -26 -47 -53c0 -29 24 -53 52 -53h14z" /> - <glyph glyph-name="ion-ios7-time-outline" unicode="" + <glyph glyph-name="ion-ios-time-outline" unicode="" d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM371 45c19 19 35 41 45 66c11 26 16 53 16 81s-5 55 -16 81c-10 25 -26 47 -45 66s-41 35 -66 45c-26 11 -53 16 -81 16s-55 -5 -81 -16c-25 -10 -47 -26 -66 -45 s-35 -41 -45 -66c-11 -26 -16 -53 -16 -81s5 -55 16 -81c10 -25 26 -47 45 -66s41 -35 66 -45c26 -11 53 -16 81 -16s55 5 81 16c25 10 47 26 66 45zM216 368c0 5 3 8 8 8s8 -3 8 -8s-3 -8 -8 -8s-8 3 -8 8zM216 16c0 5 3 8 8 8s8 -3 8 -8s-3 -8 -8 -8s-8 3 -8 8zM392 192 c0 5 3 8 8 8s8 -3 8 -8s-3 -8 -8 -8s-8 3 -8 8zM40 192c0 5 3 8 8 8s8 -3 8 -8s-3 -8 -8 -8s-8 3 -8 8zM128 344c0 5 3 8 8 8s8 -3 8 -8s-3 -8 -8 -8s-8 3 -8 8zM304 40c0 5 3 8 8 8s8 -3 8 -8s-3 -8 -8 -8s-8 3 -8 8zM368 280c0 5 3 8 8 8s8 -3 8 -8s-3 -8 -8 -8s-8 3 -8 8 zM64 104c0 5 3 8 8 8s8 -3 8 -8s-3 -8 -8 -8s-8 3 -8 8zM64 280c0 5 3 8 8 8s8 -3 8 -8s-3 -8 -8 -8s-8 3 -8 8zM368 104c0 5 3 8 8 8s8 -3 8 -8s-3 -8 -8 -8s-8 3 -8 8zM304 344c0 5 3 8 8 8s8 -3 8 -8s-3 -8 -8 -8s-8 3 -8 8zM128 40c0 5 3 8 8 8s8 -3 8 -8s-3 -8 -8 -8 s-8 3 -8 8zM238 200c4 -8 2 -18 -6 -22v-122c0 -4 -4 -8 -8 -8s-8 4 -8 8v122c-2 1 -4 4 -6 6c-3 5 -3 11 0 16l-37 63c-2 4 -1 9 3 11s8 1 10 -3l38 -63c5 0 11 -3 14 -8z" /> - <glyph glyph-name="ion-ios7-time" unicode="" + <glyph glyph-name="ion-ios-time" unicode="" d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM224 376c-4 0 -8 -4 -8 -8s4 -8 8 -8s8 4 8 8s-4 8 -8 8zM48 184c4 0 8 4 8 8s-4 8 -8 8s-8 -4 -8 -8s4 -8 8 -8zM76 97c4 2 4 7 2 11s-6 5 -10 3s-5 -7 -3 -11s7 -5 11 -3z M78 276c2 4 2 9 -2 11s-9 1 -11 -3s-1 -9 3 -11s8 -1 10 3zM132 351c-4 -2 -5 -7 -3 -11s7 -4 11 -2s5 6 3 10s-7 5 -11 3zM143 36c2 4 1 8 -3 10s-9 2 -11 -2s-1 -9 3 -11s9 -1 11 3zM224 8c4 0 8 4 8 8s-4 8 -8 8s-8 -4 -8 -8s4 -8 8 -8zM232 178c8 4 10 14 6 22 c-3 5 -9 8 -14 8l-38 64c-2 4 -7 4 -11 2s-4 -7 -2 -11l37 -63c-3 -5 -3 -11 0 -16c2 -2 4 -5 6 -6v-122c0 -4 4 -8 8 -8s8 4 8 8v122zM316 33c4 2 5 7 3 11s-7 4 -11 2s-5 -6 -3 -10s7 -5 11 -3zM319 340c2 4 1 9 -3 11s-9 1 -11 -3s-1 -8 3 -10s9 -2 11 2zM383 100 c2 4 1 9 -3 11s-8 1 -10 -3s-2 -9 2 -11s9 -1 11 3zM380 273c4 2 5 7 3 11s-7 5 -11 3s-4 -7 -2 -11s6 -5 10 -3zM400 184c4 0 8 4 8 8s-4 8 -8 8s-8 -4 -8 -8s4 -8 8 -8z" /> - <glyph glyph-name="ion-ios7-timer-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-timer-outline" unicode="" horiz-adv-x="416" d="M189 176l-1 2s-89 118 -86 120s121 -85 121 -85c1 -1 1 -2 2 -3c5 -5 8 -11 8 -18c0 -14 -11 -25 -25 -25c-8 0 -14 3 -19 9zM208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208c0 57 23 109 61 147l12 -12c-35 -35 -56 -82 -56 -135 c0 -106 85 -191 191 -191s191 85 191 191c0 100 -77 183 -175 191v-95h-16v112v0v0z" /> - <glyph glyph-name="ion-ios7-timer" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-timer" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208s-208 93 -208 208s93 208 208 208zM102 298c-2 -2 86 -120 86 -120l1 -1c5 -6 11 -10 19 -10c14 0 25 11 25 25c0 7 -3 13 -8 18l-3 3c0 0 -117 87 -120 85zM208 1c106 0 192 85 192 191s-86 192 -192 192v-96h16v78 c88 -9 158 -84 158 -174c0 -96 -78 -174 -174 -174s-175 78 -175 174c0 48 19 92 51 124l-11 12c-35 -35 -56 -83 -56 -136c0 -106 85 -191 191 -191z" /> - <glyph glyph-name="ion-ios7-toggle-outline" unicode="" + <glyph glyph-name="ion-ios-toggle-outline" unicode="" d="M96 128c-26 0 -48 -22 -48 -48s22 -48 48 -48s48 22 48 48s-22 48 -48 48zM96 144v0c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM351 160v0h-255c-44 0 -80 -36 -80 -80s36 -80 80 -80h256c44 0 80 36 80 80s-37 80 -81 80zM352 176v0 c53 0 96 -43 96 -96s-43 -96 -96 -96h-256c-53 0 -96 43 -96 96s43 96 96 96h256zM352 352c-26 0 -48 -22 -48 -48s22 -48 48 -48s48 22 48 48s-22 48 -48 48zM352 368v0c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM97 384v0c-44 0 -81 -36 -81 -80 s36 -80 80 -80h256c44 0 80 36 80 80s-36 80 -80 80h-255zM96 400v0h256c53 0 96 -43 96 -96s-43 -96 -96 -96h-256c-53 0 -96 43 -96 96s43 96 96 96z" /> - <glyph glyph-name="ion-ios7-toggle" unicode="" + <glyph glyph-name="ion-ios-toggle" unicode="" d="M96 128c26 0 48 -22 48 -48s-22 -48 -48 -48s-48 22 -48 48s22 48 48 48zM352 176c53 0 96 -43 96 -96s-43 -96 -96 -96h-256c-53 0 -96 43 -96 96s43 96 96 96h256zM96 16c35 0 64 29 64 64s-29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64zM352 256c-26 0 -48 22 -48 48 s22 48 48 48s48 -22 48 -48s-22 -48 -48 -48zM96 208c-53 0 -96 43 -96 96s43 96 96 96h256c53 0 96 -43 96 -96s-43 -96 -96 -96h-256zM352 368c-35 0 -64 -29 -64 -64s29 -64 64 -64s64 29 64 64s-29 64 -64 64z" /> - <glyph glyph-name="ion-ios7-trash-outline" unicode="" horiz-adv-x="288" + <glyph glyph-name="ion-ios-trash-outline" unicode="" horiz-adv-x="288" d="M288 335v-15h-20l-24 -291c0 -16 -13 -29 -29 -29h-141c-16 0 -29 13 -29 29l-24 291h-21v15h80v20c0 16 13 29 29 29h70c16 0 29 -13 29 -29v-20h80zM95 355v-20h98v20c0 8 -6 14 -14 14h-70c-8 0 -14 -6 -14 -14zM230 30l23 290h-217l23 -290v0v-1c0 -8 7 -14 15 -14 h141c8 0 15 6 15 14v1v0zM137 47v241h14v-241h-14zM208 288l-11 -241h-14l10 241h15zM94 288l11 -241h-14l-11 241h14z" /> - <glyph glyph-name="ion-ios7-trash" unicode="" horiz-adv-x="288" + <glyph glyph-name="ion-ios-trash" unicode="" horiz-adv-x="288" d="M208 335h80v-15h-20l-24 -291c0 -16 -13 -29 -29 -29h-141c-16 0 -29 13 -29 29l-24 291h-21v15h80v20c0 16 13 29 29 29h70c16 0 29 -13 29 -29v-20zM95 355v0v-20h98v20c0 8 -6 14 -14 14h-70c-8 0 -14 -6 -14 -14zM91 47h14l-11 241h-14zM151 47v241h-14v-241h14z M197 47l11 241h-14l-11 -241h14z" /> - <glyph glyph-name="ion-ios7-undo-outline" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-undo-outline" unicode="" horiz-adv-x="384" d="M384 80v-32h-10l-20 31c-20 33 -44 63 -75 77c-24 11 -47 19 -87 20v-80l-192 128l192 128v-80c63 -3 108 -21 143 -56c52 -53 49 -119 49 -136zM368 87c0 0 9 169 -192 169v65l-148 -97l148 -97v65c91 0 144 -24 192 -105z" /> - <glyph glyph-name="ion-ios7-undo" unicode="" horiz-adv-x="384" + <glyph glyph-name="ion-ios-undo" unicode="" horiz-adv-x="384" d="M384 80v-32h-10l-20 31c-20 33 -44 63 -75 77c-24 11 -47 19 -87 20v-80l-192 128l192 128v-80c63 -3 108 -21 143 -56c52 -53 49 -119 49 -136z" /> - <glyph glyph-name="ion-ios7-unlocked-outline" unicode="" horiz-adv-x="320" -d="M72 224h248v-240h-320v240h56v72c0 57 46 104 104 104c57 0 104 -47 104 -104v-8h-16v8c0 48 -40 88 -88 88s-88 -40 -88 -88v-72zM304 0v208h-288v-208h288zM160 160c18 0 32 -14 32 -32c0 -15 -10 -27 -24 -31v-41c0 -4 -4 -8 -8 -8s-8 4 -8 8v41c-14 4 -24 16 -24 31 -c0 18 14 32 32 32zM160 112c9 0 16 7 16 16s-7 16 -16 16s-16 -7 -16 -16s7 -16 16 -16z" /> - <glyph glyph-name="ion-ios7-unlocked" unicode="" horiz-adv-x="320" -d="M160 144c9 0 16 -7 16 -16s-7 -16 -16 -16s-16 7 -16 16s7 16 16 16zM72 224h248v-240h-320v240h56v72c0 57 46 104 104 104c57 0 104 -47 104 -104v-8h-16v8c0 48 -40 88 -88 88s-88 -40 -88 -88v-72zM168 97c14 4 24 16 24 31c0 18 -14 32 -32 32s-32 -14 -32 -32 -c0 -15 10 -27 24 -31v-41c0 -4 4 -8 8 -8s8 4 8 8v41z" /> - <glyph glyph-name="ion-ios7-upload-outline" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-unlocked-outline" unicode="" horiz-adv-x="320" +d="M160 160c18 0 32 -14 32 -32c0 -15 -10 -27 -24 -31v-33h-16v33c-14 4 -24 16 -24 31c0 18 14 32 32 32zM160 112c9 0 16 7 16 16s-7 16 -16 16s-16 -7 -16 -16s7 -16 16 -16zM72 224h248v-240h-320v240h56v72c0 57 47 104 104 104s104 -47 104 -104v-8h-16v8 +c0 49 -39 88 -88 88s-88 -39 -88 -88v-72zM304 0v208h-288v-208h288z" /> + <glyph glyph-name="ion-ios-unlocked" unicode="" horiz-adv-x="320" +d="M160 144c9 0 16 -7 16 -16s-7 -16 -16 -16s-16 7 -16 16s7 16 16 16zM72 224h248v-240h-320v240h56v72c0 57 47 104 104 104s104 -47 104 -104v-8h-16v8c0 49 -39 88 -88 88s-88 -39 -88 -88v-72zM168 97c14 4 24 16 24 31c0 18 -14 32 -32 32s-32 -14 -32 -32 +c0 -15 10 -27 24 -31v-33h16v33z" /> + <glyph glyph-name="ion-ios-upload-outline" unicode="" horiz-adv-x="320" d="M192 304h128v-304h-320v304h128v-16h-112v-272h288v272h-112v16zM97 330l-11 12l74 74l74 -74l-11 -12l-55 55v-243h-16v243z" /> - <glyph glyph-name="ion-ios7-upload" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-upload" unicode="" horiz-adv-x="320" d="M168 304h152v-304h-320v304h152v-162h16v162zM168 385v-81h-16v81l-55 -55l-11 12l74 74l74 -74l-11 -12z" /> - <glyph glyph-name="ion-ios7-videocam-outline" unicode="" horiz-adv-x="418" + <glyph glyph-name="ion-ios-videocam-outline" unicode="" horiz-adv-x="418" d="M257 320c19 0 33 -14 33 -33v-188c0 -19 -14 -35 -33 -35h-221c-19 0 -36 16 -36 35v188c0 19 17 33 36 33h221zM273 99v188c0 9 -8 16 -17 16h-221c-9 0 -18 -7 -18 -16v-188c0 -9 10 -18 19 -18h221c9 0 16 9 16 18zM320 235l98 53v-192l-98 53v86zM401 258v0l-64 -33 v-66l64 -33v132z" /> - <glyph glyph-name="ion-ios7-videocam" unicode="" horiz-adv-x="418" + <glyph glyph-name="ion-ios-videocam" unicode="" horiz-adv-x="418" d="M257 320c19 0 33 -14 33 -33v-188c0 -19 -14 -35 -33 -35h-221c-19 0 -36 16 -36 35v188c0 19 17 33 36 33h221zM320 235l98 53v-192l-98 53v86z" /> - <glyph glyph-name="ion-ios7-volume-high" unicode="" horiz-adv-x="320" + <glyph glyph-name="ion-ios-volume-high" unicode="" horiz-adv-x="320" d="M278 320c26 -36 42 -80 42 -128s-16 -92 -42 -128l-14 10c24 33 39 74 39 118s-15 85 -39 118zM224 96l-14 10c18 24 29 54 29 86s-11 62 -29 86l14 10c20 -27 32 -60 32 -96s-12 -69 -32 -96zM177 128l-13 10c12 15 18 34 18 54s-6 39 -18 54l13 10 c14 -18 22 -40 22 -64s-8 -46 -22 -64zM58 232l70 56v-192l-70 56h-58v80h58z" /> - <glyph glyph-name="ion-ios7-volume-low" unicode="" horiz-adv-x="128" + <glyph glyph-name="ion-ios-volume-low" unicode="" horiz-adv-x="128" d="M58 232l70 56v-192l-70 56h-58v80h58z" /> - <glyph glyph-name="ion-ios7-wineglass-outline" unicode="" horiz-adv-x="224" -d="M129 179c-5 -3 -9 -14 -9 -19v-160h71v-16h-160v16h73v160c0 4 -6 16 -11 19c-9 6 -22 15 -43 30c-18 13 -50 36 -50 97c0 49 29 94 29 94h166s29 -44 29 -93c0 -61 -31 -85 -50 -98c-21 -15 -35 -23 -45 -30zM40 384c-7 -13 -24 -45 -24 -78v-2h192v3 -c0 33 -17 77 -24 77h-144zM112 192c7 0 13 2 18 6c9 6 20 13 35 24c14 10 37 26 42 66h-190c2 -15 7 -28 14 -39c9 -13 20 -22 28 -27c17 -12 29 -21 37 -26c5 -3 10 -4 16 -4z" /> - <glyph glyph-name="ion-ios7-wineglass" unicode="" horiz-adv-x="224" -d="M129 179c-5 -3 -9 -14 -9 -19v-160h71v-16h-160v16h73v160c0 4 -6 16 -11 19c-9 6 -22 15 -43 30c-18 13 -50 36 -50 97c0 49 29 94 29 94h166s29 -44 29 -93c0 -61 -31 -85 -50 -98c-21 -15 -35 -23 -45 -30zM40 384c-7 -13 -24 -45 -24 -78v-2h192v3 -c0 33 -17 77 -24 77h-144z" /> - <glyph glyph-name="ion-ios7-world-outline" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-wineglass-outline" unicode="" horiz-adv-x="192" +d="M104 139v-155h72v-16h-80h-80v16h72v155c0 22 -20 39 -40 55c-8 6 -16 13 -22 19c-27 28 -26 52 -26 71v4c0 44 31 125 32 128h64h64c1 -3 32 -84 32 -128v-4c0 -19 1 -43 -26 -71c-6 -6 -14 -13 -22 -19c-20 -16 -40 -33 -40 -55zM43 400c-5 -16 -20 -63 -25 -96h156 +c-5 33 -20 80 -25 96h-53h-53zM96 175c3 0 5 0 7 2v0c9 11 20 20 31 29c8 6 15 12 20 18c22 23 22 41 22 60v4h-160v-4c0 -19 0 -37 22 -60c5 -6 12 -12 20 -18c11 -9 22 -18 31 -29v0c2 -2 4 -2 7 -2z" /> + <glyph glyph-name="ion-ios-wineglass" unicode="" horiz-adv-x="192" +d="M104 139v-155h72v-16h-80h-80v16h72v155c0 22 -20 39 -40 55c-8 6 -16 13 -22 19c-27 28 -26 52 -26 71v4c0 44 31 125 32 128h64h64c1 -3 32 -84 32 -128v-4c0 -19 1 -43 -26 -71c-6 -6 -14 -13 -22 -19c-20 -16 -40 -33 -40 -55zM43 400c-5 -16 -20 -63 -25 -96h156 +c-5 33 -20 80 -25 96h-53h-53z" /> + <glyph glyph-name="ion-ios-world-outline" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208v0v0v0c-115 0 -208 93 -208 208s93 208 208 208v0v0v0zM216 276v-76h75c-1 31 -5 60 -11 84c-21 -5 -42 -7 -64 -8zM216 292c20 1 41 3 60 8c-14 46 -38 76 -60 82v-90zM200 382c-23 -6 -45 -36 -60 -82 c19 -5 39 -7 60 -8v90zM200 276c-22 1 -44 3 -65 8c-6 -24 -10 -53 -11 -84h76v76zM108 200c1 32 4 62 11 88c-21 6 -41 15 -59 25c-26 -31 -41 -70 -43 -113h91zM108 184h-91c2 -43 17 -82 43 -113c19 10 38 19 59 25c-7 26 -10 56 -11 88zM124 184c1 -31 5 -60 11 -84 c21 5 43 8 65 9v75h-76zM200 92c-21 -1 -41 -3 -60 -8c15 -46 37 -76 60 -82v90zM216 2c22 6 46 36 60 82c-19 5 -40 7 -60 8v-90zM216 109c22 -1 43 -4 64 -9c6 24 10 53 11 84h-75v-75zM308 184c-1 -32 -5 -62 -12 -88c21 -6 41 -15 60 -25c26 31 41 70 43 113h-91z M308 200v0h91c-2 43 -17 82 -43 113c-19 -10 -38 -19 -59 -25c7 -26 10 -56 11 -88zM344 326c-25 25 -56 44 -91 52c16 -17 29 -43 39 -74c18 6 35 13 52 22zM163 378c-35 -8 -67 -27 -91 -52c16 -9 34 -15 52 -21c10 31 23 56 39 73zM72 58c25 -25 56 -44 91 -52 c-16 17 -30 43 -40 74c-18 -6 -35 -13 -51 -22zM253 6c35 8 66 27 91 52c-17 9 -34 16 -52 22c-10 -31 -23 -57 -39 -74z" /> - <glyph glyph-name="ion-ios7-world" unicode="" horiz-adv-x="416" + <glyph glyph-name="ion-ios-world" unicode="" horiz-adv-x="416" d="M208 400c115 0 208 -93 208 -208s-93 -208 -208 -208v0v0v0c-115 0 -208 93 -208 208s93 208 208 208v0v0v0zM208 1c106 0 191 85 191 191s-85 191 -191 191v0v0v0c-106 0 -191 -85 -191 -191s86 -191 191 -191v0v0v0zM274 276c6 -22 9 -48 10 -76h-68v68c20 1 39 4 58 8 zM216 366c20 -6 41 -34 54 -75c-17 -4 -36 -6 -54 -7v82zM145 291c13 42 35 69 55 75v-82c-19 1 -37 3 -55 7zM333 315c-15 -8 -31 -15 -48 -20c-9 29 -21 52 -36 67c32 -8 61 -24 84 -47zM299 200c-1 29 -4 56 -10 80c19 6 37 14 54 23c23 -28 38 -64 40 -103h-84zM132 200 c1 28 3 54 9 76c19 -5 39 -7 59 -8v-68h-68zM284 184c-1 -28 -4 -54 -10 -76c-19 5 -38 7 -58 8v68h68zM141 108c-6 22 -8 48 -9 76h68v-68c-20 -1 -40 -3 -59 -8zM200 18c-20 6 -42 33 -55 75c18 4 36 6 55 7v-82zM249 22c15 15 27 38 36 67c17 -5 33 -11 48 -19 @@ -1315,56 +1539,45 @@ c2 2 3 4 3 7s-1 5 -3 8v1c-1 2 -2 4 -2 6s1 3 2 5v1c2 3 3 5 3 8s-1 4 -3 7v1v0c-1 2 <glyph glyph-name="ion-link" unicode="" horiz-adv-x="384" d="M192 240v0v0v0zM304 288c44 0 80 -36 80 -80v-32c0 -44 -36 -80 -80 -80h-112c-33 0 -60 20 -73 48c-4 10 -7 20 -7 32v32h48v-32c0 -18 14 -32 32 -32h112c18 0 32 14 32 32v32c0 18 -14 32 -32 32v0h-16c-6 31 -32 48 -32 48h48zM266 240c4 -10 6 -21 6 -32v-32v0h-48 v0v32c0 18 -14 32 -32 32v0h-112c-18 0 -32 -14 -32 -32v-32c0 -18 14 -32 32 -32h16c6 -31 32 -48 32 -48h-48c-44 0 -80 36 -80 80v32c0 44 36 80 80 80h112c33 0 62 -20 74 -48z" /> - <glyph glyph-name="ion-load-a" unicode="" horiz-adv-x="512" -d="M192 352c0 42.6667 21.3333 64 64 64c42.6667 0 64 -21.3333 64 -64s-21.3333 -64 -64 -64c-42.6667 0 -64 21.3333 -64 64zM48 192c0 32 16 48 48 48s48 -16 48 -48s-16 -48 -48 -48s-48 16 -48 48zM360 304c0 5.33333 2.66667 8 8 8s8 -2.66667 8 -8s-2.66667 -8 -8 -8 -s-8 2.66667 -8 8zM180.1 340.4c9.9502 -10.0503 14.9253 -22.1838 14.9253 -36.4004c0 -14.2166 -4.9751 -26.3501 -14.9253 -36.4004c-9.94971 -10.0498 -21.9662 -15.0747 -36.0494 -15.0747s-26.1 5.0249 -36.0502 15.0747 -c-9.9502 10.0503 -14.9253 22.1838 -14.9253 36.4004s4.9751 26.3501 14.9253 36.4004c9.9502 10.0498 21.9669 15.0747 36.0502 15.0747c14.0833 0 26.0997 -5.0249 36.0494 -15.0747zM400 192c0 10.6667 5.33333 16 16 16s16 -5.33333 16 -16s-5.33333 -16 -16 -16 -s-16 5.33333 -16 16zM345 79c0 16 8 24 24 24s24 -8 24 -24s-8 -24 -24 -24s-24 8 -24 24zM224 32c0 21.3333 10.6667 32 32 32c21.3333 0 32 -10.6667 32 -32c0 -21.3333 -10.6667 -32 -32 -32c-21.3333 0 -32 10.6667 -32 32zM104 80c0 26.6667 13.3333 40 40 40 -c26.6667 0 40 -13.3333 40 -40s-13.3333 -40 -40 -40c-26.6667 0 -40 13.3333 -40 40z" /> - <glyph glyph-name="ion-load-b" unicode="" horiz-adv-x="512" -d="M288 288c0 -17.7002 -14.2998 -32 -32 -32v0c-17.7002 0 -32 14.2998 -32 32v96c0 17.7002 14.2998 32 32 32v0c17.7002 0 32 -14.2998 32 -32v-96zM256 128v0c17.7002 0 32 -14.2998 32 -32v-96c0 -17.7002 -14.2998 -32 -32 -32s-32 14.2998 -32 32v96 -c0 17.7002 14.2998 32 32 32zM448 224v0c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32h-96c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32h96zM160 224v0c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32h-96c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32 -h96zM346.5 237.3c-12.5 -12.5 -32.7998 -12.5 -45.2998 0v0c-12.5 12.5 -12.5 32.7998 0 45.2998l67.8994 67.9004c12.5 12.5 32.8008 12.5 45.3008 0v0c12.5 -12.5 12.5 -32.7998 0 -45.2998zM210.7 146.7v0c12.5 -12.5 12.5 -32.7002 0 -45.2998l-67.9004 -67.9004 -c-12.5 -12.5 -32.7998 -12.5 -45.2998 0s-12.5 32.7998 0 45.2998l67.9004 67.9004c12.5 12.5 32.7998 12.5 45.2998 0zM414.4 78.9004v0c12.5 -12.5 12.5 -32.8008 0 -45.3008s-32.8008 -12.5 -45.3008 0l-67.8994 67.9004c-12.5 12.5 -12.5 32.7998 0 45.2998 -s32.7998 12.5 45.2998 0zM210.7 282.5v0c12.5 -12.5 12.5 -32.7998 0 -45.2998s-32.7998 -12.5 -45.2998 0l-67.9004 67.8994c-12.5 12.5 -12.5 32.8008 0 45.3008s32.7998 12.5 45.2998 0z" /> - <glyph glyph-name="ion-load-c" unicode="" horiz-adv-x="512" -d="M479.8 221.9c0.5 -2.90039 0.100586 -6 -1.2002 -8.90039c-3.7998 -8.40039 -14.6992 -11.9004 -22.5 -6.7002c-3.69922 2.40039 -6.09961 6.40039 -6.7998 10.7002c-0.799805 4.7002 -1.59961 9.40039 -2.59961 14.0996c-4.40039 20.4004 -11.7002 40 -21.9004 58.2002 -c-12 21.4004 -27.8994 40.4004 -47 55.7998c-18.2002 14.7002 -39.2002 26 -61.5 33c-20.7002 6.5 -42.5 9.30078 -64.2002 8.90039c-1.2998 0 -2.59961 0.0996094 -3.89941 0.0996094c-3.2002 -0.299805 -6.2998 -0.299805 -9.5 -0.599609 -c-6.5 -0.5 -13 -1.5 -19.5 -2.7002c-12.7998 -2.39941 -25.4004 -6 -37.4004 -10.8994c-20.7998 -8.40039 -40 -20.3008 -56.7998 -35.1006c-16.7998 -14.7002 -31.0996 -32.0996 -42.0996 -51.3994c-12.4004 -21.6006 -20.4004 -45.3008 -24.1006 -69.9004 -c-1.7002 -11.2002 -2.39941 -22.9004 -2.09961 -34.2002c0.200195 -5.5 0.700195 -11 1.2998 -16.3994c0.700195 -6.30078 1.7002 -12.7002 3 -18.9004c5.09961 -23.9004 14.4004 -46.7998 27.9004 -67.0996c12.8994 -19.9004 29.2998 -37.5 48.1992 -51.8008 -c19.5 -14.6992 41.7002 -25.8994 65.1006 -32.7998c24.5996 -7.2998 50.7002 -9.7998 76.2998 -7.59961c25 2.2002 49.7002 8.7998 72.2998 19.7998c11.2998 5.40039 22 11.9004 32.1006 19.2998c9.89941 7.2002 18.7998 15.2998 27 24.4004 -c4.09961 4.5 8.19922 9.09961 11.7998 13.8994c3.59961 4.80078 6.89941 9.80078 10.0996 14.9004c6.2002 9.90039 11.9004 20.0996 16.7998 30.7998c3.80078 8.40039 7.80078 16.7998 11 25.5c1.60059 4.10059 3 8.2998 4.10059 12.6006 -c0.899414 3.69922 1.5 7.39941 2.2002 11.1992c0.799805 -8.59961 0.199219 -17.3994 -1.30078 -25.8994c-1 -5.40039 -2.09961 -10.9004 -3.59961 -16.2002c-1.40039 -5 -3.09961 -9.7998 -4.90039 -14.5996c-3.59961 -9.7002 -7.7998 -19.3008 -12.7998 -28.5 -c-5.7998 -10.7002 -12.7998 -20.6006 -20.5996 -30c-7.7002 -9.30078 -15.9004 -18.1006 -25.1006 -25.9004c-18.2998 -15.4004 -39.1992 -27.7002 -61.5 -36.2998c-23.1992 -8.90039 -47.7998 -13.7002 -72.5996 -14.5 -c-25.4004 -0.900391 -51.0996 2.7002 -75.2998 10.3994c-23.2002 7.40039 -45.2998 18.6006 -64.9004 33.1006c-19.2002 14.0996 -36 31.2002 -49.7998 50.5c-6.90039 9.7002 -13.0996 20 -18.4004 30.7002c-5.39941 10.8994 -9.69922 22.0996 -13.2998 33.5996 -c-5.7002 18.0996 -8.59961 37 -9.5 55.9004c-1 19.5 1 39.0996 5.2002 58.0996c5.2002 23.7998 14.7002 46.5 27.4004 67.2998c11.5 18.7002 25.7998 35.7002 42.1992 50.2998c16.4004 14.6006 34.9004 26.8008 54.8008 36.2002c23.1992 10.9004 48.3994 18 73.8994 20.5 -c9.7998 0.900391 19.7002 1.2998 29.6006 1.2002c12.6992 -0.0996094 25.1992 -1.59961 37.5996 -4.09961c24 -4.90039 47 -13.7002 68.0996 -26.1006c21.4004 -12.5 40.7002 -28.7998 56.7002 -47.7002c14.7998 -17.5996 27 -37.3994 35.9004 -58.5996 -c4.39941 -10.2998 8 -21 10.7998 -31.7998c2.2002 -8.5 3.90039 -17.1006 5.2998 -25.7998z" /> - <glyph glyph-name="ion-load-d" unicode="" horiz-adv-x="512" -d="M432 208c8.7998 0 16 -7.2002 16 -16s-7.2002 -16 -16 -16h-80c-8.7998 0 -16 7.2002 -16 16s7.2002 16 16 16h80zM176 192c0 -8.7998 -7.2002 -16 -16 -16h-80c-8.7998 0 -16 7.2002 -16 16s7.2002 16 16 16h80c8.7998 0 16 -7.2002 16 -16zM256 112 -c8.7998 0 16 -7.2002 16 -16v-80c0 -8.7998 -7.2002 -16 -16 -16s-16 7.2002 -16 16v80c0 8.7998 7.2002 16 16 16zM256 384c8.7998 0 16 -7.2002 16 -16v-80c0 -8.7998 -7.2002 -16 -16 -16s-16 7.2002 -16 16v80c0 8.7998 7.2002 16 16 16zM325.3 232 -c-4.39941 7.7002 -1.7998 17.4004 5.90039 21.9004l69.2998 40c7.7002 4.39941 17.5 1.7998 21.9004 -5.90039c4.39941 -7.7002 1.7998 -17.5 -5.90039 -21.9004l-69.2998 -40c-7.7002 -4.39941 -17.5 -1.7998 -21.9004 5.90039zM186.7 152 -c4.39941 -7.7002 1.7998 -17.4004 -5.90039 -21.9004l-69.2998 -40c-7.7002 -4.39941 -17.5 -1.7998 -21.9004 5.90039c-4.39941 7.7002 -1.7998 17.5 5.90039 21.9004l69.2998 40c7.7002 4.39941 17.5 1.7998 21.9004 -5.90039zM317.9 116.9l40 -69.3008 -c4.39941 -7.69922 1.7998 -17.5 -5.90039 -21.8994c-7.7002 -4.40039 -17.5 -1.7998 -21.9004 5.89941l-40 69.3008c-4.39941 7.69922 -1.7998 17.5 5.90039 21.8994c7.7002 4.40039 17.5 1.7998 21.9004 -5.89941zM181.9 352.4l40 -69.3008 -c4.39941 -7.69922 1.7998 -17.5 -5.90039 -21.8994c-7.7002 -4.40039 -17.5 -1.7998 -21.9004 5.89941l-40 69.3008c-4.39941 7.69922 -1.7998 17.5 5.90039 21.8994c7.7002 4.40039 17.5 1.7998 21.9004 -5.89941zM296 261.3 -c-7.7002 4.40039 -10.2998 14.2002 -5.90039 21.9004l40 69.2998c4.5 7.7002 14.2002 10.2998 21.9004 5.90039c7.7002 -4.5 10.2998 -14.2002 5.90039 -21.9004l-40 -69.2998c-4.5 -7.7002 -14.2002 -10.2998 -21.9004 -5.90039zM216 122.7 -c7.7002 -4.40039 10.2998 -14.2002 5.90039 -21.9004l-40 -69.2998c-4.5 -7.7002 -14.2002 -10.2998 -21.9004 -5.90039c-7.7002 4.5 -10.2998 14.2002 -5.90039 21.9004l40 69.2998c4.5 7.7002 14.2002 10.2998 21.9004 5.90039zM416.4 117.9 -c7.69922 -4.5 10.2998 -14.2002 5.89941 -21.9004c-4.5 -7.7002 -14.2002 -10.2998 -21.8994 -5.90039l-69.3008 40c-7.69922 4.5 -10.2998 14.2002 -5.89941 21.9004c4.5 7.7002 14.2002 10.2998 21.8994 5.90039zM95.5996 266.1 -c-7.69922 4.5 -10.2998 14.2002 -5.89941 21.9004c4.5 7.7002 14.2002 10.2998 21.8994 5.90039l69.3008 -40c7.69922 -4.5 10.3994 -14.2002 5.89941 -21.9004s-14.2002 -10.2998 -21.8994 -5.90039z" /> + <glyph glyph-name="ion-load-a" unicode="" horiz-adv-x="384" +d="M144 352c0 43 21 64 64 64s64 -21 64 -64s-21 -64 -64 -64s-64 21 -64 64zM0 192c0 32 16 48 48 48s48 -16 48 -48s-16 -48 -48 -48s-48 16 -48 48zM312 304c0 5 3 8 8 8s8 -3 8 -8s-3 -8 -8 -8s-8 3 -8 8zM132 340c10 -10 15 -22 15 -36s-5 -26 -15 -36s-22 -15 -36 -15 +s-26 5 -36 15s-15 22 -15 36s5 26 15 36s22 15 36 15s26 -5 36 -15zM352 192c0 11 5 16 16 16s16 -5 16 -16s-5 -16 -16 -16s-16 5 -16 16zM297 79c0 16 8 24 24 24s24 -8 24 -24s-8 -24 -24 -24s-24 8 -24 24zM176 32c0 21 11 32 32 32s32 -11 32 -32s-11 -32 -32 -32 +s-32 11 -32 32zM56 80c0 27 13 40 40 40s40 -13 40 -40s-13 -40 -40 -40s-40 13 -40 40z" /> + <glyph glyph-name="ion-load-b" unicode="" +d="M256 288c0 -18 -14 -32 -32 -32v0c-18 0 -32 14 -32 32v96c0 18 14 32 32 32v0c18 0 32 -14 32 -32v-96zM224 128v0c18 0 32 -14 32 -32v-96c0 -18 -14 -32 -32 -32s-32 14 -32 32v96c0 18 14 32 32 32zM416 224v0c18 0 32 -14 32 -32s-14 -32 -32 -32h-96 +c-18 0 -32 14 -32 32s14 32 32 32h96zM128 224v0c18 0 32 -14 32 -32s-14 -32 -32 -32h-96c-18 0 -32 14 -32 32s14 32 32 32h96zM314 237c-12 -12 -33 -12 -45 0v0c-12 12 -12 34 0 46l68 67c12 12 33 12 45 0v0c12 -12 12 -33 0 -45zM179 147v0c12 -12 12 -33 0 -46 +l-68 -67c-12 -12 -33 -12 -45 0s-12 33 0 45l67 68c12 12 34 12 46 0zM382 79v0c12 -12 12 -33 0 -45s-33 -12 -45 0l-68 68c-12 12 -12 33 0 45s33 12 45 0zM179 282v0c12 -12 12 -33 0 -45s-34 -12 -46 0l-67 68c-12 12 -12 33 0 45s33 12 45 0z" /> + <glyph glyph-name="ion-load-c" unicode="" +d="M448 222c0 -3 0 -6 -1 -9c-4 -8 -15 -12 -23 -7c-4 2 -6 7 -7 11c-1 5 -1 9 -2 14c-4 20 -12 40 -22 58c-12 21 -28 41 -47 56c-18 15 -40 26 -62 33c-21 6 -42 9 -64 9h-4c-3 0 -6 -1 -9 -1c-6 0 -14 -1 -20 -2c-13 -2 -25 -6 -37 -11c-21 -8 -40 -20 -57 -35 +s-31 -33 -42 -52c-12 -22 -20 -45 -24 -70c-2 -11 -2 -23 -2 -34c0 -6 0 -11 1 -16c1 -6 2 -13 3 -19c5 -24 14 -47 28 -67c13 -20 29 -38 48 -52c20 -15 42 -26 65 -33c25 -7 50 -9 76 -7c25 2 50 9 73 20c11 5 22 12 32 19s19 15 27 24c4 4 8 9 12 14s7 10 10 15 +c6 10 12 20 17 31c4 8 8 16 11 25c2 4 3 9 4 13s1 7 2 11c1 -9 1 -18 -1 -26c-1 -5 -2 -11 -4 -16c-1 -5 -3 -10 -5 -15c-4 -10 -8 -19 -13 -28c-6 -11 -12 -21 -20 -30s-16 -18 -25 -26c-18 -15 -40 -27 -62 -36c-23 -9 -48 -14 -73 -15s-51 3 -75 11c-23 7 -45 19 -65 33 +c-19 14 -36 31 -50 50c-7 10 -13 20 -18 31s-9 21 -13 33c-6 18 -9 37 -10 56c-1 20 1 39 5 58c5 24 15 47 28 68c12 19 26 35 42 50s35 27 55 36c23 11 48 19 74 21c10 1 19 1 29 1c13 0 26 -2 38 -4c24 -5 47 -14 68 -26s41 -29 57 -48c15 -18 27 -37 36 -58 +c4 -10 7 -21 10 -32c2 -8 5 -17 6 -26z" /> + <glyph glyph-name="ion-load-d" unicode="" horiz-adv-x="384" +d="M368 208c9 0 16 -7 16 -16s-7 -16 -16 -16h-80c-9 0 -16 7 -16 16s7 16 16 16h80zM112 192c0 -9 -7 -16 -16 -16h-80c-9 0 -16 7 -16 16s7 16 16 16h80c9 0 16 -7 16 -16zM192 112c9 0 16 -7 16 -16v-80c0 -9 -7 -16 -16 -16s-16 7 -16 16v80c0 9 7 16 16 16zM192 384 +c9 0 16 -7 16 -16v-80c0 -9 -7 -16 -16 -16s-16 7 -16 16v80c0 9 7 16 16 16zM261 232c-4 8 -2 18 6 22l69 40c8 4 18 2 22 -6s2 -18 -6 -22l-69 -40c-8 -4 -18 -2 -22 6zM123 152c4 -8 2 -18 -6 -22l-69 -40c-8 -4 -18 -2 -22 6s-2 18 6 22l69 40c8 4 18 2 22 -6zM254 117 +l40 -69c4 -8 2 -18 -6 -22s-18 -2 -22 6l-40 69c-4 8 -2 18 6 22s18 2 22 -6zM118 352l40 -69c4 -8 2 -18 -6 -22s-18 -2 -22 6l-40 69c-4 8 -2 18 6 22s18 2 22 -6zM232 261c-8 4 -10 14 -6 22l40 69c4 8 14 10 22 6s10 -14 6 -22l-40 -69c-4 -8 -14 -10 -22 -6zM152 123 +c8 -4 10 -14 6 -22l-40 -69c-4 -8 -14 -10 -22 -6s-10 14 -6 22l40 69c4 8 14 10 22 6zM352 118c8 -4 10 -14 6 -22s-14 -10 -22 -6l-69 40c-8 4 -10 14 -6 22s14 10 22 6zM32 266c-8 4 -10 14 -6 22s14 10 22 6l69 -40c8 -4 10 -14 6 -22s-14 -10 -22 -6z" /> <glyph glyph-name="ion-location" unicode="" horiz-adv-x="239" d="M119 384c66 0 120 -54 120 -120c0 -115 -120 -264 -120 -264s-119 149 -119 264c0 66 53 120 119 120zM119 206c31 0 57 25 57 56s-26 57 -57 57s-56 -26 -56 -57s25 -56 56 -56z" /> + <glyph glyph-name="ion-lock-combination" unicode="" horiz-adv-x="384" +d="M320 271c39 -35 64 -86 64 -143c0 -106 -86 -192 -192 -192s-192 86 -192 192c0 57 25 108 64 143v49c0 71 57 128 128 128s128 -57 128 -128v-49zM96 320v-26c28 16 61 26 96 26s68 -10 96 -26v26c0 53 -43 96 -96 96s-96 -43 -96 -96zM192 -32c88 0 160 72 160 160 +s-72 160 -160 160s-160 -72 -160 -160s72 -160 160 -160zM192 272c80 0 144 -64 144 -144s-64 -144 -144 -144s-144 64 -144 144s64 144 144 144zM315 95c2 9 4 18 4 29h-7v7h8c0 11 -2 20 -5 30l-25 -7l-4 12l25 8c-4 10 -8 18 -14 26l-11 -8l-4 6l11 8c-6 8 -13 16 -21 22 +l-15 -21l-11 8l15 20c-8 6 -17 11 -27 14l-4 -13l-6 2l5 13c-9 3 -20 5 -29 5v-13v-6h-16v6v13c-11 -1 -19 -2 -29 -5l4 -12l-6 -2l-4 12c-10 -3 -19 -8 -27 -14l15 -20l-10 -8l-15 21c-8 -6 -16 -14 -22 -22l11 -8l-4 -5l-10 8c-6 -8 -10 -17 -14 -27l24 -8l-5 -12l-25 7 +c-3 -10 -3 -19 -3 -30h6v-7h-5c0 -11 2 -20 4 -29l24 7l4 -12l-24 -8c4 -10 8 -19 14 -27l9 7l4 -5l-9 -7c6 -8 13 -16 21 -22l15 21l10 -8l-15 -20c8 -5 17 -11 27 -14l3 11l7 -2l-4 -11c10 -3 18 -4 29 -5v13v6h16v-6v-13c9 1 19 2 29 5l-5 12l6 2l4 -12c10 3 19 8 27 14 +l-15 20l11 8l15 -21c8 6 15 14 21 22l-11 7l4 6l10 -8c6 8 11 17 15 27l-25 8l4 12zM111 128c0 54 27 81 81 81s81 -27 81 -81s-27 -81 -81 -81s-81 27 -81 81z" /> <glyph glyph-name="ion-locked" unicode="" horiz-adv-x="384" d="M22 -32c-12 0 -22 10 -22 22v212c0 12 10 22 22 22h3h19v31c0 42 17 87 43 115s64 46 105 46v0v0c41 0 79 -18 105 -46s43 -73 43 -115v-31h22c12 0 22 -10 22 -22v-212c0 -12 -10 -22 -22 -22h-340zM97 255v-31h17h155h18v31c0 27 -10 61 -28 80v0v1 c-18 19 -42 29 -67 29v0v0c-25 0 -49 -10 -67 -29v-1v0c-18 -19 -28 -53 -28 -80z" /> - <glyph glyph-name="ion-log-in" unicode="" horiz-adv-x="384" -d="M160 160v48h-152c-4 0 -8 4 -8 8v16c0 4 4 8 8 8h152v48l64 -64zM376 384c4 0 8 -4 8 -8v-302c0 -8 0 -10 -9 -15l-119 -59v64h-152c-4 0 -8 4 -8 8v104h32v-80h128v224l48 32h-176v-80h-32v104c0 4 4 8 8 8h272z" /> - <glyph glyph-name="ion-log-out" unicode="" horiz-adv-x="384" -d="M320 288l64 -64l-64 -64v48h-152c-4 0 -8 4 -8 8v16c0 4 4 8 8 8h152v48zM288 272h-32v80h-176l48 -32v-224h128v80h32v-104c0 -4 -4 -8 -8 -8h-152v-64l-119 59c-9 5 -9 7 -9 15v302c0 4 4 8 8 8h272c4 0 8 -4 8 -8v-104z" /> - <glyph glyph-name="ion-loop" unicode="" horiz-adv-x="512" -d="M273.4 147.5l-0.300781 -58c48.9004 8.2002 86.3008 51 86.3008 102.5c0 15.9004 -3.60059 31 -10 44.5c-2.80078 5.7998 -6 11.2998 -9.80078 16.5l47.1006 43.5c1.09961 -1.2998 2.09961 -2.7002 3.09961 -4c20.9004 -28 33.2002 -62.7998 33.2002 -100.5v-3.7002 -c-1.5 -71.5 -47.5996 -132 -111.4 -154.6c-12.2998 -4.2998 -25.1992 -7.2998 -38.5 -8.7002l-0.0996094 -57l-76.2002 67l-26.2002 23l44.4004 38.7002zM89 195.7c1.59961 72.0996 48.2998 133 112.9 155.2c11.6992 4 24 6.7998 36.7998 8.09961l0.0996094 57 -l76.1006 -66.9004l26.1992 -23.0996l-44.2998 -38.5996l-58.3994 -50.9004l0.199219 57.9004c-48.7998 -8.30078 -86 -51.1006 -86 -102.4c0 -16 3.60059 -31.0996 10.1006 -44.7002c2.7002 -5.7998 6 -11.2002 9.7002 -16.2998l-47 -43.5996 -c-1.30078 1.59961 -2.60059 3.2998 -3.80078 5c-20.5 27.8994 -32.5996 62.2998 -32.5996 99.5996v3.7002z" /> + <glyph glyph-name="ion-log-in" unicode="" +d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224c-96 0 -177 60 -209 144h34c9 -20 23 -40 39 -56c36 -36 85 -56 136 -56s100 20 136 56s56 85 56 136s-20 100 -56 136s-85 56 -136 56s-100 -20 -136 -56c-16 -16 -30 -36 -39 -56h-34c32 84 113 144 209 144z +M175 124l52 52h-227v32h227l-52 52l22 23l91 -91l-91 -91z" /> + <glyph glyph-name="ion-log-out" unicode="" +d="M335 124l52 52h-227v32h227l-52 52l22 23l91 -91l-91 -91zM359 56c3 3 6 5 8 8h41c-40 -58 -108 -96 -184 -96c-124 0 -224 100 -224 224s100 224 224 224c76 0 144 -38 184 -96h-41c-2 3 -5 5 -8 8c-36 36 -84 56 -135 56s-100 -20 -136 -56s-56 -85 -56 -136 +s20 -100 56 -136s85 -56 136 -56s99 20 135 56z" /> + <glyph glyph-name="ion-loop" unicode="" horiz-adv-x="334" +d="M184 148v-58c49 8 86 50 86 102c0 16 -4 30 -10 44c-3 6 -5 12 -9 17l47 43c1 -1 2 -3 3 -4c21 -28 33 -62 33 -100v-4c-2 -72 -47 -131 -111 -154c-12 -4 -26 -8 -39 -9v-57l-76 67l-26 23l44 39zM0 196c2 72 48 133 113 155c12 4 24 7 37 8v57l76 -67l26 -23l-44 -39 +l-59 -51l1 58c-49 -8 -86 -51 -86 -102c0 -16 4 -31 10 -45c3 -6 5 -11 9 -16l-47 -44c-1 2 -2 3 -3 5c-20 28 -33 63 -33 100v4z" /> <glyph glyph-name="ion-magnet" unicode="" horiz-adv-x="384" d="M192 416c115 0 192 -78 192 -200c0 -49 -3 -77 -15 -128c-16 -66 -39 -113 -39 -113v-1c-2 -3 -6 -6 -10 -6c-1 0 -3 1 -4 1l-2 1l-50 20l-2 1c-3 2 -5 5 -5 9c0 1 0 3 1 4v1c7 16 27 59 37 101s13 63 13 108c0 71 -52 122 -116 122s-116 -51 -116 -122 c0 -45 3 -66 13 -108s30 -85 37 -101v-1c1 -1 1 -3 1 -4c0 -4 -2 -7 -5 -9l-2 -1l-50 -20l-2 -1c-1 0 -3 -1 -4 -1c-4 0 -8 3 -10 6v1s-24 47 -40 113c-12 51 -14 79 -14 128c0 122 77 200 192 200zM109 4c-9 19 -27 59 -36 98l-42 -12c13 -53 30 -92 35 -104l43 17v1z @@ -1376,10 +1589,10 @@ s56 -38 90 -38s66 14 90 38z" /> d="M84 341c-21 0 -37 17 -37 38s16 37 37 37s37 -16 37 -37s-16 -38 -37 -38zM121 333c28 0 47 -24 47 -48v-114c0 -22 -32 -22 -32 0v105h-5v-286c0 -28 -41 -31 -43 0v165h-1h-7v-165c-1 -29 -43 -30 -43 0v286h-6v-105c0 -22 -31 -22 -31 0v114c0 24 19 48 47 48h37h37z " /> <glyph glyph-name="ion-map" unicode="" -d="M441 311c4 -3 7 -8 7 -14v-281c0 -6 -3 -11 -8 -14c-2 -1 -5 -2 -7 -2c-3 0 -5 0 -7 2l-97 66l-97 -66c-5 -3 -11 -3 -16 0l-97 66l-97 -66c-4 -3 -10 -3 -15 0s-7 8 -7 14v281c0 6 3 11 7 14l105 71c5 3 10 3 15 0l97 -66l97 66c5 3 10 3 15 0zM103 95v241l-71 -49v-242 -zM135 95l73 -49v131l-4 -13c-7 2 -14 6 -21 10l9 13c6 -4 10 -6 16 -8v109l-73 49v-101c4 -2 8 -4 12 -7l-9 -13c-1 1 -2 1 -3 2v-123zM240 46l73 49v109l-2 -2c-2 -2 -3 -4 -5 -6l-12 11c2 2 3 4 5 6c3 3 6 7 9 10l5 -5v119l-73 -49v-112h6l3 -15c-3 0 -6 -1 -9 -1v0v-114z -M416 46v0v242l-71 49v-88c3 1 5 2 8 2l3 -15c-4 -1 -7 -2 -11 -4v-137zM67 192v-1l-16 5l1 1c2 7 4 13 9 20l13 -9c-4 -5 -5 -10 -7 -16zM97 227c-3 -1 -11 -5 -14 -7l-11 12c4 3 7 6 11 8c3 2 7 3 10 4l5 -15c-2 -1 1 -1 -1 -2zM264 182c5 2 11 5 16 10l10 -12 -c-6 -6 -12 -9 -19 -12zM166 210c4 -4 6 -7 10 -11l-11 -12c-4 4 -7 9 -11 13l-3 3l12 11c1 -1 2 -3 3 -4zM376 218l-12 12l11 10l-11 10l12 12l10 -11l10 11l12 -12l-11 -10l11 -10l-12 -12l-10 11z" /> +d="M441 311c4 -3 7 -8 7 -14v-281c0 -6 -2 -11 -7 -14c-2 -1 -5 -2 -7 -2c-3 0 -6 0 -8 2l-97 66l-97 -66c-5 -3 -10 -3 -15 0l-97 66l-97 -66c-5 -3 -10 -3 -15 0s-8 8 -8 14v281c0 6 3 11 7 14l105 71c5 3 10 3 15 0l97 -66l98 66c5 3 10 3 15 0zM103 95v242l-71 -50v-242 +zM135 95l73 -49v129l-4 -11c-7 2 -13 6 -20 10l8 13c5 -3 11 -6 16 -8v109l-73 49v-101c4 -2 9 -4 13 -7l-10 -13c-1 1 -2 1 -3 2v-123zM240 46l73 49v109c0 -1 -1 -1 -1 -2l-6 -6l-12 11l6 6c3 3 5 7 8 10l5 -5v119l-73 -49v-112h7l3 -15c-3 0 -6 -1 -9 -1h-1v-114zM416 46 +v242l-71 49v-88c3 1 5 1 8 2l4 -16c-4 -1 -8 -1 -12 -3v-137zM97 227c-3 -1 -11 -5 -14 -7l-11 12c4 3 8 6 12 8c3 2 6 3 9 4l5 -15c-2 -1 1 -1 -1 -2zM265 182c5 3 10 5 15 10l11 -12c-6 -6 -12 -10 -19 -13zM67 192v-1l-15 5v1c2 7 4 13 9 20l13 -9c-4 -5 -5 -10 -7 -16z +M166 210c3 -4 7 -8 11 -11l-11 -12c-4 4 -8 9 -12 13l-3 3l12 11c1 -1 2 -3 3 -4zM376 218l-11 12l10 10l-10 10l11 12l10 -11l11 11l11 -12l-10 -10l10 -10l-11 -12l-11 11z" /> <glyph glyph-name="ion-medkit" unicode="" d="M440 304c4 0 8 -4 8 -8v-288c0 -4 -4 -8 -8 -8h-432c-4 0 -8 4 -8 8v288c0 4 4 8 8 8h120v31c1 28 22 49 51 49h45h45c30 0 50 -21 51 -49v-31h120zM160 331v-27h128v27v1v1c0 10 -9 19 -19 19h-45h-45c-10 0 -19 -9 -19 -19v-1v-1zM320 128v64h-64v64h-64v-64h-64v-64 h64v-64h64v64h64z" /> @@ -1443,6 +1656,11 @@ c-12 0 -23 -3 -33 -9l-80 138c35 20 73 31 113 31s78 -10 113 -30l-81 -139c-10 6 -2 <glyph glyph-name="ion-outlet" unicode="" d="M338 416c61 0 110 -51 110 -113v-222c0 -62 -49 -113 -110 -113h-228c-61 0 -110 51 -110 113v222c0 62 49 113 110 113h228zM143 197v102c0 11 -9 21 -20 21h-23c-11 0 -19 -9 -20 -20v-2v-101v-1c0 -11 9 -20 20 -20h23c11 0 20 9 20 20v1zM265 52v29 c0 23 -18 42 -41 42s-41 -19 -41 -42v-29v0c0 -11 9 -20 20 -20h21h21c11 0 20 7 20 18v2zM368 197v102c0 11 -9 21 -20 21h-24c-11 0 -19 -9 -20 -20v-2v-101v-1c0 -11 9 -20 20 -20h24c11 0 20 9 20 20v1z" /> + <glyph glyph-name="ion-paintbrush" unicode="" +d="M118 165c52 0 102 -41 90 -102c-11 -52 -54 -71 -90 -77c-30 -5 -100 0 -118 35c24 9 34 26 34 49c0 49 32 95 84 95zM436 388c13 -13 17 -30 5 -45l-154 -175c2 -9 1 -17 -3 -23l-50 -58v0v0c-2 -2 -4 -2 -6 0c-1 1 -1 2 -1 3v1c2 53 -41 87 -89 90v0h-2s-2 0 -2 1 +c-2 2 -2 4 0 6l59 49c6 4 14 4 23 2l175 154c15 12 32 8 45 -5zM134 188v0v0v0z" /> + <glyph glyph-name="ion-paintbucket" unicode="" horiz-adv-x="480" +d="M112 384l32 32l275 -276l-58 -12l-163 -160l-198 192l152 152zM309 160l-110 110l-110 -110h220zM419 140c0 0 61 -66 61 -99s-27 -60 -61 -60s-60 27 -60 60s60 99 60 99z" /> <glyph glyph-name="ion-paper-airplane" unicode="" d="M0 176l448 240l-112 -448l-112 112l-80 -112l-16 160zM319 31l80 323l-322 -173l83 -31l192 154l-128 -176z" /> <glyph glyph-name="ion-paperclip" unicode="" horiz-adv-x="160" @@ -1469,11 +1687,9 @@ c0 -8 -5 -14 -12 -17c-1 0 -1 -1 -2 -1v0c-6 -3 -10 -6 -10 -13v-5l18 -118c2 -8 7 - d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM360 56c32 32 51 75 55 120l-63 8v16l63 8c-4 45 -23 88 -55 120s-75 51 -120 55l-8 -63h-16l-8 63c-45 -4 -88 -23 -120 -55s-51 -75 -55 -120l63 -8v-16l-63 -8 c4 -45 23 -88 55 -120s75 -51 120 -55l8 63h16l8 -63c45 4 88 23 120 55z" /> <glyph glyph-name="ion-pizza" unicode="" horiz-adv-x="352" -d="M317 317c5 -2 8 -7 8 -13c0 -2 0 -4 -1 -6v0l-148 -330l-148 330v0c-1 2 -1 4 -1 6c0 6 3 11 8 13v0c1 0 1 0 2 1v0c42 18 90 28 139 28s97 -10 139 -28v0s0 -1 1 -1h1zM167 330c-4 -2 -5 -7 -3 -11c0 -1 5 -9 14 -15c12 -8 27 -8 41 0c4 2 5 7 3 11s-7 5 -11 3 -c-9 -5 -16 -5 -23 0c-6 4 -10 9 -10 9c-2 4 -7 5 -11 3zM80 288c0 -18 14 -32 32 -32s32 14 32 32s-14 32 -32 32s-32 -14 -32 -32zM134 187c1 10 5 16 13 19c6 3 13 3 13 3c4 0 8 3 8 7s-3 9 -7 9c-1 0 -10 0 -20 -4c-14 -6 -22 -17 -23 -33c0 -4 3 -9 7 -9s9 4 9 8z -M188 53c13 7 20 20 20 36c0 4 -5 7 -9 7s-7 -4 -7 -8c0 -10 -4 -17 -11 -21c-6 -3 -13 -3 -13 -3c-4 0 -8 -5 -8 -9s5 -7 9 -7c1 0 10 0 19 5zM176 109c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM240 224c18 0 32 14 32 32s-14 32 -32 32 -s-32 -14 -32 -32s14 -32 32 -32zM344 382c5 -2 8 -7 8 -13c0 -2 0 -3 -1 -5v-1l-7 -16l-1 -3c-2 -5 -7 -8 -13 -8c-2 0 -4 1 -6 2h-1c-45 19 -95 30 -147 30s-102 -11 -147 -30v0c-2 -1 -4 -2 -6 -2c-6 0 -12 4 -14 9l-1 2l-7 16v1c-1 2 -1 3 -1 5c0 6 3 11 8 13v0 -c1 0 1 1 2 1v0c51 21 107 33 166 33s115 -12 166 -33v0c1 0 1 -1 2 -1z" /> +d="M315 318c10 -4 12 -13 9 -20l-148 -330s-143 320 -148 331s2 16 9 19c39 18 90 28 139 28s96 -9 139 -28zM112 256c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM176 109c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM240 224 +c18 0 32 14 32 32s-14 32 -32 32s-32 -14 -32 -32s14 -32 32 -32zM342 382c6 -3 10 -6 10 -13c0 -1 0 -3 -1 -5l-8 -19c-3 -5 -8 -9 -14 -9c-1 0 -3 1 -6 2c-41 18 -95 30 -147 30s-102 -11 -147 -30c-3 -1 -4 -2 -6 -2c-6 0 -11 4 -14 9l-8 19s-1 2 -1 5c0 8 6 12 10 14 +c49 21 107 33 166 33s118 -13 166 -34z" /> <glyph glyph-name="ion-plane" unicode="" d="M250 136c0 -7 1 -69 -6 -102c-1 -4 3 -4 5 -7l51 -33c2 -2 3 -8 3 -8l1 -18l-68 16l-12 -32l-12 32l-68 -16l1 18s0 6 2 8l52 33c2 3 6 3 5 7c-7 33 -6 95 -6 102s-8 5 -8 5l-62 -13l-128 -49c0 23 2 26 9 31l183 131s5 63 5 113c0 24 12 78 27 78s27 -54 27 -78 c0 -53 5 -113 5 -113l183 -131c6 -4 9 -7 9 -31l-128 49l-62 13s-8 2 -8 -5z" /> @@ -1521,21 +1737,16 @@ d="M48 324v-68h-48v68c0 33 28 60 61 60h67v-48h-68c-7 0 -12 -5 -12 -12zM356 384c3 c0 -7 5 -12 12 -12z" /> <glyph glyph-name="ion-quote" unicode="" horiz-adv-x="384" d="M128 384c-41 0 -73 -11 -95 -33s-33 -54 -33 -95v-256h160v256h-96c0 23 5 39 15 49s26 15 49 15zM352 384c-41 0 -73 -11 -95 -33s-33 -54 -33 -95v-256h160v256h-96c0 23 5 39 15 49s26 15 49 15z" /> - <glyph glyph-name="ion-radio-waves" unicode="" horiz-adv-x="384" -d="M128 192c0 43 21 64 64 64s64 -21 64 -64s-21 -64 -64 -64s-64 21 -64 64zM96 192c0 -9 1 -17 3 -25s6 -16 10 -23s8 -13 14 -19s12 -11 19 -15l-23 -23c-6 4 -12 10 -17 15c-25 25 -38 55 -38 90s13 65 38 90c6 6 11 11 17 15l23 -23c-14 -9 -25 -20 -33 -35 -s-13 -30 -13 -47zM288 192c0 11 -2 22 -6 33s-9 20 -16 28s-15 15 -24 21l23 23c6 -4 12 -10 17 -15c25 -25 38 -55 38 -90s-13 -65 -38 -90c-6 -6 -11 -11 -17 -15l-23 23c14 9 25 20 33 35s13 30 13 47zM32 192c0 -26 6 -50 17 -72s27 -41 47 -56l-23 -23 -c-6 5 -11 9 -17 15c-18 18 -31 38 -41 61c-10 24 -15 49 -15 75s5 51 15 75c10 23 23 43 41 61c6 6 11 10 17 15l23 -23c-13 -10 -24 -21 -34 -34s-17 -28 -22 -44s-8 -33 -8 -50zM352 192c0 26 -6 50 -17 72s-27 41 -47 56l22 23c6 -5 12 -9 18 -15c18 -18 31 -38 41 -61 -c10 -24 15 -49 15 -75s-5 -51 -15 -75c-10 -23 -23 -43 -41 -61c-6 -6 -12 -10 -18 -15l-22 23c20 15 36 34 47 56s17 46 17 72z" /> + <glyph glyph-name="ion-radio-waves" unicode="" +d="M160 192c0 43 21 64 64 64s64 -21 64 -64s-21 -64 -64 -64s-64 21 -64 64zM112 192c0 -18 5 -35 13 -50s19 -28 33 -37l-23 -25c-6 5 -13 10 -18 16c-25 26 -37 59 -37 96s12 70 37 96c5 6 12 11 18 16l23 -25c-14 -9 -25 -22 -33 -37s-13 -32 -13 -50zM336 192 +c0 18 -5 35 -13 50s-19 28 -33 37l23 25c6 -5 13 -10 18 -16c25 -26 37 -59 37 -96s-12 -70 -37 -96c-5 -6 -12 -11 -18 -16l-23 25c14 9 25 22 33 37s13 32 13 50zM32 192c0 -27 6 -53 17 -77s27 -43 47 -59l-23 -24c-6 5 -12 10 -17 16c-18 19 -31 41 -41 65 +c-10 25 -15 51 -15 79s5 54 15 79c10 24 23 46 41 65c5 6 11 11 17 16l23 -24c-10 -8 -18 -17 -26 -27s-14 -21 -20 -32s-10 -24 -13 -37s-5 -26 -5 -40zM416 192c0 27 -6 53 -17 77s-27 43 -47 59l23 24c6 -5 12 -10 17 -16c18 -19 31 -41 41 -65c10 -25 15 -51 15 -79 +s-5 -54 -15 -79c-10 -24 -23 -46 -41 -65c-4 -5 -10 -10 -17 -16l-23 24c20 16 36 35 47 59s17 50 17 77z" /> <glyph glyph-name="ion-record" unicode="" horiz-adv-x="416" d="M208 -16c-115 0 -208 93 -208 208s93 208 208 208s208 -93 208 -208s-93 -208 -208 -208z" /> - <glyph glyph-name="ion-refresh" unicode="" horiz-adv-x="512" -d="M416 96l-104 112h73.5c-6.7002 65.4004 -63.0996 112 -129.5 112c-70.5996 0 -128 -57 -128 -128s57.4004 -128 128 -128c27.5 0 52.9004 7.90039 75 24.2002l6.2002 4.59961l43.2002 -46.2002l-7.5 -5.89941c-33.8008 -26.5 -74 -40.6006 -116.9 -40.7002 -c-91 0.200195 -167.4 63.5996 -187.1 148.6v0.100586c-0.200195 1 -0.5 2.09961 -0.700195 3.2002c-0.100586 0.399414 -0.200195 0.899414 -0.299805 1.39941c-0.100586 0.700195 -0.300781 1.40039 -0.400391 2.10059c-0.200195 0.799805 -0.299805 1.69922 -0.5 2.59961 -c-0.0996094 0.400391 -0.0996094 0.700195 -0.200195 1.09961c-0.200195 1.2002 -0.399414 2.40039 -0.599609 3.60059v0.200195c-0.900391 6.19922 -1.60059 12.5996 -1.90039 19.0996v0.900391c-0.0996094 1.39941 -0.200195 2.69922 -0.200195 4.09961 -c-0.0996094 1.7002 -0.0996094 3.2998 -0.0996094 5s0.0996094 3.40039 0.0996094 5c0.100586 1.40039 0.100586 2.7002 0.200195 4.09961v0.800781c0.299805 6.39941 0.900391 12.7998 1.90039 19.0996v0.200195c0.200195 1.2002 0.399414 2.39941 0.599609 3.59961 -c0.100586 0.400391 0.100586 0.700195 0.200195 1.10059c0.200195 0.899414 0.299805 1.69922 0.5 2.59961c0.0996094 0.700195 0.299805 1.40039 0.400391 2.09961c0.0996094 0.5 0.199219 0.900391 0.299805 1.40039c0.200195 1.09961 0.399414 2.2002 0.700195 3.2998 -v0.100586c19.6992 85 95.7998 148.399 186.699 148.6v0h0.400391c10.5996 0 21.0996 -0.900391 31.2002 -2.59961c0.5 0 0.899414 -0.100586 1.39941 -0.200195c0.700195 -0.100586 1.5 -0.299805 2.2002 -0.400391c57.2002 -10.5 105.601 -46.3994 133 -95.5996 -c13 -23.2998 21.2002 -49.4004 23.5 -77.2998h64.7002z" /> + <glyph glyph-name="ion-refresh" unicode="" +d="M352 96l-104 112h74c-7 65 -64 112 -130 112c-71 0 -128 -57 -128 -128s57 -128 128 -128c28 0 53 8 75 24l6 5l43 -46l-7 -6c-34 -26 -74 -41 -117 -41c-91 0 -167 64 -187 149v0c0 1 -1 2 -1 3v1v2s-1 2 -1 3v1c0 1 -1 3 -1 4v0c-1 6 -2 13 -2 19v1v4v5v5v4v1 +c0 6 1 13 2 19v0c0 1 1 3 1 4v1c0 1 1 1 1 2v3v1c0 1 1 2 1 3v0c20 85 96 149 187 149v0v0c11 0 21 -1 31 -3h2h2c57 -10 106 -47 133 -96c13 -23 21 -49 23 -77h65z" /> <glyph glyph-name="ion-reply-all" unicode="" horiz-adv-x="416" d="M257 256c153 0 159 -208 159 -208c-51 93 -91 102 -159 102v-92l-152 134l152 144v-80zM0 192l144 136v-57l-82 -79l82 -68v-58z" /> <glyph glyph-name="ion-reply" unicode="" horiz-adv-x="384" @@ -1546,11 +1757,15 @@ s-43 96 -96 96s-96 -43 -96 -96s43 -96 96 -96zM176 184c49 0 88 -39 88 -88s-39 -88 <glyph glyph-name="ion-ribbon-b" unicode="" horiz-adv-x="384" d="M192 376c49 0 88 -39 88 -88s-39 -88 -88 -88s-88 39 -88 88s39 88 88 88zM192 416c71 0 128 -57 128 -128s-57 -128 -128 -128s-128 57 -128 128s57 128 128 128zM192 192c53 0 96 43 96 96s-43 96 -96 96s-96 -43 -96 -96s43 -96 96 -96zM83 194c26 -30 65 -50 109 -50 c12 0 23 1 34 4l-34 -74l-48 -106l-48 80h-96zM301 194l83 -146h-96l-48 -80l-40 88l45 98c22 9 41 23 56 40z" /> - <glyph glyph-name="ion-sad" unicode="" + <glyph glyph-name="ion-sad-outline" unicode="" d="M367 164c3 -9 -2 -17 -11 -19c-3 -1 -7 0 -10 1c-5 2 -9 5 -11 10s-4 12 -13 15s-14 0 -19 -3c-4 -3 -10 -3 -15 -1c-3 1 -7 3 -9 6c-6 8 -3 17 5 22c15 9 29 13 49 6s29 -21 34 -37zM165 195c8 -5 10 -14 4 -22c-2 -3 -6 -5 -9 -6c-5 -2 -11 -2 -15 1c-5 3 -10 6 -19 3 s-11 -10 -13 -15s-6 -8 -11 -10c-3 -1 -7 -2 -10 -1c-9 2 -14 10 -11 19c5 16 14 30 34 37s35 3 50 -6zM224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM360 56c36 36 56 85 56 136s-20 100 -56 136s-85 56 -136 56 s-100 -20 -136 -56s-56 -85 -56 -136s20 -100 56 -136s85 -56 136 -56s100 20 136 56zM317 89c5 -7 3 -17 -4 -22c-3 -2 -6 -3 -9 -3c-5 0 -10 3 -13 7c0 0 -19 25 -67 25s-67 -25 -67 -25c-3 -4 -8 -7 -13 -7c-3 0 -6 1 -9 3c-7 5 -9 15 -4 22c1 2 28 39 93 39 s92 -37 93 -39z" /> + <glyph glyph-name="ion-sad" unicode="" +d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM113 156c2 5 4 12 13 15s14 0 19 -3c4 -3 10 -3 15 -1c3 1 7 3 9 6c6 8 4 17 -4 22c-15 9 -30 13 -50 6s-29 -21 -34 -37c-3 -9 2 -17 11 -19c3 -1 7 0 10 1c5 2 9 5 11 10z +M313 67c7 5 9 15 4 22c-1 2 -28 39 -93 39s-92 -37 -93 -39c-5 -7 -3 -17 4 -22c3 -2 6 -3 9 -3c5 0 10 3 13 7c0 0 19 25 67 25s67 -25 67 -25c3 -4 8 -7 13 -7c3 0 6 1 9 3zM356 145c9 2 14 10 11 19c-5 16 -14 30 -34 37s-34 3 -49 -6c-8 -5 -11 -14 -5 -22 +c2 -3 6 -5 9 -6c5 -2 11 -2 15 1c5 3 10 6 19 3s11 -10 13 -15s6 -8 11 -10c3 -1 7 -2 10 -1z" /> <glyph glyph-name="ion-scissors" unicode="" horiz-adv-x="384" d="M341 332c-13 -33 -117 -172 -117 -172l-32 -32s-31 -13 -50 -43s-33 -71 -33 -71v0c-7 -26 -28 -46 -53 -46c-31 0 -56 29 -56 64s25 64 56 64c13 0 25 -5 34 -13c2 -1 3 -3 4 -4v0l2 -2c4 -4 7 -2 14 11c8 15 17 35 27 54s38 59 38 59l17 23l144 192 c23 -20 18 -51 5 -84zM56 0c15 0 28 14 28 32s-13 32 -28 32s-28 -14 -28 -32s13 -32 28 -32zM192 160c9 0 16 7 16 16s-7 16 -16 16s-16 -7 -16 -16s7 -16 16 -16zM143 183c-30 41 -90 125 -100 149c-13 33 -18 64 5 84l134 -178l-3 -4v0v0l-17 -23v-1v0 @@ -1584,6 +1799,10 @@ c7 0 13 -7 13 -14s-5 -13 -13 -13zM225 309c-7 0 -13 6 -13 13s5 14 13 14c7 0 13 -7 d="M64 180v76h224v-76v-90c0 -7 -4 -14 -11 -14h-28v-52c0 -13 -11 -24 -24 -24v0h-1c-6 0 -10 2 -14 5c-5 4 -9 11 -9 19v52h-49v-52c0 -13 -11 -24 -24 -24s-24 11 -24 24v52h-29c-7 0 -11 7 -11 14v90zM328 272c13 0 24 -11 24 -24v-96c0 -13 -11 -24 -24 -24 s-24 11 -24 24v96c0 13 11 24 24 24zM24 272c13 0 24 -11 24 -24v-96c0 -13 -11 -24 -24 -24s-24 11 -24 24v96c0 13 11 24 24 24zM231 359c48 -21 56 -72 57 -87h-224c1 15 8 66 56 87l-18 22c0 1 0 1 1 2s3 1 3 1l19 -23c14 5 31 9 51 9s36 -4 50 -9l20 23c0 1 1 0 2 -1 l2 -2zM127 309c8 0 13 6 13 13s-6 14 -13 14c-8 0 -14 -7 -14 -14s7 -13 14 -13zM225 309c7 0 14 6 14 13s-7 14 -14 14c-8 0 -13 -7 -13 -14s6 -13 13 -13z" /> + <glyph glyph-name="ion-social-angular-outline" unicode="" +d="M224 384l-188 -69l39 -230l149 -80l149 80l39 230zM224 416v0l224 -80l-46 -272l-178 -96l-178 96l-46 272zM312 96l-27 56h-122l-27 -56h-40l128 280l128 -280h-40zM182 192h84l-42 89z" /> + <glyph glyph-name="ion-social-angular" unicode="" +d="M182 192l42 89l42 -89h-84zM224 416l224 -80l-46 -272l-178 -96l-178 96l-46 272zM312 96h40l-128 280l-128 -280h40l27 56h122z" /> <glyph glyph-name="ion-social-apple-outline" unicode="" horiz-adv-x="320" d="M238 278c-15 0 -26 -4 -37 -8c-10 -4 -21 -8 -35 -8s-25 4 -37 8c-11 4 -22 8 -34 8c-11 0 -23 -3 -34 -10c-12 -7 -23 -18 -31 -31c-12 -18 -16 -47 -13 -77c3 -34 16 -69 35 -99c13 -21 30 -45 50 -45h1c8 0 13 3 20 6c10 5 23 10 44 10v0c21 0 34 -5 44 -10 c7 -3 12 -6 19 -6v0c22 0 44 35 52 48c8 12 12 20 17 31c-12 7 -22 16 -30 28c-10 15 -17 33 -18 52c-1 18 2 37 10 53c6 12 14 22 24 30c-14 13 -31 20 -47 20zM238 294v0c25 0 52 -14 71 -39c-63 -36 -53 -128 11 -153c-9 -20 -13 -28 -24 -46c-16 -25 -37 -56 -65 -56h-1 @@ -1611,6 +1830,27 @@ l-123 -60c-6 -3 -15 -4 -23 -4s-17 1 -23 4l-123 60l-19 -9l156 -75c2 -1 5 -2 9 -2s d="M7 284c-9 4 -9 11 0 15l169 82c4 2 10 3 16 3s12 -1 16 -3l169 -82c9 -4 9 -11 0 -15l-169 -82c-4 -2 -10 -3 -16 -3s-12 1 -16 3zM377 200c9 -4 9 -12 0 -16l-169 -81c-4 -2 -10 -4 -16 -4s-12 2 -16 4l-169 81c-9 4 -9 12 0 16c0 0 27 13 33 16c5 3 7 3 13 0 s123 -60 123 -60c4 -2 10 -3 16 -3s12 1 16 3c0 0 121 59 125 61s5 2 9 0s35 -17 35 -17zM377 100c9 -4 9 -11 0 -15l-169 -82c-4 -2 -10 -3 -16 -3s-12 1 -16 3l-169 82c-9 4 -9 11 0 15c0 0 27 14 33 17c5 3 7 2 13 -1s123 -59 123 -59c4 -2 10 -3 16 -3s12 1 16 3 c0 0 121 58 125 60s5 2 9 0s35 -17 35 -17z" /> + <glyph glyph-name="ion-social-chrome-outline" unicode="" +d="M224 416c123 0 224 -101 224 -224s-101 -224 -224 -224s-224 101 -224 224s101 224 224 224zM224 371c-57 0 -109 -27 -141 -68l54 -93c8 40 43 72 87 72h155c-30 54 -89 89 -155 89zM291 192c0 37 -30 67 -67 67s-67 -30 -67 -67s30 -67 67 -67s67 30 67 67zM45 192 +c0 -91 67 -166 154 -177l54 93c-9 -3 -19 -6 -29 -6c-34 0 -61 18 -77 45v0l-78 135c-16 -27 -24 -58 -24 -90zM224 13c99 0 179 80 179 179c0 24 -4 46 -13 67h-108c19 -17 32 -40 32 -67c0 -17 -5 -32 -13 -45v0z" /> + <glyph glyph-name="ion-social-chrome" unicode="" +d="M157 192c0 37 30 67 67 67s67 -30 67 -67s-30 -67 -67 -67s-67 30 -67 67zM445 230c2 -12 3 -25 3 -38c0 -106 -74 -195 -174 -218c-10 -2 -20 -4 -30 -5c-7 -1 -13 -1 -20 -1c-8 0 -17 0 -25 1v0v0v0v1l102 177c8 13 13 28 13 45c0 27 -13 50 -32 67h156 +c3 -9 5 -19 7 -29v0c-2 10 -4 20 -7 29v0c3 -9 5 -19 7 -29v0zM224 103c10 0 20 2 29 5l-78 -135v0c-42 9 -79 30 -108 59c-42 41 -67 97 -67 160c0 31 6 61 18 88c7 16 16 31 26 45v0l103 -178c16 -27 43 -44 77 -44zM59 343v0v1c24 26 55 47 90 59c23 8 49 13 75 13 +c73 0 138 -36 179 -90h1c10 -14 18 -29 25 -44v0c-7 15 -15 30 -25 44h-1c10 -14 19 -29 26 -44h-205c-44 0 -79 -32 -87 -72z" /> + <glyph glyph-name="ion-social-codepen-outline" unicode="" +d="M356 244c5 -3 7 -6 7 -12v-81c0 -6 -3 -10 -8 -13c-41 -27 -82 -55 -123 -82c-6 -4 -11 -4 -17 0c-41 27 -81 55 -122 82c-5 3 -8 7 -8 13v80c0 6 3 11 8 14c41 27 81 54 122 81c6 4 11 4 17 0c41 -27 83 -55 124 -82zM236 296v-54c0 -1 1 -2 2 -3c16 -11 31 -21 47 -32 +c1 -1 3 -1 4 0l40 26zM212 295c0 0 -62 -41 -93 -62c14 -9 27 -17 40 -26c1 -1 3 -1 4 0c15 10 31 21 46 31c1 1 3 4 3 6v51zM109 211v-40l30 20zM212 87v53c0 1 -2 3 -3 4c-15 10 -31 21 -46 31c-2 1 -3 1 -5 0l-39 -26c31 -21 93 -62 93 -62zM227 165l39 26s-34 23 -40 27 +c-1 1 -4 0 -5 -1c-5 -3 -9 -6 -14 -9c-8 -6 -25 -17 -25 -17l39 -26c2 -1 4 -1 6 0zM236 87l93 62l-38 26c-2 2 -5 2 -7 0c-15 -10 -30 -21 -45 -31c-2 -2 -3 -3 -3 -6v-51zM338 171v40l-30 -20zM224 384c-51 0 -100 -20 -136 -56s-56 -85 -56 -136s20 -100 56 -136 +s85 -56 136 -56s100 20 136 56s56 85 56 136s-20 100 -56 136s-85 56 -136 56zM224 416v0c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224z" /> + <glyph glyph-name="ion-social-codepen" unicode="" +d="M209 144c1 -1 3 -3 3 -4v-53s-62 41 -93 62l39 26c2 1 3 1 5 0c15 -10 31 -21 46 -31zM163 207c-1 -1 -3 -1 -4 0c-13 9 -26 17 -40 26c31 21 93 62 93 62v-51c0 -2 -2 -5 -3 -6c-15 -10 -31 -21 -46 -31zM238 239c-1 1 -2 2 -2 3v54l93 -63l-40 -26c-1 -1 -3 -1 -4 0 +c-16 11 -31 21 -47 32zM226 218c6 -4 40 -27 40 -27l-39 -26c-2 -1 -4 -1 -6 0l-39 26s17 11 25 17c5 3 9 6 14 9c1 1 4 2 5 1zM109 211l30 -20l-30 -20v40zM224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM363 151v81 +c0 6 -2 9 -7 12c-41 27 -83 55 -124 82c-6 4 -11 4 -17 0c-41 -27 -81 -54 -122 -81c-5 -3 -8 -8 -8 -14v-80c0 -6 3 -10 8 -13c41 -27 81 -55 122 -82c6 -4 11 -4 17 0c41 27 82 55 123 82c5 3 8 7 8 13zM284 175c2 2 5 2 7 0l38 -26l-93 -62v51c0 3 1 4 3 6 +c15 10 30 21 45 31zM338 171l-30 20l30 20v-40z" /> + <glyph glyph-name="ion-social-css3-outline" unicode="" horiz-adv-x="384" +d="M291 81l-99 -28l-98 28l-7 78h48l4 -40l53 -15v0v0l54 15l5 64h-112l-4 50h121l4 51h-184l-4 49h241zM0 416h384l-35 -403l-157 -45l-157 45zM319 37l30 347h-314l30 -347l127 -36z" /> + <glyph glyph-name="ion-social-css3" unicode="" horiz-adv-x="384" +d="M192 109v0zM0 416h384l-35 -403l-157 -45l-157 45zM291 81l22 252h-241l4 -49h184l-4 -51h-121l4 -50h112l-5 -64l-54 -15v0v0l-53 15l-4 40h-48l7 -78l98 -28z" /> <glyph glyph-name="ion-social-designernews-outline" unicode="" d="M259 302v-53l-65 103zM0 188zM297 352l151 -119v-201h-248l-200 156h63c46 0 77 33 77 82c0 20 -5 37 -15 51l-3 3l37 -29v-107h41l-2 98l63 -98h36v84v80zM432 48v178l-119 92v1v-47v-83v-17h-15h-37h-9l-4 8l-33 50l1 -42v-16h-16h-41h-16v16v29c-3 -6 -7 -12 -12 -17 c-8 -9 -18 -16 -30 -21s-24 -7 -38 -7h-16l159 -124h226zM59 298h-1h-3v-57h4c8 0 13 2 17 6c5 6 6 15 6 22c0 26 -12 29 -23 29zM59 314v0c25 0 39 -16 39 -45c0 -28 -14 -44 -40 -44h-19v89h20z" /> @@ -1629,19 +1869,25 @@ d="M113 371l79 -66l-114 -71l-78 63zM27 295l52 -42l86 53l-53 46zM306 235l78 -63l- l-78 -63l-114 71l79 66zM219 305l86 -52l52 42l-85 56z" /> <glyph glyph-name="ion-social-dropbox" unicode="" horiz-adv-x="384" d="M113 371l79 -66l-114 -71l-78 63zM0 172l78 62l114 -70l-79 -66zM192 164l114 70l78 -62l-113 -74zM384 297l-78 -63l-114 71l79 66zM192 150l80 -66l34 22v-25l-114 -68l-114 68v25l34 -22z" /> + <glyph glyph-name="ion-social-euro-outline" unicode="" horiz-adv-x="320" +d="M214 384c-53 0 -91 -9 -115 -27c-22 -16 -33 -40 -33 -74v-11v-17h-16h-34v-16h34h16v-15v-48v-17h-16h-34v-16h34h16v-15v-27c0 -34 11 -58 33 -74c24 -18 62 -27 115 -27c31 0 59 2 88 8l-5 35c-30 -4 -55 -7 -80 -7c-36 0 -59 6 -74 19c-19 16 -21 40 -21 60v13v15h16 +h103l3 16h-106h-16v17v48v15h16h118l2 16h-120h-16v17v2c0 16 2 39 21 55c16 13 39 19 74 19c24 0 51 -3 80 -7l5 35c-29 6 -57 8 -88 8zM214 400v0c35 0 68 -3 106 -12l-9 -65c-37 6 -68 9 -94 9c-64 0 -79 -22 -79 -58v-3h139l-8 -48h-131v-48h124l-7 -48h-117v-12 +c0 -44 15 -63 79 -63c26 0 57 3 94 9l9 -65c-38 -9 -71 -12 -106 -12c-115 0 -164 41 -164 117v26h-50v48h50v48h-50v48h50v12c0 76 49 117 164 117z" /> + <glyph glyph-name="ion-social-euro" unicode="" horiz-adv-x="320" +d="M138 176h124l-7 -48h-117v-13c0 -44 15 -63 79 -63c26 0 56 3 93 9l10 -65c-38 -9 -71 -12 -106 -12c-115 0 -164 41 -164 117v27h-50v48h50v48h-50v48h50v11c0 76 49 117 164 117c35 0 68 -3 106 -12l-10 -65c-37 6 -67 9 -93 9c-64 0 -79 -22 -79 -58v-2h138l-7 -48 +h-131v-48z" /> <glyph glyph-name="ion-social-facebook-outline" unicode="" horiz-adv-x="192" d="M128 256h64l-8 -64h-56v-192h-83v192h-45v64h45v43c0 54 23 85 91 85h56v-64h-34c-27 0 -30 -9 -30 -26v-38zM170 208l4 32h-45h-17v17v37c0 10 1 21 9 30c10 11 25 12 37 12h18v32h-40c-28 0 -49 -6 -60 -18c-10 -11 -15 -27 -15 -51v-43v-16h-15h-30v-32h30h15v-16 v-176h51v176v16h17h41z" /> <glyph glyph-name="ion-social-facebook" unicode="" horiz-adv-x="192" d="M128 256h64l-8 -64h-56v-192h-83v192h-45v64h45v43c0 54 23 85 91 85h56v-64h-34c-27 0 -30 -9 -30 -26v-38z" /> - <glyph glyph-name="ion-social-foursquare-outline" unicode="" -d="M439 298c12 -12 12 -32 0 -44l-196 -197c-6 -6 -14 -9 -22 -9h-5v0c-6 1 -13 4 -17 9l-118 119c-12 12 -12 31 0 43l35 35c6 6 13 9 21 9s16 -3 22 -9l62 -62l140 141c6 6 13 9 21 9v0c8 0 16 -3 22 -9zM221 80l194 196l-33 33l-161 -162l-84 84l-33 -33zM338 323l-77 78 -zM259 402c-10 9 -23 14 -36 14s-25 -5 -35 -14c20 18 51 18 71 0zM431 229c11 -11 17 -23 17 -37c0 -13 -6 -26 -17 -37l-170 -172c-10 -10 -25 -15 -38 -15s-27 5 -37 15l-171 172c-20 20 -20 54 0 74l171 172c1 1 1 0 2 1c10 9 22 14 35 14s26 -5 36 -14c1 -1 1 0 2 -1 -l77 -78l-23 -22l-77 77c-4 4 -9 6 -15 6s-10 -2 -14 -6l-171 -171c-8 -8 -8 -22 0 -30l171 -171c4 -4 8 -6 14 -6s11 2 15 6l171 171c8 8 8 22 0 30h-1l23 23v-1z" /> - <glyph glyph-name="ion-social-foursquare" unicode="" -d="M444 302c3 -3 4 -6 4 -10s-1 -8 -4 -11l-213 -213c-3 -3 -6 -4 -10 -4v0v0h-2c-3 0 -7 2 -9 4l-118 119c-6 6 -6 15 0 21l35 35c3 3 6 4 10 4s8 -1 11 -4l73 -73l167 167c3 3 6 5 10 5s8 -2 11 -5zM431 230v-1c11 -11 17 -23 17 -37s-6 -25 -17 -37l-170 -172 -c-20 -20 -55 -20 -75 0l-171 172c-10 10 -15 24 -15 37s5 27 15 37l171 172c10 10 24 15 38 15s27 -5 37 -15l77 -78l-116 -116l-55 55c-8 8 -18 12 -29 12s-21 -4 -29 -12l-35 -35c-8 -8 -12 -18 -12 -29s4 -21 12 -29l119 -119c5 -5 12 -10 19 -12h2h8c11 0 21 4 29 12z -" /> + <glyph glyph-name="ion-social-foursquare-outline" unicode="" horiz-adv-x="320" +d="M302 284c-12 -60 -25 -131 -27 -138zM281 416c35 0 45 -20 37 -57c-3 -16 -10 -44 -16 -75l-27 -137c-3 -13 -8 -35 -39 -35h-72c-3 0 -3 0 -6 -3c-2 -2 -115 -133 -115 -133c-9 -10 -23 -8 -28 -6s-15 8 -15 26v380s10 40 43 40h238zM280 352c6 31 6 32 -24 32h-195 +c-29 0 -29 -3 -29 -28v-297c0 -38 1 -38 3 -38s10 8 29 31c0 0 78 89 79 90c2 2 3 2 6 2h62c26 0 28 6 33 31c4 21 36 177 36 177zM302 284c6 31 13 59 16 75zM233 352c5 0 9 -5 8 -11l-8 -44c-1 -4 -6 -9 -11 -9h-75c-8 0 -8 -5 -8 -13v-6c0 -8 0 -13 8 -13h64 +s11 -6 10 -12s-11 -51 -12 -54s-4 -9 -11 -9h-62c-9 0 -11 -1 -17 -8l-54 -63c-1 -1 -1 -1 -1 0v231c0 5 5 11 11 11h158z" /> + <glyph glyph-name="ion-social-foursquare" unicode="" horiz-adv-x="320" +d="M281 416c35 0 45 -20 37 -57c-10 -49 -40 -202 -43 -213c-3 -13 -8 -34 -39 -34h-72c-3 0 -3 0 -6 -3c-2 -2 -115 -133 -115 -133c-9 -10 -23 -8 -28 -6s-15 8 -15 26v380s10 40 43 40h238zM275 146c3 11 33 164 43 213zM267 351c2 9 -5 16 -12 16h-191 +c-9 0 -15 -8 -15 -15v-296c0 -1 1 -1 2 0c0 0 70 84 78 94s11 11 23 11h64c9 0 14 8 15 12s8 43 10 51s-6 16 -13 16h-82c-10 0 -18 8 -18 18v13c0 10 8 17 18 17h96s14 6 15 12z" /> <glyph glyph-name="ion-social-freebsd-devil" unicode="" horiz-adv-x="512" d="M503 333c19 -37 8 -81 -20 -108s-60 -33 -60 -33c2 -32 16 -59 -41 -102c-43 -32 2 -90 2 -90c10 -14 23 -19 32 -32h-272s15 14 -7 32c0 0 -20 17 -18 29s6 13 9 15s0 7 0 7l-19 19s-13 -13 -44 -13c-38 0 -65 39 -65 39h46s-6 -8 -7 -13c-1 -4 1 -5 1 -5s11 -6 22 -6 c17 0 33 12 33 12l-24 22l-15 -4l-16 37l39 -10l-1 -15l28 -18s9 9 7 27s-9 26 -9 26s-4 0 -9 -4s-6 -6 -6 -6l-10 44s43 -19 50 -63c3 -20 -6 -35 -6 -35l17 -10s6 5 17 7s23 2 29 -8s5 -12 4 -19s0 -9 6 -11s6 -6 11 -8s15 -6 21 -2s8 11 8 18v16s-9 8 -32 20 @@ -1678,6 +1924,10 @@ M206 80c0 20 -13 31 -50 56c-3 0 -4 1 -8 1c-6 0 -31 -2 -50 -8c-16 -6 -38 -16 -38 d="M352 352h-320v-320h320v320zM384 384v0v-384h-384v384h384zM233 289h45l-64 -120v-72h-40v72l-66 120h47l40 -84z" /> <glyph glyph-name="ion-social-hackernews" unicode="" horiz-adv-x="384" d="M0 384h384v-384h-384v384zM214 169l64 120h-45l-38 -84l-40 84h-47l66 -120v-72h40v72z" /> + <glyph glyph-name="ion-social-html5-outline" unicode="" horiz-adv-x="384" +d="M0 416h384l-35 -403l-157 -45l-157 45zM319 37l30 347h-314l30 -347l127 -36zM84 184l-13 150h241l-4 -50h-184l4 -51h176l-14 -151l-98 -28l-99 28l-6 77h48l3 -39l54 -15l53 15l6 64h-167z" /> + <glyph glyph-name="ion-social-html5" unicode="" horiz-adv-x="384" +d="M0 416h384l-35 -403l-157 -45l-157 45zM308 284l4 50h-241l13 -150h167l-6 -64l-53 -15l-54 15l-3 39h-48l6 -78l99 -27l98 28l14 151h-176l-4 51h184z" /> <glyph glyph-name="ion-social-instagram-outline" unicode="" horiz-adv-x="384" d="M384 336v-289c0 -26 -22 -47 -48 -47h-288c-26 0 -48 21 -48 47v289c0 26 22 48 48 48h288c26 0 48 -22 48 -48zM192 272c-44 0 -80 -36 -80 -80s36 -80 80 -80s80 36 80 80s-36 80 -80 80zM352 288v48c0 9 -7 16 -16 16h-48c-9 0 -16 -7 -16 -16v-48c0 -9 7 -16 16 -16 h48c9 0 16 7 16 16zM337 32c9 0 15 7 15 16v176h-52c3 -10 4 -21 4 -32c0 -30 -11 -58 -32 -79s-50 -33 -80 -33s-58 12 -79 33s-33 49 -33 79c0 11 2 22 5 32h-53v-176c0 -9 8 -16 17 -16h288z" /> @@ -1685,12 +1935,32 @@ h48c9 0 16 7 16 16zM337 32c9 0 15 7 15 16v176h-52c3 -10 4 -21 4 -32c0 -30 -11 -5 d="M112 192c0 53 27 80 80 80s80 -27 80 -80s-27 -80 -80 -80s-80 27 -80 80zM113 271c-14 -14 -23 -29 -28 -47h-85v112c0 13 4 25 14 34s22 14 35 14h288c13 0 24 -5 33 -14s14 -21 14 -34v-112h-84c-5 18 -14 33 -28 47c-22 22 -49 33 -80 33s-57 -11 -79 -33zM352 300 v39c0 4 -2 7 -4 9s-5 4 -9 4h-38c-4 0 -7 -2 -9 -4s-4 -5 -4 -9v-39c0 -4 2 -7 4 -9s5 -3 9 -3h38c4 0 7 1 9 3s4 5 4 9zM272 113c22 22 32 48 32 79h80v-144c0 -13 -5 -24 -14 -34s-20 -14 -33 -14h-288c-13 0 -24 4 -34 14s-15 21 -15 34v144h81c0 -31 10 -57 32 -79 s48 -33 79 -33s58 11 80 33z" /> + <glyph glyph-name="ion-social-javascript-outline" unicode="" +d="M160 344h-48v-196c0 -30 -6 -50 -17 -64c-11 -13 -26 -20 -48 -20c-9 0 -18 1 -25 2l-4 -30c11 -2 25 -4 37 -4c34 0 59 8 76 25c19 18 29 48 29 90v197zM176 360v0v-213c0 -97 -49 -131 -121 -131c-18 0 -40 3 -55 8l8 62c10 -4 24 -6 39 -6c31 0 49 15 49 68v212h80z +M350 352c-34 0 -62 -9 -82 -26c-19 -15 -28 -36 -28 -60c0 -20 7 -36 21 -51c14 -14 34 -26 61 -36c23 -8 38 -15 48 -24c12 -11 18 -23 18 -38c0 -16 -7 -31 -20 -40c-12 -9 -28 -14 -48 -14c-28 0 -52 8 -70 15l-7 -32c18 -8 44 -14 72 -14c38 0 70 9 90 27 +c18 16 27 38 27 63c0 21 -5 36 -17 50s-31 27 -58 37v0v0c-38 15 -72 28 -72 63c0 14 7 27 19 36c11 9 26 13 45 13c24 0 43 -5 57 -11l10 32c-19 6 -42 10 -66 10zM350 368v0c38 0 65 -7 85 -16l-19 -64c-13 7 -35 17 -67 17s-48 -16 -48 -33c0 -22 19 -31 62 -48 +c58 -22 85 -53 85 -102c0 -57 -42 -106 -133 -106c-38 0 -72 10 -91 21l15 63v0c20 -11 49 -21 81 -21c34 0 52 15 52 38c0 21 -15 33 -55 47c-55 20 -93 52 -93 102c0 58 49 102 126 102z" /> + <glyph glyph-name="ion-social-javascript" unicode="" +d="M176 360v0v-213c0 -97 -49 -131 -121 -131c-18 0 -40 3 -55 8l8 62c10 -4 24 -6 39 -6c31 0 49 15 49 68v212h80zM350 368v0c38 0 65 -7 85 -16l-19 -64c-13 7 -35 17 -67 17s-48 -16 -48 -33c0 -22 19 -31 62 -48c58 -22 85 -53 85 -102c0 -57 -42 -106 -133 -106 +c-38 0 -72 10 -91 21l15 63v0c20 -11 49 -21 81 -21c34 0 52 15 52 38c0 21 -15 33 -55 47c-55 20 -93 52 -93 102c0 58 49 102 126 102z" /> <glyph glyph-name="ion-social-linkedin-outline" unicode="" horiz-adv-x="384" d="M119 64v0h-55v171h55v-171zM93 261v0v0c-18 0 -29 13 -29 29c0 17 12 30 30 30s29 -13 29 -30c0 -16 -12 -29 -30 -29zM257 239c36 0 63 -24 63 -75v-100h-55v94c0 22 -8 37 -28 37c-15 0 -24 -10 -28 -20c-2 -4 -2 -9 -2 -14v-97h-55v171h55v-24c8 11 21 28 50 28z M353 384c18 0 31 -13 31 -30v-321c0 -17 -13 -33 -31 -33h-320c-18 0 -33 16 -33 33v321c0 17 15 30 33 30h320zM350 32c1 0 2 1 2 2v316c0 1 -1 2 -2 2h-316s-2 -1 -2 -2v-315s1 -3 3 -3h315z" /> <glyph glyph-name="ion-social-linkedin" unicode="" horiz-adv-x="384" d="M353 384c18 0 31 -13 31 -30v-321c0 -17 -13 -33 -31 -33h-320c-18 0 -33 16 -33 33v321c0 17 15 30 33 30h320zM119 64v171h-55v-171h55zM93 261c18 0 30 13 30 29c0 17 -11 30 -29 30s-30 -13 -30 -30c0 -16 11 -29 29 -29v0zM320 64v100c0 51 -27 75 -63 75 c-29 0 -42 -17 -50 -28v24h-55v-171h55v97c0 5 0 10 2 14c4 10 13 20 28 20c20 0 28 -15 28 -37v-94h55z" /> + <glyph glyph-name="ion-social-markdown" unicode="" +d="M416 352c18 0 32 -14 32 -32v-256c0 -18 -14 -32 -32 -32h-384c-18 0 -32 14 -32 32v256c0 18 14 32 32 32h384zM252 96v0v192h-56l-42 -68l-42 68h-56v-192h56v96l42 -54l42 54v-96h56zM336 96v0l70 96h-42v96h-56v-96h-42z" /> + <glyph glyph-name="ion-social-nodejs" unicode="" horiz-adv-x="384" +d="M192 -32c-6 0 -12 2 -17 5l-53 32c-8 5 -4 6 -1 7c11 4 14 5 25 12c1 1 3 1 4 0l39 -23c1 -1 4 -1 5 0l156 92c1 1 2 2 2 4v187c0 2 0 4 -2 5l-156 94c-1 1 -3 1 -4 0l-155 -94c-2 -1 -3 -3 -3 -5v-187c0 -2 0 -3 2 -4l40 -24c24 -12 38 1 38 15v183c0 3 2 5 5 5h22 +c3 0 5 -2 5 -5v-183c0 -33 -19 -52 -49 -52c-9 0 -17 1 -37 11l-41 24c-10 6 -17 18 -17 30v190c0 12 7 24 17 30l158 95c10 6 24 6 34 0l158 -95c10 -6 17 -18 17 -30v-190c0 -12 -7 -24 -17 -30l-158 -94c-5 -3 -11 -5 -17 -5v0zM241 96c-65 0 -84 31 -84 59c0 3 1 5 4 5 +h21c2 0 5 -2 5 -4c3 -22 16 -31 54 -31c33 0 47 11 47 29c0 11 -3 18 -55 23c-43 4 -71 15 -71 51c0 33 28 52 73 52c46 0 76 -14 79 -51c0 -1 -1 -2 -2 -3s-2 -2 -3 -2h-20c-2 0 -5 2 -5 4c-4 17 -16 23 -49 23c-36 0 -41 -12 -41 -22c0 -12 5 -16 54 -23s72 -16 72 -51 +c0 -36 -29 -59 -79 -59v0v0z" /> + <glyph glyph-name="ion-social-octocat" unicode="" +d="M146 161c9 0 16 -4 22 -13s10 -20 10 -32s-4 -22 -10 -31s-14 -13 -22 -13c-9 0 -17 4 -23 13s-9 19 -9 31s3 24 9 32c6 9 14 13 23 13zM303 161c9 0 16 -4 22 -13s9 -20 9 -32s-3 -22 -9 -31s-13 -13 -22 -13s-18 4 -24 13s-9 19 -9 31s3 24 9 32c6 9 15 13 24 13z +M414 276c24 -27 34 -66 34 -96c0 -24 -1 -46 -6 -65c-6 -19 -13 -35 -21 -47c-9 -12 -19 -23 -32 -32s-24 -17 -34 -21s-22 -8 -36 -10c-13 -2 -24 -4 -31 -4c0 0 -28 -1 -64 -1s-64 1 -64 1c-7 0 -18 2 -31 4c-14 2 -26 6 -36 10s-22 12 -34 21c-13 9 -23 20 -32 32 +c-8 12 -15 28 -21 47c-5 19 -6 41 -6 65c0 31 10 70 34 96c0 0 -2 14 0 39s7 48 16 69c30 -3 67 -20 112 -51c15 4 36 6 62 6c28 0 48 -2 62 -6c20 14 39 24 58 33c19 8 33 13 41 15s13 3 13 3c9 -21 14 -44 16 -69s0 -39 0 -39v0zM348 42c28 13 42 40 42 81 +c0 24 -8 43 -26 59c-9 9 -20 13 -32 15s-31 1 -56 -1s-40 -4 -52 -4s-25 2 -42 3s-30 3 -39 3c-10 0 -20 1 -31 -2s-21 -7 -28 -14c-17 -15 -25 -35 -25 -59c0 -41 13 -68 41 -81c27 -13 69 -18 123 -18h2c54 0 95 5 123 18z" /> <glyph glyph-name="ion-social-pinterest-outline" unicode="" d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224s-224 100 -224 224s100 224 224 224zM360 56c36 36 56 85 56 136s-20 100 -56 136s-85 56 -136 56s-100 -20 -136 -56s-56 -85 -56 -136s20 -100 56 -136c14 -14 31 -25 48 -34c1 6 2 10 3 16c4 18 29 122 29 122 s-8 15 -8 36c0 33 20 58 44 58c20 0 30 -16 30 -34c0 -20 -13 -51 -20 -79c-6 -24 12 -43 35 -43c42 0 71 54 71 119c0 49 -33 85 -93 85c-68 0 -110 -50 -110 -107c0 -20 6 -33 15 -44c4 -5 5 -6 3 -12c-1 -4 -4 -14 -5 -18c-2 -6 -6 -8 -11 -6c-31 13 -46 48 -46 86 @@ -1699,6 +1969,10 @@ c0 64 54 140 160 140c86 0 142 -63 142 -129c0 -88 -49 -153 -121 -153c-24 0 -47 13 d="M224 416c124 0 224 -100 224 -224s-100 -224 -224 -224c-22 0 -44 3 -64 9c8 14 18 31 23 48c3 10 16 62 16 62c8 -15 30 -28 54 -28c72 0 121 65 121 153c0 66 -56 129 -142 129c-106 0 -160 -76 -160 -140c0 -39 15 -73 46 -86c5 -2 10 0 12 6c1 4 3 14 4 18 c2 6 1 7 -3 12c-9 11 -15 24 -15 44c0 57 42 107 110 107c60 0 94 -36 94 -85c0 -65 -29 -119 -71 -119c-24 0 -42 19 -36 43c7 28 20 59 20 79c0 18 -10 34 -30 34c-24 0 -43 -25 -43 -58c0 -21 7 -36 7 -36s-25 -104 -29 -122c-4 -17 -5 -35 -4 -51 c-79 35 -134 113 -134 205c0 124 100 224 224 224z" /> + <glyph glyph-name="ion-social-python" unicode="" horiz-adv-x="384" +d="M129 199c-29 -5 -49 -30 -49 -57v-43v-3h-15c-29 0 -54 29 -62 69c-2 9 -3 17 -3 27v1c0 53 29 95 65 95h127v16h-96v29c0 26 7 40 46 47c13 2 29 4 45 4s39 -1 55 -4c25 -4 46 -22 46 -47v-57v-31c0 -21 -14 -38 -33 -43c-4 -1 -8 -2 -13 -2h-104h3c-4 0 -8 0 -12 -1z +M140 321c10 0 17 7 17 17s-7 18 -17 18s-18 -8 -18 -18s8 -17 18 -17zM380 225c3 -10 4 -21 4 -33c0 -16 -3 -30 -7 -43c-11 -31 -33 -53 -58 -53h-127v-16h96v-26c0 -26 -23 -40 -46 -47c-35 -10 -68 -9 -97 0c-25 7 -49 22 -49 47v54v33c0 21 14 36 33 41c4 1 8 2 13 2 +h104c3 0 6 1 9 1c27 4 49 28 49 62v38v3h15c28 0 52 -26 61 -63zM244 65c-10 0 -18 -7 -18 -17s8 -18 18 -18s17 8 17 18s-7 17 -17 17z" /> <glyph glyph-name="ion-social-reddit-outline" unicode="" horiz-adv-x="449" d="M259 160c0 21 11 31 32 31s32 -10 32 -31s-11 -32 -32 -32s-32 11 -32 32zM127 160c0 21 11 31 32 31s32 -10 32 -31s-11 -32 -32 -32s-32 11 -32 32zM449 197c0 -20 -9 -36 -27 -45c1 -5 1 -9 1 -14c0 -38 -19 -71 -58 -98s-85 -40 -140 -40s-102 13 -141 40 s-58 59 -58 97c0 5 0 10 1 15c-18 9 -27 24 -27 45c0 14 5 25 15 35s21 15 35 15c13 0 24 -4 33 -13c36 25 79 39 129 41h7l29 98l86 -17c8 19 21 28 41 28c12 0 22 -4 31 -13s13 -20 13 -32s-4 -23 -13 -32s-19 -13 -31 -13s-23 4 -32 13s-13 19 -13 31l-69 14l-24 -77 @@ -1716,6 +1990,14 @@ d="M56 112c31 0 56 -25 56 -56s-25 -56 -56 -56s-56 25 -56 56s25 56 56 56zM56 16c2 c-12 28 -30 54 -52 76s-48 40 -76 52c-25 10 -51 16 -77 18v-47c50 -3 92 -22 123 -53s50 -73 53 -123h48zM0 384c212 0 384 -172 384 -384h-80c0 171 -133 304 -304 304v80zM227 228c56 -56 89 -131 93 -212h48c-8 190 -162 344 -352 352v-48c81 -4 155 -36 211 -92z" /> <glyph glyph-name="ion-social-rss" unicode="" horiz-adv-x="384" d="M56 112c31 0 56 -25 56 -56s-25 -56 -56 -56s-56 25 -56 56s25 56 56 56zM0 256c140 0 256 -116 256 -256h-80c0 48 -14 94 -48 128s-80 48 -128 48v80zM0 384c212 0 384 -172 384 -384h-80c0 171 -133 304 -304 304v80z" /> + <glyph glyph-name="ion-social-sass" unicode="" horiz-adv-x="512" +d="M512 119v-8c-1 -9 -7 -17 -15 -22s-12 -4 -13 -3s1 3 4 5c13 8 17 20 10 33c-5 10 -15 16 -26 20c-24 8 -48 7 -72 0c4 -12 7 -23 -2 -34c-10 -12 -23 -19 -39 -22c-7 -2 -14 2 -15 9c-3 19 17 36 30 47c-7 11 -11 24 -14 37c-15 -17 -31 -40 -26 -61 +c3 -14 -1 -27 -14 -36s-30 -14 -46 -11c-4 1 -6 5 -5 8c2 14 25 32 35 43c2 2 3 4 1 7c-6 12 -10 23 -14 36c-13 -29 -30 -80 -57 -98c-9 -6 -17 -4 -21 5c-3 8 -2 20 -1 29c-6 -13 -11 -27 -20 -38c-7 -8 -24 -7 -30 1c-16 21 -13 50 -5 73l-29 -15c7 -16 8 -32 4 -49 +c-5 -19 -17 -35 -35 -46c-19 -12 -64 -24 -77 4c-7 16 -4 30 6 44c17 24 48 37 74 50c-32 23 -80 42 -96 80c-15 35 17 68 43 89c59 48 166 95 244 59c15 -7 36 -24 31 -52c-4 -24 -13 -39 -28 -54c-32 -32 -152 -77 -176 -15c-1 1 -1 4 1 4c2 -1 20 -15 43 -16 +c17 -1 36 3 52 8c33 11 71 33 80 67c4 13 -2 28 -15 34c-49 24 -116 -4 -159 -26c-33 -17 -84 -45 -82 -87c1 -37 56 -60 81 -82c15 7 42 15 52 27c11 13 26 25 44 26c8 0 14 -3 16 -10c2 -6 1 -11 0 -19c5 4 11 4 15 -1c12 -14 -22 -50 -10 -66c14 14 21 42 30 59 +c4 8 17 51 26 53c7 2 18 4 25 0c2 -1 3 -3 2 -5c-7 -19 -7 -33 3 -52c14 20 29 43 34 67c1 2 3 3 5 4c7 2 18 3 25 0c3 -1 3 -2 2 -5c-7 -22 -6 -38 6 -58c31 11 69 15 97 -5c-3 2 -7 5 0 0c5 -4 3 -2 0 0c12 -8 19 -18 21 -32zM113 94v0c1 7 -1 13 -3 20 +c-24 -8 -66 -35 -64 -62c1 -10 8 -13 17 -12s19 7 27 13c14 11 22 24 23 41zM216 166c1 3 -2 5 -5 4c-29 -8 -43 -57 -33 -81c1 -3 4 -3 6 -1c17 16 28 56 32 78zM286 84c8 -3 27 17 26 27c-8 -9 -18 -18 -26 -27zM367 102c11 6 16 19 12 30c-8 -6 -21 -19 -20 -31 +c0 -2 6 0 8 1z" /> <glyph glyph-name="ion-social-skype-outline" unicode="" horiz-adv-x="384" d="M106 352c-41 0 -74 -33 -74 -73c0 -13 4 -25 10 -36l6 -11l-2 -12c-2 -10 -3 -20 -3 -30c0 -40 16 -77 44 -105s67 -44 107 -44c9 0 19 1 28 3l11 2l9 -5c11 -6 24 -9 36 -9c41 0 74 33 74 73c0 11 -3 22 -8 32l-5 10l3 11c2 10 3 21 3 32c0 40 -16 77 -44 105 s-67 43 -107 43c-9 0 -18 0 -26 -2l-12 -2l-10 7c-12 7 -26 11 -40 11zM106 384v0c21 0 40 -6 56 -16c10 2 21 2 32 2c101 0 183 -80 183 -180c0 -13 -1 -27 -4 -39c7 -14 11 -29 11 -46c0 -58 -47 -105 -106 -105c-18 0 -35 4 -50 12c-11 -2 -22 -3 -34 -3 @@ -1728,6 +2010,21 @@ d="M373 151c7 -14 11 -29 11 -46c0 -58 -47 -105 -106 -105c-18 0 -35 4 -50 12c-11 M288 104c9 12 12 25 12 40c0 12 -2 23 -7 32s-12 16 -21 22s-19 10 -31 14s-26 7 -41 10c-12 3 -20 5 -25 6s-10 4 -15 6s-7 5 -10 8c-2 3 -4 6 -4 10c0 7 3 13 11 18s19 7 32 7c14 0 25 -2 31 -7s11 -12 16 -20c4 -7 8 -11 11 -14c4 -3 9 -5 16 -5c8 0 13 3 18 8s8 11 8 17 c0 7 -2 14 -6 21s-10 14 -18 20s-18 11 -30 15s-27 5 -43 5c-20 0 -38 -2 -53 -8c-16 -6 -28 -15 -36 -25c-8 -11 -12 -22 -12 -36s3 -26 11 -36s19 -17 32 -23c13 -5 29 -10 48 -14c14 -3 26 -5 34 -8c8 -2 14 -6 19 -11c5 -4 7 -10 7 -17c0 -9 -4 -17 -13 -23 s-22 -9 -37 -9c-11 0 -20 2 -27 5s-11 6 -15 11s-8 12 -11 19s-6 11 -10 15s-10 6 -16 6c-8 0 -14 -2 -19 -7s-8 -10 -8 -17c0 -11 4 -22 12 -33s18 -19 30 -26c17 -9 39 -14 65 -14c22 0 42 3 58 10s29 16 37 28z" /> + <glyph glyph-name="ion-social-snapchat-outline" unicode="" horiz-adv-x="480" +d="M240 400v0v0c-71 0 -128 -54 -118 -128c2 -15 3 -32 4 -45c0 0 -2 -5 -12 -5c-6 0 -15 2 -28 7c-2 1 -4 1 -6 1c-8 0 -13 -6 -14 -12c0 -5 4 -11 8 -13c14 -7 47 -10 47 -33s-23 -47 -41 -64s-64 -21 -64 -21s0 -21 32 -29s32 -5 33 -13c2 -15 1 -22 11 -22c2 0 4 1 6 1 +c8 1 20 3 32 3c11 0 23 -2 34 -9c23 -15 41 -34 76 -34s53 19 76 34c11 7 24 9 35 9c12 0 23 -2 31 -3c2 0 4 -1 6 -1c10 0 9 7 11 22c1 8 1 5 33 13s32 29 32 29s-46 4 -64 21s-41 41 -41 64s33 26 47 33c4 2 9 8 9 13c-1 6 -6 12 -14 12c-2 0 -5 0 -7 -1 +c-13 -5 -21 -6 -27 -6c-10 0 -13 4 -13 4c1 13 2 30 4 45c10 74 -47 128 -118 128zM240 416v0c41 0 80 -16 105 -45c24 -28 34 -63 29 -101c-1 -11 -2 -22 -3 -31c4 1 10 2 18 5c4 1 8 2 12 2c16 0 29 -12 30 -27c1 -13 -9 -25 -18 -29c-4 -2 -9 -3 -14 -5 +c-7 -2 -14 -5 -19 -8c-4 -3 -5 -4 -5 -5c0 -16 20 -37 36 -52c11 -10 39 -16 54 -17l15 -1v-14c0 -2 0 -11 -6 -21c-5 -8 -16 -19 -38 -24c-6 -1 -11 -3 -15 -4c-2 -1 -5 -1 -7 -1v-1c-1 -7 -1 -13 -4 -18c-2 -5 -9 -12 -22 -12c-2 0 -6 0 -9 1c-2 0 -3 1 -5 1 +c-7 1 -15 2 -23 2c-10 0 -19 -2 -26 -6c-4 -3 -9 -7 -14 -10c-18 -13 -38 -27 -71 -27s-53 14 -71 27c-5 3 -9 7 -14 10c-7 4 -15 6 -25 6c-8 0 -17 -1 -24 -2c-2 0 -3 -1 -5 -1c-3 -1 -7 -1 -9 -1c-13 0 -20 7 -22 12c-3 5 -3 11 -4 18v1c-2 0 -4 0 -6 1c-4 1 -10 3 -16 4 +c-22 5 -33 16 -38 24c-6 10 -6 18 -6 20v15l15 1c16 1 44 7 54 17c29 27 36 43 36 52c0 1 0 2 -4 5c-5 3 -13 6 -20 8c-5 2 -10 3 -14 5c-9 4 -18 16 -17 29c1 15 14 27 30 27c4 0 8 0 12 -2c8 -3 13 -4 17 -5c-1 9 -2 19 -3 30c-5 38 5 74 29 102c25 29 64 45 105 45v0z +M240 219c-21 0 -41 8 -56 23c-3 3 -3 9 0 12s9 3 12 0c12 -12 27 -19 44 -19c16 0 32 7 44 19c3 3 9 3 12 0s3 -9 0 -12c-15 -15 -35 -23 -56 -23zM176 296c0 16 5 24 16 24s16 -8 16 -24s-5 -24 -16 -24s-16 8 -16 24zM272 296c0 16 5 24 16 24s16 -8 16 -24 +s-5 -24 -16 -24s-16 8 -16 24z" /> + <glyph glyph-name="ion-social-snapchat" unicode="" horiz-adv-x="480" +d="M480 88c0 -2 0 -11 -6 -21c-5 -8 -16 -19 -38 -24c-6 -1 -11 -3 -15 -4c-2 -1 -5 -1 -7 -1v-1c-1 -7 -1 -13 -4 -18c-2 -5 -9 -12 -22 -12c-2 0 -6 0 -9 1c-2 0 -3 1 -5 1c-7 1 -15 2 -23 2c-10 0 -19 -2 -26 -6c-4 -3 -9 -7 -14 -10c-18 -13 -38 -27 -71 -27 +s-53 14 -71 27c-5 3 -9 7 -14 10c-7 4 -15 6 -25 6c-8 0 -17 -1 -24 -2c-2 0 -3 -1 -5 -1c-3 -1 -7 -1 -9 -1c-13 0 -20 7 -22 12c-3 5 -3 11 -4 18v1c-2 0 -4 0 -6 1c-4 1 -10 3 -16 4c-22 5 -33 16 -38 24c-6 10 -6 18 -6 20v15l15 1c16 1 44 7 54 17c29 27 36 43 36 52 +c0 1 0 2 -4 5c-5 3 -13 6 -20 8c-5 2 -10 3 -14 5c-9 4 -18 16 -17 29c1 15 14 27 30 27c4 0 8 0 12 -2c8 -3 13 -4 17 -5c-1 9 -2 19 -3 30c-5 38 5 74 29 102c25 29 64 45 105 45v0c41 0 80 -16 105 -45c24 -28 34 -63 29 -101c-1 -11 -2 -22 -3 -31c4 1 10 2 18 5 +c4 1 8 2 12 2c16 0 29 -12 30 -27c1 -13 -9 -25 -18 -29c-4 -2 -9 -3 -14 -5c-7 -2 -14 -5 -19 -8c-4 -3 -5 -4 -5 -5c0 -16 20 -37 36 -52c11 -10 39 -16 54 -17l15 -1v-14zM192 320c-9 0 -16 -11 -16 -24s7 -24 16 -24s16 11 16 24s-7 24 -16 24zM296 242c3 3 3 9 0 12 +s-9 3 -12 0c-12 -12 -28 -19 -44 -19c-17 0 -32 7 -44 19c-3 3 -9 3 -12 0s-3 -9 0 -12c15 -15 35 -23 56 -23s41 8 56 23zM288 272c9 0 16 11 16 24s-7 24 -16 24s-16 -11 -16 -24s7 -24 16 -24z" /> <glyph glyph-name="ion-social-tumblr-outline" unicode="" horiz-adv-x="256" d="M193 52c21 0 42 6 63 20v-65c-18 -8 -34 -15 -48 -18s-28 -5 -45 -5c-19 0 -35 2 -50 7c-14 5 -28 12 -38 21s-17 18 -21 28s-6 25 -6 44v140h-48v58c16 5 30 14 42 24s19 21 26 35s11 37 14 59h62v-112h96v-64h-96v-101c0 -24 1 -40 4 -47c2 -7 7 -12 14 -16 c9 -6 19 -8 31 -8zM240 17v29c-15 -6 -31 -10 -47 -10c-15 0 -28 3 -40 10c-10 6 -17 15 -21 25c-2 6 -4 17 -4 52v117h96v32h-96v112h-32c-2 -16 -7 -36 -14 -50c-8 -16 -17 -29 -30 -40c-11 -9 -23 -17 -36 -23v-31h48v-156c0 -21 2 -32 4 -38c3 -8 10 -15 18 -22 @@ -1735,17 +2032,21 @@ c9 -8 19 -14 31 -18c13 -4 29 -6 46 -6c16 0 28 2 41 5c11 2 23 6 36 12z" /> <glyph glyph-name="ion-social-tumblr" unicode="" horiz-adv-x="256" d="M193 52c21 0 42 6 63 20v-65c-18 -8 -34 -15 -48 -18s-28 -5 -45 -5c-19 0 -35 2 -50 7c-14 5 -28 12 -38 21s-17 18 -21 28s-6 25 -6 44v140h-48v58c16 5 30 14 42 24s19 21 26 35s11 37 14 59h62v-112h96v-64h-96v-101c0 -24 1 -40 4 -47c2 -7 7 -12 14 -16 c9 -6 19 -8 31 -8z" /> - <glyph glyph-name="ion-social-tux" unicode="" horiz-adv-x="384" -d="M191 347c2 2 3 4 5 5c-3 -2 -5 -4 -7 -8c0 1 1 2 2 3zM362 52c7 -4 22 -10 22 -20s-16 -16 -42 -30s-33 -34 -61 -34s-26 17 -37 20s-35 3 -48 3s-33 -1 -42 -4s-23 -19 -38 -19s-26 9 -56 16s-60 7 -60 23s11 17 7 31s-7 25 -4 30s10 4 19 5s19 2 22 11c1 5 -2 17 5 25 -c-4 16 -2 27 10 44c17 23 14 38 23 53s32 36 37 45c9 16 9 22 8 55s-2 50 -2 50c0 33 20 60 58 60h14c38 0 64 -32 65 -69c0 -19 -6 -38 4 -67c0 0 12 -20 22 -33s37 -43 45 -68s13 -56 12 -66c-1 -6 -1 -9 -3 -11c3 -1 6 -2 8 -5c3 -4 2 -11 0 -26c-1 -8 5 -15 12 -19z -M138 -3c1 13 -4 21 -17 43s-32 58 -46 65c0 0 -4 2 -8 2s-12 3 -15 -7c-2 -7 0 -19 -2 -22c-2 -4 -9 -9 -14 -10s-22 -1 -25 -5s1 -12 5 -24s-6 -18 -7 -23s-2 -12 7 -15s33 -7 46 -9c15 -3 38 -14 51 -15c12 -1 24 7 25 20zM254 62c-2 10 -5 28 1 35c4 5 10 6 17 5 -c0 4 1 9 3 12c1 2 3 3 7 5s7 3 12 3c20 -1 24 -12 20 -6c-3 4 -9 9 -14 10c0 0 4 12 2 34c-4 40 -33 62 -33 62c27 -30 28 -58 28 -72c0 -6 -2 -18 -5 -24c-4 -1 -7 -2 -11 -4c-10 -5 -8 2 -8 10c0 10 2 20 -5 49c-5 22 -17 28 -18 33s-1 14 -9 30s-18 18 -15 34s5 22 -8 25 -s-23 8 -24 13v10c0 2 1 5 2 7l3 3c2 2 5 4 9 4c8 0 14 -6 14 -14c0 -3 -1 -7 -3 -10s-2 -3 -3 -4c-2 -2 3 -4 7 -4c3 0 5 1 7 10c1 3 1 8 1 13v0c0 14 -11 25 -23 25c-4 0 -8 -2 -12 -4c-2 -1 -4 -4 -6 -6c-1 -1 -1 -2 -1 -3h-1c-2 -4 -2 -8 -2 -12c0 -5 -1 -9 0 -13 -c0 -2 1 -3 0 -3c-2 0 -6 5 -10 5c-6 0 -10 -2 -10 -2s1 15 -3 23c-4 9 -18 16 -24 4s-2 -25 1 -31l3 -6c2 1 5 4 5 4s-6 3 -7 11c-1 9 3 14 7 15s10 -2 12 -8s1 -13 1 -13s-9 -8 -13 -11s-12 -8 -12 -11s0 -5 2 -7c3 -4 9 -8 13 -10s7 -4 15 -4s14 3 29 8c22 7 19 12 23 12 -s6 -3 4 -6s-6 -2 -22 -9s-22 -9 -28 -10s-12 -5 -27 9c-1 1 10 -17 17 -20s20 2 30 7s15 10 21 11s9 -2 5 -5s-16 -8 -23 -13s-19 -15 -27 -16s-21 16 -25 22c-5 8 -7 11 -5 -12c0 0 -6 -8 -10 -15s-6 -13 -7 -19c-1 -5 -1 -10 -1 -12s-12 -14 -18 -41s2 -58 -8 -55 -c-6 2 -16 14 -16 27s1 17 2 20c1 4 -4 -8 -4 -21s2 -17 7 -23c3 -4 45 -32 56 -42s10 -20 7 -27s-10 -11 -10 -11s5 -10 9 -19s2 -22 2 -22s4 1 4 9s-4 16 -5 19c0 0 17 -12 38 -10c25 2 41 12 54 22c18 13 13 23 15 4c2 -17 -12 -27 -10 -34c4 8 11 12 13 24s0 26 -2 36z -M157 323c0 -1 -1 -2 -1 -3v0c2 0 3 5 2 8c-1 4 -3 6 -4 6h-2c3 -2 5 -6 5 -11zM211 335c3 -2 6 -5 6 -10v-3v0c2 0 3 4 2 7s-3 6 -5 6h-3zM348 15c24 11 36 17 21 26c-17 10 -27 13 -27 29c0 5 4 16 2 22c-1 4 -6 5 -9 5l-1 -1c-7 -6 -13 -24 -33 -24s-27 19 -28 24 -c-4 2 -9 1 -12 -4c-4 -7 -3 -12 1 -36c6 -31 -5 -54 1 -64s18 -18 33 -10s28 23 52 33z" /> + <glyph glyph-name="ion-social-tux" unicode="" horiz-adv-x="383" +d="M189 347c2 2 -1 -1 0 0c2 2 4 4 6 5c-3 -2 -5 -4 -7 -8c0 1 0 2 1 3zM361 52c7 -4 23 -11 21 -22c-2 -10 -17 -15 -24 -19c-15 -8 -28 -14 -41 -25c-9 -8 -17 -15 -29 -17c-11 -2 -25 -1 -33 8c-5 5 -7 11 -15 12c-25 5 -54 4 -79 0c-13 -2 -21 -11 -32 -17 +c-10 -5 -20 -5 -30 -1c-13 5 -27 10 -41 13s-29 5 -43 9c-31 8 -5 30 -11 50c-3 12 -10 29 8 30c9 1 27 -1 31 11c2 7 -2 15 2 22s-1 17 1 25c4 18 19 32 25 49c5 14 8 25 18 37c9 11 22 22 29 34c10 18 9 35 8 55c-1 17 -1 33 -2 50c0 33 20 60 58 60h14 +c38 0 63 -32 64 -69c0 -19 -5 -38 5 -67c15 -27 36 -48 52 -73c10 -16 16 -31 20 -49c3 -14 9 -31 7 -45c-1 -6 -2 -9 -4 -11c3 -1 7 -2 9 -5c3 -4 2 -11 0 -26c-1 -8 5 -15 12 -19zM137 -3c2 20 -15 39 -25 56c-10 16 -21 43 -39 52c-8 4 -19 5 -23 -5c-2 -7 0 -19 -2 -22 +c-4 -9 -14 -10 -23 -11c-6 0 -17 0 -17 -8c1 -10 10 -20 7 -30c-2 -7 -8 -12 -8 -19c0 -14 38 -15 47 -17c19 -4 37 -14 57 -16c12 -1 25 7 26 20zM253 62c-2 10 2 -10 0 0s-5 28 1 35c4 5 10 6 17 5c0 4 1 9 3 12c8 13 29 8 39 0l-1 2c-3 4 -8 9 -13 10c0 0 4 12 2 34 +c-4 40 -33 62 -33 62c27 -30 27 -58 27 -72c0 -6 -1 -18 -4 -24c-4 -1 -7 -2 -11 -4c-10 -5 -8 2 -8 10c0 18 -2 36 -7 54c-3 9 -7 17 -13 24c-4 5 -4 9 -5 15c-3 12 -9 22 -16 32c-7 9 -7 17 -5 28c1 7 2 14 -6 17c-6 2 -26 5 -27 14c-1 6 -1 16 5 20c16 14 30 -11 17 -24 +c-3 -3 7 -4 8 -4c4 1 4 7 5 10c1 4 1 9 1 13c0 17 -18 32 -34 21c-6 -4 -9 -11 -10 -17c0 -2 -1 -20 0 -20c-4 0 -7 5 -11 5c-3 0 -7 0 -10 -1c0 0 2 14 -2 22c-4 9 -18 16 -24 4s-3 -25 0 -31s4 -6 4 -6c2 1 5 4 5 4s-6 3 -7 11c-1 9 3 14 7 15s10 -2 12 -8s0 -13 0 -13 +c-7 -6 -30 -18 -22 -28c14 -18 33 -15 52 -9c8 3 18 5 24 12c3 3 11 2 8 -4c-2 -5 -18 -7 -22 -9c-9 -4 -18 -8 -28 -10c-6 -1 -13 -5 -28 9c7 -6 8 -16 17 -20c13 -6 33 9 44 15c1 1 16 5 14 0c-1 -4 -11 -7 -15 -9c-11 -6 -23 -21 -36 -22c-8 -1 -21 16 -25 22 +c-1 1 -5 9 -6 4c-1 -8 2 -14 -3 -21c-6 -9 -11 -18 -13 -29c-1 -6 0 -11 -3 -16c-11 -15 -17 -33 -19 -51c0 -4 3 -43 -5 -41c-18 5 -17 33 -14 47c-3 -12 -8 -30 2 -44c12 -15 99 -55 53 -80c7 -14 14 -25 12 -41c8 7 2 20 -1 28c0 0 17 -12 38 -10c17 2 32 7 46 16 +c6 4 11 9 16 14c1 2 4 6 6 7l1 -11c2 -17 -12 -27 -10 -34c4 8 11 14 13 24c3 12 0 24 -2 36zM155 323v0v-3c2 0 2 5 1 8c-1 4 -3 6 -4 6h-2c3 -2 5 -6 5 -11zM210 335c3 -2 0 0 0 0c3 -2 5 -5 5 -10v-3c2 0 3 4 2 7s-3 6 -5 6h-2zM347 15c24 11 -24 -10 0 0 +c24 11 35 17 20 26c-17 10 -26 13 -26 29c0 5 4 16 2 22c-1 4 -6 5 -9 5c-10 -10 -17 -25 -34 -25c-14 0 -25 11 -28 24c-4 2 -10 1 -13 -4c-6 -12 1 -29 3 -41c2 -18 -4 -35 -2 -53c2 -21 26 -22 40 -13c16 10 29 22 47 30z" /> + <glyph glyph-name="ion-social-twitch-outline" unicode="" horiz-adv-x="416" +d="M32 416h384v-272l-112 -112h-80l-64 -64h-64v64h-96v304zM368 160v208h-304v-272h80v-64l64 64h96zM272 176v129h48v-129h-48zM160 176v129h48v-129h-48z" /> + <glyph glyph-name="ion-social-twitch" unicode="" horiz-adv-x="416" +d="M32 416h384v-272l-112 -112h-80l-64 -64h-64v64h-96v304zM208 176v129h-48v-129h48zM320 176v129h-48v-129h48z" /> <glyph glyph-name="ion-social-twitter-outline" unicode="" horiz-adv-x="472" d="M472 338c-13 -20 -29 -36 -48 -50v-12c0 -128 -98 -276 -276 -276c-55 0 -105 16 -148 44c8 -1 15 -2 23 -2c45 0 87 16 120 42c-42 1 -78 29 -90 67c6 -1 12 -2 18 -2c9 0 18 2 26 4c-44 9 -78 48 -78 95v1c13 -7 28 -12 44 -12c-26 17 -43 47 -43 81c0 18 5 34 13 48 c48 -59 119 -97 199 -101c-2 7 -2 14 -2 22c0 54 43 97 97 97c28 0 52 -12 70 -31c22 4 43 13 62 24c-7 -23 -23 -42 -43 -54c20 2 39 7 56 15zM414 301c3 2 8 6 11 8c-2 0 -11 -2 -19 -1s-21 5 -21 5s14 13 18 17l11 11c-4 -1 -10 -2 -14 -3l-8 -2l-6 6 @@ -1778,6 +2079,13 @@ c6 3 12 5 18 5c7 0 13 -3 18 -7c8 -7 13 -12 16 -18c6 -11 12 -24 16 -37c13 -44 26 d="M445 334c7 -33 1 -66 -13 -97s-31 -59 -51 -87c-26 -36 -52 -71 -85 -101c-19 -18 -41 -35 -66 -44c-31 -11 -52 -5 -71 22c-14 19 -22 40 -28 63c-12 45 -25 90 -38 134c-4 12 -9 22 -15 33c-3 5 -8 10 -12 14c-5 4 -11 3 -17 0c-10 -6 -28 -18 -28 -18l-21 27 c26 24 82 71 82 71c11 9 33 25 48 27c21 3 38 -4 50 -22c11 -17 15 -37 18 -57c7 -41 11 -82 23 -122c3 -10 8 -20 13 -29c7 -11 15 -13 25 -5c4 3 7 6 10 10c20 24 37 52 48 81c3 9 3 17 3 27c0 13 -10 25 -25 26s-24 -1 -39 -7c6 24 24 62 54 84c29 21 71 24 94 16 s36 -23 41 -46z" /> + <glyph glyph-name="ion-social-whatsapp-outline" unicode="" +d="M178 294c4 -11 15 -39 16 -42s2 -6 0 -10s-3 -6 -6 -9s-6 -7 -9 -9c-3 -3 -6 -6 -3 -12s14 -24 30 -39c21 -20 38 -27 44 -30s9 -3 12 1s15 16 19 21s8 5 13 3s31 -17 37 -20s10 -5 11 -7s0 -13 -5 -26s-28 -24 -38 -25s-11 -8 -67 16s-90 84 -93 88s-22 31 -21 58 +s17 41 22 46s11 7 15 7h10s9 0 13 -11zM228 384c-50 0 -97 -20 -133 -55c-35 -35 -55 -81 -55 -131c0 -34 9 -67 27 -96l8 -13l-5 -14l-19 -57l61 19l13 4l12 -6c28 -15 59 -23 91 -23c50 0 97 19 133 54c35 35 55 82 55 132s-20 96 -55 131c-36 35 -83 55 -133 55zM228 416 +v0c121 0 220 -97 220 -218s-99 -218 -220 -218c-39 0 -74 10 -106 27l-122 -39l40 117c-20 33 -32 72 -32 113c0 121 99 218 220 218z" /> + <glyph glyph-name="ion-social-whatsapp" unicode="" +d="M228 416c121 0 220 -97 220 -218s-99 -218 -220 -218c-39 0 -74 10 -106 27l-122 -39l40 117c-20 33 -32 72 -32 113c0 121 99 218 220 218zM337 115c5 13 6 24 5 26s-5 4 -11 7s-32 18 -37 20s-9 2 -13 -3s-16 -17 -19 -21s-6 -4 -12 -1s-23 10 -44 30 +c-16 15 -27 33 -30 39s0 9 3 12c3 2 6 6 9 9s4 5 6 9s1 7 0 10s-12 31 -16 42s-10 11 -13 11h-10s-10 -2 -15 -7s-21 -19 -22 -46s18 -54 21 -58s37 -64 93 -88s57 -17 67 -16s33 12 38 25z" /> <glyph glyph-name="ion-social-windows-outline" unicode="" d="M432 167h-216v-149l216 -32v181zM448 183v0v-215l-248 36v179h248zM168 167h-152v-120l152 -22v142zM184 183v0v-177l-184 27v150h184zM432 398v0l-216 -31v-152h216v183zM448 416v0v-217h-248v182zM168 360v0l-152 -22v-123h152v145zM184 378v0v-179h-184v153z" /> <glyph glyph-name="ion-social-windows" unicode="" @@ -1796,6 +2104,11 @@ d="M289 380c11 0 21 1 31 4l-128 -213v-171c-10 4 -21 4 -32 4s-22 0 -32 -4v171l-12 v-5v-151c6 1 11 0 16 0s11 1 16 0v151v5z" /> <glyph glyph-name="ion-social-yahoo" unicode="" horiz-adv-x="320" d="M289 380c11 0 21 1 31 4l-128 -213v-171c-10 4 -21 4 -32 4s-22 0 -32 -4v171l-128 213c10 -4 21 -4 32 -4s22 0 32 4l96 -160l96 160c10 -4 22 -4 33 -4z" /> + <glyph glyph-name="ion-social-yen-outline" unicode="" horiz-adv-x="384" +d="M384 416l-112 -208h48v-48h-73l-15 -31v-17h88v-48h-88v-96h-80v96h-88v48h88v17l-14 31h-74v48h48l-112 208h80l112 -221l112 221h80zM304 192h-59l13 24l99 184v0h-43l-122 -240l-122 240h-43l99 -184l13 -24h-59v-16h68l20 -44v-36h-88v-16h88v-96h48v96h88v16h-88v37 +l21 43h67v16z" /> + <glyph glyph-name="ion-social-yen" unicode="" horiz-adv-x="384" +d="M384 416l-112 -208h48v-48h-73l-15 -31v-17h88v-48h-88v-96h-80v96h-88v48h88v17l-14 31h-74v48h48l-112 208h80l112 -221l112 221h80z" /> <glyph glyph-name="ion-social-youtube-outline" unicode="" horiz-adv-x="512" d="M265 352v0h-9h-9c-65 0 -118 -2 -168 -4h-1h-1c-23 0 -42 -22 -42 -49v-1v-1c-2 -34 -3 -70 -3 -105v0v0c0 -35 1 -70 3 -104v-2v-1c0 -14 5 -26 14 -36c8 -9 17 -13 28 -13h1h1c52 -2 108 -4 166 -4h11v0v0h11c58 0 113 2 166 4h1h1c11 0 20 4 28 13c9 10 14 22 14 36v1 v2c2 34 3 68 3 104v0v0c0 36 -1 71 -3 105v1v2c0 27 -19 49 -42 49h-1h-1c-49 2 -103 3 -168 3zM265 384v0c58 0 115 0 170 -3c41 0 74 -36 74 -81c2 -36 3 -72 3 -108s-1 -71 -3 -107c0 -45 -33 -81 -74 -81c-55 -3 -111 -4 -168 -4h-11h-11c-57 0 -113 1 -168 4 @@ -1803,6 +2116,16 @@ c-41 0 -74 36 -74 81c-2 36 -3 71 -3 107s2 71 4 107c0 45 32 82 73 82c55 2 112 3 1 <glyph glyph-name="ion-social-youtube" unicode="" horiz-adv-x="512" d="M509 299c2 -36 3 -71 3 -107s-1 -71 -3 -107c0 -45 -33 -81 -74 -81c-58 -3 -118 -4 -179 -4s-121 1 -179 4c-41 0 -74 36 -74 81c-2 36 -3 71 -3 107s2 71 4 107c0 45 32 81 73 81c55 3 112 4 170 4h9h9c58 0 115 -1 170 -4c41 0 74 -36 74 -81zM207 94l145 98l-145 99 v-197z" /> + <glyph glyph-name="ion-soup-can-outline" unicode="" horiz-adv-x="320" +d="M160 304c-88 0 -160 29 -160 64s72 64 160 64s160 -29 160 -64s-72 -64 -160 -64zM160 415c-70 0 -126 -19 -126 -43s56 -43 126 -43s126 19 126 43s-56 43 -126 43zM161 288c88 0 158 29 159 64c0 -5 0 -33 -8 -40v-240c0 -35 -64 -64 -152 -64s-152 29 -152 64v240 +c-8 6 -8 40 -8 40c0 -35 73 -64 161 -64zM280 72v80c-18 -10 -43 -17 -72 -21h-2c-6 -20 -24 -35 -46 -35s-40 15 -46 35h-2c-29 4 -54 11 -72 21v-80c1 -2 9 -10 30 -18c24 -9 55 -14 90 -14s67 5 91 14c21 8 29 16 29 18zM280 184v91c-33 -12 -75 -19 -119 -19 +c-45 0 -87 7 -121 19v-91c18 -10 43 -17 73 -21h3c7 17 24 29 44 29s37 -12 44 -29h3c30 4 55 11 73 21zM178 -16zM160 -16h1h-1v0zM312 32l8 -16c0 -7 -3 -14 -8 -20c-21 -26 -81 -44 -152 -44s-131 18 -152 44c-5 6 -8 13 -8 20l8 16v16c0 -35 63 -64 152 -64 +s152 28 152 64v-16z" /> + <glyph glyph-name="ion-soup-can" unicode="" horiz-adv-x="320" +d="M0 368c0 43 53 64 160 64s160 -21 160 -64s-53 -64 -160 -64s-160 21 -160 64zM160 8c-44 0 -80 6 -109 18s-43 28 -43 46v128c0 -9 4 -19 13 -27s21 -15 37 -21s33 -10 54 -13c1 -12 7 -23 16 -31s20 -12 32 -12s23 4 32 12s15 19 16 31c31 4 56 12 75 23s29 24 29 38 +v-128c0 -18 -14 -34 -43 -46s-65 -18 -109 -18zM160 288c44 0 82 6 113 18s47 28 47 46v-8c0 -5 -1 -11 -2 -18s-3 -11 -6 -14v-96c0 -14 -10 -27 -29 -38s-44 -19 -76 -23c-2 11 -8 19 -17 26s-19 11 -30 11s-21 -4 -30 -11s-15 -15 -17 -26c-32 4 -57 12 -76 23 +s-29 24 -29 38v96c-5 5 -8 18 -8 40c0 -18 16 -34 47 -46s69 -18 113 -18zM312 56v-24l8 -16c0 -7 -3 -14 -8 -20c-11 -13 -30 -24 -58 -32s-59 -12 -94 -12s-66 4 -94 12s-47 19 -58 32c-5 6 -8 13 -8 20l8 16v24c0 -18 14 -34 43 -46s65 -18 109 -18s80 6 109 18 +s43 28 43 46z" /> <glyph glyph-name="ion-speakerphone" unicode="" d="M39 266c0 -37 20 -69 50 -86c-1 0 -2 1 -3 1s-4 1 -5 1v0c-35 3 -62 33 -69 69c-6 0 -12 7 -12 16c0 8 5 15 11 16c6 42 40 75 81 75h8c-36 -15 -61 -51 -61 -92zM433 357c10 -25 15 -56 15 -88s-5 -63 -15 -88l-3 -9c-6 -14 -15 -26 -24 -34c-10 -10 -22 -19 -34 -20h-3 c-7 0 -15 2 -22 5c-3 2 -10 5 -10 5c-22 10 -84 28 -115 29c-4 -8 -10 -20 -12 -30c-2 -9 -6 -27 -7 -61c-1 -32 1 -59 3 -82c0 -2 1 -5 1 -7c0 -6 -2 -9 -9 -9h-77c-6 0 -9 3 -9 6v7c2 72 25 140 26 145c2 9 5 17 7 30c2 12 -27 13 -40 24c-29 17 -47 49 -47 86 @@ -1813,8 +2136,8 @@ d="M312 192l8 -8l-64 -84v-4c0 -18 -14 -32 -32 -32s-32 14 -32 32s14 32 32 32h4zM2 l16 27c-25 13 -52 21 -81 22v-32h-16v32c-29 -1 -56 -9 -81 -22l16 -27l-14 -8l-16 27c-12 -8 -23 -16 -33 -26s-19 -21 -26 -33l28 -16l-8 -13l-28 15c-13 -25 -21 -52 -22 -81h32v-16h-32c1 -31 11 -61 26 -88h-36c-14 29 -22 62 -22 96c0 124 100 224 224 224z" /> <glyph glyph-name="ion-spoon" unicode="" horiz-adv-x="128" d="M128 288c0 64 -26 128 -64 128s-64 -64 -64 -128v0c1 -25 16 -54 37 -64l1 -1v0c3 -2 10 -6 10 -10c0 0 -16 -199 -16 -210s4 -20 10 -26s14 -9 22 -9v0v0c8 0 16 3 22 9s10 13 10 26s-16 210 -16 210c0 4 7 8 10 10l1 1c22 10 37 38 37 64z" /> - <glyph glyph-name="ion-star" unicode="" horiz-adv-x="384" -d="M384 240l-119 -89l47 -151l-120 96l-120 -96l47 151l-119 89h147l45 144l45 -144h147z" /> + <glyph glyph-name="ion-star" unicode="" +d="M448 248l-139 -104l55 -176l-140 112l-140 -112l55 176l-139 104h172l52 168l53 -168h171z" /> <glyph glyph-name="ion-stats-bars" unicode="" horiz-adv-x="352" d="M96 32v320h64v-320h-64zM0 32v96h64v-96h-64zM192 32v160h64v-160h-64zM288 32v224h64v-224h-64z" /> <glyph glyph-name="ion-steam" unicode="" horiz-adv-x="512" @@ -1836,6 +2159,9 @@ d="M320 240c26 0 48 -22 48 -48s-22 -48 -48 -48s-48 22 -48 48s22 48 48 48zM320 32 <glyph glyph-name="ion-toggle" unicode="" d="M320 288h-192c-53 0 -96 -43 -96 -96s43 -96 96 -96h192c53 0 96 43 96 96s-43 96 -96 96zM320 320v0c71 0 128 -57 128 -128s-57 -128 -128 -128h-192c-71 0 -128 57 -128 128s57 128 128 128h192zM128 240c-26 0 -48 -22 -48 -48s22 -48 48 -48s48 22 48 48 s-22 48 -48 48zM128 272v0c44 0 80 -36 80 -80s-36 -80 -80 -80s-80 36 -80 80s36 80 80 80z" /> + <glyph glyph-name="ion-transgender" unicode="" horiz-adv-x="512" +d="M368 448h144v-144h-40v76l-101 -100c8 -17 13 -36 13 -56c0 -63 -46 -115 -104 -126v-52h72v-46h-72v-64h-48v64h-72v46h72v52c-59 11 -104 63 -104 126c0 20 5 39 13 56l-22 22l-36 -36l-33 33l36 36l-46 45v-76h-40v144h144v-40h-70l43 -42l36 36l33 -33l-36 -36 +l17 -17c23 22 54 36 89 36c27 0 53 -8 74 -23c0 0 6 -5 15 -13l93 92h-70v40zM256 144c44 0 80 36 80 80s-36 80 -80 80s-80 -36 -80 -80s36 -80 80 -80z" /> <glyph glyph-name="ion-trash-a" unicode="" horiz-adv-x="352" d="M261 320v0h91v-32h-9s-5 -1 -8 -4s-4 -9 -4 -9l-19 -241c-2 -29 -2 -34 -36 -34h-200c-34 0 -34 5 -36 34l-19 242s-1 6 -4 9s-8 3 -8 3h-9v32h91v29c0 19 14 35 34 35h101c20 0 35 -16 35 -35v-29zM112 349v-29h128v29c0 10 -9 15 -19 15h-91c-10 0 -18 -5 -18 -15z M104 64h20l-10 192h-21zM187 64v192h-22v-192h22zM249 64l10 192h-20l-11 -192h21z" /> @@ -1845,11 +2171,16 @@ h-208c-15 0 -15 3 -17 15l-19 242c-1 12 0 15 17 15h246z" /> <glyph glyph-name="ion-trophy" unicode="" d="M448 345c0 -25 2 -73 -22 -122c-15 -30 -36 -55 -63 -75c-23 -16 -49 -28 -77 -35c-16 -17 -32 -27 -46 -31v-33s0 -49 99 -49h13v-32h-256v32h13c85 0 97 35 99 46v36c-14 4 -30 14 -46 31c-28 7 -55 19 -77 35c-27 20 -48 45 -63 75c-17 36 -21 71 -22 97v0v11v0v21v0 h80c-2 35 0 64 0 64h143h1h1h142s2 -29 0 -64h81v-7zM51 237c17 -34 43 -61 77 -78c-22 40 -33 84 -42 135c-1 8 -2 17 -3 26h-51c1 -23 5 -53 19 -83zM397 237c14 30 18 60 19 83h-51c-1 -9 -3 -18 -4 -26c-9 -51 -20 -95 -42 -135c34 17 61 43 78 78z" /> + <glyph glyph-name="ion-tshirt-outline" unicode="" +d="M146 362l-104 -31l11 -32l39 4l38 5l-2 -38l-14 -255h220l-14 255l-2 38l38 -5l39 -4l11 32l-104 31c-6 -8 -13 -14 -21 -19c-15 -10 -34 -15 -57 -15v0v0c-34 1 -59 11 -78 34zM288 400v0l160 -48l-32 -88l-64 8l16 -289h-288l16 289l-64 -8l-32 88l160 48 +c14 -27 31 -39 64 -40c33 0 50 13 64 40z" /> + <glyph glyph-name="ion-tshirt" unicode="" +d="M448 352l-32 -88l-64 8l16 -288h-288l16 288l-64 -8l-32 88l160 48c14 -27 31 -39 64 -40c33 0 50 13 64 40z" /> <glyph glyph-name="ion-umbrella" unicode="" d="M344 160v0v0v0zM104 160v0v0v0zM240 399c116 -8 208 -109 208 -227v-12c-4 25 -26 52 -52 52c-29 0 -52 -23 -52 -52v0c0 29 -23 52 -52 52s-49 -12 -52 -45v-135c0 -17 -6 -33 -18 -45s-29 -19 -46 -19c-35 0 -63 29 -63 64c0 9 7 16 16 16s16 -7 16 -16 c0 -18 14 -32 31 -32c18 0 32 14 32 32v134c-1 24 -26 46 -52 46c-29 0 -52 -23 -52 -52v0c0 29 -23 52 -52 52c-27 0 -49 -26 -52 -52v18c0 118 92 213 208 221v1c0 9 7 16 16 16s16 -7 16 -16v-1z" /> <glyph glyph-name="ion-university" unicode="" -d="M224 384l224 -111l-92 -60l-132 -85l-160 102v-198l-32 16v203l-32 21zM358 192l10 -82l-6 -3c-1 -1 -93 -54 -131 -99l-7 -8l-7 8c-38 45 -130 98 -131 99l-6 3l9 82l135 -88z" /> +d="M224 384l224 -111l-92 -60l-132 -85l-160 102v-198l-32 16v203l-32 21zM358 192l10 -82c-16 -12 -112 -78 -144 -110c-32 32 -128 98 -144 110l9 82l135 -88z" /> <glyph glyph-name="ion-unlocked" unicode="" horiz-adv-x="384" d="M22 -32c-12 0 -22 10 -22 22v212c0 12 10 22 22 22h3h19v31c0 42 17 87 43 115s64 46 105 46v0v0c41 0 79 -18 105 -46c20 -21 33 -51 39 -82h-53c-5 18 -13 35 -24 47v0v1c-18 19 -42 29 -67 29v0v0c-25 0 -49 -10 -67 -29v-1v0c-18 -19 -28 -53 -28 -80v-31h265 c12 0 22 -10 22 -22v-212c0 -12 -10 -22 -22 -22h-340z" /> diff --git a/public/assets/fonts/ionicons.ttf b/public/assets/fonts/ionicons.ttf Binary files differindex cc67b2f..c4e4632 100755 --- a/public/assets/fonts/ionicons.ttf +++ b/public/assets/fonts/ionicons.ttf diff --git a/public/assets/fonts/ionicons.woff b/public/assets/fonts/ionicons.woff Binary files differindex 1d7b977..5f3a14e 100755 --- a/public/assets/fonts/ionicons.woff +++ b/public/assets/fonts/ionicons.woff diff --git a/public/assets/javascripts/app.js b/public/assets/javascripts/app.js index a146325..3cafeca 100644 --- a/public/assets/javascripts/app.js +++ b/public/assets/javascripts/app.js @@ -21,44 +21,12 @@ app.init = function () { app.launch = function () { if ($.browser.msie || ! has3d()) { return app.fallback() } - var movements - - app.devicePixelRatio = is_mobile ? devicePixelRatio : 1 - - scene = new MX.Scene().addTo('#scene') - scene.width = window.innerWidth - scene.height = window.innerHeight - scene.perspective = window.innerHeight - - window.onresize = function () { - scene.width = window.innerWidth - scene.height = window.innerHeight - scene.perspective = window.innerHeight - scene.update() - } - - cam = scene.camera - cam.y = viewHeight - - if (MX.Map) map = app.map = new MX.Map() - - if (is_mobile) { - app.movements = new MX.MobileMovements(cam, viewHeight) - } - else { - app.movements = new MX.Movements(cam, viewHeight) - } - app.movements.init() - var last_t = 0 function animate (t) { var dt = t - last_t last_t = t requestAnimationFrame(animate) - environment.update(t) - window.path && path.update(t) - app.movements.update(dt || 0) - scene.update() + environment.update(t, dt) } var loader = new Loader(function(){ diff --git a/public/assets/javascripts/defaults.js b/public/assets/javascripts/defaults.js index 12aed62..1e1ac5b 100644 --- a/public/assets/javascripts/defaults.js +++ b/public/assets/javascripts/defaults.js @@ -1,5 +1,7 @@ +app = window.app || {} app.defaults = { viewHeight: window.viewHeight = 186, + wallHeight: 397, units: app.units = "ft", footResolution: 36, meterResolution: 100, @@ -13,7 +15,7 @@ app.defaults = { }, } -marked.setOptions({ +window.marked && marked.setOptions({ sanitize: true, smartypants: true, }) diff --git a/public/assets/javascripts/mx/extensions/mx.movements.js b/public/assets/javascripts/mx/extensions/mx.movements.js index 9af2c8d..3e34c1b 100644 --- a/public/assets/javascripts/mx/extensions/mx.movements.js +++ b/public/assets/javascripts/mx/extensions/mx.movements.js @@ -20,7 +20,7 @@ MX.Movements = function (cam) { rotationX_max = PI/6 var v = 12, - vr = Math.PI * 0.012, + vr = Math.PI * 0.018, jumpV = 23, vx = vy = vz = 0, creepFactor = 0.3 @@ -39,7 +39,7 @@ MX.Movements = function (cam) { }) function clampRotation( vr ) { - if (Rooms.mover.noclip) { + if (window.Rooms && Rooms.mover.noclip) { return clamp(vr, PI/-2, PI/2 ) } else { @@ -155,6 +155,9 @@ MX.Movements = function (cam) { app.controller.presets.hide() $(".inuse").removeClass("inuse") } + else if (Rooms.shapesMode) { + // don't show map in editor for now.. + } else { app.controller.toolbar.toggleMap() } @@ -162,10 +165,13 @@ MX.Movements = function (cam) { case 8: // backspace e.preventDefault() - if (app.controller.mediaEditor.scenery) { + if (app.controller.sculptureEditor && app.controller.sculptureEditor.sculpture) { + app.controller.sculptureEditor.sculpture.remove() + } + else if (app.controller.mediaEditor && app.controller.mediaEditor.scenery) { app.controller.mediaEditor.scenery.remove() } - else if (app.controller.textEditor.scenery) { + else if (app.controller.textEditor && app.controller.textEditor.scenery) { app.controller.textEditor.scenery.remove() } } @@ -221,15 +227,19 @@ MX.Movements = function (cam) { /* case 48: // 0 - cam.rotationX = 0 - cam.rotationY = 0 - cam.x = 0 - cam.y = viewHeight - cam.z = 0 + movements.center() break */ } }, + + center: function(){ + cam.rotationX = 0 + cam.rotationY = 0 + cam.x = 0 + cam.y = viewHeight + cam.z = 0 + }, mousedown: function (e) { if (locked) return; @@ -341,7 +351,7 @@ MX.Movements = function (cam) { jumping = false } - var ceiling = (Rooms.mover.room ? Rooms.mover.room.height : 5000) + var ceiling = ((window.Rooms && Rooms.mover.room) ? Rooms.mover.room.height : 5000) if (pos.y >= ceiling-5) { vy = 0 diff --git a/public/assets/javascripts/mx/extensions/mx.orbitCamera.js b/public/assets/javascripts/mx/extensions/mx.orbitCamera.js new file mode 100644 index 0000000..a936cef --- /dev/null +++ b/public/assets/javascripts/mx/extensions/mx.orbitCamera.js @@ -0,0 +1,97 @@ +MX.OrbitCamera = function(opt){ + var exports = {}, bound = false + exports.opt = opt = defaults(opt, { + el: window, // object to bind events on + camera: scene.camera, // camera object we'll be moving + radius: 100, + radiusRange: [ 10, 1000 ], + rotationX: PI/2, + rotationY: 0, + center: { x: 0, y: 0, z: 0 }, + sensitivity: 10, // moving 1 pixel is like moving N radians + wheelSensitivity: 10, + ease: 10, + }) + var rx, ry, radius, px, py, epsilon = 1e-10, dragging = false + exports.init = function(){ + ry = opt.rotationY + rx = opt.rotationX + radius = opt.radius + exports.wheel = new wheel({ + el: opt.el, + update: function(e, delta){ + opt.radius = clamp( opt.radius + delta * opt.wheelSensitivity, opt.radiusRange[0], opt.radiusRange[1] ) + }, + }) + exports.bind() + } + exports.toggle = function(state){ + if (state) exports.bind() + else exports.unbind() + } + exports.bind = function(){ + if (bound) return; + bound = true + opt.el.addEventListener("mousedown", down) + window.addEventListener("mousemove", move) + window.addEventListener("mouseup", up) + exports.wheel.unlock() + } + exports.unbind = function(){ + if (! bound) return; + bound = false + opt.el.removeEventListener("mousedown", down) + window.removeEventListener("mousemove", move) + window.removeEventListener("mouseup", up) + exports.wheel.lock() + } + function down (e) { + px = e.pageX + py = e.pageY + dragging = true + } + function move (e) { + if (! dragging) return + exports.delta(px- e.pageX, py - e.pageY) + px = e.pageX + py = e.pageY + } + function up (e) { + dragging = false + } + exports.delta = function(x,y){ + opt.rotationY += x/window.innerWidth * opt.sensitivity + opt.rotationX = clamp( opt.rotationX + y/window.innerHeight * opt.sensitivity, 0, PI) + } + exports.move = function(y, x){ + opt.rotationY = y + if (typeof x == "number") { opt.rotationX = x } + } + exports.update = function(){ + if (! bound) return + if (abs(ry - opt.rotationY) > epsilon) { + ry = avg(ry, opt.rotationY, opt.ease) + } + else { + ry = opt.rotationY + } + if (abs(rx - opt.rotationX) > epsilon) { + rx = avg(rx, opt.rotationX, opt.ease) + } + else { + rx = opt.rotationX + } + if (abs(radius - opt.radius) > epsilon) { + radius = avg(radius, opt.radius, opt.ease) + } + else { + radius = opt.radius + } + opt.camera.x = opt.center.x + radius * sin(rx) * cos(ry) + opt.camera.y = opt.center.y + radius * cos(rx) + opt.camera.z = opt.center.z + radius * sin(rx) * sin(ry) + opt.camera.rotationX = PI/2 - rx + opt.camera.rotationY = ry + PI/2 + } + return exports +} diff --git a/public/assets/javascripts/mx/mx.js b/public/assets/javascripts/mx/mx.js index ab9a9a0..60651eb 100644 --- a/public/assets/javascripts/mx/mx.js +++ b/public/assets/javascripts/mx/mx.js @@ -25,7 +25,7 @@ var MX = MX || (function (undefined) { var MX = { version: '0.1.0', prefix: undefined, - rotationUnit: 'rad' + rotationUnit: 'rad', } var floatPrecision = 5 @@ -162,24 +162,24 @@ var MX = MX || (function (undefined) { Object.defineProperty(this, 'width', { get: function () { return width - || parseInt(self.el.style.width, 10) * app.devicePixelRatio + || parseInt(self.el.style.width, 10) * app_devicePixelRatio || 0 }, set: function (val) { width = val - this.el.style.width = (width/app.devicePixelRatio) + 'px' + this.el.style.width = (width/app_devicePixelRatio) + 'px' } }) Object.defineProperty(this, 'height', { get: function () { return height - || parseInt(self.el.style.height, 10) * app.devicePixelRatio + || parseInt(self.el.style.height, 10) * app_devicePixelRatio || 0 }, set: function (val) { height = val - this.el.style.height = (height/app.devicePixelRatio) + 'px' + this.el.style.height = (height/app_devicePixelRatio) + 'px' } }) } @@ -302,9 +302,9 @@ var MX = MX || (function (undefined) { + (-this.y).toFixed(floatPrecision) + 'px,' + (-this.z).toFixed(floatPrecision) + 'px) ' + 'scale3d(' - + (app.devicePixelRatio * this.scaleX).toFixed(floatPrecision) + ',' - + (app.devicePixelRatio * this.scaleY).toFixed(floatPrecision) + ',' - + (app.devicePixelRatio * this.scaleZ).toFixed(floatPrecision) + ') ' + + (app_devicePixelRatio * this.scaleX).toFixed(floatPrecision) + ',' + + (app_devicePixelRatio * this.scaleY).toFixed(floatPrecision) + ',' + + (app_devicePixelRatio * this.scaleZ).toFixed(floatPrecision) + ') ' if (rotationTranslation) { transformString += rotationTranslation.before diff --git a/public/assets/javascripts/mx/primitives/mx.grid.js b/public/assets/javascripts/mx/primitives/mx.grid.js new file mode 100644 index 0000000..a765c89 --- /dev/null +++ b/public/assets/javascripts/mx/primitives/mx.grid.js @@ -0,0 +1,70 @@ +MX.Grid = MX.Object3D.extend({ + init: function (ops) { + + this.type = "Grid" + + var ops = this.ops = defaults(ops, { + x: 0, + y: 0, + z: 0, + space: 20, + cells: 20, + }) + + ops.side = ops.space * ops.cells + + var ctx, canvas = document.createElement("canvas") + + this.el = canvas + this.width = this.height = canvas.width = canvas.height = ops.side + 4 + + ctx = canvas.getContext('2d') + + this.x = ops.x || 0 + this.y = ops.y || 0 + this.z = ops.z || 0 + this.rotationX = PI/2 + this.scale = ops.scale || 1 + this.backface = ops.backface || false + + ops.className && this.el.classList.add(ops.className) + this.backface && this.el.classList.add("backface-visible") + this.el.classList.add("mx-grid") + + this.draw(ctx) + }, + + draw: function(ctx, recenter){ + ctx = ctx || this.ctx + + if (recenter) { + ctx.save() + ctx.translate( -grid.width/2, -grid.height/2 ) + } + + var cells = this.ops.cells, + space = this.ops.space, + side = this.ops.side + + ctx.strokeStyle = "#444" + ctx.lineWidth = 1 + ctx.beginPath() + ctx.translate(1,1) + for (var i = 0; i <= cells; i++) { + ctx.moveTo(i*space, 0) + ctx.lineTo(i*space, side) + ctx.moveTo(0, i*space) + ctx.lineTo(side, i*space) + } + ctx.closePath() + ctx.stroke() + + if (recenter) { + ctx.restore() + } + + }, + +}) + + diff --git a/public/assets/javascripts/mx/primitives/mx.image.js b/public/assets/javascripts/mx/primitives/mx.image.js index b8557bf..ce99592 100644 --- a/public/assets/javascripts/mx/primitives/mx.image.js +++ b/public/assets/javascripts/mx/primitives/mx.image.js @@ -1,6 +1,7 @@ MX.Image = MX.Object3D.extend({ init: function (ops) { - + ops = ops || {} + this.type = "Image" this.media = ops.media this.width = 0 @@ -18,7 +19,7 @@ MX.Image = MX.Object3D.extend({ this.el.style.backgroundRepeat = 'no-repeat' - this.load(ops) + ops.src && this.load(ops) }, load: function(ops){ @@ -41,8 +42,41 @@ MX.Image = MX.Object3D.extend({ layer.el.classList.add('image') layer.dirty = true layer.update() + layer.ops.onload + + if (ops.keepImage) { + layer.image = image + } + } + + if (ops.src) { + image.src = ops.src + } + else if (ops.media) { + image.src = ops.media.url + } + else if (ops.url) { + image.src = ops.url + } + }, + + draw: function(ctx, recenter){ + if (! this.image) { return } + + if (recenter) { + ctx.save() + ctx.scale(-1, 1) + ctx.translate( -this.width/2 * this.scale, -this.height/2 * this.scale ) + } + + ctx.drawImage(this.image, + 0, 0, this.image.naturalWidth, this.image.naturalHeight, + 0, 0, this.image.width * this.scale * devicePixelRatio, this.image.height * this.scale * devicePixelRatio + ) + + if (recenter) { + ctx.restore() } - image.src = ops.src; }, }) diff --git a/public/assets/javascripts/mx/primitives/mx.point.js b/public/assets/javascripts/mx/primitives/mx.point.js new file mode 100644 index 0000000..41a7732 --- /dev/null +++ b/public/assets/javascripts/mx/primitives/mx.point.js @@ -0,0 +1,17 @@ +MX.Point = MX.Object3D.extend({ + init: function(p){ + this.updateChildren = false + this.move({ + x: p.a, + y: 11, + z: p.b, + width: 20, + height: 20, + rotationX: PI/2, + }) + this.el.style.backgroundColor = 'rgb(' + [abs(floor(p.a*30)), 0, abs(floor(p.b*30))] + ')' + this.el.style.backfaceVisibility = "visible" + this.el.style.borderRadius = "50%" + scene.add(this) + } +}) diff --git a/public/assets/javascripts/mx/primitives/mx.polyline.js b/public/assets/javascripts/mx/primitives/mx.polyline.js new file mode 100644 index 0000000..e549150 --- /dev/null +++ b/public/assets/javascripts/mx/primitives/mx.polyline.js @@ -0,0 +1,57 @@ +MX.Polyline = MX.Object3D.extend({ + init: function(polyline){ + this.faces = [] + this.points = polyline.points + for (var i = 1; i < this.points.length; i++) { + var mx = new MX.Object3D() + var head = this.points[i-1] + var tail = this.points[i] + this.move_face(mx, head, tail) + this.faces.push(mx) + scene.add(mx) + } + }, + + rebuild: function(){ + for (var i = 1; i < this.points.length; i++) { + var mx = this.faces[i-1] + var head = this.points[i-1] + var tail = this.points[i] + this.move_face(mx, head, tail) + } + }, + + move_face: function (mx, head, tail){ + var mid_x = (head.a + tail.a) + var mid_z = (head.b + tail.b) + var len = head.distanceTo( tail ) + var angle = atan2( head.b - tail.b, head.a - tail.a ) + mx.move({ + x: mid_x / 2, + y: wallHeight/2 + 1, + z: mid_z / 2, + width: ceil(len), + height: wallHeight, + rotationY: angle + }) + // var hue = abs(round( angle / PI * 90 + 300)) + // mx.el.style.backgroundColor = 'hsl(' + [hue, "100%", "50%"] + ')' + var lum = abs(round( angle / PI * 20 + 70)) + mx.el.style.backgroundColor = 'hsla(' + ["0", "0%", lum + "%", "0.99"] + ')' + }, + + set_height: function(height){ + for (var i = 0; i < this.faces.length; i++) { + this.faces[i].height = height + this.faces[i].y = height / 2 + 1 + } + }, + + destroy: function(){ + this.faces.forEach(function(mx){ + scene.remove(mx) + }) + this.faces = null + this.points = null + }, +}) diff --git a/public/assets/javascripts/mx/primitives/mx.soundcloud.js b/public/assets/javascripts/mx/primitives/mx.soundcloud.js index 75286d9..fecb2f4 100644 --- a/public/assets/javascripts/mx/primitives/mx.soundcloud.js +++ b/public/assets/javascripts/mx/primitives/mx.soundcloud.js @@ -102,6 +102,11 @@ MX.Soundcloud = MX.Object3D.extend({ setLoop: function(state){ this.media.loop = state }, + + setVolume: function(n){ + if (this.muted || ! this.player) return + this.player.setVolume(floor( n * 100 )) + }, didPlay: function(){ this.paused = false diff --git a/public/assets/javascripts/mx/primitives/mx.text.js b/public/assets/javascripts/mx/primitives/mx.text.js index 6b5681b..3095b67 100644 --- a/public/assets/javascripts/mx/primitives/mx.text.js +++ b/public/assets/javascripts/mx/primitives/mx.text.js @@ -47,7 +47,7 @@ MX.Text = MX.Object3D.extend({ if (! font.color || font.color[0] == "#") { font.color = [0,0,0] } this.inner.style.fontFamily = "'" + font.family + "',sans-serif" - this.el.style.fontSize = (2 * font.size / devicePixelRatio) + "pt" + this.el.style.fontSize = (font.size / devicePixelRatio) + "pt" this.el.style.textAlign = font.align this.el.style.color = rgb_string(font.color) }, diff --git a/public/assets/javascripts/mx/primitives/mx.video.js b/public/assets/javascripts/mx/primitives/mx.video.js index c281f02..53ccf2e 100644 --- a/public/assets/javascripts/mx/primitives/mx.video.js +++ b/public/assets/javascripts/mx/primitives/mx.video.js @@ -21,6 +21,7 @@ MX.Video = MX.Object3D.extend({ this.el.classList.add("video") this.el.classList.add("mx-scenery") this.paused = !! this.media.autoplay + this.playing = false this.muted = app.muted || !! this.media.mute }, @@ -60,11 +61,13 @@ MX.Video = MX.Object3D.extend({ play: function(){ this.paused = false + this.playing = true this.player.play() }, pause: function(){ this.paused = true + this.playing = false this.player.pause() }, @@ -87,6 +90,11 @@ MX.Video = MX.Object3D.extend({ this.muted = false }, + setVolume: function(n){ + if (this.muted || ! this.player) return + this.player.volume = n + }, + setLoop: function(state){ this.media.loop = state }, diff --git a/public/assets/javascripts/mx/primitives/mx.vimeo.js b/public/assets/javascripts/mx/primitives/mx.vimeo.js index fe5ce86..af138ae 100644 --- a/public/assets/javascripts/mx/primitives/mx.vimeo.js +++ b/public/assets/javascripts/mx/primitives/mx.vimeo.js @@ -20,6 +20,7 @@ MX.Vimeo = MX.Object3D.extend({ this.backface && this.el.classList.add("backface-visible") this.el.classList.add("video") this.el.classList.add("mx-scenery") + this.playing = false this.paused = !! this.media.autoplay this.muted = app.muted || !! this.media.mute this.started = false @@ -99,7 +100,7 @@ MX.Vimeo = MX.Object3D.extend({ return } - if (! this.started || n === 0) { + if (! this.started) { return } @@ -130,6 +131,11 @@ MX.Vimeo = MX.Object3D.extend({ this.player.api('setVolume', 0.8) this.muted = false }, + + setVolume: function(n){ + if (this.muted || ! this.player) return + this.player.api('setVolume', n) + }, setLoop: function(state){ this.media.loop = state @@ -140,19 +146,26 @@ MX.Vimeo = MX.Object3D.extend({ if (this.paused) { this.pause() } + else { + this.playing = true + } }, onPause: function(){ if (! this.paused) { this.play() } + else { + this.playing = false + } }, finished: function(){ -// if (this.media.loop) { -// this.seek(0) -// this.play() -// } + console.log("vimeo finished") + if (this.media.loop) { + this.seek(0) + this.play() + } // else if (this.bound) { if (! this.media.loop && this.bound) { $(".playButton").removeClass('playing') diff --git a/public/assets/javascripts/mx/primitives/mx.youtube.js b/public/assets/javascripts/mx/primitives/mx.youtube.js index 5c92378..8cd9f59 100644 --- a/public/assets/javascripts/mx/primitives/mx.youtube.js +++ b/public/assets/javascripts/mx/primitives/mx.youtube.js @@ -21,6 +21,7 @@ MX.Youtube = MX.Object3D.extend({ this.el.classList.add("video") this.el.classList.add("mx-scenery") this.paused = !! this.media.autoplay + this.playing = false this.muted = app.muted || !! this.media.mute }, @@ -143,11 +144,13 @@ MX.Youtube = MX.Object3D.extend({ play: function(){ this.paused = false + this.playing = true this.player.playVideo() }, pause: function(){ this.paused = true + this.playing = false this.player.pauseVideo() }, @@ -173,6 +176,11 @@ MX.Youtube = MX.Object3D.extend({ this.player.setVolume(80) this.muted = false }, + + setVolume: function(n){ + if (this.muted || ! this.player || ! this.player.setVolume) return + this.player.setVolume( floor(n * 100) ) + }, setLoop: function(state){ this.media.loop = state diff --git a/public/assets/javascripts/rectangles/_env.js b/public/assets/javascripts/rectangles/_env.js index 3221bac..b3c7d66 100644 --- a/public/assets/javascripts/rectangles/_env.js +++ b/public/assets/javascripts/rectangles/_env.js @@ -1,6 +1,22 @@ var environment = new function(){} environment.init = function(){ + scene = new MX.Scene().addTo('#scene') + scene.width = window.innerWidth + scene.height = window.innerHeight + scene.perspective = window.innerHeight + + cam = scene.camera + cam.y = viewHeight + + if (is_mobile) { + app.movements = new MX.MobileMovements(cam, viewHeight) + } + else { + app.movements = new MX.Movements(cam, viewHeight) + } + app.movements.init() + map = new Map () if (window.scene) { @@ -16,10 +32,18 @@ environment.init = function(){ scene.camera.radius = 20 } - + + window.onresize = function () { + scene.width = window.innerWidth + scene.height = window.innerHeight + scene.perspective = window.innerHeight + scene.update() + } + Rooms.init() Walls.init() Scenery.init() + Sculpture.init() scene.update() environment.update() @@ -51,8 +75,13 @@ environment.init = function(){ } }) } -environment.update = function(t){ +environment.minimal = function(){ + environment.update = function(t){} +} +environment.update = function(t, dt){ + app.movements.update(dt || 0) + scene.update() map.update() - window.minimap && window.minimap.update && minimap.update() + window.minimap && minimap.update && minimap.update() z = false } diff --git a/public/assets/javascripts/rectangles/engine/map/_map.js b/public/assets/javascripts/rectangles/engine/map/_map.js index 202803a..ba3ec92 100644 --- a/public/assets/javascripts/rectangles/engine/map/_map.js +++ b/public/assets/javascripts/rectangles/engine/map/_map.js @@ -16,6 +16,7 @@ var Map = function(opt){ var base = this base.el = opt.el base.$el = $(base.el) + base.opt = opt if (! base.el) return @@ -33,7 +34,6 @@ var Map = function(opt){ scene.camera.x + sides.a, scene.camera.z + sides.b ) } - base.set_zoom = function (n) { n = clamp(n, opt.zoom_min, opt.zoom_max) base.zoom_exponent = n @@ -41,15 +41,40 @@ var Map = function(opt){ } base.set_zoom(opt.zoom) + base.resize = function(w, h){ + if (w && h) { + canvas.width = base.dimensions.a = w + canvas.height = base.dimensions.b = h + } + else { + // resize here - esp if 2d-hires + canvas.width = base.dimensions.a = base.el.parentNode.offsetWidth + canvas.height = base.dimensions.b = base.el.parentNode.offsetHeight + } + } + + base.toggle = function(state){ + return $(base.el).toggle(state).is(':visible') + } + var canvas = base.canvas = document.createElement("canvas") canvas.width = base.dimensions.a canvas.height = base.dimensions.b - + base.el.appendChild(canvas) - + switch (opt.type) { + case "ortho": + base.draw = new Map.Draw (base, { ortho: true }) + base.draw.grid_size = MAP_GRID_SIZE + base.ui = new Map.UI.Ortho (base) + base.sides = base.sides_for_center + $(window).resize(base.resize) + break + case "editor": base.draw = new Map.Draw (base) + base.draw.grid_size = MAP_GRID_SIZE base.ui = new Map.UI.Editor (base) base.sides = base.sides_for_center $(window).resize(base.resize) @@ -57,20 +82,11 @@ var Map = function(opt){ case "minimap": base.draw = new Map.Draw (base, { center: scene.camera, minimap: true }) + base.draw.grid_size = MAP_GRID_SIZE * 10 base.ui = new Map.UI.Minimap (base) base.sides = base.sides_for_camera break } - - base.resize = function(){ - canvas.width = base.dimensions.a = window.innerWidth - canvas.height = base.dimensions.b = window.innerHeight - } - - base.toggle = function(state){ - return $(base.el).toggle(state).is(':visible') - } - } Map.prototype.update = function(){ diff --git a/public/assets/javascripts/rectangles/engine/map/draw.js b/public/assets/javascripts/rectangles/engine/map/draw.js index eceda3c..4f4759f 100644 --- a/public/assets/javascripts/rectangles/engine/map/draw.js +++ b/public/assets/javascripts/rectangles/engine/map/draw.js @@ -5,24 +5,32 @@ Map.Draw = function(map, opt){ var draw = this - var ctx = map.canvas.getContext("2d") + var ctx = draw.ctx = map.canvas.getContext("2d") draw.animate = function(){ ctx.save() draw.clear() draw.fill("rgba(255,255,255,0.98)") - if (opt.minimap) { + if (opt.ortho) { + } + else if (opt.minimap) { ctx.translate( map.dimensions.a * 1/2, map.dimensions.b * 1/2) ctx.scale( map.zoom, map.zoom ) + if (map.opt.pivot) { ctx.rotate(scene.camera.rotationY + PI) } ctx.translate( opt.center.x, - opt.center.z ) ctx.scale( -1, 1 ) draw.coords() - draw.regions(Rooms.regions, [ "#fff" ], "#000") + if (Rooms.shapesMode) { + shapes.draw(draw.ctx, "#fff", null) + shapes.draw(draw.ctx, null, "#000") + } + else { + draw.regions(Rooms.regions, [ "#fff" ], "#000") + } draw.camera(scene.camera) } - else { ctx.translate( map.dimensions.a * 1/2, map.dimensions.b * 1/2) ctx.scale( map.zoom, map.zoom ) @@ -31,12 +39,19 @@ Map.Draw = function(map, opt){ draw.regions(Rooms.regions, [ "#f8f8f8" ], "#000") draw.mouse(map.ui.mouse.cursor) + draw.mouse_dimensions(map.ui.mouse.cursor) draw.coords() scene && draw.camera(scene.camera) } ctx.restore() } + draw.translate = function(){ + ctx.translate( map.dimensions.a * 1/2, map.dimensions.b * 1/2) + ctx.scale( map.zoom, map.zoom ) + ctx.translate( map.center.a, map.center.b ) + ctx.scale( -1, 1 ) + } // changes the ctx temporarily draw.render = function(){ @@ -56,9 +71,9 @@ Map.Draw = function(map, opt){ } var canvas = document.createElement("canvas") - ctx = canvas.getContext('2d') canvas.width = thumbnail_width canvas.height = thumbnail_height + ctx = canvas.getContext('2d') draw.clear() @@ -87,7 +102,7 @@ Map.Draw = function(map, opt){ ctx.putImageData(pixelData, 0, 0) // reset the ctx - ctx = map.canvas.getContext("2d") + ctx = draw.ctx return canvas } @@ -123,7 +138,8 @@ Map.Draw = function(map, opt){ ctx.beginPath(); ctx.arc(mouse.x.b, mouse.y.b, radius, 0, 2*Math.PI, false); ctx.fill(); - + } + draw.mouse_dimensions = function(mouse){ if (mouse.width() != 0 && mouse.height() != 0) { if (map.ui.dragging) { stroke_rect(mouse) @@ -159,36 +175,39 @@ Map.Draw = function(map, opt){ } draw.coords = function(){ - /* - ctx.fillStyle = "#888"; - dot_at(0,0) - ctx.fillStyle = "#bbb"; - dot_at(100,0) - dot_at(0,100) - ctx.fillStyle = "#ddd"; - dot_at(200,0) - dot_at(0,200) - ctx.fillStyle = "#eee"; - dot_at(300,0) - dot_at(0,300) - */ - ctx.strokeStyle = "rgba(0,0,0,0.1)" ctx.lineWidth = 1/map.zoom var sides = map.sides() - var quant = sides.clone().quantize(MAP_GRID_SIZE) - for (var x = quant.x.a - MAP_GRID_SIZE; x <= quant.x.b; x += MAP_GRID_SIZE) { - line(x, sides.y.a, x, sides.y.b) - } - for (var y = quant.y.a - MAP_GRID_SIZE; y <= quant.y.b; y += MAP_GRID_SIZE) { - line(sides.x.a, y, sides.x.b, y) + var quant = sides.clone().quantize(draw.grid_size) + for (var x = quant.x.a - draw.grid_size; x <= quant.x.b; x += draw.grid_size) { + if (Math.round(x) % 360 == 0) { + ctx.strokeStyle = "rgba(0,0,0,0.3)" + ctx.lineWidth = 1/map.zoom + } + else { + ctx.strokeStyle = "rgba(0,0,0,0.05)" + ctx.lineWidth = 1/map.zoom + } + line(x, sides.y.a, x, sides.y.b) } + + for (var y = quant.y.a - draw.grid_size; y <= quant.y.b; y += draw.grid_size) { + if (Math.round(y) % 360 == 0) { + ctx.strokeStyle = "rgba(0,0,0,0.3)" + ctx.lineWidth = 1/map.zoom + } + else { + ctx.strokeStyle = "rgba(0,0,0,0.05)" + ctx.lineWidth = 1/map.zoom + } + line(sides.x.a, y, sides.x.b, y) + } } // - function line (x,y,a,b,translation){ + var line = draw.line = function (x,y,a,b,translation){ if (translation) { x += translation.a a += translation.a @@ -219,11 +238,11 @@ Map.Draw = function(map, opt){ line(r.x.a, r.y.a, r.x.b, r.y.b, r.translation) } - function dot_at (x,z){ + draw.dot_at = function dot_at (x, z, radius){ ctx.save() ctx.translate(x,z) - var radius = 2 / map.zoom + radius = (radius || 2) / map.zoom ctx.beginPath(); ctx.arc(0, 0, radius, 0, 2*Math.PI, false); @@ -231,4 +250,29 @@ Map.Draw = function(map, opt){ ctx.restore() } + + draw.x_at = function x_at (x, z, length){ + ctx.save() + if (x && 'x' in x) { + length = z + ctx.translate(x.x,x.z) + } + else { + ctx.translate(x,z) + } + + var len = (length/2 || 4) / map.zoom + + ctx.lineCap = "square" + ctx.lineWidth = 2/map.zoom + ctx.beginPath() + ctx.moveTo( -len, -len); + ctx.lineTo( len, len); + ctx.moveTo( -len, len); + ctx.lineTo( len, -len); + ctx.stroke(); + + ctx.restore() + } + }
\ No newline at end of file diff --git a/public/assets/javascripts/rectangles/engine/map/tools/_base.js b/public/assets/javascripts/rectangles/engine/map/tools/_base.js new file mode 100644 index 0000000..17b247d --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/map/tools/_base.js @@ -0,0 +1,11 @@ +var MapTool = Fiber.extend(function(base){ + var exports = { + recenterCursor: true, + down: function(e, cursor){}, + move: function(e, cursor){}, + drag: function(e, cursor){}, + up: function(e, cursor, new_cursor){}, + cancel: function(){}, + } + return exports +})
\ No newline at end of file diff --git a/public/assets/javascripts/rectangles/engine/map/tools/arrow.js b/public/assets/javascripts/rectangles/engine/map/tools/arrow.js new file mode 100644 index 0000000..0b0557e --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/map/tools/arrow.js @@ -0,0 +1,83 @@ +// Tool used to move corners of polylines + +var ArrowTool = MapTool.extend(function(base){ + var exports = {} + + var selected_point = null, selected_segment = null, original_point = null, selected_shape = null + var src_points, dest_points + + exports.down = function(e, cursor){ + last_point.a = cursor.x.a + last_point.b = cursor.y.a + var p = shapes.findClosestPoint(last_point) + if (p && p.shape.type() !== "ortho") { + selected_shape = p.shape + selected_point = p.point + original_point = selected_point.clone() + return + } + var segment = shapes.findClosestSegment(last_point) + if (segment) { + document.body.style.cursor = "pointer" + + selected_segment = segment + console.log(segment.head, segment.tail) + selected_shape = segment.shape + src_points = segment.shape.cloneSegment( segment ) + dest_points = segment.shape.getSegment( segment ) + + last_point.a = segment.x + last_point.b = segment.y + cursor.x.a = cursor.x.b = last_point.a + cursor.y.a = cursor.y.b = last_point.b + } + else { + map.ui.set_drag_tool("position") + } + } + + exports.move = function(e, cursor){ + last_point.a = cursor.x.a + last_point.b = cursor.y.a + var p = shapes.findClosestPoint(last_point) + if (p) { + document.body.style.cursor = "pointer" + last_point.assign(p.point) + cursor.x.a = cursor.x.b = last_point.a + cursor.y.a = cursor.y.b = last_point.b + return + } + var segment = shapes.findClosestSegment(last_point) + if (segment) { + document.body.style.cursor = "pointer" + last_point.a = segment.x + last_point.b = segment.y + cursor.x.a = cursor.x.b = last_point.a + cursor.y.a = cursor.y.b = last_point.b + } + else { + document.body.style.cursor = "crosshair" + } + } + + exports.drag = function(e, cursor){ + if (selected_point) { + selected_point.a = original_point.a + cursor.x.magnitude() + selected_point.b = original_point.b + cursor.y.magnitude() + selected_shape.rebuild() + } + else if (selected_segment) { + selected_shape.translateSegment( + src_points, dest_points, + cursor.x.magnitude(), cursor.y.magnitude() + ) + selected_shape.rebuild() + } + } + + exports.up = function(e, cursor){ + selected_point = selected_shape = selected_segment = original_point = null + } + + return exports +})
\ No newline at end of file diff --git a/public/assets/javascripts/rectangles/engine/map/tools/eraser.js b/public/assets/javascripts/rectangles/engine/map/tools/eraser.js new file mode 100644 index 0000000..8fc3687 --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/map/tools/eraser.js @@ -0,0 +1,29 @@ +// Tool used to delete lines + +var EraserTool = MapTool.extend(function(base){ + var exports = {} + exports.down = function(e, cursor){ + last_point.a = cursor.x.a + last_point.b = cursor.y.a + var segment = shapes.findClosestSegment(last_point) + if (segment) { + shapes.removeSegment(segment) + } + } + exports.move = function(e, cursor){ + last_point.a = cursor.x.a + last_point.b = cursor.y.a + var segment = shapes.findClosestSegment(last_point) + if (segment) { + document.body.style.cursor = "pointer" + last_point.a = segment.x + last_point.b = segment.y + cursor.x.a = cursor.x.b = last_point.a + cursor.y.a = cursor.y.b = last_point.b + } + else { + document.body.style.cursor = "crosshair" + } + } + return exports +}) diff --git a/public/assets/javascripts/rectangles/engine/map/tools/line.js b/public/assets/javascripts/rectangles/engine/map/tools/line.js new file mode 100644 index 0000000..8175d66 --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/map/tools/line.js @@ -0,0 +1,63 @@ +// Tool is used to define a very simple line between two points. +// It is used by the BlueprintScaler to specify a sample distance to scale. + +var LineTool = MapTool.extend(function(base){ + var exports = {} + + var selected_point = null + + var line = exports.line = [] + + var can_drag, dragging + + exports.down = function(e, cursor){ + + // rightclick? + if (e.ctrlKey || e.which === 3) { + cursor.quantize(1/map.zoom) + app.router.blueprintView.map.center.a = cursor.x.a + app.router.blueprintView.map.center.b = -cursor.y.a + cursor.x.b = cursor.x.a + cursor.y.b = cursor.y.a + return + } + + this.cursor = cursor + switch (line.length) { + case 0: + line[0] = cursor.x_component() + can_drag = true + break + case 1: + line[1] = cursor.x_component() + can_drag = false + break + case 2: + line[0] = cursor.x_component() + line.pop() + can_drag = true + break + } + } + + exports.move = function(e, cursor){ + this.cursor = cursor + } + + exports.drag = function(e, cursor){ + if (dragging) { + line[1].a = cursor.x.b + line[1].b = cursor.y.b + } + else if (can_drag && cursor.magnitude() > 10/map.zoom) { + line[1] = cursor.y_component() + dragging = true + } + } + + exports.up = function(e, cursor){ + can_drag = dragging = false + } + + return exports +})
\ No newline at end of file diff --git a/public/assets/javascripts/rectangles/engine/map/tools/ortho.js b/public/assets/javascripts/rectangles/engine/map/tools/ortho.js new file mode 100644 index 0000000..374c822 --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/map/tools/ortho.js @@ -0,0 +1,118 @@ +// Tool to make a polyline where all walls are orthogonal + +var OrthoPolylineTool = MapTool.extend(function (base) { + + var prev_point, horizontal = false, first_edge_is_horizontal = false + + var exports = {} + exports.down = function(e, cursor){ + // rightclick? + if (e.ctrlKey || e.which === 3) { + e.preventDefault() + e.stopPropagation() + if (map.ui.placing) { + // close polyline or cancel + map.ui.placing = false + if (shapes.workline.points.length > 2) { + shapes.workline.build() + shapes.add(shapes.workline) + } + else { + shapes.workline.reset() + } + return + } + else { + map.ui.tools.position.rightclick(e, cursor) + } + return + } + + // compare to initial point + var p = last_point.clone() + if (map.ui.placing) { + if (shapes.workline.lastPoint().eq(p)) { + return + } + else if (shapes.workline.canCloseWith(p)) { + shapes.workline.close() + shapes.workline.build() + shapes.add(shapes.workline) + map.ui.placing = false + } + else { + shapes.workline.add(p) + prev_point = p + horizontal = ! horizontal + } + } + else { + map.ui.placing = true + shapes.workline = new OrthoPolyline () + shapes.workline.add(p) + first_point = prev_point = p + horizontal = false + } + } + exports.move = function(e, cursor){ + last_point.a = cursor.x.a + last_point.b = cursor.y.a + if (map.ui.placing) { + if (shapes.workline.points.length == 1) { + var x = abs(prev_point.a - last_point.a) + var y = abs(prev_point.b - last_point.b) + if (x > y) { + last_point.b = prev_point.b + first_edge_is_horizontal = horizontal = true + } + else { + last_point.a = prev_point.a + first_edge_is_horizontal = horizontal = false + } + } + else { + if (horizontal) { + last_point.b = prev_point.b + } + else { + last_point.a = prev_point.a + } + if (horizontal == first_edge_is_horizontal) { + // check if this point is within N pixels of the normal + // and lock it into place if so + if (horizontal && abs( first_point.a - last_point.a ) < 10/map.zoom) { + last_point.a = first_point.a + } + else if (! horizontal && abs( first_point.b - last_point.b ) < 10/map.zoom) { + last_point.b = first_point.b + } + } + } + + if (shapes.workline.canCloseWith(last_point)) { + document.body.style.cursor = "pointer" + last_point.assign(first_point) + cursor.x.a = cursor.x.b = last_point.a + cursor.y.a = cursor.y.b = last_point.b + } + return + } + var end_point = shapes.findClosestEndPoint(last_point) + if (end_point) { + document.body.style.cursor = "pointer" + last_point.assign(end_point.point) + cursor.x.a = cursor.x.b = last_point.a + cursor.y.a = cursor.y.b = last_point.b + return + } + else { + document.body.style.cursor = "crosshair" + } + } + exports.cancel = function(){ + if (map.ui.placing) { shapes.workline.reset() } + first_point = null + map.ui.placing = false + } + return exports +})
\ No newline at end of file diff --git a/public/assets/javascripts/rectangles/engine/map/tools/polyline.js b/public/assets/javascripts/rectangles/engine/map/tools/polyline.js new file mode 100644 index 0000000..445ae26 --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/map/tools/polyline.js @@ -0,0 +1,73 @@ +// Tool used to draw polylines with arbitrary angles + +var PolylineTool = MapTool.extend(function (base) { + var exports = {} + exports.down = function(e, cursor){ + + // rightclick? + if (e.ctrlKey || e.which === 3) { + e.preventDefault() + e.stopPropagation() + if (map.ui.placing) { + // close polyline or cancel + map.ui.placing = false + if (shapes.workline.points.length > 2) { + shapes.workline.build() + shapes.add(shapes.workline) + } + else { + shapes.workline.reset() + } + return + } + map.ui.tools.position.rightclick(e, cursor) + return + } + + // compare to initial point + var p = last_point.clone() + if (map.ui.placing) { + if (shapes.workline.canCloseWith(p)) { + shapes.workline.close() + shapes.workline.build() + shapes.add(shapes.workline) + map.ui.placing = false + } + else { + shapes.workline.add(p) + } + } + else { + map.ui.placing = true + shapes.workline = new Polyline () + shapes.workline.add(p) + } + } + exports.move = function(e, cursor){ + last_point.a = cursor.x.a + last_point.b = cursor.y.a + if (map.ui.placing && shapes.workline.canCloseWith(last_point)) { + document.body.style.cursor = "pointer" + last_point.assign(shapes.workline.points[0]) + cursor.x.a = cursor.x.b = last_point.a + cursor.y.a = cursor.y.b = last_point.b + return + } + var end_point = shapes.findClosestEndPoint(last_point) + if (end_point) { + document.body.style.cursor = "pointer" + last_point.assign(end_point.point) + cursor.x.a = cursor.x.b = last_point.a + cursor.y.a = cursor.y.b = last_point.b + return + } + else { + document.body.style.cursor = "crosshair" + } + } + exports.cancel = function(){ + if (map.ui.placing) { shapes.workline.reset() } + map.ui.placing = false + } + return exports +})
\ No newline at end of file diff --git a/public/assets/javascripts/rectangles/engine/map/tools/position.js b/public/assets/javascripts/rectangles/engine/map/tools/position.js new file mode 100644 index 0000000..f8365bc --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/map/tools/position.js @@ -0,0 +1,19 @@ +// Tool used to set position on the map and let you change the view by dragging. + +var PositionTool = MapTool.extend(function(base){ + var exports = { + recenterCursor: false, + drag: function(e, cursor){ + map.center.a = -cursor.x.magnitude() + map.center.b = cursor.y.magnitude() + }, + rightclick: function(e, cursor){ + cursor.quantize(1/map.zoom) + map.center.a = cursor.x.a + map.center.b = -cursor.y.a + cursor.x.b = cursor.x.a + cursor.y.b = cursor.y.a + } + } + return exports +})
\ No newline at end of file diff --git a/public/assets/javascripts/rectangles/engine/map/tools/start.js b/public/assets/javascripts/rectangles/engine/map/tools/start.js new file mode 100644 index 0000000..203a85f --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/map/tools/start.js @@ -0,0 +1,29 @@ +// Tool is used to set the start position on the map. + +var StartPositionTool = MapTool.extend(function(base){ + var exports = {} + + var selected_point = null + + var line = exports.line = [] + + var can_drag, dragging + + exports.down = function(e, cursor){ + // rightclick? + if (e.ctrlKey || e.which === 3) { + cursor.quantize(1/map.zoom) + app.router.blueprintView.map.center.a = cursor.x.a + app.router.blueprintView.map.center.b = -cursor.y.a + cursor.x.b = cursor.x.a + cursor.y.b = cursor.y.a + return + } + + cam.x = app.controller.startPosition.x = cursor.x.a + cam.z = app.controller.startPosition.z = cursor.y.a + } + + return exports + +}) diff --git a/public/assets/javascripts/rectangles/engine/map/ui_editor.js b/public/assets/javascripts/rectangles/engine/map/ui/editor.js index 7308344..699597a 100644 --- a/public/assets/javascripts/rectangles/engine/map/ui_editor.js +++ b/public/assets/javascripts/rectangles/engine/map/ui/editor.js @@ -73,7 +73,7 @@ Map.UI.Editor = function(map){ app.tube("builder-destroy-room", room) // TODO: watch individual scenery object here - Minotaur.watch( app.router.editorView.settings ) + Minotaur.watch( (app.router.builderView || app.router.editorView).settings ) return } else if (intersects.length) { @@ -205,13 +205,13 @@ Map.UI.Editor = function(map){ Rooms.rebuild() // TODO: watch individual scenery object here - Minotaur.watch( app.router.editorView.settings ) + Minotaur.watch( (app.router.builderView || app.router.editorView).settings ) } var intersects = Rooms.filter(function(r){ return r.focused = r.rect.contains(cursor.x.a, cursor.y.a) }) - if (! intersects.length) { + if (! base.dragging && ! intersects.length) { app.tube("builder-pick-nothing") } @@ -247,7 +247,7 @@ Map.UI.Editor = function(map){ Rooms.rebuild() // TODO: watch individual scenery object here - Minotaur.watch( app.router.editorView.settings ) + Minotaur.watch( (app.router.builderView || app.router.editorView).settings ) wheelState = null }, 250) diff --git a/public/assets/javascripts/rectangles/engine/map/ui_minimap.js b/public/assets/javascripts/rectangles/engine/map/ui/minimap.js index 0fdd336..0fdd336 100644 --- a/public/assets/javascripts/rectangles/engine/map/ui_minimap.js +++ b/public/assets/javascripts/rectangles/engine/map/ui/minimap.js diff --git a/public/assets/javascripts/rectangles/engine/map/ui/ortho.js b/public/assets/javascripts/rectangles/engine/map/ui/ortho.js new file mode 100644 index 0000000..5be7446 --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/map/ui/ortho.js @@ -0,0 +1,107 @@ +Map.UI = Map.UI || {} +Map.UI.Ortho = function(map){ + + var base = this + var last_event = null + + base.creating = base.dragging = base.resizing = false + + base.mouse = new mouse({ + el: map.el, + down: function(e, cursor){ + last_event = e + cursor.x.div(map.dimensions.a).add(0.5).mul(map.dimensions.a / map.zoom) + cursor.y.div(map.dimensions.b).sub(0.5).mul(map.dimensions.b / map.zoom) + if (tool.recenterCursor) { + cursor.x.add(map.center.a) + cursor.y.sub(map.center.b) + base.tools[currentTool].down(e, cursor) + } + else { + base.tools[currentTool].down(e, cursor) + cursor.x.add(map.center.a) + cursor.y.sub(map.center.b) + } + }, + move: function(e, cursor){ + last_event = e + cursor.x.div(map.dimensions.a).add(0.5).mul(map.dimensions.a / map.zoom) + cursor.y.div(map.dimensions.b).sub(0.5).mul(map.dimensions.b / map.zoom) + if (tool.recenterCursor) { + cursor.x.add(map.center.a) + cursor.y.sub(map.center.b) + base.tools[currentTool].move(e, cursor) + } + else { + base.tools[currentTool].move(e, cursor) + cursor.x.add(map.center.a) + cursor.y.sub(map.center.b) + } + }, + drag: function(e, cursor){ + last_event = e + cursor.x.b = ((cursor.x.b/map.dimensions.a)+0.5) * map.dimensions.a / map.zoom + cursor.y.b = ((cursor.y.b/map.dimensions.b)-0.5) * map.dimensions.b / map.zoom + if (tool.recenterCursor) { + cursor.x.b += map.center.a + cursor.y.b -= map.center.b + base.tools[currentTool].drag(e, cursor) + } + else { + base.tools[currentTool].drag(e, cursor) + cursor.x.b += map.center.a + cursor.y.b -= map.center.b + } + }, + up: function(e, cursor, new_cursor){ + last_event = e + new_cursor.x.div(map.dimensions.a).add(0.5).mul(map.dimensions.a / map.zoom) + new_cursor.y.div(map.dimensions.b).sub(0.5).mul(map.dimensions.b / map.zoom) + if (tool.recenterCursor) { + new_cursor.x.add(map.center.a) + new_cursor.y.sub(map.center.b) + base.tools[currentTool].up(e, cursor, new_cursor) + } + else { + base.tools[currentTool].up(e, cursor, new_cursor) + new_cursor.x.add(map.center.a) + new_cursor.y.sub(map.center.b) + } + if (nextTool) { + console.log('found nextTool') + base.set_tool(nextTool) + nextTool = null + } + } + }) + + var currentTool = "polyline", nextTool, tool + base.add_tool = function(name, tool){ + base.tools[name] = tool + } + base.set_tool = function(s){ + console.log("set tool to", s) + if (base.tools[currentTool]) { + base.tools[currentTool].cancel() + } + currentTool = s + tool = base.tools[currentTool] + } + base.set_drag_tool = function(s){ + console.log('set drag tool to', s) + nextTool = currentTool + currentTool = s + tool = base.tools[currentTool] + base.tools[currentTool].down(last_event, base.mouse.cursor) + } + base.tools = {} + + base.wheel = new wheel({ + el: map.el, + update: mousewheel, + }) + + function mousewheel (e, deltaY, deltaX){ + map.set_zoom(map.zoom_exponent - deltaY/20) + } +} diff --git a/public/assets/javascripts/rectangles/engine/rooms/_rooms.js b/public/assets/javascripts/rectangles/engine/rooms/_rooms.js index 46c1d7f..9aff33f 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/_rooms.js +++ b/public/assets/javascripts/rectangles/engine/rooms/_rooms.js @@ -37,6 +37,7 @@ base.list = {} base.regions = [] + base.shapesMode = false base.uid = new UidGenerator(base.list) @@ -95,6 +96,7 @@ } base.rebuild = function(walls_data){ + if (base.shapesMode) return walls_data = walls_data || Walls.serialize() Rooms.clipper.update() Rooms.builder.rebuild() @@ -124,6 +126,45 @@ }) Rooms.rebuild(walls_data) } + + base.deserializeFromShapes = function(data, walls_data) { + walls_data = walls_data || Walls.serialize() + base.shapesMode = true + window.viewHeight = data.viewHeight || app.defaults.viewHeight + window.wallHeight = data.wallHeight || app.defaults.wallHeight + $(".units").val( data.units ) + + Rooms.builder.clear() + + shapes.deserialize( data.shapes ) + // shapes.build() + var regions = RegionList.build() + + regions.forEach(function(region){ + var room = new Room({ + rect: region, + regions: [region], + height: wallHeight, + }) + + room.sides = region.sides + region.id = Rooms.uid("room_") + Rooms.list[ region.id ] = room + var mx_walls = Rooms.builder.build_walls(region) + room.mx_floor = Rooms.builder.make_floor(room, region) + room.mx_ceiling = Rooms.builder.make_ceiling(room, region) + + mx_walls.forEach(function(mx){ scene.add(mx) }) + scene.add(room.mx_floor) + scene.add(room.mx_ceiling) + }) + + Rooms.grouper.build() + + Walls.paint() + Walls.deserialize(walls_data) + app.tube("rooms-built") + } base.report = function(){ var data = [] diff --git a/public/assets/javascripts/rectangles/engine/scenery/_scenery.js b/public/assets/javascripts/rectangles/engine/scenery/_scenery.js index d52fe21..6203c20 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/_scenery.js +++ b/public/assets/javascripts/rectangles/engine/scenery/_scenery.js @@ -11,6 +11,7 @@ var Scenery = new function(){ base.init = function(){ base.resize.init() + base.sound.init() } base.add = function(opt){ @@ -113,6 +114,35 @@ var Scenery = new function(){ return added } + base.rewindAll = function(){ + base.forEach(function(scenery){ + if (scenery.type == "video") scenery.seek(0) + }) + } + base.playAll = function(){ + base.forEach(function(scenery){ + if (scenery.type == "video") { + scenery.unmute() + scenery.play() + } + }) + } + base.pauseAll = function(){ + base.forEach(function(scenery){ + if (scenery.type == "video") scenery.pause() + }) + } + base.muteAll = function(){ + base.forEach(function(scenery){ + if (scenery.type == "video") scenery.mx.mute() + }) + } + base.unmuteAll = function(){ + base.forEach(function(scenery){ + if (scenery.type == "video") scenery.mx.unmute() + }) + } + return base } diff --git a/public/assets/javascripts/rectangles/engine/scenery/move.js b/public/assets/javascripts/rectangles/engine/scenery/move.js index f57ddba..94c6281 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/move.js +++ b/public/assets/javascripts/rectangles/engine/scenery/move.js @@ -28,7 +28,7 @@ Scenery.move = function(base){ base.remove() return } - + // load the modal app.controller.pick(base) @@ -75,13 +75,14 @@ Scenery.move = function(base){ switch (base.wall.side) { case FRONT: case BACK: - base.mx.x = position.a + delta.a * cos(wall_rotation[base.wall.side]) + dimension.a / 2 + base.mx.x = position.a + delta.a * cos(base.wall.rotationY) + dimension.a / 2 break case LEFT: case RIGHT: - base.mx.z = position.a + delta.a * sin(wall_rotation[base.wall.side]) + dimension.a / 2 + base.mx.z = position.a + delta.a * sin(base.wall.rotationY) + dimension.a / 2 break } + if (editor.permissions.resize) { Scenery.resize.move_dots() } @@ -104,7 +105,6 @@ Scenery.move = function(base){ dragging = moved = false oldState = null document.body.classList.remove("dragging") - } function switch_wall (e, target, cursor){ diff --git a/public/assets/javascripts/rectangles/engine/scenery/resize.js b/public/assets/javascripts/rectangles/engine/scenery/resize.js index 5af7f3f..252af74 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/resize.js +++ b/public/assets/javascripts/rectangles/engine/scenery/resize.js @@ -8,6 +8,7 @@ Scenery.resize = new function(){ var dragging = false var naturalDimension, naturalDimensionCopy, dimension, position, scale var oldState + var rotationY var dots = [], dot, selected_dot @@ -49,7 +50,8 @@ Scenery.resize = new function(){ // rotate the dots as appropriate base.rotate_dots = function(){ - rotationY = wall_rotation[obj.wall.side] + // console.trace() + rotationY = obj.wall.rotationY dots.forEach(function(dot){ dot.rotationY = rotationY }) @@ -93,6 +95,7 @@ Scenery.resize = new function(){ base.add_dots() base.rotate_dots() base.move_dots() + Sculpture.resize.hide() } // dismiss the dots on blur diff --git a/public/assets/javascripts/rectangles/engine/scenery/sound.js b/public/assets/javascripts/rectangles/engine/scenery/sound.js new file mode 100644 index 0000000..5a783d6 --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/scenery/sound.js @@ -0,0 +1,16 @@ + +Scenery.sound = {} +Scenery.sound.max_distance = 1500 +Scenery.sound.init = function(){ + app.tube.on("move", Scenery.sound.move) +} +Scenery.sound.move = function(){ + Scenery.forEach(function(scenery){ + if ((scenery.type == "video" || scenery.type == "audio")) { // && ! scenery.muted()) { + var distance = dist(cam.x, cam.z, + scenery.mx.x, scenery.mx.z) + var volume = 1 - (clamp( distance, 0, Scenery.sound.max_distance ) / Scenery.sound.max_distance) + scenery.setVolume(volume) + } + }) +} diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/_object.js b/public/assets/javascripts/rectangles/engine/scenery/types/_object.js index cd3f981..e3b9b4d 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/types/_object.js +++ b/public/assets/javascripts/rectangles/engine/scenery/types/_object.js @@ -90,11 +90,11 @@ Scenery.types.base = Fiber.extend(function(base){ switch (this.wall.side) { case FRONT: case BACK: - this.position.a += delta.a * cos(wall_rotation[this.wall.side]) + this.position.a += delta.a * cos(this.wall.rotationY) break case LEFT: case RIGHT: - this.position.a += delta.a * sin(wall_rotation[this.wall.side]) + this.position.a += delta.a * sin(this.wall.rotationY) break } }, diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/audio.js b/public/assets/javascripts/rectangles/engine/scenery/types/audio.js index 82f984e..fdd221d 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/types/audio.js +++ b/public/assets/javascripts/rectangles/engine/scenery/types/audio.js @@ -39,6 +39,10 @@ Scenery.types.audio = Scenery.types.base.extend(function(base){ this.dimensions.deserialize(data.dimensions) }, + setVolume: function(n){ + this.mx.setVolume(n) + }, + play: function(){ this.mx.play() }, diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/video.js b/public/assets/javascripts/rectangles/engine/scenery/types/video.js index d1b1763..163e19e 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/types/video.js +++ b/public/assets/javascripts/rectangles/engine/scenery/types/video.js @@ -38,7 +38,8 @@ Scenery.types.video = Scenery.types.base.extend(function(base){ backface: false, }) scene.add(this.mx) - this.mx.load() + + this.mx.load() }, play: function(){ @@ -90,6 +91,14 @@ Scenery.types.video = Scenery.types.base.extend(function(base){ } }, + unmute: function(){ + this.mx.unmute() + }, + + setVolume: function(n){ + this.mx.setVolume(n) + }, + serialize: function(){ var data = base.serialize.call(this) return data diff --git a/public/assets/javascripts/rectangles/engine/scenery/undo.js b/public/assets/javascripts/rectangles/engine/scenery/undo.js index 1232780..b976ea2 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/undo.js +++ b/public/assets/javascripts/rectangles/engine/scenery/undo.js @@ -195,5 +195,70 @@ }, }, + // + { + type: "create-sculpture", + undo: function(state){ + Sculpture.remove(state.id) + Sculpture.resize.hide() + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + }, + redo: function(state){ + var scenery = Sculpture.deserialize([ state ]) + Sculpture.resize.show( sculpture ) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + }, + }, + { + type: "update-sculpture", + undo: function(state){ + var sculpture = Sculpture.find(state.id) + + sculpture.deserialize(state) + + if (editor.permissions.resize) { + Sculpture.resize.show(sculpture) + } + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + }, + redo: function(state){ + var sculpture = Sculpture.find(state.id) + + sculpture.deserialize(state) + + if (editor.permissions.resize) { + Sculpture.resize.show(sculpture) + Sculpture.resize.move_dots() + Sculpture.resize.rotate_dots() + } + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + }, + }, + { + type: "destroy-sculpture", + undo: function(state){ + var sculpture = Sculpture.deserialize([ state ]) + Sculpture.resize.show( sculpture ) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + }, + redo: function(state){ + Sculpture.resize.hide() + Sculpture.remove(state.id) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + }, + }, + ]) })() diff --git a/public/assets/javascripts/rectangles/engine/sculpture/_sculpture.js b/public/assets/javascripts/rectangles/engine/sculpture/_sculpture.js new file mode 100644 index 0000000..888b925 --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/sculpture/_sculpture.js @@ -0,0 +1,105 @@ + +var Sculpture = new function(){ + + var base = this; + + base.list = {} + + base.mouse = new mouse ({ use_offset: false, mousedownUsesCapture: true }) + + base.init = function(){ + app.on("move", base.updateBillboards) + base.resize.init() + } + + base.updateBillboards = function(){ + base.forEach(function(sculpture){ + if (sculpture.billboard) { + sculpture.mx.rotationY = cam.rotationY + } + }) + if (Sculpture.resize.obj && Sculpture.resize.obj.billboard) { + Sculpture.resize.move_dots() + } + } + + base.add = function(opt){ + var sculpture + switch (opt.media.type) { + case 'image': + sculpture = new Sculpture.types.image (opt) + break + } + base.list[sculpture.id] = sculpture + return sculpture + } + + base.addNext = function(opt){ + opt.newMedia = true + opt.media = Scenery.nextMedia + var sculpture = base.add(opt) + + // test if sculpture was placed here + if (! sculpture) { + return null + } + else { + Scenery.nextMedia = null + return sculpture + } + } + + base.find = function(id){ + return base.list[id] || null + } + + base.remove = function(id){ + var scene_media = base.list[id] + delete base.list[id] + scene_media && scene_media.destroy() + } + + base.removeAll = function(){ + base.forEach(function(scene_media){ + base.remove(scene_media.id) + }) + } + + base.uid = new UidGenerator(base.list) + + base.forEach = function(f){ + return base.values().forEach(f) + } + + base.map = function(f){ + return base.values().map(f) + } + + base.values = function(){ + return _.values(base.list) + } + + base.serialize = function(){ + var sculptures = base.map(function(sculpture){ + return sculpture.serialize() + }) + return sculptures + } + + base.deserialize = function(sculpture_data){ + var added = [] + sculpture_data.forEach(function(data){ + var scene_media = base.add({ + id: data.id, + data: data, + media: data.media, + }) + added.push(scene_media) + }) + return added + } + + return base +} + +Sculpture.types = {} diff --git a/public/assets/javascripts/rectangles/engine/sculpture/move.js b/public/assets/javascripts/rectangles/engine/sculpture/move.js new file mode 100644 index 0000000..0cbeccd --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/sculpture/move.js @@ -0,0 +1,111 @@ + +Sculpture.move = function(base){ + + var x, y, z, position, dimension, bounds + var rotationY + var dragging = false, altPressed = false, shiftPressed = false, moved = false + var oldState + var height, width + + this.bind = function(){ + Sculpture.mouse.bind_el(base.mx.el) + Sculpture.mouse.on("down", down) + Sculpture.mouse.on("drag", drag) + Sculpture.mouse.on("up", up) + } + + this.unbind = function(){ + base.focused = false + Sculpture.mouse.unbind_el(base.mx.el) + Sculpture.mouse.off("down", down) + Sculpture.mouse.off("drag", drag) + Sculpture.mouse.off("up", up) + } + + function down (e, cursor){ + if (e.target != base.mx.el && (e.target != base.mx.overlay)) return; + if (editor.permissions.destroy) { + base.remove() + return + } + + // load the modal + app.controller.pick(base) + + if (! base.focused) { + e.clickAccepted = false + base.focused = true + return + } + if (! (editor.permissions.move || editor.permissions.resize) ) { + e.clickAccepted = false + return + } + altPressed = (e.altKey && ! base.billboard) + shiftPressed = e.shiftKey + dragging = true + moved = false + x = base.mx.x + y = base.mx.y + z = base.mx.z + rotationY = base.mx.rotationY + height = base.mx.height * base.mx.scale + + bounds = base.bounds + dimension = base.dimensions + + oldState = base.serialize() + document.body.classList.add("dragging") + } + + function drag (e, cursor){ + if (! dragging) return + + moved = true + + var delta = cursor.delta() + delta.mul( cursor_amp ) // TODO: this should be proportional to your distance from the wall + delta.b *= -1 + + // here we need to move the element based on the XY coords, as + // base.mx.y = position.b + delta.b + dimension.b / 2 + if (shiftPressed) { + base.mx.y = clamp( y + delta.b, height/2 + sculpture_distance_from_floor, Infinity ) + } + else if (altPressed) { + base.mx.rotationY = mod( rotationY + delta.a / (window.innerWidth / 2) , TWO_PI ) + Sculpture.resize.move_dots() + } + else { + base.mx.x = x + delta.a * cos(cam.rotationY) - delta.b * sin(cam.rotationY) + base.mx.z = z + delta.a * sin(cam.rotationY) + delta.b * cos(cam.rotationY) + } + + if (editor.permissions.resize) { + Sculpture.resize.move_dots() + base.updateOutline() + } + } + + function up (e, cursor){ + if (! dragging || ! oldState) return + + if (moved) { + UndoStack.push({ + type: 'update-sculpture', + undo: oldState, + redo: base.serialize(), + }) + + // TODO: watch individual sculpture object here + Minotaur.watch( app.router.editorView.settings ) + } + + dragging = moved = false + oldState = null + document.body.classList.remove("dragging") + } + + return this + +}
\ No newline at end of file diff --git a/public/assets/javascripts/rectangles/engine/sculpture/resize.js b/public/assets/javascripts/rectangles/engine/sculpture/resize.js new file mode 100644 index 0000000..5f21d66 --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/sculpture/resize.js @@ -0,0 +1,208 @@ +Sculpture.resize = new function(){ + + var base = this + + var obj + var x, y, z, bounds + var dragging = false + var naturalDimension, naturalDimensionCopy, dimension, position, scale + var oldState + var rotationY + + var dots = [], dot, selected_dot + + base.init = function(){ + base.build() + base.bind() + } + + // create 9 dots at the corners of the div + base.build = function(){ + [ TOP, + TOP_RIGHT, + RIGHT, + BOTTOM_RIGHT, + BOTTOM, + BOTTOM_LEFT, + LEFT, + TOP_LEFT ].forEach(base.build_dot) + } + + // generate a dot element + base.build_dot = function(side) { + var dot = new MX.Object3D('.dot') + dot.width = dot.height = dot_side * 2 + dot.scale = 0.5 + dot.side = side + $(dot.el).on({ + mouseenter: function(){ base.hovering = true }, + mouseleave: function(){ base.hovering = false }, + }) + dots.push(dot) + } + + base.add_dots = function(){ + dots.forEach(function(dot){ + scene.add(dot) + }) + } + + // move all the dots to the object's current position + base.move_dots = function(){ + rotationY = obj.mx.rotationY + + var x = obj.mx.x + sin(rotationY) * dot_distance_from_picture + var y = obj.mx.y + var z = obj.mx.z - cos(rotationY) * dot_distance_from_picture + + dots.forEach(function(dot){ + base.move_dot(dot, { x: x, y: y, z: z, rotationY: rotationY }) + }) + } + + // move a dot .. to the initial position of the image + base.move_dot = function(dot, pos){ + if (dot.side & TOP) { + pos.y += obj.dimensions.b / 2 + } + if (dot.side & BOTTOM) { + pos.y -= obj.dimensions.b / 2 + } + if (dot.side & LEFT) { + pos.x -= cos(rotationY) * (obj.dimensions.a) / 2 + pos.z -= sin(rotationY) * (obj.dimensions.a) / 2 + } + if (dot.side & RIGHT) { + pos.x += cos(rotationY) * (obj.dimensions.a) / 2 + pos.z += sin(rotationY) * (obj.dimensions.a) / 2 + } + dot.move(pos) + } + + // pick a new object to focus on and show the dots + base.show = function(new_object) { + // if (obj === new_object) return + if (! new_object) return + base.obj = obj = new_object + base.add_dots() + base.move_dots() + } + + // dismiss the dots on blur + var dotsHideTimeout; + base.defer_hide = function(){ + clearTimeout(dotsHideTimeout) + + dotsHideTimeout = setTimeout(function(){ + if (Scenery.hovering || Scenery.resize.hovering || Scenery.mouse.down) return + Scenery.resize.hide() + }, dot_hide_delay) + } + + base.hide = function () { + if (! obj) return + base.obj = obj = null + dots.forEach(function(dot){ + scene.remove(dot) + }) + } + + base.bind = function(){ + dots.forEach(function(dot){ + Sculpture.mouse.bind_el(dot.el) + }) + Sculpture.mouse.on("down", down) + Sculpture.mouse.on("drag", drag) + Sculpture.mouse.on("up", up) + } + + base.unbind = function(){ + dots.forEach(function(dot){ + Sculpture.mouse.unbind_el(dot.el) + }) + Sculpture.mouse.off("down", down) + Sculpture.mouse.off("drag", drag) + Sculpture.mouse.off("up", up) + } + + function down (e, cursor){ + var selection = dots.filter(function(dot){return e.target == dot.el}) + if (! selection.length) return + + selected_dot = selection[0] + dragging = true + + naturalDimension = obj.naturalDimensions + dimension = obj.dimensions + position = new vec3(obj.mx.x, obj.mx.y, obj.mx.z) + oldState = obj.serialize() + + if (obj.type == "text") { + naturalDimensionCopy = naturalDimension.clone() + positionCopy = position.clone() + } + + document.body.classList.add("dragging") + } + + function drag (e, cursor){ + if (! dragging) return + + var x_sign = selected_dot.side & LEFT ? -1 : selected_dot.side & RIGHT ? 1 : 0 + var y_sign = selected_dot.side & TOP ? -1 : selected_dot.side & BOTTOM ? 1 : 0 + var width = cursor.x.magnitude() + var height = cursor.y.magnitude() + var mag = cursor.magnitude() + + if (abs(width) >Â abs(height)) { + mag = x_sign * mag * sign(width) + } + else { + mag = y_sign * mag * sign(height) + } + + if (obj.type == "text") { + obj.mx.width = obj.media.width = naturalDimension.a = naturalDimensionCopy.a + (mag * 2) + obj.mx.height = obj.media.height = naturalDimension.b = naturalDimensionCopy.b + (mag * 2) + dimension.a = naturalDimension.a * obj.scale + dimension.b = naturalDimension.b * obj.scale + } + else { + obj.set_scale( ( dimension.a + mag ) / naturalDimension.a ) + } + + if (selected_dot.side & LEFT_RIGHT) { + obj.mx.x = position.a + cos(rotationY) * mag/2 * (x_sign) + obj.mx.z = position.c + sin(rotationY) * mag/2 * (x_sign) + } + if (selected_dot.side & TOP_BOTTOM) { + obj.mx.y = position.b - mag/2 * y_sign + } + + base.move_dots() + obj.updateOutline() + + app.controller.sculptureEditor.setDimensions() + } + + function up (e, cursor){ + if (! dragging) return + dragging = false + if (! editor.permissions.resize) { return } + + obj.scale = obj.mx.ops.scale = obj.mx.scale + obj.dimensions.assign(obj.naturalDimensions).mul(obj.scale) + + UndoStack.push({ + type: 'update-sculpture', + undo: oldState, + redo: obj.serialize(), + }) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + + document.body.classList.remove("dragging") + selected_dot = null + } +}
\ No newline at end of file diff --git a/public/assets/javascripts/rectangles/engine/sculpture/types/_object.js b/public/assets/javascripts/rectangles/engine/sculpture/types/_object.js new file mode 100644 index 0000000..2f593e8 --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/sculpture/types/_object.js @@ -0,0 +1,176 @@ +Sculpture.types.base = Fiber.extend(function(base){ + + var exports = { + + init: function(opt){ + this.id = opt.id || Sculpture.uid("sculpture") + // this.move = new Sculpture.move (this) + this.media = opt.media + this.naturalDimensions = new vec3(this.media.width, this.media.height, this.media.width) + this.dimensions = new vec3(this.media.width, this.media.height, this.media.width) + + this.move = new Sculpture.move (this) + this.billboard = true + this.backface = true + + this.set_scale( opt.scale || this.media.scale || 1.0 ) + this.position = new vec2(0,0) + + this.isSculpture = true + }, + + set_scale: function(scale){ + this.scale = scale || 1.0 + if (this.mx) { + this.mx.scale = this.mx.ops.scale = this.scale + } + this.dimensions = this.naturalDimensions.clone().mul(this.scale) + }, + set_depth: function(depth){ + console.log(this.dimensions.c, this.naturalDimensions.c, depth) + this.dimensions.c = depth + this.naturalDimensions.c = depth / this.scale + }, + + place: function(opt){ + if (opt.data) { + this.deserialize(opt.data) + } + else { + this.mx.move(opt.position) + } + }, + + bind: function(){ + this.move.bind() + }, + + unbind: function(){ + this.move.unbind() + }, + + setOutline: function(val){ + this.outline = val + if (val && ! this.outlineEl) { + this.buildOutline() + } + this.outlineEl.el.style.display = val ? "block" : "none" + }, + setOutlineColor: function(val){ + this.outlineColor = val + if (this.outlineEl) { + this.outlineColor = this.outlineEl.el.style.borderColor = val + } + }, + setBillboard: function(val){ + this.billboard = val + if (this.billboard) { + this.mx.el.classList.add("backface-hidden") + this.mx.el.classList.remove("backface-visible") + this.mx.rotationY = cam.rotationY + } + else { + this.mx.el.classList.add("backface-visible") + this.mx.el.classList.remove("backface-hidden") + this.mx.rotationY = quantize(cam.rotationY, PI/2) + } + Sculpture.resize.move_dots() + }, + + buildOutline: function(){ + this.outlineEl = new MX.Object3D(".mx-outline") + this.outlineEl.width = this.naturalDimensions.a + this.outlineEl.height = this.naturalDimensions.c + this.outlineEl.scale = this.mx.scale + this.outlineEl.rotationX = -PI/2 + this.outlineEl.x = this.mx.x + this.outlineEl.y = sculpture_distance_from_floor + this.outlineEl.z = this.mx.z + this.outlineEl.el.style.borderColor = this.outlineColor || "#000000" + scene.add(this.outlineEl) + }, + updateOutline: function(){ + if (! this.outline) { return } + if (! this.outlineEl) { + this.buildOutline() + } + this.outlineEl.x = this.mx.x + this.outlineEl.y = sculpture_distance_from_floor + this.outlineEl.z = this.mx.z + this.outlineEl.width = this.naturalDimensions.a + this.outlineEl.height = this.naturalDimensions.c + + this.outlineEl.scale = this.mx.scale + }, + + remove: function(){ + if (this.removed) return + this.removed = true + + UndoStack.push({ + type: 'destroy-sculpture', + undo: this.serialize(), + redo: { id: this.id }, + }) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + + Sculpture.remove(this.id) + + Sculpture.resize.hide() + if (app.controller.sculptureEditor) { + app.controller.sculptureEditor.tainted = false + app.controller.sculptureEditor.hide() + } + }, + + destroy: function(){ + this.unbind() + scene.remove(this.mx) + this.mx.media = null + this.mx.ops = null + this.mx = null + this.move = null + this.media = null + this.dimensions = null + this.naturalDimensions = null + this.wall = null + this.bounds = null + this.center = null + }, + + serialize: function(){ + var data = { + id: this.id, + dimensions: this.dimensions.serialize(), + position: app.position(this.mx), + scale: this.scale, + media: this.media, + billboard: this.billboard, + outline: this.outline, + outlineColor: this.outlineColor || "#000000", + backface: this.backface, + } + return data + }, + + deserialize: function(data){ + this.mx.move(data.position) + this.mx.ops.width = data.dimensions.a + this.mx.ops.height = data.dimensions.b + this.billboard = data.billboard + this.outline = data.outline + this.outlineColor = data.outlineColor || "#000000" + this.backface = data.backface + if (! this.backface) this.mx.el.classList.remove("backface-visible") + this.dimensions.deserialize(data.dimensions) + if (this.outline) { + this.buildOutline() + } + }, + } + + return exports + +}) diff --git a/public/assets/javascripts/rectangles/engine/sculpture/types/image.js b/public/assets/javascripts/rectangles/engine/sculpture/types/image.js new file mode 100644 index 0000000..1a53f5b --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/sculpture/types/image.js @@ -0,0 +1,38 @@ + +Sculpture.types.image = Sculpture.types.base.extend(function(base){ + + var exports = { + + type: 'image', + + init: function(opt){ + + opt.scale = opt.scale || (opt.data && opt.data.scale) || DEFAULT_PICTURE_WIDTH / max(DEFAULT_PICTURE_WIDTH, opt.media.width) + + base.init.call(this, opt) + + this.build(opt) + this.bind() + this.place(opt) + }, + + build: function(opt){ + this.mx = new MX.Image({ + src: this.media.url, + scale: this.scale, + media: this.media, + backface: true, + }) + + if (opt.position) { + opt.position.y = opt.position.y || this.scale * this.media.height/2 + sculpture_distance_from_floor + opt.position.rotationY = opt.position.rotationY || scene.camera.rotationY + } + + scene.add( this.mx ) + }, + + } + + return exports +}) diff --git a/public/assets/javascripts/rectangles/engine/shapes/ortho.js b/public/assets/javascripts/rectangles/engine/shapes/ortho.js new file mode 100644 index 0000000..163f646 --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/shapes/ortho.js @@ -0,0 +1,66 @@ +// An OrthoPolyline is a Polyline where all angles are 90 degrees. + +if (! ('window' in this) ) { + var Polyline = require("./polyline.js") +} + +var OrthoPolyline = Polyline.extend(function(base){ + var exports = {} + exports.type = function(){ + return "ortho" + } + exports.instantiate = function(){ + return new OrthoPolyline + } + exports.canCloseWith = function(p){ + return (this.points.length > 2 && this.points[0].distanceTo( p ) < 10/map.zoom) + } + exports.draw = function(ctx, fillStyle, strokeStyle){ + var points = this.points + if (! points.length) return + if (points.length == 1) { + ctx.fillStyle = "#f80" + map.draw.dot_at(this.points[0].a, points[0].b, 5) + } + if (points.length > 1) { + ctx.fillStyle = fillStyle + ctx.strokeStyle = strokeStyle + ctx.lineWidth = 2 / map.zoom + ctx.beginPath() + ctx.moveTo(points[0].a, points[0].b) + points.forEach(function(point, i){ + i && ctx.lineTo(point.a, point.b) + }) + strokeStyle && ctx.stroke() + if (! map.ui.placing || this.closed) { + fillStyle && ctx.fill() + } + } + } + exports.translateSegment = function(src, dest, dx, dy) { + if (src[0].a == src[1].a) { + dest[0].a = src[0].a + dx + dest[1].a = src[1].a + dx + if (src.length == 3) { + dest[2].a = src[2].a + dx + } + } + else { + dest[0].b = src[0].b + dy + dest[1].b = src[1].b + dy + if (src.length == 3) { + dest[2].b = src[2].b + dy + } + } + } + exports.close = function(){ + this.points[this.points.length] = this.points[0] + this.closed = true + } + return exports +}) + + +if (! ('window' in this) ) { + module.exports = OrthoPolyline +} diff --git a/public/assets/javascripts/rectangles/engine/shapes/polyline.js b/public/assets/javascripts/rectangles/engine/shapes/polyline.js new file mode 100644 index 0000000..b2cd92f --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/shapes/polyline.js @@ -0,0 +1,212 @@ +// A Polyline is a set of points inputted by the user using the V2 editor to trace a blueprint. +// Additionally, it manages a set of MX objects which correspond to the walls in 3D. +// In this way, it attempts to bridge the 2D (canvas, imperative) and 3D (css, declarative) views. + +if (! ('window' in this) ) { + var Fiber = require("../../../vendor/bower_components/fiber/src/fiber.js") + var vec2 = require("../../models/vec2") +} + +var Polyline = Fiber.extend(function(base){ + var exports = {} + exports.init = function(){ + this.points = [] + this.mx_points = [] + this.closed = false + } + exports.type = function(){ + return "polyline" + } + exports.instantiate = function(){ + return new Polyline + } + exports.add = function(p){ + this.points.push( p ) + this.mx_points.push( new MX.Point(p) ) + } + exports.firstPoint = function(){ + return this.points[0] + } + exports.lastPoint = function(){ + return this.points[this.points.length-1] + } + exports.canCloseWith = function(p){ + return (this.points.length > 2 && this.points[0].distanceTo( p ) < 10/map.zoom) + } + exports.getHeadAtIndex = function(index){ + if (index == 0) { return null } + if (index == this.points.length-1) { return this.clone() } + var head = this.instantiate() + head.points = this.points.slice(0, index+1) + return head + } + exports.getTailAtIndex = function(index){ + if (index == this.points.length-1) { return null } + if (index == 0) { return this.clone() } + var tail = this.instantiate() + tail.points = this.points.slice(index, this.points.length) + return tail + } + exports.clone = function(){ + var clone = this.instantiate() + clone.points = this.points.concat() + } + exports.getSegment = function(segment){ + var seg = [ + this.points[segment.head], + this.points[segment.tail], + ] + if (segment.head == 0) { + seg.push( this.lastPoint() ) + } + else if (segment.tail == this.points.length-1) { + seg.push( this.firstPoint() ) + } + return seg + } + exports.cloneSegment = function(segment){ + return this.getSegment(segment).map(function(point){ return point.clone() }) + } + exports.translateSegment = function(src, dest, dx, dy){ + dest[0].a = src[0].a + dx + dest[0].b = src[0].b + dy + dest[1].a = src[1].a + dx + dest[1].b = src[1].b + dy + if (src.length == 3) { + dest[2].a = src[2].a + dx + dest[2].b = src[2].b + dy + } + } + exports.hasPointNear = function(p){ + var point + for (var i = 0; i <Â this.points.length; i++){ + point = this.points[i] + if (point.distanceTo( p ) < 10/map.zoom) { + return point + } + } + return null + } + exports.hasEndPointNear = function(p){ + if (this.closed || ! this.points.length) return null + if (this.firstPoint().distanceTo( p ) < 10/map.zoom) { + return this.firstPoint() + } + if (this.lastPoint().distanceTo( p ) < 10/map.zoom) { + return this.lastPoint() + } + return null + } + exports.hasSegmentNear = function(p, min_dist){ + var p1, p2, d1, d2, sum, rat + var dx, dy, new_x, new_y, x, y, closest_distance = min_dist || Infinity + var closest_i = -1 + var points = this.points + var p1, p2 = points[0] + for (var i = 1; i < points.length; i++) { + p1 = p2 + p2 = points[i] + d1 = p2.a - p1.a + d2 = p2.b - p1.b + sum = d1*d1 + d2*d2 + rat = ((p.a - p1.a) * d1 + (p.b - p1.b) * d2) / sum + rat = rat < 0 ? 0 : rat < 1 ? rat : 1 + new_x = p1.a + rat * d1 + new_y = p1.b + rat * d2 + dx = new_x - p.a + dy = new_y - p.b + sum2 = sqrt(dx*dx+dy*dy) + if (sum2 < closest_distance) { + x = new_x + y = new_y + closest_distance = sum2 + closest_i = i + } + } + if (closest_i == -1) return null + return { + x: x, + y: y, + distance: closest_distance, + head: closest_i-1, + tail: closest_i, + } + } + exports.draw = function(ctx, fillStyle, strokeStyle){ + var points = this.points + if (! points.length) return + if (points.length == 1) { + ctx.fillStyle = "#f80" + map.draw.dot_at(this.points[0].a, points[0].b, 5) + } + if (points.length > 1) { + ctx.fillStyle = fillStyle + ctx.strokeStyle = strokeStyle + ctx.lineWidth = 2 / map.zoom + ctx.beginPath() + ctx.moveTo(points[0].a, points[0].b) + points.forEach(function(point, i){ + i && ctx.lineTo(point.a, point.b) + }) + strokeStyle && ctx.stroke() + if (! map.ui.placing || this.closed) { + fillStyle && ctx.fill() + } + } + } + exports.draw_line = function (ctx, p){ + var last = this.points[this.points.length-1] + ctx.strokeStyle = "#f80" + ctx.lineWidth = 2 / map.zoom + ctx.beginPath() + ctx.moveTo(last.a, last.b) + ctx.lineTo(p.a, p.b) + ctx.stroke() + } + exports.close = function(){ + this.points[this.points.length] = this.points[0] + this.closed = true + } + exports.build = function(){ + this.mx_points && this.mx_points.forEach(function(mx){ scene.remove(mx) }) + this.mx = new MX.Polyline(this) + } + exports.rebuild = function(){ + this.mx.rebuild() + } + exports.getSegments = function(){ + if (this.points.length == 1) { + return [] + } + var segments = [] + for (var i = 1; i < this.points.length; i++) { + segments.push( [ this.points[i-1], this.points[i] ] ) + } + return segments + } + exports.serialize = function(){ + return { + type: this.type(), + closed: this.closed, + points: this.points.map(function(point){ return [point.a, point.b] }), + } + } + exports.deserialize = function(data){ + this.closed = data.closed || false + this.points = (data.points || data).map(function(point){ return new vec2(point[0], point[1]) }) + } + exports.reset = function(){ + this.mx_points.forEach(function(mx){ scene.remove(mx) }) + this.mx_points.length = 0 + this.points.length = 0 + } + exports.destroy = function(){ + this.reset() + this.mx && this.mx.destroy() + } + return exports +}) + +if (! ('window' in this) ) { + module.exports = Polyline +} diff --git a/public/assets/javascripts/rectangles/engine/shapes/regionlist.js b/public/assets/javascripts/rectangles/engine/shapes/regionlist.js new file mode 100644 index 0000000..8c9e732 --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/shapes/regionlist.js @@ -0,0 +1,240 @@ +// This algorithm takes the polylines from ShapeList as input and produces +// a set of Rooms which can be used by the existing V1 mover and editor. + +// The algorithm assumes that +// 1) all angles are orthogonal +// 2) all polylines are closed + +if (! ('window' in this) ) { + var Fiber = require("../../../vendor/bower_components/fiber/src/fiber.js") + var vec2 = require("../../models/vec2") + var Rect = require("../../models/rect") + var sort = require("../../util/sort") +} + +var RegionList = (function(){ + + var RegionList = {} + var regions = RegionList.regions + + // Build a list of regions from the existing shapes. + // Operates on all the shapes at once. + RegionList.build = function(){ + var segments = RegionList.getSortedSegments() + return RegionList.buildRoomsFromSegments(segments) + } + + // Build a list of regions from the individual shapes. + // Same, but operates on the shapes individually + RegionList.buildByShape = function(){ + var shapes = RegionList.getSortedSegmentsByShape() + var region_lists = shapes.map(function(shape){ + return RegionList.buildRoomsFromSegments(shape.segments) + }) + var regions = [] + return regions.concat.apply(regions, region_lists); + } + + RegionList.buildRoomsFromSegments = function(segments){ + + var rooms = [] + var seen_rooms = {} + var open_segments = [] + + var segment, open_segment, x_segment, y_segments, overlapped, seen_segments + + // first pass: generate rooms from the vertical segments only + for (var i = 0; i < segments.length; i++) { + segment = segments[i] + if (! segment.isVertical()) { + continue + } + + // check all the "open segments" we know about, i.e. rooms where we've only found + // the right wall. + overlapped = false + for (var j = 0; j < open_segments.length; j++) { + open_segment = open_segments[j] + + // if these two segments overlap each other, then there is a room between them. + if (segment.y.overlaps(open_segment.y)) { + overlapped = true + open_segments.splice(j--, 1) + + // the X part of the room will be the span between these two vertical segments' + // X components. the Y part of the room is the "split" or subdivision between + // the two horizontal vectors. + + // the split function is non-commutative, + // so we need to call A split B and B split A, + // then dedupe the segments we got back.. + x_segment = new vec2( open_segment.x.a, segment.x.b ) + y_segments = open_segment.y.split(segment.y, 0, 0) + + seen_segments = {} + + // check each of the splits.. if the two segments overlap, then we definitely + // have a room here. + y_segments.forEach(function(seg){ + seen_segments[ seg[0]+"" ] = true + var room = new Rect( x_segment, seg[0] ) + + if (seen_rooms[ room+"" ]) return + seen_rooms[ room+"" ] = true + + room.sides = 0 + + rooms.push(room) + var new_seg = new Rect( segment.x, seg[0] ) + open_segments.unshift(new_seg) + j++ + }) + + // splitting the other way.. + y_segments = segment.y.split(open_segment.y, 0, 0) + y_segments.forEach(function(seg){ + if (seen_segments[ seg[0]+"" ]) return; + var new_seg = new Rect( segment.x, seg[0] ) + open_segments.unshift(new_seg) + j++ + }) + } + } + + // if we have overlap, then re-sort the open segments Y-wise + // and (again) dedupe.. + if (overlapped) { + open_segments = open_segments.sort(function(a,b){ + if (a.y.a < b.y.a) { return -1 } + if (a.y.a == b.y.a) { return 0 } + if (a.y.a > b.y.a) { return 1 } + }) + + if (open_segments.length < 2) { continue } + + for (var k = 1; k < open_segments.length; k++) { + if (open_segments[k-1].y.containsVec(open_segments[k].y)) { + open_segments.splice(k--, 1) + } + else if (open_segments[k-1].y.overlaps(open_segments[k].y)) { + open_segments[k].y = open_segments[k].y.clone() + open_segments[k].y.a = open_segments[k-1].y.b + } + } + } + // if we don't have any overlap, then this is a new open segment. + else { + open_segments.push(segment) + } + } + + var splits, splitter + + // second pass: now that we have a bunch of rooms, assign sides to all of them. + // sides are used in the "mover" script to do bounds checking. + for (var i = 0; i < segments.length; i++) { + segment = segments[i] + var horizontal = segment.isHorizontal(), vertical = segment.isVertical() + for (var r = 0; r < rooms.length; r++){ + room = rooms[r] + + // vertical segments determine the left and right edges of the room, fairly simply. + if (vertical) { + if (segment.y.containsVec(room.y)) { + if (segment.x.a == room.x.a) { + room.sides |= LEFT + } + if (segment.x.a == room.x.b) { + room.sides |= RIGHT + } + } + } + + // horizontal segments determine the front and back edges of the room. + if (horizontal) { + if (segment.x.containsVec(room.x)) { + if (segment.y.a == room.y.a) { + room.sides |= FRONT + } + if (segment.y.a == room.y.b) { + room.sides |= BACK + } + } + + // however, since we did not split on horizontal segments, our rooms may + // only have partial overlap with these segments, in which case we need to + // split the rooms apart. + else if ((segment.y.a == room.y.a || segment.y.a == room.y.b) && room.x.overlaps(segment.x)) { + + // split the room across the segment. preserve whether or not we know the + // room borders a segment on the left or right. + splits = room.x.split(segment.x, room.sides & LEFT, room.sides & RIGHT) + rooms.splice(r--, 1) + for (var k = 0; k < splits.length; k++) { + splitter = splits[k] + var new_room = new Rect( splitter[0], room.y ) + new_room.sides = splitter[1] | (Â room.sides & FRONT_BACK ) + if (segment.x.overlaps( splitter[0] )) { + if (segment.y.a == new_room.y.a) { + new_room.sides |= FRONT + } + if (segment.y.a == new_room.y.b) { + new_room.sides |= BACK + } + } + rooms.unshift(new_room) + r++ + } + } + + } + } + } + + return rooms + } + + // Gets a list of polylines from the ShapeList and sorts the segments. + RegionList.getSortedSegments = function(){ + // get a list of all segments from these polylines + var segments = shapes.getAllSegments() + + segments = segments.map(RegionList.segmentsToRects) + + return sort.rects_by_position(segments) + } + + RegionList.getSortedSegmentsByShape = function(){ + return shapes.getAllShapeSegments().map(function(shape){ + var segments = shape.map(RegionList.segmentsToRects) + return { + shape: shape, + segments: sort.rects_by_position(segments) + } + }) + } + + // re-orient a segment so it's either facing up or right and make it into a rect + RegionList.segmentsToRects = function(segment){ + // vertical + if (segment[0].a == segment[1].a) { + if (segment[0].b > segment[1].b) { + segment.push(segment.shift()) + } + } + // horizontal + else if (segment[0].b == segment[1].b) { + if (segment[0].a > segment[1].a) { + segment.push(segment.shift()) + } + } + return new Rect( segment[0].a, segment[0].b, segment[1].a, segment[1].b ) + } + + if (! ('window' in this) ) { + module.exports = RegionList + } + + return RegionList + +})()
\ No newline at end of file diff --git a/public/assets/javascripts/rectangles/engine/shapes/shapelist.js b/public/assets/javascripts/rectangles/engine/shapes/shapelist.js new file mode 100644 index 0000000..21beb76 --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/shapes/shapelist.js @@ -0,0 +1,124 @@ +// The ShapeList manages the list of polylines which form a V2 layout. + +if (! ('window' in this) ) { + var Fiber = require("../../../vendor/bower_components/fiber/src/fiber.js") + var Polyline = require("./polyline.js") + var OrthoPolyline = require("./ortho.js") +} + +var ShapeList = Fiber.extend(function(base){ + var exports = {} + exports.init = function(){ + this.shapes = [] + this.workline = null + } + exports.add = function(shape){ + this.shapes.push(shape) + } + exports.remove = function(shape){ + var index = this.shapes.indexOf(shape) + if (index !== -1) { + this.shapes.splice(index, 1) + } + } + exports.destroy = function(){ + this.shapes.forEach(function(shape){ + shape.destroy() + }) + this.shapes = [] + } + exports.count = function(){ + return this.shapes.length + } + exports.removeSegment = function (segment){ + var shape = segment.shape + var head = shape.getHeadAtIndex(segment.head) + var tail = shape.getTailAtIndex(segment.tail) + this.remove(shape) + shape.destroy() + if (head) { + this.add(head) + head.build() + } + if (tail) { + this.add(tail) + tail.build() + } + } + exports.findClosestPoint = function (p){ + var point + for (var i = 0; i < this.shapes.length; i++) { + point = this.shapes[i].hasPointNear(p) + if (point) return { point: point, shape: this.shapes[i] } + } + return null + } + exports.findClosestEndPoint = function (p){ + var point + for (var i = 0; i < this.shapes.length; i++) { + point = this.shapes[i].hasEndPointNear(p) + if (point) return { point: point, shape: this.shapes[i] } + } + return null + } + exports.findClosestSegment = function (p){ + var segment = null, closest_segment = null + for (var i = 0; i < this.shapes.length; i++) { + segment = this.shapes[i].hasSegmentNear(p, 10) + if (segment && (! closest_segment || segment.distance < closest_segment.distance)) { + closest_segment = segment + closest_segment.shape = this.shapes[i] + } + } + return closest_segment + } + exports.forEach = function(fn){ + this.shapes.forEach(fn) + } + exports.getAllShapeSegments = function(){ + return this.shapes.map(function(shape){ return shape.getSegments() }) + } + exports.getAllSegments = function(){ + var segments = [] + this.shapes.forEach(function(shape){ + segments = segments.concat( shape.getSegments() ) + }) + return segments + } + exports.draw = function(ctx, fillStyle, strokeStyle) { + this.shapes.forEach(function(shape){ + shape.draw(ctx, fillStyle, strokeStyle) + }) + } + exports.serialize = function(){ + return this.shapes.map(function(shape){ + return shape.serialize() + }) + } + exports.deserialize = function(data){ + data && data.forEach(function(shape_data){ + var line + switch (shape_data.type) { + case 'ortho': + line = new OrthoPolyline() + break + default: + line = new Polyline() + break + } + line.deserialize(shape_data) + shapes.add(line) + }.bind(this)) + } + exports.build = function(){ + this.shapes.forEach(function(shape){ + shape.build() + }) + } + return exports +}) + +if (! ('window' in this) ) { + shapes = new ShapeList + module.exports = shapes +} diff --git a/public/assets/javascripts/rectangles/models/floor.js b/public/assets/javascripts/rectangles/models/floor.js index 51537f3..417494b 100644 --- a/public/assets/javascripts/rectangles/models/floor.js +++ b/public/assets/javascripts/rectangles/models/floor.js @@ -68,8 +68,43 @@ } return } + - if (Scenery.nextWallpaper) { + var offset = offsetFromPoint(e, mx.el) + if (! offset) { return } + + var x = mx.x + mx.width * (offset.left-0.5) + var z = mx.z + mx.height * (0.5-offset.top) + + if (Scenery.nextMedia) { + e.preventDefault() + + var sculpture = Sculpture.addNext({ + position: { x: x, y: 0, z: z }, + }) + + // scenery was not placed + if (! sculpture) { + e.stopPropagation() + return + } + + app.controller.toolbar.resetPermissions() + Sculpture.resize.show(sculpture) + Sculpture.hovering = true + + // app.controller.pick(sculpture) + + UndoStack.push({ + type: 'create-sculpture', + undo: { id: sculpture.id }, + redo: sculpture.serialize(), + }) + + // TODO: watch individual sculpture object here + Minotaur.watch( app.router.editorView.settings ) + } + else if (Scenery.nextWallpaper) { var oldState = base.serialize() base.wallpaper(Scenery.nextWallpaper) // Scenery.nextWallpaper = null @@ -98,7 +133,7 @@ this.mx.reverse() } } - + Floor.prototype.color = function(color){ this.$els.css("background-color", color) } diff --git a/public/assets/javascripts/rectangles/models/rect.js b/public/assets/javascripts/rectangles/models/rect.js index c667cf5..4f73bec 100644 --- a/public/assets/javascripts/rectangles/models/rect.js +++ b/public/assets/javascripts/rectangles/models/rect.js @@ -1,4 +1,3 @@ - (function(){ var vec2 if ('window' in this) { @@ -8,17 +7,17 @@ vec2 = require('./vec2') FRONT = 0x1, BACK = 0x2, LEFT = 0x4, RIGHT = 0x8, FLOOR = 0x10, CEILING = 0x20 TOP = CEILING, BOTTOM = FLOOR - function sidesToString(sides){ - var s = "" - if (sides & FRONT) s += "front " - if (sides & BACK) s += "back " - if (sides & LEFT) s += "left " - if (sides & RIGHT) s += "right " - if (sides & TOP) s += "top " - if (sides & BOTTOM) s += "bottom " - return s - } } + function sidesToString(sides){ + var s = "" + if (sides & FRONT) s += "front " + if (sides & BACK) s += "back " + if (sides & LEFT) s += "left " + if (sides & RIGHT) s += "right " + if (sides & TOP) s += "top " + if (sides & BOTTOM) s += "bottom " + return s + } var Rect = function (x0,y0,x1,y1){ if (x0 instanceof vec2) { @@ -39,6 +38,12 @@ Rect.prototype.clone = function(){ return new Rect( this.x.clone(), this.y.clone() ) } + Rect.prototype.x_component = function(){ + return new vec2( this.x.a, this.y.a ) + } + Rect.prototype.y_component = function(){ + return new vec2( this.x.b, this.y.b ) + } Rect.prototype.assign = function(r) { this.x.assign(r.x) this.y.assign(r.y) @@ -56,6 +61,12 @@ Rect.prototype.maxDimension = function(){ return abs(this.width) > abs(this.height) ? this.width : this.height } + Rect.prototype.isVertical = function(){ + return this.x.isPoint() + } + Rect.prototype.isHorizontal = function(){ + return this.y.isPoint() + } Rect.prototype.mul = function(n){ this.x.mul(n) diff --git a/public/assets/javascripts/rectangles/models/room.js b/public/assets/javascripts/rectangles/models/room.js index 26bf055..1abe2ba 100644 --- a/public/assets/javascripts/rectangles/models/room.js +++ b/public/assets/javascripts/rectangles/models/room.js @@ -31,10 +31,14 @@ var Room = function(opt){ this.id = opt.id || Rooms.uid("room_") this.rect = opt.rect - this.regions = [] + this.regions = opt.regions || [] this.height = opt.height || 200 this.focused = false + + this.mx_walls = [] + this.mx_floor = [] + this.mx_ceiling = [] } Room.prototype.copy = function(){ @@ -125,6 +129,7 @@ Room.prototype.collidesDisc = function(src, dest, radius){ var x = dest.x, y = dest.z var collision = 0, wall_collision, contains_x, contains_y + this.regions.forEach(function(r){ if (! r.sides) return diff --git a/public/assets/javascripts/rectangles/models/vec2.js b/public/assets/javascripts/rectangles/models/vec2.js index 14d0e6b..8942d92 100644 --- a/public/assets/javascripts/rectangles/models/vec2.js +++ b/public/assets/javascripts/rectangles/models/vec2.js @@ -43,6 +43,9 @@ vec2.prototype.eq = function(v){ return this.a == v.a && this.b == v.b } + vec2.prototype.isPoint = function(){ + return this.a == this.b + } vec2.prototype.add = function(n){ this.a += n this.b += n @@ -80,6 +83,11 @@ this.a = Math.round(this.a) this.b = Math.round(this.b) } + vec2.prototype.distanceTo = function(v){ + var va = (this.a - v.a) + var vb = (this.b - v.b) + return Math.sqrt( va*va + vb*vb ) + } vec2.prototype.setPosition = function(n){ var len = this.length() this.a = n @@ -103,6 +111,12 @@ vec2.prototype.containsDisc = function(n,r){ return this.a <= n-r && n+r <= this.b } + vec2.prototype.containsVec = function(v){ + return this.a <= v.a && v.b <= this.b + } + vec2.prototype.containsCenterVec = function(v){ + return this.a < v.a && v.b < this.b + } vec2.prototype.clamp = function(n){ return clamp(n, this.a, this.b) } @@ -200,13 +214,13 @@ } vec2.prototype.toString = function(){ - return "[" + round(this.a) + " " + round(this.b) + "]" + return "[" + Math.round(this.a) + " " + Math.round(this.b) + "]" } vec2.prototype.exactString = function(){ return "[" + this.a + " " + this.b + "]" } vec2.prototype.serialize = function(){ - return [ round(this.a), round(this.b) ] + return [ Math.round(this.a), Math.round(this.b) ] } vec2.prototype.deserialize = function(data){ this.a = data[0] diff --git a/public/assets/javascripts/rectangles/models/vec3.js b/public/assets/javascripts/rectangles/models/vec3.js index c44dfe6..b3825a9 100644 --- a/public/assets/javascripts/rectangles/models/vec3.js +++ b/public/assets/javascripts/rectangles/models/vec3.js @@ -32,3 +32,28 @@ vec3.prototype.apply_projection = function (m) { return this; } + +vec3.prototype.serialize = function(){ + return [ round(this.a), round(this.b), round(this.c) ] +} +vec3.prototype.deserialize = function(data){ + this.a = data[0] + this.b = data[1] + this.c = data[2] || data[0] + return this +} +vec3.prototype.clone = function(){ + return new vec3(this.a, this.b, this.c) +} +vec3.prototype.assign = function(v){ + this.a = v.a + this.b = v.b + this.c = v.c + return this +} +vec3.prototype.mul = function(n) { + this.a *= n + this.b *= n + this.c *= n + return this +}
\ No newline at end of file diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index fc1ccbe..dadcd53 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -10,6 +10,11 @@ vec2 = require('./vec2') Rect = require('./rect') UidGenerator = require('../util/uid') + wall_rotation = {} + wall_rotation[FRONT] = PI + wall_rotation[BACK] = 0 + wall_rotation[LEFT] = HALF_PI + wall_rotation[RIGHT] = -HALF_PI } var Wall = function(opt){ @@ -18,6 +23,7 @@ this.edge = opt.edge this.side = opt.side this.surface = opt.surface + this.rotationY = ('rotationY' in opt) ? opt.rotationY : wall_rotation[opt.side] this.mx = opt.mx this.background = { src: "none" } } @@ -89,7 +95,7 @@ mx_dot.move(mx_pos) mx_dot.width = 5 mx_dot.height = 5 - mx_dot.rotationY = wall_rotation[base.side] + mx_dot.rotationY = base.rotationY mx_dot.el.style.backgroundColor = "red" scene.add(mx_dot) } @@ -192,7 +198,7 @@ } Wall.prototype.serialize = function(){ - return { + return { id: this.id, background: this.background, } @@ -236,7 +242,7 @@ x: x, y: position.b + dimension.b / 2, z: z, - rotationY: wall_rotation[ this.side ], + rotationY: this.rotationY, } } Wall.prototype.mxToPosition = function(mx, dimension) { diff --git a/public/assets/javascripts/rectangles/util/constants.js b/public/assets/javascripts/rectangles/util/constants.js index 3bc314c..522689b 100644 --- a/public/assets/javascripts/rectangles/util/constants.js +++ b/public/assets/javascripts/rectangles/util/constants.js @@ -22,10 +22,11 @@ var height_min = 200, resize_margin = 8, cursor_amp = 1.5, DEFAULT_PICTURE_WIDTH = 350, - MAP_GRID_SIZE = 360 // 10 feet + MAP_GRID_SIZE = 36 // 10 feet var painting_distance_from_wall = 10, - dot_distance_from_picture = 3 + dot_distance_from_picture = 3, + sculpture_distance_from_floor = 3 var dot_hide_delay = 50, // ms dot_side = 20 diff --git a/public/assets/javascripts/rectangles/util/coords.js b/public/assets/javascripts/rectangles/util/coords.js index 74b7fda..ff56199 100644 --- a/public/assets/javascripts/rectangles/util/coords.js +++ b/public/assets/javascripts/rectangles/util/coords.js @@ -30,4 +30,4 @@ function offsetFromPoint(event, element) { return 'left: ' + l + '%, top: ' + t + '%'; } } : null; -} +}
\ No newline at end of file diff --git a/public/assets/javascripts/rectangles/util/measurement.js b/public/assets/javascripts/rectangles/util/measurement.js index d6a0b35..6346eac 100644 --- a/public/assets/javascripts/rectangles/util/measurement.js +++ b/public/assets/javascripts/rectangles/util/measurement.js @@ -28,6 +28,10 @@ function measurementToString( n ) { case 'ft': ft = floor(n / 36) inch = abs(round((n % 36) / 3)) + if (inch == 12) { + inch = 0 + ft += 1 + } s = ft + "'" if (inch > 0) { s += " " + inch + '"' diff --git a/public/assets/javascripts/rectangles/util/minotaur.js b/public/assets/javascripts/rectangles/util/minotaur.js index d165ccc..8b1abfe 100644 --- a/public/assets/javascripts/rectangles/util/minotaur.js +++ b/public/assets/javascripts/rectangles/util/minotaur.js @@ -38,7 +38,7 @@ for (var id in base.objects[type]) { var obj = base.objects[type][id] if (obj) { - obj.save(null, function(){ base.hide() }, function(){}) + obj.save(null, function(){ base.hide() }, function(){ base.hide() }) } delete base.objects[type][id] saving = true @@ -53,9 +53,7 @@ } base.hide = function () { - setTimeout(function(){ - base.$el.removeClass() - }, 500) + base.$el.removeClass('saving') } base.init(); diff --git a/public/assets/javascripts/rectangles/util/mouse.js b/public/assets/javascripts/rectangles/util/mouse.js index cb36038..6d9862c 100644 --- a/public/assets/javascripts/rectangles/util/mouse.js +++ b/public/assets/javascripts/rectangles/util/mouse.js @@ -54,10 +54,20 @@ function mouse (opt) { opt.up && base.tube.on("up", opt.up) opt.rightclick && base.tube.on("rightclick", opt.rightclick) - var offset = (opt.use_offset && opt.el) ? opt.el.getBoundingClientRect() : null + var offset; base.init = function (){ base.bind() + base.set_offset() + } + + base.set_offset = function(){ + if (opt.use_offset && opt.el) { + offset = opt.el.getBoundingClientRect() + } + else { + offset = null + } } base.on = function(){ @@ -73,9 +83,20 @@ function mouse (opt) { opt.el.addEventListener("mousedown", base.mousedown) opt.el.addEventListener("contextmenu", base.contextmenu) } + if (opt.use_offset) { + window.addEventListener("resize", base.set_offset) + } window.addEventListener("mousemove", base.mousemove) window.addEventListener("mouseup", base.mouseup) } + base.unbind = function(){ + if (opt.el) { + opt.el.removeEventListener("mousedown", base.mousedown) + opt.el.removeEventListener("contextmenu", base.contextmenu) + } + window.removeEventListener("mousemove", base.mousemove) + window.removeEventListener("mouseup", base.mouseup) + } base.bind_el = function(el){ el.addEventListener("mousedown", base.mousedown) @@ -126,7 +147,7 @@ function mouse (opt) { } var x = pos.a, y = pos.b - + if (base.down) { base.cursor.x.b = x base.cursor.y.b = y diff --git a/public/assets/javascripts/rectangles/util/wheel.js b/public/assets/javascripts/rectangles/util/wheel.js index 712d470..4155a70 100644 --- a/public/assets/javascripts/rectangles/util/wheel.js +++ b/public/assets/javascripts/rectangles/util/wheel.js @@ -3,8 +3,8 @@ base.wheel = new wheel({ el: document.querySelector("#map"), - update: function(e, val, delta){ - // do something with val + update: function(e, delta){ + // do something with delta }, }) @@ -13,7 +13,7 @@ function wheel (opt) { opt = defaults(opt, { el: document, - fn: function(e, val, delta){}, + update: function(e, delta){}, propagate: false, locked: false, reversible: true, @@ -22,7 +22,7 @@ function wheel (opt) { }) opt.el.addEventListener('wheel', onMouseWheel, false); -// opt.el.addEventListener('mousewheel', onMouseWheel, false); + // opt.el.addEventListener('mousewheel', onMouseWheel, false); opt.el.addEventListener('DOMMouseScroll', onMouseWheel, false); function onMouseWheel (e) { @@ -58,6 +58,8 @@ function wheel (opt) { // opt.val = clamp(opt.val + delta, opt.min, opt.max) + // deltaX is also passed, but these values tend to be unusable + // try http://vvalls.com/assets/test/wheel.html with a trackpad opt.update(e, deltaY, deltaX) } diff --git a/public/assets/javascripts/ui/_router.js b/public/assets/javascripts/ui/_router.js index 3532428..61b1d1b 100644 --- a/public/assets/javascripts/ui/_router.js +++ b/public/assets/javascripts/ui/_router.js @@ -9,6 +9,7 @@ var SiteRouter = Router.extend({ "click [data-role='new-project-modal']": 'newProject', "click [data-role='edit-project-modal']": 'editProject', "click [data-role='edit-profile-modal']": 'editProfile', + "click [data-role='edit-subscription-modal']": 'editSubscription', "click [data-role='new-document-modal']": 'newDocument', "click [data-role='edit-document-modal']": 'editDocument', "click [data-role='destroy-document-modal']": 'destroyDocument', @@ -17,31 +18,38 @@ var SiteRouter = Router.extend({ }, routes: { - "/": 'home', - "/home": 'home', - "/login": 'signin', - "/signin": 'signin', - "/signup": 'signup', + "/": 'home', + "/home": 'home', + "/login": 'signin', + "/signin": 'signin', + "/signup": 'signup', - "/auth/usernameTaken": 'usernameTaken', - "/auth/password": 'passwordReset', - "/auth/forgotPassword": 'passwordForgot', + "/auth/usernameTaken": 'usernameTaken', + "/auth/password": 'passwordReset', + "/auth/forgotPassword": 'passwordForgot', - "/profile": 'profile', - "/profile/edit": 'editProfile', - "/profile/:name": 'profile', - "/about/:name/edit": 'editDocument', - "/about/new": 'newDocument', + "/profile": 'profile', + "/profile/edit": 'editProfile', + "/profile/billing": 'editSubscription', + "/profile/:name": 'profile', + "/about/:name/edit": 'editDocument', + "/about/new": 'newDocument', - "/layout": 'layoutPicker', - "/layout/:name": 'layoutEditor', + "/layout": 'layoutPicker', + "/layout/:name": 'layoutEditor', - "/project": 'projectPicker', - "/project/new": 'newProject', - "/project/new/:layout": 'projectNewWithLayout', - "/project/:name": 'projectViewer', - "/project/:name/edit": 'projectEditor', - "/project/:name/view": 'projectViewer', + "/blueprint": 'blueprintEditor', + "/blueprint/:name": 'blueprintEditor', + + "/project": 'projectPicker', + "/project/new": 'newProject', + "/project/blueprint/:blueprint": 'projectNewWithBlueprint', + "/project/new/:layout": 'projectNewWithLayout', + "/project/:name": 'projectViewer', + "/project/:name/edit": 'projectEditor', + "/project/:name/view": 'projectViewer', + + "/test/blueprint": 'blueprintEditor', }, mobileRoutes: { @@ -56,6 +64,7 @@ var SiteRouter = Router.extend({ "/profile": 'profile', "/profile/edit": 'editProfile', + "/profile/billing": 'editSubscription', "/profile/:name": 'profile', "/project/:name": 'projectViewer', @@ -69,6 +78,7 @@ var SiteRouter = Router.extend({ this.newProjectModal = new NewProjectModal() this.editProjectModal = new EditProjectModal() this.editProfileModal = new EditProfileModal() + this.editSubscriptionModal = new EditSubscriptionModal() this.passwordForgotModal = new PasswordForgot() this.documentModal = new DocumentModal() this.profileView = new ProfileView() @@ -83,7 +93,9 @@ var SiteRouter = Router.extend({ }) } - $("body").removeClass("loading") + setTimeout(function(){ + $("body").removeClass("loading") + }, 200) }, layoutEditor: function(e, name){ @@ -112,6 +124,22 @@ var SiteRouter = Router.extend({ window.history.pushState(null, document.title, "/project/new") this.newProjectModal.load() }, + + projectNewWithBlueprint: function(e, blueprint){ + e && e.preventDefault() + + Rooms.shapesMode = true + + app.mode.editor = true + app.launch() + if (app.unsupported) return + + blueprint = slugify(blueprint) + + window.history.pushState(null, document.title, "/project/blueprint/" + blueprint) + this.editorView = app.controller = new EditorView() + this.editorView.loadBlueprint(blueprint) + }, projectNewWithLayout: function(e, layout){ e && e.preventDefault() @@ -153,6 +181,15 @@ var SiteRouter = Router.extend({ this.readerView = app.controller = new ReaderView() this.readerView.load(name) }, + + blueprintEditor: function(e, name){ + environment.init = environment.minimal + app.launch() + if (app.unsupported) return + + this.blueprintView = app.controller = new BlueprintView () + this.blueprintView.load(name) + }, signup: function(e){ e && e.preventDefault() @@ -195,7 +232,12 @@ var SiteRouter = Router.extend({ this.editProfileModal.load() }, + editSubscription: function(e){ + e && e.preventDefault() + window.history.pushState(null, document.title, "/profile/billing") + this.editSubscriptionModal.load() + }, newDocument: function(e){ e && e.preventDefault() diff --git a/public/assets/javascripts/ui/blueprint/BlueprintEditor.js b/public/assets/javascripts/ui/blueprint/BlueprintEditor.js new file mode 100644 index 0000000..7704689 --- /dev/null +++ b/public/assets/javascripts/ui/blueprint/BlueprintEditor.js @@ -0,0 +1,129 @@ + +var wallHeight = 180 +var shapes = new ShapeList +var last_point = new vec2 (0,0) + +var BlueprintEditor = View.extend(AnimatedView.prototype).extend({ + + regions: [], + + initialize: function(opt){ + this.parent = opt.parent + + $(window).resize(this.resize.bind(this)) + + scene = new MX.Scene().addTo("#perspective") + scene.camera.radius = 20 + cam = scene.camera + + scene.width = window.innerWidth/2 + scene.height = window.innerHeight + scene.perspective = window.innerHeight + + movements = new MX.Movements(cam, viewHeight) + movements.init() + movements.lock() + + app.on("move", function(pos){ + cam.x = pos.x + cam.y = pos.y + cam.z = pos.z + }) + + var floorplan = this.floorplan = new MX.Image({ + backface: true, + }) + scene.add(this.floorplan) + + // recenter perspective view by rightclicking map + this.floorplan.el.addEventListener("contextmenu", function(e){ + e.preventDefault() + var offset = offsetFromPoint(e, this) + var x = (offset.left - 0.5) * floorplan.width * floorplan.scale + var z = (offset.top - 0.5) * floorplan.height * floorplan.scale + controls.opt.center.x = -x + controls.opt.center.y = 0 + controls.opt.center.z = z + }, true) + + scene.update() + + controls = new MX.OrbitCamera({ + el: scene.el, + radius: 3000, + radiusRange: [ 10, 10000 ], + rotationX: PI/4, + rotationY: PI/2, + }) + controls.init() + }, + + resize: function(){ + if (this.parent.orbiting) { + scene.width = window.innerWidth/2 + scene.height = window.innerHeight + this.parent.map.resize( window.innerWidth/2, window.innerHeight ) + this.parent.map.canvas.style.display = "block" + } + else { + scene.width = window.innerWidth + scene.height = window.innerHeight + this.parent.map.canvas.style.display = "none" + } + }, + + loadFloorplan: function(media){ + // console.log(media) + this.floorplan.load({ + media: media, + keepImage: true, + rotationX: -PI/2, + rotationY: PI, + scale: media.scale, + }) + this.startAnimating() + this.regions = RegionList.buildByShape() + }, + + animate: function(t, dt){ + map.update(t) + + movements.update(dt) + controls.update() + scene.update() + + map.draw.ctx.save() + map.draw.translate() + + this.floorplan.draw(map.draw.ctx, true) + + map.draw.coords() + + if (shapes.workline) { + shapes.workline.draw(map.draw.ctx, "rgba(255,255,0,0.1)", "#f80") + if (map.ui.placing && last_point) { + shapes.workline.draw_line( map.draw.ctx, last_point ) + } + } + + shapes.draw(map.draw.ctx, "rgba(255,255,0,0.1)", "#f80") + + map.draw.ctx.strokeStyle = "#f00"; + map.draw.x_at( this.parent.startPosition ) + map.draw.mouse(map.ui.mouse.cursor) + map.draw.camera(scene.camera) + +// var colors = ["rgba(0,0,0,0.1)"] +// var colors = ["rgba(255,255,255,1)"] + +// map.draw.regions(this.regions, colors, "#000") + +// this.regions.forEach(function(room,i){ +// map.draw.ctx.fillStyle = colors[i % colors.length] +// map.draw.ctx.fillRect( room.x.a, room.y.a, room.width(), room.height() ) +// }) + + map.draw.ctx.restore() + }, + +}) diff --git a/public/assets/javascripts/ui/blueprint/BlueprintInfo.js b/public/assets/javascripts/ui/blueprint/BlueprintInfo.js new file mode 100644 index 0000000..51b310e --- /dev/null +++ b/public/assets/javascripts/ui/blueprint/BlueprintInfo.js @@ -0,0 +1,92 @@ + +var BlueprintInfo = View.extend({ + el: "#blueprintInfo", + + events: { + "mousedown": "stopPropagation", + "keydown": 'stopPropagation', + "change [name=height]": 'changeHeight', + "keydown [name=height]": 'enterHeight', + "change [name=units]": 'changeUnits', + "keydown [name=viewHeight]": 'enterViewHeight', + "change [name=viewHeight]": 'changeViewHeight', + "click .openScaler": 'openScaler', + }, + + initialize: function(opt){ + this.parent = opt.parent + this.$height = this.$("[name=height]") + this.$units = this.$("[name=units]") + this.$viewHeight = this.$("[name=viewHeight]") + this.$unitName = this.$(".unitName") + this.$blueprintScaleDisplay = this.$("#blueprintScaleDisplay") + }, + + load: function(data){ + this.$viewHeight.unitVal( window.viewHeight = data.viewHeight || app.defaults.viewHeight ) + this.$height.unitVal( window.wallHeight = data.wallHeight || app.defaults.wallHeight ) + this.$units.val( data.units ) + this.$('span.units').html( data.units ) + this.$unitName.html( data.units ) + + var resolution + switch (data.units) { + case 'ft': + resolution = app.defaults.footResolution + break + case 'm': + resolution = app.defaults.meterResolution + break + case 'px': + default: + resolution = 1 + break + } + this.$blueprintScaleDisplay.html( ((1/data.scale) * resolution).toFixed(1) ) + this.show() + }, + + toggle: function(state){ + this.$el.toggleClass("active", state) + this.$viewHeight.unitVal( window.viewHeight ) + }, + + openScaler: function(){ + this.parent.scaler.pick( this.parent.data, true ) + this.parent.scaler.show() + }, + + show: function(){ + this.toggle(true) + }, + + hide: function(){ + this.toggle(false) + }, + + deselect: function(){ + this.toggle(true) + }, + + enterHeight: function(e){ + if (e.keyCode == 13) this.changeHeight(e) + }, + changeHeight: function(e){ + e.stopPropagation() + window.wallHeight = this.$height.unitVal() + shapes.forEach(function(line){ + line.mx.set_height( window.wallHeight ) + }) + }, + changeUnits: function(){ + app.units = this.$units.val() + this.$('.units').resetUnitVal() + }, + enterViewHeight: function(e){ + if (e.keyCode == 13) this.changeViewHeight(e) + }, + changeViewHeight: function(){ + window.viewHeight = this.$viewHeight.unitVal() + } + +}) diff --git a/public/assets/javascripts/ui/blueprint/BlueprintNotice.js b/public/assets/javascripts/ui/blueprint/BlueprintNotice.js new file mode 100644 index 0000000..4b799a6 --- /dev/null +++ b/public/assets/javascripts/ui/blueprint/BlueprintNotice.js @@ -0,0 +1,62 @@ +var BlueprintNotice = View.extend(ToggleableView.prototype).extend({ + + el: "#blueprintNotice", + + events: { + "click .next": "next", + }, + + initialize: function(opt){ + this.parent = opt.parent + this.$notice = this.$(".notice") + this.$next = this.$(".next") + }, + + notice: function(msg){ + this.$notice.html(msg) + }, + + showCreateProjectNotice: function(){ + this.notice("<a href='/project/blueprint/" + this.parent.data.slug + + "'>Start a new project</a> with this blueprint.") + this.$next.hide() + this.nextFn = null + this.show() + }, + + showStartPositionNotice: function(){ + this.parent.settings.hide() + this.notice("First, click the map to set the starting location.") + this.$next.show().html("Next") + this.show() + this.nextFn = this.showStartAngleNotice.bind(this) + }, + + showStartAngleNotice: function(){ + this.parent.settings.hide() + this.notice("Next, rotate the camera to the desired orientation.") + this.$next.show().html("Done") + this.show() + this.nextFn = this.doneSettingPosition.bind(this) + this.parent.toolbar.toggleOrbitMode(false) + }, + + doneSettingPosition: function(){ + this.nextFn = null + this.$next.hide() + this.hide() + this.parent.settings.show() + this.parent.startPosition.rotationX = cam.rotationX + this.parent.startPosition.rotationY = cam.rotationY + this.parent.toolbar.toggleOrbitMode(true) + this.parent.toolbar.orthoPolylineMode() + }, + + nextFn: null, + next: function(){ + if (this.nextFn) { + this.nextFn() + } + }, + +})
\ No newline at end of file diff --git a/public/assets/javascripts/ui/blueprint/BlueprintScaler.js b/public/assets/javascripts/ui/blueprint/BlueprintScaler.js new file mode 100644 index 0000000..cd370ef --- /dev/null +++ b/public/assets/javascripts/ui/blueprint/BlueprintScaler.js @@ -0,0 +1,158 @@ + +var BlueprintScaler = ModalFormView.extend(AnimatedView.prototype).extend({ + el: ".blueprintScaler", + + fixedClose: true, + + action: "/api/blueprint/scale", + + events: { + "change [name=blueprint-dimensions]": "changeDimensions", + "change [name=blueprint-units]": "changeUnits", + "click .uploadNewBlueprint": "showUploader", + }, + + initialize: function(opt){ + this.parent = opt.parent + + this.$blueprintMap = this.$("#blueprintMap") + this.$blueprintDimensionsRapper = this.$("#blueprintDimensions") + this.$dimensions = this.$("[name=blueprint-dimensions]") + this.$pixels = this.$("[name=blueprint-pixels]") + this.$units = this.$("[name=blueprint-units]") + this.$save = this.$("#saveBlueprint") + + this.map = new Map ({ + type: "ortho", + el: this.$blueprintMap.get(0), + width: window.innerWidth, + height: window.innerHeight, + zoom: -2, + zoom_min: -7.0, + zoom_max: 2, + }) + this.lineTool = new LineTool + this.map.ui.add_tool("line", this.lineTool) + this.map.ui.set_tool("line") + + scene = scene || { camera: { x: 0, y: 0, z: 0 } } + + this.floorplan = new MX.Image () + }, + + showUploader: function(){ + this.parent.uploader.show() + }, + + pick: function(media, shouldEdit){ + this.media = media + + this.floorplan.load({ media: media, scale: 1, keepImage: true }) + + if (!! media.units && ! shouldEdit) { + this.parent.ready(media) + this.hide() + this.stopAnimating() + return + } + + if (media.units && media.line && media.scale) { + var points = media.line.split(",") + this.lineTool.line[0] = new vec2( +points[0], +points[1] ) + this.lineTool.line[1] = new vec2( +points[2], +points[3] ) + + app.units = media.units + this.$units.val( media.units ) + this.$dimensions.unitVal( media.scale * this.lineLength() ) + } + + this.startAnimating() + }, + + animate: function(t, dt){ + this.map.update(t) + + this.map.draw.ctx.save() + this.map.draw.translate() + + this.floorplan.draw(this.map.draw.ctx, true) + + this.map.draw.ctx.save() + this.map.draw.ctx.strokeStyle = "#f00" + this.map.draw.ctx.lineWidth = 1/map.zoom + switch (this.lineTool.line.length) { + case 1: + this.map.draw.line( + this.lineTool.line[0].a, + this.lineTool.line[0].b, + this.lineTool.cursor.x.a, + this.lineTool.cursor.y.a + ) + break + case 2: + this.map.draw.line( + this.lineTool.line[0].a, + this.lineTool.line[0].b, + this.lineTool.line[1].a, + this.lineTool.line[1].b + ) + break + } + this.map.draw.ctx.restore() + + this.map.draw.coords() + + this.map.draw.mouse(this.map.ui.mouse.cursor) + + this.map.draw.ctx.restore() + }, + + changeDimensions: function(){ + app.units = this.$units.val() + this.$dimensions.unitVal() + }, + changeUnits: function(){ + app.units = this.$units.val() + this.$dimensions.resetUnitVal() + }, + lineLength: function(){ + if (this.lineTool.line.length !== 2) return 0 + var line = this.lineTool.line + return dist( line[0].a, line[0].b, line[1].a, line[1].b ) + }, + + validate: function(){ + var val = this.$dimensions.unitVal() + var errors = [] + if (! this.lineLength()) { + errors.push("no line") + this.$dimensions.val("") + alert("Please click two corners of a wall and then specify how long it is in feet or meters.") + } + else if (val == 0) { + errors.push("no measurement") + alert("Please tell us how long the wall is in feet or meters.") + } + return errors + }, + + showErrors: function(){}, + + serialize: function(){ + var fd = new FormData(), line = this.lineTool.line + fd.append( "_id", this.media._id) + fd.append( "units", this.$units.val() ) + fd.append( "scale", this.$dimensions.unitVal() / this.lineLength() ) + fd.append( "line", [line[0].a,line[0].b,line[1].a,line[1].b].join(",") ) + fd.append( "_csrf", $("[name=_csrf]").val()) + return fd + }, + + success: function(){ + this.media.scale = this.$dimensions.unitVal() / this.lineLength() + this.stopAnimating() + this.parent.ready(this.media) + this.hide() + }, + +}) diff --git a/public/assets/javascripts/ui/blueprint/BlueprintSettings.js b/public/assets/javascripts/ui/blueprint/BlueprintSettings.js new file mode 100644 index 0000000..8addb9c --- /dev/null +++ b/public/assets/javascripts/ui/blueprint/BlueprintSettings.js @@ -0,0 +1,123 @@ + +var BlueprintSettings = FormView.extend(ToggleableView.prototype).extend({ + el: "#blueprintSettings", + + action: "/api/blueprint/edit", + destroyAction: "/api/blueprint/destroy", + + events: { + "mousedown": "stopPropagation", + "keydown": 'stopPropagation', + "keydown [name=name]": 'enterSubmit', + "click [data-role='save-layout']": 'clickSave', + "click [data-role='clear-layout']": 'clear', + "click [data-role='destroy-layout']": 'destroy', + }, + + initialize: function(opt){ + this.parent = opt.parent + this.__super__.initialize.call(this) + + this.$id = this.$("[name=_id]") + this.$csrf = this.$("[name=_csrf]") + this.$name = this.$("[name=name]") + }, + + load: function(data){ + this.$id.val(data._id) + if (data.name) { + this.$name.val(data.name) + this.hide() + } + else { + this.$name.val("") + } + if (data.shapes) { + shapes.destroy() + shapes.deserialize( data.shapes ) + shapes.build() + } + }, + + clear: function(){ + shapes.destroy() + }, + + destroy: function(){ + var msg = "Are you sure you want to delete the blueprint " + sanitize(this.$name.val()) + "?" + ConfirmModal.confirm(msg, function(){ + $.ajax({ + url: this.destroyAction, + type: "delete", + data: { _id: this.$id.val(), _csrf: this.$csrf.val() }, + success: function(data){ + window.location.href = "/layout" + } + }) + }.bind(this)) + }, + + enterSubmit: function (e) { + e.stopPropagation() + var base = this + if (e.keyCode == 13) { + setTimeout(function(){ base.save(e) }, 100) + } + }, + + validate: function(){ + var errors = [] + var name = this.$name.val() + if (! name || ! name.length) { + errors.push("Blueprint needs a name.") + } + if (shapes.count() == 0) { + errors.push("Please add some walls.") + } + return errors + }, + + showErrors: function(errors){ + var $errors = $("<span>") + errors.forEach(function(err){ + var $row = $("<div>") + $row.html(err) + $errors.append( $row ) + }) + ErrorModal.alert($errors) + }, + + serialize: function(){ + var fd = new FormData() + fd.append( "_csrf", this.$csrf.val() ) + fd.append( "_id", this.$id.val() ) + fd.append( "name", this.$name.val() ) + fd.append( "shapes", JSON.stringify( shapes.serialize() ) ) + fd.append( "startPosition", JSON.stringify( this.parent.quantizeStartPosition() ) ) + fd.append( "wallHeight", this.parent.info.$height.unitVal() ) + fd.append( "units", this.parent.info.$units.val() ) + return fd + }, + + clickSave: function(){ + this.toggle(false) + this.save() + }, + + success: function(data){ + this.parent.data = data + + this.$id.val(data._id) + this.$name.val(data.name) + this.action = this.updateAction + + this.hide() + this.parent.notice.showCreateProjectNotice() + + Minotaur.unwatch(this) + Minotaur.hide() + + window.history.pushState(null, document.title, "/blueprint/" + data.slug) + }, + +}) diff --git a/public/assets/javascripts/ui/blueprint/BlueprintToolbar.js b/public/assets/javascripts/ui/blueprint/BlueprintToolbar.js new file mode 100644 index 0000000..458357d --- /dev/null +++ b/public/assets/javascripts/ui/blueprint/BlueprintToolbar.js @@ -0,0 +1,97 @@ +var BlueprintToolbar = View.extend({ + + el: "#blueprintToolbar", + + events: { + "click [data-role=upload-floorplan]": 'showUploader', + "click [data-role=toggle-orbit-mode]": 'toggleOrbitMode', + "click [data-role=arrow-mode]": 'arrowMode', + "click [data-role=polyline-mode]": 'polylineMode', + "click [data-role=ortho-polyline-mode]": 'orthoPolylineMode', + "click [data-role=eraser-mode]": 'eraserMode', + "click [data-role=start-position-mode]": 'startPositionMode', + "click [data-role=toggle-layout-settings]": 'toggleSettings', + }, + + initialize: function(opt){ + this.parent = opt.parent + + this.$modes = this.$('.mode') + this.$toggleOrbitMode = this.$('[data-role=toggle-orbit-mode]') + this.$arrowMode = this.$('[data-role=arrow-mode]') + this.$polylineMode = this.$('[data-role=polyline-mode]') + this.$orthoPolylineMode = this.$('[data-role=ortho-polyline-mode]') + this.$eraserMode = this.$('[data-role=eraser-mode]') + this.$startPositionMode = this.$('[data-role=start-position-mode]') + + keys.on('escape', function(){ + app.controller.toolbar.toggleOrbitMode() + }) + + this.arrowMode() + }, + + showUploader: function(){ + this.parent.scaler.show() + this.parent.uploader.show() + }, + + toggleOrbitMode: function(state){ + this.parent.orbiting = typeof state == "boolean" ? state : ! this.parent.orbiting + this.$toggleOrbitMode.toggleClass("inuse", ! this.parent.orbiting) + this.parent.editor.resize() + if (this.parent.orbiting) { + controls.toggle(true) + movements.lock() + } + else { + controls.toggle(false) + movements.unlock() + movements.gravity(true) + var pos = this.parent.quantizeStartPosition() + cam.rotationX = pos.rotationX + cam.rotationY = pos.rotationY + cam.x = pos.x + cam.y = viewHeight + cam.z = pos.z + } + }, + + toggleSettings: function(){ + this.parent.settings.toggle() + this.parent.notice.toggle( ! this.parent.data.isNew && ! this.parent.settings.visible() ) + }, + + setActiveMode: function( $el ) { + this.$modes.removeClass('active') + $el.addClass('active') + }, + + arrowMode: function(){ + this.setActiveMode( this.$arrowMode ) + this.parent.map.ui.set_tool("arrow") + }, + + polylineMode: function(){ + this.setActiveMode( this.$polylineMode ) + this.parent.map.ui.set_tool("polyline") + }, + + orthoPolylineMode: function(){ + this.setActiveMode( this.$orthoPolylineMode ) + this.parent.map.ui.set_tool("ortho-polyline") + }, + + eraserMode: function(){ + this.setActiveMode( this.$eraserMode ) + this.parent.map.ui.set_tool("eraser") + }, + + startPositionMode: function(){ + this.setActiveMode( this.$startPositionMode ) + this.parent.map.ui.set_tool("start-position") + this.parent.settings.hide() + this.parent.notice.showStartPositionNotice() + }, + +})
\ No newline at end of file diff --git a/public/assets/javascripts/ui/blueprint/BlueprintUploader.js b/public/assets/javascripts/ui/blueprint/BlueprintUploader.js new file mode 100644 index 0000000..aa62a4c --- /dev/null +++ b/public/assets/javascripts/ui/blueprint/BlueprintUploader.js @@ -0,0 +1,147 @@ + +var BlueprintUploader = UploadView.extend({ + el: ".blueprintUploader", + + mediaTag: "blueprint", + createAction: "/api/blueprint/new", + uploadAction: "/api/blueprint/upload", + listAction: "/api/blueprint/user", + destroyAction: "/api/blueprint/destroy", + + events: { + "mousedown": 'stopPropagation', + "change .url": "enterUrl", + "keydown .url": "enterSetUrl", + + "click .blueprint": "pick", + "click .remove": "destroy", + }, + + initialize: function(opt){ + this.parent = opt.parent + this.__super__.initialize.call(this) + + this.$url = this.$(".url") + this.$blueprints = this.$(".blueprints") + }, + + loaded: false, + nameToShow: null, + load: function(name){ + this.nameToShow = name || "" + $.get(this.listAction, { tag: this.mediaTag }, this.populate.bind(this)) + }, + + populate: function(data){ + this.loaded = true + if (data && data.length) { + this.$blueprints.show() + data.forEach(this.append.bind(this)) + if (this.nameToShow === "new") { + // don't pick anything.. + this.show() + } + else if (! this.nameToShow) { + this.hide() + data.some(function(el){ + if (el.slug == this.nameToShow) { + this.parent.scaler.pick(el) + return true + } + }.bind(this)) + } + else { + this.hide() + this.parent.scaler.pick(data[0]) + } + } + else { + this.parent.scaler.hideClose() + this.show() + } + }, + + pick: function(e){ + var $el = $(e.currentTarget) + var media = $el.data("media") + this.hide() + this.parent.scaler.pick(media) + if (media.slug) { + window.history.pushState(null, document.title, "/blueprint/" + media.slug) + } + }, + + destroy: function(e){ + e.stopPropagation() + var $el = $(e.currentTarget) + var _id = $el.closest(".blueprint").data("id") + $el.remove() + $.ajax({ + type: "delete", + url: this.destroyAction, + data: { _id: _id, _csrf: $("[name=_csrf]").val() } + }).complete(function(){ + }) + }, + + show: function(){ + this.toggle(true) + }, + hide: function(){ + this.toggle(false) + }, + toggle: function (state) { + this.$el.toggleClass("active", state) + }, + + addUrl: function (url){ + Parser.loadImage(url, function(media){ + if (! media) return + media._csrf = $("[name=_csrf]").val() + media.tag = this.mediaTag + + var request = $.ajax({ + type: "post", + url: this.createAction, + data: media, + }) + request.done(this.add.bind(this)) + + }.bind(this)) + }, + enterUrl: function(){ + var url = this.$url.sanitize() + this.addUrl(url) + this.$url.val("") + }, + enterSetUrl: function (e) { + e.stopPropagation() + if (e.keyCode == 13) { + setTimeout(this.enterUrl.bind(this), 100) + } + }, + + add: function(media){ + this.$blueprints.show() + this.append(media) + this.hide() + this.parent.scaler.pick(media, true) + }, + + append: function(media){ + var $el = $("<span>") + var img = new Image () + img.src = media.url + var remove = document.createElement("span") + remove.className = "remove" + remove.innerHTML = "<span>x</span>" + + $el.data("id", media._id) + $el.data("media", media) + $el.append(img) + $el.append(remove) + $el.addClass("blueprint") + this.$blueprints.append($el) + }, + +}) diff --git a/public/assets/javascripts/ui/blueprint/BlueprintView.js b/public/assets/javascripts/ui/blueprint/BlueprintView.js new file mode 100644 index 0000000..1858c3d --- /dev/null +++ b/public/assets/javascripts/ui/blueprint/BlueprintView.js @@ -0,0 +1,106 @@ + +var BlueprintView = View.extend({ + el: "#blueprintView", + + action: "/api/blueprint/show/", + + events: { + }, + + initialize: function(){ +// this.colorControl = new ColorControl ({ parent: this }) +// this.cursor = new HelpCursor({ parent: this }) + this.map = this.buildMap() + this.editor = new BlueprintEditor ({ parent: this }) + this.toolbar = new BlueprintToolbar ({ parent: this }) + this.uploader = new BlueprintUploader ({ parent: this }) + this.scaler = new BlueprintScaler ({ parent: this }) + this.info = new BlueprintInfo ({ parent: this }) + this.settings = new BlueprintSettings ({ parent: this }) + this.notice = new BlueprintNotice ({ parent: this }) + Rooms.shapesMode = true + }, + + load: function(name){ + name = sanitize(name) || "new" + this.uploader.load(name) +// name = sanitize(name) +// $.get(this.action + name, this.ready.bind(this)) + }, + + orbiting: true, + startPosition: {}, + quantizeStartPosition: function(){ + // + var regions = RegionList.build() + var pos = this.startPosition + var startPositionIsInARoom = regions.some(function(region){ + return region.contains(pos.x, pos.z) + }) + if (startPositionIsInARoom) { + return this.startPosition + } + else if (! regions.length) { + return { + x: 0, + y: viewHeight, + z: 0, + rotationX: 0, + rotationY: Math.PI/2, + } + } + else { + var center = regions[0].center() + return { + x: center.a, + y: viewHeight, + z: center.b, + rotationX: 0, + rotationY: Math.PI/2, + } + } + }, + + buildMap: function(){ + // i forget if this has to be global + map = new Map ({ + type: "ortho", + el: document.querySelector("#orthographic"), + width: window.innerWidth/2, + height: window.innerHeight, + zoom: -2, + zoom_min: -6.2, + zoom_max: 1, + }) + map.ui.add_tool("arrow", new ArrowTool) + map.ui.add_tool("polyline", new PolylineTool) + map.ui.add_tool("ortho-polyline", new OrthoPolylineTool) + map.ui.add_tool("eraser", new EraserTool) + map.ui.add_tool("position", new PositionTool) + map.ui.add_tool("start-position", new StartPositionTool) + map.ui.placing = false + return map + }, + + ready: function(data){ + this.data = data + this.info.load(data) + this.settings.load(data) + this.editor.loadFloorplan(data) + if (! data.shapes || data.shapes.length == 0) { + this.startPosition = { x: 0, y: 0, z: 0, rotationX: 0, rotationY: Math.PI/2 } + } + else { + this.startPosition = data.startPosition + } + this.notice.hide() + this.settings.show() + }, + + hideExtras: function(){ + }, + + pickWall: function(wall, pos){ + }, + +}) diff --git a/public/assets/javascripts/ui/builder/BuilderInfo.js b/public/assets/javascripts/ui/builder/BuilderInfo.js index 9a7dbf9..aa58d6e 100644 --- a/public/assets/javascripts/ui/builder/BuilderInfo.js +++ b/public/assets/javascripts/ui/builder/BuilderInfo.js @@ -40,8 +40,8 @@ var BuilderInfo = View.extend({ load: function(data){ this.$viewHeight.unitVal( window.viewHeight = data.viewHeight || app.defaults.viewHeight ) - this.$units.val( "ft" ) - this.$unitName.html( "ft" ) + this.$units.val( data.units || "ft" ) + this.$unitName.html( data.units || "ft" ) if (Rooms.regions.length == 0) { this.changeHeightGlobal(true) diff --git a/public/assets/javascripts/ui/builder/BuilderSettings.js b/public/assets/javascripts/ui/builder/BuilderSettings.js index c8c8880..256bffe 100644 --- a/public/assets/javascripts/ui/builder/BuilderSettings.js +++ b/public/assets/javascripts/ui/builder/BuilderSettings.js @@ -52,7 +52,7 @@ var BuilderSettings = FormView.extend({ this.$name.val( names.join(" ") ) this.action = this.createAction - window.history.pushState(null, document.title, "/builder/new") + window.history.pushState(null, document.title, "/layout/new") }, clear: function(){ diff --git a/public/assets/javascripts/ui/builder/BuilderToolbar.js b/public/assets/javascripts/ui/builder/BuilderToolbar.js index 6c218be..e9dcce3 100644 --- a/public/assets/javascripts/ui/builder/BuilderToolbar.js +++ b/public/assets/javascripts/ui/builder/BuilderToolbar.js @@ -60,6 +60,9 @@ var BuilderToolbar = View.extend({ var state = map.ui.permissions.toggle("destroy") $(".inuse").removeClass("inuse") $(e.currentTarget).toggleClass("inuse", state) + if (! state) { + this.resetPermissions() + } }, }) diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js index b319404..5aa88e9 100644 --- a/public/assets/javascripts/ui/editor/EditorSettings.js +++ b/public/assets/javascripts/ui/editor/EditorSettings.js @@ -41,7 +41,12 @@ var EditorSettings = FormView.extend({ this.action = data.isNew ? this.createAction : this.updateAction this.parent.data = data - data.rooms && Rooms.deserialize(data.rooms, data.walls) + if (data.shapes && data.shapes.length) { + Rooms.deserializeFromShapes(data, data.walls) + } + else if (data.rooms) { + Rooms.deserialize(data.rooms, data.walls) + } if (data.startPosition) { scene.camera.move(data.startPosition) this.startPosition = data.startPosition @@ -77,6 +82,7 @@ var EditorSettings = FormView.extend({ data.privacy && this.$privacy.find("[value=" + data.privacy + "]").prop("checked", "checked") data.media && Scenery.deserialize(data.media) + data.sculpture && Sculpture.deserialize(data.sculpture) } }, @@ -112,6 +118,7 @@ var EditorSettings = FormView.extend({ clear: function(e){ e.preventDefault() Scenery.removeAll() + Sculpture.removeAll() }, destroy: function(){ @@ -187,10 +194,16 @@ var EditorSettings = FormView.extend({ fd.append( "description", this.$description.val() ) fd.append( "privacy", this.$privacy.filter(":checked").val() == "private" ) fd.append( "viewHeight", window.viewHeight ) - fd.append( "rooms", JSON.stringify( Rooms.serialize() ) ) + if (Rooms.shapesMode) { + fd.append( "shapes", JSON.stringify( shapes.serialize() ) ) + } + else { + fd.append( "rooms", JSON.stringify( Rooms.serialize() ) ) + } fd.append( "walls", JSON.stringify( Walls.serialize() ) ) fd.append( "colors", JSON.stringify( Walls.colors ) ) fd.append( "media", JSON.stringify( Scenery.serialize() ) ) + fd.append( "sculpture", JSON.stringify( Sculpture.serialize() ) ) fd.append( "startPosition", JSON.stringify( this.startPosition || false ) ) fd.append( "lastPosition", JSON.stringify( app.position(scene.camera) ) ) diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js index 50d3650..c05b373 100644 --- a/public/assets/javascripts/ui/editor/EditorView.js +++ b/public/assets/javascripts/ui/editor/EditorView.js @@ -2,6 +2,7 @@ var EditorView = View.extend({ el: "#editorView", + blueprintAction: "/api/blueprint/user/", projectAction: "/api/project/", layoutAction: "/api/layout/", @@ -17,6 +18,7 @@ var EditorView = View.extend({ this.mediaUpload = new MediaUpload ({ parent: this }) this.mediaTumblr = new MediaTumblr ({ parent: this }) this.mediaEditor = new MediaEditor ({ parent: this }) + this.sculptureEditor = new SculptureEditor ({ parent: this }) this.wallpaperPicker = new WallpaperPicker ({ parent: this }) this.colorControl = new ColorControl ({ parent: this }) this.textEditor = new TextEditor ({ parent: this }) @@ -40,6 +42,10 @@ var EditorView = View.extend({ $.get(this.layoutAction + layout, this.readyLayout.bind(this)) }, + loadBlueprint: function(blueprint){ + $.get(this.blueprintAction + blueprint, this.readyLayout.bind(this)) + }, + ready: function(data){ $("#map").hide() @@ -56,12 +62,19 @@ var EditorView = View.extend({ }, pick: function(scenery){ - if (scenery.type == "text") { + if (scenery.isSculpture) { + this.mediaEditor.hide() + this.textEditor.hide() + this.sculptureEditor.pick(scenery) + } + else if (scenery.type == "text") { this.mediaEditor.hide() + this.sculptureEditor.hide() this.textEditor.pick(scenery) } else { this.textEditor.hide() + this.sculptureEditor.hide() this.mediaEditor.pick(scenery) } }, @@ -72,9 +85,11 @@ var EditorView = View.extend({ }, hideExtras: function(){ + this.sculptureEditor.hide() this.mediaEditor.hide() this.textEditor.hide() this.share.hide() + Sculpture.resize.hide() Scenery.resize.hide() Scenery.hovering = false } diff --git a/public/assets/javascripts/ui/editor/SculptureEditor.js b/public/assets/javascripts/ui/editor/SculptureEditor.js new file mode 100644 index 0000000..953260c --- /dev/null +++ b/public/assets/javascripts/ui/editor/SculptureEditor.js @@ -0,0 +1,237 @@ + +var SculptureEditor = FormView.extend({ + el: "#sculptureEditor", + + events: { + "keydown": 'taint', + "focus [name]": "clearMinotaur", + "click [data-role=play-media]": "togglePaused", + "mousedown [name=keyframe]": "stopPropagation", + "mousedown": "stopPropagation", + "change [name=keyframe]": "seek", + "change [name=autoplay]": "setAutoplay", + "change [name=billboard]": "setBillboard", + "change [name=outline]": "setOutline", + "change [name=outlineColor]": "setOutlineColor", + "change [name=loop]": "setLoop", + "change [name=mute]": "setMute", + "change [name=width]": 'changeWidth', + "change [name=height]": 'changeHeight', + "change [name=depth]": 'changeDepth', + "change [name=units]": 'changeUnits', + "click [data-role=destroy-sculpture]": "destroy", + }, + + initialize: function(opt){ + this.parent = opt.parent + this.__super__.initialize.call(this) + + this.$name = this.$("[name=name]") + this.$description = this.$("[name=description]") + + this.$billboard = this.$("[name=billboard]") + this.$outline = this.$("[name=outline]") + this.$outlineColor = this.$("[name=outlineColor]") + + // image fields + this.$width = this.$("[name=width]") + this.$height = this.$("[name=height]") + this.$depth = this.$("[name=depth]") + this.$units = this.$("[name=units]") + + // video fields + this.$playButton = this.$("[data-role=play-media]") + this.$autoplay = this.$("[name=autoplay]") + this.$loop = this.$("[name=loop]") + this.$mute = this.$("[name=mute]") + this.$keyframe = this.$("[name=keyframe]") + }, + + toggle: function(state) { + if (state) { + this.parent.settings.toggle() + } + this.$el.toggleClass("active", state); + }, + + togglePaused: function(state){ + var state = this.sculpture.toggle(state) + this.$playButton.toggleClass("paused", ! state) + }, + + pick: function(sculpture) { + if (this.sculpture && sculpture !== this.sculpture) { + this.unbind() + } + + this.bind(sculpture) + this.$el.addClass("active") + +// app.controller.toolbar.resetMode() + app.controller.toolbar.resetControls() + Sculpture.resize.show(sculpture) + Sculpture.hovering = true + + var media = sculpture.media + + // console.log(media) + this.$name.val(media.title || "") // || filenameFromUrl(media.url) ) + this.$description.val(media.description || "") + this.setDimensions() + this.$units.val( "ft" ) + + this.$outline.prop( 'checked', !! sculpture.outline ) + this.$outlineColor.val( sculpture.outlineColor || "#000000" ) + this.$billboard.prop( 'checked', !! sculpture.billboard ) + + switch (media.type) { + case "image": + this.$(".video").hide() + this.$(".audio").hide() + this.$(".image").show() + break + + case "youtube": + case "vimeo": + case "video": + this.$(".image").hide() + this.$(".audio").hide() + this.$(".video").show() + + this.$playButton.toggleClass("paused", ! this.sculpture.paused()) + this.$autoplay.prop('checked', !! media.autoplay) + this.$loop.prop('checked', !! media.loop) + this.$mute.prop('checked', !! media.mute) + this.$keyframe.val( Number(media.keyframe || 0) ) + break + + case "soundcloud": + this.$(".image").hide() + this.$(".video").hide() + this.$(".audio").show() + this.$playButton.toggleClass("paused", ! this.sculpture.paused()) + this.$autoplay.prop('checked', !! media.autoplay) + this.$loop.prop('checked', !! media.loop) + break + } + }, + + hide: function(sculpture){ + if (this.sculpture) { + this.unbind() + } + this.toggle(false) + }, + + seek: function(){ + var n = parseFloat( this.$keyframe.val() ) + this.sculpture.seek(n) + this.tainted = true + + this.sculpture.media.keyframe = n + }, + setAutoplay: function(){ + var checked = this.$autoplay.prop('checked') + this.sculpture.media.autoplay = checked + this.tainted = true + if (checked && this.sculpture.paused()) { + this.togglePaused() + } + }, + setLoop: function(){ + var checked = this.$loop.prop('checked') + this.sculpture.setLoop(checked) + this.tainted = true + }, + setMute: function(){ + var checked = this.$mute.prop('checked') + this.sculpture.media.mute = checked + this.sculpture.mute(checked) + this.tainted = true + }, + + setBillboard: function(){ + var checked = this.$billboard.prop('checked') + this.sculpture.setBillboard(checked) + this.tainted = true + }, + setOutline: function(){ + var checked = this.$outline.prop('checked') + this.sculpture.setOutline(checked) + this.tainted = true + }, + setOutlineColor: function(){ + var color = this.$outlineColor.val() + this.sculpture.setOutlineColor(color) + this.tainted = true + }, + + setDimensions: function(){ + if (! this.sculpture) return + this.$width.unitVal( Number(this.sculpture.naturalDimensions.a * this.sculpture.scale) || "" ) + this.$height.unitVal( Number(this.sculpture.naturalDimensions.b * this.sculpture.scale) || "" ) + this.$depth.unitVal( Number(this.sculpture.naturalDimensions.c * this.sculpture.scale) || "" ) + this.tainted = true + }, + changeWidth: function(e){ + e.stopPropagation() + this.sculpture.set_scale( this.$width.unitVal() / this.sculpture.naturalDimensions.a ) + this.setDimensions() + this.sculpture.updateOutline() + }, + changeHeight: function(e){ + e.stopPropagation() + this.sculpture.set_scale( this.$height.unitVal() / this.sculpture.naturalDimensions.b ) + this.setDimensions() + this.sculpture.updateOutline() + }, + changeDepth: function(e){ + e.stopPropagation() + this.sculpture.set_depth( this.$depth.unitVal() ) + this.$depth.unitVal( Number(this.sculpture.naturalDimensions.c * this.sculpture.scale) || "" ) + this.sculpture.updateOutline() + }, + changeUnits: function(){ + app.units = this.$units.val() + this.$('.units').resetUnitVal() + }, + + taint: function(e){ + e.stopPropagation() + this.tainted = true + }, + + bind: function(sculpture){ + this.sculpture = sculpture + this.sculpture.mx.bound = true + this.sculpture.mx.el.classList.add("picked") + }, + + unbind: function(){ + if (this.sculpture) { + this.sculpture.focused = false + if (this.tainted && this.sculpture.media) { + this.sculpture.media.title = this.$name.val() + this.sculpture.media.description = this.$description.val() + Minotaur.watch( app.router.editorView.settings ) + } + if (this.sculpture.mx) { + this.sculpture.mx.bound = false + this.sculpture.mx.el.classList.remove("picked") + } + } + this.tainted = false + this.sculpture = null + }, + + destroy: function(){ + var sculpture = this.sculpture + this.hide() + + sculpture.remove() + + this.tainted = false + this.sculpture = null + }, + +}) diff --git a/public/assets/javascripts/ui/lib/AnimatedView.js b/public/assets/javascripts/ui/lib/AnimatedView.js new file mode 100644 index 0000000..3c50b0a --- /dev/null +++ b/public/assets/javascripts/ui/lib/AnimatedView.js @@ -0,0 +1,31 @@ +var AnimatedView = View.extend({ + + _animating: false, + last_t: 0, + + startAnimating: function(){ + if (this._animating) return + this._animating = true + this._animate() + }, + + stopAnimating: function(){ + this._animating = false + }, + + _animate: function(t){ + if (! this._animating) return + + requestAnimationFrame(this._animate.bind(this)) + + var dt = t - this.last_t + this.last_t = t + + if (! t) return + + this.animate(t, dt) + }, + + animate: function(t, dt){}, + +})
\ No newline at end of file diff --git a/public/assets/javascripts/ui/lib/ConfirmModal.js b/public/assets/javascripts/ui/lib/ConfirmModal.js index a72b31e..7d9da67 100644 --- a/public/assets/javascripts/ui/lib/ConfirmModal.js +++ b/public/assets/javascripts/ui/lib/ConfirmModal.js @@ -4,21 +4,31 @@ var ConfirmModal = new( ModalFormView.extend({ el: ".mediaDrawer.confirm", events: { - "click .yes": "advance", - "click .no": "hide", + "click .yes": "agree", + "click .no": "cancel", }, - confirm: function(question, callback){ + confirm: function(question, agreeCallback, cancelCallback){ this.$(".question").empty().append(question) - this.callback = callback + this.agreeCallback = agreeCallback + this.cancelCallback = cancelCallback this.show() }, - advance: function(e){ + agree: function(e){ e && e.preventDefault() this.hide() - this.callback && this.callback() - this.callback = null + this.agreeCallback && this.agreeCallback() + this.agreeCallback = null + this.cancelCallback = null + }, + + cancel: function(e){ + e && e.preventDefault() + this.hide() + this.cancelCallback && this.cancelCallback() + this.agreeCallback = null + this.cancelCallback = null } }) )
\ No newline at end of file diff --git a/public/assets/javascripts/ui/lib/FormView.js b/public/assets/javascripts/ui/lib/FormView.js index f5845e7..a952ecb 100644 --- a/public/assets/javascripts/ui/lib/FormView.js +++ b/public/assets/javascripts/ui/lib/FormView.js @@ -63,13 +63,15 @@ var FormView = View.extend({ save: function(e, successCallback, errorCallback){ e && e.preventDefault() - this.$errors.hide().css("opacity", 0.0); + this.$errors && this.$errors.hide().css("opacity", 0.0); if (this.validate) { var errors = this.validate() if (errors && errors.length) { if (errorCallback) { - errorCallback(errors) + setTimeout(function(){ + errorCallback(errors) + }) } else { this.showErrors(errors) @@ -77,7 +79,6 @@ var FormView = View.extend({ return } } - var action = typeof this.action == "function" ? this.action() : this.action if (! action) return @@ -112,7 +113,9 @@ var FormView = View.extend({ return } else { + console.log("ok") if (successCallback) { + console.log("use cb") successCallback(response) } if (this.success) { diff --git a/public/assets/javascripts/ui/lib/LabColorPicker.js b/public/assets/javascripts/ui/lib/LabColorPicker.js index 7ddcdd5..2c8fb90 100644 --- a/public/assets/javascripts/ui/lib/LabColorPicker.js +++ b/public/assets/javascripts/ui/lib/LabColorPicker.js @@ -1,9 +1,12 @@ var LabColorPicker = function (parent, w, h) { var base = this var canvas = this.canvas = document.createElement('canvas') - var ctx = this.ctx = canvas.getContext('2d') - var imageData = ctx.createImageData(w,h) - var data = imageData.data + canvas.width = w + canvas.height = h + var ctx = this.ctx = canvas.getContext('2d-lodpi') +// canvas.className = "colorPicker" +// var imageData = ctx.createImageData(w, h) +// var data = imageData.data var cursor = this.cursor = document.createElement("div") cursor.className = "colorPickerCursor" @@ -15,10 +18,6 @@ var LabColorPicker = function (parent, w, h) { brightnessControl.setAttribute("max", "110") brightnessControl.setAttribute("value", "0") - canvas.width = w - canvas.height = h - canvas.className = "colorPicker" - var ww = w-1 var hh = h-1 @@ -84,11 +83,14 @@ var LabColorPicker = function (parent, w, h) { } this.paint = function() { val = clamp(val, L_range[0], L_range[1]) - var x, y, t - for (var i = 0; i < w; i++) { - for (var j = 0; j < h; j++) { - x = mix( i/ww, a_range[0], a_range[1] ) - y = mix( j/hh, b_range[0], b_range[1] ) + var imageData = ctx.createImageData(canvas.width, canvas.height) + var data = imageData.data + var x, y, t, cw = imageData.width, ch = imageData.height + var cww = cw-1, chh = ch-1 + for (var i = 0; i < cw; i++) { + for (var j = 0; j < ch; j++) { + x = mix( i/cww, a_range[0], a_range[1] ) + y = mix( j/chh, b_range[0], b_range[1] ) t = (j*w + i) * 4 rgb = xyz2rgb(hunterlab2xyz(val, x, y)) data[t] = Math.round( rgb[0] ) diff --git a/public/assets/javascripts/ui/lib/ModalView.js b/public/assets/javascripts/ui/lib/ModalView.js index 6f1c729..e0070ce 100644 --- a/public/assets/javascripts/ui/lib/ModalView.js +++ b/public/assets/javascripts/ui/lib/ModalView.js @@ -35,6 +35,11 @@ var ModalView = View.extend({ $("body").removeClass("noOverflow"); }, + hideClose: function(){ + $("#fixed_close").removeClass("active") + $("#fixed_close").unbind("click", this.hide.bind(this)) + }, + close: function(){ if (window.isModalView) { window.location.pathname = "/" diff --git a/public/assets/javascripts/ui/lib/ToggleableView.js b/public/assets/javascripts/ui/lib/ToggleableView.js new file mode 100644 index 0000000..371629f --- /dev/null +++ b/public/assets/javascripts/ui/lib/ToggleableView.js @@ -0,0 +1,19 @@ +var ToggleableView = View.extend({ + + toggle: function(state){ + this.$el.toggleClass("active", state) + }, + + show: function(){ + this.toggle(true) + }, + + hide: function(){ + this.toggle(false) + }, + + visible: function(){ + return this.$el.hasClass("active") + } + +})
\ No newline at end of file diff --git a/public/assets/javascripts/ui/lib/Toolbar.js b/public/assets/javascripts/ui/lib/Toolbar.js new file mode 100644 index 0000000..a9ce51c --- /dev/null +++ b/public/assets/javascripts/ui/lib/Toolbar.js @@ -0,0 +1,22 @@ +var Toolbar = Fiber.extend(function(base){ + var exports = {} + exports.init = function(rapper){ + this.rapper = (typeof rapper == "string") ? $(rapper)[0] : rapper + this.tools = {} + this.els = {} + } + exports.add = function(role, fn){ + var self = this + this.tools[role] = fn + this.els[role] = $("[data-role=" + role + "]", self.rapper) + this.els[role].click(function(){ + $(".active", self.rapper).removeClass('active') + $(this).addClass('active') + fn() + }) + } + exports.pick = function(role){ + this.els[role].trigger("click") + } + return exports +})
\ No newline at end of file diff --git a/public/assets/javascripts/ui/reader/MediaPlayer.js b/public/assets/javascripts/ui/reader/MediaPlayer.js index 8424d9c..8e65976 100644 --- a/public/assets/javascripts/ui/reader/MediaPlayer.js +++ b/public/assets/javascripts/ui/reader/MediaPlayer.js @@ -1,5 +1,5 @@ -var MediaPlayer = FormView.extend({ +var MediaPlayer = View.extend({ el: "#mediaPlayer", events: { diff --git a/public/assets/javascripts/ui/reader/ReaderView.js b/public/assets/javascripts/ui/reader/ReaderView.js index 617a145..43e81d8 100644 --- a/public/assets/javascripts/ui/reader/ReaderView.js +++ b/public/assets/javascripts/ui/reader/ReaderView.js @@ -31,7 +31,12 @@ var ReaderView = View.extend({ this.tracker = new Tracker ({ mode: mode }) - $.get(this.projectAction + name, this.ready.bind(this)) + if ('vvalls_data' in window) { + this.ready(window.vvalls_data) + } + else { + $.get(this.projectAction + name, this.ready.bind(this)) + } }, getQS: function(){ @@ -71,9 +76,15 @@ var ReaderView = View.extend({ }, build: function(data){ - data.rooms && Rooms.deserialize(data.rooms) + if (data.shapes.length) { + Rooms.deserializeFromShapes(data) + } + else { + Rooms.deserialize(data.rooms) + } data.walls && Walls.deserialize(data.walls) data.media && Scenery.deserialize(data.media) + data.sculpture && Sculpture.deserialize(data.sculpture) data.startPosition && scene.camera.move(data.startPosition) cam.y = window.viewHeight = data.viewHeight || app.defaults.viewHeight @@ -84,9 +95,12 @@ var ReaderView = View.extend({ Walls.setColor[mode](colors[mode]) }) - editor.permissions.clear() + window.editor && editor.permissions.clear() - this.listen() + // disable until we start using spinning again + // this.listen() + + app.tube("site-ready") }, listen: function(){ diff --git a/public/assets/javascripts/ui/reader/Tracker.js b/public/assets/javascripts/ui/reader/Tracker.js index ce32c59..d2dec39 100644 --- a/public/assets/javascripts/ui/reader/Tracker.js +++ b/public/assets/javascripts/ui/reader/Tracker.js @@ -1,8 +1,12 @@ -(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ -(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), -m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) -})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); - +if (window.location.host.indexOf("lvh.me") === -1) { + (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) + })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); +} +else { + ga = function(){} +} ga('create', 'UA-56883705-1', 'auto'); ga('send', 'pageview'); diff --git a/public/assets/javascripts/ui/reader/_router.js b/public/assets/javascripts/ui/reader/_router.js new file mode 100644 index 0000000..f3b121b --- /dev/null +++ b/public/assets/javascripts/ui/reader/_router.js @@ -0,0 +1,24 @@ + +var SiteRouter = Router.extend({ + el: "body", + + initialize: function(){ + app.launch() + if (app.unsupported) return + + this.readerView = app.controller = new ReaderView() + this.readerView.load() + + $("body").removeClass("loading") + } + +}) + +var editor = { + permissions: new Permissions({ + 'pick': true, + 'move': true, + 'resize': true, + 'destroy': false, + }) +} diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js new file mode 100644 index 0000000..c1dc9f8 --- /dev/null +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -0,0 +1,290 @@ + +var EditSubscriptionModal = ModalView.extend({ + el: ".mediaDrawer.editSubscription", + action: "/api/subscription", + syncAction: "/api/subscription/sync", + updateAction: "/api/subscription", + destroyAction: "/api/subscription/destroy", + + fixedClose: true, + editing: false, + subscriber: null, + tempSubscriber: null, + + events: { + "click [data-role='addLayouts']": 'addLayouts', + "click [data-role='changePlan']": 'changePlan', + "click [data-role='cancelSubscription']": 'destroy', + "click .gear": 'sync', + "click .planList button": 'followLink', + + "click [data-role=showEditMenu]": "editMode", + + "click [data-role=closeMenu]": "resetMode", + + "input [data-role=basicLayoutInput]": "updateQuantity", + "input [data-role=proLayoutInput]": "updateQuantity", + "click [data-role=saveChanges]": "saveChanges", + + "change [name=planRadio]": "updatePlan", + "click [data-role=savePlan]": "savePlan", + + "submit form": "preventDefault", + }, + + initialize: function(){ + // this.parent = opt.parent + this.__super__.initialize.call(this) + + // two sections + this.$freePlan = this.$(".freePlan") + this.$paidPlan = this.$(".paidPlan") + + // subscription table + this.$planInfo = this.$(".planInfo") + this.$planRow = this.$(".planRow") + this.$basicLayoutRow = this.$(".basicLayoutRow") + this.$proLayoutRow = this.$(".proLayoutRow") + this.$totalRow = this.$(".totalRow") + this.$planList = this.$(".planList") + + this.$billingInterval = this.$("[data-role=billingInterval]") + + // plan stuff + this.$planName = this.$("[data-role=planName]") + this.$planCost = this.$("[data-role=planCost]") + this.$planTotal = this.$("[data-role=planTotal]") + + this.$basicPlanName = this.$("[data-role=basicPlanName]") + this.$basicPlanCost = this.$("[data-role=basicPlanCost]") + + this.$proPlanName = this.$("[data-role=proPlanName]") + this.$proPlanCost = this.$("[data-role=proPlanCost]") + + // basic + pro layout stuff + this.$basicLayoutCost = this.$("[data-role=basicLayoutCost]") + this.$basicLayoutQuantity = this.$("[data-role=basicLayoutQuantity]") + this.$basicLayoutTotal = this.$("[data-role=basicLayoutTotal]") + + this.$proLayoutCost = this.$("[data-role=proLayoutCost]") + this.$proLayoutQuantity = this.$("[data-role=proLayoutQuantity]") + this.$proLayoutTotal = this.$("[data-role=proLayoutTotal]") + + // menus.. main menu + this.$showEditMenu = this.$("[data-role=showEditMenu]") + this.$cancelSubscription = this.$("[data-role=cancelSubscription]") + + // three submenus + this.$editMenu = this.$("[data-role=editMenu]") + this.$planMenu = this.$("[data-role=planMenu]") + + this.$buyLayouts = this.$("[data-role=buyLayouts]") + this.$closeMenu = this.$("[data-role=closeMenu]") + this.$changePlan = this.$("[data-role=changePlan]") + + // input fields + this.$basicLayoutInput = this.$("[data-role=basicLayoutInput]") + this.$proLayoutInput = this.$("[data-role=proLayoutInput]") + this.$planRadio = this.$("[name=planRadio]") + this.$basicPlanInput = this.$("[data-role=basicPlanInput]") + this.$proPlanInput = this.$("[data-role=proPlanInput]") + + this.$gear = this.$(".gear") + }, + + plan_levels: { + free: 0, + basic: 1, + pro: 2, + custom: 3, + artist: 4, + }, + + loaded: false, + load: function(){ + if (this.loaded) { return this.show() } + $.get(this.action, this.didLoad.bind(this)) + }, + didLoad: function(data){ + this.loaded = true + this.plans = data.plans + if (data.subscription) { + this.subscriber = data.subscription + } + else if (data.error) { + // ...no subscription found + this.subscriber = null + } + return this.show() + }, + followLink: function(e){ + e.preventDefault(); + window.location.href = $(e.target).closest("a").attr("href") + }, + + show: function(){ + this.$gear.removeClass("turning") + if (! this.subscriber) { + this.$freePlan.show() + this.$paidPlan.hide() + this.$planList.load("/partials/plans", function(){ + this.$(".free_plan_info").remove() + this.__super__.show.call(this) + }.bind(this)) + return + } + + this.$freePlan.hide() + this.$paidPlan.show() + + this.resetMode() + + this.__super__.show.call(this) + }, + reset: function(){ + var subscriber = this.subscriber + var plan = this.getPlan(subscriber.plan_type) + this.displayTotals(subscriber, plan) + }, + getPlan: function(plan_type){ + return this.plans[ this.plan_levels[ plan_type ] ] + }, + calculateTotals: function(subscriber, plan){ + var t = {} + t.is_pro = subscriber.plan_type == "pro" + t.is_monthly = subscriber.plan_period == "monthly" + t.plan_price = t.is_monthly ? plan.monthly_price : plan.yearly_price + t.basic_layout_price = t.is_monthly ? plan.basic_layout_monthly_price : plan.basic_layout_yearly_price + t.basic_layout_total = subscriber.basic_layouts * t.basic_layout_price + t.pro_layout_price = t.is_monthly ? plan.pro_layout_monthly_price : plan.pro_layout_yearly_price + t.pro_layout_total = t.is_pro ? subscriber.pro_layouts * t.pro_layout_price : 0 + t.plan_total = t.plan_price + t.basic_layout_total + t.pro_layout_total + return t + }, + displayTotals: function(subscriber, plan){ + var totals = this.calculateTotals(subscriber, plan) + + this.$basicPlanName.html ( this.plans[1].name ) + this.$proPlanName.html ( this.plans[2].name ) + this.$basicPlanCost.toDollars ( totals.is_monthly ? this.plans[1].monthly_price : this.plans[2].yearly_price) + this.$proPlanCost.toDollars ( totals.is_monthly ? this.plans[2].monthly_price : this.plans[2].yearly_price) + + this.$planName.html ( plan.name ) + this.$planCost.toDollars ( totals.plan_price ) + + this.$billingInterval.html ( totals.is_monthly ? "mo." : "yr." ) + this.$basicLayoutRow.toggle ( subscriber.basic_layouts > 0 ) + this.$proLayoutRow.toggle ( totals.is_pro && subscriber.pro_layouts > 0) + + this.$basicLayoutCost.toDollars ( totals.basic_layout_price ) + this.$basicLayoutQuantity.html ( subscriber.basic_layouts ) + this.$basicLayoutTotal.toDollars ( totals.basic_layout_total ) + + this.$proLayoutCost.toDollars ( totals.pro_layout_price ) + this.$proLayoutQuantity.html ( subscriber.pro_layouts ) + this.$proLayoutTotal.toDollars ( totals.pro_layout_total ) + + this.$planTotal.toDollars ( totals.plan_total ) + }, + + editMode: function(e){ + e && e.preventDefault() + + this.editing = true + this.$el.addClass("editing") + this.tempSubscriber = defaults({}, this.subscriber) + this.$basicLayoutInput.val( this.subscriber.basic_layouts ) + this.$proLayoutInput.val( this.subscriber.pro_layouts ) + this.$basicLayoutRow.show() + this.$proLayoutRow.toggle(this.subscriber.plan_type == "pro") + switch (this.subscriber.plan_type) { + case 'basic': this.$basicPlanInput.prop('checked', true); break; + case 'pro': this.$proPlanInput.prop('checked', true); break; + } + }, + resetMode: function(e){ + e && e.preventDefault() + this.editing = false + this.$el.removeClass("editing") + this.reset() + }, + + updateQuantity: function(e){ + e && e.preventDefault() + var plan = this.getPlan( this.tempSubscriber.plan_type ) + this.tempSubscriber.basic_layouts = clamp( this.$basicLayoutInput.int() || 0, 0, 100) + this.tempSubscriber.pro_layouts = clamp( this.$proLayoutInput.int() || 0, 0, 100) + + this.$basicLayoutInput.val(this.tempSubscriber.basic_layouts) + this.$proLayoutInput.val(this.tempSubscriber.pro_layouts) + this.displayTotals(this.tempSubscriber, plan) + this.$basicLayoutRow.show() + this.$proLayoutRow.toggle(this.tempSubscriber.plan_type == "pro") + }, + saveChanges: function(e){ + e && e.preventDefault() + var is_changed = false + var diff = {} + "plan_type basic_layouts pro_layouts".split(" ").forEach(function(field){ + diff[field] = this.tempSubscriber[field] + if (this.tempSubscriber[field] != this.subscriber[field]) { + is_changed = true + } + }.bind(this)) + + if (is_changed) { + this.update(diff) + } + this.subscriber = this.tempSubscriber + this.resetMode() + }, + + updatePlan: function(e){ + e && e.preventDefault() + this.tempSubscriber.plan_type = this.$("[name=planRadio]:checked").val() + this.updateQuantity() + }, + + sync: function(){ + this.$gear.addClass("turning") + $.ajax({ + url: this.syncAction, + type: "put", + data: { _csrf: $("[name=_csrf]").val() }, + success: this.didLoad.bind(this) + }) + }, + + update: function(data){ + data['_csrf'] = $("[name=_csrf]").val() + this.$gear.addClass("turning") + $.ajax({ + url: this.updateAction, + type: "put", + data: data, + success: function(data){ + this.$gear.removeClass("turning") + }.bind(this) + }) + }, + + destroy: function(e){ + e.preventDefault() + var msg = "Are you sure you want to cancel your subscription?" + ConfirmModal.confirm(msg, function(){ + $.ajax({ + url: this.destroyAction, + type: "delete", + data: { _csrf: $("[name=_csrf]").val() }, + success: function(data){ + this.subscriber = null + this.didLoad(data) + }.bind(this) + }) + }.bind(this), + function(){ + this.show() + }.bind(this)) + }, + +}) diff --git a/public/assets/javascripts/ui/site/HomeView.js b/public/assets/javascripts/ui/site/HomeView.js index a04bac1..20452bd 100644 --- a/public/assets/javascripts/ui/site/HomeView.js +++ b/public/assets/javascripts/ui/site/HomeView.js @@ -22,7 +22,7 @@ var HomeView = View.extend({ player.api('play') }) - $('.videoModal .ion-ios7-close-empty').click( function(){ + $('.videoModal .ion-ios-close-empty').click( function(){ player.api('pause') hide() }) diff --git a/public/assets/javascripts/ui/site/LayoutsIndex.js b/public/assets/javascripts/ui/site/LayoutsIndex.js new file mode 100644 index 0000000..f7272bb --- /dev/null +++ b/public/assets/javascripts/ui/site/LayoutsIndex.js @@ -0,0 +1,85 @@ + +var LayoutsIndex = View.extend({ + + initialize: function(){ + this.$templates = this.$(".templates") + this.$templatesList = this.$(".templates-list") + this.$noTemplates = this.$(".no-templates") + this.$form = this.$("form") + + this.$userTemplatesList = this.$(".userTemplatesList") + this.$blueprintsList = this.$(".blueprintsList") + this.$newBlueprintButton = this.$("[data-role='create-new-blueprint']") + }, + + load: function(type){ + this.$templates.children("span").remove() + + $.get(this.action, this.populate.bind(this)) + }, + + populate: function(data){ + if (! data.layouts.length) { + this.$templates.hide() + this.$form.hide() + this.$noTemplates.show() + } + this.$templatesList.empty() + data.layouts.forEach(function(room){ + var $span = $("<span>") + $span.data("slug", room.slug) + + var $label = $("<label>") + $label.html( room.name ) + + var $image = $("<span>") + $image.addClass("image").css("background-image", "url(" + room.photo + ")") + + $span.append( $image ) + $span.append( $label ) + + this.$templatesList.append($span) + }.bind(this)) + this.show() + } + +}) + + + +var ProjectsModal = ModalView.extend(LayoutsIndex.prototype).extend({ + el: ".mediaDrawer.projects", + + action: "/api/project", + + events: { + "click .templates span": 'toggleActive', + "submit form": 'newProject', + }, + + populate: function(data){ + if (! data.length) { + app.router.newProject() + } + else { + this.__super__.populate.call(this, data) + } + }, + + toggleActive: function(e){ + e.preventDefault() + this.$(".templates .active").removeClass("active") + var $layout = $(e.currentTarget) + $layout.addClass("active") + + // actually do + window.location.pathname = "/project/" + $layout.data("slug") + "/edit" + }, + + newProject: function(e){ + e && e.preventDefault() + window.location.pathname = "/project/new" + } + +}) + diff --git a/public/assets/javascripts/ui/site/LayoutsModal.js b/public/assets/javascripts/ui/site/LayoutsModal.js index 5974fc3..0222077 100644 --- a/public/assets/javascripts/ui/site/LayoutsModal.js +++ b/public/assets/javascripts/ui/site/LayoutsModal.js @@ -1,27 +1,52 @@ +var LayoutsModal = ModalView.extend(LayoutsIndex.prototype).extend({ + el: ".mediaDrawer.layouts", -var LayoutsIndex = View.extend({ + action: "/api/layout", - initialize: function(){ - this.$templates = this.$(".templates") - this.$templatesList = this.$(".templates-list") - this.$noTemplates = this.$(".no-templates") - this.$form = this.$("form") + events: { + "click [data-role='create-new-layout']": 'createNewLayout', + "click [data-role='create-new-blueprint']": 'createNewBlueprint', + "click .templates span": 'pick', }, + + pick: function(e){ + e.preventDefault() + var layout = $(e.currentTarget).data("slug") + var isBlueprint = $(e.currentTarget).data("blueprint") - load: function(type){ - this.$templates.children("span").remove() + if (! layout || ! layout.length) return - $.get(this.action, this.populate.bind(this)) + if (isBlueprint) { + window.location.pathname = "/blueprint/" + layout + } + else { + window.location.pathname = "/layout/" + layout + } + }, + + createNewLayout: function(e){ + e.preventDefault() + window.location.pathname = "/layout/new" + }, + + createNewBlueprint: function(e){ + e.preventDefault() + window.location.pathname = "/blueprint/new" }, populate: function(data){ - if (! data.length) { +/* + if (data.user.plan_level < 1 && data.projectCount == 1) { + // show lockout message + } +*/ + if (! data.layouts.length) { this.$templates.hide() this.$form.hide() this.$noTemplates.show() } this.$templatesList.empty() - data.forEach(function(room){ + data.layouts.forEach(function(room){ var $span = $("<span>") $span.data("slug", room.slug) @@ -36,103 +61,46 @@ var LayoutsIndex = View.extend({ this.$templatesList.append($span) }.bind(this)) - this.show() - } - -}) -var ProjectsModal = ModalView.extend(LayoutsIndex.prototype).extend({ - el: ".mediaDrawer.projects", - - action: "/api/project", - - events: { - "click .templates span": 'toggleActive', - "submit form": 'newProject', - }, - - populate: function(data){ - if (! data.length) { - app.router.newProject() - } - else { - this.__super__.populate.call(this, data) - } - }, - - toggleActive: function(e){ - e.preventDefault() - this.$(".templates .active").removeClass("active") - var $layout = $(e.currentTarget) - $layout.addClass("active") - - // actually do - window.location.pathname = "/project/" + $layout.data("slug") + "/edit" - }, - - newProject: function(e){ - e && e.preventDefault() - window.location.pathname = "/project/new" - } - -}) - - -var LayoutsModal = ModalView.extend(LayoutsIndex.prototype).extend({ - el: ".mediaDrawer.layouts", - - action: "/api/layout", - - events: { - "click .templates span": 'toggleActive', - "submit form": 'newLayout', - }, - - toggleActive: function(e){ - e.preventDefault() - this.$(".templates .active").removeClass("active") - var $layout = $(e.currentTarget) - $layout.addClass("active") + data.user_layouts.forEach(function(room){ + var $span = $("<span>") + $span.data("slug", room.slug) + + var $label = $("<label>") + $label.html( room.name ) + + var $image = $("<span>") + $image.addClass("image").css("background-image", "url(" + room.photo + ")") + + $span.append( $image ) + $span.append( $label ) + + this.$templatesList.append($span) + }.bind(this)) + + data.blueprints.forEach(function(blueprint){ + var $span = $("<span>") + $span.data("slug", blueprint.slug) + $span.data("blueprint", true) + + var $label = $("<label>") + $label.html( blueprint.name ) + + var $image = $("<span>") + $image.addClass("image").css("background-image", "url(" + blueprint.url + ")") + + $span.append( $image ) + $span.append( $label ) + + this.$templatesList.append($span) + }.bind(this)) - // actually do - window.location.pathname = "/layout/" + $layout.data("slug") + this.show() }, - + newLayout: function(e){ e && e.preventDefault() window.location.pathname = "/layout/new" } }) - - -var NewProjectModal = ModalView.extend(LayoutsIndex.prototype).extend({ - el: ".mediaDrawer.newProject", - - action: "/api/layout", - - events: { - "click [data-role='create-new-layout']": 'createNewLayout', - "click .templates span": 'choose', - "submit form": 'choose', - }, - - toggleActive: function(e){ - e.preventDefault() - this.$(".templates .active").removeClass("active") - $(e.currentTarget).addClass("active") - }, - - choose: function(e){ - e && e.preventDefault() -// var layout = this.$(".templates .active").data("slug") - var layout = $(e.currentTarget).data("slug") - if (! layout || ! layout.length) return - window.location.pathname = "/project/new/" + layout - }, - - createNewLayout: function(){ - window.location.pathname = "/project/new/empty" - }, - -}) diff --git a/public/assets/javascripts/ui/site/NewProjectModal.js b/public/assets/javascripts/ui/site/NewProjectModal.js new file mode 100644 index 0000000..31675ba --- /dev/null +++ b/public/assets/javascripts/ui/site/NewProjectModal.js @@ -0,0 +1,118 @@ +var NewProjectModal = ModalView.extend(LayoutsIndex.prototype).extend({ + el: ".mediaDrawer.newProject", + + action: "/api/layout", + + events: { + "click [data-role='create-new-layout']": 'createNewLayout', + "click [data-role='create-new-blueprint']": 'createNewBlueprint', + "click .templates span": 'pick', + }, + + toggleActive: function(e){ + e.preventDefault() + this.$(".templates .active").removeClass("active") + $(e.currentTarget).addClass("active") + }, + + pick: function(e){ + e && e.preventDefault() +// var layout = this.$(".templates .active").data("slug") + var layout = $(e.currentTarget).data("slug") + var isBlueprint = $(e.currentTarget).data("blueprint") + if (! layout || ! layout.length) return + + if (isBlueprint) { + window.location.pathname = "/project/blueprint/" + layout + } + else { + window.location.pathname = "/project/new/" + layout + } + }, + + createNewLayout: function(e){ + e.preventDefault() + window.location.pathname = "/project/new/empty" + }, + + createNewBlueprint: function(e){ + e.preventDefault() + window.location.pathname = "/blueprint/new" + }, + + populate: function(data){ +/* + if (data.user.plan_level < 1 && data.projectCount == 1) { + // show lockout message + this.$newBlueprintButton.hide() + } +*/ + if (! data.layouts.length) { + this.$templates.hide() + this.$form.hide() + this.$noTemplates.show() + } + if (! data.blueprints.length) { + this.$blueprintsList.parent().hide() + } + if (! data.user_layouts.length) { + this.$userTemplatesList.parent().hide() + } + + this.$templatesList.empty() + data.layouts.forEach(function(room){ + var $span = $("<span>") + $span.data("slug", room.slug) + + var $label = $("<label>") + $label.html( room.name ) + + var $image = $("<span>") + $image.addClass("image").css("background-image", "url(" + room.photo + ")") + + $span.append( $image ) + $span.append( $label ) + + this.$templatesList.append($span) + }.bind(this)) + + data.user_layouts.forEach(function(room){ + var $span = $("<span>") + $span.data("slug", room.slug) + + var $label = $("<label>") + $label.html( room.name ) + + var $image = $("<span>") + $image.addClass("image").css("background-image", "url(" + room.photo + ")") + + $span.append( $image ) + $span.append( $label ) + + this.$templatesList.append($span) + }.bind(this)) + + data.blueprints.forEach(function(blueprint){ + if (! blueprint.slug) { return } + + var $span = $("<span>") + $span.data("blueprint", true) + $span.data("slug", blueprint.slug) + + var $label = $("<label>") + $label.html( blueprint.name ) + + var $image = $("<span>") + $image.addClass("image").css("background-image", "url(" + blueprint.url + ")") + + $span.append( $image ) + $span.append( $label ) + + this.$templatesList.append($span) + }.bind(this)) + + this.show() + }, + + +})
\ No newline at end of file diff --git a/public/assets/javascripts/ui/site/StaffView.js b/public/assets/javascripts/ui/site/StaffView.js index 0398f71..97f86c2 100644 --- a/public/assets/javascripts/ui/site/StaffView.js +++ b/public/assets/javascripts/ui/site/StaffView.js @@ -4,11 +4,15 @@ var StaffView = View.extend({ events: { "click #toggle-staff": "toggleStaff", "click #toggle-featured": "toggleFeatured", + "click #toggle-stock": "toggleStock", + "click #toggle-artist": "toggleArtist", }, initialize: function() { this.$toggleStaff = $("#toggle-staff") this.$toggleFeatured = $("#toggle-featured") + this.$toggleStock = $("#toggle-stock") + this.$toggleArtist = $("#toggle-artist") this.$mediaEmbed = $("#media-embed") if (this.$toggleStaff.length && this.$toggleStaff.data().isstaff) { this.$toggleStaff.html("Is Staff") @@ -16,6 +20,12 @@ var StaffView = View.extend({ if (this.$toggleFeatured.length && this.$toggleFeatured.data().featured) { this.$toggleFeatured.html("Featured Project") } + if (this.$toggleStock.length && this.$toggleStock.data().stock) { + this.$toggleStock.html("Layout is Stock") + } + if (this.$toggleArtist.length && this.$toggleArtist.data().isartist) { + this.$toggleArtist.html("Is Artist") + } if (this.$mediaEmbed.length) { var media = this.$mediaEmbed.data() this.$mediaEmbed.html( Parser.tag( media ) ) @@ -67,6 +77,41 @@ var StaffView = View.extend({ $("#isFeaturedProject").html(data.state ? "yes" : "no") }.bind(this) }) - }, + }, + + toggleStock: function(){ + var state = ! this.$toggleStock.data().stock + $.ajax({ + type: "put", + dataType: "json", + url: window.location.href + "/stock", + data: { + state: state, + _csrf: $("#_csrf").val(), + }, + success: function(data){ + this.$toggleStock.data("stock", data.state) + this.$toggleStock.html(data.state ? "Stock Layout" : "Make this layout Stock") + $("#isStockLayout").html(data.state ? "yes" : "no") + }.bind(this) + }) + }, + toggleArtist: function(){ + var state = ! this.$toggleArtist.data().isartist + $.ajax({ + type: "put", + dataType: "json", + url: window.location.href + "/artist", + data: { + state: state, + _csrf: $("#_csrf").val(), + }, + success: function(data){ + this.$toggleArtist.data("stock", data.state) + this.$toggleArtist.html(data.state ? "Is Artist" : "Make Artist") + $("#isArtist").html(data.state ? "yes" : "no") + }.bind(this) + }) + }, }) diff --git a/public/assets/javascripts/util.js b/public/assets/javascripts/util.js index 2cfe0de..0f5c6ed 100644 --- a/public/assets/javascripts/util.js +++ b/public/assets/javascripts/util.js @@ -6,6 +6,7 @@ if (window.$) { $.fn.disable = function() { return $(this).attr("disabled","disabled") } $.fn.sanitize = function(s) { return trim(sanitize($(this).val())) } $.fn.htmlSafe = function(s) { return $(this).html(sanitize(s)) } + $.fn.toDollars = function(i) { return $(this).html((i/100).toFixed(2)) } } function trim (s){ return s.replace(/^\s+/,"").replace(/\s+$/,"") } diff --git a/public/assets/javascripts/vendor/polyfill.js b/public/assets/javascripts/vendor/polyfill.js index 499cbc5..2139618 100644 --- a/public/assets/javascripts/vendor/polyfill.js +++ b/public/assets/javascripts/vendor/polyfill.js @@ -48,7 +48,7 @@ function has3d(){ } else if ( browser.webkit ) { browser.safari = true; } - $.browser = browser; + if (window.$) $.browser = browser; return browser; })( navigator.userAgent ); @@ -58,6 +58,7 @@ var is_ipad = (navigator.userAgent.match(/iPad/i)) var is_android = (navigator.userAgent.match(/Android/i)) var is_mobile = is_iphone || is_ipad || is_android var is_desktop = ! is_mobile; +var app_devicePixelRatio = is_mobile ? devicePixelRatio : 1; // rAF shim diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 62a5682..7dda058 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -53,9 +53,11 @@ body.noOverflow{ overflow:hidden; } -body.loading * { - -webkit-transition: all 0 ease 0 !important; - transition: all 0 ease 0 !important; +body.loading *, +body.loading .animate { + opacity: 0.2; + -webkit-transition: none !important; + transition: none !important; } html, body { @@ -72,7 +74,7 @@ body.pastePaper .wallpaper.active span:hover{ cursor:url(../img/paintbucket.png), auto; } -a{ +a { color:black; text-decoration: none; } @@ -139,7 +141,7 @@ a{ background: rgba(255,255,255,0.9); } -.videoModal .ion-ios7-close-empty { +.videoModal .ion-ios-close-empty { position: absolute; right: 50px; top: 10px; @@ -148,7 +150,7 @@ a{ color:#444; } -.desktop .videoModal .ion-ios7-close-empty:hover { +.desktop .videoModal .ion-ios-close-empty:hover { color:black; } @@ -156,7 +158,7 @@ a{ display: none; border-right:0px!important; } -.editProfile, .profileLink { +.profileLink { border-right:0px!important; } .editing #help-button { @@ -419,6 +421,10 @@ h5 { float: right; } +.projectList.about.makeAccountSingleton a { + margin: 0 20%; +} + .page .showcase { height:70vh; } @@ -604,7 +610,9 @@ iframe.embed { .page h1:nth-child(2) { margin-top: 40px; } - +.page h1.leader { + margin-top: 60px; +} .page p { margin: 20px; } @@ -673,7 +681,21 @@ iframe.embed { font-weight: 300; } +.aboutintro { + text-align: center; + line-height: 43px; + font-size: 24px; + padding: 5% 0; + font-weight: 300; +} +.aboutintro .inner { + max-width: 800px; + margin: 0 auto; + text-align: center; +} + /* PROFILE PAGE */ + .profilePic { background-size: cover; background-position: center; @@ -687,7 +709,7 @@ iframe.embed { border-right: 1px solid; } -.profilePic .ion-ios7-person-outline { +.profilePic .ion-ios-person-outline { font-size: 100px; } @@ -833,6 +855,7 @@ iframe.embed { } + .projectList.about.gopro { padding:6% 0; } @@ -884,14 +907,264 @@ iframe.embed { background:black; color:white; } + +/* PLANS BROCHURE */ +.about_custom { + clear: both; + max-width: 600px; + margin: 0 auto; + font-size: 14px; + border-bottom: 1px solid #e5e5e5; +} +.about_custom h3 { + text-transform: uppercase; + letter-spacing: 3px; + font-size: 1.25em; + font-weight: 500; + background: #3A3A3A; + color: white; + text-align: center; +} +.about_custom li { + list-style-type: none; + line-height: 2em; + padding: 10px 20px; + background: white; + text-align: center; + border-left: 1px solid #e5e5e5; + border-right: 1px solid #e5e5e5; +} +.about_custom a { + border-bottom: 1px solid black; +} + +ul#plans { + margin: 0 auto; + text-align: center; + font-size: 14px; +} + +ul#plans>li { + display: inline-block; + width: 300px; + vertical-align: top; + margin: 0 25px 25px 0; + position: relative; +} + +ul#plans>li.most-popular:before { + content: 'Most Popular'; + display: block; + background: #F17E6F; + color: white; + font-size: 1em; + font-weight: 500; + letter-spacing: 1px; + text-transform: uppercase; + width: 100%; + position: absolute; + top: -31px; +} + +ul#plans .top { + background: #3A3A3A; + color: white; + padding: 30px 0; + height: 266px; +} + +ul#plans h2 { + padding: 0; + font-size: 1.25em; + margin-bottom: 1.75em; + text-transform: uppercase; + letter-spacing: 3px; + font-weight: 500; +} + +ul#plans h3 { + margin: 0 0 20px; + font-weight: 200; +} + +ul#plans h3 span.dollar { + font-size: 1.25em; + vertical-align: top; + position: relative; + top: -14px; +} + +ul#plans h3 span.price { + font-size: 5em; + font-weight: 100; +} + +ul#plans h4 { + font-size: 0.85em; + color: #e6e6e6; + margin: 0 auto; + width: 50%; + font-weight: 500; + line-height: 30px; +} + +ul#plans ul { + border-left: 1px solid #e5e5e5; + border-right: 1px solid #e5e5e5; +} + +ul#plans ul li { + text-align: left; + border-bottom: 1px solid #e5e5e5; + padding: 5px 20px; + font-weight: 700; + list-style: none; + background: white; + color:#333; +} + +ul#plans .signup { + background: #3A3A3A; + padding: 25px 0; +} + +.signup .current { + display: inline-block; + color: white; + font-weight: bold; + font-size: 1em; + padding: 4px 30px 3px; +} + +.signup .button { + font-weight: bold; + padding: 16px 30px 14px; + -o-transition: background 0.2s ease-in-out; + -webkit-transition: background 0.2s ease-in-out; + transition: background 0.2s ease-in-out; + display: inline-block; + background: #F17E6F; + color: white; + text-decoration: none; + font-size: 1em; + padding: 4px 30px 3px; + border: none; + cursor: pointer; +} + + +.signup .button:hover { + color: white; + background: #ef6958; +} + + +/* debug sync button */ +.editSubscription .gear { + position: absolute; + top: 10px; + left: 10px; + opacity: 0.1; + cursor: pointer; + -webkit-transition: all 0.3s; + -webkit-transform-origin: 49% 53%; + transition: all 0.3s; + transform-origin: 49% 53%; +} +.editSubscription .gear.turning { + opacity: 0.3; + -webkit-animation: gear 1s infinite linear; + animation: gear 1s infinite linear; +} +@-webkit-keyframes gear { + from { transform: rotate(0deg); } + to { transform: rotate(720deg); } +} +@keyframes gear { + from { transform: rotate(0deg); } + to { transform: rotate(720deg); } +} +.paidPlan { + text-align: left; + font-size: 14px; +} +.planInfo { + margin: 10px 0; + width: 100%; + padding: 0; +} +.planInfo td, .planInfo th { + text-align: left; + padding: 10px 3px; + margin: 0; +} +.planInfo td { + height: 60px; + vertical-align: middle; +} +.planInfo td:nth-child(2), +.planInfo th:nth-child(2), +.planInfo td:nth-child(3), +.planInfo td:nth-child(4), +.planInfo th:nth-child(3) { + text-align: right; +} +.planInfo td:nth-child(4) { + width: 90px; +} + +.planInfo [data-role="billingInterval"] { + font-size: 10px; +} +.totalRow td:nth-child(4) { + border-top: 1px solid; +} +.paidPlan button { + width: 200px; + float: none; + margin: 5px 7px; +} +.paidPlan [data-role="cancelSubscription"] { + color: #800; + border-color: black; + width: 200px; + float: none; +} +.paidPlan [data-role="cancelSubscription"]:hover { + color: white; + background: red; + border-color: red; +} +/* purchase mode */ +.paidPlan input[type=number] { display: none; float: right; } +form .paidPlan div { float: none; } +form .paidPlan label { float: none; font-size: 16px; margin: 0 10px; } +.paidPlan .upgradeMenu div { padding: 5px 10px; } +.paidPlan .editMenu { display: none } +.paidPlan .planMenu { display: none } + +.editing .section_break { display: none } +.editing .paidPlan .currentPlanLevel { display: none } +.editing .paidPlan .billingMenu { display: none } +.editing .paidPlan .editMenu { display: block } +.editing .paidPlan .planMenu { display: block } +.editing .paidPlan input[type=number] { display: inline-block } +.editing .paidPlan input[type=number]+span { display: none } + +.editMenu .fineprint { font-size: 12px; width: auto; text-align: justify; } +/* LAYOUTS MODAL */ + .templates { overflow: auto; max-height: 100%; width: 100%; height: 100%; padding: 20px 0 40px 0; + text-align: center; } -.templates-list { +.templates-list, +.userTemplatesList, +.blueprintsList { display: inline-block; width: 100%; margin-bottom: 40px; @@ -902,8 +1175,8 @@ iframe.embed { } .templates::-webkit-scrollbar-thumb { -background-color: white; -border-left: 1px solid black; + background-color: white; + border-left: 1px solid black; } .templates::-webkit-scrollbar-track { @@ -918,8 +1191,7 @@ border-left: 1px solid black; } .templates span { - display: block; - float: left; + display: inline-block; margin: 1vw 0; width:20%; padding: 2vw; @@ -974,6 +1246,8 @@ border-left: 1px solid black; float:right; } +/* MX SCENE STUFF */ + .mx-scene { position:fixed; top:0; @@ -1001,6 +1275,13 @@ border-left: 1px solid black; -webkit-box-sizing: content-box; box-sizing: content-box; } +.mx-outline { + border-width: 2px; + border-style: dashed; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} .destroyActive .mx-scene, .destroyActive .mx-object3d.image { cursor:url(/assets/img/delete-cursor.png), auto; } @@ -1054,6 +1335,8 @@ border-left: 1px solid black; #hud { position: fixed; top:0;left:0; + width: 100%; + height: 100%; z-index: 2; } #palette { @@ -1229,7 +1512,8 @@ border-left: 1px solid black; cursor:pointer; } -.menu span.inuse { +.menu span.inuse, +.menu span.active { color:white; background:black; cursor:pointer; @@ -1255,7 +1539,7 @@ border-left: 1px solid black; font-weight:600; } -.menu span.ion-ios7-sunny-outline:hover:after { +.menu span.ion-ios-sunny-outline:hover:after { width: 130px; } @@ -1324,7 +1608,8 @@ border-left: 1px solid black; .mediaDrawer.signin, .mediaDrawer.signup, .mediaDrawer.alert, .mediaDrawer.confirm, .mediaDrawer.passwordForgot, .mediaDrawer.passwordReset, .mediaDrawer.usernameTaken, -.mediaDrawer.layouts, .mediaDrawer.projects, .mediaDrawer.newProject { +.mediaDrawer.layouts, .mediaDrawer.projects, .mediaDrawer.newProject, +.mediaDrawer.blueprintEditor { display:table; } .confirm button { @@ -1423,7 +1708,7 @@ border-left: 1px solid black; transform: translateY(0%); } -.fileUpload .ion-ios7-upload-outline { +.fileUpload .ion-ios-upload-outline { font-size:40px; } .fileUpload .upload-icon.uploading { @@ -2075,6 +2360,20 @@ input[type="range"]::-webkit-slider-thumb { transition: -webkit-transform 0.2s ease-in-out; width: 210px; } +#blueprintNotice.settings { + width: 230px; +} +#blueprintNotice a { + border-bottom: 1px solid; +} +#blueprintNotice .next { + display: inline-block; + background: black; color: white; + padding: 4px; + margin: 4px 0 0 0; + float: right; + cursor: pointer; +} #textEditor.settings { width: 320px; } @@ -2212,6 +2511,9 @@ input[type="range"]::-webkit-slider-thumb { top: 5px; font-weight:600; } +.setting.number.scale label { + top: 0; +} .setting.number label:after { content:":"; } @@ -2251,6 +2553,9 @@ input[type="range"]::-webkit-slider-thumb { #mediaEditor .setting.number [type=text] { width: 140px; } +#sculptureEditor .setting.number input[type=text] { + width: 130px; +} .playButton,.muteButton { border-radius: 50%; @@ -2468,7 +2773,7 @@ form li { form label { float:left; } -form input[type="text"],form input[type="password"] { +form input[type="text"],form input[type="password"],form input[type="number"] { border: 1px solid; font-size: 20px; padding: 5px; @@ -2488,7 +2793,7 @@ form input[type="submit"]:hover { border:1px solid black; cursor:pointer; } -form p{ +form p { display: block; float: left; font-size: 15px; @@ -2765,6 +3070,8 @@ a[data-role="forgot-password"] { font-size: 13px; margin: 5px 0 0 0; } + + .share { display:inline-block; width:100%; @@ -2976,6 +3283,105 @@ a[data-role="forgot-password"] { } +/* blueprint upload box */ + +.blueprintUploader { + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + width: 340px; + position: absolute; + top: 50%; left: 50%; + background: white; + padding: 10px; + border: 1px solid black; + box-shadow: -3px 3px #000; + -webkit-transform: translate3D(0%,-200%,0); + transform: translate3D(0%,-200%,0); + margin-left: -175px; + margin-top: -200px; + opacity: 0; +} +.blueprintUploader.active { + -webkit-transform: translate3D(0,0,0); + transform: translate3D(0,0,0); + opacity: 1; +} +.blueprintUploader .toolButton { + float: none; + width: 108px; + display: inline-block; +} +.blueprintUploader .url { + font-size: 15px; + border: 1px solid #888; + padding: 2px; + font-weight: 300; + position: relative; + top: 3px; + margin-right: 10px; + width: 190px; +} +.blueprintUploader p { + font-weight: 300; + font-size: 13px; +} +.blueprintUploader .blueprints { + display: none; +} +.blueprintUploader .blueprints h5 { + width: 250px; + margin: 10px auto; + padding-top: 9px; +} +.blueprints .blueprint { + border: 2px solid black; + background: white; + padding: 0px; + position: relative; + display: inline-block; + margin: 0 2px; +} +.blueprints .blueprint img { + height: 100px; + max-width: 200px; + display: block; + cursor: pointer; +} +.blueprints .blueprint .remove { + box-shadow: -2px 2px #000; + cursor: pointer; + position: absolute; + color: red; + top: 7px; + right: 7px; + width: 20px; height: 20px; + text-align: center; + background: #fff; + border: 1px solid black; +} +.blueprints .blueprint .remove span { + position: relative; + top: -2px; +} +.blueprintUploader .wallpaperUpload .upload-icon { + margin: 0 4px; +} +.uploadNewBlueprint { + color: #333; + border-bottom: 1px solid; + cursor: pointer; +} + + +[data-role="create-new-blueprint"] { + margin-bottom: 10px; +} +.openScaler { + margin-left: 10px; + border-bottom: 1px solid; + cursor: pointer; +} + /* KEYBOARD SHORTCUTS */ .keyboard { float: left; width: 50%; margin-top: 50px; } @@ -3038,8 +3444,8 @@ a[data-role="forgot-password"] { form li { font-size: 16px; } - form input[type="text"], form input[type="password"] { - font-size: 15px; + form input[type="text"],form input[type="password"],form input[type="number"] { + font-size: 15px; } .page h1 { font-size: 26px; @@ -3160,7 +3566,7 @@ a[data-role="forgot-password"] { .footer { padding:50px 0 120px 0; } - .videoModal .ion-ios7-close-empty { + .videoModal .ion-ios-close-empty { right: 10px; top: 20px; } diff --git a/public/assets/stylesheets/ionicons.css b/public/assets/stylesheets/ionicons.css index 34c20e2..885aa6b 100755 --- a/public/assets/stylesheets/ionicons.css +++ b/public/assets/stylesheets/ionicons.css @@ -1,25 +1,17 @@ +@charset "UTF-8"; /*! - Ionicons, v1.5.2 + Ionicons, v2.0.0 Created by Ben Sperry for the Ionic Framework, http://ionicons.com/ https://twitter.com/benjsperry https://twitter.com/ionicframework MIT License: https://github.com/driftyco/ionicons -*/ -@font-face { font-family: "Ionicons"; src: url("../fonts/ionicons.eot?v=1.5.2"); src: url("../fonts/ionicons.eot?v=1.5.2#iefix") format("embedded-opentype"), url("../fonts/ionicons.ttf?v=1.5.2") format("truetype"), url("../fonts/ionicons.woff?v=1.5.2") format("woff"), url("../fonts/ionicons.svg?v=1.5.2#Ionicons") format("svg"); font-weight: normal; font-style: normal; } -.ion, .ion-loading-a, .ion-loading-b, .ion-loading-c, .ion-loading-d, .ion-looping, .ion-refreshing, .ion-ios7-reloading, .ionicons, .ion-alert:before, .ion-alert-circled:before, .ion-android-add:before, .ion-android-add-contact:before, .ion-android-alarm:before, .ion-android-archive:before, .ion-android-arrow-back:before, .ion-android-arrow-down-left:before, .ion-android-arrow-down-right:before, .ion-android-arrow-forward:before, .ion-android-arrow-up-left:before, .ion-android-arrow-up-right:before, .ion-android-battery:before, .ion-android-book:before, .ion-android-calendar:before, .ion-android-call:before, .ion-android-camera:before, .ion-android-chat:before, .ion-android-checkmark:before, .ion-android-clock:before, .ion-android-close:before, .ion-android-contact:before, .ion-android-contacts:before, .ion-android-data:before, .ion-android-developer:before, .ion-android-display:before, .ion-android-download:before, .ion-android-drawer:before, .ion-android-dropdown:before, .ion-android-earth:before, .ion-android-folder:before, .ion-android-forums:before, .ion-android-friends:before, .ion-android-hand:before, .ion-android-image:before, .ion-android-inbox:before, .ion-android-information:before, .ion-android-keypad:before, .ion-android-lightbulb:before, .ion-android-locate:before, .ion-android-location:before, .ion-android-mail:before, .ion-android-microphone:before, .ion-android-mixer:before, .ion-android-more:before, .ion-android-note:before, .ion-android-playstore:before, .ion-android-printer:before, .ion-android-promotion:before, .ion-android-reminder:before, .ion-android-remove:before, .ion-android-search:before, .ion-android-send:before, .ion-android-settings:before, .ion-android-share:before, .ion-android-social:before, .ion-android-social-user:before, .ion-android-sort:before, .ion-android-stair-drawer:before, .ion-android-star:before, .ion-android-stopwatch:before, .ion-android-storage:before, .ion-android-system-back:before, .ion-android-system-home:before, .ion-android-system-windows:before, .ion-android-timer:before, .ion-android-trash:before, .ion-android-user-menu:before, .ion-android-volume:before, .ion-android-wifi:before, .ion-aperture:before, .ion-archive:before, .ion-arrow-down-a:before, .ion-arrow-down-b:before, .ion-arrow-down-c:before, .ion-arrow-expand:before, .ion-arrow-graph-down-left:before, .ion-arrow-graph-down-right:before, .ion-arrow-graph-up-left:before, .ion-arrow-graph-up-right:before, .ion-arrow-left-a:before, .ion-arrow-left-b:before, .ion-arrow-left-c:before, .ion-arrow-move:before, .ion-arrow-resize:before, .ion-arrow-return-left:before, .ion-arrow-return-right:before, .ion-arrow-right-a:before, .ion-arrow-right-b:before, .ion-arrow-right-c:before, .ion-arrow-shrink:before, .ion-arrow-swap:before, .ion-arrow-up-a:before, .ion-arrow-up-b:before, .ion-arrow-up-c:before, .ion-asterisk:before, .ion-at:before, .ion-bag:before, .ion-battery-charging:before, .ion-battery-empty:before, .ion-battery-full:before, .ion-battery-half:before, .ion-battery-low:before, .ion-beaker:before, .ion-beer:before, .ion-bluetooth:before, .ion-bonfire:before, .ion-bookmark:before, .ion-briefcase:before, .ion-bug:before, .ion-calculator:before, .ion-calendar:before, .ion-camera:before, .ion-card:before, .ion-cash:before, .ion-chatbox:before, .ion-chatbox-working:before, .ion-chatboxes:before, .ion-chatbubble:before, .ion-chatbubble-working:before, .ion-chatbubbles:before, .ion-checkmark:before, .ion-checkmark-circled:before, .ion-checkmark-round:before, .ion-chevron-down:before, .ion-chevron-left:before, .ion-chevron-right:before, .ion-chevron-up:before, .ion-clipboard:before, .ion-clock:before, .ion-close:before, .ion-close-circled:before, .ion-close-round:before, .ion-closed-captioning:before, .ion-cloud:before, .ion-code:before, .ion-code-download:before, .ion-code-working:before, .ion-coffee:before, .ion-compass:before, .ion-compose:before, .ion-connection-bars:before, .ion-contrast:before, .ion-cube:before, .ion-disc:before, .ion-document:before, .ion-document-text:before, .ion-drag:before, .ion-earth:before, .ion-edit:before, .ion-egg:before, .ion-eject:before, .ion-email:before, .ion-eye:before, .ion-eye-disabled:before, .ion-female:before, .ion-filing:before, .ion-film-marker:before, .ion-fireball:before, .ion-flag:before, .ion-flame:before, .ion-flash:before, .ion-flash-off:before, .ion-flask:before, .ion-folder:before, .ion-fork:before, .ion-fork-repo:before, .ion-forward:before, .ion-funnel:before, .ion-game-controller-a:before, .ion-game-controller-b:before, .ion-gear-a:before, .ion-gear-b:before, .ion-grid:before, .ion-hammer:before, .ion-happy:before, .ion-headphone:before, .ion-heart:before, .ion-heart-broken:before, .ion-help:before, .ion-help-buoy:before, .ion-help-circled:before, .ion-home:before, .ion-icecream:before, .ion-icon-social-google-plus:before, .ion-icon-social-google-plus-outline:before, .ion-image:before, .ion-images:before, .ion-information:before, .ion-information-circled:before, .ion-ionic:before, .ion-ios7-alarm:before, .ion-ios7-alarm-outline:before, .ion-ios7-albums:before, .ion-ios7-albums-outline:before, .ion-ios7-americanfootball:before, .ion-ios7-americanfootball-outline:before, .ion-ios7-analytics:before, .ion-ios7-analytics-outline:before, .ion-ios7-arrow-back:before, .ion-ios7-arrow-down:before, .ion-ios7-arrow-forward:before, .ion-ios7-arrow-left:before, .ion-ios7-arrow-right:before, .ion-ios7-arrow-thin-down:before, .ion-ios7-arrow-thin-left:before, .ion-ios7-arrow-thin-right:before, .ion-ios7-arrow-thin-up:before, .ion-ios7-arrow-up:before, .ion-ios7-at:before, .ion-ios7-at-outline:before, .ion-ios7-barcode:before, .ion-ios7-barcode-outline:before, .ion-ios7-baseball:before, .ion-ios7-baseball-outline:before, .ion-ios7-basketball:before, .ion-ios7-basketball-outline:before, .ion-ios7-bell:before, .ion-ios7-bell-outline:before, .ion-ios7-bolt:before, .ion-ios7-bolt-outline:before, .ion-ios7-bookmarks:before, .ion-ios7-bookmarks-outline:before, .ion-ios7-box:before, .ion-ios7-box-outline:before, .ion-ios7-briefcase:before, .ion-ios7-briefcase-outline:before, .ion-ios7-browsers:before, .ion-ios7-browsers-outline:before, .ion-ios7-calculator:before, .ion-ios7-calculator-outline:before, .ion-ios7-calendar:before, .ion-ios7-calendar-outline:before, .ion-ios7-camera:before, .ion-ios7-camera-outline:before, .ion-ios7-cart:before, .ion-ios7-cart-outline:before, .ion-ios7-chatboxes:before, .ion-ios7-chatboxes-outline:before, .ion-ios7-chatbubble:before, .ion-ios7-chatbubble-outline:before, .ion-ios7-checkmark:before, .ion-ios7-checkmark-empty:before, .ion-ios7-checkmark-outline:before, .ion-ios7-circle-filled:before, .ion-ios7-circle-outline:before, .ion-ios7-clock:before, .ion-ios7-clock-outline:before, .ion-ios7-close:before, .ion-ios7-close-empty:before, .ion-ios7-close-outline:before, .ion-ios7-cloud:before, .ion-ios7-cloud-download:before, .ion-ios7-cloud-download-outline:before, .ion-ios7-cloud-outline:before, .ion-ios7-cloud-upload:before, .ion-ios7-cloud-upload-outline:before, .ion-ios7-cloudy:before, .ion-ios7-cloudy-night:before, .ion-ios7-cloudy-night-outline:before, .ion-ios7-cloudy-outline:before, .ion-ios7-cog:before, .ion-ios7-cog-outline:before, .ion-ios7-compose:before, .ion-ios7-compose-outline:before, .ion-ios7-contact:before, .ion-ios7-contact-outline:before, .ion-ios7-copy:before, .ion-ios7-copy-outline:before, .ion-ios7-download:before, .ion-ios7-download-outline:before, .ion-ios7-drag:before, .ion-ios7-email:before, .ion-ios7-email-outline:before, .ion-ios7-expand:before, .ion-ios7-eye:before, .ion-ios7-eye-outline:before, .ion-ios7-fastforward:before, .ion-ios7-fastforward-outline:before, .ion-ios7-filing:before, .ion-ios7-filing-outline:before, .ion-ios7-film:before, .ion-ios7-film-outline:before, .ion-ios7-flag:before, .ion-ios7-flag-outline:before, .ion-ios7-folder:before, .ion-ios7-folder-outline:before, .ion-ios7-football:before, .ion-ios7-football-outline:before, .ion-ios7-gear:before, .ion-ios7-gear-outline:before, .ion-ios7-glasses:before, .ion-ios7-glasses-outline:before, .ion-ios7-heart:before, .ion-ios7-heart-outline:before, .ion-ios7-help:before, .ion-ios7-help-empty:before, .ion-ios7-help-outline:before, .ion-ios7-home:before, .ion-ios7-home-outline:before, .ion-ios7-infinite:before, .ion-ios7-infinite-outline:before, .ion-ios7-information:before, .ion-ios7-information-empty:before, .ion-ios7-information-outline:before, .ion-ios7-ionic-outline:before, .ion-ios7-keypad:before, .ion-ios7-keypad-outline:before, .ion-ios7-lightbulb:before, .ion-ios7-lightbulb-outline:before, .ion-ios7-location:before, .ion-ios7-location-outline:before, .ion-ios7-locked:before, .ion-ios7-locked-outline:before, .ion-ios7-loop:before, .ion-ios7-loop-strong:before, .ion-ios7-medkit:before, .ion-ios7-medkit-outline:before, .ion-ios7-mic:before, .ion-ios7-mic-off:before, .ion-ios7-mic-outline:before, .ion-ios7-minus:before, .ion-ios7-minus-empty:before, .ion-ios7-minus-outline:before, .ion-ios7-monitor:before, .ion-ios7-monitor-outline:before, .ion-ios7-moon:before, .ion-ios7-moon-outline:before, .ion-ios7-more:before, .ion-ios7-more-outline:before, .ion-ios7-musical-note:before, .ion-ios7-musical-notes:before, .ion-ios7-navigate:before, .ion-ios7-navigate-outline:before, .ion-ios7-paper:before, .ion-ios7-paper-outline:before, .ion-ios7-paperplane:before, .ion-ios7-paperplane-outline:before, .ion-ios7-partlysunny:before, .ion-ios7-partlysunny-outline:before, .ion-ios7-pause:before, .ion-ios7-pause-outline:before, .ion-ios7-paw:before, .ion-ios7-paw-outline:before, .ion-ios7-people:before, .ion-ios7-people-outline:before, .ion-ios7-person:before, .ion-ios7-person-outline:before, .ion-ios7-personadd:before, .ion-ios7-personadd-outline:before, .ion-ios7-photos:before, .ion-ios7-photos-outline:before, .ion-ios7-pie:before, .ion-ios7-pie-outline:before, .ion-ios7-play:before, .ion-ios7-play-outline:before, .ion-ios7-plus:before, .ion-ios7-plus-empty:before, .ion-ios7-plus-outline:before, .ion-ios7-pricetag:before, .ion-ios7-pricetag-outline:before, .ion-ios7-pricetags:before, .ion-ios7-pricetags-outline:before, .ion-ios7-printer:before, .ion-ios7-printer-outline:before, .ion-ios7-pulse:before, .ion-ios7-pulse-strong:before, .ion-ios7-rainy:before, .ion-ios7-rainy-outline:before, .ion-ios7-recording:before, .ion-ios7-recording-outline:before, .ion-ios7-redo:before, .ion-ios7-redo-outline:before, .ion-ios7-refresh:before, .ion-ios7-refresh-empty:before, .ion-ios7-refresh-outline:before, .ion-ios7-reload:before, .ion-ios7-reloading:before, .ion-ios7-reverse-camera:before, .ion-ios7-reverse-camera-outline:before, .ion-ios7-rewind:before, .ion-ios7-rewind-outline:before, .ion-ios7-search:before, .ion-ios7-search-strong:before, .ion-ios7-settings:before, .ion-ios7-settings-strong:before, .ion-ios7-shrink:before, .ion-ios7-skipbackward:before, .ion-ios7-skipbackward-outline:before, .ion-ios7-skipforward:before, .ion-ios7-skipforward-outline:before, .ion-ios7-snowy:before, .ion-ios7-speedometer:before, .ion-ios7-speedometer-outline:before, .ion-ios7-star:before, .ion-ios7-star-half:before, .ion-ios7-star-outline:before, .ion-ios7-stopwatch:before, .ion-ios7-stopwatch-outline:before, .ion-ios7-sunny:before, .ion-ios7-sunny-outline:before, .ion-ios7-telephone:before, .ion-ios7-telephone-outline:before, .ion-ios7-tennisball:before, .ion-ios7-tennisball-outline:before, .ion-ios7-thunderstorm:before, .ion-ios7-thunderstorm-outline:before, .ion-ios7-time:before, .ion-ios7-time-outline:before, .ion-ios7-timer:before, .ion-ios7-timer-outline:before, .ion-ios7-toggle:before, .ion-ios7-toggle-outline:before, .ion-ios7-trash:before, .ion-ios7-trash-outline:before, .ion-ios7-undo:before, .ion-ios7-undo-outline:before, .ion-ios7-unlocked:before, .ion-ios7-unlocked-outline:before, .ion-ios7-upload:before, .ion-ios7-upload-outline:before, .ion-ios7-videocam:before, .ion-ios7-videocam-outline:before, .ion-ios7-volume-high:before, .ion-ios7-volume-low:before, .ion-ios7-wineglass:before, .ion-ios7-wineglass-outline:before, .ion-ios7-world:before, .ion-ios7-world-outline:before, .ion-ipad:before, .ion-iphone:before, .ion-ipod:before, .ion-jet:before, .ion-key:before, .ion-knife:before, .ion-laptop:before, .ion-leaf:before, .ion-levels:before, .ion-lightbulb:before, .ion-link:before, .ion-load-a:before, .ion-loading-a:before, .ion-load-b:before, .ion-loading-b:before, .ion-load-c:before, .ion-loading-c:before, .ion-load-d:before, .ion-loading-d:before, .ion-location:before, .ion-locked:before, .ion-log-in:before, .ion-log-out:before, .ion-loop:before, .ion-looping:before, .ion-magnet:before, .ion-male:before, .ion-man:before, .ion-map:before, .ion-medkit:before, .ion-merge:before, .ion-mic-a:before, .ion-mic-b:before, .ion-mic-c:before, .ion-minus:before, .ion-minus-circled:before, .ion-minus-round:before, .ion-model-s:before, .ion-monitor:before, .ion-more:before, .ion-mouse:before, .ion-music-note:before, .ion-navicon:before, .ion-navicon-round:before, .ion-navigate:before, .ion-network:before, .ion-no-smoking:before, .ion-nuclear:before, .ion-outlet:before, .ion-paper-airplane:before, .ion-paperclip:before, .ion-pause:before, .ion-person:before, .ion-person-add:before, .ion-person-stalker:before, .ion-pie-graph:before, .ion-pin:before, .ion-pinpoint:before, .ion-pizza:before, .ion-plane:before, .ion-planet:before, .ion-play:before, .ion-playstation:before, .ion-plus:before, .ion-plus-circled:before, .ion-plus-round:before, .ion-podium:before, .ion-pound:before, .ion-power:before, .ion-pricetag:before, .ion-pricetags:before, .ion-printer:before, .ion-pull-request:before, .ion-qr-scanner:before, .ion-quote:before, .ion-radio-waves:before, .ion-record:before, .ion-refresh:before, .ion-refreshing:before, .ion-reply:before, .ion-reply-all:before, .ion-ribbon-a:before, .ion-ribbon-b:before, .ion-sad:before, .ion-scissors:before, .ion-search:before, .ion-settings:before, .ion-share:before, .ion-shuffle:before, .ion-skip-backward:before, .ion-skip-forward:before, .ion-social-android:before, .ion-social-android-outline:before, .ion-social-apple:before, .ion-social-apple-outline:before, .ion-social-bitcoin:before, .ion-social-bitcoin-outline:before, .ion-social-buffer:before, .ion-social-buffer-outline:before, .ion-social-designernews:before, .ion-social-designernews-outline:before, .ion-social-dribbble:before, .ion-social-dribbble-outline:before, .ion-social-dropbox:before, .ion-social-dropbox-outline:before, .ion-social-facebook:before, .ion-social-facebook-outline:before, .ion-social-foursquare:before, .ion-social-foursquare-outline:before, .ion-social-freebsd-devil:before, .ion-social-github:before, .ion-social-github-outline:before, .ion-social-google:before, .ion-social-google-outline:before, .ion-social-googleplus:before, .ion-social-googleplus-outline:before, .ion-social-hackernews:before, .ion-social-hackernews-outline:before, .ion-social-instagram:before, .ion-social-instagram-outline:before, .ion-social-linkedin:before, .ion-social-linkedin-outline:before, .ion-social-pinterest:before, .ion-social-pinterest-outline:before, .ion-social-reddit:before, .ion-social-reddit-outline:before, .ion-social-rss:before, .ion-social-rss-outline:before, .ion-social-skype:before, .ion-social-skype-outline:before, .ion-social-tumblr:before, .ion-social-tumblr-outline:before, .ion-social-tux:before, .ion-social-twitter:before, .ion-social-twitter-outline:before, .ion-social-usd:before, .ion-social-usd-outline:before, .ion-social-vimeo:before, .ion-social-vimeo-outline:before, .ion-social-windows:before, .ion-social-windows-outline:before, .ion-social-wordpress:before, .ion-social-wordpress-outline:before, .ion-social-yahoo:before, .ion-social-yahoo-outline:before, .ion-social-youtube:before, .ion-social-youtube-outline:before, .ion-speakerphone:before, .ion-speedometer:before, .ion-spoon:before, .ion-star:before, .ion-stats-bars:before, .ion-steam:before, .ion-stop:before, .ion-thermometer:before, .ion-thumbsdown:before, .ion-thumbsup:before, .ion-toggle:before, .ion-toggle-filled:before, .ion-trash-a:before, .ion-trash-b:before, .ion-trophy:before, .ion-umbrella:before, .ion-university:before, .ion-unlocked:before, .ion-upload:before, .ion-usb:before, .ion-videocamera:before, .ion-volume-high:before, .ion-volume-low:before, .ion-volume-medium:before, .ion-volume-mute:before, .ion-wand:before, .ion-waterdrop:before, .ion-wifi:before, .ion-wineglass:before, .ion-woman:before, .ion-wrench:before, .ion-xbox:before { display: inline-block; font-family: "Ionicons"; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; text-rendering: auto; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } - -.ion-spin, .ion-loading-a, .ion-loading-b, .ion-loading-c, .ion-loading-d, .ion-looping, .ion-refreshing, .ion-ios7-reloading { -webkit-animation: spin 1s infinite linear; -moz-animation: spin 1s infinite linear; -o-animation: spin 1s infinite linear; animation: spin 1s infinite linear; } -@-moz-keyframes spin { 0% { -moz-transform: rotate(0deg); } - 100% { -moz-transform: rotate(359deg); } } -@-webkit-keyframes spin { 0% { -webkit-transform: rotate(0deg); } - 100% { -webkit-transform: rotate(359deg); } } -@-o-keyframes spin { 0% { -o-transform: rotate(0deg); } - 100% { -o-transform: rotate(359deg); } } -@-ms-keyframes spin { 0% { -ms-transform: rotate(0deg); } - 100% { -ms-transform: rotate(359deg); } } -@keyframes spin { 0% { transform: rotate(0deg); } - 100% { transform: rotate(359deg); } } -.ion-loading-a { -webkit-animation-timing-function: steps(8, start); -moz-animation-timing-function: steps(8, start); animation-timing-function: steps(8, start); } + Android-style icons originally built by Google’s + Material Design Icons: https://github.com/google/material-design-icons + used under CC BY http://creativecommons.org/licenses/by/4.0/ + Modified icons to fit ionicon’s grid from original. +*/ +@font-face { font-family: "Ionicons"; src: url("../fonts/ionicons.eot?v=2.0.0"); src: url("../fonts/ionicons.eot?v=2.0.0#iefix") format("embedded-opentype"), url("../fonts/ionicons.ttf?v=2.0.0") format("truetype"), url("../fonts/ionicons.woff?v=2.0.0") format("woff"), url("../fonts/ionicons.svg?v=2.0.0#Ionicons") format("svg"); font-weight: normal; font-style: normal; } +.ion, .ionicons, .ion-alert:before, .ion-alert-circled:before, .ion-android-add:before, .ion-android-add-circle:before, .ion-android-alarm-clock:before, .ion-android-alert:before, .ion-android-apps:before, .ion-android-archive:before, .ion-android-arrow-back:before, .ion-android-arrow-down:before, .ion-android-arrow-dropdown:before, .ion-android-arrow-dropdown-circle:before, .ion-android-arrow-dropleft:before, .ion-android-arrow-dropleft-circle:before, .ion-android-arrow-dropright:before, .ion-android-arrow-dropright-circle:before, .ion-android-arrow-dropup:before, .ion-android-arrow-dropup-circle:before, .ion-android-arrow-forward:before, .ion-android-arrow-up:before, .ion-android-attach:before, .ion-android-bar:before, .ion-android-bicycle:before, .ion-android-boat:before, .ion-android-bookmark:before, .ion-android-bulb:before, .ion-android-bus:before, .ion-android-calendar:before, .ion-android-call:before, .ion-android-camera:before, .ion-android-cancel:before, .ion-android-car:before, .ion-android-cart:before, .ion-android-chat:before, .ion-android-checkbox:before, .ion-android-checkbox-blank:before, .ion-android-checkbox-outline:before, .ion-android-checkbox-outline-blank:before, .ion-android-checkmark-circle:before, .ion-android-clipboard:before, .ion-android-close:before, .ion-android-cloud:before, .ion-android-cloud-circle:before, .ion-android-cloud-done:before, .ion-android-cloud-outline:before, .ion-android-color-palette:before, .ion-android-compass:before, .ion-android-contact:before, .ion-android-contacts:before, .ion-android-contract:before, .ion-android-create:before, .ion-android-delete:before, .ion-android-desktop:before, .ion-android-document:before, .ion-android-done:before, .ion-android-done-all:before, .ion-android-download:before, .ion-android-drafts:before, .ion-android-exit:before, .ion-android-expand:before, .ion-android-favorite:before, .ion-android-favorite-outline:before, .ion-android-film:before, .ion-android-folder:before, .ion-android-folder-open:before, .ion-android-funnel:before, .ion-android-globe:before, .ion-android-hand:before, .ion-android-hangout:before, .ion-android-happy:before, .ion-android-home:before, .ion-android-image:before, .ion-android-laptop:before, .ion-android-list:before, .ion-android-locate:before, .ion-android-lock:before, .ion-android-mail:before, .ion-android-map:before, .ion-android-menu:before, .ion-android-microphone:before, .ion-android-microphone-off:before, .ion-android-more-horizontal:before, .ion-android-more-vertical:before, .ion-android-navigate:before, .ion-android-notifications:before, .ion-android-notifications-none:before, .ion-android-notifications-off:before, .ion-android-open:before, .ion-android-options:before, .ion-android-people:before, .ion-android-person:before, .ion-android-person-add:before, .ion-android-phone-landscape:before, .ion-android-phone-portrait:before, .ion-android-pin:before, .ion-android-plane:before, .ion-android-playstore:before, .ion-android-print:before, .ion-android-radio-button-off:before, .ion-android-radio-button-on:before, .ion-android-refresh:before, .ion-android-remove:before, .ion-android-remove-circle:before, .ion-android-restaurant:before, .ion-android-sad:before, .ion-android-search:before, .ion-android-send:before, .ion-android-settings:before, .ion-android-share:before, .ion-android-share-alt:before, .ion-android-star:before, .ion-android-star-half:before, .ion-android-star-outline:before, .ion-android-stopwatch:before, .ion-android-subway:before, .ion-android-sunny:before, .ion-android-sync:before, .ion-android-textsms:before, .ion-android-time:before, .ion-android-train:before, .ion-android-unlock:before, .ion-android-upload:before, .ion-android-volume-down:before, .ion-android-volume-mute:before, .ion-android-volume-off:before, .ion-android-volume-up:before, .ion-android-walk:before, .ion-android-warning:before, .ion-android-watch:before, .ion-android-wifi:before, .ion-aperture:before, .ion-archive:before, .ion-arrow-down-a:before, .ion-arrow-down-b:before, .ion-arrow-down-c:before, .ion-arrow-expand:before, .ion-arrow-graph-down-left:before, .ion-arrow-graph-down-right:before, .ion-arrow-graph-up-left:before, .ion-arrow-graph-up-right:before, .ion-arrow-left-a:before, .ion-arrow-left-b:before, .ion-arrow-left-c:before, .ion-arrow-move:before, .ion-arrow-resize:before, .ion-arrow-return-left:before, .ion-arrow-return-right:before, .ion-arrow-right-a:before, .ion-arrow-right-b:before, .ion-arrow-right-c:before, .ion-arrow-shrink:before, .ion-arrow-swap:before, .ion-arrow-up-a:before, .ion-arrow-up-b:before, .ion-arrow-up-c:before, .ion-asterisk:before, .ion-at:before, .ion-backspace:before, .ion-backspace-outline:before, .ion-bag:before, .ion-battery-charging:before, .ion-battery-empty:before, .ion-battery-full:before, .ion-battery-half:before, .ion-battery-low:before, .ion-beaker:before, .ion-beer:before, .ion-bluetooth:before, .ion-bonfire:before, .ion-bookmark:before, .ion-bowtie:before, .ion-briefcase:before, .ion-bug:before, .ion-calculator:before, .ion-calendar:before, .ion-camera:before, .ion-card:before, .ion-cash:before, .ion-chatbox:before, .ion-chatbox-working:before, .ion-chatboxes:before, .ion-chatbubble:before, .ion-chatbubble-working:before, .ion-chatbubbles:before, .ion-checkmark:before, .ion-checkmark-circled:before, .ion-checkmark-round:before, .ion-chevron-down:before, .ion-chevron-left:before, .ion-chevron-right:before, .ion-chevron-up:before, .ion-clipboard:before, .ion-clock:before, .ion-close:before, .ion-close-circled:before, .ion-close-round:before, .ion-closed-captioning:before, .ion-cloud:before, .ion-code:before, .ion-code-download:before, .ion-code-working:before, .ion-coffee:before, .ion-compass:before, .ion-compose:before, .ion-connection-bars:before, .ion-contrast:before, .ion-crop:before, .ion-cube:before, .ion-disc:before, .ion-document:before, .ion-document-text:before, .ion-drag:before, .ion-earth:before, .ion-easel:before, .ion-edit:before, .ion-egg:before, .ion-eject:before, .ion-email:before, .ion-email-unread:before, .ion-erlenmeyer-flask:before, .ion-erlenmeyer-flask-bubbles:before, .ion-eye:before, .ion-eye-disabled:before, .ion-female:before, .ion-filing:before, .ion-film-marker:before, .ion-fireball:before, .ion-flag:before, .ion-flame:before, .ion-flash:before, .ion-flash-off:before, .ion-folder:before, .ion-fork:before, .ion-fork-repo:before, .ion-forward:before, .ion-funnel:before, .ion-gear-a:before, .ion-gear-b:before, .ion-grid:before, .ion-hammer:before, .ion-happy:before, .ion-happy-outline:before, .ion-headphone:before, .ion-heart:before, .ion-heart-broken:before, .ion-help:before, .ion-help-buoy:before, .ion-help-circled:before, .ion-home:before, .ion-icecream:before, .ion-image:before, .ion-images:before, .ion-information:before, .ion-information-circled:before, .ion-ionic:before, .ion-ios-alarm:before, .ion-ios-alarm-outline:before, .ion-ios-albums:before, .ion-ios-albums-outline:before, .ion-ios-americanfootball:before, .ion-ios-americanfootball-outline:before, .ion-ios-analytics:before, .ion-ios-analytics-outline:before, .ion-ios-arrow-back:before, .ion-ios-arrow-down:before, .ion-ios-arrow-forward:before, .ion-ios-arrow-left:before, .ion-ios-arrow-right:before, .ion-ios-arrow-thin-down:before, .ion-ios-arrow-thin-left:before, .ion-ios-arrow-thin-right:before, .ion-ios-arrow-thin-up:before, .ion-ios-arrow-up:before, .ion-ios-at:before, .ion-ios-at-outline:before, .ion-ios-barcode:before, .ion-ios-barcode-outline:before, .ion-ios-baseball:before, .ion-ios-baseball-outline:before, .ion-ios-basketball:before, .ion-ios-basketball-outline:before, .ion-ios-bell:before, .ion-ios-bell-outline:before, .ion-ios-body:before, .ion-ios-body-outline:before, .ion-ios-bolt:before, .ion-ios-bolt-outline:before, .ion-ios-book:before, .ion-ios-book-outline:before, .ion-ios-bookmarks:before, .ion-ios-bookmarks-outline:before, .ion-ios-box:before, .ion-ios-box-outline:before, .ion-ios-briefcase:before, .ion-ios-briefcase-outline:before, .ion-ios-browsers:before, .ion-ios-browsers-outline:before, .ion-ios-calculator:before, .ion-ios-calculator-outline:before, .ion-ios-calendar:before, .ion-ios-calendar-outline:before, .ion-ios-camera:before, .ion-ios-camera-outline:before, .ion-ios-cart:before, .ion-ios-cart-outline:before, .ion-ios-chatboxes:before, .ion-ios-chatboxes-outline:before, .ion-ios-chatbubble:before, .ion-ios-chatbubble-outline:before, .ion-ios-checkmark:before, .ion-ios-checkmark-empty:before, .ion-ios-checkmark-outline:before, .ion-ios-circle-filled:before, .ion-ios-circle-outline:before, .ion-ios-clock:before, .ion-ios-clock-outline:before, .ion-ios-close:before, .ion-ios-close-empty:before, .ion-ios-close-outline:before, .ion-ios-cloud:before, .ion-ios-cloud-download:before, .ion-ios-cloud-download-outline:before, .ion-ios-cloud-outline:before, .ion-ios-cloud-upload:before, .ion-ios-cloud-upload-outline:before, .ion-ios-cloudy:before, .ion-ios-cloudy-night:before, .ion-ios-cloudy-night-outline:before, .ion-ios-cloudy-outline:before, .ion-ios-cog:before, .ion-ios-cog-outline:before, .ion-ios-color-filter:before, .ion-ios-color-filter-outline:before, .ion-ios-color-wand:before, .ion-ios-color-wand-outline:before, .ion-ios-compose:before, .ion-ios-compose-outline:before, .ion-ios-contact:before, .ion-ios-contact-outline:before, .ion-ios-copy:before, .ion-ios-copy-outline:before, .ion-ios-crop:before, .ion-ios-crop-strong:before, .ion-ios-download:before, .ion-ios-download-outline:before, .ion-ios-drag:before, .ion-ios-email:before, .ion-ios-email-outline:before, .ion-ios-eye:before, .ion-ios-eye-outline:before, .ion-ios-fastforward:before, .ion-ios-fastforward-outline:before, .ion-ios-filing:before, .ion-ios-filing-outline:before, .ion-ios-film:before, .ion-ios-film-outline:before, .ion-ios-flag:before, .ion-ios-flag-outline:before, .ion-ios-flame:before, .ion-ios-flame-outline:before, .ion-ios-flask:before, .ion-ios-flask-outline:before, .ion-ios-flower:before, .ion-ios-flower-outline:before, .ion-ios-folder:before, .ion-ios-folder-outline:before, .ion-ios-football:before, .ion-ios-football-outline:before, .ion-ios-game-controller-a:before, .ion-ios-game-controller-a-outline:before, .ion-ios-game-controller-b:before, .ion-ios-game-controller-b-outline:before, .ion-ios-gear:before, .ion-ios-gear-outline:before, .ion-ios-glasses:before, .ion-ios-glasses-outline:before, .ion-ios-grid-view:before, .ion-ios-grid-view-outline:before, .ion-ios-heart:before, .ion-ios-heart-outline:before, .ion-ios-help:before, .ion-ios-help-empty:before, .ion-ios-help-outline:before, .ion-ios-home:before, .ion-ios-home-outline:before, .ion-ios-infinite:before, .ion-ios-infinite-outline:before, .ion-ios-information:before, .ion-ios-information-empty:before, .ion-ios-information-outline:before, .ion-ios-ionic-outline:before, .ion-ios-keypad:before, .ion-ios-keypad-outline:before, .ion-ios-lightbulb:before, .ion-ios-lightbulb-outline:before, .ion-ios-list:before, .ion-ios-list-outline:before, .ion-ios-location:before, .ion-ios-location-outline:before, .ion-ios-locked:before, .ion-ios-locked-outline:before, .ion-ios-loop:before, .ion-ios-loop-strong:before, .ion-ios-medical:before, .ion-ios-medical-outline:before, .ion-ios-medkit:before, .ion-ios-medkit-outline:before, .ion-ios-mic:before, .ion-ios-mic-off:before, .ion-ios-mic-outline:before, .ion-ios-minus:before, .ion-ios-minus-empty:before, .ion-ios-minus-outline:before, .ion-ios-monitor:before, .ion-ios-monitor-outline:before, .ion-ios-moon:before, .ion-ios-moon-outline:before, .ion-ios-more:before, .ion-ios-more-outline:before, .ion-ios-musical-note:before, .ion-ios-musical-notes:before, .ion-ios-navigate:before, .ion-ios-navigate-outline:before, .ion-ios-nutrition:before, .ion-ios-nutrition-outline:before, .ion-ios-paper:before, .ion-ios-paper-outline:before, .ion-ios-paperplane:before, .ion-ios-paperplane-outline:before, .ion-ios-partlysunny:before, .ion-ios-partlysunny-outline:before, .ion-ios-pause:before, .ion-ios-pause-outline:before, .ion-ios-paw:before, .ion-ios-paw-outline:before, .ion-ios-people:before, .ion-ios-people-outline:before, .ion-ios-person:before, .ion-ios-person-outline:before, .ion-ios-personadd:before, .ion-ios-personadd-outline:before, .ion-ios-photos:before, .ion-ios-photos-outline:before, .ion-ios-pie:before, .ion-ios-pie-outline:before, .ion-ios-pint:before, .ion-ios-pint-outline:before, .ion-ios-play:before, .ion-ios-play-outline:before, .ion-ios-plus:before, .ion-ios-plus-empty:before, .ion-ios-plus-outline:before, .ion-ios-pricetag:before, .ion-ios-pricetag-outline:before, .ion-ios-pricetags:before, .ion-ios-pricetags-outline:before, .ion-ios-printer:before, .ion-ios-printer-outline:before, .ion-ios-pulse:before, .ion-ios-pulse-strong:before, .ion-ios-rainy:before, .ion-ios-rainy-outline:before, .ion-ios-recording:before, .ion-ios-recording-outline:before, .ion-ios-redo:before, .ion-ios-redo-outline:before, .ion-ios-refresh:before, .ion-ios-refresh-empty:before, .ion-ios-refresh-outline:before, .ion-ios-reload:before, .ion-ios-reverse-camera:before, .ion-ios-reverse-camera-outline:before, .ion-ios-rewind:before, .ion-ios-rewind-outline:before, .ion-ios-rose:before, .ion-ios-rose-outline:before, .ion-ios-search:before, .ion-ios-search-strong:before, .ion-ios-settings:before, .ion-ios-settings-strong:before, .ion-ios-shuffle:before, .ion-ios-shuffle-strong:before, .ion-ios-skipbackward:before, .ion-ios-skipbackward-outline:before, .ion-ios-skipforward:before, .ion-ios-skipforward-outline:before, .ion-ios-snowy:before, .ion-ios-speedometer:before, .ion-ios-speedometer-outline:before, .ion-ios-star:before, .ion-ios-star-half:before, .ion-ios-star-outline:before, .ion-ios-stopwatch:before, .ion-ios-stopwatch-outline:before, .ion-ios-sunny:before, .ion-ios-sunny-outline:before, .ion-ios-telephone:before, .ion-ios-telephone-outline:before, .ion-ios-tennisball:before, .ion-ios-tennisball-outline:before, .ion-ios-thunderstorm:before, .ion-ios-thunderstorm-outline:before, .ion-ios-time:before, .ion-ios-time-outline:before, .ion-ios-timer:before, .ion-ios-timer-outline:before, .ion-ios-toggle:before, .ion-ios-toggle-outline:before, .ion-ios-trash:before, .ion-ios-trash-outline:before, .ion-ios-undo:before, .ion-ios-undo-outline:before, .ion-ios-unlocked:before, .ion-ios-unlocked-outline:before, .ion-ios-upload:before, .ion-ios-upload-outline:before, .ion-ios-videocam:before, .ion-ios-videocam-outline:before, .ion-ios-volume-high:before, .ion-ios-volume-low:before, .ion-ios-wineglass:before, .ion-ios-wineglass-outline:before, .ion-ios-world:before, .ion-ios-world-outline:before, .ion-ipad:before, .ion-iphone:before, .ion-ipod:before, .ion-jet:before, .ion-key:before, .ion-knife:before, .ion-laptop:before, .ion-leaf:before, .ion-levels:before, .ion-lightbulb:before, .ion-link:before, .ion-load-a:before, .ion-load-b:before, .ion-load-c:before, .ion-load-d:before, .ion-location:before, .ion-lock-combination:before, .ion-locked:before, .ion-log-in:before, .ion-log-out:before, .ion-loop:before, .ion-magnet:before, .ion-male:before, .ion-man:before, .ion-map:before, .ion-medkit:before, .ion-merge:before, .ion-mic-a:before, .ion-mic-b:before, .ion-mic-c:before, .ion-minus:before, .ion-minus-circled:before, .ion-minus-round:before, .ion-model-s:before, .ion-monitor:before, .ion-more:before, .ion-mouse:before, .ion-music-note:before, .ion-navicon:before, .ion-navicon-round:before, .ion-navigate:before, .ion-network:before, .ion-no-smoking:before, .ion-nuclear:before, .ion-outlet:before, .ion-paintbrush:before, .ion-paintbucket:before, .ion-paper-airplane:before, .ion-paperclip:before, .ion-pause:before, .ion-person:before, .ion-person-add:before, .ion-person-stalker:before, .ion-pie-graph:before, .ion-pin:before, .ion-pinpoint:before, .ion-pizza:before, .ion-plane:before, .ion-planet:before, .ion-play:before, .ion-playstation:before, .ion-plus:before, .ion-plus-circled:before, .ion-plus-round:before, .ion-podium:before, .ion-pound:before, .ion-power:before, .ion-pricetag:before, .ion-pricetags:before, .ion-printer:before, .ion-pull-request:before, .ion-qr-scanner:before, .ion-quote:before, .ion-radio-waves:before, .ion-record:before, .ion-refresh:before, .ion-reply:before, .ion-reply-all:before, .ion-ribbon-a:before, .ion-ribbon-b:before, .ion-sad:before, .ion-sad-outline:before, .ion-scissors:before, .ion-search:before, .ion-settings:before, .ion-share:before, .ion-shuffle:before, .ion-skip-backward:before, .ion-skip-forward:before, .ion-social-android:before, .ion-social-android-outline:before, .ion-social-angular:before, .ion-social-angular-outline:before, .ion-social-apple:before, .ion-social-apple-outline:before, .ion-social-bitcoin:before, .ion-social-bitcoin-outline:before, .ion-social-buffer:before, .ion-social-buffer-outline:before, .ion-social-chrome:before, .ion-social-chrome-outline:before, .ion-social-codepen:before, .ion-social-codepen-outline:before, .ion-social-css3:before, .ion-social-css3-outline:before, .ion-social-designernews:before, .ion-social-designernews-outline:before, .ion-social-dribbble:before, .ion-social-dribbble-outline:before, .ion-social-dropbox:before, .ion-social-dropbox-outline:before, .ion-social-euro:before, .ion-social-euro-outline:before, .ion-social-facebook:before, .ion-social-facebook-outline:before, .ion-social-foursquare:before, .ion-social-foursquare-outline:before, .ion-social-freebsd-devil:before, .ion-social-github:before, .ion-social-github-outline:before, .ion-social-google:before, .ion-social-google-outline:before, .ion-social-googleplus:before, .ion-social-googleplus-outline:before, .ion-social-hackernews:before, .ion-social-hackernews-outline:before, .ion-social-html5:before, .ion-social-html5-outline:before, .ion-social-instagram:before, .ion-social-instagram-outline:before, .ion-social-javascript:before, .ion-social-javascript-outline:before, .ion-social-linkedin:before, .ion-social-linkedin-outline:before, .ion-social-markdown:before, .ion-social-nodejs:before, .ion-social-octocat:before, .ion-social-pinterest:before, .ion-social-pinterest-outline:before, .ion-social-python:before, .ion-social-reddit:before, .ion-social-reddit-outline:before, .ion-social-rss:before, .ion-social-rss-outline:before, .ion-social-sass:before, .ion-social-skype:before, .ion-social-skype-outline:before, .ion-social-snapchat:before, .ion-social-snapchat-outline:before, .ion-social-tumblr:before, .ion-social-tumblr-outline:before, .ion-social-tux:before, .ion-social-twitch:before, .ion-social-twitch-outline:before, .ion-social-twitter:before, .ion-social-twitter-outline:before, .ion-social-usd:before, .ion-social-usd-outline:before, .ion-social-vimeo:before, .ion-social-vimeo-outline:before, .ion-social-whatsapp:before, .ion-social-whatsapp-outline:before, .ion-social-windows:before, .ion-social-windows-outline:before, .ion-social-wordpress:before, .ion-social-wordpress-outline:before, .ion-social-yahoo:before, .ion-social-yahoo-outline:before, .ion-social-yen:before, .ion-social-yen-outline:before, .ion-social-youtube:before, .ion-social-youtube-outline:before, .ion-soup-can:before, .ion-soup-can-outline:before, .ion-speakerphone:before, .ion-speedometer:before, .ion-spoon:before, .ion-star:before, .ion-stats-bars:before, .ion-steam:before, .ion-stop:before, .ion-thermometer:before, .ion-thumbsdown:before, .ion-thumbsup:before, .ion-toggle:before, .ion-toggle-filled:before, .ion-transgender:before, .ion-trash-a:before, .ion-trash-b:before, .ion-trophy:before, .ion-tshirt:before, .ion-tshirt-outline:before, .ion-umbrella:before, .ion-university:before, .ion-unlocked:before, .ion-upload:before, .ion-usb:before, .ion-videocamera:before, .ion-volume-high:before, .ion-volume-low:before, .ion-volume-medium:before, .ion-volume-mute:before, .ion-wand:before, .ion-waterdrop:before, .ion-wifi:before, .ion-wineglass:before, .ion-woman:before, .ion-wrench:before, .ion-xbox:before { display: inline-block; font-family: "Ionicons"; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; text-rendering: auto; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .ion-alert:before { content: "\f101"; } @@ -27,27 +19,53 @@ .ion-android-add:before { content: "\f2c7"; } -.ion-android-add-contact:before { content: "\f2c6"; } +.ion-android-add-circle:before { content: "\f359"; } + +.ion-android-alarm-clock:before { content: "\f35a"; } + +.ion-android-alert:before { content: "\f35b"; } -.ion-android-alarm:before { content: "\f2c8"; } +.ion-android-apps:before { content: "\f35c"; } .ion-android-archive:before { content: "\f2c9"; } .ion-android-arrow-back:before { content: "\f2ca"; } -.ion-android-arrow-down-left:before { content: "\f2cb"; } +.ion-android-arrow-down:before { content: "\f35d"; } + +.ion-android-arrow-dropdown:before { content: "\f35f"; } + +.ion-android-arrow-dropdown-circle:before { content: "\f35e"; } + +.ion-android-arrow-dropleft:before { content: "\f361"; } + +.ion-android-arrow-dropleft-circle:before { content: "\f360"; } + +.ion-android-arrow-dropright:before { content: "\f363"; } -.ion-android-arrow-down-right:before { content: "\f2cc"; } +.ion-android-arrow-dropright-circle:before { content: "\f362"; } + +.ion-android-arrow-dropup:before { content: "\f365"; } + +.ion-android-arrow-dropup-circle:before { content: "\f364"; } .ion-android-arrow-forward:before { content: "\f30f"; } -.ion-android-arrow-up-left:before { content: "\f2cd"; } +.ion-android-arrow-up:before { content: "\f366"; } + +.ion-android-attach:before { content: "\f367"; } + +.ion-android-bar:before { content: "\f368"; } + +.ion-android-bicycle:before { content: "\f369"; } -.ion-android-arrow-up-right:before { content: "\f2ce"; } +.ion-android-boat:before { content: "\f36a"; } -.ion-android-battery:before { content: "\f2cf"; } +.ion-android-bookmark:before { content: "\f36b"; } -.ion-android-book:before { content: "\f2d0"; } +.ion-android-bulb:before { content: "\f36c"; } + +.ion-android-bus:before { content: "\f36d"; } .ion-android-calendar:before { content: "\f2d1"; } @@ -55,74 +73,156 @@ .ion-android-camera:before { content: "\f2d3"; } +.ion-android-cancel:before { content: "\f36e"; } + +.ion-android-car:before { content: "\f36f"; } + +.ion-android-cart:before { content: "\f370"; } + .ion-android-chat:before { content: "\f2d4"; } -.ion-android-checkmark:before { content: "\f2d5"; } +.ion-android-checkbox:before { content: "\f374"; } -.ion-android-clock:before { content: "\f2d6"; } +.ion-android-checkbox-blank:before { content: "\f371"; } + +.ion-android-checkbox-outline:before { content: "\f373"; } + +.ion-android-checkbox-outline-blank:before { content: "\f372"; } + +.ion-android-checkmark-circle:before { content: "\f375"; } + +.ion-android-clipboard:before { content: "\f376"; } .ion-android-close:before { content: "\f2d7"; } +.ion-android-cloud:before { content: "\f37a"; } + +.ion-android-cloud-circle:before { content: "\f377"; } + +.ion-android-cloud-done:before { content: "\f378"; } + +.ion-android-cloud-outline:before { content: "\f379"; } + +.ion-android-color-palette:before { content: "\f37b"; } + +.ion-android-compass:before { content: "\f37c"; } + .ion-android-contact:before { content: "\f2d8"; } .ion-android-contacts:before { content: "\f2d9"; } -.ion-android-data:before { content: "\f2da"; } +.ion-android-contract:before { content: "\f37d"; } -.ion-android-developer:before { content: "\f2db"; } +.ion-android-create:before { content: "\f37e"; } -.ion-android-display:before { content: "\f2dc"; } +.ion-android-delete:before { content: "\f37f"; } + +.ion-android-desktop:before { content: "\f380"; } + +.ion-android-document:before { content: "\f381"; } + +.ion-android-done:before { content: "\f383"; } + +.ion-android-done-all:before { content: "\f382"; } .ion-android-download:before { content: "\f2dd"; } -.ion-android-drawer:before { content: "\f310"; } +.ion-android-drafts:before { content: "\f384"; } + +.ion-android-exit:before { content: "\f385"; } -.ion-android-dropdown:before { content: "\f2de"; } +.ion-android-expand:before { content: "\f386"; } -.ion-android-earth:before { content: "\f2df"; } +.ion-android-favorite:before { content: "\f388"; } + +.ion-android-favorite-outline:before { content: "\f387"; } + +.ion-android-film:before { content: "\f389"; } .ion-android-folder:before { content: "\f2e0"; } -.ion-android-forums:before { content: "\f2e1"; } +.ion-android-folder-open:before { content: "\f38a"; } -.ion-android-friends:before { content: "\f2e2"; } +.ion-android-funnel:before { content: "\f38b"; } + +.ion-android-globe:before { content: "\f38c"; } .ion-android-hand:before { content: "\f2e3"; } -.ion-android-image:before { content: "\f2e4"; } +.ion-android-hangout:before { content: "\f38d"; } -.ion-android-inbox:before { content: "\f2e5"; } +.ion-android-happy:before { content: "\f38e"; } -.ion-android-information:before { content: "\f2e6"; } +.ion-android-home:before { content: "\f38f"; } -.ion-android-keypad:before { content: "\f2e7"; } +.ion-android-image:before { content: "\f2e4"; } + +.ion-android-laptop:before { content: "\f390"; } -.ion-android-lightbulb:before { content: "\f2e8"; } +.ion-android-list:before { content: "\f391"; } .ion-android-locate:before { content: "\f2e9"; } -.ion-android-location:before { content: "\f2ea"; } +.ion-android-lock:before { content: "\f392"; } .ion-android-mail:before { content: "\f2eb"; } +.ion-android-map:before { content: "\f393"; } + +.ion-android-menu:before { content: "\f394"; } + .ion-android-microphone:before { content: "\f2ec"; } -.ion-android-mixer:before { content: "\f2ed"; } +.ion-android-microphone-off:before { content: "\f395"; } + +.ion-android-more-horizontal:before { content: "\f396"; } + +.ion-android-more-vertical:before { content: "\f397"; } + +.ion-android-navigate:before { content: "\f398"; } + +.ion-android-notifications:before { content: "\f39b"; } + +.ion-android-notifications-none:before { content: "\f399"; } + +.ion-android-notifications-off:before { content: "\f39a"; } -.ion-android-more:before { content: "\f2ee"; } +.ion-android-open:before { content: "\f39c"; } -.ion-android-note:before { content: "\f2ef"; } +.ion-android-options:before { content: "\f39d"; } + +.ion-android-people:before { content: "\f39e"; } + +.ion-android-person:before { content: "\f3a0"; } + +.ion-android-person-add:before { content: "\f39f"; } + +.ion-android-phone-landscape:before { content: "\f3a1"; } + +.ion-android-phone-portrait:before { content: "\f3a2"; } + +.ion-android-pin:before { content: "\f3a3"; } + +.ion-android-plane:before { content: "\f3a4"; } .ion-android-playstore:before { content: "\f2f0"; } -.ion-android-printer:before { content: "\f2f1"; } +.ion-android-print:before { content: "\f3a5"; } -.ion-android-promotion:before { content: "\f2f2"; } +.ion-android-radio-button-off:before { content: "\f3a6"; } -.ion-android-reminder:before { content: "\f2f3"; } +.ion-android-radio-button-on:before { content: "\f3a7"; } + +.ion-android-refresh:before { content: "\f3a8"; } .ion-android-remove:before { content: "\f2f4"; } +.ion-android-remove-circle:before { content: "\f3a9"; } + +.ion-android-restaurant:before { content: "\f3aa"; } + +.ion-android-sad:before { content: "\f3ab"; } + .ion-android-search:before { content: "\f2f5"; } .ion-android-send:before { content: "\f2f6"; } @@ -131,33 +231,45 @@ .ion-android-share:before { content: "\f2f8"; } -.ion-android-social:before { content: "\f2fa"; } - -.ion-android-social-user:before { content: "\f2f9"; } +.ion-android-share-alt:before { content: "\f3ac"; } -.ion-android-sort:before { content: "\f2fb"; } +.ion-android-star:before { content: "\f2fc"; } -.ion-android-stair-drawer:before { content: "\f311"; } +.ion-android-star-half:before { content: "\f3ad"; } -.ion-android-star:before { content: "\f2fc"; } +.ion-android-star-outline:before { content: "\f3ae"; } .ion-android-stopwatch:before { content: "\f2fd"; } -.ion-android-storage:before { content: "\f2fe"; } +.ion-android-subway:before { content: "\f3af"; } + +.ion-android-sunny:before { content: "\f3b0"; } + +.ion-android-sync:before { content: "\f3b1"; } + +.ion-android-textsms:before { content: "\f3b2"; } + +.ion-android-time:before { content: "\f3b3"; } + +.ion-android-train:before { content: "\f3b4"; } -.ion-android-system-back:before { content: "\f2ff"; } +.ion-android-unlock:before { content: "\f3b5"; } -.ion-android-system-home:before { content: "\f300"; } +.ion-android-upload:before { content: "\f3b6"; } -.ion-android-system-windows:before { content: "\f301"; } +.ion-android-volume-down:before { content: "\f3b7"; } -.ion-android-timer:before { content: "\f302"; } +.ion-android-volume-mute:before { content: "\f3b8"; } -.ion-android-trash:before { content: "\f303"; } +.ion-android-volume-off:before { content: "\f3b9"; } -.ion-android-user-menu:before { content: "\f312"; } +.ion-android-volume-up:before { content: "\f3ba"; } -.ion-android-volume:before { content: "\f304"; } +.ion-android-walk:before { content: "\f3bb"; } + +.ion-android-warning:before { content: "\f3bc"; } + +.ion-android-watch:before { content: "\f3bd"; } .ion-android-wifi:before { content: "\f305"; } @@ -215,6 +327,10 @@ .ion-at:before { content: "\f10f"; } +.ion-backspace:before { content: "\f3bf"; } + +.ion-backspace-outline:before { content: "\f3be"; } + .ion-bag:before { content: "\f110"; } .ion-battery-charging:before { content: "\f111"; } @@ -237,6 +353,8 @@ .ion-bookmark:before { content: "\f26b"; } +.ion-bowtie:before { content: "\f3c0"; } + .ion-briefcase:before { content: "\f26c"; } .ion-bug:before { content: "\f2be"; } @@ -307,6 +425,8 @@ .ion-contrast:before { content: "\f275"; } +.ion-crop:before { content: "\f3c1"; } + .ion-cube:before { content: "\f318"; } .ion-disc:before { content: "\f12d"; } @@ -319,6 +439,8 @@ .ion-earth:before { content: "\f276"; } +.ion-easel:before { content: "\f3c2"; } + .ion-edit:before { content: "\f2bf"; } .ion-egg:before { content: "\f277"; } @@ -327,6 +449,12 @@ .ion-email:before { content: "\f132"; } +.ion-email-unread:before { content: "\f3c3"; } + +.ion-erlenmeyer-flask:before { content: "\f3c5"; } + +.ion-erlenmeyer-flask-bubbles:before { content: "\f3c4"; } + .ion-eye:before { content: "\f133"; } .ion-eye-disabled:before { content: "\f306"; } @@ -347,8 +475,6 @@ .ion-flash-off:before { content: "\f136"; } -.ion-flask:before { content: "\f138"; } - .ion-folder:before { content: "\f139"; } .ion-fork:before { content: "\f27a"; } @@ -359,10 +485,6 @@ .ion-funnel:before { content: "\f31b"; } -.ion-game-controller-a:before { content: "\f13b"; } - -.ion-game-controller-b:before { content: "\f13c"; } - .ion-gear-a:before { content: "\f13d"; } .ion-gear-b:before { content: "\f13e"; } @@ -373,6 +495,8 @@ .ion-happy:before { content: "\f31c"; } +.ion-happy-outline:before { content: "\f3c6"; } + .ion-headphone:before { content: "\f140"; } .ion-heart:before { content: "\f141"; } @@ -389,10 +513,6 @@ .ion-icecream:before { content: "\f27d"; } -.ion-icon-social-google-plus:before { content: "\f146"; } - -.ion-icon-social-google-plus-outline:before { content: "\f145"; } - .ion-image:before { content: "\f147"; } .ion-images:before { content: "\f148"; } @@ -403,479 +523,543 @@ .ion-ionic:before { content: "\f14b"; } -.ion-ios7-alarm:before { content: "\f14d"; } +.ion-ios-alarm:before { content: "\f3c8"; } + +.ion-ios-alarm-outline:before { content: "\f3c7"; } + +.ion-ios-albums:before { content: "\f3ca"; } + +.ion-ios-albums-outline:before { content: "\f3c9"; } + +.ion-ios-americanfootball:before { content: "\f3cc"; } + +.ion-ios-americanfootball-outline:before { content: "\f3cb"; } + +.ion-ios-analytics:before { content: "\f3ce"; } + +.ion-ios-analytics-outline:before { content: "\f3cd"; } + +.ion-ios-arrow-back:before { content: "\f3cf"; } + +.ion-ios-arrow-down:before { content: "\f3d0"; } + +.ion-ios-arrow-forward:before { content: "\f3d1"; } + +.ion-ios-arrow-left:before { content: "\f3d2"; } + +.ion-ios-arrow-right:before { content: "\f3d3"; } + +.ion-ios-arrow-thin-down:before { content: "\f3d4"; } + +.ion-ios-arrow-thin-left:before { content: "\f3d5"; } + +.ion-ios-arrow-thin-right:before { content: "\f3d6"; } + +.ion-ios-arrow-thin-up:before { content: "\f3d7"; } + +.ion-ios-arrow-up:before { content: "\f3d8"; } + +.ion-ios-at:before { content: "\f3da"; } + +.ion-ios-at-outline:before { content: "\f3d9"; } + +.ion-ios-barcode:before { content: "\f3dc"; } + +.ion-ios-barcode-outline:before { content: "\f3db"; } + +.ion-ios-baseball:before { content: "\f3de"; } + +.ion-ios-baseball-outline:before { content: "\f3dd"; } + +.ion-ios-basketball:before { content: "\f3e0"; } + +.ion-ios-basketball-outline:before { content: "\f3df"; } + +.ion-ios-bell:before { content: "\f3e2"; } + +.ion-ios-bell-outline:before { content: "\f3e1"; } + +.ion-ios-body:before { content: "\f3e4"; } + +.ion-ios-body-outline:before { content: "\f3e3"; } + +.ion-ios-bolt:before { content: "\f3e6"; } + +.ion-ios-bolt-outline:before { content: "\f3e5"; } -.ion-ios7-alarm-outline:before { content: "\f14c"; } +.ion-ios-book:before { content: "\f3e8"; } -.ion-ios7-albums:before { content: "\f14f"; } +.ion-ios-book-outline:before { content: "\f3e7"; } -.ion-ios7-albums-outline:before { content: "\f14e"; } +.ion-ios-bookmarks:before { content: "\f3ea"; } -.ion-ios7-americanfootball:before { content: "\f31f"; } +.ion-ios-bookmarks-outline:before { content: "\f3e9"; } -.ion-ios7-americanfootball-outline:before { content: "\f31e"; } +.ion-ios-box:before { content: "\f3ec"; } -.ion-ios7-analytics:before { content: "\f321"; } +.ion-ios-box-outline:before { content: "\f3eb"; } -.ion-ios7-analytics-outline:before { content: "\f320"; } +.ion-ios-briefcase:before { content: "\f3ee"; } -.ion-ios7-arrow-back:before { content: "\f150"; } +.ion-ios-briefcase-outline:before { content: "\f3ed"; } -.ion-ios7-arrow-down:before { content: "\f151"; } +.ion-ios-browsers:before { content: "\f3f0"; } -.ion-ios7-arrow-forward:before { content: "\f152"; } +.ion-ios-browsers-outline:before { content: "\f3ef"; } -.ion-ios7-arrow-left:before { content: "\f153"; } +.ion-ios-calculator:before { content: "\f3f2"; } -.ion-ios7-arrow-right:before { content: "\f154"; } +.ion-ios-calculator-outline:before { content: "\f3f1"; } -.ion-ios7-arrow-thin-down:before { content: "\f27e"; } +.ion-ios-calendar:before { content: "\f3f4"; } -.ion-ios7-arrow-thin-left:before { content: "\f27f"; } +.ion-ios-calendar-outline:before { content: "\f3f3"; } -.ion-ios7-arrow-thin-right:before { content: "\f280"; } +.ion-ios-camera:before { content: "\f3f6"; } -.ion-ios7-arrow-thin-up:before { content: "\f281"; } +.ion-ios-camera-outline:before { content: "\f3f5"; } -.ion-ios7-arrow-up:before { content: "\f155"; } +.ion-ios-cart:before { content: "\f3f8"; } -.ion-ios7-at:before { content: "\f157"; } +.ion-ios-cart-outline:before { content: "\f3f7"; } -.ion-ios7-at-outline:before { content: "\f156"; } +.ion-ios-chatboxes:before { content: "\f3fa"; } -.ion-ios7-barcode:before { content: "\f323"; } +.ion-ios-chatboxes-outline:before { content: "\f3f9"; } -.ion-ios7-barcode-outline:before { content: "\f322"; } +.ion-ios-chatbubble:before { content: "\f3fc"; } -.ion-ios7-baseball:before { content: "\f325"; } +.ion-ios-chatbubble-outline:before { content: "\f3fb"; } -.ion-ios7-baseball-outline:before { content: "\f324"; } +.ion-ios-checkmark:before { content: "\f3ff"; } -.ion-ios7-basketball:before { content: "\f327"; } +.ion-ios-checkmark-empty:before { content: "\f3fd"; } -.ion-ios7-basketball-outline:before { content: "\f326"; } +.ion-ios-checkmark-outline:before { content: "\f3fe"; } -.ion-ios7-bell:before { content: "\f159"; } +.ion-ios-circle-filled:before { content: "\f400"; } -.ion-ios7-bell-outline:before { content: "\f158"; } +.ion-ios-circle-outline:before { content: "\f401"; } -.ion-ios7-bolt:before { content: "\f15b"; } +.ion-ios-clock:before { content: "\f403"; } -.ion-ios7-bolt-outline:before { content: "\f15a"; } +.ion-ios-clock-outline:before { content: "\f402"; } -.ion-ios7-bookmarks:before { content: "\f15d"; } +.ion-ios-close:before { content: "\f406"; } -.ion-ios7-bookmarks-outline:before { content: "\f15c"; } +.ion-ios-close-empty:before { content: "\f404"; } -.ion-ios7-box:before { content: "\f15f"; } +.ion-ios-close-outline:before { content: "\f405"; } -.ion-ios7-box-outline:before { content: "\f15e"; } +.ion-ios-cloud:before { content: "\f40c"; } -.ion-ios7-briefcase:before { content: "\f283"; } +.ion-ios-cloud-download:before { content: "\f408"; } -.ion-ios7-briefcase-outline:before { content: "\f282"; } +.ion-ios-cloud-download-outline:before { content: "\f407"; } -.ion-ios7-browsers:before { content: "\f161"; } +.ion-ios-cloud-outline:before { content: "\f409"; } -.ion-ios7-browsers-outline:before { content: "\f160"; } +.ion-ios-cloud-upload:before { content: "\f40b"; } -.ion-ios7-calculator:before { content: "\f285"; } +.ion-ios-cloud-upload-outline:before { content: "\f40a"; } -.ion-ios7-calculator-outline:before { content: "\f284"; } +.ion-ios-cloudy:before { content: "\f410"; } -.ion-ios7-calendar:before { content: "\f163"; } +.ion-ios-cloudy-night:before { content: "\f40e"; } -.ion-ios7-calendar-outline:before { content: "\f162"; } +.ion-ios-cloudy-night-outline:before { content: "\f40d"; } -.ion-ios7-camera:before { content: "\f165"; } +.ion-ios-cloudy-outline:before { content: "\f40f"; } -.ion-ios7-camera-outline:before { content: "\f164"; } +.ion-ios-cog:before { content: "\f412"; } -.ion-ios7-cart:before { content: "\f167"; } +.ion-ios-cog-outline:before { content: "\f411"; } -.ion-ios7-cart-outline:before { content: "\f166"; } +.ion-ios-color-filter:before { content: "\f414"; } -.ion-ios7-chatboxes:before { content: "\f169"; } +.ion-ios-color-filter-outline:before { content: "\f413"; } -.ion-ios7-chatboxes-outline:before { content: "\f168"; } +.ion-ios-color-wand:before { content: "\f416"; } -.ion-ios7-chatbubble:before { content: "\f16b"; } +.ion-ios-color-wand-outline:before { content: "\f415"; } -.ion-ios7-chatbubble-outline:before { content: "\f16a"; } +.ion-ios-compose:before { content: "\f418"; } -.ion-ios7-checkmark:before { content: "\f16e"; } +.ion-ios-compose-outline:before { content: "\f417"; } -.ion-ios7-checkmark-empty:before { content: "\f16c"; } +.ion-ios-contact:before { content: "\f41a"; } -.ion-ios7-checkmark-outline:before { content: "\f16d"; } +.ion-ios-contact-outline:before { content: "\f419"; } -.ion-ios7-circle-filled:before { content: "\f16f"; } +.ion-ios-copy:before { content: "\f41c"; } -.ion-ios7-circle-outline:before { content: "\f170"; } +.ion-ios-copy-outline:before { content: "\f41b"; } -.ion-ios7-clock:before { content: "\f172"; } +.ion-ios-crop:before { content: "\f41e"; } -.ion-ios7-clock-outline:before { content: "\f171"; } +.ion-ios-crop-strong:before { content: "\f41d"; } -.ion-ios7-close:before { content: "\f2bc"; } +.ion-ios-download:before { content: "\f420"; } -.ion-ios7-close-empty:before { content: "\f2bd"; } +.ion-ios-download-outline:before { content: "\f41f"; } -.ion-ios7-close-outline:before { content: "\f2bb"; } +.ion-ios-drag:before { content: "\f421"; } -.ion-ios7-cloud:before { content: "\f178"; } +.ion-ios-email:before { content: "\f423"; } -.ion-ios7-cloud-download:before { content: "\f174"; } +.ion-ios-email-outline:before { content: "\f422"; } -.ion-ios7-cloud-download-outline:before { content: "\f173"; } +.ion-ios-eye:before { content: "\f425"; } -.ion-ios7-cloud-outline:before { content: "\f175"; } +.ion-ios-eye-outline:before { content: "\f424"; } -.ion-ios7-cloud-upload:before { content: "\f177"; } +.ion-ios-fastforward:before { content: "\f427"; } -.ion-ios7-cloud-upload-outline:before { content: "\f176"; } +.ion-ios-fastforward-outline:before { content: "\f426"; } -.ion-ios7-cloudy:before { content: "\f17a"; } +.ion-ios-filing:before { content: "\f429"; } -.ion-ios7-cloudy-night:before { content: "\f308"; } +.ion-ios-filing-outline:before { content: "\f428"; } -.ion-ios7-cloudy-night-outline:before { content: "\f307"; } +.ion-ios-film:before { content: "\f42b"; } -.ion-ios7-cloudy-outline:before { content: "\f179"; } +.ion-ios-film-outline:before { content: "\f42a"; } -.ion-ios7-cog:before { content: "\f17c"; } +.ion-ios-flag:before { content: "\f42d"; } -.ion-ios7-cog-outline:before { content: "\f17b"; } +.ion-ios-flag-outline:before { content: "\f42c"; } -.ion-ios7-compose:before { content: "\f17e"; } +.ion-ios-flame:before { content: "\f42f"; } -.ion-ios7-compose-outline:before { content: "\f17d"; } +.ion-ios-flame-outline:before { content: "\f42e"; } -.ion-ios7-contact:before { content: "\f180"; } +.ion-ios-flask:before { content: "\f431"; } -.ion-ios7-contact-outline:before { content: "\f17f"; } +.ion-ios-flask-outline:before { content: "\f430"; } -.ion-ios7-copy:before { content: "\f182"; } +.ion-ios-flower:before { content: "\f433"; } -.ion-ios7-copy-outline:before { content: "\f181"; } +.ion-ios-flower-outline:before { content: "\f432"; } -.ion-ios7-download:before { content: "\f184"; } +.ion-ios-folder:before { content: "\f435"; } -.ion-ios7-download-outline:before { content: "\f183"; } +.ion-ios-folder-outline:before { content: "\f434"; } -.ion-ios7-drag:before { content: "\f185"; } +.ion-ios-football:before { content: "\f437"; } -.ion-ios7-email:before { content: "\f187"; } +.ion-ios-football-outline:before { content: "\f436"; } -.ion-ios7-email-outline:before { content: "\f186"; } +.ion-ios-game-controller-a:before { content: "\f439"; } -.ion-ios7-expand:before { content: "\f30d"; } +.ion-ios-game-controller-a-outline:before { content: "\f438"; } -.ion-ios7-eye:before { content: "\f189"; } +.ion-ios-game-controller-b:before { content: "\f43b"; } -.ion-ios7-eye-outline:before { content: "\f188"; } +.ion-ios-game-controller-b-outline:before { content: "\f43a"; } -.ion-ios7-fastforward:before { content: "\f18b"; } +.ion-ios-gear:before { content: "\f43d"; } -.ion-ios7-fastforward-outline:before { content: "\f18a"; } +.ion-ios-gear-outline:before { content: "\f43c"; } -.ion-ios7-filing:before { content: "\f18d"; } +.ion-ios-glasses:before { content: "\f43f"; } -.ion-ios7-filing-outline:before { content: "\f18c"; } +.ion-ios-glasses-outline:before { content: "\f43e"; } -.ion-ios7-film:before { content: "\f18f"; } +.ion-ios-grid-view:before { content: "\f441"; } -.ion-ios7-film-outline:before { content: "\f18e"; } +.ion-ios-grid-view-outline:before { content: "\f440"; } -.ion-ios7-flag:before { content: "\f191"; } +.ion-ios-heart:before { content: "\f443"; } -.ion-ios7-flag-outline:before { content: "\f190"; } +.ion-ios-heart-outline:before { content: "\f442"; } -.ion-ios7-folder:before { content: "\f193"; } +.ion-ios-help:before { content: "\f446"; } -.ion-ios7-folder-outline:before { content: "\f192"; } +.ion-ios-help-empty:before { content: "\f444"; } -.ion-ios7-football:before { content: "\f329"; } +.ion-ios-help-outline:before { content: "\f445"; } -.ion-ios7-football-outline:before { content: "\f328"; } +.ion-ios-home:before { content: "\f448"; } -.ion-ios7-gear:before { content: "\f195"; } +.ion-ios-home-outline:before { content: "\f447"; } -.ion-ios7-gear-outline:before { content: "\f194"; } +.ion-ios-infinite:before { content: "\f44a"; } -.ion-ios7-glasses:before { content: "\f197"; } +.ion-ios-infinite-outline:before { content: "\f449"; } -.ion-ios7-glasses-outline:before { content: "\f196"; } +.ion-ios-information:before { content: "\f44d"; } -.ion-ios7-heart:before { content: "\f199"; } +.ion-ios-information-empty:before { content: "\f44b"; } -.ion-ios7-heart-outline:before { content: "\f198"; } +.ion-ios-information-outline:before { content: "\f44c"; } -.ion-ios7-help:before { content: "\f19c"; } +.ion-ios-ionic-outline:before { content: "\f44e"; } -.ion-ios7-help-empty:before { content: "\f19a"; } +.ion-ios-keypad:before { content: "\f450"; } -.ion-ios7-help-outline:before { content: "\f19b"; } +.ion-ios-keypad-outline:before { content: "\f44f"; } -.ion-ios7-home:before { content: "\f32b"; } +.ion-ios-lightbulb:before { content: "\f452"; } -.ion-ios7-home-outline:before { content: "\f32a"; } +.ion-ios-lightbulb-outline:before { content: "\f451"; } -.ion-ios7-infinite:before { content: "\f19e"; } +.ion-ios-list:before { content: "\f454"; } -.ion-ios7-infinite-outline:before { content: "\f19d"; } +.ion-ios-list-outline:before { content: "\f453"; } -.ion-ios7-information:before { content: "\f1a1"; } +.ion-ios-location:before { content: "\f456"; } -.ion-ios7-information-empty:before { content: "\f19f"; } +.ion-ios-location-outline:before { content: "\f455"; } -.ion-ios7-information-outline:before { content: "\f1a0"; } +.ion-ios-locked:before { content: "\f458"; } -.ion-ios7-ionic-outline:before { content: "\f1a2"; } +.ion-ios-locked-outline:before { content: "\f457"; } -.ion-ios7-keypad:before { content: "\f1a4"; } +.ion-ios-loop:before { content: "\f45a"; } -.ion-ios7-keypad-outline:before { content: "\f1a3"; } +.ion-ios-loop-strong:before { content: "\f459"; } -.ion-ios7-lightbulb:before { content: "\f287"; } +.ion-ios-medical:before { content: "\f45c"; } -.ion-ios7-lightbulb-outline:before { content: "\f286"; } +.ion-ios-medical-outline:before { content: "\f45b"; } -.ion-ios7-location:before { content: "\f1a6"; } +.ion-ios-medkit:before { content: "\f45e"; } -.ion-ios7-location-outline:before { content: "\f1a5"; } +.ion-ios-medkit-outline:before { content: "\f45d"; } -.ion-ios7-locked:before { content: "\f1a8"; } +.ion-ios-mic:before { content: "\f461"; } -.ion-ios7-locked-outline:before { content: "\f1a7"; } +.ion-ios-mic-off:before { content: "\f45f"; } -.ion-ios7-loop:before { content: "\f32d"; } +.ion-ios-mic-outline:before { content: "\f460"; } -.ion-ios7-loop-strong:before { content: "\f32c"; } +.ion-ios-minus:before { content: "\f464"; } -.ion-ios7-medkit:before { content: "\f289"; } +.ion-ios-minus-empty:before { content: "\f462"; } -.ion-ios7-medkit-outline:before { content: "\f288"; } +.ion-ios-minus-outline:before { content: "\f463"; } -.ion-ios7-mic:before { content: "\f1ab"; } +.ion-ios-monitor:before { content: "\f466"; } -.ion-ios7-mic-off:before { content: "\f1a9"; } +.ion-ios-monitor-outline:before { content: "\f465"; } -.ion-ios7-mic-outline:before { content: "\f1aa"; } +.ion-ios-moon:before { content: "\f468"; } -.ion-ios7-minus:before { content: "\f1ae"; } +.ion-ios-moon-outline:before { content: "\f467"; } -.ion-ios7-minus-empty:before { content: "\f1ac"; } +.ion-ios-more:before { content: "\f46a"; } -.ion-ios7-minus-outline:before { content: "\f1ad"; } +.ion-ios-more-outline:before { content: "\f469"; } -.ion-ios7-monitor:before { content: "\f1b0"; } +.ion-ios-musical-note:before { content: "\f46b"; } -.ion-ios7-monitor-outline:before { content: "\f1af"; } +.ion-ios-musical-notes:before { content: "\f46c"; } -.ion-ios7-moon:before { content: "\f1b2"; } +.ion-ios-navigate:before { content: "\f46e"; } -.ion-ios7-moon-outline:before { content: "\f1b1"; } +.ion-ios-navigate-outline:before { content: "\f46d"; } -.ion-ios7-more:before { content: "\f1b4"; } +.ion-ios-nutrition:before { content: "\f470"; } -.ion-ios7-more-outline:before { content: "\f1b3"; } +.ion-ios-nutrition-outline:before { content: "\f46f"; } -.ion-ios7-musical-note:before { content: "\f1b5"; } +.ion-ios-paper:before { content: "\f472"; } -.ion-ios7-musical-notes:before { content: "\f1b6"; } +.ion-ios-paper-outline:before { content: "\f471"; } -.ion-ios7-navigate:before { content: "\f1b8"; } +.ion-ios-paperplane:before { content: "\f474"; } -.ion-ios7-navigate-outline:before { content: "\f1b7"; } +.ion-ios-paperplane-outline:before { content: "\f473"; } -.ion-ios7-paper:before { content: "\f32f"; } +.ion-ios-partlysunny:before { content: "\f476"; } -.ion-ios7-paper-outline:before { content: "\f32e"; } +.ion-ios-partlysunny-outline:before { content: "\f475"; } -.ion-ios7-paperplane:before { content: "\f1ba"; } +.ion-ios-pause:before { content: "\f478"; } -.ion-ios7-paperplane-outline:before { content: "\f1b9"; } +.ion-ios-pause-outline:before { content: "\f477"; } -.ion-ios7-partlysunny:before { content: "\f1bc"; } +.ion-ios-paw:before { content: "\f47a"; } -.ion-ios7-partlysunny-outline:before { content: "\f1bb"; } +.ion-ios-paw-outline:before { content: "\f479"; } -.ion-ios7-pause:before { content: "\f1be"; } +.ion-ios-people:before { content: "\f47c"; } -.ion-ios7-pause-outline:before { content: "\f1bd"; } +.ion-ios-people-outline:before { content: "\f47b"; } -.ion-ios7-paw:before { content: "\f331"; } +.ion-ios-person:before { content: "\f47e"; } -.ion-ios7-paw-outline:before { content: "\f330"; } +.ion-ios-person-outline:before { content: "\f47d"; } -.ion-ios7-people:before { content: "\f1c0"; } +.ion-ios-personadd:before { content: "\f480"; } -.ion-ios7-people-outline:before { content: "\f1bf"; } +.ion-ios-personadd-outline:before { content: "\f47f"; } -.ion-ios7-person:before { content: "\f1c2"; } +.ion-ios-photos:before { content: "\f482"; } -.ion-ios7-person-outline:before { content: "\f1c1"; } +.ion-ios-photos-outline:before { content: "\f481"; } -.ion-ios7-personadd:before { content: "\f1c4"; } +.ion-ios-pie:before { content: "\f484"; } -.ion-ios7-personadd-outline:before { content: "\f1c3"; } +.ion-ios-pie-outline:before { content: "\f483"; } -.ion-ios7-photos:before { content: "\f1c6"; } +.ion-ios-pint:before { content: "\f486"; } -.ion-ios7-photos-outline:before { content: "\f1c5"; } +.ion-ios-pint-outline:before { content: "\f485"; } -.ion-ios7-pie:before { content: "\f28b"; } +.ion-ios-play:before { content: "\f488"; } -.ion-ios7-pie-outline:before { content: "\f28a"; } +.ion-ios-play-outline:before { content: "\f487"; } -.ion-ios7-play:before { content: "\f1c8"; } +.ion-ios-plus:before { content: "\f48b"; } -.ion-ios7-play-outline:before { content: "\f1c7"; } +.ion-ios-plus-empty:before { content: "\f489"; } -.ion-ios7-plus:before { content: "\f1cb"; } +.ion-ios-plus-outline:before { content: "\f48a"; } -.ion-ios7-plus-empty:before { content: "\f1c9"; } +.ion-ios-pricetag:before { content: "\f48d"; } -.ion-ios7-plus-outline:before { content: "\f1ca"; } +.ion-ios-pricetag-outline:before { content: "\f48c"; } -.ion-ios7-pricetag:before { content: "\f28d"; } +.ion-ios-pricetags:before { content: "\f48f"; } -.ion-ios7-pricetag-outline:before { content: "\f28c"; } +.ion-ios-pricetags-outline:before { content: "\f48e"; } -.ion-ios7-pricetags:before { content: "\f333"; } +.ion-ios-printer:before { content: "\f491"; } -.ion-ios7-pricetags-outline:before { content: "\f332"; } +.ion-ios-printer-outline:before { content: "\f490"; } -.ion-ios7-printer:before { content: "\f1cd"; } +.ion-ios-pulse:before { content: "\f493"; } -.ion-ios7-printer-outline:before { content: "\f1cc"; } +.ion-ios-pulse-strong:before { content: "\f492"; } -.ion-ios7-pulse:before { content: "\f335"; } +.ion-ios-rainy:before { content: "\f495"; } -.ion-ios7-pulse-strong:before { content: "\f334"; } +.ion-ios-rainy-outline:before { content: "\f494"; } -.ion-ios7-rainy:before { content: "\f1cf"; } +.ion-ios-recording:before { content: "\f497"; } -.ion-ios7-rainy-outline:before { content: "\f1ce"; } +.ion-ios-recording-outline:before { content: "\f496"; } -.ion-ios7-recording:before { content: "\f1d1"; } +.ion-ios-redo:before { content: "\f499"; } -.ion-ios7-recording-outline:before { content: "\f1d0"; } +.ion-ios-redo-outline:before { content: "\f498"; } -.ion-ios7-redo:before { content: "\f1d3"; } +.ion-ios-refresh:before { content: "\f49c"; } -.ion-ios7-redo-outline:before { content: "\f1d2"; } +.ion-ios-refresh-empty:before { content: "\f49a"; } -.ion-ios7-refresh:before { content: "\f1d6"; } +.ion-ios-refresh-outline:before { content: "\f49b"; } -.ion-ios7-refresh-empty:before { content: "\f1d4"; } +.ion-ios-reload:before { content: "\f49d"; } -.ion-ios7-refresh-outline:before { content: "\f1d5"; } +.ion-ios-reverse-camera:before { content: "\f49f"; } -.ion-ios7-reload:before, .ion-ios7-reloading:before { content: "\f28e"; } +.ion-ios-reverse-camera-outline:before { content: "\f49e"; } -.ion-ios7-reverse-camera:before { content: "\f337"; } +.ion-ios-rewind:before { content: "\f4a1"; } -.ion-ios7-reverse-camera-outline:before { content: "\f336"; } +.ion-ios-rewind-outline:before { content: "\f4a0"; } -.ion-ios7-rewind:before { content: "\f1d8"; } +.ion-ios-rose:before { content: "\f4a3"; } -.ion-ios7-rewind-outline:before { content: "\f1d7"; } +.ion-ios-rose-outline:before { content: "\f4a2"; } -.ion-ios7-search:before { content: "\f1da"; } +.ion-ios-search:before { content: "\f4a5"; } -.ion-ios7-search-strong:before { content: "\f1d9"; } +.ion-ios-search-strong:before { content: "\f4a4"; } -.ion-ios7-settings:before { content: "\f339"; } +.ion-ios-settings:before { content: "\f4a7"; } -.ion-ios7-settings-strong:before { content: "\f338"; } +.ion-ios-settings-strong:before { content: "\f4a6"; } -.ion-ios7-shrink:before { content: "\f30e"; } +.ion-ios-shuffle:before { content: "\f4a9"; } -.ion-ios7-skipbackward:before { content: "\f1dc"; } +.ion-ios-shuffle-strong:before { content: "\f4a8"; } -.ion-ios7-skipbackward-outline:before { content: "\f1db"; } +.ion-ios-skipbackward:before { content: "\f4ab"; } -.ion-ios7-skipforward:before { content: "\f1de"; } +.ion-ios-skipbackward-outline:before { content: "\f4aa"; } -.ion-ios7-skipforward-outline:before { content: "\f1dd"; } +.ion-ios-skipforward:before { content: "\f4ad"; } -.ion-ios7-snowy:before { content: "\f309"; } +.ion-ios-skipforward-outline:before { content: "\f4ac"; } -.ion-ios7-speedometer:before { content: "\f290"; } +.ion-ios-snowy:before { content: "\f4ae"; } -.ion-ios7-speedometer-outline:before { content: "\f28f"; } +.ion-ios-speedometer:before { content: "\f4b0"; } -.ion-ios7-star:before { content: "\f1e0"; } +.ion-ios-speedometer-outline:before { content: "\f4af"; } -.ion-ios7-star-half:before { content: "\f33a"; } +.ion-ios-star:before { content: "\f4b3"; } -.ion-ios7-star-outline:before { content: "\f1df"; } +.ion-ios-star-half:before { content: "\f4b1"; } -.ion-ios7-stopwatch:before { content: "\f1e2"; } +.ion-ios-star-outline:before { content: "\f4b2"; } -.ion-ios7-stopwatch-outline:before { content: "\f1e1"; } +.ion-ios-stopwatch:before { content: "\f4b5"; } -.ion-ios7-sunny:before { content: "\f1e4"; } +.ion-ios-stopwatch-outline:before { content: "\f4b4"; } -.ion-ios7-sunny-outline:before { content: "\f1e3"; } +.ion-ios-sunny:before { content: "\f4b7"; } -.ion-ios7-telephone:before { content: "\f1e6"; } +.ion-ios-sunny-outline:before { content: "\f4b6"; } -.ion-ios7-telephone-outline:before { content: "\f1e5"; } +.ion-ios-telephone:before { content: "\f4b9"; } -.ion-ios7-tennisball:before { content: "\f33c"; } +.ion-ios-telephone-outline:before { content: "\f4b8"; } -.ion-ios7-tennisball-outline:before { content: "\f33b"; } +.ion-ios-tennisball:before { content: "\f4bb"; } -.ion-ios7-thunderstorm:before { content: "\f1e8"; } +.ion-ios-tennisball-outline:before { content: "\f4ba"; } -.ion-ios7-thunderstorm-outline:before { content: "\f1e7"; } +.ion-ios-thunderstorm:before { content: "\f4bd"; } -.ion-ios7-time:before { content: "\f292"; } +.ion-ios-thunderstorm-outline:before { content: "\f4bc"; } -.ion-ios7-time-outline:before { content: "\f291"; } +.ion-ios-time:before { content: "\f4bf"; } -.ion-ios7-timer:before { content: "\f1ea"; } +.ion-ios-time-outline:before { content: "\f4be"; } -.ion-ios7-timer-outline:before { content: "\f1e9"; } +.ion-ios-timer:before { content: "\f4c1"; } -.ion-ios7-toggle:before { content: "\f33e"; } +.ion-ios-timer-outline:before { content: "\f4c0"; } -.ion-ios7-toggle-outline:before { content: "\f33d"; } +.ion-ios-toggle:before { content: "\f4c3"; } -.ion-ios7-trash:before { content: "\f1ec"; } +.ion-ios-toggle-outline:before { content: "\f4c2"; } -.ion-ios7-trash-outline:before { content: "\f1eb"; } +.ion-ios-trash:before { content: "\f4c5"; } -.ion-ios7-undo:before { content: "\f1ee"; } +.ion-ios-trash-outline:before { content: "\f4c4"; } -.ion-ios7-undo-outline:before { content: "\f1ed"; } +.ion-ios-undo:before { content: "\f4c7"; } -.ion-ios7-unlocked:before { content: "\f1f0"; } +.ion-ios-undo-outline:before { content: "\f4c6"; } -.ion-ios7-unlocked-outline:before { content: "\f1ef"; } +.ion-ios-unlocked:before { content: "\f4c9"; } -.ion-ios7-upload:before { content: "\f1f2"; } +.ion-ios-unlocked-outline:before { content: "\f4c8"; } -.ion-ios7-upload-outline:before { content: "\f1f1"; } +.ion-ios-upload:before { content: "\f4cb"; } -.ion-ios7-videocam:before { content: "\f1f4"; } +.ion-ios-upload-outline:before { content: "\f4ca"; } -.ion-ios7-videocam-outline:before { content: "\f1f3"; } +.ion-ios-videocam:before { content: "\f4cd"; } -.ion-ios7-volume-high:before { content: "\f1f5"; } +.ion-ios-videocam-outline:before { content: "\f4cc"; } -.ion-ios7-volume-low:before { content: "\f1f6"; } +.ion-ios-volume-high:before { content: "\f4ce"; } -.ion-ios7-wineglass:before { content: "\f294"; } +.ion-ios-volume-low:before { content: "\f4cf"; } -.ion-ios7-wineglass-outline:before { content: "\f293"; } +.ion-ios-wineglass:before { content: "\f4d1"; } -.ion-ios7-world:before { content: "\f1f8"; } +.ion-ios-wineglass-outline:before { content: "\f4d0"; } -.ion-ios7-world-outline:before { content: "\f1f7"; } +.ion-ios-world:before { content: "\f4d3"; } + +.ion-ios-world-outline:before { content: "\f4d2"; } .ion-ipad:before { content: "\f1f9"; } @@ -899,23 +1083,25 @@ .ion-link:before { content: "\f1fe"; } -.ion-load-a:before, .ion-loading-a:before { content: "\f29a"; } +.ion-load-a:before { content: "\f29a"; } -.ion-load-b:before, .ion-loading-b:before { content: "\f29b"; } +.ion-load-b:before { content: "\f29b"; } -.ion-load-c:before, .ion-loading-c:before { content: "\f29c"; } +.ion-load-c:before { content: "\f29c"; } -.ion-load-d:before, .ion-loading-d:before { content: "\f29d"; } +.ion-load-d:before { content: "\f29d"; } .ion-location:before { content: "\f1ff"; } +.ion-lock-combination:before { content: "\f4d4"; } + .ion-locked:before { content: "\f200"; } .ion-log-in:before { content: "\f29e"; } .ion-log-out:before { content: "\f29f"; } -.ion-loop:before, .ion-looping:before { content: "\f201"; } +.ion-loop:before { content: "\f201"; } .ion-magnet:before { content: "\f2a0"; } @@ -965,6 +1151,10 @@ .ion-outlet:before { content: "\f342"; } +.ion-paintbrush:before { content: "\f4d5"; } + +.ion-paintbucket:before { content: "\f4d6"; } + .ion-paper-airplane:before { content: "\f2c3"; } .ion-paperclip:before { content: "\f20f"; } @@ -1021,7 +1211,7 @@ .ion-record:before { content: "\f21b"; } -.ion-refresh:before, .ion-refreshing:before { content: "\f21c"; } +.ion-refresh:before { content: "\f21c"; } .ion-reply:before { content: "\f21e"; } @@ -1033,6 +1223,8 @@ .ion-sad:before { content: "\f34a"; } +.ion-sad-outline:before { content: "\f4d7"; } + .ion-scissors:before { content: "\f34b"; } .ion-search:before { content: "\f21f"; } @@ -1051,6 +1243,10 @@ .ion-social-android-outline:before { content: "\f224"; } +.ion-social-angular:before { content: "\f4d9"; } + +.ion-social-angular-outline:before { content: "\f4d8"; } + .ion-social-apple:before { content: "\f227"; } .ion-social-apple-outline:before { content: "\f226"; } @@ -1063,6 +1259,18 @@ .ion-social-buffer-outline:before { content: "\f228"; } +.ion-social-chrome:before { content: "\f4db"; } + +.ion-social-chrome-outline:before { content: "\f4da"; } + +.ion-social-codepen:before { content: "\f4dd"; } + +.ion-social-codepen-outline:before { content: "\f4dc"; } + +.ion-social-css3:before { content: "\f4df"; } + +.ion-social-css3-outline:before { content: "\f4de"; } + .ion-social-designernews:before { content: "\f22b"; } .ion-social-designernews-outline:before { content: "\f22a"; } @@ -1075,6 +1283,10 @@ .ion-social-dropbox-outline:before { content: "\f22e"; } +.ion-social-euro:before { content: "\f4e1"; } + +.ion-social-euro-outline:before { content: "\f4e0"; } + .ion-social-facebook:before { content: "\f231"; } .ion-social-facebook-outline:before { content: "\f230"; } @@ -1101,18 +1313,34 @@ .ion-social-hackernews-outline:before { content: "\f236"; } +.ion-social-html5:before { content: "\f4e3"; } + +.ion-social-html5-outline:before { content: "\f4e2"; } + .ion-social-instagram:before { content: "\f351"; } .ion-social-instagram-outline:before { content: "\f350"; } +.ion-social-javascript:before { content: "\f4e5"; } + +.ion-social-javascript-outline:before { content: "\f4e4"; } + .ion-social-linkedin:before { content: "\f239"; } .ion-social-linkedin-outline:before { content: "\f238"; } +.ion-social-markdown:before { content: "\f4e6"; } + +.ion-social-nodejs:before { content: "\f4e7"; } + +.ion-social-octocat:before { content: "\f4e8"; } + .ion-social-pinterest:before { content: "\f2b1"; } .ion-social-pinterest-outline:before { content: "\f2b0"; } +.ion-social-python:before { content: "\f4e9"; } + .ion-social-reddit:before { content: "\f23b"; } .ion-social-reddit-outline:before { content: "\f23a"; } @@ -1121,16 +1349,26 @@ .ion-social-rss-outline:before { content: "\f23c"; } +.ion-social-sass:before { content: "\f4ea"; } + .ion-social-skype:before { content: "\f23f"; } .ion-social-skype-outline:before { content: "\f23e"; } +.ion-social-snapchat:before { content: "\f4ec"; } + +.ion-social-snapchat-outline:before { content: "\f4eb"; } + .ion-social-tumblr:before { content: "\f241"; } .ion-social-tumblr-outline:before { content: "\f240"; } .ion-social-tux:before { content: "\f2c5"; } +.ion-social-twitch:before { content: "\f4ee"; } + +.ion-social-twitch-outline:before { content: "\f4ed"; } + .ion-social-twitter:before { content: "\f243"; } .ion-social-twitter-outline:before { content: "\f242"; } @@ -1143,6 +1381,10 @@ .ion-social-vimeo-outline:before { content: "\f244"; } +.ion-social-whatsapp:before { content: "\f4f0"; } + +.ion-social-whatsapp-outline:before { content: "\f4ef"; } + .ion-social-windows:before { content: "\f247"; } .ion-social-windows-outline:before { content: "\f246"; } @@ -1155,10 +1397,18 @@ .ion-social-yahoo-outline:before { content: "\f24a"; } +.ion-social-yen:before { content: "\f4f2"; } + +.ion-social-yen-outline:before { content: "\f4f1"; } + .ion-social-youtube:before { content: "\f24d"; } .ion-social-youtube-outline:before { content: "\f24c"; } +.ion-soup-can:before { content: "\f4f4"; } + +.ion-soup-can-outline:before { content: "\f4f3"; } + .ion-speakerphone:before { content: "\f2b2"; } .ion-speedometer:before { content: "\f2b3"; } @@ -1183,12 +1433,18 @@ .ion-toggle-filled:before { content: "\f354"; } +.ion-transgender:before { content: "\f4f5"; } + .ion-trash-a:before { content: "\f252"; } .ion-trash-b:before { content: "\f253"; } .ion-trophy:before { content: "\f356"; } +.ion-tshirt:before { content: "\f4f7"; } + +.ion-tshirt-outline:before { content: "\f4f6"; } + .ion-umbrella:before { content: "\f2b7"; } .ion-university:before { content: "\f357"; } diff --git a/public/assets/stylesheets/staff.css b/public/assets/stylesheets/staff.css index de31571..7ae4a1e 100644 --- a/public/assets/stylesheets/staff.css +++ b/public/assets/stylesheets/staff.css @@ -30,6 +30,23 @@ nav { nav a { margin-left: 10px; } +nav.subnav { + background: white; + padding: 10px; + font-weight: 200; + font-size: 12px; +} +.alphabet a { + margin-left: 5px; +} +.body .error { + color: #f00; + border: 1px solid #f00; + margin: 20px 5px 200px 5px; + padding: 10px; + width: 400px; + display: block; +} hr { border: 1px solid #bbb; margin: 10px auto 10px; @@ -62,15 +79,36 @@ hr { user-select: none; } .staff { + background: white; font-size: 15px; } +.staff hr { + border: 1px solid black; + border-top: 0; +} .staff .body a { border-bottom: 1px dotted; } -.staff .editLinks a { +.staff .editLinks a, .staff a.bluelink { color: #00f; border-bottom: 1px solid; } +.staff form { + max-width: none; + width: 600px; + padding: 20px; +} +.staff form label { + float: none; +} +.staff form p { + width: 350px; + margin: 5px 0; + color: #444; +} +.staff form div li { + width: 180px; +} #iframe-embed, #iframe-embed tr, #iframe-embed td { width: 79vw; } diff --git a/public/assets/test/bg.html b/public/assets/test/bg.html index fecf811..65dd5d9 100644 --- a/public/assets/test/bg.html +++ b/public/assets/test/bg.html @@ -5,6 +5,7 @@ <div id="cursor" style="width:30px;height:30px;background:blue;display:inline-block;"></div> </div> <script src="/assets/javascripts/util.js"></script> +<script src="/assets/javascripts/vendor/bower_components/hidpi-canvas/dist/hidpi-canvas.js"></script> <script src="/assets/javascripts/vendor/tube.js"></script> <script src="/assets/javascripts/vendor/loader.js"></script> <script src="/assets/javascripts/rectangles/util/constants.js"></script> diff --git a/public/assets/test/intersect.html b/public/assets/test/intersect.html index 4e5b0bb..92f1d5d 100644 --- a/public/assets/test/intersect.html +++ b/public/assets/test/intersect.html @@ -2,6 +2,7 @@ <div id="hud"></div> <script src="/assets/javascripts/util.js"></script> +<script src="/assets/javascripts/vendor/bower_components/hidpi-canvas/dist/hidpi-canvas.js"></script> <script src="/assets/javascripts/vendor/tube.js"></script> <script src="/assets/javascripts/rectangles/util/constants.js"></script> <script src="/assets/javascripts/rectangles/util/mouse.js"></script> @@ -10,11 +11,11 @@ <script src="/assets/javascripts/vendor/canvasutilities.js"></script> <script> -var ctx = canvas.getContext('2d') - var w = canvas.width = 600 var h = canvas.height = 400 +var ctx = canvas.getContext('2d') + var vec_a = new Rect( 100, 120, 50, 100 ) var vec_b = new Rect( 20, 200, 120, 120 ) var vecs = [ vec_a, vec_b ] diff --git a/public/assets/test/intersect2.html b/public/assets/test/intersect2.html index 3df9f30..553e2f7 100644 --- a/public/assets/test/intersect2.html +++ b/public/assets/test/intersect2.html @@ -6,9 +6,11 @@ body,html{margin:0;padding:0;} <div id="hud"></div> <script src="/assets/javascripts/util.js"></script> -<script src="/assets/javascripts/vendor/tube.js"></script> <script src="/assets/javascripts/vendor/bower_components/jquery/dist/jquery.min.js"></script> -<script src="/assets/javascripts/vendor/bower_components/lodash/dist/lodash.min.js"></script> +<script src="/assets/javascripts/vendor/bower_components/lodash/lodash.min.js"></script> +<script src="/assets/javascripts/vendor/bower_components/hidpi-canvas/dist/hidpi-canvas.js"></script> +<script src="/assets/javascripts/vendor/polyfill.js"></script> +<script src="/assets/javascripts/vendor/tube.js"></script> <script src="/assets/javascripts/mx/mx.js"></script> <script src="/assets/javascripts/mx/extensions/mx.scene.js"></script> <script src="/assets/javascripts/rectangles/util/constants.js"></script> @@ -29,12 +31,12 @@ body,html{margin:0;padding:0;} <script src="/assets/javascripts/vendor/canvasutilities.js"></script> <script> -var ctx = canvas.getContext('2d') -var scene = new MX.Scene() - var w = canvas.width = window.innerWidth var h = canvas.height = window.innerHeight +var ctx = canvas.getContext('2d') +var scene = new MX.Scene() + var cursor = new Rect( 150, 250, 150, 250 ) var wall_vec = new Rect ( 0, 0, 0, 0 ) var points = [ cursor.x, cursor.y ] diff --git a/public/assets/test/intersect3.html b/public/assets/test/intersect3.html index 5440a76..b8f9a0d 100644 --- a/public/assets/test/intersect3.html +++ b/public/assets/test/intersect3.html @@ -6,9 +6,11 @@ body,html{margin:0;padding:0;} <div id="hud"></div> <script src="/assets/javascripts/util.js"></script> -<script src="/assets/javascripts/vendor/tube.js"></script> <script src="/assets/javascripts/vendor/bower_components/jquery/dist/jquery.min.js"></script> -<script src="/assets/javascripts/vendor/bower_components/lodash/dist/lodash.min.js"></script> +<script src="/assets/javascripts/vendor/bower_components/lodash/lodash.min.js"></script> +<script src="/assets/javascripts/vendor/bower_components/hidpi-canvas/dist/hidpi-canvas.js"></script> +<script src="/assets/javascripts/vendor/polyfill.js"></script> +<script src="/assets/javascripts/vendor/tube.js"></script> <script src="/assets/javascripts/mx/mx.js"></script> <script src="/assets/javascripts/mx/extensions/mx.scene.js"></script> <script src="/assets/javascripts/rectangles/util/constants.js"></script> @@ -29,12 +31,12 @@ body,html{margin:0;padding:0;} <script src="/assets/javascripts/vendor/canvasutilities.js"></script> <script> -var ctx = canvas.getContext('2d') -var scene = new MX.Scene() - var w = canvas.width = window.innerWidth var h = canvas.height = window.innerHeight +var ctx = canvas.getContext('2d') +var scene = new MX.Scene() + var cursor = new Rect( new vec2(400, 200), new vec2(800, 500) ) var wall_vec = new Rect ( 0, 0, 0, 0 ) var points = [ cursor.x, cursor.y ] diff --git a/public/assets/test/orbit.html b/public/assets/test/orbit.html new file mode 100644 index 0000000..0416ff7 --- /dev/null +++ b/public/assets/test/orbit.html @@ -0,0 +1,154 @@ +<style type="text/css"> +html,body{width:100%;height:100%;margin:0;padding:0;} +body { + font-family: Menlo, monospace; + overflow: hidden; +} +#perspective { + position: absolute; + left:0%; + top:0px +} +#orthographic { + position: absolute; + left:50%; + top:0px +} +#hud { + white-space: pre; +} +</style> + +<div id="perspective"></div> +<div id="orthographic"></div> + +<div id="hud"></div> + +<script src="/assets/javascripts/util.js"></script> +<script src="/assets/javascripts/vendor/bower_components/jquery/dist/jquery.min.js"></script> +<script src="/assets/javascripts/vendor/bower_components/lodash/lodash.min.js"></script> +<script src="/assets/javascripts/vendor/bower_components/hidpi-canvas/dist/hidpi-canvas.js"></script> +<script src="/assets/javascripts/vendor/polyfill.js"></script> +<script src="/assets/javascripts/vendor/tube.js"></script> +<script src="/assets/javascripts/mx/mx.js"></script> +<script src="/assets/javascripts/mx/extensions/mx.scene.js"></script> +<script src="/assets/javascripts/mx/extensions/mx.orbitCamera.js"></script> +<script src="/assets/javascripts/rectangles/util/constants.js"></script> +<script src="/assets/javascripts/rectangles/util/mouse.js"></script> +<script src="/assets/javascripts/rectangles/util/wheel.js"></script> +<script src="/assets/javascripts/rectangles/models/vec2.js"></script> +<script src="/assets/javascripts/rectangles/models/rect.js"></script> +<script src="/assets/javascripts/rectangles/models/rect.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/_map.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/draw.js"></script> + +<script> + +Map.UI = Map.UI || {} +Map.UI.Ortho = function(map){ + + var base = this + + base.creating = base.dragging = base.resizing = false + + base.mouse = new mouse({ + el: map.el, + move: function(e, cursor){ + cursor.x.div(map.dimensions.a).add(0.5).mul(map.dimensions.a / map.zoom).add(map.center.a) + cursor.y.div(map.dimensions.b).sub(0.5).mul(map.dimensions.b / map.zoom).sub(map.center.b) + }, + }) +} + +var scene, map, controls + +map = new Map ({ + type: "ortho", + el: document.querySelector("#orthographic"), + width: window.innerWidth/2, + height: window.innerHeight, +}) + +var ctx = map.draw.ctx + +document.addEventListener('DOMContentLoaded', build_circle) +function add_mx_point (p, theta, i) { + var mx = new MX.Object3D() + mx.updateChildren = false + mx.move({ + x: p.a, + y: i/2, + z: p.b, + rotationY: -theta, + width: 1, + height: i, + }) + mx.el.style.backgroundColor = 'rgb(' + [abs(floor(p.a*30)), 0, abs(floor(p.b*30))] + ')' + mx.el.style.backfaceVisibility = "visible" + scene.add(mx) + mx.update() +} +function add_center () { + var mx = new MX.Object3D() + mx.width = 79 + mx.height = 64 + mx.y = 32 * 0.05 + mx.scale = 0.05 + mx.el.style.backgroundImage = "url(http://i.asdf.us/im/b8/_1400215546_frankhats_1400215573_frankhats.gif)" + scene.add(mx) +} +function build_circle () { + scene = new MX.Scene().addTo("#perspective") + scene.camera.move({ + "x": 0, + "y": 0, + "z": 0, + "rotationX": 0, // PI/2, + "rotationY": PI/2, // PI + }) + scene.camera.radius = 20 + + scene.width = window.innerWidth/2 + scene.height = window.innerHeight + scene.perspective = window.innerHeight + + var theta, rad = 16; + for (var i = 0; i < 100; i++) { + theta = (i/100 * TWO_PI) + add_mx_point({ + a: sin(theta) * rad, + b: cos(theta) * rad, + }, theta, i) + } + + add_center() + + scene.update() + + controls = new MX.OrbitCamera({ el: document.querySelector("#perspective") }) + controls.init() + + console.log("ready..perhaps") + animate(0) +} +function animate(time){ + requestAnimationFrame(animate) + map.update(time) + + controls.update() + hud.innerHTML = scene.camera.toString() + scene.update() + + map.draw.ctx.save() + map.draw.translate() + + map.draw.coords() + ctx.strokeStyle = "#f00"; + map.draw.x_at(0,0) + map.draw.mouse(map.ui.mouse.cursor) + map.draw.camera(scene.camera) + + map.draw.ctx.restore() +} + +</script>
\ No newline at end of file diff --git a/public/assets/test/ortho.html b/public/assets/test/ortho.html new file mode 100644 index 0000000..2257006 --- /dev/null +++ b/public/assets/test/ortho.html @@ -0,0 +1,290 @@ +<style type="text/css"> +html,body{width:100%;height:100%;margin:0;padding:0;} +body { + font-family: Menlo, monospace; + overflow: hidden; +} +#perspective { + position: absolute; + left:0%; + top:0px +} +#orthographic { + position: absolute; + left:50%; + top:0px +} +#hud { + white-space: pre; +} +</style> + +<div id="perspective"></div> +<div id="orthographic"></div> + +<div id="hud"></div> + +<script src="/assets/javascripts/util.js"></script> +<script src="/assets/javascripts/vendor/bower_components/jquery/dist/jquery.min.js"></script> +<script src="/assets/javascripts/vendor/bower_components/lodash/lodash.min.js"></script> +<script src="/assets/javascripts/vendor/bower_components/hidpi-canvas/dist/hidpi-canvas.js"></script> +<script src="/assets/javascripts/vendor/polyfill.js"></script> +<script src="/assets/javascripts/vendor/tube.js"></script> +<script src="/assets/javascripts/mx/mx.js"></script> +<script src="/assets/javascripts/mx/extensions/mx.scene.js"></script> +<script src="/assets/javascripts/mx/extensions/mx.orbitCamera.js"></script> +<script src="/assets/javascripts/rectangles/util/constants.js"></script> +<script src="/assets/javascripts/rectangles/util/mouse.js"></script> +<script src="/assets/javascripts/rectangles/util/wheel.js"></script> +<script src="/assets/javascripts/rectangles/models/vec2.js"></script> +<script src="/assets/javascripts/rectangles/models/rect.js"></script> +<script src="/assets/javascripts/rectangles/models/rect.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/_map.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/draw.js"></script> + +<script> + +Map.UI = Map.UI || {} +Map.UI.Ortho = function(map){ + + var base = this + + base.creating = base.dragging = base.resizing = false + + base.mouse = new mouse({ + el: map.el, + down: function(e, cursor){ + cursor.x.div(map.dimensions.a).add(0.5).mul(map.dimensions.a / map.zoom).add(map.center.a) + cursor.y.div(map.dimensions.b).sub(0.5).mul(map.dimensions.b / map.zoom).sub(map.center.b) + // compare to initial point + var p = new vec2( cursor.x.a, cursor.y.a ) + if (placing) { + if (points.length > 2 && points[0].distanceTo( p ) < 10/map.zoom) { + points.push( points[0].clone() ) + placing = false + add_mx_polyline(points) + } + else { + points.push( p ) + mx_points.push( add_mx_point(p) ) + } + } + else { + placing = true + points = [] + points.push( p ) + mx_points.push( add_mx_point(p) ) + } + }, + move: function(e, cursor){ + cursor.x.div(map.dimensions.a).add(0.5).mul(map.dimensions.a / map.zoom).add(map.center.a) + cursor.y.div(map.dimensions.b).sub(0.5).mul(map.dimensions.b / map.zoom).sub(map.center.b) + last_point = new vec2( cursor.x.a, cursor.y.a ) + if (placing && points.length > 1 && points[0].distanceTo( last_point ) < 10/map.zoom) { + document.body.style.cursor = "pointer" + last_point.assign(points[0]) + cursor.x.a = cursor.x.b = last_point.a + cursor.y.a = cursor.y.b =last_point.b + } + else { + document.body.style.cursor = "crosshair" + } + }, + drag: function(e, cursor){ + cursor.x.b = ((cursor.x.b/map.dimensions.a)+0.5) * map.dimensions.a / map.zoom + map.center.a + cursor.y.b = ((cursor.y.b/map.dimensions.b)-0.5) * map.dimensions.b / map.zoom - map.center.b + }, + up: function(e, cursor, new_cursor){ + new_cursor.x.div(map.dimensions.a).add(0.5).mul(map.dimensions.a / map.zoom).add(map.center.a) + new_cursor.y.div(map.dimensions.b).sub(0.5).mul(map.dimensions.b / map.zoom).sub(map.center.b) + } + }) + + base.wheel = new wheel({ + el: map.el, + update: mousewheel, + }) + + function mousewheel (e, deltaY, deltaX){ + map.set_zoom(map.zoom_exponent - deltaY/20) + } +} + +var scene, map, controls + +map = new Map ({ + type: "ortho", + el: document.querySelector("#orthographic"), + width: window.innerWidth/2, + height: window.innerHeight, + zoom: 0, +}) + +var placing = false +var points, mx_points = [] +var shapes = [] +var ctx = map.draw.ctx +var last_point + +function polyline (points, finished) { + if (! points) return + if (points.length == 1) { + ctx.fillStyle = "#f80" + map.draw.dot_at(points[0].a, points[0].b, 5) + } + if (points.length > 1) { + ctx.fillStyle = "#ff0" + ctx.strokeStyle = "#f80" + ctx.lineWidth = 2 / map.zoom + ctx.beginPath() + ctx.moveTo(points[0].a, points[0].b) + points.forEach(function(point, i){ + i && ctx.lineTo(point.a, point.b) + }) + ctx.stroke() + if (! placing || finished) { + ctx.fill() + } + } +} + +function add_mx_polyline (points) { + mx_points.forEach(function(mx){ scene.remove(mx) }) + var faces = [] + for (var i = 1; i < points.length; i++) { + var head = points[i-1] + var tail = points[i] + face = add_mx_polyline_face(head, tail) + faces.push(face) + } + shapes.push({ + mx: faces, + points: points, + }) + points = [] +} +function add_mx_polyline_face(head, tail){ + var mx = new MX.Object3D() + var mid_x = (head.a + tail.a) + var mid_z = (head.b + tail.b) + var len = head.distanceTo( tail ) + var angle = atan2( head.b - tail.b, head.a - tail.a ) + mx.move({ + x: mid_x / 2, + y: 25 + 1, + z: mid_z / 2, + width: ceil(len), + height: 50, + rotationY: angle + }) + var hue = abs(round( angle / PI * 90 + 300)) + mx.el.style.backgroundColor = 'hsl(' + [hue, "100%", "50%"] + ')' + scene.add(mx) + return mx +} + +function add_mx_point (p, i) { + var mx = new MX.Object3D() + mx.updateChildren = false + mx.move({ + x: p.a, + y: 11, + z: p.b, + width: 20, + height: 20, + }) + mx.el.style.backgroundColor = 'rgb(' + [abs(floor(p.a*30)), 0, abs(floor(p.b*30))] + ')' + mx.el.style.backfaceVisibility = "visible" + scene.add(mx) + return mx +} +function mx_grid () { + var space = 20, cells = 20, side = space*cells + var ctx, canvas = document.createElement("canvas") + canvas.width = canvas.height = side + 4 + ctx = canvas.getContext('2d') + + draw_grid(ctx, 20, 20) + + var mx = new MX.Object3D(canvas) + mx.rotationX = PI/2 + scene.add(mx) +} +function draw_grid (ctx, cells, space) { + var side = space * cells + ctx.strokeStyle = "#444" + ctx.lineWidth = 1 + ctx.beginPath() + ctx.translate(1,1) + for (var i = 0; i <= cells; i++) { + ctx.moveTo(i*space, 0) + ctx.lineTo(i*space, side) + ctx.moveTo(0, i*space) + ctx.lineTo(side, i*space) + } + ctx.closePath() + ctx.stroke() +} + +document.addEventListener('DOMContentLoaded', build) +function build () { + scene = new MX.Scene().addTo("#perspective") + scene.camera.radius = 20 + + scene.width = window.innerWidth/2 + scene.height = window.innerHeight + scene.perspective = window.innerHeight + + mx_grid() + + scene.update() + + controls = new MX.OrbitCamera({ + radius: 1000, + rotationX: PI/4, + rotationY: PI/2, + }) + controls.init() + + animate(0) +} +function animate(time){ + requestAnimationFrame(animate) + map.update(time) + + controls.update() + scene.update() + + map.draw.ctx.save() + map.draw.translate() + + map.draw.ctx.save() + map.draw.ctx.translate(-(20*20)/2, -(20*20)/2) + draw_grid(map.draw.ctx, 20, 20) + map.draw.ctx.restore() + + map.draw.coords() + + polyline(points) + if (placing && last_point) { + ctx.strokeStyle = "#f80" + ctx.lineWidth = 2 / map.zoom + ctx.beginPath() + ctx.moveTo(points[points.length-1].a, points[points.length-1].b) + ctx.lineTo(last_point.a, last_point.b) + ctx.stroke() + } + + shapes.forEach(function(shape){ + polyline(shape.points, true) + }) + + ctx.strokeStyle = "#f00"; + map.draw.x_at(0,0) + map.draw.mouse(map.ui.mouse.cursor) + map.draw.camera(scene.camera) + + map.draw.ctx.restore() +} + +</script>
\ No newline at end of file diff --git a/public/assets/test/ortho2.html b/public/assets/test/ortho2.html new file mode 100644 index 0000000..ef77256 --- /dev/null +++ b/public/assets/test/ortho2.html @@ -0,0 +1,374 @@ +<link href='/assets/stylesheets/ionicons.css' rel='stylesheet' type='text/css'> +<style type="text/css"> +html,body{width:100%;height:100%;margin:0;padding:0;} +body { + font-family: Menlo, monospace; + overflow: hidden; +} +#perspective { + position: absolute; + left:0%; + top:0px +} +#orthographic { + position: absolute; + left:50%; + top:0px +} +#hud { + position: absolute; + top: 0; + left: 0; + padding: 10px; + background: white; +} +#url { width: 300px } +#hud span { color: #888; cursor: pointer; } +#hud span.active { color: #000; } +</style> + +<div id="perspective"></div> +<div id="orthographic"></div> + +<div id="hud"> + <input type="text" id="url" placeholder="paste an image URL here!"> + <span class="ion-ionic active" data-role="orbit-mode"></span> + <span class="ion-archive" data-role="keyboard-mode"></span> +</div> + +<script src="/assets/javascripts/util.js"></script> +<script src="/assets/javascripts/defaults.js"></script> +<script src="/assets/javascripts/vendor/bower_components/jquery/dist/jquery.min.js"></script> +<script src="/assets/javascripts/vendor/bower_components/lodash/lodash.min.js"></script> +<script src="/assets/javascripts/vendor/bower_components/hidpi-canvas/dist/hidpi-canvas.js"></script> +<script src="/assets/javascripts/vendor/bower_components/fiber/src/fiber.min.js"></script> +<script src="/assets/javascripts/vendor/polyfill.js"></script> +<script src="/assets/javascripts/vendor/tube.js"></script> +<script src="/assets/javascripts/mx/mx.js"></script> +<script src="/assets/javascripts/mx/extensions/mx.scene.js"></script> +<script src="/assets/javascripts/mx/extensions/mx.orbitCamera.js"></script> +<script src="/assets/javascripts/mx/extensions/mx.movements.js"></script> +<script src="/assets/javascripts/mx/primitives/mx.grid.js"></script> +<script src="/assets/javascripts/mx/primitives/mx.image.js"></script> +<script src="/assets/javascripts/rectangles/util/constants.js"></script> +<script src="/assets/javascripts/rectangles/util/coords.js"></script> +<script src="/assets/javascripts/rectangles/util/mouse.js"></script> +<script src="/assets/javascripts/rectangles/util/wheel.js"></script> +<script src="/assets/javascripts/rectangles/models/vec2.js"></script> +<script src="/assets/javascripts/rectangles/models/rect.js"></script> +<script src="/assets/javascripts/rectangles/models/rect.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/_map.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/ui/ortho.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/tools/_base.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/tools/arrow.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/draw.js"></script> + +<script> +var app = window.app || {} +app.tube = new Tube () +app.on = function(){ app.tube.on.apply(app.tube, arguments) } +app.off = function(){ app.tube.off.apply(app.tube, arguments) } + +var MapTool = Fiber.extend(function(base){ + var exports = { + down: function(e, cursor){}, + move: function(e, cursor){}, + drag: function(e, cursor){}, + up: function(e, cursor, new_cursor){}, + cancel: function(){}, + } + return exports +}) + +var PositionTool = MapTool.extend(function(base){ + var exports = { + down: function(e, cursor){ + cursor.quantize(1/map.zoom) + map.center.a = cursor.x.a + map.center.b = -cursor.y.a + cursor.x.b = cursor.x.a + cursor.y.b = cursor.y.a + map.ui.mouse.down = false + }, + } + return exports +}) + +var PolylineTool = MapTool.extend(function (base) { + var exports = {} + exports.down = function(e, cursor){ + + // rightclick? + if (e.ctrlKey || e.which === 3) { + e.preventDefault() + e.stopPropagation() + if (placing) { + // close polyline or cancel + placing = false + if (points.length > 2) { + add_mx_polyline(points) + } + else { + points.length = 0 + } + return + } + map.ui.tools.position.down(e, cursor) + return + } + + // compare to initial point + var p = new vec2( cursor.x.a, cursor.y.a ) + if (placing) { + if (points.length > 2 && points[0].distanceTo( p ) < 10/map.zoom) { + points.push( points[0].clone() ) + placing = false + add_mx_polyline(points) + } + else { + points.push( p ) + mx_points.push( add_mx_point(p) ) + } + } + else { + placing = true + points = [] + points.push( p ) + mx_points.push( add_mx_point(p) ) + } + } + exports.move = function(e, cursor){ + last_point = new vec2( cursor.x.a, cursor.y.a ) + if (placing && points.length > 1 && points[0].distanceTo( last_point ) < 10/map.zoom) { + document.body.style.cursor = "pointer" + last_point.assign(points[0]) + cursor.x.a = cursor.x.b = last_point.a + cursor.y.a = cursor.y.b = last_point.b + } + else { + document.body.style.cursor = "crosshair" + } + } + return exports +}) + +var scene, map, controls +var last_point = new vec2(0,0) + +map = new Map ({ + type: "ortho", + el: document.querySelector("#orthographic"), + width: window.innerWidth/2, + height: window.innerHeight, + zoom: -2, +}) +map.ui.add_tool("arrow", new ArrowTool) +map.ui.add_tool("polyline", new PolylineTool) +map.ui.add_tool("position", new PositionTool) +map.ui.set_tool("arrow") + +$(window).resize(function(){ + scene.width = window.innerWidth/2 + map.canvas.width = map.dimensions.a = window.innerWidth/2 +}) + +var wallHeight = 180 +var placing = false +var points, mx_points = [] +var shapes = [] +var ctx = map.draw.ctx +var last_point + +shapes.findClosestPoint = function(){} + +function polyline (points, finished) { + if (! points) return + if (points.length == 1) { + ctx.fillStyle = "#f80" + map.draw.dot_at(points[0].a, points[0].b, 5) + } + if (points.length > 1) { + ctx.fillStyle = "rgba(255,255,0,0.1)" + ctx.strokeStyle = "#f80" + ctx.lineWidth = 2 / map.zoom + ctx.beginPath() + ctx.moveTo(points[0].a, points[0].b) + points.forEach(function(point, i){ + i && ctx.lineTo(point.a, point.b) + }) + ctx.stroke() + if (! placing || finished) { + ctx.fill() + } + } +} + +function add_mx_polyline (points) { + mx_points.forEach(function(mx){ scene.remove(mx) }) + var faces = [] + for (var i = 1; i < points.length; i++) { + var head = points[i-1] + var tail = points[i] + face = add_mx_polyline_face(head, tail) + faces.push(face) + } + shapes.push({ + mx: faces, + points: points, + }) + points = [] +} +function add_mx_polyline_face(head, tail){ + var mx = new MX.Object3D() + var mid_x = (head.a + tail.a) + var mid_z = (head.b + tail.b) + var len = head.distanceTo( tail ) + var angle = atan2( head.b - tail.b, head.a - tail.a ) + mx.move({ + x: mid_x / 2, + y: wallHeight/2 + 1, + z: mid_z / 2, + width: ceil(len), + height: wallHeight, + rotationY: angle + }) + var hue = abs(round( angle / PI * 90 + 300)) + mx.el.style.backgroundColor = 'hsl(' + [hue, "100%", "50%"] + ')' + scene.add(mx) + return mx +} +function add_mx_point (p, i) { + var mx = new MX.Object3D() + mx.updateChildren = false + mx.move({ + x: p.a, + y: 11, + z: p.b, + width: 20, + height: 20, + rotationX: PI/2, + }) + mx.el.style.backgroundColor = 'rgb(' + [abs(floor(p.a*30)), 0, abs(floor(p.b*30))] + ')' + mx.el.style.backfaceVisibility = "visible" + mx.el.style.borderRadius = "50%" + scene.add(mx) + return mx +} + +$("#url").on("input", function(){ + floorplan.load({ src: this.value }) +}) +$("[data-role=orbit-mode]").click(function(){ + $("#hud .active").removeClass('active') + $(this).addClass('active') + controls.toggle(true) + movements.lock() +}) +$("[data-role=keyboard-mode]").click(function(){ + $("#hud .active").removeClass('active') + $(this).addClass('active') + controls.toggle(false) + movements.unlock() + movements.gravity(true) + cam.rotationX = 0 + cam.rotationY = -cam.rotationY + cam.x = 0 + cam.y = viewHeight + 100 + cam.z = 0 +}) + +document.addEventListener('DOMContentLoaded', build) +function build () { + scene = new MX.Scene().addTo("#perspective") + scene.camera.radius = 20 + + viewHeight = 100 + + scene.width = window.innerWidth/2 + scene.height = window.innerHeight + scene.perspective = window.innerHeight + + cam = scene.camera + movements = new MX.Movements(cam, viewHeight) + movements.init() + movements.lock() + movements.velocity(8) + app.on("move", function(pos){ + cam.x = pos.x + cam.y = pos.y + cam.z = pos.z + }) + + floorplan = new MX.Image({ + src: "https://s3.amazonaws.com/luckyplop/fbf4295da80f1f66c5e4a248f2ea3e1ce7a22c3d.jpg", + keepImage: true, + rotationX: -PI/2, + rotationY: PI, + }) + scene.add(floorplan) + floorplan.el.addEventListener("contextmenu", function(e){ + e.preventDefault() + var offset = offsetFromPoint(e, this) + var x = (offset.left - 0.5) * floorplan.width * floorplan.scale + var z = (offset.top - 0.5) * floorplan.height * floorplan.scale + controls.opt.center.x = -x + controls.opt.center.y = 0 + controls.opt.center.z = -z + }, true) + + scene.update() + + controls = new MX.OrbitCamera({ + el: scene.el, + radius: 3000, + radiusRange: [ 10, 10000 ], + rotationX: PI/4, + rotationY: PI/2, + }) + controls.init() + + animate(0) +} +var last_t = 0 +function animate(t){ + requestAnimationFrame(animate) + + var dt = t - last_t + last_t = t + + map.update(t) + + movements.update(dt) + controls.update() + scene.update() + + map.draw.ctx.save() + map.draw.translate() + + floorplan.draw(map.draw.ctx, true) + + map.draw.coords() + + polyline(points) + if (placing && last_point) { + ctx.strokeStyle = "#f80" + ctx.lineWidth = 2 / map.zoom + ctx.beginPath() + ctx.moveTo(points[points.length-1].a, points[points.length-1].b) + ctx.lineTo(last_point.a, last_point.b) + ctx.stroke() + } + + shapes.forEach(function(shape){ + polyline(shape.points, true) + }) + + ctx.strokeStyle = "#f00"; + map.draw.x_at(0,0) + map.draw.mouse(map.ui.mouse.cursor) + map.draw.camera(scene.camera) + + map.draw.ctx.restore() +} + +</script>
\ No newline at end of file diff --git a/public/assets/test/ortho3.html b/public/assets/test/ortho3.html new file mode 100644 index 0000000..71e43f1 --- /dev/null +++ b/public/assets/test/ortho3.html @@ -0,0 +1,258 @@ +<link href='/assets/stylesheets/ionicons.css' rel='stylesheet' type='text/css'> +<style type="text/css"> +html,body{width:100%;height:100%;margin:0;padding:0;} +body { + font-family: Menlo, monospace; + overflow: hidden; +} +#perspective { + position: absolute; + left:0%; + top:0px +} +#orthographic { + position: absolute; + left:50%; + top:0px +} +.hud { + position: absolute; + top: 0; + left: 0; + padding: 10px; + background: white; +} +.ortho-hud { + left: 50%; + border-left: 1px solid black; +} +#url { width: 300px } +.hud span { color: #888; cursor: pointer; } +.hud span.active { color: #000; } +</style> + +<div id="perspective"></div> +<div id="orthographic"></div> + +<div class="hud persp-hud"> + <input type="text" id="url" placeholder="paste an image URL here!"> + <span class="ion-ionic active" data-role="orbit-mode"></span> + <span class="ion-archive" data-role="keyboard-mode"></span> +</div> + +<div class="hud ortho-hud"> + <span class="ion-navigate" data-role="arrow-mode"></span> + <span class="ion-ios-pulse active" data-role="polyline-mode"></span> + <span class="ion-ios-grid-view-outline" data-role="ortho-polyline-mode"></span> + <span class="ion-scissors" data-role="eraser-mode"></span> +</div> + +<script src="/assets/javascripts/util.js"></script> +<script src="/assets/javascripts/defaults.js"></script> +<script src="/assets/javascripts/vendor/bower_components/jquery/dist/jquery.min.js"></script> +<script src="/assets/javascripts/vendor/bower_components/lodash/lodash.min.js"></script> +<script src="/assets/javascripts/vendor/bower_components/hidpi-canvas/dist/hidpi-canvas.js"></script> +<script src="/assets/javascripts/vendor/bower_components/fiber/src/fiber.min.js"></script> +<script src="/assets/javascripts/vendor/polyfill.js"></script> +<script src="/assets/javascripts/vendor/tube.js"></script> +<script src="/assets/javascripts/mx/mx.js"></script> +<script src="/assets/javascripts/mx/extensions/mx.scene.js"></script> +<script src="/assets/javascripts/mx/extensions/mx.orbitCamera.js"></script> +<script src="/assets/javascripts/mx/extensions/mx.movements.js"></script> +<script src="/assets/javascripts/mx/primitives/mx.grid.js"></script> +<script src="/assets/javascripts/mx/primitives/mx.image.js"></script> +<script src="/assets/javascripts/mx/primitives/mx.point.js"></script> +<script src="/assets/javascripts/mx/primitives/mx.polyline.js"></script> +<script src="/assets/javascripts/rectangles/util/constants.js"></script> +<script src="/assets/javascripts/rectangles/util/coords.js"></script> +<script src="/assets/javascripts/rectangles/util/mouse.js"></script> +<script src="/assets/javascripts/rectangles/util/wheel.js"></script> +<script src="/assets/javascripts/rectangles/models/vec2.js"></script> +<script src="/assets/javascripts/rectangles/models/rect.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/_map.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/draw.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/ui/ortho.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/tools/_base.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/tools/arrow.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/tools/eraser.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/tools/ortho.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/tools/polyline.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/tools/position.js"></script> +<script src="/assets/javascripts/rectangles/engine/shapes/shapelist.js"></script> +<script src="/assets/javascripts/rectangles/engine/shapes/polyline.js"></script> +<script src="/assets/javascripts/ui/lib/Toolbar.js"></script> + +<script> +var app = window.app || {} +app.tube = new Tube () +app.on = function(){ app.tube.on.apply(app.tube, arguments) } +app.off = function(){ app.tube.off.apply(app.tube, arguments) } + +var scene, map, controls + +map = new Map ({ + type: "ortho", + el: document.querySelector("#orthographic"), + width: window.innerWidth/2, + height: window.innerHeight, + zoom: -2, + zoom_min: -6.2, + zoom_max: 1, +}) +map.ui.add_tool("arrow", new ArrowTool) +map.ui.add_tool("polyline", new PolylineTool) +map.ui.add_tool("ortho-polyline", new OrthoPolylineTool) +map.ui.add_tool("eraser", new EraserTool) +map.ui.add_tool("position", new PositionTool) + +map.ui.placing = false + +$(window).resize(function(){ + scene.width = window.innerWidth/2 + map.canvas.width = map.dimensions.a = window.innerWidth/2 +}) + +var wallHeight = 180 +var shapes = new ShapeList +var ctx = map.draw.ctx +var last_point = new vec2 (0,0) + +$("#url").on("input", function(){ + floorplan.load({ src: this.value }) +}) + +var PerspectiveToolbar = new Toolbar (".persp-hud") +PerspectiveToolbar.add("orbit-mode", function(){ + controls.toggle(true) + movements.lock() +}) +PerspectiveToolbar.add("keyboard-mode", function(){ + controls.toggle(false) + movements.unlock() + movements.gravity(true) + cam.rotationX = 0 + cam.rotationY = -cam.rotationY + cam.x = 0 + cam.y = viewHeight + 100 + cam.z = 0 +}) + +var OrthographicToolbar = new Toolbar (".ortho-hud") +OrthographicToolbar.add("arrow-mode", function(){ + map.ui.set_tool("arrow") +}) +OrthographicToolbar.add("polyline-mode", function(){ + map.ui.set_tool("polyline") +}) +OrthographicToolbar.add("ortho-polyline-mode", function(){ + map.ui.set_tool("ortho-polyline") +}) +OrthographicToolbar.add("eraser-mode", function(){ + map.ui.set_tool("eraser") +}) +OrthographicToolbar.pick("ortho-polyline-mode") +// OrthographicToolbar.pick("eraser-mode") + + +document.addEventListener('DOMContentLoaded', build) +function build () { + scene = new MX.Scene().addTo("#perspective") + scene.camera.radius = 20 + + viewHeight = 100 + + scene.width = window.innerWidth/2 + scene.height = window.innerHeight + scene.perspective = window.innerHeight + + cam = scene.camera + movements = new MX.Movements(cam, viewHeight) + movements.init() + movements.lock() + movements.velocity(8) + app.on("move", function(pos){ + cam.x = pos.x + cam.y = pos.y + cam.z = pos.z + }) + + floorplan = new MX.Image({ + src: "https://s3.amazonaws.com/luckyplop/fbf4295da80f1f66c5e4a248f2ea3e1ce7a22c3d.jpg", + keepImage: true, + rotationX: -PI/2, + rotationY: PI, + }) + scene.add(floorplan) + + // recenter perspective view by rightclicking map + floorplan.el.addEventListener("contextmenu", function(e){ + e.preventDefault() + var offset = offsetFromPoint(e, this) + var x = (offset.left - 0.5) * floorplan.width * floorplan.scale + var z = (offset.top - 0.5) * floorplan.height * floorplan.scale + controls.opt.center.x = -x + controls.opt.center.y = 0 + controls.opt.center.z = -z + }, true) + + scene.update() + + controls = new MX.OrbitCamera({ + el: scene.el, + radius: 3000, + radiusRange: [ 10, 10000 ], + rotationX: PI/4, + rotationY: PI/2, + }) + controls.init() + + var line = new Polyline () + line.add( new vec2(-100,100) ) + line.add( new vec2(100,100) ) + line.add( new vec2(100,-100) ) + line.add( new vec2(-100,-100) ) + line.close() + line.build() + + animate(0) +} +var last_t = 0 +function animate(t){ + requestAnimationFrame(animate) + + var dt = t - last_t + last_t = t + + map.update(t) + + movements.update(dt) + controls.update() + scene.update() + + map.draw.ctx.save() + map.draw.translate() + + floorplan.draw(map.draw.ctx, true) + + map.draw.coords() + + if (shapes.workline) { + shapes.workline.draw(map.draw.ctx) + if (map.ui.placing && last_point) { + shapes.workline.draw_line( map.draw.ctx, last_point ) + } + } + + shapes.forEach(function(shape){ + shape.draw(map.draw.ctx) + }) + + ctx.strokeStyle = "#f00"; + map.draw.x_at(0,0) + map.draw.mouse(map.ui.mouse.cursor) + map.draw.camera(scene.camera) + + map.draw.ctx.restore() +} + +</script>
\ No newline at end of file diff --git a/public/assets/test/ortho4.html b/public/assets/test/ortho4.html new file mode 100644 index 0000000..8db7ead --- /dev/null +++ b/public/assets/test/ortho4.html @@ -0,0 +1,303 @@ +<link href='/assets/stylesheets/app.css' rel='stylesheet' type='text/css'> +<link href='/assets/stylesheets/ionicons.css' rel='stylesheet' type='text/css'> +<style type="text/css"> +html,body{width:100%;height:100%;margin:0;padding:0;} +body { + overflow: hidden; +} +#perspective, +#perspective .mx-scene { + position: absolute; + left:0%; + top:0px; + -webkit-transform: translateZ(0); + transform: translateZ(0); +} + +#orthographic { + position: absolute; + left:50%; + top:0px +} +.hud { + position: absolute; + top: 0; + left: 0; + padding: 10px; + background: white; +} +.ortho-hud { + left: 50%; + border-left: 1px solid black; +} +#url { width: 300px } +.hud span { color: #888; cursor: pointer; } +.hud span.active { color: #000; } + +#blueprintForm { + width: 240px; +} +</style> + +<div id="perspective"></div> +<div id="orthographic"></div> + +<div class="hud persp-hud"> + <input type="text" id="url" placeholder="paste an image URL here!"> + <span class="ion-ionic active" data-role="orbit-mode"></span> + <span class="ion-archive" data-role="keyboard-mode"></span> +</div> + +<div class="hud ortho-hud"> + <span class="ion-navigate" data-role="arrow-mode"></span> + <span class="ion-ios-pulse active" data-role="polyline-mode"></span> + <span class="ion-ios-grid-view-outline" data-role="ortho-polyline-mode"></span> + <span class="ion-scissors" data-role="eraser-mode"></span> +</div> + +<div class="mediaDrawer fixed animate blueprintUpload active"> + <span class="close">X</span> + <div class="box"> + + <h2>Upload A Room Image</h2> + + <div id="blueprintForm"> + <div class="wallpaperUpload toolButton"> + <form> + <span class="ion-ios-upload-outline upload-icon"></span> + <label>Upload</label> + <input type="file" accept="image/*" multiple> + </form> + </div> + <input type="text" class="url" placeholder="Enter an image URL or..."> + </div> + + Please tell us the scale of your map. + Click both corners of a wall, and then enter how long the wall is. + + <div id="blueprintMap"> + </div> + + <div id="blueprintDimensions"> + <input type="text" name="blueprint-dimensions"> + <select id="blueprint-units" name="blueprint-units"> + <option value="ft">foot</option> + <option value="m">meter</option> + </select> + + <button id="saveBlueprint">Save</button> + </div> + + </div> +</div> + +<script src="/assets/javascripts/vendor/bower_components/jquery/dist/jquery.min.js"></script> +<script src="/assets/javascripts/vendor/bower_components/lodash/lodash.min.js"></script> +<script src="/assets/javascripts/vendor/bower_components/hidpi-canvas/dist/hidpi-canvas.js"></script> +<script src="/assets/javascripts/vendor/bower_components/fiber/src/fiber.min.js"></script> +<script src="/assets/javascripts/vendor/polyfill.js"></script> +<script src="/assets/javascripts/vendor/tube.js"></script> + +<script src="/assets/javascripts/util.js"></script> +<script src="/assets/javascripts/defaults.js"></script> + +<script src="/assets/javascripts/mx/mx.js"></script> +<script src="/assets/javascripts/mx/extensions/mx.scene.js"></script> +<script src="/assets/javascripts/mx/extensions/mx.orbitCamera.js"></script> +<script src="/assets/javascripts/mx/extensions/mx.movements.js"></script> +<script src="/assets/javascripts/mx/primitives/mx.grid.js"></script> +<script src="/assets/javascripts/mx/primitives/mx.image.js"></script> +<script src="/assets/javascripts/mx/primitives/mx.point.js"></script> +<script src="/assets/javascripts/mx/primitives/mx.polyline.js"></script> +<script src="/assets/javascripts/rectangles/util/constants.js"></script> +<script src="/assets/javascripts/rectangles/util/coords.js"></script> +<script src="/assets/javascripts/rectangles/util/mouse.js"></script> +<script src="/assets/javascripts/rectangles/util/wheel.js"></script> +<script src="/assets/javascripts/rectangles/models/vec2.js"></script> +<script src="/assets/javascripts/rectangles/models/rect.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/_map.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/draw.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/ui/ortho.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/tools/_base.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/tools/arrow.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/tools/eraser.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/tools/ortho.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/tools/polyline.js"></script> +<script src="/assets/javascripts/rectangles/engine/map/tools/position.js"></script> +<script src="/assets/javascripts/rectangles/engine/shapes/shapelist.js"></script> +<script src="/assets/javascripts/rectangles/engine/shapes/polyline.js"></script> +<script src="/assets/javascripts/ui/lib/View.js"></script> +<script src="/assets/javascripts/ui/lib/ModalView.js"></script> +<script src="/assets/javascripts/ui/lib/UploadView.js"></script> +<script src="/assets/javascripts/ui/lib/Parser.js"></script> +<script src="/assets/javascripts/ui/lib/Toolbar.js"></script> +<script src="/assets/javascripts/ui/builder/BlueprintUpload.js"></script> + +<script> +var app = window.app || {} +app.tube = new Tube () +app.on = function(){ app.tube.on.apply(app.tube, arguments) } +app.off = function(){ app.tube.off.apply(app.tube, arguments) } + +var scene, map, controls + +map = new Map ({ + type: "ortho", + el: document.querySelector("#orthographic"), + width: window.innerWidth/2, + height: window.innerHeight, + zoom: -2, + zoom_min: -6.2, + zoom_max: 1, +}) +map.ui.add_tool("arrow", new ArrowTool) +map.ui.add_tool("polyline", new PolylineTool) +map.ui.add_tool("ortho-polyline", new OrthoPolylineTool) +map.ui.add_tool("eraser", new EraserTool) +map.ui.add_tool("position", new PositionTool) + +map.ui.placing = false + +$(window).resize(function(){ + scene.width = window.innerWidth/2 + scene.height = window.innerHeight + map.canvas.width = map.dimensions.a = window.innerWidth/2 + map.canvas.height = map.dimensions.b = window.innerHeight/2 +}) + +var wallHeight = 180 +var shapes = new ShapeList +var ctx = map.draw.ctx +var last_point = new vec2 (0,0) + +$("#url").on("input", function(){ + floorplan.load({ src: this.value }) +}) + +var PerspectiveToolbar = new Toolbar (".persp-hud") +PerspectiveToolbar.add("orbit-mode", function(){ + controls.toggle(true) + movements.lock() +}) +PerspectiveToolbar.add("keyboard-mode", function(){ + controls.toggle(false) + movements.unlock() + movements.gravity(true) + cam.rotationX = 0 + cam.rotationY = -cam.rotationY + cam.x = 0 + cam.y = viewHeight + 100 + cam.z = 0 +}) + +var OrthographicToolbar = new Toolbar (".ortho-hud") +OrthographicToolbar.add("arrow-mode", function(){ + map.ui.set_tool("arrow") +}) +OrthographicToolbar.add("polyline-mode", function(){ + map.ui.set_tool("polyline") +}) +OrthographicToolbar.add("ortho-polyline-mode", function(){ + map.ui.set_tool("ortho-polyline") +}) +OrthographicToolbar.add("eraser-mode", function(){ + map.ui.set_tool("eraser") +}) +OrthographicToolbar.pick("ortho-polyline-mode") + +var BlueprintUpload = new BlueprintUploadView ({}) + +document.addEventListener('DOMContentLoaded', build) +function build () { + scene = new MX.Scene().addTo("#perspective") + scene.camera.radius = 20 + + viewHeight = 100 + + scene.width = window.innerWidth/2 + scene.height = window.innerHeight + scene.perspective = window.innerHeight + + cam = scene.camera + movements = new MX.Movements(cam, viewHeight) + movements.init() + movements.lock() + movements.velocity(8) + app.on("move", function(pos){ + cam.x = pos.x + cam.y = pos.y + cam.z = pos.z + }) + + floorplan = new MX.Image({ + src: "https://s3.amazonaws.com/luckyplop/fbf4295da80f1f66c5e4a248f2ea3e1ce7a22c3d.jpg", + keepImage: true, + rotationX: -PI/2, + rotationY: PI, + }) + scene.add(floorplan) + + // recenter perspective view by rightclicking map + floorplan.el.addEventListener("contextmenu", function(e){ + e.preventDefault() + var offset = offsetFromPoint(e, this) + var x = (offset.left - 0.5) * floorplan.width * floorplan.scale + var z = (offset.top - 0.5) * floorplan.height * floorplan.scale + controls.opt.center.x = -x + controls.opt.center.y = 0 + controls.opt.center.z = -z + }, true) + + scene.update() + + controls = new MX.OrbitCamera({ + el: scene.el, + radius: 3000, + radiusRange: [ 10, 10000 ], + rotationX: PI/4, + rotationY: PI/2, + }) + controls.init() + + animate(0) +} +var last_t = 0 +function animate(t){ + requestAnimationFrame(animate) + + var dt = t - last_t + last_t = t + + map.update(t) + + movements.update(dt) + controls.update() + scene.update() + + map.draw.ctx.save() + map.draw.translate() + + floorplan.draw(map.draw.ctx, true) + + map.draw.coords() + + if (shapes.workline) { + shapes.workline.draw(map.draw.ctx) + if (map.ui.placing && last_point) { + shapes.workline.draw_line( map.draw.ctx, last_point ) + } + } + + shapes.forEach(function(shape){ + shape.draw(map.draw.ctx) + }) + + ctx.strokeStyle = "#f00"; + map.draw.x_at(0,0) + map.draw.mouse(map.ui.mouse.cursor) + map.draw.camera(scene.camera) + + map.draw.ctx.restore() +} + +</script>
\ No newline at end of file diff --git a/public/assets/test/static.html b/public/assets/test/static.html new file mode 100644 index 0000000..dc098de --- /dev/null +++ b/public/assets/test/static.html @@ -0,0 +1,152 @@ +<!doctype html> +<html> +<head> + <title>VValls</title> + +<!-----+ +------+ +------+ +------+ +------+ +|`. `. |\ \ | | / /| .' .'| +| `+------+ | +------+ +------+ +------+ | +------+' | +| | | | | | | | | | | | | | ++ | | + | | | | | | + | | + + `. | | \| | | | | |/ | | .' + `+------+ +------+ +------+ +------+ +------+' + VVALLS - developed by okfoc.us + .+------+ +------+ +------+ +------+ +------+. + .' .'| / /| | | |\ \ |`. `. ++------+' | +------+ | +------+ | +------+ | `+------+ +| | | | | | | | | | | | | | +| | + | | + | | + | | + | | +| | .' | |/ | | \| | `. | | ++------+' +------+ +------+ +------+ `+-------> + + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable = no"> + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="description" content="3D gallery space, fully customizable" /> + <meta name="author" content="VValls" /> + <link rel="shortcut icon" href="/favicon.ico" /> + <meta property="og:title" content="Leaves and such" /> + <meta property="og:type" content="website" /> + <meta property="og:image" content="http://www.sport-fitness-advisor.com/images/plyometric_drills_overhead_throws.gif" /> + <meta property="og:url" content="http://vvalls.com/project/leaves-and-such-1429563199123/" /> + <meta property="og:site_name" content="vvalls" /> + <link rel="icon" href="/favicon.ico" type="image/x-icon"> + <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"> + <link href='http://fonts.googleapis.com/css?family=Lato:100,300,400,700,900,100italic,300italic,400italic,700italic,900italic' rel='stylesheet' type='text/css'> + <link href='/assets/stylesheets/ionicons.css' rel='stylesheet' type='text/css'> + <link href='/assets/stylesheets/app.css' rel='stylesheet' type='text/css'> +</head> +<body class="loading reader"> + +<div id="scene"></div> + +<div class="rapper"> + <div id="header"> + <a href="/" class="logo"> + <svg version="1.1" + xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" + x="0px" y="0px" width="117px" height="44px" viewBox="-0.896 -0.441 117 44" + overflow="visible" enable-background="new -0.896 -0.441 117 44" xml:space="preserve"> + <defs> + </defs> + <path d="M0.54,38.759c0-1.44,0.66-3.72,1.56-6.18c1.38-3.84,3.42-8.22,4.5-11.16c0.48-1.32,0.78-2.34,0.78-2.88 + c0-0.72-0.24-1.02-0.72-1.02c-1.38,0-4.74,5.16-5.4,6.24c-0.36,0.6-0.48,0.78-0.78,0.78c-0.3,0-0.48-0.06-0.48-0.36 + c0-0.18,0.18-0.84,0.66-1.62c0.9-1.44,2.22-3.6,3.9-5.28c1.44-1.5,3.12-2.64,4.74-2.64c1.38,0,1.92,1.32,1.92,2.7 + c0,1.02-0.42,2.58-1.02,4.32c-1.26,3.72-3.359,8.521-4.68,12.18c-0.66,1.92-1.14,3.54-1.14,4.62c0,1.38,0.48,2.459,1.979,2.459 + c6.48,0,13.56-14.639,13.56-17.759c0-1.2-0.3-1.92-0.6-2.58c-0.42-0.9-0.9-1.62-0.9-3.18c0-1.86,0.84-2.76,1.8-2.76 + c0.9,0,1.98,1.08,1.98,3.66c0,9.179-9.6,24.66-17.58,24.66c-2.82,0-4.08-1.561-4.08-4.141V38.759z"/> + <path d="M23.879,38.759c0-1.44,0.66-3.72,1.56-6.18c1.38-3.84,3.42-8.22,4.5-11.16c0.48-1.32,0.78-2.34,0.78-2.88 + c0-0.72-0.24-1.02-0.72-1.02c-1.38,0-4.74,5.16-5.4,6.24c-0.36,0.6-0.48,0.78-0.78,0.78c-0.3,0-0.48-0.06-0.48-0.36 + c0-0.18,0.18-0.84,0.66-1.62c0.9-1.44,2.22-3.6,3.9-5.28c1.44-1.5,3.12-2.64,4.74-2.64c1.38,0,1.92,1.32,1.92,2.7 + c0,1.02-0.42,2.58-1.02,4.32c-1.26,3.72-3.36,8.521-4.68,12.18c-0.66,1.92-1.14,3.54-1.14,4.62c0,1.38,0.48,2.459,1.98,2.459 + c6.479,0,13.559-14.639,13.559-17.759c0-1.2-0.3-1.92-0.6-2.58c-0.42-0.9-0.9-1.62-0.9-3.18c0-1.86,0.84-2.76,1.8-2.76 + c0.9,0,1.979,1.08,1.979,3.66c0,9.179-9.6,24.66-17.579,24.66c-2.82,0-4.08-1.561-4.08-4.141V38.759z"/> + <path d="M44.339,37.799c0-5.22,2.76-10.92,6.36-15.299c3.66-4.44,8.159-7.5,11.759-7.5c2.7,0,3.78,1.44,3.9,1.44 + s0.48-0.96,0.66-1.44c0.18-0.48,0.3-0.6,1.02-0.6h1.74c0.359,0,0.6,0.06,0.6,0.42c0,0.18-0.119,0.6-0.24,0.9 + c-1.919,5.82-3.839,11.64-5.819,17.519c-1.14,3.48-1.26,4.381-1.26,5.041c0,0.659,0.3,0.84,0.66,0.84c0.54,0,1.68-1.141,3.72-4.26 + c1.5-2.28,1.26-2.94,1.86-2.94c0.3,0,0.42,0.181,0.42,0.479c0,0.84-1.38,3.541-3.24,6c-1.8,2.52-4.14,4.8-6.12,4.8 + c-1.38,0-1.62-0.96-1.62-2.159c0-0.961,0.24-2.101,0.72-3.66c0.54-1.98,1.5-4.62,2.82-8.52l-0.12-0.12 + c-2.16,3.3-9.36,14.459-14.1,14.459c-2.76,0-3.72-2.159-3.72-5.339V37.799z M65.338,18.839c0-1.8-1.08-2.76-2.76-2.76 + c-3,0-6.6,3.72-9.48,8.22c-2.82,4.5-4.919,9.839-4.919,13.019c0,1.561,0.54,2.641,1.86,2.641c2.22,0,6.06-4.26,9.3-9 + c3.3-4.74,6-10.02,6-12.06V18.839z"/> + <path d="M72.178,39.839c0-1.08,0.479-3.479,1.2-6.479c1.74-7.02,4.979-17.52,6.6-23.64c0.66-2.46,1.08-4.2,1.08-4.8 + c0-0.78-0.24-1.32-1.62-1.44c-1.14-0.12-1.38-0.3-1.38-0.78c0.061-0.42,0.779-0.66,1.8-0.66c2.58,0,4.2-0.78,5.16-1.38 + c0.6-0.36,0.96-0.66,1.14-0.66c0.3,0,0.42,0.12,0.42,0.48c0,0.3-0.6,1.56-1.14,3.479c-5.04,17.759-7.38,25.799-8.46,29.698 + c-0.84,3.061-0.96,3.84-0.96,4.681c0,0.6,0.3,1.02,0.78,1.02c0.84,0,1.619-0.659,3.479-3.72c1.08-1.74,1.92-4.199,2.46-4.199 + c0.301,0,0.42,0.239,0.42,0.539c0,0.42-0.84,2.521-2.16,4.74c-1.739,3-4.319,6.24-6.719,6.24c-1.681,0-2.101-1.32-2.101-3.061 + V39.839z"/> + <path d="M85.497,39.839c0-1.08,0.48-3.479,1.2-6.479c1.739-7.02,4.979-17.52,6.6-23.64c0.66-2.46,1.08-4.2,1.08-4.8 + c0-0.78-0.24-1.32-1.62-1.44c-1.14-0.12-1.38-0.3-1.38-0.78c0.06-0.42,0.78-0.66,1.8-0.66c2.58,0,4.2-0.78,5.16-1.38 + c0.6-0.36,0.96-0.66,1.14-0.66c0.3,0,0.42,0.12,0.42,0.48c0,0.3-0.6,1.56-1.14,3.479c-5.04,17.759-7.38,25.799-8.46,29.698 + c-0.84,3.061-0.96,3.84-0.96,4.681c0,0.6,0.301,1.02,0.78,1.02c0.84,0,1.62-0.659,3.479-3.72c1.08-1.74,1.92-4.199,2.46-4.199 + c0.3,0,0.42,0.239,0.42,0.539c0,0.42-0.84,2.521-2.159,4.74c-1.74,3-4.32,6.24-6.721,6.24c-1.68,0-2.1-1.32-2.1-3.061V39.839z"/> + <path d="M111.416,34.619c0,2.34-0.96,4.439-2.46,5.939c-1.68,1.68-4.02,2.64-6.479,2.64c-1.86,0-3.84-0.78-5.04-1.56 + c-0.6-0.42-1.02-0.84-1.02-1.2c0-0.96,0.359-3.12,0.959-5.819c0.42-1.98,0.48-2.34,1.08-2.34c0.541,0,0.601,0.359,0.601,2.16 + c0,3.84,1.2,7.319,4.92,7.319c2.34,0,4.2-2.46,4.2-4.74c0-2.819-1.561-4.979-3.24-6.96c-1.68-1.979-3.24-4.08-3.24-6.899 + c0-4.38,3.24-8.76,7.859-8.76c3,0,5.82,1.38,5.82,2.1c0,1.14-0.301,2.4-0.66,3.9c-0.72,2.76-0.779,3.06-1.38,3.06 + c-0.899,0-0.78-1.92-1.08-3.84c-0.3-1.86-1.08-3.78-3.6-3.78c-2.34,0-4.08,2.04-4.08,4.439s1.62,4.44,3.24,6.6 + c1.8,2.34,3.6,4.68,3.6,7.68V34.619z"/> + </svg> + </a> + + <div id="minotaur"> + <span class="label"></span> + </div> + + <span class="topLinks"> + </span> + </div> + + <div id="editorView"> + <div class="aboutRoom vvbox"> + <h1> + <span class="roomName">Leaves and such</span> + <br> + <a href="/profile/asdf" class="authorName"><div class="profilePic" style="background-image:url(https://vvalls.s3.amazonaws.com/images/avatars/20141010/1412971714922-Screen-Shot-2014-10-09-at-12.png)"></div></a> + <a href="/profile/asdf" class="authorName">asdf</a> + </h1> + <span class="txt">Last modified 4/20/2015</span> + <!-- + <div class="share"> + <h2>Share on–</h2> + <a id="share_facebook">Facebook</a> + <a id="share_twitter">Twitter</a> + </div> + --> + </div> + + <div class="vvbox settings" id="mediaPlayer"> + <span class="playButton video audio" data-role="play-media"> + <span class="on ion-play"></span> + <span class="off ion-pause"></span> + </span> + + <span class="muteButton video" data-role="mute-media"> + <span class="on ion-volume-high"></span> + <span class="off ion-volume-mute"></span> + </span> + + <span class="name"></span> + + <div class="author"></div> + <div class="txt description"></div> + <div class="dimensions"></div> + </div> + </div> + + <div id="minimap" class="vvbox" data-intro="Mini-map shows your position and orientation in a room. Navigate with WASD keys or drag here." data-position="top"> + <span class="el"></span> + </div> +</div> + + <img src="/assets/img/keys.png" id="keyhint"> + <img src="/assets/img/360.png" id="threesixty"> +</body> +<script type="text/javascript"> +vvalls_data={"name":"Leaves and such","viewHeight":186,"colors":{"wall":[255,255,255],"outline":[0,0,0],"floor":[246,246,246],"ceiling":[255,255,255]},"startPosition":false,"lastPosition":{"x":-224,"y":186,"z":300.756,"rotationX":0,"rotationY":1.665},"user_id":"54383cb3b45a88b2a64dc240","slug":"leaves-and-such-1429563199123","created_at":"2015-04-01T19:08:10.150Z","photo":"https://vvalls.s3.amazonaws.com/images/projects/20150401/1427920106818-blob.png","updated_at":"2015-04-20T21:27:41.909Z","featured":false,"sculpture":[{"media":{"url":"http://www.sport-fitness-advisor.com/images/soccer_circuit_dips.gif","type":"image","user_id":"54383cb3b45a88b2a64dc240","created_at":"2014-11-17T16:53:21.043Z","tag":"","keyframe":0,"mute":true,"loop":false,"autoplay":false,"description":"","title":"","height":200,"width":200,"thumbnail":"","token":""},"scale":1,"position":{"rotationY":2.513,"rotationX":0,"z":-470.285,"y":180,"x":-1541.305},"dimensions":[200,200],"id":"sculpture1"},{"backface":true,"billboard":true,"media":{"url":"http://dumpfm.s3.amazonaws.com/images/20120519/1337401400140-dumpfm-FAUXreal-Greek_Marble_Statue.png","type":"image","user_id":"54383cb3b45a88b2a64dc240","created_at":"2015-04-03T22:49:00.855Z","tag":"","keyframe":0,"mute":true,"loop":false,"autoplay":false,"description":"","title":"","height":380,"width":280,"thumbnail":"","token":""},"scale":0.501,"position":{"scale":0.501,"rotationY":1.665,"rotationX":0,"z":370.922,"y":144.466,"x":-1111.901},"dimensions":[141,191],"id":"sculpture5"},{"backface":true,"billboard":false,"media":{"token":"","thumbnail":"","width":238,"height":210,"title":"","description":"","autoplay":false,"loop":false,"mute":true,"keyframe":0,"tag":"","created_at":"2014-11-17T16:53:38.690Z","user_id":"54383cb3b45a88b2a64dc240","type":"image","url":"http://www.sport-fitness-advisor.com/images/plyometric_drills_overhead_throws.gif"},"scale":0.715,"position":{"scale":0.715,"rotationY":2.911,"rotationX":0,"z":-504.672,"y":480.528,"x":-1015.969},"dimensions":[170,150],"id":"sculpture0"},{"backface":true,"billboard":false,"media":{"url":"http://dump.fm/images/20100825/1282780054021-dumpfm-timb-statue.eyez.gif","type":"image","user_id":"54383cb3b45a88b2a64dc240","created_at":"2015-04-03T22:48:39.613Z","tag":"","keyframe":0,"mute":true,"loop":false,"autoplay":false,"description":"","title":"","height":409,"width":295,"thumbnail":"","token":""},"scale":0.800,"position":{"scale":0.800,"rotationY":0.827,"rotationX":0,"z":457.221,"y":250.467,"x":-1331.614},"dimensions":[236,327],"id":"sculpture2"},{"backface":true,"billboard":true,"media":{"url":"http://simpleascension.com/wp-content/uploads/2009/05/leaves.gif","type":"image","user_id":"54383cb3b45a88b2a64dc240","created_at":"2015-04-20T20:52:13.261Z","tag":"","keyframe":0,"mute":true,"loop":false,"autoplay":false,"description":"","title":"","height":300,"width":300,"thumbnail":"","token":""},"scale":1,"position":{"rotationY":1.665,"rotationX":0,"z":500.971,"y":535.5,"x":-919.926},"dimensions":[300,300],"id":"sculpture3"},{"backface":true,"billboard":false,"media":{"url":"http://simpleascension.com/wp-content/uploads/2009/05/leaves.gif","type":"image","user_id":"54383cb3b45a88b2a64dc240","created_at":"2015-04-20T20:52:13.261Z","tag":"","keyframe":0,"mute":true,"loop":false,"autoplay":false,"description":"","title":"","height":300,"width":300,"thumbnail":"","token":""},"scale":1,"position":{"rotationY":2.358,"rotationX":0,"z":-402.875,"y":493.5,"x":-1341.121},"dimensions":[300,300],"id":"sculpture4"},{"backface":true,"billboard":false,"media":{"url":"http://simpleascension.com/wp-content/uploads/2009/05/leaves.gif","type":"image","user_id":"54383cb3b45a88b2a64dc240","created_at":"2015-04-20T20:52:13.261Z","tag":"","keyframe":0,"mute":true,"loop":false,"autoplay":false,"description":"","title":"","height":300,"width":300,"thumbnail":"","token":""},"scale":1,"position":{"rotationY":2.264,"rotationX":0,"z":-310.913,"y":492,"x":-718.718},"dimensions":[300,300],"id":"sculpture6"}],"media":[{"media":{"url":"http://www.sport-fitness-advisor.com/images/plyometric_drills_overhead_throws.gif","type":"image","user_id":"54383cb3b45a88b2a64dc240","created_at":"2014-11-17T16:53:38.690Z","tag":"","keyframe":0,"mute":true,"loop":false,"autoplay":false,"description":"","title":"","height":210,"width":238,"thumbnail":"","token":""},"scale":1,"position":{"rotationY":1.570,"rotationX":0,"z":137.5,"y":350,"x":-1721},"dimensions":[238,210],"side":4,"wall_id":"4_-1731_-636","id":"scenery0"}],"walls":[{"background":{"src":"none","x":0,"y":0,"scale":1},"id":"1_-636_-1731"},{"background":{"src":"none","x":0,"y":0,"scale":1},"id":"1_-168_-204"},{"background":{"src":"none","x":0,"y":0,"scale":1},"id":"2_156_-204"},{"background":{"src":"none","x":0,"y":0,"scale":1},"id":"2_652_-1731"},{"background":{"src":"none","x":0,"y":0,"scale":1},"id":"4_-1731_-636"},{"background":{"src":"none","x":0,"y":0,"scale":1},"id":"8_726_-168"},{"background":{"src":"none","x":0,"y":0,"scale":1},"id":"8_-204_-636"},{"background":{"src":"none","x":0,"y":0,"scale":1},"id":"8_-204_156"},{"background":{"src":"none","x":0,"y":0,"scale":1},"id":"floor"},{"background":{"src":"none","x":0,"y":0,"scale":1},"id":"ceiling"}],"rooms":[{"height":681,"rect":{"y":[-168,156],"x":[-284,726]},"id":"room_0"},{"height":681,"rect":{"y":[-636,652],"x":[-1731,-204]},"id":"room_1"}],"privacy":false,"description":""} +</script> +<script type="text/javascript" src="/assets/javascripts/static.min.js"></script> +<script type="text/javascript" src="http://www.youtube.com/player_api"></script> +<script type="text/javascript" src="https://w.soundcloud.com/player/api.js"></script> +</html> diff --git a/public/assets/test/surface.html b/public/assets/test/surface.html index 85e3a7b..9e6abe8 100644 --- a/public/assets/test/surface.html +++ b/public/assets/test/surface.html @@ -1,6 +1,7 @@ <canvas id="canvas"></canvas> <script src="/assets/javascripts/util.js"></script> +<script src="/assets/javascripts/vendor/bower_components/hidpi-canvas/dist/hidpi-canvas.js"></script> <script src="/assets/javascripts/vendor/tube.js"></script> <script src="/assets/javascripts/rectangles/util/constants.js"></script> <script src="/assets/javascripts/rectangles/util/mouse.js"></script> @@ -9,11 +10,11 @@ <script src="/assets/javascripts/rectangles/models/surface.js"></script> <script> -var ctx = canvas.getContext('2d') - var w = canvas.width = 600 var h = canvas.height = 400 +var ctx = canvas.getContext('2d') + var surface = new Surface () surface.add( new Rect( new vec2(10, 100), new vec2(0, 400) ) ) surface.add( new Rect( new vec2(100, 300), new vec2(200, 400) ) ) diff --git a/server/fetch.js b/server/fetch.js new file mode 100644 index 0000000..b76eeff --- /dev/null +++ b/server/fetch.js @@ -0,0 +1,41 @@ +var DB_HOST = 'localhost' +var mongoose = require('mongoose') +var _ = require('lodash') +var Project = require("./lib/schemas/Project") + +if (process.argv.length != 3) { + console.error("usage: node fetch.js [project-slug] > project.json") + process.exit() +} +var slug = process.argv[2] + +mongoose.connect('mongodb://' + DB_HOST + '/vvalls', {}, function(){ + // console.error("vvalls: connected to", DB_HOST) + Project.findOne({ slug: slug }).exec(function(err, data){ + if (err || ! data) { + console.error("Project " + slug + " not found!") + } + else { + console.error("Exporting " + data.name + " (" + slug + ") as JSON") + var str = JSON.stringify( simplify(data.toObject()) ).replace(/(\.\d\d\d)\d+/g, "$1") + console.log( "vvalls_data=" + str ) + } + process.exit() + }) +}) + +function simplify (data) { + delete data._id + delete data.__v + _(data).keys().forEach(function(key){ + var val = data[key] + if (typeof val != "object") return; + if (val.hasOwnProperty('length')) { + data[key].forEach(simplify) + } + else { + data[key] = simplify(val) + } + }) + return data +} diff --git a/server/index.js b/server/index.js index f9a104f..d3aeb9e 100644 --- a/server/index.js +++ b/server/index.js @@ -16,11 +16,13 @@ var http = require('http'), MongoStore = require('connect-mongo')(express), passport = require('passport'), path = require('path'), - mongoose = require('mongoose'); + mongoose = require('mongoose'), + methodOverride = require('method-override'); var app = express() var server +// var DATABASE_URI = process.env.MONGOLAB_URI || ('mongodb://localhost/vvalls') var DATABASE_URI = process.env.MONGOLAB_URI || ('mongodb://' + config.databaseHost + '/vvalls') // @@ -40,6 +42,7 @@ site.ready = function(){ site.setup = function(){ var SessionStore = new MongoStore({ mongoose_connection: mongoose.connection }) + // auth.initBasicAuth(app) app.set('port', config.port); app.set('views', path.join(__dirname, '../views')); app.set('view engine', 'ejs'); @@ -58,7 +61,7 @@ site.setup = function(){ app.use(multer()); app.use(express.query()); app.use(express.csrf()); - app.use(express.methodOverride()); + app.use(methodOverride('X-HTTP-Method-Override')) app.use(passport.initialize()); app.use(passport.session()); app.use(app.router); @@ -66,6 +69,10 @@ site.setup = function(){ app.set('env', config.env.production ? "production" : "development") app.get('env') === 'development' && app.use(express.errorHandler()); + if (config.env.production) { + app.set('json spaces', 0) + } + // Essential middleware // app.all('*', middleware.enableCORS); app.all('*', middleware.ensureLocals); @@ -73,11 +80,13 @@ site.setup = function(){ server = http.createServer(app) server.listen(app.get('port'), function () { - console.log('Express server listening on port ' + app.get('port')); + console.log('VValls server listening on port ' + app.get('port')); }); // var io = websocket.listen(server) // auth.initSockets(io, SessionStore) + + middleware.updatePlans() } site.route = function () { @@ -103,6 +112,7 @@ site.route = function () { app.get('/profile', views.profile) app.get('/profile/edit', views.profile) + app.get('/profile/billing', views.profile) app.get('/profile/:username', views.profile) app.get('/about', views.docs); @@ -120,6 +130,9 @@ site.route = function () { app.get('/layout', middleware.ensureAuthenticated, middleware.ensureIsStaff, views.modal) app.get('/layout/:name', middleware.ensureAuthenticated, middleware.ensureIsStaff, views.builder) + app.get('/blueprint', middleware.ensureAuthenticated, middleware.ensureIsStaff, views.blueprint) + app.get('/blueprint/:name', middleware.ensureAuthenticated, middleware.ensureIsStaff, views.blueprint) + app.get('/join/:nonce', middleware.ensureAuthenticated, api.collaborator.join) app.get('/api/collaborator/:slug/index', middleware.ensureAuthenticated, middleware.ensureProject, api.collaborator.index) app.post('/api/collaborator/:slug/create', middleware.ensureAuthenticated, middleware.ensureProject, api.collaborator.create) @@ -128,11 +141,12 @@ site.route = function () { app.get('/project', middleware.ensureAuthenticated, views.modal) app.get('/project/new', middleware.ensureAuthenticated, views.modal) app.get('/project/new/:layout', middleware.ensureAuthenticated, views.editor_new) + app.get('/project/blueprint/:layout', middleware.ensureAuthenticated, views.editor_new) app.get('/project/:slug', middleware.ensureProject, middleware.ensureIsCollaborator, views.reader) app.get('/project/:slug/view', middleware.ensureProject, middleware.ensureIsCollaborator, views.reader) app.get('/project/:slug/edit', middleware.ensureProject, middleware.ensureIsCollaborator, views.editor) - app.get('/api/layout', middleware.ensureAuthenticated, api.layouts.index) + app.get('/api/layout', middleware.ensureAuthenticated, middleware.ensureUserProjectsCount, middleware.ensureUserLayoutsCount, api.layouts.index) app.get('/api/layout/:slug', middleware.ensureAuthenticated, api.layouts.show) app.post('/api/layout/new', middleware.ensureAuthenticated, middleware.ensureIsStaff, api.layouts.create) app.post('/api/layout/edit', middleware.ensureAuthenticated, middleware.ensureIsStaff, api.layouts.update) @@ -151,6 +165,21 @@ site.route = function () { app.post('/api/media/upload', middleware.ensureAuthenticated, api.media.upload) app.delete('/api/media/destroy', middleware.ensureAuthenticated, api.media.destroy) + app.post('/api/blueprint/new', middleware.ensureAuthenticated, api.blueprint.create) + app.post('/api/blueprint/upload', middleware.ensureAuthenticated, api.blueprint.upload) + app.get('/api/blueprint/user/:slug', middleware.ensureAuthenticated, api.blueprint.show) + app.get('/api/blueprint/user', middleware.ensureAuthenticated, api.blueprint.user) + app.post('/api/blueprint/scale', middleware.ensureAuthenticated, api.blueprint.scale) + app.post('/api/blueprint/edit', middleware.ensureAuthenticated, api.blueprint.update) + app.delete('/api/blueprint/destroy', middleware.ensureAuthenticated, api.blueprint.destroy) + + app.get('/api/subscription', middleware.ensureAuthenticated, api.subscription.middleware.ensurePlans, api.subscription.middleware.ensureSubscription, api.subscription.show) + app.put('/api/subscription', middleware.ensureAuthenticated, api.subscription.middleware.ensureSubscription, api.subscription.update) + app.put('/api/subscription/sync', middleware.ensureAuthenticated, api.subscription.middleware.ensurePlans, api.subscription.middleware.ensureSubscription, api.subscription.sync) + app.delete('/api/subscription/destroy', middleware.ensureAuthenticated, api.subscription.middleware.ensureSubscription, api.subscription.destroy) + + app.get('/partials/plans', views.partials.plans) + app.get('/test/*', middleware.ensureAuthenticated, middleware.ensureIsStaff, views.modal) views.staff.route(app) diff --git a/server/lib/api/blueprint.js b/server/lib/api/blueprint.js new file mode 100644 index 0000000..e780b92 --- /dev/null +++ b/server/lib/api/blueprint.js @@ -0,0 +1,142 @@ +/* jshint node: true */ + +var _ = require('lodash'), + crypto = require('crypto'), + util = require('../util'), + upload = require('../upload'), + config = require('../../../config.json'), + Blueprint = require('../schemas/Blueprint'); + +var blueprint = { + + user: function(req, res){ + var offset = Number(req.query.offset) || 0 + var limit = Math.min( Number(req.query.limit), 50 ) || 20 + var query = { user_id: req.user._id } + if (req.query.tag) { + query.tag = req.query.tag + } + Blueprint.find(query) + .sort({'created_at': -1}) + .skip(offset) + .limit(limit) + .exec(function(err, media){ + res.json(media || []) + }) + }, + + show: function(req, res){ + Blueprint.findOne({ slug: req.params.slug }, function(err, doc){ + if (doc) { + res.json(doc) + return + } + else { + Project.count({}, function(err, count){ + var name = "Project #" + (count || 0) + res.json({ _id: "new", name: name, isNew: true }) + }) + } + }) + }, + + create: function(req, res){ + var data = util.cleanQuery(req.body) + data.user_id = req.user._id + data.created_at = new Date () + + if (data.tag) { + data.tag = util.sanitize(data.tag) + } + + new Blueprint(data).save(function(err, rec){ + if (err || ! rec) { return res.json({ error: err }) } + return res.json(rec) + }) + }, + + upload: function(req, res){ + var data = util.cleanQuery(req.body) + data.user_id = req.user._id + data.created_at = new Date () + data.type = "image" + + upload.put("media", req.files.image, { + username: req.user.username, + unacceptable: function(err){ + res.json({ error: { errors: { media: { message: "Problem saving image: " + err } } } }) + }, + success: function(url){ + data.url = url + done() + } + }) + + function done () { + new Blueprint(data).save(function(err, rec) { + if (err || ! rec) { return res.json({ error: err }) } + res.json(rec) + }) + } + }, + + scale: function(req, res){ + var _id = req.body._id + var data = util.cleanQuery(req.body) + if (! _id) { return res.json({ error: 404 }) } + Blueprint.findOne({ _id: _id }, function(err, doc){ + if (! doc) { return res.json({ error: 404 }) } + if (String(doc.user_id) !== String(req.user._id)) { return res.json({ error: 404 }) } + doc.scale = data.scale + doc.units = data.units + doc.line = data.line + doc.save(function(err, rec){ + if (err || ! rec) { return res.json({ error: err }) } + res.json(rec) + }) + }) + }, + + update: function(req, res){ + var _id = req.body._id + var data = util.cleanQuery(req.body) + if (! _id) { return res.json({ error: 404 }) } + Blueprint.findOne({ _id: _id }, function(err, doc){ + if (! doc) { return res.json({ error: 404 }) } + if (String(doc.user_id) !== String(req.user._id)) { return res.json({ error: 404 }) } + + doc.name = util.sanitize(data.name) + doc.slug = util.slugify(data.name) + doc.units = util.sanitize(data.units) + doc.viewHeight = util.sanitizeNumber(data.viewHeight) + doc.wallHeight = util.sanitizeNumber(data.wallHeight) + doc.shapes = JSON.parse(data.shapes) + doc.startPosition = JSON.parse(data.startPosition) + + doc.save(function(err, rec){ + if (err || ! rec) { return res.json({ error: err }) } + res.json(rec) + }) + }) + }, + + destroy: function(req, res){ + var _id = util.sanitize(req.body._id) + if (! _id || ! _id.length) { + res.json({ error: 404 }) + return + } + Blueprint.findOne({ _id: _id }, function(err, doc){ + if (! doc) { return res.json({ error: 404 }) } + if (String(doc.user_id) !== String(req.user._id)) { + return res.json({ error: "access denied" }) + } + Blueprint.remove({ _id: _id }, function(err){ + res.json({ status: "OK" }) + }) + }) + } + +} + +module.exports = blueprint diff --git a/server/lib/api/index.js b/server/lib/api/index.js index 11e13fc..8254232 100644 --- a/server/lib/api/index.js +++ b/server/lib/api/index.js @@ -1,6 +1,7 @@ /* jshint node: true */ var api = { + blueprint: require('./blueprint'), docs: require('./docs'), layouts: require('./layouts'), media: require('./media'), @@ -8,6 +9,7 @@ var api = { projects: require('./projects'), rooms: require('./rooms'), collaborator: require('./collaborator'), + subscription: require('./subscription'), } module.exports = api diff --git a/server/lib/api/layouts.js b/server/lib/api/layouts.js index 641e9e2..2c68f71 100644 --- a/server/lib/api/layouts.js +++ b/server/lib/api/layouts.js @@ -3,13 +3,26 @@ var _ = require('lodash'), util = require('../util'), upload = require('../upload'), + middleware = require('../middleware'), config = require('../../../config.json'), + Blueprint = require('../schemas/Blueprint'), Layout = require('../schemas/Layout'); var layouts = { index: function(req, res){ - Layout.find({}, function(err, docs){ - res.json(docs) + Layout.find({ is_stock: true }, function(err, stock_layouts){ + Layout.find({ user_id: req.user._id, is_stock: false }, function(err, user_layouts){ + Blueprint.find({ user_id: req.user._id }, function(err, blueprints){ + res.json({ + layouts: stock_layouts, + user_layouts: user_layouts, + blueprints: blueprints, + user: res.locals.user, + layoutCount: res.locals.layoutCount, + projectCount: res.locals.projectCount, + }) + }) + }) }) }, @@ -37,15 +50,24 @@ var layouts = { data.rooms = JSON.parse(data.rooms) data.startPosition = JSON.parse(data.startPosition) - upload.put("layouts", req.files.thumbnail, { - unacceptable: function(err){ - res.json({ error: { errors: { thumbnail: { message: "Problem saving thumbnail: " + err } } } }) - }, - success: function(url){ - data.photo = url - done() - } - }) + Layout.findOne({ slug: data.slug }, function(err, doc){ + if (! err || doc) { + data.slug = data.slug + "-" + Date.now() + } + do_upload() + }) + + function do_upload () { + upload.put("layouts", req.files.thumbnail, { + unacceptable: function(err){ + res.json({ error: { errors: { thumbnail: { message: "Problem saving thumbnail: " + err } } } }) + }, + success: function(url){ + data.photo = url + done() + } + }) + } function done() { new Layout(data).save(function(err, doc){ diff --git a/server/lib/api/profile.js b/server/lib/api/profile.js index 996505f..d72a2c3 100644 --- a/server/lib/api/profile.js +++ b/server/lib/api/profile.js @@ -32,6 +32,7 @@ var profile = { delete data.old_password delete data.new_password delete data.isStaff + delete data.plan_level data.updated_at = new Date () if (req.files.avatar) { diff --git a/server/lib/api/projects.js b/server/lib/api/projects.js index 1bf046f..50d3b49 100644 --- a/server/lib/api/projects.js +++ b/server/lib/api/projects.js @@ -37,9 +37,15 @@ var projects = { data.slug = util.slugify(data.name) + "-" + (+new Date) data.description = util.sanitize(data.description) data.viewHeight = Number(data.viewHeight || 0) - data.rooms = JSON.parse(data.rooms) + if (data.shapes) { + data.shapes = JSON.parse(data.shapes) + } + else { + data.rooms = JSON.parse(data.rooms) + } data.walls = JSON.parse(data.walls) data.media = JSON.parse(data.media) + data.sculpture = JSON.parse(data.sculpture) data.colors = JSON.parse(data.colors) data.startPosition = JSON.parse(data.startPosition) data.lastPosition = JSON.parse(data.lastPosition) @@ -100,11 +106,17 @@ var projects = { data.updated_at = new Date () _.extend(doc, data) - - doc.rooms = JSON.parse(data.rooms) + + if (data.shapes) { + doc.shapes = JSON.parse(data.shapes) + } + else { + doc.rooms = JSON.parse(data.rooms) + } doc.walls = JSON.parse(data.walls) doc.colors = JSON.parse(data.colors) doc.media = JSON.parse(data.media) + doc.sculpture = JSON.parse(data.sculpture) doc.startPosition = JSON.parse(data.startPosition) doc.lastPosition = JSON.parse(data.lastPosition) diff --git a/server/lib/api/rooms.js b/server/lib/api/rooms.js index c044309..2a1d2fe 100644 --- a/server/lib/api/rooms.js +++ b/server/lib/api/rooms.js @@ -6,6 +6,8 @@ var Clipper = require("../../../public/assets/javascripts/rectangles/engine/room var Builder = require("../../../public/assets/javascripts/rectangles/engine/rooms/builder.js") var Grouper = require("../../../public/assets/javascripts/rectangles/engine/rooms/grouper.js") var Walls = require("../../../public/assets/javascripts/rectangles/engine/rooms/_walls.js") +var shapes = require("../../../public/assets/javascripts/rectangles/engine/shapes/shapelist.js") +var RegionList = require("../../../public/assets/javascripts/rectangles/engine/shapes/regionlist.js") /* jshint node: true */ @@ -21,47 +23,106 @@ var rooms = module.exports = { if (! doc) { res.json({ status: 404 }); return } doc = doc.toObject() - doc.rooms.forEach(function(data){ - var rect = new Rect(data.rect.x[0], data.rect.y[0], data.rect.x[1], data.rect.y[1]) - var room = new Room({ - id: data.id, - rect: rect, - height: data.height - }) - Rooms.add(room) - }) - Rooms.clipper.solve_rects() - Rooms.builder.build() - - var walls = [], mx_walls = [], mx_floor = [], mx_ceiling = [] - var collections = Rooms.grouper.collect() - Rooms.grouper.cull(collections) - Rooms.grouper.group(walls, collections, FRONT) - Rooms.grouper.group(walls, collections, BACK) - Rooms.grouper.group(walls, collections, LEFT) - Rooms.grouper.group(walls, collections, RIGHT) - walls.forEach(function(wall){ - wall.mx.forEach(function(mx){ - var data = mx.report() - data.id = wall.id - mx_walls.push(data) - }) - }) - - doc.mx_walls = mx_walls - doc.mx_floor = mx_floor - doc.mx_ceiling = mx_ceiling - - Rooms.forEach(function(room){ - room.mx_floor.forEach(function(mx){ - mx_floor.push( mx.report() ) - }) - room.mx_ceiling.forEach(function(mx){ - mx_ceiling.push( mx.report() ) - }) - }) + if (doc.shapes.length) { + parseMxShapes(doc) + } + else { + parseMxRooms(doc) + } res.json(doc) }) } } + +function parseMxShapes (doc) { + var viewHeight = doc.viewHeight + var wallHeight = doc.wallHeight + + shapes.deserialize( doc.shapes ) + + var walls = [], mx_walls = [], mx_floor = [], mx_ceiling = [] + var regions = RegionList.build() + + regions.forEach(function(region){ + var room = new Room({ + rect: region, + regions: [region], + height: wallHeight, + }) + + room.sides = region.sides + region.id = Rooms.uid("room_") + Rooms.list[ region.id ] = room + Rooms.builder.build_walls(region) + mx_floor.push( Rooms.builder.make_floor(room, region) ) + mx_ceiling.push( Rooms.builder.make_ceiling(room, region) ) + }) + + var collections = Rooms.grouper.collect() + Rooms.grouper.cull(collections) + Rooms.grouper.group(walls, collections, FRONT) + Rooms.grouper.group(walls, collections, BACK) + Rooms.grouper.group(walls, collections, LEFT) + Rooms.grouper.group(walls, collections, RIGHT) + walls.forEach(function(wall){ + wall.mx.forEach(function(mx){ + var data = mx.report() + data.id = wall.id + mx_walls.push(data) + }) + }) + + doc.mx_walls = mx_walls + doc.mx_floor = mx_floor + doc.mx_ceiling = mx_ceiling + + Rooms.forEach(function(room){ + mx_floor.push( room.mx_floor ) + room.mx_ceiling.forEach(function(mx){ + mx_ceiling.push( mx.report() ) + }) + }) +} + +function parseMxRooms (doc) { + doc.rooms.forEach(function(data){ + var rect = new Rect(data.rect.x[0], data.rect.y[0], data.rect.x[1], data.rect.y[1]) + var room = new Room({ + id: data.id, + rect: rect, + height: data.height + }) + Rooms.add(room) + }) + Rooms.clipper.solve_rects() + Rooms.builder.build() + + var walls = [], mx_walls = [], mx_floor = [], mx_ceiling = [] + var collections = Rooms.grouper.collect() + Rooms.grouper.cull(collections) + Rooms.grouper.group(walls, collections, FRONT) + Rooms.grouper.group(walls, collections, BACK) + Rooms.grouper.group(walls, collections, LEFT) + Rooms.grouper.group(walls, collections, RIGHT) + walls.forEach(function(wall){ + wall.mx.forEach(function(mx){ + var data = mx.report() + data.id = wall.id + mx_walls.push(data) + }) + }) + + doc.mx_walls = mx_walls + doc.mx_floor = mx_floor + doc.mx_ceiling = mx_ceiling + + Rooms.forEach(function(room){ + room.mx_floor.forEach(function(mx){ + mx_floor.push( mx.report() ) + }) + room.mx_ceiling.forEach(function(mx){ + mx_ceiling.push( mx.report() ) + }) + }) +}
\ No newline at end of file diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js new file mode 100644 index 0000000..c2fff4c --- /dev/null +++ b/server/lib/api/subscription.js @@ -0,0 +1,206 @@ +/* jshint node: true */ + +var _ = require('lodash'), + util = require('../util'), + upload = require('../upload'), + config = require('../../../config.json'), + User = require('../schemas/User'), + Project = require('../schemas/Project'), + Layout = require('../schemas/Layout'), + Plan = require('../schemas/Plan'); + Subscription = require('../schemas/Subscription'), + Recurly = require('node-recurly'), + recurly = new Recurly(require('../webhook/recurly-config')); + +var plan_levels = { + free: 0, + basic: 1, + pro: 2, + custom: 3, +} + +var subscription = module.exports = { + middleware: { + ensureSubscription: function(req, res, next){ + Subscription.findOne({ user_id: req.user._id }, function(err, data){ + if (err) { return next() } + req.subscription = data + next() + }) + }, + ensurePlans: function(req, res, next){ + Plan.find({}).sort({ 'level': 1 }).exec(function (err, plans) { + res.locals.plans = (plans || []) + next() + }) + }, + }, + + // synchronise an account with recurly.. + // useful when testing locally (where webhooks cannot be received) + // parses the XML from the subscription API into something usable + sync: function(req, res){ + var subscriber = req.subscription || new Subscription () + var user = req.user + recurly.subscriptions.listByAccount(req.user._id, function(recurlyRes){ + var data = recurlyRes.data + if (recurlyRes.description !== 200) { + res.json({ error: "no account" }) + return + } + var subscriptions = data.subscriptions.subscription.length ? data.subscriptions.subscription : [data.subscriptions.subscription] + var is_active = subscriptions.some(function(subscription_data){ + if (subscription_data.state == "active") { + set_active(subscription_data) + return true + } + return false + }) + if (! is_active) { + set_cancelled() + } + }) + function set_cancelled(){ + user.plan_type = "free" + user.plan_level = plan_levels["free"] + + return subscriber.remove(function(){ + user.save(function(){ + res.json({ error: "account cancelled" }) + }) + }) + } + function set_active(data){ + var plan = data.plan.plan_code.split("-") + var plan_type = plan[0] + var plan_period = plan[1] + + user.plan_type = plan_type + user.plan_level = plan_levels[plan_type] + + subscriber.uuid = data.uuid + subscriber.user_id = user._id + subscriber.plan_type = plan_type + subscriber.plan_period = plan_period + subscriber.plan_level = plan_levels[plan_type] + + var add_ons = data.subscription_add_ons.subscription_add_on + if (add_ons) { + if (add_ons.add_on_code) { + add_ons = [ add_ons ] + } + // TODO: handle multiple add-ons.. presumably this will work + add_ons.forEach(function(add_on){ + var add_on_type = add_on.add_on_code.split("-")[1] + if (add_on_type == "basic") { + subscriber.basic_layouts = parseInt( add_on.quantity._ ) + } + if (add_on_type == "pro") { + subscriber.pro_layouts = parseInt( add_on.quantity._ ) + } + }) + } + else { + subscriber.basic_layouts = 0 + subscriber.pro_layouts = 0 + } + subscriber.save(function(){ + user.save(function(){ + res.json({ + subscription: subscriber, + plans: res.locals.plans + }) + }) + }) + } + }, + + show: function(req, res){ + if (req.subscription) { + res.json({ + subscription: req.subscription, + plans: res.locals.plans + }) + } + else { + res.json({ + error: "no subscription", + plans: res.locals.plans, + }) + } + }, + + update: function(req, res){ + if (! req.subscription ) { + return res.json({ error: "no subscription" }) + } + if (! (req.body.plan_type in plan_levels)) { + return res.json({ error: "bad input" }) + } + var subscriber = req.subscription + var user = req.user + + var plan_type = req.body.plan_type + var basic_layouts = Math.max(0, parseInt(req.body.basic_layouts || 0, 10)) + var pro_layouts = Math.max(0, parseInt(req.body.pro_layouts || 0, 10)) + if (plan_type != "pro") { pro_layouts = 0 } + + if (plan_type == subscription.plan_type + && basic_layouts == subscriber.basic_layouts + && pro_layouts == subscriber.pro_layouts) { + return res.json(subscriber) + } + + var data = { subscription_add_ons: [] } + data.plan_code = plan_type + "-monthly" + + if (plan_levels[plan_type] > 0 && basic_layouts > 0) { + data.subscription_add_ons.push({ add_on_code: "extra-basic-layout", quantity: basic_layouts }) + } + + if (plan_type == "pro" && pro_layouts > 0) { + data.subscription_add_ons.push({ add_on_code: "extra-pro-layout", quantity: pro_layouts }) + } + + // data.plan_code + // data.subscription_add_ons = [] + // add_on.add_on_code + // add_on.quantity + console.log(data) + recurly.subscriptions.update(subscriber.uuid, data, function(err, data){ + console.log("got response from RECURLY ...") + if (err) { + console.log("error updating recurly subscription", err) + return res.json({ error: err }) + } + subscriber.plan_type = plan_type + subscriber.basic_layouts = basic_layouts + subscriber.pro_layouts = pro_layouts + subscriber.save(function(){ + user.plan_level = plan_levels[plan_type] + user.plan_type = plan_type + user.save(function(){ + return res.json(subscriber) + }) + }) + }) + }, + + destroy: function(req, res){ + if (! req.subscription ) { + return res.json({ error: "no subscription" }) + } + var subscriber = req.subscription + + recurly.subscriptions.terminate(subscriber.uuid, "partial", function(err, data){ + subscriber.remove(function(){ + req.user.plan_code = 0 + req.user.plan_type = "free" + req.user.save(function(){ + res.json({ status: "OK" }) + }) + }) + }) + }, + +};
\ No newline at end of file diff --git a/server/lib/auth/index.js b/server/lib/auth/index.js index a9a2400..46bff21 100644 --- a/server/lib/auth/index.js +++ b/server/lib/auth/index.js @@ -39,7 +39,14 @@ var auth = { auth.mail.init() }, - + initBasicAuth: function(app){ + if (config.basicAuth) { + app.use(express.basicAuth(function(user, pass) { + return user === config.basicAuth.user && + pass === config.basicAuth.pass + })) + } + }, initSockets: function (io, SessionStore) { io.set('authorization', passportSocketIo.authorize({ cookieParser: express.cookieParser, @@ -135,12 +142,12 @@ var auth = { deserializeUser: function (id, done) { try { var _id = mongoose.Types.ObjectId(id) - User.findOne({ _id: _id }, "_id displayName username photo isStaff", function (err, user) { + User.findOne({ _id: _id }, "_id displayName username photo isStaff plan_level", function (err, user) { done(err, user); }); } catch (e) { - User.findOne({ twitter_id: id }, "_id displayName username photo isStaff", function (err, user) { + User.findOne({ twitter_id: id }, "_id displayName username photo isStaff plan_level", function (err, user) { done(err, user); }); } @@ -240,7 +247,7 @@ var auth = { facebookUrl: profile.username ? "https://facebook.com/" + profile.username : "" }; - User.findOne({twitter_id: profile.id}, function(err, data){ + User.findOne({facebook_id: profile.id}, function(err, data){ if (! err && data) { return done(err, data); } diff --git a/server/lib/auth/mail.js b/server/lib/auth/mail.js index eac4007..990b53f 100644 --- a/server/lib/auth/mail.js +++ b/server/lib/auth/mail.js @@ -6,7 +6,7 @@ var email = require("emailjs"), var mail = { - from: 'VValls <info@vvalls.com>', + from: 'VValls <hello@vvalls.com>', templates: {}, init: function(){ diff --git a/server/lib/middleware.js b/server/lib/middleware.js index 4848ab0..0a0a9ce 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -6,11 +6,16 @@ var passport = require('passport'), config = require('../../config.json'), User = require('./schemas/User'), Collaborator = require('./schemas/Collaborator'), - Project = require('./schemas/Project'); + Project = require('./schemas/Project'), + Layout = require('./schemas/Layout'), + Blueprint = require('./schemas/Blueprint'), + Plan = require('./schemas/Plan'); var middleware = { + plans: [], + enableCORS: function (req, res, next) { res.header('Access-Control-Allow-Credentials', true); // TODO Check https vs. http @@ -46,7 +51,7 @@ var middleware = { }, ensureLocals: function (req, res, next) { - res.locals.token = req.csrfToken(); + res.locals.token = req.csrfToken() res.locals.logged_in = req.isAuthenticated() res.locals.user = req.user || { _id: undefined } res.locals.config = config @@ -56,10 +61,31 @@ var middleware = { res.locals.ogUrl = "http://vvalls.com/" res.locals.ogDescription = "3D gallery space, fully customizable" res.locals.ogAuthor = "VValls" + res.locals.plans = middleware.plans res.locals.opt = {} next() }, - + + ensureUserProjectsCount: function(req, res, next){ + var counts = { stock: 0, basic: 0, pro: 0 } + res.locals.projectCounts = counts + Project.count({ user_id: req.user._id }, function(err, count){ + res.locals.projectCount = count || 0 + next() + }) + }, + + ensureUserLayoutsCount: function(req, res, next){ + var counts = { basic: 0, pro: 0 } + res.locals.layoutCounts = counts + if (req.user.plan_level == 0) { return next() } + + Layout.count({ user_id: req.user._id }, function(err, count){ + res.locals.layoutCount = count || 0 + next() + }) + }, + ensureProject: function (req, res, next) { if (req.params.slug) { Project.findOne({ slug: req.params.slug }, function(err, project){ @@ -75,13 +101,57 @@ var middleware = { } next() }) - } + } else { req.project = null next() } }, + ensureLayout: function (req, res, next) { + if (req.params.slug) { + Layout.findOne({ slug: req.params.slug }, function(err, layout){ + if (err) { + console.error(err) + req.layout = null + } + else if (! layout) { + req.layout = null + } + else { + req.layout = layout + } + next() + }) + } + else { + req.layout = null + next() + } + }, + + ensureBlueprint: function (req, res, next) { + if (req.params.slug) { + Blueprint.findOne({ slug: req.params.slug }, function(err, blueprint){ + if (err) { + console.error(err) + req.blueprint = null + } + else if (! blueprint) { + req.blueprint = null + } + else { + req.blueprint = blueprint + } + next() + }) + } + else { + req.blueprint = null + next() + } + }, + ensureIsCollaborator: function(req, res, next) { req.isCollaborator = false req.isOwner = false @@ -106,6 +176,12 @@ var middleware = { }) } }, + + updatePlans: function(){ + Plan.find({}).sort({ 'level': -1 }).exec(function (err, plans) { + middleware.plans = plans.map(function(plan){ return plan.toObject() }) + }) + }, } diff --git a/server/lib/schemas/Blueprint.js b/server/lib/schemas/Blueprint.js new file mode 100644 index 0000000..3c3b0cc --- /dev/null +++ b/server/lib/schemas/Blueprint.js @@ -0,0 +1,66 @@ +/* jshint node: true */ + +var mongoose = require('mongoose'), + _ = require('lodash'), + util = require('../util'); + +var BlueprintSchema = new mongoose.Schema({ + type: { + type: String, + required: true + }, + url: { + type: String, + required: true, + }, + token: { + type: String, + default: "" + }, + thumbnail: { + type: String, + default: "" + }, + width: { + type: Number, + default: 0 + }, + height: { + type: Number, + default: 0 + }, + name: { + type: String, + default: "" + }, + slug: { + type: String, +// required: true, + validate: [function (val){ + val = util.sanitize(val || this.displayName || "") +// if (! val.length) return false + return true + },"{PATH} name is required"] + }, + description: { + type: String, + default: "" + }, + tag: { type: String, default: "" }, + scale: { type: Number, default: 1.0 }, + + widthDimension: { type: Number }, + heightDimension: { type: Number }, + wallHeight: { type: Number }, + units: { type: String }, + line: { type: String }, + + shapes: [mongoose.Schema.Types.Mixed], + startPosition: mongoose.Schema.Types.Mixed, + + user_id: { type: mongoose.Schema.ObjectId, index: true }, + created_at: { type: Date }, +}); + +module.exports = exports = mongoose.model('blueprint', BlueprintSchema) +exports.schema = BlueprintSchema; diff --git a/server/lib/schemas/Layout.js b/server/lib/schemas/Layout.js index e3f2616..e15e188 100644 --- a/server/lib/schemas/Layout.js +++ b/server/lib/schemas/Layout.js @@ -23,9 +23,12 @@ var LayoutSchema = new mongoose.Schema({ photo: { type: String, }, + media: mongoose.Schema.Types.Mixed, rooms: [mongoose.Schema.Types.Mixed], startPosition: mongoose.Schema.Types.Mixed, viewHeight: { type: Number }, + is_stock: { type: Boolean, default: false }, + is_pro: { type: Boolean, default: false }, user_id: { type: mongoose.Schema.ObjectId, index: true }, created_at: { type: Date }, updated_at: { type: Date }, diff --git a/server/lib/schemas/Media.js b/server/lib/schemas/Media.js index 1de354d..f37fb12 100644 --- a/server/lib/schemas/Media.js +++ b/server/lib/schemas/Media.js @@ -37,11 +37,12 @@ var MediaSchema = new mongoose.Schema({ type: String, default: "" }, - autoplay: { type: Boolean, default: false }, - loop: { type: Boolean, default: false }, - mute: { type: Boolean, default: true }, + autoplay: { type: Boolean, default: true }, + loop: { type: Boolean, default: true }, + mute: { type: Boolean, default: false }, keyframe: { type: Number, default: 0.0 }, tag: { type: String, default: "" }, + scale: { type: Number, default: 1.0 }, widthDimension: { type: Number }, heightDimension: { type: Number }, diff --git a/server/lib/schemas/Plan.js b/server/lib/schemas/Plan.js new file mode 100644 index 0000000..388ce69 --- /dev/null +++ b/server/lib/schemas/Plan.js @@ -0,0 +1,44 @@ +/* jshint node: true */ + +var mongoose = require('mongoose'), + _ = require('lodash'), + crypto = require('crypto'), + config = require('../../../config.json'), + util = require('../util'); + +var PlanSchema = new mongoose.Schema({ + name: { type: String }, + slug: { type: String }, + + level: { type: Number }, + + monthly_price: { type: Number }, + yearly_price: { type: Number }, + + basic_layout_monthly_price: { type: Number }, + basic_layout_yearly_price: { type: Number }, + + pro_layout_monthly_price: { type: Number }, + pro_layout_yearly_price: { type: Number }, + + basic_layout_limit: { type: Number }, + pro_layout_limit: { type: Number }, + + stock_project_limit: { type: Number }, + basic_project_limit: { type: Number }, + pro_project_limit: { type: Number }, + + permissions: { + basic_editor: { type: Boolean, default: false }, + pro_editor: { type: Boolean, default: false }, + sculpture: { type: Boolean, default: false }, + collaborators: { type: Boolean, default: false }, + no_logo: { type: Boolean, default: false }, + }, + + created_at: { type: Date, default: Date.now }, + updated_at: { type: Date, default: Date.now }, +}) + +module.exports = exports = mongoose.model('plan', PlanSchema); +exports.schema = PlanSchema; diff --git a/server/lib/schemas/Project.js b/server/lib/schemas/Project.js index a923d85..687555d 100644 --- a/server/lib/schemas/Project.js +++ b/server/lib/schemas/Project.js @@ -28,16 +28,20 @@ var ProjectSchema = new mongoose.Schema({ type: String, }, rooms: [mongoose.Schema.Types.Mixed], + shapes: [mongoose.Schema.Types.Mixed], walls: [mongoose.Schema.Types.Mixed], media: [mongoose.Schema.Types.Mixed], + sculpture: [mongoose.Schema.Types.Mixed], colors: mongoose.Schema.Types.Mixed, startPosition: mongoose.Schema.Types.Mixed, lastPosition: mongoose.Schema.Types.Mixed, viewHeight: { type: Number }, + units: { type: String, default: "ft" }, user_id: { type: mongoose.Schema.ObjectId, index: true }, created_at: { type: Date }, updated_at: { type: Date }, featured: { type: Boolean, default: false }, + layout_type: { type: Number, default: 0 }, }); module.exports = exports = mongoose.model('project', ProjectSchema); diff --git a/server/lib/schemas/Subscription.js b/server/lib/schemas/Subscription.js new file mode 100644 index 0000000..bf43e8b --- /dev/null +++ b/server/lib/schemas/Subscription.js @@ -0,0 +1,31 @@ +/* jshint node: true */ + +var mongoose = require('mongoose'), + _ = require('lodash'), + crypto = require('crypto'), + config = require('../../../config.json'), + util = require('../util'); + +var SubscriptionSchema = new mongoose.Schema({ + user_id: { type: mongoose.Schema.ObjectId, index: true }, + + plan_code: { type: String, default: "" }, + plan_type: { type: String, default: "free" }, + plan_period: { type: String, default: "monthly" }, + + uuid: { type: String }, + basic_layouts: { type: Number, default: 0 }, + pro_layouts: { type: Number, default: 0 }, + + history: [{ + action: { type: String }, + data: { type: String }, + created_at: { type: Date, default: Date.now }, + }], + + created_at: { type: Date, default: Date.now }, + updated_at: { type: Date, default: Date.now }, +}) + +module.exports = exports = mongoose.model('subscription', SubscriptionSchema); +exports.schema = SubscriptionSchema; diff --git a/server/lib/schemas/User.js b/server/lib/schemas/User.js index 180a140..829b360 100644 --- a/server/lib/schemas/User.js +++ b/server/lib/schemas/User.js @@ -54,7 +54,12 @@ var UserSchema = new mongoose.Schema({ type: String, default: "", }, - + + plan_code: { type: String, default: "" }, + plan_level: { type: Number, default: 0 }, + plan_type: { type: String, default: "free" }, + last_charged: { type: Date, default: null }, + location: { type: String, default: "" }, photo: { type: String, default: "" }, bio: { type: String, default: "" }, @@ -62,6 +67,8 @@ var UserSchema = new mongoose.Schema({ twitterName: { type: String, default: "" }, facebookUrl: { type: String, default: "" }, isStaff: { type: Boolean, default: false }, + isArtist: { type: Boolean, default: false }, + subscription_id: { type: mongoose.Schema.ObjectId }, created_at: { type: Date }, updated_at: { type: Date }, last_seen: { type: Date }, diff --git a/server/lib/util.js b/server/lib/util.js index e3fd1ed..86fbdcc 100644 --- a/server/lib/util.js +++ b/server/lib/util.js @@ -5,6 +5,7 @@ var whitespace = new RegExp('\\s', 'g') var whitespaceHead = /^\s+/ var whitespaceTail = /\s+$/ var nonAlphanumerics = new RegExp('[^-_a-zA-Z0-9]', 'g') +var nonNumerics = new RegExp('[^0-9]', 'g') var consecutiveDashes = new RegExp("-+", 'g') var entities = new RegExp("[<>&]", 'g') @@ -19,6 +20,9 @@ util.slugify = function (s){ util.sanitize = function (s){ return (s || "").replace(entities, "") } +util.sanitizeNumber = function (s){ + return (s || "").replace(nonNumerics, "") +} util.escape = function (s){ return (s || "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") } diff --git a/server/lib/views/index.js b/server/lib/views/index.js index 8c3e63d..523f628 100644 --- a/server/lib/views/index.js +++ b/server/lib/views/index.js @@ -4,6 +4,7 @@ var User = require('../schemas/User'), Project = require('../schemas/Project'), Documentation = require('../schemas/Documentation'), Collaborator = require('../schemas/Collaborator'), + Plan = require('../schemas/Plan'), config = require('../../../config'), marked = require('marked'), util = require('../util'), @@ -83,33 +84,42 @@ var views = module.exports = { res.render('builder') }, + blueprint: function (req, res) { + res.render('blueprint') + }, + modal: function (req, res) { res.render('modal'); }, home: function (req, res) { - // while in development, blank homepage if not logged in -/* - if (! req.user) { - res.send("<html></html>") - return - } -*/ - views_middleware.fetchProjects({ featured: true }, null, null, function(err, projects){ - res.render('home', { - projects: projects || [] + views_middleware.ensurePlans(req, res, function(err){ + views_middleware.fetchProjects({ featured: true }, null, null, function(err, projects){ + res.render('home', { + projects: projects || [], + }) }) }) }, demoHome: function (req, res) { - views_middleware.fetchProjects({ featured: true }, null, null, function(err, projects){ - res.render('home', { - projects: projects || [] + views_middleware.ensurePlans(req, res, function(err){ + views_middleware.fetchProjects({ featured: true }, null, null, function(err, projects){ + res.render('home', { + projects: projects || [], + }) }) }) }, + partials: { + plans: function (req, res){ + views_middleware.ensurePlans(req, res, function(){ + res.render('about/_plans', { logged_in: res.locals.logged_in || false }) + }) + }, + }, + docs: function (req, res){ var name = req.params.name || "about" @@ -117,6 +127,13 @@ var views = module.exports = { res.render('about/' + name) return } + if (name == "brochure" || name == "plans") { + // TODO: fetch plans + views_middleware.ensurePlans(req, res, function(){ + res.render('about/' + name) + }) + return + } if (name == "about" || name == "index") { res.render('about/' + name) return @@ -225,6 +242,19 @@ var views = module.exports = { } var views_middleware = { + ensurePlans: function(req, res, next){ + Plan.find(function (err, plans) { + res.locals.plans = {} + plans.forEach(function(plan){ + res.locals.plans[ plan.slug ] = plan + "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price pro_layout_monthly_price pro_layout_yearly_price".split(" ").forEach(function(key){ + plan[key] = (plan[key]/100).toFixed(2)+"" + }) + }) + next() + }) + }, + fetchProjects: function (criteria, limit, offset, next) { limit = limit || 7 offset = offset || 0 diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js deleted file mode 100644 index 49f492b..0000000 --- a/server/lib/views/staff.js +++ /dev/null @@ -1,545 +0,0 @@ -/* jshint node: true */ - -var User = require('../schemas/User'), - Project = require('../schemas/Project'), - Media = require('../schemas/Media'), - Collaborator = require('../schemas/Collaborator'), - config = require('../../../config'), - middleware = require('../middleware'), - util = require('../util'), - _ = require('lodash'), - moment = require('moment'); - - -var staff = module.exports = { - - fields: { - user: "_id username displayName photo created_at updated_at last_seen created_ip last_ip", - project: "_id name slug user_id privacy created_at updated_at", - }, - - defaults: { - user: { - _id: "", username: "", displayName: "", - created_at: "", updated_at: "", created_ip: "", last_ip: "", - }, - }, - - middleware: { - - ensureUsers: function(req, res, next){ - var paginationInfo = res.locals.pagination = {} - var criteria = req.criteria || {} - var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) - var offset = paginationInfo.offset = Number(req.query.offset) || 0 - var sort - paginationInfo.sort = req.query.sort - paginationInfo.sortOptions = ["date", "last_seen", "username"] - switch (req.query.sort) { - case 'date': - sort = {'created_at': -1} - break - case 'last_seen': - sort = {'last_seen': -1} - break - case 'username': - default: - sort = {'username': 1} - paginationInfo.sort = "username" - break - } - User.find(criteria) - .select(staff.fields.user) - .sort(sort) - .skip(offset) - .limit(limit) - .exec(function (err, users) { - res.locals.users = users.map(staff.helpers.user) - next() - }) - }, - - ensureRecentUsers: function(req, res, next){ - var dreq = { query: { sort: 'last_seen', limit: 20, offset: 0 } } - staff.middleware.ensureUsers(dreq, res, next) - }, - - ensureProjects: function(req, res, next){ - var paginationInfo = res.locals.pagination = {} - var criteria = req.criteria || {} - var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) - var offset = paginationInfo.offset = Number(req.query.offset) || 0 - var sort - paginationInfo.sort = req.query.sort - paginationInfo.sortOptions = ["date", "name"] - switch (req.query.sort) { - default: - case 'date': - sort = {'updated_at': -1} - break - case 'name': - paginationInfo.sort = "name" - sort = {'slug': 1} - break - } - Project.find(criteria) - .select(staff.fields.project) - .sort(sort) - .skip(offset) - .limit(limit) - .exec(function (err, projects) { - res.locals.projects = projects.map(staff.helpers.project) - next() - }) - }, - - ensureMedia: function(req, res, next){ - var paginationInfo = res.locals.pagination = {} - var criteria = req.criteria || {} - var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) - var offset = paginationInfo.offset = Number(req.query.offset) || 0 - var sort - paginationInfo.sort = req.query.sort - paginationInfo.sortOptions = ["date"] - switch (req.query.sort) { - default: - case 'date': - paginationInfo.sort = "date" - sort = {'created_at': -1} - break - } - Media.find(criteria) - // .select(staff.fields.media) - .sort(sort) - .skip(offset) - .limit(limit) - .exec(function (err, media) { - res.locals.media = media.map(staff.helpers.media) - next() - }) - }, - - ensureRecentProjects: function(req, res, next){ - var dreq = { params: { sort: 'created_at', limit: 20, offset: 0 } } - staff.middleware.ensureProjects(dreq, res, next) - }, - - ensureProjectsUsers: function(req, res, next){ - if (! res.locals.projects || ! res.locals.projects.length) { return next() } - staff.middleware.ensureObjectsUsers(res.locals.projects, next) - }, - - ensureMediaUsers: function(req, res, next){ - if (! res.locals.media || ! res.locals.media.length) { return next() } - staff.middleware.ensureObjectsUsers(res.locals.media, next) - }, - - ensureMediaUser: function(req, res, next){ - if (! res.locals.media) { return next() } - staff.middleware.ensureObjectsUsers([ res.locals.media ], function(){ - res.locals.mediaUser = res.locals.media.User - next() - }) - }, - - ensureObjectsUsers: function(objects, next){ - if (! objects) { return next () } - var dedupe = {}, user_ids - objects.forEach(function(obj){ - dedupe[ obj.user_id ] = dedupe[ obj.user_id ] || [] - dedupe[ obj.user_id ].push(obj) - }) - user_ids = _.keys(dedupe) - User.find({ _id: { $in: user_ids } }) - .select(staff.fields.user) - .exec(function (err, users) { - if (! users) { return next () } - users.forEach(function(user){ - dedupe[user._id].forEach(function(obj){ - obj.user = user - }) - }) - next() - }) - }, - - ensureProfile: function(req, res, next){ - var username = req.params.username - if (username) { - User.findOne({ username: username }, function (err, user) { - if (user) { - res.locals.profile = req.method == "GET" ? staff.helpers.user(user) : user - } - else { - res.locals.profile = null - } - next() - }) - } - else { - res.locals.profile = null - next() - } - }, - - ensureSingleMedia: function(req, res, next){ - var id = req.params.id - if (id) { - Media.findOne({ _id: id }, function (err, media) { - if (media) { - res.locals.media = req.method == "GET" ? staff.helpers.media(media) : media - } - else { - res.locals.media = null - } - next() - }) - } - else { - res.locals.media = null - next() - } - }, - - ensureUsersCount: function(req, res, next){ - User.count({}, function(err, count){ - res.locals.userCount = count || 0 - next() - }) - }, - - ensureProjectsCount: function(req, res, next){ - Project.count({}, function(err, count){ - res.locals.projectCount = count || 0 - next() - }) - }, - - ensureMediaCount: function(req, res, next){ - Media.count({}, function(err, count){ - res.locals.mediaCount = count || 0 - next() - }) - }, - - ensureProfileProjectCount: function(req, res, next){ - if (! res.locals.profile) { return next() } - Project.count({ user_id: res.locals.profile._id}, function(err, count){ - res.locals.profile.projectCount = count || 0 - next() - }) - }, - - ensureProfileMediaCount: function(req, res, next){ - if (! res.locals.profile) { return next() } - Media.count({ user_id: res.locals.profile._id}, function(err, count){ - res.locals.profile.mediaCount = count || 0 - next() - }) - }, - - ensureProfileProjects: function(req, res, next){ - if (! res.locals.profile) { return next() } - Project.find({ user_id: res.locals.profile._id }, staff.fields.project, function(err, projects){ - res.locals.projects = projects.map(staff.helpers.project) - next() - }) - }, - - ensureProfileMedia: function(req, res, next){ - if (! res.locals.profile) { return next() } - req.criteria = { user_id: res.locals.profile._id } - staff.middleware.ensureMedia(req, res, next) - }, - - ensureProject: function(req, res, next){ - res.locals.project = req.project - next() - }, - - ensureProjectUser: function(req, res, next){ - if (! res.locals.project) { return next() } - User.findOne({ _id: res.locals.project.user_id }, staff.fields.user, function(err, user){ - res.locals.projectUser = staff.helpers.user(user) || staff.defaults.user - next() - }) - }, - - ensureProjectCollaborators: function(req, res, next){ - if (! res.locals.project) { - res.locals.collaborators = [] - return next() - } - Collaborator.find({ project_id: res.locals.project._id}, function(err, collaborators){ - res.locals.collaborators = collaborators || [] - next() - }) - }, - }, - - helpers: { - user: function(user){ - user = user.toObject() - user.last_seen = moment( user.last_seen || user.updated_at || user.created_at ).fromNow() - user.created_ip = util.num2ip( user.created_ip ) - user.last_ip = util.num2ip( user.last_ip ) - return user - }, - - project: function(project){ - project = project.toObject() - project.date = moment( project.updated_at || project.created_at ).format("M/DD/YYYY hh:mm a") - project.user = {} - return project - }, - - media: function(media){ - media = media.toObject() - media.date = moment( media.updated_at || media.created_at ).format("M/DD/YYYY hh:mm a") - media.user = {} - media.shortUrl = media.url.replace(/^http.:\/\//,"") - return media - } - }, - - route: function(app){ - app.get('/staff', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureRecentUsers, - staff.middleware.ensureUsersCount, - staff.middleware.ensureProjectsCount, - staff.middleware.ensureMediaCount, - - staff.index - ); - - // - // users - - app.get('/staff/users', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureUsersCount, - staff.middleware.ensureUsers, - - staff.users.index - ); - app.get('/staff/users/:username', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureProfile, - staff.middleware.ensureProfileProjectCount, - staff.middleware.ensureProfileMediaCount, - staff.middleware.ensureProfileProjects, - - staff.users.show - ); - app.get('/staff/users/:username/media', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureProfile, - staff.middleware.ensureProfileMedia, - staff.middleware.ensureProfileMediaCount, - - staff.users.media - ); - app.put('/staff/users/:username/bless', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureProfile, - - staff.users.bless - ); - - if (app.get('env') === 'development') { - app.get('/staff/authorize', - middleware.ensureAuthenticated, - staff.users.blessSelf - ); - } - - // - // projects - - app.get('/staff/projects', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureProjectsCount, - - staff.middleware.ensureProjects, - staff.middleware.ensureProjectsUsers, - - staff.projects.index - ); - app.get('/staff/projects/:slug', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - middleware.ensureProject, - staff.middleware.ensureProject, - staff.middleware.ensureProjectUser, - staff.middleware.ensureProjectCollaborators, - - staff.projects.show - ); - app.put('/staff/projects/:slug/feature', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - middleware.ensureProject, - staff.middleware.ensureProject, - - staff.projects.feature - ); - - // - // media - - app.get('/staff/media', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureMediaCount, - - staff.middleware.ensureMedia, - staff.middleware.ensureMediaUsers, - - staff.media.index - ); - app.get('/staff/media/:id', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureSingleMedia, - staff.middleware.ensureMediaUser, - - staff.media.show - ); - - }, - - paginate: function(req, res){ - var info = res.locals.pagination - info.query = "sort=" + info.sort + "&limit=" + info.limit - info.first_page = 0 - info.last_page = Math.max(0, info.max - info.limit) - info.sortOptions = info.sortOptions - if (info.offset > 0) { - info.prev_page = Math.max(0, info.offset - info.limit) - } - else { - info.prev_page = -1 - } - if (info.count == info.limit && info.offset + info.limit < info.max) { - info.next_page = info.offset + info.limit - } - else { - info.next_page = -1 - } - }, - - index: function(req, res){ - res.render('staff/index') - }, - - // /staff/users/ - // /staff/users/:username - users: { - index: function(req, res){ - res.locals.pagination.count = res.locals.users.length - res.locals.pagination.max = res.locals.userCount - staff.paginate(req, res) - res.render('staff/users/index') - }, - show: function(req, res){ - if (res.locals.profile) { - res.render('staff/users/show', { - profileJSON: util.escape( JSON.stringify( res.locals.profile ) ) - }) - } - else { - res.render('staff/users/show_404') - } - }, - media: function(req, res){ - if (res.locals.profile) { - res.locals.pagination.count = res.locals.media.length - res.locals.pagination.max = res.locals.profile.mediaCount - staff.paginate(req, res) - res.render('staff/users/media') - } - else { - res.render('staff/users/show_404') - } - }, - blessSelf: function(req, res){ - req.user.isStaff = true - req.user.save(function(err, user){ - res.json({ state: user.isStaff }) - }) - }, - bless: function(req, res){ - res.locals.profile.isStaff = req.body.state == "true" - res.locals.profile.save(function(err, user){ - res.json({ state: user.isStaff }) - }) - }, - }, - - // /staff/projects/ - // /staff/projects/:name - projects: { - index: function(req, res){ - res.locals.pagination.count = res.locals.projects.length - res.locals.pagination.max = res.locals.projectCount - staff.paginate(req, res) - res.render('staff/projects/index') - }, - show: function(req, res){ - if (res.locals.project) { - res.render('staff/projects/show', { - projectJSON: util.escape( JSON.stringify( res.locals.project ) ), - projectUserJSON: util.escape( JSON.stringify( res.locals.projectUser ) ), - collaboratorsJSON: util.escape( JSON.stringify( res.locals.collaborators ) ), - }) - } - else { - res.render('staff/projects/show_404') - } - }, - feature: function(req, res){ - res.locals.project.featured = req.body.state == "true" - res.locals.project.save(function(err, project){ - res.json({ state: project.featured }) - }) - }, - }, - - media: { - index: function(req, res){ - res.locals.pagination.count = res.locals.media.length - res.locals.pagination.max = res.locals.mediaCount - staff.paginate(req, res) - res.render('staff/media/index') - }, - show: function(req, res){ - if (res.locals.media) { - res.render('staff/media/show', { - mediaJSON: util.escape( JSON.stringify( res.locals.media ) ), - mediaUserJSON: util.escape( JSON.stringify( res.locals.mediaUser ) ), - }) - } - else { - res.render('staff/media/show_404') - } - }, - } - -} diff --git a/server/lib/views/staff/defaults.js b/server/lib/views/staff/defaults.js new file mode 100644 index 0000000..4d86c41 --- /dev/null +++ b/server/lib/views/staff/defaults.js @@ -0,0 +1,6 @@ +module.exports = { + user: { + _id: "", username: "", displayName: "", + created_at: "", updated_at: "", created_ip: "", last_ip: "", + }, +} diff --git a/server/lib/views/staff/fields.js b/server/lib/views/staff/fields.js new file mode 100644 index 0000000..84c1efa --- /dev/null +++ b/server/lib/views/staff/fields.js @@ -0,0 +1,10 @@ +module.exports = { + user: "_id username displayName photo created_at updated_at last_seen created_ip last_ip", + project: "_id name slug user_id privacy layout_type created_at updated_at", + layout: "_id name slug user_id layout_type is_stock created_at updated_at", + blueprint: "_id name slug user_id created_at updated_at", + plans: "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price " + + "pro_layout_monthly_price pro_layout_yearly_price " + + "basic_layout_limit pro_layout_limit stock_project_limit basic_project_limit pro_project_limit", + plans_permissions: "basic_editor pro_editor sculpture collaborators no_logo", +} diff --git a/server/lib/views/staff/helpers.js b/server/lib/views/staff/helpers.js new file mode 100644 index 0000000..ff4065a --- /dev/null +++ b/server/lib/views/staff/helpers.js @@ -0,0 +1,59 @@ + +var util = require('../../util'), + _ = require('lodash'), + moment = require('moment'); + +module.exports = { + user: function(user){ + var last_seen = moment( user.last_seen || user.updated_at || user.created_at ) + user = user.toObject() + user.last_seen = last_seen.format("YYYY/MM/DD HH:MM") + " " + last_seen.fromNow() + user.last_charged = user.last_charged && moment( user.last_charged ).format("YYYY/MM/DD HH:MM") + user.created_ip = util.num2ip( user.created_ip ) + user.last_ip = util.num2ip( user.last_ip ) + return user + }, + + project: function(project){ + project = project.toObject() + project.date = moment( project.updated_at || project.created_at ).format("M/DD/YYYY hh:mm a") + project.user = {} + return project + }, + + layout: function(layout){ + layout = layout.toObject() + layout.date = moment( layout.updated_at || layout.created_at ).format("M/DD/YYYY hh:mm a") + layout.user = {} + return layout + }, + + blueprint: function(blueprint){ + blueprint = blueprint.toObject() + blueprint.date = moment( blueprint.updated_at || blueprint.created_at ).format("M/DD/YYYY hh:mm a") + blueprint.user = {} + return blueprint + }, + + media: function(media){ + media = media.toObject() + media.date = moment( media.updated_at || media.created_at ).format("M/DD/YYYY hh:mm a") + media.user = {} + media.shortUrl = media.url.replace(/^http.?:\/\//,"") + return media + }, + + plan: function(plan){ + plan = plan.toObject() + plan.date = moment( plan.updated_at || plan.created_at ).format("M/DD/YYYY hh:mm a") + plan.user = {} + return plan + }, + + subscription: function(subscription){ + subscription = subscription.toObject() + subscription.date = moment( subscription.updated_at || subscription.created_at ).format("M/DD/YYYY hh:mm a") + subscription.user = {} + return subscription + }, +} diff --git a/server/lib/views/staff/index.js b/server/lib/views/staff/index.js new file mode 100644 index 0000000..49a0384 --- /dev/null +++ b/server/lib/views/staff/index.js @@ -0,0 +1,511 @@ +/* jshint node: true */ + +var User = require('../../schemas/User'), + Project = require('../../schemas/Project'), + Media = require('../../schemas/Media'), + Collaborator = require('../../schemas/Collaborator'), + Plan = require('../../schemas/Plan'), + Subscription = require('../../schemas/Subscription'), + Layout = require('../../schemas/Layout'), + Blueprint = require('../../schemas/Blueprint'), + config = require('../../../../config'), + middleware = require('../../middleware'), + util = require('../../util'), + _ = require('lodash'), + moment = require('moment'); + + +var staff = module.exports = { + + fields: require('./fields'), + defaults: require('./defaults'), + middleware: require('./middleware'), + helpers: require('./helpers'), + + route: function(app){ + app.get('/staff', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureRecentUsers, + staff.middleware.ensureUsersCount, + staff.middleware.ensureProjectsCount, + staff.middleware.ensureMediaCount, + + staff.index + ); + + // + // users + + app.get('/staff/users', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureUsersCount, + staff.middleware.ensureUsers, + + staff.users.index + ); + app.get('/staff/users/:username', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureProfile, + staff.middleware.ensureProfileProjectCount, + staff.middleware.ensureProfileMediaCount, + staff.middleware.ensureProfileProjects, + + staff.users.show + ); + app.get('/staff/users/:username/media', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureProfile, + staff.middleware.ensureProfileMedia, + staff.middleware.ensureProfileMediaCount, + + staff.users.media + ); + app.put('/staff/users/:username/bless', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureProfile, + + staff.users.bless + ); + app.put('/staff/users/:username/artist', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureProfile, + + staff.users.make_artist + ); + + if (app.get('env') === 'development') { + app.get('/staff/authorize', + middleware.ensureAuthenticated, + staff.users.blessSelf + ); + } + + // + // projects + + app.get('/staff/projects', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureProjectsCount, + + staff.middleware.ensureProjects, + staff.middleware.ensureProjectsUsers, + + staff.projects.index + ); + app.get('/staff/projects/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureProject, + staff.middleware.ensureProject, + staff.middleware.ensureProjectUser, + staff.middleware.ensureProjectCollaborators, + + staff.projects.show + ); + app.put('/staff/projects/:slug/feature', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureProject, + staff.middleware.ensureProject, + + staff.projects.feature + ); + + // + // layouts + + app.get('/staff/layouts', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureLayoutsCount, + + staff.middleware.ensureLayouts, + staff.middleware.ensureLayoutsUsers, + + staff.layouts.index + ); + app.get('/staff/layouts/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureLayout, + staff.middleware.ensureLayout, + staff.middleware.ensureLayoutUser, + + staff.layouts.show + ); + app.put('/staff/layouts/:slug/stock', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureLayout, + staff.middleware.ensureLayout, + + staff.layouts.make_stock + ); + + // + // blueprints + + app.get('/staff/blueprints', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureBlueprintsCount, + + staff.middleware.ensureBlueprints, + staff.middleware.ensureBlueprintsUsers, + + staff.blueprints.index + ); + app.get('/staff/blueprints/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureBlueprint, + staff.middleware.ensureBlueprint, + staff.middleware.ensureBlueprintUser, + + staff.blueprints.show + ); + + // + // media + + app.get('/staff/media', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureMediaCount, + + staff.middleware.ensureMedia, + staff.middleware.ensureMediaUsers, + + staff.media.index + ); + app.get('/staff/media/:id', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureSingleMedia, + staff.middleware.ensureMediaUser, + + staff.media.show + ); + + // + // plans + + app.get('/staff/plans', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensurePlans, + + staff.plans.index + ); + app.get('/staff/plans/new', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.plans.new + ); + app.post('/staff/plans/new', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.plans.create + ); + app.get('/staff/plans/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensurePlan, + + staff.plans.edit + ); + app.post('/staff/plans/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensurePlan, + + staff.plans.update + ); + + // + // subscriptions + app.get('/staff/subscriptions', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureSubscriptions, + staff.middleware.ensureSubscriptionsUsers, + + staff.subscriptions.index + ); + app.get('/staff/subscriptions/:id', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureSubscription, + staff.middleware.ensureSubscriptionUser, + + staff.subscriptions.show + ); + }, + + paginate: function(req, res){ + var info = res.locals.pagination + info.query = "sort=" + info.sort + "&limit=" + info.limit + info.first_page = 0 + info.last_page = Math.max(0, info.max - info.limit) + info.sortOptions = info.sortOptions + if (info.offset > 0) { + info.prev_page = Math.max(0, info.offset - info.limit) + } + else { + info.prev_page = -1 + } + if (info.count == info.limit && info.offset + info.limit < info.max) { + info.next_page = info.offset + info.limit + } + else { + info.next_page = -1 + } + }, + + index: function(req, res){ + res.render('staff/index') + }, + + // /staff/users/ + // /staff/users/:username + users: { + index: function(req, res){ + res.locals.pagination.count = res.locals.users.length + res.locals.pagination.max = res.locals.userCount + staff.paginate(req, res) + res.render('staff/users/index') + }, + show: function(req, res){ + if (res.locals.profile) { + res.render('staff/users/show', { + profileJSON: util.escape( JSON.stringify( res.locals.profile ) ) + }) + } + else { + res.render('staff/users/show_404') + } + }, + media: function(req, res){ + if (res.locals.profile) { + res.locals.pagination.count = res.locals.media.length + res.locals.pagination.max = res.locals.profile.mediaCount + staff.paginate(req, res) + res.render('staff/users/media') + } + else { + res.render('staff/users/show_404') + } + }, + blessSelf: function(req, res){ + req.user.isStaff = true + req.user.save(function(err, user){ + res.json({ state: user.isStaff }) + }) + }, + bless: function(req, res){ + res.locals.profile.isStaff = req.body.state == "true" + res.locals.profile.save(function(err, user){ + res.json({ state: user.isStaff }) + }) + }, + make_artist: function(req, res){ + res.locals.profile.isArtist = req.body.state == "true" + res.locals.profile.save(function(err, user){ + res.json({ state: user.isArtist }) + }) + }, + }, + + // /staff/projects/ + // /staff/projects/:slug + projects: { + index: function(req, res){ + res.locals.pagination.count = res.locals.projects.length + res.locals.pagination.max = res.locals.projectCount + staff.paginate(req, res) + res.render('staff/projects/index') + }, + show: function(req, res){ + if (res.locals.project) { + res.render('staff/projects/show', { + projectJSON: util.escape( JSON.stringify( res.locals.project ) ), + projectUserJSON: util.escape( JSON.stringify( res.locals.projectUser ) ), + collaboratorsJSON: util.escape( JSON.stringify( res.locals.collaborators ) ), + }) + } + else { + res.render('staff/projects/show_404') + } + }, + feature: function(req, res){ + res.locals.project.featured = req.body.state == "true" + res.locals.project.save(function(err, project){ + res.json({ state: project.featured }) + }) + }, + }, + + // /staff/layouts/ + // /staff/layouts/:slug + layouts: { + index: function(req, res){ + res.locals.pagination.count = res.locals.layouts.length + res.locals.pagination.max = res.locals.layoutCount + staff.paginate(req, res) + res.render('staff/layouts/index') + }, + show: function(req, res){ + if (res.locals.layout) { + res.render('staff/layouts/show', { + }) + } + else { + res.render('staff/layouts/show_404') + } + }, + make_stock: function(req, res){ + res.locals.layout.is_stock = req.body.state == "true" + res.locals.layout.save(function(err, layout){ + res.json({ state: layout.is_stock }) + }) + }, + }, + + // /staff/blueprints/ + // /staff/blueprints/:slug + blueprints: { + index: function(req, res){ + res.locals.pagination.count = res.locals.blueprints.length + res.locals.pagination.max = res.locals.blueprintCount + staff.paginate(req, res) + res.render('staff/blueprints/index') + }, + show: function(req, res){ + if (res.locals.blueprint) { + res.render('staff/blueprints/show', { + }) + } + else { + res.render('staff/blueprints/show_404') + } + }, + }, + + media: { + index: function(req, res){ + res.locals.pagination.count = res.locals.media.length + res.locals.pagination.max = res.locals.mediaCount + staff.paginate(req, res) + res.render('staff/media/index') + }, + show: function(req, res){ + if (res.locals.media) { + res.render('staff/media/show', { + mediaJSON: util.escape( JSON.stringify( res.locals.media ) ), + mediaUserJSON: util.escape( JSON.stringify( res.locals.mediaUser ) ), + }) + } + else { + res.render('staff/media/show_404') + } + }, + }, + + plans: { + index: function(req, res){ + res.locals.fields = staff.fields.plans.split(" ") + res.locals.permissions = staff.fields.plans_permissions.split(" ") + res.render('staff/plans/index') + }, + new: function(req, res){ + res.locals.plan = new Plan () + res.render('staff/plans/new') + }, + edit: function(req, res){ + res.locals.plan = req.plan + res.render('staff/plans/edit') + }, + create: function(req, res){ + var plan = new Plan () + var fields = staff.fields.plans.split(" ") + var permissions = staff.fields.plans_permissions.split(" ") + + var data = util.cleanQuery(req.body) + data.name = util.sanitize(data.name) + data.slug = util.sanitize(data.slug.toLowerCase()) + + data.permissions = {} + permissions.forEach(function(field){ + data.permissions[field] = data["permissions_" + field].length == 2 + }) + + new Plan (data).save(function(err, doc){ + if (err || ! doc) { return res.json({ error: err }) } + middleware.updatePlans() + res.redirect("/staff/plans/") + }) + }, + update: function(req, res){ + var fields = staff.fields.plans.split(" ") + var permissions = staff.fields.plans_permissions.split(" ") + + var data = util.cleanQuery(req.body) + data.name = util.sanitize(data.name) + data.slug = util.sanitize(data.slug.toLowerCase()) + + _.extend(req.plan, data) + permissions.forEach(function(field){ + req.plan.permissions[field] = data["permissions_" + field].length == 2 + }) + + req.plan.save(function(err, doc){ + if (err || ! doc) { return res.json({ error: err }) } + middleware.updatePlans() + res.redirect("/staff/plans/") + }) + }, + }, + + subscriptions: { + index: function(req, res){ + res.locals.pagination.count = res.locals.subscriptions.length + res.locals.pagination.max = res.locals.subscriptionCount + staff.paginate(req, res) + res.render('staff/subscriptions/index') + }, + show: function(req, res){ + res.render('staff/subscriptions/show') + }, + }, + +} diff --git a/server/lib/views/staff/middleware.js b/server/lib/views/staff/middleware.js new file mode 100644 index 0000000..03fda2e --- /dev/null +++ b/server/lib/views/staff/middleware.js @@ -0,0 +1,476 @@ + +var User = require('../../schemas/User'), + Project = require('../../schemas/Project'), + Media = require('../../schemas/Media'), + Collaborator = require('../../schemas/Collaborator'), + Plan = require('../../schemas/Plan'), + Subscription = require('../../schemas/Subscription'), + Layout = require('../../schemas/Layout'), + Blueprint = require('../../schemas/Blueprint'), + util = require('../../util'), + fields = require('./fields'), + helpers = require('./helpers'), + defaults = require('./defaults'), + _ = require('lodash'), + moment = require('moment'); + + +var middleware = module.exports = { + + ensureUsers: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var initial = util.sanitize(req.query.initial) + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date", "last_seen", "username"] + switch (req.query.sort) { + case 'date': + sort = {'created_at': -1} + break + case 'last_seen': + sort = {'last_seen': -1} + break + case 'username': + default: + sort = {'username': 1} + paginationInfo.sort = "username" + break + } + if (initial) { + if (initial == "?") { + criteria.username = new RegExp('^[^a-zA-Z]', "i") + } + else { + criteria.username = new RegExp('^' + initial, "i") + } + } + User.find(criteria) + .select(fields.user) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, users) { + res.locals.users = users.map(helpers.user) + if (! res.locals.users.length) { + if (initial) { + res.locals.opt.error = "No users found starting with <b>" + initial.toUpperCase() + "</b>" + } + else { + res.locals.opt.error = "No users found" + } + } + next() + }) + }, + + ensureRecentUsers: function(req, res, next){ + var dreq = { query: { sort: 'last_seen', limit: 20, offset: 0 } } + middleware.ensureUsers(dreq, res, next) + }, + + ensureProjects: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date", "name"] + switch (req.query.sort) { + default: + case 'date': + sort = {'updated_at': -1} + break + case 'name': + paginationInfo.sort = "name" + sort = {'slug': 1} + break + } + Project.find(criteria) + .select(fields.project) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, projects) { + res.locals.projects = projects.map(helpers.project) + next() + }) + }, + + ensureLayouts: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date", "name"] + switch (req.query.sort) { + default: + case 'date': + sort = {'updated_at': -1} + break + case 'name': + paginationInfo.sort = "name" + sort = {'slug': 1} + break + } + Layout.find(criteria) + .select(fields.layout) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, layouts) { + res.locals.layouts = layouts.map(helpers.layout) + next() + }) + }, + + ensureBlueprints: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date", "name"] + switch (req.query.sort) { + default: + case 'date': + sort = {'updated_at': -1} + break + case 'name': + paginationInfo.sort = "name" + sort = {'slug': 1} + break + } + Blueprint.find(criteria) + .select(fields.blueprint) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, blueprints) { + res.locals.blueprints = blueprints.map(helpers.blueprint) + next() + }) + }, + + ensureMedia: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date"] + switch (req.query.sort) { + default: + case 'date': + paginationInfo.sort = "date" + sort = {'created_at': -1} + break + } + Media.find(criteria) + // .select(fields.media) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, media) { + res.locals.media = media.map(helpers.media) + next() + }) + }, + + ensureSubscriptions: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date", "name"] + switch (req.query.sort) { + case 'created': + sort = {'created_at': -1} + break + default: + case 'date': + sort = {'updated_at': -1} + break + } + Subscription.find(criteria) + .select(fields.project) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, subscriptions) { + res.locals.subscriptions = subscriptions.map(helpers.subscription) + next() + }) + }, + + ensurePlans: function(req, res, next){ + Plan.find({}).sort({ 'level': -1 }).exec(function (err, plans) { + res.locals.plans = (plans || []).map(helpers.plan) + res.locals.plans.sort(function(a,b){ return a.monthly_price }) + next() + }) + }, + ensurePlan: function (req, res, next) { + if (req.params.slug) { + Plan.findOne({ slug: req.params.slug }, function(err, plan){ + if (err || ! plan) { + console.error(err) + res.redirect("/staff/plans/") + } + else { + req.plan = plan + next() + } + }) + } + else { + res.redirect("/staff/plans/") + } + }, + + ensureSubscription: function (req, res, next) { + if (req.params.id) { + Subscription.findOne({ _id: req.params.id }, function(err, subscription){ + if (err || ! subscription) { + console.error(err) + res.redirect("/staff/subscriptions/") + } + else { + req.subscription = subscription + next() + } + }) + } + else { + res.redirect("/staff/subscriptions/") + } + }, + + ensureRecentProjects: function(req, res, next){ + var dreq = { params: { sort: 'created_at', limit: 20, offset: 0 } } + middleware.ensureProjects(dreq, res, next) + }, + + ensureProjectsUsers: function(req, res, next){ + if (! res.locals.projects || ! res.locals.projects.length) { return next() } + middleware.ensureObjectsUsers(res.locals.projects, next) + }, + + ensureLayoutsUsers: function(req, res, next){ + if (! res.locals.layouts || ! res.locals.layouts.length) { return next() } + middleware.ensureObjectsUsers(res.locals.layouts, next) + }, + + ensureBlueprintsUsers: function(req, res, next){ + if (! res.locals.blueprints || ! res.locals.blueprints.length) { return next() } + middleware.ensureObjectsUsers(res.locals.blueprints, next) + }, + + ensureSubscriptionsUsers: function(req, res, next){ + if (! res.locals.subscriptions || ! res.locals.subscriptions.length) { return next() } + middleware.ensureObjectsUsers(res.locals.subscriptions, next) + }, + + ensureMediaUsers: function(req, res, next){ + if (! res.locals.media || ! res.locals.media.length) { return next() } + middleware.ensureObjectsUsers(res.locals.media, next) + }, + + ensureSubscriptionUser: function(req, res, next){ + if (! res.locals.subscription) { return next() } + middleware.ensureObjectsUsers([ res.locals.subscription ], function(){ + next() + }) + }, + + ensureMediaUser: function(req, res, next){ + if (! res.locals.media) { return next() } + middleware.ensureObjectsUsers([ res.locals.media ], function(){ + res.locals.mediaUser = res.locals.media.User + next() + }) + }, + + ensureObjectsUsers: function(objects, next){ + if (! objects) { return next () } + var dedupe = {}, user_ids + objects.forEach(function(obj){ + dedupe[ obj.user_id ] = dedupe[ obj.user_id ] || [] + dedupe[ obj.user_id ].push(obj) + }) + user_ids = _.keys(dedupe) + User.find({ _id: { $in: user_ids } }) + .select(fields.user) + .exec(function (err, users) { + if (! users) { return next () } + users.forEach(function(user){ + dedupe[user._id].forEach(function(obj){ + obj.user = user + }) + }) + next() + }) + }, + + ensureProfile: function(req, res, next){ + var username = req.params.username + if (username) { + User.findOne({ username: username }, function (err, user) { + if (user) { + res.locals.profile = req.method == "GET" ? helpers.user(user) : user + } + else { + res.locals.profile = null + } + next() + }) + } + else { + res.locals.profile = null + next() + } + }, + + ensureSingleMedia: function(req, res, next){ + var id = req.params.id + if (id) { + Media.findOne({ _id: id }, function (err, media) { + if (media) { + res.locals.media = req.method == "GET" ? helpers.media(media) : media + } + else { + res.locals.media = null + } + next() + }) + } + else { + res.locals.media = null + next() + } + }, + + ensureUsersCount: function(req, res, next){ + User.count({}, function(err, count){ + res.locals.userCount = count || 0 + next() + }) + }, + + ensureProjectsCount: function(req, res, next){ + Project.count({}, function(err, count){ + res.locals.projectCount = count || 0 + next() + }) + }, + + ensureLayoutsCount: function(req, res, next){ + Layout.count({}, function(err, count){ + res.locals.layoutCount = count || 0 + next() + }) + }, + + ensureBlueprintsCount: function(req, res, next){ + Blueprint.count({}, function(err, count){ + res.locals.blueprintCount = count || 0 + next() + }) + }, + + ensureMediaCount: function(req, res, next){ + Media.count({}, function(err, count){ + res.locals.mediaCount = count || 0 + next() + }) + }, + + ensureProfileProjectCount: function(req, res, next){ + if (! res.locals.profile) { return next() } + Project.count({ user_id: res.locals.profile._id}, function(err, count){ + res.locals.profile.projectCount = count || 0 + next() + }) + }, + + ensureProfileMediaCount: function(req, res, next){ + if (! res.locals.profile) { return next() } + Media.count({ user_id: res.locals.profile._id}, function(err, count){ + res.locals.profile.mediaCount = count || 0 + next() + }) + }, + + ensureProfileProjects: function(req, res, next){ + if (! res.locals.profile) { return next() } + Project.find({ user_id: res.locals.profile._id }, fields.project, function(err, projects){ + res.locals.projects = projects.map(helpers.project) + next() + }) + }, + + ensureProfileMedia: function(req, res, next){ + if (! res.locals.profile) { return next() } + req.criteria = { user_id: res.locals.profile._id } + middleware.ensureMedia(req, res, next) + }, + + ensureProject: function(req, res, next){ + res.locals.project = req.project + next() + }, + + ensureProjectUser: function(req, res, next){ + if (! res.locals.project) { return next() } + User.findOne({ _id: res.locals.project.user_id }, fields.user, function(err, user){ + res.locals.projectUser = helpers.user(user) || defaults.user + next() + }) + }, + + ensureProjectCollaborators: function(req, res, next){ + if (! res.locals.project) { + res.locals.collaborators = [] + return next() + } + Collaborator.find({ project_id: res.locals.project._id}, function(err, collaborators){ + res.locals.collaborators = collaborators || [] + next() + }) + }, + + ensureLayout: function(req, res, next){ + res.locals.layout = req.layout + next() + }, + ensureLayoutUser: function(req, res, next){ + if (! res.locals.layout) { return next() } + User.findOne({ _id: res.locals.layout.user_id }, fields.user, function(err, user){ + res.locals.layoutUser = helpers.user(user) || defaults.user + next() + }) + }, + + ensureBlueprint: function(req, res, next){ + res.locals.blueprint = req.blueprint + next() + }, + ensureBlueprintUser: function(req, res, next){ + if (! res.locals.blueprint) { return next() } + User.findOne({ _id: res.locals.blueprint.user_id }, fields.user, function(err, user){ + res.locals.blueprintUser = helpers.user(user) || defaults.user + next() + }) + }, + + +}
\ No newline at end of file diff --git a/server/lib/webhook/index.js b/server/lib/webhook/index.js new file mode 100644 index 0000000..a5f23ac --- /dev/null +++ b/server/lib/webhook/index.js @@ -0,0 +1,44 @@ +var config = require('../../../config.json'), + http = require('http'), + express = require('express'), + bodyParser = require('body-parser'), + mongoose = require('mongoose'); + +var http = require('http'), + express = require('express'), + bodyParser = require('body-parser'), + multer = require('multer'), + MongoStore = require('connect-mongo')(express), + passport = require('passport'), + path = require('path'), + mongoose = require('mongoose'); + +var webhook = require('./webhook'); + +var app = express() +var server +var DATABASE_URI = process.env.MONGOLAB_URI || ('mongodb://' + config.databaseHost + '/vvalls') + +var site = {} + +site.init = function(){ + mongoose.connect(DATABASE_URI, {}, site.ready); +} + +site.ready = function(){ + app.set('port', config.webhookPort); + // app.use(bodyParser()); + app.use(express.query()); + app.set('env', config.env.production ? "production" : "development") + app.get('env') === 'development' && app.use(express.errorHandler()); + + server = http.createServer(app) + server.listen(app.get('port'), function () { + console.log('Webhook server listening on port ' + app.get('port')); + }); + + app.get('/', function(req,res){ res.send('hello@vvalls.com') }) + webhook.route(app) +} + +site.init() diff --git a/server/lib/webhook/recurly-config.js b/server/lib/webhook/recurly-config.js new file mode 100644 index 0000000..3d7e1c5 --- /dev/null +++ b/server/lib/webhook/recurly-config.js @@ -0,0 +1,6 @@ +module.exports = { + API_KEY: process.env['VVALLS_RECURLY_SECRET'], + SUBDOMAIN: 'vvalls', + ENVIRONMENT: 'sandbox', + DEBUG: true, +}; diff --git a/server/lib/webhook/webhook.js b/server/lib/webhook/webhook.js new file mode 100644 index 0000000..896d836 --- /dev/null +++ b/server/lib/webhook/webhook.js @@ -0,0 +1,178 @@ +// // where should this live? + +/* +app.use(express.basicAuth(function(user, pass, callback) { + var result = (user === 'testUser' && pass === 'testPass'); + callback(null, result); +})); +*/ + + +/* jshint node: true */ + +var User = require('../schemas/User'), + Subscription = require('../schemas/Subscription'), + config = require('../../../config'), + middleware = require('../middleware'), + util = require('../util'), + _ = require('lodash'), + moment = require('moment'), + xml2js = require('xml2js'), + Recurly = require('node-recurly'), + recurly = new Recurly(require('./recurly-config')); + +var xml_bodyparser = require('express-xml-bodyparser'); + +var parser = new xml2js.Parser(); + +var subscribe = module.exports = { + plan_levels: { + free: 0, + basic: 1, + pro: 2, + custom: 3, + artist: 4, + }, + + callbacks: { +/* + // accounts + new_account_notification: function(data, user){ + // fires on successful signup + }, + canceled_account_notification: function(data, user){ + }, + billing_info_updated_notification: function(data, user){ + }, + reactivated_account_notification: function(data, user){ + }, + + // invoices + new_invoice_notification: function(data, user){ + }, + closed_invoice_notification: function(data, user){ + }, + past_due_invoice_notification: function(data, user){ + }, +*/ + + // subscriptions + new_subscription_notification: function(data, user){ + var account = data.account[0].account_code[0] + var subscrip = data.subscription[0] + var uuid = subscrip.uuid[0] + Subscription.findOne({ "uuid": uuid }, function(err, old_subscriber){ + // if (err) return; + + var plan, plan_type, plan_code + var plan_code = subscrip.plan[0].plan_code[0] + + if (plan_code.indexOf("-") !== -1) { + plan = plan_code.split("-") + plan_type = plan[0] + plan_period = plan[1] + } + else { + plan_type = "custom" + plan_period = "monthly" + } + + user.plan_code = plan_code + user.plan_type = plan_type + user.plan_level = subscribe.plan_levels[plan_type] + + var subscriber = old_subscriber || new Subscription () + subscriber.uuid = uuid + subscriber.user_id = user._id + subscriber.plan_code = plan_code + subscriber.plan_type = plan_type + subscriber.plan_period = plan_period + subscriber.plan_level = subscribe.plan_levels[plan_type] + subscriber.add_ons = [] + var add_ons = subscrip.subscription_add_ons[0].subscription_add_on + if (add_ons) { + add_ons.forEach(function(add_on){ + switch (add_on.add_on_code[0]) { + case 'extra-basic-layout': + subscriber.basic_layouts = parseInt(add_on.quantity[0]._, 10) || 0 + break + case 'extra-pro-layout': + subscriber.pro_layouts = parseInt(add_on.quantity[0]._, 10) || 0 + break + } + }) + } + subscriber.save(function(err, data){ + if (err) return; + user.save(function(err){ + // saved! + }) + }) + }) + }, + +/* + updated_subscription_notification: function(data, user){ + }, + canceled_subscription_notification: function(data, user){ + }, + expired_subscription_notification: function(data, user){ + }, + renewed_subscription_notification: function(data, user){ + }, +*/ + // payments + successful_payment_notification: function(data, user){ + var account = data.account[0] + user.last_charged = new Date(data.transaction[0].date[0]._) + user.save(function(){ + }) + }, +/* + failed_payment_notification: function(data, user){ + }, + successful_refund_notification: function(data, user){ + }, + void_payment_notification: function(data, user){ + }, +*/ + }, + + execute: function(action, data){ + User.findOne({ _id: data.account[0].account_code[0] }, function(err, user){ + if (err) { return } + subscribe.callbacks[action](data, user) + }) + }, + + // then calls to get appropriate info from the recurly api + handle: function(req, res){ + console.log(req.body) + // parser.parseString(req.body, function (err, result) { + var result = req.body + for (var action in result) { + if (subscribe.callbacks[action]) { + subscribe.execute(action, result[action]); + } + } + return res.status(200).end() + }, + + list: function(req, res){ + recurly.subscriptions.listByAccount(req.params.id, function(data){ + if (data.data != 404) { + res.json(data) + return + } + else { + res.json(data) + return + } + }) + }, + + route: function(app){ + app.post('/subscribe/webhook', xml_bodyparser(), subscribe.handle); + app.get('/subscribe/list/:id', subscribe.list); + }, +} diff --git a/server/repl.js b/server/repl.js index ba94d45..353d8c5 100644 --- a/server/repl.js +++ b/server/repl.js @@ -9,6 +9,8 @@ mongoose.connect('mongodb://' + DB_HOST + '/vvalls', {}, function(){ "./lib/schemas/Layout", "./lib/schemas/Media", "./lib/schemas/Project", + "./lib/schemas/Plan", + "./lib/schemas/Subscription", ].forEach(function(modName){ // console.log(name, modName) var namez = modName.split("/"), name = namez[namez.length-1]; diff --git a/views/about/_blank.ejs b/views/about/_blank.ejs index 0e9ea7e..732ea3f 100644 --- a/views/about/_blank.ejs +++ b/views/about/_blank.ejs @@ -1,14 +1,14 @@ <!doctype html> <html> <head> - <title>vvalls</title> + <title>VValls</title> [[ include ../partials/meta ]] </head> <body class="loading"> <div class="rapper page home"> [[ include ../partials/header ]] - + <h1 class="leader">Hallo</h1> <!-- put stuff here --> diff --git a/views/about/_old_plans.ejs b/views/about/_old_plans.ejs new file mode 100644 index 0000000..e4b07be --- /dev/null +++ b/views/about/_old_plans.ejs @@ -0,0 +1,63 @@ + <div class="about_plan planbox free_plan_info"> + <h3>[[- plans.free.name ]]</h3> + <ul> + <li> [[- plans.free.stock_project_limit ]] exhibition with pre-designed template floor plan + </ul> + </div> + + <div class="about_plan planbox"> + <h3>[[- plans.basic.name ]]</h3> + <ul> + <li> $[[- plans.basic.monthly_price ]]/mo or $[[- plans.basic.yearly_price ]]/year + <li> Comes with [[- plans.basic.basic_layout_limit ]] basic floor plan and [[- plans.basic.basic_project_limit ]] exhibitions + <li> Each new basic floor plan costs $[[- plans.basic.basic_layout_monthly_price ]]/mo + or $[[- plans.basic.basic_layout_yearly_price ]]/year, minimum 3 months + <li> Each new floor plan can have up to [[- plans.basic.basic_project_limit ]] exhibitions + <li> VValls logo appears when embedding an exhibition on a web page + <li> + [[ if (! logged_in) { ]] + <button data-role="show-signup-modal">Sign Up</button> + [[ } else if (! user.plan_level) { ]] + <a href="https://vvalls.recurly.com/subscribe/basic-monthly/[[- user._id ]]/[[- user.username ]]"><button>Buy Now</button></a> + [[ } else if (user.plan_level == plans.basic.level) { ]] + Current Level + [[ } ]] + </ul> + </div> + + <div class="about_plan planbox"> + <h3>[[- plans.pro.name ]]</h3> + <ul> + <li> $[[- plans.pro.monthly_price ]]/mo or $[[- plans.pro.yearly_price ]]/year + <li> Comes with [[- plans.pro.pro_layout_limit ]] pro floor plan and [[- plans.pro.pro_project_limit ]] exhibitions + <li> Each new pro floor plan costs $[[- plans.pro.pro_layout_monthly_price ]]/mo + or $[[- plans.pro.pro_layout_yearly_price ]]/year, minimum 3 months + <li> Each new pro floor plan can have up to [[- plans.pro.pro_project_limit ]] exhibitions + <li> Includes planning for 3D objects in the room + <li> No VValls logo on embed + <li> + [[ if (! logged_in) { ]] + <button data-role="show-signup-modal">Sign Up</button> + [[ } else if (! user.plan_level) { ]] + <a href="https://vvalls.recurly.com/subscribe/pro-monthly/[[- user._id ]]/[[- user.username ]]"><button>Buy Now</button></a> + [[ } else if (user.plan_level == plans.pro.level) { ]] + Current Level + [[ } else if (user.plan_level < plans.pro.level) { ]] + <a href="/profile/billing"><button>Upgrade Now</button></a> + [[ } ]] + </ul> + </div> + + <div class="about_custom planbox miscbox"> + <ul> + <li> Buying any extra floor plan unlocks collaboration.<br>Invite an artist or curator to work on the exhibition with you. + <li> Basic Floor plan: Rectangle-based design of any dimension. + <li> Pro Floor plan: Trace an arbitrary floor plan from image. + </ul> + </div> + + <div class="about_custom custombox planbox"> + <h3>Want Something Custom?</h3> + <li> We offer customized white-label options for business and educational uses. + <li> <a href="mailto:hello@vvalls.com">Contact us</a> for more information. + </div> diff --git a/views/about/_plans.ejs b/views/about/_plans.ejs new file mode 100644 index 0000000..95b8d2f --- /dev/null +++ b/views/about/_plans.ejs @@ -0,0 +1,121 @@ +<ul id="plans"> + <li class="most-popular"> + <div class="top"> + <h2>[[- plans.pro.name ]]</h2> + <h3><span class="dollar">$</span><span class="price large">[[- plans.pro.monthly_price ]]</span> <span class="month large">/ mo </span></h3> + <h4>Ideal for large galleries<br>and small businesses.</h4> + </div> + <ul> + <li> + [[- plans.pro.pro_layout_limit ]] Pro Floor Plans and [[- plans.pro.pro_project_limit ]] Exhibitions + </li> + <li> + Trace a Floor Plan from a Drawing + </li> + <li> + Image Hosting For Artworks + </li> + <li> + Planning for 3D Objects + </li> + <li> + Everything the Medium Plan Contains + </li> + <li> + No Branding! + </li> + </ul> + <div class="signup"> + [[ if (! logged_in) { ]] + <a class="button" href="#" data-role="show-signup-modal">Sign Up for [[- plans.pro.name ]]</a> + [[ } else if (! user.plan_level || user.plan_level < plans.pro.level) { ]] + <a class="button" href="https://vvalls.recurly.com/subscribe/pro-monthly/[[- user._id ]]/[[- user.username ]]">Sign Up for [[- plans.pro.name ]]</a> + [[ } else if (user.plan_level == plans.pro.level) { ]] + <div class="current">Current Level</div> + [[ } ]] + </div> + </li> + <li> + <div class="top"> + <h2>[[- plans.basic.name ]]</h2> + <h3><span class="dollar">$</span><span class="price medium">[[- plans.basic.monthly_price ]]</span> <span class="month medium">/ mo </span></h3> + <h4>Great for small galleries<br>and art projects.</h4> + </div> + <ul> + <li> + [[- plans.basic.basic_layout_limit ]] Basic Floor Plan and [[- plans.basic.basic_project_limit ]] Exhibitions + </li> + <li> + Add More Basic Floor Plans for $[[- plans.basic.basic_layout_monthly_price ]]/mo + </li> + <li> + Invite Artists to Collaborate + </li> + <li> + Prepay a Year and Get Two Months Free + </li> + <li> + Everything the Small Plan Contains + </li> + <li> + VValls Branding + </li> + </ul> + <div class="signup"> + [[ if (! logged_in) { ]] + <a class="button" href="#" data-role="show-signup-modal">Sign Up for [[- plans.basic.name ]]</a> + [[ } else if (! user.plan_level || user.plan_level < plans.basic.level) { ]] + <a class="button" href="https://vvalls.recurly.com/subscribe/basic-monthly/[[- user._id ]]/[[- user.username ]]">Sign Up for [[- plans.basic.name ]]</a> + [[ } else if (user.plan_level == plans.basic.level) { ]] + <div class="current">Current Level</div> + [[ } else { ]] + <div class="current"> </div> + [[ } ]] + </div> + </li> + <li> + <div class="top"> + <h2>[[- plans.free.name ]]</h2> + <h3><span class="dollar">$</span><span class="price small">0</span> <span class="month small">/ mo </span></h3> + <h4>Free forever.</h4> + </div> + <ul> + <li> + [[- plans.free.stock_project_limit ]] Basic Exhibition + </li> + <li> + Use Any of our Built-In Floor Plans + </li> + <li> + Embed Images and Videos in your Room + </li> + <li> + Custom Color and Wallpaper + </li> + <li> + Embed Room on Your Website + </li> + <li> + VValls Branding + </li> + </ul> + + <div class="signup"> + [[ if (! logged_in) { ]] + <a class="button" href="#" data-role="show-signup-modal">Sign Up for Small</a> + [[ } else if (! user.plan_level || user.plan_level == plans.free.level) { ]] + <div class="current">Current Level</div> + [[ } else { ]] + <div class="current"> </div> + [[ } ]] + </div> + </li> +</ul> + +<br> +<div class="about_custom custombox planbox"> + <h3>Want Something Custom?</h3> + <li> We offer customized white-label options for business and educational uses. + <br> + <a href="mailto:hello@vvalls.com">Contact us</a> for more information. +</div> diff --git a/views/about/about.ejs b/views/about/about.ejs index dd536be..6d5f011 100644 --- a/views/about/about.ejs +++ b/views/about/about.ejs @@ -1,14 +1,14 @@ <!doctype html> <html> <head> - <title>vvalls</title> + <title>About VValls</title> [[ include ../partials/meta ]] </head> <body class="loading"> <div class="rapper page"> [[ include ../partials/header ]] - <h1>About VValls</h1> + <h1 class="leader">About VValls</h1> <div class="projectList about aboutintro"> <div class="inner"> @@ -50,17 +50,3 @@ </body> [[ include ../partials/scripts ]] </html> -<style> -.aboutintro { - text-align: center; - line-height: 43px; - font-size: 24px; - padding: 5% 0; - font-weight: 300; -} -.aboutintro .inner { - max-width: 800px; - margin: 0 auto; - text-align: center; -} -</style>
\ No newline at end of file diff --git a/views/about/brochure.ejs b/views/about/brochure.ejs new file mode 100644 index 0000000..e34d3d3 --- /dev/null +++ b/views/about/brochure.ejs @@ -0,0 +1,25 @@ +<!doctype html> +<html> +<head> + <title>VValls Subscriptions</title> + [[ include ../partials/meta ]] +</head> +<body class="loading"> + <div class="rapper page"> + [[ include ../partials/header ]] + + <h1 class="leader">Subscriptions</h1> + + <div class="projectList about aboutintro"> + [[ include _plans ]] + </div> + + [[ include ../partials/confirm-modal ]] + [[ include ../projects/layouts-modal ]] + [[ include ../partials/sign-in ]] + [[ include ../partials/footer ]] + + </div> +</body> +[[ include ../partials/scripts ]] +</html> diff --git a/views/about/howto.ejs b/views/about/howto.ejs index 5278a40..914c3b3 100644 --- a/views/about/howto.ejs +++ b/views/about/howto.ejs @@ -1,7 +1,7 @@ <!doctype html> <html> <head> - <title>vvalls</title> + <title>How to Use VValls</title> [[ include ../partials/meta ]] </head> <body class="loading"> diff --git a/views/blueprint.ejs b/views/blueprint.ejs new file mode 100644 index 0000000..13e8182 --- /dev/null +++ b/views/blueprint.ejs @@ -0,0 +1,30 @@ +<!doctype html> +<html> +<head> + <title>VValls</title> + [[ include partials/meta ]] +</head> +<body class="editing loading"> + + <div id="scene"></div> + + <div class="rapper"> + [[ include partials/header ]] + + <div id="builderView"> + [[ include controls/blueprint/info ]] + [[ include controls/blueprint/toolbar ]] + [[ include controls/blueprint/settings ]] + [[ include controls/blueprint/editor ]] + [[ include controls/blueprint/scaler ]] + [[ include controls/blueprint/notice ]] + </div> + </div> + + [[ include partials/confirm-modal ]] + [[ include projects/layouts-modal ]] + [[ include partials/sign-in ]] + +</body> +[[ include partials/scripts ]] +</html> diff --git a/views/builder.ejs b/views/builder.ejs index afb8c66..6a31e22 100644 --- a/views/builder.ejs +++ b/views/builder.ejs @@ -1,7 +1,7 @@ <!doctype html> <html> <head> - <title>vvalls</title> + <title>VValls</title> [[ include partials/meta ]] </head> <body class="editing loading"> @@ -17,22 +17,6 @@ [[ include controls/builder/settings ]] </div> - <!-- - <div id="minimap" class="vvbox"> - <span class="el"></span> - </div> - - <select id="palette"> - <option>colors</option> - <option>redblue</option> - <option>gray</option> - <option selected>bone</option> - <option>alpha</option> - <option>white</option> - <option>black</option> - </select> - --> - <div id="hud"> <div id="map" style="display: block"> </div> diff --git a/views/controls/blueprint/editor.ejs b/views/controls/blueprint/editor.ejs new file mode 100644 index 0000000..0dbac8e --- /dev/null +++ b/views/controls/blueprint/editor.ejs @@ -0,0 +1,36 @@ +<style type="text/css"> +#perspective, +#perspective .mx-scene { + position: absolute; + left:0%; + top:0px; + -webkit-transform: translateZ(0); + transform: translateZ(0); +} +#orthographic { + position: absolute; + left:50%; + top:0px +} +.blueprintInfo { + bottom: 14px; + left: 10px; + width: 270px; + font-size: 13px; + font-weight: 300; + padding: 10px; +} +.blueprintInfo .setting { + margin-bottom: 20px; +} +.blueprintInfo .setting.number input[type=text] { + width: 100px; + font-size: 16px; +} +</style> + +<div id="blueprintView"> + <div id="perspective"></div> + <div id="orthographic"></div> +</div> + diff --git a/views/controls/blueprint/info.ejs b/views/controls/blueprint/info.ejs new file mode 100644 index 0000000..a86481b --- /dev/null +++ b/views/controls/blueprint/info.ejs @@ -0,0 +1,30 @@ +<div class="vvbox settings info" id="blueprintInfo"> + <h4>Blueprint Editor</h4> + + <div class="setting number twoline"> + <label for="room-height">ceiling height</label> + <input type="text" class="units" name="height" id="room-height"> + </div> + + <div class="setting number twoline"> + <label for="viewHeight">camera height</label> + <input type="text" class="units" name="viewHeight" id="viewHeight"> + </div> + + <div class="setting number twoline"> + <label for="builder-units">units</label> + <select id="builder-units" name="units"> + <option value="px">pixels</option> + <option value="ft">feet</option> + <option value="m">meters</option> + </select> + </div> + + <div class="setting number scale"> + <label>scale</label> + <span id="blueprintScaleDisplay"></span> + px/<span class="units"></span> + <span class="openScaler">[edit scale]</span> + </div> + +</div> diff --git a/views/controls/blueprint/notice.ejs b/views/controls/blueprint/notice.ejs new file mode 100644 index 0000000..bf1a310 --- /dev/null +++ b/views/controls/blueprint/notice.ejs @@ -0,0 +1,4 @@ +<div class="vvbox settings" id="blueprintNotice"> + <div class="notice"></div> + <span class="next">Next</span> +</div> diff --git a/views/controls/blueprint/scaler.ejs b/views/controls/blueprint/scaler.ejs new file mode 100644 index 0000000..82fd2b2 --- /dev/null +++ b/views/controls/blueprint/scaler.ejs @@ -0,0 +1,48 @@ +<div class="mediaDrawer fixed animate active blueprintScaler"> + <div class="box"> + + <div class="blueprintUploader"> + <h2>Upload your Blueprint</h2> + <p> + Upload an image which you will trace to make a floor plan. + Images should be at least 1000x1000. + </p> + <input type="hidden" name="_csrf" value="[[- token ]]"> + <input type="text" class="url" placeholder="Enter an image URL or..."> + <div class="wallpaperUpload toolButton"> + <form> + <span class="ion-ios-upload-outline upload-icon"></span> + <label>Upload a File</label> + <input type="file" accept="image/*" multiple> + </form> + </div> + <div class="blueprints"> + <h5>Your uploaded blueprints</h5> + </div> + </div> + + <div class="blueprintInfo vvbox"> + Please tell us the scale of your blueprint. + Click two corners of a wall, and then enter how long the wall is. + <br><br> + You can also <span class="uploadNewBlueprint">upload another blueprint</span>. + <br><br> + + <form> + <div class="setting number"> + <label for="blueprint-dimensions">length</label> + <input type="text" class="units" name="blueprint-dimensions" id="blueprint-dimensions"> + <select id="blueprint-units" name="blueprint-units"> + <option value="ft">feet</option> + <option value="m">meters</option> + </select> + </div> + <button id="saveBlueprint">Save</button> + </form> + </div> + + <div id="blueprintMap"> + </div> + + </div> +</div>
\ No newline at end of file diff --git a/views/controls/blueprint/settings.ejs b/views/controls/blueprint/settings.ejs new file mode 100644 index 0000000..9c615ea --- /dev/null +++ b/views/controls/blueprint/settings.ejs @@ -0,0 +1,18 @@ +<div class="vvbox settings active" id="blueprintSettings"> + <input type="hidden" name="_csrf" value="[[- token ]]"> + <input type="hidden" name="_id" value="new"> + + <div class="setting"> + <input type="text" name="name" placeholder="Blueprint name"> + </div> + + <div class="setting"> + <button data-role="save-layout">Save</button> + </div> + + <div class="setting subButtons"> + <a href="#" data-role="clear-layout">Clear</a> + <a href="#" data-role="destroy-layout">Delete</a> + </div> + +</div> diff --git a/views/controls/blueprint/toolbar.ejs b/views/controls/blueprint/toolbar.ejs new file mode 100644 index 0000000..ba795e3 --- /dev/null +++ b/views/controls/blueprint/toolbar.ejs @@ -0,0 +1,42 @@ +<div class="edit menu vvbox" id="blueprintToolbar"> + + <span + data-role='upload-floorplan' + data-info="upload a new floorplan" + class="ion-ios-upload-outline"></span> + + <span + data-role='toggle-orbit-mode' + data-info="toggle 3D mode" + class="ion-ios-photos-outline"></span> + + <span + data-role="arrow-mode" + data-info="move endpoints" + class="ion-navigate mode"></span> +<!-- + <span + data-role="polyline-mode" + data-info="draw walls" + class="ion-ios-pulse mode"></span> +--> + <span + data-role="ortho-polyline-mode" + data-info="draw right-angled walls" + class="ion-ios-grid-view-outline mode"></span> + + <span + data-role="eraser-mode" + data-info="remove walls" + class="ion-scissors mode"></span> + + <span + data-role="start-position-mode" + data-info="set starting position" + class="ion-ios-home-outline mode"></span> + + <span + data-role='toggle-layout-settings' + data-info="save blueprint" + class="ion-ios-compose-outline"></span> +</div> diff --git a/views/controls/builder/info.ejs b/views/controls/builder/info.ejs index 8a0e0d5..11e995a 100644 --- a/views/controls/builder/info.ejs +++ b/views/controls/builder/info.ejs @@ -34,8 +34,8 @@ <label for="builder-units">units</label> <select id="builder-units" name="units"> <option value="px">pixels</option> - <option value="ft">foot</option> - <option value="m">meter</option> + <option value="ft">feet</option> + <option value="m">meters</option> </select> </div> diff --git a/views/controls/builder/settings.ejs b/views/controls/builder/settings.ejs index aae67d0..f7642ae 100644 --- a/views/controls/builder/settings.ejs +++ b/views/controls/builder/settings.ejs @@ -4,7 +4,7 @@ <div class="setting"> <a href="#" id="startpoint"> - <span class="ion-ios7-navigate-outline"></span> + <span class="ion-ios-navigate-outline"></span> <span id="startText">Select Startpoint</span> <span id="moveText">Move to Desired Point</span></a> </div> diff --git a/views/controls/builder/toolbar.ejs b/views/controls/builder/toolbar.ejs index 8b2e9b8..ad51f0e 100644 --- a/views/controls/builder/toolbar.ejs +++ b/views/controls/builder/toolbar.ejs @@ -2,7 +2,7 @@ <span data-role='toggle-map-view' data-info="toggle map view" - class="ion-ios7-photos-outline"></span> + class="ion-ios-photos-outline"></span> <!-- <span data-role='create-mode' @@ -20,7 +20,7 @@ <span data-role='destroy-mode' data-info="delete" - class="ion-ios7-trash-outline"></span> + class="ion-ios-trash-outline"></span> <!-- <span data-role='undo' @@ -30,5 +30,5 @@ <span data-role='toggle-layout-settings' data-info="save layout" - class="ion-ios7-compose-outline"></span> + class="ion-ios-compose-outline"></span> </div> diff --git a/views/controls/editor/media-drawer.ejs b/views/controls/editor/media-drawer.ejs index f9bce61..8070941 100644 --- a/views/controls/editor/media-drawer.ejs +++ b/views/controls/editor/media-drawer.ejs @@ -3,8 +3,6 @@ <img class="floatingImg"> </div> -<span class="close" id="fixed_close">X</span> - <div class="mediaDrawer fixed animate mediaViewer"> <h2> <a href="#" class="userToggle active">Your Media</a> @@ -35,7 +33,7 @@ <span class="fileUpload" id="fileUpload"> <input type="hidden" name="_csrf" value="[[- token ]]"> <form> - <span class="ion-ios7-upload-outline upload-icon"></span><br> + <span class="ion-ios-upload-outline upload-icon"></span><br> Upload File <input type="file" accept="image/*" multiple> </form> diff --git a/views/controls/editor/media-editor.ejs b/views/controls/editor/media-editor.ejs index 99746e8..225bdc8 100644 --- a/views/controls/editor/media-editor.ejs +++ b/views/controls/editor/media-editor.ejs @@ -13,8 +13,8 @@ <div class="video audio setting"> <span class="playButton" data-role="play-media"> - <span class="on ion-ios7-play-outline"></span> - <span class="off ion-ios7-pause-outline"></span> + <span class="on ion-ios-play-outline"></span> + <span class="off ion-ios-pause-outline"></span> </span> <!-- ion-volume-high @@ -49,8 +49,8 @@ <div class="setting number"> <select id="builder-units" name="units"> <option value="px">pixels</option> - <option value="ft">foot</option> - <option value="m">meter</option> + <option value="ft">feet</option> + <option value="m">meters</option> </select> </div> --> diff --git a/views/controls/editor/sculpture.ejs b/views/controls/editor/sculpture.ejs new file mode 100644 index 0000000..dfe917f --- /dev/null +++ b/views/controls/editor/sculpture.ejs @@ -0,0 +1,42 @@ +<div class="vvbox settings" id="sculptureEditor"> + <h4>3D Object</h4> + + <input type="hidden" name="_csrf" value="[[- token ]]"> + <input type="hidden" name="_id" value="new"> + + <div class="setting"> + <input type="text" name="name" placeholder="media title"> + </div> + + <div class="setting"> + <textarea name="description" placeholder="short description"></textarea> + </div> + + <div class="setting"> + <input type="checkbox" name="outline" value="1" id="sculpture-outline"> + <label for="sculpture-outline">Show outline?</label> + <input type="color" name="outlineColor" value="#000000"> + </div> + + <div class="setting"> + <input type="checkbox" name="billboard" value="1" id="sculpture-billboard"> + <label for="sculpture-billboard">Billboard?</label> + </div> + + <div class="setting number"> + <label for="sculpture-width">width</label> + <input type="text" class="units" name="width" id="sculpture-width"> + </div> + <div class="setting number"> + <label for="sculpture-height">height</label> + <input type="text" class="units" name="height" id="sculpture-height"> + </div> + <div class="setting number"> + <label for="sculpture-height">depth</label> + <input type="text" class="units" name="depth" id="sculpture-depth"> + </div> + <div class="setting"> + <a href="#" class="warn btn" data-role="destroy-sculpture">remove object</a> + </div> + +</div> diff --git a/views/controls/editor/settings.ejs b/views/controls/editor/settings.ejs index cd915c5..0ee00de 100644 --- a/views/controls/editor/settings.ejs +++ b/views/controls/editor/settings.ejs @@ -7,7 +7,7 @@ <div class="setting" id="startpoint"> <a href="#" class="modalLink"> - <span class="ion-ios7-navigate-outline"></span> + <span class="ion-ios-navigate-outline"></span> <span id="startText">Set Startpoint</span> <span id="moveText">Move to Desired Point <span class="done">done</span></span> <span id="confirmText">Set Startpoint</span> @@ -17,7 +17,7 @@ <div class="setting"> <a href="#" class="modalLink" data-role='show-collaborators'> - <span class="ion-ios7-plus-outline"></span> + <span class="ion-ios-plus-outline"></span> Add Collaborators </a> </div> @@ -29,7 +29,7 @@ </a> <a href="#" class="modalLink" data-role='view-project' style="margin-left: 40px;"> - <span class="ion-ios7-search-strong"></span> + <span class="ion-ios-search-strong"></span> View project </a> diff --git a/views/controls/editor/toolbar.ejs b/views/controls/editor/toolbar.ejs index 6960cbc..1a3e2d7 100644 --- a/views/controls/editor/toolbar.ejs +++ b/views/controls/editor/toolbar.ejs @@ -9,11 +9,11 @@ <span data-role='open-media-viewer' data-info="add media" - class="ion-ios7-photos-outline"></span> + class="ion-ios-photos-outline"></span> <span data-role='toggle-presets' data-info="preset styles" - class="ion-ios7-briefcase-outline"></span> + class="ion-ios-briefcase-outline"></span> <!-- <span data-role='resize-media' @@ -22,25 +22,25 @@ <span data-role='destroy-media' data-info="delete media" - class="ion-ios7-trash-outline"></span> + class="ion-ios-trash-outline"></span> --> <span data-role='toggle-wallpaper-panel' data-info="add wallpaper" - class="ion-ios7-keypad-outline"></span> + class="ion-ios-keypad-outline"></span> <span data-role='toggle-color-control' data-info="edit room colors" - class="ion-ios7-sunny-outline"></span> + class="ion-ios-sunny-outline"></span> <span data-role='toggle-text-editor' data-info="add text to wall" - class="ion-ios7-compose-outline"></span> + class="ion-ios-compose-outline"></span> <!-- <span data-role='toggle-map-view' data-info="toggle map view" - class="ion-ios7-world-outline"></span> + class="ion-ios-world-outline"></span> --> <span data-role='toggle-project-settings' diff --git a/views/controls/editor/wallpaper.ejs b/views/controls/editor/wallpaper.ejs index 3168f1c..a53f462 100644 --- a/views/controls/editor/wallpaper.ejs +++ b/views/controls/editor/wallpaper.ejs @@ -19,7 +19,7 @@ <div class="wallpaperUpload toolButton"> <form> - <span class="ion-ios7-upload-outline upload-icon"></span> + <span class="ion-ios-upload-outline upload-icon"></span> <label>Upload</label> <input type="file" accept="image/*" multiple> </form> diff --git a/views/controls/reader/about-room.ejs b/views/controls/reader/about-room.ejs index 974fe0f..a9ef738 100644 --- a/views/controls/reader/about-room.ejs +++ b/views/controls/reader/about-room.ejs @@ -5,7 +5,7 @@ [[ if (authorpic) { ]] <a href="[[- authorlink ]]" class="authorName"><div class="profilePic" style="background-image:url([[- authorpic ]])"></div></a> [[ } else { ]] - <a href="[[- authorlink ]]" class="authorName"><span class="ion-ios7-person-outline"></span></a> + <a href="[[- authorlink ]]" class="authorName"><span class="ion-ios-person-outline"></span></a> [[ } ]] <a href="[[- authorlink ]]" class="authorName">[[- author ]]</a> </h1> diff --git a/views/docs.ejs b/views/docs.ejs index b3ead82..a1f081f 100644 --- a/views/docs.ejs +++ b/views/docs.ejs @@ -1,7 +1,7 @@ <!doctype html> <html> <head> - <title>vvalls</title> + <title>VValls</title> [[ include partials/meta ]] </head> <body class="loading"> diff --git a/views/editor.ejs b/views/editor.ejs index 656615c..08959a0 100755 --- a/views/editor.ejs +++ b/views/editor.ejs @@ -1,7 +1,7 @@ <!doctype html> <html> <head> - <title>vvalls</title> + <title>VValls</title> [[ include partials/meta ]] </head> <body class="editing loading"> @@ -16,6 +16,7 @@ [[ include controls/builder/info ]] [[ include controls/editor/media-drawer ]] [[ include controls/editor/media-editor ]] + [[ include controls/editor/sculpture ]] [[ include controls/editor/wallpaper ]] [[ include controls/editor/color-control ]] [[ include controls/editor/text-editor ]] diff --git a/views/home.ejs b/views/home.ejs index 36fc2fc..e3303ed 100755 --- a/views/home.ejs +++ b/views/home.ejs @@ -1,18 +1,18 @@ <!doctype html> <html> <head> - <title>vvalls</title> + <title>VValls</title> [[ include partials/meta ]] </head> <body class="loading"> <div class="rapper page home"> [[ include partials/header ]] - <div class="hero" style="background-image:url(http://okfocus.s3.amazonaws.com/images/vvalls-video-still1.jpg)"> + <div class="hero" style="background-image:url(http://okfocus.s3.amazonaws.com/images/vvalls-video-still2.jpg)"> <div class="holder"> <span class="circle"> <span class="videoTitle">Create 3D Rooms</span><br> - <span class="ion-ios7-play"></span><br> + <span class="ion-ios-play"></span><br> <span class="videoTitle">Watch video.</span> </span> </div> @@ -38,7 +38,7 @@ </span> <span> <h3>Defy The Status Quo</h3> - <words>There is no platform on the internet quite like VValls. VValls opens up the possibilities of expression online. Go crazy, make otherworldly rooms.</words> + <words>There is no platform on the Internet quite like VValls. VValls opens up the possibilities of expression online. Go crazy, make otherworldly rooms.</words> </span> </div> </div> @@ -60,17 +60,13 @@ <h1>Room Showcase</h1> [[ include projects/list-projects ]] + + [[ if (! logged_in) { ]] + <div class="projectList about makeAccountSingleton"> + <a href="/about/howto" class="greenbtn learn">Make an Account</a> + </div> + [[ } ]] - - <div class="projectList about gopro"> - - <span> - <h3>Ready To Go Pro?</h3> - Use VValls as part of your product, service, or marketing campaign. - We offer many types of customizations, including automation of layouts, more elaborate floor plans, enhanced video, interactivity, and other features. - <a href="mailto:info@vvalls.com?subject=VValls platform" class="greenbtn">Contact</a> - </span> - </div> [[ include partials/confirm-modal ]] [[ include projects/layouts-modal ]] [[ include partials/sign-in ]] @@ -78,7 +74,7 @@ </div> <div class="videoModal"> -<span class="ion-ios7-close-empty"></span> +<span class="ion-ios-close-empty"></span> <div class="holder"> <div class="video" style="width: 960px; margin: 0 auto; height: 540px; overflow: hidden; position: relative;"><iframe frameborder="0" scrolling="no" seamless="seamless" webkitallowfullscreen="webkitAllowFullScreen" mozallowfullscreen="mozallowfullscreen" allowfullscreen="allowfullscreen" id="okplayer" src="http://player.vimeo.com/video/109947131?api=1&player_id=okplayer" width="960" height="540" style="width: 960px; height: 800px; margin-top: -130px;"></iframe></div> </div> diff --git a/views/modal.ejs b/views/modal.ejs index 7ca869c..dfc5573 100644 --- a/views/modal.ejs +++ b/views/modal.ejs @@ -1,7 +1,7 @@ <!doctype html> <html> <head> - <title>vvalls</title> + <title>VValls</title> [[ include partials/meta ]] </head> <body class="loading"> @@ -10,7 +10,7 @@ <div style="height: 70%; clear: both;" id="content"></div> - [[ include partials/confirm-modal ]] + [[ include partials/confirm-modal ]] [[ include partials/sign-in ]] [[ include projects/layouts-modal ]] [[ include projects/edit-project ]] diff --git a/views/partials/edit-profile.ejs b/views/partials/edit-profile.ejs index 5775ca5..5720bc8 100644 --- a/views/partials/edit-profile.ejs +++ b/views/partials/edit-profile.ejs @@ -83,7 +83,7 @@ </li> </div> <li class="buttons"> - <input id="saveForm" class="button_text" type="submit" value="Submit" /> + <input id="saveForm" class="button_text" type="submit" value="Save Changes"> </li> <div class="errors"> <div>There was a problem with your submission:</div> diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs new file mode 100644 index 0000000..f3c3589 --- /dev/null +++ b/views/partials/edit-subscription.ejs @@ -0,0 +1,78 @@ +<div class="mediaDrawer fixed animate editSubscription"> + <span class="close">X</span> + <div id="form_container"> + <form> + <input type="hidden" name="_csrf" value="[[- token ]]"> + <ul> + <li class="section_break"> + <h3>Edit Subscription</h3> + </li> + <li class="freePlan"> + You are currently using the free version of VValls. For access to all of VValls features, + consider upgrading to a paid plan. + <br><br> + <div class="planList"></div> + <br><br><br> + </li> + <li class="paidPlan"> + <div class="currentPlanLevel"> + Your current plan level is <span data-role="planName"></span> + </div> + <div class="planMenu"> + <h3>Select desired plan:</h3> + <div> + <input type="radio" id="chooseBasicPlan" data-role="basicPlanInput" name="planRadio" value="basic"> + <label for="chooseBasicPlan" data-role="basicPlanName"></label> + $<span data-role="basicPlanCost"></span>/<span data-role="billingInterval"></span> + </div> + <div> + <input type="radio" id="chooseProPlan" data-role="proPlanInput" name="planRadio" value="pro"> + <label for="chooseProPlan" data-role="proPlanName"></label> + $<span data-role="proPlanCost"></span>/<span data-role="billingInterval"></span> + </div> + </div> + <table class="planInfo"> + <tr class="planRow"> + <th><span data-role="planName"></span></th> + <td></td> + <td></td> + <td>$<span data-role="planCost"></span>/<span data-role="billingInterval"></span></td> + </tr> + <tr class="basicLayoutRow"> + <th>Basic layouts</th> + <td><input type="number" min="0" max="100" step="1" data-role="basicLayoutInput"><span data-role="basicLayoutQuantity"></span></td> + <td>each $<span data-role="basicLayoutCost"></span>/<span data-role="billingInterval"></span></td> + <td>$<span data-role="basicLayoutTotal"></span>/<span data-role="billingInterval"></span></td> + </tr> + <tr class="proLayoutRow"> + <th>Pro layouts</th> + <td><input type="number" min="0" max="100" data-role="proLayoutInput"><span data-role="proLayoutQuantity"></span></td> + <td>each $<span data-role="proLayoutCost"></span>/<span data-role="billingInterval"></span></td> + <td>$<span data-role="proLayoutTotal"></span>/<span data-role="billingInterval"></span></td> + </tr> + <tr class="totalRow"> + <td></td> + <td></td> + <th>Total</th> + <td>$<span data-role="planTotal"></span>/<span data-role="billingInterval"></span></td> + </tr> + </table> + <div class="billingMenu"> + <button data-role="showEditMenu">Edit Your Plan</button><br> + <button data-role="cancelSubscription">Cancel your subscription</button> + </div> + <div class="editMenu"> + <div class="fineprint"> + Your credit card will be charged the difference of XXXX for this month. + Your subscription will renew at XXXX at the start of your next billing cycle. + We thank you for your support! + </div> + <button data-role="saveChanges">Save Subscription</button> + <button data-role="closeMenu">Cancel</button> + </div> + </li> + <div class="gear"><span class="ion-gear-a"></span></div> + </ul> + </form> + </div> +</div> diff --git a/views/partials/footer.ejs b/views/partials/footer.ejs index e3c572f..2d9fb59 100644 --- a/views/partials/footer.ejs +++ b/views/partials/footer.ejs @@ -2,7 +2,7 @@ [[ if (logged_in) { ]] <span> - signed in as → + signed in as <a href="/profile/[[- user.username ]]"><b>[[- user.displayName ]]</b></a> [[ if (user.isStaff) { ]] <a href="/staff">Staff Area</a> @@ -15,11 +15,17 @@ <a href="/about">About</a> <a href="/about/howto">How To</a> + + [[ if (logged_in && user.plan_level > 0) { ]] + <a href="/profile/billing">Billing</a> + [[ } else { ]] + <a href="/about/brochure">Subscribe</a> + [[ } ]] <a href="/about/terms">Terms</a> <a href="/about/privacy">Privacy</a> <a href="mailto:hello@vvalls.com">Contact</a> <br><br> - <span>©2014 Dot Dash 3, Inc.</span> + <span>© 2016 Dot Dash 3, Inc.</span> <a href="http://okfoc.us/">Site by OKFocus</a> </div> diff --git a/views/partials/header.ejs b/views/partials/header.ejs index ce5bab9..ce9ffae 100644 --- a/views/partials/header.ejs +++ b/views/partials/header.ejs @@ -64,6 +64,9 @@ [[ if (profile && String(user._id) == String(profile._id)) { ]] <a href="/profile" data-role="edit-profile-modal" class="topLink editProfile">Settings</a> +<!-- + <a href="/profile" data-role="edit-subscription-modal" class="topLink editSubscription">Subscription</a> + --> [[ } else if (! profile) { ]] <a href="/profile" class="topLink profileLink">Profile</a> [[ } ]] @@ -77,4 +80,6 @@ <a href="/signin" data-role="show-signin-modal" class="signIn topLink">Sign In</a> [[ } ]] </span> -</div>
\ No newline at end of file +</div> + +<span class="close" id="fixed_close">X</span>
\ No newline at end of file diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index fc94992..da3f0ba 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -2,9 +2,10 @@ <script type="text/javascript" src="/assets/javascripts/app.min.js"></script> [[ } else { ]] <script type="text/javascript" src="/assets/javascripts/vendor/bower_components/jquery/dist/jquery.min.js"></script> -<script type="text/javascript" src="/assets/javascripts/vendor/bower_components/lodash/dist/lodash.min.js"></script> +<script type="text/javascript" src="/assets/javascripts/vendor/bower_components/lodash/lodash.min.js"></script> <script type="text/javascript" src="/assets/javascripts/vendor/bower_components/momentjs/min/moment.min.js"></script> <script type="text/javascript" src="/assets/javascripts/vendor/bower_components/fiber/src/fiber.min.js"></script> +<script type="text/javascript" src="/assets/javascripts/vendor/bower_components/hidpi-canvas/dist/hidpi-canvas.js"></script> <!-- <script type="text/javascript" src="/assets/javascripts/vendor/bower_components/prefixfree/prefixfree.min.js"></script> --> <script type="text/javascript" src="/assets/javascripts/vendor/bower_components/marked/lib/marked.js"></script> <script type="text/javascript" src="/assets/javascripts/vendor/tube.js"></script> @@ -18,15 +19,21 @@ <script type="text/javascript" src="/assets/javascripts/util.js"></script> <script type="text/javascript" src="/assets/javascripts/mx/mx.js"></script> + <script type="text/javascript" src="/assets/javascripts/mx/extensions/mx.scene.js"></script> <script type="text/javascript" src="/assets/javascripts/mx/extensions/mx.movements.js"></script> <script type="text/javascript" src="/assets/javascripts/mx/extensions/mx.movementsMobile.js"></script> +<script type="text/javascript" src="/assets/javascripts/mx/extensions/mx.orbitCamera.js"></script> + <script type="text/javascript" src="/assets/javascripts/mx/primitives/mx.image.js"></script> <script type="text/javascript" src="/assets/javascripts/mx/primitives/mx.text.js"></script> <script type="text/javascript" src="/assets/javascripts/mx/primitives/mx.video.js"></script> <script type="text/javascript" src="/assets/javascripts/mx/primitives/mx.youtube.js"></script> <script type="text/javascript" src="/assets/javascripts/mx/primitives/mx.vimeo.js"></script> <script type="text/javascript" src="/assets/javascripts/mx/primitives/mx.soundcloud.js"></script> +<script type="text/javascript" src="/assets/javascripts/mx/primitives/mx.grid.js"></script> +<script type="text/javascript" src="/assets/javascripts/mx/primitives/mx.point.js"></script> +<script type="text/javascript" src="/assets/javascripts/mx/primitives/mx.polyline.js"></script> <script type="text/javascript" src="/assets/javascripts/rectangles/_env.js"></script> @@ -64,6 +71,7 @@ <script type="text/javascript" src="/assets/javascripts/rectangles/engine/scenery/move.js"></script> <script type="text/javascript" src="/assets/javascripts/rectangles/engine/scenery/resize.js"></script> <script type="text/javascript" src="/assets/javascripts/rectangles/engine/scenery/randomize.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/scenery/sound.js"></script> <script type="text/javascript" src="/assets/javascripts/rectangles/engine/scenery/undo.js"></script> <script type="text/javascript" src="/assets/javascripts/rectangles/engine/scenery/types/_object.js"></script> <script type="text/javascript" src="/assets/javascripts/rectangles/engine/scenery/types/audio.js"></script> @@ -71,16 +79,38 @@ <script type="text/javascript" src="/assets/javascripts/rectangles/engine/scenery/types/text.js"></script> <script type="text/javascript" src="/assets/javascripts/rectangles/engine/scenery/types/video.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/sculpture/_sculpture.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/sculpture/move.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/sculpture/resize.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/sculpture/types/_object.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/sculpture/types/image.js"></script> + +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/shapes/polyline.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/shapes/ortho.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/shapes/shapelist.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/shapes/regionlist.js"></script> + <script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/_map.js"></script> -<script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/ui_editor.js"></script> -<script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/ui_minimap.js"></script> <script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/draw.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/ui/editor.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/ui/minimap.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/ui/ortho.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/tools/_base.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/tools/arrow.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/tools/line.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/tools/eraser.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/tools/ortho.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/tools/polyline.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/tools/position.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/tools/start.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/lib/View.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/lib/Router.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/lib/ModalView.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/lib/FormView.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/lib/UploadView.js"></script> +<script type="text/javascript" src="/assets/javascripts/ui/lib/AnimatedView.js"></script> +<script type="text/javascript" src="/assets/javascripts/ui/lib/ToggleableView.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/lib/AlertModal.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/lib/ConfirmModal.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/lib/ErrorModal.js"></script> @@ -92,9 +122,12 @@ <script type="text/javascript" src="/assets/javascripts/ui/site/UsernameTaken.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/site/PasswordForgot.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/site/PasswordReset.js"></script> +<script type="text/javascript" src="/assets/javascripts/ui/site/LayoutsIndex.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/site/LayoutsModal.js"></script> +<script type="text/javascript" src="/assets/javascripts/ui/site/NewProjectModal.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/site/EditProjectModal.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/site/EditProfileModal.js"></script> +<script type="text/javascript" src="/assets/javascripts/ui/site/EditSubscriptionModal.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/site/DocumentModal.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/site/HomeView.js"></script> @@ -106,6 +139,15 @@ <script type="text/javascript" src="/assets/javascripts/ui/builder/BuilderToolbar.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/builder/BuilderInfo.js"></script> +<script type="text/javascript" src="/assets/javascripts/ui/blueprint/BlueprintView.js"></script> +<script type="text/javascript" src="/assets/javascripts/ui/blueprint/BlueprintInfo.js"></script> +<script type="text/javascript" src="/assets/javascripts/ui/blueprint/BlueprintSettings.js"></script> +<script type="text/javascript" src="/assets/javascripts/ui/blueprint/BlueprintEditor.js"></script> +<script type="text/javascript" src="/assets/javascripts/ui/blueprint/BlueprintScaler.js"></script> +<script type="text/javascript" src="/assets/javascripts/ui/blueprint/BlueprintToolbar.js"></script> +<script type="text/javascript" src="/assets/javascripts/ui/blueprint/BlueprintUploader.js"></script> +<script type="text/javascript" src="/assets/javascripts/ui/blueprint/BlueprintNotice.js"></script> + <script type="text/javascript" src="/assets/javascripts/ui/editor/EditorView.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/editor/EditorSettings.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/editor/EditorToolbar.js"></script> @@ -117,6 +159,7 @@ <script type="text/javascript" src="/assets/javascripts/ui/editor/MediaUpload.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/editor/MediaViewer.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/editor/Presets.js"></script> +<script type="text/javascript" src="/assets/javascripts/ui/editor/SculptureEditor.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/editor/TextEditor.js"></script> <script type="text/javascript" src="/assets/javascripts/ui/editor/WallpaperPicker.js"></script> diff --git a/views/profile.ejs b/views/profile.ejs index a62652c..d3ae10e 100644 --- a/views/profile.ejs +++ b/views/profile.ejs @@ -1,7 +1,7 @@ <!doctype html> <html> <head> - <title>vvalls</title> + <title>VValls | [[- profile.displayName ]]</title> [[ include partials/meta ]] </head> <body class="loading"> @@ -9,48 +9,53 @@ [[- include partials/header ]] <div class="profilepage"> - [[ if (profile.photo && profile.photo.length) { ]] - <div class="profilePic" style="background-image:url([[- profile.photo ]])"> - </div> - [[ } else { ]] - <div class="profilePic noPic"> - <span class="holder"> - <span class="ion-ios7-person-outline"></span> - [[ if (isOwnProfile) { ]] - <div>click to add profile pic</div> - <input id="profile_avatar" name="avatar" class="element file" type="file"> - [[ } ]] - </span> - </div> + [[ if (profile.photo && profile.photo.length) { ]] + <div class="profilePic" style="background-image:url([[- profile.photo ]])"> + </div> + [[ } else { ]] + <div class="profilePic noPic"> + <span class="holder"> + <span class="ion-ios-person-outline"></span> + [[ if (isOwnProfile) { ]] + <div>click to add profile pic</div> + <input id="profile_avatar" name="avatar" class="element file" type="file"> [[ } ]] - <div class="bio"> - <div class="holder"> - <h2>[[- profile.displayName ]]</h2> - [[ if (profile.location) { ]] - <span> - [[- profile.location ]] - </span> - [[ } ]] - [[ if (profile.website && profile.website.length) { ]] - <span> - <a href="[[- profile.website ]]" target="_blank">[[- profile.website ]]</a> - </span> - [[ } ]] - [[ if (profile.twitterName && profile.twitterName.length) { ]] - <span> - <a href="https://twitter.com/[[- profile.twitterName ]]" target="_blank">@[[- profile.twitterName ]]</a> - </span> - [[ } ]] - </div> - </div> - + </span> + </div> + [[ } ]] + <div class="bio"> + <div class="holder"> + <h2>[[- profile.displayName ]]</h2> + [[ if (profile.location) { ]] + <span> + [[- profile.location ]] + </span> + [[ } ]] + [[ if (profile.website && profile.website.length) { ]] + <span> + <a href="[[- profile.website ]]" target="_blank">[[- profile.website ]]</a> + </span> + [[ } ]] + [[ if (profile.twitterName && profile.twitterName.length) { ]] + <span> + <a href="https://twitter.com/[[- profile.twitterName ]]" target="_blank">@[[- profile.twitterName ]]</a> + </span> + [[ } ]] + [[ if (profile.plan_level == 1) { ]] + <span class="plan_level premium">PREMIUM</span> + [[ } else if (profile.plan_level == 2) { ]] + <span class="plan_level pro">PRO</span> + [[ } ]] + </div> + </div> [[ if (projects.length) { ]] + <h1>[[- profile.username ]] has [[- projectCount ]] project[[- projectCount != 1 ? "s" : "" ]]</h1> - [[ include projects/list-projects ]] + [[ } else { ]] - + <h1>Welcome to VVALLS</h1> <div class="projectList about"> <h2> @@ -69,8 +74,13 @@ <h3>This person has no projects.</h3> [[ } ]] </div> + [[ } ]] - </div> + + </div> +<!-- + [[ include partials/edit-subscription ]] + --> [[ include partials/edit-profile ]] [[ include projects/layouts-modal ]] [[ include projects/edit-project ]] diff --git a/views/projects/layouts-modal.ejs b/views/projects/layouts-modal.ejs index 6f60d81..0d648cd 100644 --- a/views/projects/layouts-modal.ejs +++ b/views/projects/layouts-modal.ejs @@ -7,7 +7,8 @@ <div class="templates-list"> </div> <form> - <input data-role="create-new-layout" class="button_text" type="submit" value="New Layout"> + <input data-role="create-new-blueprint" class="button_text" type="submit" value="Trace a Blueprint"> + <input data-role="create-new-layout" class="button_text" type="submit" value="Make a Standard Layout"> </form> </div> <div class="no-templates"> @@ -43,7 +44,9 @@ <div class="templates-list"> </div> + <form> + <input data-role="create-new-blueprint" class="button_text" type="submit" value="trace a blueprint"> <input data-role="create-new-layout" class="button_text" type="submit" value="or make your own template"> </form> </div> diff --git a/views/reader.ejs b/views/reader.ejs index 6c9856a..7035356 100644 --- a/views/reader.ejs +++ b/views/reader.ejs @@ -1,7 +1,7 @@ <!doctype html> <html> <head> - <title>vvalls</title> + <title>VValls</title> [[ include partials/meta ]] </head> <body class="loading reader"> diff --git a/views/staff/_blueprints.ejs b/views/staff/_blueprints.ejs new file mode 100644 index 0000000..58fe2a3 --- /dev/null +++ b/views/staff/_blueprints.ejs @@ -0,0 +1,21 @@ +<table id="users"> +[[ blueprints.forEach(function(blueprint){ ]] + <tr> + <td> + <a href="/staff/blueprints/[[- blueprint.slug ]]">[[- blueprint.name ]]</a> + </td> + <td class="editLinks"> + <a href="/blueprint/[[- blueprint.slug ]]">[view]</a> +<!-- + <a href="/api/rooms/[[- blueprint.slug ]]">[api]</a> + --> + </td> + <td> + <a href="/staff/users/[[- blueprint.user.username ]]">[[- blueprint.user.username ]]</a> + </td> + <td> + [[- blueprint.date ]] + </td> + </tr> +[[ }) ]] +</table> diff --git a/views/staff/_header.ejs b/views/staff/_header.ejs index 3bbf4f1..a73c12e 100644 --- a/views/staff/_header.ejs +++ b/views/staff/_header.ejs @@ -1,7 +1,7 @@ <!doctype html> <html> <head> - <title>vvalls | staff</title> + <title>VValls | staff</title> [[ include ../partials/meta ]] <link rel="stylesheet" href="/assets/javascripts/vendor/bower_components/jquery-jsonview/dist/jquery.jsonview.css"></script> <link rel="stylesheet" href="/assets/stylesheets/staff.css"></script> diff --git a/views/staff/_layouts.ejs b/views/staff/_layouts.ejs new file mode 100644 index 0000000..d97883b --- /dev/null +++ b/views/staff/_layouts.ejs @@ -0,0 +1,22 @@ +<table id="users"> +[[ layouts.forEach(function(layout){ ]] + <tr> + <td> + <a href="/staff/layouts/[[- layout.slug ]]">[[- layout.name ]]</a> + </td> + <td class="editLinks"> + <a href="/layout/[[- layout.slug ]]">[view]</a> + <a href="/layout/[[- layout.slug ]]/edit">[edit]</a> +<!-- + <a href="/api/rooms/[[- layout.slug ]]">[api]</a> + --> + </td> + <td> + <a href="/staff/users/[[- layout.user.username ]]">[[- layout.user.username ]]</a> + </td> + <td> + [[- layout.date ]] + </td> + </tr> +[[ }) ]] +</table> diff --git a/views/staff/_nav.ejs b/views/staff/_nav.ejs new file mode 100644 index 0000000..702a374 --- /dev/null +++ b/views/staff/_nav.ejs @@ -0,0 +1,10 @@ +<nav> + <a href="/staff">home</a> + <a href="/staff/users">users</a> + <a href="/staff/projects">projects</a> + <a href="/staff/layouts">layouts</a> + <a href="/staff/blueprints">blueprints</a> + <a href="/staff/media">media</a> + <a href="/staff/plans">plans</a> +<!-- <a href="/staff/subscriptions">subscriptions</a> --> +</nav>
\ No newline at end of file diff --git a/views/staff/_pagination.ejs b/views/staff/_pagination.ejs index 6c3bfb1..7d85c71 100644 --- a/views/staff/_pagination.ejs +++ b/views/staff/_pagination.ejs @@ -10,7 +10,7 @@ [[ if (pagination.next_page !== -1) { ]] <a href="?[[- pagination.query ]]&offset=[[- pagination.next_page ]]">Next page →</a> [[ } else { ]] - → + -> [[ } ]] </div> diff --git a/views/staff/_users.ejs b/views/staff/_users.ejs index d46058f..ee988ab 100644 --- a/views/staff/_users.ejs +++ b/views/staff/_users.ejs @@ -1,3 +1,18 @@ +<nav class="subnav"> + sort by <a href="?sort=date">join date</a> ... <a href="?sort=last_seen">recent</a> ... <a href="?sort=name">name</a> ... jump to a letter: + <span class="alphabet"> + [[ "abcdefghijklmnopqrstuvwxyz?".split("").forEach(function(letter){ ]] + <a href="?sort=name&initial=[[- letter ]]">[[- letter.toUpperCase() ]]</a> + [[ }) ]] + </span> +</nav> + +[[ if (! users.length || opt.error) { ]] +<div class="error"> + [[- opt.error ]] +</div> +[[ } ]] + <table id="users"> [[ users.forEach(function(user){ ]] <tr> @@ -5,6 +20,10 @@ <a href="/staff/users/[[- user.username ]]"><div style="background-image:url([[- user.photo ]])" class="avatar"></div></a> </td> <td> + [[- user.plan_type ]] + [[- user.last_charged ]] + </td> + <td> <a href="/staff/users/[[- user.username ]]">[[- user.username ]]</a> </td> <td> @@ -12,6 +31,8 @@ </td> <td class="editLinks"> <a href="/profile/[[- user.username ]]">[view profile]</a> + <a href="/staff/users/[[- user.username ]]/media">[view media]</a> + <a href="https://vvalls.recurly.com/accounts/[[- user._id ]]">[recurly]</a> </td> <td> [[- user.last_seen ]] diff --git a/views/staff/blueprints/index.ejs b/views/staff/blueprints/index.ejs new file mode 100644 index 0000000..2206a1c --- /dev/null +++ b/views/staff/blueprints/index.ejs @@ -0,0 +1,13 @@ +[[ include ../_header ]] + + <h1>Blueprints</h1> + +[[ include ../_nav ]] + + <hr> + +[[ include ../_pagination ]] +[[ include ../_blueprints ]] +[[ include ../_pagination ]] + +[[ include ../_footer ]] diff --git a/views/staff/blueprints/show.ejs b/views/staff/blueprints/show.ejs new file mode 100644 index 0000000..5fd9db6 --- /dev/null +++ b/views/staff/blueprints/show.ejs @@ -0,0 +1,59 @@ +[[ include ../_header ]] + + <h1>[[- blueprint.name ]]</h1> + +[[ include ../_nav ]] + + <hr> + + <table> + <tr> + <td> + <a href="/staff/blueprints/[[- blueprint.slug ]]">[[- blueprint.name ]]</a> + </td> + <td class="editLinks"> + <a href="/blueprint/[[- blueprint.slug ]]">[view]</a> + <a href="/blueprint/[[- blueprint.slug ]]/edit">[edit]</a> +<!-- + <a href="/api/rooms/[[- blueprint.slug ]]">[api]</a> + --> + </td> + <td> + [[- blueprint.date ]] + </td> + </tr> + <tr> + <td> + [[ if (blueprintUser.photo) { ]] + <a href="/staff/users/[[- blueprintUser.username ]]"><div style="background-image:url([[- blueprintUser.photo ]])" class="avatar"></div></a> + [[ } ]] + <a href="/staff/users/[[- blueprintUser.username ]]">[[- blueprintUser.username ]]</a> + </td> + </tr> + <tr> + <td colspan="999"> + <img src="[[- blueprint.url ]]" style="max-width: 400px"> + </td> + </tr> + <tr> + <td>Width</td> + <td>[[- blueprint.width ]]</td> + </tr> + <tr> + <td>Height</td> + <td>[[- blueprint.height ]]</td> + </tr> + <tr> + <td>Scale</td> + <td>[[- blueprint.scale ]]</td> + </tr> + </table> + + <br><br> + <div id="actions"> + </div> + + <br> + <br> + +[[ include ../_footer ]] diff --git a/views/staff/blueprints/show_404.ejs b/views/staff/blueprints/show_404.ejs new file mode 100644 index 0000000..0ffca86 --- /dev/null +++ b/views/staff/blueprints/show_404.ejs @@ -0,0 +1,9 @@ +[[ include ../_header ]] + + <h1>Blueprint not found</h1> + +[[ include ../_nav ]] + + <hr> + +[[ include ../_footer ]] diff --git a/views/staff/index.ejs b/views/staff/index.ejs index 5ca7269..1b73641 100644 --- a/views/staff/index.ejs +++ b/views/staff/index.ejs @@ -2,11 +2,7 @@ <h1>Staff Area</h1> - <nav> - <a href="/staff/users">users</a> - <a href="/staff/projects">projects</a> - <a href="/staff/media">media</a> - </nav> + [[ include _nav ]] <hr> diff --git a/views/staff/layouts/index.ejs b/views/staff/layouts/index.ejs new file mode 100644 index 0000000..71f5dc7 --- /dev/null +++ b/views/staff/layouts/index.ejs @@ -0,0 +1,13 @@ +[[ include ../_header ]] + + <h1>Layouts</h1> + +[[ include ../_nav ]] + + <hr> + +[[ include ../_pagination ]] +[[ include ../_layouts ]] +[[ include ../_pagination ]] + +[[ include ../_footer ]] diff --git a/views/staff/layouts/show.ejs b/views/staff/layouts/show.ejs new file mode 100644 index 0000000..2742c1f --- /dev/null +++ b/views/staff/layouts/show.ejs @@ -0,0 +1,61 @@ +[[ include ../_header ]] + + <h1>[[- layout.name ]]</h1> + +[[ include ../_nav ]] + + <hr> + + <table> + <tr> + <td> + <a href="/staff/layouts/[[- layout.slug ]]">[[- layout.name ]]</a> + </td> + <td class="editLinks"> + <a href="/layout/[[- layout.slug ]]">[view]</a> + <a href="/layout/[[- layout.slug ]]/edit">[edit]</a> +<!-- + <a href="/api/rooms/[[- layout.slug ]]">[api]</a> + --> + </td> + <td> + [[- layout.date ]] + </td> +<!-- + <td> + [[- layout.privacy ? "private" : "" ]] + </td> + --> + </tr> + <tr> + <td> + [[ if (layoutUser.photo) { ]] + <a href="/staff/users/[[- layoutUser.username ]]"><div style="background-image:url([[- layoutUser.photo ]])" class="avatar"></div></a> + [[ } ]] + <a href="/staff/users/[[- layoutUser.username ]]">[[- layoutUser.username ]]</a> + </td> + </tr> + <tr> + <td colspan="999" class="description"> + "[[- layout.description ]]" + </td> + </tr> + <tr> + <th> + stock layout? + </th> + <td id="isStockLayout"> + [[- layout.is_stock ? "yes" : "no" ]] + </td> + </tr> + </table> + + <br><br> + <div id="actions"> + <button id="toggle-stock" data-stock="[[- !! (layout.is_stock) ]]">Make this layout Stock</button> + </div> + + <br> + <br> + +[[ include ../_footer ]] diff --git a/views/staff/layouts/show_404.ejs b/views/staff/layouts/show_404.ejs new file mode 100644 index 0000000..5d24aa8 --- /dev/null +++ b/views/staff/layouts/show_404.ejs @@ -0,0 +1,9 @@ +[[ include ../_header ]] + + <h1>Layout not found</h1> + +[[ include ../_nav ]] + + <hr> + +[[ include ../_footer ]] diff --git a/views/staff/media/index.ejs b/views/staff/media/index.ejs index 516af2d..3805c8e 100644 --- a/views/staff/media/index.ejs +++ b/views/staff/media/index.ejs @@ -2,12 +2,7 @@ <h1>Media</h1> - <nav> - <a href="/staff">home</a> - <a href="/staff/users">users</a> - <a href="/staff/projects">projects</a> - <a href="/staff/media">media</a> - </nav> +[[ include ../_nav ]] <hr> diff --git a/views/staff/media/show.ejs b/views/staff/media/show.ejs index 76dcd32..9d05cb9 100644 --- a/views/staff/media/show.ejs +++ b/views/staff/media/show.ejs @@ -2,12 +2,7 @@ <h1>Media: [[- media.type ]]</h1> - <nav> - <a href="/staff">home</a> - <a href="/staff/users">users</a> - <a href="/staff/projects">projects</a> - <a href="/staff/media">media</a> - </nav> +[[ include ../_nav ]] <hr> diff --git a/views/staff/media/show_404.ejs b/views/staff/media/show_404.ejs index f07cef2..c6bac6f 100644 --- a/views/staff/media/show_404.ejs +++ b/views/staff/media/show_404.ejs @@ -2,13 +2,8 @@ <h1>Media not found</h1> - <nav> - <a href="/staff">home</a> - <a href="/staff/users">users</a> - <a href="/staff/projects">projects</a> - <a href="/staff/media">media</a> - </nav> - +[[ include ../_nav ]] + <hr> [[ include ../_footer ]] diff --git a/views/staff/plans/_form.ejs b/views/staff/plans/_form.ejs new file mode 100644 index 0000000..85375fa --- /dev/null +++ b/views/staff/plans/_form.ejs @@ -0,0 +1,154 @@ +<input type="hidden" id="_csrf" name="_csrf" value="[[- token ]]"> + +<ul> + +<li class="section_break"> + <h3>New Plan</h3> +</li> + +<li> + <label for="plan_name">Name</label> + <div><input id="plan_name" name="name" type="text" value="[[- plan.name ]]"></div> +</li> + +<li> + <label for="plan_slug">Slug</label> + <div><input id="plan_slug" name="slug" type="text" value="[[- plan.slug ]]"></div> +</li> + +<li> + <label for="plan_level">Level</label> + <div><input id="plan_level" name="level" type="number" min="0" value="[[- plan.level ]]"></div> +</li> + +<!-- - - - - --> + +<li class="section_break"> + <h3>Plan Pricing</h3> +</li> + +<li> + <label for="plan_monthly_price">Monthly Price</label> + <div><input id="plan_monthly_price" name="monthly_price" type="number" min="0" value="[[- plan.monthly_price ]]"></div> +</li> + +<li> + <label for="plan_yearly_price">Yearly Price</label> + <div><input id="plan_yearly_price" name="yearly_price" type="number" min="0" value="[[- plan.yearly_price ]]"></div> +</li> + +<p> + <i>Note:</i> Pricing should be in cents, i.e. a price of $10.00 should be entered as 1000. +</p> + +<!-- - - - - --> + +<li class="section_break"> + <h3>Additional Template Pricing</h3> +</li> + +<li> + <label for="plan_basic_layout_monthly_price">Basic Template Price (Monthly)</label> + <div><input id="plan_basic_layout_monthly_price" name="basic_layout_monthly_price" type="number" min="0" value="[[- plan.basic_layout_monthly_price ]]"></div> +</li> + +<li> + <label for="plan_basic_layout_yearly_price">Basic Template Price (Yearly)</label> + <div><input id="plan_basic_layout_yearly_price" name="basic_layout_yearly_price" type="number" min="0" value="[[- plan.basic_layout_yearly_price ]]"></div> +</li> + +<li> + <label for="plan_pro_layout_monthly_price">Pro Template Price (Monthly)</label> + <div><input id="plan_pro_layout_monthly_price" name="pro_layout_monthly_price" type="number" min="0" value="[[- plan.pro_layout_monthly_price ]]"></div> +</li> + +<li> + <label for="plan_pro_layout_yearly_price">Pro Template Price (Yearly)</label> + <div><input id="plan_pro_layout_yearly_price" name="pro_layout_yearly_price" type="number" min="0" value="[[- plan.pro_layout_yearly_price ]]"></div> +</li> + +<!-- - - - - --> + +<li class="section_break"> + <h3>Per-Plan Template Limits</h3> +</li> + +<li> + <label for="plan_basic_layout_limit">Basic Template Limit</label> + <div><input id="plan_basic_layout_limit" name="basic_layout_limit" type="number" min="0" value="[[- plan.basic_layout_limit ]]"></div> +</li> + +<li> + <label for="plan_pro_layout_limit">Pro Template Limit</label> + <div><input id="plan_pro_layout_limit" name="pro_layout_limit" type="number" min="0" value="[[- plan.pro_layout_limit ]]"></div> +</li> + +<!-- - - - - --> + +<li class="section_break"> + <h3>Per-Plan Project Limits</h3> +</li> + +<li> + <label for="plan_stock_project_limit">Stock Project Limit</label> + <div><input id="plan_stock_project_limit" name="stock_project_limit" type="number" min="0" value="[[- plan.stock_project_limit ]]"></div> +</li> + +<li> + <label for="plan_basic_project_limit">Basic Project Limit</label> + <div><input id="plan_basic_project_limit" name="basic_project_limit" type="number" min="0" value="[[- plan.basic_project_limit ]]"></div> +</li> + +<li> + <label for="plan_pro_project_limit">Pro Project Limit</label> + <div><input id="plan_pro_project_limit" name="pro_project_limit" type="number" min="0" value="[[- plan.pro_project_limit ]]"></div> +</li> + +<!-- - - - - --> + +<li class="section_break"> + <h3>Permissions</h3> +</li> + +<div> +<li> + <input name="permissions_basic_editor" type="hidden" value="0"> + <input id="plan_permissions_basic_editor" name="permissions_basic_editor" type="checkbox" value="1" [[ if (plan.permissions.basic_editor) { ]]checked[[ } ]]> + <label for="plan_permissions_basic_editor">Basic Editor</label> +</li> + +<li> + <input name="permissions_pro_editor" type="hidden" value="0"> + <input id="plan_permissions_pro_editor" name="permissions_pro_editor" type="checkbox" value="1" [[ if (plan.permissions.pro_editor) { ]]checked[[ } ]]> + <label for="plan_permissions_pro_editor">Pro Editor</label> +</li> + +<li> + <input name="permissions_sculpture" type="hidden" value="0"> + <input id="plan_permissions_sculpture" name="permissions_sculpture" type="checkbox" value="1" [[ if (plan.permissions.sculpture) { ]]checked[[ } ]]> + <label for="plan_permissions_sculpture">3D Objects</label> +</li> + +<li> + <input name="permissions_collaborators" type="hidden" value="0"> + <input id="plan_permissions_collaborators" name="permissions_collaborators" type="checkbox" value="1" [[ if (plan.permissions.collaborators) { ]]checked[[ } ]]> + <label for="plan_permissions_collaborators">Collaborators</label> +</li> + +<li> + <input name="permissions_no_logo" type="hidden" value="0"> + <input id="plan_permissions_no_logo" name="permissions_no_logo" type="checkbox" value="1" [[ if (plan.permissions.no_logo) { ]]checked[[ } ]]> + <label for="plan_permissions_no_logo">No Logo</label> +</li> + +<p> + These permissions should harmonize with the restrictions on layouts set above. +</p> + +</div> + +<li> + <input type="submit" value="Save Changes"> +</li> + +</ul> diff --git a/views/staff/plans/edit.ejs b/views/staff/plans/edit.ejs new file mode 100644 index 0000000..9848873 --- /dev/null +++ b/views/staff/plans/edit.ejs @@ -0,0 +1,13 @@ +[[ include ../_header ]] + + <h1>Edit Plan</h1> + +[[ include ../_nav ]] + + <hr> + +<form action="" method="post"> +[[- include _form ]] +</form> + +[[ include ../_footer ]] diff --git a/views/staff/plans/index.ejs b/views/staff/plans/index.ejs new file mode 100644 index 0000000..16fcf14 --- /dev/null +++ b/views/staff/plans/index.ejs @@ -0,0 +1,65 @@ +[[ include ../_header ]] + + <h1>Plans</h1> + +[[ include ../_nav ]] + + <hr> + +<table> + <tr> + <td> + </td> + [[ plans.forEach(function(plan){ ]] + <td style="text-align:right; min-width: 100px;"> + <b style="text-transform:uppercase">[[- plan.name ]]</b> + </td> + [[ }) ]] + </tr> + + <tr class="editLinks"> + <td> + <a href="/staff/plans/new">New Plan</a> + </td> + [[ plans.forEach(function(plan){ ]] + <td style="text-align:right"> + [<a href="/staff/plans/[[- plan.slug ]]">edit</a>] + </td> + [[ }) ]] + </tr> + + [[ fields.forEach(function(field){ ]] + <tr> + <td style="text-transform:capitalize">[[- field.replace(/_/g," ") ]]</td> + [[ plans.forEach(function(plan){ ]] + <td style="text-align:right"> + [[ if (field.indexOf("_price") != -1) { ]] + [[- plan[field] == 0 ? "" : "$" + (plan[field]/100).toFixed(2) ]] + [[ } else { ]] + [[- plan[field] ]] + [[ } ]] + </td> + [[ }) ]] + </tr> + [[ }) ]] + + <tr> + <td style="border-bottom: 1px dotted #888;" colspan='10'></td> + </tr> + + [[ permissions.forEach(function(permission){ ]] + <tr> + <td style="text-transform:capitalize">[[- permission.replace(/_/g," ") ]]</td> + [[ plans.forEach(function(plan){ ]] + <td style="text-align:right"> + [[- plan.permissions[permission] ? "<b>x</b>" : " " ]] + </td> + [[ }) ]] + </tr> + [[ }) ]] +</table> +<br clear="all"> + + <hr> + +[[ include ../_footer ]] diff --git a/views/staff/plans/new.ejs b/views/staff/plans/new.ejs new file mode 100644 index 0000000..297d3d6 --- /dev/null +++ b/views/staff/plans/new.ejs @@ -0,0 +1,13 @@ +[[ include ../_header ]] + + <h1>New Plan</h1> + +[[ include ../_nav ]] + + <hr> + +<form action="" method="post"> +[[- include _form ]] +</form> + +[[ include ../_footer ]] diff --git a/views/staff/projects/index.ejs b/views/staff/projects/index.ejs index 482ea25..e4ba469 100644 --- a/views/staff/projects/index.ejs +++ b/views/staff/projects/index.ejs @@ -2,12 +2,7 @@ <h1>Projects</h1> - <nav> - <a href="/staff">home</a> - <a href="/staff/users">users</a> - <a href="/staff/projects">projects</a> - <a href="/staff/media">media</a> - </nav> +[[ include ../_nav ]] <hr> diff --git a/views/staff/projects/show.ejs b/views/staff/projects/show.ejs index 1034b31..b090a41 100644 --- a/views/staff/projects/show.ejs +++ b/views/staff/projects/show.ejs @@ -2,13 +2,8 @@ <h1>[[- project.name ]]</h1> - <nav> - <a href="/staff">home</a> - <a href="/staff/users">users</a> - <a href="/staff/projects">projects</a> - <a href="/staff/media">media</a> - </nav> - +[[ include ../_nav ]] + <hr> <table> diff --git a/views/staff/projects/show_404.ejs b/views/staff/projects/show_404.ejs index 70320c0..f5e1658 100644 --- a/views/staff/projects/show_404.ejs +++ b/views/staff/projects/show_404.ejs @@ -2,12 +2,7 @@ <h1>Project not found</h1> - <nav> - <a href="/staff">home</a> - <a href="/staff/users">users</a> - <a href="/staff/projects">projects</a> - <a href="/staff/media">media</a> - </nav> +[[ include ../_nav ]] <hr> diff --git a/views/staff/subscriptions/index.ejs b/views/staff/subscriptions/index.ejs new file mode 100644 index 0000000..adf148c --- /dev/null +++ b/views/staff/subscriptions/index.ejs @@ -0,0 +1,39 @@ +[[ include ../_header ]] + + <h1>Subscriptions</h1> + +[[ include ../_nav ]] + + <hr> + +[[ include ../_pagination ]] + +<table id="users"> +[[ subscriptions.forEach(function(subscription){ ]] + <tr> + <td> + <a href="/staff/subscriptions/[[- subscription._id ]]"><div style="background-image:url([[- subscription.user.photo ]])" class="avatar"></div></a> + </td> + <td> + <a href="/staff/subscriptions/[[- subscription._id ]]">[[- subscription.user.username ]]</a> + </td> + <td> + [[- subscription.user.displayName ]] + </td> + <td class="editLinks"> + <a href="/profile/[[- user.username ]]">[view profile]</a> + </td> + <td> + [[- subscription.user.last_seen ]] + </td> + <td> + [[- subscription.plan_code ]] + </td> + </tr> +[[ }) ]] +</table> + + +[[ include ../_pagination ]] + +[[ include ../_footer ]] diff --git a/views/staff/subscriptions/show.ejs b/views/staff/subscriptions/show.ejs new file mode 100644 index 0000000..e2839a6 --- /dev/null +++ b/views/staff/subscriptions/show.ejs @@ -0,0 +1,12 @@ +[[ include ../_header ]] + <h1>User: [[- subscription.user.username ]]</h1> + +[[ include ../_nav ]] + + <hr> + +<pre> +info to show.. +- link to recurly profile +- link to vvalls profile +- subscription tier + add-ons diff --git a/views/staff/users/index.ejs b/views/staff/users/index.ejs index f14d666..1795dde 100644 --- a/views/staff/users/index.ejs +++ b/views/staff/users/index.ejs @@ -2,12 +2,7 @@ <h1>Users</h1> - <nav> - <a href="/staff">home</a> - <a href="/staff/users">users</a> - <a href="/staff/projects">projects</a> - <a href="/staff/media">media</a> - </nav> +[[ include ../_nav ]] <hr> diff --git a/views/staff/users/media.ejs b/views/staff/users/media.ejs index c1097dd..8927c00 100644 --- a/views/staff/users/media.ejs +++ b/views/staff/users/media.ejs @@ -1,15 +1,10 @@ [[ include ../_header ]] - <h1>User Media: [[- profile.username ]]</h1> +<h1>User Media: [[- profile.username ]]</h1> - <nav> - <a href="/staff">home</a> - <a href="/staff/users">users</a> - <a href="/staff/projects">projects</a> - <a href="/staff/media">media</a> - </nav> - - <hr> +[[ include ../_nav ]] + +<hr> [[ include ../_pagination ]] [[ include ../_gallery ]] diff --git a/views/staff/users/show.ejs b/views/staff/users/show.ejs index 8e9b447..a434b57 100644 --- a/views/staff/users/show.ejs +++ b/views/staff/users/show.ejs @@ -1,12 +1,7 @@ [[ include ../_header ]] <h1>User: [[- profile.username ]]</h1> - <nav> - <a href="/staff">home</a> - <a href="/staff/users">users</a> - <a href="/staff/projects">projects</a> - <a href="/staff/media">media</a> - </nav> +[[ include ../_nav ]] <hr> @@ -22,12 +17,38 @@ [[- profile.displayName ]] </td> <td class="editLinks"> - <a href="/profile/[[- profile.username ]]">[view profile]</a> - <a href="/staff/users/[[- profile.username ]]/media">[view media]</a> + <a href="/profile/[[- profile.username ]]">[profile]</a> + <a href="/staff/users/[[- profile.username ]]/media">[media]</a> + [[ if (profile.subscription) { ]] + <a href="https://vvalls.recurly.com/accounts/[[- profile._id ]]">[recurly]</a> + [[ } ]] </td> </tr> </table> + + [[ if (profile.subscription) { ]] + <h2>Subscription</h2> + <table> + <tr> + <th> + plan + </th> + <td> + [[- profile.plan_code ]] + </td> + </tr> + <tr> + <th> + last charged + </th> + <td> + [[- profile.last_charged ]] + </td> + </tr> + </table> + [[ } ]] + <h2>Profile</h2> <table> @@ -80,12 +101,21 @@ [[- profile.isStaff ? "yes" : "no" ]] </td> </tr> + <tr> + <th> + is artist? + </th> + <td id="is-artist"> + [[- profile.isArtist ? "yes" : "no" ]] + </td> + </tr> </table> <br><br> <div id="actions"> [[ if (String(user._id) != String(profile._id)) { ]] <button id="toggle-staff" data-isStaff="[[- !! profile.isStaff ]]">Make Staff</button> + <button id="toggle-artist" data-isArtist="[[- !! profile.isArtist ]]">Make Artist</button> [[ } ]] </div> diff --git a/views/staff/users/show_404.ejs b/views/staff/users/show_404.ejs index bcd0271..11663fa 100644 --- a/views/staff/users/show_404.ejs +++ b/views/staff/users/show_404.ejs @@ -1,13 +1,9 @@ [[ include ../_header ]] - <h1>User not found</h1> - <nav> - <a href="/staff">home</a> - <a href="/staff/users">users</a> - <a href="/staff/projects">projects</a> - <a href="/staff/media">media</a> - </nav> - - <hr> +<h1>User not found</h1> + +[[ include ../_nav ]] + +<hr> [[ include ../_footer ]] |
