summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Gruntfile.js277
-rw-r--r--Procfile3
-rw-r--r--README.md17
-rw-r--r--bower.json3
-rw-r--r--config.json.example13
-rw-r--r--package.json58
-rwxr-xr-xpublic/assets/fonts/ionicons.eotbin101984 -> 120724 bytes
-rwxr-xr-xpublic/assets/fonts/ionicons.svg1725
-rwxr-xr-xpublic/assets/fonts/ionicons.ttfbin164548 -> 188508 bytes
-rwxr-xr-xpublic/assets/fonts/ionicons.woffbin57276 -> 67904 bytes
-rw-r--r--public/assets/javascripts/app.js34
-rw-r--r--public/assets/javascripts/defaults.js4
-rw-r--r--public/assets/javascripts/mx/extensions/mx.movements.js30
-rw-r--r--public/assets/javascripts/mx/extensions/mx.orbitCamera.js97
-rw-r--r--public/assets/javascripts/mx/mx.js16
-rw-r--r--public/assets/javascripts/mx/primitives/mx.grid.js70
-rw-r--r--public/assets/javascripts/mx/primitives/mx.image.js40
-rw-r--r--public/assets/javascripts/mx/primitives/mx.point.js17
-rw-r--r--public/assets/javascripts/mx/primitives/mx.polyline.js57
-rw-r--r--public/assets/javascripts/mx/primitives/mx.soundcloud.js5
-rw-r--r--public/assets/javascripts/mx/primitives/mx.text.js2
-rw-r--r--public/assets/javascripts/mx/primitives/mx.video.js8
-rw-r--r--public/assets/javascripts/mx/primitives/mx.vimeo.js23
-rw-r--r--public/assets/javascripts/mx/primitives/mx.youtube.js8
-rw-r--r--public/assets/javascripts/rectangles/_env.js35
-rw-r--r--public/assets/javascripts/rectangles/engine/map/_map.js42
-rw-r--r--public/assets/javascripts/rectangles/engine/map/draw.js104
-rw-r--r--public/assets/javascripts/rectangles/engine/map/tools/_base.js11
-rw-r--r--public/assets/javascripts/rectangles/engine/map/tools/arrow.js83
-rw-r--r--public/assets/javascripts/rectangles/engine/map/tools/eraser.js29
-rw-r--r--public/assets/javascripts/rectangles/engine/map/tools/line.js63
-rw-r--r--public/assets/javascripts/rectangles/engine/map/tools/ortho.js118
-rw-r--r--public/assets/javascripts/rectangles/engine/map/tools/polyline.js73
-rw-r--r--public/assets/javascripts/rectangles/engine/map/tools/position.js19
-rw-r--r--public/assets/javascripts/rectangles/engine/map/tools/start.js29
-rw-r--r--public/assets/javascripts/rectangles/engine/map/ui/editor.js (renamed from public/assets/javascripts/rectangles/engine/map/ui_editor.js)8
-rw-r--r--public/assets/javascripts/rectangles/engine/map/ui/minimap.js (renamed from public/assets/javascripts/rectangles/engine/map/ui_minimap.js)0
-rw-r--r--public/assets/javascripts/rectangles/engine/map/ui/ortho.js107
-rw-r--r--public/assets/javascripts/rectangles/engine/rooms/_rooms.js41
-rw-r--r--public/assets/javascripts/rectangles/engine/scenery/_scenery.js30
-rw-r--r--public/assets/javascripts/rectangles/engine/scenery/move.js8
-rw-r--r--public/assets/javascripts/rectangles/engine/scenery/resize.js5
-rw-r--r--public/assets/javascripts/rectangles/engine/scenery/sound.js16
-rw-r--r--public/assets/javascripts/rectangles/engine/scenery/types/_object.js4
-rw-r--r--public/assets/javascripts/rectangles/engine/scenery/types/audio.js4
-rw-r--r--public/assets/javascripts/rectangles/engine/scenery/types/video.js11
-rw-r--r--public/assets/javascripts/rectangles/engine/scenery/undo.js65
-rw-r--r--public/assets/javascripts/rectangles/engine/sculpture/_sculpture.js105
-rw-r--r--public/assets/javascripts/rectangles/engine/sculpture/move.js111
-rw-r--r--public/assets/javascripts/rectangles/engine/sculpture/resize.js208
-rw-r--r--public/assets/javascripts/rectangles/engine/sculpture/types/_object.js176
-rw-r--r--public/assets/javascripts/rectangles/engine/sculpture/types/image.js38
-rw-r--r--public/assets/javascripts/rectangles/engine/shapes/ortho.js66
-rw-r--r--public/assets/javascripts/rectangles/engine/shapes/polyline.js212
-rw-r--r--public/assets/javascripts/rectangles/engine/shapes/regionlist.js240
-rw-r--r--public/assets/javascripts/rectangles/engine/shapes/shapelist.js124
-rw-r--r--public/assets/javascripts/rectangles/models/floor.js39
-rw-r--r--public/assets/javascripts/rectangles/models/rect.js33
-rw-r--r--public/assets/javascripts/rectangles/models/room.js7
-rw-r--r--public/assets/javascripts/rectangles/models/vec2.js18
-rw-r--r--public/assets/javascripts/rectangles/models/vec3.js25
-rw-r--r--public/assets/javascripts/rectangles/models/wall.js12
-rw-r--r--public/assets/javascripts/rectangles/util/constants.js5
-rw-r--r--public/assets/javascripts/rectangles/util/coords.js2
-rw-r--r--public/assets/javascripts/rectangles/util/measurement.js4
-rw-r--r--public/assets/javascripts/rectangles/util/minotaur.js6
-rw-r--r--public/assets/javascripts/rectangles/util/mouse.js25
-rw-r--r--public/assets/javascripts/rectangles/util/wheel.js10
-rw-r--r--public/assets/javascripts/ui/_router.js86
-rw-r--r--public/assets/javascripts/ui/blueprint/BlueprintEditor.js129
-rw-r--r--public/assets/javascripts/ui/blueprint/BlueprintInfo.js92
-rw-r--r--public/assets/javascripts/ui/blueprint/BlueprintNotice.js62
-rw-r--r--public/assets/javascripts/ui/blueprint/BlueprintScaler.js158
-rw-r--r--public/assets/javascripts/ui/blueprint/BlueprintSettings.js123
-rw-r--r--public/assets/javascripts/ui/blueprint/BlueprintToolbar.js97
-rw-r--r--public/assets/javascripts/ui/blueprint/BlueprintUploader.js147
-rw-r--r--public/assets/javascripts/ui/blueprint/BlueprintView.js106
-rw-r--r--public/assets/javascripts/ui/builder/BuilderInfo.js4
-rw-r--r--public/assets/javascripts/ui/builder/BuilderSettings.js2
-rw-r--r--public/assets/javascripts/ui/builder/BuilderToolbar.js3
-rw-r--r--public/assets/javascripts/ui/editor/EditorSettings.js17
-rw-r--r--public/assets/javascripts/ui/editor/EditorView.js17
-rw-r--r--public/assets/javascripts/ui/editor/SculptureEditor.js237
-rw-r--r--public/assets/javascripts/ui/lib/AnimatedView.js31
-rw-r--r--public/assets/javascripts/ui/lib/ConfirmModal.js24
-rw-r--r--public/assets/javascripts/ui/lib/FormView.js9
-rw-r--r--public/assets/javascripts/ui/lib/LabColorPicker.js26
-rw-r--r--public/assets/javascripts/ui/lib/ModalView.js5
-rw-r--r--public/assets/javascripts/ui/lib/ToggleableView.js19
-rw-r--r--public/assets/javascripts/ui/lib/Toolbar.js22
-rw-r--r--public/assets/javascripts/ui/reader/MediaPlayer.js2
-rw-r--r--public/assets/javascripts/ui/reader/ReaderView.js22
-rw-r--r--public/assets/javascripts/ui/reader/Tracker.js14
-rw-r--r--public/assets/javascripts/ui/reader/_router.js24
-rw-r--r--public/assets/javascripts/ui/site/EditSubscriptionModal.js290
-rw-r--r--public/assets/javascripts/ui/site/HomeView.js2
-rw-r--r--public/assets/javascripts/ui/site/LayoutsIndex.js85
-rw-r--r--public/assets/javascripts/ui/site/LayoutsModal.js172
-rw-r--r--public/assets/javascripts/ui/site/NewProjectModal.js118
-rw-r--r--public/assets/javascripts/ui/site/StaffView.js47
-rw-r--r--public/assets/javascripts/util.js1
-rw-r--r--public/assets/javascripts/vendor/polyfill.js3
-rwxr-xr-xpublic/assets/stylesheets/app.css452
-rwxr-xr-xpublic/assets/stylesheets/ionicons.css884
-rw-r--r--public/assets/stylesheets/staff.css40
-rw-r--r--public/assets/test/bg.html1
-rw-r--r--public/assets/test/intersect.html5
-rw-r--r--public/assets/test/intersect2.html12
-rw-r--r--public/assets/test/intersect3.html12
-rw-r--r--public/assets/test/orbit.html154
-rw-r--r--public/assets/test/ortho.html290
-rw-r--r--public/assets/test/ortho2.html374
-rw-r--r--public/assets/test/ortho3.html258
-rw-r--r--public/assets/test/ortho4.html303
-rw-r--r--public/assets/test/static.html152
-rw-r--r--public/assets/test/surface.html5
-rw-r--r--server/fetch.js41
-rw-r--r--server/index.js37
-rw-r--r--server/lib/api/blueprint.js142
-rw-r--r--server/lib/api/index.js2
-rw-r--r--server/lib/api/layouts.js44
-rw-r--r--server/lib/api/profile.js1
-rw-r--r--server/lib/api/projects.js18
-rw-r--r--server/lib/api/rooms.js139
-rw-r--r--server/lib/api/subscription.js206
-rw-r--r--server/lib/auth/index.js15
-rw-r--r--server/lib/auth/mail.js2
-rw-r--r--server/lib/middleware.js84
-rw-r--r--server/lib/schemas/Blueprint.js66
-rw-r--r--server/lib/schemas/Layout.js3
-rw-r--r--server/lib/schemas/Media.js7
-rw-r--r--server/lib/schemas/Plan.js44
-rw-r--r--server/lib/schemas/Project.js4
-rw-r--r--server/lib/schemas/Subscription.js31
-rw-r--r--server/lib/schemas/User.js9
-rw-r--r--server/lib/util.js4
-rw-r--r--server/lib/views/index.js56
-rw-r--r--server/lib/views/staff.js545
-rw-r--r--server/lib/views/staff/defaults.js6
-rw-r--r--server/lib/views/staff/fields.js10
-rw-r--r--server/lib/views/staff/helpers.js59
-rw-r--r--server/lib/views/staff/index.js511
-rw-r--r--server/lib/views/staff/middleware.js476
-rw-r--r--server/lib/webhook/index.js44
-rw-r--r--server/lib/webhook/recurly-config.js6
-rw-r--r--server/lib/webhook/webhook.js178
-rw-r--r--server/repl.js2
-rw-r--r--views/about/_blank.ejs4
-rw-r--r--views/about/_old_plans.ejs63
-rw-r--r--views/about/_plans.ejs121
-rw-r--r--views/about/about.ejs18
-rw-r--r--views/about/brochure.ejs25
-rw-r--r--views/about/howto.ejs2
-rw-r--r--views/blueprint.ejs30
-rw-r--r--views/builder.ejs18
-rw-r--r--views/controls/blueprint/editor.ejs36
-rw-r--r--views/controls/blueprint/info.ejs30
-rw-r--r--views/controls/blueprint/notice.ejs4
-rw-r--r--views/controls/blueprint/scaler.ejs48
-rw-r--r--views/controls/blueprint/settings.ejs18
-rw-r--r--views/controls/blueprint/toolbar.ejs42
-rw-r--r--views/controls/builder/info.ejs4
-rw-r--r--views/controls/builder/settings.ejs2
-rw-r--r--views/controls/builder/toolbar.ejs6
-rw-r--r--views/controls/editor/media-drawer.ejs4
-rw-r--r--views/controls/editor/media-editor.ejs8
-rw-r--r--views/controls/editor/sculpture.ejs42
-rw-r--r--views/controls/editor/settings.ejs6
-rw-r--r--views/controls/editor/toolbar.ejs14
-rw-r--r--views/controls/editor/wallpaper.ejs2
-rw-r--r--views/controls/reader/about-room.ejs2
-rw-r--r--views/docs.ejs2
-rwxr-xr-xviews/editor.ejs3
-rwxr-xr-xviews/home.ejs26
-rw-r--r--views/modal.ejs4
-rw-r--r--views/partials/edit-profile.ejs2
-rw-r--r--views/partials/edit-subscription.ejs78
-rw-r--r--views/partials/footer.ejs10
-rw-r--r--views/partials/header.ejs7
-rw-r--r--views/partials/scripts.ejs49
-rw-r--r--views/profile.ejs86
-rw-r--r--views/projects/layouts-modal.ejs5
-rw-r--r--views/reader.ejs2
-rw-r--r--views/staff/_blueprints.ejs21
-rw-r--r--views/staff/_header.ejs2
-rw-r--r--views/staff/_layouts.ejs22
-rw-r--r--views/staff/_nav.ejs10
-rw-r--r--views/staff/_pagination.ejs2
-rw-r--r--views/staff/_users.ejs21
-rw-r--r--views/staff/blueprints/index.ejs13
-rw-r--r--views/staff/blueprints/show.ejs59
-rw-r--r--views/staff/blueprints/show_404.ejs9
-rw-r--r--views/staff/index.ejs6
-rw-r--r--views/staff/layouts/index.ejs13
-rw-r--r--views/staff/layouts/show.ejs61
-rw-r--r--views/staff/layouts/show_404.ejs9
-rw-r--r--views/staff/media/index.ejs7
-rw-r--r--views/staff/media/show.ejs7
-rw-r--r--views/staff/media/show_404.ejs9
-rw-r--r--views/staff/plans/_form.ejs154
-rw-r--r--views/staff/plans/edit.ejs13
-rw-r--r--views/staff/plans/index.ejs65
-rw-r--r--views/staff/plans/new.ejs13
-rw-r--r--views/staff/projects/index.ejs7
-rw-r--r--views/staff/projects/show.ejs9
-rw-r--r--views/staff/projects/show_404.ejs7
-rw-r--r--views/staff/subscriptions/index.ejs39
-rw-r--r--views/staff/subscriptions/show.ejs12
-rw-r--r--views/staff/users/index.ejs7
-rw-r--r--views/staff/users/media.ejs13
-rw-r--r--views/staff/users/show.ejs46
-rw-r--r--views/staff/users/show_404.ejs14
213 files changed, 12021 insertions, 2283 deletions
diff --git a/.gitignore b/.gitignore
index 50f54f1..2a58e7f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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']);
};
diff --git a/Procfile b/Procfile
index 983db91..bab08fb 100644
--- a/Procfile
+++ b/Procfile
@@ -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
diff --git a/README.md b/README.md
index 1c95b14..3bb1093 100644
--- a/README.md
+++ b/README.md
@@ -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)
+
diff --git a/bower.json b/bower.json
index 5f35d6c..e3e83ca 100644
--- a/bower.json
+++ b/bower.json
@@ -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
index 52b1e57..92a3f20 100755
--- a/public/assets/fonts/ionicons.eot
+++ b/public/assets/fonts/ionicons.eot
Binary files differ
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="&#xf100;"
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="&#xf101;" horiz-adv-x="128"
d="M128 -32h-128v96h128v-96zM112 128h-96l-16 288h128z" />
- <glyph glyph-name="ion-android-add-contact" unicode="&#xf2c6;" 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="&#xf2c7;" horiz-adv-x="512"
-d="M512 224v-64h-224v-224h-64v224h-224v64h224v224h64v-224h224z" />
- <glyph glyph-name="ion-android-alarm" unicode="&#xf2c8;" 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="&#xf2c9;" 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="&#xf2ca;" horiz-adv-x="256"
-d="M256 448l-144 -256l144 -256h-112l-144 256l144 256h112z" />
- <glyph glyph-name="ion-android-arrow-down-left" unicode="&#xf2cb;" horiz-adv-x="480"
-d="M0 256h80v-167l343 343l57 -57l-343 -343h167v-80h-304v304z" />
- <glyph glyph-name="ion-android-arrow-down-right" unicode="&#xf2cc;" horiz-adv-x="480"
-d="M480 256v-304h-304v80h167l-343 343l57 57l343 -343v167h80z" />
- <glyph glyph-name="ion-android-arrow-forward" unicode="&#xf30f;" horiz-adv-x="256"
-d="M0 448h112l144 -256l-144 -256h-112l144 256z" />
- <glyph glyph-name="ion-android-arrow-up-left" unicode="&#xf2cd;" 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="&#xf2ce;" horiz-adv-x="480"
-d="M176 432h304v-304h-80v167l-343 -343l-57 57l343 343h-167v80z" />
- <glyph glyph-name="ion-android-battery" unicode="&#xf2cf;" 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="&#xf2d0;" 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="&#xf2d1;" 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="&#xf2d2;" 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="&#xf2d3;" 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="&#xf2d4;" 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="&#xf2d5;" horiz-adv-x="512"
-d="M176 -16l-176 176l80 83l112 -107l248 248l72 -72z" />
- <glyph glyph-name="ion-android-clock" unicode="&#xf2d6;"
-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="&#xf2d7;" 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="&#xf2d8;" 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="&#xf2d9;" 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="&#xf2da;"
-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="&#xf2db;" 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="&#xf2dc;" 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="&#xf2dd;"
-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="&#xf310;" horiz-adv-x="256"
-d="M0 320v64h256v-64h-256zM0 0v64h256v-64h-256zM0 160v64h256v-64h-256z" />
- <glyph glyph-name="ion-android-dropdown" unicode="&#xf2de;" horiz-adv-x="288"
-d="M0 32l288 288v-288h-288z" />
- <glyph glyph-name="ion-android-earth" unicode="&#xf2df;"
-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="&#xf2e0;" horiz-adv-x="512"
-d="M432 16h-432v352h144l48 -64h240v-32h-368l-40 -128l16 -16l40 128h432z" />
- <glyph glyph-name="ion-android-forums" unicode="&#xf2e1;" 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="&#xf2e2;" 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="&#xf2e3;" 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="&#xf2e4;" 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="&#xf2e5;" 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="&#xf2e6;"
-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="&#xf2e7;" 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="&#xf2e8;" 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="&#xf2e9;" 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="&#xf2ea;" 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="&#xf2eb;" horiz-adv-x="512"
-d="M256 142l256 124v-266h-512v266zM512 310l-256 -123l-256 123v74h512v-74z" />
+ <glyph glyph-name="ion-android-add-circle" unicode="&#xf359;" 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="&#xf2c7;" horiz-adv-x="320"
+d="M320 171h-139v-139h-42v139h-139v42h139v139h42v-139h139v-42z" />
+ <glyph glyph-name="ion-android-alarm-clock" unicode="&#xf35a;" 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="&#xf35b;" 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="&#xf35c;" 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="&#xf2c9;" 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="&#xf2ca;" 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="&#xf35d;" 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="&#xf35e;" 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="&#xf35f;" horiz-adv-x="256"
+d="M0 256h256l-128 -128z" />
+ <glyph glyph-name="ion-android-arrow-dropleft-circle" unicode="&#xf360;" 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="&#xf361;" horiz-adv-x="128"
+d="M128 320v-256l-128 128z" />
+ <glyph glyph-name="ion-android-arrow-dropright-circle" unicode="&#xf362;" 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="&#xf363;" horiz-adv-x="128"
+d="M0 320l128 -128l-128 -128v256z" />
+ <glyph glyph-name="ion-android-arrow-dropup-circle" unicode="&#xf364;" 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="&#xf365;" horiz-adv-x="256"
+d="M0 128l128 128l128 -128h-256z" />
+ <glyph glyph-name="ion-android-arrow-forward" unicode="&#xf30f;" 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="&#xf366;" 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="&#xf367;" 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="&#xf368;" 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="&#xf369;"
+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="&#xf36a;"
+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="&#xf36b;" 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="&#xf36c;"
+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="&#xf36d;" 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="&#xf2d1;" 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="&#xf2d2;" 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="&#xf2d3;"
+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="&#xf36e;" 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="&#xf36f;" 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="&#xf370;" 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="&#xf2d4;" 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="&#xf371;" 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="&#xf372;" 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="&#xf373;" 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="&#xf374;" 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="&#xf375;" 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="&#xf376;" 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="&#xf2d7;" 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="&#xf377;" 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="&#xf378;" 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="&#xf379;" 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="&#xf37a;" 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="&#xf37b;" 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="&#xf37c;"
+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="&#xf2d8;" 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="&#xf2d9;"
+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="&#xf37d;" 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="&#xf37e;" 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="&#xf37f;" 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="&#xf380;"
+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="&#xf381;" 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="&#xf382;" 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="&#xf383;" horiz-adv-x="384"
+d="M122 108l230 230l32 -31l-262 -261l-122 122l32 31z" />
+ <glyph glyph-name="ion-android-download" unicode="&#xf2dd;" 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="&#xf384;"
+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="&#xf385;" 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="&#xf386;" 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="&#xf387;" 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="&#xf388;" 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="&#xf389;" 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="&#xf38a;"
+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="&#xf2e0;"
+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="&#xf38b;"
+d="M176 48v48h96v-48h-96zM0 336h448v-48h-448v48zM80 167v50h288v-50h-288z" />
+ <glyph glyph-name="ion-android-globe" unicode="&#xf38c;" 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="&#xf2e3;" 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="&#xf38d;" 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="&#xf38e;" 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="&#xf38f;" horiz-adv-x="416"
+d="M160 0h-98v192h-62l208 192l208 -192h-62v-192h-98v128h-96v-128z" />
+ <glyph glyph-name="ion-android-image" unicode="&#xf2e4;" 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="&#xf390;" 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="&#xf391;" 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="&#xf2e9;"
+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="&#xf392;" 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="&#xf2eb;"
+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="&#xf393;" 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="&#xf394;" horiz-adv-x="384"
+d="M0 64v43h384v-43h-384zM0 171v42h384v-42h-384zM0 320h384v-43h-384v43z" />
+ <glyph glyph-name="ion-android-microphone-off" unicode="&#xf395;" 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="&#xf2ec;" 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="&#xf2ed;" 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="&#xf2ee;" horiz-adv-x="128"
-d="M0 128v128h128v-128h-128zM0 320v128h128v-128h-128zM0 -64v128h128v-128h-128z" />
- <glyph glyph-name="ion-android-note" unicode="&#xf2ef;" 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="&#xf2f0;" 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="&#xf2f1;" 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="&#xf2f2;" 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="&#xf2f3;" 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="&#xf2f4;" horiz-adv-x="512"
-d="M0 160v64h512v-64h-512z" />
- <glyph glyph-name="ion-android-search" unicode="&#xf2f5;" 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="&#xf2f6;" horiz-adv-x="512"
-d="M0 448l512 -256l-512 -256l43 235l426 21l-426 21z" />
- <glyph glyph-name="ion-android-settings" unicode="&#xf2f7;" 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="&#xf2f8;" 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="&#xf2f9;" 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="&#xf2fa;" 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="&#xf2fb;" horiz-adv-x="512"
-d="M0 288v64h512v-64h-512zM0 160v64h352v-64h-352zM0 32v64h192v-64h-192z" />
- <glyph glyph-name="ion-android-stair-drawer" unicode="&#xf311;" horiz-adv-x="512"
-d="M0 0v96h256v-96h-256zM128 144v96h256v-96h-256zM256 288v96h256v-96h-256z" />
- <glyph glyph-name="ion-android-star" unicode="&#xf2fc;" 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="&#xf2fd;"
-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="&#xf2fe;"
-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="&#xf2ff;" 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="&#xf300;" horiz-adv-x="512"
-d="M256 303l-224 -84v-123h448v123zM256 338v0l256 -96v-178h-512v178z" />
- <glyph glyph-name="ion-android-system-windows" unicode="&#xf301;" horiz-adv-x="512"
-d="M0 256h416v-192h-416v192zM384 96v128h-352v-128h352zM128 320h384v-192h-32v160h-352v32z" />
- <glyph glyph-name="ion-android-timer" unicode="&#xf302;" 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="&#xf303;" 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="&#xf312;"
-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="&#xf304;" 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="&#xf305;" 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="&#xf396;" 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="&#xf397;" 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="&#xf398;" horiz-adv-x="320"
+d="M160 384l160 -369l-15 -15l-145 64l-145 -64l-15 15z" />
+ <glyph glyph-name="ion-android-notifications-none" unicode="&#xf399;" 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="&#xf39a;" 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="&#xf39b;" 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="&#xf39c;" 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="&#xf39d;"
+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="&#xf39e;"
+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="&#xf39f;" 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="&#xf3a0;" 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="&#xf3a1;"
+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="&#xf3a2;" 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="&#xf3a3;" 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="&#xf3a4;" 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="&#xf2f0;" 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="&#xf3a5;" 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="&#xf3a6;" 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="&#xf3a7;" 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="&#xf3a8;" 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="&#xf3a9;" 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="&#xf2f4;" horiz-adv-x="320"
+d="M0 171v42h320v-42h-320z" />
+ <glyph glyph-name="ion-android-restaurant" unicode="&#xf3aa;" 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="&#xf3ab;" 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="&#xf2f5;" 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="&#xf2f6;" horiz-adv-x="416"
+d="M0 0v149l298 43l-298 43v149l416 -192z" />
+ <glyph glyph-name="ion-android-settings" unicode="&#xf2f7;" 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="&#xf3ac;" 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="&#xf2f8;" 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="&#xf3ad;" 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="&#xf3ae;" 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="&#xf2fc;" 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="&#xf2fd;" 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="&#xf3af;" 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="&#xf3b0;"
+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="&#xf3b1;" 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="&#xf3b2;" 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="&#xf3b3;" 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="&#xf3b4;" 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="&#xf3b5;" 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="&#xf3b6;" 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="&#xf3b7;" 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="&#xf3b8;" horiz-adv-x="192"
+d="M0 256h85l107 112v-352l-107 112h-85v128z" />
+ <glyph glyph-name="ion-android-volume-off" unicode="&#xf3b9;" 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="&#xf3ba;" 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="&#xf3bb;" 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="&#xf3bc;"
+d="M0 -16l224 416l224 -416h-448zM248 48v48h-48v-48h48zM248 128v96h-48v-96h48z" />
+ <glyph glyph-name="ion-android-watch" unicode="&#xf3bd;" 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="&#xf305;" 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="&#xf313;"
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="&#xf3be;" 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="&#xf3bf;" 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="&#xf110;"
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="&#xf115;"
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="&#xf269;" 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="&#xf26a;"
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="&#xf26b;" 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="&#xf3c0;"
+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="&#xf26c;"
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="&#xf11a;" 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="&#xf126;"
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="&#xf127;" 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="&#xf26e;"
-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="&#xf128;"
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="&#xf275;"
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="&#xf3c1;"
+d="M320 -32v48h64v-48h-64zM384 96h64v-64h-384v256h-64v64h64v64h64v-320h192v192h-176v64h240v-256z" />
<glyph glyph-name="ion-cube" unicode="&#xf318;"
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="&#xf130;" horiz-adv-x="512"
d="M0 272v32h512v-32h-512zM0 176v32h512v-32h-512zM0 80v32h512v-32h-512z" />
<glyph glyph-name="ion-earth" unicode="&#xf276;"
-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="&#xf3c2;"
+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="&#xf2bf;"
-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="&#xf277;" 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="&#xf131;" 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="&#xf3c3;" 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="&#xf132;" 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="&#xf3c4;" 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="&#xf3c5;" 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="&#xf306;"
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="&#xf137;" horiz-adv-x="320"
d="M0 160l224 256l-51 -192h147l-224 -256l51 192h-147z" />
- <glyph glyph-name="ion-flask" unicode="&#xf138;" 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="&#xf139;" 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="&#xf2c0;" 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="&#xf13a;" 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="&#xf31b;"
-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="&#xf13b;"
-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="&#xf13c;"
-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="&#xf13d;" 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="&#xf27b;" 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="&#xf31c;"
+ <glyph glyph-name="ion-happy-outline" unicode="&#xf3c6;"
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="&#xf31c;"
+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="&#xf140;" 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="&#xf27d;" 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="&#xf145;"
-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="&#xf146;"
-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="&#xf147;"
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="&#xf14a;" 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="&#xf14b;" 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="&#xf14c;" horiz-adv-x="404"
+ <glyph glyph-name="ion-ios-alarm-outline" unicode="&#xf3c7;" 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="&#xf14d;" horiz-adv-x="404"
+ <glyph glyph-name="ion-ios-alarm" unicode="&#xf3c8;" 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="&#xf14e;"
+ <glyph glyph-name="ion-ios-albums-outline" unicode="&#xf3c9;"
d="M432 304h-416v-288h416v288zM448 320v0v-320h-448v320h448zM40 336v16h368v-16h-368zM72 368v16h304v-16h-304z" />
- <glyph glyph-name="ion-ios7-albums" unicode="&#xf14f;"
+ <glyph glyph-name="ion-ios-albums" unicode="&#xf3ca;"
d="M448 320v0v-320h-448v320h448zM40 336v16h368v-16h-368zM72 368v16h304v-16h-304z" />
- <glyph glyph-name="ion-ios7-americanfootball-outline" unicode="&#xf31e;"
-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="&#xf31f;"
-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="&#xf320;"
+ <glyph glyph-name="ion-ios-americanfootball-outline" unicode="&#xf3cb;" 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="&#xf3cc;" 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="&#xf3cd;"
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="&#xf321;"
+ <glyph glyph-name="ion-ios-analytics" unicode="&#xf3ce;"
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="&#xf150;" horiz-adv-x="192"
+ <glyph glyph-name="ion-ios-arrow-back" unicode="&#xf3cf;" horiz-adv-x="192"
d="M192 320l-127 -128l127 -128l-32 -32l-160 160v0v0l160 160z" />
- <glyph glyph-name="ion-ios7-arrow-down" unicode="&#xf151;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-arrow-down" unicode="&#xf3d0;" horiz-adv-x="320"
d="M301 288l19 -21l-160 -171l-160 171l19 21l141 -150z" />
- <glyph glyph-name="ion-ios7-arrow-forward" unicode="&#xf152;" horiz-adv-x="192"
+ <glyph glyph-name="ion-ios-arrow-forward" unicode="&#xf3d1;" horiz-adv-x="192"
d="M0 320l32 32l160 -160v0v0l-160 -160l-32 32l127 128z" />
- <glyph glyph-name="ion-ios7-arrow-left" unicode="&#xf153;" horiz-adv-x="192"
+ <glyph glyph-name="ion-ios-arrow-left" unicode="&#xf3d2;" horiz-adv-x="192"
d="M192 333l-150 -141l150 -141l-21 -19l-171 160l171 160z" />
- <glyph glyph-name="ion-ios7-arrow-right" unicode="&#xf154;" horiz-adv-x="192"
+ <glyph glyph-name="ion-ios-arrow-right" unicode="&#xf3d3;" horiz-adv-x="192"
d="M0 333l21 19l171 -160l-171 -160l-21 19l150 141z" />
- <glyph glyph-name="ion-ios7-arrow-thin-down" unicode="&#xf27e;" horiz-adv-x="192"
+ <glyph glyph-name="ion-ios-arrow-thin-down" unicode="&#xf3d4;" 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="&#xf27f;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-arrow-thin-left" unicode="&#xf3d5;" 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="&#xf280;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-arrow-thin-right" unicode="&#xf3d6;" 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="&#xf281;" horiz-adv-x="192"
+ <glyph glyph-name="ion-ios-arrow-thin-up" unicode="&#xf3d7;" 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="&#xf155;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-arrow-up" unicode="&#xf3d8;" horiz-adv-x="320"
d="M301 96l-141 150l-141 -150l-19 21l160 171l160 -171z" />
- <glyph glyph-name="ion-ios7-at-outline" unicode="&#xf156;" horiz-adv-x="255"
+ <glyph glyph-name="ion-ios-at-outline" unicode="&#xf3d9;" 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="&#xf157;" horiz-adv-x="256"
+ <glyph glyph-name="ion-ios-at" unicode="&#xf3da;" 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="&#xf322;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-barcode-outline" unicode="&#xf3db;" 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="&#xf323;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-barcode" unicode="&#xf3dc;" 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="&#xf324;"
-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="&#xf325;"
-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="&#xf326;"
-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="&#xf327;"
-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="&#xf158;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-baseball-outline" unicode="&#xf3dd;" 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="&#xf3de;" 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="&#xf3df;" 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="&#xf3e0;" 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="&#xf3e1;" 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="&#xf159;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-bell" unicode="&#xf3e2;" 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="&#xf15a;" horiz-adv-x="226"
+ <glyph glyph-name="ion-ios-body-outline" unicode="&#xf3e3;" 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="&#xf3e4;" 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="&#xf3e5;" 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="&#xf15b;" horiz-adv-x="226"
+ <glyph glyph-name="ion-ios-bolt" unicode="&#xf3e6;" horiz-adv-x="226"
d="M160 384v0l-30 -160h96l-160 -224l30 160h-96z" />
- <glyph glyph-name="ion-ios7-bookmarks-outline" unicode="&#xf15c;" horiz-adv-x="418"
+ <glyph glyph-name="ion-ios-book-outline" unicode="&#xf3e7;" 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="&#xf3e8;" 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="&#xf3e9;" 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="&#xf15d;" horiz-adv-x="418"
+ <glyph glyph-name="ion-ios-bookmarks" unicode="&#xf3ea;" 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="&#xf15e;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-box-outline" unicode="&#xf3eb;" 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="&#xf15f;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-box" unicode="&#xf3ec;" 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="&#xf282;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-briefcase-outline" unicode="&#xf3ed;" 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="&#xf283;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-briefcase" unicode="&#xf3ee;" 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="&#xf160;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-browsers-outline" unicode="&#xf3ef;" 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="&#xf161;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-browsers" unicode="&#xf3f0;" horiz-adv-x="384"
d="M0 304h304v-304h-304v304zM80 384h304v-304h-64v240h-240v64z" />
- <glyph glyph-name="ion-ios7-calculator-outline" unicode="&#xf284;" horiz-adv-x="288"
+ <glyph glyph-name="ion-ios-calculator-outline" unicode="&#xf3f1;" 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="&#xf285;" horiz-adv-x="288"
+ <glyph glyph-name="ion-ios-calculator" unicode="&#xf3f2;" 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="&#xf162;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-calendar-outline" unicode="&#xf3f3;" 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="&#xf163;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-calendar" unicode="&#xf3f4;" 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="&#xf164;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-camera-outline" unicode="&#xf3f5;" 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="&#xf165;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-camera" unicode="&#xf3f6;" 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="&#xf166;" 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="&#xf167;" 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="&#xf168;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-cart-outline" unicode="&#xf3f7;" 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="&#xf3f8;" 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="&#xf3f9;" 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="&#xf169;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-chatboxes" unicode="&#xf3fa;" 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="&#xf16a;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-chatbubble-outline" unicode="&#xf3fb;" 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="&#xf16b;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-chatbubble" unicode="&#xf3fc;" 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="&#xf16c;" horiz-adv-x="207"
+ <glyph glyph-name="ion-ios-checkmark-empty" unicode="&#xf3fd;" 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="&#xf16d;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-checkmark-outline" unicode="&#xf3fe;" 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="&#xf16e;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-checkmark" unicode="&#xf3ff;" 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="&#xf16f;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-circle-filled" unicode="&#xf400;" 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="&#xf170;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-circle-outline" unicode="&#xf401;" 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="&#xf171;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-clock-outline" unicode="&#xf402;" 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="&#xf172;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-clock" unicode="&#xf403;" 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="&#xf2bd;" horiz-adv-x="192"
+ <glyph glyph-name="ion-ios-close-empty" unicode="&#xf404;" 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="&#xf2bb;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-close-outline" unicode="&#xf405;" 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="&#xf2bc;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-close" unicode="&#xf406;" 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="&#xf173;"
+ <glyph glyph-name="ion-ios-cloud-download-outline" unicode="&#xf407;"
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="&#xf174;"
+ <glyph glyph-name="ion-ios-cloud-download" unicode="&#xf408;"
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="&#xf175;"
+ <glyph glyph-name="ion-ios-cloud-outline" unicode="&#xf409;"
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="&#xf176;"
+ <glyph glyph-name="ion-ios-cloud-upload-outline" unicode="&#xf40a;"
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="&#xf177;"
+ <glyph glyph-name="ion-ios-cloud-upload" unicode="&#xf40b;"
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="&#xf178;"
+ <glyph glyph-name="ion-ios-cloud" unicode="&#xf40c;"
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="&#xf307;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-cloudy-night-outline" unicode="&#xf40d;" 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="&#xf308;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-cloudy-night" unicode="&#xf40e;" 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="&#xf179;" horiz-adv-x="274"
+ <glyph glyph-name="ion-ios-cloudy-outline" unicode="&#xf40f;" 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="&#xf17a;" horiz-adv-x="274"
+ <glyph glyph-name="ion-ios-cloudy" unicode="&#xf410;" 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="&#xf17b;" 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="&#xf17c;" 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="&#xf17d;" 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="&#xf17e;" 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="&#xf17f;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-cog-outline" unicode="&#xf411;" 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="&#xf412;" 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="&#xf413;" 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="&#xf414;" 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="&#xf415;" 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="&#xf416;" 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="&#xf417;" 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="&#xf418;" 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="&#xf419;" 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="&#xf180;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-contact" unicode="&#xf41a;" 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="&#xf181;" horiz-adv-x="288"
+ <glyph glyph-name="ion-ios-copy-outline" unicode="&#xf41b;" 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="&#xf182;" horiz-adv-x="288"
+ <glyph glyph-name="ion-ios-copy" unicode="&#xf41c;" 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="&#xf183;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-crop-strong" unicode="&#xf41d;" 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="&#xf41e;" 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="&#xf41f;" 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="&#xf184;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-download" unicode="&#xf420;" 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="&#xf185;" horiz-adv-x="352"
+ <glyph glyph-name="ion-ios-drag" unicode="&#xf421;" horiz-adv-x="352"
d="M0 128v16h352v-16h-352zM0 184v16h352v-16h-352zM0 240v16h352v-16h-352z" />
- <glyph glyph-name="ion-ios7-email-outline" unicode="&#xf186;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-email-outline" unicode="&#xf422;" 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="&#xf187;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-email" unicode="&#xf423;" 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="&#xf30d;" 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="&#xf188;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-eye-outline" unicode="&#xf424;" 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="&#xf189;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-eye" unicode="&#xf425;" 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="&#xf18a;"
+ <glyph glyph-name="ion-ios-fastforward-outline" unicode="&#xf426;"
d="M16 293v-202l184 101zM240 292v0v-78v-27v-95l176 100zM224 320v0l224 -128l-224 -128v123l-224 -123v256l224 -123v123z" />
- <glyph glyph-name="ion-ios7-fastforward" unicode="&#xf18b;"
+ <glyph glyph-name="ion-ios-fastforward" unicode="&#xf427;"
d="M224 320v0l224 -128l-224 -128v123l-224 -123v256l224 -123v123z" />
- <glyph glyph-name="ion-ios7-filing-outline" unicode="&#xf18c;" horiz-adv-x="352"
+ <glyph glyph-name="ion-ios-filing-outline" unicode="&#xf428;" 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="&#xf18d;" horiz-adv-x="352"
+ <glyph glyph-name="ion-ios-filing" unicode="&#xf429;" 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="&#xf18e;" 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="&#xf18f;" 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="&#xf190;" horiz-adv-x="256"
+ <glyph glyph-name="ion-ios-film-outline" unicode="&#xf42a;" 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="&#xf42b;" 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="&#xf42c;" 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="&#xf191;" horiz-adv-x="256"
+ <glyph glyph-name="ion-ios-flag" unicode="&#xf42d;" 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="&#xf192;" 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="&#xf193;" 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="&#xf328;"
-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="&#xf329;"
-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="&#xf194;" 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="&#xf195;" 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="&#xf196;"
+ <glyph glyph-name="ion-ios-flame-outline" unicode="&#xf42e;" 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="&#xf42f;" 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="&#xf430;" 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="&#xf431;" 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="&#xf432;"
+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="&#xf433;"
+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="&#xf434;"
+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="&#xf435;"
+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="&#xf436;" 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="&#xf437;" 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="&#xf438;"
+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="&#xf439;"
+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="&#xf43a;"
+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="&#xf43b;"
+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="&#xf43c;" 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="&#xf43d;" 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="&#xf43e;"
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="&#xf197;"
+ <glyph glyph-name="ion-ios-glasses" unicode="&#xf43f;"
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="&#xf198;" 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="&#xf199;" 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="&#xf19a;" horiz-adv-x="128"
+ <glyph glyph-name="ion-ios-grid-view-outline" unicode="&#xf440;" 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="&#xf441;" 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="&#xf442;"
+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="&#xf443;"
+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="&#xf444;" 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="&#xf19b;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-help-outline" unicode="&#xf445;" 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="&#xf19c;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-help" unicode="&#xf446;" 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="&#xf32a;" 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="&#xf32b;" 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="&#xf19d;" 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="&#xf19e;" 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="&#xf19f;" horiz-adv-x="64"
+ <glyph glyph-name="ion-ios-home-outline" unicode="&#xf447;" 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="&#xf448;" 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="&#xf449;"
+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="&#xf44a;" 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="&#xf44b;" 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="&#xf1a0;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-information-outline" unicode="&#xf44c;" 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="&#xf1a1;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-information" unicode="&#xf44d;" 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="&#xf1a2;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-ionic-outline" unicode="&#xf44e;" 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="&#xf1a3;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-keypad-outline" unicode="&#xf44f;" 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="&#xf1a4;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-keypad" unicode="&#xf450;" 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="&#xf286;" horiz-adv-x="288"
+ <glyph glyph-name="ion-ios-lightbulb-outline" unicode="&#xf451;" 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="&#xf287;" horiz-adv-x="288"
+ <glyph glyph-name="ion-ios-lightbulb" unicode="&#xf452;" 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="&#xf1a5;" 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="&#xf1a6;" 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="&#xf1a7;" 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="&#xf1a8;" 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="&#xf32c;" horiz-adv-x="512"
+ <glyph glyph-name="ion-ios-list-outline" unicode="&#xf453;" 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="&#xf454;" 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="&#xf455;" 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="&#xf456;" 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="&#xf457;" 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="&#xf458;" 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="&#xf459;" 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="&#xf32d;" horiz-adv-x="489"
+ <glyph glyph-name="ion-ios-loop" unicode="&#xf45a;" 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="&#xf288;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-medical-outline" unicode="&#xf45b;" 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="&#xf45c;" 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="&#xf45d;" 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="&#xf289;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-medkit" unicode="&#xf45e;" 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="&#xf1a9;" horiz-adv-x="280"
+ <glyph glyph-name="ion-ios-mic-off" unicode="&#xf45f;" 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="&#xf1aa;" horiz-adv-x="256"
+ <glyph glyph-name="ion-ios-mic-outline" unicode="&#xf460;" 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="&#xf1ab;" horiz-adv-x="256"
+ <glyph glyph-name="ion-ios-mic" unicode="&#xf461;" 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="&#xf1ac;" horiz-adv-x="256"
+ <glyph glyph-name="ion-ios-minus-empty" unicode="&#xf462;" horiz-adv-x="256"
d="M256 183h-256v17h256v-17z" />
- <glyph glyph-name="ion-ios7-minus-outline" unicode="&#xf1ad;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-minus-outline" unicode="&#xf463;" 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="&#xf1ae;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-minus" unicode="&#xf464;" 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="&#xf1af;" horiz-adv-x="480"
+ <glyph glyph-name="ion-ios-monitor-outline" unicode="&#xf465;" horiz-adv-x="480"
d="M480 64h-176v-16h64v-16h-257v16h64v16h-175v288h480v-288zM16 336v-256h448v256h-448z" />
- <glyph glyph-name="ion-ios7-monitor" unicode="&#xf1b0;" horiz-adv-x="480"
+ <glyph glyph-name="ion-ios-monitor" unicode="&#xf466;" 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="&#xf1b1;" horiz-adv-x="216"
+ <glyph glyph-name="ion-ios-moon-outline" unicode="&#xf467;" 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="&#xf1b2;" horiz-adv-x="216"
+ <glyph glyph-name="ion-ios-moon" unicode="&#xf468;" 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="&#xf1b3;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-more-outline" unicode="&#xf469;" 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="&#xf1b4;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-more" unicode="&#xf46a;" 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="&#xf1b5;" horiz-adv-x="192"
+ <glyph glyph-name="ion-ios-musical-note" unicode="&#xf46b;" 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="&#xf1b6;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-musical-notes" unicode="&#xf46c;" 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="&#xf1b7;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-navigate-outline" unicode="&#xf46d;" 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="&#xf1b8;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-navigate" unicode="&#xf46e;" 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="&#xf32e;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-nutrition-outline" unicode="&#xf46f;" 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="&#xf470;" 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="&#xf471;" 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="&#xf32f;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-paper" unicode="&#xf472;" 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="&#xf1b9;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-paperplane-outline" unicode="&#xf473;" 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="&#xf1ba;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-paperplane" unicode="&#xf474;" horiz-adv-x="320"
d="M0 198l320 154l-214 -200zM320 352l-146 -320l-52 104z" />
- <glyph glyph-name="ion-ios7-partlysunny-outline" unicode="&#xf1bb;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-partlysunny-outline" unicode="&#xf475;" 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="&#xf1bc;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-partlysunny" unicode="&#xf476;" 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="&#xf1bd;" horiz-adv-x="256"
+ <glyph glyph-name="ion-ios-pause-outline" unicode="&#xf477;" 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="&#xf1be;" horiz-adv-x="256"
+ <glyph glyph-name="ion-ios-pause" unicode="&#xf478;" horiz-adv-x="256"
d="M0 32v320h79v-320h-79zM177 32v320h79v-320h-79z" />
- <glyph glyph-name="ion-ios7-paw-outline" unicode="&#xf330;" 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="&#xf331;" 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="&#xf1bf;"
+ <glyph glyph-name="ion-ios-paw-outline" unicode="&#xf479;" 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="&#xf47a;" 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="&#xf47b;"
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="&#xf1c0;"
+ <glyph glyph-name="ion-ios-people" unicode="&#xf47c;"
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="&#xf1c1;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-person-outline" unicode="&#xf47d;" 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="&#xf1c2;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-person" unicode="&#xf47e;" 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="&#xf1c3;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-personadd-outline" unicode="&#xf47f;" 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="&#xf1c4;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-personadd" unicode="&#xf480;" 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="&#xf1c5;"
+ <glyph glyph-name="ion-ios-photos-outline" unicode="&#xf481;"
d="M64 320h384v-320h-384v320zM432 16v288h-352v-288h352zM0 384h384v-48h-16v32h-352v-288h32v-16h-48v320z" />
- <glyph glyph-name="ion-ios7-photos" unicode="&#xf1c6;"
+ <glyph glyph-name="ion-ios-photos" unicode="&#xf482;"
d="M64 320h384v-320h-384v320zM384 384v-48h-336v-272h-48v320h384z" />
- <glyph glyph-name="ion-ios7-pie-outline" unicode="&#xf28a;"
-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="&#xf28b;"
-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="&#xf1c7;" horiz-adv-x="256"
+ <glyph glyph-name="ion-ios-pie-outline" unicode="&#xf483;"
+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="&#xf484;"
+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="&#xf485;" 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="&#xf486;" 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="&#xf487;" horiz-adv-x="256"
d="M16 323v-262l210 131zM0 352v0l256 -160l-256 -160v320z" />
- <glyph glyph-name="ion-ios7-play" unicode="&#xf1c8;" horiz-adv-x="256"
+ <glyph glyph-name="ion-ios-play" unicode="&#xf488;" horiz-adv-x="256"
d="M0 352v0l256 -160l-256 -160v320z" />
- <glyph glyph-name="ion-ios7-plus-empty" unicode="&#xf1c9;" horiz-adv-x="256"
+ <glyph glyph-name="ion-ios-plus-empty" unicode="&#xf489;" horiz-adv-x="256"
d="M256 183h-120v-119h-17v119h-119v17h119v120h17v-120h120v-17z" />
- <glyph glyph-name="ion-ios7-plus-outline" unicode="&#xf1ca;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-plus-outline" unicode="&#xf48a;" 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="&#xf1cb;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-plus" unicode="&#xf48b;" 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="&#xf28c;" 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="&#xf28d;" 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="&#xf332;"
+ <glyph glyph-name="ion-ios-pricetag-outline" unicode="&#xf48c;" 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="&#xf48d;" 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="&#xf48e;"
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="&#xf333;"
+ <glyph glyph-name="ion-ios-pricetags" unicode="&#xf48f;"
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="&#xf1cc;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-printer-outline" unicode="&#xf490;" 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="&#xf1cd;" 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="&#xf334;" horiz-adv-x="480"
+ <glyph glyph-name="ion-ios-printer" unicode="&#xf491;" 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="&#xf492;" 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="&#xf335;"
+ <glyph glyph-name="ion-ios-pulse" unicode="&#xf493;"
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="&#xf1ce;" horiz-adv-x="288"
+ <glyph glyph-name="ion-ios-rainy-outline" unicode="&#xf494;" 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="&#xf1cf;" horiz-adv-x="288"
+ <glyph glyph-name="ion-ios-rainy" unicode="&#xf495;" 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="&#xf1d0;" horiz-adv-x="480"
+ <glyph glyph-name="ion-ios-recording-outline" unicode="&#xf496;" 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="&#xf1d1;" horiz-adv-x="480"
+ <glyph glyph-name="ion-ios-recording" unicode="&#xf497;" 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="&#xf1d2;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-redo-outline" unicode="&#xf498;" 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="&#xf1d3;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-redo" unicode="&#xf499;" 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="&#xf1d4;" horiz-adv-x="256"
+ <glyph glyph-name="ion-ios-refresh-empty" unicode="&#xf49a;" 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="&#xf1d5;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-refresh-outline" unicode="&#xf49b;" 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="&#xf1d6;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-refresh" unicode="&#xf49c;" 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="&#xf28e;" 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="&#xf336;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-reload" unicode="&#xf49d;"
+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="&#xf49e;" 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="&#xf337;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-reverse-camera" unicode="&#xf49f;" 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="&#xf1d7;"
+ <glyph glyph-name="ion-ios-rewind-outline" unicode="&#xf4a0;"
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="&#xf1d8;"
+ <glyph glyph-name="ion-ios-rewind" unicode="&#xf4a1;"
d="M224 320v0v-123l224 123v-256l-224 123v-123l-224 128z" />
- <glyph glyph-name="ion-ios7-search-strong" unicode="&#xf1d9;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-rose-outline" unicode="&#xf4a2;" 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="&#xf4a3;" 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="&#xf4a4;" 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="&#xf1da;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-search" unicode="&#xf4a5;" 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="&#xf338;"
+ <glyph glyph-name="ion-ios-settings-strong" unicode="&#xf4a6;"
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="&#xf339;"
+ <glyph glyph-name="ion-ios-settings" unicode="&#xf4a7;"
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="&#xf30e;" 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="&#xf1db;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-shuffle-strong" unicode="&#xf4a8;" 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="&#xf4a9;" 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="&#xf4aa;" 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="&#xf1dc;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-skipbackward" unicode="&#xf4ab;" horiz-adv-x="320"
d="M0 352h79v-142l241 142v-320l-241 142v-142h-79v320z" />
- <glyph glyph-name="ion-ios7-skipforward-outline" unicode="&#xf1dd;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-skipforward-outline" unicode="&#xf4ac;" 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="&#xf1de;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-skipforward" unicode="&#xf4ad;" horiz-adv-x="320"
d="M241 352h79v-320h-79v142l-241 -142v320l241 -142v142z" />
- <glyph glyph-name="ion-ios7-snowy" unicode="&#xf309;" horiz-adv-x="256"
+ <glyph glyph-name="ion-ios-snowy" unicode="&#xf4ae;" 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="&#xf28f;"
-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="&#xf290;"
-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="&#xf33a;"
+ <glyph glyph-name="ion-ios-speedometer-outline" unicode="&#xf4af;"
+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="&#xf4b0;"
+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="&#xf4b1;"
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="&#xf1df;"
+ <glyph glyph-name="ion-ios-star-outline" unicode="&#xf4b2;"
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="&#xf1e0;"
+ <glyph glyph-name="ion-ios-star" unicode="&#xf4b3;"
d="M448 241l-140 -98l54 -159l-138 99l-138 -99l54 159l-140 98h171l53 159l53 -159h171z" />
- <glyph glyph-name="ion-ios7-stopwatch-outline" unicode="&#xf1e1;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-stopwatch-outline" unicode="&#xf4b4;" 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="&#xf1e2;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-stopwatch" unicode="&#xf4b5;" 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="&#xf1e3;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-sunny-outline" unicode="&#xf4b6;" 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="&#xf1e4;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-sunny" unicode="&#xf4b7;" 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="&#xf1e5;" horiz-adv-x="352"
+ <glyph glyph-name="ion-ios-telephone-outline" unicode="&#xf4b8;" 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="&#xf1e6;" horiz-adv-x="352"
+ <glyph glyph-name="ion-ios-telephone" unicode="&#xf4b9;" 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="&#xf33b;"
-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="&#xf33c;"
-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="&#xf1e7;" horiz-adv-x="274"
+ <glyph glyph-name="ion-ios-tennisball-outline" unicode="&#xf4ba;" 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="&#xf4bb;" 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="&#xf4bc;" 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="&#xf1e8;" horiz-adv-x="274"
+ <glyph glyph-name="ion-ios-thunderstorm" unicode="&#xf4bd;" 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="&#xf291;"
+ <glyph glyph-name="ion-ios-time-outline" unicode="&#xf4be;"
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="&#xf292;"
+ <glyph glyph-name="ion-ios-time" unicode="&#xf4bf;"
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="&#xf1e9;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-timer-outline" unicode="&#xf4c0;" 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="&#xf1ea;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-timer" unicode="&#xf4c1;" 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="&#xf33d;"
+ <glyph glyph-name="ion-ios-toggle-outline" unicode="&#xf4c2;"
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="&#xf33e;"
+ <glyph glyph-name="ion-ios-toggle" unicode="&#xf4c3;"
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="&#xf1eb;" horiz-adv-x="288"
+ <glyph glyph-name="ion-ios-trash-outline" unicode="&#xf4c4;" 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="&#xf1ec;" horiz-adv-x="288"
+ <glyph glyph-name="ion-ios-trash" unicode="&#xf4c5;" 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="&#xf1ed;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-undo-outline" unicode="&#xf4c6;" 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="&#xf1ee;" horiz-adv-x="384"
+ <glyph glyph-name="ion-ios-undo" unicode="&#xf4c7;" 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="&#xf1ef;" 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="&#xf1f0;" 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="&#xf1f1;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-unlocked-outline" unicode="&#xf4c8;" 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="&#xf4c9;" 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="&#xf4ca;" 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="&#xf1f2;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-upload" unicode="&#xf4cb;" 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="&#xf1f3;" horiz-adv-x="418"
+ <glyph glyph-name="ion-ios-videocam-outline" unicode="&#xf4cc;" 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="&#xf1f4;" horiz-adv-x="418"
+ <glyph glyph-name="ion-ios-videocam" unicode="&#xf4cd;" 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="&#xf1f5;" horiz-adv-x="320"
+ <glyph glyph-name="ion-ios-volume-high" unicode="&#xf4ce;" 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="&#xf1f6;" horiz-adv-x="128"
+ <glyph glyph-name="ion-ios-volume-low" unicode="&#xf4cf;" horiz-adv-x="128"
d="M58 232l70 56v-192l-70 56h-58v80h58z" />
- <glyph glyph-name="ion-ios7-wineglass-outline" unicode="&#xf293;" 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="&#xf294;" 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="&#xf1f7;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-wineglass-outline" unicode="&#xf4d0;" 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="&#xf4d1;" 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="&#xf4d2;" 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="&#xf1f8;" horiz-adv-x="416"
+ <glyph glyph-name="ion-ios-world" unicode="&#xf4d3;" 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="&#xf1fe;" 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="&#xf29a;" 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="&#xf29b;" 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="&#xf29c;" 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="&#xf29d;" 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="&#xf29a;" 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="&#xf29b;"
+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="&#xf29c;"
+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="&#xf29d;" 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="&#xf1ff;" 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="&#xf4d4;" 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="&#xf200;" 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="&#xf29e;" 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="&#xf29f;" 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="&#xf201;" 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="&#xf29e;"
+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="&#xf29f;"
+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="&#xf201;" 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="&#xf2a0;" 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="&#xf203;"
-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="&#xf2a2;"
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="&#xf342;"
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="&#xf4d5;"
+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="&#xf4d6;" 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="&#xf2c3;"
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="&#xf20f;" 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="&#xf2a8;" 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="&#xf214;"
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="&#xf347;" 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="&#xf2ac;" 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="&#xf2ac;"
+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="&#xf21b;" 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="&#xf21c;" 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="&#xf21c;"
+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="&#xf21d;" 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="&#xf21e;" 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="&#xf349;" 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="&#xf34a;"
+ <glyph glyph-name="ion-sad-outline" unicode="&#xf4d7;"
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="&#xf34a;"
+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="&#xf34b;" 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="&#xf4d8;"
+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="&#xf4d9;"
+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="&#xf226;" 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="&#xf4da;"
+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="&#xf4db;"
+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="&#xf4dc;"
+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="&#xf4dd;"
+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="&#xf4de;" 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="&#xf4df;" 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="&#xf22a;"
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="&#xf22f;" 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="&#xf4e0;" 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="&#xf4e1;" 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="&#xf230;" 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="&#xf231;" 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="&#xf34c;"
-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="&#xf34d;"
-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="&#xf34c;" 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="&#xf34d;" 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="&#xf2c4;" 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="&#xf237;" 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="&#xf4e2;" 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="&#xf4e3;" 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="&#xf350;" 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="&#xf4e4;"
+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="&#xf4e5;"
+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="&#xf238;" 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="&#xf239;" 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="&#xf4e6;"
+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="&#xf4e7;" 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="&#xf4e8;"
+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="&#xf2b0;"
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="&#xf4e9;" 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="&#xf23a;" 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="&#xf23d;" 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="&#xf4ea;" 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="&#xf23e;" 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="&#xf4eb;" 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="&#xf4ec;" 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="&#xf240;" 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="&#xf241;" 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="&#xf2c5;" 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="&#xf2c5;" 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="&#xf4ed;" 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="&#xf4ee;" 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="&#xf242;" 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="&#xf4ef;"
+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="&#xf4f0;"
+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="&#xf246;"
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="&#xf247;"
@@ -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="&#xf24b;" 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="&#xf4f1;" 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="&#xf4f2;" 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="&#xf24c;" 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="&#xf24d;" 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="&#xf4f3;" 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="&#xf4f4;" 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="&#xf2b2;"
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="&#xf2b4;" 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="&#xf24e;" 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="&#xf24e;"
+d="M448 248l-139 -104l55 -176l-140 112l-140 -112l55 176l-139 104h172l52 168l53 -168h171z" />
<glyph glyph-name="ion-stats-bars" unicode="&#xf2b5;" horiz-adv-x="352"
d="M96 32v320h64v-320h-64zM0 32v96h64v-96h-64zM192 32v160h64v-160h-64zM288 32v224h64v-224h-64z" />
<glyph glyph-name="ion-steam" unicode="&#xf30b;" 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="&#xf355;"
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="&#xf4f5;" 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="&#xf252;" 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="&#xf356;"
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="&#xf4f6;"
+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="&#xf4f7;"
+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="&#xf2b7;"
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="&#xf357;"
-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="&#xf254;" 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
index cc67b2f..c4e4632 100755
--- a/public/assets/fonts/ionicons.ttf
+++ b/public/assets/fonts/ionicons.ttf
Binary files differ
diff --git a/public/assets/fonts/ionicons.woff b/public/assets/fonts/ionicons.woff
index 1d7b977..5f3a14e 100755
--- a/public/assets/fonts/ionicons.woff
+++ b/public/assets/fonts/ionicons.woff
Binary files differ
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
}
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">&nbsp;</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">&nbsp;</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 &rarr;
+ 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>&copy; 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 &rarr;</a>
[[ } else { ]]
- &rarr;
+ ->
[[ } ]]
</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 ]]