[
  {
    "path": ".bowerrc",
    "content": "{\n    \"directory\": \"app/bower_components\"\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "# EditorConfig helps developers define and maintain consistent\n# coding styles between different editors and IDEs\n# editorconfig.org\n\nroot = false\n\n\n[*]\n\n# Change these settings to your own preference\nindent_style = space\nindent_size = 2\n\n# We recommend you to keep these unchanged\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\ntemp\n.sass-cache\napp/bower_components\n.tmp/\ndist_desktop\n.DS_Store\ndist\n"
  },
  {
    "path": "Gruntfile.js",
    "content": "'use strict';\nvar lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;\nvar mountFolder = function (connect, dir) {\n    return connect.static(require('path').resolve(dir));\n};\n\n// # Globbing\n// for performance reasons we're only matching one level down:\n// 'test/spec/{,*/}*.js'\n// use this if you want to match all subfolders:\n// 'test/spec/**/*.js'\n// templateFramework: 'lodash'\n\nmodule.exports = function (grunt) {\n    // load all grunt tasks\n    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);\n\n    // configurable paths\n    var yeomanConfig = {\n        app: 'app',\n        dist: 'dist'\n    };\n\n    grunt.initConfig({\n        yeoman: yeomanConfig,\n        clean: {\n            dist: ['.tmp', '<%= yeoman.dist %>/*'],\n            server: '.tmp'\n        },\n        // This task uses James Burke's excellent r.js AMD builder to take all\n        // modules and concatenate them into a single file.\n        requirejs: {\n          release: {\n            options: {\n\n              mainConfigFile: \"app/scripts/config.js\",\n\n              include: [\"main\"],\n              insertRequire: [\"main\"],\n\n              out: \"dist/source.min.js\",\n              optimize: \"uglify\",\n\n              // Since we bootstrap with nested `require` calls this option allows\n              // R.js to find them.\n              findNestedDependencies: true,\n\n              // Include a minimal AMD implementation shim.\n              name: \"almond\",\n\n              // Setting the base url to the distribution directory allows the\n              // Uglify minification process to correctly map paths for Source\n              // Maps.\n              baseUrl: \"app/scripts\",\n\n              // Wrap everything in an IIFE.\n              wrap: true,\n\n              // Do not preserve any license comments when working with source\n              // maps.  These options are incompatible.\n              preserveLicenseComments: true\n            }\n          },\n          customizer: {\n            options: {\n\n              mainConfigFile: \"app/scripts/config.js\",\n\n              include: [\"customizer\"],\n              insertRequire: [\"customizer\"],\n\n              out: \"dist/customizer.min.js\",\n              optimize: \"uglify\",\n              findNestedDependencies: true,\n              name: \"almond\",\n              baseUrl: \"app/scripts\",\n              wrap: true,\n              preserveLicenseComments: true\n            }\n          }\n        },\n        imagemin: {\n            dist: {\n                files: [{\n                    expand: true,\n                    cwd: '<%= yeoman.app %>/images',\n                    src: '{,*/}*.{png,jpg,jpeg}',\n                    dest: '<%= yeoman.dist %>/images'\n                }]\n            },\n            jqueryui: {\n                files: [{\n                    expand: true,\n                    flatten: true,\n                    cwd: '<%= yeoman.app %>',\n                    src: 'bower_components/jquery.ui/themes/base/images/*.png',\n                    dest: '<%= yeoman.dist %>/images'\n                }]\n            }\n        },\n        cssmin: {\n            dist: {\n                files: {\n                    '<%= yeoman.dist %>/app.min.css': [\n                        '.tmp/styles/{,*/}*.css',\n                        '<%= yeoman.app %>/bower_components/jquery.ui/themes/base/*.css',\n                        '<%= yeoman.app %>/bower_components/components-font-awesome/css/font-awesome.min.css',\n                        '<%= yeoman.app %>/styles/bootstrap.css',\n\t\t\t'<%= yeoman.app %>/bower_components/CodeMirror/lib/codemirror.css',\n\t\t\t'<%= yeoman.app %>/bower_components/CodeMirror/addon/hint/show-hint.css',\n\t\t\t'<%= yeoman.app %>/styles/main.css',\n                    ],\n                    '<%= yeoman.dist %>/customizer.min.css': [\n                        '.tmp/styles/{,*/}*.css',\n                        '<%= yeoman.app %>/bower_components/jquery.ui/themes/base/*.css',\n                        '<%= yeoman.app %>/bower_components/components-font-awesome/css/font-awesome.min.css',\n                        '<%= yeoman.app %>/styles/bootstrap.css',\n                        '<%= yeoman.app %>/styles/main.css',\n                        '<%= yeoman.app %>/styles/customizer.css'\n                    ]\n                }\n            }\n        },\n        copy: {\n            dist: {\n                files: [{\n                    expand: true,\n                    dot: true,\n                    cwd: '<%= yeoman.app %>',\n                    dest: '<%= yeoman.dist %>',\n                    src: [\n                        '*.{ico,txt}',\n                        '.htaccess',\n                        '*.html',\n                        '*.json',\n                        'images/{,*/}*.{webp,gif,png}',\n                        'bower_components/jquery/jquery.js',\n                        'bower_components/components-font-awesome/css/font-awesome.min.css',\n                        'bower_components/components-font-awesome/fonts/*.{ttf,eot,svg,woff,otf}',\n                        'scripts/lib/flood/*.js'\n                    ]\n                }]\n            },\n            fonts: {\n                files: [{\n                    expand: true,\n                    dot: true,\n                    flatten: true,\n                    cwd: '<%= yeoman.app %>',\n                    dest: '<%= yeoman.dist %>/fonts',\n                    src: [\n                        'bower_components/components-font-awesome/fonts/*.{ttf,eot,svg,woff,otf}'\n                    ]\n                }]\n            }\n        },\n        bower: {\n            all: {\n                rjsConfig: '<%= yeoman.app %>/scripts/main.js'\n            }\n        },\n        processhtml: {\n          release: {\n            files: {\n              \"dist/app.html\": [\"app/app.html\"],\n              \"dist/customizer.html\": [\"app/customizer.html\"]\n            }\n          }\n        },\n        nodewebkit: {\n            options: {\n                version: '0.8.1',\n                build_dir: './dist_desktop', // Where the build version of my node-webkit app is saved\n                mac: true, // We want to build it for mac\n                win: true, // We want to build it for win\n                linux32: false, // We don't need linux32\n                linux64: false // We don't need linux64\n            },\n            src: ['./dist/**'] // Your node-wekit app\n        }\n    });\n\n    grunt.registerTask('build', [\n        'clean:dist',\n        'requirejs',\n        'imagemin',\n        'cssmin',\n        'copy',\n        'processhtml'\n    ]);\n\n    grunt.registerTask('desktop', [\n        'clean:dist',\n        'requirejs',\n        'imagemin',\n        'cssmin',\n        'copy',\n        'processhtml',\n        'nodewebkit'\n    ]);\n\n    grunt.registerTask('default', [\n        'build'\n    ]);\n};\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) Peter Boyer 2013\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "README.md",
    "content": "![Image](https://raw.github.com/pboyer/flood/master/extra/screenshot.png) \n\n\n## flood\n\n### What is it?\n\nflood is a [dataflow](http://en.wikipedia.org/wiki/Dataflow_programming)-style visual programming language based on Scheme written in JavaScript.  flood runs in a browser and as a standalone application on all platforms via [node-webkit](https://github.com/rogerwang/node-webkit).  \n\n### Features\n\n* Constructive solid geometry - Cube, cylinder, sphere, union, intersect, subtract\n* Formula node - evaluate javascript in a node\n* Never save your work\n* Fast node library search\n* Undo/redo across user sessions\n* Copy/paste\n* Multiple workspaces\n* Async evaluation\n* Partial function application\n* \"Always on\" continuous execution\n\nflood, like early versions of [Dynamo](http://github.com/ikeough/Dynamo), is based on Scheme and thus has many of the features of that language.  It uses a [lightweight scheme interpreter](http://github.com/pboyer/scheme.js) I wrote called scheme.js.\n\n### Getting started\n\nThe flood app is scaffolded with [Yeoman](http://yeoman.io/), uses [Grunt](http://gruntjs.com/) for task management and [Bower](http://bower.io/) for web package management.  If you're not familiar with these tools, you should take a look at the docs and get them installed.  \n\nflood uses [require.js](http://requirejs.org/) to manage dependencies between JavaScript files and [backbone.js](http://backbonejs.org/) to stick it all together. \n\nflood also has a server written in node.js that handles user authentication and model synchronization. \n\n#### Installing dependencies for the app\n\nTo install all of the dependencies for the flood app, run the following commands in the root directory:\n\n\tbower install\n\tnpm install\n\nThis will install all of the development dependencies for Grunt and all of the public dependencies with bower.\n\n#### Installing dependencies for the server\n\nTo install all of the node.js dependencies for the flood server, run the following commands in the \"server\" directory:\n\n\tnpm install\n\nYou will also need to install MongoDB and run an instance on port 27017, the default port for MongoDB.  You can get MongoDB [here](http://www.mongodb.org/downloads).\n\n\n#### Running the server\n\nFor development, I recommend using the great nodemon tool:\n\n\tnpm install -g nodemon\n\nGo to the \"server\" directory and run:\n\n\tnodemon app.js\n\nYou can also run the server using:\n\n\tnode app.js\n\n\n#### Building for the web (outdated)\n\nThe entire app can be compressed into lightweight, minified, and concatenated css, js, and html files using Grunt:\n\n\tgrunt \n\n\n#### Building for the desktop\n\nflood can be used as a standalone application via node-webkit.  Just do this:\n\n\tgrunt desktop\n\nThis will generate binaries for use on Mac and Windows in the dist_desktop folder.\n\n\n### License\n\nThe MIT License (MIT)\n\nCopyright (c) Peter Boyer 2014-2020\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n"
  },
  {
    "path": "app/.htaccess",
    "content": "# Apache configuration file\n# httpd.apache.org/docs/2.2/mod/quickreference.html\n\n# Note .htaccess files are an overhead, this logic should be in your Apache\n# config if possible: httpd.apache.org/docs/2.2/howto/htaccess.html\n\n# Techniques in here adapted from all over, including:\n#   Kroc Camen: camendesign.com/.htaccess\n#   perishablepress.com/press/2006/01/10/stupid-htaccess-tricks/\n#   Sample .htaccess file of CMS MODx: modxcms.com\n\n\n# ----------------------------------------------------------------------\n# Better website experience for IE users\n# ----------------------------------------------------------------------\n\n# Force the latest IE version, in various cases when it may fall back to IE7 mode\n#  github.com/rails/rails/commit/123eb25#commitcomment-118920\n# Use ChromeFrame if it's installed for a better experience for the poor IE folk\n\n<IfModule mod_headers.c>\n  Header set X-UA-Compatible \"IE=Edge,chrome=1\"\n  # mod_headers can't match by content-type, but we don't want to send this header on *everything*...\n  <FilesMatch \"\\.(js|css|gif|png|jpe?g|pdf|xml|oga|ogg|m4a|ogv|mp4|m4v|webm|svg|svgz|eot|ttf|otf|woff|ico|webp|appcache|manifest|htc|crx|oex|xpi|safariextz|vcf)$\" >\n    Header unset X-UA-Compatible\n  </FilesMatch>\n</IfModule>\n\n\n# ----------------------------------------------------------------------\n# Cross-domain AJAX requests\n# ----------------------------------------------------------------------\n\n# Serve cross-domain Ajax requests, disabled by default.\n# enable-cors.org\n# code.google.com/p/html5security/wiki/CrossOriginRequestSecurity\n\n#  <IfModule mod_headers.c>\n#    Header set Access-Control-Allow-Origin \"*\"\n#  </IfModule>\n\n\n# ----------------------------------------------------------------------\n# CORS-enabled images (@crossorigin)\n# ----------------------------------------------------------------------\n\n# Send CORS headers if browsers request them; enabled by default for images.\n# developer.mozilla.org/en/CORS_Enabled_Image\n# blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html\n# hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/\n# wiki.mozilla.org/Security/Reviews/crossoriginAttribute\n\n<IfModule mod_setenvif.c>\n  <IfModule mod_headers.c>\n    # mod_headers, y u no match by Content-Type?!\n    <FilesMatch \"\\.(gif|png|jpe?g|svg|svgz|ico|webp)$\">\n      SetEnvIf Origin \":\" IS_CORS\n      Header set Access-Control-Allow-Origin \"*\" env=IS_CORS\n    </FilesMatch>\n  </IfModule>\n</IfModule>\n\n\n# ----------------------------------------------------------------------\n# Webfont access\n# ----------------------------------------------------------------------\n\n# Allow access from all domains for webfonts.\n# Alternatively you could only whitelist your\n# subdomains like \"subdomain.example.com\".\n\n<IfModule mod_headers.c>\n  <FilesMatch \"\\.(ttf|ttc|otf|eot|woff|font.css)$\">\n    Header set Access-Control-Allow-Origin \"*\"\n  </FilesMatch>\n</IfModule>\n\n\n# ----------------------------------------------------------------------\n# Proper MIME type for all files\n# ----------------------------------------------------------------------\n\n# JavaScript\n#   Normalize to standard type (it's sniffed in IE anyways)\n#   tools.ietf.org/html/rfc4329#section-7.2\nAddType application/javascript         js jsonp\nAddType application/json               json\n\n# Audio\nAddType audio/ogg                      oga ogg\nAddType audio/mp4                      m4a f4a f4b\n\n# Video\nAddType video/ogg                      ogv\nAddType video/mp4                      mp4 m4v f4v f4p\nAddType video/webm                     webm\nAddType video/x-flv                    flv\n\n# SVG\n#   Required for svg webfonts on iPad\n#   twitter.com/FontSquirrel/status/14855840545\nAddType     image/svg+xml              svg svgz\nAddEncoding gzip                       svgz\n\n# Webfonts\nAddType application/vnd.ms-fontobject  eot\nAddType application/x-font-ttf         ttf ttc\nAddType font/opentype                  otf\nAddType application/x-font-woff        woff\n\n# Assorted types\nAddType image/x-icon                        ico\nAddType image/webp                          webp\nAddType text/cache-manifest                 appcache manifest\nAddType text/x-component                    htc\nAddType application/xml                     rss atom xml rdf\nAddType application/x-chrome-extension      crx\nAddType application/x-opera-extension       oex\nAddType application/x-xpinstall             xpi\nAddType application/octet-stream            safariextz\nAddType application/x-web-app-manifest+json webapp\nAddType text/x-vcard                        vcf\nAddType application/x-shockwave-flash       swf\nAddType text/vtt                            vtt\n\n\n# ----------------------------------------------------------------------\n# Allow concatenation from within specific js and css files\n# ----------------------------------------------------------------------\n\n# e.g. Inside of script.combined.js you could have\n#   <!--#include file=\"libs/jquery-1.5.0.min.js\" -->\n#   <!--#include file=\"plugins/jquery.idletimer.js\" -->\n# and they would be included into this single file.\n\n# This is not in use in the boilerplate as it stands. You may\n# choose to use this technique if you do not have a build process.\n\n#<FilesMatch \"\\.combined\\.js$\">\n#  Options +Includes\n#  AddOutputFilterByType INCLUDES application/javascript application/json\n#  SetOutputFilter INCLUDES\n#</FilesMatch>\n\n#<FilesMatch \"\\.combined\\.css$\">\n#  Options +Includes\n#  AddOutputFilterByType INCLUDES text/css\n#  SetOutputFilter INCLUDES\n#</FilesMatch>\n\n\n# ----------------------------------------------------------------------\n# Gzip compression\n# ----------------------------------------------------------------------\n\n<IfModule mod_deflate.c>\n\n  # Force deflate for mangled headers developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/\n  <IfModule mod_setenvif.c>\n    <IfModule mod_headers.c>\n      SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\\s*,?\\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding\n      RequestHeader append Accept-Encoding \"gzip,deflate\" env=HAVE_Accept-Encoding\n    </IfModule>\n  </IfModule>\n\n  # HTML, TXT, CSS, JavaScript, JSON, XML, HTC:\n  <IfModule filter_module>\n    FilterDeclare   COMPRESS\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/html\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/css\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/plain\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/xml\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/x-component\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/javascript\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/json\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/xml\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/xhtml+xml\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/rss+xml\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/atom+xml\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/vnd.ms-fontobject\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $image/svg+xml\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $image/x-icon\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/x-font-ttf\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $font/opentype\n    FilterChain     COMPRESS\n    FilterProtocol  COMPRESS  DEFLATE change=yes;byteranges=no\n  </IfModule>\n\n  <IfModule !mod_filter.c>\n    # Legacy versions of Apache\n    AddOutputFilterByType DEFLATE text/html text/plain text/css application/json\n    AddOutputFilterByType DEFLATE application/javascript\n    AddOutputFilterByType DEFLATE text/xml application/xml text/x-component\n    AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml\n    AddOutputFilterByType DEFLATE image/x-icon image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype\n  </IfModule>\n\n</IfModule>\n\n\n# ----------------------------------------------------------------------\n# Expires headers (for better cache control)\n# ----------------------------------------------------------------------\n\n# These are pretty far-future expires headers.\n# They assume you control versioning with filename-based cache busting\n# Additionally, consider that outdated proxies may miscache\n#   www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/\n\n# If you don't use filenames to version, lower the CSS and JS to something like\n# \"access plus 1 week\".\n\n<IfModule mod_expires.c>\n  ExpiresActive on\n\n# Perhaps better to whitelist expires rules? Perhaps.\n  ExpiresDefault                          \"access plus 1 month\"\n\n# cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5)\n  ExpiresByType text/cache-manifest       \"access plus 0 seconds\"\n\n# Your document html\n  ExpiresByType text/html                 \"access plus 0 seconds\"\n\n# Data\n  ExpiresByType text/xml                  \"access plus 0 seconds\"\n  ExpiresByType application/xml           \"access plus 0 seconds\"\n  ExpiresByType application/json          \"access plus 0 seconds\"\n\n# Feed\n  ExpiresByType application/rss+xml       \"access plus 1 hour\"\n  ExpiresByType application/atom+xml      \"access plus 1 hour\"\n\n# Favicon (cannot be renamed)\n  ExpiresByType image/x-icon              \"access plus 1 week\"\n\n# Media: images, video, audio\n  ExpiresByType image/gif                 \"access plus 1 month\"\n  ExpiresByType image/png                 \"access plus 1 month\"\n  ExpiresByType image/jpeg                \"access plus 1 month\"\n  ExpiresByType video/ogg                 \"access plus 1 month\"\n  ExpiresByType audio/ogg                 \"access plus 1 month\"\n  ExpiresByType video/mp4                 \"access plus 1 month\"\n  ExpiresByType video/webm                \"access plus 1 month\"\n\n# HTC files  (css3pie)\n  ExpiresByType text/x-component          \"access plus 1 month\"\n\n# Webfonts\n  ExpiresByType application/x-font-ttf    \"access plus 1 month\"\n  ExpiresByType font/opentype             \"access plus 1 month\"\n  ExpiresByType application/x-font-woff   \"access plus 1 month\"\n  ExpiresByType image/svg+xml             \"access plus 1 month\"\n  ExpiresByType application/vnd.ms-fontobject \"access plus 1 month\"\n\n# CSS and JavaScript\n  ExpiresByType text/css                  \"access plus 1 year\"\n  ExpiresByType application/javascript    \"access plus 1 year\"\n\n</IfModule>\n\n\n# ----------------------------------------------------------------------\n# Prevent mobile network providers from modifying your site\n# ----------------------------------------------------------------------\n\n# The following header prevents modification of your code over 3G on some\n# European providers.\n# This is the official 'bypass' suggested by O2 in the UK.\n\n# <IfModule mod_headers.c>\n# Header set Cache-Control \"no-transform\"\n# </IfModule>\n\n\n# ----------------------------------------------------------------------\n# ETag removal\n# ----------------------------------------------------------------------\n\n# FileETag None is not enough for every server.\n<IfModule mod_headers.c>\n  Header unset ETag\n</IfModule>\n\n# Since we're sending far-future expires, we don't need ETags for\n# static content.\n#   developer.yahoo.com/performance/rules.html#etags\nFileETag None\n\n\n# ----------------------------------------------------------------------\n# Stop screen flicker in IE on CSS rollovers\n# ----------------------------------------------------------------------\n\n# The following directives stop screen flicker in IE on CSS rollovers - in\n# combination with the \"ExpiresByType\" rules for images (see above).\n\n# BrowserMatch \"MSIE\" brokenvary=1\n# BrowserMatch \"Mozilla/4.[0-9]{2}\" brokenvary=1\n# BrowserMatch \"Opera\" !brokenvary\n# SetEnvIf brokenvary 1 force-no-vary\n\n\n# ----------------------------------------------------------------------\n# Set Keep-Alive Header\n# ----------------------------------------------------------------------\n\n# Keep-Alive allows the server to send multiple requests through one\n# TCP-connection. Be aware of possible disadvantages of this setting. Turn on\n# if you serve a lot of static content.\n\n# <IfModule mod_headers.c>\n#   Header set Connection Keep-Alive\n# </IfModule>\n\n\n# ----------------------------------------------------------------------\n# Cookie setting from iframes\n# ----------------------------------------------------------------------\n\n# Allow cookies to be set from iframes (for IE only)\n# If needed, specify a path or regex in the Location directive.\n\n# <IfModule mod_headers.c>\n#   Header set P3P \"policyref=\\\"/w3c/p3p.xml\\\", CP=\\\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\\\"\"\n# </IfModule>\n\n\n# ----------------------------------------------------------------------\n# Start rewrite engine\n# ----------------------------------------------------------------------\n\n# Turning on the rewrite engine is necessary for the following rules and\n# features. FollowSymLinks must be enabled for this to work.\n\n# Some cloud hosting services require RewriteBase to be set: goo.gl/HOcPN\n# If using the h5bp in a subdirectory, use `RewriteBase /foo` instead where\n# 'foo' is your directory.\n\n# If your web host doesn't allow the FollowSymlinks option, you may need to\n# comment it out and use `Options +SymLinksOfOwnerMatch`, but be aware of the\n# performance impact: http://goo.gl/Mluzd\n\n<IfModule mod_rewrite.c>\n  Options +FollowSymlinks\n# Options +SymLinksIfOwnerMatch\n  Options +FollowSymlinks\n  RewriteEngine On\n# RewriteBase /\n</IfModule>\n\n\n# ----------------------------------------------------------------------\n# Suppress or force the \"www.\" at the beginning of URLs\n# ----------------------------------------------------------------------\n\n# The same content should never be available under two different URLs -\n# especially not with and without \"www.\" at the beginning, since this can cause\n# SEO problems (duplicate content). That's why you should choose one of the\n# alternatives and redirect the other one.\n\n# By default option 1 (no \"www.\") is activated.\n# no-www.org/faq.php?q=class_b\n\n# If you'd prefer to use option 2, just comment out all option 1 lines\n# and uncomment option 2.\n\n# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME!\n\n# ----------------------------------------------------------------------\n\n# Option 1:\n# Rewrite \"www.example.com -> example.com\".\n\n<IfModule mod_rewrite.c>\n  RewriteCond %{HTTPS} !=on\n  RewriteCond %{HTTP_HOST} ^www\\.(.+)$ [NC]\n  RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]\n</IfModule>\n\n# ----------------------------------------------------------------------\n\n# Option 2:\n# Rewrite \"example.com -> www.example.com\".\n# Be aware that the following rule might not be a good idea if you use \"real\"\n# subdomains for certain parts of your website.\n\n# <IfModule mod_rewrite.c>\n#   RewriteCond %{HTTPS} !=on\n#   RewriteCond %{HTTP_HOST} !^www\\..+$ [NC]\n#   RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]\n# </IfModule>\n\n\n# ----------------------------------------------------------------------\n# Built-in filename-based cache busting\n# ----------------------------------------------------------------------\n\n# If you're not using the build script to manage your filename version revving,\n# you might want to consider enabling this, which will route requests for\n# /css/style.20110203.css to /css/style.css\n\n# To understand why this is important and a better idea than all.css?v1231,\n# read: github.com/h5bp/html5-boilerplate/wiki/cachebusting\n\n# <IfModule mod_rewrite.c>\n#   RewriteCond %{REQUEST_FILENAME} !-f\n#   RewriteCond %{REQUEST_FILENAME} !-d\n#   RewriteRule ^(.+)\\.(\\d+)\\.(js|css|png|jpg|gif)$ $1.$3 [L]\n# </IfModule>\n\n\n# ----------------------------------------------------------------------\n# Prevent SSL cert warnings\n# ----------------------------------------------------------------------\n\n# Rewrite secure requests properly to prevent SSL cert warnings, e.g. prevent\n# https://www.example.com when your cert only allows https://secure.example.com\n\n# <IfModule mod_rewrite.c>\n#   RewriteCond %{SERVER_PORT} !^443\n#   RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L]\n# </IfModule>\n\n\n# ----------------------------------------------------------------------\n# Prevent 404 errors for non-existing redirected folders\n# ----------------------------------------------------------------------\n\n# without -MultiViews, Apache will give a 404 for a rewrite if a folder of the\n# same name does not exist.\n# webmasterworld.com/apache/3808792.htm\n\nOptions -MultiViews\n\n\n# ----------------------------------------------------------------------\n# Custom 404 page\n# ----------------------------------------------------------------------\n\n# You can add custom pages to handle 500 or 403 pretty easily, if you like.\n# If you are hosting your site in subdirectory, adjust this accordingly\n#    e.g. ErrorDocument 404 /subdir/404.html\nErrorDocument 404 /404.html\n\n\n# ----------------------------------------------------------------------\n# UTF-8 encoding\n# ----------------------------------------------------------------------\n\n# Use UTF-8 encoding for anything served text/plain or text/html\nAddDefaultCharset utf-8\n\n# Force UTF-8 for a number of file formats\nAddCharset utf-8 .atom .css .js .json .rss .vtt .xml\n\n\n# ----------------------------------------------------------------------\n# A little more security\n# ----------------------------------------------------------------------\n\n# To avoid displaying the exact version number of Apache being used, add the\n# following to httpd.conf (it will not work in .htaccess):\n# ServerTokens Prod\n\n# \"-Indexes\" will have Apache block users from browsing folders without a\n# default document Usually you should leave this activated, because you\n# shouldn't allow everybody to surf through every folder on your server (which\n# includes rather private places like CMS system folders).\n<IfModule mod_autoindex.c>\n  Options -Indexes\n</IfModule>\n\n# Block access to \"hidden\" directories or files whose names begin with a\n# period. This includes directories used by version control systems such as\n# Subversion or Git.\n<IfModule mod_rewrite.c>\n  RewriteCond %{SCRIPT_FILENAME} -d [OR]\n  RewriteCond %{SCRIPT_FILENAME} -f\n  RewriteRule \"(^|/)\\.\" - [F]\n</IfModule>\n\n# Block access to backup and source files. These files may be left by some\n# text/html editors and pose a great security danger, when anyone can access\n# them.\n<FilesMatch \"(\\.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)|~)$\">\n  Order allow,deny\n  Deny from all\n  Satisfy All\n</FilesMatch>\n\n# If your server is not already configured as such, the following directive\n# should be uncommented in order to set PHP's register_globals option to OFF.\n# This closes a major security hole that is abused by most XSS (cross-site\n# scripting) attacks. For more information: http://php.net/register_globals\n#\n# IF REGISTER_GLOBALS DIRECTIVE CAUSES 500 INTERNAL SERVER ERRORS:\n#\n# Your server does not allow PHP directives to be set via .htaccess. In that\n# case you must make this change in your php.ini file instead. If you are\n# using a commercial web host, contact the administrators for assistance in\n# doing this. Not all servers allow local php.ini files, and they should\n# include all PHP configurations (not just this one), or you will effectively\n# reset everything to PHP defaults. Consult www.php.net for more detailed\n# information about setting PHP directives.\n\n# php_flag register_globals Off\n\n# Rename session cookie to something else, than PHPSESSID\n# php_value session.name sid\n\n# Disable magic quotes (This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.)\n# php_flag magic_quotes_gpc Off\n\n# Do not show you are using PHP\n# Note: Move this line to php.ini since it won't work in .htaccess\n# php_flag expose_php Off\n\n# Level of log detail - log all errors\n# php_value error_reporting -1\n\n# Write errors to log file\n# php_flag log_errors On\n\n# Do not display errors in browser (production - Off, development - On)\n# php_flag display_errors Off\n\n# Do not display startup errors (production - Off, development - On)\n# php_flag display_startup_errors Off\n\n# Format errors in plain text\n# Note: Leave this setting 'On' for xdebug's var_dump() output\n# php_flag html_errors Off\n\n# Show multiple occurrence of error\n# php_flag ignore_repeated_errors Off\n\n# Show same errors from different sources\n# php_flag ignore_repeated_source Off\n\n# Size limit for error messages\n# php_value log_errors_max_len 1024\n\n# Don't precede error with string (doesn't accept empty string, use whitespace if you need)\n# php_value error_prepend_string \" \"\n\n# Don't prepend to error (doesn't accept empty string, use whitespace if you need)\n# php_value error_append_string \" \"\n\n# Increase cookie security\n<IfModule php5_module>\n  php_value session.cookie_httponly true\n</IfModule>\n"
  },
  {
    "path": "app/404.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <meta charset=\"utf-8\">\n        <title>Page Not Found :(</title>\n        <style>\n            ::-moz-selection {\n                background: #b3d4fc;\n                text-shadow: none;\n            }\n\n            ::selection {\n                background: #b3d4fc;\n                text-shadow: none;\n            }\n\n            html {\n                padding: 30px 10px;\n                font-size: 20px;\n                line-height: 1.4;\n                color: #737373;\n                background: #f0f0f0;\n                -webkit-text-size-adjust: 100%;\n                -ms-text-size-adjust: 100%;\n            }\n\n            html,\n            input {\n                font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n            }\n\n            body {\n                max-width: 500px;\n                _width: 500px;\n                padding: 30px 20px 50px;\n                border: 1px solid #b3b3b3;\n                border-radius: 4px;\n                margin: 0 auto;\n                box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;\n                background: #fcfcfc;\n            }\n\n            h1 {\n                margin: 0 10px;\n                font-size: 50px;\n                text-align: center;\n            }\n\n            h1 span {\n                color: #bbb;\n            }\n\n            h3 {\n                margin: 1.5em 0 0.5em;\n            }\n\n            p {\n                margin: 1em 0;\n            }\n\n            ul {\n                padding: 0 0 0 40px;\n                margin: 1em 0;\n            }\n\n            .container {\n                max-width: 380px;\n                _width: 380px;\n                margin: 0 auto;\n            }\n\n            /* google search */\n\n            #goog-fixurl ul {\n                list-style: none;\n                padding: 0;\n                margin: 0;\n            }\n\n            #goog-fixurl form {\n                margin: 0;\n            }\n\n            #goog-wm-qt,\n            #goog-wm-sb {\n                border: 1px solid #bbb;\n                font-size: 16px;\n                line-height: normal;\n                vertical-align: top;\n                color: #444;\n                border-radius: 2px;\n            }\n\n            #goog-wm-qt {\n                width: 220px;\n                height: 20px;\n                padding: 5px;\n                margin: 5px 10px 0 0;\n                box-shadow: inset 0 1px 1px #ccc;\n            }\n\n            #goog-wm-sb {\n                display: inline-block;\n                height: 32px;\n                padding: 0 10px;\n                margin: 5px 0 0;\n                white-space: nowrap;\n                cursor: pointer;\n                background-color: #f5f5f5;\n                background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                -webkit-appearance: none;\n                -moz-appearance: none;\n                appearance: none;\n                *overflow: visible;\n                *display: inline;\n                *zoom: 1;\n            }\n\n            #goog-wm-sb:hover,\n            #goog-wm-sb:focus {\n                border-color: #aaa;\n                box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);\n                background-color: #f8f8f8;\n            }\n\n            #goog-wm-qt:hover,\n            #goog-wm-qt:focus {\n                border-color: #105cb6;\n                outline: 0;\n                color: #222;\n            }\n\n            input::-moz-focus-inner {\n                padding: 0;\n                border: 0;\n            }\n        </style>\n    </head>\n    <body>\n        <div class=\"container\">\n            <h1>Not found <span>:(</span></h1>\n            <p>Sorry, but the page you were trying to view does not exist.</p>\n            <p>It looks like this was the result of either:</p>\n            <ul>\n                <li>a mistyped address</li>\n                <li>an out-of-date link</li>\n            </ul>\n            <script>\n                var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),GOOG_FIXURL_SITE = location.host;\n            </script>\n            <script src=\"http://linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js\"></script>\n        </div>\n    </body>\n</html>\n"
  },
  {
    "path": "app/app.html",
    "content": "<!doctype html>\n<!--[if lt IE 7]>      <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\"> <![endif]-->\n<!--[if IE 7]>         <html class=\"no-js lt-ie9 lt-ie8\"> <![endif]-->\n<!--[if IE 8]>         <html class=\"no-js lt-ie9\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js\"> <!--<![endif]-->\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n        <title>Editor Beta - Flood</title>\n        <meta name=\"description\" content=\"\">\n        <meta name=\"viewport\" content=\"user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1\">\n\n        <!-- build:css app.min.css -->\n        <link rel=\"stylesheet\" href=\"bower_components/jquery.ui/themes/base/jquery.ui.all.css\">\n        <link rel=\"stylesheet\" href=\"bower_components/components-font-awesome/css/font-awesome.min.css\">\n        <link rel=\"stylesheet\" href=\"styles/bootstrap.css\">\n        <link rel=\"stylesheet\" href=\"bower_components/CodeMirror/lib/codemirror.css\">\n\t<link rel=\"stylesheet\" href=\"bower_components/CodeMirror/addon/hint/show-hint.css\">\n        <link rel=\"stylesheet\" href=\"styles/main.css\">\n        <!-- /build -->\n\n        <style>\n\n          body {\n            margin: 0;\n            padding: 0;\n            font-family:Helvetica, Arial, \"Lucida Grande\", sans-serif;\n          }\n\n          #login {\n            background: #e3e3e3;\n            text-align: center;\n            z-index: 120;\n            right: 0;\n            left: 0;\n            top: 0;\n            bottom: 0;\n\n            background-image: -ms-radial-gradient(center, circle closest-corner, #E3E3E3 0%, #C4C4C4 100%);\n            background-image: -moz-radial-gradient(center, circle closest-corner, #E3E3E3 0%, #C4C4C4 100%);\n            background-image: -o-radial-gradient(center, circle closest-corner, #E3E3E3 0%, #C4C4C4 100%);\n            background-image: -webkit-gradient(radial, center center, 0, center center, 497, color-stop(0, #E3E3E3), color-stop(1, #C4C4C4));\n            background-image: -webkit-radial-gradient(center, circle closest-corner, #E3E3E3 0%, #C4C4C4 100%);\n            background-image: radial-gradient(circle closest-corner at center, #E3E3E3 0%, #C4C4C4 100%);\n          }\n\n          .editor-container {\n            letter-spacing: 60px;\n            padding-top: 230px;\n            width: 450px;\n            margin-left: auto;\n            margin-right: auto;\n            font-size: 16px;\n            color: #666;\n            text-shadow: 0 1px white;\n          }\n\n          .editor-container span {\n            margin-left: 45px;\n          }\n\n          #title a {\n            text-decoration: none;\n          }\n\n          .title-box {\n            font-family:Helvetica, Arial, \"Lucida Grande\", sans-serif;\n            padding: 0;\n            margin: 0;\n            font-size: 180px;\n\n            text-shadow: 0 1px white;\n            width: 500px;\n            left: 50%;\n            margin-left: -250px;\n\n            position: absolute;\n            overflow: hidden;\n\n            transition: height 5s;\n            transition-timing-function: ease-out;\n          }\n\n\n          #title-grey {\n            height: 145px;\n            z-index: 122;\n            color: #272822;\n            width: 500px;\n          }\n\n          #title-blue {\n            position: absolute;\n            color: #589cc8;\n            width: 500px;\n          }\n\n          .form-group {padding: 5px;}\n\n          .form-group label { color: #AAA; }\n\n          .login-container {\n            padding-top: 50px;\n            width: 300px;\n            margin-left: auto;\n            margin-right: auto;\n          }\n\n          .login-container h5 {\n            font-size: 18px;\n            color: #666;\n            text-shadow: 0 1px white;\n          }\n\n          #app-fail {\n            position: absolute;\n            top: 0;\n            bottom: 0;\n            left: 0;\n            right: 0;\n            background: white;\n            color: #333;\n            z-index: 125;\n            background: #960018;\n          }\n\n          #app-fail-container {\n            border-radius: 6px;\n            width: 450px;\n            margin-left: auto;\n            margin-right: auto;\n            padding: 20px;\n            background: whitesmoke;\n            margin-top: 50px;\n          }\n    \n          #app-fail-container i {\n            font-size: 150px;\n            color: grey;\n          }\n\n          #app-fail-container h1 {\n            text-align: center;\n          }\n\n          #app-fail-container p {\n            padding-top: 20px;\n            color: grey;\n          }\n\n        </style>\n\n    </head>\n    \n    <body>\n\n        <div id=\"app\" class=\"row col\">\n\n          <div id=\"top_container\" class=\"row\" style=\"overflow: visible;\">\n                \n            <div id=\"workspace-tabs\"></div>\n\n            <div id=\"add-workspace-button\" class=\"menu-element\" style=\"float: left;\">\n              <i class=\"fa fa-file dim-button\"></i>\n            </div>\n\n            <div id=\"add-workspace-select-element\">\n              <div id=\"add-workspace-select-container\">\n                <ul>\n                  <li id=\"add-project-workspace\">Project</li>\n                  <li id=\"add-node-workspace\">Custom node</li>\n                </ul>\n              </div>\n            </div>\n\n            <div id=\"more-menu\">\n              <div id=\"login-button\" class=\"menu-element\">\n                <i class=\"fa fa-sign-out fa-fw\"></i>\n                Logout\n              </div>\n              <div id=\"workspace-browser-button\" class=\"menu-element\">\n                <i class=\"fa fa-list-ul fa-fw\"></i>Workspaces\n              </div>\n            </div>\n  \n          </div> \n\n          <div id=\"extra-menu\">\n            <div id=\"feedback-button\" class=\"menu-element\">\n              <i class=\"fa fa-comment fa-fw\"></i>\n            </div>\n            <div id=\"help-button\" class=\"menu-element\">\n              <i class=\"fa fa-question fa-fw\"></i>\n            </div>\n\n            <div id=\"share-button\" style=\"margin-top: 15px\" class=\"menu-element\">\n              <i class=\"fa fa-share fa-fw\"></i>\n            </div>\n          </div>\n\n          <div id=\"workspaces\">\n\n            <div id=\"workspace_hide\" class=\"rightside workspace-search-button-active\">\n              <span>3D</span> <i class=\"fa fa-fw fa-cube fa-2x\" style=\"margin-left: 10px\"></i>\n            </div>\n            <div class=\"workspaces_curtain row\"></div>\n\n          </div>\n\n          <div id=\"login\" class=\"row col scroll-y\">\n\n            <div id=\"title-container\">\n              <div class=\"title-box\" id=\"title-grey\">flood</div>\n              <div class=\"title-box\" id=\"title-blue\">flood</div>\n            </div>\n\n            <div class=\"editor-container\"><span>EDITOR</span></div>\n\n            <div class=\"login-container\">\n              <h5>Wait for it...</h5>\n            </div>\n          </div>\n\n          <div id=\"help\" class=\"col\">\n            \n          </div>\n\n          <div id=\"feedback\" class=\"modal row col\">\n            \n          </div>\n\n          <div id=\"share\" class=\"modal row col\">\n            \n          </div>\n\n          <div id=\"workspace-browser\" class=\"col\">\n            \n          </div>\n\n          <div id=\"viewer\" class=\"row blur\"></div>\n\n          <div id=\"app-fail\" style=\"display: none\">\n  \n            <div id=\"app-fail-container\">\n              <h1><i class=\"fa fa-fw fa-2x fa-exclamation-triangle\"></i></h1>\n              <h1>Flood requires WebGL!</h1>\n              <p>\n                It's also possible that WebGL is disabled in your browser or has failed to load.  You'll need to use a \n                web browser that <a href=\"http://caniuse.com/#search=webgl\">supports WebGL</a> to use Flood.  \n              </p>\n            </div>\n\n          </div>\n\n        </div>\n\n      </body>\n\n      <script>\n        setTimeout(function(){ \n          document.getElementById(\"title-grey\").style.height = \"10px\";\n        }, 10);\n      </script>\n\n      <script type=\"text/template\" id=\"node-template\">\n\n        <div class=\"node-last-value-container\">\n          <div class=\"node-last-value\"><%- preview %></div>\n          <div class=\"node-failure-message\"><%- failureMessage %></div>\n        </div>\n\n        <ul class=\"node-inputs\">\n\n          <% _.each(type.inputs, function(ele, index) { %> \n            <li class=\"node-port node-port-input\" data-index=\" <%= index %> \"> \n              <span class=\"node-port-name\"><%= ele.name %></span>\n            </li>\n          <% }); %>\n        </ul>\n\n        <ul class=\"node-inputs-extra\">\n          <% _.each(type.inputs, function(ele, index) { %> \n            <li class=\"node-port-extra\" data-index=\" <%= index %> \"> \n              \n              <div class=\"dropdown\">\n\n                <a data-toggle=\"dropdown\" href=\"#\">&#8942;</a>\n\n                <ul class=\"dropdown-menu node-dropdown-menu\" role=\"menu\" aria-labelledby=\"dLabel\">\n\n                  <% if (ele.typeName) { %>\n                    <li class=\"dropdown-header\">Type</li>\n                    <span class=\"node-dropown-menu-item\"><%= ele.typeName %></span>\n                  <% } %>\n\n                  <li role=\"presentation\" style=\"color: black\">\n                    <li class=\"dropdown-header\" style=\"padding: 0\">Use Default</li>\n                    \n                    <span class=\"node-dropown-menu-item\"> \n                      <input type=\"checkbox\" class=\"use-default-checkbox\" data-index=\"<%= index %>\" <%= !ignoreDefaults[index] ? \"checked\" : \"\"%> >\n                      <%= ele.defaultVal != undefined ? JSON.stringify( ele.defaultVal ) : \"None\" %>\n                    </span>\n                  </li>\n\n                </ul>\n              </div>\n                    \n            </li>\n          <% }); %>\n        </ul>\n\n        <div class=\"node-data-container\" >\n          <span class=\"name\">\n            <% if ( !name || name === \"DefaultNodeName\" || name === \"\") { %>\n              <%= typeName != \"CustomNode\" ? typeName : type.functionName  %>\n            <% } else { %>\n              <%= name %>\n            <% } %>\n          </span>\n        </div>\n\n        <ul class=\"node-outputs\" >\n          <% _.each(type.outputs, function(ele, index) { %> \n            <li class=\"node-port node-port-output\" data-index=\" <%= index %> \"> <span class=\"node-port-name\"> <%= ele.name %> </span> </li> \n          <% }); %>\n        </ul>\n\n        <div class=\"dropdown node-settings\" style=\"position:absolute\">\n\n          <a data-toggle=\"dropdown\" href=\"#\">\n            <span style=\"color:black; padding: 1px\">...</span>\n          </a>\n\n          <ul class=\"dropdown-menu node-dropdown-menu\" role=\"menu\" aria-labelledby=\"dLabel\">\n\n            <li class=\"dropdown-header\" style=\"font-size: 10px; padding: 0\" >Visibility</li>\n\n            <li class=\"toggle-vis node-dropown-menu-item\" style=\"display:block\">\n              <i class=\"fa fa-fw fa-eye\"></i><span style=\"padding-left: 5px\">Hide geometry</span>\n            </li>\n\n            <li class=\"dropdown-header\">Replication</li>\n\n            <li class=\"node-dropown-menu-item\">\n              <div class=\"btn-group btn-group-xs\" style=\"padding: 0px; padding-top: 5px; font-size: 10px\">\n                <button type=\"button\" class=\"rep-type btn btn-default\"  style=\"font-size: 10px\" data-rep-type=\"applyLongest\">Long</button>\n                <button type=\"button\" class=\"rep-type btn btn-default\"  style=\"font-size: 10px\" data-rep-type=\"applyCartesian\">Cross</button>\n              </div>\n            </li>\n\n            <li class=\"dropdown-header\">Name</li>\n            <li class=\"node-dropown-menu-item\">\n              <input class=\"name-input\" value=\"<%= name %>\">\n            </li>\n\n          </ul>\n        </div>\n\n      </script>\n\n      <script type=\"text/template\" id=\"node-custom-template\">\n\n          <i class=\"fa fa-fw fa-bolt\"></i>          \n          <span class=\"name searchfield\"><%= type.functionName  %></span>\n\n      </script>\n\n      <script type=\"text/template\" id=\"node-script-template\">\n\t<div class=\"script-add-remove-ports\">\n\t\t<a href=\"#\" class=\"add-input\"> + </a> \n        \t<a href=\"#\" class=\"remove-input\" style=\"padding-left: 10px; padding-right: 10px\"> - </a>\n\t</div>\n        <textarea type=\"text\" class=\"script-text-input\" placeholder=\"Custom formula\"><%= extra.script %></textarea>\n      </script>\n\n      <script type=\"text/template\" id=\"node-input-template\">\n\n        <div class=\"node-data-container node-input-container\">\n          <input type=\"text\" class=\"text-input\" placeholder=\"Input name\" value=\"<%= extra.script %>\">\n        </div>\n\n        <ul class=\"node-outputs\" >\n          <% _.each(type.outputs, function(ele, index) { %> \n            <li class=\"node-port node-port-output\" data-index=\" <%= index %> \"> <span class=\"node-port-name\"> <%= ele.name %> </span> </li> \n          <% }); %>\n        </ul>\n\n      </script>\n\n      <script type=\"text/template\" id=\"node-output-template\">\n\n        <ul class=\"node-inputs\">\n          <% _.each(type.inputs, function(ele, index) { %> \n            <li class=\"node-port node-port-input\" data-index=\" <%= index %> \"> <span class=\"node-port-name\"> <%= ele.name %> </span>  </li> \n          <% }); %>\n        </ul>\n\n        <div class=\"node-data-container node-output-container\">\n          <input type=\"text\" class=\"text-input\" placeholder=\"Output name\" value=\"<%= extra.script %>\">\n        </div>\n\n      </script>\n\n      <script type=\"text/template\" id=\"node-watch-template\">\n\n        <ul class=\"node-inputs\">\n          <% _.each(type.inputs, function(ele, index) { %> \n            <li class=\"node-port node-port-input\" data-index=\" <%= index %> \"> <span class=\"node-port-name\"> <%= ele.name %> </span>  </li> \n          <% }); %>\n        </ul>\n\n        <div class=\"node-data-container watch-data-container\">\n          <span class=\"name searchfield\"><pre><%= prettyValue ? prettyValue : \"Nothing\" %></pre></span>\n        </div>\n\n      </script>\n\n      <script type=\"text/template\" id=\"workspace-tab-template\">\n\n        <i class=\"fa fa-fw fa-pencil dim-button edit-button\" style=\"visibility: hidden; margin-left: 10px\"></i>\n        <span class=\"workspace-tab-function <%= isCustomNode ? \"\" : \"hidden\" %>\">\n          <i class=\"fa fa-bolt\"></i>\n        </span>\n        <input class=\"workspace-name\" disabled=\"disabled\" value=\"<%= name %>\"></input>\n        <i class=\"fa fa-fw fa-times dim-button remove-button\"></i>\n\n      </script>\n\n      <script type=\"text/template\" id=\"node-num-template\">\n\n        <div class=\"node-data-container\">\n\n          <% if (name && name != \"DefaultNodeName\" && name != \"\") { %>\n            <span style=\"margin-right: 10px\" class=\"name\">\n              <%= name %>\n            </span>\n          <% } %>\n\n          <div class=\"slider\" style=\"display: inline-block; width: 120px; height: 8px; margin: 0; padding: 0\"></div>\n\n          <div class=\"num-data-container\" style=\"display: inline-block;\">\n            <input type=\"number\" class=\"currentValue\" style=\"number-node-input\" value=\"<%= type.value %>\" />\n          </div>\n\n        </div>\n\n        <ul class=\"node-outputs\" >\n          <% _.each(type.outputs, function(ele, index) { %> \n            <li class=\"node-port node-port-output\" data-index=\" <%= index %> \"> <span class=\"node-port-name\"> <%= ele.name %> </span> </li> \n          <% }); %>\n        </ul>\n\n         <div class=\"dropdown keep-open node-settings\" style=\"position:absolute\">\n\n          <a href=\"#\" data-toggle=\"dropdown\" href=\"#\">\n            <span style=\"color:black; padding: 1px\">...</span>\n          </a>\n\n          <ul class=\"dropdown-menu node-dropdown-menu\" role=\"menu\" style=\"color: black\" aria-labelledby=\"dLabel\">\n\n            <li class=\"dropdown-header\">Min</li>\n            <li class=\"node-dropown-menu-item\">\n              <input type=\"number\" class=\"num-min\">\n            </li>\n\n            <li class=\"dropdown-header\">Max</li>\n            <li class=\"node-dropown-menu-item\">\n              <input type=\"number\" class=\"num-max\">\n            </li>\n\n            <li class=\"dropdown-header\">Stepsize</li>\n            <li class=\"node-dropown-menu-item\">\n              <input type=\"number\" class=\"num-step\">\n            </li>\n\n            <li class=\"dropdown-header\">Name</li>\n            <li class=\"node-dropown-menu-item\">\n              <input class=\"name-input\" value=\"<%= name %>\">\n            </li>\n            \n            <li class=\"dropdown-header\">\n              Hide in customizer <input type=\"checkbox\" style=\"margin-left: 10px\" <%= extra.lock ? \"checked\" : \"\"%> class=\"lock-input\">\n            </li>\n\n          </ul>\n        </div>\n\n      </script>\n\n      <script type=\"text/template\" id=\"search-template\">\n        <div class=\"search-top-container\">\n          <input placeholder=\"Add a node...\" class=\"library-search-input search\"></input>\n        </div>\n        <ul class=\"list search-list\">\n        </ul>\n      </script>\n\n      <script type=\"text/template\" id=\"workspace-browser-template\">\n\n        <div id=\"workspace-browser-contents\">\n\n          <span class=\"workspace-browser-header row\" id=\"workspace-browser-header-projects\">\n            Projects\n            <i class=\"workspace-browser-header-refresh icon-refresh dim-button workspace-browser-refresh\" ></i>\n          </span>\n          <ul class=\"workspace-browser-element-list row scroll-y\" id=\"workspace-browser-projects\"></ul>\n\n          <span class=\"workspace-browser-header row\" id=\"workspace-browser-header-custom-nodes\">\n            Custom Nodes\n            <i class=\"workspace-browser-header-refresh icon-refresh dim-button workspace-browser-refresh\" ></i>\n          </span>\n          <ul class=\"workspace-browser-element-list row scroll-y\" id=\"workspace-browser-custom-nodes\"></ul>\n\n        </div>\n      </script>\n\n      <script type=\"text/template\" id=\"workspace-browser-element-template\">\n\n        <div style=\"display: inline-block;\" class=\"workspace-browser-element-data\">\n          <%= name %>\n          <br>\n          <span class=\"workspace-browser-element-date\"><%= prettyDate %></span>\n        </div>\n        \n        <div style=\"display: inline-block; visibility: hidden\" class=\"dropdown workspace-browser-element-ellipsis\" >\n\n          <a data-toggle=\"dropdown\" href=\"#\">&#8230;</a>\n\n          <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"dLabel\">\n\n            <li role=\"presentation\" class=\"deleteWorkspace\">\n              <a role=\"menuitem\" tabindex=\"-1\" href=\"#\">\n                Delete...\n              </a>\n            </li>\n\n          </ul>\n        </div>\n\n        <div style=\"float: right; visibility: hidden\" class=\"workspace-browser-element-open\">\n          Open\n        </div>\n      </script>\n\n      <script type=\"text/template\" id=\"workspace-search-template\">\n        \n        <div class=\"workspace-search-container\" id=\"workspace-search-input-container\">\n\n          <ul class=\"list search-list\" style=\"display:none;\">\n          </ul>\n\n          <div class=\"search-bottom-container\">\n\n            <i style=\"display:inline-block;\" class=\"icon-search icon-white dim-button\" ></i>\n            <input placeholder=\"Add a node...\" id=\"bottom-search\" class=\"library-search-input search\"></input>\n\n          </div>\n\n        </div>\n\n        <div class=\"workspace-search-container\">\n\n          <div id=\"undo-button\" class=\"workspace-search-button workspace-search-button-active\">\n\n            <i class=\"fa fa-lg fa-fw dim-button fa-rotate-left white-icon\"></i>\n\n          </div>\n\n          <div id=\"redo-button\" class=\"workspace-search-button workspace-search-button-active\">\n\n             <i class=\"fa fa-lg fa-fw  dim-button fa-repeat white-icon\"></i>\n\n          </div>\n\n        </div>\n\n        <div class=\"workspace-search-container\">\n\n          <div id=\"copy-button\" class=\"workspace-search-button workspace-search-button-active\">\n\n            <i class=\"fa fa-lg fa-fw dim-button fa-copy white-icon\"></i>\n\n          </div>\n\n          <div id=\"paste-button\" class=\"workspace-search-button workspace-search-button-active\">\n\n            <i class=\"fa fa-lg fa-fw dim-button fa-paste white-icon\"></i>\n\n          </div>\n\n          <div id=\"delete-button\" class=\"workspace-search-button workspace-search-button-active\">\n\n            <i class=\"fa fa-lg fa-fw dim-button fa-eraser white-icon\"></i>\n\n          </div>\n\n        </div>\n\n        <div class=\"workspace-search-container\">\n\n          <div id=\"zoomin-button\" class=\"workspace-search-button workspace-search-button-active\">\n              <i class=\"fa fa-lg fa-fw dim-button fa-plus white-icon\"></i>\n          </div>\n\n          <div id=\"zoomout-button\" class=\"workspace-search-button workspace-search-button-active\">\n            <i class=\"fa fa-lg fa-fw dim-button fa-minus white-icon\"></i>\n          </div>\n\n          <div id=\"zoomreset-button\" class=\"workspace-search-button workspace-search-button-active\">\n             <i class=\"fa fa-lg fa-fw dim-button fa-arrows-alt white-icon\"></i>\n          </div>\n\n        </div>\n\n        <div class=\"workspace-search-container\">\n\n          <div id=\"export-button\" class=\"workspace-search-button workspace-search-button-active\">\n            <i class=\"fa fa-lg fa-fw dim-button fa-download white-icon\"></i>\n          </div>\n\n        </div>\n\n      </script>\n\n      <script type=\"text/template\" id=\"workspace-runner-status-template\">\n\n      </script>\n\n      <script type=\"text/template\" id=\"search-element-template\">\n        <span class=\"name\"><%= name %></span>\n      </script>\n\n      <script type=\"text/template\" id=\"connection-template\">\n        M<%-aX%>,<%-aY%> C<%-bX%>,<%-bY%> <%-cX%>,<%-cY%> <%-dX%>,<%-dY%>\n      </script>\n\n      <script type=\"text/template\" id=\"login-template\">\n\n        <div id=\"login-failure-message\">\n        </div>\n\n        <div id=\"tab-button-container\">\n          <a id=\"login-tab-button\" href=\"#\" class=\"btn btn-block btn-flood btn-social\"><i class=\"fa fa-check\"></i>Sign in with Flood</a>\n        </div>\n\n        <form id=\"signup-form\" style=\"display:none\">\n\n          <input type=\"hidden\" name=\"_csrf\">\n\n          <div class=\"form-group\">\n            <label for=\"email\" class=\"control-label\">Email</label>\n            <input type=\"email\" name=\"email\" id=\"email\" placeholder=\"Email\" autofocus class=\"form-control\">\n          </div>\n\n          <div class=\"form-group\">\n            <label for=\"password\" class=\"control-label\">Password</label>\n            <input type=\"password\" name=\"password\" id=\"password\" placeholder=\"Password\" class=\"form-control\">\n          </div>\n\n          <div class=\"form-group\">\n            <label for=\"confirmPassword\" class=\"control-label\">Confirm Password</label>\n            <input type=\"password\" name=\"confirmPassword\" id=\"confirmPassword\" placeholder=\"Confirm Password\" class=\"form-control\">\n          </div>\n\n          <div class=\"form-group\">\n            <button type=\"submit\" class=\"btn btn-success\"><i class=\"fa fa-fw fa-check\"></i>Signup</button>\n          </div>\n\n        </form>\n\n        <form id=\"login-form\" style=\"display:none\">\n\n          <input type=\"hidden\" name=\"_csrf\">\n\n          <div class=\"form-group\">\n            <label for=\"email\" class=\"control-label\">Email</label>\n            <input type=\"email\" name=\"email\" id=\"login-email\" placeholder=\"Email\" autofocus=\"\" class=\"form-control\">\n          </div>\n\n          <div class=\"form-group\">\n            <label for=\"password\" class=\"control-label\">Password</label>\n            <input type=\"password\" name=\"password\" id=\"login-password\" placeholder=\"Password\" class=\"form-control\">\n          </div>\n\n          <div class=\"form-group\">\n            <button type=\"submit\" id=\"submit-login\" class=\"btn btn-primary\"><i class=\"fa fa-fw fa-unlock-alt\"></i>Login</button>\n          </div>\n\n        </form> \n\n        <div id=\"signup-tab-button\" class=\"tab-button\"><a href=\"#\">New account...</a></div>\n\n        <a href=\"/auth/google\" class=\"btn btn-block btn-google-plus btn-social\"><i class=\"fa fa-google-plus\"></i>Sign in with Google</a>\n        <a href=\"/auth/facebook\" class=\"btn btn-block btn-facebook btn-social\"><i class=\"fa fa-facebook\"></i>Sign in with Facebook</a>\n\n      </script>\n\n      <script type=\"text/template\" id=\"share-template\">\n\n        <div id=\"share-box\" class=\"modal-box\">\n\n          <i id=\"exit-share\" class=\"fa fa-fw fa-times dim-button\"></i>\n          <h3 id=\"feedback-title\">\n            <i class=\"fa fa-share fa-2x fa-fw\" style=\"padding-right: 10px\"></i>Share\n          </h3>\n          <p>Share your project as a customizable product website</p>\n\n          <div class=\"inner-box\">\n           <span class=\"label\">Sharing</span> \n           <br>\n            <i class=\"fa fa-fw fa-toggle-off dim-button is-customizer-checkbox\"></i> \n            <span class=\"indicator public\">public</span> <span class=\"indicator private\">private</span>\n          </div>\n\n          <div class=\"inner-box\">\n            <span class=\"label\">Stable URL</span> <a href=\"http://<%= url %>\" target=\"_blank\" style=\"font-style: italic; \">Visit</a>\n            <br>\n            <input type=\"text\" readonly class=\"customizer-url\" placeholder=\"Project Url\" value=\"<%= url %>\">\n          </div>\n\n        </div>\n\n      </script>\n\n      <script type=\"text/template\" id=\"feedback-template\">\n\n        <div id=\"feedback-box\" class=\"modal-box\">\n          <i id=\"exit-feedback\" class=\"fa fa-fw fa-times dim-button\"></i>\n          <h3 id=\"feedback-title\">\n            <i class=\"fa fa-comment fa-2x fa-fw\" style=\"padding-right: 10px\"></i>Send Feedback\n          </h3>\n          <p>Feel free to send comments, suggestions, or issues.</p>\n\n          <div id=\"feedback-failure-message\"></div>\n          <div id=\"feedback-sending-message\">Sending...</div>\n          <div id=\"feedback-success-message\">Sent!</div>\n\n          <form id=\"feedback-form\">\n\n            <input type=\"hidden\" name=\"_csrf\">\n\n            <div class=\"form-group\">\n              <label for=\"subject\" class=\"control-label\">Subject</label>\n              <input type=\"text\" name=\"subject\" id=\"feedback-subject\" placeholder=\"Subject\" autofocus=\"\" class=\"form-control\">\n            </div>\n\n            <div class=\"form-group\">\n              <label for=\"message\" class=\"control-label\">Message</label>\n              <textarea name=\"message\" id=\"feedback-message\" placeholder=\"Message\" autofocus=\"\" class=\"form-control\"></textarea>\n            </div>\n\n            <div class=\"form-group\">\n              <button type=\"submit\" id=\"submit-feedback\" class=\"btn btn-primary\">Submit</button>\n            </div>\n\n          </form>\n        </div>\n        </div>\n\n      </script>\n\n      <script type=\"text/template\" id=\"help-section-template\">\n\n        <div class=\"enter-help-section\" data-target-id=\"<%= targetId %>\" style=\"left: <%= elementPosition[0] %>px; top: <%= elementPosition[1] %>px;\">\n          ?\n        </div>\n        <div class=\"help-section\" data-target-id=\"<%= targetId %>\" style=\"left: <%= elementPosition[0] + offset[0] %>px; top: <%= elementPosition[1] + offset[1]  %>px;\">\n          <span><%= title %> </span>\n          <p><%= text %></p>\n          <div class=\"exit-help-section\" data-target-id=\"<%= targetId %>\">Ok, got it!</div>\n          <div class=\"exit-help\" data-target-id=\"<%= targetId %>\">Exit all</div>\n        </div>\n\n      </script>\n\n\n      <script>\n\n        function checkWebGL() { \n           try{\n            var canvas = document.createElement( 'canvas' ); \n            return !! window.WebGLRenderingContext && ( \n                 canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) );\n           }catch( e ) { return false; } \n         };\n\n        if (!checkWebGL()) {\n          var appfail = document.getElementById(\"app-fail\");\n          appfail.style.display = '';\n        }\n\n      </script>\n\n        <!--[if lt IE 7]>\n            <p class=\"chromeframe\">You are using an <strong>outdated</strong> browser. Please <a href=\"http://browsehappy.com/\">upgrade your browser</a> or <a href=\"http://www.google.com/chromeframe/?redirect=true\">activate Google Chrome Frame</a> to improve your experience.</p>\n        <![endif]-->\n\n    <!-- Application source. -->\n    <!-- build:[src] source.min.js -->\n    <script data-main=\"/scripts/main\" src=\"/bower_components/requirejs/require.js\"></script>\n    <!-- /build -->\n\n    <script>\n\n      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\n      ga('create', 'UA-54947421-1', 'auto');\n      ga('send', 'pageview');\n\n    </script>\n\n</body>\n</html>\n"
  },
  {
    "path": "app/customizer.html",
    "content": "<!doctype html>\n<!--[if lt IE 7]>      <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\"> <![endif]-->\n<!--[if IE 7]>         <html class=\"no-js lt-ie9 lt-ie8\"> <![endif]-->\n<!--[if IE 8]>         <html class=\"no-js lt-ie9\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js\"> <!--<![endif]-->\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n        <title>Customizer - Flood</title>\n        <meta name=\"description\" content=\"\">\n        <meta name=\"viewport\" content=\"user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1\">\n\n        <!-- build:css customizer.min.css -->\n        <link rel=\"stylesheet\" href=\"bower_components/jquery.ui/themes/base/jquery.ui.all.css\">\n        <link rel=\"stylesheet\" href=\"bower_components/components-font-awesome/css/font-awesome.min.css\">\n        <link rel=\"stylesheet\" href=\"styles/customizer.css\">\n        <link rel=\"stylesheet\" href=\"styles/bootstrap.css\">\n        <link rel=\"stylesheet\" href=\"styles/main.css\">\n        <!-- /build -->\n\n        <style>\n\n          body {\n            margin: 0;\n            padding: 0;\n            font-family:Helvetica, Arial, \"Lucida Grande\", sans-serif;\n          }\n\n          #login {\n            background: #e3e3e3;\n            text-align: center;\n            z-index: 120;\n            right: 0;\n            left: 0;\n            top: 0;\n            bottom: 0;\n\n            background-image: -ms-radial-gradient(center, circle closest-corner, #E3E3E3 0%, #C4C4C4 100%);\n            background-image: -moz-radial-gradient(center, circle closest-corner, #E3E3E3 0%, #C4C4C4 100%);\n            background-image: -o-radial-gradient(center, circle closest-corner, #E3E3E3 0%, #C4C4C4 100%);\n            background-image: -webkit-gradient(radial, center center, 0, center center, 497, color-stop(0, #E3E3E3), color-stop(1, #C4C4C4));\n            background-image: -webkit-radial-gradient(center, circle closest-corner, #E3E3E3 0%, #C4C4C4 100%);\n            background-image: radial-gradient(circle closest-corner at center, #E3E3E3 0%, #C4C4C4 100%);\n          }\n\n          .editor-container {\n            letter-spacing: 60px;\n            padding-top: 230px;\n            width: 450px;\n            margin-left: auto;\n            margin-right: auto;\n            font-size: 16px;\n            color: #666;\n            text-shadow: 0 1px white;\n          }\n\n          .editor-container span {\n            margin-left: 45px;\n          }\n\n          #title a {\n            text-decoration: none;\n          }\n\n          .title-box {\n            font-family:Helvetica, Arial, \"Lucida Grande\", sans-serif;\n            padding: 0;\n            margin: 0;\n            font-size: 180px;\n\n            text-shadow: 0 1px white;\n            width: 500px;\n            left: 50%;\n            margin-left: -250px;\n\n            position: absolute;\n            overflow: hidden;\n\n            transition: height 5s;\n            transition-timing-function: ease-out;\n          }\n\n\n          #title-grey {\n            height: 145px;\n            z-index: 122;\n            color: #272822;\n            width: 500px;\n          }\n\n          #title-blue {\n            position: absolute;\n            color: #589cc8;\n            width: 500px;\n          }\n\n          .form-group {padding: 5px;}\n\n          .form-group label { color: #AAA; }\n\n          .login-container {\n            padding-top: 50px;\n            width: 300px;\n            margin-left: auto;\n            margin-right: auto;\n          }\n\n          .login-container h5 {\n            font-size: 18px;\n            color: #666;\n            text-shadow: 0 1px white;\n          }\n\n          #app-fail {\n            position: absolute;\n            top: 0;\n            bottom: 0;\n            left: 0;\n            right: 0;\n            background: white;\n            color: #333;\n            z-index: 125;\n            background: #960018;\n          }\n\n          #app-fail-container {\n            border-radius: 6px;\n            width: 450px;\n            margin-left: auto;\n            margin-right: auto;\n            padding: 20px;\n            background: whitesmoke;\n            margin-top: 50px;\n          }\n    \n          #app-fail-container i {\n            font-size: 150px;\n            color: grey;\n          }\n\n          #app-fail-container h1 {\n            text-align: center;\n          }\n\n          #app-fail-container p {\n            padding-top: 20px;\n            color: grey;\n          }\n\n        </style>\n\n    </head>\n    \n    <body>\n\n        <div id=\"customizer-app\">\n\n          <div id=\"customizer-header\">\n          </div>\n\n          <div id=\"customizer-workspace\">\n            <div id=\"customizer-workspace-header\">\n              <div id=\"hide-workspace\" class=\"dim-button\"><i class=\"fa fa-fw fa-arrow-circle-left\"></i></div>\n            </div>\n          </div>\n\n          <div id=\"customizer-viewer\"></div>\n\n          <div id=\"powered-by\">Powered by <a href=\"http://www.floodeditor.com\">FLOOD</a></div>\n\n          <div id=\"customizer-login\" class=\"row col scroll-y\" style=\"display: none\">\n\n            <div id=\"title-container\">\n              <div class=\"title-box\" id=\"title-grey\">flood</div>\n              <div class=\"title-box\" id=\"title-blue\">flood</div>\n            </div>\n\n            <div class=\"editor-container\"><span>EDITOR</span></div>\n\n            <div class=\"customizer-login-container\">\n              <h5>Wait for it...</h5>\n            </div>\n          </div>\n\n          <div id=\"app-fail\" style=\"display: none\">\n  \n            <div id=\"app-fail-container\">\n              <h1><i class=\"fa fa-fw fa-2x fa-exclamation-triangle\"></i></h1>\n              <h1>Requires WebGL!</h1>\n              <p>\n                It's also possible that WebGL is disabled in your browser or has failed to load.  You'll need to use a \n                web browser that <a href=\"http://caniuse.com/#search=webgl\">supports WebGL</a> to use this app.  \n              </p>\n            </div>\n\n          </div>\n\n        </div>\n\n      </body>\n\n      <script>\n        setTimeout(function(){ \n          document.getElementById(\"title-grey\").style.height = \"10px\";\n        }, 10);\n      </script>\n\n      <script type=\"text/template\" id=\"widget-template\">\n        \n        <span class=\"name\">\n          <% if ( !name || name === \"DefaultNodeName\" || name === \"\") { %>\n            <%= typeName != \"CustomNode\" ? typeName : type.functionName  %>\n          <% } else { %>\n            <%= name %>\n          <% } %>\n        </span>\n\n      </script>\n\n      <script type=\"text/template\" id=\"widget-number-template\">\n\n        <span class=\"name\">\n          <% if ( !name || name === \"DefaultNodeName\" || name === \"\") { %>\n            <%= typeName != \"CustomNode\" ? typeName : type.functionName  %>\n          <% } else { %>\n            <%= name %>\n          <% } %>\n        </span>\n\n        <div class=\"slider\" style=\"display: inline-block; width: 140px; height: 8px; margin: 0; padding: 0\"></div>\n\n        <div class=\"num-data-container\" style=\"display: inline-block;\">\n          <input type=\"number\" class=\"currentValue\" style=\"number-node-input\" value=\"<%= type.value %>\" />\n        </div>\n\n      </script>\n\n      <script type=\"text/template\" id=\"header-template\">\n\n        <div class=\"customize-header-container\">\n          <span class=\"customize-header\" id=\"customize-header-tag\">Custom</span>\n          <span class=\"customize-header\" id=\"customize-header-title\"><%= name %></span>\n        </div>\n\n        <div id=\"customizer-header-controls\" class=\"dropdown\">\n\n          <% if (!isCustomizer) { %> \n            <span class=\"indicator private\">private</span>\n          <% } %>\n\n          <i class=\"fa fa-download fa-fw stl-download dim-button\"></i>\n\n        </div>\n\n        <!--\n\n        <div id=\"customizer-header-controls\" class=\"dropdown\">\n\n          <a href=\"#\" data-toggle=\"dropdown\" href=\"#\">\n            <i class=\"fa fa-download fa-fw\"></i>\n          </a>\n\n          <ul class=\"dropdown-menu\" role=\"menu\" style=\"color: black\" aria-labelledby=\"dLabel\">\n\n            <span class=\"dropdown-header\">Min</span>\n            <input type=\"number\" class=\"num-min\">\n\n            <span class=\"dropdown-header\">Max</span>\n            <input type=\"number\" class=\"num-max\">\n\n          </ul>\n        </div>\n\n        !-->\n\n      </script>\n\n      <script>\n\n        function checkWebGL() { \n           try{\n            var canvas = document.createElement( 'canvas' ); \n            return !! window.WebGLRenderingContext && ( \n                 canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) );\n           }catch( e ) { return false; } \n         };\n\n        if (!checkWebGL()) {\n          var appfail = document.getElementById(\"app-fail\");\n          appfail.style.display = '';\n        }\n\n      </script>\n\n        <!--[if lt IE 7]>\n            <p class=\"chromeframe\">You are using an <strong>outdated</strong> browser. Please <a href=\"http://browsehappy.com/\">upgrade your browser</a> or <a href=\"http://www.google.com/chromeframe/?redirect=true\">activate Google Chrome Frame</a> to improve your experience.</p>\n        <![endif]-->\n\n    <!-- Application source. -->\n    <!-- build:[src] customizer.min.js -->\n    <script data-main=\"/scripts/customizer\" src=\"/bower_components/requirejs/require.js\"></script>\n    <!-- /build -->\n\n    <script>\n\n      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\n      ga('create', 'UA-54947421-1', 'auto');\n      ga('send', 'pageview');\n\n    </script>\n\n</body>\n</html>\n"
  },
  {
    "path": "app/index.html",
    "content": "<!doctype html>\n<!--[if lt IE 7]>      <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\"> <![endif]-->\n<!--[if IE 7]>         <html class=\"no-js lt-ie9 lt-ie8\"> <![endif]-->\n<!--[if IE 8]>         <html class=\"no-js lt-ie9\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js\"> <!--<![endif]-->\n    <head>\n      <meta charset=\"utf-8\">\n      <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n      <title>Welcome - Flood</title>\n      <meta name=\"description\" content=\"\">\n      <meta name=\"viewport\" content=\"user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1\">\n\n      <link rel=\"stylesheet\" href=\"bower_components/components-font-awesome/css/font-awesome.min.css\">\n      <script src=\"bower_components/jquery/jquery.js\"></script>\n\n      <style>\n\n        body {\n          margin: 0;\n          padding: 0;\n          font-family:Helvetica, Arial, \"Lucida Grande\", sans-serif;\n          background: #272822;\n        }\n\n        .row, .col { overflow: hidden; position: absolute; }\n        .row { left: 0; right: 0; }\n        .col { top: 0; bottom: 0; }\n        .scroll-x { overflow-x: auto; }\n        .scroll-y { overflow-y: auto; }\n\n        #title {\n          font-family:Helvetica, Arial, \"Lucida Grande\", sans-serif;\n          background: #e3e3e3;\n          text-align: center;\n          padding: 40px;\n          right: 0;\n          left: 0;\n          top: 0;\n          height: 400px;\n\n          background-image: -ms-radial-gradient(center, circle closest-corner, #E3E3E3 0%, #C4C4C4 100%);\n          background-image: -moz-radial-gradient(center, circle closest-corner, #E3E3E3 0%, #C4C4C4 100%);\n          background-image: -o-radial-gradient(center, circle closest-corner, #E3E3E3 0%, #C4C4C4 100%);\n          background-image: -webkit-gradient(radial, center center, 0, center center, 497, color-stop(0, #E3E3E3), color-stop(1, #C4C4C4));\n          background-image: -webkit-radial-gradient(center, circle closest-corner, #E3E3E3 0%, #C4C4C4 100%);\n          background-image: radial-gradient(circle closest-corner at center, #E3E3E3 0%, #C4C4C4 100%);\n        }\n\n        #title a {\n          text-decoration: none;\n        }\n\n        .title-box { \n          padding: 0;\n          margin: 0;\n          font-size: 180px;\n          text-shadow: 0 1px white;\n          left: 50%;\n          margin-left: -250px;\n\n          position: absolute;\n          overflow: hidden;\n\n          transition: height 15s;\n          transition-timing-function: ease-out;\n        }\n\n        #title-grey {\n          height: 145px;\n          z-index: 122;\n          color: #272822;\n          width: 500px;\n        }\n\n        #title-blue {\n          position: absolute;\n          color: #589cc8;\n          width: 500px;\n        }\n\n        .editor-container {\n          letter-spacing: 60px;\n          padding-top: 200px;\n          width: 450px;\n          margin-left: auto;\n          margin-right: auto;\n          font-size: 16px;\n          color: #666;\n          text-shadow: 0 1px white;\n        }\n\n        .editor-container span {\n          margin-left: 45px;\n        }\n\n        #tagline {\n          background: #272822;\n          padding: 30px;\n          font-size: 24px;\n          text-align: center;\n          right: 0;\n          left: 0;\n          top: 400px;\n          height: 100px;\n          color: #DDD;\n        }\n\n        .link-button {\n          display: inline-block;\n          padding: 20px;\n          color: grey;\n          background: whitesmoke;\n          font-size: 20px;\n          border-radius: 3px;\n          box-shadow: 1px 3px 5px #999;\n        }\n\n        #tryit {\n          width: 150px;\n        }\n\n        #github {\n          font-size: 17px;\n          background: none;\n          color: #BBB;\n          box-shadow: none;\n        }\n\n        #github:hover {\n          color: black;\n        }\n\n        .link-button:hover {\n          color: #111;\n          background: white;\n        }\n\n        #links-container {\n          margin-top: 60px;\n          width: 400px;\n          font-size: 20px;\n          margin-left: auto;\n          margin-right: auto;\n        }\n\n        #links-container span {\n          color: #777;\n          margin: 18px;\n          display: inline-block;\n          font-size: 14px;\n        }\n\n        .example {\n          position: relative;\n          width: 700px;\n          margin-top: 20px;\n          margin-bottom: 20px;\n          margin-left: auto;\n          margin-right: auto;\n          box-shadow: 0px 0px 20px #111;\n        }\n\n        .hidden {\n          display: none;\n        }\n\n        #example-row {\n          font-weight: 300;\n          background: #272822;\n          padding-top: 35px;\n          padding-bottom: 25px;\n          top: 500px;\n          bottom: 60px;\n        }\n\n        #example-nav {\n          text-align: center;\n          width: 700px;\n          margin-left: auto;\n          margin-right: auto;\n        }\n\n        .example-nav-button {\n          display: inline-block;\n          color: white;\n          padding: 25px;\n          font-size: 20px;\n          opacity: 0.3;\n          font-size: 20px;\n          font-weight: 300;\n          text-shadow: 0px 2px 2px #111;\n        }\n\n        .example-nav-button:hover {\n          opacity: 0.9;\n        }\n\n        .selected {\n          opacity:1.0;\n        }\n\n        .example-text {\n          background: black;\n          z-index: 1;\n          color: white;\n          position: absolute;\n          top: 0;\n          right: 0;\n          bottom: 0;\n          width: 300px;\n          color: #DDD;\n          background: #555;\n          font-size: 14px;\n        }\n\n        .example-text-internal {\n          padding: 25px;\n        }\n\n        .example-image {\n          z-index: 0;;\n        }\n\n        .example-text h3 {\n          font-size: 26px;\n          font-weight: 300;\n        }\n        \n        #footer {\n          background: #e3e3e3;\n          color: #333;\n          text-align: right;\n          height: 50px;\n          left: 0;\n          right: 0;\n          bottom: 0;\n          font-size: 14px;\n          position: absolute;\n        }\n  \n        #footer p {\n          display: inline-block;\n          padding-left: 15px;\n          color: grey;\n          padding: 7px;\n        }\n\n        #container {\n          top: 0;\n          left: 0;\n          right: 0;\n          bottom: 50px;\n        }\n\n        #footer a {\n          color: #333;\n          text-decoration: none;\n        }\n\n        #footer a:hover {\n          color: black;\n          text-decoration: underline;\n        }\n\n      </style>\n\n    </head>\n    \n    <body>\n    \n      <div id=\"container\" class=\"row scroll-y\">\n  \n        <div id=\"title\">\n            \n          <div id=\"title-container\">\n            <div class=\"title-box\" id=\"title-grey\">flood</div>\n            <div class=\"title-box\" id=\"title-blue\">flood</div>\n          </div>\n\n          <div class=\"editor-container\"><span>EDITOR</span></div>\n\n          <div id=\"links-container\">\n            <a href=\"https://www.floodeditor.com/app.html\">\n              <div class=\"link-button\" id=\"tryit\">Try the beta!</div>\n            </a>\n            <br>\n            <span>Firefox, Safari, or Chrome with WebGL recommended</span>\n          </div>\n\n        </div>\n\n        <div id=\"example-row\">\n\n          <div id=\"example-nav\">\n            <div class=\"example-nav-button selected\" id=\"example-nav-button-3d\">3D Modeling & Printing</div>\n            <div class=\"example-nav-button\" id=\"example-nav-button-programming\">Visual Programming</div>\n            <div class=\"example-nav-button\" id=\"example-nav-button-cloudbased\">Cloud-Based</div>\n          </div>\n\n          <div id=\"example-3d\" class=\"example\">\n\n            <div class=\"example-text\">\n              <div class=\"example-text-internal\">\n                <h3>Parametric solid modeling for 3D printing</h3>\n                <p>Flood beta is a parametric solid modeler in your browser.  It provides:</p>\n                <ul>\n                  <li>An intuitive, familiar modeling process</li>\n                  <li>Watertight meshes suitable for 3D printing</li>\n                  <li>STL export (accepted by Shapeways)</li>\n                </ul>\n                <p>Further, because Flood is a fully-fledged programming language, you can create your own solid types\n                  and combine them however you want.\n                </p>\n              </div>\n            </div>\n\n            <div class=\"example-image\">\n              <img src=\"images/thumb.csg.png\">\n            </div>\n\n          </div>\n\n          <div id=\"example-programming\" class=\"example hidden\">\n            <div class=\"example-image\">\n              <img src=\"images/thumb.programming.png\">\n            </div>\n            <div class=\"example-text\">\n              <div class=\"example-text-internal\">\n                <h3>Visual programming powered by HTML5</h3>\n                <p>Flood is a fully-fledged, open-source visual programming language.  It includes:</p>\n                <ul>\n                  <li>Custom nodes - Create your own nodes for reuse</li>\n                  <li>Write JavaScript inline in your nodes</li>\n                  <li>Functional programming - Map, filter, reduce</li>\n                </ul>\n                <p>All execution is performed in a background thread in your browser, so Flood is responsive and safe.\n              </div>\n            </div>\n          </div>\n\n          <div id=\"example-cloudbased\" class=\"example hidden\">\n            <div class=\"example-image\">\n              <img src=\"images/cloudbased.png\">\n            </div>\n            <div class=\"example-text\">\n              <div class=\"example-text-internal\">\n                <h3>No need to save</h3>\n                <p>\n                  Like most familiar cloud-based applications, you never have to save in Flood.  Your work is\n                  automatically synced, and everytime you open the application you come right back \n                  to the state you were in before.  \n                </p>\n\n                <ul>\n                  <li>Continuous autosave</li>\n                  <li>Undo-redo</li>\n                  <li>Come back to your previous session with zero effort</li>\n                </ul>\n                <p>\n                  So feel free to come back to your work wherever \n                  and whenever you want!\n                </p>\n              </div>\n            </div>\n          </div>\n\n        </div>\n\n      </div>\n\n      <div id=\"footer\" class=\"row\">\n        <p style=\"\">\n          © 2014 Peter Boyer. Code licensed under the <a href=\"http://footer.org/licenses/MIT\">MIT License.</a>\n        </p>\n        <p>\n          <a href=\"http://www.github.com/pboyer/flood\"><i class=\"fa fa-github-square\"></i> Check it out on Github</a>\n        </p>\n        <p>\n          <a href=\"http://www.twitter.com/ptrbyr\"><i class=\"fa fa-twitter\"></i> Follow me on Twitter</a>\n        </p>\n      </div>\n      \n    </body>\n\n    <script>\n      // start the title animation\n      setTimeout(function(){ \n        document.getElementById(\"title-grey\").style.height = \"10px\";\n      }, 10);\n\n      $('.example-nav-button').click(function(x){\n        \n        $('.example-nav-button').removeClass('selected');\n        $(\"#\" + x.target.id).addClass('selected');\n\n        $('.example').addClass('hidden');\n        $('#example-' + x.target.id.substring(19)).removeClass('hidden');\n        \n      });\n\n    </script>\n\n    <!--[if lt IE 7]>\n        <p class=\"chromeframe\">You are using an <strong>outdated</strong> browser. Please <a href=\"http://browsehappy.com/\">upgrade your browser</a> or <a href=\"http://www.google.com/chromeframe/?redirect=true\">activate Google Chrome Frame</a> to improve your experience.</p>\n    <![endif]-->\n\n    <script>\n      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\n      ga('create', 'UA-54947421-1', 'auto');\n      ga('send', 'pageview');\n\n    </script>\n\n</body>\n</html>\n"
  },
  {
    "path": "app/package.json",
    "content": "{\n  \"name\": \"flood\",\n  \"version\": \"0.0.4\",\n  \"description\": \"A visual programming language for JavaScript, based on Scheme\",\n  \"main\": \"index.html\",\n  \"window\": {\n    \"toolbar\": false,\n    \"frame\": true,\n    \"width\": 1280,\n    \"height\": 960\n  }\n}\n"
  },
  {
    "path": "app/robots.txt",
    "content": "# robotstxt.org\n\nUser-agent: *\n"
  },
  {
    "path": "app/scripts/collections/Connections.js",
    "content": "define(['backbone', 'Connection'], function(Backbone, Connection) {\n\n\treturn Backbone.Collection.extend({\n\n\t\tmodel: Connection\n\n\t});\n\n});"
  },
  {
    "path": "app/scripts/collections/Nodes.js",
    "content": "define(['backbone', 'Node'], function(Backbone, Node) {\n\n\treturn Backbone.Collection.extend({\n\n\t\tmodel: Node,\n\n\t\tinitialDragPositions: [],\n\n\t\ttoJSON: function(){\n\n\t\t\treturn this.models.map(function(x){\n\t\t\t\treturn x.serialize();\n\t\t\t});\n\n\t\t},\n\n\t\tselectAll: function() {\n\t\t\tthis.where({selected: false}).forEach( function(e){ e.set({selected: true}) } );\n\t\t},\n\t\t\n\t\tdeselectAll: function() {\n\t\t\tthis.where({selected: true}).forEach( function(e){ \n\t\t\t\t\te.set('selected', false);\n\t\t\t\t});\n\t\t},\n\n\t\tmoveSelected: function(offset, masterEle) {\n\t\t\tvar that = this;\n\t\t\tvar count = 0;\n\t\t\tthis.where({selected: true}).forEach( function(e, i){ \n\t\t\t\t\tif (e === masterEle) return;\n\t\t\t\t\tvar initialPos = that.initialDragPositions[count++];\n\t\t\t\t\te.set('position', [initialPos[0] + offset[0], initialPos[1] + offset[1]]);\n\t\t\t\t});\n\t\t},\n\n\t\tstartDragging: function(masterEle){\n\t\t\tthis.initialDragPositions = [];\n\t\t\tvar that = this;\n\t\t\tthis.where({selected: true}).forEach( function(e){ \n\t\t\t\t\tif (e === masterEle) return;\n\t\t\t\t\tthat.initialDragPositions.push(e.get('position'));\n\t\t\t\t});\n\t\t}\n\n\t});\n\n});\n\n"
  },
  {
    "path": "app/scripts/collections/SearchElements.js",
    "content": "define(['backbone', 'SearchElement', 'FLOOD'], function(Backbone, SearchElement, FLOOD) {\n\n\treturn Backbone.Collection.extend({\n\n\t\tmodel: SearchElement,\n\n\t\tinitialize: function(atts) {\n\t\t\tthis.app = atts.app;\n\t\t},\n\n\t\taddCustomNode: function(customNode){\n\n\t\t\tvar match = this.where({ functionId: customNode.functionId });\n\t\t\tif (match) this.remove( match );\n\n\t\t\tthis.add(new SearchElement({name: customNode.functionName, functionName: customNode.functionName, \n\t\t\t\tisCustomNode: true, functionId: customNode.functionId, app: this.app, numInputs: customNode.inputs.length, \n\t\t\t\tnumOutputs: customNode.outputs.length }));\n\n\t\t},\n\n\t\tfetch: function() {\n\n\t\t\tthis.models.length = 0;\n\n\t\t\tfor (var key in FLOOD.nodeTypes){\n\t\t\t\tthis.models.push( new SearchElement({name: key, app: this.app}) );\t\n\t\t\t}\n\n\t\t}\n\n\t});\n});\n\n"
  },
  {
    "path": "app/scripts/collections/WorkspaceBrowserElements.js",
    "content": "define(['backbone', 'WorkspaceBrowserElement'], function(Backbone, WorkspaceBrowserElement) {\n\n\treturn Backbone.Collection.extend({\n\n    url: '/ws',\n\t\tmodel: WorkspaceBrowserElement\n\n\t});\n\n});"
  },
  {
    "path": "app/scripts/collections/Workspaces.js",
    "content": "define(['backbone', 'Workspace'], function(Backbone, Workspace) {\n\n\treturn Backbone.Collection.extend({\n\n\t  model: Workspace\n\n\t});\n\n});\n"
  },
  {
    "path": "app/scripts/config.js",
    "content": "/*global require*/\n'use strict';\n\nrequire.config({\n    shim: {\n        underscore: {\n            exports: '_'\n        },\n        backbone: {\n            deps: [\n                'underscore',\n                'jquery'\n            ],\n            exports: 'Backbone'\n        },\n        List: {\n            deps: [\n                'jquery'\n            ],\n            exports: 'List'\n        },\n        Three: {\n            exports: 'Three'\n        },\n        CSG: {\n            exports: 'CSG'\n        },\n        FLOODCSG: {\n            deps: ['CSG'],\n            exports: 'FLOODCSG'\n        },\n        Viewport: {\n            deps: [\n                'Three',\n                'OrbitControls'\n            ],\n            exports: 'Viewport'\n        },\n        OrbitControls: {\n            deps: [\n                'Three'\n            ],\n            exports: 'OrbitControls'\n        },\n        jqueryuicore: {\n            deps: [\n                'jquery'\n            ],\n            exports: 'jqueryuicore'\n        },\n        jqueryuiwidget: {\n            deps: [\n                'jquery'\n            ],\n            exports: 'jqueryuiwidget'\n        },\n        jqueryuimouse: {\n            deps: [\n                'jquery',\n                'jqueryuiwidget'\n            ],\n            exports: 'jqueryuimouse'\n        },\n        jqueryuitouchpunch: {\n            deps: [\n                'jquery',\n                'jqueryuicore',\n                'jqueryuimouse'\n            ],\n            exports: 'jqueryuitouchpunch'\n        },\n        jqueryuislider: {\n            deps: [\n                'jquery',\n                'jqueryuitouchpunch',\n                'jqueryuimouse',\n                'jqueryuicore',\n                'jqueryuiwidget'\n            ],\n            exports: 'jqueryuislider'\n        },\n        jqueryuidraggable: {\n            deps: [\n                'jquery',\n                'jqueryuitouchpunch',\n                'jqueryuimouse',\n                'jqueryuicore',\n                'jqueryuiwidget'\n            ],\n            exports: 'jqueryuidraggable'\n        },\n        bootstrap: {\n            deps: [\n                'jquery'\n            ],\n            exports: 'bootstrap'\n        },\n        almond: {\n            deps: [\n            ],\n            exports: 'almond'\n        }\n   },\n    packages: [{\n        name: \"codemirror\",\n        location: \"../bower_components/CodeMirror/\",\n        main: \"lib/codemirror\"\n    }],\n    paths: {\n\n        // backbone collections\n        Connections: 'collections/Connections',\n        SearchElements: 'collections/SearchElements',\n        Nodes: 'collections/Nodes',\n        Workspaces: 'collections/Workspaces',\n        WorkspaceBrowserElements: 'collections/WorkspaceBrowserElements',\n\n        // backbone models\n\n            // customizer\n            CustomizerApp: 'models/customizer/CustomizerApp',\n\n            // editor\n            App: 'models/App',\n            Connection: 'models/Connection',\n            Marquee: 'models/Marquee',\n            Node: 'models/Node',\n            Search: 'models/Search',\n            SearchElement: 'models/SearchElement',\n            Workspace: 'models/Workspace',\n            Runner: 'models/Runner',\n            Help: 'models/Help',\n            Feedback: 'models/Feedback',\n            Share: 'models/Share',\n            Login: 'models/Login',\n            GeometryExport: 'models/GeometryExport',\n            WorkspaceBrowserElement: 'models/WorkspaceBrowserElement',\n            WorkspaceBrowser: 'models/WorkspaceBrowser',\n            WorkspaceResolver: 'models/WorkspaceResolver',\n\n        // backbone views\n\n            // customizer\n            BaseWidgetView: 'views/customizer/widgets/Base',\n            GeometryWidgetView: 'views/customizer/widgets/Geometry',\n            NumberWidgetView: 'views/customizer/widgets/Number',\n\n            CustomizerAppView: 'views/customizer/CustomizerAppView',\n            CustomizerHeaderView: 'views/customizer/CustomizerHeaderView',\n            CustomizerViewerView: 'views/customizer/CustomizerViewerView',\n            CustomizerWorkspaceView: 'views/customizer/CustomizerWorkspaceView',\n\n            // editor\n            AppView: 'views/AppView',\n            ConnectionView: 'views/ConnectionView',\n            MarqueeView: 'views/MarqueeView',\n            SearchView: 'views/SearchView',\n            WorkspaceControlsView: 'views/WorkspaceControlsView',\n            SearchElementView: 'views/SearchElementView',\n            WorkspaceView: 'views/WorkspaceView',\n            WorkspaceTabView: 'views/WorkspaceTabView',\n            HelpView: 'views/HelpView',\n            FeedbackView: 'views/FeedbackView',\n            ShareView: 'views/ShareView',\n            LoginView: 'views/LoginView',\n            WorkspaceBrowserElementView: 'views/WorkspaceBrowserElementView',\n            WorkspaceBrowserView: 'views/WorkspaceBrowserView',\n\n        // node backbone views\n        NodeViewTypes: 'views/nodeviews/NodeViews',\n        BaseNodeView: 'views/nodeviews/Base',\n        WatchNodeView: 'views/nodeviews/Watch',\n        NumNodeView: 'views/nodeviews/Num',\n        ScriptView: 'views/nodeviews/Script',\n        InputView: 'views/nodeviews/Input',\n        OutputView: 'views/nodeviews/Output',\n        CustomNodeView: 'views/nodeviews/CustomNode',\n        ThreeCSGNodeView: 'views/nodeviews/ThreeCSG',\n\n        OrbitControls: 'lib/OrbitControls',\n        Viewport: 'lib/Viewport',\n        FLOODCSG: 'lib/flood/flood_csg',\n        FLOOD: 'lib/flood/flood',\n        CSG: 'lib/flood/csg',\n        scheme: 'lib/flood/scheme',\n\n        // bower\n\n        Hammer: '../bower_components/hammerjs/hammer',\n        almond: '../bower_components/almond/almond',\n        bootstrap: '../bower_components/bootstrap/dist/js/bootstrap',\n        List: '../bower_components/listjs/dist/list.min',\n        Three: '../bower_components/threejs/build/three.min',\n        jqueryuitouchpunch: '../bower_components/jqueryui-touch-punch/jquery.ui.touch-punch',\n        jqueryuislider: '../bower_components/jquery.ui/ui/jquery.ui.slider',\n        jqueryuidraggable: '../bower_components/jquery.ui/ui/jquery.ui.draggable',\n        jqueryuicore: '../bower_components/jquery.ui/ui/jquery.ui.core',\n        jqueryuimouse: '../bower_components/jquery.ui/ui/jquery.ui.mouse',\n        jqueryuiwidget: '../bower_components/jquery.ui/ui/jquery.ui.widget',\n        jquery: '../bower_components/jquery/jquery.min',\n        backbone: '../bower_components/backbone-amd/backbone-min',\n        underscore: '../bower_components/underscore-amd/underscore-min',\n        fastclick: '../bower_components/fastclick/lib/fastclick',\n        FileSaver: '../bower_components/FileSaver/FileSaver'\n    }\n\n});\n\n\n\n"
  },
  {
    "path": "app/scripts/customizer.js",
    "content": "require([\"config\"], function() {\n\n  require(['backbone', 'CustomizerApp', 'CustomizerAppView', 'Three', 'FLOODCSG', 'bootstrap' ], function (Backbone, CustomizerApp, CustomizerAppView, THREE) {\n\n    var app = new CustomizerApp();\n\n    app.fetch({\n      error: function(result) {\n        console.error('error');\n        console.error(result);\n      },\n      success: function(){\n      }\n    });\n\n    var appView = new CustomizerAppView({model: app});\n\n  });\n\n});\n\n"
  },
  {
    "path": "app/scripts/lib/OrbitControls.js",
    "content": "/**\n * @author qiao / https://github.com/qiao\n * @author mrdoob / http://mrdoob.com\n * @author alteredq / http://alteredqualia.com/\n * @author WestLangley / http://github.com/WestLangley\n * @author erich666 / http://erichaines.com\n */\n/*global THREE, console */\n\n// This set of controls performs orbiting, dollying (zooming), and panning. It maintains\n// the \"up\" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is\n// supported.\n//\n//    Orbit - left mouse / touch: one finger move\n//    Zoom - middle mouse, or mousewheel / touch: two finger spread or squish\n//    Pan - right mouse, or arrow keys / touch: three finter swipe\n//\n// This is a drop-in replacement for (most) TrackballControls used in examples.\n// That is, include this js file and wherever you see:\n//    \tcontrols = new THREE.TrackballControls( camera );\n//      controls.target.z = 150;\n// Simple substitute \"OrbitControls\" and the control should work as-is.\n\nTHREE.OrbitControls = function ( object, domElement ) {\n\n\tthis.object = object;\n\tthis.domElement = ( domElement !== undefined ) ? domElement : document;\n\n\t// API\n\n\t// Set to false to disable this control\n\tthis.enabled = true;\n\n\t// \"target\" sets the location of focus, where the control orbits around\n\t// and where it pans with respect to.\n\tthis.target = new THREE.Vector3();\n\n\t// center is old, deprecated; use \"target\" instead\n\tthis.center = this.target;\n\n\t// This option actually enables dollying in and out; left as \"zoom\" for\n\t// backwards compatibility\n\tthis.noZoom = false;\n\tthis.zoomSpeed = 1.0;\n\n\t// Limits to how far you can dolly in and out\n\tthis.minDistance = 0;\n\tthis.maxDistance = Infinity;\n\n\t// Set to true to disable this control\n\tthis.noRotate = false;\n\tthis.rotateSpeed = 1.0;\n\n\t// Set to true to disable this control\n\tthis.noPan = false;\n\tthis.keyPanSpeed = 7.0;\t// pixels moved per arrow key push\n\n\t// Set to true to automatically rotate around the target\n\tthis.autoRotate = false;\n\tthis.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60\n\n\t// How far you can orbit vertically, upper and lower limits.\n\t// Range is 0 to Math.PI radians.\n\tthis.minPolarAngle = 0; // radians\n\tthis.maxPolarAngle = Math.PI; // radians\n\n\t// Set to true to disable use of the keys\n\tthis.noKeys = true;\n\n\t// The four arrow keys\n\tthis.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };\n\n\t////////////\n\t// internals\n\n\tvar scope = this;\n\n\tvar EPS = 0.000001;\n\n\tvar rotateStart = new THREE.Vector2();\n\tvar rotateEnd = new THREE.Vector2();\n\tvar rotateDelta = new THREE.Vector2();\n\n\tvar panStart = new THREE.Vector2();\n\tvar panEnd = new THREE.Vector2();\n\tvar panDelta = new THREE.Vector2();\n\tvar panOffset = new THREE.Vector3();\n\n\tvar offset = new THREE.Vector3();\n\n\tvar dollyStart = new THREE.Vector2();\n\tvar dollyEnd = new THREE.Vector2();\n\tvar dollyDelta = new THREE.Vector2();\n\n\tvar phiDelta = 0;\n\tvar thetaDelta = 0;\n\tvar scale = 1;\n\tvar pan = new THREE.Vector3();\n\n\tvar lastPosition = new THREE.Vector3();\n\n\tvar STATE = { NONE : -1, ROTATE : 0, DOLLY : 1, PAN : 2, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5 };\n\n\tvar state = STATE.NONE;\n\n\t// for reset\n\n\tthis.target0 = this.target.clone();\n\tthis.position0 = this.object.position.clone();\n\n\t// so camera.up is the orbit axis\n\n\tvar quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );\n\tvar quatInverse = quat.clone().inverse();\n\n\t// events\n\n\tvar changeEvent = { type: 'change' };\n\tvar startEvent = { type: 'start'};\n\tvar endEvent = { type: 'end'};\n\n\tthis.rotateLeft = function ( angle ) {\n\n\t\tif ( angle === undefined ) {\n\n\t\t\tangle = getAutoRotationAngle();\n\n\t\t}\n\n\t\tthetaDelta -= angle;\n\n\t};\n\n\tthis.rotateUp = function ( angle ) {\n\n\t\tif ( angle === undefined ) {\n\n\t\t\tangle = getAutoRotationAngle();\n\n\t\t}\n\n\t\tphiDelta -= angle;\n\n\t};\n\n\t// pass in distance in world space to move left\n\tthis.panLeft = function ( distance ) {\n\n\t\tvar te = this.object.matrix.elements;\n\n\t\t// get X column of matrix\n\t\tpanOffset.set( te[ 0 ], te[ 1 ], te[ 2 ] );\n\t\tpanOffset.multiplyScalar( - distance );\n\t\t\n\t\tpan.add( panOffset );\n\n\t};\n\n\t// pass in distance in world space to move up\n\tthis.panUp = function ( distance ) {\n\n\t\tvar te = this.object.matrix.elements;\n\n\t\t// get Y column of matrix\n\t\tpanOffset.set( te[ 4 ], te[ 5 ], te[ 6 ] );\n\t\tpanOffset.multiplyScalar( distance );\n\t\t\n\t\tpan.add( panOffset );\n\n\t};\n\t\n\t// pass in x,y of change desired in pixel space,\n\t// right and down are positive\n\tthis.pan = function ( deltaX, deltaY ) {\n\n\t\tvar element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\n\t\tif ( scope.object.fov !== undefined ) {\n\n\t\t\t// perspective\n\t\t\tvar position = scope.object.position;\n\t\t\tvar offset = position.clone().sub( scope.target );\n\t\t\tvar targetDistance = offset.length();\n\n\t\t\t// half of the fov is center to top of screen\n\t\t\ttargetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );\n\n\t\t\t// we actually don't use screenWidth, since perspective camera is fixed to screen height\n\t\t\tscope.panLeft( 2 * deltaX * targetDistance / element.clientHeight );\n\t\t\tscope.panUp( 2 * deltaY * targetDistance / element.clientHeight );\n\n\t\t} else if ( scope.object.top !== undefined ) {\n\n\t\t\t// orthographic\n\t\t\tscope.panLeft( deltaX * (scope.object.right - scope.object.left) / element.clientWidth );\n\t\t\tscope.panUp( deltaY * (scope.object.top - scope.object.bottom) / element.clientHeight );\n\n\t\t} else {\n\n\t\t\t// camera neither orthographic or perspective\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );\n\n\t\t}\n\n\t};\n\n\tthis.dollyIn = function ( dollyScale ) {\n\n\t\tif ( dollyScale === undefined ) {\n\n\t\t\tdollyScale = getZoomScale();\n\n\t\t}\n\n\t\tscale /= dollyScale;\n\n\t};\n\n\tthis.dollyOut = function ( dollyScale ) {\n\n\t\tif ( dollyScale === undefined ) {\n\n\t\t\tdollyScale = getZoomScale();\n\n\t\t}\n\n\t\tscale *= dollyScale;\n\n\t};\n\n\tthis.update = function () {\n\n\t\tvar position = this.object.position;\n\n\t\toffset.copy( position ).sub( this.target );\n\n\t\t// rotate offset to \"y-axis-is-up\" space\n\t\toffset.applyQuaternion( quat );\n\n\t\t// angle from z-axis around y-axis\n\n\t\tvar theta = Math.atan2( offset.x, offset.z );\n\n\t\t// angle from y-axis\n\n\t\tvar phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );\n\n\t\tif ( this.autoRotate ) {\n\n\t\t\tthis.rotateLeft( getAutoRotationAngle() );\n\n\t\t}\n\n\t\ttheta += thetaDelta;\n\t\tphi += phiDelta;\n\n\t\t// restrict phi to be between desired limits\n\t\tphi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );\n\n\t\t// restrict phi to be betwee EPS and PI-EPS\n\t\tphi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );\n\n\t\tvar radius = offset.length() * scale;\n\n\t\t// restrict radius to be between desired limits\n\t\tradius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );\n\t\t\n\t\t// move target to panned location\n\t\tthis.target.add( pan );\n\n\t\toffset.x = radius * Math.sin( phi ) * Math.sin( theta );\n\t\toffset.y = radius * Math.cos( phi );\n\t\toffset.z = radius * Math.sin( phi ) * Math.cos( theta );\n\n\t\t// rotate offset back to \"camera-up-vector-is-up\" space\n\t\toffset.applyQuaternion( quatInverse );\n\n\t\tposition.copy( this.target ).add( offset );\n\n\t\tthis.object.lookAt( this.target );\n\n\t\tthetaDelta = 0;\n\t\tphiDelta = 0;\n\t\tscale = 1;\n\t\tpan.set( 0, 0, 0 );\n\n\t\tif ( lastPosition.distanceToSquared( this.object.position ) > EPS ) {\n\n\t\t\tthis.dispatchEvent( changeEvent );\n\n\t\t\tlastPosition.copy( this.object.position );\n\n\t\t}\n\n\t};\n\n\n\tthis.reset = function () {\n\n\t\tstate = STATE.NONE;\n\n\t\tthis.target.copy( this.target0 );\n\t\tthis.object.position.copy( this.position0 );\n\n\t\tthis.update();\n\n\t};\n\n\tfunction getAutoRotationAngle() {\n\n\t\treturn 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;\n\n\t}\n\n\tfunction getZoomScale() {\n\n\t\treturn Math.pow( 0.95, scope.zoomSpeed );\n\n\t}\n\n\tfunction onMouseDown( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\t\tevent.preventDefault();\n\n\t\tif ( event.button === 0 && !event.ctrlKey ) {\n\t\t\tif ( scope.noRotate === true ) return;\n\n\t\t\tstate = STATE.ROTATE;\n\n\t\t\trotateStart.set( event.clientX, event.clientY );\n\n\t\t} else if ( event.button === 2 ) {\n\t\t\tif ( scope.noZoom === true ) return;\n\n\t\t\tstate = STATE.DOLLY;\n\n\t\t\tdollyStart.set( event.clientX, event.clientY );\n\n\t\t} else if ( event.button === 1 || (event.button === 0 && event.ctrlKey) ) {\n\t\t\tif ( scope.noPan === true ) return;\n\n\t\t\tstate = STATE.PAN;\n\n\t\t\tpanStart.set( event.clientX, event.clientY );\n\n\t\t}\n\n\t\tscope.domElement.addEventListener( 'mousemove', onMouseMove, false );\n\t\tscope.domElement.addEventListener( 'mouseup', onMouseUp, false );\n\t\tscope.dispatchEvent( startEvent );\n\n\t}\n\n\tfunction onMouseMove( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\n\t\tvar element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\n\t\tif ( state === STATE.ROTATE ) {\n\n\t\t\tif ( scope.noRotate === true ) return;\n\n\t\t\trotateEnd.set( event.clientX, event.clientY );\n\t\t\trotateDelta.subVectors( rotateEnd, rotateStart );\n\n\t\t\t// rotating across whole screen goes 360 degrees around\n\t\t\tscope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );\n\n\t\t\t// rotating up and down along whole screen attempts to go 360, but limited to 180\n\t\t\tscope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );\n\n\t\t\trotateStart.copy( rotateEnd );\n\n\t\t} else if ( state === STATE.DOLLY ) {\n\n\t\t\tif ( scope.noZoom === true ) return;\n\n\t\t\tdollyEnd.set( event.clientX, event.clientY );\n\t\t\tdollyDelta.subVectors( dollyEnd, dollyStart );\n\n\t\t\tif ( dollyDelta.y > 0 ) {\n\n\t\t\t\tscope.dollyIn();\n\n\t\t\t} else {\n\n\t\t\t\tscope.dollyOut();\n\n\t\t\t}\n\n\t\t\tdollyStart.copy( dollyEnd );\n\n\t\t} else if ( state === STATE.PAN ) {\n\n\t\t\tif ( scope.noPan === true ) return;\n\n\t\t\tpanEnd.set( event.clientX, event.clientY );\n\t\t\tpanDelta.subVectors( panEnd, panStart );\n\t\t\t\n\t\t\tscope.pan( panDelta.x, panDelta.y );\n\n\t\t\tpanStart.copy( panEnd );\n\n\t\t}\n\n\t\tscope.update();\n\n\t}\n\n\tfunction onMouseUp( /* event */ ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tscope.domElement.removeEventListener( 'mousemove', onMouseMove, false );\n\t\tscope.domElement.removeEventListener( 'mouseup', onMouseUp, false );\n\t\tscope.dispatchEvent( endEvent );\n\t\tstate = STATE.NONE;\n\n\t}\n\n\tfunction onMouseWheel( event ) {\n\n\t\tif ( scope.enabled === false || scope.noZoom === true ) return;\n\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tvar delta = 0;\n\n\t\tif ( event.wheelDelta !== undefined ) { // WebKit / Opera / Explorer 9\n\n\t\t\tdelta = event.wheelDelta;\n\n\t\t} else if ( event.detail !== undefined ) { // Firefox\n\n\t\t\tdelta = - event.detail;\n\n\t\t}\n\n\t\tif ( delta > 0 ) {\n\n\t\t\tscope.dollyOut();\n\n\t\t} else {\n\n\t\t\tscope.dollyIn();\n\n\t\t}\n\n\t\tscope.update();\n\t\tscope.dispatchEvent( startEvent );\n\t\tscope.dispatchEvent( endEvent );\n\n\t}\n\n\tfunction onKeyDown( event ) {\n\n\t\tif ( scope.enabled === false || scope.noKeys === true || scope.noPan === true ) return;\n\t\t\n\t\tswitch ( event.keyCode ) {\n\n\t\t\tcase scope.keys.UP:\n\t\t\t\tscope.pan( 0, scope.keyPanSpeed );\n\t\t\t\tscope.update();\n\t\t\t\tbreak;\n\n\t\t\tcase scope.keys.BOTTOM:\n\t\t\t\tscope.pan( 0, - scope.keyPanSpeed );\n\t\t\t\tscope.update();\n\t\t\t\tbreak;\n\n\t\t\tcase scope.keys.LEFT:\n\t\t\t\tscope.pan( scope.keyPanSpeed, 0 );\n\t\t\t\tscope.update();\n\t\t\t\tbreak;\n\n\t\t\tcase scope.keys.RIGHT:\n\t\t\t\tscope.pan( - scope.keyPanSpeed, 0 );\n\t\t\t\tscope.update();\n\t\t\t\tbreak;\n\n\t\t}\n\n\t}\n\n\tfunction touchstart( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tswitch ( event.touches.length ) {\n\n\t\t\tcase 1:\t// one-fingered touch: rotate\n\n\t\t\t\tif ( scope.noRotate === true ) return;\n\n\t\t\t\tstate = STATE.TOUCH_ROTATE;\n\n\t\t\t\trotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\t\t\t\tbreak;\n\n\t\t\tcase 2:\t// two-fingered touch: dolly\n\n\t\t\t\tif ( scope.noZoom === true ) return;\n\n\t\t\t\tstate = STATE.TOUCH_DOLLY;\n\n\t\t\t\tvar dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\n\t\t\t\tvar dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\n\t\t\t\tvar distance = Math.sqrt( dx * dx + dy * dy );\n\t\t\t\tdollyStart.set( 0, distance );\n\t\t\t\tbreak;\n\n\t\t\tcase 3: // three-fingered touch: pan\n\n\t\t\t\tif ( scope.noPan === true ) return;\n\n\t\t\t\tstate = STATE.TOUCH_PAN;\n\n\t\t\t\tpanStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tstate = STATE.NONE;\n\n\t\t}\n\n\t\tscope.dispatchEvent( startEvent );\n\n\t}\n\n\tfunction touchmove( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tvar element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\n\t\tswitch ( event.touches.length ) {\n\n\t\t\tcase 1: // one-fingered touch: rotate\n\n\t\t\t\tif ( scope.noRotate === true ) return;\n\t\t\t\tif ( state !== STATE.TOUCH_ROTATE ) return;\n\n\t\t\t\trotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\t\t\t\trotateDelta.subVectors( rotateEnd, rotateStart );\n\n\t\t\t\t// rotating across whole screen goes 360 degrees around\n\t\t\t\tscope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );\n\t\t\t\t// rotating up and down along whole screen attempts to go 360, but limited to 180\n\t\t\t\tscope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );\n\n\t\t\t\trotateStart.copy( rotateEnd );\n\n\t\t\t\tscope.update();\n\t\t\t\tbreak;\n\n\t\t\tcase 2: // two-fingered touch: dolly\n\n\t\t\t\tif ( scope.noZoom === true ) return;\n\t\t\t\tif ( state !== STATE.TOUCH_DOLLY ) return;\n\n\t\t\t\tvar dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\n\t\t\t\tvar dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\n\t\t\t\tvar distance = Math.sqrt( dx * dx + dy * dy );\n\n\t\t\t\tdollyEnd.set( 0, distance );\n\t\t\t\tdollyDelta.subVectors( dollyEnd, dollyStart );\n\n\t\t\t\tif ( dollyDelta.y > 0 ) {\n\n\t\t\t\t\tscope.dollyOut();\n\n\t\t\t\t} else {\n\n\t\t\t\t\tscope.dollyIn();\n\n\t\t\t\t}\n\n\t\t\t\tdollyStart.copy( dollyEnd );\n\n\t\t\t\tscope.update();\n\t\t\t\tbreak;\n\n\t\t\tcase 3: // three-fingered touch: pan\n\n\t\t\t\tif ( scope.noPan === true ) return;\n\t\t\t\tif ( state !== STATE.TOUCH_PAN ) return;\n\n\t\t\t\tpanEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\t\t\t\tpanDelta.subVectors( panEnd, panStart );\n\t\t\t\t\n\t\t\t\tscope.pan( panDelta.x, panDelta.y );\n\n\t\t\t\tpanStart.copy( panEnd );\n\n\t\t\t\tscope.update();\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tstate = STATE.NONE;\n\n\t\t}\n\n\t}\n\n\tfunction touchend( /* event */ ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tscope.dispatchEvent( endEvent );\n\t\tstate = STATE.NONE;\n\n\t}\n\n\tthis.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );\n\tthis.domElement.addEventListener( 'mousedown', onMouseDown, false );\n\tthis.domElement.addEventListener( 'mousewheel', onMouseWheel, false );\n\tthis.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox\n\n\tthis.domElement.addEventListener( 'touchstart', touchstart, false );\n\tthis.domElement.addEventListener( 'touchend', touchend, false );\n\tthis.domElement.addEventListener( 'touchmove', touchmove, false );\n\n\twindow.addEventListener( 'keydown', onKeyDown, false );\n\n\t// force an update at start\n\tthis.update();\n\n};\n\nTHREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );\n\n\n"
  },
  {
    "path": "app/scripts/lib/Viewport.js",
    "content": "var container, $container;\n\nvar camera, controls, scene, renderer;\n\nvar geometry, group;\n\nvar mouse = new THREE.Vector2(),\noffset = new THREE.Vector3(),\nINTERSECTED, SELECTED;\n\nvar objects = [], plane;\n\nvar mouseX = 0, mouseY = 0;\n\nvar windowHalfX = window.innerWidth / 2;\nvar windowHalfY = window.innerHeight / 2;\n\ninit();\nrender();\n\nfunction init() {\n\n\tcontainer = document.getElementById(\"viewer\");\n\t$container = $(container);\n\n\tcamera = new THREE.PerspectiveCamera( 30, $container.width() / $container.height(), 1, 10000 );\n\n\tcamera.position.set( 140, 140, 140 );\n\tcamera.up.set( 0, 0, 1 );\n\tcamera.lookAt( new THREE.Vector3(0,0,0) );\n\n\tscene = new THREE.Scene();\n\n\trenderer = new THREE.WebGLRenderer({antialias: true});\n\trenderer.setClearColor( 0xffffff, 1 );\n\trenderer.setSize( $container.width(), $container.height() );\n\trenderer.sortObjects = false;\n\n\tcontainer.appendChild( renderer.domElement );\n\trenderer.domElement.setAttribute(\"id\", \"renderer_canvas\");\n\n\t// add subtle ambient lighting\n\tvar ambientLight = new THREE.AmbientLight(0x555555);\n\tscene.add(ambientLight);\n\n\t// add directional light source\n\tvar directionalLight = new THREE.DirectionalLight(0xbbbbbb);\n\tdirectionalLight.position.set(50, 30, 50);\n\tscene.add(directionalLight);\n\n\tvar directionalLight = new THREE.DirectionalLight(0xaaaaaa);\n\tdirectionalLight.position.set(-0.2, -0.8, 1).normalize();\n\tscene.add(directionalLight);\n\n\tmakeGrid();\n\n\tcontrols = new THREE.OrbitControls(camera, container);\n\n\twindow.addEventListener( 'resize', onWindowResize, false );\n\n\t// full screen blur\n\t// composer = new THREE.EffectComposer( renderer );\n\t// composer.addPass( new THREE.RenderPass( scene, camera ) );\n\n\t// hblur = new THREE.ShaderPass( THREE.HorizontalBlurShader );\n\t// composer.addPass( hblur );\n\n\t// vblur = new THREE.ShaderPass( THREE.VerticalBlurShader );\n\t// // set this shader pass to render to screen so we can see the effects\n\t// vblur.renderToScreen = true;\n\t// composer.addPass( vblur );\n\n\n\tanimate();\n\n}\n\nfunction makeGrid(){\n\n\tvar l = 60;\n\n\tvar axisHelper = new THREE.AxisHelper( l );\n\tscene.add( axisHelper );\n\n\tvar geometry = new THREE.Geometry();\n\tvar geometryThick = new THREE.Geometry();\n\n\tvar n = l;\n\tvar inc = 2 * l / n;\n\tvar rate = 10;\n\n\tfor (var i = 0; i < n + 1; i++){\n\n    \tvar v1 = new THREE.Vector3(-l, -l + i * inc, 0);\n\t\tvar v2 = new THREE.Vector3(l, -l + i * inc, 0);\n\n    \tgeometry.vertices.push(v1);\n    \tgeometry.vertices.push(v2);\n\n    \tif (i % rate == 0){\n\t\t\tgeometryThick.vertices.push(v1);\n    \t\tgeometryThick.vertices.push(v2);\n    \t}\n\t}\n\n\tfor (var i = 0; i < n + 1; i++){\n\t\tvar v1 = new THREE.Vector3(-l + i * inc, l, 0);\n\t\tvar v2 = new THREE.Vector3(-l + i * inc, -l, 0);\n\n\t\tgeometry.vertices.push(v1);\n    \tgeometry.vertices.push(v2);\n\n    \tif (i % rate == 0){\n\t\t\tgeometryThick.vertices.push(v1);\n    \t\tgeometryThick.vertices.push(v2);\n    \t}\n\t}\n\n\tvar material = new THREE.LineBasicMaterial({\n        color: 0xeeeeee,\n        linewidth: 0.1\n    });\n\n    var materialThick = new THREE.LineBasicMaterial({\n        color: 0xeeeeee,\n        linewidth: 2\n    });\n\n    var line = new THREE.Line(geometry, material, THREE.LinePieces);\n    var lineThick = new THREE.Line(geometryThick, materialThick, THREE.LinePieces);\n\n    scene.add(line);\n    scene.add(lineThick);\n\n}\n\nfunction onWindowResize() {\n\n\twindowHalfX = $container.width() / 2;\n\twindowHalfY = $container.height() / 2;\n\n\tcamera.aspect = windowHalfX/ windowHalfY;\n\tcamera.updateProjectionMatrix();\n\n\trenderer.setSize( 2*windowHalfX, 2*windowHalfY );\n\n\trender();\n\n}\n\nfunction animate() {\n\n\trequestAnimationFrame( animate );\n\trender();\n\n}\n\nvar doBlur = true;\n\nfunction render() {\n\n\tcontrols.update();\n\trenderer.render( scene, camera );\n\t\n\tif (doBlur){\n\t\t// composer.render();\n\t}\n\n}\n\n\n"
  },
  {
    "path": "app/scripts/lib/flood/async.js",
    "content": "/*!\n * async\n * https://github.com/caolan/async\n *\n * Copyright 2010-2014 Caolan McMahon\n * Released under the MIT license\n */\n/*jshint onevar: false, indent:4 */\n/*global setImmediate: false, setTimeout: false, console: false */\n(function () {\n\n    var async = {};\n\n    // global on the server, window in the browser\n    var root, previous_async;\n\n    root = this;\n    if (root != null) {\n      previous_async = root.async;\n    }\n\n    async.noConflict = function () {\n        root.async = previous_async;\n        return async;\n    };\n\n    function only_once(fn) {\n        var called = false;\n        return function() {\n            if (called) throw new Error(\"Callback was already called.\");\n            called = true;\n            fn.apply(root, arguments);\n        }\n    }\n\n    //// cross-browser compatiblity functions ////\n\n    var _toString = Object.prototype.toString;\n\n    var _isArray = Array.isArray || function (obj) {\n        return _toString.call(obj) === '[object Array]';\n    };\n\n    var _each = function (arr, iterator) {\n        if (arr.forEach) {\n            return arr.forEach(iterator);\n        }\n        for (var i = 0; i < arr.length; i += 1) {\n            iterator(arr[i], i, arr);\n        }\n    };\n\n    var _map = function (arr, iterator) {\n        if (arr.map) {\n            return arr.map(iterator);\n        }\n        var results = [];\n        _each(arr, function (x, i, a) {\n            results.push(iterator(x, i, a));\n        });\n        return results;\n    };\n\n    var _reduce = function (arr, iterator, memo) {\n        if (arr.reduce) {\n            return arr.reduce(iterator, memo);\n        }\n        _each(arr, function (x, i, a) {\n            memo = iterator(memo, x, i, a);\n        });\n        return memo;\n    };\n\n    var _keys = function (obj) {\n        if (Object.keys) {\n            return Object.keys(obj);\n        }\n        var keys = [];\n        for (var k in obj) {\n            if (obj.hasOwnProperty(k)) {\n                keys.push(k);\n            }\n        }\n        return keys;\n    };\n\n    //// exported async module functions ////\n\n    //// nextTick implementation with browser-compatible fallback ////\n    if (typeof process === 'undefined' || !(process.nextTick)) {\n        if (typeof setImmediate === 'function') {\n            async.nextTick = function (fn) {\n                // not a direct alias for IE10 compatibility\n                setImmediate(fn);\n            };\n            async.setImmediate = async.nextTick;\n        }\n        else {\n            async.nextTick = function (fn) {\n                setTimeout(fn, 0);\n            };\n            async.setImmediate = async.nextTick;\n        }\n    }\n    else {\n        async.nextTick = process.nextTick;\n        if (typeof setImmediate !== 'undefined') {\n            async.setImmediate = function (fn) {\n              // not a direct alias for IE10 compatibility\n              setImmediate(fn);\n            };\n        }\n        else {\n            async.setImmediate = async.nextTick;\n        }\n    }\n\n    async.each = function (arr, iterator, callback) {\n        callback = callback || function () {};\n        if (!arr.length) {\n            return callback();\n        }\n        var completed = 0;\n        _each(arr, function (x) {\n            iterator(x, only_once(done) );\n        });\n        function done(err) {\n          if (err) {\n              callback(err);\n              callback = function () {};\n          }\n          else {\n              completed += 1;\n              if (completed >= arr.length) {\n                  callback();\n              }\n          }\n        }\n    };\n    async.forEach = async.each;\n\n    async.eachSeries = function (arr, iterator, callback) {\n        callback = callback || function () {};\n        if (!arr.length) {\n            return callback();\n        }\n        var completed = 0;\n        var iterate = function () {\n            iterator(arr[completed], function (err) {\n                if (err) {\n                    callback(err);\n                    callback = function () {};\n                }\n                else {\n                    completed += 1;\n                    if (completed >= arr.length) {\n                        callback();\n                    }\n                    else {\n                        iterate();\n                    }\n                }\n            });\n        };\n        iterate();\n    };\n    async.forEachSeries = async.eachSeries;\n\n    async.eachLimit = function (arr, limit, iterator, callback) {\n        var fn = _eachLimit(limit);\n        fn.apply(null, [arr, iterator, callback]);\n    };\n    async.forEachLimit = async.eachLimit;\n\n    var _eachLimit = function (limit) {\n\n        return function (arr, iterator, callback) {\n            callback = callback || function () {};\n            if (!arr.length || limit <= 0) {\n                return callback();\n            }\n            var completed = 0;\n            var started = 0;\n            var running = 0;\n\n            (function replenish () {\n                if (completed >= arr.length) {\n                    return callback();\n                }\n\n                while (running < limit && started < arr.length) {\n                    started += 1;\n                    running += 1;\n                    iterator(arr[started - 1], function (err) {\n                        if (err) {\n                            callback(err);\n                            callback = function () {};\n                        }\n                        else {\n                            completed += 1;\n                            running -= 1;\n                            if (completed >= arr.length) {\n                                callback();\n                            }\n                            else {\n                                replenish();\n                            }\n                        }\n                    });\n                }\n            })();\n        };\n    };\n\n\n    var doParallel = function (fn) {\n        return function () {\n            var args = Array.prototype.slice.call(arguments);\n            return fn.apply(null, [async.each].concat(args));\n        };\n    };\n    var doParallelLimit = function(limit, fn) {\n        return function () {\n            var args = Array.prototype.slice.call(arguments);\n            return fn.apply(null, [_eachLimit(limit)].concat(args));\n        };\n    };\n    var doSeries = function (fn) {\n        return function () {\n            var args = Array.prototype.slice.call(arguments);\n            return fn.apply(null, [async.eachSeries].concat(args));\n        };\n    };\n\n\n    var _asyncMap = function (eachfn, arr, iterator, callback) {\n        arr = _map(arr, function (x, i) {\n            return {index: i, value: x};\n        });\n        if (!callback) {\n            eachfn(arr, function (x, callback) {\n                iterator(x.value, function (err) {\n                    callback(err);\n                });\n            });\n        } else {\n            var results = [];\n            eachfn(arr, function (x, callback) {\n                iterator(x.value, function (err, v) {\n                    results[x.index] = v;\n                    callback(err);\n                });\n            }, function (err) {\n                callback(err, results);\n            });\n        }\n    };\n    async.map = doParallel(_asyncMap);\n    async.mapSeries = doSeries(_asyncMap);\n    async.mapLimit = function (arr, limit, iterator, callback) {\n        return _mapLimit(limit)(arr, iterator, callback);\n    };\n\n    var _mapLimit = function(limit) {\n        return doParallelLimit(limit, _asyncMap);\n    };\n\n    // reduce only has a series version, as doing reduce in parallel won't\n    // work in many situations.\n    async.reduce = function (arr, memo, iterator, callback) {\n        async.eachSeries(arr, function (x, callback) {\n            iterator(memo, x, function (err, v) {\n                memo = v;\n                callback(err);\n            });\n        }, function (err) {\n            callback(err, memo);\n        });\n    };\n    // inject alias\n    async.inject = async.reduce;\n    // foldl alias\n    async.foldl = async.reduce;\n\n    async.reduceRight = function (arr, memo, iterator, callback) {\n        var reversed = _map(arr, function (x) {\n            return x;\n        }).reverse();\n        async.reduce(reversed, memo, iterator, callback);\n    };\n    // foldr alias\n    async.foldr = async.reduceRight;\n\n    var _filter = function (eachfn, arr, iterator, callback) {\n        var results = [];\n        arr = _map(arr, function (x, i) {\n            return {index: i, value: x};\n        });\n        eachfn(arr, function (x, callback) {\n            iterator(x.value, function (v) {\n                if (v) {\n                    results.push(x);\n                }\n                callback();\n            });\n        }, function (err) {\n            callback(_map(results.sort(function (a, b) {\n                return a.index - b.index;\n            }), function (x) {\n                return x.value;\n            }));\n        });\n    };\n    async.filter = doParallel(_filter);\n    async.filterSeries = doSeries(_filter);\n    // select alias\n    async.select = async.filter;\n    async.selectSeries = async.filterSeries;\n\n    var _reject = function (eachfn, arr, iterator, callback) {\n        var results = [];\n        arr = _map(arr, function (x, i) {\n            return {index: i, value: x};\n        });\n        eachfn(arr, function (x, callback) {\n            iterator(x.value, function (v) {\n                if (!v) {\n                    results.push(x);\n                }\n                callback();\n            });\n        }, function (err) {\n            callback(_map(results.sort(function (a, b) {\n                return a.index - b.index;\n            }), function (x) {\n                return x.value;\n            }));\n        });\n    };\n    async.reject = doParallel(_reject);\n    async.rejectSeries = doSeries(_reject);\n\n    var _detect = function (eachfn, arr, iterator, main_callback) {\n        eachfn(arr, function (x, callback) {\n            iterator(x, function (result) {\n                if (result) {\n                    main_callback(x);\n                    main_callback = function () {};\n                }\n                else {\n                    callback();\n                }\n            });\n        }, function (err) {\n            main_callback();\n        });\n    };\n    async.detect = doParallel(_detect);\n    async.detectSeries = doSeries(_detect);\n\n    async.some = function (arr, iterator, main_callback) {\n        async.each(arr, function (x, callback) {\n            iterator(x, function (v) {\n                if (v) {\n                    main_callback(true);\n                    main_callback = function () {};\n                }\n                callback();\n            });\n        }, function (err) {\n            main_callback(false);\n        });\n    };\n    // any alias\n    async.any = async.some;\n\n    async.every = function (arr, iterator, main_callback) {\n        async.each(arr, function (x, callback) {\n            iterator(x, function (v) {\n                if (!v) {\n                    main_callback(false);\n                    main_callback = function () {};\n                }\n                callback();\n            });\n        }, function (err) {\n            main_callback(true);\n        });\n    };\n    // all alias\n    async.all = async.every;\n\n    async.sortBy = function (arr, iterator, callback) {\n        async.map(arr, function (x, callback) {\n            iterator(x, function (err, criteria) {\n                if (err) {\n                    callback(err);\n                }\n                else {\n                    callback(null, {value: x, criteria: criteria});\n                }\n            });\n        }, function (err, results) {\n            if (err) {\n                return callback(err);\n            }\n            else {\n                var fn = function (left, right) {\n                    var a = left.criteria, b = right.criteria;\n                    return a < b ? -1 : a > b ? 1 : 0;\n                };\n                callback(null, _map(results.sort(fn), function (x) {\n                    return x.value;\n                }));\n            }\n        });\n    };\n\n    async.auto = function (tasks, callback) {\n        callback = callback || function () {};\n        var keys = _keys(tasks);\n        var remainingTasks = keys.length\n        if (!remainingTasks) {\n            return callback();\n        }\n\n        var results = {};\n\n        var listeners = [];\n        var addListener = function (fn) {\n            listeners.unshift(fn);\n        };\n        var removeListener = function (fn) {\n            for (var i = 0; i < listeners.length; i += 1) {\n                if (listeners[i] === fn) {\n                    listeners.splice(i, 1);\n                    return;\n                }\n            }\n        };\n        var taskComplete = function () {\n            remainingTasks--\n            _each(listeners.slice(0), function (fn) {\n                fn();\n            });\n        };\n\n        addListener(function () {\n            if (!remainingTasks) {\n                var theCallback = callback;\n                // prevent final callback from calling itself if it errors\n                callback = function () {};\n\n                theCallback(null, results);\n            }\n        });\n\n        _each(keys, function (k) {\n            var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];\n            var taskCallback = function (err) {\n                var args = Array.prototype.slice.call(arguments, 1);\n                if (args.length <= 1) {\n                    args = args[0];\n                }\n                if (err) {\n                    var safeResults = {};\n                    _each(_keys(results), function(rkey) {\n                        safeResults[rkey] = results[rkey];\n                    });\n                    safeResults[k] = args;\n                    callback(err, safeResults);\n                    // stop subsequent errors hitting callback multiple times\n                    callback = function () {};\n                }\n                else {\n                    results[k] = args;\n                    async.setImmediate(taskComplete);\n                }\n            };\n            var requires = task.slice(0, Math.abs(task.length - 1)) || [];\n            var ready = function () {\n                return _reduce(requires, function (a, x) {\n                    return (a && results.hasOwnProperty(x));\n                }, true) && !results.hasOwnProperty(k);\n            };\n            if (ready()) {\n                task[task.length - 1](taskCallback, results);\n            }\n            else {\n                var listener = function () {\n                    if (ready()) {\n                        removeListener(listener);\n                        task[task.length - 1](taskCallback, results);\n                    }\n                };\n                addListener(listener);\n            }\n        });\n    };\n\n    async.retry = function(times, task, callback) {\n        var DEFAULT_TIMES = 5;\n        var attempts = [];\n        // Use defaults if times not passed\n        if (typeof times === 'function') {\n            callback = task;\n            task = times;\n            times = DEFAULT_TIMES;\n        }\n        // Make sure times is a number\n        times = parseInt(times, 10) || DEFAULT_TIMES;\n        var wrappedTask = function(wrappedCallback, wrappedResults) {\n            var retryAttempt = function(task, finalAttempt) {\n                return function(seriesCallback) {\n                    task(function(err, result){\n                        seriesCallback(!err || finalAttempt, {err: err, result: result});\n                    }, wrappedResults);\n                };\n            };\n            while (times) {\n                attempts.push(retryAttempt(task, !(times-=1)));\n            }\n            async.series(attempts, function(done, data){\n                data = data[data.length - 1];\n                (wrappedCallback || callback)(data.err, data.result);\n            });\n        }\n        // If a callback is passed, run this as a controll flow\n        return callback ? wrappedTask() : wrappedTask\n    };\n\n    async.waterfall = function (tasks, callback) {\n        callback = callback || function () {};\n        if (!_isArray(tasks)) {\n          var err = new Error('First argument to waterfall must be an array of functions');\n          return callback(err);\n        }\n        if (!tasks.length) {\n            return callback();\n        }\n        var wrapIterator = function (iterator) {\n            return function (err) {\n                if (err) {\n                    callback.apply(null, arguments);\n                    callback = function () {};\n                }\n                else {\n                    var args = Array.prototype.slice.call(arguments, 1);\n                    var next = iterator.next();\n                    if (next) {\n                        args.push(wrapIterator(next));\n                    }\n                    else {\n                        args.push(callback);\n                    }\n                    async.setImmediate(function () {\n                        iterator.apply(null, args);\n                    });\n                }\n            };\n        };\n        wrapIterator(async.iterator(tasks))();\n    };\n\n    var _parallel = function(eachfn, tasks, callback) {\n        callback = callback || function () {};\n        if (_isArray(tasks)) {\n            eachfn.map(tasks, function (fn, callback) {\n                if (fn) {\n                    fn(function (err) {\n                        var args = Array.prototype.slice.call(arguments, 1);\n                        if (args.length <= 1) {\n                            args = args[0];\n                        }\n                        callback.call(null, err, args);\n                    });\n                }\n            }, callback);\n        }\n        else {\n            var results = {};\n            eachfn.each(_keys(tasks), function (k, callback) {\n                tasks[k](function (err) {\n                    var args = Array.prototype.slice.call(arguments, 1);\n                    if (args.length <= 1) {\n                        args = args[0];\n                    }\n                    results[k] = args;\n                    callback(err);\n                });\n            }, function (err) {\n                callback(err, results);\n            });\n        }\n    };\n\n    async.parallel = function (tasks, callback) {\n        _parallel({ map: async.map, each: async.each }, tasks, callback);\n    };\n\n    async.parallelLimit = function(tasks, limit, callback) {\n        _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);\n    };\n\n    async.series = function (tasks, callback) {\n        callback = callback || function () {};\n        if (_isArray(tasks)) {\n            async.mapSeries(tasks, function (fn, callback) {\n                if (fn) {\n                    fn(function (err) {\n                        var args = Array.prototype.slice.call(arguments, 1);\n                        if (args.length <= 1) {\n                            args = args[0];\n                        }\n                        callback.call(null, err, args);\n                    });\n                }\n            }, callback);\n        }\n        else {\n            var results = {};\n            async.eachSeries(_keys(tasks), function (k, callback) {\n                tasks[k](function (err) {\n                    var args = Array.prototype.slice.call(arguments, 1);\n                    if (args.length <= 1) {\n                        args = args[0];\n                    }\n                    results[k] = args;\n                    callback(err);\n                });\n            }, function (err) {\n                callback(err, results);\n            });\n        }\n    };\n\n    async.iterator = function (tasks) {\n        var makeCallback = function (index) {\n            var fn = function () {\n                if (tasks.length) {\n                    tasks[index].apply(null, arguments);\n                }\n                return fn.next();\n            };\n            fn.next = function () {\n                return (index < tasks.length - 1) ? makeCallback(index + 1): null;\n            };\n            return fn;\n        };\n        return makeCallback(0);\n    };\n\n    async.apply = function (fn) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        return function () {\n            return fn.apply(\n                null, args.concat(Array.prototype.slice.call(arguments))\n            );\n        };\n    };\n\n    var _concat = function (eachfn, arr, fn, callback) {\n        var r = [];\n        eachfn(arr, function (x, cb) {\n            fn(x, function (err, y) {\n                r = r.concat(y || []);\n                cb(err);\n            });\n        }, function (err) {\n            callback(err, r);\n        });\n    };\n    async.concat = doParallel(_concat);\n    async.concatSeries = doSeries(_concat);\n\n    async.whilst = function (test, iterator, callback) {\n        if (test()) {\n            iterator(function (err) {\n                if (err) {\n                    return callback(err);\n                }\n                async.whilst(test, iterator, callback);\n            });\n        }\n        else {\n            callback();\n        }\n    };\n\n    async.doWhilst = function (iterator, test, callback) {\n        iterator(function (err) {\n            if (err) {\n                return callback(err);\n            }\n            var args = Array.prototype.slice.call(arguments, 1);\n            if (test.apply(null, args)) {\n                async.doWhilst(iterator, test, callback);\n            }\n            else {\n                callback();\n            }\n        });\n    };\n\n    async.until = function (test, iterator, callback) {\n        if (!test()) {\n            iterator(function (err) {\n                if (err) {\n                    return callback(err);\n                }\n                async.until(test, iterator, callback);\n            });\n        }\n        else {\n            callback();\n        }\n    };\n\n    async.doUntil = function (iterator, test, callback) {\n        iterator(function (err) {\n            if (err) {\n                return callback(err);\n            }\n            var args = Array.prototype.slice.call(arguments, 1);\n            if (!test.apply(null, args)) {\n                async.doUntil(iterator, test, callback);\n            }\n            else {\n                callback();\n            }\n        });\n    };\n\n    async.queue = function (worker, concurrency) {\n        if (concurrency === undefined) {\n            concurrency = 1;\n        }\n        function _insert(q, data, pos, callback) {\n          if (!q.started){\n            q.started = true;\n          }\n          if (!_isArray(data)) {\n              data = [data];\n          }\n          if(data.length == 0) {\n             // call drain immediately if there are no tasks\n             return async.setImmediate(function() {\n                 if (q.drain) {\n                     q.drain();\n                 }\n             });\n          }\n          _each(data, function(task) {\n              var item = {\n                  data: task,\n                  callback: typeof callback === 'function' ? callback : null\n              };\n\n              if (pos) {\n                q.tasks.unshift(item);\n              } else {\n                q.tasks.push(item);\n              }\n\n              if (q.saturated && q.tasks.length === q.concurrency) {\n                  q.saturated();\n              }\n              async.setImmediate(q.process);\n          });\n        }\n\n        var workers = 0;\n        var q = {\n            tasks: [],\n            concurrency: concurrency,\n            saturated: null,\n            empty: null,\n            drain: null,\n            started: false,\n            paused: false,\n            push: function (data, callback) {\n              _insert(q, data, false, callback);\n            },\n            kill: function () {\n              q.drain = null;\n              q.tasks = [];\n            },\n            unshift: function (data, callback) {\n              _insert(q, data, true, callback);\n            },\n            process: function () {\n                if (!q.paused && workers < q.concurrency && q.tasks.length) {\n                    var task = q.tasks.shift();\n                    if (q.empty && q.tasks.length === 0) {\n                        q.empty();\n                    }\n                    workers += 1;\n                    var next = function () {\n                        workers -= 1;\n                        if (task.callback) {\n                            task.callback.apply(task, arguments);\n                        }\n                        if (q.drain && q.tasks.length + workers === 0) {\n                            q.drain();\n                        }\n                        q.process();\n                    };\n                    var cb = only_once(next);\n                    worker(task.data, cb);\n                }\n            },\n            length: function () {\n                return q.tasks.length;\n            },\n            running: function () {\n                return workers;\n            },\n            idle: function() {\n                return q.tasks.length + workers === 0;\n            },\n            pause: function () {\n                if (q.paused === true) { return; }\n                q.paused = true;\n            },\n            resume: function () {\n                if (q.paused === false) { return; }\n                q.paused = false;\n                // Need to call q.process once per concurrent\n                // worker to preserve full concurrency after pause\n                for (var w = 1; w <= q.concurrency; w++) {\n                    async.setImmediate(q.process);\n                }\n            }\n        };\n        return q;\n    };\n\n    async.priorityQueue = function (worker, concurrency) {\n\n        function _compareTasks(a, b){\n          return a.priority - b.priority;\n        };\n\n        function _binarySearch(sequence, item, compare) {\n          var beg = -1,\n              end = sequence.length - 1;\n          while (beg < end) {\n            var mid = beg + ((end - beg + 1) >>> 1);\n            if (compare(item, sequence[mid]) >= 0) {\n              beg = mid;\n            } else {\n              end = mid - 1;\n            }\n          }\n          return beg;\n        }\n\n        function _insert(q, data, priority, callback) {\n          if (!q.started){\n            q.started = true;\n          }\n          if (!_isArray(data)) {\n              data = [data];\n          }\n          if(data.length == 0) {\n             // call drain immediately if there are no tasks\n             return async.setImmediate(function() {\n                 if (q.drain) {\n                     q.drain();\n                 }\n             });\n          }\n          _each(data, function(task) {\n              var item = {\n                  data: task,\n                  priority: priority,\n                  callback: typeof callback === 'function' ? callback : null\n              };\n\n              q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);\n\n              if (q.saturated && q.tasks.length === q.concurrency) {\n                  q.saturated();\n              }\n              async.setImmediate(q.process);\n          });\n        }\n\n        // Start with a normal queue\n        var q = async.queue(worker, concurrency);\n\n        // Override push to accept second parameter representing priority\n        q.push = function (data, priority, callback) {\n          _insert(q, data, priority, callback);\n        };\n\n        // Remove unshift function\n        delete q.unshift;\n\n        return q;\n    };\n\n    async.cargo = function (worker, payload) {\n        var working     = false,\n            tasks       = [];\n\n        var cargo = {\n            tasks: tasks,\n            payload: payload,\n            saturated: null,\n            empty: null,\n            drain: null,\n            drained: true,\n            push: function (data, callback) {\n                if (!_isArray(data)) {\n                    data = [data];\n                }\n                _each(data, function(task) {\n                    tasks.push({\n                        data: task,\n                        callback: typeof callback === 'function' ? callback : null\n                    });\n                    cargo.drained = false;\n                    if (cargo.saturated && tasks.length === payload) {\n                        cargo.saturated();\n                    }\n                });\n                async.setImmediate(cargo.process);\n            },\n            process: function process() {\n                if (working) return;\n                if (tasks.length === 0) {\n                    if(cargo.drain && !cargo.drained) cargo.drain();\n                    cargo.drained = true;\n                    return;\n                }\n\n                var ts = typeof payload === 'number'\n                            ? tasks.splice(0, payload)\n                            : tasks.splice(0, tasks.length);\n\n                var ds = _map(ts, function (task) {\n                    return task.data;\n                });\n\n                if(cargo.empty) cargo.empty();\n                working = true;\n                worker(ds, function () {\n                    working = false;\n\n                    var args = arguments;\n                    _each(ts, function (data) {\n                        if (data.callback) {\n                            data.callback.apply(null, args);\n                        }\n                    });\n\n                    process();\n                });\n            },\n            length: function () {\n                return tasks.length;\n            },\n            running: function () {\n                return working;\n            }\n        };\n        return cargo;\n    };\n\n    var _console_fn = function (name) {\n        return function (fn) {\n            var args = Array.prototype.slice.call(arguments, 1);\n            fn.apply(null, args.concat([function (err) {\n                var args = Array.prototype.slice.call(arguments, 1);\n                if (typeof console !== 'undefined') {\n                    if (err) {\n                        if (console.error) {\n                            console.error(err);\n                        }\n                    }\n                    else if (console[name]) {\n                        _each(args, function (x) {\n                            console[name](x);\n                        });\n                    }\n                }\n            }]));\n        };\n    };\n    async.log = _console_fn('log');\n    async.dir = _console_fn('dir');\n    /*async.info = _console_fn('info');\n    async.warn = _console_fn('warn');\n    async.error = _console_fn('error');*/\n\n    async.memoize = function (fn, hasher) {\n        var memo = {};\n        var queues = {};\n        hasher = hasher || function (x) {\n            return x;\n        };\n        var memoized = function () {\n            var args = Array.prototype.slice.call(arguments);\n            var callback = args.pop();\n            var key = hasher.apply(null, args);\n            if (key in memo) {\n                async.nextTick(function () {\n                    callback.apply(null, memo[key]);\n                });\n            }\n            else if (key in queues) {\n                queues[key].push(callback);\n            }\n            else {\n                queues[key] = [callback];\n                fn.apply(null, args.concat([function () {\n                    memo[key] = arguments;\n                    var q = queues[key];\n                    delete queues[key];\n                    for (var i = 0, l = q.length; i < l; i++) {\n                      q[i].apply(null, arguments);\n                    }\n                }]));\n            }\n        };\n        memoized.memo = memo;\n        memoized.unmemoized = fn;\n        return memoized;\n    };\n\n    async.unmemoize = function (fn) {\n      return function () {\n        return (fn.unmemoized || fn).apply(null, arguments);\n      };\n    };\n\n    async.times = function (count, iterator, callback) {\n        var counter = [];\n        for (var i = 0; i < count; i++) {\n            counter.push(i);\n        }\n        return async.map(counter, iterator, callback);\n    };\n\n    async.timesSeries = function (count, iterator, callback) {\n        var counter = [];\n        for (var i = 0; i < count; i++) {\n            counter.push(i);\n        }\n        return async.mapSeries(counter, iterator, callback);\n    };\n\n    async.seq = function (/* functions... */) {\n        var fns = arguments;\n        return function () {\n            var that = this;\n            var args = Array.prototype.slice.call(arguments);\n            var callback = args.pop();\n            async.reduce(fns, args, function (newargs, fn, cb) {\n                fn.apply(that, newargs.concat([function () {\n                    var err = arguments[0];\n                    var nextargs = Array.prototype.slice.call(arguments, 1);\n                    cb(err, nextargs);\n                }]))\n            },\n            function (err, results) {\n                callback.apply(that, [err].concat(results));\n            });\n        };\n    };\n\n    async.compose = function (/* functions... */) {\n      return async.seq.apply(null, Array.prototype.reverse.call(arguments));\n    };\n\n    var _applyEach = function (eachfn, fns /*args...*/) {\n        var go = function () {\n            var that = this;\n            var args = Array.prototype.slice.call(arguments);\n            var callback = args.pop();\n            return eachfn(fns, function (fn, cb) {\n                fn.apply(that, args.concat([cb]));\n            },\n            callback);\n        };\n        if (arguments.length > 2) {\n            var args = Array.prototype.slice.call(arguments, 2);\n            return go.apply(this, args);\n        }\n        else {\n            return go;\n        }\n    };\n    async.applyEach = doParallel(_applyEach);\n    async.applyEachSeries = doSeries(_applyEach);\n\n    async.forever = function (fn, callback) {\n        function next(err) {\n            if (err) {\n                if (callback) {\n                    return callback(err);\n                }\n                throw err;\n            }\n            fn(next);\n        }\n        next();\n    };\n\n    // Node.js\n    if (typeof module !== 'undefined' && module.exports) {\n        module.exports = async;\n    }\n    // AMD / RequireJS\n    else if (typeof define !== 'undefined' && define.amd) {\n        define([], function () {\n            return async;\n        });\n    }\n    // included directly via <script> tag\n    else {\n        root.async = async;\n    }\n\n}());"
  },
  {
    "path": "app/scripts/lib/flood/csg.js",
    "content": "// Constructive Solid Geometry (CSG) is a modeling technique that uses Boolean\n// operations like union and intersection to combine 3D solids. This library\n// implements CSG operations on meshes elegantly and concisely using BSP trees,\n// and is meant to serve as an easily understandable implementation of the\n// algorithm. All edge cases involving overlapping coplanar polygons in both\n// solids are correctly handled.\n// \n// Example usage:\n// \n//     var cube = CSG.cube();\n//     var sphere = CSG.sphere({ radius: 1.3 });\n//     var polygons = cube.subtract(sphere).toPolygons();\n// \n// ## Implementation Details\n// \n// All CSG operations are implemented in terms of two functions, `clipTo()` and\n// `invert()`, which remove parts of a BSP tree inside another BSP tree and swap\n// solid and empty space, respectively. To find the union of `a` and `b`, we\n// want to remove everything in `a` inside `b` and everything in `b` inside `a`,\n// then combine polygons from `a` and `b` into one solid:\n// \n//     a.clipTo(b);\n//     b.clipTo(a);\n//     a.build(b.allPolygons());\n// \n// The only tricky part is handling overlapping coplanar polygons in both trees.\n// The code above keeps both copies, but we need to keep them in one tree and\n// remove them in the other tree. To remove them from `b` we can clip the\n// inverse of `b` against `a`. The code for union now looks like this:\n// \n//     a.clipTo(b);\n//     b.clipTo(a);\n//     b.invert();\n//     b.clipTo(a);\n//     b.invert();\n//     a.build(b.allPolygons());\n// \n// Subtraction and intersection naturally follow from set operations. If\n// union is `A | B`, subtraction is `A - B = ~(~A | B)` and intersection is\n// `A & B = ~(~A | ~B)` where `~` is the complement operator.\n// \n// ## License\n// \n// Copyright (c) 2011 Evan Wallace (http://madebyevan.com/), under the MIT license.\n// Parts Copyright (c) 2012 Joost Nieuwenhuijse (joost@newhouse.nl) under the MIT license.\n\n// # class CSG\n\n// Holds a binary space partition tree representing a 3D solid. Two solids can\n// be combined using the `union()`, `subtract()`, and `intersect()` methods.\n\nCSG = function() {\n  this.polygons = [];\n};\n\n// Construct a CSG solid from a list of `CSG.Polygon` instances.\nCSG.fromPolygons = function(polygons) {\n  var csg = new CSG();\n  csg.polygons = polygons;\n  return csg;\n};\n\nCSG.prototype = {\n  clone: function() {\n    var csg = new CSG();\n    csg.polygons = this.polygons.map(function(p) { return p.clone(); });\n    return csg;\n  },\n\n  toPolygons: function() {\n    return this.polygons;\n  },\n\n  // Return a new CSG solid representing space in either this solid or in the\n  // solid `csg`. Neither this solid nor the solid `csg` are modified.\n  // \n  //     A.union(B)\n  // \n  //     +-------+            +-------+\n  //     |       |            |       |\n  //     |   A   |            |       |\n  //     |    +--+----+   =   |       +----+\n  //     +----+--+    |       +----+       |\n  //          |   B   |            |       |\n  //          |       |            |       |\n  //          +-------+            +-------+\n  // \n  union: function(csg) {\n    var a = new CSG.Node(this.clone().polygons);\n    var b = new CSG.Node(csg.clone().polygons);\n    a.clipTo(b);\n    b.clipTo(a);\n    b.invert();\n    b.clipTo(a);\n    b.invert();\n    a.build(b.allPolygons());\n    return CSG.fromPolygons(a.allPolygons());\n  },\n\n  // Return a new CSG solid representing space in this solid but not in the\n  // solid `csg`. Neither this solid nor the solid `csg` are modified.\n  // \n  //     A.subtract(B)\n  // \n  //     +-------+            +-------+\n  //     |       |            |       |\n  //     |   A   |            |       |\n  //     |    +--+----+   =   |    +--+\n  //     +----+--+    |       +----+\n  //          |   B   |\n  //          |       |\n  //          +-------+\n  // \n  subtract: function(csg) {\n    var a = new CSG.Node(this.clone().polygons);\n    var b = new CSG.Node(csg.clone().polygons);\n    a.invert();\n    a.clipTo(b);\n    b.clipTo(a);\n    b.invert();\n    b.clipTo(a);\n    b.invert();\n    a.build(b.allPolygons());\n    a.invert();\n    return CSG.fromPolygons(a.allPolygons());\n  },\n\n  // Return a new CSG solid representing space both this solid and in the\n  // solid `csg`. Neither this solid nor the solid `csg` are modified.\n  // \n  //     A.intersect(B)\n  // \n  //     +-------+\n  //     |       |\n  //     |   A   |\n  //     |    +--+----+   =   +--+\n  //     +----+--+    |       +--+\n  //          |   B   |\n  //          |       |\n  //          +-------+\n  // \n  intersect: function(csg) {\n    var a = new CSG.Node(this.clone().polygons);\n    var b = new CSG.Node(csg.clone().polygons);\n    a.invert();\n    b.clipTo(a);\n    b.invert();\n    a.clipTo(b);\n    b.clipTo(a);\n    a.build(b.allPolygons());\n    a.invert();\n    return CSG.fromPolygons(a.allPolygons());\n  },\n\n  // Return a new CSG solid with solid and empty space switched. This solid is\n  // not modified.\n  inverse: function() {\n    var csg = this.clone();\n    csg.polygons.map(function(p) { p.flip(); });\n    return csg;\n  },\n  \n  // Affine transformation of CSG object. Returns a new CSG object\n  transform: function(matrix4x4) {\n    var newpolygons = this.polygons.map(function(p) { return p.transform(matrix4x4); } );\n    return CSG.fromPolygons(newpolygons);  \n  },\n  \n  translate: function(v) {\n    return this.transform(CSG.Matrix4x4.translation(v));\n  },\n  \n  scale: function(f) {\n    return this.transform(CSG.Matrix4x4.scaling(f));\n  },\n  \n  rotateX: function(deg) {\n    return this.transform(CSG.Matrix4x4.rotationX(deg));\n  },\n  \n  rotateY: function(deg) {\n    return this.transform(CSG.Matrix4x4.rotationY(deg));\n  },\n  \n  rotateZ: function(deg) {\n    return this.transform(CSG.Matrix4x4.rotationZ(deg));\n  },\n  \n  toStlString: function() {\n    var result=\"solid csg.js\\n\";\n    this.polygons.map(function(p){ result += p.toStlString(); });\n    result += \"endsolid csg.js\\n\";\n    return result;\n  }\n};\n\n// Construct an axis-aligned solid cuboid. Optional parameters are `center` and\n// `radius`, which default to `[0, 0, 0]` and `[1, 1, 1]`. The radius can be\n// specified using a single number or a list of three numbers, one for each axis.\n// \n// Example code:\n// \n//     var cube = CSG.cube({\n//       center: [0, 0, 0],\n//       radius: 1\n//     });\nCSG.cube = function(options) {\n  options = options || {};\n  var c = new CSG.Vector(options.center || [0, 0, 0]);\n  var r = !options.radius ? [1, 1, 1] : options.radius.length ?\n           options.radius : [options.radius, options.radius, options.radius];\n  return CSG.fromPolygons([\n    [[0, 4, 6, 2], [-1, 0, 0]],\n    [[1, 3, 7, 5], [+1, 0, 0]],\n    [[0, 1, 5, 4], [0, -1, 0]],\n    [[2, 6, 7, 3], [0, +1, 0]],\n    [[0, 2, 3, 1], [0, 0, -1]],\n    [[4, 5, 7, 6], [0, 0, +1]]\n  ].map(function(info) {\n    return new CSG.Polygon(info[0].map(function(i) {\n      var pos = new CSG.Vector(\n        c.x + r[0] * (2 * !!(i & 1) - 1),\n        c.y + r[1] * (2 * !!(i & 2) - 1),\n        c.z + r[2] * (2 * !!(i & 4) - 1)\n      );\n      return new CSG.Vertex(pos, new CSG.Vector(info[1]));\n    }));\n  }));\n};\n\n// Construct a solid sphere. Optional parameters are `center`, `radius`,\n// `slices`, and `stacks`, which default to `[0, 0, 0]`, `1`, `16`, and `8`.\n// The `slices` and `stacks` parameters control the tessellation along the\n// longitude and latitude directions.\n// \n// Example usage:\n// \n//     var sphere = CSG.sphere({\n//       center: [0, 0, 0],\n//       radius: 1,\n//       slices: 16,\n//       stacks: 8\n//     });\nCSG.sphere = function(options) {\n  options = options || {};\n  var c = new CSG.Vector(options.center || [0, 0, 0]);\n  var r = options.radius || 1;\n  var slices = options.slices || 16;\n  var stacks = options.stacks || 8;\n  var polygons = [], vertices;\n  function vertex(theta, phi) {\n    theta *= Math.PI * 2;\n    phi *= Math.PI;\n    var dir = new CSG.Vector(\n      Math.cos(theta) * Math.sin(phi),\n      Math.cos(phi),\n      Math.sin(theta) * Math.sin(phi)\n    );\n    vertices.push(new CSG.Vertex(c.plus(dir.times(r)), dir));\n  }\n  for (var i = 0; i < slices; i++) {\n    for (var j = 0; j < stacks; j++) {\n      vertices = [];\n      vertex(i / slices, j / stacks);\n      if (j > 0) vertex((i + 1) / slices, j / stacks);\n      if (j < stacks - 1) vertex((i + 1) / slices, (j + 1) / stacks);\n      vertex(i / slices, (j + 1) / stacks);\n      polygons.push(new CSG.Polygon(vertices));\n    }\n  }\n  return CSG.fromPolygons(polygons);\n};\n\n// Construct a solid cylinder. Optional parameters are `start`, `end`,\n// `radius`, and `slices`, which default to `[0, -1, 0]`, `[0, 1, 0]`, `1`, and\n// `16`. The `slices` parameter controls the tessellation.\n// \n// Example usage:\n// \n//     var cylinder = CSG.cylinder({\n//       start: [0, -1, 0],\n//       end: [0, 1, 0],\n//       radius: 1,\n//       slices: 16\n//     });\nCSG.cylinder = function(options) {\n  options = options || {};\n  var s = new CSG.Vector(options.start || [0, -1, 0]);\n  var e = new CSG.Vector(options.end || [0, 1, 0]);\n  var ray = e.minus(s);\n  var r = options.radius || 1;\n  var slices = options.slices || 16;\n  var axisZ = ray.unit(), isY = (Math.abs(axisZ.y) > 0.5);\n  var axisX = new CSG.Vector(isY, !isY, 0).cross(axisZ).unit();\n  var axisY = axisX.cross(axisZ).unit();\n  var start = new CSG.Vertex(s, axisZ.negated());\n  var end = new CSG.Vertex(e, axisZ.unit());\n  var polygons = [];\n  function point(stack, slice, normalBlend) {\n    var angle = slice * Math.PI * 2;\n    var out = axisX.times(Math.cos(angle)).plus(axisY.times(Math.sin(angle)));\n    var pos = s.plus(ray.times(stack)).plus(out.times(r));\n    var normal = out.times(1 - Math.abs(normalBlend)).plus(axisZ.times(normalBlend));\n    return new CSG.Vertex(pos, normal);\n  }\n  for (var i = 0; i < slices; i++) {\n    var t0 = i / slices, t1 = (i + 1) / slices;\n    polygons.push(new CSG.Polygon([start, point(0, t0, -1), point(0, t1, -1)]));\n    polygons.push(new CSG.Polygon([point(0, t1, 0), point(0, t0, 0), point(1, t0, 0), point(1, t1, 0)]));\n    polygons.push(new CSG.Polygon([end, point(1, t1, 1), point(1, t0, 1)]));\n  }\n  return CSG.fromPolygons(polygons);\n};\n\n// # class Vector\n\n// Represents a 3D vector.\n// \n// Example usage:\n// \n//     new CSG.Vector(1, 2, 3);\n//     new CSG.Vector([1, 2, 3]);\n//     new CSG.Vector({ x: 1, y: 2, z: 3 });\n\nCSG.Vector = function(x, y, z) {\n  if (arguments.length == 3) {\n    this.x = x;\n    this.y = y;\n    this.z = z;\n  } else if ('x' in x) {\n    this.x = x.x;\n    this.y = x.y;\n    this.z = x.z;\n  } else {\n    this.x = x[0];\n    this.y = x[1];\n    this.z = x[2];\n  }\n};\n\nCSG.Vector.prototype = {\n  clone: function() {\n    return new CSG.Vector(this.x, this.y, this.z);\n  },\n\n  negated: function() {\n    return new CSG.Vector(-this.x, -this.y, -this.z);\n  },\n\n  plus: function(a) {\n    return new CSG.Vector(this.x + a.x, this.y + a.y, this.z + a.z);\n  },\n\n  minus: function(a) {\n    return new CSG.Vector(this.x - a.x, this.y - a.y, this.z - a.z);\n  },\n\n  times: function(a) {\n    return new CSG.Vector(this.x * a, this.y * a, this.z * a);\n  },\n\n  dividedBy: function(a) {\n    return new CSG.Vector(this.x / a, this.y / a, this.z / a);\n  },\n\n  dot: function(a) {\n    return this.x * a.x + this.y * a.y + this.z * a.z;\n  },\n\n  lerp: function(a, t) {\n    return this.plus(a.minus(this).times(t));\n  },\n\n  length: function() {\n    return Math.sqrt(this.dot(this));\n  },\n\n  unit: function() {\n    return this.dividedBy(this.length());\n  },\n\n  cross: function(a) {\n    return new CSG.Vector(\n      this.y * a.z - this.z * a.y,\n      this.z * a.x - this.x * a.z,\n      this.x * a.y - this.y * a.x\n    );\n  },\n  \n  // Right multiply by a 4x4 matrix (the vector is interpreted as a row vector)\n  // Returns a new CSG.Vector\n  multiply4x4: function(matrix4x4) {\n    return matrix4x4.rightMultiply1x3Vector(this);\n  },\n  \n  toStlString: function() {\n    return this.x+\" \"+this.y+\" \"+this.z;\n  }\n};\n\n// # class Vertex\n\n// Represents a vertex of a polygon. Use your own vertex class instead of this\n// one to provide additional features like texture coordinates and vertex\n// colors. Custom vertex classes need to provide a `pos` property and `clone()`,\n// `flip()`, and `interpolate()` methods that behave analogous to the ones\n// defined by `CSG.Vertex`. This class provides `normal` so convenience\n// functions like `CSG.sphere()` can return a smooth vertex normal, but `normal`\n// is not used anywhere else.\n\nCSG.Vertex = function(pos, normal) {\n  this.pos = new CSG.Vector(pos);\n  this.normal = new CSG.Vector(normal);\n};\n\nCSG.Vertex.prototype = {\n  clone: function() {\n    return new CSG.Vertex(this.pos.clone(), this.normal.clone());\n  },\n\n  // Invert all orientation-specific data (e.g. vertex normal). Called when the\n  // orientation of a polygon is flipped.\n  flip: function() {\n    this.normal = this.normal.negated();\n  },\n\n  // Create a new vertex between this vertex and `other` by linearly\n  // interpolating all properties using a parameter of `t`. Subclasses should\n  // override this to interpolate additional properties.\n  interpolate: function(other, t) {\n    return new CSG.Vertex(\n      this.pos.lerp(other.pos, t),\n      this.normal.lerp(other.normal, t)\n    );\n  },\n  \n  // Affine transformation of vertex. Returns a new CSG.Vertex\n  transform: function(matrix4x4) {\n    var newpos = this.pos.multiply4x4(matrix4x4);\n    var posPlusNormal = this.pos.plus(this.normal);\n    var newPosPlusNormal = posPlusNormal.multiply4x4(matrix4x4);\n    var newnormal = newPosPlusNormal.minus(newpos).unit();\n    return new CSG.Vertex(newpos, newnormal);  \n  },\n  \n  toStlString: function() {\n    return \"vertex \"+this.pos.toStlString()+\"\\n\";\n  }\n};\n\n// # class Plane\n\n// Represents a plane in 3D space.\n\nCSG.Plane = function(normal, w) {\n  this.normal = normal;\n  this.w = w; // the distance from the origin along the normal\n\n  \n};\n\n// `CSG.Plane.EPSILON` is the tolerance used by `splitPolygon()` to decide if a\n// point is on the plane.\nCSG.Plane.EPSILON = 1e-5;\n\nCSG.Plane.fromPoints = function(a, b, c) {\n  var n = b.minus(a).cross(c.minus(a)).unit();\n  return new CSG.Plane(n, n.dot(a));\n};\n\nCSG.Plane.prototype = {\n  clone: function() {\n    return new CSG.Plane(this.normal.clone(), this.w);\n  },\n\n  flip: function() {\n    this.normal = this.normal.negated();\n    this.w = -this.w;\n  },\n\n  // Split `polygon` by this plane if needed, then put the polygon or polygon\n  // fragments in the appropriate lists. Coplanar polygons go into either\n  // `coplanarFront` or `coplanarBack` depending on their orientation with\n  // respect to this plane. Polygons in front or in back of this plane go into\n  // either `front` or `back`.\n  splitPolygon: function(polygon, coplanarFront, coplanarBack, front, back) {\n    var COPLANAR = 0;\n    var FRONT = 1;\n    var BACK = 2;\n    var SPANNING = 3;\n\n    // Classify each point as well as the entire polygon into one of the above\n    // four classes.\n    var polygonType = 0;\n    var types = [];\n    for (var i = 0; i < polygon.vertices.length; i++) {\n      var t = this.normal.dot(polygon.vertices[i].pos) - this.w;\n      var type = (t < -CSG.Plane.EPSILON) ? BACK : (t > CSG.Plane.EPSILON) ? FRONT : COPLANAR;\n      polygonType |= type;\n      types.push(type);\n    }\n\n    // Put the polygon in the correct list, splitting it when necessary.\n    switch (polygonType) {\n      case COPLANAR:\n        (this.normal.dot(polygon.plane.normal) > 0 ? coplanarFront : coplanarBack).push(polygon);\n        break;\n      case FRONT:\n        front.push(polygon);\n        break;\n      case BACK:\n        back.push(polygon);\n        break;\n      case SPANNING:\n        var f = [], b = [];\n        for (var i = 0; i < polygon.vertices.length; i++) {\n          var j = (i + 1) % polygon.vertices.length;\n          var ti = types[i], tj = types[j];\n          var vi = polygon.vertices[i], vj = polygon.vertices[j];\n          if (ti != BACK) f.push(vi);\n          if (ti != FRONT) b.push(ti != BACK ? vi.clone() : vi);\n          if ((ti | tj) == SPANNING) {\n            var t = (this.w - this.normal.dot(vi.pos)) / this.normal.dot(vj.pos.minus(vi.pos));\n            var v = vi.interpolate(vj, t);\n            f.push(v);\n            b.push(v.clone());\n          }\n        }\n        if (f.length >= 3) front.push(new CSG.Polygon(f, polygon.shared));\n        if (b.length >= 3) back.push(new CSG.Polygon(b, polygon.shared));\n        break;\n    }\n  }\n};\n\n// # class Polygon\n\n// Represents a convex polygon. The vertices used to initialize a polygon must\n// be coplanar and form a convex loop. They do not have to be `CSG.Vertex`\n// instances but they must behave similarly (duck typing can be used for\n// customization).\n// \n// Each convex polygon has a `shared` property, which is shared between all\n// polygons that are clones of each other or were split from the same polygon.\n// This can be used to define per-polygon properties (such as surface color).\n\nCSG.Polygon = function(vertices, shared) {\n  this.vertices = vertices;\n  this.shared = shared;\n  this.plane = CSG.Plane.fromPoints(vertices[0].pos, vertices[1].pos, vertices[2].pos);\n};\n\nCSG.Polygon.prototype = {\n  clone: function() {\n    var vertices = this.vertices.map(function(v) { return v.clone(); });\n    return new CSG.Polygon(vertices, this.shared);\n  },\n\n  flip: function() {\n    this.vertices.reverse().map(function(v) { v.flip(); });\n    this.plane.flip();\n  },\n  \n  // Affine transformation of polygon. Returns a new CSG.Polygon\n  transform: function(matrix4x4) {\n    var newvertices = this.vertices.map(function(v) { return v.transform(matrix4x4); } );\n    return new CSG.Polygon(newvertices, this.shared);\n  },\n\n  translate: function(matrix4x4) {\n    var newvertices = this.vertices.map(function(v) { return v.transform(matrix4x4); } );\n    return new CSG.Polygon(newvertices, this.shared);\n  },\n\n  scale: function(matrix4x4) {\n    var newvertices = this.vertices.map(function(v) { return v.transform(matrix4x4); } );\n    return new CSG.Polygon(newvertices, this.shared);\n  },\n  \n  toStlString: function() {\n    var result=\"\";\n    if(this.vertices.length >= 3) // should be!\n    {\n      // SLT requires triangular polygons. If our polygon has more vertices, create\n      // multiple triangles:\n      var firstVertexStl = this.vertices[0].toStlString();\n      for(var i=0; i < this.vertices.length-2; i++)\n      {\n        result += \"facet normal \"+this.plane.normal.toStlString()+\"\\nouter loop\\n\";\n        result += firstVertexStl;\n        result += this.vertices[i+1].toStlString();\n        result += this.vertices[i+2].toStlString();\n        result += \"endloop\\nendfacet\\n\";    \n      } \n    }\n    return result;\n  }\n};\n\n// Create a polygon from the given points\nCSG.Polygon.createFromPoints = function(points, shared) {\n  // initially set a dummy vertex normal:\n  var dummynormal = new CSG.Vector(0, 0, 0);\n  var vertices = [];\n  points.map( function(p) {\n    var vec = new CSG.Vector(p);\n    var vertex = new CSG.Vertex(vec, dummynormal);\n    vertices.push(vertex); \n  });            \n  var polygon = new CSG.Polygon(vertices, shared);\n  // now set the vertex normals to the polygon normal:\n  var normal = polygon.plane.normal;\n  polygon.vertices.map( function(v) {\n    v.normal = normal;\n  });\n  return polygon;\n};\n\n// # class Node\n\n// Holds a node in a BSP tree. A BSP tree is built from a collection of polygons\n// by picking a polygon to split along. That polygon (and all other coplanar\n// polygons) are added directly to that node and the other polygons are added to\n// the front and/or back subtrees. This is not a leafy BSP tree since there is\n// no distinction between internal and leaf nodes.\n\nCSG.Node = function(polygons) {\n  this.plane = null;\n  this.front = null;\n  this.back = null;\n  this.polygons = [];\n  if (polygons) this.build(polygons);\n};\n\nCSG.Node.prototype = {\n  clone: function() {\n    var node = new CSG.Node();\n    node.plane = this.plane && this.plane.clone();\n    node.front = this.front && this.front.clone();\n    node.back = this.back && this.back.clone();\n    node.polygons = this.polygons.map(function(p) { return p.clone(); });\n    return node;\n  },\n\n  // Convert solid space to empty space and empty space to solid space.\n  invert: function() {\n    for (var i = 0; i < this.polygons.length; i++) {\n      this.polygons[i].flip();\n    }\n    this.plane.flip();\n    if (this.front) this.front.invert();\n    if (this.back) this.back.invert();\n    var temp = this.front;\n    this.front = this.back;\n    this.back = temp;\n  },\n\n  // Recursively remove all polygons in `polygons` that are inside this BSP\n  // tree.\n  clipPolygons: function(polygons) {\n    if (!this.plane) return polygons.slice();\n    var front = [], back = [];\n    for (var i = 0; i < polygons.length; i++) {\n      this.plane.splitPolygon(polygons[i], front, back, front, back);\n    }\n    if (this.front) front = this.front.clipPolygons(front);\n    if (this.back) back = this.back.clipPolygons(back);\n    else back = [];\n    return front.concat(back);\n  },\n\n  // Remove all polygons in this BSP tree that are inside the other BSP tree\n  // `bsp`.\n  clipTo: function(bsp) {\n    this.polygons = bsp.clipPolygons(this.polygons);\n    if (this.front) this.front.clipTo(bsp);\n    if (this.back) this.back.clipTo(bsp);\n  },\n\n  // Return a list of all polygons in this BSP tree.\n  allPolygons: function() {\n    var polygons = this.polygons.slice();\n    if (this.front) polygons = polygons.concat(this.front.allPolygons());\n    if (this.back) polygons = polygons.concat(this.back.allPolygons());\n    return polygons;\n  },\n\n  // Build a BSP tree out of `polygons`. When called on an existing tree, the\n  // new polygons are filtered down to the bottom of the tree and become new\n  // nodes there. Each set of polygons is partitioned using the first polygon\n  // (no heuristic is used to pick a good split).\n  build: function(polygons) {\n    if (!polygons.length) return;\n    if (!this.plane) this.plane = polygons[0].plane.clone();\n    var front = [], back = [];\n    for (var i = 0; i < polygons.length; i++) {\n      this.plane.splitPolygon(polygons[i], this.polygons, this.polygons, front, back);\n    }\n    if (front.length) {\n      if (!this.front) this.front = new CSG.Node();\n      this.front.build(front);\n    }\n    if (back.length) {\n      if (!this.back) this.back = new CSG.Node();\n      this.back.build(back);\n    }\n  }\n};\n\n// # class Matrix4x4:\n// Represents a 4x4 matrix. Elements are specified in row order\nCSG.Matrix4x4 = function(elements) {\n  if (arguments.length >= 1) {\n    this.elements=elements;\n  }\n  else\n  {\n    // if no arguments passed: create unity matrix  \n    this.elements=[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];\n  }\n}\n\nCSG.Matrix4x4.prototype = {\n  plus: function(m) {\n    var r=[];\n    for(var i=0; i < 16; i++)\n    {\n      r[i]=this.elements[i]+m.elements[i];\n    }\n    return new CSG.Matrix4x4(r);\n  },\n  \n  minus: function(m) {\n    var r=[];\n    for(var i=0; i < 16; i++)\n    {\n      r[i]=this.elements[i]-m.elements[i];\n    }\n    return new CSG.Matrix4x4(r);\n  },\n\n  // right multiply by another 4x4 matrix:\n  multiply: function(m) {\n    // cache elements in local variables, for speedup:\n    var this0=this.elements[0];\n    var this1=this.elements[1];\n    var this2=this.elements[2];\n    var this3=this.elements[3];\n    var this4=this.elements[4];\n    var this5=this.elements[5];\n    var this6=this.elements[6];\n    var this7=this.elements[7];\n    var this8=this.elements[8];\n    var this9=this.elements[9];\n    var this10=this.elements[10];\n    var this11=this.elements[11];\n    var this12=this.elements[12];\n    var this13=this.elements[13];\n    var this14=this.elements[14];\n    var this15=this.elements[15];\n    var m0=m.elements[0];\n    var m1=m.elements[1];\n    var m2=m.elements[2];\n    var m3=m.elements[3];\n    var m4=m.elements[4];\n    var m5=m.elements[5];\n    var m6=m.elements[6];\n    var m7=m.elements[7];\n    var m8=m.elements[8];\n    var m9=m.elements[9];\n    var m10=m.elements[10];\n    var m11=m.elements[11];\n    var m12=m.elements[12];\n    var m13=m.elements[13];\n    var m14=m.elements[14];\n    var m15=m.elements[15];\n    \n    var result=[];\n    result[0] = this0*m0 + this1*m4 + this2*m8 + this3*m12;\n    result[1] = this0*m1 + this1*m5 + this2*m9 + this3*m13;\n    result[2] = this0*m2 + this1*m6 + this2*m10 + this3*m14;\n    result[3] = this0*m3 + this1*m7 + this2*m11 + this3*m15;\n    result[4] = this4*m0 + this5*m4 + this6*m8 + this7*m12;\n    result[5] = this4*m1 + this5*m5 + this6*m9 + this7*m13;\n    result[6] = this4*m2 + this5*m6 + this6*m10 + this7*m14;\n    result[7] = this4*m3 + this5*m7 + this6*m11 + this7*m15;\n    result[8] = this8*m0 + this9*m4 + this10*m8 + this11*m12;\n    result[9] = this8*m1 + this9*m5 + this10*m9 + this11*m13;\n    result[10] = this8*m2 + this9*m6 + this10*m10 + this11*m14;\n    result[11] = this8*m3 + this9*m7 + this10*m11 + this11*m15;\n    result[12] = this12*m0 + this13*m4 + this14*m8 + this15*m12;\n    result[13] = this12*m1 + this13*m5 + this14*m9 + this15*m13;\n    result[14] = this12*m2 + this13*m6 + this14*m10 + this15*m14;\n    result[15] = this12*m3 + this13*m7 + this14*m11 + this15*m15;\n    return new CSG.Matrix4x4(result);\n  },\n  \n  clone: function() {\n    var elements = this.elements.map(function(p) { return p; }); \n    return new CSG.Matrix4x4(elements);\n  },\n  \n  // Multiply a CSG.Vector (interpreted as 1 row, 3 column) by this matrix \n  // Fourth element is taken as 1\n  rightMultiply1x3Vector: function(v) {\n    var v0 = v.x;\n    var v1 = v.y;\n    var v2 = v.z;\n    var v3 = 1;    \n    var x = v0*this.elements[0] + v1*this.elements[1] + v2*this.elements[2] + v3*this.elements[3];    \n    var y = v0*this.elements[4] + v1*this.elements[5] + v2*this.elements[6] + v3*this.elements[7];    \n    var z = v0*this.elements[8] + v1*this.elements[9] + v2*this.elements[10] + v3*this.elements[11];    \n    var w = v0*this.elements[12] + v1*this.elements[13] + v2*this.elements[14] + v3*this.elements[15];\n    // scale such that fourth element becomes 1:\n    if(w != 1)\n    {\n      var invw=1.0/w;\n      x *= invw;\n      y *= invw;\n      z *= invw;\n    }\n    return new CSG.Vector(x,y,z);       \n  },\n  \n  // Multiply a CSG.Vector2D (interpreted as 1 row, 2 column) by this matrix \n  // Fourth element is taken as 1\n  rightMultiply1x2Vector: function(v) {\n    var v0 = v.x;\n    var v1 = v.y;\n    var v2 = 0;\n    var v3 = 1;    \n    var x = v0*this.elements[0] + v1*this.elements[1] + v2*this.elements[2] + v3*this.elements[3];    \n    var y = v0*this.elements[4] + v1*this.elements[5] + v2*this.elements[6] + v3*this.elements[7];    \n    var z = v0*this.elements[8] + v1*this.elements[9] + v2*this.elements[10] + v3*this.elements[11];    \n    var w = v0*this.elements[12] + v1*this.elements[13] + v2*this.elements[14] + v3*this.elements[15];\n    // scale such that fourth element becomes 1:\n    if(w != 1)\n    {\n      var invw=1.0/w;\n      x *= invw;\n      y *= invw;\n      z *= invw;\n    }\n    return new CSG.Vector2D(x,y);       \n  },\n};\n\n// return the unity matrix\nCSG.Matrix4x4.unity = function() {\n  return new CSG.Matrix4x4(); \n};\n\n// Create a rotation matrix for rotating around the x axis\nCSG.Matrix4x4.rotationX = function(degrees) {\n  var radians = degrees * Math.PI * (1.0/180.0);\n  var cos = Math.cos(radians);\n  var sin = Math.sin(radians);\n  var els = [\n    1, 0, 0, 0,\n    0, cos, -sin, 0,\n    0, sin, cos, 0,\n    0, 0, 0, 1\n  ];\n  return new CSG.Matrix4x4(els);\n};\n\n// Create a rotation matrix for rotating around the y axis\nCSG.Matrix4x4.rotationY = function(degrees) {\n  var radians = degrees * Math.PI * (1.0/180.0);\n  var cos = Math.cos(radians);\n  var sin = Math.sin(radians);\n  var els = [\n    cos, 0, sin, 0,\n    0, 1, 0, 0,\n    -sin, 0, cos, 0,\n    0, 0, 0, 1\n  ];\n  return new CSG.Matrix4x4(els);\n};\n\n// Create a rotation matrix for rotating around the z axis\nCSG.Matrix4x4.rotationZ = function(degrees) {\n  var radians = degrees * Math.PI * (1.0/180.0);\n  var cos = Math.cos(radians);\n  var sin = Math.sin(radians);\n  var els = [\n    cos, -sin, 0, 0,\n    sin, cos, 0, 0,\n    0, 0, 1, 0,\n    0, 0, 0, 1\n  ];\n  return new CSG.Matrix4x4(els);\n};\n\n// Create an affine matrix for translation:\nCSG.Matrix4x4.translation = function(v) {\n  // parse as CSG.Vector, so we can pass an array or a CSG.Vector\n  var vec = new CSG.Vector(v);\n  var els = [\n    1, 0, 0, vec.x,\n    0, 1, 0, vec.y,\n    0, 0, 1, vec.z,\n    0, 0, 0, 1\n  ];\n  return new CSG.Matrix4x4(els);\n};\n\n// Create an affine matrix for scaling:\nCSG.Matrix4x4.scaling = function(v) {\n  // parse as CSG.Vector, so we can pass an array or a CSG.Vector\n  var vec = new CSG.Vector(v);\n  var els = [\n    vec.x, 0, 0, 0,\n    0, vec.y, 0, 0,\n    0, 0, vec.z, 0,\n    0, 0, 0, 1\n  ];\n  return new CSG.Matrix4x4(els);\n};\n\n///////////////////////////////////////////////////\n\n// # class Vector2D:\n// Represents a 2 element vector\nCSG.Vector2D = function(x, y) {\n  if (arguments.length == 2) {\n    this.x = x;\n    this.y = y;\n  } else if ('x' in x) {\n    this.x = x.x;\n    this.y = x.y;\n  } else {\n    this.x = x[0];\n    this.y = x[1];\n  }\n};\n\nCSG.Vector2D.prototype = {\n  // extend to a 3D vector by adding a z coordinate:\n  toVector3D: function(z) {\n    return new CSG.Vector(this.x, this.y, z);\n  },\n  \n  clone: function() {\n    return new CSG.Vector(this.x, this.y);\n  },\n\n  negated: function() {\n    return new CSG.Vector(-this.x, -this.y);\n  },\n\n  plus: function(a) {\n    return new CSG.Vector(this.x + a.x, this.y + a.y);\n  },\n\n  minus: function(a) {\n    return new CSG.Vector(this.x - a.x, this.y - a.y);\n  },\n\n  times: function(a) {\n    return new CSG.Vector(this.x * a, this.y * a);\n  },\n\n  dividedBy: function(a) {\n    return new CSG.Vector(this.x / a, this.y / a);\n  },\n\n  dot: function(a) {\n    return this.x * a.x + this.y * a.y;\n  },\n\n  lerp: function(a, t) {\n    return this.plus(a.minus(this).times(t));\n  },\n\n  length: function() {\n    return Math.sqrt(this.dot(this));\n  },\n\n  unit: function() {\n    return this.dividedBy(this.length());\n  },\n\n  // Right multiply by a 4x4 matrix (the vector is interpreted as a row vector)\n  // Returns a new CSG.Vector2D\n  multiply4x4: function(matrix4x4) {\n    return matrix4x4.rightMultiply1x2Vector(this);\n  },\n};\n\n\n// A polygon in 2D space:\nCSG.Polygon2D = function(points, shared) {\n  var vectors = [];\n  if(arguments.length >= 1) {\n    points.map( function(p) {\n      vectors.push(new CSG.Vector2D(p) );\n    });    \n  }\n  this.points = vectors;\n  this.shared = shared;\n};\n\nCSG.Polygon2D.prototype = {\n  // Matrix transformation of polygon. Returns a new CSG.Polygon2D\n  transform: function(matrix4x4) {\n    var newpoints = this.points.map(function(p) { return p.multiply4x4(matrix4x4); } );\n    return new CSG.Polygon2D(newpoints, this.shared);\n  },\n  \n  translate: function(v) {\n    v=new CSG.Vector2D(v);\n    return this.transform(CSG.Matrix4x4.translation(v.toVector3D(0)));\n  },\n  \n  scale: function(f) {\n    f=new CSG.Vector2D(f);\n    return this.transform(CSG.Matrix4x4.scaling(f.toVector3D(1)));\n  },\n  \n  rotate: function(deg) {\n    return this.transform(CSG.Matrix4x4.rotationZ(deg));\n  },    \n  \n  // convert into a CSG.Polygon; set z coordinate to the given value\n  toPolygon3D: function(z) {\n    var points3d=[];\n    this.points.map( function(p) {\n      var vec3d = p.toVector3D(z);      \n      points3d.push(vec3d);\n    });\n    return CSG.Polygon.createFromPoints(points3d, this.shared);\n  },\n  \n  // extruded=shape2d.extrude({offset: [0,0,10], twistangle: 360, twiststeps: 100});\n  // linear extrusion of 2D polygon, with optional twist\n  // The 2d polygon is placed in in z=0 plane and extruded into direction <offset> (a CSG.Vector)\n  // The final face is rotated <twistangle> degrees. Rotation is done around the origin of the 2d shape (i.e. x=0, y=0)\n  // twiststeps determines the resolution of the twist (should be >= 1)  \n  // returns a CSG object\n  extrude: function(params) {\n    // parse parameters:\n    if(!params) params={};\n    var offsetvector;\n    if(\"offset\" in params)\n    {\n      offsetvector = new CSG.Vector(params.offset); // reparse as a CSG.Vector\n    }\n    else\n    {\n      offsetvector = new CSG.Vector(0,0,1);\n    }\n    \n    var twistangle=0;\n    if(\"twistangle\" in params)\n    {\n      twistangle = params.twistangle;\n    }\n    \n    var twiststeps=10;\n    if(\"twiststeps\" in params)\n    {\n      twiststeps = params.twiststeps;\n    }\n    if(twistangle == 0) twiststeps=1;\n    if(twiststeps < 1) twiststeps=1;\n\n    // create the polygons:        \n    var newpolygons = [];\n    \n    // bottom face polygon:\n    var bottomfacepolygon = this.toPolygon3D(0);\n    var direction = bottomfacepolygon.plane.normal.dot(offsetvector);\n    if(direction > 0)\n    {\n      bottomfacepolygon.flip();\n    }\n    newpolygons.push(bottomfacepolygon);\n    \n    var getTwistedPolygon = function(twiststep) {\n\n      var fraction = (twiststep + 1) / twiststeps;\n      var rotation = twistangle * fraction;\n      var offset = offsetvector.times(fraction);\n      var transformmatrix = CSG.Matrix4x4.rotationZ(rotation).multiply( CSG.Matrix4x4.translation(offset) );\n      var polygon = bottomfacepolygon.transform(transformmatrix);      \n      return polygon;\n\n    };\n\n    // create the side face polygons:\n    var numvertices = bottomfacepolygon.vertices.length;\n    var prevlevelpolygon = bottomfacepolygon;\n    for(var twiststep=0; twiststep < twiststeps; ++twiststep)\n    {\n      var levelpolygon = getTwistedPolygon(twiststep);\n      for(var i=0; i < numvertices; i++)\n      {\n        var sidefacepoints = [];\n        var nexti = (i < (numvertices-1))? i+1:0;\n        sidefacepoints.push(prevlevelpolygon.vertices[i].pos);\n        sidefacepoints.push(levelpolygon.vertices[i].pos);\n        sidefacepoints.push(levelpolygon.vertices[nexti].pos);\n        sidefacepoints.push(prevlevelpolygon.vertices[nexti].pos);\n        var sidefacepolygon=CSG.Polygon.createFromPoints(sidefacepoints, this.shared);\n        newpolygons.push(sidefacepolygon);\n      }\n      if(twiststep == (twiststeps -1) )\n      {\n        // last level; add the top face polygon:\n        levelpolygon.flip(); // flip so that the normal points outwards\n        newpolygons.push(levelpolygon);\n      }\n      prevlevelpolygon = levelpolygon;\n    }\n\n    return CSG.fromPolygons(newpolygons);\n  }\n};\n"
  },
  {
    "path": "app/scripts/lib/flood/flood.js",
    "content": "if (typeof define !== 'function') {\n    var define = require('amdefine')(module);\n}\n\n// Webworker context\nif (typeof require != 'function' && typeof window != \"object\") { \n\n\tvar FLOOD = {};\n\tvar define = function(x, y){\n\t\tif (typeof x === \"function\") FLOOD = x();\n\t\tif (typeof y === \"function\") FLOOD = y();\n\t};\n\n}\n\ndefine('FLOOD',function() {\n\n\t// initialize core types\n\tif (!FLOOD) var FLOOD = {};\n\n\tFLOOD.baseTypes = {};\n\tFLOOD.nodeTypes = {};\n\tFLOOD.internalNodeTypes = {};\n\n\tif (typeof Object.create !== 'function') {\n\t    Object.create = function (o) {\n\t        function F() {}\n\t        F.prototype = o;\n\t        return new F();\n\t    };\n\t}\n\n\t// partial function application\n\tFunction.prototype.curry = function() {\n    var fn = this, args = Array.prototype.slice.call(arguments);\n\n    return function() {\n      return fn.apply(this, args.concat(\n        Array.prototype.slice.call(arguments)));\n    };\n  };\n\n  Function.prototype.partial = function(){\n    var fn = this, args = Array.prototype.slice.call(arguments);\n    return function(){\n      var arg = 0;\n      for ( var i = 0; i < args.length && arg < arguments.length; i++ )\n        if ( args[i] === undefined )\n          args[i] = arguments[arg++];\n      return fn.apply(this, args);\n    };\n  };\n\n\tArray.prototype.remove = function(from, to) {\n\t  var rest = this.slice((to || from) + 1 || this.length);\n\t  this.length = from < 0 ? this.length + from : from;\n\t  return this.push.apply(this, rest);\n\t};\n\n\tArray.prototype.last = function() {\n\t    return this[this.length-1];\n\t}\n\n\tFunction.prototype.method = function (name, func) {\n\t    this.prototype[name] = func;\n\t    return this;\n\t};\n\n\tFunction.method('inherits', function (parent) {\n\t    this.prototype = new parent();\n\t    var d = {}, \n\t        p = this.prototype;\n\t    this.prototype.constructor = parent; \n\t    return this;\n\t});\n\n\t// MultiOutResult\n\t// ===========\n\t//\n\n\tfunction MultiOutResult(object){\n\t\tfor (var i in object){\n\t\t\tthis[i] = object[i];\n\t\t}\n\t};\n\tMultiOutResult.prototype = new Object();\n\n\tMultiOutResult.wrap = function(){\n\n\t\tif (arguments.length === 0) return undefined;\n\n\t\treturn arguments.length === 1 ? arguments[0] : \n\t\t\tnew FLOOD.MultiOutResult( arguments );\n\n\t};\n\n\tMultiOutResult.prototype.constructor = MultiOutResult;\n\tFLOOD.MultiOutResult = MultiOutResult;\n\n\t// QuotedArray\n\t// ===========\n\t// QuotedArray is a slight modification of Array.  It makes it \n\t// clear to the interpreter whether we're intending to pass\n\t// an expression Array or an Array as a value.  The interpreter checks\n\t// the constructor function in order to check the type.\n\n\tfunction QuotedArray(){\n\t\tArray.apply(this, arguments);\n\t};\n\n\tQuotedArray.prototype = new Array();\n\tQuotedArray.prototype.toString = function(){\n\t\tif (this.length === 0) return \"[]\";\n\t\tvar eles = []; \n\t\tfor (var i = 0; i < this.length; i++){\n\t\t\teles.push( this[i] );\n\t\t}\n\t\treturn \"[ \" + eles.join(\", \") + \" ]\"\n\t};\n\n\tArray.prototype.flatten = function(){\n\n\t\tif (this.length === 0) return [];\n\n\t\tif ( isObjectTypeMatch( this[0], Array) ){\n\t\t\treturn this[0].flatten().concat( this.slice(1).flatten() );\n\t\t} \n\n\t\treturn [ this[0] ].concat( this.slice(1).flatten() );\n\t};\n\n\tArray.prototype.toQuotedArray = function(){\n\n\t\tvar qa = new QuotedArray();\n\t\tfor (var i = 0; i < this.length; i++){\n\t\t\tqa.push( this[i].toQuotedArray ? this[i].toQuotedArray() : this[i] );\n\t\t}\n\t\treturn qa;\n\t};\n\n\tQuotedArray.prototype.constructor = QuotedArray;\n\tFLOOD.QuotedArray = QuotedArray;\n\n\tFLOOD.baseTypes.NodeType = function(options) {\n\n\t\tvar that = this;\n\t\tvar options = options || {};\n\t\tthis.replication = options.replication || \"applyLongest\";\n\n\t\t// tell the inputs about their parent node & index\n\t\tif (options.inputs) {\n\t\t\toptions.inputs.forEach( function(e, i) {\n\t\t\t\te.parentNode = that;\n\t\t\t\te.parentIndex = i;\n\t\t\t});\n\n\t\t\tthis.inputs = options.inputs;\n\t\t} else {\n\t\t\tthis.inputs = [];\n\t\t}\n\n\t\t// tell the outputs about their parent node & index\n\t\tif (options.outputs) {\n\t\t\toptions.outputs.forEach( function(e, i) {\n\t\t\t\te.parentNode = that;\n\t\t\t\te.parentIndex = i;\n\t\t\t});\n\n\t\t\tthis.outputs = options.outputs;\n\t\t} else {\n\t\t\tthis.outputs = [];\n\t\t}\n\n\t\tthis.typeName = options.typeName || \"noTypeName\";\n\n\t\tvar _isDirty = true;\n\n\t\tthis.extend = function(args){\n\n\t\t}\n\n\t\tthis.alwaysDirty = false;\n\t\tthis.doPostProcess = true;\n\n\t\tthis.isDirty = function() {\n\t\t\treturn this.alwaysDirty ? true : _isDirty;\n\t\t};\n\n\t\tthis.markClean = function() {\n\t\t\t_isDirty = false;\n\t\t};\n\n\t\tthis.setDirty = function() {\n\t\t\t_isDirty = true;\n\t\t};\n\n\t\tthis.inputTypes = function(){\n\t\t\treturn this.inputs.map(function(x){ return x.type; });\n\t\t};\n\n\t\tthis.getIndexOfInputNode = function( otherNode ){\n\t\t\tfor (var i = 0; i < this.inputs.length; i++){\n\t\t\t\tif ( this.inputs[i].isConnectedTo( otherNode ) ) return i;\n\t\t\t}\n\n\t\t\treturn -1;\n\t\t};\n\n\t\tthis.markDirty = function() {\n\n\t\t\t_isDirty = this.inputs.reduce(function(m, n){ \n\n\t\t\t\t// there's nothing connected to this port\n\t\t\t\tif ( !n.oppNode ){\n\t\t\t\t\treturn m;\n\t\t\t\t}\n\n\t\t\t\treturn n.oppNode.markDirty() || m; \n\n\t\t\t}, false) || _isDirty;\n\t\t\treturn _isDirty;\n\n\t\t};\n\n\t\tthis.printExpression = function() { \n\t\t\treturn \"(\" + this.typeName + \" \" + this.inputs.map(function(n){ return n.printExpression(); }).join(' ') + \")\";\t\t\t\t\t\n\t\t};\n\n\t\tthis.addInputPort = function(name, type, defaultVal){\n\t\t\tthis.inputs.push( new FLOOD.baseTypes.InputPort( name, type, defaultVal, this, this.inputs.length ) );\n\t\t}\n\n\t\tthis.addOutputPort = function(name, type){\n\t\t\tthis.outputs.push( new FLOOD.baseTypes.OutputPort( name, type, this, this.outputs.length ) );\n\t\t}\n\n\t\tthis.evalComplete = function() {};\n\t\tthis.evalFailed = function() {};\n\t\tthis.evalBegin = function() {};\n\n\t\tthis.compile = function() { \n\t\t\t\n\t\t\tvar that = this;\n\n\t\t\tvar partialEvalClosure = (function() { \n\n\t\t\t\t\t// if we have enough args, eval, otherwise return function\n\t\t\t\t\treturn function() {\n\n\t\t\t\t\t\tvar dirty = that.isDirty();\n\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\tthat.evalBegin(that, dirty);\n\n\t\t\t\t\t\t\tif ( dirty ){\n\n\t\t\t\t\t\t\t\t// if any argument is undefined, perform partial function application\n\t\t\t\t\t\t\t\tvar noUndefinedArgs = true;\n\t\t\t\t\t\t\t\tfor (var i = 0; i < arguments.length; i++){\n\t\t\t\t\t\t\t\t\tif ( arguments[i] === undefined ){\n\t\t\t\t\t\t\t\t\t\tnoUndefinedArgs = false;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (noUndefinedArgs){ \n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t// build replication options and types\n\t\t\t\t\t\t\t\t\tvar options = {\n\t\t\t\t\t\t\t\t\t\treplication: that.replication,\n\t\t\t\t\t\t\t\t\t\texpected_arg_types: that.inputTypes()\n\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t// actually evaluate the function!\n\t\t\t\t\t\t\t\t\t\tthat.value = that.eval.mapApply(that, Array.prototype.slice.call(arguments, 0), options);\n\t\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\t\tthat.value = null;\n\t\t\t\t\t\t\t\t\t\tthat.evalFailed(that, e);\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t} else { \n\t\t\t\t\t\t\t\t\t// return a partial function application\n\t\t\t\t\t\t\t\t\tvar originalArgs = arguments;\n\t\t\t\t\t\t\t\t\tthat.value = (function(){\n\t\t\t\t\t\t\t\t\t\t// return a closure\n\t\t\t\t\t\t\t\t\t\treturn function(){\n\t\t\t\t\t\t\t\t\t\t\treturn that.eval.partial.apply(that.eval, originalArgs).apply(that, arguments);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t})();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tthat.markClean();\n\n\t\t\t\t\t\t\t\tif ( that.doPostProcess && that.postProcess ){\n\t\t\t\t\t\t\t\t\tthat.prettyValue = that.postProcess( that.value );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// tell listeners that the evalation is complete\n\t\t\t\t\t\t\tthat.evalComplete( that, arguments, dirty, that.value, that.prettyValue );\n\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthat.evalFailed(that, e);\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// yield the value\n\t\t\t\t\t\treturn that.value;\n\t\t\t\t\t};\n\n\t\t\t})();\n\n\t\t\t// return an s-expression, represented by the function to execute, and the list\n\t\t\t// of arguments to apply to it\n\t\t\treturn [partialEvalClosure].concat( this.inputs.map(function(input){\n\t\t\t\treturn input.compile();\n\t\t\t}));\n\t\t\n\t\t};\n\n\t}\n\n\tFLOOD.baseTypes.NodePort = function(name, type, parentNode, parentIndex, oppNode, oppIndex) {\n\t\t\n\t\tfunction constructPortTypeName(type) { \n\t\t\tif (!type) return;\n\t\t\tif (type instanceof Array) return type.map( constructPortTypeName ).join(\" of \");\n\t\t\tif (type.floodTypeName) return type.floodTypeName;\n\n\t\t\tvar funcNameRegex = /function (.{1,})\\(/;\n\t\t\tvar results = (funcNameRegex).exec(type.toString());\n\t\t\treturn (results && results.length > 1) ? results[1] : \"\";\n\t\t};\n\n\t\tthis.name = name;\n\t\tthis.type = type;\n\t\tthis.typeName = constructPortTypeName( type );\n\t\tthis.parentNode = parentNode;\n\t\tthis.parentIndex = parentIndex != undefined ? parentIndex : 0;\n\t\tthis.oppNode = oppNode;\n\t\tthis.oppIndex = oppIndex != undefined ? oppIndex : 0;\n\n\t};\n\n\tFLOOD.baseTypes.OutputPort = function(name, type, parentNode, parentIndex, oppNode, oppIndex) {\n\t\t\n\t\tFLOOD.baseTypes.NodePort.call(this, name, type, parentNode, parentIndex, oppNode, oppIndex );\n\n\t\tthis.value = function(){\n\t\t\tif ( !(this.parentNode.value instanceof Array) )\n\t\t\t\treturn this.parentNode.value;\n\t\t\treturn this.parentNode.value[this.parentIndex];\n\t\t};\n\n\t\tthis.asInputPort = function(parentNode, parentIndex, defaultVal) {\n\t\t\treturn new FLOOD.baseTypes.InputPort( this.name, this.type, defaultVal, parentNode, parentIndex );\n\t\t}\n\n\t}.inherits( FLOOD.baseTypes.NodePort );\n\n\tFLOOD.baseTypes.InputPort = function(name, type, defaultVal, parentNode, parentIndex, oppNode, oppIndex) {\n\n\t\tFLOOD.baseTypes.NodePort.call(this, name, type, parentNode, parentIndex, oppNode, oppIndex );\n\t\tthis.defaultVal = defaultVal;\n\t\tthis.useDefault = defaultVal === undefined ? false : true;\n\n\t\tthis.printExpression = function() {\n\t\t\tif (this.oppNode && this.oppIndex === 0 && this.oppNode.outputs.length === 1)\n\t\t\t\treturn this.oppNode.printExpression();\n\t\t\tif (this.oppNode)\n\t\t\t\treturn '(pick ' + this.oppIndex + ' ' + this.oppNode.printExpression() + ')';\n\t\t\tif (this.useDefault === true )\n\t\t\t\treturn this.defaultVal;\n\t\t\treturn \"_\";\n\t\t}\n\n\t\tvar autoPick = function(name, x){\n\n\t\t\tif ( isObjectTypeMatch(x, QuotedArray) ){\n\t\t\t\treturn x.map( autoPick.curry( name ) );\n\t\t\t} else if ( isObjectTypeMatch(x, MultiOutResult ) ){\n\t\t\t\treturn x[name] != undefined ? x[name] : null;\n\t\t\t}\n\n\t\t\treturn null;\n\t\t};\n\n\t\tthis.compile = function() {\n\n\t\t\tvar val = null;\n\n\t\t\tif (this.oppNode && this.oppIndex === 0 && this.oppNode.outputs.length === 1){\n\t\t\t\tval = this.oppNode.compile();\n\t\t\t\treturn val;\n\t\t\t} else if (this.oppNode){\n\t\t\t\tval = [ autoPick, this.oppIndex, this.oppNode.compile() ];\n\t\t\t\treturn val;\n\t\t\t} else if (this.useDefault === true) {\n\t\t\t\tval = this.defaultVal;\n\t\t\t\treturn val;\n\t\t\t}\n\n\t\t\t// undefined value causes partial function application\n\t\t\treturn undefined;\n\t\t}\n\n\t\tthis.isConnectedTo = function( otherNode ){\n\t\t\treturn this.oppNode === otherNode;\n\t\t}\n\n\t\tthis.connect = function(otherNode, outIndexOnOtherNode){\n\t\t\tthis.oppNode = otherNode;\n\t\t\tthis.oppIndex = outIndexOnOtherNode != undefined ? outIndexOnOtherNode : 0;\n\t\t\tthis.parentNode.setDirty();\n\t\t}\n\n\t\tthis.disconnect = function(){\n\t\t\tthis.oppNode = null;\n\t\t\tthis.oppIndex = 0;\n\t\t\tthis.parentNode.setDirty();\n\t\t}\n\n\t}.inherits( FLOOD.baseTypes.NodePort );\n\n\tFLOOD.internalNodeTypes.CustomNode = function(functionName, functionId, lambda) {\n\n\t\tvar typeData = {\n\t\t\ttypeName: \"CustomNode\"\n\t\t};\n\n\t\tthis.functionName = functionName;\n\t\tthis.functionId = functionId;\n\t\tthis.lambda = lambda;\n\n\t\tif (scheme) var S = new scheme.Interpreter();\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function() {\n\n\t\t\tthis.lambda = FLOOD.environment[this.functionId];\n\n\t\t\tif ( !this.lambda ) throw new Error(\"The custom node is not yet compiled.\");\n\n\t\t\tvar args = Array.prototype.slice.call(arguments, 0);\n\t\t\tvar exp = [ this.lambda ].concat(args) ;\n\n\t\t\treturn S.eval( exp );\n\n\t\t};\n\n\t\tthis.printExpression = function() { \n\t\t\treturn \"(\" + this.functionName + \" \" + this.inputs.map(function(n){ return n.printExpression(); }).join(' ') + \")\";\t\t\t\t\t\n\t\t};\n\n\t\tthis.extend = function(args){\n\n\t\t\tif (args.functionName && typeof args.functionName === \"string\"){\n\t\t\t\tthis.functionName = args.functionName;\n\t\t\t}\n\n\t\t\tif (args.functionId && typeof args.functionId === \"string\"){\n\t\t\t\tthis.functionId = args.functionId;\n\t\t\t}\n\n\t\t\tif (args.numInputs && typeof args.numInputs === \"number\" ){\n\t\t\t\tthis.setNumInputs(args.numInputs);\n\t\t\t}\n\n\t\t\tif (args.numOutputs && typeof args.numOutputs === \"number\" ){\n\t\t\t\tthis.setNumOutputs(args.numOutputs);\n\t\t\t}\n\n\t\t};\n\n\t\tvar that = this;\n\n\n\t\tthis.setInputTypes = function( inputTypes ){\n\n\t\t\tfor (var i = 0; i < this.inputs.length; i++) \n\t\t\t\tthis.inputs[i].type = inputTypes[i];\n\n\t\t};\n\n\t\tthis.setNumInputs = function( num ){\n\n\t\t\tif (typeof num != \"number\" || num < 0 || this.inputs.length === num) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (this.inputs.length < num) addInput();\n\t\t\tif (this.inputs.length > num) removeInput();\n\n\t\t\tthis.setNumInputs( num );\n\t\t};\n\n\t\tthis.setNumOutputs = function( num ){\n\n\t\t\tif (typeof num != \"number\" || num < 0 || this.outputs.length === num) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (this.outputs.length < num) addOutput();\n\t\t\tif (this.outputs.length > num) removeOutput();\n\n\t\t\tthis.setNumOutputs( num );\n\t\t};\n\n\t\tvar addInput = function(){\n\t\t\tvar port = new FLOOD.baseTypes.InputPort( characters[ that.inputs.length ], [AnyTypeButQuotedArray], 0 );\n\t\t\tport.parentNode = that;\n\t\t\tport.parentIndex = that.inputs.length;\n\t\t\tthat.inputs.push( port );\n\t\t};\n\n\t\tvar removeInput = function(){\n\t\t\tif (that.inputs.length === 0) return;\n\t\t\tthat.inputs.pop();\n\t\t};\n\n\t\tvar addOutput = function(){\n\t\t\tvar port = new FLOOD.baseTypes.OutputPort( characters[ that.outputs.length ], [AnyType] );\n\t\t\tport.parentNode = that;\n\t\t\tport.parentIndex = that.outputs.length;\n\t\t\tthat.outputs.push( port );\n\t\t};\n\n\t\tvar removeOutput = function(){\n\t\t\tif (that.outputs.length === 0) return;\n\t\t\tthat.outputs.pop();\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.internalNodeTypes.CustomNode.nodesOfType = function(type, nodes){\n\n\t\treturn nodes.filter(function(x){\n\t\t\treturn x instanceof type;\n\t\t});\n\t};\n\n\tFLOOD.internalNodeTypes.CustomNode.findInputTypes = function(nodes){\n\n\t\tvar inputNodes = FLOOD.internalNodeTypes.CustomNode.nodesOfType( FLOOD.nodeTypes.Input, nodes );\n\n\t\treturn inputNodes.map(function(inode, index){\n\n\t\t\t// get all of the types for all connections to this one\n\t\t\tvar allPotentialTypes = nodes.reduce(function(agg, node){\n\n\t\t\t\tvar con = node.getIndexOfInputNode( inode );\n\t\t\t\tif (con < 0) return agg;\n\n\t\t\t\tagg.push( node.inputs[con].type );\n\t\t\t\treturn agg;\n\n\t\t\t}, []);\n\t\t\t\n\t\t\t// check if input port is not connected - if so, short-circuit\n\t\t\tif (allPotentialTypes.length === 0) return AnyTypeButQuotedArray;\n\n\t\t\t// each type is an array - the last position is the concrete type\n\t\t\tvar typeToMatch = allPotentialTypes[0];\n\t\t\tvar firstConcreteType = typeToMatch.last();\n\n\t\t\t// assert all types match\n\t\t\tallPotentialTypes.map(function(t){\n\t\t\t\treturn t.last();\n\t\t\t}).forEach(function(t){\n\n\t\t\t\tif ( t === firstConcreteType ||\n\t\t\t\t\t\t t === AnyType ||\n\t\t\t\t\t\t t === AnyTypeButQuotedArray ) return;\n\n\t\t\t\tthrow new TypeError(\"One of the inputs is connected to multiple nodes with incompatible types!\")\n\n\t\t\t});\n\n\t\t\t// get the most complex type, this is simply the longest array\n\t\t\tvar maxLen = 0;\n\t\t\tvar idMax = -1;\n\t\t\tfor (var i = allPotentialTypes.length - 1; i >= 0; i--) {\n\t\t\t\tif ( allPotentialTypes[i].length > maxLen ) {\n\t\t\t\t\tidMax = i;\n\t\t\t\t\tmaxLen = allPotentialTypes[i].length;\n\t\t\t\t} \n\t\t\t};\n\n\t\t\treturn allPotentialTypes[maxLen];\n\n\t\t});\n\t};\n\n\tFLOOD.internalNodeTypes.CustomNode.compileNodesToLambda = function(nodes){\n\n\t\t// find all input nodes\n\t\tvar inputNodes = nodes.filter(function(x){\n\t\t\treturn x instanceof FLOOD.nodeTypes.Input;\n\t\t});\n\n\t\t// find all output nodes\n\t\tvar outputNodes = nodes.filter(function(x){\n\t\t\treturn x instanceof FLOOD.nodeTypes.Output;\n\t\t});\n\n\t\t// compile the input nodes, forming the arg list\n\t\tvar args = inputNodes.map(function(x){\n\t\t\treturn x.compile();\n\t\t});\n\n\t\t// compile the output nodes, forming the internal value expressions\n\t\tvar internalExp = outputNodes.map( function(x){ return x.compile(); });\n\n\t\t// we need a function to box up the internal expression\n\t\t// in a dictionary if there are multiple outputs\n\t\tvar boxedExp = internalExp.length > 1 ? \n\t\t\t[ FLOOD.MultiOutResult.wrap ].concat( internalExp ) : internalExp[0];\n\n\t\t// nodes in a custom node do not cache their value\n\t\tnodes.forEach(function(x){ x.alwaysDirty = true; });\n\n\t\t// ( lambda (args) boxedExp )\n\t\treturn [\"lambda\", args, boxedExp];\n\t};\n\n\tFLOOD.nodeTypes.Number = function() {\n\n\t\tvar typeData = {\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [Number] ) ],\n\t\t\ttypeName: \"Number\" \n\t\t};\n\n\t\tthis.lastValue = 0;\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData);\n\n\t\tthis.printExpression = function(){\n\t\t\treturn this.lastValue;\n\t\t};\n\n\t\tthis.compile = function(){\n\t\t\tthis.markClean();\n\t\t\treturn this.lastValue;\n\t\t}\n\n\t\tthis.extend = function(args){\n\n\t\t\tif (args.value != undefined && typeof args.value === \"number\"){\n\t\t\t\tthis.lastValue = args.value;\n\t\t\t} else {\n\t\t\t\tthis.lastValue = 0;\n\t\t\t}\n\t\n\t\t}\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tvar characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\tvar currentInputChar = 0;\n\n\tFLOOD.nodeTypes.Script = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [AnyTypeButQuotedArray], 0 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyType] ) ],\n\t\t\ttypeName: \"Script\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData);\n\n\t\tvar csgPostProcess = function(value){\n\n\t\t\tif (!value) return {};\n\n\t\t\tif ( value.map ) {\n\n\t\t\t\tvar d = [];\n\t\t\t\tfor (var i = 0; i < value.length; i++){\n\t\t\t\t\tif (value[i] === undefined) continue;\n\t\t\t\t\td.push( value[i].render ? value[i].render() : value[i] );\n\t\t\t\t}\n\n\t\t\t\treturn d;\n\t\t\t}\n\n\t\t\tif (!value.render) return value;\n\n\t\t\treturn value.render();\n\n\t\t};\n\n\t\tthis.postProcess = csgPostProcess;\n\n\t\t// extend the environment for formula implementers convenience\n\t\tvar Sin = Math.sin, Cos = Math.cos, Abs = Math.abs, Tan = Math.tan, Random = Math.random,\n\t\t\tAsin = Math.asin, Atan = Math.atan, Acos = Math.acos, Exp = Math.exp, Sqrt = Math.sqrt,\n\t\t\tPow = Math.pow, Pi = Math.PI, Eval = eval;\n\n\t\t// extend the environment with all of the node types\n\t\tvar e = \"\";\n\t\tfor (var nt in FLOOD.nodeTypes){\n\t\t\te = e + \"var \" + nt + \" = function(){ return (new FLOOD.nodeTypes.\" + nt + \").eval.apply(this, arguments); };\";\t\t\t\t\n\t\t}\n\n\t\teval(e);\n\n\t\tthis.eval = function() {\n\t\t\tvar _fa = Array.prototype.slice.call(arguments, 0);\n\t\t\tvar val = eval( this.expression );\n\n\t\t\t// if array value, quote it\n\t\t\tif (val instanceof Array) return val.toQuotedArray();\n\t\t\treturn val;\n\t\t};\n\n\t\tthis.script = \"A;\";\n\t\tthis.portNames = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n\n\t\tthis.extend = function(args){\n\n\t\t\tif (args.script && typeof args.script === \"string\"){\n\t\t\t\tthis.script = args.script;\n\t\t\t\tcompileExpression();\n\t\t\t}\n\n\t\t\tif (args.numInputs && typeof args.numInputs === \"number\" ){\n\t\t\t\tthis.setNumInputs(args.numInputs);\n\t\t\t}\n\n\t\t}\n\n\t\tthis.setNumInputs = function( numInputs ){\n\n\t\t\tif (typeof numInputs != \"number\" || numInputs < 0 || this.inputs.length === numInputs) {\n\t\t\t\treturn compileExpression();\n\t\t\t}\n\n\t\t\tif (this.inputs.length < numInputs) addFormulaInput();\n\t\t\tif (this.inputs.length > numInputs) removeFormulaInput();\n\n\t\t\tthis.setNumInputs( numInputs );\n\t\t}\n\n\t\tvar that = this;\n\n\t\tvar prefix = function(){\n\n\t\t\tvar inputNames = that.inputs.map(function(x){\n\t\t\t\treturn x.name;\n\t\t\t}).join(',');\n\n\t\t\treturn '(function('+ inputNames + ')' + '{ return ';\n\t\t};\n\n\t\tvar suffix = function(){\n\n\t\t\tvar argNames = that.inputs.map(function(x,i){\n\t\t\t\treturn \"_fa[\" + i + \"]\";\n\t\t\t}).join(',');\n\n\t\t\treturn '}(' + argNames + '))';\n\t\t};\n\n\t\tvar compileExpression = function(){\n\t\t\tthat.expression = prefix() + that.script + suffix();\n\t\t\treturn that.expression;\n\t\t};\n\n\t\tvar addFormulaInput = function(){\n\t\t\tvar port = new FLOOD.baseTypes.InputPort( that.portNames[ that.inputs.length ], [AnyTypeButQuotedArray], 0 );\n\t\t\tport.parentNode = that;\n\t\t\tport.parentIndex = that.inputs.length;\n\t\t\tthat.inputs.push( port );\n\t\t};\n\n\t\tvar removeFormulaInput = function(){\n\t\t\tif (that.inputs.length === 0) return;\n\t\t\tthat.inputs.pop();\n\t\t};\n\n\t\tcompileExpression();\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.Pi = function() {\n\n\t\tvar typeData = {\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [Number] ) ],\n\t\t\ttypeName: \"Pi\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData);\n\n\t\tthis.eval = function(){\n\t\t\treturn Math.PI;\n\t\t}\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.Show = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Anything\", [AnyType], null ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyType] ) ],\n\t\t\ttypeName: \"Show\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.value = 0;\n\n\t\tthis.eval = function(a) {\n\t\t\treturn a;\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.Add = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [Number], 0 ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [Number], 0 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [Number] ) ],\n\t\t\ttypeName: \"Add\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\n\t\t\treturn a + b;\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.Subtract = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [Number], 0 ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [Number], 0 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [Number] ) ],\n\t\t\ttypeName: \"Subtract\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a - b;\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.Multiply = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [Number], 0 ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [Number], 0 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [Number] ) ],\n\t\t\ttypeName: \"Multiply\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a * b;\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.Divide = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [Number], 0 ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [Number], 0 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [Number] ) ],\n\t\t\ttypeName: \"Divide\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a / b;\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.Negate = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [Number], 1 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [Number] ) ],\n\t\t\ttypeName: \"Negate\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a) {\n\t\t\treturn -1 * a;\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.Equal = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [AnyTypeButQuotedArray], 0 ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [AnyTypeButQuotedArray], 0 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [Boolean] ) ],\n\t\t\ttypeName: \"Equal\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a === b;\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.GreaterThan = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [Number], 0 ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [Number], 0 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [Boolean] ) ],\n\t\t\ttypeName: \"GreaterThan\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a > b;\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.LessThan = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [Number], 0 ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [Number], 0 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [Boolean] ) ],\n\t\t\ttypeName: \"LessThan\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a < b;\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.LessThanOrEqual = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [Number], 0 ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [Number], 0 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [Boolean] ) ],\n\t\t\ttypeName: \"LessThanOrEqual\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a <= b;\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.GreaterThanOrEqual = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [Number], 0 ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [Number], 0 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [Boolean] ) ],\n\t\t\ttypeName: \"GreaterThanOrEqual\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a >= b;\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.Input = function(name) {\n\n\t\tvar typeData = {\n\t\t\ttypeName: \"Input\",\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyTypeButQuotedArray] ) ],\n\t\t};\n\n\t\tif (name === undefined) name = characters[currentInputChar++];\n\n\t\tthis.name = name;\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData);\n\n\t\tthis.compile = function() {\n\t\t\treturn this.name;\n\t\t}\n\n\t\tthis.printExpression = function(){\n\t\t\treturn this.name;\n\t\t}\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tvar currentOutputChar = 0;\n\n\tFLOOD.nodeTypes.Output = function(name) {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"⇒\", [AnyType] ) ],\n\t\t\ttypeName: \"Output\"\n\t\t};\n\n\t\tif (name === undefined) name = characters[currentOutputChar++];\n\n\t\tthis.name = name;\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData);\n\n\t\tthis.compile = function() {\n\t\t\treturn this.inputs[0].compile();\n\t\t}\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.Range = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Min\", [Number], 0.0 ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Max\", [Number], 1.0 ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Steps\", [Number], 10 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [QuotedArray, Number] ) ],\n\t\t\ttypeName: \"Range\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(min, max, steps) {\n\n\t\t\tif (min > max) throw new Error('Max must be greater than Min!');\n\t\t\tif (steps <= 0) throw new Error('The Steps must be greater than 0.');\n\t\t\tif (min === max) throw new Error('Min is equal to Max!');\n\n\t\t\tvar range = new QuotedArray();\n\n\t\t\tif (steps > 1){\n\t\t\t\tvar stepSize = (max - min) / (steps-1);\n\t\t\t\tfor (var i = 0; i < steps-1; i++){\n\t\t\t\t\trange.push(min + i * stepSize);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trange.push(max);\n\n\t\t\treturn range;\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.Steps = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Min\", [Number], 0.0 ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Max\", [Number], 1.0 ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"StepSize\", [Number], 0.1 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [QuotedArray, Number] ) ],\n\t\t\ttypeName: \"Steps\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(min, max, stepSize) {\n\n\t\t\tif (min > max) throw new Error('Max must be greater than Min!');\n\t\t\tif (stepSize <= 1e-6 ) throw new Error('The StepSize is less than 0.');\n\t\t\tif (min === max) throw new Error('Min is equal to Max!');\n\n\t\t\tvar range = new QuotedArray();\n\n\n\t\t\tvar step = min;\n\n\t\t\twhile (step <= max){\n\t\t\t\trange.push(step);\n\t\t\t\tstep += stepSize;\n\t\t\t}\n\n\t\t\treturn range;\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.Repeat = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Value\", [AnyType], 0 ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Count\", [Number], 0 )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [QuotedArray, AnyType] ) ],\n\t\t\ttypeName: \"Repeat\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(v, t) {\n\n\t\t\tvar a = new QuotedArray();\n\n\t\t\tif ( t > 0 ) for (var i = 0; i < t; i++) a.push(v);\n\t\t\treturn a;\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.ListLength = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"List\", [QuotedArray, AnyType] )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [Number] ) ],\n\t\t\ttypeName: \"ListLength\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(l) {\n\t\t\treturn l.length;\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.ListFirst = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"List\", [QuotedArray, AnyType] )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyType] ) ],\n\t\t\ttypeName: \"ListFirst\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(l) {\n\t\t\treturn l[0];\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.ListLast = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"List\", [QuotedArray, AnyType] )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyType] ) ],\n\t\t\ttypeName: \"ListLast\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(l) {\n\t\t\tif (l.length === 0) return null;\n\t\t\treturn l[l.length-1];\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.ListRest = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"List\", [QuotedArray, AnyType] )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyType] ) ],\n\t\t\ttypeName: \"ListRest\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(l) {\n\t\t\tif (l.length <= 1) return [].toQuotedArray();\n\t\t\treturn l.slice(1).toQuotedArray();\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.ListAddToFront = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Item\", [AnyTypeButQuotedArray] ), \n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"List\", [QuotedArray, AnyType] )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyType] ) ],\n\t\t\ttypeName: \"ListAddToFront\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(i, l) {\n\t\t\treturn [i].concat(l).toQuotedArray();\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.ListItemAtIndex = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"List\", [QuotedArray, AnyType] ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Index\", [Number] )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyType] ) ],\n\t\t\ttypeName: \"ListItemAtIndex\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(l, i) {\n\t\t\treturn l[i];\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.ListReverse = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"List\", [QuotedArray, AnyType], new QuotedArray() )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyType] ) ],\n\t\t\ttypeName: \"ListReverse\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(L) {\n\t\t\treturn L.slice(0).reverse().toQuotedArray();\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.ListSort = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Function\", [Function], function(a){ return a; } ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"List\", [QuotedArray, AnyType], new QuotedArray() )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [QuotedArray, AnyType] ) ],\n\t\t\ttypeName: \"ListSort\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(F, L) {\n\n\t\t\treturn L.sort(F).toQuotedArray();\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.ListMap = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Function\", [Function], function(a){ return a; } ),\n\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"List\", [QuotedArray, AnyType] ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [QuotedArray, AnyType] ) ],\n\t\t\ttypeName: \"ListMap\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(F, L) {\n\n\t\t\treturn L.map(F).toQuotedArray();\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.ListDivide = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"List\", [QuotedArray, AnyType] ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Length\", [Number], 1 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [QuotedArray, AnyType] ) ],\n\t\t\ttypeName: \"ListDivide\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(l, d) {\n\n\t\t\tif (l.length === 0) return l;\n\t\t\tif (l.length <= d) return l;\n\t\t\tif (d < 1) return l;\n\n\t\t\tvar acc = new QuotedArray();\n\n\t\t\tfor (var i = 0; i < l.length; i+=d){\n\t\t\t\tif (i+d > l.length) break;\n\t\t\t\tacc.push( l.slice(i, i + d ).toQuotedArray() );\n\t\t\t}\n\n\t\t\treturn acc;\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.ListReduce = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Function\", [Function] ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"List\", [QuotedArray, AnyType] ), \n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Base\", [AnyType] ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyType] ) ],\n\t\t\ttypeName: \"ListReduce\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(F, L, A) {\n\n\t\t\treturn L.reduce(F, A);\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.ListFilter = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Function\", [Function] ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"List\", [QuotedArray, AnyType] )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyType] ) ],\n\t\t\ttypeName: \"ListFilter\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(F, L) {\n\n\t\t\treturn L.filter(F).toQuotedArray();\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.ListFlatten = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Function\", [QuotedArray, AnyType] )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [QuotedArray, AnyType] ) ],\n\t\t\ttypeName: \"ListFlatten\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a) {\n\n\t\t\treturn a.flatten().toQuotedArray();\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.StringToNumber = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"String\", [String] )] ,\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [Number] ) ],\n\t\t\ttypeName: \"StringToNumber\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(s) {\n\t\t\treturn parseFloat(s);\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.StringSplit = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"String\", [String], \" \" ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Delimiter\", [String], \",\") ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [QuotedArray, String] ) ],\n\t\t\ttypeName: \"StringSplit\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(s, d) {\n\n\t\t\treturn s.split(d).toQuotedArray();\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.StringSubString = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"String\", [String], \"\" ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Start\", [Number], 0),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Length\", [Number], -1) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [String] ) ],\n\t\t\ttypeName: \"StringSubString\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(s, st, l) {\n\n\t\t\tif (l < 0) \n\t\t\t\tl = undefined;\n\t\t\treturn s.substring(st, l);\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.Eval = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Code\", [String] ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyType] ) ],\n\t\t\ttypeName: \"Eval\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a) {\n\t\t\treturn eval( a );\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.Apply = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Function\", [Function] ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Arguments\", [QuotedArray, AnyType] ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyType] ) ],\n\t\t\ttypeName: \"Apply\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(f, a) {\n\t\t\treturn f.apply(this, a);\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.ApplyToLeaves = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Function\", [Function] ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Arguments\", [QuotedArray, AnyTypeButQuotedArray] ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyType] ) ],\n\t\t\ttypeName: \"ApplyToLeaves\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call( this, typeData );\n\n\t\tthis.eval = function(f, a) {\n\t\t\treturn f.apply(this, a);\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.internalNodeTypes.Begin = function() {\n\n\t\tvar typeData = {\n\t\t\ttypeName: \"begin\",\n\t\t\tisVisibleInLibrary: false\n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.compile = function() {\n\t\t\treturn [this.typeName].concat( this.inputs.map(function(input){\n\t\t\t\treturn input.compile();\n\t\t\t}));\n\t\t}\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.If = function() {\n\n\t\tvar typeData = {\n\t\t\ttypeName: \"if\",\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Test\", [AnyType], true ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Then\", [AnyType] ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Else\", [AnyType] ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [AnyType] ) ],\n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.compile = function() {\n\t\t\treturn [this.typeName, this.inputs[0].compile(), this.inputs[1].compile(), \n\t\t\t\tthis.inputs[2].compile() ];\n\t\t}\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\t// represents any type\n\tfunction AnyType() {};\n\tFLOOD.AnyType = AnyType;\n\n\tfunction AnyTypeButQuotedArray() {};\n\tFLOOD.AnyTypeButQuotedArray = AnyTypeButQuotedArray;\n\n\tFLOOD.isObjectTypeMatch = isObjectTypeMatch;\n\tFLOOD.isFastTypeMatch = isFastTypeMatch;\n\tFLOOD.doAllTypesMatch = doAllTypesMatch;\n\n\tfunction isObjectTypeMatch(arg, arg_type) {\n\n\t\tif ( arg_type === undefined || arg_type === null){\n\t\t\treturn true;\n\t\t}\n\n\t\tif (arg_type === AnyType){\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( arg === undefined || arg === null ){\n\t\t\treturn false;\n\t\t}\n\n\t\tif (arg_type === AnyTypeButQuotedArray && arg.constructor != QuotedArray){\n\t\t\treturn true;\n\t\t}\n\n\t\tif (arg_type === AnyType && arg.constructor === QuotedArray ){\n\t\t\treturn false;\n\t\t}\n\n\t\treturn arg.constructor === arg_type || arg instanceof arg_type;\n\n\t\t// NOTE: instanceof will return FALSE for numbers\n\t\t// if they aren't created with new.  This behavior\n\t\t// sucks, so we use the constructor.\n\n\t};\n\n  function isFastTypeMatch( arg, arg_type ){\n\t\n\t  // wrap with an arg array\n\t\tvar wrap_arg = [ arg ];\n\n\t\tfor (var j = 0; j < arg_type.length; j++){\n\n\t\t\t// \"fast\" means we only check the first element\n\t\t\twrap_arg = wrap_arg[0];\n\n\t\t\t// check its type, return early on fail\n\t\t\tif ( !isObjectTypeMatch( wrap_arg, arg_type[j] ) ){\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// all arg types are matched\n\t\treturn true;\n\n  };\n\n  // first arg is the arguments to the node\n  // second is the expected types\n  function doAllTypesMatch( node_args, expected_arg_types ){\n\n  \t// if no supplied, just use default js dispatch\n  \tif ( !expected_arg_types ){\n  \t\treturn true;\n  \t}\n\n  \t// if the Number of args and expected types don't match, return false\n  \tif (node_args.length != expected_arg_types.length){\n  \t\treturn false;\n  \t}\n\n  \t// for each arg type, check match with expected input types\n  \tfor (var i = 0; i < node_args.length; i++){\n  \t\t// do a fast type match\n  \t\tif ( !isFastTypeMatch(node_args[i], expected_arg_types[i]) ){\n  \t\t\treturn false;\n  \t\t}\n  \t}\n\n  \treturn true;\n  }\n\n  function allQuotedArrays( array ){\n\n  \tfor (var i = 0; i < array.length; i++){\n  \t\tif ( !(array[i] instanceof QuotedArray) ){\n  \t\t\treturn false;\n  \t\t}\n  \t}\n\n  \treturn true;\n\n  }\n\n  function newNestedQuotedArrayByElements(eles){\n\n  \tvar a = new QuotedArray();\n  \tfor (var i = 0; i < eles.length; i++){\n  \t\tvar b = new QuotedArray();\n  \t\tb.push(eles[i]);\n  \t\ta.push(b);\n  \t}\n\n  \treturn a;\n\n  }\n\n  Function.prototype.applyCartesian = function( this_arg, args, options ){\n\n  \t// initialize the argument lists\n  \tvar argmap = [];\n  \tif (args[0] instanceof Array){\n  \t\targs[0].map(function(x){\n  \t\t\targmap.push([ x ]);\n  \t\t})\n  \t} else {\n  \t\targmap.push( [ args[0] ] );\n  \t}\n\n  \t// for every arg position after first\n  \tfor (var i = 1; i < args.length; i++){\n\n  \t\tvar newmap = new QuotedArray();\n\n  \t\t// for every element in argmap\n  \t\tfor (var j = 0; j < argmap.length; j++){\n\n  \t\t\t// if arg position is not an array, just push the element\n  \t\t\tif ( !(args[i] instanceof Array) ){\n  \t\t\t\tnewmap.push( argmap[j].concat([ args[i] ]) );\n  \t\t\t\tcontinue;\n  \t\t\t}\n\n  \t\t\t// project each one of those previous elements as \n  \t\t\t// many times as their are args in new position\n  \t\t\tfor (var k = 0; k < args[i].length; k++){\n  \t\t\t\tnewmap.push( argmap[j].concat( [ args[i][k] ] ) );\n  \t\t\t}\n\n  \t\t}\n\n  \t\targmap = newmap;\n\n  \t}\n\n  \tvar results = new QuotedArray();\n\n  \tfor (var i = 0; i < argmap.length; i++){\n  \t\tresults.push( this.mapApply( this_arg, argmap[i], options ) );\n  \t}\n\t\t\n\t\treturn results;\n  }\n\n  Function.prototype.applyLongest = function( this_arg, args, options ){\n\n\t  // longest \n  \tvar length_array = args.map( function( a ){ \n\n  \t\tif (a instanceof Array) {\n  \t\t\treturn a.length;\n  \t\t} else {\n  \t\t\treturn -1; // return -1 if arg is not an array\n  \t\t}\n\n  \t});\n\n  \t// get the longest list array\n  \tvar max_length = Math.max.apply( Math, length_array );\n\n  \tvar result = new QuotedArray();\n  \tfor (var i = 0; i < max_length; i++){\n\n  \t\tvar this_node_args = [];\n  \t\tfor (var j = 0; j < args.length; j++){\t\n  \t\t\t\n  \t\t\tvar arg = args[j];\n  \t\t\tif ( arg instanceof QuotedArray){\n\n  \t\t\t\t// this may not be the longest, pick its length\n  \t\t\t\tvar arg_max_length = Math.min(max_length, arg.length ) - 1;\n  \t\t\t\tthis_node_args.push( args[j][ Math.min( i, arg_max_length )] );\n\n  \t\t\t} else {\n\n  \t\t\t\tthis_node_args.push( arg );\n\n  \t\t\t}\n  \t\t}\n\n  \t\tresult.push( this.mapApply(this_arg, this_node_args, options) );\n  \t}\n\n  \treturn result;\n\n  }\n\n  var prettyPrint = function(key, val){\n\n  \tif (val instanceof Array){ return val; }\n  \tif (typeof val === \"function\"){ return }\n\n  }\n\n  Function.prototype.mapApply = function( this_arg, args, options ){\n\n\t  options = options || {};\n\n\t  // check if args matches types expected for node inputs - if so, execute\n\t  if ( doAllTypesMatch( args, options.expected_arg_types ) ){\n\t  \treturn this.apply(this_arg, args);\n\t  } \n\n\t  var replicationType = options.replication || \"applyLongest\";\n\n\t  var result = this[ replicationType ](this_arg, args, options);\n\n\t  if (result.length === 0){\n\t  \tthrow new Error(\"The type of data you supplied to this node is incorrect! The ports were expecting: \" \n\t  \t\t\t+ this_arg.inputs.map(function(x){ return x.name + \":\" + x.typeName; }).join(\", \") );\n\t  }\n\n\t  return result;\n\n  }\n\n\n\n\n\treturn FLOOD;\n\n});\n\n\n\n\n\n\n"
  },
  {
    "path": "app/scripts/lib/flood/flood_csg.js",
    "content": "if (typeof define !== 'function') {\n    var define = require('amdefine')(module);\n}\n\n// web worker context\nif (typeof require != 'function' && typeof window != \"object\") { \n\n\tvar define = function(name, x, y){\n\t\tif (typeof x === \"function\") x(FLOOD);\n\t\tif (typeof y === \"function\") y(FLOOD);\n\t};\n\n}\n\ndefine('FLOODCSG',['FLOOD'], function(FLOOD) {\n\n\t// type name overrides\n\tCSG.floodTypeName = \"Solid\";\n\tCSG.Polygon.floodTypeName = \"Polygon\";\n\tCSG.Vector.floodTypeName = \"Vector\";\n\tCSG.Plane.floodTypeName = \"Plane\";\n\t\n\tCSG.Polygon.postProcess = csgPostProcess;\n\tCSG.Vector.postProcess = csgPostProcess;\n\tCSG.Plane.postProcess = csgPostProcess;\n\n\tCSG.prototype.render = function() {\n\n\t\tvar obj = { vertices : [], faces: [] };\n\n\t\tvar i, j, vertices, face,\n\t\t\tpolygons = this.toPolygons();\n\t\t\t\n\t\tfor ( i = 0; i < polygons.length; i++ ) {\n\t\t\t\n\t\t\tvertices = [];\n\t\t\tfor ( j = 0; j < polygons[i].vertices.length; j++ ) {\n\t\t\t\tvertices.push( this.getVertexIndex( obj, polygons[i].vertices[j].pos ) );\n\t\t\t}\n\n\t\t\tif ( vertices[0] === vertices[vertices.length - 1] ) {\n\t\t\t\tvertices.pop();\n\t\t\t}\n\t\t\t\n\t\t\tfor (var j = 2; j < vertices.length; j++) {\n\t\t\t\tvar n = polygons[i].plane.normal;\n\t\t\t\tface = [ vertices[0], vertices[j-1], vertices[j], [n.x, n.y, n.z] ];\n\t\t\t\tobj.faces.push( face );\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn obj;\n\n\t};\n\n\tCSG.prototype.getVertexIndex = function ( geometry, pos ) {\n\n\t\tvar i;\n\t\tfor ( i = 0; i < geometry.vertices.length; i++ ) {\n\t\t\tif ( geometry.vertices[i][0] === pos.x && geometry.vertices[i][1] === pos.y && geometry.vertices[i][2] === pos.z ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t};\n\t\t\n\t\tgeometry.vertices.push( [ pos.x, pos.y, pos.z ] );\n\t\treturn geometry.vertices.length - 1;\n\t};\n\n\tCSG.Polygon.prototype.render = function() {\n\n\t\tvar obj = { linestrip : [] }\n\t\t\t, vertices = this.vertices;\n\t\t\t\n\t\tfor ( var i = 0; i < vertices.length; i++ ) { \n\t\t\tobj.linestrip.push( [vertices[i].pos.x, vertices[i].pos.y, vertices[i].pos.z] );\n\t\t}\n\n\t\tobj.linestrip.push( [vertices[0].pos.x, vertices[0].pos.y, vertices[0].pos.z] );\n\t\n\n\t\treturn obj;\n\t};\n\n\tCSG.Plane.prototype.render = function() {\n\n\t\tvar origin = this.origin;\n\n\t\tvar linestrip = [ origin.plus( this.xaxis )\n\t\t\t\t\t\t\t\t\t\t, origin.minus( this.xaxis )\n\t\t\t\t\t\t\t\t\t\t, origin\n\t\t\t\t\t\t\t\t\t\t, origin.minus( this.yaxis )\n\t\t\t\t\t\t\t\t\t\t, origin.plus( this.yaxis )\n\t\t\t\t\t\t\t\t\t\t, origin\n\t\t\t\t\t\t\t\t\t\t, origin.plus( this.normal ) ];\n\n\t\tlinestrip = linestrip.map(function(x){ return [x.x, x.y, x.z]; });\n\n\t\treturn{ \"linestrip\": linestrip };\n\n\t};\n\n\n\n\tFLOOD.nodeTypes.Vector = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"X\", [Number], 0 ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Y\", [Number], 0 ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Z\", [Number], 0 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG.Vector ] ) ],\n\t\t\ttypeName: \"Vector\"\n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(x,y,z) {\n\n\t\t\treturn new CSG.Vector([x,y,z]);\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.VectorAdd = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [ CSG.Vector ], new CSG.Vector([0,0,0]) ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [ CSG.Vector ], new CSG.Vector([0,0,0]) ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG.Vector ] ) ],\n\t\t\ttypeName: \"VectorAdd\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a.plus(b);\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.VectorMultiply = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Vector\", [ CSG.Vector ], new CSG.Vector([0,0,0]) ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Scalar\", [ Number ], 1 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG.Vector ] ) ],\n\t\t\ttypeName: \"VectorMultiply\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a.times(b);\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.VectorSubtract = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Vector\", [ CSG.Vector ], new CSG.Vector([1,0,0]) ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Vector\", [ CSG.Vector ], new CSG.Vector([0,0,0]) )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG.Vector ] ) ],\n\t\t\ttypeName: \"VectorSubtract\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a.minus(b);\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.VectorDot = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [ CSG.Vector ], new CSG.Vector([0,0,0]) ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [ CSG.Vector ], new CSG.Vector([0,0,0]) )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG.Vector ] ) ],\n\t\t\ttypeName: \"VectorDot\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a.dot(b);\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.VectorCross = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [ CSG.Vector ], new CSG.Vector([1,0,0]) ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [ CSG.Vector ], new CSG.Vector([0,1,0]) )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG.Vector ] ) ],\n\t\t\ttypeName: \"VectorCross\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a.cross(b);\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.VectorNormalized = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Vector\", [ CSG.Vector ], new CSG.Vector([1,0,0]) )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG.Vector ] ) ],\n\t\t\ttypeName: \"VectorNormalized\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a) {\n\t\t\treturn a.unit();\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.VectorDistance = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [ CSG.Vector ], new CSG.Vector([0,0,0]) ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [ CSG.Vector ], new CSG.Vector([0,0,0]) )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG.Vector ] ) ],\n\t\t\ttypeName: \"VectorDistance\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a,b) {\n\t\t\treturn a.minus(b).length();\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.VectorLength = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Vector\", [ CSG.Vector ], new CSG.Vector([1,0,0]) )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ Number ] ) ],\n\t\t\ttypeName: \"VectorLength\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a) {\n\t\t\treturn a.length();\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.nodeTypes.VectorLerp = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [ CSG.Vector ], new CSG.Vector([0,0,0]) ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [ CSG.Vector ], new CSG.Vector([1,0,0]) ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Interp\", [ Number ], 0.5 )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG.Vector ] ) ],\n\t\t\ttypeName: \"VectorLerp\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, t) {\n\t\t\treturn a.lerp(b, t);\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType);\n\n\tFLOOD.nodeTypes.VectorComponents = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [ CSG.Vector ], new CSG.Vector([0,0,0]) )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"X\", [ Number ] ), \n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.OutputPort( \"Y\", [ Number ] ), \n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.OutputPort( \"Z\", [ Number ] )],\n\t\t\ttypeName: \"VectorComponents\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a) {\n\t\t\treturn new FLOOD.MultiOutResult({\"0\" : a.x, \"1\" : a.y, \"2\" : a.z });\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType);\n\n\tFLOOD.nodeTypes.Point = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Vector\", [ CSG.Vector ], new CSG.Vector([0,0,0]) ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG.Vector ] ) ],\n\t\t\ttypeName: \"Point\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a) {\n\t\t\treturn a;\n\t\t};\n\n\t\tthis.postProcess = function(value){\n\n\t\t\tvar p = { vertices: [] };\n\n\t\t\tif ( value.map ) {\n\t\t\t\tfor (var i = 0; i < value.length; i++){\n\t\t\t\t\tvar v = value[i];\n\t\t\t\t\tp.vertices.push( [ v.x, v.y, v.z ]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tp.vertices.push( [ value.x, value.y, value.z ] );\n\n\t\t\treturn p;\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tvar csgPostProcess = function(value){\n\n\t\tif (!value) return {};\n\n\t\tif ( value.map ) {\n\n\t\t\tvar d = [];\n\t\t\tfor (var i = 0; i < value.length; i++){\n\t\t\t\tif (value[i] === undefined) continue;\n\t\t\t\td.push( value[i].render ? value[i].render() : value[i] );\n\t\t\t}\n\n\t\t\treturn d;\n\t\t}\n\n\t\tif (!value.render) return value;\n\n\t\treturn value.render();\n\n\t};\n\n\tFLOOD.baseTypes.CSG = function(typeData) {\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.postProcess = csgPostProcess;\n\n\t}.inherits( FLOOD.baseTypes.NodeType );\n\n\tFLOOD.baseTypes.NodeType.prototype.postProcess = csgPostProcess;\n\n\tFLOOD.nodeTypes.Plane = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Origin\", [ CSG.Vector ], new CSG.Vector(0,0,0) ),\n\t\t\t \t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"XAxis\", [ CSG.Vector ], new CSG.Vector(1,0,0) ),\n\t\t\t \t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"YAxis\", [ CSG.Vector ], new CSG.Vector(0,1,0) ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG.Plane ] ) ],\n\t\t\ttypeName: \"Plane\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData);\n\n\t\tthis.eval = function(o, x, y) {\n\n\t\t\tif (x.length() < 1e-6) throw new Error(\"The X Axis must be longer than 0.\");\n\t\t\tif (y.length() < 1e-6) throw new Error(\"The Y Axis must be longer than 0.\");\n\t\t\tif (x.cross(y).length() < 1e-6) throw new Error(\"The X and Y Axis must form a plane\");\n\n\t\t\tvar n = x.cross(y).unit();\n\t\t\tvar w = n.dot(o);\n\n\t\t\tvar pl = new CSG.Plane(n,w);\n\t\t\tpl.origin = o;\n\t\t\tpl.xaxis = x.unit();\n\t\t\tpl.yaxis = n.cross(x).unit();\n\t\t\t\n\t\t\treturn pl;\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n\tFLOOD.nodeTypes.PlaneComponents = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Plane\", [ CSG.Plane ], initPlane() )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"Origin\", [ CSG.Vector ] ), \n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.OutputPort( \"XAxis\", [ CSG.Vector ] ), \n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.OutputPort( \"YAxis\", [ CSG.Vector ] ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.OutputPort( \"Normal\", [ CSG.Vector ] )],\n\t\t\ttypeName: \"PlaneComponents\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(plane) {\n\t\t\treturn new FLOOD.MultiOutResult({\"0\" : plane.origin, \"1\" : plane.xaxis, \"2\" : plane.yaxis, \"3\" : plane.xaxis.cross(plane.yaxis) });\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.NodeType);\n\n\tvar initPlane = function(){\n\n\t\tvar n = new CSG.Vector(0,0,1);\n\t\tvar w = 0;\n\n\t\tvar pl = new CSG.Plane(n,w);\n\t\t\n\t\tpl.origin = new CSG.Vector(0,0,0);\n\t\tpl.xaxis = new CSG.Vector(1,0,0);\n\t\tpl.yaxis = new CSG.Vector(0,1,0);\n\n\t\treturn pl;\n\n\t};\n\n\tvar ptOnPlane = function(pl, x, y){\n\t\treturn pl.origin.plus( pl.xaxis.times( x ).plus( pl.yaxis.times( y ) ) );\n\t};\n\n\tFLOOD.nodeTypes.RegularPolygon = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Sides\", [ Number ], 3 ),\n\t\t\t \t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Radius\", [ Number ], 10 ),\n\t\t\t \t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Plane\", [ CSG.Plane ], initPlane() )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG.Polygon ] ) ],\n\t\t\ttypeName: \"RegularPolygon\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData);\n\n\t\tthis.eval = function(numSides, radius, pl) {\n\n\t\t\tnumSides = Math.floor(numSides);\n\n\t\t\tif (numSides < 3) throw new Error(\"Sides must be >= 3\");\n\n\t\t\tvar inc = 2 * Math.PI / numSides;\n\n\t\t\tvar pts = [];\n\t\t\tvar ang = 0;\n\n\t\t\tfor (var i = 0; i < numSides; i++) {\n\t\t\t\tang += inc;\n\t\t\t\tpts.push( ptOnPlane(pl, radius * Math.cos(ang), radius * Math.sin(ang) ) );\n\t\t\t}\n\n\t\t\treturn CSG.Polygon.createFromPoints( pts, false );\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n\tFLOOD.nodeTypes.Rectangle = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Width\", [ Number ], 5 ),\n\t\t\t \t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Height\", [ Number ], 10 ),\n\t\t\t \t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Plane\", [ CSG.Plane ], initPlane() )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG.Polygon ] ) ],\n\t\t\ttypeName: \"Rectangle\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData);\n\n\t\tthis.eval = function(width, height, pl) {\n\n\t\t\tvar pts = [\n\t\t\t\tptOnPlane(pl, width/2, height/2),\n\t\t\t\tptOnPlane(pl, -width/2, height/2),\n\t\t\t\tptOnPlane(pl, -width/2, -height/2),\n\t\t\t\tptOnPlane(pl, width/2, -height/2)\n\t\t\t];\n\n\t\t\treturn CSG.Polygon.createFromPoints( pts, false );\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\t\n\tFLOOD.nodeTypes.Polygon = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Corners\", [ FLOOD.QuotedArray, CSG.Vector ] )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG.Polygon ] ) ],\n\t\t\ttypeName: \"Polygon\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData);\n\n\t\tthis.eval = function(pts) {\n\n\t\t\tif (pts.length < 3) throw new Exception(\"You need more than 3 points to make a polygon\");\n\n\t\t\treturn CSG.Polygon.createFromPoints( pts, false );\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n\tFLOOD.nodeTypes.SolidCuboid = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"MinCorner\", [ CSG.Vector ], new CSG.Vector([0,0,0]) ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"MaxCorner\", [ CSG.Vector ], new CSG.Vector([5, 5, 5]) ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG ] ) ],\n\t\t\ttypeName: \"SolidCuboid\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(minPoint, maxPoint) {\n\n\t\t\tif (minPoint.z > maxPoint.z ){\n\t\t\t\tvar t = minPoint;\n\t\t\t\tminPoint = maxPoint;\n\t\t\t\tmaxPoint = t;\n\t\t\t}\n\n\t\t\tvar x = new CSG.Vector([1,0,0]);\n\t\t\tvar y = new CSG.Vector([0,1,0]);\n\t\t\tvar w = maxPoint.x - minPoint.x;\n\t\t\tvar h = maxPoint.y - minPoint.y;\n\t\t\tvar d = maxPoint.z - minPoint.z;\n\n\t\t\tvar pts = [\n\t\t\t\tminPoint, \n\t\t\t\tminPoint.plus( x.times(w) ),\n\t\t\t\tminPoint.plus( x.times(w)).plus( y.times(h) ),\n\t\t\t\tminPoint.plus( y.times(h) )\n\t\t\t];\n\n\t\t\tvar poly = CSG.Polygon.createFromPoints( pts, false );\n\n\t\t\treturn extrude( poly, new CSG.Vector( [0,0,d] ));\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n\tFLOOD.nodeTypes.SolidCube = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Center\", [ CSG.Vector ], new CSG.Vector([0,0,0]) ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Radius\", [ Number ], 10 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG ] ) ],\n\t\t\ttypeName: \"SolidCube\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(center, radius) {\n\n\t\t\treturn CSG.cube({\n\t\t\t\t\t  center: center,\n\t\t\t\t\t  radius: radius\n\t\t\t\t\t});\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n\t// FLOOD.nodeTypes.ScaleUneven ( Solid, Plane, XFactor, YFactor, ZFactor )\n\n\tFLOOD.nodeTypes.SolidSphere = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Center\", [ CSG.Vector ], new CSG.Vector([0,0,0]) ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Radius\", [Number], 10 ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Slices\", [Number], 12 ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Stacks\", [Number], 6 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG ] ) ],\n\t\t\ttypeName: \"SolidSphere\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(cen, rad, xd, yd) {\n\n\t\t\treturn CSG.sphere({\n\t\t\t\t\t  center: cen,\n\t\t\t\t\t  radius: rad,\n\t\t\t\t\t  slices: xd,\n\t\t\t\t\t  stacks: yd });\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n\tFLOOD.nodeTypes.SolidCylinder = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"StartPoint\", [ CSG.Vector ], new CSG.Vector([0,-5,0]) ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"EndPoint\", [ CSG.Vector ], new CSG.Vector([0,5,0]) ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Radius\", [Number], 5 ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Slices\", [Number], 20 ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG ] ) ],\n\t\t\ttypeName: \"SolidCylinder\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(start, end, radius, slices) {\n\t\t\treturn CSG.cylinder({\n\t\t\t\t\t  start: start,\n\t\t\t\t\t  end: end,\n\t\t\t\t\t  radius: radius,\n\t\t\t\t\t  slices: slices });\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n\tCSG.Matrix4x4.prototype.inverse = function(){\n\n\t\t// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm\n\t\tvar te = new Array(16);\n\t\tvar me = this.elements;\n\n\t\tvar n11 = me[0], n12 = me[4], n13 = me[8], n14 = me[12];\n\t\tvar n21 = me[1], n22 = me[5], n23 = me[9], n24 = me[13];\n\t\tvar n31 = me[2], n32 = me[6], n33 = me[10], n34 = me[14];\n\t\tvar n41 = me[3], n42 = me[7], n43 = me[11], n44 = me[15];\n\n\t\tte[0] = n23*n34*n42 - n24*n33*n42 + n24*n32*n43 - n22*n34*n43 - n23*n32*n44 + n22*n33*n44;\n\t\tte[4] = n14*n33*n42 - n13*n34*n42 - n14*n32*n43 + n12*n34*n43 + n13*n32*n44 - n12*n33*n44;\n\t\tte[8] = n13*n24*n42 - n14*n23*n42 + n14*n22*n43 - n12*n24*n43 - n13*n22*n44 + n12*n23*n44;\n\t\tte[12] = n14*n23*n32 - n13*n24*n32 - n14*n22*n33 + n12*n24*n33 + n13*n22*n34 - n12*n23*n34;\n\t\tte[1] = n24*n33*n41 - n23*n34*n41 - n24*n31*n43 + n21*n34*n43 + n23*n31*n44 - n21*n33*n44;\n\t\tte[5] = n13*n34*n41 - n14*n33*n41 + n14*n31*n43 - n11*n34*n43 - n13*n31*n44 + n11*n33*n44;\n\t\tte[9] = n14*n23*n41 - n13*n24*n41 - n14*n21*n43 + n11*n24*n43 + n13*n21*n44 - n11*n23*n44;\n\t\tte[13] = n13*n24*n31 - n14*n23*n31 + n14*n21*n33 - n11*n24*n33 - n13*n21*n34 + n11*n23*n34;\n\t\tte[2] = n22*n34*n41 - n24*n32*n41 + n24*n31*n42 - n21*n34*n42 - n22*n31*n44 + n21*n32*n44;\n\t\tte[6] = n14*n32*n41 - n12*n34*n41 - n14*n31*n42 + n11*n34*n42 + n12*n31*n44 - n11*n32*n44;\n\t\tte[10] = n12*n24*n41 - n14*n22*n41 + n14*n21*n42 - n11*n24*n42 - n12*n21*n44 + n11*n22*n44;\n\t\tte[14] = n14*n22*n31 - n12*n24*n31 - n14*n21*n32 + n11*n24*n32 + n12*n21*n34 - n11*n22*n34;\n\t\tte[3] = n23*n32*n41 - n22*n33*n41 - n23*n31*n42 + n21*n33*n42 + n22*n31*n43 - n21*n32*n43;\n\t\tte[7] = n12*n33*n41 - n13*n32*n41 + n13*n31*n42 - n11*n33*n42 - n12*n31*n43 + n11*n32*n43;\n\t\tte[11] = n13*n22*n41 - n12*n23*n41 - n13*n21*n42 + n11*n23*n42 + n12*n21*n43 - n11*n22*n43;\n\t\tte[15] = n12*n23*n31 - n13*n22*n31 + n13*n21*n32 - n11*n23*n32 - n12*n21*n33 + n11*n22*n33;\n\n\t\tvar det = n11 * te[ 0 ] + n21 * te[ 4 ] + n31 * te[ 8 ] + n41 * te[ 12 ];\n\n\t\tif ( det == 0 ) {\n\t\t\tvar msg = \"Matrix4.getInverse(): can't invert matrix, determinant is 0\";\n\t\t\tthrow new Error( msg ); \n\t\t}\n\n\t\tvar detInv = 1 / det;\n\n\t\tte = te.map(function(x){ return x * detInv });\n\n\t\treturn new CSG.Matrix4x4( te );\n\t}\n\n\tvar extrude = function(polygon, offset) {\n\n\t\t// get CS from profile plane\n\t\tvar plane = polygon.plane;\n\t\tvar z = plane.normal;\n\t\tvar o = polygon.vertices[0].pos;\n\n\t\tvar helperVec = z.minus(new CSG.Vector(1,0,0)).length() > 1e-5 ? new CSG.Vector(1,0,0) : new CSG.Vector(0,1,0);\n\n\t\tvar x = z.cross( helperVec ).unit();\n\t\tvar y = z.cross( x );\n\n\t\tvar trf = new CSG.Matrix4x4( [ \tx.x, x.y, x.z, 0, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ty.x, y.y, y.z, 0, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tz.x, z.y, z.z, 0,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0,   0,   0,   1    ]);\n\n\t\tvar trfinv = trf.inverse();\n\n\t\tvar cc = [];\n\n\t\tfor (var i = 0; i < polygon.vertices.length; i++){\n\t\t\tvar cp = polygon.vertices[i].pos.minus( o );\n\t\t\tvar cpp = trf.rightMultiply1x3Vector( cp );\n\t\t\tcc.push( new CSG.Vector2D( cpp.x, cpp.y ) );\n\t\t}\n\n\t\t// extrude to create polygon\n\t\tvar profile2D = new CSG.Polygon2D( cc, false );\n\t\tvar offsetTrf = trf.rightMultiply1x3Vector( offset );\n\t\tvar ext = profile2D.extrude({ offset: offsetTrf });\n\n\t\t// transform solid back to original cs\n\t\treturn ext.transform( CSG.Matrix4x4.translation( o ).multiply( trfinv ) );\n\t};\n\n\tFLOOD.nodeTypes.SolidExtrusion = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Profile\", [ CSG.Polygon ] ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Vector\", [ CSG.Vector ], new CSG.Vector(0, 0, 1) ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG ] ) ],\n\t\t\ttypeName: \"SolidExtrusion\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = extrude;\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n\tFLOOD.nodeTypes.SolidIntersect = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [ CSG ] ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [ CSG ] ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG ] ) ],\n\t\t\ttypeName: \"SolidIntersect\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a.intersect(b);\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n\tFLOOD.nodeTypes.SolidUnionAll = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Solids\", [ FLOOD.QuotedArray, CSG ]) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG ] ) ],\n\t\t\ttypeName: \"SolidUnionAll\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(s) {\n\n\t\t\tvar acc = s.pop();\n\t\t\treturn s.reduce(function(a, b){ return a.union(b); }, acc)\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n\tFLOOD.nodeTypes.SolidUnion = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [ CSG ] ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [ CSG ] ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG ] ) ],\n\t\t\ttypeName: \"SolidUnion\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a.union(b);\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n\tFLOOD.nodeTypes.SolidSubtract = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"A\", [ CSG ] ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"B\", [ CSG ] ) ],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG ] ) ],\n\t\t\ttypeName: \"SolidSubtract\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(a, b) {\n\t\t\treturn a.subtract(b);\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n\tFLOOD.nodeTypes.Move = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Geom\", [ FLOOD.AnyTypeButQuotedArray ] ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Vector\", [ CSG.Vector ], new CSG.Vector( [0,0,0] ) )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG ] ) ],\n\t\t\ttypeName: \"Move\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(s, v) {\n\t\t\treturn s.transform( CSG.Matrix4x4.translation( v ) );\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n\tFLOOD.nodeTypes.Scale = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Geom\", [ FLOOD.AnyTypeButQuotedArray ] ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Center\", [ CSG.Vector ], new CSG.Vector([0,0,0]) ),\n\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Factor\", [ Number ], 1 )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG ] ) ],\n\t\t\ttypeName: \"Scale\" \n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(s, c, f) {\n\n\t\t\tvar m0 = CSG.Matrix4x4.translation( c.negated() );\n\t\t\tvar sc = CSG.Matrix4x4.scaling( [f,f,f] );\n\t\t\tvar m1 = CSG.Matrix4x4.translation( c );\n\t\t\tvar tr = m1.multiply(sc).multiply(m0);\n\n\t\t\treturn s.transform( tr );\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n\tFLOOD.nodeTypes.Rotate = function() {\n\n\t\tvar typeData = {\n\t\t\tinputs: [ \tnew FLOOD.baseTypes.InputPort( \"Geom\", [ FLOOD.AnyTypeButQuotedArray ] ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Axis\", [ CSG.Vector ], new CSG.Vector([0,0,1]) ),\n\t\t\t\t\t\t\t\t\tnew FLOOD.baseTypes.InputPort( \"Degrees\", [ Number ], 30 )],\n\t\t\toutputs: [ \tnew FLOOD.baseTypes.OutputPort( \"⇒\", [ CSG ] ) ],\n\t\t\ttypeName: \"Rotate\" \n\t\t};\n\n\t\tvar matrixFromAxisAngle = function(angle, axis) {\n\n\t    var c = Math.cos(angle);\n\t    var s = Math.sin(angle);\n\t    var t = 1.0 - c;\n\n\t    var m00 = c + axis.x*axis.x*t;\n\t    var m11 = c + axis.y*axis.y*t;\n\t    var m22 = c + axis.z*axis.z*t;\n\n\t    var tmp1 = axis.x*axis.y*t;\n\t    var tmp2 = axis.z*s;\n\t    var m10 = tmp1 + tmp2;\n\t    var m01 = tmp1 - tmp2;\n\t    var tmp1 = axis.x*axis.z*t;\n\t    var tmp2 = axis.y*s;\n\t    var m20 = tmp1 - tmp2;\n\t    var m02 = tmp1 + tmp2;    \n\t    var tmp1 = axis.y*axis.z*t;\n\t    var tmp2 = axis.x*s;\n\t    var m21 = tmp1 + tmp2;\n\t    var m12 = tmp1 - tmp2;\n\n\t    return new CSG.Matrix4x4([ m00, m01, m02, 0,\n\t\t\t\t\t\t\t\t\t\t    \t\t\t\t m10, m11, m12, 0,\n\t\t\t\t\t\t\t\t\t\t    \t\t\t\t m20, m21, m22, 0,\n\t\t\t\t\t\t\t\t\t\t    \t\t\t\t 0,\t\t0, \t\t 0, 1 ] );\n\n\t\t};\n\n\t\tFLOOD.baseTypes.NodeType.call(this, typeData );\n\n\t\tthis.eval = function(s, ax, ang) {\n\n\t\t\tvar tr = matrixFromAxisAngle( ang * Math.PI / 180, ax.unit() );\n\t\t\treturn s.transform( tr );\n\n\t\t};\n\n\t}.inherits( FLOOD.baseTypes.CSG );\n\n});\n\n"
  },
  {
    "path": "app/scripts/lib/flood/flood_runner.js",
    "content": "importScripts( 'scheme.js', 'flood.js', 'csg.js', 'flood_csg.js'); \n\n// Routing\nvar that = this;\n\nonmessage = function (m) {\n\n\tif (!checkCommandData(m.data)) return;\n\tcommands.push(m.data);\n\tthat[ \"on_\" + m.data.kind ](m.data);\n\n};\n\ncheckCommandData = function(data){\n\n\tif (!data.kind) {\n\t\tfail({kind: \"noCommand\", msg: \"No command given\"});\n\t\treturn false;\n\t}\n\n\tvar handler = \"on_\" + data.kind;\n\n\tif (!that[handler]) {\n\t\tfail({kind: data.kind, msg: \"No such command\"});\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nsuccess = function(m, silent){\n\tif (silent) return;\n\tm.success = true;\n\tpostMessage(m);\n};\n\nupdate = function(m, silent){\n\tif (silent) return;\n\tm.success = true;\n\tpostMessage(m);\n}\n\nfail = function(m, silent){\n\tif (silent) return;\n\tm.success = false;\n\tpostMessage(m);\n};\n\nworkspaces = {};\nfunctionDefinitions = {};\ncommands = [];\n\n// Receive\n\non_currentState = function(){\n\n\tvar s = { kind: \"currentState\", workspaceCount: workspaceCount() };\t\n\tsuccess(s);\n\n};\n\non_removeAll = function(){\n\n\tworkspaces = {};\n\tsuccess({kind: \"removeAll\"});\n\n};\n\non_run = function(data){\n\n\tvar workspace = lookupWorkspace(data.workspace_id);\n\tif (!workspace) return fail({ kind: \"run\", msg: \"The workspace id given is not valid\" }, data.silent);\n\n\tvar ts = Date.now();\n\n\t// get all nodes with output ports\n\tvar S = new scheme.Interpreter();\n\n\t// recompile custom nodes and store in env\n\tif (!FLOOD.environment) FLOOD.environment = {};\n\tfor (var funcId in functionDefinitions){\n\t\tFLOOD.environment[funcId] = FLOOD.internalNodeTypes.CustomNode.compileNodesToLambda( workspaces[funcId].nodes );\n\t}\n\n\tvar baseNode = null\n\t  , bottomNodes = workspace.nodes\n\t                      .filter(function(ele){\n\t                        return !(data.bottom_ids.indexOf(ele.id) < 0 );\n\t                      }).map(function(type){\n\t                        return type.outputs[0];\n\t                      });\n\n\tif ( bottomNodes.length > 1) {\n\t  baseNode = new FLOOD.internalNodeTypes.Begin();\n\t  var count = 0;\n\t  bottomNodes.forEach( function(output){ \n\t    baseNode.inputs.push( output.asInputPort(baseNode, count++) ); \n\t    baseNode.inputs[baseNode.inputs.length-1].connect( output.parentNode );\n\t  });\n\n\t} else if (bottomNodes.length == 1) {\n\t  baseNode = bottomNodes[0].parentNode;\n\t}\n\n\tif (baseNode){\n\t  baseNode.markDirty();\n\t  S.eval( baseNode.compile() );\n\t}\t\n\n\tvar te = Date.now();\n\n\tvar msg = { kind: \"run\", workspace_id: workspace.id, elapsed: te - ts, expression: \"\" };\n\n\tif (baseNode){\n\t\tmsg.expression = baseNode.printExpression();\n\t}\n\n\treturn success(msg, data.silent);\n\n};\n\non_addWorkspace = function(data){\n\n\tvar workspace = lookupWorkspace(data.workspace_id);\n\n\tif (workspace) return fail({kind: \"addWorkspace\", msg: \"A workspace with that id already exists\"});\n\n\tvar workspace = { id: data.workspace_id, nodes: [] };\n\n\tworkspaces[data.workspace_id] = workspace;\n\n\tif (data.nodes){\n\t\tdata.nodes.forEach(function(x){\n\t\t\tx.workspace_id = workspace.id;\n\t\t\tx.silent = true;\n\t\t\ton_addNode(x);\n\t\t});\n\t}\n\n\tif (data.connections){\n\t\tdata.connections.forEach(function(x){\n\t\t\tx.workspace_id = workspace.id;\n\t\t\tx.silent = true;\n\t\t\ton_addConnection(x);\n\t\t});\n\t}\n\n\treturn success({kind: \"addWorkspace\", workspace_id: data.workspace_id }, data.silent);\n\n};\n\non_removeWorkspace = function(data){\n\n\tvar workspace = lookupWorkspace(data.id);\n\tif (!workspace) return fail({kind: \"removeWorkspace\", msg: \"Workspace with that id does not exist\"});\n\n\tdelete workspaces[data.id];\n\n\treturn success({ kind: \"removeWorkspace\" }, data.silent);\n\n}\n\non_addDefinition = function(data){\n\n\tthis.functionDefinitions[data._id] = null;\n\tdata.workspace_id = data._id;\n\ton_addWorkspace( data );\n\n};\n\non_addConnection = function(data){\n\n\tvar ws = lookupWorkspace(data.workspace_id);\n\tif (!ws) return fail({ kind: \"run\", msg: \"The workspace id given is not valid\" }, data.silent);\n\n\tvar sn = lookupNode(ws, data.startNodeId );\n\tif (!sn) return fail({ kind: \"addConnection\", msg: \"Start node with given id does not exist\", workspace_id: data.workspace_id, startNodeId : data.startNodeId  });\n\n\tvar en = lookupNode(ws, data.endNodeId);\n\tif (!en) return fail({ kind: \"addConnection\", msg: \"End node with given id does not exist\", workspace_id: data.workspace_id, endNodeId: data.endNodeId });\n\n\tvar si = data.startPortIndex;\n\tvar ei = data.endPortIndex;\n\n\tif (si < 0 || si >= sn.outputs.length ) \n\t\treturn fail({ kind: \"addConnection\", msg: \"Start port index too high\" });\n\n\tif (ei < 0 || ei >= en.inputs.length ) \n\t\treturn fail({ kind: \"addConnection\", msg: \"End port index too high\" });\n\n\ten.inputs[ei].connect( sn, si );\n\n\treturn success({ kind: \"addConnection\" }, data.silent);\n\n};\n\non_recompile = function(data){\n\n\tvar wsToRecompile = lookupWorkspace(data._id);\n\tif (!wsToRecompile) return fail({ kind: \"run\", msg: \"The workspace id given is not valid\" }, data.silent);\n\n\tvar nodes = wsToRecompile.nodes;\n\n\t// recompile it\n\tvar lambda = FLOOD.internalNodeTypes.CustomNode.compileNodesToLambda( nodes );\n\t// var inputTypes = FLOOD.internalNodeTypes.CustomNode.findInputTypes( nodes );\n\tvar numInputs = FLOOD.internalNodeTypes.CustomNode.nodesOfType( FLOOD.nodeTypes.Input, nodes ).length;\n\tvar numOutputs = FLOOD.internalNodeTypes.CustomNode.nodesOfType( FLOOD.nodeTypes.Output, nodes ).length;\n\n\t// mark all instances of this custom node as dirty\n\tfor (var id in workspaces){\t\n\n\t\tvar ws = lookupWorkspace( id );\n\n\t\tws.nodes.forEach(function(n){\n\n\t\t\tif ( n.functionId && n.functionId === data._id ){\n\n\t\t\t\tn.lambda = lambda;\n\n\t\t\t\tn.setNumInputs( numInputs );\n\t\t\t\tn.setNumOutputs( numOutputs );\n\t\t\t\t// n.setInputTypes( inputTypes );\n\n\t\t\t\tn.setDirty();\n\n\t\t\t}\n\n\t\t});\n\n\t};\n\n\treturn success({ kind: \"recompile\", _id: data.workspace_id }, data.silent);\n\n}\n\non_removeConnection = function(data){\n\n\tvar ws = lookupWorkspace( data.workspace_id );\n\tif (!ws) return fail({ kind: \"removeConnection\", msg: \"The workspace does not exist\" }, data.silent);\n\n\tvar end = lookupNode( ws, data._id );\n\tif (!end) end = lookupNode( ws, data.endNodeId );\n\n\tif (!end) return fail({ kind: \"removeConnection\", msg: \"The node does not exist\" }, data.silent);\n\n\tif (data.portIndex < 0 || data.portIndex >= end.inputs.length) \n\t\treturn fail({ kind: \"removeConnection\", msg: \"The port index does not exist\" }, data.silent);\n\n\tend.inputs[data.portIndex].disconnect();\n\n  return success({ kind: \"removeConnection\", _id: data._id }, data.silent);\n\n};\n\non_updateNode = function(data){\n\n\tvar ws = lookupWorkspace(data.workspace_id);\n\tif (!ws) return fail({ kind: \"updateNode\", msg: \"The workspace does not exist\" }, data.silent);\n\n\tvar node = lookupNode(ws, data._id);\n\tif (!node) return fail({ kind: \"updateNode\", msg: \"Node with given id does not exist\", workspace_id: data.workspace_id, _id: data._id });\n\n\tif ( node.typeName != data.typeName ) \n\t\treturn fail({ kind: \"updateNode\", msg: \"Cannot change the type of a node\", workspace_id: data.workspace_id, _id: data._id, \n\t\t\tcurrent_type_name: node.typeName, requested_type_name: data.typeName });\n\n\tnode.replication = data.replication;\n\tif ( data.lastValue != undefined ) node.lastValue = data.lastValue;\n\tnode.extend( data.extra );\n\n\tfor (var i = 0; i < node.inputs.length; i++){\n\t\tnode.inputs[i].useDefault = data.ignoreDefaults[i] != undefined ? !data.ignoreDefaults[i] : true;\n\t}\n\n\tnode.setDirty();\n\n\treturn success({ kind: \"updateNode\", workspace_id: data.workspace_id, _id: data._id }, data.silent);\n\n};\n\non_addNode = function(data){\n\n\tvar ws = lookupWorkspace(data.workspace_id);\n\tif (!ws) return fail({ kind: \"addNode\", msg: \"The workspace does not exist\" }, data.silent);\n\n\tvar id = lookupNodeIndex(ws, data._id);\n\tif (!(id < 0)) return fail({ kind: \"addNode\", msg: \"Node with given id already exists\", workspace_id: data.workspace_id, _id: data._id });\n\n\tif ( !FLOOD.nodeTypes[data.typeName] && !FLOOD.internalNodeTypes[data.typeName] ) \n\t\treturn fail({ kind: \"addNode\", msg: \"Node with that name does not exist\", typeName: data.typeName, workspace_id: data.workspace_id, _id: data._id });\n\n\tvar type = FLOOD.nodeTypes[ data.typeName ] || FLOOD.internalNodeTypes[ data.typeName ];\n\n\tvar node = new type();\n\n\tnode.id = data._id;\n\tnode.replication = data.replication;\n\tnode.lastValue = data.lastValue;\n\tnode.evalComplete = post_nodeEvalComplete;\n\tnode.evalBegin = post_nodeEvalBegin;\n\tnode.evalFailed = post_nodeEvalFailed;\n\tif ( data.isClean ) node.setClean();\n\tnode.extend( data.extra );\n\n\tfor (var i = 0; i < node.inputs.length; i++){\n\t\tnode.inputs[i].useDefault = data.ignoreDefaults[i] != undefined ? !data.ignoreDefaults[i] : true;\n\t}\n\n\tws.nodes.push(node);\n\n\treturn success({ kind: \"addNode\", workspace_id: data.workspace_id, _id: data._id }, data.silent);\n\n};\n\non_removeNode = function(data){\n\n\tvar ws = lookupWorkspace(data.workspace_id);\n\tif (!ws) return fail({ kind: \"removeNode\", msg: \"The workspace does not exist\" }, data.silent);\n\n\tvar i = lookupNodeIndex(ws, data._id );\n\tif (i < 0) return fail({ kind: \"removeNode\", msg: \"A node with the given id does not exist.\" }, data.silent);\n\n\t// remove node from the workspace\n\tws.nodes.splice(i, 1);\n\n\t// delete all connections from the deleted node - effective removing\n\t// any references to the node\n\tws.nodes.forEach(function(n){\n\t\tn.inputs.forEach(function(p){\n\t\t\tif ( p.oppNode && p.oppNode.id === data._id ){\n\t\t\t\tp.disconnect();\n\t\t\t}\n\t\t});\n\t});\n\n\treturn success({ kind: \"removeNode\", _id : data._id, workspace_id: data.workspace_id }, data.silent);\n\n};\n\n// set the nodes & connections for a workspace\n// the entire set of nodes must be sent\non_setWorkspaceContents = function(data){\n\n\tvar workspace = lookupWorkspace(data.workspace_id);\n\tif (!workspace) return fail({ kind: \"setWorkspaceContents\", msg: \"A workspace with the given id does not exist\" }, data.silent);\n\n\tif (data.nodes){\n\t\tdata.nodes.forEach(function(x){\n\t\t\tx.workspace_id = workspace.id;\n\t\t\tx.silent = true;\n\t\t\ton_addNode(x);\n\t\t});\n\t} else {\n\t\tdata.nodes = [];\n\t}\n\n\tif (data.connections){\n\t\tdata.connections.forEach(function(x){\n\t\t\tx.workspace_id = workspace.id;\n\t\t\tx.silent = true;\n\t\t\ton_addConnection(x);\n\t\t});\n\t} else {\n\t\tdata.connections = [];\n\t}\n\n\treturn success({kind: \"setWorkspaceContents\", workspace_id: data.workspace_id }, data.silent);\n\n};\n\non_setReplication = function(data){\n\n\tvar ws = lookupWorkspace(data.workspace_id);\n\tif (!ws) return fail({ kind: \"setReplication\", msg: \"The workspace does not exist\" }, data.silent);\n\n\tvar node = lookupNode(ws, data.id);\n\tif (!node) return fail({ kind: \"setReplication\", msg: \"A node with the given id does not exist.\" }, data.silent);\n\n\tnode.replication = data.replication;\n\treturn success({ kind: \"setReplication\", id: data.id, workspace_id: data.workspace_id, replication: data.replication }, data.silent);\n\n};\n\n// Post\n\npost_nodeDirtied = function(id, value){\n\n\treturn success({ kind: \"nodeDirty\", _id: id });\n\n};\n\npost_nodeEvalBegin = function(node, isNew){\n\n\treturn success({ kind: \"nodeEvalBegin\", isNew: isNew, _id: node.id });\n\n};\n\npost_nodeEvalComplete = function(node, args, isNew, value, prettyValue ){\n\n\tif (typeof value === \"function\") {\n\t\tvalue = value.toString();\n\t\tprettyValue = value.toString();\n\t}\n\t\n\tif ( isNew ){\n\t\t// console.log('copying value', node.typeName );\n\t\treturn success({ kind: \"nodeEvalComplete\", isNew : isNew, _id: node.id, value : value, prettyValue: prettyValue  });\n\t} else {\n\t\t// console.log('not copying value', node.typeName );\n\t\treturn success({ kind: \"nodeEvalComplete\", isNew : isNew, _id: node.id });\n\t}\n\n};\n\npost_nodeEvalFailed = function(node, exception){\n\n\tconsole.log( JSON.stringify(exception) )\n\treturn fail({ kind: \"nodeEvalFailed\", _id: node.id, exception: exception.toString() });\n\n};\n\n// Helpers\n\nfunction clone (oToBeCloned) {\n  if (oToBeCloned === null || !(oToBeCloned instanceof Object)) { return oToBeCloned; }\n  var oClone, fConstr = oToBeCloned.constructor;\n  switch (fConstr) {\n    // implement other special objects here!\n    case RegExp:\n      oClone = new fConstr(oToBeCloned.source, \"g\".substr(0, Number(oToBeCloned.global)) + \"i\".substr(0, Number(oToBeCloned.ignoreCase)) + \"m\".substr(0, Number(oToBeCloned.multiline)));\n      break;\n    case Function:\n      return oToBeCloned.toString();\n    case Date:\n      oClone = new fConstr(oToBeCloned.getTime());\n      break;\n    // etc.\n    default:\n      oClone = new fConstr();\n  }\n  for (var sProp in oToBeCloned) { oClone[sProp] = clone(oToBeCloned[sProp]); }\n  return oClone;\n}\n\nfunction objectLength( object ) {\n    var length = 0;\n    for( var key in object ) {\n        if( object.hasOwnProperty(key) ) {\n            ++length;\n        }\n    }\n    return length;\n};\n\nworkspaceCount = function(){\n\n\treturn objectLength(workspaces);\n\n}\n \nlookupWorkspace = function(id){\n\n\treturn workspaces[ id ];\n\n};\n\nlookupNode = function(ws, id){\n\n\tvar i = lookupNodeIndex(ws, id);\n\tif (i < 0) return;\n\treturn ws.nodes[i];\n\n};\n\nlookupNodeIndex = function(ws, id){\n\n\tfor (var i = 0; i < ws.nodes.length; i++){\n\t\tif (ws.nodes[i].id === id) return i;\n\t}\n\n\treturn -1;\n\n};"
  },
  {
    "path": "app/scripts/lib/flood/scheme.js",
    "content": "if (typeof define !== 'function' && typeof require === 'function') {\n    var define = require('amdefine')(module);\n    var async = require('./async.js');\n} \n\nif (typeof require != 'function' && typeof window != \"object\") { \n\n\tvar scheme = {};\n\n\tvar define = function(x, y){\n\t\tif (typeof x === \"function\") scheme = x();\n\t\tif (typeof y === \"function\") scheme = y();\n\t};\n\n}\n\t\ndefine('scheme',function() {\n\n\t// Env\n\t// A dictionary of symbol-value pairs\n\tvar Env = function(vars, args, outer){\n\n\t\tvars = typeof vars !== 'undefined' ? vars : [];\n\t\tthis.scope = {};\n\t\tvar that = this;\n\t\tvars.forEach(function(val, i) {\n\t\t\tthat.scope[val] = args[i];\n\t\t});\n\t\touter = typeof outer !== 'undefined' ? outer : null;\n\t\tthis.outer = outer;\n\n\t\tthis.find = function(key){\n\t\t\tif ( this.scope[key] != null) \n\t\t\t\treturn this.scope\n\n\t\t\tif (this.outer != null) \n\t\t\t\treturn this.outer.find(key);\n\n\t\t\tthrow new Error(\"Could not find identifier: \" + key)\n\t\t};\n\n\t\tthis.add_methods = function(object) {\n\t\t\tvar that = this;\n\t\t\tObject.getOwnPropertyNames(object).forEach(function(ele){\n\t\t\t\tif (typeof object[ele] === \"function\"){\n\t\t\t\t\tthat.scope[ele] = object[ele];\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t};\n\n\t// The built-in symbols in the global Env\n\tvar built_ins = {\n\t\t'+': function(x, y) { return x + y; },\n\t\t'-': function(x, y) { return x - y; },\n\t\t'*': function(x, y) { return x * y; },\n\t\t'/': function(x, y) { return x / y; },\n\t\t'<': function(x, y) { return x < y; },\n\t\t'<=': function(x, y) { return x <= y; },\n\t\t'>': function(x, y) { return x > y; },\n\t\t'>=': function(x, y) { return x >= y; },\n\t\t'%': function(x, y) { return x % y; },\n\t\t'length': function(x) { return x.length; },\n\t\t'cons': function(l, val) { l.push(val); return l; },\n\t\t'car': function(l) { return l[0]; },\n\t\t'cdr': function(l) { return l.slice(1); },\n\t\t'list': function() { return Array.prototype.slice.call(arguments, 0); },\n\t\t'list?': function(e) { return e instanceof Array; },\n\t\t'null?': function(e) { return e === []; },\n\t\t'symbol?': function(e) { return typeof e === \"string\"; },\n\t\t'pick': function(i, l) { \n\t\t\treturn l[i]; \n\t\t},\n\t\t'map': function(f, l) { return l.map(f); },\n\t\t'reduce': function(f, a, l) { return l.reduce(f, a); },\n\t\t'filter': function(f, l) { return l.filter(f); },\n\t\t'reverse': function(l) { return l.reverse(); },\n\t\t'sort': function(l, f) { return l.sort(f); },\n\t}\n\n\tfunction add_globals(env) {\n\t\tenv.add_methods(Math);\n\t\tenv.add_methods(built_ins);\n\t\treturn env;\n\t}\n\n\t// Interpreter\n\t// Evaluates S-expressions\n\tvar Interpreter = function(){\n\n\t\tthis.global_env = add_globals( new Env() );\n\n\t\tthis.parse_eval = function(exp){\n\t\t\treturn this.eval( this.parse(exp) );\n\t\t}\n\n\t\tfunction defer(x){\n\t\t\tsetTimeout(x, 0);\n\t\t}\n\n\t\tthis.eval_async = function(x, env, cb) {\n\n\t\t\tenv = typeof env !== 'undefined' ? env : this.global_env;\n\n\t\t\tvar that = this;\n\t\t\tif ( typeof x === \"string\") {\t\t\t\t\t\t\t// variable reference\n\n\t\t\t\tdefer(function(){ cb( env.find(x)[x] ); });\n\n\t\t\t} else if ( !(x instanceof Array) ){\t\t\t\t\t// literal\t\n\n\t\t\t\t// console.log( \"hi\", x );\n\t\t\t\tdefer(function(){ cb( x ) });\n\n\t\t\t} else if (x[0] === \"quote\") {\t\t\t\t\t\t\t// (quote exp)\n\n\t\t\t\tdefer(function(){ cb( x[1] ); });\n\n\t\t\t} else if (x[0] === \"if\") {\t\t\t\t\t\t\t\t// (if test conseq alt)\n\n\t\t\t\tvar test = x[1], conseq = x[2], alt = x[3];\n\n\t\t\t\tthis.eval_async( test, env, function(res){\n\t\t\t\t\tthis.eval_async( res ? conseq : alt, env, cb );\n\t\t\t\t});\n\n\t\t\t} else if (x[0] === \"lambda\") {\t\t\t\t\t\t\t// (lambda (var*) exp)\n\n\t\t\t\tvar vars = x[1], exp = x[2];\n\n\t\t\t\tdefer(function(){ \n\t\t\t\t\tcb( function(args) {\n\t\t\t\t\t\treturn that.eval( exp, new Env(vars, arguments, env) );\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t} else if (x[0] === \"begin\") {\t\t\t\t\t\t\t// (begin exp*)\n\n\t\t\t\tx.shift();\n\n\t\t\t\t// build up all of the evaluations\n\t\t\t\tvar exps = x.map(function(exp){\n\t\t\t\t\treturn function(cbi){\n\t\t\t\t\t\tthat.eval_async( exp, env, function(res){\n\t\t\t\t\t\t\tcbi(null, res);\n\t\t\t\t\t\t});\n\t\t\t\t\t};\n\t\t\t\t});\n\n\t\t\t\t// do all in parallel, returning results as array\n\t\t\t\treturn async.parallel( exps, function(err, res){\n\n\t\t\t\t\t// return the last element\n\t\t\t\t\tdefer(function(){ cb( res[res.length -1] ); });\n\n\t\t\t\t});\n\n\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t// (proc exp*)\n\n\t\t\t\t// build all evaluations\n\t\t\t\tvar exps = x.map(function(exp){\n\t\t\t\t\treturn function(cbi){\n\t\t\t\t\t\tthat.eval_async( exp, env, function(res){\n\t\t\t\t\t\t\tcbi(null, res);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t// evaluate all of the inputs in parallel\n\t\t\t\tasync.parallel( exps, function(err, results){\n\n\t\t\t\t\t// then finally apply function in deferred fashion\n\t\t\t\t\tdefer(function(){\n\t\t\t\t\t\tvar proc = results.shift();\n\t\t\t  \t\tcb( proc.apply(that, results) );\n\t\t\t\t\t});\n\n\t\t\t\t});\n\t\t\t\n\t\t\t}\n\n\t\t}\n\n\t\tthis.eval = function(x, env) {\n\t\t\tenv = typeof env !== 'undefined' ? env : this.global_env;\n\n\t\t\tvar that = this;\n\t\t\tif ( typeof x === \"string\") {\t\t\t\t\t\t\t// variable reference\n\t\t\t\treturn env.find(x)[x];\n\t\t\t} else if ( !(x instanceof Array) ){\t\t\t\t\t// literal\t\n\t\t\t\treturn x; \n\t\t\t} else if (x[0] === \"quote\") {\t\t\t\t\t\t\t// (quote exp)\n\t\t\t\treturn x[1];\n\t\t\t} else if (x[0] === \"if\") {\t\t\t\t\t\t\t\t// (if test conseq alt)\n\t\t\t\tvar test = x[1], conseq = x[2], alt = x[3];\n\t\t    return this.eval( (this.eval(test, env) ? conseq : alt), env );\n\t\t\t} else if (x[0] === \"set!\") {\t\t\t\t\t\t\t// (set! var exp)\n\t\t\t\tvar vari = x[1], exp = x[2];\n\t\t\t\tenv.find(vari)[vari] = this.eval(exp); \n\t\t\t} else if (x[0] === \"define\") { \t\t\t\t\t\t// (define var exp)\n\t\t\t\tvar vari = x[1], exp = x[2];\n\t\t\t\tenv.scope[vari] = this.eval(exp, env);\n\t\t\t} else if (x[0] === \"lambda\") {\t\t\t\t\t\t\t// (lambda (var*) exp)\n\t\t\t\tvar vars = x[1], exp = x[2];\n\t\t\t\treturn (function(args) {\n\t\t\t\t\treturn that.eval( exp, new Env(vars, arguments, env) );\n\t\t\t\t});\n\t\t\t} else if (x[0] === \"begin\") {\t\t\t\t\t\t\t// (begin exp*)\n\t\t\t\tvar f;\n\t\t\t\tfor (var i = 1, l = x.length; i < l; i++) {\n\t\t\t\t\tf = this.eval( x[i] );\n\t\t\t\t}\n\t\t\t\treturn f;\n\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t// (proc exp*)\n\t\t\t\tvar that = this;\t\t\t\t\t\t\t\t\t\n\t\t\t\tvar exps = x.map(function(exp) { \t\t\t\t\t\n\t\t\t\t\treturn that.eval(exp, env);\n\t\t\t\t});\n\n\t\t\t  var proc = exps.shift();\n\t\t\t  return proc.apply(this, exps);\n\t\t\t}\n\n\t\t}\n\n\t\tthis.parse = function(s) {\n\t\t\treturn this.read_from( this.tokenize( s ) );\n\t\t}\n\n\t\tthis.tokenize = function(s) {\n\t\t\treturn s.replace(/\\(/g,\" ( \").replace(/\\)/g,\" ) \").split(\" \").filter(function(e){ return e; });\n\t\t};\n\n\t\tthis.read_from = function(tokens) {\n\t\t\tif (tokens.length === 0) throw \"unexpected EOF\";\n\t\t\ttoken = tokens.shift();\n\t\t\tif (token === \"(\") {\n\t\t\t\tvar L = [];\n\t\t\t\twhile (tokens[0] !== \")\") {\n\t\t\t\t\tL.push( this.read_from( tokens ) );\n\t\t\t\t}\n\t\t\t\ttokens.shift();\n\t\t\t\treturn L;\n\t\t\t} else if (token === \")\") {\n\t\t\t\tthrow \"expected )\";\n\t\t\t} else {\n\t\t\t\treturn this.atom(token);\n\t\t\t}\n\t\t};\n\n\t\tthis.atom = function(token){\n\t\t\tvar t = parseFloat( token );\n\t\t\treturn isNaN(t) ? token : t;\n\t\t};\n\n\t};\n\n\tif ( typeof exports != 'object' || exports === undefined )  // browser context\n\t{\n\t\tif (!scheme) var scheme = {};\n\t\tscheme.Interpreter = Interpreter;\n\t\tscheme.Env = Env;\n\t\treturn scheme;\n\t}\n\telse // node.js context\n\t{\n\t\t// Export these objects \n\t\texports.Interpreter = Interpreter;\n\t\texports.Env = Env;\n\t\treturn exports;\n\n\t}\n\n});\n\n\n\n\n\n\n\n"
  },
  {
    "path": "app/scripts/lib/flood/scheme_async.js",
    "content": "if (typeof define !== 'function' && typeof require === 'function') {\n    var define = require('amdefine')(module);\n} \n\nif (typeof require != 'function' && typeof window != \"object\") { \n\n\tvar scheme = {};\n\tvar define = function(x, y){\n\t\tif (typeof x === \"function\") scheme = x();\n\t\tif (typeof y === \"function\") scheme = y();\n\t};\n\n}\n\n\ndefine(function() {\n\n  // an extremely small async promise implementation\n  var Promise = function(func){\n\n    this.f = func;\n    this.redeemed = false;\n    var shouldContinue = true;\n\n    this.then = function(func){\n\n      this.next = func.constructor === Promise ? func : new Promise(func);\n      this.next.first = this;\n\n      return this.next;\n\n    };\n\n    this.test = function(trueFunc, falseFunc){\n\n    \tthis.nextTrue = trueFunc.constructor === Promise ? trueFunc : new Promise(trueFunc);\n    \tthis.nextFalse = falseFunc.constructor === Promise ? falseFunc : new Promise(falseFunc);\n\n    \tthis.nextTrue.first = this;\n    \tthis.nextFalse.first = this;\n\n    \treturn this.nextFalse;\n\n    };\n\n    this.cancel = function(){\n\n    \tshouldContinue = false;\n\n    };\n\n    this.done = function(){\n\n      var that = this;\n      var args = arguments;\n\n      // do work async\n      setTimeout(function(){\n\n        if ( that.first && !that.first.redeemed ){\n          return that.first.done.apply( that.first, args );\n        }\n\n        var res = that.f.apply(that, args);\n        that.redeemed = true;\n\n        that.continueNext( res );\n\n      }, 0);\n\n     };\n\n     this.continueNext = function(res){\n\n     \t\tif ( !shouldContinue ) return res;\n\n        // imperative\n        if (that.next){\n        \treturn that.next.done.call(that.next, res);\n        }\n\n        // conditional\n        if (that.nextTrue){\n        \treturn res ? \n        \t\tthat.nextTrue.done.call(that.nextTrue, res) : \n        \t\tthat.nextFalse.done.call(that.nextFalse, res);\n        }\n\n     }\n\n  }\n\n  Promise.prototype.all = function(promises){\n\n\t\t// the results of all the evaluations\n\t\tvar promiseCountdown = promises.length;\n\t\tvar startedAll = false;\n\t\tvar results = new Array( promiseCountdown );\n\n  \tpromises.forEach(function(p, i){\n\n  \t\tvar index = i;\n\n  \t\tp.then(function(res){\n\n  \t\t\t// running one promise causes the execution of all of them\n  \t\t\tif (!startedAll){\n\t  \t\t\tfor (var j = 1; j < promises.length; j++){\n\t  \t\t\t\tpromises[j].done();\n\t  \t\t\t} \n  \t\t\t}\n\n  \t\t\tresults[index] = res;\n\n  \t\t\tpromiseCountdown--;\n\n  \t\t\tif (promiseCountdown != 0){\n  \t\t\t\tthis.cancel();\n  \t\t\t\treturn res;\n  \t\t\t}\n\n  \t\t\treturn results;\n\n  \t\t});\n\n  \t});\n\n  \treturn promises[ 0 ];\n\n  }\n\n\t// Env\n\t// A dictionary of symbol-value pairs\n\tvar Env = function(vars, args, outer){\n\n\t\tvars = typeof vars !== 'undefined' ? vars : [];\n\t\tthis.scope = {};\n\t\tvar that = this;\n\t\tvars.forEach(function(val, i) {\n\t\t\tthat.scope[val] = args[i];\n\t\t});\n\t\touter = typeof outer !== 'undefined' ? outer : null;\n\t\tthis.outer = outer;\n\n\t\tthis.find = function(key){\n\t\t\treturn this.scope[key] != null ? this.scope: this.outer.find(key);\n\t\t};\n\n\t\tthis.add_methods = function(object) {\n\t\t\tvar that = this;\n\t\t\tObject.getOwnPropertyNames(object).forEach(function(ele){\n\t\t\t\tif (typeof object[ele] === \"function\"){\n\t\t\t\t\tthat.scope[ele] = object[ele];\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t};\n\n\t// The built-in symbols in the global Env\n\tvar built_ins = {\n\t\t'+': function(x, y) { return x + y; },\n\t\t'-': function(x, y) { return x - y; },\n\t\t'*': function(x, y) { return x * y; },\n\t\t'/': function(x, y) { return x / y; },\n\t\t'<': function(x, y) { return x < y; },\n\t\t'<=': function(x, y) { return x <= y; },\n\t\t'>': function(x, y) { return x > y; },\n\t\t'>=': function(x, y) { return x >= y; },\n\t\t'%': function(x, y) { return x % y; },\n\t\t'length': function(x) { return x.length; },\n\t\t'cons': function(l, val) { l.push(val); return l; },\n\t\t'car': function(l) { return l[0]; },\n\t\t'cdr': function(l) { return l.slice(1); },\n\t\t'list': function() { return Array.prototype.slice.call(arguments, 0); },\n\t\t'list?': function(e) { return e instanceof Array; },\n\t\t'null?': function(e) { return e === []; },\n\t\t'symbol?': function(e) { return typeof e === \"string\"; },\n\t\t'pick': function(i, l) { \n\t\t\treturn l[i]; \n\t\t},\n\t\t'map': function(f, l) { return l.map(f); },\n\t\t'reduce': function(f, a, l) { return l.reduce(f, a); },\n\t\t'filter': function(f, l) { return l.filter(f); },\n\t\t'reverse': function(l) { return l.reverse(); },\n\t\t'sort': function(l, f) { return l.sort(f); },\n\t}\n\n\tfunction add_globals(env) {\n\t\tenv.add_methods(Math);\n\t\tenv.add_methods(built_ins);\n\t\treturn env;\n\t}\n\n\t// Interpreter\n\t// Evaluates S-expressions\n\tvar Interpreter = function(){\n\n\t\tthis.global_env = add_globals( new Env() );\n\n\t\tthis.parse_eval = function(exp){\n\t\t\treturn this.eval( this.parse(exp) );\n\t\t}\n\n\n\t\tthis.async = function(x, env) {\n\n\t\t\tenv = typeof env !== 'undefined' ? env : this.global_env;\n\n\t\t\tvar that = this;\n\n\t\t\tif ( typeof x === \"string\") {\t\t\t\t\t\t\t// variable reference\n\n\t\t\t\treturn new Promise(function(){ return env.find(x)[x]; });\n\n\t\t\t\t// return env.find(x)[x]; \n\n\t\t\t} else if ( !(x instanceof Array) ){\t\t\t\t\t// literal\t\n\n\t\t\t\treturn new Promise(function(){ return x; });\n\n\t\t\t\t// return x; \n\n\t\t\t} else if (x[0] === \"quote\") {\t\t\t\t\t\t\t// (quote exp)\n\n\t\t\t\treturn new Promise(function(){ return x[1]; });\t\t\n\t\t\t\t\t\t\n\t\t\t\t// return x[1];\n\n\t\t\t} else if (x[0] === \"if\") {\t\t\t\t\t\t\t\t// (if test conseq alt)\n\n\t\t\t\tvar test = x[1], conseq = x[2], alt = x[3];\n\t\t    // return this.eval( (this.eval(test, env) ? conseq : alt), env );\n\n\t\t    return that.async(test, env).test( that.async(conseq, env), that.async(alt, env) );\n\n\t\t\t} else if (x[0] === \"set!\") {\t\t\t\t\t\t\t// (set! var exp)\n\n\t\t\t\tvar vari = x[1], exp = x[2];\n\t\t\t\t// env.find(vari)[vari] = this.eval(exp); \n\n\t\t\t\treturn that.async( exp, env ).then(function(val){\n\t\t\t\t\tenv.find(vari)[vari] = val;\n\t\t\t\t});\n\n\t\t\t} else if (x[0] === \"define\") { \t\t\t\t\t\t// (define var exp)\n\n\t\t\t\tvar vari = x[1], exp = x[2];\n\n\t\t\t\treturn that.async( exp, env ).then(function(val){\n\t\t\t\t\tenv.scope[vari] = val;\n\t\t\t\t});\n\n\t\t\t\t// env.scope[vari] = this.eval(exp, env);\n\n\t\t\t} else if (x[0] === \"lambda\") {\t\t\t\t\t\t\t// (lambda (var*) exp)\n\n\t\t\t\tvar vars = x[1], exp = x[2];\n\n\t\t\t\t// todo\n\n\t\t\t\treturn (function(args) {\n\t\t\t\t\treturn that.eval( exp, new Env(vars, arguments, env) );\n\t\t\t\t});\n\n\n\t\t\t} else if (x[0] === \"begin\") {\t\t\t\t\t\t\t// (begin exp*)\n\n\t\t\t\t// do all individually\n\t\t\t\tvar f = that.async( x[1], env );\n\n\t\t\t\tfor (var i = 2, l = x.length; i < l; i++) {\n\n\t\t\t\t\tf.then( that.async( x[i], env ) );\n\n\t\t\t\t\t// f = this.eval( x[i] );\n\t\t\t\t}\n\n\t\t\t\treturn f;\n\n\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t// (proc exp*)\n\n\t\t\t\tvar proc = this.async( x[0] );\n\n\t\t\t\tvar promises = [];\n\n\t\t\t\tfor (var i = 1; i < x.length; i++){\n\n\t\t\t\t\tvar index = i;\n\t\t\t\t\tvar promise = this.async( x[i], env );\n\n\t\t\t\t\tpromises.push( promise );\n\n\t\t\t\t}\n\n\t\t\t \tvar resultsPromise = Promise.all( promises );\n\n\t\t\t \treturn resultsPromise.then( proc );\n\n\t\t\t\t// var that = this;  \t\t\n\n\t\t\t\t// var exps = x.map(function(exp) { \t\t\t\t\t\n\t\t\t\t// \treturn that.eval(exp, env);\n\t\t\t\t// });\n\n\t\t\t //  var proc = exps.shift();\n\t\t\t //  return proc.apply(this, exps);\n\t\t\t}\n\n\t\t}\n\n\t\t// for each - go go go - when all results are collected - continue\n\n\n\t\tthis.async_eval = function(x, env){\n\n\t\t\treturn this.async(x, env).go();\n\n\t\t}\n\n\n\t\tthis.eval = function(x, env) {\n\t\t\tenv = typeof env !== 'undefined' ? env : this.global_env;\n\n\t\t\tvar that = this;\n\t\t\tif ( typeof x === \"string\") {\t\t\t\t\t\t\t// variable reference\n\t\t\t\treturn env.find(x)[x];\n\t\t\t} else if ( !(x instanceof Array) ){\t\t\t\t\t// literal\t\n\t\t\t\treturn x; \n\t\t\t} else if (x[0] === \"quote\") {\t\t\t\t\t\t\t// (quote exp)\n\t\t\t\treturn x[1];\n\t\t\t} else if (x[0] === \"if\") {\t\t\t\t\t\t\t\t// (if test conseq alt)\n\t\t\t\tvar test = x[1], conseq = x[2], alt = x[3];\n\t\t    return this.eval( (this.eval(test, env) ? conseq : alt), env );\n\t\t\t} else if (x[0] === \"set!\") {\t\t\t\t\t\t\t// (set! var exp)\n\t\t\t\tvar vari = x[1], exp = x[2];\n\t\t\t\tenv.find(vari)[vari] = this.eval(exp); \n\t\t\t} else if (x[0] === \"define\") { \t\t\t\t\t\t// (define var exp)\n\t\t\t\tvar vari = x[1], exp = x[2];\n\t\t\t\tenv.scope[vari] = this.eval(exp, env);\n\t\t\t} else if (x[0] === \"lambda\") {\t\t\t\t\t\t\t// (lambda (var*) exp)\n\t\t\t\tvar vars = x[1], exp = x[2];\n\t\t\t\treturn (function(args) {\n\t\t\t\t\treturn that.eval( exp, new Env(vars, arguments, env) );\n\t\t\t\t});\n\t\t\t} else if (x[0] === \"begin\") {\t\t\t\t\t\t\t// (begin exp*)\n\t\t\t\tvar f;\n\t\t\t\tfor (var i = 1, l = x.length; i < l; i++) {\n\t\t\t\t\tf = this.eval( x[i] );\n\t\t\t\t}\n\t\t\t\treturn f;\n\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t// (proc exp*)\n\t\t\t\tvar that = this;\t\t\t\t\t\t\t\t\t\n\t\t\t\tvar exps = x.map(function(exp) { \t\t\t\t\t\n\t\t\t\t\treturn that.eval(exp, env);\n\t\t\t\t});\n\t\t\t  var proc = exps.shift();\n\t\t\t  return proc.apply(this, exps);\n\t\t\t}\n\n\t\t}\n\n\t\tthis.parse = function(s) {\n\t\t\treturn this.read_from( this.tokenize( s ) );\n\t\t}\n\n\t\tthis.tokenize = function(s) {\n\t\t\treturn s.replace(/\\(/g,\" ( \").replace(/\\)/g,\" ) \").split(\" \").filter(function(e){ return e; });\n\t\t};\n\n\t\tthis.read_from = function(tokens) {\n\t\t\tif (tokens.length === 0) throw \"unexpected EOF\";\n\t\t\ttoken = tokens.shift();\n\t\t\tif (token === \"(\") {\n\t\t\t\tvar L = [];\n\t\t\t\twhile (tokens[0] !== \")\") {\n\t\t\t\t\tL.push( this.read_from( tokens ) );\n\t\t\t\t}\n\t\t\t\ttokens.shift();\n\t\t\t\treturn L;\n\t\t\t} else if (token === \")\") {\n\t\t\t\tthrow \"expected )\";\n\t\t\t} else {\n\t\t\t\treturn this.atom(token);\n\t\t\t}\n\t\t};\n\n\t\tthis.atom = function(token){\n\t\t\tvar t = parseFloat( token );\n\t\t\treturn isNaN(t) ? token : t;\n\t\t};\n\n\t};\n\n\tif ( typeof exports != 'object' || exports === undefined )  // browser context\n\t{\n\t\tif (!scheme) var scheme = {};\n\t\tscheme.Interpreter = Interpreter;\n\t\tscheme.Env = Env;\n\t\treturn scheme;\n\t}\n\telse // node.js context\n\t{\n\t\t// Export these objects \n\t\texports.Interpreter = Interpreter;\n\t\texports.Env = Env;\n\t\treturn exports;\n\n\t}\n\n});\n\n\n\n\n\n\n\n"
  },
  {
    "path": "app/scripts/lib/flood/test/flood_csg_test.js",
    "content": "var FLOOD = new require('../flood.js')\n\t, assert = require('assert')\n\t, scheme = require('../scheme.js')\n\t, f = require('../flood_csg.js');\n\n// mapApply - applyLongest with nesting\n(function(scheme, FLOOD) {\n\n\tvar add = new FLOOD.nodeTypes.Add();\n\n\t// expected_arg_types\n\tvar options = {};\n\toptions.expected_arg_types = [[Number], [Number]];\n\toptions.replication = \"applyLongest\";\n\n\tvar arrA = new FLOOD.QuotedArray();\n\tvar arr0 = new FLOOD.QuotedArray();\n\tarrA.push(arr0);\n\tarr0.push(1);\n\n\tvar arrB = new FLOOD.QuotedArray();\n\tvar arr1 = new FLOOD.QuotedArray();\n\tarrB.push(arr1);\n\tarr1.push(2);\n\n\tvar res = add.eval.mapApply(eval, [arrA, arrB], options);\n\n\tassert.equal( 1, res.length );\n\tassert.equal( \"[ [ 3 ] ]\", res.toString() );\n\n\tvar res = add.eval.mapApply(eval, [4, arrB], options);\n\n\tassert.equal( 1, res.length );\n\tassert.equal( \"[ [ 6 ] ]\", res.toString() );\n\n\tvar res = add.eval.mapApply(eval, [arrA, 2], options);\n\n\tassert.equal( 1, res.length );\n\tassert.equal( \"[ [ 3 ] ]\", res.toString() );\n\n\tarr0.push(2);\n\tvar res = add.eval.mapApply(eval, [arrA, 2], options);\n\n\tassert.equal( 1, res.length );\n\tassert.equal( \"[ [ 3, 4 ] ]\", res.toString() );\n\n\tvar res = add.eval.mapApply(eval, [arrA, arrA], options);\n\n\tassert.equal( 1, res.length );\n\tassert.equal( \"[ [ 2, 4 ] ]\", res.toString() );\n\n\n})(scheme, FLOOD);\n\n// mapApply - applyLongest without nesting\n(function(scheme, FLOOD) {\n\n\tvar add = new FLOOD.nodeTypes.Add();\n\n\t// expected_arg_types\n\tvar options = {};\n\toptions.expected_arg_types = [[Number], [Number]];\n\toptions.replication = \"applyLongest\";\n\n\tvar arr = new FLOOD.QuotedArray();\n\tarr.push(8);\n\tarr.push(9);\n\tarr.push(10);\n\n\tvar res = add.eval.mapApply(eval, [1, arr], options);\n\tassert.equal( 3, res.length );\n\tassert.equal( \"[ 9, 10, 11 ]\", res.toString() );\n\n\tvar res = add.eval.mapApply(eval, [arr, arr], options);\n\tassert.equal( 3, res.length );\n\tassert.equal( \"[ 16, 18, 20 ]\", res.toString() );\n\n\tarr.push(11);\n\n\tvar res = add.eval.mapApply(eval, [1, arr], options);\n\tassert.equal( 4, res.length );\n\tassert.equal( \"[ 9, 10, 11, 12 ]\", res.toString() );\n\n})(scheme, FLOOD);\n\n// doAllTypesMatch\n(function(scheme, FLOOD) {\n\n\tvar arg = [null], arg_type = [[ FLOOD.AnyType ]];\n\tassert.equal( true, FLOOD.doAllTypesMatch( arg, arg_type ) );\n\n\tvar arg = [8], arg_type = [[ Number ]];\n\tassert.equal( true, FLOOD.doAllTypesMatch( arg, arg_type ) );\n\n\tvar arrNum = new FLOOD.QuotedArray();\n\tarrNum.push(8);\n\tvar arg = [ 8, arrNum ], arg_type = [[ Number ], [ FLOOD.QuotedArray, Number ]];\n\tassert.equal( true, FLOOD.doAllTypesMatch( arg, arg_type ) );\n\n\tvar arrString = new FLOOD.QuotedArray();\n\tarrString.push(\"frog\");\n\tvar arg = [ 8, arrNum, arrString ], arg_type = [ [ Number ], [ FLOOD.QuotedArray, Number ], [ FLOOD.QuotedArray, String ] ];\n\tassert.equal( true, FLOOD.doAllTypesMatch( arg, arg_type ) );\n\n\tvar arg = [ 8, arrString, arrNum ], arg_type = [ [ Number ], [ FLOOD.QuotedArray, Number ], [ FLOOD.QuotedArray, String ] ];\n\tassert.equal( false, FLOOD.doAllTypesMatch( arg, arg_type ) );\n\n})(scheme, FLOOD);\n\n// isFastTypeMatch\n(function(scheme, FLOOD) {\n\n\tvar arg = null, arg_type = [ FLOOD.AnyType ];\n\tassert.equal( true, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n\tvar arg = new FLOOD.QuotedArray(null), arg_type = [ FLOOD.QuotedArray, FLOOD.AnyType ];\n\tassert.equal( true, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n\tvar arg = null, arg_type = [ FLOOD.QuotedArray, FLOOD.AnyType ];\n\tassert.equal( false, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n\tvar arg = new FLOOD.QuotedArray(), arg_type = [ FLOOD.QuotedArray, Number ];\n\targ.push(8);\n\tassert.equal( true, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n\tvar arg = new FLOOD.QuotedArray(), arg_type = [ FLOOD.QuotedArray, FLOOD.QuotedArray, Number ];\n\targ.push(\"peter\");\n\targ.push(8);\n\tassert.equal( false, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n\tvar arg = [[8, 8]], arg_type = [Array, Array, Number];\n\tassert.equal( true, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n\tvar arg = [[[8]]], arg_type = [Array, Array, Array, Number];\n\tassert.equal( true, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n\t// new constructor function\n\tfunction Turtle(){};\n\tvar arg = [[[new Turtle()]]], arg_type = [Array, Array, Array, Turtle];\n\tassert.equal( true, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n})(scheme, FLOOD);\n\n// isObjectTypeMatch\n(function(scheme, FLOOD) {\n\n\tvar arg = null, arg_type = FLOOD.AnyType;\n\tassert.equal( true, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = 8, arg_type = Number;\n\tassert.equal( true, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = -8.23, arg_type = Number;\n\tassert.equal( true, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = \"peter\", arg_type = String;\n\tassert.equal( true, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = new FLOOD.QuotedArray(), arg_type = FLOOD.QuotedArray;\n\tassert.equal( true, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = [], arg_type = Number;\n\tassert.equal( false, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = \"peter\", arg_type = Number;\n\tassert.equal( false, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = function(){}, arg_type = Function;\n\tassert.equal( true, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = function(){}, arg_type = Number;\n\tassert.equal( false, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n})(scheme, FLOOD);\n\n\n// test case 1\n(function(scheme, FLOOD) {\n\n\tvar add = new FLOOD.nodeTypes.Add();\n\tvar num5 = new FLOOD.nodeTypes.Number();\n\tnum5.value = 5;\n\tvar num2 = new FLOOD.nodeTypes.Number();\n\tnum2.value = 2;\n\n\tadd.inputs[0].connect( num5 );\n\tadd.inputs[1].connect( num2 );\n\n\tassert.equal( add.printExpression() , '(+ 5 2)' );\n\n\tvar S = new scheme.Interpreter();\n\tassert.equal( S.eval( add.compile() ) , 7 );\n\n})(scheme, FLOOD);\n\n\n// test case 2\n(function(scheme, FLOOD) {\n\n\tvar add = new FLOOD.nodeTypes.Add();\n\tvar num5 = new FLOOD.nodeTypes.Number();\n\tnum5.value = 5;\n\n\tvar num2 = new FLOOD.nodeTypes.Number();\n\tnum2.value = 2;\n\n\tadd.inputs[0].connect( num5 );\n\tadd.inputs[1].connect( num2 );\n\n\tvar divide = new FLOOD.nodeTypes.Div();\n\n\tdivide.inputs[0].connect( num5 );\n\tdivide.inputs[1].connect( add );\n\n\tassert.equal( divide.printExpression() , '(/ 5 (+ 5 2))' );\n\n\tvar S = new scheme.Interpreter();\n\tassert.equal( S.eval( divide.compile() ), 5/7);\n\n})(scheme, FLOOD);\n\n\n// test case 3\n(function(scheme, FLOOD) {\n\n\tvar add = new FLOOD.nodeTypes.Add();\n\tvar num5 = new FLOOD.nodeTypes.Number();\n\tnum5.value = 5;\n\tvar num2 = new FLOOD.nodeTypes.Number();\n\tnum2.value = 2;\n\n\tadd.inputs[0].connect( num5 );\n\tadd.inputs[1].connect( num2 );\n\n\tvar divide = new FLOOD.nodeTypes.Div();\n\n\tdivide.inputs[0].connect( num5 );\n\tdivide.inputs[1].connect( add );\n\n\tvar multiply = new FLOOD.nodeTypes.Mult();\n\n\tmultiply.inputs[0].connect( num5 );\n\tmultiply.inputs[1].connect( add );\n\n\tvar begin = new FLOOD.nodeTypes.Begin();\n\n\tbegin.inputs.push( multiply.outputs[0].asInputPort(begin, 0) );\n\tbegin.inputs.push( divide.outputs[0].asInputPort(begin, 0) );\n\n\tbegin.inputs[0].connect( multiply );\n\tbegin.inputs[1].connect( divide );\n\n\tassert.equal( begin.printExpression(), '(begin (* 5 (+ 5 2)) (/ 5 (+ 5 2)))' );\n\n\tvar S = new scheme.Interpreter();\n\tbegin.markDirty();\n\tassert.equal( S.eval( begin.compile() ), 5/7);\n\n})(scheme, FLOOD);\n\n// // test case 4, check that add if curried correctly\n// (function(scheme, FLOOD) {\n\n// \tvar add = new FLOOD.nodeTypes.Add();\n// \tadd.inputs[0].defaultVal = 1;\n// \tadd.inputs[1].useDefault = false;\n\n// \tassert.equal( add.printExpression(), '(+ 1 _)' );\n\n// \tvar S = new scheme.Interpreter();\n// \tadd.markDirty();\n\n// \tvar add1 = S.eval( add.compile() );\n\n// \tassert.equal( add1(6), 7);\n\n// })(scheme, FLOOD);\n\n// // test case 4, use a curried function with map\n// (function(scheme, FLOOD) {\n\n// \tvar num5 = new FLOOD.nodeTypes.Num();\n// \tnum5.value = 5;\n\n// \tvar add = new FLOOD.nodeTypes.Add();\n// \tadd.inputs[0].useDefault = false;\n\n// \tadd.inputs[1].connect( num5 );\n\n// \tvar map = new FLOOD.nodeTypes.Map();\n\n// \tmap.inputs[0].connect( add );\n// \tmap.inputs[1].defaultVal = [\"quote\", [0, 1, 2]];\n\n// \tvar S = new scheme.Interpreter();\n// \tmap.markDirty();\n\n// \tvar mapVal = S.eval( map.compile() );\n\t\n// \tassert.equal( map.value.length, 3);\n// \tassert.equal( map.value[0], 5);\n// \tassert.equal( map.value[1], 6);\n// \tassert.equal( map.value[2], 7);\n\n// })(scheme, FLOOD);\n\n\n\n"
  },
  {
    "path": "app/scripts/lib/flood/test/flood_lambda_test.js",
    "content": "var FLOOD = new require('../flood.js')\n\t, assert = require('assert')\n\t, scheme = require('../scheme.js');\n\n\n(function(scheme, FLOOD) {\n\n\tvar nodes = [];\n\n\tvar input0 = new FLOOD.nodeTypes.Input(\"A\");\n\tvar input1 = new FLOOD.nodeTypes.Input(\"B\");\n\t\n\tnodes.push(input0);\n\tnodes.push(input1);\n\n\tvar add = new FLOOD.nodeTypes.Add();\n\tnodes.push(add);\n\n\tadd.inputs[0].connect( input0 );\n\tadd.inputs[1].connect( input1 );\n\n\tvar mult = new FLOOD.nodeTypes.Multiply();\n\tnodes.push(mult);\n\n\tmult.inputs[0].connect( input0 );\n\tmult.inputs[1].connect( input1 );\n\n\tvar output = new FLOOD.nodeTypes.Output(\"A\");\n\tvar output1 = new FLOOD.nodeTypes.Output(\"B\");\n\tnodes.push(output);\n\tnodes.push(output1);\n\n\t// compile this into a function\n\toutput.inputs[0].connect( add );\n\toutput1.inputs[0].connect( mult );\n\n\tvar lambda = FLOOD.compileNodesToLambda( nodes );\n\n\tvar S = new scheme.Interpreter();\n\n\tvar eres = S.eval( [ lambda, 5, 7 ] );\n\n\tassert.equal( eres[0], 12 );\n\tassert.equal( eres[1], 35 );\n\n})(scheme, FLOOD);"
  },
  {
    "path": "app/scripts/lib/flood/test/flood_runner_test.html",
    "content": "<script>\n  var worker = new Worker('../flood_router.js');\n\n  worker.addEventListener('message', function(e) {\n    console.log(e.data);\n  }, false);\n\n  worker.postMessage({kind: \"currentState\"});\n  worker.postMessage({kind: \"addWorkspace\", workspace_id: 0, connections: [], nodes: [{ typeName: \"Add\", id: 5, lastValue: 2 }] });\n  worker.postMessage({kind: \"currentState\"});\n  worker.postMessage({kind: \"removeNode\", workspace_id: 0, id: 5 });\n  worker.postMessage({kind: \"currentState\"});\n  worker.postMessage({kind: \"setWorkspaceContents\", \n                            workspace_id: 0, \n                            connections: [{ start_id: 0, start_port_index: 0, end_id: 5, end_port_index: 0 },\n                                          { start_id: 1, start_port_index: 0, end_id: 5, end_port_index: 1 }],\n                            nodes: [{ typeName: \"Number\", id: 0, lastValue: 0, extensions: { value : 5 } }, \n                                    { typeName: \"Number\", id: 1, lastValue: 2, extensions: { value : 11 } }, \n                                    { typeName: \"Add\", id: 5, lastValue: 4 }] });\n  worker.postMessage({ kind: \"run\", workspace_id: 0, bottom_ids: [5] });\n  worker.postMessage({ kind: \"removeConnection\", workspace_id: 0, id: 5, port_index: 0 })\n  worker.postMessage({ kind: \"run\", workspace_id: 0, bottom_ids: [5] });\n  worker.postMessage({ kind: \"removeNode\", workspace_id: 0, id: 1 });\n  worker.postMessage({ kind: \"run\", workspace_id: 0, bottom_ids: [5] });\n  worker.postMessage({ kind: \"currentState\" });\n  worker.postMessage({ kind: \"removeAll\" });\n  worker.postMessage({ kind: \"currentState\" });\n\n</script>\n\n"
  },
  {
    "path": "app/scripts/lib/flood/test/flood_test.js",
    "content": "var FLOOD = new require('../flood.js')\n\t, assert = require('assert')\n\t, scheme = require('../scheme.js');\n\n// mapApply - applyCartesian without nesting\n(function(scheme, FLOOD) {\n\n\tvar add = new FLOOD.nodeTypes.Add();\n\n\t// expected_arg_types\n\tvar options = {};\n\toptions.expected_arg_types = [[Number], [Number]];\n\toptions.replication = \"applyCartesian\";\n\n\tvar arr0 = new FLOOD.QuotedArray();\n\tarr0.push(-10);\n\tarr0.push(2);\n\n\tvar arr1 = new FLOOD.QuotedArray();\n\tarr1.push(2);\n\tarr1.push(3);\t\n\n\tvar res = add.eval.mapApply(add.eval, [arr0, arr1], options);\n\tassert.equal( 4, res.length );\n\tassert.equal( \"[ -8, -7, 4, 5 ]\", res.toString() );\n\n\tvar res = add.eval.mapApply(add.eval, [arr0, 1], options);\n\tassert.equal( 2, res.length );\n\tassert.equal( \"[ -9, 3 ]\", res.toString() );\n\n\tvar res = add.eval.mapApply(add.eval, [1, 1], options);\n\tassert.equal( \"2\", res.toString() );\n\n\tvar res = add.eval.mapApply(add.eval, [1, arr1], options);\n\tassert.equal( 2, res.length );\n\tassert.equal( \"[ 3, 4 ]\", res.toString() );\n\n})(scheme, FLOOD);\n\n// mapApply - applyLongest with nesting\n(function(scheme, FLOOD) {\n\n\tvar add = new FLOOD.nodeTypes.Add();\n\n\t// expected_arg_types\n\tvar options = {};\n\toptions.expected_arg_types = [[Number], [Number]];\n\toptions.replication = \"applyLongest\";\n\n\tvar arrA = new FLOOD.QuotedArray();\n\tvar arr0 = new FLOOD.QuotedArray();\n\tarrA.push(arr0);\n\tarr0.push(1);\n\n\tvar arrB = new FLOOD.QuotedArray();\n\tvar arr1 = new FLOOD.QuotedArray();\n\tarrB.push(arr1);\n\tarr1.push(2);\n\n\tvar res = add.eval.mapApply(eval, [arrA, arrB], options);\n\n\tassert.equal( 1, res.length );\n\tassert.equal( \"[ [ 3 ] ]\", res.toString() );\n\n\tvar res = add.eval.mapApply(eval, [4, arrB], options);\n\n\tassert.equal( 1, res.length );\n\tassert.equal( \"[ [ 6 ] ]\", res.toString() );\n\n\tvar res = add.eval.mapApply(eval, [arrA, 2], options);\n\n\tassert.equal( 1, res.length );\n\tassert.equal( \"[ [ 3 ] ]\", res.toString() );\n\n\tarr0.push(2);\n\tvar res = add.eval.mapApply(eval, [arrA, 2], options);\n\n\tassert.equal( 1, res.length );\n\tassert.equal( \"[ [ 3, 4 ] ]\", res.toString() );\n\n\tvar res = add.eval.mapApply(eval, [arrA, arrA], options);\n\n\tassert.equal( 1, res.length );\n\tassert.equal( \"[ [ 2, 4 ] ]\", res.toString() );\n\n})(scheme, FLOOD);\n\n// mapApply - applyLongest without nesting\n(function(scheme, FLOOD) {\n\n\tvar add = new FLOOD.nodeTypes.Add();\n\n\t// expected_arg_types\n\tvar options = {};\n\toptions.expected_arg_types = [[Number], [Number]];\n\toptions.replication = \"applyLongest\";\n\n\tvar arr = new FLOOD.QuotedArray();\n\tarr.push(8);\n\tarr.push(9);\n\tarr.push(10);\n\n\tvar res = add.eval.mapApply(eval, [1, arr], options);\n\tassert.equal( 3, res.length );\n\tassert.equal( \"[ 9, 10, 11 ]\", res.toString() );\n\n\tvar res = add.eval.mapApply(eval, [arr, arr], options);\n\tassert.equal( 3, res.length );\n\tassert.equal( \"[ 16, 18, 20 ]\", res.toString() );\n\n\tarr.push(11);\n\n\tvar res = add.eval.mapApply(eval, [1, arr], options);\n\tassert.equal( 4, res.length );\n\tassert.equal( \"[ 9, 10, 11, 12 ]\", res.toString() );\n\n})(scheme, FLOOD);\n\n// doAllTypesMatch\n(function(scheme, FLOOD) {\n\n\tvar arg = [null], arg_type = [[ FLOOD.AnyType ]];\n\tassert.equal( true, FLOOD.doAllTypesMatch( arg, arg_type ) );\n\n\tvar arg = [8], arg_type = [[ Number ]];\n\tassert.equal( true, FLOOD.doAllTypesMatch( arg, arg_type ) );\n\n\tvar arrNum = new FLOOD.QuotedArray();\n\tarrNum.push(8);\n\tvar arg = [ 8, arrNum ], arg_type = [[ Number ], [ FLOOD.QuotedArray, Number ]];\n\tassert.equal( true, FLOOD.doAllTypesMatch( arg, arg_type ) );\n\n\tvar arrString = new FLOOD.QuotedArray();\n\tarrString.push(\"frog\");\n\tvar arg = [ 8, arrNum, arrString ], arg_type = [ [ Number ], [ FLOOD.QuotedArray, Number ], [ FLOOD.QuotedArray, String ] ];\n\tassert.equal( true, FLOOD.doAllTypesMatch( arg, arg_type ) );\n\n\tvar arg = [ 8, arrString, arrNum ], arg_type = [ [ Number ], [ FLOOD.QuotedArray, Number ], [ FLOOD.QuotedArray, String ] ];\n\tassert.equal( false, FLOOD.doAllTypesMatch( arg, arg_type ) );\n\n})(scheme, FLOOD);\n\n// isFastTypeMatch\n(function(scheme, FLOOD) {\n\n\tvar arg = null, arg_type = [ FLOOD.AnyType ];\n\tassert.equal( true, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n\tvar arg = new FLOOD.QuotedArray(null), arg_type = [ FLOOD.QuotedArray, FLOOD.AnyType ];\n\tassert.equal( true, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n\tvar arg = null, arg_type = [ FLOOD.QuotedArray, FLOOD.AnyType ];\n\tassert.equal( false, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n\tvar arg = new FLOOD.QuotedArray(), arg_type = [ FLOOD.QuotedArray, Number ];\n\targ.push(8);\n\tassert.equal( true, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n\tvar arg = new FLOOD.QuotedArray(), arg_type = [ FLOOD.QuotedArray, FLOOD.QuotedArray, Number ];\n\targ.push(\"peter\");\n\targ.push(8);\n\tassert.equal( false, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n\tvar arg = [[8, 8]], arg_type = [Array, Array, Number];\n\tassert.equal( true, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n\tvar arg = [[[8]]], arg_type = [Array, Array, Array, Number];\n\tassert.equal( true, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n\t// new constructor function\n\tfunction Turtle(){};\n\tvar arg = [[[new Turtle()]]], arg_type = [Array, Array, Array, Turtle];\n\tassert.equal( true, FLOOD.isFastTypeMatch(arg, arg_type) );\n\n})(scheme, FLOOD);\n\n// isObjectTypeMatch\n(function(scheme, FLOOD) {\n\n\tvar arg = null, arg_type = FLOOD.AnyType;\n\tassert.equal( true, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = 8, arg_type = Number;\n\tassert.equal( true, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = -8.23, arg_type = Number;\n\tassert.equal( true, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = \"peter\", arg_type = String;\n\tassert.equal( true, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = new FLOOD.QuotedArray(), arg_type = FLOOD.QuotedArray;\n\tassert.equal( true, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = [], arg_type = Number;\n\tassert.equal( false, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = \"peter\", arg_type = Number;\n\tassert.equal( false, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = function(){}, arg_type = Function;\n\tassert.equal( true, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n\tvar arg = function(){}, arg_type = Number;\n\tassert.equal( false, FLOOD.isObjectTypeMatch(arg, arg_type) );\n\n})(scheme, FLOOD);\n\n\n// test case 1\n(function(scheme, FLOOD) {\n\n\tvar add = new FLOOD.nodeTypes.Add();\n\tvar num5 = new FLOOD.nodeTypes.Number();\n\tnum5.value = 5;\n\tvar num2 = new FLOOD.nodeTypes.Number();\n\tnum2.value = 2;\n\n\tadd.inputs[0].connect( num5 );\n\tadd.inputs[1].connect( num2 );\n\n\tassert.equal( add.printExpression() , '(+ 5 2)' );\n\n\tvar S = new scheme.Interpreter();\n\tassert.equal( S.eval( add.compile() ) , 7 );\n\n})(scheme, FLOOD);\n\n\n// test case 2\n(function(scheme, FLOOD) {\n\n\tvar add = new FLOOD.nodeTypes.Add();\n\tvar num5 = new FLOOD.nodeTypes.Number();\n\tnum5.value = 5;\n\n\tvar num2 = new FLOOD.nodeTypes.Number();\n\tnum2.value = 2;\n\n\tadd.inputs[0].connect( num5 );\n\tadd.inputs[1].connect( num2 );\n\n\tvar divide = new FLOOD.nodeTypes.Div();\n\n\tdivide.inputs[0].connect( num5 );\n\tdivide.inputs[1].connect( add );\n\n\tassert.equal( divide.printExpression() , '(/ 5 (+ 5 2))' );\n\n\tvar S = new scheme.Interpreter();\n\tassert.equal( S.eval( divide.compile() ), 5/7);\n\n})(scheme, FLOOD);\n\n\n// test case 3\n(function(scheme, FLOOD) {\n\n\tvar add = new FLOOD.nodeTypes.Add();\n\tvar num5 = new FLOOD.nodeTypes.Number();\n\tnum5.value = 5;\n\tvar num2 = new FLOOD.nodeTypes.Number();\n\tnum2.value = 2;\n\n\tadd.inputs[0].connect( num5 );\n\tadd.inputs[1].connect( num2 );\n\n\tvar divide = new FLOOD.nodeTypes.Div();\n\n\tdivide.inputs[0].connect( num5 );\n\tdivide.inputs[1].connect( add );\n\n\tvar multiply = new FLOOD.nodeTypes.Mult();\n\n\tmultiply.inputs[0].connect( num5 );\n\tmultiply.inputs[1].connect( add );\n\n\tvar begin = new FLOOD.nodeTypes.Begin();\n\n\tbegin.inputs.push( multiply.outputs[0].asInputPort(begin, 0) );\n\tbegin.inputs.push( divide.outputs[0].asInputPort(begin, 0) );\n\n\tbegin.inputs[0].connect( multiply );\n\tbegin.inputs[1].connect( divide );\n\n\tassert.equal( begin.printExpression(), '(begin (* 5 (+ 5 2)) (/ 5 (+ 5 2)))' );\n\n\tvar S = new scheme.Interpreter();\n\tbegin.markDirty();\n\tassert.equal( S.eval( begin.compile() ), 5/7);\n\n})(scheme, FLOOD);\n\n// // test case 4, check that add if curried correctly\n// (function(scheme, FLOOD) {\n\n// \tvar add = new FLOOD.nodeTypes.Add();\n// \tadd.inputs[0].defaultVal = 1;\n// \tadd.inputs[1].useDefault = false;\n\n// \tassert.equal( add.printExpression(), '(+ 1 _)' );\n\n// \tvar S = new scheme.Interpreter();\n// \tadd.markDirty();\n\n// \tvar add1 = S.eval( add.compile() );\n\n// \tassert.equal( add1(6), 7);\n\n// })(scheme, FLOOD);\n\n// // test case 4, use a curried function with map\n// (function(scheme, FLOOD) {\n\n// \tvar num5 = new FLOOD.nodeTypes.Num();\n// \tnum5.value = 5;\n\n// \tvar add = new FLOOD.nodeTypes.Add();\n// \tadd.inputs[0].useDefault = false;\n\n// \tadd.inputs[1].connect( num5 );\n\n// \tvar map = new FLOOD.nodeTypes.Map();\n\n// \tmap.inputs[0].connect( add );\n// \tmap.inputs[1].defaultVal = [\"quote\", [0, 1, 2]];\n\n// \tvar S = new scheme.Interpreter();\n// \tmap.markDirty();\n\n// \tvar mapVal = S.eval( map.compile() );\n\t\n// \tassert.equal( map.value.length, 3);\n// \tassert.equal( map.value[0], 5);\n// \tassert.equal( map.value[1], 6);\n// \tassert.equal( map.value[2], 7);\n\n// })(scheme, FLOOD);\n\n\n\n"
  },
  {
    "path": "app/scripts/lib/flood/test/scheme_async_test.html",
    "content": "\n<script src=\"../../../../bower_components/q/q.js\"></script>\n\n<script>\n\n\n  // an async promise implementation\n  var Promise = function(func){\n\n    this.f = func;\n    this.fulfilled = false;\n    this.shouldContinue = true;\n\n    this.dependents = [];\n\n    this.then = function(func){\n\n      if (!func) return this;\n\n      var prom = func.constructor === Promise ? func : new Promise(func);\n\n      this.dependents.push( prom );\n\n      return prom;\n\n    };\n\n    this.cancel = function(){\n\n      this.shouldContinue = false;\n\n    };\n\n    this.done = function(){\n\n      var that = this;\n      var args = arguments;\n\n      // do work async\n      setTimeout(function(){\n\n        if ( that.first && !that.first.fulfilled ){\n          return that.first.done.apply( that.first, args );\n        }\n\n        var res = that.f.apply(that, args);\n        \n\n        if (res != undefined && res.constructor === Promise){\n\n          res.then( that.next );\n          res.done();\n\n        } else {\n\n          that.resolve( res );\n\n        }\n        \n      }, 0);\n\n     };\n\n     this.resolve = function(res){\n\n        this.fulfilled = true;\n\n        if ( !this.shouldContinue ) {\n          return res;\n        } \n\n        if (this.dependents){\n          this.dependents.forEach(function(p){\n            p.done.call(p, res);\n          });\n        }\n\n     }\n\n  }\n\n  Promise.all = function(promises){\n\n    var promiseCountdown = promises.length;\n    var startedAll = false;\n    var results = new Array( promiseCountdown );\n\n    var prom = new Promise(function(x){\n      return x;\n    });\n\n    promises.forEach(function(p, i){\n\n      return p.then(function(res){\n\n        results[i] = res;\n\n        promiseCountdown--;\n\n        if (promiseCountdown === 0) {\n          return results;\n        }\n\n        console.log(this.f);\n\n        this.cancel();\n        return res;\n        \n      });\n\n    });\n\n    return prom;\n\n  }\n\n  new Promise(function(){ console.log(\"a\"); return 1; })\n  .then(function(){\n    console.log(\"b\");\n  }).then(function(){\n    console.log(\"c\");\n  }).then(function(){ \n    console.log(\"d\"); \n    return new Promise(function(){\n      console.log(\"e\")\n    });\n  }).then(function(){ \n    console.log(\"f\"); \n    return 3; \n  }).done();\n\n\n\n  Promise.all(\n\n    [\n      new Promise(function(){ console.log(\"a\"); return 1; }),\n      new Promise(function(){ console.log(\"b\"); return new Promise(function(){\n        console.log(\"c\")\n      }); }),\n      new Promise(function(){ console.log(\"d\"); return 3; })\n    ]\n\n  ).then(function(res){\n\n    console.log('yo yo yo');\n\n  }).done();\n\n</script>\n\n"
  },
  {
    "path": "app/scripts/lib/flood/test/scheme_eval_async_test.js",
    "content": "var assert = require('assert')\n\t, async = require('../async.js')\n\t, scheme = require('../scheme.js');\n\n\n(function(scheme) {\n\n\tvar S = new scheme.Interpreter();\n\n\tS.eval_async( [\"begin\", 1, 2, 4], undefined, function(res){\n\t\tconsole.log(res);\n\t});\n\n\tS.eval_async( [function(x){ return x * 3; }, [ function(){ return 2; } ] ], undefined, function(res){\n\t\tconsole.log(res);\n\t});\n\n\tS.eval_async( [ \"quote\", \"cool yo\" ], undefined, function(res){\n\t\tconsole.log(res);\n\t});\n\n\t// allows interpreter execution to not block!\n\n})(scheme);"
  },
  {
    "path": "app/scripts/main.js",
    "content": "require([\"config\"], function() {\n\n  require(['backbone', 'App', 'AppView', 'Three', 'Viewport', 'FLOODCSG', 'bootstrap'], function (Backbone, App, AppView) {\n\n    var app = new App();\n\n    app.fetch({\n      error: function(result) {\n        console.error('error');\n        console.error(result);\n      },\n      success: function(){\n        app.enableAutosave();\n      }\n    });\n\n    var appView = new AppView({model: app});\n\n  });\n\n});\n\n"
  },
  {
    "path": "app/scripts/models/App.js",
    "content": "define(['backbone', 'Workspaces', 'Node', 'Login', 'Workspace', 'SearchElements'], \n    function(Backbone, Workspaces, Node, Login, Workspace, SearchElements){\n\n  return Backbone.Model.extend({\n\n    idAttribute: \"_id\",\n\n    url: function() {\n      return '/mys';\n    },\n\n    defaults: {\n      name: \"DefaultSession\",\n      workspaces: new Workspaces(),\n      backgroundWorkspaces: [],\n      currentWorkspace: null,\n      showingBrowser: false,\n      showingSearch: false,\n      showingFeedback: false,\n      showingShare: false,\n      showingHelp: false,\n      isFirstExperience: false,\n      clipBoard: {}\n    },\n\n    initialize: function(args, options){\n      this.on('change:currentWorkspace', this.updateCurrentWorkspace, this);\n      this.updateCurrentWorkspace();\n\n      this.login = new Login({}, { app: this });\n\n      this.SearchElements = new SearchElements({app:this});\n      this.SearchElements.fetch();\n\n      this.get('workspaces').on('remove', this.workspaceRemoved, this);\n    },\n\n    workspaceIdsAwaitingParse : [],\n\n    parse : function(resp) {\n\n      var old = this.get('workspaces').slice();\n\n      this.workspaceIdsAwaitingParse = _.pluck( resp.workspaces, '_id');\n\n      this.get('workspaces').add(resp.workspaces, {app: this});\n      this.get('workspaces').remove(old);\n\n      this.workspaceIdsAwaitingParse = [];\n\n      resp.workspaces = this.get('workspaces');\n\n      return resp;\n\n    },\n\n    fetch : function(options){\n\n      this.login.fetch();\n      Backbone.Model.prototype.fetch.call(this, options);\n      \n    },\n\n    toJSON : function() {\n\n      if (this._isSerializing) {\n          return this.id || this.cid;\n      }\n\n      this._isSerializing = true;\n\n      var json = _.clone(this.attributes);\n\n      _.each(json, function(value, name) {\n          _.isFunction(value.toJSON) && (json[name] = value.toJSON());\n      });\n\n      this._isSerializing = false;\n\n      // dont save the background workspaces, they will be dynamically\n      // loaded on startup\n      var backWs = this.get('backgroundWorkspaces');\n      json.workspaces = json.workspaces.filter(function(x){\n        return !_.contains( backWs, x._id );\n      });\n\n      return json;\n    },\n\n    enableAutosave: function(){\n\n      this.get('workspaces').on('add remove', function(){ this.sync(\"update\", this); }, this );\n      this.on('change:currentWorkspace', function(){ this.sync(\"update\", this); }, this);\n      this.on('change:isFirstExperience', function(){ this.sync(\"update\", this); }, this);\n      this.on('change:backgroundWorkspaces', function(){ this.sync(\"update\", this); }, this);\n\n    },\n\n    newNodePosition: [0,0],\n\n    makeId: function(){\n      return Math.floor(Math.random() * 1e9);\n    },\n\n    getCurrentWorkspace: function(){\n      return this.get('workspaces').get( this.get('currentWorkspace') );\n    },\n\n    getLoadedWorkspace: function(id){\n      return this.get('workspaces').get(id);\n    },\n\n    newWorkspace: function( callback ){\n\n      var that = this;\n\n      $.get(\"/nws\", function(data, status){\n\n        var ws = new Workspace(data, {app: that });\n        that.get('workspaces').add( ws );\n        that.set('currentWorkspace', ws.get('_id') );\n        if (callback) callback( ws );\n\n      }).fail(function(){\n        console.error(\"failed to get new workspace\");\n      });\n\n    },\n\n    newNodeWorkspace: function( callback ){\n\n      var that = this;\n\n      $.get(\"/nws\", function(data, status){\n\n        data.isCustomNode = true;\n\n        var ws = new Workspace(data, { app: that });\n\n        that.get('workspaces').add( ws );\n        that.set('currentWorkspace', ws.get('_id') );\n        if (callback) callback( ws );\n\n      }).fail(function(){\n        console.error(\"failed to get new workspace\");\n      });\n\n    },\n\n    loadWorkspaceDependency: function(id){\n\n      if ( _.contains( this.workspaceIdsAwaitingParse, id ) ) return;\n\n      this.setWorkspaceToBackground( id );\n      this.loadWorkspace( id );\n\n    },\n\n    loadWorkspace: function( id, callback ){\n\n      var that = this;\n\n      $.get(\"/ws/\" + id, function(data, status){\n\n        console.log('workspace loaded ' + data.name )\n\n        var ws = new Workspace(data, {app: that});\n        that.get('workspaces').add( ws );\n        if (callback) callback( ws );\n\n      }).fail(function(){\n        console.error(\"failed to get workspace with id: \" + id);\n      });\n\n    },\n\n    isBackgroundWorkspace: function(id){\n      return this.get('backgroundWorkspaces').indexOf(id) != -1;\n    },\n\n    setWorkspaceToBackground: function(id){\n\n      if ( !this.isBackgroundWorkspace( id ) ){\n        var copy = this.get('backgroundWorkspaces').slice(0);\n        copy.push(id);\n        this.set('backgroundWorkspaces', copy);\n      }\n\n    },\n\n    removeWorkspaceFromBackground: function( id ){\n\n      if ( _.contains( this.get('backgroundWorkspaces'), id) ){\n        var copy = this.get('backgroundWorkspaces').slice(0);\n        copy.remove(copy.indexOf(id));\n        this.set('backgroundWorkspaces', copy);\n      }\n\n    },\n\n    openWorkspace: function( id, callback ){\n\n      this.removeWorkspaceFromBackground( id );\n\n      var ws = this.get('workspaces').get(id);\n\n      if ( ws ){\n        this.set('currentWorkspace', id);\n      }\n\n      var that = this;\n\n      this.loadWorkspace( id, function(ws){\n\n        that.set('currentWorkspace', ws.get('_id') );\n        if (callback) callback( ws );\n\n      });\n\n    },\n\n    updateCurrentWorkspace: function(){\n\n      if (this.get('workspaces').length === 0)\n        return;\n\n      this.get('workspaces').each(function(ele){\n        ele.set('current', false);\n      });\n\n      if ( this.get('currentWorkspace') === null || !this.get('workspaces').get(this.get('currentWorkspace'))) {\n        var ele = this.get('workspaces').at(0);\n        this.set('currentWorkspace', ele.get('_id') );\n      } \n\n      this.get('workspaces').get(this.get('currentWorkspace')).set('current', true);\n\n    },\n\n  });\n\n\n})\n\n\n\n\n"
  },
  {
    "path": "app/scripts/models/Connection.js",
    "content": "define(['backbone'], function(Backbone) {\n\n  return Backbone.Model.extend({\n\n    idAttribute: \"_id\",\n\n    defaults: {\n      startNodeId: 0\n      , endNodeId: 0\n      , startPortIndex: 0\n      , endPortIndex: 0\n      , startProxy: false\n      , endProxy: false\n      , startProxyPosition: [0,0]\n      , endProxyPosition: [0,0]\n      , hidden: false\n    },\n\n    workspace : null,\n    startNode: null,\n    endNode: null,\n\n    initialize: function(args, options){\n\n      this.workspace = options.workspace;\n\n      // proxyconnections bind to the proxyMove event on the workspace\n      if ( args.startProxy || args.endProxy ) {\n        this.workspace.bind('proxyMove', this.proxyMove, this);\n      } else {\n\n        // bind to end nodes\n        this.startNode = this.workspace.get('nodes').get(args.startNodeId);\n        this.endNode = this.workspace.get('nodes').get(args.endNodeId);\n      }\n\n    },\n\n    getOpposite: function(startNode){\n\n      if ( startNode === this.startNode )\n      {\n        return {node: this.endNode, portIndex: this.get('endPortIndex')};\n      }\n\n      if ( startNode === this.endNode )\n      {\n        return {node: this.startNode, portIndex: this.get('startPortIndex')};\n      }\n\n      return {};\n\n    }\n\n  });\n\n});\n"
  },
  {
    "path": "app/scripts/models/Feedback.js",
    "content": "define(['backbone'], function(Backbone) {\n\n\treturn Backbone.Model.extend({\n\n\t  defaults: {\n\t  \tshowing: false,\n\t  \tfailure: false,\n\t  \tfailureMessage: \"Unidentified error\"\n\t  },\n\n\t  send: function(data){\n\n\t  \tif ( !data.subject ){\n\t  \t\tthis.set('failureMessage', 'Please supply a subject for your feedback!');\n\t  \t\tthis.set('failure', true);\n\t  \t\treturn;\n\t  \t}\n\n\t  \tvar that = this;\n\t  \t$.post('/feedback', data, function(e){\n\n\t  \t\tif (e.length && e.length > 0 ) {\n\t  \t\t\tthat.set('failureMessage', e[0].msg);\n\t  \t\t\treturn that.set('failure', true);\n\t  \t\t}\n\n\t  \t\tthat.set('failure', false);\n\t  \t\tthat.trigger('success');\n\t  \t});\n\n\t  }\n\n\t});\n\n});\n\n\n\n"
  },
  {
    "path": "app/scripts/models/GeometryExport.js",
    "content": "define(['FileSaver'], function(FileSaver) {\n\n\t/// Adapted from: https://github.com/stephomi/sculptgl/blob/master/src/misc/ExportSTL.js\n\n\t'use strict';\n\n\tvar Export = {};\n\tvar Utils = {};\n\n\t/** Export STL file */\n\tExport.toSTL = function (scene, filename) {\n\n\t\t// merge all Geometry in three.js scene into one big bag of triangles\n\t\tvar numTris = 0;\n\t\tvar vertices = [];\n\t\tvar faces = [];\n\t\tvar faceNormals = [];\n\t\tvar vertOffset = 0;\n\n     \tscene.traverse(function(ele) {\n\t    \t\n     \t\tif (!ele.visible || !(ele instanceof THREE.Mesh) ) return;\n\n \t\t\t// collect vertices\n \t\t\tele.geometry.vertices.forEach(function(v){\n \t\t\t\tvertices.push( v.x );\n \t\t\t\tvertices.push( v.y );\n \t\t\t\tvertices.push( v.z );\n \t\t\t});\n\n \t\t\t// collect faces, face normals\n \t\t\tele.geometry.faces.forEach(function(face){\n \t\t\t\tfaces.push(vertOffset + face.a);\n \t\t\t\tfaces.push(vertOffset + face.b);\n \t\t\t\tfaces.push(vertOffset + face.c);\n\n \t\t\t\tfaceNormals.push( face.normal.x );\n \t\t\t\tfaceNormals.push( face.normal.y );\n \t\t\t\tfaceNormals.push( face.normal.z );\n\n \t\t\t\tnumTris += 1;\n \t\t\t});\n\n \t\t\tvertOffset += ele.geometry.vertices.length;\n\n      \t});\n\n     \tvar blob = Export.toAsciiSTL(vertices, faces, faceNormals, numTris );\n\n     \tFileSaver( blob, filename );\n\t\t\n\t};\n\n\tUtils.normalizeArrayVec3 = function (array, out) {\n\t\tvar arrayOut = out || array;\n\t\tfor (var i = 0, l = array.length; i < l; ++i) {\n\t\t  var j = i * 3;\n\t\t  var nx = array[j];\n\t\t  var ny = array[j + 1];\n\t\t  var nz = array[j + 2];\n\t\t  var len = 1.0 / Math.sqrt(nx * nx + ny * ny + nz * nz);\n\t\t  arrayOut[j] = nx * len;\n\t\t  arrayOut[j + 1] = ny * len;\n\t\t  arrayOut[j + 2] = nz * len;\n\t\t}\n\t\treturn arrayOut;\n\t};\n\n\t/** Return a buffer array which is at least nbBytes long */\n\tUtils.getMemory = (function () {\n\t\tvar pool = new ArrayBuffer(100000);\n\t\treturn function (nbBytes) {\n\t\t  if (pool.byteLength >= nbBytes)\n\t\t    return pool;\n\t\t  pool = new ArrayBuffer(nbBytes);\n\t\t  return pool;\n\t\t};\n\t})();\n\n\t/** Export Ascii STL file */\n\tExport.toAsciiSTL = function (vAr, iAr, origFN, nbTriangles) {\n\n\t\tvar faceNormals = new Float32Array(Utils.getMemory(origFN.length * 4), 0, origFN.length);\n\t\tUtils.normalizeArrayVec3(origFN, faceNormals);\n\t\tvar data = 'solid mesh\\n';\n\n\t\tfor (var i = 0; i < nbTriangles; ++i) {\n\t\t  var j = i * 3;\n\t\t  data += ' facet normal ' + faceNormals[j] + ' ' + faceNormals[j + 1] + ' ' + faceNormals[j + 2] + '\\n';\n\t\t  data += '  outer loop\\n';\n\t\t  var iv1 = iAr[j] * 3;\n\t\t  var iv2 = iAr[j + 1] * 3;\n\t\t  var iv3 = iAr[j + 2] * 3;\n\t\t  data += '   vertex ' + vAr[iv1] + ' ' + vAr[iv1 + 1] + ' ' + vAr[iv1 + 2] + '\\n';\n\t\t  data += '   vertex ' + vAr[iv2] + ' ' + vAr[iv2 + 1] + ' ' + vAr[iv2 + 2] + '\\n';\n\t\t  data += '   vertex ' + vAr[iv3] + ' ' + vAr[iv3 + 1] + ' ' + vAr[iv3 + 2] + '\\n';\n\t\t  data += '  endloop\\n';\n\t\t  data += ' endfacet\\n';\n\t\t}\n\t\tdata += 'endsolid mesh\\n';\n\n\t\treturn new Blob([data]);\n\t};\n\n\treturn Export;\n\n});"
  },
  {
    "path": "app/scripts/models/Help.js",
    "content": "define(['backbone'], function(Backbone) {\n\n\treturn Backbone.Model.extend({\n\n\t  defaults: {\n\t  \tsections:\n\t  \t\t[ { title: \"Workspace Tabs\",\n\t  \t\t\t\ttargetId : \"add-workspace-button\",\n\t  \t\t\t\toffset: [5, 5],\n\t  \t\t\t\ttext: \"Switch between or add new active workspaces\"\n\t  \t\t\t},\n\t  \t\t\t{ title: \"Node Library\",\n\t  \t\t\t\ttargetId : \"bottom-search\",\n\t  \t\t\t\toffset: [5, -110],\n\t  \t\t\t\ttext: \"This is one place where you can add new nodes.  You can also double click on the workspace to add nodes.\"\n\t  \t\t\t},\n\t  \t\t\t{ title: \"3D Focus Control\",\n\t  \t\t\t\ttargetId : \"workspace_hide\",\n\t  \t\t\t\toffset: [-170,-100],\n\t  \t\t\t\ttext: \"Toggle between the 3D view and your workspace\"\n\t  \t\t\t},\n\t  \t\t\t{ title: \"Workspace Browser\",\n\t  \t\t\t\ttargetId : \"workspace-browser-button\",\n\t  \t\t\t\toffset: [-170,0],\n\t  \t\t\t\ttext: \"You can find all of your past work in the Workspace Browser\"\n\t  \t\t\t},\n\t  \t\t\t{ title: \"Export STL\",\n\t  \t\t\t\ttargetId : \"export-button\",\n\t  \t\t\t\toffset: [20,-110],\n\t  \t\t\t\ttext: \"Export all visible geometry to STL for 3D printing\"\n\t  \t\t\t},\n\t  \t\t\t{ title: \"Share a customizer\",\n\t  \t\t\t\ttargetId : \"share-button\",\n\t  \t\t\t\toffset: [-200,10],\n\t  \t\t\t\ttext: \"Share a customizer with anyone on the internet!\"\n\t  \t\t\t},\n                // { title: \"Zoom\",\n\t  \t\t\t// \ttargetId : \"zoomreset-button\",\n\t  \t\t\t// \toffset: [20,-110],\n\t  \t\t\t// \ttext: \"Use this control the workspace zoom, or use Ctrl +, Ctrl -\"\n\t  \t\t\t// }\n\t  \t\t]\n\t  }\n\n\t});\n});\n"
  },
  {
    "path": "app/scripts/models/Login.js",
    "content": "define(['backbone'], function(Backbone) {\n\n\treturn Backbone.Model.extend({\n\n\t  defaults: {\n\t  \tisLoggedIn : false,\n\t  \tfailed : false,\n\t  \tfailureMessage : \"\",\n\t  \tshowing: false,\n\t  \temail : \"\"\n\t  },\n\n\tinitialize: function(atts, vals) {\n\t  \tthis.app = vals.app;\n\t  },\n\n\t  fetch : function(){\n\n\t  \tvar that = this;\n\t  \t$.get('/email', function(e){\n\t  \t\tif (e.email) {\n\t  \t\t\tthat.set('email', e.email);\n\t  \t\t\tthat.set('isLoggedIn', true); \n\t  \t\t} else {\n\t  \t\t\tthat.set('isLoggedIn', false);\n\t  \t\t}\n\t  \t});\n\n\t  },\n\n\t\ttoggle: function(){\n\t\t  return this.get('showing') ? this.hide() : this.show();\n\t\t},\n\n\t\tshow: function() {\n\t\t  this.set('showing', true);\n\t\t},\n\n\t\thide: function() {\n\t\t  this.set('showing', false);\n\t\t},\n\n\t  signup: function(data){\n\n\t  \tvar that = this;\n\t  \t$.post('/signup', data, function(e){\n\n\t  \t\tif (e.length && e.length > 0 ) {\n\t  \t\t\tthat.set('failureMessage', e[0].msg);\n\t  \t\t\treturn that.set('failed', true);\n\t  \t\t}\n\n\t  \t\tthat.set('failed', false);\n\t  \t\tthat.app.fetch();\n\t  \t});\n\n\t  },\n\n\t  login: function(data){\n\n\t  \tvar that = this;\n\t  \t$.post('/login', data, function(e){\n\n\t  \t\tif (e.length && e.length > 0 ) {\n\t  \t\t\tthat.set('failureMessage', e[0].msg);\n\t  \t\t\treturn that.set('failed', true);\n\t  \t\t}\n\n\t  \t\tthat.set('failed', false);\n\t  \t\tthat.app.fetch();\n\t  \t});\n\n\t  },\n\n\t  logout: function(){\n\n\t  \tvar that = this;\n\t  \t$.get('/logout', {}, function(e){\n\t  \t\tthat.app.fetch();\n\t  \t});\n\n\t  }\n\n\t});\n});\n"
  },
  {
    "path": "app/scripts/models/Marquee.js",
    "content": "define(['backbone'], function(Backbone) {\n\n  return Backbone.Model.extend({\n\n    idAttribute: \"_id\",\n\n    defaults: {\n      x: 10\n      , y: 10\n      , width: 50\n      , height: 50\n      , hidden: true\n    },\n\n    startCorner: [10,10],\n\n    endCorner: [20, 20],\n\n    initialize: function(args, options){\n\n      this.workspace = options.workspace;\n\n    },\n\n    updateRawValues: function(){\n\n      this.set('width', Math.abs( this.startCorner[0] - this.endCorner[0] ) );\n      this.set('height', Math.abs( this.startCorner[1] - this.endCorner[1] ) );\n      this.set('x', Math.min( this.startCorner[0], this.endCorner[0] ) );\n      this.set('y', Math.min( this.startCorner[1], this.endCorner[1] ) );\n\n    },\n\n    setStartCorner: function( posInWorkspace ){\n\n      this.startCorner = posInWorkspace;\n      this.endCorner = posInWorkspace;\n\n      this.updateRawValues();\n\n    },\n\n    setEndCorner: function( posInWorkspace ){\n\n      this.endCorner = posInWorkspace;\n\n      this.updateRawValues();\n\n    }\n\n  });\n\n});\n"
  },
  {
    "path": "app/scripts/models/Node.js",
    "content": "var app = app || {};\n\ndefine(['backbone', 'FLOOD'], function(Backbone, FLOOD) {\n\n  return Backbone.Model.extend({\n\n    idAttribute: \"_id\",\n\n    defaults: {\n      name: 'DefaultNodeName'\n      , position: [10, 10]\n      , typeName: 'Add'\n      , type: null\n      , inputConnections: []\n      , outputConnections: []\n      , selected: true\n      , lastValue: null\n      , failureMessage: null\n      , visible: true\n      , replication: \"applyLongest\"\n      , extra: {}\n      , ignoreDefaults: []\n      , isEvaluating: false\n    },\n\n    initialize: function(atts, vals) {\n\n      // we need to know the type in order to create the node\n      if ( atts.typeName != null && FLOOD.nodeTypes[atts.typeName] != undefined){\n        this.set( 'type', new FLOOD.nodeTypes[ atts.typeName ]() );\n      } else if ( atts.typeName != null && FLOOD.internalNodeTypes[atts.typeName] != undefined ) {\n        this.set( 'type', new FLOOD.internalNodeTypes[ atts.typeName ]() );\n      } else {\n        this.set( 'type', new FLOOD.nodeTypes.Add() );\n      }\n\n      if (atts.extra){ this.get('type').extend( atts.extra );  }\n\n      if (atts.lastValue){\n        this.get('type').value = atts.lastValue;\n      }\n\n      if (atts.ignoreDefaults && atts.ignoreDefaults.length > 0){\n\n        for (var i = 0; i < this.get('type').inputs.length; i++){\n          this.get('type').inputs[i].useDefault = !atts.ignoreDefaults[i];\n        }\n        \n      } else {\n        atts.ignoreDefaults = this.get('type').inputs.map(function(x){ return !x.useDefault; });\n      }\n\n      this.set('ignoreDefaults', atts.ignoreDefaults );\n      \n      var that = this;\n      this.on('connection', this.onConnectPort);\n      \n      this.on('disconnection', this.onDisconnectPort);\n      this.workspace = vals.workspace;\n\n      this.on('remove', this.onRemove);\n\n      this.initializePorts();\n      \n    },\n\n    // called when saving the node to server\n    serialize : function() {\n\n      var vals = {\n        name: this.get(\"name\")\n        , position: this.get('position')\n        , typeName: this.get('typeName')\n        , selected: this.get('selected')\n        , visible: this.get('visible')\n        , ignoreDefaults: this.get('ignoreDefaults')\n        , _id: this.get('_id')\n        , replication: this.get('replication')\n        , extra: this.get('extra')\n      };\n\n      return vals;\n\n    },\n\n    initializePorts: function() {\n\n      var type = this.get('type');\n   \n      this.set('inputConnections', new Array( type.inputs.length ));\n      this.set('outputConnections', new Array( type.outputs.length ));\n\n    },\n\n    onRemove: function(){\n\n      this.trigger('removed');\n\n    },\n\n    onEvalFailed: function(ex){\n\n      this.trigger('evalFailed', ex);\n\n    },\n\n    onEvalBegin: function(isNew){\n\n      if (!isNew) return;\n      this.trigger('evalBegin');\n      this.set('isEvaluating', true);\n\n    },\n\n    onEvalComplete: function(isNew, value, prettyValue){\n\n      if (!isNew) return;\n\n      this.set('lastValue', value);\n      this.set('prettyLastValue', prettyValue);\n      this.set('isEvaluating', false);\n      this.trigger('evalComplete');\n\n    },\n\n    select: function() {\n      this.set('selected', false);\n    },\n\n    deselect: function() {\n      this.set('selected', true);\n    },\n\n    // get the input or output ports of a node\n    getPorts: function(isOutput){\n      return isOutput ? this.get('outputConnections') : this.get('inputConnections');\n    },\n\n    // determine if a given port is connected or not\n    isPortConnected: function(index, isOutput){\n\n      if ( !this.isValidPort(index, isOutput) ) {\n        return true;\n      }\n\n      var ports = this.getPorts(isOutput);\n      return ports[index] != null && ports[index].length > 0;\n\n    },\n\n    isPartialFunctionApplication: function(){\n\n      var numInPorts = this.get('inputConnections').length;\n\n      for (var i = 0; i < numInPorts; i++){\n        if (!this.isPortConnected(i, false) && !this.isInputPortUsingDefault(i) ){\n          return true;\n        } \n      }\n\n      return false;\n\n    },\n\n    isInputPortUsingDefault: function(index){\n\n      if ( !this.isValidPort(index, false) ) {\n        return false;\n      }\n\n      return !this.get('ignoreDefaults')[index];\n\n    },\n\n    // get the type of a given node port\n    getPortType: function(index, isOutput){\n      \n      if (index < 0)\n        return null;\n\n      var type = this.get('type')\n        , ports = isOutput ? type.outputs : type.inputs;\n\n      if ( ports.length > index )\n        return ports[index].type\n\n      return null;\n\n    },\n\n    isValidPort: function(index, isOutput){\n      return this.getPortType(index, isOutput) != null;\n    },\n\n    // get the node and index of the opposite end of a port\n    // returns object containing \"node\", \"portIndex\" fields\n    // if out of range, returns null\n    getOppositeNodeAndPort: function(index, isOutput){\n\n      if ( !this.isValidPort(index, isOutput) ) {\n        return null;\n      }\n\n      return this.getPorts(isOutput)[index];\n    },\n\n    isOutputNode: function(){\n      return this.get('outputConnections').reduce(function(memo, ele){\n        return memo && (ele.length === 0);\n      }, true);\n    },\n\n    connectPort: function( portIndex, isOutput, connection ) {\n\n      if ( !this.isValidPort(portIndex, isOutput) ) {\n        return null; // the port doesn't exist\n      }\n\n      // initialize if necessary\n      if ( this.getPorts( isOutput )[portIndex] === undefined )\n        this.getPorts( isOutput )[portIndex] = [];\n\n      // add the connection to the array\n      this.getPorts( isOutput )[portIndex].push(connection);\n\n      // listen for deletion or update of the connection\n      var that = this;\n      this.listenTo( connection, 'remove', (function(){\n        return function(){\n          that.disconnectPort( portIndex, connection, isOutput );\n        };\n      })());\n\n      this.trigger('connection', portIndex, isOutput, connection);\n      this.trigger('change');\n\n      return this;\n\n    },\n\n    getConnectionAtIndex: function( portIndex, isOutput, connectionIndex ){\n\n      var ports = this.getAllConnectionsAtPort( portIndex, isOutput );\n\n      if (ports == null) return null;\n      if ( connectionIndex === undefined ) connectionIndex = 0;\n      if ( connectionIndex >= ports.length || connectionIndex < 0) return null;\n\n      return ports[connectionIndex];\n\n    },\n\n    getAllConnectionsAtPort: function( portIndex, isOutput ){\n\n      if (!this.isValidPort(portIndex, isOutput)) return null;\n\n      if (isOutput === undefined) isOutput = false;\n\n      var ports = this.getPorts(isOutput)[portIndex];\n      return ports;\n\n    },\n\n    disconnectPort: function( portIndex, connection, isOutput ){\n\n      if (!this.isValidPort(portIndex, isOutput)){\n        return;\n      }\n\n      var port = this.getPorts(isOutput)[portIndex];\n\n      if (port == null)\n        return;\n\n      var index = -1;\n      if ( connection ){\n\n        var index = port.indexOf(connection);\n\n      } else if (!isOutput && port.length > 0) {\n\n        index = 0;\n        connection = port[0];\n        isOutput = false;\n        this.workspace.get('connections').remove( connection );\n\n      }\n        \n      if (index === -1) return;\n        \n      // remove the requested connection on the port\n      port.remove(index);\n\n      this.trigger('disconnection', portIndex, isOutput, connection);\n      this.trigger('change');\n        \n    },\n\n    onConnectPort: function( portIndex, isOutput, connection){\n      \n      if (isOutput)\n        return;\n\n      // connect the logic nodes\n      var type = this.get('type')\n        , opp = connection.getOpposite( this )\n        , oppType = opp.node.get('type')\n        , oppIndex = opp.portIndex;\n\n      type.inputs[portIndex].connect( oppType, oppIndex );\n\n    },\n\n    onDisconnectPort: function( portIndex, isOutput, connection ){\n      \n      if (isOutput){\n        return;\n      }\n\n      if (!isOutput){\n        this.get('type').inputs[portIndex].disconnect();\n      }\n\n      if (this.workspace)\n        this.workspace.run();\n\n    }\n\n  });\n\n});\n\n\n\n"
  },
  {
    "path": "app/scripts/models/Runner.js",
    "content": "define(['backbone','underscore'], function(Backbone, _) {\n\n\treturn Backbone.Model.extend({\n\n\t  defaults: {\n\t  \tisRunning : false\n\t  },\n\n\t\tinitialize: function(atts, vals) {\n\n\t\t\tthis.app = vals.app;\n\t\t\tvar ws = vals.workspace;\n\t\t\tthis.workspace = ws;\n\n\t\t\tthis.set('id', ws.get('_id') );\n\n\t\t\tthis.reset();\n\n\t\t\tvals.workspace.get('connections').on('add', this.addConnection, this );\n\t\t\tvals.workspace.get('connections').on('remove', this.removeConnection, this );\n\n\t\t\tvals.workspace.get('nodes').on('add', this.addNode, this );\n\t\t\tvals.workspace.get('nodes').on('remove', this.removeNode, this );\n\n\t\t\tthis.runCount = 0;\n\t\t\tthis.averageRunTime = 0;\n\n\t\t\tthis.run = _.throttle(this.run, 120);\n\n\t  },\n\n\t  post: function(data, quiet){\n\n\t  \tif (!data.workspace_id)\n\t  \t\tdata.workspace_id = this.workspace.get('_id');\n\n\t  \tthis.worker.postMessage(data);\n\n\t  \tif (quiet) return;\n\n\t  \tthis.trigger('post', data );\n\n\t  },\n\n\t  onWorkerMessage: function(data){\n\n\t  \tvar cb = this[\"on_\" + data.kind];\n\t  \tif ( cb ) cb.call(this, data);\n\t\t\t\n\t  },\n\n\t  initWorker: function(){\n\n\t  \tthis.worker = new Worker(\"scripts/lib/flood/flood_runner.js\");\n\n\t  \tvar that = this;\n\n\t\t\tthis.worker.addEventListener('message', function(e) {\n\t\t\t\treturn that.onWorkerMessage.call(that, e.data);\t\n\t\t\t}, false);\n\n\t  },\n\n\t  initWorkspace: function(){\n\n\t  \tthis.post({kind: 'addWorkspace'});\n\n\t  \tvar wsc = this.workspace.toJSON();\n\t  \tvar ncb = function(){ this.updateNode( node ); };\n\n\t  \tvar that = this;\n\t  \tthis.workspace.get('nodes').each(function(x){\n\t  \t\tthat.watchNodeEvents.call(that, x);\n\t  \t});\n\n\t  \twsc.kind = \"setWorkspaceContents\";\n  \t  this.post( wsc );\n\n\t  },\n\n\t  on_nodeEvalComplete: function(data){\n\n\t  \tvar node = this.workspace.get('nodes').get( data._id );\n\t  \tif (node)\n\t  \t\tnode.onEvalComplete( data.isNew, data.value, data.prettyValue );\n\n\t  },\n\n\t \ton_nodeEvalFailed: function(data){\n\n\t \t\tvar node = this.workspace.get('nodes').get( data._id );\n\t  \tif (node)\n\t  \t\tthis.workspace.get('nodes').get( data._id ).onEvalFailed(data.exception);\n\n\t  },\n\n\t \ton_nodeEvalBegin: function(data){\n\n\t \t\tvar node = this.workspace.get('nodes').get( data._id );\n\t  \tif (node)\n\t  \t\tthis.workspace.get('nodes').get( data._id ).onEvalBegin( data.isNew );\n\n\t  },\n\n\t  on_run: function(data){\n\n\t  \tconsole.log( data );\n\t  \tthis.set('isRunning', false);\n\t  \tthis.runCount++;\n\n\t  \tthis.trigger('runComplete');\n\n\t  },\n\n\t  cancel: function(){\n\n\t  \tthis.set('isRunning', false);\n\t  \tthis.worker.terminate();\n\t  \tthis.reset();\n\n\t  },\n\n\t  runQueued : false,\n\n\t  run: function( bottomIds ){\n\n\t  \tthis.post({ kind: \"run\", bottom_ids: bottomIds });\n\t  \tthis.set('isRunning', true);\n\n\t  },\n\n\t  watchNodeEvents: function( node ){\n\n\t  \tvar u = function(){ this.updateNode( node ); };\n\t  \tnode.on('change:replication', u, this );\n      node.on('change:ignoreDefaults', u, this);\n  \t\tnode.on('updateRunner', u, this );\n\n\t  },\n\n\t  updateNode: function( node ){\n\n\t  \tvar n = node.serialize();\n\n\t  \tn.kind = \"updateNode\";\n\t  \tn.workspace_id = node.workspace.id;\n\n\t  \tthis.post( n );\n\n\t  },\n\n\t  addNode: function(node){\n\n\t  \tvar n = node.serialize();\n\t  \tn.kind = \"addNode\";\n\t  \tn.workspace_id = node.workspace.id;\n\n\t  \tthis.watchNodeEvents( node );\n\n\t  \tthis.post(n);\n\n\t  },\n\n\t  removeNode: function(node){\n\n\t  \tvar n = node.serialize();\n\t  \tn.kind = \"removeNode\";\n\t  \tn.workspace_id = node.workspace.id;\n\n\t  \tthis.post( n );\n\n\t  },\n\n\t  addConnection: function(connection, workspace){\n\n\t  \tvar c = connection.toJSON();\n\t  \tc.kind = \"addConnection\";\n\t  \tc.id = connection.get('_id');\n\t  \tc.workspace_id = connection.workspace.id;\n\n\t  \tthis.post(c);\n\n\t  },\n\n\t  removeConnection: function(connection){\n\n\t  \tvar c = connection.toJSON();\n\t  \tc.kind = \"removeConnection\";\n\t  \tc.id = connection.get('endNodeId');\n\t  \tc.portIndex = connection.get('endPortIndex');\n\t  \tc.workspace_id = connection.workspace.id;\n\n\t  \tthis.post( c );\n\n\t  },\t\n\n\t  recompile: function(workspace){\n\n\t  \tvar c = workspace.toJSON();\n\t  \tc.kind = \"recompile\";\n\n\t  \tthis.post( c );\n\n\t  },\n\n\t \taddDefinition: function(workspace){\n\n\t  \tvar c = workspace.toJSON();\n\t  \tc.kind = \"addDefinition\";\n\t  \tc.workspace_id = c._id;\n\n\t  \tvar that = this;\n\t  \tworkspace.get('nodes').each(function(x){\n\t  \t\tthat.watchNodeEvents.call(that, x);\n\t  \t});\n\n\t\t\tworkspace.get('connections').on('add', function(x){ \n\t\t\t\tthis.addConnection(x);\n\t\t\t\tthis.recompile(workspace);\n\t\t\t\tthis.workspace.trigger('requestRun');\n\t\t\t}, this );\n\n\t\t\tworkspace.get('connections').on('remove', function(x){ \n\t\t\t\tthis.removeConnection(x);\n\t\t\t\tthis.recompile(workspace);\n\t\t\t\tthis.workspace.trigger('requestRun');\n\t\t\t}, this );\n\n\t\t\tworkspace.get('nodes').on('add', function(x){ \n\t\t\t\tthis.addNode(x);\n\t\t\t\tthis.recompile(workspace);\n\t\t\t\tthis.workspace.trigger('requestRun');\n\t\t\t}, this );\n\n\t\t\tworkspace.get('nodes').on('remove', function(x){ \n\t\t\t\tthis.removeNode(x);\n\t\t\t\tthis.recompile(workspace);\n\t\t\t\tthis.workspace.trigger('requestRun');\n\t\t\t}, this );\n\n\t  \tthis.post( c );\n\n\t  },\t\n\n\t  on_recompile: function(data){\n\t  \tconsole.log(data);\n\t  },\n\n\t  reset: function(){\n\n\t  \tthis.initWorker();\n\t  \tthis.initWorkspace();\n\n\t  }\n\n\t});\n});"
  },
  {
    "path": "app/scripts/models/Search.js",
    "content": "define(['backbone'], function(Backbone) {\n\n\treturn Backbone.Model.extend({\n\n\t  defaults: {\n\n\t  },\n\n\t  initialize: function(atts, vals) {\n\t  \t\n\t  }\n\n\t});\n\n});\n\n\n\n"
  },
  {
    "path": "app/scripts/models/SearchElement.js",
    "content": "define(['backbone'], function(Backbone) {\n\n  return Backbone.Model.extend({\n\n    defaults: {\n      name: null,\n      isCustomNode: false,\n      functionId: -1\n    }, \n    \n    initialize: function(a, b) {\n      this.app = a.app;\n    }\n\n  });\n\n});\n\n\n"
  },
  {
    "path": "app/scripts/models/Share.js",
    "content": "define(['backbone'], function(Backbone) {\n\n\treturn Backbone.Model.extend({\n\n\t  defaults: {\n\t  \tisProjectWorkspace: false,\n\t  },\n\n\t  initialize: function(atts, vals) {\n\n\t  \tthis.app = atts.app;\n\n\t  \t// this.app.on('change:currentWorkspace', function(x){\n\t  \t// \tconsole.log( this.app.getCurrentWorkspace() );\n\t  \t// }, this);\n\n\t  },\n\n\t});\n\n});"
  },
  {
    "path": "app/scripts/models/Workspace.js",
    "content": "define(['backbone', 'Nodes', 'Connection', 'Connections', 'scheme', 'FLOOD', 'Runner', 'Node', 'Marquee', 'WorkspaceResolver', 'GeometryExport'], \n    function(Backbone, Nodes, Connection, Connections, scheme, FLOOD, Runner, Node, Marquee, WorkspaceResolver, GeometryExport) {\n\n  return Backbone.Model.extend({\n\n    idAttribute: \"_id\",\n\n    url: function(){\n      return '/ws/' + this.get('_id');\n    },\n\n    defaults: {\n      name: \"Unnamed Workspace\",\n      nodes: null,\n      connections: null,\n      zoom: 1,\n      current: false,\n      isPublic: false,\n      isRunning: false,\n      lastSaved: Date.now(),\n      offset: [4000,4000],\n\n      // undo/redo stack\n      undoStack: [],\n      redoStack: [],\n      clipBoard: [],\n\n      // for custom nodes\n      workspaceDependencyIds: [],\n      isCustomNode: false,\n      isCustomizer: false\n    },\n\n    // connection creation\n    draggingProxy: false,\n    proxyConnection: null,\n\n    // marquee selection\n    dragSelect: false,\n\n    runAllowed: false,\n\n    initialize: function(atts, arr) {\n\n      atts = atts || {};\n\n      // if offset is not defined\n      if (!atts.offset || isNaN( atts.offset[0] ) || isNaN( atts.offset[1] )){\n        atts.offset = this.defaults.offset;\n        this.set( 'offset', this.defaults.offset );\n      }\n\n\n      this.app = arr.app;\n\n      this.set('nodes', new Nodes( atts.nodes, { workspace: this }) );\n      this.set('connections', new Connections( atts.connections, { workspace: this}) );\n\n      // tell all nodes about connections\n      _.each( this.get('connections').where({startProxy: false, endProxy: false}), function(ele, i) {\n        this.get('nodes').get(ele.get('startNodeId')).connectPort( ele.get('startPortIndex'), true, ele);\n        this.get('nodes').get(ele.get('endNodeId')).connectPort(ele.get('endPortIndex'), false, ele);\n      }, this);\n\n      // updates to connections and nodes are emitted to listeners\n      var that = this;\n\n      this.get('connections').on('add remove', function(){ \n        that.trigger('change:connections'); \n        that.trigger('requestRun');\n      });\n\n      this.get('nodes').on('add remove', function(){ \n        that.trigger('change:nodes'); \n        that.trigger('requestRun');\n      });\n\n      this.proxyConnection = new Connection({\n        _id: -1, \n        startProxy: true, \n        endProxy: true, \n        startProxyPosition: [0,0], \n        endProxyPosition: [0,0],\n        hidden: true }, { workspace: this });\n\n      this.marquee = new Marquee({\n        _id: -1, \n        hidden: true }, { workspace: this });\n\n      this.runAllowed = true;\n\n      if ( !this.get('isCustomNode') ) this.initializeRunner();\n\n      this.sync = _.throttle(this.sync, 2000);\n\n      // save on every change\n      var throttledSync = _.throttle(function(){ this.sync('update', this); }, 1000);\n      this.on('runCommand', throttledSync, this);\n      this.on('change:name', throttledSync, this);\n      this.on('change:zoom', throttledSync, this);\n      this.on('change:offset', throttledSync, this);\n      this.on('change:workspaceDependencyIds', throttledSync, this);\n      this.on('requestRun', this.run, this);\n\n      // this should not be throttled\n      this.on('change:isCustomizer', function(){ this.sync('update', this); }, this);\n\n      if ( this.get('isCustomNode') ) this.initializeCustomNode();\n\n      this.resolver = new WorkspaceResolver(null, { app : this.app, workspace : this });\n      this.resolver.resolveAll();\n\n      this.app.trigger('workspaceLoaded', this);\n\n    },\n\n    getCustomizerUrl: function(){\n\n      // if (!this.get('isCustomizer')){\n      //   return \"none\";\n      // }\n\n      var domain = document.URL.match(/:\\/\\/(.[^/]+)/)[1];\n      return domain + \"/customize-\" + this.id;\n    },\n\n    exportSTL: function(){\n\n      GeometryExport.toSTL(scene, this.get('name') + \".stl\" );\n\n    },\n\n    customNode : null,\n\n    initializeCustomNode: function(){\n\n      this.customNode = new FLOOD.internalNodeTypes.CustomNode( this.get('name'), this.get('_id') );\n\n      var ni = this.get('nodes').where({typeName: \"Input\"}).length;\n      var no = this.get('nodes').where({typeName: \"Output\"}).length;\n\n      this.customNode.setNumInputs(ni);\n      this.customNode.setNumOutputs(no);\n\n      this.app.SearchElements.addCustomNode( this.customNode );\n\n      var that = this;\n\n      this.on('change:name', function(){\n        that.customNode.functionName = that.get('name');\n        that.app.SearchElements.addCustomNode( that.customNode );\n      }, this);\n\n    },\n\n    toJSON : function() {\n\n        this.set('undoStack', _.last( this.get('undoStack'), 10) );\n        this.set('redoStack', _.last( this.get('redoStack'), 10) );\n\n        if (this._isSerializing) {\n            return this.id || this.cid;\n        }\n\n        this._isSerializing = true;\n\n        var json = _.clone(this.attributes);\n\n        _.each(json, function(value, name) {\n            _.isFunction(value.toJSON) && (json[name] = value.toJSON());\n        });\n\n        this._isSerializing = false;\n\n        return json;\n    },\n\n    initializeRunner: function(){\n\n      this.runner = new Runner({id : this.get('_id') }, { workspace: this });\n\n      var that = this;\n      this.runner.on('change:isRunning', function(v){\n        that.set('isRunning', v.get('isRunning'));\n      });\n\n    },\n\n    getCustomNodeInputsOutputs: function(getOutputs){\n\n      var typeName = getOutputs ? \"Output\" : \"Input\";\n\n      return this.get('nodes').filter(function(x){\n        return x.get('type').typeName === typeName;\n      });\n\n    },\n\n    getCustomNodes: function(){\n\n      return this.get('nodes').filter(function(x){\n        return x.get('type') instanceof FLOOD.internalNodeTypes.CustomNode;\n      });\n\n    },\n\n    getCustomNodesWithId: function(functionId){\n\n      return this.getCustomNodes().filter(function(x){\n        return x.get('type').functionId === functionId;\n      });\n\n    },\n\n\n    zoomIn: function(){\n\n      if ( this.get('zoom') + 0.2 > 1 ){\n        return this.set('zoom', 1);\n      }\n\n      this.set('zoom', this.get('zoom') + 0.2);\n\n    },\n\n    zoomOut: function(){\n\n      if ( this.get('zoom') - 0.2 < 0.2 ){\n        return this.set('zoom', 0.2);\n      }\n\n      this.set('zoom', this.get('zoom') - 0.2);\n\n    },\n\n    parse : function(resp) {\n      resp.nodes = new Nodes( resp.nodes );\n      resp.connections = new Connections( resp.connections )\n      return resp;\n    },\n\n    printModel: function(){\n      console.log(this.toJSON());\n    },\n\n    addToUndoAndClearRedo: function(cmd){\n\n      this.get('undoStack').push(cmd);\n      this.get('redoStack').length = 0;\n\n    },  \n\n    removeSelected: function(){\n\n      // get all selected nodes\n      var that = this;\n      var nodeFound = false;\n      var nodesToRemove = {};\n      this.get('nodes')\n          .each(function(x){ \n            if ( x.get('selected') ){\n              nodeFound = true;\n              nodesToRemove[ x.get('_id') ] = x.serialize();\n            }\n          });\n\n      if (!nodeFound) return;\n\n      // get all relevant connections\n      var connsToRemove = {};\n      this.get('connections')\n        .each(function(x){\n          if ( nodesToRemove[ x.get('startNodeId') ] || nodesToRemove[ x.get('endNodeId') ] ){\n            if ( !connsToRemove[ x.get('_id')  ] ){\n              connsToRemove[ x.get('_id') ] = x.toJSON();\n            } \n          }\n        });\n\n      // construct composite command\n      var multipleCmd = { kind: \"multiple\", commands: [] };\n\n      // first remove all connections\n      for (var connId in connsToRemove){\n        var connToRemove = connsToRemove[connId];\n        connToRemove.kind = \"removeConnection\";\n        multipleCmd.commands.push( connToRemove );\n      }\n\n      // then remove all nodes\n      for (var nodeId in nodesToRemove){\n        var nodeToRemove = nodesToRemove[nodeId];\n        nodeToRemove.kind = \"removeNode\";\n        multipleCmd.commands.push( nodeToRemove );\n      }\n\n      this.runInternalCommand( multipleCmd );\n      this.addToUndoAndClearRedo( multipleCmd );\n\n    },\n\n    makeId: function(){\n      return this.app.makeId();\n    },\n\n    copy: function(){\n\n      // get all selected nodes\n      var that = this;\n      var nodeFound = false;\n      var copyNodes = {};\n      this.get('nodes')\n          .each(function(x){ \n            if ( x.get('selected') ){\n              nodeFound = true;\n              copyNodes[ x.get('_id') ] = x.serialize();\n            }\n          });\n\n      // TODO: clear the clipboard!\n      if (!nodeFound) return;\n\n      // get all relevant connections\n      var copyConns = {};\n      var connCount = 0;\n      this.get('connections')\n        .each(function(x){\n\n          if (x.get('_id') === -1 || x.get('startProxy') || x.get('endProxy')) return;\n\n          if ( ( copyNodes[ x.get('startNodeId') ] && copyNodes[ x.get('endNodeId') ] ) || copyNodes[ x.get('endNodeId') ]  ){\n\n            if ( !copyConns[ x.get('_id')  ] ){\n              connCount++;\n              copyConns[ x.get('_id') ] = x.toJSON();\n            } \n          }\n        });\n\n      this.app.set('clipboard', { nodes: copyNodes, connections: copyConns });\n\n    },\n\n    paste: function(){\n\n      // build the command\n      var cb = JSON.parse( JSON.stringify( this.app.get('clipboard') ) );\n\n      var that = this;\n\n      var nodes = {};\n\n      var centerX = (1 / this.get('zoom')) * (this.get('offset')[0] + 80);\n      var centerY = (1 / this.get('zoom')) * (this.get('offset')[1] + 80);\n\n      var topLeft = _.reduce(cb.nodes, function(a, x){\n        return [ Math.min(a[0], x.position[0] ), Math.min(a[1], x.position[1] )];\n      }, [ 1e8, 1e8 ] );\n\n      var nodeCount = 0;\n\n      _.each(cb.nodes, function(x){\n\n        // give new id for building the paste\n        nodes[x._id] = x;\n\n        var posX = x.position[0] - topLeft[0] + centerX;\n        var posY = x.position[1] - topLeft[1] + centerY;\n\n        nodes[x._id].position = [ posX, posY ];\n        nodes[x._id]._id = that.makeId();\n        nodeCount++;\n\n      });\n\n      if (nodeCount > 0) this.get('nodes').deselectAll();\n\n      var connections = {};\n\n      _.each(cb.connections, function(x){\n\n        if ( nodes[ x.endNodeId ] ){\n          x.endNodeId = nodes[ x.endNodeId ]._id;\n        }\n\n        if ( nodes[x.startNodeId]){\n          x.startNodeId = nodes[ x.startNodeId ]._id;\n        }\n\n        connections[x._id] = x;\n        connections[x._id]._id = that.makeId();\n\n      });\n\n      // build the command\n      var multipleCmd = { kind: \"multiple\", commands: [] };\n\n      // build all of the nodes\n      for (var id in nodes){\n        var cpnode = cb.nodes[id];\n        cpnode.kind = \"addNode\";\n        multipleCmd.commands.push( cpnode );\n      }\n\n      // then builds the connections\n      for (var id in connections){\n        var cpConn = connections[id];\n        cpConn.kind = \"addConnection\";\n        multipleCmd.commands.push( cpConn );\n      }\n\n      this.runInternalCommand( multipleCmd );\n      this.addToUndoAndClearRedo( multipleCmd );\n\n    },\n\n    addNodeByNameAndPosition: function(name, position){\n\n      if (name === undefined || position === undefined ) return;\n\n      var se = this.app.SearchElements.where({ name: name })[0];\n\n      if (!se) {\n        console.warn('Could not find node with name in Library: ' + name)\n        return;\n      }\n\n      if (se.get('isCustomNode')){\n\n        var sec = { typeName: \"CustomNode\"\n                    , position: position\n                    , _id: this.makeId()  };\n\n        sec.extra = { functionId: se.get('functionId')\n                      , functionName: se.get('functionName')\n                      , numInputs: se.get('numInputs')\n                      , numOutputs: se.get('numOutputs')\n                    };\n\n        return this.addNode( sec );\n\n      }\n\n      this.addNode({ typeName: name, position: position, _id: this.makeId() });\n\n    },\n\n    regenerateDependencies: function(){\n\n      var that = this;\n      var directDependencies = this.getCustomNodes().map(function(x){ return x.get('type').functionId; });\n      var indirectDependencies = directDependencies.map(function(x){ return that.app.get('workspaces').get(x); }).map(function(x){ return x.get('workspaceDependencyIds'); });\n\n      var allDependencyLists = directDependencies.concat( indirectDependencies );\n\n      return _.union.apply(null, allDependencyLists );\n\n    },\n\n    addNode: function(data){\n\n      this.get('nodes').deselectAll();\n\n      if ( data.typeName === \"CustomNode\" ){\n        var id = data.extra.functionId;\n\n        // do not allow recursion\n        if (id === this.get('_id')) return;\n\n        this.addWorkspaceDependency( id, true );\n        this.sendCompleteDefinitionRunner( id );\n      }\n\n      var datac = JSON.parse( JSON.stringify( data ) );\n      datac.kind = \"addNode\";\n      this.runInternalCommand(datac);\n      this.addToUndoAndClearRedo( datac );\n\n      if ( data.typeName === \"CustomNode\" ){\n        this.syncCustomNodesWithWorkspace( id );\n      }\n\n      this.trigger('requestRun');\n\n    },\n\n    addWorkspaceDependency: function(id, watchDependency){\n\n      this.resolver.addWorkspaceDependency(id, watchDependency);\n\n    },\n\n    syncCustomNodesWithWorkspace: function(workspace){\n\n      this.resolver.syncCustomNodesWithWorkspace(workspace);\n\n    },\n\n    sendCompleteDefinitionRunner: function( id ){\n\n      // custom node workspace\n      if (!this.runner) {\n        return;\n      }\n\n      var ws = this.app.getLoadedWorkspace( id );\n\n      var allDeps = ws.regenerateDependencies().concat([id]);\n\n      var that = this;\n      allDeps.forEach(function(depId){\n        that.sendDefinitionToRunner( depId );\n      });\n\n    },\n\n    sendDefinitionToRunner: function( id ){\n\n      // custom node workspace\n      if (!this.runner) {\n        return;\n      }\n\n      var ws = this.app.getLoadedWorkspace( id );\n\n      this.runner.addDefinition( ws );\n\n    },\n\n    removeNode: function(data){\n\n      var datac = JSON.parse( JSON.stringify( data ) );\n      datac.kind = \"removeNode\";\n      this.runInternalCommand(datac);\n      this.addToUndoAndClearRedo( datac );\n\n    },\n\n    addConnection: function(data){\n\n      var datac = JSON.parse( JSON.stringify( data ) );\n      datac.kind = \"addConnection\";\n      this.runInternalCommand(datac);\n      this.addToUndoAndClearRedo( datac );\n\n    },\n\n    addConnectionAndRemoveExisting : function(startNodeId, startPort, endNodeId, endPort) {\n      \n      var multiCmd = { kind: \"multiple\", commands: [] };\n\n      // remove any existing connection\n      var endNode = this.get('nodes').get(endNodeId)\n      if ( !endNode ) return this;\n      var existingConnection = endNode.getConnectionAtIndex( endPort );\n\n      if (existingConnection != null){\n        var rmConn = existingConnection.toJSON();\n        rmConn.kind = \"removeConnection\";\n        multiCmd.commands.push( rmConn );\n      }\n\n      var newConn = {\n          kind: \"addConnection\",\n          startNodeId: startNodeId,\n          startPortIndex: startPort,\n          endNodeId: endNodeId,\n          endPortIndex: endPort,\n          _id: this.app.makeId()\n        };  \n\n      multiCmd.commands.push( newConn );\n\n      this.runInternalCommand( multiCmd );\n      this.addToUndoAndClearRedo( multiCmd );\n\n      return this;\n    },\n\n    removeConnection: function(data){\n\n      var datac = JSON.parse( JSON.stringify( data ) );\n      datac.kind = \"removeConnection\";\n      this.runInternalCommand(datac);\n      this.addToUndoAndClearRedo( datac );\n\n    }, \n\n    setNodeProperty: function(data){\n\n      var datac = JSON.parse( JSON.stringify( data ) );\n      datac.kind = \"setNodeProperty\";\n      this.runInternalCommand(datac);\n      this.addToUndoAndClearRedo( datac );\n\n    },\n\n    internalCommands: {\n\n      multiple: function(data){\n\n        // we prevent runs until all of the changes have been committed\n        var previousRunAllowedState = this.runAllowed;\n        this.runAllowed = false;\n\n        // run all of the commands\n        var that = this;\n        data.commands.forEach(function(x){\n          that.runInternalCommand.call(that, x);\n        });\n\n        // restore previous runAllowed state and, if necessary, do run\n        this.runAllowed = previousRunAllowedState;\n        if (this.runRejected) this.run();\n\n      },\n\n      addNode: function(data){\n\n        var node = new Node( data, { workspace: this });\n        this.get('nodes').add( node );\n\n      },\n\n      removeNode: function(data){\n\n        var node = this.get('nodes').get(data._id);\n        this.get('nodes').remove( node );\n\n      }, \n\n      addConnection: function(data){\n\n        var nodes = this.get('nodes');\n        if ( !nodes.get( data.startNodeId ) || !nodes.get( data.endNodeId ) ) return;\n\n        var conn = new Connection(data, { workspace: this });\n        this.get('connections').add( conn );\n        this.get('nodes').get(conn.get('startNodeId')).connectPort( conn.get('startPortIndex'), true, conn);\n        this.get('nodes').get(conn.get('endNodeId')).connectPort(conn.get('endPortIndex'), false, conn);\n\n      }, \n\n      removeConnection: function(data){\n\n        var conn = this.get('connections').get(data._id);\n        if (conn) this.get('connections').remove( conn );\n\n      }, \n\n      setNodeProperty: function(data){\n\n        var node = this.get('nodes').get( data._id );\n        var prop = data.property;\n        if (!data.oldValue) data.oldValue = JSON.parse( JSON.stringify( node.get(prop) ) ); \n\n        node.set( prop, data.newValue );\n\n      }\n\n    },\n\n    runInternalCommand: function(commandData){\n\n      var cmd = this.internalCommands[ commandData.kind ];\n      if (cmd){\n        cmd.call(this, commandData);\n        this.trigger('runCommand');\n        return;\n      } \n\n      console.warn('Could not find the command: ' + cmd.kind);\n\n    },\n\n    redo: function(){\n\n      var rs = this.get('redoStack');\n\n      if (rs.length === 0) {\n        return console.warn(\"Nothing to redo!\");\n      }\n\n      var data = rs.pop();\n      this.get('undoStack').push(data);\n      this.runInternalCommand(data);\n      \n    },\n\n    undo: function(){\n\n      var us = this.get('undoStack');\n      if (us.length === 0) {\n        return;\n      }\n\n      var command = us.pop();\n      var undoCommand = this.invertCommand( command );\n      this.get('redoStack').push( command );\n\n      this.runInternalCommand(undoCommand);\n\n    },\n\n    invertCommand: function(cmd){\n\n      var inverter = this.commandInversions[cmd.kind];\n      if ( inverter ){\n        return inverter.call(this, cmd);\n      }\n\n      return {};\n\n    },\n\n    commandInversions: {\n\n      addNode: function( cmd ){\n\n        var cmdcop = JSON.parse( JSON.stringify( cmd ) );\n        cmdcop.kind = \"removeNode\";\n        return cmdcop;\n\n      },\n\n      multiple: function( cmd ){\n\n        var cmdcop = JSON.parse( JSON.stringify( cmd ) );\n\n        var that = this;\n        cmdcop.commands = cmdcop.commands.map(function(x){\n          return that.invertCommand.call(that, x);\n        });\n        cmdcop.commands.reverse();\n        \n        return cmdcop;\n\n      },\n\n      removeNode: function( cmd ){\n\n        var cmdcop = JSON.parse( JSON.stringify( cmd ) );\n        cmdcop.kind = \"addNode\";\n        return cmdcop;\n\n      },\n\n      addConnection: function(cmd){\n\n        var cmdcop = JSON.parse( JSON.stringify( cmd ) );\n        cmdcop.kind = \"removeConnection\";\n        return cmdcop;\n\n      },\n\n      removeConnection: function(cmd){\n\n        var cmdcop = JSON.parse( JSON.stringify( cmd ) );\n        cmdcop.kind = \"addConnection\";\n        return cmdcop;\n\n      },\n\n      setNodeProperty: function(cmd){\n\n        var cmdcop = JSON.parse( JSON.stringify( cmd) ); \n\n        var temp = cmdcop.oldValue;\n        cmdcop.oldValue = cmdcop.newValue;\n        cmdcop.newValue = temp;\n        return cmdcop; \n\n      }\n\n    },\n\n    run: function() {\n\n      if ( !this.runAllowed || this.get('isCustomNode') ){\n        this.runRejected = true;\n        return;\n      }\n\n      this.runReject = false;\n\n      if (this.get('nodes').length === 0){\n        return;\n      }\n        \n      var bottomNodes = this.get('nodes')\n                            .filter(function(ele){\n                              return ele.isOutputNode() && ele.get('type').outputs.length > 0;\n                            }).map(function(ele){\n                              return ele.get('_id');\n                            });\n\n      this.runner.run( bottomNodes );\n\n    },\n\n    startMarqueeSelect: function(startPosition) {\n\n      this.set('marqueeStart', startPosition );\n      this.set('marqueeEnd', startPosition );\n      this.set('marqueeSelectEnabled', true);\n\n      return this;\n    },\n\n    endMarqueeSelect: function() {\n\n      this.set('marqueeSelectEnabled', false);\n  \n      return this;\n    },\n\n    startProxyConnection: function(startNodeId, nodePort, startPosition) {\n\n      // Note: this is a quick fix for when the proxy connection\n      this.set('proxyStartId', startNodeId);\n      this.set('proxyStartPortIndex', nodePort);\n\n      // set the initial properties for a dragging proxy\n      this.proxyConnection.set('hidden', false);\n      this.proxyConnection.set('startNodeId', startNodeId);\n\n      this.proxyConnection.set('startPortIndex', nodePort );\n\n      this.proxyConnection.set('startProxy', false );\n\n      this.proxyConnection.set('endProxy', true );\n      this.proxyConnection.set('endProxyPosition', startPosition);\n\n      this.draggingProxy = true;\n\n      this.trigger('startProxyDrag');\n      return this;\n    },\n\n    completeProxyConnection: function(endNodeId, endPortIndex) {\n\n      this.draggingProxy = false;\n      this.trigger('endProxyDrag');\n\n      var startNodeId = this.proxyConnection.get('startNodeId')\n        , startPortIndex = this.proxyConnection.get('startPortIndex');\n\n      this.addConnectionAndRemoveExisting(startNodeId, startPortIndex, endNodeId, endPortIndex);\n      \n      return this;\n    },\n\n    endProxyConnection: function() {\n\n      this.proxyConnection.set('hidden', true);\n      this.draggingProxy = false;\n      return this;\n\n    }\n\n  });\n\n});\n\n\n\n"
  },
  {
    "path": "app/scripts/models/WorkspaceBrowser.js",
    "content": "define(['backbone', 'WorkspaceBrowserElements'], function(Backbone, WorkspaceBrowserElements) {\n\n\treturn Backbone.Model.extend({\n\n\t  defaults: {\n      workspaces: new WorkspaceBrowserElements()\n\t  },\n\n\t  initialize: function(atts, vals) {\n\t  \tthis.get('workspaces').fetch();\n\t  },\n\n\t  refresh: function(){\n\t  \tthis.get('workspaces').reset();\n\t  \tthis.get('workspaces').fetch();\n\t  }\n\n\t});\n});"
  },
  {
    "path": "app/scripts/models/WorkspaceBrowserElement.js",
    "content": "define(['backbone'], function(Backbone) {\n\n\treturn Backbone.Model.extend({\n\n\t\tidAttribute: \"_id\",\n\n    defaults: {\n      name: \"Unnamed Workspace\",\n      isPublic: false,\n      isCustomNode: false,\n      lastSaved: Date.now()\n    },\n\n\t  initialize: function(atts, vals) {\n\n\t  }\n\n\t});\n});"
  },
  {
    "path": "app/scripts/models/WorkspaceResolver.js",
    "content": "define(['backbone', 'FLOOD'], \n    function(Backbone, FLOOD) {\n\n  return Backbone.Model.extend({\n\n    initialize: function(atts, arr) {\n\n      this.workspace = arr.workspace;\n      this.app = arr.app;\n\n    },\n\n    resolveAll: function(){\n      this.initializeDependencies( this.workspace.get('workspaceDependencyIds') );\n    },\n\n    initializeDependencies: function(depIds){\n\n      if (depIds.length === 0 || !depIds ) {\n        this.workspace.trigger('requestRun');\n        return;\n      }\n\n      this.awaitedWorkspaceDependencyIds = [];\n\n      var that = this;\n      this.app.get('workspaces').on('add', function(ws){ that.resolveDependency.call(that, ws); }, this);\n\n      depIds.forEach(function(x){\n        that.awaitOrResolveDependency.call(that, x);\n      });\n    },\n\n    cleanupDependencies: function(){\n      this.workspace.set( 'workspaceDependencyIds', this.workspace.regenerateDependencies() );\n    },\n\n    awaitOrResolveDependency: function(id){\n\n      var ws = this.app.getLoadedWorkspace(id);\n      if (ws) return this.resolveDependency(ws);\n \n      this.awaitedWorkspaceDependencyIds.push(id);\n      this.app.loadWorkspaceDependency( id ); \n\n    },\n\n    resolveDependency: function(workspace){\n\n      if (workspace.id === this.id) return;\n\n      var index = this.awaitedWorkspaceDependencyIds.indexOf( workspace.id );\n\n      if (index < 0) return;\n\n      this.awaitedWorkspaceDependencyIds.remove(index);\n      this.workspace.sendDefinitionToRunner( workspace.id );\n      this.watchOneDependency( workspace );\n      this.syncCustomNodesWithWorkspace( workspace );\n\n      if (this.awaitedWorkspaceDependencyIds.length === 0) {\n        this.workspace.run();\n        this.cleanupDependencies();\n      }\n\n    },\n\n    addWorkspaceDependency: function( id, watch ){\n\n      var ws = this.app.getLoadedWorkspace(id);\n\n      if (!ws) throw new Error(\"You tried to add an unloaded workspace as a dependency!\")\n\n      var depDeps = ws.get('workspaceDependencyIds')\n        , currentDeps = this.workspace.get('workspaceDependencyIds')\n        , unionDeps = _.union( [id], currentDeps, depDeps );\n\n      this.workspace.set( 'workspaceDependencyIds', unionDeps );\n\n      if (watch) this.watchDependency( id );\n\n    },\n\n    watchDependency: function( id ){\n\n      var ws = this.app.getLoadedWorkspace(id);\n\n      var allDepWorkspaces = ws.get('workspaceDependencyIds').concat( id );\n\n      allDepWorkspaces.forEach(function(depWs){\n        this.watchOneDependency( depWs );\n      }.bind( this ) );\n\n    },\n\n    watchedDependencies: {},\n\n    watchOneDependency: function( customNodeWorkspace ){\n\n      if ( !customNodeWorkspace.id ){\n        customNodeWorkspace = this.app.getLoadedWorkspace( customNodeWorkspace );\n      } \n\n      if ( this.watchedDependencies[ customNodeWorkspace.id ] ) return;\n      this.watchedDependencies[ customNodeWorkspace.id ] = true;\n\n      var that = this;\n\n      var sync = function(){ that.syncCustomNodesWithWorkspace.call(that, customNodeWorkspace) }\n        , syncAndRequestRun = function(){ that.syncCustomNodesWithWorkspace.call(that, customNodeWorkspace); that.workspace.trigger('requestRun'); }\n        , syncAndUpdateRunner = function(){ that.syncCustomNodesWithWorkspace.call(that, customNodeWorkspace); that.workspace.trigger('updateRunner'); };\n\n      customNodeWorkspace.on('change:name', sync, this);\n      customNodeWorkspace.on('change:workspaceDependencyIds', sync, this);\n      customNodeWorkspace.on('requestRun', syncAndRequestRun, this );\n      customNodeWorkspace.on('updateRunner', syncAndUpdateRunner, this );\n\n    },\n\n    syncCustomNodesWithWorkspace: function(workspace){\n\n      if (typeof workspace === \"string\") workspace = this.app.getLoadedWorkspace(workspace);\n\n      this.syncDependencies( workspace );\n      this.syncDirectlyAffectedCustomNodesWithWorkspace( workspace );\n      this.syncIndirectlyAffectedCustomNodesWithWorkspace( workspace );\n\n    },\n\n    syncDependencies: function( depWorkspace ){\n\n      // if a new dependency is now added, make sure we add it to this workspace's runner\n      var currDeps = this.workspace.get('workspaceDependencyIds');\n      var depDeps = depWorkspace.get('workspaceDependencyIds');\n      \n      var newDeps = _.difference( depDeps, currDeps );\n\n      newDeps.forEach(function(id){\n        this.workspace.sendDefinitionToRunner( this.app.getLoadedWorkspace( id ) );\n        this.addWorkspaceDependency( id, true );\n      }.bind(this));\n\n    },\n\n    syncDirectlyAffectedCustomNodesWithWorkspace: function(workspace){\n\n      // get the nodes directly affected by this change\n      var directlyAffectedCustomNodes = this.workspace.getCustomNodesWithId(workspace.id);\n\n      // get the workspace inputs/outputs\n      var inputNodes = workspace.getCustomNodeInputsOutputs();\n      var outputNodes = workspace.getCustomNodeInputsOutputs(true);\n\n      directlyAffectedCustomNodes.forEach(function(x){\n\n        // cleanup hanging input connections\n          var inputConns = x.get('inputConnections');\n          var diff = inputNodes.length - inputConns.length;\n\n          if (diff > 0){\n            for (var i = 0; i < diff; i++){\n              inputConns.push([]);\n            }\n          } else {\n            for (var i = 0; i < -diff; i++){\n\n              var inConn = x.getConnectionAtIndex(inputConns.length - 1);\n\n              if (inConn != null){\n                x.workspace.removeConnection(inConn);\n              }\n\n              inputConns.pop();\n            }\n\n          }\n\n        // clean up hanging output connections\n\n          var outputConns = x.get('outputConnections');\n          var diff2 = outputNodes.length - outputConns.length;\n\n          if (diff2 > 0){\n\n            for (var i = 0; i < diff2; i++){\n              outputConns.push( [] );\n            }\n\n          } else {\n\n            for (var i = 0; i < -diff2; i++){\n\n              var ocs = x.get('outputConnections')\n                .last();\n\n              if (ocs){\n                ocs.slice(0).forEach(function(outConn){ x.workspace.removeConnection(outConn); })\n              }\n\n              outputConns.pop();\n            }\n\n          }\n\n        // set the type\n\n          x.get('type').functionName = workspace.get('name');\n          x.get('type').setNumInputs(inputNodes.length);\n          x.get('type').setNumOutputs(outputNodes.length);\n\n        // save to extra \n\n          var extraCop = JSON.parse( JSON.stringify( x.get('extra') ) );\n\n          extraCop.numInputs = inputNodes.length;\n          extraCop.numOutputs = outputNodes.length;\n          extraCop.functionName = workspace.get('name');\n\n        // sync the input names  ------------------------\n\n          extraCop.inputNames = inputNodes.map(function(inputNode, ind){\n            var ex = inputNode.get('extra');\n\n            if (ex === undefined || !ex.name || ex.name === \"\" ){\n              return String.fromCharCode(97 + ind);\n            } \n\n            return ex.name;\n          });\n\n          extraCop.inputNames.forEach(function(name, ind) {\n            x.get('type').inputs[ind].name = name;\n          });\n\n        // sync the output names  ------------------------\n\n          extraCop.outputNames = outputNodes.map(function(outputNode, ind){\n            var ex = outputNode.get('extra');\n\n            if (ex === undefined || !ex.name || ex.name === \"\" ){\n              return String.fromCharCode(97 + ind);\n            } \n\n            return ex.name;\n          });\n\n          extraCop.outputNames.forEach(function(name, ind) {\n            x.get('type').outputs[ind].name = name;\n          });\n\n        // silently set for serialization\n        x.set('extra', extraCop);\n\n        // triggers a redraw\n        x.trigger('requestRender');\n\n        // update runner\n        x.trigger('updateRunner');\n\n      });\n\n      if (directlyAffectedCustomNodes.length > 0) this.workspace.sync('update', this.workspace);\n\n    },\n\n    syncIndirectlyAffectedCustomNodesWithWorkspace: function(workspace){\n\n      var indirectlyAffectedNodes = this.getIndirectlyAffectedCustomNodes( workspace.id );\n\n      indirectlyAffectedNodes.forEach(function(x){\n        x.trigger('updateRunner');\n      });\n\n      if (indirectlyAffectedNodes.length > 0) this.workspace.sync('update', this.workspace );\n\n    },\n\n    getIndirectlyAffectedCustomNodes: function(functionId){\n\n      var cns = this.workspace.getCustomNodes();\n\n      var thisApp = this.app;\n      return cns.filter(function(cn){\n\n        var id = cn.get('type').functionId\n          , ws = thisApp.getLoadedWorkspace( id );\n\n        if (!ws) return false;\n\n        var wsd = ws.get('workspaceDependencyIds');\n        return id != functionId && wsd.indexOf( functionId ) != -1;\n\n      });\n\n    },\n\n\n  });\n\n});\n\n\n\n"
  },
  {
    "path": "app/scripts/models/customizer/CustomizerApp.js",
    "content": "define(['backbone', 'App'], \n    function(Backbone, App){\n\n  return App.extend({\n\n    url: function() {\n\n      // get the url from the page\n      // customize this url\n\n      var comps = document.URL.split('/customize-');\n      return '/custdata/' + comps[ comps.length - 1];\n    },\n\n    parse : function(resp) {\n\n      resp._id = 1;\n\n      this.get('workspaces').add(resp, {app: this});\n\n      var modresp = {};\n\n      modresp.name = resp.name;\n      modresp.currentWorkspace = 1;\n\n      return modresp;\n\n    },\n\n    fetch : function(options){\n\n      // this.login.fetch();\n      Backbone.Model.prototype.fetch.call(this, options);\n      \n    },\n\n    enableAutosave: function(){\n\n      // this.get('workspaces').on('add remove', function(){ this.sync(\"update\", this); }, this );\n      // this.on('change:currentWorkspace', function(){ this.sync(\"update\", this); }, this);\n      // this.on('change:isFirstExperience', function(){ this.sync(\"update\", this); }, this);\n      // this.on('change:backgroundWorkspaces', function(){ this.sync(\"update\", this); }, this);\n\n    }\n\n  });\n\n})\n\n\n\n\n"
  },
  {
    "path": "app/scripts/views/AppView.js",
    "content": "define([  'backbone', \n          'App', \n          'WorkspaceView', \n          'Search', \n          'SearchView', \n          'WorkspaceControlsView', \n          'WorkspaceTabView', \n          'Workspace',\n          'WorkspaceBrowser',\n          'WorkspaceBrowserView',\n          'HelpView',\n          'Help',\n          'LoginView',\n          'Login',\n          'FeedbackView',\n          'Feedback', \n          'ShareView',\n          'Share',\n          'fastclick' ], \n          function(Backbone, App, WorkspaceView, Search, SearchView, WorkspaceControlsView, \n            WorkspaceTabView, Workspace, WorkspaceBrowser, WorkspaceBrowserView, HelpView, \n            Help, LoginView, Login, FeedbackView, Feedback, ShareView, Share, fastclick ) {\n\n  return Backbone.View.extend({\n\n    el: '#app',\n\n    initialize: function() { \n\n      var f = new fastclick(document.body);\n\n      this.listenTo(this.model, 'change', this.render);\n      this.$workspace_tabs = this.$('#workspace-tabs');\n\n      this.model.get('workspaces').on('add', this.workspaceAdded, this);\n      this.model.get('workspaces').on('remove', this.workspaceRemoved, this);\n\n      this.model.on('change:showingSettings', this.viewSettings, this);\n      this.model.on('change:showingFeedback', this.viewFeedback, this);\n      this.model.on('change:showingShare', this.viewShare, this);\n      this.model.on('change:showingHelp', this.viewHelp, this);\n      this.model.on('change:showingBrowser', this.viewBrowser, this);\n\n      this.model.login.on('change:isLoggedIn', this.showHelpOnFirstExperience, this );\n      this.model.login.on('change:isFirstExperience', this.showHelpOnFirstExperience, this );\n\n      $(document).bind('keydown', $.proxy( this.keydownHandler, this) );\n\n      // deactivate the context menu\n      $(document).bind(\"contextmenu\",function(e){ return false; });\n\n    },\n\n    events: {\n      'click #save-button' : 'saveClick',\n      'click .workspaces_curtain' : 'endSearch',\n      'click #help-button': 'toggleHelp',\n      'click #settings-button': 'showSettings',\n      'click #workspace_hide' : 'toggleViewer',\n      'click #workspace-browser-button': 'toggleBrowser',\n      'click #feedback-button': 'toggleFeedback',\n      'click #share-button': 'toggleShare',\n\n      'click #add-project-workspace' : 'newWorkspace',\n      'click #add-node-workspace' : 'newNodeWorkspace',\n\n      'mouseover #add-workspace-button': 'showAddWorkspaceSelect',\n      'mouseout #add-workspace-button': 'hideAddWorkspaceSelect',\n      'mouseover #add-workspace-select-element': 'showAddWorkspaceSelect',\n      'mouseout #add-workspace-select-element': 'hideAddWorkspaceSelect',\n\n      // touch\n      'touchstart #add-workspace-button': 'toggleAddWorkspaceSelect'\n\n    },\n\n    toggleAddWorkspaceSelect: function(){\n\n      $('#add-workspace-select-element').toggle();\n\n    },\n\n    showHelpOnFirstExperience: function(){\n\n      var that = this;\n\n      setTimeout(function(){\n        if (that.model.login.get('isLoggedIn') && that.model.get('isFirstExperience')){\n          that.model.set( 'showingHelp', true);\n        } else {\n          that.model.set( 'showingHelp', false);\n        }\n      }, 800);\n\n    },\n\n    showAddWorkspaceSelect: function(){\n      $('#add-workspace-select-element').show();\n    },\n\n    hideAddWorkspaceSelect: function(){\n      $('#add-workspace-select-element').hide();\n    },\n\n    newWorkspace: function(){\n      this.model.newWorkspace();\n      this.hideAddWorkspaceSelect();\n    },\n\n    newNodeWorkspace: function(){\n      this.model.newNodeWorkspace();\n      this.hideAddWorkspaceSelect();\n    },\n\n    keydownHandler: function(e){\n\n      var isBackspaceOrDelete = e.keyCode === 46 || e.keyCode === 8;\n\n      if ( !(e.metaKey || e.ctrlKey) && !isBackspaceOrDelete ) return;\n\n      // do not capture from input\n      if (e.originalEvent.srcElement && e.originalEvent.srcElement.nodeName === \"INPUT\" ) return;\n      if (e.target.nodeName === \"INPUT\") return;\n\n      // do not capture from textarea\n      if (e.originalEvent.srcElement && e.originalEvent.srcElement.nodeName === \"TEXTAREA\" ) return;\n      if (e.target.nodeName === \"TEXTAREA\") return;\n\n      // keycodes: http://css-tricks.com/snippets/javascript/javascript-keycodes/\n      switch (e.keyCode) {\n        case 78:\n          this.newWorkspace();\n          return e.preventDefault();\n      }\n\n      this.currentWorkspaceView.keydownHandler(e);\n    },\n\n    saveClick: function(e){\n      this.model.sync(\"update\", this.model);\n    },  \n\n    endSearch: function() {\n      this.model.set('showingSearch', false);\n    },\n\n    toggleBrowser: function(e){\n\n      if (this.model.get('showingBrowser') === true){\n        $(e.currentTarget).removeClass('workspace-browser-button-active');\n        this.model.set('showingBrowser', false);\n      } else {\n        $(e.currentTarget).addClass('workspace-browser-button-active');\n        this.model.set('showingBrowser', true);\n      }\n\n    },\n\n    viewBrowser: function(){\n      if (!this.browserView){\n        this.browserView = new WorkspaceBrowserView({model: new WorkspaceBrowser() }, { app: this.model });\n        this.browserView.render();\n      }\n\n      if (this.model.get('showingBrowser') === true){\n        this.browserView.$el.show();  \n      } else {\n        this.browserView.$el.hide();\n      }\n    },\n\n    viewHelp: function(){\n      if (!this.helpView){\n        this.helpView = new HelpView({model: new Help() }, { app: this.model });\n      }\n      \n      if (this.model.get('showingHelp') === true){\n        this.focusWorkspace();\n        this.helpView.render();\n        this.helpView.$el.fadeIn();  \n      } else {\n        this.helpView.$el.fadeOut();\n      }\n    },\n\n    viewFeedback: function(){\n      if (!this.feedbackView){\n        this.feedbackView = new FeedbackView({model: new Feedback() }, { app: this.model });\n        this.feedbackView.render();\n      }\n\n      if (this.model.get('showingFeedback') === true){\n        this.feedbackView.$el.fadeIn();  \n      } else {\n        this.feedbackView.$el.fadeOut();\n      }\n    },\n\n    viewShare: function(){\n      if (!this.shareView){\n        this.shareView = new ShareView({model: new Share({ app : this.model }) }, { app: this.model });\n      }\n\n      if (this.model.get('showingShare') === true){\n        this.shareView.render();\n        this.shareView.$el.fadeIn();  \n      } else {\n        this.shareView.$el.fadeOut();\n      }\n    },\n\n    toggleHelp: function(){\n      this.model.set('showingHelp', !this.model.get('showingHelp'));\n    },\n\n    toggleFeedback: function(){\n      this.model.set('showingFeedback', !this.model.get('showingFeedback'));\n    },\n\n    toggleShare: function(){\n      this.model.set('showingShare', !this.model.get('showingShare'));\n    },\n\n    showHelp: function(){\n      this.model.set('showingHelp', true);\n    },\n\n    hideHelp: function(){\n      this.model.set('showingHelp', false);\n    },\n\n    showFeedback: function(){\n      this.model.set('showingFeedback', true);\n    },\n\n    hideFeedback: function(){\n      this.model.set('showingFeedback', false);\n    },\n\n    showLogin: function(){\n      this.model.set('showingLogin', true);\n    },\n\n    showSettings: function(){\n      this.model.showSettings();\n    },\n\n    showSearch: function() {\n\n      if (this.model.get('showingSearch') === true) {\n        \n        // darken the workspace container\n        this.$el.find('.workspaces_curtain').css('display', 'block');\n\n        // if we haven't already, create the search view element and add to the ui\n        if (this.searchView === undefined){\n          this.searchView = new SearchView( { model: new Search() }, {app: this.model, appView: this } );\n          this.searchView.render();\n          this.$el.find('#workspaces').prepend(this.searchView.$el);\n\n        } else {\n          this.searchView.$el.css('display', 'block');\n        }\n\n        $('.workspace_container').addClass('blur');\n        this.searchView.$el.find('.library-search-input').focus();\n\n      } else {\n\n        $('.workspace_container').removeClass('blur');\n        \n        this.$el.find('.workspaces_curtain').css('display', 'none');\n        if (this.searchView != undefined) {\n          this.searchView.$el.css('display', 'none');\n        }\n\n      }\n\n    },\n\n    showingHelp: false,\n    showingBrowser: false,\n    showingSettings: false,\n    showingSearch: false,\n    showingLogin: false,\n\n    currentWorkspaceView: null,\n    currentWorkspaceId: null,\n    workspaceTabViews: {},\n    workspaceViews: {},\n\n    workspaceCounter: 1,\n\n    workspaceAdded: function(workspace){\n\n      if ( this.model.isBackgroundWorkspace(workspace.id) ) return;\n\n      if ( this.workspaceTabViews[workspace.get('_id')] != undefined) return;\n\n      var view = new WorkspaceTabView({ model: workspace });\n      this.workspaceTabViews[workspace.get('_id')] = view;\n\n      view.render();\n      this.$workspace_tabs.append( view.$el );\n\n    },\n\n    workspaceRemoved: function(workspace){\n\n      // The Workspace can no longer be current\n      workspace.set('current', false);\n\n       // check if the removed workspace is the current one\n      if (workspace.get('_id') == this.model.get('currentWorkspace') ){\n\n        // are there any more workspaces?\n        if ( this.model.get('workspaces').length != 0 ){\n          this.model.set('currentWorkspace', this.model.get('workspaces').first().get('_id') );\n\n        // if we're out of workspaces, just add a new one\n        } else {\n          var that = this;\n          this.newWorkspace();\n        }\n      }\n\n      this.workspaceTabViews[workspace.get('_id')].$el.remove();\n      delete this.workspaceTabViews[workspace.get('_id')];\n      delete this.workspaceViews[workspace.get('_id')];\n\n    },\n\n    getCurrentWorkspaceCenter: function(){\n\n      var w = this.currentWorkspaceView.$el.width()\n        , h = this.currentWorkspaceView.$el.height()\n        , ho = this.currentWorkspaceView.$el.scrollTop()\n        , wo = this.currentWorkspaceView.$el.scrollLeft()\n        , zoom = 1 / this.model.getCurrentWorkspace().get('zoom');\n\n      return [zoom * (wo + w / 2), zoom * (ho + h / 2)];\n\n    },\n\n    getWorkspaceView: function(workspaceModel) {\n\n      if (!workspaceModel) return;\n\n      var workspaceId = workspaceModel.get('_id');\n\n      if ( !this.workspaceViewIsInstantiated( workspaceId )){\n\n        var workspaceView = new WorkspaceView( {\n                model: workspaceModel,\n                app: this\n            });\n          \n        this.workspaceViews[workspaceId] = workspaceView;\n\n      } else {\n        var workspaceView = this.workspaceViews[ workspaceId ];\n      }\n\n      return workspaceView;\n    },\n\n    workspaceViewIsInstantiated: function(workspaceId){\n      return (this.workspaceViews[workspaceId] != undefined);\n    },\n\n    hideWorkspace: function(workspaceView){\n      if (workspaceView != undefined)\n        workspaceView.$el.css('display','none');\n    },\n\n    showWorkspace: function(workspaceView){\n\n      // if the workspace tab does not exist\n      this.model.removeWorkspaceFromBackground( workspaceView.model.id );\n      this.workspaceAdded( workspaceView.model );\n\n      if (!$.contains(document.documentElement, workspaceView.$el[0])){\n        this.$el.children('#workspaces').append( this.currentWorkspaceView.$el );\n      }\n      \n      workspaceView.$el.css('display','block');\n\n    },\n\n    render: function(arg) {\n\n      var model = this.model;\n      var workspaces = this.model.get('workspaces')\n      var currentWorkspaceId = this.model.get('currentWorkspace');\n\n      if (!currentWorkspaceId){\n        var currentWorkspace = workspaces.first();\n      } else {\n        var currentWorkspace = workspaces.get(currentWorkspaceId);\n      }\n      \n      this.model.updateCurrentWorkspace();\n    \n      // render search\n        if (!this.workspaceControlsView){\n\n          this.workspaceControlsView = new WorkspaceControlsView( { model: new Search() }, {app: this.model, appView : this } );\n          this.workspaceControlsView.render();\n\n          this.$el.find('#workspaces').prepend( this.workspaceControlsView.$el );\n\n        }\n\n      // render tabs\n        if (!this.workspaceTabViews){\n          this.workspaceTabViews = {};\n\n          workspaces.each( this.workspaceAdded, this );\n        }\n\n      // hide current workspace, show workspace\n\n        if (this.model.changed.currentWorkspace && currentWorkspace){\n\n          this.hideWorkspace(this.currentWorkspaceView);\n          this.currentWorkspaceView = this.getWorkspaceView( currentWorkspace );\n\n          this.showWorkspace( this.currentWorkspaceView );\n          this.currentWorkspaceView.render();\n          this.currentWorkspaceId = currentWorkspaceId;\n          this.focusWorkspace();\n        }\n\n      this.showSearch();\n      this.renderLogin();\n\n      return this;\n\n    },\n\n    renderLogin: function(){\n\n      if (!this.loginView){\n        this.loginView = new LoginView({model: this.model.login }, { app: this.model });\n        this.loginView.render();\n      }\n\n    },\n\n    lookingAtViewer: false,\n\n    focusWorkspace: function(){\n\n      this.$el.find('#workspace_hide').removeClass('leftside');\n      this.$el.find('#workspace_hide').addClass('rightside');\n\n      this.$el.find('#workspace_hide i').removeClass('icon-arrow-right');\n      this.$el.find('#workspace_hide i').addClass('icon-arrow-left');\n\n      // change whether workspace_container is visible or not\n      this.currentWorkspaceView.$el.css('display','block');\n      this.workspaceControlsView.$el.css('display','block');\n\n      $('#viewer').addClass('blur');\n    },\n\n    focusViewer: function(){\n\n      this.$el.find('#workspace_hide').addClass('leftside');\n      this.$el.find('#workspace_hide').removeClass('rightside');\n\n      this.$el.find('#workspace_hide i').removeClass('icon-arrow-left');\n      this.$el.find('#workspace_hide i').addClass('icon-arrow-right');\n\n      this.currentWorkspaceView.$el.hide();\n      this.workspaceControlsView.$el.hide();\n\n      $('#viewer').removeClass('blur');\n\n    },\n\n    getCurrentWorkspace: function(){\n      return this.get('workspaces').get(this.get('currentWorkspace'));\n    },\n\n    toggleViewer: function(event) {\n\n      this.lookingAtViewer = !this.lookingAtViewer;\n\n      if ( this.lookingAtViewer ){\n        this.focusViewer();\n      } else {\n        this.focusWorkspace();\n      }\n\n    }\n\n  });\n});\n\n\n\n\n\n"
  },
  {
    "path": "app/scripts/views/ConnectionView.js",
    "content": "define(['backbone'], function(Backbone) {\n\n  return Backbone.View.extend({\n\n    template: _.template( $('#connection-template').html() ),\n\n    workspaceView : null,\n\n    initialize: function( args ) {\n\n      this.model = args.model;\n\n      if (args.isProxy ){\n        this.isProxy = true;\n      }\n\n      this.workspace = args.workspace;\n      this.workspaceView = args.workspaceView;\n\n      if (this.model.startNode){\n        this.model.startNode.on('change:ignoreDefaults', this.render, this);\n      }\n\n    },\n\n    delegateEvents: function() {\n\n      Backbone.View.prototype.delegateEvents.apply(this, arguments);\n\n      if (!this.isProxy ){\n        this.startId = this.model.get('startNodeId');\n        this.endId = this.model.get('endNodeId');\n        var nodes = this.workspace.get('nodes');\n\n        if (nodes.get(this.endId) != undefined ){\n          this.listenTo( nodes.get(this.endId), 'change:position resized', this.render);\n        }\n        \n        if (nodes.get(this.startId) != undefined ){\n          this.listenTo( nodes.get(this.startId), 'change:position resized', this.render);\n        }\n      }\n      \n      this.listenTo(this.model, 'change', this.render);\n\n    },\n\n    render: function() {\n\n      this.makeCurveOnce();\n\n      return this.updateControlPoints()\n        .updateHidden()\n        .updateColor();\n\n    },\n\n    updateControlPoints: function(){\n      this.el.setAttribute('d', this.template( this.getControlPoints() ))\n      return this;\n    },\n\n    updateHidden: function(){\n\n      if (this.model.get('hidden')) {\n        this.el.setAttribute('class','connection collapsed');\n      } else {\n        this.el.setAttribute('class','connection');\n      }\n\n      return this;\n\n    },\n\n    updateColor: function(){\n\n      var startNode = this.model.startNode;\n\n      if (!startNode) return this;\n\n      if (startNode.isPartialFunctionApplication()){\n        this.el.setAttribute('class','partial-function-connection');\n      } else {\n        this.el.setAttribute('class','connection');\n      }\n\n      return this;\n    },\n\n    curveInit: false, \n\n    makeCurveOnce: function() {\n\n      if (!this.curveInit) {\n        var crv = document.createElementNS('http://www.w3.org/2000/svg','path');\n        crv.setAttribute('class','connection');\n        this.el = crv;\n        this.$el = $(crv);\n        this.curveInit = true;\n      }\n      return this.el;\n\n    },\n\n    // construct the control points for a bezier curve\n    getControlPoints: function() {\n\n      if (!this.model.get('startProxy') || !this.model.get('endProxy')) {\n\n        var nodeViews = this.workspaceView.nodeViews\n          , startId = this.model.get('startNodeId')\n          , endId = this.model.get('endNodeId')\n          , startPortIndex = this.model.get('startPortIndex')\n          , endPortIndex = this.model.get('endPortIndex')\n      }    \n\n      if (!this.model.get('startProxy')) {\n        if (!this.workspaceView.nodeViews[startId] ){\n          startId = this.model.workspace.get('proxyStartId');\n          startPortIndex = this.model.workspace.get('proxyStartPortIndex');\n        }\n\n        startPos = this.workspaceView.nodeViews[startId].getPortPosition(startPortIndex, true);\n      } else {\n        startPos = this.model.get('startProxyPosition');\n      }\n\n      if (!this.model.get('endProxy')) {\n        endPos = nodeViews[endId].getPortPosition(endPortIndex, false);\n      } else {\n        endPos = this.model.get('endProxyPosition');\n      }\n\n      var offset = 0.65 * Math.sqrt( Math.pow( endPos[0]-startPos[0], 2 ) + Math.pow( startPos[1]-endPos[1], 2 ) );\n\n      return {\n          aX : startPos[0]\n          , aY : startPos[1]\n          , bX : startPos[0] + offset\n          , bY : startPos[1]\n          , dX : endPos[0]\n          , dY : endPos[1]\n          , cX : endPos[0] - offset\n          , cY : endPos[1]\n        };\n    }\n\n  });\n\n});\n"
  },
  {
    "path": "app/scripts/views/FeedbackView.js",
    "content": "define(['backbone'], function(Backbone) {\n\n  'use strict';\n\n  return Backbone.View.extend({\n\n    el: '#feedback',\n\n    events: { 'click #exit-feedback' : 'clickExit',\n              'submit #submit-feedback' : 'clickSend', \n              'click #submit-feedback' : 'clickSend',\n              'click' : 'clickExit',\n              'click .modal-box': 'stopPropagation' \n            },\n\n    template: _.template( $('#feedback-template').html() ),\n\n    initialize: function( args, atts ) {\n      this.app = atts.app;\n\n      this.model.on('change:failure', this.fail, this );\n      this.model.on('success', this.success, this );\n    },\n\n    render: function() {\n\n      this.$el.html( this.template( this.model.toJSON() ) );\n\n      this.subject = this.$el.find('#feedback-subject');\n      this.message = this.$el.find('#feedback-message');\n      this.failureView = this.$el.find('#feedback-failure-message');\n      this.successView = this.$el.find('#feedback-success-message');\n      this.sendingView = this.$el.find('#feedback-sending-message');\n\n      return this;\n\n    },\n\n    stopPropagation: function(e){\n      e.stopPropagation();\n    },\n\n    fail: function(){\n\n      this.sendingView.hide();\n\n      if (!this.failureView) return;\n\n      if (!this.model.get('failure')) {\n        this.failureView.hide();\n        return;\n      }\n\n      this.failureView.html( this.model.get('failureMessage') );\n      this.failureView.show();\n\n    },\n\n    success: function(){\n\n      this.sendingView.hide();\n      this.successView.show();\n\n      var that = this;\n\n      setTimeout(function(){\n        that.app.set(\"showingFeedback\", false);\n\n        that.subject.val(\"\");\n        that.message.val(\"\");\n\n        that.successView.fadeOut();\n      }, 800);\n\n    },\n\n    clickExit: function(e){\n      this.app.set(\"showingFeedback\", false);\n    },\n\n    clickSend: function(e) {\n      \n      e.preventDefault();\n      this.sendingView.show();\n      this.model.send({ subject: this.subject.val(), message: this.message.val() });\n\n    }\n\n  });\n});"
  },
  {
    "path": "app/scripts/views/HelpView.js",
    "content": "define(['backbone'], function(Backbone) {\n\n  return Backbone.View.extend({\n\n    el: '#help',\n\n    events: { \"click .exit-help\": 'hide', \n              'click .enter-help-section' : 'clickEnterHelpSection',\n              'click .exit-all-help' : 'hide',\n              'click .exit-help-section' : 'clickExitHelpSection' \n            },\n\n    initialize: function( args, atts ) {\n      this.app = atts.app;\n    },\n\n    render: function() {\n\n      var template = _.template( $('#help-section-template').html() );\n\n      var that = this;\n\n      this.$el.empty();\n\n      this.model.get('sections').forEach(function(section){\n\n        var el = $('#' + section.targetId );\n        \n        if (!el) return;\n\n        var offset = el.offset();\n        var height = el.height();\n        var width = el.width();\n\n        if (section.offset[0] < 0) {\n          width = -10;\n        }\n\n        if (section.offset[1] < 0) {\n          height = -10;\n          width -= 10;\n        }\n\n        section.elementPosition = [ offset.left + width, offset.top + height ];\n        that.$el.append(template( section ));\n\n      });\n\n      return this;\n\n    },\n\n    getHelpSection: function(e){\n\n      var ui = $(e.target);\n      var attr = ui.attr('data-target-id');\n\n      return this.$el.find(\".help-section[data-target-id='\" + attr + \"']\");\n\n    },\n\n    clickEnterHelpSection: function(e){\n\n      var ele = this.getHelpSection(e);\n      var ui = $(e.target);\n\n      ele.fadeIn();\n      ui.fadeOut();\n\n    },\n\n    clickExitHelpSection: function(e){\n\n      var ele = this.getHelpSection(e);\n      ele.fadeOut();\n\n    },\n\n    hide: function() {\n      this.app.set('showingHelp', false);\n    }\n\n  });\n});"
  },
  {
    "path": "app/scripts/views/LoginView.js",
    "content": "define(['backbone'], function(Backbone) {\n\n  return Backbone.View.extend({\n\n    el: '#login',\n\n    template: _.template( $('#login-template').html() ),\n\n    events: { 'submit #login-form' : 'login',\n              'submit #signup-form' : 'signup',\n              'click #logout' : 'logout',\n              \"click .exit-login\": 'hide', \n              'click #signup-tab-button': 'focusSignup',\n              'click #login-tab-button': 'focusLogin'},\n\n    initialize: function( args, atts ) {\n\n      this.app = atts.app;\n      this.model.on('change:showing', this.render, this);\n      this.model.on('change:isLoggedIn', this.render, this);\n      this.model.on('change:failed', this.render, this);\n      this.model.on('change:failureMessage', this.render, this);\n\n      var that = this;\n      $('#login-button').click(function(){ that.tabClick.call(that); });\n    },\n\n    rendered : false,\n\n    render: function() {\n\n      if ( !this.rendered ) {\n        this.$el.find('.login-container').html( this.template( this.model.toJSON() ) );\n        this.rendered = true;\n\n        this.$el.find('.login-container').show(); \n      }\n\n      var failureMessage = this.$el.find('#login-failure-message');\n\n      if (this.model.get('failed')){\n        failureMessage.html( this.model.get('failureMessage') );\n        failureMessage.show();\n      } else {\n        failureMessage.hide();\n      }\n\n      if (this.model.get('showing') === true){\n        this.$el.show();  \n      } else {\n        this.$el.hide();\n      }\n\n      this.renderLoginState();\n\n      return this;\n    },\n\n    focusSignup: function(e){\n      \n      this.model.set('failed', false);\n      this.$el.find('#login-tab-button').removeClass('tab-button-hilite');\n      this.$el.find('#signup-tab-button').addClass('tab-button-hilite');\n      this.$el.find('#login-form').hide();\n      this.$el.find('#signup-form').show();\n\n    },\n\n    focusLogin: function(e){\n\n      this.model.set('failed', false);\n      this.$el.find('#signup-tab-button').removeClass('tab-button-hilite');\n      this.$el.find('#login-tab-button').addClass('tab-button-hilite');\n      this.$el.find('#signup-form').hide();\n      this.$el.find('#login-form').show();\n    },\n\n    renderLoginState: function(){\n\n      if( this.model.get('isLoggedIn') ){\n        this.model.hide();\n      } else {\n        this.$el.show();\n      }\n\n      return this;\n    },\n\n    tabClick: function(){\n\n      if (this.model.get('isLoggedIn')){\n        this.model.logout();\n      } else {\n        this.model.toggle();\n      }\n\n    },\n\n    signup: function(e) {  \n      e.preventDefault();\n      this.model.signup( this.$('#signup-form').serialize());\n    },\n\n    login: function(e) {  \n      e.preventDefault();\n      this.model.login( this.$('#login-form').serialize() );\n    }\n\n  });\n});"
  },
  {
    "path": "app/scripts/views/MarqueeView.js",
    "content": "define(['backbone'], function(Backbone) {\n\n  return Backbone.View.extend({\n\n    workspaceView : null,\n\n    initialize: function( args ) {\n\n      this.model = args.model;\n      this.workspace = args.workspace;\n      this.workspaceView = args.workspaceView;\n\n      this.listenTo(this.model, 'change', this.render);\n\n    },\n\n    render: function() {\n\n      this.makeElementOnce();\n\n      return this.updateCorners()\n        .updateHidden()\n        .updateColor()\n        .updateStroke();\n\n    },\n\n    updateCorners: function(){\n      this.el.setAttribute('d', this.template( this.getCorners() ))\n      return this;\n    },\n\n    updateHidden: function(){\n\n      if (this.model.get('hidden')) {\n        this.el.setAttribute('class','marquee collapsed');\n      } else {\n        this.el.setAttribute('class','marquee');\n      }\n\n      return this;\n\n    },\n\n    updateColor: function(){\n      return this;\n    },\n\n    curveInit: false, \n\n    makeElementOnce: function() {\n\n      if (!this.curveInit) {\n\n        var crv = document.createElementNS('http://www.w3.org/2000/svg','rect');\n        crv.setAttribute('class','marquee');\n\n        this.updateCorners();\n        this.updateStroke();\n\n        this.el = crv;\n        this.$el = $(crv);\n        this.curveInit = true;\n\n      }\n      return this.el;\n\n    },\n\n    updateCorners: function() {\n\n      this.el.setAttribute('x',this.model.get('x'));\n      this.el.setAttribute('y',this.model.get('y'));\n      this.el.setAttribute('width',this.model.get('width'));\n      this.el.setAttribute('height',this.model.get('height'));\n\n      return this;\n\n    },\n\n    updateStroke: function() {\n\n      // we scale the stroke to avoid the marquee being overly thin or thick\n      // when zoomed\n      var zoom = 1 / this.workspace.get('zoom');\n\n      this.el.setAttribute('stroke-dasharray', (zoom * 4) + \",\" + (zoom * 4) );\n      this.el.setAttribute('stroke', zoom * 2  );\n\n      return this;\n    }\n\n  });\n\n});"
  },
  {
    "path": "app/scripts/views/NodeViews/Base.js",
    "content": "define(['backbone', 'jqueryuidraggable', 'bootstrap', 'Hammer'], function(Backbone, jqueryuidraggable, bootstrap, Hammer) {\n\n  return Backbone.View.extend({\n\n    tagName: 'div',\n    className: 'node',\n\n    template: _.template( $('#node-template').html() ),\n\n    portHeight: 29, \n\n    events: {\n      'mousedown .node-port-output': 'beginPortConnection',\n      'mousedown .node-port-input': 'beginPortDisconnection',\n      'mouseup .node-port-input': 'endPortConnection',\n\n      'touchstart .node-port-output': 'beginTouchConnection',\n      'touchstart .node-port-input': 'beginTouchDisconnection',\n      \n      'touchstart': 'touchstart',\n      'click':  'selectThis',\n\n      'change .use-default-checkbox': 'useDefaultClick',\n      'blur .name-input': 'updateName',\n      'click .toggle-vis': 'toggleGeomVis',\n      'click .rep-type': 'replicationClick'\n    },\n\n    initialize: function(args) {\n\n      this.workspace = args.workspace;\n      this.workspaceView = args.workspaceView;\n\n      this.listenTo(this.model, 'requestRender', this.render );\n      this.listenTo(this.model, 'change:position', this.move );\n      this.listenTo(this.model, 'change:lastValue', this.renderLastValue );\n      this.listenTo(this.model, 'change:failureMessage', this.renderLastValue );\n      this.listenTo(this.model, 'change:ignoreDefaults', this.colorPorts );\n      this.listenTo(this.model, 'change:name', this.render );\n      this.listenTo(this.model, 'connection', this.colorPorts);\n      this.listenTo(this.model, 'disconnection', this.colorPorts);\n      this.listenTo(this.model, 'change:selected', this.colorSelected);\n      this.listenTo(this.model, 'change:visible', this.render);\n      this.listenTo(this.model, 'change:isEvaluating', this.colorEvaluating);\n      this.listenTo(this.model, 'evalFailed', this.onEvalFailed );\n      this.listenTo(this.model, 'evalBegin', this.onEvalBegin );\n\n      this.makeDraggable();\n      this.$workspace_canvas = $('#workspace_canvas');\n      this.position = this.model.get('position');\n\n    },\n\n    updateName: function(e){\n      var val = this.$el.find('.name-input').val();\n      if (this.model.get('name') === val) return;\n      \n      var cmd = { property: 'name', _id: this.model.get('_id'), newValue : val };\n      this.model.workspace.setNodeProperty(cmd);\n    },\n\n    onEvalFailed: function(exception){\n      this.$el.addClass('node-failed');\n      this.model.set('failureMessage', exception);\n    },\n\n    onEvalBegin: function(){\n      this.$el.removeClass('node-failed');\n    },\n\n    useDefaultClick : function(e){\n\n      var index = parseInt( $(e.currentTarget).attr('data-index') );\n\n      var ign = JSON.parse( JSON.stringify( this.model.get('ignoreDefaults') ) );\n      ign[index] = !$(e.target).is(':checked');\n\n      var cmd = { property: 'ignoreDefaults', _id: this.model.get('_id'), \n            newValue : ign };\n\n      this.model.workspace.setNodeProperty(cmd);\n      this.model.workspace.run();\n\n    },\n\n    replicationClick : function(e){\n\n      var cmd = { property: 'replication', _id: this.model.get('_id'), \n            newValue : $(e.target).attr('data-rep-type') };\n      this.model.workspace.setNodeProperty(cmd);\n      this.model.workspace.run();\n\n    },\n\n    // should be part of nodeView subclass\n    toggleGeomVis: function(e) {\n      this.model.set('visible', !this.model.get('visible') );\n      e.stopPropagation()\n    },\n\n    makeDraggable: function() {\n\n      var that = this;\n      this.initPos = [];\n      this.$el.draggable( {\n        drag : function(e, ui) {\n          var zoom = 1 / that.workspace.get('zoom');\n\n          ui.position.left = zoom * ui.position.left;\n          ui.position.top = zoom * ui.position.top;\n\n          that.workspace.get('nodes').moveSelected([ ui.position.left - that.initPos[0], ui.position.top - that.initPos[1]], that);\n\n          that.model.set('position', [ ui.position.left, ui.position.top ]);\n\n        },\n        start : function(startEvent) {\n\n          if ( !that.model.get('selected') ){\n            that.model.workspace.get('nodes').deselectAll();\n          }\n\n          that.model.set('selected', true );\n          that.workspace.get('nodes').startDragging(that);\n\n          var zoom = 1 / that.model.workspace.get('zoom');\n          var pos = that.model.get('position');\n\n          that.initPos = [ pos[0], pos[1] ];\n\n        },\n        stop : function() {\n\n          var start = [ that.initPos[0], that.initPos[1] ];\n          var pos = that.model.get('position');\n          var end = [ pos[0], pos[1] ];\n\n          var cmd = { property: 'position', _id: that.model.get('_id'), \n            oldValue: start, newValue : end };\n          that.model.workspace.setNodeProperty( cmd );\n\n        }\n      });  \n      this.$el.css('position', 'absolute');\n\n    },\n\n    beginPortDisconnection: function(e){\n      var index = parseInt( $(e.currentTarget).attr('data-index') );\n\n      if ( !this.model.isPortConnected(index, false) )\n        return;\n\n      var inputConnections = this.model.get('inputConnections')\n        , connection = inputConnections[index][0]\n        , oppos = connection.getOpposite( this.model );\n\n      this.workspace.startProxyConnection( oppos.node.get('_id'), oppos.portIndex, this.getPortPosition(index, false));\n      this.workspace.removeConnection( connection.toJSON() );\n\n      e.stopPropagation();\n    },\n\n    beginPortConnection: function(e){\n      var index = parseInt( $(e.currentTarget).attr('data-index') );\n      this.workspace.startProxyConnection(this.model.get('_id'), index, this.getPortPosition(index, true));\n      e.stopPropagation();\n    },\n\n    endPortConnection: function(e){\n\n      if ( !this.workspace.draggingProxy )\n        return;\n\n      var index = parseInt( $(e.currentTarget).attr('data-index') );\n      this.workspace.completeProxyConnection(this.model.get('_id'), index );\n      e.stopPropagation();\n\n    },\n\n    // touch-specific handlers\n\n    // simply kill the connection\n    beginTouchDisconnection: function(e){\n      \n      var index = parseInt( $(e.currentTarget).attr('data-index') );\n\n      if ( !this.model.isPortConnected(index, false) )\n        return;\n\n      var inputConnections = this.model.get('inputConnections')\n        , connection = inputConnections[index][0]\n        , oppos = connection.getOpposite( this.model );\n\n      this.workspace.removeConnection( connection.toJSON() );\n\n      e.stopPropagation();\n      e.preventDefault();\n    },\n\n    // special handling of touch events\n    beginTouchConnection: function(e){\n      \n      $('body').one('touchend', function(e){\n\n        var changedTouches = e.originalEvent.changedTouches[0];\n        var elem = $( document.elementFromPoint(changedTouches.pageX, changedTouches.pageY) );\n\n        if (!elem.hasClass(\"node-port-input\")){\n          elem = elem.parent('.node-port-input')\n        }\n\n        if (!elem.attr('data-index')) return;\n\n        this.workspace.draggingProxy = true;\n\n        var e = $.Event( \"mouseup\" );\n        elem.trigger(e);\n\n        this.workspace.draggingProxy = false;\n\n      }.bind( this ));\n\n    },\n\n    select: function() {\n      this.model.set( 'selected', true );\n    },\n\n    touchstart: function(event){\n      // is the user pressing on an input?\n      var shouldIgnore = event.target != null \n          && ( event.target.tagName.toLowerCase() == \"input\" || event.target.tagName.toLowerCase() == \"textarea\" );\n\n      if(shouldIgnore) {\n        // need to focus the input - on iOS the input never gets focussed\n        event.target.focus();\n\n        // we prevent the node from being selected\n        this.selectable = false;\n        setTimeout(function(){ this.selectable = true; }.bind(this), 300);\n      }\n    },\n\n    selectable: true,\n\n    selectThis: function(event) {\n\n      if (!this.selectable) return;\n\n      if ( !this.model.get('selected') ){\n        if (!event.shiftKey)\n          this.workspace.get('nodes').deselectAll();\n        this.model.set('selected', true );\n      } else {\n        this.workspace.get('nodes').deselectAll();\n      }\n\n    },\n\n    render: function() {\n\n      this\n      .renderNode()\n      .colorSelected()\n      .colorEvaluating()\n      .moveNode()\n      .renderPorts();\n\n      return this;\n\n    },\n\n    renderNode: function() {\n\n      var json = this.model.toJSON();\n\n      json.preview = this.formatPreview( json.lastValue );\n\n      this.$el.html( this.template( json ) );\n\n      if (this.getCustomContents){\n        this.$el.find('.node-data-container').html( this.getCustomContents() );\n      }\n\n      return this;\n    },\n\n    truncatePreview: function( value, maxElements ){\n\n      if (typeof value === \"string\") return value;\n\n      if (!value || value.length === undefined || value.length < 100) {\n        return value;\n      }\n\n      if ( maxElements === undefined ) maxElements = 20;\n\n      var shortVal = {};\n      var count = 0;\n      for (var k in value){\n        if (count > maxElements) break;\n        shortVal[k] = value[k];\n        count++;\n      }\n\n      shortVal.length = value.length;\n\n      return shortVal;\n\n    },\n\n    formatPreview: function( value ){\n\n      var that = this;\n      return JSON.stringify( this.truncatePreview( value ), function(k, v){ return that.prettyPrint.call(that, k, v);} );\n\n    },\n\n    prettyPrint: function(key, val){\n\n      if (typeof val === \"number\"){\n        return val.toPrecision(4);\n      }\n\n      if (typeof val === \"string\"){\n        return val.replace(new RegExp(\"\\t\", 'g'), \"\").replace(new RegExp(\"\\n\", 'g'), \"\")\n      }\n\n      if (val && val.length != undefined && val.length > 100) {\n        return this.truncatePreview( val );\n      }\n\n      return val;\n    },\n\n    renderLastValue: function() {\n\n      return this.renderNode();\n\n    },\n\n    colorEvaluating: function() {\n\n      if ( this.model.get('isEvaluating') ){\n        this.$el.addClass('node-evaluating');\n      } else {\n        this.$el.removeClass('node-evaluating');\n      }\n\n      return this;\n\n    },\n\n    colorSelected: function() {\n\n      if ( this.model.get('selected') ){\n        this.$el.addClass('node-selected');\n      } else {\n        this.$el.removeClass('node-selected');\n      }\n\n      return this;\n\n    },\n\n    svgTransform: function() {\n      return 'translate(' + this.position[0] + ' ' + this.position[1] +')';\n    },\n\n    // Get the position of a particular port.  Only valid after render()\n    // has been called\n    getPortPosition: function( index, isOutputPort ) {\n      \n      var x = this.position[0]\n        , y = this.position[1];\n\n      if (isOutputPort) {\n        try {\n          x += parseInt( this.outputPorts[index].getAttribute('cx')) + 5;\n          y += parseInt( this.outputPorts[index].getAttribute('cy'));      \n        } catch (e){\n\n        }\n  \n      } else {\n        try {\n          x += parseInt( this.inputPorts[index].getAttribute('cx')) - 5;\n          y += parseInt( this.inputPorts[index].getAttribute('cy'));   \n        } catch (e){\n\n        }\n      }\n\n      return [x, y];\n\n    },\n\n    colorPorts: function() {\n\n      // update port colors\n      var that = this;\n      var isPartial = false;\n\n      this.inputPorts.forEach(function(ele, ind){\n\n        ele.setAttribute('stroke','black');\n\n        if (that.model.isPortConnected(ind, false) ){\n          ele.setAttribute('fill','black');\n        } else if (that.model.isInputPortUsingDefault(ind)){\n          ele.setAttribute('fill','white');\n        } else {\n          isPartial = true;\n          ele.setAttribute('fill','grey');\n          ele.setAttribute('stroke','white');\n        }\n          \n      });\n\n      this.outputPorts.forEach(function(ele, ind){\n\n        ele.setAttribute('stroke','black');\n\n        if (that.model.isPortConnected(ind, true)){\n          ele.setAttribute('fill','black');\n        } else if (isPartial) {\n          ele.setAttribute('fill','grey');\n          ele.setAttribute('stroke','white');\n        } else {\n          ele.setAttribute('fill','white');\n        }\n          \n      });\n\n      return this;\n\n    },\n\n    move: function() {\n      return this.moveNode().movePorts();\n    },\n\n    moveNode: function() {\n      \n      var pos = this.model.get('position');\n\n      if (pos[0] < 0) pos[0] = 0;\n      if (pos[1] < 0) pos[1] = 0;\n\n      this.position = pos;\n\n      this.$el.css(\"left\", this.position[0] );\n      this.$el.css(\"top\", this.position[1] );\n\n      return this;\n    },\n\n    movePorts: function(){\n      if (this.portGroup) { \n        this.portGroup.setAttribute( 'transform', this.svgTransform() );\n      }\n\n      return this;\n    },\n\n    renderPorts: function() {\n\n      if ( this.portGroup ) {\n        // we need to redraw the ports\n        $(this.portGroup).empty();\n      } else {\n        // create an svg group to hold the port circles\n        this.portGroup = document.createElementNS('http://www.w3.org/2000/svg','g');\n        this.portGroup.setAttribute( 'transform', this.svgTransform() );\n      }\n\n      // create data structures to store the input ports\n      this.inputPorts = [];\n      this.outputPorts = [];\n\n      // draw the circles\n      var that = this;\n      var inIndex = 0;\n      var outIndex = 0;\n\n      // set the zoom from the workspace container\n      var zoom = 1.0\n        , ele = this.$el.parent().css('transform');\n\n      if (ele != \"none\") zoom = ele.match(/-?[0-9\\.]+/g)[0];\n        \n\n      this.$el.find('.node-port').each(function(index, ele) {\n\n        var nodeCircle = document.createElementNS('http://www.w3.org/2000/svg','circle');\n        \n        // assign default appearance\n        nodeCircle.setAttribute('r',3);\n        nodeCircle.setAttribute('stroke','black');\n        nodeCircle.setAttribute('fill','white');\n        nodeCircle.setAttribute('stroke-width','1.5');\n\n        // position input ports on left side, output ports on right side\n        if ( $(ele).hasClass('node-port-input') ) {\n          nodeCircle.setAttribute('cx', 0);\n          nodeCircle.setAttribute('cy', that.portHeight / 2 + 1/zoom * $(ele).position().top ); \n          that.inputPorts.push(nodeCircle);\n          inIndex++;\n        } else {\n          nodeCircle.setAttribute('cx', that.$el.width() + 2.5 );\n          nodeCircle.setAttribute('cy', that.portHeight / 2 + 1/zoom * $(ele).position().top ); \n          that.outputPorts.push(nodeCircle);\n          outIndex++;\n        }\n        \n        // append \n        that.portGroup.appendChild(nodeCircle);\n\n      });\n\n      this.colorPorts();\n\n      return this;\n\n    },\n\n    remove: function() {\n      this.$el.remove();\n      if (this.portGroup.parentNode)\n        this.portGroup.parentNode.removeChild(this.portGroup);\n    }\n\n  });\n\n});\n"
  },
  {
    "path": "app/scripts/views/NodeViews/CustomNode.js",
    "content": "define(['underscore', 'jquery', 'ThreeCSGNodeView'], function(_, $, ThreeCSGNodeView) {\n\n  return ThreeCSGNodeView.extend({\n\n    innerTemplate : _.template( $('#node-custom-template').html() ),\n\n    getCustomContents: function() {\n\n      var that = this;\n\n      // open the parent workspace on double click\n      this.$el.bind('dblclick', function(){\n        this.model.workspace.app.openWorkspace( this.model.get('type').functionId );\n      }.bind(this) );\n\n      var js = this.model.toJSON() ;\n      if (!js.extra.script) js.extra.script = this.model.get('type').script;\n\n      return this.innerTemplate( js );\n\n    }\n\n  });\n\n});"
  },
  {
    "path": "app/scripts/views/NodeViews/Input.js",
    "content": "define(['backbone', 'underscore', 'jquery', 'BaseNodeView'], function(Backbone, _, $, BaseNodeView) {\n\n  return BaseNodeView.extend({\n\n    template: _.template( $('#node-input-template').html() ),\n\n    initialize: function(args) {\n      BaseNodeView.prototype.initialize.apply(this, arguments);\n\n      this.model.on('change:extra', function() { \n        \n        var ex = this.model.get('extra') ;\n        var name = ex != undefined ? ex.name : \"\";\n        \n        this.silentSyncUI( name );\n        this.model.trigger('updateRunner'); \n\n      }, this);\n\n    },\n\n    render: function(){\n\n      BaseNodeView.prototype.render.apply(this, arguments);\n\n      this.$el.addClass('input-node');\n\n      var that = this;\n      var extra = this.model.get('extra');\n      var name = extra.name != undefined ? extra.name : \"\";\n\n      this.inputText = this.$el.find(\".text-input\");\n      this.inputText.val( name );\n      this.inputText.change( function(e){ that.nameChanged.call(that, e); e.stopPropagation(); });\n\n      return this;\n\n    },\n\n    nameChanged: function(){\n      this.inputSet();\n      this.model.workspace.trigger('updateRunner');\n    },\n\n    silentSyncUI: function(name){\n\n      this.silent = true;\n      this.inputText.val( name );\n      this.silent = false;\n\n    },\n\n    inputSet: function(e,ui) {\n\n      if ( this.silent ) return;\n\n      var newValue = { name: this.inputText.val() };\n      this.model.workspace.setNodeProperty({property: 'extra', _id: this.model.get('_id'), newValue: newValue });      \n\n    }\n\n  });\n\n});\n"
  },
  {
    "path": "app/scripts/views/NodeViews/NodeViews.js",
    "content": "define(['BaseNodeView', 'WatchNodeView', 'NumNodeView', 'ThreeCSGNodeView', 'ScriptView', 'OutputView', 'InputView','CustomNodeView'], \n  function(BaseNodeView, WatchNodeView, NumNodeView, ThreeCSGNodeView, ScriptView, OutputView, InputView, CustomNodeView){\n\n  var nodeViewTypes = {};\n\n  nodeViewTypes.Base = ThreeCSGNodeView;\n  nodeViewTypes.Show = WatchNodeView;\n  nodeViewTypes.Number = NumNodeView;\n  nodeViewTypes.CustomNode = CustomNodeView;\n\n  nodeViewTypes.Script = ScriptView;\n  nodeViewTypes.Input = InputView;\n  nodeViewTypes.Output = OutputView;\n\n  return nodeViewTypes;\n\n});\n"
  },
  {
    "path": "app/scripts/views/NodeViews/Num.js",
    "content": "define(['backbone', 'underscore', 'jquery', 'BaseNodeView', 'jqueryuislider'], function(Backbone, _, $, BaseNodeView) {\n\n  return BaseNodeView.extend({\n\n    template: _.template( $('#node-num-template').html() ),\n\n    initialize: function(args) {\n\n      BaseNodeView.prototype.initialize.apply(this, arguments);\n      this.rendered = false;\n\n      this.model.on('change:extra', function() { \n        \n        var ex = this.model.get('extra') ;\n\n        this.silentSyncUI( ex );\n\n        this.model.trigger('updateRunner'); \n        this.model.workspace.trigger('requestRun');\n\n      }, this);\n\n    },\n \n    render: function() {\n      \n      BaseNodeView.prototype.render.apply(this, arguments);\n\n      if (this.rendered) return this;\n\n      // make the slider\n      this.slider = this.$el.find('.slider');\n      if (!this.slider) return;\n\n      var extra = this.model.get('extra');\n      var min = extra.min != undefined ? extra.min : -150;\n      var max = extra.max != undefined ? extra.max : 150;\n      var step = extra.step != undefined ? extra.step : 0.1;\n      var lock = extra.lock != undefined ? extra.lock : false;\n      var value = extra.value != undefined ? extra.value : 0;\n      if (value === undefined ) value = this.model.get('lastValue');\n\n      var that = this;\n      this.slider.slider(\n        { min: min, \n          max: max, \n          step: step, \n          value: value,\n          change: function(e, ui){  that.inputSet.call(that, e, ui); },\n          slide: function(e, ui){ that.inputChanged.call(that, e, ui); } \n        });\n\n      this.currentValueInput = this.$el.find('.currentValue');\n      this.currentValueInput.val( value );\n      this.currentValueInput.change( function(e){ that.valChanged.call(that, e); e.stopPropagation(); });\n\n      this.minInput = this.$el.find('.num-min');\n      this.minInput.val(min);\n      this.minInput.change( function(e){ that.minChanged.call(that, e); e.stopPropagation(); });\n\n      this.maxInput = this.$el.find('.num-max');\n      this.maxInput.val(max);\n      this.maxInput.change( function(e){ that.maxChanged.call(that, e); e.stopPropagation(); });\n\n      this.stepInput = this.$el.find('.num-step');\n      this.stepInput.val(step);\n      this.stepInput.change( function(e){ that.stepChanged.call(that, e); e.stopPropagation(); });\n\n      this.lockInput = this.$el.find('.lock-input');\n      this.lockInput.val( lock );\n      this.lockInput.change( function(e){ that.lockChanged.call(that, e); e.stopPropagation(); });\n\n      // adjust settings dropdown so that it stays open while editing\n      // doesn't select the node when you're editing\n      $('.dropdown.keep-open').on({\n        \"shown.bs.dropdown\": function() {\n          that.selectable = false;\n          that.model.set('selected', false);\n          $(this).data('closable', false);\n        },\n        \"mouseleave\": function() {\n          $(this).data('closable', true);\n        },\n        \"click\": function() {\n          $(this).data('closable', false);\n        },\n        \"hide.bs.dropdown\": function() {\n          if ( $(this).data('closable') ) that.selectable = true;\n          return $(this).data('closable');\n        }\n      });\n\n      // this.rendered = true;\n\n      return this;\n\n    },\n\n    silentSyncUI: function(data){\n\n      this.silent = true;\n      this.currentValueInput.val( data.value );\n      this.setSliderValue( data.value );\n      this.minInput.html( data.min );\n      this.maxInput.html( data.max );\n      this.stepInput.html( data.step );\n      this.lockInput.val( data.lock );\n      this.silent = false;\n\n    },\n\n    currentValue: function(){\n      return this.slider.slider(\"option\", \"value\");\n    },\n\n    setSliderValue: function(val){\n      return this.slider.slider(\"option\", \"value\", val);\n    },\n\n    valChanged: function(val){\n      var val = parseFloat( this.currentValueInput.val() );\n      if (isNaN(val)) return;\n      return this.setSliderValue( val );\n    },\n\n    minChanged: function(e, u){\n      var val = parseFloat( this.minInput.val() );\n      if (isNaN(val)) return;\n      if (this.currentValue < val) this.setSliderValue(val);\n      this.slider.slider(\"option\", \"min\", val);\n    },\n\n    maxChanged: function(e){\n      var val = parseFloat( this.maxInput.val() );\n      if (isNaN(val)) return;\n      if (this.currentValue > val) this.setSliderValue(val);\n      this.slider.slider(\"option\", \"max\", val);\n    },\n\n    stepChanged: function(e){\n      var val = parseFloat( this.stepInput.val() );\n      if (isNaN(val)) return;\n      this.slider.slider(\"option\", \"step\", val);\n    },\n\n    lockChanged: function(e){\n      this.inputSet();\n    },\n\n    inputChanged: function(e,ui) {\n      var val = ui.value;\n      this.$el.find('.currentValue').html(val);\n    },\n\n    inputSet: function() {\n\n      if ( this.silent ) return;\n\n      var newValue = {   value: this.slider.slider(\"option\", \"value\"), min: this.slider.slider(\"option\", \"min\"), \n        step: this.slider.slider(\"option\", \"step\"), max: this.slider.slider(\"option\", \"max\"), lock: this.lockInput.is(':checked') };\n\n      this.model.workspace.setNodeProperty({property: 'extra', _id: this.model.get('_id'), newValue: newValue });      \n\n    }\n\n  });\n\n});"
  },
  {
    "path": "app/scripts/views/NodeViews/Output.js",
    "content": "define(['backbone', 'underscore', 'jquery', 'BaseNodeView'], function(Backbone, _, $, BaseNodeView) {\n\n  return BaseNodeView.extend({\n\n    template: _.template( $('#node-output-template').html() ),\n\n    initialize: function(args) {\n      BaseNodeView.prototype.initialize.apply(this, arguments);\n\n      this.model.on('change:extra', function() { \n        \n        var ex = this.model.get('extra') ;\n        var name = ex != undefined ? ex.name : \"\";\n        \n        this.silentSyncUI( name );\n        this.model.trigger('updateRunner'); \n\n      }, this);\n\n    },\n\n    render: function(){\n\n      BaseNodeView.prototype.render.apply(this, arguments);\n\n      this.$el.addClass('output-node');\n\n      var that = this;\n      var extra = this.model.get('extra');\n      var name = extra.name != undefined ? extra.name : \"\";\n\n      this.inputText = this.$el.find(\".text-input\");\n      this.inputText.val( name );\n      this.inputText.change( function(e){ that.nameChanged.call(that, e); e.stopPropagation(); });\n\n      return this;\n\n    },\n\n    nameChanged: function(){\n      this.inputSet();\n      this.model.workspace.trigger('updateRunner');\n    },\n\n    silentSyncUI: function(name){\n      this.silent = true;\n      this.inputText.val( name );\n      this.silent = false;\n    },\n\n    inputSet: function(e,ui) {\n      if ( this.silent ) return;\n\n      var newValue = { name: this.inputText.val() };\n      this.model.workspace.setNodeProperty({property: 'extra', _id: this.model.get('_id'), newValue: newValue });      \n    }\n\n  });\n\n});\n"
  },
  {
    "path": "app/scripts/views/NodeViews/Script.js",
    "content": "define(['backbone', 'underscore', 'jquery', 'ThreeCSGNodeView', 'FLOOD', 'codemirror', 'codemirror/mode/javascript/javascript','codemirror/addon/hint/show-hint', 'codemirror/addon/hint/javascript-hint' ], function(Backbone, _, $, ThreeCSGNodeView, FLOOD, CodeMirror) {\n\n  return ThreeCSGNodeView.extend({\n\n    initialize: function(args) {\n      ThreeCSGNodeView.prototype.initialize.apply(this, arguments);\n      this.listenTo(this.model,'change:extra', this.onChangedExtra);\n    },\n\n    innerTemplate : _.template( $('#node-script-template').html() ),\n\n    getCustomContents: function() {\n\n      var js = this.model.toJSON() ;\n      if (!js.extra.script) js.extra.script = this.model.get('type').script;\n\n      return this.innerTemplate( js );\n\n    },\n\n    onChangedExtra: function(){\n\n      var ex = this.model.get('extra') || {};\n\n      if (ex.numInputs != undefined ){\n        this.setNumInputConnections( ex.numInputs )\n        this.model.get('type').setNumInputs( ex.numInputs );\n      }\n\n    \tthis.render();\n    \tthis.model.trigger('updateRunner');\n\t\t  this.model.workspace.run();\n    },\n\n    setNumInputConnections: function(num){\n\n      if (num === undefined) return;\n\n      var inputConns = this.model.get('inputConnections');\n\n      var diff = num - inputConns.length;\n\n      if (diff === 0) return;\n\n      if (diff > 0){\n        for (var i = 0; i < diff; i++){\n          inputConns.push([]);\n        }\n      } else {\n        for (var i = 0; i < -diff; i++){\n\n          var conn = this.model.getConnectionAtIndex(inputConns.length - 1);\n\n          if (conn != null){\n            this.model.workspace.removeConnection(conn);\n          }\n\n          inputConns.pop();\n        }\n\n      }\n\n    },\n\n    extendScope: _.once(function(){\n\n     var or = CodeMirror.hint.javascript;\n     CodeMirror.hint.javascript = function(editor, options){\n\toptions.globalScope = FLOOD.nodeTypes;\n\treturn or(editor, options);\t\n     }\n    }),\n\n    renderNode: function() {\n      ThreeCSGNodeView.prototype.renderNode.apply(this, arguments);\n\n      this.extendScope();\n\n      var ta = this.$el.find('.script-text-input');\n      var cm = CodeMirror.fromTextArea(ta[0], \n      \t{ extraKeys: {\"Ctrl-Space\": \"autocomplete\"},\n\t  mode: { name :\"javascript\" }\n\t});\n\t\n     var that = this;\n      \n      cm.on(\"focus\",function(e){\n\tthat.selectable = false;\n      \tthat.model.set('selected', false);\n      });\n\n      cm.on(\"change\", function(){\n\t// we need to update the ports and connectors after moving the node\n        setTimeout(function(){ \n\t\t// update the position of the node ports\n\t\tthat.renderPorts(); \n\t\t// update the position of the connections\n\t\tthat.model.trigger('resized'); \n\t}, 0);\n      });\n\n      cm.on(\"blur\",function(){\n     \tvar ex = JSON.parse( JSON.stringify( that.model.get('extra') ) );\n      \tif ( ex.script === cm.getValue() ) return;\n\n      \tex.script = cm.getValue();\n\n      \tthat.model.workspace.setNodeProperty({property: \"extra\", _id: that.model.get('_id'), newValue: ex });\n      \tthat.selectable = true;\n      });\n      \n      this.$el.find('.add-input').click(function(){ that.addInput.call(that); });\n      this.$el.find('.remove-input').click(function(){ that.removeInput.call(that); });\n      \n      return this;\n    },\n\n    setNumInputsProperty: function(numInputs){\n      if (numInputs === undefined) return;\n\n      var ex = this.model.get('extra');\n      var exCopy = JSON.parse( JSON.stringify( ex ) );\n\n      exCopy.numInputs = numInputs;\n      this.model.workspace.setNodeProperty({property: \"extra\", _id: this.model.get('_id'), newValue: exCopy, oldValue: ex });\n    },\n\n    addInput: function(){\n\n    \tvar type = this.model.get('type');\n      var ex = this.model.get('extra');\n  \t  var numInputs = ex.numInputs;\n\n  \t  if (numInputs === undefined) numInputs = 0;\n  \t  if (type.inputs.length === 26) return;\n\n      this.setNumInputsProperty(numInputs + 1);\n\n    },\n\n    removeInput: function(){\n\n    \tvar type = this.model.get('type');\n      var ex = this.model.get('extra');\n  \t  var numInputs = ex.numInputs;\n\n  \t  if (numInputs === undefined) numInputs = 1;\n  \t  if (type.inputs.length === 0) return;\n\n      this.setNumInputsProperty(numInputs - 1);\n\n    }\n\n  });\n\n});\n"
  },
  {
    "path": "app/scripts/views/NodeViews/ThreeCSG.js",
    "content": "define(['backbone', 'underscore', 'jquery', 'BaseNodeView'], function(Backbone, _, $, BaseNodeView) {\n\n  return BaseNodeView.extend({\n\n    initialize: function(args) {\n\n      BaseNodeView.prototype.initialize.apply(this, arguments);\n\n      this.model.on('change:selected', this.colorSelected, this);\n      this.model.on('change:visible', this.changeVisibility, this);\n      this.model.on('remove', this.onRemove, this);\n      this.model.on('change:prettyLastValue', this.onEvalComplete, this );\n      this.model.workspace.on('change:current', this.changeVisibility, this);\n\n      this.onEvalComplete();\n\n    },\n\n    setMaterials: function(partMat, meshMat, lineMat){\n\n      this.threeGeom.traverse(function(ele) {\n        if (ele instanceof THREE.Mesh) {\n          ele.material = meshMat;\n        } else if (ele instanceof THREE.Line) {\n          ele.material = lineMat;\n        } else {\n          ele.material = partMat;\n        }\n      });\n\n    },\n\n    colorSelected: function(){\n\n      BaseNodeView.prototype.colorSelected.apply(this, arguments);\n\n      if ( !( this.threeGeom && this.model.get('visible')) ) return this;\n\n      if (this.model.get('selected')) {\n\n        var meshMat = new THREE.MeshPhongMaterial({color: 0x66d6ff });\n        var partMat = new THREE.ParticleBasicMaterial({color: 0x66d6ff, size: 5, sizeAttenuation: false});\n        var lineMat = new THREE.LineBasicMaterial({ color: 0x66d6ff });\n\n      } else {\n\n        var meshMat = new THREE.MeshPhongMaterial({color: 0x999999});\n        var partMat = new THREE.ParticleBasicMaterial({color: 0x999999, size: 5, sizeAttenuation: false});\n        var lineMat = new THREE.LineBasicMaterial({ color: 0x000000 });\n\n      }\n\n      this.setMaterials(partMat, meshMat, lineMat);\n\n      return this;\n\n    }, \n\n    formatPreview: function(data){\n\n      // ugh this is terrible code\n\n      if (data == null || data === undefined)\n        return BaseNodeView.prototype.formatPreview.apply(this, arguments);\n\n      if (data.length === undefined && !data.normal && !data.polygons && !data.vertices) \n        return BaseNodeView.prototype.formatPreview.apply(this, arguments);\n\n      if (data.length > 0 && !data[0].normal && !data[0].polygons && !data[0].vertices) \n        return BaseNodeView.prototype.formatPreview.apply(this, arguments);\n\n      if (data.normal) return \"Plane\";\n      if (data.polygons) return \"Solid\";\n      if (data.vertices) return \"Polygon\";\n\n      if (data.length) {\n\n        var solidCount = 0;\n        var polyCount = 0;\n        var planeCount = 0;\n\n        for (var i = 0; i < data.length; i++) {\n          if ( data[i].polygons ) solidCount++;\n          if ( data[i].normal ) planeCount++;\n          if ( data[i].vertices ) polyCount++;\n        }\n\n        var solidString = solidCount + \" Solids\";\n        var polyString = polyCount + \" Polygons\";\n        var planeString = planeCount + \" Planes\";\n\n        var stringArr = [];\n\n        if (solidCount > 0) stringArr.push(solidString);\n        if (planeCount > 0) stringArr.push(planeString);\n        if (polyCount > 0) stringArr.push(polyString);\n\n        if (planeCount === 0 && solidCount === 0 && polyCount === 0) return \"Nothing\";\n\n        return stringArr.join(',');\n\n      }\n      return \"Nothing\";\n\n    },\n\n    // 3D move to node subclass\n    onRemove: function(){\n      this.model.workspace.off('change:current', this.changeVisibility, this);\n      scene.remove(this.threeGeom); \n    }, \n\n    evaluated: false,\n\n    toThreeGeom: function( rawGeom ) {\n\n      var threeGeom = new THREE.Geometry(), face;\n\n      if (!rawGeom) return threeGeom;\n\n      if (!rawGeom.vertices && !rawGeom.linestrip ) return threeGeom;\n\n      if (rawGeom.linestrip) return this.addLineStrip( rawGeom, threeGeom );\n\n      if (rawGeom.vertices && !rawGeom.faces) return this.addPoints( rawGeom, threeGeom );\n\n      for ( var i = 0; i < rawGeom.vertices.length; i++ ) {\n        var v = rawGeom.vertices[i];\n        threeGeom.vertices.push( new THREE.Vector3( v[0], v[1], v[2] ) );\n      }\n\n      if (!rawGeom.faces) return threeGeom;\n\n      for ( var i = 0; i < rawGeom.faces.length; i++ ) {\n        var f = rawGeom.faces[i];\n        face = new THREE.Face3( f[0], f[1], f[2], new THREE.Vector3( f[3][0], f[3][1], f[3][2] ) );\n        threeGeom.faces.push( face );\n      }\n      \n      threeGeom._floodType = 0;\n\n      return threeGeom;\n\n    },\n\n    addPoints: function( rawGeom, threeGeom ){\n\n      for ( var i = 0; i < rawGeom.vertices.length; i++ ) {\n        var v = rawGeom.vertices[i];\n        threeGeom.vertices.push( new THREE.Vector3( v[0], v[1], v[2] ) );\n      }\n\n      threeGeom._floodType = 1;\n\n      return threeGeom;\n    },\n\n    addLineStrip: function( rawGeom, threeGeom ){\n\n      for ( var i = 0; i < rawGeom.linestrip.length; i++ ) {\n        var v = rawGeom.linestrip[i];\n        threeGeom.vertices.push( new THREE.Vector3( v[0], v[1], v[2] ) );\n      }\n\n      threeGeom._floodType = 2;\n\n      return threeGeom;\n      \n    },\n\n    onEvalComplete: function(a, b, newValue){\n\n      if (!newValue && this.evaluated) return;\n\n      this.evaluated = true;\n\n      var lastValue = this.model.get('prettyLastValue');\n      var temp;\n\n      if ( !lastValue ) return;\n\n      if ( lastValue.vertices || lastValue.linestrip ){ \n        temp = [];\n        temp.push(lastValue);\n      } else {\n        temp = lastValue; // extract the list\n      } \n\n      var threeTemp = new THREE.Object3D();\n      this.drawChunked( threeTemp, temp, function() { \n\n        if ( this.threeGeom ){\n          scene.remove( this.threeGeom );\n        }\n\n        this.threeGeom = threeTemp;\n        scene.add( this.threeGeom );\n        this.changeVisibility();\n\n      }, this );\n\n    }, \n\n    // creating this data may be quite slow, we'll need to be careful\n    drawChunked: function(geom, list, callback, that){\n\n      var i = 0;\n      var tick = function() {\n\n        var start = new Date().getTime();\n        for (; i < list.length && (new Date().getTime()) - start < 50; i++) {\n        \n          var g3  = that.toThreeGeom( list[i] );\n\n          if (that.model.get('selected')){\n            var color = 0x66d6ff;\n          } else {\n            var color = 0x999999;\n          }\n\n          switch (g3._floodType) {\n            case 0:\n              geom.add( new THREE.Mesh(g3, new THREE.MeshPhongMaterial({color: color})) );\n              break;\n            case 1:\n              geom.add( new THREE.ParticleSystem(g3, new THREE.ParticleBasicMaterial({color: color, size: 5, sizeAttenuation: false}) ));\n              break;\n            case 2:\n              geom.add( new THREE.Line(g3, new THREE.LineBasicMaterial({ color: 0x000000 })));\n              break;\n          }\n\n        }\n\n        if (i < list.length) {\n          setTimeout(tick, 25);\n        } else {\n          callback.call(that);\n        }\n\n      };\n\n      setTimeout(tick, 0);\n\n    },\n\n    changeVisibility: function(){\n\n      if ( !this.threeGeom ){\n        return;\n      }\n        \n      if (!this.model.get('visible') || !this.model.workspace.get('current') )\n      {\n        this.threeGeom.traverse(function(e) { e.visible = false; });\n      } else if ( this.model.get('visible') )\n      {\n        this.threeGeom.traverse(function(e) { e.visible = true; });\n      }\n\n    },\n\n    renderNode: function() {\n      \n      BaseNodeView.prototype.renderNode.apply(this, arguments);\n\n      this.$toggleVis = this.$el.find('.toggle-vis');\n      this.$toggleVis.show();\n\n      var icon = this.$toggleVis.find('i');\n      var label = this.$toggleVis.find('span');\n\n      if (this.model.get('visible')){\n        icon.addClass('fa-eye');\n        icon.removeClass('fa-eye-slash');\n        label.html('Hide geometry');\n      } else {\n        icon.removeClass('fa-eye');\n        icon.addClass('fa-eye-slash');\n        label.html('Show geometry');\n      }\n\n      return this;\n\n    },\n\n  });\n\n});\n"
  },
  {
    "path": "app/scripts/views/NodeViews/Watch.js",
    "content": "define(['backbone', 'underscore', 'jquery', 'BaseNodeView'], function(Backbone, _, $, BaseNodeView) {\n\n  return BaseNodeView.extend({\n\n    template: _.template( $('#node-watch-template').html() ),\n\n    initialize: function(args) {\n\n      BaseNodeView.prototype.initialize.apply(this, arguments);\n      this.model.on( 'change:lastValue', this.renderNode, this );\n      this.model.on( 'disconnection', this.renderNode, this );\n\n    },\n\n    renderNode: function(){\n\n    \tvar pretty = this.model.get('lastValue') != undefined ? JSON.stringify(this.model.get('lastValue'), this.prettyPrint, 2) : this.model.get('lastValue');\n    \tthis.model.set('prettyValue', pretty );\n\n    \treturn BaseNodeView.prototype.renderNode.apply(this, arguments);\n\n    },\n\n    prettyPrint: function(key, val){\n\n    \tif (typeof val === \"number\"){\n    \t\treturn val.toPrecision(4);\n    \t}\n\n    \tif (typeof val === \"string\"){\n    \t\treturn val.replace(new RegExp(\"\\t\", 'g'), \"\").replace(new RegExp(\"\\n\", 'g'), \"<br>\")\n    \t}\n\n    \treturn val;\n    }\n\n  });\n\n});\n"
  },
  {
    "path": "app/scripts/views/SearchElementView.js",
    "content": "define(['backbone'], function(Backbone) {\n\n  return Backbone.View.extend({\n\n    tagName: 'li',\n    className: 'search-element',\n\n    template: _.template( $('#search-element-template').html() ),\n\n    events: {\n      'click':  'click'\n    },\n\n    initialize: function(a, arr){\n      this.app = arr.app;\n      this.appView = arr.appView;\n      this.elementClick = arr.click;\n    },\n\n    render: function() {\n      this.$el.html( this.template( this.model.toJSON() ) );\n    },\n\n    click: function(e) {\n      if (!this.elementClick) return;\n      this.elementClick(this);\n    }\n\n  });\n\n});"
  },
  {
    "path": "app/scripts/views/SearchView.js",
    "content": "define(['backbone', 'List', 'SearchElementView'], function(Backbone, List, SearchElementView) {\n\n  return Backbone.View.extend({\n\n    tagName: 'div',\n    className: 'search-container row',\n\n    initialize: function(atts, arr) {\n      this.app = arr.app;\n      this.app.on('change:showingSearch', this.highlightInput, this );\n      this.app.SearchElements.on('add remove', this.render, this);\n    },\n\n    template: _.template( $('#search-template').html() ),\n\n    events: {\n      'keyup .library-search-input': 'searchKeyup'\n    },\n\n    render: function(arg) {\n\n      this.$el.html( this.template( this.model.toJSON() ) );\n\n      this.$input = this.$('.library-search-input');\n      this.$list = this.$('.search-list');\n\n      this.$list.empty();\n\n      var that = this;\n\n      this.app.SearchElements.forEach(function(ele) {\n\n        if (ele.name === null) return;\n\n        var eleView = new SearchElementView({ model: ele }, { app: that.app, click: function(e){ that.elementClick.call(that, e) } });\n\n        eleView.render();\n        that.$list.append( eleView.$el );\n\n      });\n\n      var options = {\n          valueNames: [ 'name' ]\n      };\n\n      this.list = new List(this.el, options);\n\n    },\n\n    highlightInput: function(){\n\n      if (this.app.get('showingSearch')) {\n        this.$input.focus().select();\n      } else {\n        this.$input.blur();\n      }\n    },\n\n    addNode: function(name){\n      this.app.getCurrentWorkspace().addNodeByNameAndPosition( name, this.app.newNodePosition );\n    },\n\n    elementClick: function(ele){\n\n      this.addNode(ele.model.get('name'));\n      this.app.set('showingSearch', false);\n\n    },\n\n    searchKeyup: function(event) {\n\n      if ( event.keyCode === 13) { // enter key causes first result to be inserted\n        var nodeName = this.$list.find('.search-element').first().find('.name').first().html();\n        if (nodeName === undefined ) return;\n\n        this.addNode( nodeName );\n        this.app.set('showingSearch', false);\n        \n      } else if ( event.keyCode === 27) { // esc key exits search\n        this.app.set('showingSearch', false);\n      }\n    } \n\n  });\n\n});\n\n"
  },
  {
    "path": "app/scripts/views/ShareView.js",
    "content": "define(['backbone'], function(Backbone) {\n\n  return Backbone.View.extend({\n\n    el: '#share',\n\n    events: { \n      'click #exit-share' : 'clickExit', \n      'click' : 'clickExit',\n      'click .modal-box': 'stopPropagation',\n      'click .is-customizer-checkbox': 'checkboxChanged'\n    },\n\n    template: _.template( $('#share-template').html() ),\n\n    initialize: function( args, atts ) {\n      this.app = atts.app;\n\n      this.model.on('success', this.success, this );\n    },\n\n    stopPropagation: function(e){\n      e.stopPropagation();\n    },\n\n    render: function() {\n\n      var ws = this.app.getCurrentWorkspace();\n\n      this.$el.html( this.template({\n        name: ws.get('name'),\n        isCustomizer: ws.get('isCustomizer'),\n        url: ws.getCustomizerUrl()\n      }) );\n\n      if (!ws.isCustomizer){\n        // we defer this as the input isn't necessarily yet in the dom\n        _.defer(function(){ this.$el.find('.customizer-url').focus().select(); }.bind(this) );\n      }\n\n      this.updatePublicPrivate();\n\n      return this;\n\n    },\n\n    updatePublicPrivate: function(){\n\n      if ( this.app.getCurrentWorkspace().get('isCustomizer') ){\n        this.$el.find('.is-customizer-checkbox').removeClass(\"fa-toggle-off\");\n        this.$el.find('.is-customizer-checkbox').addClass(\"fa-toggle-on\");\n        this.$el.find('.public').show();\n        this.$el.find('.private').hide();\n      } else {\n        this.$el.find('.is-customizer-checkbox').removeClass(\"fa-toggle-on\");\n        this.$el.find('.is-customizer-checkbox').addClass(\"fa-toggle-off\");\n        this.$el.find('.public').hide();\n        this.$el.find('.private').show();\n      }\n\n    },\n\n    checkboxChanged: function(){\n\n      var ws = this.app.getCurrentWorkspace();\n      ws.set('isCustomizer', !ws.get('isCustomizer') );\n\n      this.updatePublicPrivate();\n\n    },\n\n    clickExit: function(e){\n      this.app.set(\"showingShare\", false);\n    }\n\n  });\n});"
  },
  {
    "path": "app/scripts/views/WorkspaceBrowserElementView.js",
    "content": "define(['backbone'], function(Backbone) {\n\n  return Backbone.View.extend({\n\n    tagName: 'li',\n    className: 'workspace-browser-element',\n\n    template: _.template( $('#workspace-browser-element-template').html() ),\n\n    events: {\n      'click':  'clickOpen',\n      'click .delete-workspace':  'clickDelete',\n      'mouseenter': 'mouseenter',\n      'mouseleave': 'mouseleave'\n    },\n\n    initialize: function(_, vals){\n      this.app = vals.app;\n    },\n\n    render: function() {\n\n      var v = this.model.toJSON();\n      var lastSave = this.model.get('lastSaved');\n\n      if (typeof lastSave === \"string\") {\n        v[\"prettyDate\"] = this.prettyDate( new Date(lastSave) );\n      } else {\n        v[\"prettyDate\"] = \"Unknown\";\n      }\n      \n      this.$el.html( this.template( v ) );\n      this.$open = this.$el.find('.workspace-browser-element-open');\n\n    },\n\n    prettyDate: function(date){\n\n      var diff = (((new Date()).getTime() - date.getTime()) / 1000),\n        day_diff = Math.floor(diff / 86400);\n          \n      if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 )\n        return;\n          \n      return day_diff == 0 && (\n          diff < 60 && \"just now\" ||\n          diff < 120 && \"1 minute ago\" ||\n          diff < 3600 && Math.floor( diff / 60 ) + \" minutes ago\" ||\n          diff < 7200 && \"1 hour ago\" ||\n          diff < 86400 && Math.floor( diff / 3600 ) + \" hours ago\") ||\n        day_diff == 1 && \"Yesterday\" ||\n        day_diff < 7 && day_diff + \" days ago\" ||\n        day_diff < 31 && Math.ceil( day_diff / 7 ) + \" weeks ago\";\n    },\n\n    clickOpen: function(e) {\n      this.app.openWorkspace( this.model.get('_id') );\n    },\n\n    clickDelete: function(e){\n\n    }\n\n  });\n\n});"
  },
  {
    "path": "app/scripts/views/WorkspaceBrowserView.js",
    "content": "define(['backbone', 'WorkspaceBrowserElementView'], function(Backbone, WorkspaceBrowserElementView) {\n\n  return Backbone.View.extend({\n\n    el: '#workspace-browser',\n\n    initialize: function(atts, arr) {\n      this.app = arr.app;\n\n      this.model.get('workspaces').on('reset', this.render, this );\n      this.model.get('workspaces').on('add', this.addWorkspaceElement, this );\n      this.model.get('workspaces').on('remove', this.removeWorkspaceElement, this );\n\n      this.render();\n    },\n\n    template: _.template( $('#workspace-browser-template').html() ),\n\n    events: { \n      'click .workspace-browser-refresh': \"refreshClick\",\n      'click #workspace-browser-header-custom-nodes': \"customNodeHeaderClick\",\n      'click #workspace-browser-header-projects': \"projectHeaderClick\"\n    },\n\n    render: function(arg) {\n\n      if (!this.rendered) {\n        this.$el.html( this.template( this.model.toJSON() ) );\n        this.contents = this.$el.find('#workspace-browser-contents');\n        this.customNodes = this.$el.find('#workspace-browser-custom-nodes');\n        this.projects = this.$el.find('#workspace-browser-projects');\n      }\n\n      this.rendered = true;\n      \n      this.customNodes.empty();\n      this.projects.empty();\n\n    },\n\n    refreshClick: function(e){\n      this.model.refresh();\n      e.stopPropagation();\n    },\n\n    customNodeHeaderClick: function(e){\n\n      // do not resize when refresh is clicked\n      if ( $(e.target).hasClass('workspace-browser-refresh') ) return;\n\n      this.projects.hide();\n      this.customNodes.show();\n\n      $('#workspace-browser-header-custom-nodes').css('bottom','').css('top','40px');\n\n    },\n\n    projectHeaderClick: function(e){\n\n      if ( $(e.target).hasClass('workspace-browser-refresh') ) return;\n      \n      this.customNodes.hide();\n      this.projects.show();\n\n      $('#workspace-browser-header-custom-nodes').css('bottom','0').css('top','');\n\n    },\n\n    addWorkspaceElement: function(x){\n\n      if (!this.contents) this.render();\n\n      var v = new WorkspaceBrowserElementView( { model: x }, { app : this.app } );\n      v.render();\n\n      if ( x.get('isCustomNode') ){\n        this.customNodes.append( v.$el );\n      } else {\n        this.projects.append( v.$el );\n      }\n      \n    }, \n\n    removeWorkspaceElement: function(ws){\n\n      if (!this.contents) return;\n      this.contents.find('.workspace-browser-element[data-id*=' + ws.get('_id') + ']').remove();\n\n    }\n\n  });\n\n});\n\n"
  },
  {
    "path": "app/scripts/views/WorkspaceControlsView.js",
    "content": "define(['backbone', 'List', 'SearchElementView', 'bootstrap', 'jquery'], function(Backbone, List, SearchElementView, bootstrap, $) {\n\n  return Backbone.View.extend({\n\n    tagName: 'div',\n    className: 'workspace-search',\n\n    initialize: function(atts, arr) {\n      this.app = arr.app;\n      this.appView = arr.appView;\n\n      this.app.SearchElements.on('add remove', this.render, this);\n    },\n\n    template: _.template( $('#workspace-search-template').html() ),\n\n    events: {\n      'keyup .library-search-input': 'searchKeyup',\n      'focus .library-search-input': 'focus',\n      'blur .library-search-input': 'blur',\n      'click #delete-button': 'deleteClick',\n      'click #undo-button': 'undoClick',\n      'click #redo-button': 'redoClick',\n      'click #copy-button': 'copyClick',\n      'click #paste-button': 'pasteClick',\n      'click #zoomin-button': 'zoominClick',\n      'click #zoomout-button': 'zoomoutClick',\n      'click #zoomreset-button': 'zoomresetClick',\n      'click #export-button': 'exportClick'\n    },\n\n    render: function(arg) {\n\n      this.$el.html( this.template( this.model.toJSON() ) );\n\n      this.$input = this.$('.library-search-input');\n      this.$list = this.$('.search-list');\n\n      // highlight text in the search input when focussed\n      this.$input.focus(function(){ this.select(); });\n\n      this.$list.empty();\n\n      var that = this;\n\n      this.app.SearchElements.forEach(function(ele) {\n\n        var eleView = new SearchElementView({ model: ele }, { appView: that.appView, app: that.app,\n          click: function(e){ that.elementClick.call(that, e); }\n        });\n\n        eleView.render();\n        that.$list.append( eleView.$el );\n\n      });\n\n      var options = {\n          valueNames: [ 'name' ]\n      };\n\n      this.list = new List(this.el, options);\n\n      // build button tooltips\n      this.$el.find('#undo-button').tooltip({title: \"Undo\"});\n      this.$el.find('#redo-button').tooltip({title: \"Redo\"});\n\n      this.$el.find('#copy-button').tooltip({title: \"Copy\"});\n      this.$el.find('#paste-button').tooltip({title: \"Paste\"});\n\n      this.$el.find('#delete-button').tooltip({title: \"Delete\"});\n\n      this.$el.find('#zoomin-button').tooltip({title: \"Zoom in\"});\n      this.$el.find('#zoomout-button').tooltip({title: \"Zoom out\"});\n      this.$el.find('#zoomreset-button').tooltip({title: \"Zoom fit\"});\n\n      this.$el.find('#export-button').tooltip({title: \"Export as STL\"});\n\n      $('#workspace_hide').tooltip({title: \"Switch between 3D view and nodes\"});\n\n      $('#help-button').tooltip({title: \"Help\", placement: \"left\"});\n      $('#feedback-button').tooltip({title: \"Feedback\", placement: \"left\"});\n      $('#share-button').tooltip({title: \"Share\", placement: \"left\"});\n\n    },\n\n    focus: function(event){\n      this.$('.search-list').show();\n      this.$('.library-search-input').select();\n    },\n\n    blur: function(event){\n      var that = this;\n      window.setTimeout(function(){\n        that.$('.search-list').hide();\n      }, 100);\n    },\n\n    deleteClick: function(){\n      this.app.getCurrentWorkspace().removeSelected();\n    },\n\n    copyClick: function(){\n      this.app.getCurrentWorkspace().copy();\n    },\n\n    pasteClick: function(){\n      this.app.getCurrentWorkspace().paste();\n    },\n\n    undoClick: function(){\n      this.app.getCurrentWorkspace().undo();\n    },\n\n    redoClick: function(){\n      this.app.getCurrentWorkspace().redo();\n    },\n\n    zoomresetClick: function(){\n      this.appView.currentWorkspaceView.zoomAll();\n    },\n\n    zoominClick: function(){\n      this.app.getCurrentWorkspace().zoomIn();\n    },\n\n    zoomoutClick: function(){\n      this.app.getCurrentWorkspace().zoomOut();\n    },\n\n    addNode: function(name){\n\n      if (name === undefined ) return;\n      this.app.getCurrentWorkspace().addNodeByNameAndPosition( name, this.appView.getCurrentWorkspaceCenter() );\n\n    },\n\n    exportClick: function(e){\n\n      this.app.getCurrentWorkspace().exportSTL();\n\n    },\n\n    elementClick: function(ele){\n\n      this.addNode( ele.model.get('name') );\n\n    },\n\n    searchKeyup: function(event) {\n\n      // enter key causes first result to be inserted\n      if ( event.keyCode === 13) {\n\n        var nodeName = this.$list.find('.search-element').first().find('.name').first().html();\n        if (nodeName === undefined ) return;\n\n        this.addNode( nodeName );\n\n      }\n\n    }\n\n  });\n\n});\n\n"
  },
  {
    "path": "app/scripts/views/WorkspaceTabView.js",
    "content": "define(['backbone'], function(Backbone) {\n\n  return Backbone.View.extend({\n\n    tagName: 'div',\n    className: 'workspace-tab',\n\n    initialize: function(atts) { \n\n      this.app = this.model.app;\n      this.listenTo( this.model, 'change:name', this.render);\n      this.listenTo( this.model, 'change:current', this.render);\n\n    },\n\n    template: _.template( $('#workspace-tab-template').html() ),\n\n    events: {\n\n      'click': 'click',\n      'click .remove-button': 'remove',\n      'mouseover': 'showEditButton',\n      'mouseout': 'hideEditButton',\n      'click .edit-button': 'startEdit',\n      'blur .workspace-name': 'endEdit',\n\n      // touch\n      'touchstart .edit-button': 'startEdit',\n      'touchstart': 'toggleShowingEditButton'\n\n    },\n\n    render: function() {\n\n      this.$el.html( this.template( this.model.toJSON() ) );\n\n      if (this.model.get('current') === true){\n        this.$el.addClass('current-workspace')\n      } else {\n        this.$el.removeClass('current-workspace')\n      }\n\n      this.$input = this.$('.workspace-name');\n\n    },\n\n    toggleShowingEditButton: function(){\n\n      if ( this.editButtonShown ){\n        this.editButtonShown = false;\n        this.hideEditButton();\n      } else {\n        this.editButtonShown = true;\n        this.showEditButton();\n      }\n\n    },\n\n    showEditButton: function() {\n      this.$('.edit-button').css('visibility', 'visible');\n    },\n\n    hideEditButton: function() {\n      this.$('.edit-button').css('visibility', 'hidden');\n    },\n\n    startEdit: function(e) {\n      \n      this.$input.prop('disabled', false);\n      this.$input.focus().select();\n      this.$input.css('pointer-events', 'auto');\n\n      e.stopPropagation();\n    },\n\n    endEdit: function() {\n\n      // the edit button is still visible on touch devices\n      this.hideEditButton();\n\n      this.$input.prop('disabled', true);\n      this.$input.css('pointer-events', 'none');\n      this.model.set('name', this.$input.val() );\n    },\n\n    click: function(e) {\n      this.model.app.set('currentWorkspace', this.model.get('_id'));\n    },\n\n    remove: function(e){\n      this.model.app.get('workspaces').remove(this.model);\n      e.stopPropagation();\n    }\n\n  });\n\n});"
  },
  {
    "path": "app/scripts/views/WorkspaceView.js",
    "content": "define(['backbone', 'Workspace', 'ConnectionView', 'MarqueeView', 'NodeViewTypes', 'Hammer'], function(Backbone, Workspace, ConnectionView, MarqueeView, NodeViewTypes, Hammer){\n\n  return Backbone.View.extend({\n\n    tagName: 'div',\n    className: 'workspace_container row',\n\n    events: {\n      'mousedown .workspace_back':  'deselectAll',\n      'touchstart .workspace_back':  'deselectAll',\n      'mousedown .workspace_back':  'startWorkspaceDrag',\n      'dblclick .workspace_back':  'showNodeSearch',\n\n      // mousewheel\n      'mousewheel':  'mousewheelMove',\n      'DOMMouseScroll':  'mousewheelMove',\n      'MozMousePixelScroll':  'mousewheelMove',\n    },\n\n    initialize: function(atts) { \n\n      this.nodeViews = {};\n      this.connectionViews = {};\n\n      this.app = this.model.app;\n\n      this.$workspace = $('<div/>', {class: 'workspace'});\n\n      this.$workspace_back = $('<div/>', {class: 'workspace_back'});\n      this.$workspace_canvas = $('<svg class=\"workspace_canvas\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" />');\n\n      this.$el.append( this.$workspace );\n      this.$workspace.append( this.$workspace_back );\n      this.$workspace.append( this.$workspace_canvas );\n\n      var that = this;\n\n      this.listenTo(this.model, 'change:connections', function() {\n        that.cleanup().renderConnections();\n      });\n\n      this.model.on('change:zoom', this.updateZoom, this );\n      this.model.on('change:offset', this.updateOffset, this );\n      this.model.on('change:isRunning', this.renderRunnerStatus, this);\n\n      this.listenTo(this.model, 'change:nodes', function() {\n        that.cleanup().renderNodes();\n      });\n\n      this.listenTo(this.model, 'change:current', this.onChangeCurrent );\n\n      this.listenTo(this.model, 'startProxyDrag', this.startProxyDrag);\n      this.listenTo(this.model, 'endProxyDrag', this.endProxyDrag);\n\n      this.renderProxyConnection();\n      this.renderMarquee();\n\n      this.renderRunnerStatus();\n\n    },\n\n    render: function() {\n\n      return this\n              .cleanup()\n              .renderNodes()\n              .renderConnections()\n              .renderNodes()\n              .renderRunnerStatus()\n              .updateZoom()\n              .updateOffset()\n              .setupHammer();\n    },\n\n    hammerSetupDone: false,\n\n    inWorkspaceCoordinates: function(x, y){\n      var offset = this.$workspace.offset()\n        , zoom = this.model.get('zoom');\n\n      return [ (1 / zoom) * (x - offset.left), (1 / zoom) * ( y - offset.top) ];\n    },\n\n    setupHammer: function(){\n\n      if (this.hammerSetupDone) return this;\n      this.hammerSetupDone = true;\n\n      function isTouchDevice() {  \n        return 'ontouchstart' in window // works on most browsers \n          || 'onmsgesturechange' in window; // works on ie10\n      }\n\n      if (!isTouchDevice()) return;\n\n      this.$workspace_back.on('touchmove', function(e){\n        e.preventDefault();\n      })\n\n      // marquee - single finger on .workspace_back\n\n      var mcm = new Hammer.Manager(this.$workspace_back.get(0));\n      mcm.add( new Hammer.Pan({ direction: Hammer.DIRECTION_ALL, pointers: 1 }) );\n\n      // start marquee\n      mcm.on('panstart', function(event){\n\n        this.model.marquee.setStartCorner( this.inWorkspaceCoordinates(event.center.x, event.center.y) );\n\n      }.bind(this));\n\n      // marquee\n      mcm.on('pan', function(event) {\n\n        this.model.marquee.set('hidden', false);\n        this.model.marquee.setEndCorner( this.inWorkspaceCoordinates(event.center.x, event.center.y) );\n        this.doMarqueeSelect();\n\n      }.bind(this));\n\n      // end marquee\n      mcm.on('panend', function(){\n\n        this.model.marquee.set('hidden', true);\n\n      }.bind(this));\n\n\n      var mc = new Hammer.Manager(this.el);\n      mc.add( new Hammer.Pan({ direction: Hammer.DIRECTION_ALL, pointers: 3 }) );\n\n      // start pan\n      mc.on('panstart', function(){\n        this.scrollStart = [ this.$el.scrollLeft(), this.$el.scrollTop() ];\n      }.bind(this));\n\n      // pan\n      mc.on('pan', function(ev) {\n        this.model.set('offset', [ this.scrollStart[0] - ev.deltaX, this.scrollStart[1] - ev.deltaY ] );\n      }.bind(this));\n\n      // end pan\n      mc.on('panend', function(){\n        this.zoomDisabled = true;\n        setTimeout(function(){ this.zoomDisabled = false; }.bind(this), 200)\n      }.bind(this));\n\n      // pinching\n      mc.add( new Hammer.Pinch({ threshold: 0.1 }) );\n\n      mc.on('pinchstart', function(ev) {\n        this.zoomStart = this.model.get('zoom');\n      }.bind( this ));\n\n      mc.on('pinch', function(ev) {\n        if (this.zoomDisabled) return;\n\n        var val = this.zoomStart * ev.scale;\n\n        if (val < 0.25) val = 0.25;\n        if (val > 1.2) val = 1.2;\n\n        this.model.set('zoom', val );\n      }.bind( this ));\n\n\n      // tap\n      mc.add( new Hammer.Tap({ taps: 2 }) );\n\n      mc.on('tap', function(e) {\n        this.showNodeSearch({ clientX: e.center.x, clientY: e.center.y });\n      }.bind( this ));\n\n      return this;\n\n    },\n\n    mousewheelMove: function(e){\n\n      this.isMouseWheel = true;\n      this.clientX = e.clientX;\n      this.clientY = e.clientY;\n\n      var delta = 0;\n\n      if ( e.originalEvent.wheelDelta !== undefined ) { // WebKit / Opera / Explorer 9\n        delta = e.originalEvent.wheelDelta;\n      } else if ( e.originalEvent.detail !== undefined ) { // Firefox\n        delta = -e.originalEvent.detail;\n      }\n\n      if( delta > 0 ) {\n          if (this.model.get('zoom') < 1) \n            this.model.set('zoom', Math.min(1, this.model.get('zoom') + delta * 0.0005 ));\n      } else {\n          if (this.model.get('zoom') > 0.25) \n            this.model.set('zoom', Math.max( 0.25, this.model.get('zoom') + delta * 0.0005 ));\n      }\n\n      this.isMouseWheel = false;\n\n      return false;\n\n    },\n\n    startWorkspaceDrag: function(event){\n      this.deselectAll();\n\n      if (event.ctrlKey || event.which === 2){\n        this.startWorkspacePan(event);\n      } else {\n        this.startMarqueeDrag(event);\n      }\n    },\n\n    // workspace panning\n\n    panStart: [0,0],\n\n    startWorkspacePan: function(event){\n      event.preventDefault();\n\n      this.panStart = [ event.pageX,  event.pageY ];\n      this.scrollStart = [ this.$el.scrollLeft(), this.$el.scrollTop() ];\n      \n      this.$workspace.bind('mousemove', $.proxy( this.workspacePan, this) );\n      this.$workspace.bind('mouseup', $.proxy( this.endWorkspacePan, this) );\n    },\n\n    endWorkspacePan: function(event){\n      this.model.set('offset', [this.$el.scrollLeft(), this.$el.scrollTop()])\n      this.$workspace.unbind('mousemove', this.workspacePan);\n      this.$workspace.unbind('mouseup', this.endWorkspacePan);\n    },\n\n    workspacePan: function(event){\n      this.$el.scrollLeft( this.scrollStart[0] + this.panStart[0] - event.pageX );\n      this.$el.scrollTop( this.scrollStart[1] + this.panStart[1] - event.pageY );\n    },\n\n    // marquee drag\n\n    startMarqueeDrag: function(event){\n      this.model.marquee.setStartCorner( this.inWorkspaceCoordinates(event.pageX, event.pageY) );\n      \n      this.$workspace.bind('mousemove', $.proxy( this.marqueeDrag, this) );\n      this.$workspace.bind('mouseup', $.proxy( this.endMarqueeDrag, this) );\n    },\n\n    endMarqueeDrag: function(event){\n      this.model.marquee.set('hidden', true);\n      this.$workspace.unbind('mousemove', this.marqueeDrag);\n      this.$workspace.unbind('mouseup', this.endMarqueeDrag);\n    },\n\n    marqueeDrag: function(event){\n\n      this.model.marquee.set('hidden', false);\n      this.model.marquee.setEndCorner( this.inWorkspaceCoordinates(event.pageX, event.pageY) );\n      this.doMarqueeSelect();\n\n    },\n\n    doMarqueeSelect: function(){\n\n      var x1 = this.model.marquee.get('x')\n        , y1 = this.model.marquee.get('y')\n        , x2 = this.model.marquee.get('x') + this.model.marquee.get('width')\n        , y2 = this.model.marquee.get('y') + this.model.marquee.get('height');\n\n      for (var nodeId in this.nodeViews ){ \n\n        var node = this.nodeViews[nodeId];\n\n        var w = node.$el.width();\n        var h = node.$el.height();\n\n        var px = node.model.get('position');\n        var x = px[0], y = px[1];\n\n        var corners = [ [x, y], [x + w, y], [x + w, y + h], [x, y + h] ];\n\n        var cornerIn = false;\n\n        corners.forEach(function(c){\n\n          var cx = c[0], cy = c[1];\n          if ( cx < x2 && cx > x1 && cy > y1 && cy < y2 ) {\n            cornerIn = true;\n          }\n\n        });\n\n        if (cornerIn && !node.model.get('selected') ){\n          node.model.set('selected', true);\n        } else if ( !cornerIn && node.model.get('selected') ){\n          node.model.set('selected', false);\n        }\n\n      }\n\n    },\n\n    getCenter: function(){\n\n      var w = this.$el.width()\n        , h = this.$el.height()\n        , ho = this.$el.scrollTop()\n        , wo = this.$el.scrollLeft()\n        , zoom = 1 / this.model.get('zoom');\n\n      return [zoom * (wo + w / 2), zoom * (ho + h / 2)];\n\n    },\n\n    updateZoom: function(){\n\n      if (this.model.get('zoom') < 0) {\n        this.model.set('zoom', 0.25); \n        return this;\n      }\n\n      if (this.cachedZoom === this.model.get('zoom')) {\n        return this;\n      }\n\n      this.zoomFactor = this.model.get('zoom') / (this.cachedZoom ? this.cachedZoom : this.model.get('zoom') );\n      this.cachedZoom = this.model.get('zoom');\n\n      this.$workspace.css('transform', 'scale(' + this.model.get('zoom') + ')' );\n      this.$workspace.css('transform-origin', \"0 0\" );\n\n      // get scroll here, because it gets removed by the following lines\n      if (this.isMouseWheel){\n        var s = this.getNewScroll( this.clientX, this.clientY );\n      } else {\n        var s = this.getNewScroll();\n      }\n\n      this.model.set('offset', s);\n\n      return this;\n\n    },\n\n    getNewScroll: function(x, y){\n\n      var z = this.zoomFactor;\n      var ox = this.model.get('offset')[0];\n      var oy = this.model.get('offset')[1];\n\n      if (!x || !y){\n        var w = this.$el.width();\n        var h = this.$el.height();\n\n        // this is the offset from the center in document coordinates\n        var centerOffset = [w / 2, h / 2]; \n      } else {\n        var centerOffset = [x,y];\n      }\n\n      var sx = z * ( ox + centerOffset[0] ) - centerOffset[0];\n      var sy = z * ( oy + centerOffset[1] ) - centerOffset[1];\n\n      if (sx < 0) sx = 0;\n      if (sy < 0) sy = 0;\n\n      return [sx,sy];\n    },\n\n    boundingBox: function(){\n\n      // build list of nodeViews in ws\n      var nvs = [];\n      for (var nv in this.nodeViews){ \n        nvs.push( this.nodeViews[nv] ); \n      }\n\n      return nvs.reduce(function(a, x){\n\n        var p = x.model.get('position');\n        var nw = x.$el.width();\n        var nh = x.$el.height();\n\n        return [  Math.min(p[0], a[0]), \n                  Math.max(p[0] + nw, a[1]),\n                  Math.min(p[1], a[2]),\n                  Math.max(p[1] + nh, a[3]) ];\n\n      }, [ Number.MAX_VALUE, 0, Number.MAX_VALUE, 0 ] ); // minx, maxx, miny, maxy\n\n    },\n\n    zoomAll: function(){\n\n      var bb = this.boundingBox();\n\n      // this is the min offset we expect from the bounding box in document space\n      var o = 20 * (1 / this.model.get('zoom') );\n      bb = [bb[0] - o, bb[1] + o, bb[2] - o, bb[3] + o ];\n\n      // calculate zoom\n\n      // we do this by first determining the width and height of the ws\n      var wsw = this.$el.width();\n      var wsh = this.$el.height();\n\n      // now we determine the width of the node collection\n      var ntw = bb[1] - bb[0];\n      var nth = bb[3] - bb[2];\n\n      // we calculate the zoom from the ratio between the node bbox and workspace size\n      var zx = wsw / ntw;\n      var zy = wsh / nth;\n      var nz = Math.min( zx, zy ); // the new zoom is the lesser of these two - TODO account for zoom min\n\n      nz = Math.min(1, nz);\n\n      // set the zoom\n      this.model.set('zoom', nz );\n\n      // set the offset, taking into account the new zoom\n      var offset = [ nz * bb[0], nz * bb[2] ];\n      this.model.set('offset', offset);\n\n    },\n\n    updateOffset: function(){\n\n      var s = this.model.get('offset');\n\n      this.$el.scrollLeft( s[0] );\n      this.$el.scrollTop( s[1] );\n\n      return this;\n\n    },\n\n    $runnerStatus : undefined,\n    runnerTemplate : _.template( $('#workspace-runner-status-template').html() ),\n    renderRunnerStatus: function(){\n\n      // placeholder for future work\n      return this;\n\n    },\n\n    showNodeSearch: function(e){\n      this.app.set('showingSearch', true);\n\n      // the position of the click in workspace coordinates\n      var z = 1 / this.model.get('zoom');\n      var offX  = z * (e.clientX + this.$el.scrollLeft());\n      var offY  = z * (e.clientY + this.$el.scrollTop());\n\n      this.app.newNodePosition = [offX, offY];\n    },\n\n    startProxyDrag: function(event){\n      this.$workspace.bind('touchmove', $.proxy( this.proxyTouchDrag, this) );\n      this.$workspace.bind('mousemove', $.proxy( this.proxyDrag, this) );\n      this.$workspace.bind('touchend', $.proxy( this.endProxyDrag, this) );\n      this.$workspace.bind('mouseup', $.proxy( this.endProxyDrag, this) );\n    },\n\n    endProxyDrag: function(event){\n      this.$workspace.unbind('touchmove', this.proxyTouchDrag );\n      this.$workspace.unbind('mousemove', this.proxyDrag);\n      this.$workspace.unbind('touchend', this.endProxyDrag);\n      this.$workspace.unbind('mouseup', this.endProxyDrag);\n      \n      this.model.endProxyConnection();\n    },\n\n    proxyTouchDrag: function(event){\n      this.model.proxyConnection.set('endProxyPosition', \n        this.inWorkspaceCoordinates(event.originalEvent.touches[0].pageX, event.originalEvent.touches[0].pageY));\n      event.preventDefault(); // prevents mousemove\n    },\n\n    proxyDrag: function(event){\n      this.model.proxyConnection.set('endProxyPosition', this.inWorkspaceCoordinates(event.pageX, event.pageY));\n    },\n\n    renderProxyConnection: function() {\n\n      var view = new ConnectionView({ \n        model: this.model.proxyConnection, \n        workspaceView: this, \n        workspace: this.model, \n        isProxy: true\n      });\n\n      view.render();\n      this.$workspace_canvas.prepend( view.el );\n\n    },\n\n    renderMarquee: function() {\n\n      var view = new MarqueeView({ \n        model: this.model.marquee, \n        workspaceView: this, \n        workspace: this.model\n      });\n\n      view.render();\n      this.$workspace_canvas.prepend( view.el );\n\n    },\n\n    cleanup: function() {\n      this.clearDeadNodes();\n      this.clearDeadConnections();\n      return this;\n    },\n\n    renderNodes: function() {\n\n      var this_ = this;\n\n      this.model.get('nodes').each(function(nodeModel) {\n\n        var nodeView = this_.nodeViews[nodeModel.get('_id')];\n\n        // if NodeView has not been drawn\n        if ( nodeView === undefined){\n\n          var NodeView = NodeViewTypes.Base;\n          if ( NodeViewTypes[ nodeModel.get('typeName') ] != undefined)\n          {\n            NodeView = NodeViewTypes[ nodeModel.get('typeName') ];\n          }\n          nodeView = new NodeView({ model: nodeModel, workspaceView: this_, workspace: this_.model });\n          this_.nodeViews[ nodeView.model.get('_id') ] = nodeView;\n\n          this_.$workspace.prepend( nodeView.$el );\n          nodeView.render();\n          nodeView.makeDraggable();\n          nodeView.delegateEvents();\n          \n          this_.$workspace_canvas.append( nodeView.portGroup );\n\n        }\n\n      });\n\n      return this;\n\n    },\n\n    keydownHandler: function(e){\n\n      var isBackspaceOrDelete = e.keyCode === 46 || e.keyCode === 8;\n\n      if ( !(e.metaKey || e.ctrlKey) && !isBackspaceOrDelete ) return;\n\n      // do not capture from input\n      if (e.originalEvent.srcElement && e.originalEvent.srcElement.nodeName === \"INPUT\") return;\n      if (e.target.nodeName === \"INPUT\") return;\n\n      // keycodes: http://css-tricks.com/snippets/javascript/javascript-keycodes/\n\n      switch (e.keyCode) {\n        case 8:\n          this.model.removeSelected();\n          return e.preventDefault();\n        case 46:\n          this.model.removeSelected();\n          return e.preventDefault();\n        case 61:\n        case 187:\n          this.model.zoomIn();\n          return e.preventDefault();\n        case 189:\n        case 173:\n          this.model.zoomOut();\n          return e.preventDefault();\n        case 67:\n          this.model.copy();\n          return e.preventDefault();\n        case 86:\n          this.model.paste();\n          return e.preventDefault();\n        case 88:\n          this.model.copy();\n          this.model.removeSelected();\n          return e.preventDefault();\n        case 89:\n          this.model.redo();\n          return e.preventDefault();\n        case 90:\n          this.model.undo();\n          return e.preventDefault();\n      }\n\n    },\n\n    renderConnections: function() {\n\n      var this_ = this;\n\n      this.model.get('connections').forEach( function( cntn ) {\n\n        var view = this_.connectionViews[cntn.get('_id')]\n\n        if ( this_.connectionViews[cntn.get('_id')] === undefined){\n          view = new ConnectionView({ model: cntn, workspaceView: this_, workspace: this_.model });\n        }\n\n        view.delegateEvents();\n\n        if (!view.el.parentNode){\n\n          view.render();\n          this_.$workspace_canvas.prepend( view.el );\n\n          this_.connectionViews[ view.model.get('_id') ] = view;\n        }\n\n      });\n\n      return this;\n\n    },\n\n    clearDeadNodes: function() {\n\n      for (var key in this.nodeViews){\n        if (this.model.get('nodes').get(key) === undefined){\n          this.nodeViews[key].remove();\n          delete this.nodeViews[key];\n        }\n      }\n\n    },\n\n    clearDeadConnections: function() {\n      for (var key in this.connectionViews){\n        if (this.model.get('connections').get(key) === undefined){\n          this.connectionViews[key].remove();\n          delete this.connectionViews[key];\n        }\n      }\n    },\n\n    onRemove: function(){\n      this.get('nodes').forEach(function(n){\n        if (n.onRemove) n.onRemove();\n      })\n    },\n\n    deselectAll: function() {\n      this.model.get('nodes').deselectAll();\n    },\n\n  });\n});\n"
  },
  {
    "path": "app/scripts/views/customizer/CustomizerAppView.js",
    "content": "// the application is constituted by\n\n// CustomizerAppView, CustomizerApp - controls visibility of widget\n// CustomizerWorkspaceView - collection of node widgets, similar to a nodeview, includes mask for which widgets will be visible\n// CustomizerNodeView - similar to a nodeview, but no inputs/outputs, simplified controls, potentially multiple options with labels\n// CustomizerViewer - allows you to view your customized geometry, with saved camera position\n\ndefine(['backbone', 'CustomizerViewerView', 'CustomizerHeaderView', 'CustomizerWorkspaceView'],\n  function(Backbone, CustomizerViewer, CustomizerHeaderView, CustomizerWorkspaceView ) {\n\n  'use strict';\n\n  return Backbone.View.extend({\n\n    el: '#customizer-app ',\n\n    events: {  },\n\n    initialize: function( args, atts ) {\n      this.listenTo(this.model, 'change', this.render);\n    },\n\n    render: _.once(function() {\n\n      (new CustomizerViewer()).render();\n      var hv = new CustomizerHeaderView({model: this.model.getCurrentWorkspace() })\n      this.listenTo( hv, \"download-stl\", function(){ this.model.getCurrentWorkspace().exportSTL() } );;\n      hv.render();\n      (new CustomizerWorkspaceView({model: this.model.getCurrentWorkspace() })).render();\n\n      return this;\n\n    }),\n\n  });\n});\n"
  },
  {
    "path": "app/scripts/views/customizer/CustomizerHeaderView.js",
    "content": "define(['backbone'], function(Backbone) {\n\n  return Backbone.View.extend({\n\n    el: '#customizer-header',\n\n    template: _.template( $('#header-template').html() ),\n\n    events: { \"click .stl-download\" : \"downloadStl\" },\n\n    initialize: function( args, atts ) {\n      this.listenTo(this.model, 'change', this.render);\n    },\n\n    render: function() {\n\n      this.$el.html( this.template( this.model.toJSON() ) );\n      return this;\n\n    },\n\n    downloadStl: function() {\n        this.trigger(\"download-stl\")\n    }\n\n  });\n});\n"
  },
  {
    "path": "app/scripts/views/customizer/CustomizerViewerView.js",
    "content": "define(['backbone', 'Three', 'OrbitControls'], function(Backbone) {\n\n\tvar container, $container;\n\tvar camera, controls, renderer;\n\tvar geometry, group;\n\n\tscene = {};\n\n\tvar mouse = new THREE.Vector2(),\n\toffset = new THREE.Vector3(),\n\tINTERSECTED, SELECTED;\n\n\tvar objects = [], plane;\n\n\tvar mouseX = 0, mouseY = 0;\n\tvar animate;\n\n\tvar windowHalfX = window.innerWidth / 2;\n\tvar windowHalfY = window.innerHeight / 2;\n\n  return Backbone.View.extend({\n\n    el: '#customizer-viewer',\n\n    events: {  },\n\n    initialize: function( args, atts ) {\n\n    },\n\n    done: false,\n\n    render: _.once(function() {\n\n    \tthis.init();\n\t\t\tthis.renderView();\n\n    }),\n\n    init: function() {\n\n\t\t\tcontainer = document.getElementById(\"customizer-viewer\");\n\t\t\t$container = $(container);\n\n\t\t\tcamera = new THREE.PerspectiveCamera( 30, $container.width() / $container.height(), 1, 10000 );\n\n\t\t\tcamera.position.set( 140, 140, 140 );\n\t\t\tcamera.up.set( 0, 0, 1 );\n\t\t\tcamera.lookAt( new THREE.Vector3(0,0,0) );\n\n\t\t\tscene = new THREE.Scene();\n\n\t\t\trenderer = new THREE.WebGLRenderer({antialias: true});\n\t\t\trenderer.setClearColor( 0xffffff, 1 );\n\t\t\trenderer.setSize( $container.width(), $container.height() );\n\t\t\trenderer.sortObjects = false;\n\n\t\t\tcontainer.appendChild( renderer.domElement );\n\t\t\trenderer.domElement.setAttribute(\"id\", \"renderer_canvas\");\n\n\t\t\t// add subtle ambient lighting\n\t\t\tvar ambientLight = new THREE.AmbientLight(0x555555);\n\t\t\tscene.add(ambientLight);\n\n\t\t\t// add directional light source\n\t\t\tvar directionalLight = new THREE.DirectionalLight(0xbbbbbb);\n\t\t\tdirectionalLight.position.set(50, 30, 50);\n\t\t\tscene.add(directionalLight);\n\n\t\t\tvar directionalLight = new THREE.DirectionalLight(0xaaaaaa);\n\t\t\tdirectionalLight.position.set(-0.2, -0.8, 1).normalize();\n\t\t\tscene.add(directionalLight);\n\n\t\t\tthis.makeGrid();\n\n\t\t\tcontrols = new THREE.OrbitControls(camera, container);\n\n\t\t\tvar that = this;\n\n\t\t\tanimate = function(){\n\t\t\t\trequestAnimationFrame( animate );\n\t\t\t\tthat.renderView();\n\t\t\t};\n\n\t\t\trequestAnimationFrame(animate);\n\n\t\t\twindow.addEventListener( 'resize', this.onWindowResize.bind(this), false );\n\n\t\t},\n\n\t\tonWindowResize : function() {\n\n\t\t\twindowHalfX = $container.width() / 2;\n\t\t\twindowHalfY = $container.height() / 2;\n\n\t\t\tcamera.aspect = windowHalfX/ windowHalfY;\n\t\t\tcamera.updateProjectionMatrix();\n\n\t\t\trenderer.setSize( 2*windowHalfX, 2*windowHalfY );\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\trenderView: function() {\n\n\t\t\tcontrols.update();\n\t\t\trenderer.render( scene, camera );\n\n\t\t},\n\n\t\tmakeGrid: function(){\n\n\t\t\tvar l = 60;\n\n\t\t\tvar axisHelper = new THREE.AxisHelper( l );\n\t\t\tscene.add( axisHelper );\n\n\t\t\tvar geometry = new THREE.Geometry();\n\t\t\tvar geometryThick = new THREE.Geometry();\n\n\t\t\tvar n = l;\n\t\t\tvar inc = 2 * l / n;\n\t\t\tvar rate = 10;\n\n\t\t\tfor (var i = 0; i < n + 1; i++){\n\n\t\t    \tvar v1 = new THREE.Vector3(-l, -l + i * inc, 0);\n\t\t\t\tvar v2 = new THREE.Vector3(l, -l + i * inc, 0);\n\n\t\t    \tgeometry.vertices.push(v1);\n\t\t    \tgeometry.vertices.push(v2);\n\n\t\t    \tif (i % rate == 0){\n\t\t\t\t\tgeometryThick.vertices.push(v1);\n\t\t    \t\tgeometryThick.vertices.push(v2);\n\t\t    \t}\n\t\t\t}\n\n\t\t\tfor (var i = 0; i < n + 1; i++){\n\t\t\t\tvar v1 = new THREE.Vector3(-l + i * inc, l, 0);\n\t\t\t\tvar v2 = new THREE.Vector3(-l + i * inc, -l, 0);\n\n\t\t\t\tgeometry.vertices.push(v1);\n\t\t    \tgeometry.vertices.push(v2);\n\n\t\t    \tif (i % rate == 0){\n\t\t\t\t\tgeometryThick.vertices.push(v1);\n\t\t    \t\tgeometryThick.vertices.push(v2);\n\t\t    \t}\n\t\t\t}\n\n\t\t\tvar material = new THREE.LineBasicMaterial({\n\t\t        color: 0xeeeeee,\n\t\t        linewidth: 0.1\n\t\t    });\n\n\t\t    var materialThick = new THREE.LineBasicMaterial({\n\t\t        color: 0xeeeeee,\n\t\t        linewidth: 2\n\t\t    });\n\n\t\t    var line = new THREE.Line(geometry, material, THREE.LinePieces);\n\t\t    var lineThick = new THREE.Line(geometryThick, materialThick, THREE.LinePieces);\n\n\t\t    scene.add(line);\n\t\t    scene.add(lineThick);\n\n\t\t}\n\n  });\n});\n\n\n\n\n"
  },
  {
    "path": "app/scripts/views/customizer/CustomizerWorkspaceView.js",
    "content": "define(['backbone', 'BaseWidgetView', 'GeometryWidgetView', 'NumberWidgetView'], \n  function(Backbone, BaseWidgetView, GeometryWidgetView, NumberWidgetView) {\n\n  return Backbone.View.extend({\n\n    el: '#customizer-workspace',\n\n    events: { \n      \"click #hide-workspace\" : \"hideWorkspace\"\n     },\n\n    initialize: function( args, atts ) {\n\n    },\n\n    map: {\n      \"Number\" : NumberWidgetView\n    },\n\n    hasWidgets: false,\n\n    buildWidget: function(x){\n\n      if (x.get('extra') != undefined && x.get('extra').lock) return;\n\n      var widgetView = GeometryWidgetView;\n\n      if (x.get('type').typeName in this.map){\n        widgetView = this.map[x.get('type').typeName];\n      }\n\n      var widget = new widgetView({model: x});\n\n      if (x.get('type').typeName in this.map){\n        this.$el.append( widget.render().$el );\n        this.hasWidgets = true;\n      }\n\n    },\n\n    visible: true,\n\n    hideWorkspace: function(){\n\n      if (this.visible){\n        this.$el.addClass('workspace-contracted');\n        this.$el.find('.widget').css('visibility', 'hidden');\n        this.$el.find('#hide-workspace i').removeClass('fa-arrow-circle-left');\n        this.$el.find('#hide-workspace i').addClass('fa-arrow-circle-right');\n        this.visible = false;\n      } else {\n        this.$el.removeClass('workspace-contracted');\n        this.$el.find('.widget').css('visibility', 'visible');\n        this.$el.find('#hide-workspace i').removeClass('fa-arrow-circle-right');\n        this.$el.find('#hide-workspace i').addClass('fa-arrow-circle-left');\n        this.visible = true;\n      }\n\n    },\n\n    render: function() {\n\n      this.model.get('nodes').each(this.buildWidget.bind(this));\n\n      if (!this.hasWidgets) this.$el.hide();\n\n      return this;\n\n    }\n\n  });\n});"
  },
  {
    "path": "app/scripts/views/customizer/widgets/Base.js",
    "content": "define(['backbone'], function(Backbone) {\n\n  return Backbone.View.extend({\n\n    tagName: 'div',\n    className: 'widget',\n\n    template: _.template( $('#widget-template').html() ),\n\n    initialize: function(args) {\n\n      this.model.on('evalFailed', this.onEvalFailed, this );\n      this.model.on('evalBegin', this.onEvalBegin, this );\n\n      this.listenTo(this.model, 'requestRender', this.render );\n      this.listenTo(this.model, 'change:position', this.move );\n      this.listenTo(this.model, 'change:lastValue', this.renderLastValue );\n      this.listenTo(this.model, 'change:failureMessage', this.renderLastValue );\n      this.listenTo(this.model, 'change:ignoreDefaults', this.colorPorts );\n      this.listenTo(this.model, 'change:selected', this.colorSelected);\n      this.listenTo(this.model, 'change:visible', this.render);\n      this.listenTo(this.model, 'change:isEvaluating', this.colorEvaluating);\n\n      this.model.on('evalFailed', this.onEvalFailed, this );\n      this.model.on('evalBegin', this.onEvalBegin, this );\n\n    },\n\n    colorSelected: function(){\n\n    },\n\n    render: function() {\n\n      this.$el.html( this.template( this.model.toJSON() ) );\n      return this;\n\n    }\n\n  });\n\n});\n"
  },
  {
    "path": "app/scripts/views/customizer/widgets/Geometry.js",
    "content": "define(['backbone', 'underscore', 'jquery', 'BaseWidgetView'], function(Backbone, _, $, BaseWidgetView) {\n\n  return BaseWidgetView.extend({\n\n    initialize: function(args) {\n\n      BaseWidgetView.prototype.initialize.apply(this, arguments);\n\n      this.model.on('change:selected', this.colorSelected, this);\n      this.model.on('change:visible', this.changeVisibility, this);\n      this.model.on('remove', this.onRemove, this);\n      this.model.on('change:prettyLastValue', this.onEvalComplete, this );\n      this.model.workspace.on('change:current', this.changeVisibility, this);\n\n      this.onEvalComplete();\n\n    },\n\n    setMaterials: function(partMat, meshMat, lineMat){\n\n      this.threeGeom.traverse(function(ele) {\n        if (ele instanceof THREE.Mesh) {\n          ele.material = meshMat;\n        } else if (ele instanceof THREE.Line) {\n          ele.material = lineMat;\n        } else {\n          ele.material = partMat;\n        }\n      });\n\n    },\n\n    colorSelected: function(){\n\n      BaseWidgetView.prototype.colorSelected.apply(this, arguments);\n\n      if ( !( this.threeGeom && this.model.get('visible')) ) return this;\n\n      if (this.model.get('selected')) {\n\n        var meshMat = new THREE.MeshPhongMaterial({color: 0x66d6ff });\n        var partMat = new THREE.ParticleBasicMaterial({color: 0x66d6ff, size: 5, sizeAttenuation: false});\n        var lineMat = new THREE.LineBasicMaterial({ color: 0x66d6ff });\n\n      } else {\n\n        var meshMat = new THREE.MeshPhongMaterial({color: 0x999999});\n        var partMat = new THREE.ParticleBasicMaterial({color: 0x999999, size: 5, sizeAttenuation: false});\n        var lineMat = new THREE.LineBasicMaterial({ color: 0x000000 });\n\n      }\n\n      this.setMaterials(partMat, meshMat, lineMat);\n\n      return this;\n\n    }, \n\n    // 3D move to node subclass\n    onRemove: function(){\n      this.model.workspace.off('change:current', this.changeVisibility, this);\n      scene.remove(this.threeGeom); \n    }, \n\n    evaluated: false,\n\n    toThreeGeom: function( rawGeom ) {\n\n      var threeGeom = new THREE.Geometry(), face;\n\n      if (!rawGeom) return threeGeom;\n\n      if (!rawGeom.vertices && !rawGeom.linestrip ) return threeGeom;\n\n      if (rawGeom.linestrip) return this.addLineStrip( rawGeom, threeGeom );\n\n      if (rawGeom.vertices && !rawGeom.faces) return this.addPoints( rawGeom, threeGeom );\n\n      for ( var i = 0; i < rawGeom.vertices.length; i++ ) {\n        var v = rawGeom.vertices[i];\n        threeGeom.vertices.push( new THREE.Vector3( v[0], v[1], v[2] ) );\n      }\n\n      if (!rawGeom.faces) return threeGeom;\n\n      for ( var i = 0; i < rawGeom.faces.length; i++ ) {\n        var f = rawGeom.faces[i];\n        face = new THREE.Face3( f[0], f[1], f[2], new THREE.Vector3( f[3][0], f[3][1], f[3][2] ) );\n        threeGeom.faces.push( face );\n      }\n      \n      threeGeom._floodType = 0;\n\n      return threeGeom;\n\n    },\n\n    addPoints: function( rawGeom, threeGeom ){\n\n      for ( var i = 0; i < rawGeom.vertices.length; i++ ) {\n        var v = rawGeom.vertices[i];\n        threeGeom.vertices.push( new THREE.Vector3( v[0], v[1], v[2] ) );\n      }\n\n      threeGeom._floodType = 1;\n\n      return threeGeom;\n    },\n\n    addLineStrip: function( rawGeom, threeGeom ){\n\n      for ( var i = 0; i < rawGeom.linestrip.length; i++ ) {\n        var v = rawGeom.linestrip[i];\n        threeGeom.vertices.push( new THREE.Vector3( v[0], v[1], v[2] ) );\n      }\n\n      threeGeom._floodType = 2;\n\n      return threeGeom;\n      \n    },\n\n    onEvalComplete: function(a, b, newValue){\n\n      if (!newValue && this.evaluated) return;\n\n      this.evaluated = true;\n\n      var lastValue = this.model.get('prettyLastValue');\n      var temp;\n\n      if ( !lastValue ) return;\n\n      if ( lastValue.vertices || lastValue.linestrip ){ \n        temp = [];\n        temp.push(lastValue);\n      } else {\n        temp = lastValue; // extract the list\n      } \n\n      var threeTemp = new THREE.Object3D();\n      this.drawChunked( threeTemp, temp, function() { \n\n        if ( this.threeGeom ){\n          scene.remove( this.threeGeom );\n        }\n\n        this.threeGeom = threeTemp;\n        scene.add( this.threeGeom );\n        this.changeVisibility();\n\n      }, this );\n\n    }, \n\n    // creating this data may be quite slow, we'll need to be careful\n    drawChunked: function(geom, list, callback, that){\n\n      var i = 0;\n      var tick = function() {\n\n        var start = new Date().getTime();\n        for (; i < list.length && (new Date().getTime()) - start < 50; i++) {\n        \n          var g3  = that.toThreeGeom( list[i] );\n\n          if (that.model.get('selected')){\n            var color = 0x66d6ff;\n          } else {\n            var color = 0x999999;\n          }\n\n          switch (g3._floodType) {\n            case 0:\n              geom.add( new THREE.Mesh(g3, new THREE.MeshPhongMaterial({color: color})) );\n              break;\n            case 1:\n              geom.add( new THREE.ParticleSystem(g3, new THREE.ParticleBasicMaterial({color: color, size: 5, sizeAttenuation: false}) ));\n              break;\n            case 2:\n              geom.add( new THREE.Line(g3, new THREE.LineBasicMaterial({ color: 0x000000 })));\n              break;\n          }\n\n        }\n\n        if (i < list.length) {\n          setTimeout(tick, 25);\n        } else {\n          callback.call(that);\n        }\n\n      };\n\n      setTimeout(tick, 0);\n\n    },\n\n    changeVisibility: function(){\n\n      if ( !this.threeGeom ){\n        return;\n      }\n        \n      if (!this.model.get('visible') || !this.model.workspace.get('current') )\n      {\n        this.threeGeom.traverse(function(e) { e.visible = false; });\n      } else if ( this.model.get('visible') )\n      {\n        this.threeGeom.traverse(function(e) { e.visible = true; });\n      }\n\n    },\n\n    renderNode: function() {\n      \n      BaseWidgetView.prototype.renderNode.apply(this, arguments);\n\n      // this.$toggleVis = this.$el.find('.toggle-vis');\n      // this.$toggleVis.show();\n\n      // var icon = this.$toggleVis.find('i');\n      // var label = this.$toggleVis.find('span');\n\n      // if (this.model.get('visible')){\n      //   icon.addClass('icon-eye-open');\n      //   icon.removeClass('icon-eye-close');\n      //   label.html('Hide geometry');\n      // } else {\n      //   icon.removeClass('icon-eye-open');\n      //   icon.addClass('icon-eye-close');\n      //   label.html('Show geometry');\n      // }\n\n      return this;\n\n    },\n\n  });\n\n});"
  },
  {
    "path": "app/scripts/views/customizer/widgets/Number.js",
    "content": "define(['backbone', 'underscore', 'jquery', 'BaseWidgetView', 'jqueryuislider'], function(Backbone, _, $, BaseWidgetView) {\n\n  return BaseWidgetView.extend({\n\n    template: _.template( $('#widget-number-template').html() ),\n\n    initialize: function(args) {\n\n      BaseWidgetView.prototype.initialize.apply(this, arguments);\n      this.rendered = false;\n\n      this.model.on('change:extra', function() { \n        \n        var ex = this.model.get('extra') ;\n\n        this.silentSyncUI( ex );\n\n        this.model.trigger('updateRunner'); \n        this.model.workspace.trigger('requestRun');\n\n      }, this);\n\n    },\n \n    render: function() {\n      \n      BaseWidgetView.prototype.render.apply(this, arguments);\n\n      if (this.rendered) return this;\n\n      // make the slider\n      this.slider = this.$el.find('.slider');\n      if (!this.slider) return;\n\n      var extra = this.model.get('extra');\n      var min = extra.min != undefined ? extra.min : -150;\n      var max = extra.max != undefined ? extra.max : 150;\n      var step = extra.step != undefined ? extra.step : 0.1;\n      var value = extra.value != undefined ? extra.value : 0;\n      if (value === undefined ) value = this.model.get('lastValue');\n\n      var that = this;\n      this.slider.slider(\n        { min: min, \n          max: max, \n          step: step, \n          value: value,\n          change: function(e, ui){  that.inputSet.call(that, e, ui); },\n          slide: function(e, ui){ that.inputChanged.call(that, e, ui); } \n        });\n\n      // this.currentValueInput = this.$el.find('.currentValue');\n      // this.currentValueInput.html( value );\n\n      this.currentValueInput = this.$el.find('.currentValue');\n      this.currentValueInput.val( value );\n      this.currentValueInput.change( function(e){ that.valChanged.call(that, e); e.stopPropagation(); });\n\n      this.minInput = this.$el.find('.num-min');\n      this.minInput.val(min);\n      this.minInput.change( function(e){ that.minChanged.call(that, e); e.stopPropagation(); });\n\n      this.maxInput = this.$el.find('.num-max');\n      this.maxInput.val(max);\n      this.maxInput.change( function(e){ that.maxChanged.call(that, e); e.stopPropagation(); });\n\n      this.stepInput = this.$el.find('.num-step');\n      this.stepInput.val(step);\n      this.stepInput.change( function(e){ that.stepChanged.call(that, e); e.stopPropagation(); });\n\n      // adjust settings dropdown so that it stays open while editing\n      // doesn't select the node when you're editing\n      $('.dropdown.keep-open').on({\n        \"shown.bs.dropdown\": function() {\n          that.selectable = false;\n          that.model.set('selected', false);\n          $(this).data('closable', false);\n        },\n        \"mouseleave\": function() {\n          $(this).data('closable', true);\n        },\n        \"click\": function() {\n          $(this).data('closable', false);\n        },\n        \"hide.bs.dropdown\": function() {\n          if ( $(this).data('closable') ) that.selectable = true;\n          return $(this).data('closable');\n        }\n      });\n\n      // this.rendered = true;\n\n      return this;\n\n    },\n\n    silentSyncUI: function(data){\n\n      this.silent = true;\n      this.currentValueInput.val( data.value );\n      this.setSliderValue( data.value );\n      this.minInput.html( data.min );\n      this.maxInput.html( data.max );\n      this.stepInput.html( data.step );\n      this.silent = false;\n\n    },\n\n    currentValue: function(){\n      return this.slider.slider(\"option\", \"value\");\n    },\n\n    setSliderValue: function(val){\n      return this.slider.slider(\"option\", \"value\", val);\n    },\n\n    valChanged: function(val){\n      var val = parseFloat( this.currentValueInput.val() );\n      if (isNaN(val)) return;\n      return this.setSliderValue( val );\n    },\n\n    minChanged: function(e, u){\n      var val = parseFloat( this.minInput.val() );\n      if (isNaN(val)) return;\n      if (this.currentValue < val) this.setSliderValue(val);\n      this.slider.slider(\"option\", \"min\", val);\n    },\n\n    maxChanged: function(e){\n      var val = parseFloat( this.maxInput.val() );\n      if (isNaN(val)) return;\n      if (this.currentValue > val) this.setSliderValue(val);\n      this.slider.slider(\"option\", \"max\", val);\n    },\n\n    stepChanged: function(e){\n      var val = parseFloat( this.stepInput.val() );\n      if (isNaN(val)) return;\n      this.slider.slider(\"option\", \"step\", val);\n    },\n\n    inputChanged: function(e,ui) {\n\n      var val = ui.value;\n      this.$el.find('.currentValue').html(val);\n\n    },\n\n    inputSet: function(e,ui) {\n\n      if ( this.silent ) return;\n\n      var newValue = {   value: this.slider.slider(\"option\", \"value\"), min: this.slider.slider(\"option\", \"min\"), \n        step: this.slider.slider(\"option\", \"step\"), max: this.slider.slider(\"option\", \"max\") };\n\n      this.model.workspace.setNodeProperty({property: 'extra', _id: this.model.get('_id'), newValue: newValue });      \n\n    }\n\n  });\n\n});"
  },
  {
    "path": "app/styles/bootstrap.css",
    "content": "/*!\n * Bootstrap v3.0.3 (http://getbootstrap.com)\n * Copyright 2013 Twitter, Inc.\n * Licensed under http://www.apache.org/licenses/LICENSE-2.0\n */\n\n/*! normalize.css v2.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a{background:transparent}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{margin:.67em 0;font-size:2em}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box}mark{color:#000;background:#ff0}code,kbd,samp{font-family:monospace,serif;font-size:1em}q{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid #c0c0c0}legend{padding:0;border:0}button,input,select,textarea{margin:0;font-family:inherit;font-size:100%}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=\"button\"],input[type=\"reset\"],input[type=\"submit\"]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type=\"checkbox\"],input[type=\"radio\"]{padding:0;box-sizing:border-box}input[type=\"search\"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=\"search\"]::-webkit-search-cancel-button,input[type=\"search\"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:\" (\" attr(href) \")\"}abbr[title]:after{content:\" (\" attr(title) \")\"}a[href^=\"javascript:\"]:after,a[href^=\"#\"]:after{content:\"\"}blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:2cm .5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:\"Helvetica Neue\",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}img{vertical-align:middle}.img-responsive{display:block;height:auto;max-width:100%}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:\"Helvetica Neue\",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{margin-top:20px;margin-bottom:10px}h1 small,h2 small,h3 small,h1 .small,h2 .small,h3 .small{font-size:65%}h4,h5,h6{margin-top:10px;margin-bottom:10px}h4 small,h5 small,h6 small,h4 .small,h5 .small,h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media(min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-muted{color:#999}.text-primary{color:#428bca}.text-primary:hover{color:#3071a9}.text-warning{color:#8a6d3b}.text-warning:hover{color:#66512c}.text-danger{color:#a94442}.text-danger:hover{color:#843534}.text-success{color:#3c763d}.text-success:hover{color:#2b542c}.text-info{color:#31708f}.text-info:hover{color:#245269}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}.list-inline>li:first-child{padding-left:0}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.428571429}dt{font-weight:bold}dd{margin-left:0}@media(min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:\" \"}.dl-horizontal dd:after{clear:both}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:\" \"}.dl-horizontal dd:after{clear:both}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small,blockquote .small{display:block;line-height:1.428571429;color:#999}blockquote small:before,blockquote .small:before{content:'\\2014 \\00A0'}blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small,blockquote.pull-right .small{text-align:right}blockquote.pull-right small:before,blockquote.pull-right .small:before{content:''}blockquote.pull-right small:after,blockquote.pull-right .small:after{content:'\\00A0 \\2014'}blockquote:before,blockquote:after{content:\"\"}address{margin-bottom:20px;font-style:normal;line-height:1.428571429}code,kbd,samp{font-family:Menlo,Monaco,Consolas,\"Courier New\",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;white-space:nowrap;background-color:#f9f2f4;border-radius:4px}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.container:before,.container:after{display:table;content:\" \"}.container:after{clear:both}.container:before,.container:after{display:table;content:\" \"}.container:after{clear:both}@media(min-width:768px){.container{width:750px}}@media(min-width:992px){.container{width:970px}}@media(min-width:1200px){.container{width:1170px}}.row{}.row:before,.row:after{display:table;content:\" \"}.row:after{clear:both}.row:before,.row:after{display:table;content:\" \"}.row:after{clear:both}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666666666666%}.col-xs-10{width:83.33333333333334%}.col-xs-9{width:75%}.col-xs-8{width:66.66666666666666%}.col-xs-7{width:58.333333333333336%}.col-xs-6{width:50%}.col-xs-5{width:41.66666666666667%}.col-xs-4{width:33.33333333333333%}.col-xs-3{width:25%}.col-xs-2{width:16.666666666666664%}.col-xs-1{width:8.333333333333332%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666666666666%}.col-xs-pull-10{right:83.33333333333334%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666666666666%}.col-xs-pull-7{right:58.333333333333336%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666666666667%}.col-xs-pull-4{right:33.33333333333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.666666666666664%}.col-xs-pull-1{right:8.333333333333332%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666666666666%}.col-xs-push-10{left:83.33333333333334%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666666666666%}.col-xs-push-7{left:58.333333333333336%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666666666667%}.col-xs-push-4{left:33.33333333333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.666666666666664%}.col-xs-push-1{left:8.333333333333332%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666666666666%}.col-xs-offset-10{margin-left:83.33333333333334%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666666666666%}.col-xs-offset-7{margin-left:58.333333333333336%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666666666667%}.col-xs-offset-4{margin-left:33.33333333333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.666666666666664%}.col-xs-offset-1{margin-left:8.333333333333332%}.col-xs-offset-0{margin-left:0}@media(min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media(min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media(min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*=\"col-\"]{position:static;display:table-column;float:none}table td[class*=\"col-\"],table th[class*=\"col-\"]{display:table-cell;float:none}.table>thead>tr>.active,.table>tbody>tr>.active,.table>tfoot>tr>.active,.table>thead>.active>td,.table>tbody>.active>td,.table>tfoot>.active>td,.table>thead>.active>th,.table>tbody>.active>th,.table>tfoot>.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>.active:hover,.table-hover>tbody>.active:hover>td,.table-hover>tbody>.active:hover>th{background-color:#e8e8e8}.table>thead>tr>.success,.table>tbody>tr>.success,.table>tfoot>tr>.success,.table>thead>.success>td,.table>tbody>.success>td,.table>tfoot>.success>td,.table>thead>.success>th,.table>tbody>.success>th,.table>tfoot>.success>th{background-color:#dff0d8}.table-hover>tbody>tr>.success:hover,.table-hover>tbody>.success:hover>td,.table-hover>tbody>.success:hover>th{background-color:#d0e9c6}.table>thead>tr>.danger,.table>tbody>tr>.danger,.table>tfoot>tr>.danger,.table>thead>.danger>td,.table>tbody>.danger>td,.table>tfoot>.danger>td,.table>thead>.danger>th,.table>tbody>.danger>th,.table>tfoot>.danger>th{background-color:#f2dede}.table-hover>tbody>tr>.danger:hover,.table-hover>tbody>.danger:hover>td,.table-hover>tbody>.danger:hover>th{background-color:#ebcccc}.table>thead>tr>.warning,.table>tbody>tr>.warning,.table>tfoot>tr>.warning,.table>thead>.warning>td,.table>tbody>.warning>td,.table>tfoot>.warning>td,.table>thead>.warning>th,.table>tbody>.warning>th,.table>tfoot>.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>.warning:hover,.table-hover>tbody>.warning:hover>td,.table-hover>tbody>.warning:hover>th{background-color:#faf2cc}@media(max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type=\"search\"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=\"radio\"],input[type=\"checkbox\"]{margin:4px 0 0;margin-top:1px \\9;line-height:normal}input[type=\"file\"]{display:block}select[multiple],select[size]{height:auto}select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}input[type=\"file\"]:focus,input[type=\"radio\"]:focus,input[type=\"checkbox\"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}input[type=\"number\"]::-webkit-outer-spin-button,input[type=\"number\"]::-webkit-inner-spin-button{height:auto}output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}textarea.form-control{height:auto}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;padding-left:20px;margin-top:10px;margin-bottom:10px;vertical-align:middle}.radio label,.checkbox label{display:inline;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type=\"radio\"],.radio-inline input[type=\"radio\"],.checkbox input[type=\"checkbox\"],.checkbox-inline input[type=\"checkbox\"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:normal;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type=\"radio\"][disabled],input[type=\"checkbox\"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type=\"radio\"],fieldset[disabled] input[type=\"checkbox\"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg{height:auto}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media(min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block}.form-inline select.form-control{width:auto}.form-inline .radio,.form-inline .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .radio input[type=\"radio\"],.form-inline .checkbox input[type=\"checkbox\"]{float:none;margin-left:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:\" \"}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:\" \"}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-control-static{padding-top:7px}@media(min-width:768px){.form-horizontal .control-label{text-align:right}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:normal;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#fff}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-link{font-weight:normal;color:#428bca;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0}.btn-block+.btn-block{margin-top:5px}input[type=\"submit\"].btn-block,input[type=\"reset\"].btn-block,input[type=\"button\"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;line-height:1;-moz-osx-font-smoothing:grayscale}.glyphicon:empty{width:1em}.glyphicon-asterisk:before{content:\"\\2a\"}.glyphicon-plus:before{content:\"\\2b\"}.glyphicon-euro:before{content:\"\\20ac\"}.glyphicon-minus:before{content:\"\\2212\"}.glyphicon-cloud:before{content:\"\\2601\"}.glyphicon-envelope:before{content:\"\\2709\"}.glyphicon-pencil:before{content:\"\\270f\"}.glyphicon-glass:before{content:\"\\e001\"}.glyphicon-music:before{content:\"\\e002\"}.glyphicon-search:before{content:\"\\e003\"}.glyphicon-heart:before{content:\"\\e005\"}.glyphicon-star:before{content:\"\\e006\"}.glyphicon-star-empty:before{content:\"\\e007\"}.glyphicon-user:before{content:\"\\e008\"}.glyphicon-film:before{content:\"\\e009\"}.glyphicon-th-large:before{content:\"\\e010\"}.glyphicon-th:before{content:\"\\e011\"}.glyphicon-th-list:before{content:\"\\e012\"}.glyphicon-ok:before{content:\"\\e013\"}.glyphicon-remove:before{content:\"\\e014\"}.glyphicon-zoom-in:before{content:\"\\e015\"}.glyphicon-zoom-out:before{content:\"\\e016\"}.glyphicon-off:before{content:\"\\e017\"}.glyphicon-signal:before{content:\"\\e018\"}.glyphicon-cog:before{content:\"\\e019\"}.glyphicon-trash:before{content:\"\\e020\"}.glyphicon-home:before{content:\"\\e021\"}.glyphicon-file:before{content:\"\\e022\"}.glyphicon-time:before{content:\"\\e023\"}.glyphicon-road:before{content:\"\\e024\"}.glyphicon-download-alt:before{content:\"\\e025\"}.glyphicon-download:before{content:\"\\e026\"}.glyphicon-upload:before{content:\"\\e027\"}.glyphicon-inbox:before{content:\"\\e028\"}.glyphicon-play-circle:before{content:\"\\e029\"}.glyphicon-repeat:before{content:\"\\e030\"}.glyphicon-refresh:before{content:\"\\e031\"}.glyphicon-list-alt:before{content:\"\\e032\"}.glyphicon-lock:before{content:\"\\e033\"}.glyphicon-flag:before{content:\"\\e034\"}.glyphicon-headphones:before{content:\"\\e035\"}.glyphicon-volume-off:before{content:\"\\e036\"}.glyphicon-volume-down:before{content:\"\\e037\"}.glyphicon-volume-up:before{content:\"\\e038\"}.glyphicon-qrcode:before{content:\"\\e039\"}.glyphicon-barcode:before{content:\"\\e040\"}.glyphicon-tag:before{content:\"\\e041\"}.glyphicon-tags:before{content:\"\\e042\"}.glyphicon-book:before{content:\"\\e043\"}.glyphicon-bookmark:before{content:\"\\e044\"}.glyphicon-print:before{content:\"\\e045\"}.glyphicon-camera:before{content:\"\\e046\"}.glyphicon-font:before{content:\"\\e047\"}.glyphicon-bold:before{content:\"\\e048\"}.glyphicon-italic:before{content:\"\\e049\"}.glyphicon-text-height:before{content:\"\\e050\"}.glyphicon-text-width:before{content:\"\\e051\"}.glyphicon-align-left:before{content:\"\\e052\"}.glyphicon-align-center:before{content:\"\\e053\"}.glyphicon-align-right:before{content:\"\\e054\"}.glyphicon-align-justify:before{content:\"\\e055\"}.glyphicon-list:before{content:\"\\e056\"}.glyphicon-indent-left:before{content:\"\\e057\"}.glyphicon-indent-right:before{content:\"\\e058\"}.glyphicon-facetime-video:before{content:\"\\e059\"}.glyphicon-picture:before{content:\"\\e060\"}.glyphicon-map-marker:before{content:\"\\e062\"}.glyphicon-adjust:before{content:\"\\e063\"}.glyphicon-tint:before{content:\"\\e064\"}.glyphicon-edit:before{content:\"\\e065\"}.glyphicon-share:before{content:\"\\e066\"}.glyphicon-check:before{content:\"\\e067\"}.glyphicon-move:before{content:\"\\e068\"}.glyphicon-step-backward:before{content:\"\\e069\"}.glyphicon-fast-backward:before{content:\"\\e070\"}.glyphicon-backward:before{content:\"\\e071\"}.glyphicon-play:before{content:\"\\e072\"}.glyphicon-pause:before{content:\"\\e073\"}.glyphicon-stop:before{content:\"\\e074\"}.glyphicon-forward:before{content:\"\\e075\"}.glyphicon-fast-forward:before{content:\"\\e076\"}.glyphicon-step-forward:before{content:\"\\e077\"}.glyphicon-eject:before{content:\"\\e078\"}.glyphicon-chevron-left:before{content:\"\\e079\"}.glyphicon-chevron-right:before{content:\"\\e080\"}.glyphicon-plus-sign:before{content:\"\\e081\"}.glyphicon-minus-sign:before{content:\"\\e082\"}.glyphicon-remove-sign:before{content:\"\\e083\"}.glyphicon-ok-sign:before{content:\"\\e084\"}.glyphicon-question-sign:before{content:\"\\e085\"}.glyphicon-info-sign:before{content:\"\\e086\"}.glyphicon-screenshot:before{content:\"\\e087\"}.glyphicon-remove-circle:before{content:\"\\e088\"}.glyphicon-ok-circle:before{content:\"\\e089\"}.glyphicon-ban-circle:before{content:\"\\e090\"}.glyphicon-arrow-left:before{content:\"\\e091\"}.glyphicon-arrow-right:before{content:\"\\e092\"}.glyphicon-arrow-up:before{content:\"\\e093\"}.glyphicon-arrow-down:before{content:\"\\e094\"}.glyphicon-share-alt:before{content:\"\\e095\"}.glyphicon-resize-full:before{content:\"\\e096\"}.glyphicon-resize-small:before{content:\"\\e097\"}.glyphicon-exclamation-sign:before{content:\"\\e101\"}.glyphicon-gift:before{content:\"\\e102\"}.glyphicon-leaf:before{content:\"\\e103\"}.glyphicon-fire:before{content:\"\\e104\"}.glyphicon-eye-open:before{content:\"\\e105\"}.glyphicon-eye-close:before{content:\"\\e106\"}.glyphicon-warning-sign:before{content:\"\\e107\"}.glyphicon-plane:before{content:\"\\e108\"}.glyphicon-calendar:before{content:\"\\e109\"}.glyphicon-random:before{content:\"\\e110\"}.glyphicon-comment:before{content:\"\\e111\"}.glyphicon-magnet:before{content:\"\\e112\"}.glyphicon-chevron-up:before{content:\"\\e113\"}.glyphicon-chevron-down:before{content:\"\\e114\"}.glyphicon-retweet:before{content:\"\\e115\"}.glyphicon-shopping-cart:before{content:\"\\e116\"}.glyphicon-folder-close:before{content:\"\\e117\"}.glyphicon-folder-open:before{content:\"\\e118\"}.glyphicon-resize-vertical:before{content:\"\\e119\"}.glyphicon-resize-horizontal:before{content:\"\\e120\"}.glyphicon-hdd:before{content:\"\\e121\"}.glyphicon-bullhorn:before{content:\"\\e122\"}.glyphicon-bell:before{content:\"\\e123\"}.glyphicon-certificate:before{content:\"\\e124\"}.glyphicon-thumbs-up:before{content:\"\\e125\"}.glyphicon-thumbs-down:before{content:\"\\e126\"}.glyphicon-hand-right:before{content:\"\\e127\"}.glyphicon-hand-left:before{content:\"\\e128\"}.glyphicon-hand-up:before{content:\"\\e129\"}.glyphicon-hand-down:before{content:\"\\e130\"}.glyphicon-circle-arrow-right:before{content:\"\\e131\"}.glyphicon-circle-arrow-left:before{content:\"\\e132\"}.glyphicon-circle-arrow-up:before{content:\"\\e133\"}.glyphicon-circle-arrow-down:before{content:\"\\e134\"}.glyphicon-globe:before{content:\"\\e135\"}.glyphicon-wrench:before{content:\"\\e136\"}.glyphicon-tasks:before{content:\"\\e137\"}.glyphicon-filter:before{content:\"\\e138\"}.glyphicon-briefcase:before{content:\"\\e139\"}.glyphicon-fullscreen:before{content:\"\\e140\"}.glyphicon-dashboard:before{content:\"\\e141\"}.glyphicon-paperclip:before{content:\"\\e142\"}.glyphicon-heart-empty:before{content:\"\\e143\"}.glyphicon-link:before{content:\"\\e144\"}.glyphicon-phone:before{content:\"\\e145\"}.glyphicon-pushpin:before{content:\"\\e146\"}.glyphicon-usd:before{content:\"\\e148\"}.glyphicon-gbp:before{content:\"\\e149\"}.glyphicon-sort:before{content:\"\\e150\"}.glyphicon-sort-by-alphabet:before{content:\"\\e151\"}.glyphicon-sort-by-alphabet-alt:before{content:\"\\e152\"}.glyphicon-sort-by-order:before{content:\"\\e153\"}.glyphicon-sort-by-order-alt:before{content:\"\\e154\"}.glyphicon-sort-by-attributes:before{content:\"\\e155\"}.glyphicon-sort-by-attributes-alt:before{content:\"\\e156\"}.glyphicon-unchecked:before{content:\"\\e157\"}.glyphicon-expand:before{content:\"\\e158\"}.glyphicon-collapse-down:before{content:\"\\e159\"}.glyphicon-collapse-up:before{content:\"\\e160\"}.glyphicon-log-in:before{content:\"\\e161\"}.glyphicon-flash:before{content:\"\\e162\"}.glyphicon-log-out:before{content:\"\\e163\"}.glyphicon-new-window:before{content:\"\\e164\"}.glyphicon-record:before{content:\"\\e165\"}.glyphicon-save:before{content:\"\\e166\"}.glyphicon-open:before{content:\"\\e167\"}.glyphicon-saved:before{content:\"\\e168\"}.glyphicon-import:before{content:\"\\e169\"}.glyphicon-export:before{content:\"\\e170\"}.glyphicon-send:before{content:\"\\e171\"}.glyphicon-floppy-disk:before{content:\"\\e172\"}.glyphicon-floppy-saved:before{content:\"\\e173\"}.glyphicon-floppy-remove:before{content:\"\\e174\"}.glyphicon-floppy-save:before{content:\"\\e175\"}.glyphicon-floppy-open:before{content:\"\\e176\"}.glyphicon-credit-card:before{content:\"\\e177\"}.glyphicon-transfer:before{content:\"\\e178\"}.glyphicon-cutlery:before{content:\"\\e179\"}.glyphicon-header:before{content:\"\\e180\"}.glyphicon-compressed:before{content:\"\\e181\"}.glyphicon-earphone:before{content:\"\\e182\"}.glyphicon-phone-alt:before{content:\"\\e183\"}.glyphicon-tower:before{content:\"\\e184\"}.glyphicon-stats:before{content:\"\\e185\"}.glyphicon-sd-video:before{content:\"\\e186\"}.glyphicon-hd-video:before{content:\"\\e187\"}.glyphicon-subtitles:before{content:\"\\e188\"}.glyphicon-sound-stereo:before{content:\"\\e189\"}.glyphicon-sound-dolby:before{content:\"\\e190\"}.glyphicon-sound-5-1:before{content:\"\\e191\"}.glyphicon-sound-6-1:before{content:\"\\e192\"}.glyphicon-sound-7-1:before{content:\"\\e193\"}.glyphicon-copyright-mark:before{content:\"\\e194\"}.glyphicon-registration-mark:before{content:\"\\e195\"}.glyphicon-cloud-download:before{content:\"\\e197\"}.glyphicon-cloud-upload:before{content:\"\\e198\"}.glyphicon-tree-conifer:before{content:\"\\e199\"}.glyphicon-tree-deciduous:before{content:\"\\e200\"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#428bca;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:\"\"}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media(min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar:before,.btn-toolbar:after{display:table;content:\" \"}.btn-toolbar:after{clear:both}.btn-toolbar:before,.btn-toolbar:after{display:table;content:\" \"}.btn-toolbar:after{clear:both}.btn-toolbar .btn-group{float:left}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group,.btn-toolbar>.btn-group+.btn-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:\" \"}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:\" \"}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-bottom-left-radius:4px;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child>.btn:last-child,.btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;border-collapse:separate;table-layout:fixed}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle=\"buttons\"]>.btn>input[type=\"radio\"],[data-toggle=\"buttons\"]>.btn>input[type=\"checkbox\"]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=\"col-\"]{float:none;padding-right:0;padding-left:0}.input-group .form-control{width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=\"radio\"],.input-group-addon input[type=\"checkbox\"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;white-space:nowrap}.input-group-btn:first-child>.btn{margin-right:-1px}.input-group-btn:last-child>.btn{margin-left:-1px}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-4px}.input-group-btn>.btn:hover,.input-group-btn>.btn:active{z-index:2}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav:before,.nav:after{display:table;content:\" \"}.nav:after{clear:both}.nav:before,.nav:after{display:table;content:\" \"}.nav:after{clear:both}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media(min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media(min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media(min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media(min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}.navbar:before,.navbar:after{display:table;content:\" \"}.navbar:after{clear:both}.navbar:before,.navbar:after{display:table;content:\" \"}.navbar:after{clear:both}@media(min-width:768px){.navbar{border-radius:4px}}.navbar-header:before,.navbar-header:after{display:table;content:\" \"}.navbar-header:after{clear:both}.navbar-header:before,.navbar-header:after{display:table;content:\" \"}.navbar-header:after{clear:both}@media(min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse:before,.navbar-collapse:after{display:table;content:\" \"}.navbar-collapse:after{clear:both}.navbar-collapse:before,.navbar-collapse:after{display:table;content:\" \"}.navbar-collapse:after{clear:both}.navbar-collapse.in{overflow-y:auto}@media(min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-right:0;padding-left:0}}.container>.navbar-header,.container>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media(min-width:768px){.container>.navbar-header,.container>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media(min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media(min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media(min-width:768px){.navbar>.container .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media(min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media(max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media(min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media(min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}@media(min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block}.navbar-form select.form-control{width:auto}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.navbar-form .radio input[type=\"radio\"],.navbar-form .checkbox input[type=\"checkbox\"]{float:none;margin-left:0}}@media(max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media(min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-nav.pull-right>li>.dropdown-menu,.navbar-nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media(min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}@media(max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}@media(max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:\"/\\00a0\"}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#eee}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager:before,.pager:after{display:table;content:\" \"}.pager:after{clear:both}.pager:before,.pager:after{display:table;content:\" \"}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#999;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{line-height:1;color:inherit}.jumbotron p{line-height:1.4}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{display:block;height:auto;max-width:100%;margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-body:before,.panel-body:after{display:table;content:\" \"}.panel-body:after{clear:both}.panel-body:before,.panel-body:after{display:table;content:\" \"}.panel-body:after{clear:both}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0}.panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child th,.panel>.table>tbody:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:last-child>th,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:last-child>td,.panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-group .panel{margin-bottom:0;overflow:hidden;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:auto;overflow-y:scroll}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;z-index:1050;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{min-height:16.428571429px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{padding:19px 20px 20px;margin-top:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:before,.modal-footer:after{display:table;content:\" \"}.modal-footer:after{clear:both}.modal-footer:before,.modal-footer:after{display:table;content:\" \"}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media screen and (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}}.tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:\"\"}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0;content:\" \"}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0;content:\" \"}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0;content:\" \"}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0;content:\" \"}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;height:auto;max-width:100%;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);opacity:.5;filter:alpha(opacity=50)}.carousel-control.left{background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.5) 0),color-stop(rgba(0,0,0,0.0001) 100%));background-image:linear-gradient(to right,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000',endColorstr='#00000000',GradientType=1)}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.0001) 0),color-stop(rgba(0,0,0,0.5) 100%));background-image:linear-gradient(to right,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#80000000',GradientType=1)}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;outline:0;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\\2039'}.carousel-control .icon-next:before{content:'\\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after{display:table;content:\" \"}.clearfix:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,tr.visible-xs,th.visible-xs,td.visible-xs{display:none!important}@media(max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}table.visible-xs.visible-sm{display:table}tr.visible-xs.visible-sm{display:table-row!important}th.visible-xs.visible-sm,td.visible-xs.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block!important}table.visible-xs.visible-md{display:table}tr.visible-xs.visible-md{display:table-row!important}th.visible-xs.visible-md,td.visible-xs.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-xs.visible-lg{display:block!important}table.visible-xs.visible-lg{display:table}tr.visible-xs.visible-lg{display:table-row!important}th.visible-xs.visible-lg,td.visible-xs.visible-lg{display:table-cell!important}}.visible-sm,tr.visible-sm,th.visible-sm,td.visible-sm{display:none!important}@media(max-width:767px){.visible-sm.visible-xs{display:block!important}table.visible-sm.visible-xs{display:table}tr.visible-sm.visible-xs{display:table-row!important}th.visible-sm.visible-xs,td.visible-sm.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block!important}table.visible-sm.visible-md{display:table}tr.visible-sm.visible-md{display:table-row!important}th.visible-sm.visible-md,td.visible-sm.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-sm.visible-lg{display:block!important}table.visible-sm.visible-lg{display:table}tr.visible-sm.visible-lg{display:table-row!important}th.visible-sm.visible-lg,td.visible-sm.visible-lg{display:table-cell!important}}.visible-md,tr.visible-md,th.visible-md,td.visible-md{display:none!important}@media(max-width:767px){.visible-md.visible-xs{display:block!important}table.visible-md.visible-xs{display:table}tr.visible-md.visible-xs{display:table-row!important}th.visible-md.visible-xs,td.visible-md.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}table.visible-md.visible-sm{display:table}tr.visible-md.visible-sm{display:table-row!important}th.visible-md.visible-sm,td.visible-md.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-md.visible-lg{display:block!important}table.visible-md.visible-lg{display:table}tr.visible-md.visible-lg{display:table-row!important}th.visible-md.visible-lg,td.visible-md.visible-lg{display:table-cell!important}}.visible-lg,tr.visible-lg,th.visible-lg,td.visible-lg{display:none!important}@media(max-width:767px){.visible-lg.visible-xs{display:block!important}table.visible-lg.visible-xs{display:table}tr.visible-lg.visible-xs{display:table-row!important}th.visible-lg.visible-xs,td.visible-lg.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}table.visible-lg.visible-sm{display:table}tr.visible-lg.visible-sm{display:table-row!important}th.visible-lg.visible-sm,td.visible-lg.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block!important}table.visible-lg.visible-md{display:table}tr.visible-lg.visible-md{display:table-row!important}th.visible-lg.visible-md,td.visible-lg.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}.hidden-xs{display:block!important}table.hidden-xs{display:table}tr.hidden-xs{display:table-row!important}th.hidden-xs,td.hidden-xs{display:table-cell!important}@media(max-width:767px){.hidden-xs,tr.hidden-xs,th.hidden-xs,td.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm,tr.hidden-xs.hidden-sm,th.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md,tr.hidden-xs.hidden-md,th.hidden-xs.hidden-md,td.hidden-xs.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-xs.hidden-lg,tr.hidden-xs.hidden-lg,th.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg{display:none!important}}.hidden-sm{display:block!important}table.hidden-sm{display:table}tr.hidden-sm{display:table-row!important}th.hidden-sm,td.hidden-sm{display:table-cell!important}@media(max-width:767px){.hidden-sm.hidden-xs,tr.hidden-sm.hidden-xs,th.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-sm,tr.hidden-sm,th.hidden-sm,td.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md,tr.hidden-sm.hidden-md,th.hidden-sm.hidden-md,td.hidden-sm.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-sm.hidden-lg,tr.hidden-sm.hidden-lg,th.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg{display:none!important}}.hidden-md{display:block!important}table.hidden-md{display:table}tr.hidden-md{display:table-row!important}th.hidden-md,td.hidden-md{display:table-cell!important}@media(max-width:767px){.hidden-md.hidden-xs,tr.hidden-md.hidden-xs,th.hidden-md.hidden-xs,td.hidden-md.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-md.hidden-sm,tr.hidden-md.hidden-sm,th.hidden-md.hidden-sm,td.hidden-md.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-md,tr.hidden-md,th.hidden-md,td.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-md.hidden-lg,tr.hidden-md.hidden-lg,th.hidden-md.hidden-lg,td.hidden-md.hidden-lg{display:none!important}}.hidden-lg{display:block!important}table.hidden-lg{display:table}tr.hidden-lg{display:table-row!important}th.hidden-lg,td.hidden-lg{display:table-cell!important}@media(max-width:767px){.hidden-lg.hidden-xs,tr.hidden-lg.hidden-xs,th.hidden-lg.hidden-xs,td.hidden-lg.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-lg.hidden-sm,tr.hidden-lg.hidden-sm,th.hidden-lg.hidden-sm,td.hidden-lg.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-lg.hidden-md,tr.hidden-lg.hidden-md,th.hidden-lg.hidden-md,td.hidden-lg.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-lg,tr.hidden-lg,th.hidden-lg,td.hidden-lg{display:none!important}}.visible-print,tr.visible-print,th.visible-print,td.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}.hidden-print,tr.hidden-print,th.hidden-print,td.hidden-print{display:none!important}}`"
  },
  {
    "path": "app/styles/customizer.css",
    "content": "#customizer-app {\n\tbackground: #e3e3e3;\n\ttop: 0;\n\tright: 0;\n\tleft: 0;\n\tbottom: 0;\n\tposition: absolute;\n}\n\n#customizer-workspace-header {\n\tposition: absolute;\n\tbottom: -12px;\n\tright: -12px;\n\tcolor: #444;\n\theight: 20px;\n\tpadding: 10px;\n\tfont-size: 18px;\n\ttext-shadow: 0px 1px 1px whitesmoke;\n\ttext-align: right;\n}\n\n\n#customizer-workspace {\n\tcolor: black;\n\tposition: absolute;\n\ttop: 100px;\n\tleft: 0;\n\twidth: 380px;\n\tz-index: 1;\n\tbackground: rgba(0, 0, 0, 0.14);\n}\n\n#customizer-workspace.workspace-contracted {\n\twidth: 20px;\n}\n\n#customizer-viewer {\n\tposition: absolute;\n\ttop: 0;\n\tright: 0;\n\tbottom: 0;\n\tleft: 0;\n\tbackground: black;\n\tz-index: 0;\n}\n\n#customizer-header {\n\tposition: absolute;\n\ttop: 0;\n\tright: 0;\n\tleft: 0;\n\theight: 50px;\n\tz-index: 2;\n\tfont-size: 20px;\n\tdisplay: inline-block;\n\tpadding: 20px;\n\tpadding-left: 30px;\n\tfont-color: #222;\n\ttext-shadow: 0px 1px 1px whitesmoke;\n}\n\n.indicator {\n\tmargin-right: 30px;\n}\n\n#customize-header-tag {\n\ttext-transform: uppercase;\n\tfont-size: 13px;\n\tcolor: grey;\n\tfont-weight: bold;\n}\n\n#powered-by {\n\tposition: absolute;\n\tz-index: 2;\n\tright: 0;\n\tbottom: 0;\n\theight: 36px;\n\tpadding: 10px;\n\tfont-size: 12px;\n\tcolor: black;\n\ttext-shadow: 0px 1px 0px grey;\n}\n\n#customize-header-title {\n\tpadding-left: 20px;\n\tfont-size: 24px;\n}\n\n#customizer-header-controls {\n\tpadding: 30px;\n\tposition: absolute;\n\ttop: 0;\n\tright: 0;\n}\n\n.widget {\n\twidth:370px;\n\tmargin: 20px;\n}\n\n.widget .name {\n\tfont-weight: bold;\n\ttext-transform: uppercase;\n\tcolor: #222;\n\tdisplay: inline-block;\n\twidth: 130px;\n\ttext-align: right;\n\tpadding-right: 15px;\n\tfont-size: 11px;\n\ttext-shadow: 0px 1px 1px white;\n}"
  },
  {
    "path": "app/styles/main.css",
    "content": "body { \n\twidth:  100%;\n  \theight: 100%;\n  \tmargin: 0px;\n  \tmargin: 0;\n  \t-webkit-backface-visibility: hidden;\n  }\n\n.row, .col { overflow: hidden; position: absolute; }\n.row { left: 0; right: 0; }\n.col { top: 0; bottom: 0; }\n.scroll-x { overflow-x: auto; }\n.scroll-y { overflow-y: auto; }\n\n.btn-block {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  margin-left: auto;\n  margin-right: auto;\n  display: block;\n  width: 200px;\n  padding-left: 0;\n  padding-right: 0;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\n/*\n * Social Buttons for Bootstrap\n *\n * Copyright 2013-2014 Panayiotis Lipiridis\n * Licensed under the MIT License\n *\n * https://github.com/lipis/bootstrap-social\n */\n.btn-social {\n  position: relative;\n  padding-left: 44px;\n  text-align: left;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n.btn-social :first-child {\n  position: absolute;\n  left: 0;\n  top: 0;\n  bottom: 0;\n  width: 32px;\n  line-height: 34px;\n  font-size: 1.6em;\n  text-align: center;\n  border-right: 1px solid rgba(0, 0, 0, 0.2);\n}\n.btn-social.btn-lg {\n  padding-left: 61px;\n}\n.btn-social.btn-lg :first-child {\n  line-height: 45px;\n  width: 45px;\n  font-size: 1.8em;\n}\n.btn-social.btn-sm {\n  padding-left: 38px;\n}\n.btn-social.btn-sm :first-child {\n  line-height: 28px;\n  width: 28px;\n  font-size: 1.4em;\n}\n.btn-social.btn-xs {\n  padding-left: 30px;\n}\n.btn-social.btn-xs :first-child {\n  line-height: 20px;\n  width: 20px;\n  font-size: 1.2em;\n}\n.btn-social-icon {\n  position: relative;\n  padding-left: 44px;\n  text-align: left;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  border-radius: 2px;\n  height: 34px;\n  width: 34px;\n  padding: 0;\n}\n.btn-social-icon :first-child {\n  position: absolute;\n  left: 0;\n  top: 0;\n  bottom: 0;\n  width: 32px;\n  line-height: 34px;\n  font-size: 1.6em;\n  text-align: center;\n  border-right: 1px solid rgba(0, 0, 0, 0.2);\n}\n.btn-social-icon.btn-lg {\n  padding-left: 61px;\n}\n.btn-social-icon.btn-lg :first-child {\n  line-height: 45px;\n  width: 45px;\n  font-size: 1.8em;\n}\n.btn-social-icon.btn-sm {\n  padding-left: 38px;\n}\n.btn-social-icon.btn-sm :first-child {\n  line-height: 28px;\n  width: 28px;\n  font-size: 1.4em;\n}\n.btn-social-icon.btn-xs {\n  padding-left: 30px;\n}\n.btn-social-icon.btn-xs :first-child {\n  line-height: 20px;\n  width: 20px;\n  font-size: 1.2em;\n}\n.btn-social-icon :first-child {\n  border: none;\n  text-align: center;\n  width: 100% !important;\n}\n.btn-social-icon.btn-lg {\n  height: 45px;\n  width: 45px;\n  padding-left: 0;\n  padding-right: 0;\n}\n.btn-social-icon.btn-sm {\n  height: 30px;\n  width: 30px;\n  padding-left: 0;\n  padding-right: 0;\n}\n.btn-social-icon.btn-xs {\n  height: 22px;\n  width: 22px;\n  padding-left: 0;\n  padding-right: 0;\n}\n\n.btn-facebook {\n  color: #ffffff;\n  background-color: #3b5998;\n  border-color: rgba(0, 0, 0, 0.2);\n}\n.btn-facebook:hover,\n.btn-facebook:focus,\n.btn-facebook:active,\n.btn-facebook.active,\n.open .dropdown-toggle .btn-facebook {\n  color: #ffffff;\n  background-color: #30487b;\n  border-color: rgba(0, 0, 0, 0.2);\n}\n.btn-facebook:active,\n.btn-facebook.active,\n.open .dropdown-toggle .btn-facebook {\n  background-image: none;\n}\n\n.btn-flood {\n  margin-top: 40px;\n  color: #ffffff;\n  background-color: #AAA;\n  border-color: rgba(0, 0, 0, 0.2);\n}\n.btn-flood:hover,\n.btn-flood:focus,\n.btn-flood:active,\n.btn-flood.active,\n.open .dropdown-toggle .btn-flood {\n  color: #ffffff;\n  background-color: #999;\n  border-color: rgba(0, 0, 0, 0.2);\n}\n\n.btn-google-plus {\n  margin-top: 40px;\n  color: #ffffff;\n  background-color: #dd4b39;\n  border-color: rgba(0, 0, 0, 0.2);\n}\n.btn-google-plus:hover,\n.btn-google-plus:focus,\n.btn-google-plus:active,\n.btn-google-plus.active,\n.open .dropdown-toggle .btn-google-plus {\n  color: #ffffff;\n  background-color: #ca3523;\n  border-color: rgba(0, 0, 0, 0.2);\n}\n.btn-google-plus:active,\n.btn-google-plus.active,\n.open .dropdown-toggle .btn-google-plus {\n  background-image: none;\n}\n.btn-google-plus.disabled,\n.btn-google-plus[disabled],\nfieldset[disabled] .btn-google-plus,\n.btn-google-plus.disabled:hover,\n.btn-google-plus[disabled]:hover,\nfieldset[disabled] .btn-google-plus:hover,\n.btn-google-plus.disabled:focus,\n.btn-google-plus[disabled]:focus,\nfieldset[disabled] .btn-google-plus:focus,\n.btn-google-plus.disabled:active,\n.btn-google-plus[disabled]:active,\nfieldset[disabled] .btn-google-plus:active,\n.btn-google-plus.disabled.active,\n.btn-google-plus[disabled].active,\nfieldset[disabled] .btn-google-plus.active {\n  background-color: #dd4b39;\n  border-color: rgba(0, 0, 0, 0.2);\n}\n.btn-google-plus .badge {\n  color: #dd4b39;\n  background-color: #ffffff;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.dropdown-menu {\n\tfont-size: 10px;\n}\n\n.CodeMirror {\n\tfont-family: monospace;\n\theight: auto;\n\tborder: 1px solid rgba(0,0,0,0.2);\n}\n\n.CodeMirror-hints {\n \tz-index: 150;\n\tfont-size: 10px;\n}\n\n.workspace-runner-status {\n\ttop: 90px;\n\tright: 60px;\n\tz-index: 100;\n\tposition: absolute;\n\tbackground: none;\n}\n\n.workspace-search {\n\tbottom: 0px;\n\tleft: 0px;\n\tfont-size: 11px; \n\tposition: absolute;\n\tz-index: 100;\n}\n\n.workspace-tab-function {\n\tfont-style: italic;\n\tfont-family: serif;\n\tcolor: gray;\n\tfont-size: 15px;\n\tpadding-left: 7px;\n}\n\n#workspace-search-input-container {\n\tpadding-left: 10px;\n\tbox-shadow: 0 10px 12px #444;\n}\n\n.workspace-search-container ul {\n\tmax-height: 500px;\n\toverflow-y: scroll;\n\tlist-style: none;\n\tpadding: 0;\n\tmargin: 0;\n}\n\n.workspace-search-container {\n\tcolor: #BBB;\n\tdisplay: inline-block;\n\tbackground-color: #222;\n}\n\n.workspace-search input {\n\tpadding: 0;\n\tmargin: 0;\n\toutline: 0;\n\tfont-size: 11px; \n\theight: 32px;\n\tdisplay:inline-block; \n}\n\n.workspace-search-container:last-child {\n\tborder-right: none;\n}\n\n.workspace-search-button-active {\n\tcolor: #BBB;\n\tbackground-color: #222;\n\tborder-right: 1px solid #333;\n}\n\n.workspace-search-button-active:hover {\n\tcolor: white;\n\tbackground-color: #333;\n}\n\n.workspace-search-button-active:hover i {\n\topacity: 1;\n}\n\n.workspace-search-button-inactive {\n\tcolor: #444;\n}\n\n.workspace-search-button {\n\theight: 32px;\n\tpadding: 8px;\n\tmargin-left: 0;\n\tborder-right: 1px solid #333;\n\tdisplay:inline-block;\n}\n\n.workspace-search input:focus {\n   outline:none;\n}\n\n#present-button {\n\tborder-left: 1px solid #444;\n\tcolor: #444;\n}\n\n.connection {\n\tfill:none; \n\tstroke-width: 3.2;\n\tstroke:#333;\n}\n\n.partial-function-connection {\n\tfill:none; \n\tstroke-width: 2.6;\n\tstroke: white;\n}\n\n.node:hover .node-last-value-container {\n\tdisplay: block;\n\theight: 26px;\n\tbottom: -26px;\n\tpadding: 3px;\n\tborder: 1px solid #999;\n\n\ttransition-delay: 0.3s;\n\t-webkit-transition-delay: 0.3s; /* Safari */\n\ttransition-duration: 0.1s;\n\t-webkit-transition-duration: 0.1s; /* Safari */\n}\n\n.node:hover .node-last-value-container:hover {\n\tright: -100px;\n\tleft: -100px;\n\theight: 60px;\n\tbottom: -60px;\n\toverflow-x: scroll;\n\toverflow-y: scroll;\n}\n\n.node:hover .node-last-value-container:hover .node-last-value {\n\twidth: 100%;\n\tword-wrap: break-word;\n}\n\n.node-failed .node-last-value {\n\tdisplay: none;\n}\n\n.node-failed .node-failure-message {\n\tdisplay: block;\n\twidth: 100%;\n\tcolor: red;\n}\n\n.node-last-value-container {\n\theight: 0;\n\tbottom: 0;\n\tpadding: 0;\n\n\ttransition-duration: 0.2s;\n\t-webkit-transition-duration: 0.2s; /* Safari */\n\n\topacity: 0.8;\n\tposition: absolute;\n\tleft: -1px;\n\tright: -1px;\n\n\tbackground: white;\n\tcolor: #444;\n\n\toverflow-x: hidden;\n\toverflow-y: hidden;\n}\n\n\n#login-failure-message {\n\tpadding: 10px;\n\tmargin: 10px;\n\tbackground-color: #FF7A7A;\n\tcolor: white;\n\tfont-weight: bold;\n}\n\n#extra-menu .menu-element {\n\theight: 38px;\n\twidth: 38px;\n\tfont-size: 14px;\n\tbackground: #222;\n\tborder:none;\n}\n\n#extra-menu #help-button:hover {\n\tcolor: #92d199;\n} \n\n#extra-menu #feedback-button:hover {\n\tcolor: #589cc8;\n} \n\n#feedback-form textarea {\n\tmax-width: 100%;\n}\n\n.node-dropdown-menu .dropdown-header {\n\ttext-transform: uppercase;\n\tfont-size: 9px;\n\tpadding: 2px;\n}\n\n.node-dropown-menu-item {\n\tdisplay: inline-block;\n\tmargin: 5px 0px 5px 10px;\n\tcolor: black;\n}\n\n.node-dropown-menu-item:hover {\n\tcolor: black;\n}\n\n.node-dropdown-menu {\n\tpadding: 10px;\n}\n\n#extra-menu .menu-element:hover {\n\tbackground: #444;\n\tcolor: white;\n}\n\n#extra-menu {\n\tz-index: 99;\n\tposition: absolute;\n\twidth: 38px;\n\ttop: 80px;\n\tright: 0px;\n}\n\n.modal-box p {\n\tfont-style: 12px;\n\tpadding: 5px;\n}\n\n#feedback-sending-message {\n\tdisplay: none;\n\tpadding: 10px;\n\tmargin: 10px;\n\tbackground-color: lightblue;\n\tcolor: white;\n\tfont-weight: bold;\n}\n\n#feedback-success-message {\n\tdisplay: none;\n\tpadding: 10px;\n\tmargin: 10px;\n\tbackground-color: green;\n\tcolor: white;\n\tfont-weight: bold;\n}\n\n.script-add-remove-ports {\n\tfloat: left;\n}\n\n#feedback-failure-message {\n\tdisplay: none;\n\tpadding: 10px;\n\tmargin: 10px;\n\tbackground-color: #FF7A7A;\n\tcolor: white;\n\tfont-weight: bold;\n}\n\n.node-failure-message {\n\tdisplay: none;\n\tpadding: 2px;\n\tleft: 0;\n\tright: 0;\n}\n\n.node-last-value {\n\tdisplay: inline-block;\n\tpadding: 2px;\n\tleft: 0;\n\tright: 0;\n}\n\n.tab-button {\n\tdisplay: inline-block;\n\tpadding: 5px;\n}\n\n.menu-element i {\n\tmargin-left: 2px;\n\tmargin-right: 2px;\n}\n\n.tab-button a {\n\tcolor: grey;\n}\n\n.tab-button:hover a {\n\tcolor: #222;\n}\n\n.tab-button-hilite a {\n\tcolor: black;\n}\n\n#tab-button-container {\n\tmargin-left: auto;\n\tmargin-right: auto;\n\twidth: 300px;\n}\n\n#workspace-browser {\n\tbackground: #e0e0e0;\n\tcolor: #666;\n\tdisplay: none;\n\tz-index: 105;\n\tright: 0;\n\twidth: 200px;\n\tbottom: 0;\n\ttop: 30px;\n}\n\n.workspace-browser-header {\n\tbackground: #DDD;\n\tcolor: #444;\n\tpadding: 10px;\n\tdisplay: block;\n\twidth: 100%;\n\theight: 40px;\n\tborder-bottom: 1px solid #c7bbb1;\n}\n\n.workspace-browser-header:hover {\n\tbackground: white;\n}\n\n#workspace-browser-header-projects {\n\ttop: 0px;\n\tz-index: 1;\n}\n\n#workspace-browser-header-custom-nodes {\n\tbottom: 0px;\n}\n\n.workspace-browser-element-list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding : 0;\n\tbackground: #222;\n}\t\n\n#workspace-browser-projects {\n\ttop: 40px;\n\tbottom: 40px;\n}\n\n#workspace-browser-custom-nodes {\n\tdisplay: none;\n\ttop: 80px;\n\tbottom: 0px;\n}\n\n.workspace-name {\n  pointer-events: none;\n}\n\n.workspace-browser-element-ellipsis {\n\tfloat: right;\n}\n\n.workspace-browser-element-open {\n\tfloat: right;\n\tcolor: #666;\n}\n\n.workspace-browser-element-open:hover {\n\tcolor: white;\n}\n\n.workspace-browser-element {\n\tfont-size: 12px;\n}\n\n.workspace-browser-element-date {\n\tfont-size: 10px;\n}\n\n.workspace-browser-element {\n\tmargin: 0;\n\tpadding: 5px;\n\tpadding-left: 14px;\n\n\tbackground: #333;\n\tcolor: white;\n\tborder-top: solid 1px #444;\n\tborder-bottom: solid 1px #222;\n}\n\n.workspace-browser-header-refresh {\n\tmargin: 5px;\n\tfloat: right;\n}\n\n.workspace-browser-element:hover {\n\tbackground: #444;\n\tcolor: white;\n}\n\n#help {\n\tdisplay: none;\n\tz-index: 100;\n\toverflow: visible;\n}\n\n.help-section {\n\tfont-size: 11px;\n\tdisplay: none;\n\tposition: absolute;\n\tbackground: whitesmoke;\n\tborder: 1px solid #AAA;\n\twidth: 200px;\t\n\tpadding: 10px;\n\tbox-shadow: 1px 1px 10px #444;\n}\n\n.help-section span {\n\tcolor: grey;\n\tfont-size: 13px;\n\tdisplay: block;\n\tpadding-bottom: 8px;\n}\n\n.exit-help-section {\n\tdisplay: inline-block;\n\tfont-size: 12px;\n\tpadding: 2px 10px 2px 30px;\n}\n\n.exit-help {\n\tdisplay: inline-block;\n\tcolor: grey;\n\tpadding: 2px 10px 2px 10px;\n}\n\n.enter-help-section {\n\tbox-shadow: 0 0 10px white;\n\tcolor: white;\n\tposition: absolute;\n\theight: 24px;\n\twidth: 24px;\n\tpadding: 3px;\n\tpadding-left: 8px;\n\tborder-radius: 15px;\n\tbackground: #92d199;\n}\n\n.help-container {\n\tmargin: 30px;\n}\n\n#share .inner-box {\n\tpadding-top: 8px;\n\tpadding-bottom: 15px;\n}\n\n#share .inner-box .label {\n\tfont-weight: bold;\n\tcolor: grey;\n}\n\n#share .is-customizer-checkbox {\n\tpadding: 8px;\n\tmargin: 10px;\n\tmargin-right: 24px;\n\tfont-size: 20px;\n}\n\n.indicator {\n\tborder-radius: 2px;\n\tcolor: white;\n\tpadding: 8px;\n\tfont-size: 14px;\n\ttext-transform: uppercase;\n}\n\n.private {\n\tbackground-color: #666;\n}\n\n.public {\n\tbackground-color: green;\n}\n\n#share .customizer-url {\n\twidth: 100%;\n\tfont-size: 14px;\n\tcolor: black;\n\tpadding: 4px;\n}\n\n#share span {\n\ttext-transform: uppercase;\n\tpadding: 5px;\n\tfont-size: 14px;\n}\n\n#exit-share {\n\tposition: absolute;\n\tright: 10px;\n\ttop: 10px;\n}\n\n.modal {\n\tz-index: 130;\n\tdisplay: none;\n\ttop: 0;\n\tright: 0;\n\tleft: 0;\n\tbottom: 0;\n\tbackground-color: rgba(0,0,0,0.6);\n}\n\n.white-icon {\n\tcolor: white;\n}\n\n.modal-box {\n\tbackground: whitesmoke;\n\tborder: 1px solid #AAA;\n\tposition: relative;\n\tpadding: 18px;\n\ttop: 70px;\n\twidth: 400px;\n\tmargin-left: auto;\n\tmargin-right: auto;\n\tmargin-bottom: auto;\n}\n\n.modal p {\n\tfont-size: 18px;\n\tcolor: #444;\n\tpadding-top: 20px;\n\tpadding-bottom: 10px;\n\ttext-shadow: 0px 1px 0px white;\n}\n\n.modal-box h3 {\n\tcolor: #444;\n\ttext-shadow: 0px 1px 0px white;\n\tfont-size: 35px;\n}\n\n#exit-feedback {\n\tposition: absolute;\n\tright: 10px;\n\ttop: 10px;\n}\n\n#top_container { \n\tz-index: 100;\n\tcolor: black;\n\tfont-size: 11px;\n\ttop: 0;\n\theight: 30px;\n\tbackground: #e3e3e3;\n\twidth: 100%;\n\tborder-bottom: 1px solid #c7bbb1;\n}\n\n#menus {\n\tfloat: right;\n\tpadding-left: 20px;\n\tpadding-top: 10px;\n}\n\n.menu {\n\tpadding-right: 15px;\n\tcolor: gray;\n}\n\n#file span { \n\tfont-weight: 100;\n\tpadding-top: 50px;\n\tmargin-left: 20px;\n}\n\n#bottom-search {\n\n}\n\n.search-container {\n\tz-index: 105;\n\ttop: 40%;\n\tleft: 50%;\n\tmax-height:  500px;\n\tmargin-top: -150px;\n\tmargin-left: -100px;\n\twidth: 130px;\n\tbackground: none;\n}\n\n.search-title {\n\tcolor: white;\n\tpadding: 5px;\n\tmargin: 0px;\n}\n\n.search-list {\n\tmax-height:  300px;\n\toverflow-y: scroll;\n\toverflow-x: hidden;\n\tlist-style: none;\n\tpadding: 0;\n\tmargin: 0;\n}\n\n.search-element {\n\tbackground: #333;\n\tcolor: white;\n\tdisplay: block;\n\twidth: 100%;\n\tmargin: 0;\n\tfont-size: 11px;\n\tborder-top: solid 1px #444;\n\tborder-bottom: solid 1px #222;\n\tpadding: 5px;\n}\n\n.search-element:hover {\n\tbackground: #444;\n}\n\n.library-search-input {\n\tcolor: whitesmoke;\n\tpadding: 10px;\n\twidth: 130px;\n\tbackground: #222;\n\tborder: none;\n\tfont-size: 15px;\n}\n\n.library-search-input:focus {\n    outline:none;\n}\n\n#workspaces {\n\toverflow:hidden; /*hide the scrollbar*/\n}\n\n#viewer {\n\tposition: absolute;\n\ttop: 0px;\n\tbottom: 0px;\n}\n\n.workspace_container {\n\tposition: absolute;\n\ttop: 26px;\n\toverflow: auto;\n\n\t/* hide the scrollbar */\n\tbottom: -18px;\n\tright: -18px;\n}\n\n.menu-element {\n\tcolor: #666;\n\tfont-size: 11px;\n\tfont-weight: bold;\n\theight: 30px;\n\tfloat: right;\n\tpadding: 7px;\n\tdisplay: inline-block;\n\tborder-left: 1px solid #c7bbb1;\n}\n\n.menu-element:hover {\n\tcolor: black;\n\tbackground: #FFF;\n}\n\n#add-workspace-button {\n\tpadding: 5px;\n\tborder-right: 1px solid #c7bbb1;\n}\n\n#add-workspace-button i {\n\tcolor: black;\n\tfont-size: 12px;\n\tpadding-top: 3px;\n}\n\n#add-workspace-select-element {\n\tfloat: left; \n\toverflow: visible;\n\tdisplay: none;\n}\n\n#add-workspace-select-container {\n\tz-index: 200; \n\tposition:relative; \n\ttop: 30px; \n\tleft: -25px; \n\twidth: 80px;\n\tcolor: #DDD\n}\n\n#add-workspace-select-container ul {\n\tbackground: #444; \n\tlist-style: none; \n\tpadding: 0; \n\tmargin: 0;\n}\n\n#add-workspace-select-container li {\n\tpadding: 5px;\n\tbackground: #333;\n\tcolor: white;\n\tborder-top: solid 1px #444;\n\tborder-bottom: solid 1px #222;\n}\n\n#add-workspace-select-container li:hover {\n\tbackground: #444;\n\tcolor: white;\n}\n\n.workspace-browser-button-active {\n\tcolor: black;\n\tbackground: #C6c6c6;\n}\n\n.dim-button {\n\topacity: 0.4;\n}\n\n.dim-button:hover{\n\topacity: 1;\n}\n\n.workspace-tab {\n\tfont-size: 11px;\n\tfloat: left;\n\theight: 30px;\n\tcolor: #e3e3e3;\n\tdisplay: inline-block;\n\tborder-left: 1px solid #c7bbb1;\n}\n\n.workspace-tab i {\n\tcolor: black;\n\tfont-size: 12px;\n}\n\n.workspace-tab input{\n\tborder: none;\n\tmargin: 0px 5px 0px 0px;\n\tpadding: 8px 0 5px 5px;\n\tdisplay: inline-block;\n\tbackground: rgba(0,0,0,0);\n}\n\n.workspace-tab input:focus{\n\toutline: none;\n\tbackground: rgba(0,0,0,0.1);\n}\n\n.current-workspace {\n\tcolor: black;\n\tbackground: #C6c6c6;\n}\n\n.workspace-tab:hover {\n\tcolor: black;\n\tbackground: #FFF;\n}\n\n.workspaces_curtain {\n\tdisplay: none;\n\topacity: 0.4;\n\tbackground: black;\n\ttop: 0;\n\tbottom: 0;\n\tz-index: 95;\n}\n\n.collapsed {\n\topacity: 0;\n}\n\n.marquee {\n\tfill: none;\n\tstroke: black;\n}\n\n.workspace {\n\tz-index: 90;\n\tposition: absolute;\n\twidth: 20000px;\n\theight: 20000px;\n}\n\n.workspace_back {\n\tz-index: 50;\n\tposition: absolute;\n\twidth: 20000px;\n\theight: 20000px;\n}\n\n.workspace_canvas {\n\tposition: absolute;\n\twidth: 20000px;\n\theight: 20000px;\n\tbackground-color: rgba(0,0,0,0.3);\n}\n\n#workspace_hide {\n\tfont-size: 12px;\n\tbottom: 0px;\n\tbackground: #222;\n\tposition: absolute;\n\tz-index: 100;\n\tpadding: 15px;\n}\n\n#workspace_hide span {\n\tfont-weight: bold;\n}\n\n#workspace_hide:hover {\n\tbackground: #333;\n\tcolor: white;\n}\n\n.rightside {\n\tright: 0;\n}\n\n.leftside {\n\tright: 0;\n}\n\n.remove-button {\n\tmargin: 0 10px 0 0;\n}\n\n.node {\n\n\tfont-size: 10px;\n\t-webkit-user-select: none; /* Chrome/Safari */        \n\t-moz-user-select: none; /* Firefox */\n\t-ms-user-select: none; /* IE10+ */\n\n\t/* Rules below not implemented in browsers yet */\n\t-o-user-select: none;\n\tuser-select: none;\n\n\tz-index: 98;\n\n\tposition: absolute;\n\tbackground: #e3e3e3;\n\tpadding-top: 2px;\n\tpadding-bottom: 2px;\n\tcolor: #111;\n\n\tborder: 1px solid #999;\n}\n\n.node a {\n\toutline: 0;\n\tcolor: #a5a5a5;\n\ttext-decoration: none;\n}\n\n.node a:hover{\n\toutline: 0;\n\ttext-decoration: none;\n}\n\n.node a:link{\n\toutline: 0;\n\ttext-decoration: none;\n}\n\n.node a:visited{\n\toutline: 0;\n\ttext-decoration: none;\n}\n\n.node a:active{\n\toutline: 0;\n\ttext-decoration: none;\n}\n\n.currentValue {\n\tcolor:black;\n}\n\n.node-settings {\n\tposition: absolute;\n\tbottom: 0;\n\tright: 0;\n\topacity: 0.3;\n\tpadding: 1px 2px 1px 1px;\n}\n\n.node-settings:hover {\n\topacity: 1;\n}\n\n.toggle-vis {\n\tdisplay: none;\n}\n\n.toggle-vis i {\n\tfont-size: 13px;\n}\n\n.node-number-input {\n\tpadding:2px;\n\tmargin:2px;\n}\n\n.currentValue {\n\tbox-shadow: none;\n}\n\n.currentValue:-moz-placeholder,\n.currentValue:focus {\n    box-shadow:none !important;\n}\n\n.node-evaluating {\n\tcolor: #444;\n\tbackground-color: #C6c6c6;\n}\n\n.node-failed {\n\tbackground-color: #FF7A7A;\n}\n\n.node-selected {\n\tz-index: 99;\n\tborder: 1px solid #0BB;\n\tcolor: black;\n\tbackground-color: #aed1d1;\n}\n\n.node-data-container {\n\tcolor: #555;\n\tfont-weight: bold;\n\tdisplay: inline-block;\n\tfloat: left;\n\tpadding: 5px 10px 14px 5px;\n}\n\n.node-data-container input {\n\tfont-family: monospace;\n\tfont-weight: normal;\n}\n\n.watch-data-container{\n\tmax-width: 300px;\n\tmax-height: 200px;\n\tmargin: 0px 5px 0px 10px;\n\tpadding: 2px;\n\tcolor: black;\n\toverflow-y: scroll;\n\toverflow-x: scroll;\n\tbackground: #f6f6f6;\n\tborder: 1px solid #BBB;\n}\n\n.watch-data-container pre {\n\tpadding: none;\n\tmargin: none;\n\ttext-align: left;\n}\n\n.num-data-container input{\n\twidth: 60px;\n\tmargin-left: 5px;\n}\n\n.input-node {\n\tbackground: #f7e5a3;\n}\n\n.output-node {\n\tbackground: #f7e5a3;\n}\n\n.node-inputs, .node-outputs {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n\tdisplay: inline-block;\n\tborder-bottom: 1px solid rgba(0,0,0,0.2);\n\tfloat: left;\n}\n\n.node-outputs {\n\tmargin-bottom: 8px; /* particularly useful for node output collections */\n}\n\n.node-inputs-extra {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n\tdisplay: inline-block;\n\tfloat: left;\n}\n\n.node-port-extra {\n\tpadding: 5px;\n\tmargin: 0;\n\tcolor: #AAA;\n\tborder: 1px solid rgba(0,0,0,0);\n\tborder-bottom: none;\n}\n\n.node-port-extra:hover {\n\tcolor: #FFF;\n}\n\n.node-port {\n\tpadding: 5px;\n\tmargin: 0;\n\n\tborder: 1px solid rgba(0,0,0,0.2);\n\tborder-bottom: none;\n}\n\n.node-port:hover {\n\tcolor: black;\n\tbackground: #FFF;\n}\n\n.node-port-output {\n\tborder-right: none;\n}\n\n.node-port-input {\n\tborder-left: none;\n}\n\nbody {\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.btn-group-xs {\n\tfont-size: 20px;\n}\n\n/*!\n * jQuery UI Slider @VERSION\n * http://jqueryui.com\n *\n * Copyright 2013 jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Slider#theming\n */\n.ui-slider {\n\tposition: relative;\n\ttext-align: left;\n}\n.ui-slider .ui-slider-handle {\n\tposition: absolute;\n\tz-index: 2;\n\twidth: 1.2em;\n\theight: 1.2em;\n\tcursor: default;\n}\n.ui-slider .ui-slider-range {\n\tposition: absolute;\n\tz-index: 1;\n\tfont-size: .7em;\n\tdisplay: block;\n\tborder: 0;\n\tbackground-position: 0 0;\n}\n\n/* For IE8 - See #6727 */\n.ui-slider.ui-state-disabled .ui-slider-handle,\n.ui-slider.ui-state-disabled .ui-slider-range {\n\tfilter: inherit;\n}\n\n.ui-slider-horizontal {\n\theight: .8em;\n}\n.ui-slider-horizontal .ui-slider-handle {\n\ttop: -.3em;\n\tmargin-left: -.6em;\n}\n.ui-slider-horizontal .ui-slider-range {\n\ttop: 0;\n\theight: 100%;\n}\n.ui-slider-horizontal .ui-slider-range-min {\n\tleft: 0;\n}\n.ui-slider-horizontal .ui-slider-range-max {\n\tright: 0;\n}\n\n.ui-slider-vertical {\n\twidth: .8em;\n\theight: 100px;\n}\n.ui-slider-vertical .ui-slider-handle {\n\tleft: -.3em;\n\tmargin-left: 0;\n\tmargin-bottom: -.6em;\n}\n.ui-slider-vertical .ui-slider-range {\n\tleft: 0;\n\twidth: 100%;\n}\n.ui-slider-vertical .ui-slider-range-min {\n\tbottom: 0;\n}\n.ui-slider-vertical .ui-slider-range-max {\n\ttop: 0;\n}\n"
  },
  {
    "path": "bower.json",
    "content": "{\n  \"name\": \"flood\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"jquery\": \"1.9.1\",\n    \"requirejs\": \"~2.1.5\",\n    \"requirejs-text\": \"~2.0.5\",\n    \"backbone-amd\": \"~1.0.0\",\n    \"almond\": \"0.2.6\",\n    \"bootstrap\": \"3.0.3\",\n    \"underscore-amd\": \"~1.4.4\",\n    \"threejs\": \"r67\",\n    \"jquery.ui\": \"1.10.3\",\n    \"listjs\": \"1.0.0\",\n    \"modernizr\": \"~2.6.2\",\n    \"q\": \"1.0\",\n    \"jqueryui-touch-punch\": \"furf/jquery-ui-touch-punch\",\n    \"pace\": \"0.5.1\",\n    \"components-font-awesome\": \"4.3.0\",\n    \"hammerjs\": \"~2.0.4\",\n    \"fastclick\": \"~1.0.3\",\n    \"FileSaver\": \"eliGrey/FileSaver.js\",\n    \"CodeMirror\": \"~5.3.0\"\n  },\n  \"devDependencies\": {}\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"flood\",\n  \"version\": \"0.0.4\",\n  \"description\": \"A visual programming language for JavaScript, based on Scheme\",\n  \"dependencies\": {\n    \n  },\n  \"devDependencies\": {\n    \"grunt-node-webkit-builder\": \"~0.1.13\",\n    \"grunt\": \"0.4.2\",\n    \"grunt-processhtml\": \"~0.2.6\",\n    \"grunt-contrib-copy\": \"0.4.1\",\n    \"grunt-contrib-concat\": \"0.3.0\",\n    \"grunt-contrib-uglify\": \"0.2.7\",\n    \"grunt-contrib-compass\": \"0.7.0\",\n    \"grunt-contrib-jshint\": \"0.7.2\",\n    \"grunt-contrib-cssmin\": \"0.7.0\",\n    \"grunt-contrib-connect\": \"0.3.0\",\n    \"grunt-contrib-clean\": \"0.5.0\",\n    \"grunt-contrib-imagemin\": \"0.4.0\",\n    \"grunt-contrib-livereload\": \"0.1.2\",\n    \"grunt-mocha\": \"0.4.7\",\n    \"grunt-bower-requirejs\": \"0.8.0\",\n    \"grunt-requirejs\": \"0.4.0\",\n    \"grunt-regarde\": \"0.1.1\",\n    \"grunt-open\": \"0.2.2\",\n    \"matchdep\": \"0.3.0\",\n    \"amdefine\": \">=0.0.5\",\n    \"webworker\": \"*\"\n  },\n  \"engines\": {\n    \"node\": \">=0.10.0\"\n  }\n\n}\n"
  },
  {
    "path": "server/.gitignore",
    "content": "lib-cov\n*.seed\n*.log\n*.csv\n*.dat\n*.out\n*.pid\n*.gz\n*.swp\n\npids\nlogs\nresults\ntmp\n\nnpm-debug.log\nnode_modules\n.idea\n*.iml\n.DS_Store\nThumbs.db\n\npublic/css/styles.css\n\nbuiltAssets\n\nssl\n"
  },
  {
    "path": "server/.travis.yml",
    "content": "language: node_js\n\nservices:\n  - mongodb\n\nnode_js:\n  - '0.10'"
  },
  {
    "path": "server/app.js",
    "content": "/**\n * Module dependencies.\n */\n\nvar express = require('express');\nvar cookieParser = require('cookie-parser');\nvar compress = require('compression');\nvar session = require('express-session');\nvar bodyParser = require('body-parser');\nvar logger = require('morgan');\nvar errorHandler = require('errorhandler');\n// var csrf = require('csurf');\nvar methodOverride = require('method-override');\n\nvar MongoStore = require('connect-mongo')({ session: session });\nvar flash = require('express-flash');\nvar path = require('path');\nvar mongoose = require('mongoose');\nvar passport = require('passport');\nvar expressValidator = require('express-validator');\nvar connectAssets = require('connect-assets');\nvar https = require('https');\nvar http = require('http');\nvar fs = require('fs');\n\n/**\n * Load controllers.\n */\n\nvar feedbackController = require('./controllers/feedback');\nvar floodController = require('./controllers/flood');\nvar homeController = require('./controllers/home');\nvar userController = require('./controllers/user');\nvar apiController = require('./controllers/api');\nvar contactController = require('./controllers/contact');\n\n/**\n * API keys + Passport configuration.\n */\n\nvar secrets = require('./config/secrets');\nvar passportConf = require('./config/passport');\n\n/**\n * Create Express server.\n */\n\nvar app = express();\n\n/**\n * Mongoose configuration.\n */\n\nmongoose.connect(secrets.db);\nmongoose.connection.on('error', function() {\n  console.error('✗ MongoDB Connection Error. Please make sure MongoDB is running.');\n});\n\n/**\n * Express configuration.\n */\nvar hour = 3600000;\nvar day = hour * 24;\nvar week = day * 7;\n\napp.set('port', process.env.PORT || 3000);\napp.set('views', path.join(__dirname, 'views'));\napp.set('view engine', 'jade');\napp.use(connectAssets({\n  paths: ['public/css', 'public/js'],\n  helperContext: app.locals\n}));\napp.use(compress());\napp.use(logger('dev'));\napp.use(bodyParser.json());\napp.use(bodyParser.urlencoded());\napp.use(expressValidator());\napp.use(methodOverride());\napp.use(cookieParser());\napp.use(session({\n  secret: secrets.sessionSecret,\n  store: new MongoStore({\n    url: secrets.db,\n    auto_reconnect: true\n  })\n}));\n// app.use(csrf());\napp.use(passport.initialize());\napp.use(passport.session());\napp.use(function(req, res, next) {\n  res.locals.user = req.user;\n  // res.locals._csrf = req.csrfToken();\n  res.locals.secrets = secrets;\n  next();\n});\napp.use(flash());\n\nvar staticFolder = process.env.FLOOD_STATIC || '../app';\napp.use(express.static(path.join(__dirname, staticFolder )));\napp.use(function(req, res, next) {\n  // Keep track of previous URL\n  if (req.method !== 'GET') return next();\n  var path = req.path.split('/')[1];\n  if (/(auth|login|logout|signup)$/i.test(path)) return next();\n  req.session.returnTo = req.path;\n  next();\n});\n\n/**\n * Application routes.\n */\n\n// flood routes\n\n// customizer (experimental)\napp.get('/customize-:id',function(req,res){\n   var fileStream = fs.createReadStream(staticFolder + '/customizer.html');\n    fileStream.on('open', function () {\n        fileStream.pipe(res);\n    });\n});\n\napp.get('/custdata/:id', floodController.getCustomizerWorkspace);\n\napp.get('/mys', floodController.getMySession);\napp.put('/mys', floodController.putMySession);\napp.get('/nws', floodController.getNewWorkspace );\n\napp.get('/ws', floodController.getWorkspaces);\n\napp.get('/ws/:id', floodController.getWorkspace);\napp.put('/ws/:id', floodController.putWorkspace);\n\napp.get('/', homeController.index);\n\napp.get('/email', userController.getEmail );\n\napp.post('/feedback', feedbackController.postFeedback );\n\napp.get('/login', userController.getLogin);\napp.get('/login2', userController.getLogin);\napp.post('/login', userController.postLogin);\napp.get('/logout', userController.logout);\napp.get('/forgot', userController.getForgot);\napp.post('/forgot', userController.postForgot);\napp.get('/reset/:token', userController.getReset);\napp.post('/reset/:token', userController.postReset);\napp.get('/signup', userController.getSignup);\napp.post('/signup', userController.postSignup);\napp.get('/contact', contactController.getContact);\napp.post('/contact', contactController.postContact);\napp.post('/contact', contactController.postContact);\napp.get('/account', passportConf.isAuthenticated, userController.getAccount);\napp.post('/account/profile', passportConf.isAuthenticated, userController.postUpdateProfile);\napp.post('/account/password', passportConf.isAuthenticated, userController.postUpdatePassword);\napp.post('/account/delete', passportConf.isAuthenticated, userController.postDeleteAccount);\napp.get('/account/unlink/:provider', passportConf.isAuthenticated, userController.getOauthUnlink);\n\napp.get('/api', apiController.getApi);\napp.get('/api/lastfm', apiController.getLastfm);\napp.get('/api/nyt', apiController.getNewYorkTimes);\napp.get('/api/aviary', apiController.getAviary);\napp.get('/api/paypal', apiController.getPayPal);\napp.get('/api/paypal/success', apiController.getPayPalSuccess);\napp.get('/api/paypal/cancel', apiController.getPayPalCancel);\napp.get('/api/steam', apiController.getSteam);\napp.get('/api/scraping', apiController.getScraping);\napp.get('/api/twilio', apiController.getTwilio);\napp.post('/api/twilio', apiController.postTwilio);\napp.get('/api/clockwork', apiController.getClockwork);\napp.post('/api/clockwork', apiController.postClockwork);\napp.get('/api/foursquare', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getFoursquare);\napp.get('/api/tumblr', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getTumblr);\napp.get('/api/facebook', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getFacebook);\napp.get('/api/github', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getGithub);\napp.get('/api/twitter', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getTwitter);\napp.get('/api/venmo', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getVenmo);\napp.post('/api/venmo', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.postVenmo);\napp.get('/api/linkedin', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getLinkedin);\n\n/**\n * OAuth routes for sign-in.\n */\n\napp.get('/auth/facebook', passport.authenticate('facebook', { scope: ['email', 'user_location'] }));\napp.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/login' }), function(req, res) {\n  res.redirect('/app.html');\n});\napp.get('/auth/github', passport.authenticate('github'));\napp.get('/auth/github/callback', passport.authenticate('github', { failureRedirect: '/login' }), function(req, res) {\n  res.redirect(req.session.returnTo || '/');\n});\napp.get('/auth/google', passport.authenticate('google', { scope: 'profile email' }));\napp.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/login' }), function(req, res) {\n  res.redirect('/app.html');\n});\napp.get('/auth/twitter', passport.authenticate('twitter'));\napp.get('/auth/twitter/callback', passport.authenticate('twitter', { failureRedirect: '/login' }), function(req, res) {\n  res.redirect(req.session.returnTo || '/');\n});\napp.get('/auth/linkedin', passport.authenticate('linkedin', { state: 'SOME STATE' }));\napp.get('/auth/linkedin/callback', passport.authenticate('linkedin', { failureRedirect: '/login' }), function(req, res) {\n  res.redirect(req.session.returnTo || '/');\n});\n\n/**\n * OAuth routes for API examples that require authorization.\n */\n\napp.get('/auth/foursquare', passport.authorize('foursquare'));\napp.get('/auth/foursquare/callback', passport.authorize('foursquare', { failureRedirect: '/api' }), function(req, res) {\n  res.redirect('/api/foursquare');\n});\napp.get('/auth/tumblr', passport.authorize('tumblr'));\napp.get('/auth/tumblr/callback', passport.authorize('tumblr', { failureRedirect: '/api' }), function(req, res) {\n  res.redirect('/api/tumblr');\n});\napp.get('/auth/venmo', passport.authorize('venmo', { scope: 'make_payments access_profile access_balance access_email access_phone' }));\napp.get('/auth/venmo/callback', passport.authorize('venmo', { failureRedirect: '/api' }), function(req, res) {\n  res.redirect('/api/venmo');\n});\n\n\n// 404 error handler\napp.use(function(req, res) {\n  res.status(404);\n  res.render('404');\n});\n\n// 500 error handler\napp.use(errorHandler());\n\n/**\n * Start Express server.\n */\n\nvar keyfn = 'ssl/server.key';\nvar crtfn = 'ssl/server.crt';\nvar intafn = 'ssl/int_ssl_a.pem';\nvar intbfn = 'ssl/int_ssl_b.pem';\nvar intcfn = 'ssl/int_ssl_c.pem';\n\nif ( fs.existsSync( keyfn ) && fs.existsSync( crtfn ) \n  && fs.existsSync( intafn ) && fs.existsSync( intbfn ) && fs.existsSync( intcfn )){\n\n  var key = fs.readFileSync(keyfn, 'utf8');\n  var crt = fs.readFileSync(crtfn, 'utf8');\n  var inta = fs.readFileSync(intafn, 'utf8');\n  var intb = fs.readFileSync(intbfn, 'utf8');\n  var intc = fs.readFileSync(intcfn, 'utf8');\n\n  var cred = { key: key, cert: crt, ca: [ inta, intb, intc ] };\n\n  https.createServer(cred, app).listen(443, function() {\n    console.log(\"✔ Secure Express server listening on port %d in %s mode\", 443, app.get('env'));\n  });\n\n}\n\napp.listen( app.get('port'), function() {\n  console.log(\"✔ Express server listening on port %d in %s mode\", app.get('port'), app.get('env'));\n});\n\nmodule.exports = app;\n"
  },
  {
    "path": "server/cluster_app.js",
    "content": "/**\n * Module dependencies.\n */\n\nvar os = require('os');\nvar cluster = require('cluster');\n\n/**\n * Cluster setup.\n */\n\n// Setup the cluster to use app.js\ncluster.setupMaster({\n  exec: 'app.js'\n});\n\n// Listen for dying workers\ncluster.on('exit', function(worker) {\n  console.log('Worker ' + worker.id + ' died');\n  // Replace the dead worker\n  cluster.fork();\n});\n\n// Fork a worker for each available CPU\nfor (var i = 0; i < os.cpus().length; i++) {\n  cluster.fork();\n}\n"
  },
  {
    "path": "server/config/passport.js",
    "content": "var _ = require('underscore');\nvar passport = require('passport');\nvar LocalStrategy = require('passport-local').Strategy;\nvar FacebookStrategy = require('passport-facebook').Strategy;\nvar TwitterStrategy = require('passport-twitter').Strategy;\nvar GitHubStrategy = require('passport-github').Strategy;\nvar GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;\nvar LinkedInStrategy = require('passport-linkedin-oauth2').Strategy;\nvar OAuthStrategy = require('passport-oauth').OAuthStrategy; // Tumblr\nvar OAuth2Strategy = require('passport-oauth').OAuth2Strategy; // Venmo, Foursquare\nvar User = require('../models/User');\nvar secrets = require('./secrets');\n\npassport.serializeUser(function(user, done) {\n  done(null, user.id);\n});\n\npassport.deserializeUser(function(id, done) {\n  User.findById(id, function(err, user) {\n    done(err, user);\n  });\n});\n\n/**\n * Sign in using Email and Password.\n */\n\npassport.use(new LocalStrategy({ usernameField: 'email' }, function(email, password, done) {\n  User.findOne({ email: email }, function(err, user) {\n    if (!user) return done(null, false, { message: 'Email ' + email + ' not found'});\n    user.comparePassword(password, function(err, isMatch) {\n      if (isMatch) {\n        return done(null, user);\n      } else {\n        return done(null, false, { message: 'Invalid email or password.' });\n      }\n    });\n  });\n}));\n\n/**\n * OAuth Strategy Overview\n *\n * - User is already logged in.\n *   - Check if there is an existing account with a provider id or email.\n *     - If there is, return an error message. (Account merging not supported)\n *     - Else link new OAuth account with currently logged-in user.\n * - User is not logged in.\n *   - Check if it's a returning user.\n *     - If returning user, sign in and we are done.\n *     - Else check if there is an existing account with user's email.\n *       - If there is, return an error message.\n *       - Else create a new account.\n */\n\n/**\n * Sign in with Facebook.\n */\n\npassport.use(new FacebookStrategy(secrets.facebook, function(req, accessToken, refreshToken, profile, done) {\n  if (req.user) {\n    User.findOne({ $or: [{ facebook: profile.id }, { email: profile.email }] }, function(err, existingUser) {\n      if (existingUser) {\n        req.flash('errors', { msg: 'There is already a Facebook account that belongs to you. Sign in with that account or delete it, then link it with your current account.' });\n        done(err);\n      } else {\n        User.findById(req.user.id, function(err, user) {\n          user.facebook = profile.id;\n          user.tokens.push({ kind: 'facebook', accessToken: accessToken });\n          user.profile.name = user.profile.name || profile.displayName;\n          user.profile.gender = user.profile.gender || profile._json.gender;\n          user.profile.picture = user.profile.picture || 'https://graph.facebook.com/' + profile.id + '/picture?type=large';\n          user.save(function(err) {\n            req.flash('info', { msg: 'Facebook account has been linked.' });\n            done(err, user);\n          });\n        });\n      }\n    });\n  } else {\n    User.findOne({ facebook: profile.id }, function(err, existingUser) {\n      if (existingUser) return done(null, existingUser);\n      User.findOne({ email: profile._json.email }, function(err, existingEmailUser) {\n        if (existingEmailUser) {\n          req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with Facebook manually from Account Settings.' });\n          done(err);\n        } else {\n          var user = new User();\n          user.email = profile._json.email;\n          user.facebook = profile.id;\n          user.tokens.push({ kind: 'facebook', accessToken: accessToken });\n          user.profile.name = profile.displayName;\n          user.profile.gender = profile._json.gender;\n          user.profile.picture = 'https://graph.facebook.com/' + profile.id + '/picture?type=large';\n          user.profile.location = (profile._json.location) ? profile._json.location.name : '';\n          user.save(function(err) {\n            done(err, user);\n          });\n        }\n      });\n    });\n  }\n}));\n\n/**\n * Sign in with GitHub.\n */\n\npassport.use(new GitHubStrategy(secrets.github, function(req, accessToken, refreshToken, profile, done) {\n  if (req.user) {\n    User.findOne({ $or: [{ github: profile.id }, { email: profile.email }] }, function(err, existingUser) {\n      if (existingUser) {\n        req.flash('errors', { msg: 'There is already a GitHub account that belongs to you. Sign in with that account or delete it, then link it with your current account.' });\n        done(err);\n      } else {\n        User.findById(req.user.id, function(err, user) {\n          user.github = profile.id;\n          user.tokens.push({ kind: 'github', accessToken: accessToken });\n          user.profile.name = user.profile.name || profile.displayName;\n          user.profile.picture = user.profile.picture || profile._json.avatar_url;\n          user.profile.location = user.profile.location || profile._json.location;\n          user.profile.website = user.profile.website || profile._json.blog;\n          user.save(function(err) {\n            req.flash('info', { msg: 'GitHub account has been linked.' });\n            done(err, user);\n          });\n        });\n      }\n    });\n  } else {\n    User.findOne({ github: profile.id }, function(err, existingUser) {\n      if (existingUser) return done(null, existingUser);\n      User.findOne({ email: profile._json.email }, function(err, existingEmailUser) {\n        if (existingEmailUser) {\n          req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with GitHub manually from Account Settings.' });\n          done(err);\n        } else {\n          var user = new User();\n          user.email = profile._json.email;\n          user.github = profile.id;\n          user.tokens.push({ kind: 'github', accessToken: accessToken });\n          user.profile.name = profile.displayName;\n          user.profile.picture = profile._json.avatar_url;\n          user.profile.location = profile._json.location;\n          user.profile.website = profile._json.blog;\n          user.save(function(err) {\n            done(err, user);\n          });\n        }\n      });\n    });\n  }\n}));\n\n/**\n * Sign in with Twitter.\n */\n\npassport.use(new TwitterStrategy(secrets.twitter, function(req, accessToken, tokenSecret, profile, done) {\n  if (req.user) {\n    User.findOne({ twitter: profile.id }, function(err, existingUser) {\n      if (existingUser) {\n        req.flash('errors', { msg: 'There is already a Twitter account that belongs to you. Sign in with that account or delete it, then link it with your current account.' });\n        done(err);\n      } else {\n        User.findById(req.user.id, function(err, user) {\n          user.twitter = profile.id;\n          user.tokens.push({ kind: 'twitter', accessToken: accessToken, tokenSecret: tokenSecret });\n          user.profile.name = user.profile.name || profile.displayName;\n          user.profile.location = user.profile.location || profile._json.location;\n          user.profile.picture = user.profile.picture || profile._json.profile_image_url;\n          user.save(function(err) {\n            req.flash('info', { msg: 'Twitter account has been linked.' });\n            done(err, user);\n          });\n        });\n      }\n    });\n\n  } else {\n    User.findOne({ twitter: profile.id }, function(err, existingUser) {\n      if (existingUser) return done(null, existingUser);\n      var user = new User();\n      // Twitter will not provide an email address.  Period.\n      // But a person’s twitter username is guaranteed to be unique\n      // so we can \"fake\" a twitter email address as follows:\n      user.email = profile.username + \"@twitter.com\";\n      user.twitter = profile.id;\n      user.tokens.push({ kind: 'twitter', accessToken: accessToken, tokenSecret: tokenSecret });\n      user.profile.name = profile.displayName;\n      user.profile.location = profile._json.location;\n      user.profile.picture = profile._json.profile_image_url;\n      user.save(function(err) {\n        done(err, user);\n      });\n    });\n  }\n}));\n\n/**\n * Sign in with Google.\n */\n\npassport.use(new GoogleStrategy(secrets.google, function(req, accessToken, refreshToken, profile, done) {\n  if (req.user) {\n    User.findOne({ $or: [{ google: profile.id }, { email: profile.email }] }, function(err, existingUser) {\n      if (existingUser) {\n        req.flash('errors', { msg: 'There is already a Google account that belongs to you. Sign in with that account or delete it, then link it with your current account.' });\n        done(err);\n      } else {\n        User.findById(req.user.id, function(err, user) {\n          user.google = profile.id;\n          user.tokens.push({ kind: 'google', accessToken: accessToken });\n          user.profile.name = user.profile.name || profile.displayName;\n          user.profile.gender = user.profile.gender || profile._json.gender;\n          user.profile.picture = user.profile.picture || profile._json.picture;\n          user.save(function(err) {\n            req.flash('info', { msg: 'Google account has been linked.' });\n            done(err, user);\n          });\n        });\n      }\n    });\n  } else {\n    User.findOne({ google: profile.id }, function(err, existingUser) {\n      if (existingUser) return done(null, existingUser);\n      User.findOne({ email: profile._json.email }, function(err, existingEmailUser) {\n        if (existingEmailUser) {\n          req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with Google manually from Account Settings.' });\n          done(err);\n        } else {\n          var user = new User();\n          user.email = profile._json.email;\n          user.google = profile.id;\n          user.tokens.push({ kind: 'google', accessToken: accessToken });\n          user.profile.name = profile.displayName;\n          user.profile.gender = profile._json.gender;\n          user.profile.picture = profile._json.picture;\n          user.save(function(err) {\n            done(err, user);\n          });\n        }\n      });\n    });\n  }\n}));\n\n/**\n * Sign in with LinkedIn.\n */\n\npassport.use(new LinkedInStrategy(secrets.linkedin, function(req, accessToken, refreshToken, profile, done) {\n  if (req.user) {\n    User.findOne({ $or: [\n      { linkedin: profile.id },\n      { email: profile._json.emailAddress }\n    ] }, function(err, existingUser) {\n      if (existingUser) {\n        req.flash('errors', { msg: 'There is already a LinkedIn account that belongs to you. Sign in with that account or delete it, then link it with your current account.' });\n        done(err);\n      } else {\n        User.findById(req.user.id, function(err, user) {\n          user.linkedin = profile.id;\n          user.tokens.push({ kind: 'linkedin', accessToken: accessToken });\n          user.profile.name = user.profile.name || profile.displayName;\n          user.profile.location = user.profile.location || profile._json.location.name;\n          user.profile.picture = user.profile.picture || profile._json.pictureUrl;\n          user.profile.website = user.profile.website || profile._json.publicProfileUrl;\n          user.save(function(err) {\n            req.flash('info', { msg: 'LinkedIn account has been linked.' });\n            done(err, user);\n          });\n        });\n      }\n    });\n  } else {\n    User.findOne({ linkedin: profile.id }, function(err, existingUser) {\n      if (existingUser) return done(null, existingUser);\n      User.findOne({ email: profile._json.emailAddress }, function(err, existingEmailUser) {\n        if (existingEmailUser) {\n          req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with LinkedIn manually from Account Settings.' });\n          done(err);\n        } else {\n          var user = new User();\n          user.linkedin = profile.id;\n          user.tokens.push({ kind: 'linkedin', accessToken: accessToken });\n          user.email = profile._json.emailAddress;\n          user.profile.name = profile.displayName;\n          user.profile.location = profile._json.location.name;\n          user.profile.picture = profile._json.pictureUrl;\n          user.profile.website = profile._json.publicProfileUrl;\n          user.save(function(err) {\n            done(err, user);\n          });\n        }\n      });\n    });\n  }\n}));\n\n/**\n * Tumblr API\n * Uses OAuth 1.0a Strategy.\n */\n\npassport.use('tumblr', new OAuthStrategy({\n    requestTokenURL: 'http://www.tumblr.com/oauth/request_token',\n    accessTokenURL: 'http://www.tumblr.com/oauth/access_token',\n    userAuthorizationURL: 'http://www.tumblr.com/oauth/authorize',\n    consumerKey: secrets.tumblr.consumerKey,\n    consumerSecret: secrets.tumblr.consumerSecret,\n    callbackURL: secrets.tumblr.callbackURL,\n    passReqToCallback: true\n  },\n  function(req, token, tokenSecret, profile, done) {\n    User.findById(req.user._id, function(err, user) {\n      user.tokens.push({ kind: 'tumblr', accessToken: token, tokenSecret: tokenSecret });\n      user.save(function(err) {\n        done(err, user);\n      });\n    });\n  }\n));\n\n/**\n * Foursquare API\n * Uses OAuth 2.0 Strategy.\n */\n\npassport.use('foursquare', new OAuth2Strategy({\n    authorizationURL: 'https://foursquare.com/oauth2/authorize',\n    tokenURL: 'https://foursquare.com/oauth2/access_token',\n    clientID: secrets.foursquare.clientId,\n    clientSecret: secrets.foursquare.clientSecret,\n    callbackURL: secrets.foursquare.redirectUrl,\n    passReqToCallback: true\n  },\n  function(req, accessToken, refreshToken, profile, done) {\n    User.findById(req.user._id, function(err, user) {\n      user.tokens.push({ kind: 'foursquare', accessToken: accessToken });\n      user.save(function(err) {\n        done(err, user);\n      });\n    });\n  }\n));\n\n/**\n * Venmo API\n * Uses OAuth 2.0 Strategy.\n */\n\npassport.use('venmo', new OAuth2Strategy({\n    authorizationURL: 'https://api.venmo.com/v1/oauth/authorize',\n    tokenURL: 'https://api.venmo.com/v1/oauth/access_token',\n    clientID: secrets.venmo.clientId,\n    clientSecret: secrets.venmo.clientSecret,\n    callbackURL: secrets.venmo.redirectUrl,\n    passReqToCallback: true\n  },\n  function(req, accessToken, refreshToken, profile, done) {\n    User.findById(req.user._id, function(err, user) {\n      user.tokens.push({ kind: 'venmo', accessToken: accessToken });\n      user.save(function(err) {\n        done(err, user);\n      });\n    });\n  }\n));\n\n/**\n * Login Required middleware.\n */\n\nexports.isAuthenticated = function(req, res, next) {\n  if (req.isAuthenticated()) return next();\n  res.redirect('/login');\n};\n\n/**\n * Authorization Required middleware.\n */\n\nexports.isAuthorized = function(req, res, next) {\n  var provider = req.path.split('/').slice(-1)[0];\n  if (_.findWhere(req.user.tokens, { kind: provider })) next();\n  else res.redirect('/auth/' + provider);\n};\n"
  },
  {
    "path": "server/config/secrets.js",
    "content": "module.exports = {\n  db: process.env.MONGODB|| 'mongodb://localhost:27017/test',\n\n  sessionSecret: process.env.SESSION_SECRET || 'Your Session Secret goes here',\n\n  localAuth: true,\n\n  feedback: { \n    email: process.env.FEEDBACK_EMAIL || \"Your email\"\n  },\n\n  mailgun: {\n    login: process.env.MAILGUN_LOGIN || 'Your Mailgun SMTP Username',\n    password: process.env.MAILGUN_PASSWORD || 'Your Mailgun SMTP Password'\n  },\n\n  sendgrid: {\n    user: process.env.SENDGRID_USER || 'Your SendGrid Username',\n    password: process.env.SENDGRID_PASSWORD || 'Your SendGrid Password'\n  },\n\n  nyt: {\n    key: process.env.NYT_KEY || 'Your New York Times API Key'\n  },\n\n  lastfm: {\n    api_key: process.env.LASTFM_KEY || 'Your API Key',\n    secret: process.env.LASTFM_SECRET || 'Your API Secret'\n  },\n\n  facebookAuth: true,\n  facebook: {\n    clientID: process.env.FACEBOOK_ID || 'Your App ID',\n    clientSecret: process.env.FACEBOOK_SECRET || 'Your App Secret',\n    callbackURL: '/auth/facebook/callback',\n    passReqToCallback: true\n  },\n\n  githubAuth: false,\n  github: {\n    clientID: process.env.GITHUB_ID || 'Your Client ID',\n    clientSecret: process.env.GITHUB_SECRET || 'Your Client Secret',\n    callbackURL: '/auth/github/callback',\n    passReqToCallback: true\n  },\n\n  twitterAuth: false,\n  twitter: {\n    consumerKey: process.env.TWITTER_KEY || 'Your Consumer Key',\n    consumerSecret: process.env.TWITTER_SECRET  || 'Your Consumer Secret',\n    callbackURL: '/auth/twitter/callback',\n    passReqToCallback: true\n  },\n\n  googleAuth: true,\n  google: {\n    clientID: process.env.GOOGLE_ID || 'Your Client ID',\n    clientSecret: process.env.GOOGLE_SECRET || 'Your Client Secret',\n    callbackURL: '/auth/google/callback',\n    passReqToCallback: true\n  },\n\n  linkedinAuth: false,\n  linkedin: {\n    clientID: process.env.LINKEDIN_ID || 'Your Client ID',\n    clientSecret: process.env.LINKEDIN_SECRET || 'Your Client Secret',\n    callbackURL: '/auth/linkedin/callback',\n    scope: ['r_fullprofile', 'r_emailaddress', 'r_network'],\n    passReqToCallback: true\n  },\n\n  steam: {\n    apiKey: process.env.STEAM_KEY || 'Your Steam API Key'\n  },\n\n  twilio: {\n    sid: process.env.TWILIO_SID || 'Your Twilio SID',\n    token: process.env.TWILIO_TOKEN || 'Your Twilio token'\n  },\n\n  clockwork: {\n    apiKey: process.env.CLOCKWORK_KEY || 'Your Clockwork SMS API Key'\n  },\n\n  tumblr: {\n    consumerKey: process.env.TUMBLR_KEY || 'Your Consumer Key',\n    consumerSecret: process.env.TUMBLR_SECRET || 'Your Consumer Secret',\n    callbackURL: '/auth/tumblr/callback'\n  },\n\n  foursquare: {\n    clientId: process.env.FOURSQUARE_ID || 'Your Client ID',\n    clientSecret: process.env.FOURSQUARE_SECRET || 'Your Client Secret',\n    redirectUrl: process.env.FOURSQUARE_REDIRECT_URL || 'http://localhost:3000/auth/foursquare/callback'\n  },\n\n  venmo: {\n    clientId: process.env.VENMO_ID || 'Your Venmo Client ID',\n    clientSecret: process.env.VENMO_SECRET || 'Your Venmo Client Secret',\n    redirectUrl: process.env.VENMO_REDIRECT_URL || 'http://localhost:3000/auth/venmo/callback'\n  },\n\n  paypal: {\n    host: process.env.PAYPAL_HOST || 'api.sandbox.paypal.com',\n    client_id: process.env.PAYPAL_ID || 'Your Client ID',\n    client_secret: process.env.PAYPAL_SECRET || 'Your Client Secret',\n    returnUrl: process.env.PAYPAL_RETURN_URL || 'http://localhost:3000/api/paypal/success',\n    cancelUrl: process.env.PAYPAL_CANCEL_URL || 'http://localhost:3000/api/paypal/cancel'\n  }\n};\n"
  },
  {
    "path": "server/controllers/api.js",
    "content": "var secrets = require('../config/secrets');\nvar User = require('../models/User');\nvar querystring = require('querystring');\nvar validator = require('validator');\nvar async = require('async');\nvar cheerio = require('cheerio');\nvar request = require('request');\nvar _ = require('underscore');\nvar graph = require('fbgraph');\nvar LastFmNode = require('lastfm').LastFmNode;\nvar tumblr = require('tumblr.js');\nvar foursquare = require('node-foursquare')({ secrets: secrets.foursquare });\nvar Github = require('github-api');\nvar Twit = require('twit');\nvar paypal = require('paypal-rest-sdk');\nvar twilio = require('twilio')(secrets.twilio.sid, secrets.twilio.token);\nvar Linkedin = require('node-linkedin')(secrets.linkedin.clientID, secrets.linkedin.clientSecret, secrets.linkedin.callbackURL);\nvar clockwork = require('clockwork')({key: secrets.clockwork.apiKey});\n\n/**\n * GET /api\n * List of API examples.\n */\n\nexports.getApi = function(req, res) {\n  res.render('api/index', {\n    title: 'API Browser'\n  });\n};\n\n/**\n * GET /api/foursquare\n * Foursquare API example.\n */\n\nexports.getFoursquare = function(req, res, next) {\n  var token = _.findWhere(req.user.tokens, { kind: 'foursquare' });\n  async.parallel({\n    trendingVenues: function(callback) {\n      foursquare.Venues.getTrending('40.7222756', '-74.0022724', { limit: 50 }, token.accessToken, function(err, results) {\n        callback(err, results);\n      });\n    },\n    venueDetail: function(callback) {\n      foursquare.Venues.getVenue('49da74aef964a5208b5e1fe3', token.accessToken, function(err, results) {\n        callback(err, results);\n      });\n    },\n    userCheckins: function(callback) {\n      foursquare.Users.getCheckins('self', null, token.accessToken, function(err, results) {\n        callback(err, results);\n      });\n    }\n  },\n  function(err, results) {\n    if (err) return next(err);\n    res.render('api/foursquare', {\n      title: 'Foursquare API',\n      trendingVenues: results.trendingVenues,\n      venueDetail: results.venueDetail,\n      userCheckins: results.userCheckins\n    });\n  });\n};\n\n/**\n * GET /api/tumblr\n * Tumblr API example.\n */\n\nexports.getTumblr = function(req, res) {\n  var token = _.findWhere(req.user.tokens, { kind: 'tumblr' });\n  var client = tumblr.createClient({\n    consumer_key: secrets.tumblr.consumerKey,\n    consumer_secret: secrets.tumblr.consumerSecret,\n    token: token.accessToken,\n    token_secret: token.tokenSecret\n  });\n  client.posts('goddess-of-imaginary-light.tumblr.com', { type: 'photo' }, function(err, data) {\n    res.render('api/tumblr', {\n      title: 'Tumblr API',\n      blog: data.blog,\n      photoset: data.posts[0].photos\n    });\n  });\n};\n\n/**\n * GET /api/facebook\n * Facebook API example.\n */\n\nexports.getFacebook = function(req, res, next) {\n  var token = _.findWhere(req.user.tokens, { kind: 'facebook' });\n  graph.setAccessToken(token.accessToken);\n  async.parallel({\n    getMe: function(done) {\n      graph.get(req.user.facebook, function(err, me) {\n        done(err, me);\n      });\n    },\n    getMyFriends: function(done) {\n      graph.get(req.user.facebook + '/friends', function(err, friends) {\n        done(err, friends.data);\n      });\n    }\n  },\n  function(err, results) {\n    if (err) return next(err);\n    res.render('api/facebook', {\n      title: 'Facebook API',\n      me: results.getMe,\n      friends: results.getMyFriends\n    });\n  });\n};\n\n/**\n * GET /api/scraping\n * Web scraping example using Cheerio library.\n */\n\nexports.getScraping = function(req, res, next) {\n  request.get('https://news.ycombinator.com/', function(err, request, body) {\n    if (err) return next(err);\n    var $ = cheerio.load(body);\n    var links = [];\n    $(\".title a[href^='http'], a[href^='https']\").each(function() {\n      links.push($(this));\n    });\n    res.render('api/scraping', {\n      title: 'Web Scraping',\n      links: links\n    });\n  });\n};\n\n/**\n * GET /api/github\n * GitHub API Example.\n */\nexports.getGithub = function(req, res) {\n  var token = _.findWhere(req.user.tokens, { kind: 'github' });\n  var github = new Github({ token: token.accessToken });\n  var repo = github.getRepo('sahat', 'requirejs-library');\n  repo.show(function(err, repo) {\n    res.render('api/github', {\n      title: 'GitHub API',\n      repo: repo\n    });\n  });\n\n};\n\n/**\n * GET /api/aviary\n * Aviary image processing example.\n */\n\nexports.getAviary = function(req, res) {\n  res.render('api/aviary', {\n    title: 'Aviary API'\n  });\n};\n\n/**\n * GET /api/nyt\n * New York Times API example.\n */\n\nexports.getNewYorkTimes = function(req, res, next) {\n  var query = querystring.stringify({ 'api-key': secrets.nyt.key, 'list-name': 'young-adult' });\n  var url = 'http://api.nytimes.com/svc/books/v2/lists?' + query;\n  request.get(url, function(error, request, body) {\n    if (request.statusCode === 403) return next(Error('Missing or Invalid New York Times API Key'));\n    var bestsellers = JSON.parse(body);\n    res.render('api/nyt', {\n      title: 'New York Times API',\n      books: bestsellers.results\n    });\n  });\n};\n\n/**\n * GET /api/lastfm\n * Last.fm API example.\n */\n\nexports.getLastfm = function(req, res, next) {\n  var lastfm = new LastFmNode(secrets.lastfm);\n  async.parallel({\n    artistInfo: function(done) {\n      lastfm.request(\"artist.getInfo\", {\n        artist: 'Epica',\n        handlers: {\n          success: function(data) {\n            done(null, data);\n          },\n          error: function(err) {\n            done(err);\n          }\n        }\n      });\n    },\n    artistTopAlbums: function(done) {\n      lastfm.request(\"artist.getTopAlbums\", {\n        artist: 'Epica',\n        handlers: {\n          success: function(data) {\n            var albums = [];\n            _.each(data.topalbums.album, function(album) {\n              albums.push(album.image.slice(-1)[0]['#text']);\n            });\n            done(null, albums.slice(0, 4));\n          },\n          error: function(err) {\n            done(err);\n          }\n        }\n      });\n    }\n  },\n  function(err, results) {\n    if (err) return next(err.message);\n    var artist = {\n      name: results.artistInfo.artist.name,\n      image: results.artistInfo.artist.image.slice(-1)[0]['#text'],\n      tags: results.artistInfo.artist.tags.tag,\n      bio: results.artistInfo.artist.bio.summary,\n      stats: results.artistInfo.artist.stats,\n      similar: results.artistInfo.artist.similar.artist,\n      topAlbums: results.artistTopAlbums\n    };\n    res.render('api/lastfm', {\n      title: 'Last.fm API',\n      artist: artist\n    });\n  });\n};\n\n/**\n * GET /api/twitter\n * Twiter API example.\n */\n\nexports.getTwitter = function(req, res, next) {\n  var token = _.findWhere(req.user.tokens, { kind: 'twitter' });\n  var T = new Twit({\n    consumer_key: secrets.twitter.consumerKey,\n    consumer_secret: secrets.twitter.consumerSecret,\n    access_token: token.accessToken,\n    access_token_secret: token.tokenSecret\n  });\n  T.get('search/tweets', { q: 'hackathon since:2013-01-01', geocode: '40.71448,-74.00598,5mi', count: 50 }, function(err, reply) {\n    if (err) return next(err);\n    res.render('api/twitter', {\n      title: 'Twitter API',\n      tweets: reply.statuses\n    });\n  });\n};\n\n/**\n * GET /api/paypal\n * PayPal SDK example.\n */\n\nexports.getPayPal = function(req, res, next) {\n  paypal.configure(secrets.paypal);\n\n  var paymentDetails = {\n    intent: 'sale',\n    payer: {\n      payment_method: 'paypal'\n    },\n    redirect_urls: {\n      return_url: secrets.paypal.returnUrl,\n      cancel_url: secrets.paypal.cancelUrl\n    },\n    transactions: [\n      {\n        description: 'Node.js Boilerplate',\n        amount: {\n          currency: 'USD',\n          total: '2.99'\n        }\n      }\n    ]\n  };\n\n  paypal.payment.create(paymentDetails, function(err, payment) {\n    if (err) return next(err);\n    req.session.paymentId = payment.id;\n    var links = payment.links;\n    for (var i = 0; i < links.length; i++) {\n      if (links[i].rel === 'approval_url') {\n        res.render('api/paypal', {\n          approval_url: links[i].href\n        });\n      }\n    }\n  });\n};\n\n/**\n * GET /api/paypal/success\n * PayPal SDK example.\n */\n\nexports.getPayPalSuccess = function(req, res, next) {\n  var paymentId = req.session.paymentId;\n  var paymentDetails = { 'payer_id': req.query.PayerID };\n  paypal.payment.execute(paymentId, paymentDetails, function(err, payment) {\n    if (err) {\n      res.render('api/paypal', {\n        result: true,\n        success: false\n      });\n    } else {\n      res.render('api/paypal', {\n        result: true,\n        success: true\n      });\n    }\n  });\n};\n\n/**\n * GET /api/paypal/cancel\n * PayPal SDK example.\n */\n\nexports.getPayPalCancel = function(req, res, next) {\n  req.session.payment_id = null;\n  res.render('api/paypal', {\n    result: true,\n    canceled: true\n  });\n};\n\n/**\n * GET /api/steam\n * Steam API example.\n */\n\nexports.getSteam = function(req, res, next) {\n  var steamId = '76561197982488301';\n  var query = { l: 'english', steamid: steamId, key: secrets.steam.apiKey };\n\n  async.parallel({\n    playerAchievements: function(done) {\n      query.appid = '49520';\n      var qs = querystring.stringify(query);\n      request.get({ url: 'http://api.steampowered.com/ISteamUserStats/GetPlayerAchievements/v0001/?' + qs, json: true }, function(error, request, body) {\n        if (request.statusCode === 401) return done(new Error('Missing or Invalid Steam API Key'));\n        done(error, body);\n      });\n    },\n    playerSummaries: function(done) {\n      query.steamids = steamId;\n      var qs = querystring.stringify(query);\n      request.get({ url: 'http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?' + qs, json: true }, function(error, request, body) {\n        if (request.statusCode === 401) return done(new Error('Missing or Invalid Steam API Key'));\n        done(error, body);\n      });\n    },\n    ownedGames: function(done) {\n      query.include_appinfo = 1;\n      query.include_played_free_games = 1;\n      var qs = querystring.stringify(query);\n      request.get({ url: 'http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?' + qs, json: true }, function(error, request, body) {\n        if (request.statusCode === 401) return done(new Error('Missing or Invalid Steam API Key'));\n        done(error, body);\n      });\n    }\n  },\n  function(err, results) {\n    if (err) return next(err);\n    res.render('api/steam', {\n      title: 'Steam Web API',\n      ownedGames: results.ownedGames.response.games,\n      playerAchievemments: results.playerAchievements.playerstats,\n      playerSummary: results.playerSummaries.response.players[0]\n    });\n  });\n};\n\n/**\n * GET /api/twilio\n * Twilio API example.\n */\n\nexports.getTwilio = function(req, res, next) {\n  res.render('api/twilio', {\n    title: 'Twilio API'\n  });\n};\n\n/**\n * POST /api/twilio\n * Twilio API example.\n * @param telephone\n */\n\nexports.postTwilio = function(req, res, next) {\n  var message = {\n    to: req.body.telephone,\n    from: '+13472235148',\n    body: 'Hello from the Hackathon Starter'\n  };\n  twilio.sendMessage(message, function(err, responseData) {\n    if (err) return next(err.message);\n    req.flash('success', { msg: 'Text sent to ' + responseData.to + '.'})\n    res.redirect('/api/twilio');\n  });\n};\n\n/**\n * GET /api/clockwork\n * Clockwork SMS API example.\n */\n\nexports.getClockwork = function(req, res) {\n  res.render('api/clockwork', {\n    title: 'Clockwork SMS API'\n  });\n};\n\n/**\n * POST /api/clockwork\n * Clockwork SMS API example.\n * @param telephone\n */\n\nexports.postClockwork = function(req, res, next) {\n  var message = {\n    To: req.body.telephone,\n    From: 'Hackathon',\n    Content: 'Hello from the Hackathon Starter'\n  };\n  clockwork.sendSms(message, function(err, responseData) {\n    if (err) return next(err.errDesc);\n    req.flash('success', { msg: 'Text sent to ' + responseData.responses[0].to });\n    res.redirect('/api/clockwork');\n  });\n};\n\n/**\n * GET /api/venmo\n * Venmo API example.\n */\n\nexports.getVenmo = function(req, res, next) {\n  var token = _.findWhere(req.user.tokens, { kind: 'venmo' });\n  var query = querystring.stringify({ access_token: token.accessToken });\n\n  async.parallel({\n    getProfile: function(done) {\n      request.get({ url: 'https://api.venmo.com/v1/me?' + query, json: true }, function(err, request, body) {\n        done(err, body);\n      });\n    },\n    getRecentPayments: function(done) {\n      request.get({ url: 'https://api.venmo.com/v1/payments?' + query, json: true }, function(err, request, body) {\n        done(err, body);\n\n      });\n    }\n  },\n  function(err, results) {\n    if (err) return next(err);\n    res.render('api/venmo', {\n      title: 'Venmo API',\n      profile: results.getProfile.data,\n      recentPayments: results.getRecentPayments.data\n    });\n  });\n};\n\n/**\n * POST /api/venmo\n * @param user\n * @param note\n * @param amount\n * Send money.\n */\n\nexports.postVenmo = function(req, res, next) {\n  req.assert('user', 'Phone, Email or Venmo User ID cannot be blank').notEmpty();\n  req.assert('note', 'Please enter a message to accompany the payment').notEmpty();\n  req.assert('amount', 'The amount you want to pay cannot be blank').notEmpty();\n\n  var errors = req.validationErrors();\n\n  if (errors) {\n    req.flash('errors', errors);\n    return res.redirect('/api/venmo');\n  }\n\n  var token = _.findWhere(req.user.tokens, { kind: 'venmo' });\n\n  var formData = {\n    access_token: token.accessToken,\n    note: req.body.note,\n    amount: req.body.amount\n  };\n\n  if (validator.isEmail(req.body.user)) {\n    formData.email = req.body.user;\n  } else if (validator.isNumeric(req.body.user) &&\n    validator.isLength(req.body.user, 10, 11)) {\n    formData.phone = req.body.user;\n  } else {\n    formData.user_id = req.body.user;\n  }\n\n  request.post('https://api.venmo.com/v1/payments', { form: formData }, function(err, request, body) {\n    if (err) return next(err);\n    if (request.statusCode !== 200) {\n      req.flash('errors', { msg: JSON.parse(body).error.message });\n      return res.redirect('/api/venmo');\n    }\n    req.flash('success', { msg: 'Venmo money transfer complete' });\n    res.redirect('/api/venmo');\n  });\n};\n\n/**\n * GET /api/linkedin\n * LinkedIn API example.\n */\n\nexports.getLinkedin = function(req, res, next) {\n  var token = _.findWhere(req.user.tokens, { kind: 'linkedin' });\n  var linkedin = Linkedin.init(token.accessToken);\n\n  linkedin.people.me(function(err, $in) {\n    if (err) return next(err);\n    res.render('api/linkedin', {\n      title: 'LinkedIn API',\n      profile: $in\n    });\n  });\n};\n"
  },
  {
    "path": "server/controllers/contact.js",
    "content": "var secrets = require('../config/secrets');\nvar nodemailer = require(\"nodemailer\");\nvar smtpTransport = nodemailer.createTransport('SMTP', {\n//  service: 'Mailgun',\n//  auth: {\n//    user: secrets.mailgun.login,\n//    pass: secrets.mailgun.password\n//  }\n  service: 'SendGrid',\n  auth: {\n       user: secrets.sendgrid.user,\n       pass: secrets.sendgrid.password\n  }\n});\n\n/**\n * GET /contact\n * Contact form page.\n */\n\nexports.getContact = function(req, res) {\n  res.render('contact', {\n    title: 'Contact'\n  });\n};\n\n/**\n * POST /contact\n * Send a contact form via Nodemailer.\n * @param email\n * @param name\n * @param message\n */\n\nexports.postContact = function(req, res) {\n  req.assert('name', 'Name cannot be blank').notEmpty();\n  req.assert('email', 'Email is not valid').isEmail();\n  req.assert('message', 'Message cannot be blank').notEmpty();\n\n  var errors = req.validationErrors();\n\n  if (errors) {\n    req.flash('errors', errors);\n    return res.redirect('/contact');\n  }\n\n  var from = req.body.email;\n  var name = req.body.name;\n  var body = req.body.message;\n  var to = 'your@email.com';\n  var subject = 'Contact Form | Flood';\n\n  var mailOptions = {\n    to: to,\n    from: from,\n    subject: subject,\n    text: body\n  };\n\n  smtpTransport.sendMail(mailOptions, function(err) {\n    if (err) {\n      req.flash('errors', { msg: err.message });\n      return res.redirect('/contact');\n    }\n    req.flash('success', { msg: 'Email has been sent successfully!' });\n    res.redirect('/contact');\n  });\n};\n"
  },
  {
    "path": "server/controllers/exampleWorkspaces.js",
    "content": "exports.myFirstProject = \n{  \n  \"connections\":[  \n    {  \n      \"kind\":\"addConnection\",\n      \"startNodeId\":398809118,\n      \"startPortIndex\":0,\n      \"endNodeId\":23624844,\n      \"endPortIndex\":0,\n      \"_id\":964734507,\n      \"startProxy\":false,\n      \"endProxy\":false,\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"hidden\":false\n    },\n    {  \n      \"kind\":\"addConnection\",\n      \"startNodeId\":604762864,\n      \"startPortIndex\":0,\n      \"endNodeId\":398809118,\n      \"endPortIndex\":0,\n      \"_id\":647386019,\n      \"startProxy\":false,\n      \"endProxy\":false,\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"hidden\":false\n    },\n    {  \n      \"kind\":\"addConnection\",\n      \"startNodeId\":598617458,\n      \"startPortIndex\":0,\n      \"endNodeId\":23624844,\n      \"endPortIndex\":1,\n      \"_id\":564971549,\n      \"startProxy\":false,\n      \"endProxy\":false,\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"hidden\":false\n    },\n    {  \n      \"kind\":\"addConnection\",\n      \"startNodeId\":3271050,\n      \"startPortIndex\":0,\n      \"endNodeId\":598617458,\n      \"endPortIndex\":2,\n      \"_id\":742143501,\n      \"startProxy\":false,\n      \"endProxy\":false,\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"hidden\":false\n    },\n    {  \n      \"kind\":\"addConnection\",\n      \"startNodeId\":440238000,\n      \"startPortIndex\":0,\n      \"endNodeId\":42665510,\n      \"endPortIndex\":0,\n      \"_id\":661808583,\n      \"startProxy\":false,\n      \"endProxy\":false,\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"hidden\":false\n    },\n    {  \n      \"kind\":\"addConnection\",\n      \"startNodeId\":42665510,\n      \"startPortIndex\":0,\n      \"endNodeId\":945248858,\n      \"endPortIndex\":0,\n      \"_id\":359041827,\n      \"startProxy\":false,\n      \"endProxy\":false,\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"hidden\":false\n    },\n    {  \n      \"kind\":\"addConnection\",\n      \"startNodeId\":604762864,\n      \"startPortIndex\":0,\n      \"endNodeId\":398809118,\n      \"endPortIndex\":1,\n      \"_id\":899758279,\n      \"startProxy\":false,\n      \"endProxy\":false,\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"hidden\":false\n    },\n    {  \n      \"kind\":\"addConnection\",\n      \"startNodeId\":823934643,\n      \"startPortIndex\":0,\n      \"endNodeId\":42665510,\n      \"endPortIndex\":1,\n      \"_id\":764520692,\n      \"startProxy\":false,\n      \"endProxy\":false,\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"hidden\":false\n    },\n    {  \n      \"hidden\":false,\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxy\":false,\n      \"startProxy\":false,\n      \"_id\":794491759,\n      \"endPortIndex\":1,\n      \"endNodeId\":440238000,\n      \"startPortIndex\":0,\n      \"startNodeId\":282252545,\n      \"kind\":\"addConnection\"\n    },\n    {  \n      \"hidden\":false,\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxy\":false,\n      \"startProxy\":false,\n      \"_id\":965267809,\n      \"endPortIndex\":2,\n      \"endNodeId\":440238000,\n      \"startPortIndex\":0,\n      \"startNodeId\":498266200,\n      \"kind\":\"addConnection\"\n    },\n    {  \n      \"hidden\":false,\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxy\":false,\n      \"startProxy\":false,\n      \"_id\":267211310,\n      \"endPortIndex\":0,\n      \"endNodeId\":317753978,\n      \"startPortIndex\":0,\n      \"startNodeId\":440238000,\n      \"kind\":\"addConnection\"\n    },\n    {  \n      \"hidden\":false,\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxy\":false,\n      \"startProxy\":false,\n      \"_id\":573083411,\n      \"endPortIndex\":2,\n      \"endNodeId\":42665510,\n      \"startPortIndex\":0,\n      \"startNodeId\":317753978,\n      \"kind\":\"addConnection\"\n    }\n  ],\n  \"nodes\":[  \n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        4596,\n        4119\n      ],\n      \"typeName\":\"SolidExtrusion\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n        true,\n        false\n      ],\n      \"_id\":23624844,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n        \"script\":\"A;\"\n      }\n    },\n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        4350,\n        4067\n      ],\n      \"typeName\":\"RegularPolygon\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n        false,\n        false,\n        false\n      ],\n      \"_id\":398809118,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n        \"script\":\"A;\"\n      }\n    },\n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        4062,\n        4085\n      ],\n      \"typeName\":\"Number\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n\n      ],\n      \"_id\":604762864,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n        \"value\":8,\n        \"min\":0,\n        \"step\":0.1,\n        \"max\":20\n      }\n    },\n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        4351,\n        4181\n      ],\n      \"typeName\":\"Vector\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n        false,\n        false,\n        false\n      ],\n      \"_id\":598617458,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n        \"script\":\"A;\"\n      }\n    },\n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        4063,\n        4230\n      ],\n      \"typeName\":\"Number\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n\n      ],\n      \"_id\":3271050,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n        \"max\":40,\n        \"step\":0.1,\n        \"min\":-40,\n        \"value\":15\n      }\n    },\n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        4346,\n        4449\n      ],\n      \"typeName\":\"Range\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n        false,\n        false,\n        false\n      ],\n      \"_id\":440238000,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n        \"script\":\"A;\"\n      }\n    },\n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        4859,\n        4452\n      ],\n      \"typeName\":\"Vector\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n        false,\n        false,\n        false\n      ],\n      \"_id\":42665510,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n        \"script\":\"A;\"\n      }\n    },\n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        5006,\n        4451\n      ],\n      \"typeName\":\"Point\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n        false\n      ],\n      \"_id\":945248858,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n        \"script\":\"A;\"\n      }\n    },\n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        4047,\n        4442\n      ],\n      \"typeName\":\"Number\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n\n      ],\n      \"_id\":282252545,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n        \"max\":100,\n        \"step\":0.1,\n        \"min\":0,\n        \"value\":20\n      }\n    },\n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        4534,\n        4486\n      ],\n      \"typeName\":\"Number\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n\n      ],\n      \"_id\":823934643,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n        \"max\":150,\n        \"step\":0.1,\n        \"min\":-150,\n        \"value\":30\n      }\n    },\n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        4050,\n        4532\n      ],\n      \"typeName\":\"Number\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n\n      ],\n      \"_id\":498266200,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n        \"max\":150,\n        \"step\":0.1,\n        \"min\":0,\n        \"value\":150\n      }\n    },\n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        4501,\n        4561\n      ],\n      \"typeName\":\"Script\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n        false\n      ],\n      \"_id\":317753978,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n        \"script\":\"10 * Sin(A);\"\n      }\n    }\n  ],\n  \"name\":\"Example Project\",\n};\n\nexports.myFirstCustomNode = \n{\n  \"connections\":[  \n    {  \n      \"hidden\":false,\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxy\":false,\n      \"startProxy\":false,\n      \"_id\":137881318,\n      \"endPortIndex\":0,\n      \"endNodeId\":263728761,\n      \"startPortIndex\":0,\n      \"startNodeId\":253762878,\n      \"kind\":\"addConnection\"\n    },\n    {  \n      \"hidden\":false,\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxy\":false,\n      \"startProxy\":false,\n      \"_id\":525878839,\n      \"endPortIndex\":1,\n      \"endNodeId\":263728761,\n      \"startPortIndex\":0,\n      \"startNodeId\":253762878,\n      \"kind\":\"addConnection\"\n    },\n    {  \n      \"hidden\":false,\n      \"endProxyPosition\":[  \n        0,\n        0\n      ],\n      \"startProxyPosition\":[  \n        0,\n        0\n      ],\n      \"endProxy\":false,\n      \"startProxy\":false,\n      \"_id\":144876797,\n      \"endPortIndex\":0,\n      \"endNodeId\":892555475,\n      \"startPortIndex\":0,\n      \"startNodeId\":263728761,\n      \"kind\":\"addConnection\"\n    }\n  ],\n  \"nodes\":[  \n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        4107,\n        4161\n      ],\n      \"typeName\":\"Input\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n\n      ],\n      \"_id\":253762878,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n        \"name\":\"X\"\n      }\n    },\n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        4548,\n        4156\n      ],\n      \"typeName\":\"Output\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n        true\n      ],\n      \"_id\":892555475,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n        \"name\":\"X * X\"\n      }\n    },\n    {  \n      \"name\":\"DefaultNodeName\",\n      \"position\":[  \n        4359,\n        4152\n      ],\n      \"typeName\":\"Multiply\",\n      \"selected\":false,\n      \"visible\":true,\n      \"ignoreDefaults\":[  \n        false,\n        false\n      ],\n      \"_id\":263728761,\n      \"replication\":\"applyLongest\",\n      \"extra\":{  \n\n      }\n    }\n  ],\n  \"name\":\"Example Custom Node\",\n  \"isCustomNode\": true\n};"
  },
  {
    "path": "server/controllers/feedback.js",
    "content": "var _ = require('underscore')\n\t, nodemailer = require('nodemailer')\n\t, secrets = require('../config/secrets');\n\n\nvar smtpTransport = nodemailer.createTransport('SMTP', {\n service: 'Mailgun',\n auth: {\n   user: secrets.mailgun.login,\n   pass: secrets.mailgun.password\n }\n});\n\nvar emailTarget = secrets.feedback.email;\n\nexports.postFeedback = function(req, res) {\n\n\tif (!req.user) return res.status(401).send(\"You are not logged in\");\n\n\tif (!req.body) return res.status(500).send('Malformed body');\n\n\tvar ns = req.body;\n\n\tif (!emailTarget) return res.status(500).send({ msg: \"Feedback temporarily unsupported\" });\n\n\tsmtpTransport.sendMail({\n\t    from: req.user.email,\n\t    to: emailTarget,\n\t    subject: \"[FLOOD FEEDBACK] : \\\"\" + ns.subject ? ns.subject : \"Empty subject\" + \"\\\"\",\n\t    text: ns.message ? ns.message : \"Empty body\",\n\t\t}, function(err) {\n\t    if (err) {\n\t      return res.status(500).send({ msg: \"Could not send feedback!  Try again later!\" });\n\t    }\n\t    return res.send({ msg: 'Feedback has been sent successfully!' });\n\t  });\n\n};"
  },
  {
    "path": "server/controllers/flood.js",
    "content": "var mongoose = require('mongoose')\n\t, Session = require('../models/Workspace').SessionModel\n\t, Workspace = require('../models/Workspace').WorkspaceModel\n\t, User = require('../models/User')\n\t, async = require('async')\n\t, _ = require('underscore')\n\t, ExampleWorkspaces = require('./exampleWorkspaces');\n\nvar initNonUserSession = function(req, res){\n\n\tvar user = req.user;\n\tvar nws = new Workspace({name : \"My first workspace\"});\n\tvar newSesh = new Session({name : \"Empty session\", workspaces : [ nws ]});\n\n\tnws.save(function(errWs){\n\n\t\tif (errWs) return res.status(500).send(\"Failed to initialize user workspace\");\n\n\t\tnewSesh.save(function(errSesh){\n\n\t\t\t\tif (errSesh) return res.status(500).send(\"Failed to initialize user session\");\n\n\t\t\t\tSession\n\t\t\t\t\t.findById(newSesh.id)\n\t\t\t\t\t.populate('workspaces')\n\t\t\t\t\t.exec( function(err, sesh){\n\n\t\t\t\t\t\tif (err || !sesh ) return res.status(500).send(\"Failed to obtain user session\");\n\t\t\t\t\t\treturn res.send(sesh);\n\t\t\t\t\t});\n\t\t\t});\n\t});\n\n}\n\nvar initUserSession = function(req, res){\n\n\tvar user = req.user;\n\tvar nws = new Workspace(ExampleWorkspaces.myFirstProject);\n\tvar nws1 = new Workspace(ExampleWorkspaces.myFirstCustomNode);\n\tvar newSesh = new Session({name : \"Session\", workspaces : [ nws, nws1 ]});\n\n\tnws.maintainers = [ req.user ];\n\tnws1.maintainers = [ req.user ];\n\n\tnws.save(function(errWs){\n\n\t\tif (errWs) return res.status(500).send(\"Failed to initialize user workspace\");\n\n\t\tnws1.save(function(errWs1){\n\n\t\t\tif (errWs1) return res.status(500).send(\"Failed to initialize user workspace\");\n\n\t\t\tnewSesh.save(function(errSesh){\n\n\t\t\t\tif (errSesh) return res.status(500).send(\"Failed to initialize user session\");\n\n\t\t\t\tuser.lastSession = newSesh;\n\t\t\t\tuser.workspaces = [ nws, nws1 ];\n\t\t\t\tuser.markModified(\"lastSession workspaces\");\n\n\t\t\t\tuser.save(function(err){\n\t\t\t\t\tif (err) return res.status(500).send(\"Failed to save user session\");\n\n\t\t\t\t\tSession\n\t\t\t\t\t.findById(user.lastSession )\n\t\t\t\t\t.populate('workspaces')\n\t\t\t\t\t.exec( function(err, sesh){\n\n\t\t\t\t\t\tif (err || !sesh ) return res.status(500).send(\"Failed to obtain user session\");\n\t\t\t\t\t\treturn res.send(sesh);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\n\t\t});\n\n\t});\n\n};\n\nexports.getCustomizerWorkspace = function(req, res){\n\n\tWorkspace.findById( req.params.id, function(err, ws){\n\n\t\tif (err || !ws) res.status(404).send(\"Workspace not found!\");\n\n\t\t// its a public customizable workspace\n\t\tif (ws.isCustomizer === true) return res.send( ws );\n\n\t\t// its the users workspace, so they can see it\n\t\tif (req.user && ws.maintainers.indexOf(req.user._id) != -1) return res.send( ws );\n\n\t\treturn res.status(401).send(\"This workspace is either not public or you are not authorized to access it.\")\n\n\t});\n}\n\nexports.getMySession = function(req, res) {\n\n\tvar user = req.user;\n\n\tif (!req.user) {\n\t\treturn initNonUserSession(req,res);\n\t}\n\n\tif (!user.lastSession){\n\t\treturn initUserSession(req, res);\n\t}\n\n\tSession\n\t.findById(user.lastSession )\n\t.populate('workspaces')\n\t.exec( function(err, sesh){\n\t\tif (err || !sesh || !sesh.workspaces || sesh.workspaces.length == 0 ) {\n\t\t\treturn initUserSession(req, res);\n\t\t}\n\t\tsesh.isFirstExperience = false;\n\t\treturn res.send(sesh);\n\t});\n\n};\n\nexports.putMySession = function(req, res) {\n\n\tif (!req.user) {\n\t\treturn res.status(401).send(\"You are not logged in\");\n\t}\n\n\tif (!req.body || !req.body._id) return res.status(500).send('Malformed body');\n\n  var ns = req.body;\n  var sid = ns._id;\n\n\t// build all of the workspace saves\n\tvar workspaceSaves = ns.workspaces.map(function(x){\n\n\t\treturn function(callback){\n\n\t\t\tWorkspace.findById(x._id, function(e, w){\n\n\t\t\t\tif (e || !w) return callback(\"Failed to find workspace\");\n\n\t\t\t\t// todo optimize this\n\t\t\t\tw.name = x.name || w.name;\n\t\t\t\tw.nodes = x.nodes || w.nodes;\n\t\t\t\tw.connections = x.connections || w.connections;\n\t\t\t\tw.currentWorkspace = x.currentWorkspace || w.currentWorkspace;\n\t\t\t\tw.selectedNodes = x.selectedNodes || w.selectedNodes;\n\t\t\t\tw.zoom = x.zoom || w.zoom;\n\t\t\t\tw.offset = x.offset || w.offset;\n\t\t\t\tw.lastSaved = Date.now();\n\t\t\t\tw.redoStack = x.redoStack || w.redoStack;\n\t\t\t\tw.undoStack = x.undoStack || w.undoStack;\n\t\t\t\tw.workspaceDependencyIds = x.workspaceDependencyIds || w.workspaceDependencyIds;\n\t\t\t\tw.isCustomNode = ( x.isCustomNode != undefined ) ? x.isCustomNode : w.isCustomNode;\n\t\t\t\tw.isEdited = true;\n\t\t\t\tw.isCustomizer = ( x.isCustomizer != undefined ) ? x.isCustomizer : w.isCustomizer;\n\n\t\t\t\tw.markModified(\"workspaceDependencyIds offset isCustomNode isCustomizer isEditor name nodes connections currentWorkspace selectedNodes zoom lastSaved undoStack redoStack\");\n\n\t\t\t\tw.save(function(se){\n\t\t\t\t\tif (se) return callback(se);\n\t\t\t\t\treturn callback();\n\t\t\t\t});\n\n\t\t\t});\n\n\t\t};\n\n\t});\n\n\tasync.waterfall(workspaceSaves, function(err) {\n\n\t\tif (err) return res.status(500).send(err);\n\n\t\t// save session\n\t\tSession.findById( sid, function(e, s) {\n\n\t\t\tif (e || !s) return res.status(500).send('Invalid session id');\n\n\t\t\ts.name = ns.name || s.name;\n\n\t\t\t// TODO: validate ids\n\t\t\ts.workspaces = ns.workspaces.map(function(x){ return x._id; });\n\t\t\ts.currentWorkspace = ns.currentWorkspace;\n\t\t\ts.isFirstExperience = false;\n\t\t\ts.lastSaved = Date.now();\n\n\t\t\ts.markModified('isFirstExperience workspaces currentWorkspace lastSave name');\n\n\t\t\ts.save(function(e){\n\t\t\t\tif (e) return res.status(500).send(\"Failed to save session\");\n\t\t\t\treturn res.send(\"Success\");\n\t\t\t});\n\n\t\t});\n\n\t});\n\n};\n\nexports.getNewWorkspace = function(req, res){\n\n\tvar user = req.user;\n\n\tif (!user) return res.status(403).send(\"Must be logged in to create a new workspace\")\n\n\tvar nws = new Workspace({name : \"New workspace\", maintainers : [ user._id ] });\n\n\tnws.save(function(e){\n\n\t\tif (e) return res.status(500).send(\"Failed to create new workspace\");\n\n\t\tuser.workspaces.push(nws);\n\t\tuser.markModified('workspaces');\n\n\t\tuser.save(function(eu){\n\n\t\t\tif (eu) return res.status(500).send(\"Failed to update user profile\");\n\t\t\treturn res.send(nws);\n\n\t\t})\n\n\t});\n\n};\n\nvar dateSort = function(a, b){\n\n\tif (a.lastSaved && !b.lastSaved){\n\t\treturn -1;\n\t}\n\n\tif (b.lastSaved && !a.lastSaved){\n\t\treturn 1;\n\t}\n\n\tif ( !b.lastSaved && !a.lastSaved )\n\t\treturn 0;\n\n\tif ( a.lastSaved > b.lastSaved )\n     return -1;\n\n  if ( a.lastSaved < b.lastSaved )\n     return 1;\n\n  return 0;\n}\n\nexports.getWorkspaces = function(req, res) {\n\n\tvar user = req.user;\n\n\tif (!user) return res.status(403).send(\"Must be logged in to list your workspaces\")\n\n\tUser.findById( user._id )\n\t\t.populate('workspaces', 'name lastSaved isPublic maintainers isEdited isCustomNode')\n\t\t.exec(function(e, u) {\n            return res.send(u.workspaces );\n\t});\n\n};\n\nexports.getWorkspace = function(req, res) {\n\n  var wid = req.params.id;\n\n\tWorkspace.findById( wid , function(e, ws) {\n\n\t\tif (e) {\n\t  \t\treturn res.send('Workspace not found');\n\t\t}\n\n\t\treturn res.send(ws);\n\n\t});\n\n};\n\nexports.putWorkspace = function(req, res) {\n\n  var wid = req.params.id;\n\tvar x = req.body;\n\n\tif (!req.user) {\n\t\treturn res.status(401).send(\"You need to be logged in to save a workspace\");\n\t}\n\n\tWorkspace.findById( wid , function(e, w) {\n\n\t\tif (e) {\n\t  \t\treturn res.status(404).send('Workspace not found');\n\t\t}\n\n\t\tw.name = x.name || w.name;\n\t\tw.nodes = x.nodes || w.nodes;\n\t\tw.connections = x.connections || w.connections;\n\t\tw.currentWorkspace = x.currentWorkspace || w.currentWorkspace;\n\t\tw.selectedNodes = x.selectedNodes || w.selectedNodes;\n\t\tw.zoom = x.zoom || w.zoom;\n\t\tw.lastSaved = Date.now();\n\t\tw.redoStack = x.redoStack || w.redoStack;\n\t\tw.undoStack = x.undoStack || w.undoStack;\n\t\tw.isCustomNode = ( x.isCustomNode != undefined ) ? x.isCustomNode : w.isCustomNode;\n\t\tw.isCustomizer = ( x.isCustomizer != undefined ) ? x.isCustomizer : w.isCustomizer;\n\t\tw.workspaceDependencyIds = x.workspaceDependencyIds || w.workspaceDependencyIds;\n\t\tw.offset = x.offset || w.offset;\n\t\tw.isEdited = true;\n\n\t\tw.markModified(\"workspaceDependencyIds name isCustomNode isCustomizer nodes connections currentWorkspace selectedNodes zoom offset lastSaved undoStack redoStack isEdited\");\n\n\t\tw.save(function(se){\n\t\t\tif (se) return res.status(500).send('Could not save the workspace');\n\t\t\treturn res.status(200).send('Saved workspace');\n\t\t});\n\n\t});\n\n};\n\n"
  },
  {
    "path": "server/controllers/home.js",
    "content": "var flood = require('../models/Workspace');\n\n/**\n * GET /\n * Home page.\n */\n\nexports.index = function(req, res) {\n  res.render('home', {\n    title: 'Home'\n  });\n};"
  },
  {
    "path": "server/controllers/user.js",
    "content": "var _ = require('underscore');\nvar async = require('async');\nvar crypto = require('crypto');\nvar nodemailer = require('nodemailer');\nvar passport = require('passport');\nvar User = require('../models/User');\nvar secrets = require('../config/secrets');\n\n/**\n* GET /email\n* Get user email\n*/\n\nexports.getEmail = function(req, res ){\n  if (!req.user) {\n    return res.send(\"Not logged in\");\n  }\n  return res.send({ email: req.user.email });\n}\n\n/**\n * GET /login\n * Login page.\n */\n\nexports.getLogin = function(req, res) {\n  if (req.user) return res.redirect('/');\n  res.render('account/login', {\n    title: 'Login'\n  });\n};\n\n/**\n * POST /login\n * Sign in using email and password.\n * @param email\n * @param password\n */\n\nexports.postLogin = function(req, res, next) {\n  req.assert('email', 'Email is not valid').isEmail();\n  req.assert('password', 'Password cannot be blank').notEmpty();\n\n  var errors = req.validationErrors();\n\n  if (errors) {\n    // req.flash('errors', errors);\n    // return res.redirect('/login');\n    return res.send(errors);\n  }\n\n  passport.authenticate('local', function(err, user, info) {\n    if (err) return next(err);\n    if (!user) {\n      return res.send([{ msg: info.message }]);\n    }\n    req.logIn(user, function(err) {\n      if (err) return next(err);\n      return res.send({ msg: 'Success! You are logged in.' });\n    });\n  })(req, res, next);\n};\n\n/**\n * GET /logout\n * Log out.\n */\n\nexports.logout = function(req, res) {\n  req.logout();\n  res.send({ msg: 'Success! You are logged out.' });\n};\n\n/**\n * GET /signup\n * Signup page.\n */\n\nexports.getSignup = function(req, res) {\n  if (req.user) return res.redirect('/');\n  res.render('account/signup', {\n    title: 'Create Account'\n  });\n};\n\n/**\n * POST /signup\n * Create a new local account.\n * @param email\n * @param password\n */\n\nexports.postSignup = function(req, res, next) {\n  req.assert('email', 'Email is not valid').isEmail();\n  req.assert('password', 'Password must be at least 4 characters long').len(4);\n  req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password);\n\n  var errors = req.validationErrors();\n\n  if (errors) {\n    return res.send(errors);\n  }\n\n  var user = new User({\n    email: req.body.email,\n    password: req.body.password\n  });\n\n  user.save(function(err) {\n    if (err) {\n      if (err.code === 11000) {\n        return res.send([{ msg: 'User with that email already exists.' }]);\n      }\n      res.status(500).send({msg: 'Unknown error on signup'});\n    }\n    req.logIn(user, function(err) {\n      if (err) return next(err);\n      return res.send({ msg: 'Successful signup' });\n    });\n  });\n};\n\n/**\n * GET /account\n * Profile page.\n */\n\nexports.getAccount = function(req, res) {\n  res.render('account/profile', {\n    title: 'Account Management'\n  });\n};\n\n/**\n * POST /account/profile\n * Update profile information.\n */\n\nexports.postUpdateProfile = function(req, res, next) {\n  User.findById(req.user.id, function(err, user) {\n    if (err) return next(err);\n    user.email = req.body.email || '';\n    user.profile.name = req.body.name || '';\n    user.profile.gender = req.body.gender || '';\n    user.profile.location = req.body.location || '';\n    user.profile.website = req.body.website || '';\n\n    user.save(function(err) {\n      if (err) return next(err);\n      req.flash('success', { msg: 'Profile information updated.' });\n      res.redirect('/account');\n    });\n  });\n};\n\n/**\n * POST /account/password\n * Update current password.\n * @param password\n */\n\nexports.postUpdatePassword = function(req, res, next) {\n  req.assert('password', 'Password must be at least 4 characters long').len(4);\n  req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password);\n\n  var errors = req.validationErrors();\n\n  if (errors) {\n    req.flash('errors', errors);\n    return res.redirect('/account');\n  }\n\n  User.findById(req.user.id, function(err, user) {\n    if (err) return next(err);\n\n    user.password = req.body.password;\n\n    user.save(function(err) {\n      if (err) return next(err);\n      req.flash('success', { msg: 'Password has been changed.' });\n      res.redirect('/account');\n    });\n  });\n};\n\n/**\n * POST /account/delete\n * Delete user account.\n * @param id - User ObjectId\n */\n\nexports.postDeleteAccount = function(req, res, next) {\n  User.remove({ _id: req.user.id }, function(err) {\n    if (err) return next(err);\n    req.logout();\n    res.redirect('/');\n  });\n};\n\n/**\n * GET /account/unlink/:provider\n * Unlink OAuth2 provider from the current user.\n * @param provider\n * @param id - User ObjectId\n */\n\nexports.getOauthUnlink = function(req, res, next) {\n  var provider = req.params.provider;\n  User.findById(req.user.id, function(err, user) {\n    if (err) return next(err);\n\n    user[provider] = undefined;\n    user.tokens = _.reject(user.tokens, function(token) { return token.kind === provider; });\n\n    user.save(function(err) {\n      if (err) return next(err);\n      req.flash('info', { msg: provider + ' account has been unlinked.' });\n      res.redirect('/account');\n    });\n  });\n};\n\n/**\n * GET /reset/:token\n * Reset Password page.\n */\n\nexports.getReset = function(req, res) {\n  if (req.isAuthenticated()) {\n    return res.redirect('/');\n  }\n\n  User\n    .findOne({ resetPasswordToken: req.params.token })\n    .where('resetPasswordExpires').gt(Date.now())\n    .exec(function(err, user) {\n      if (!user) {\n        req.flash('errors', { msg: 'Password reset token is invalid or has expired.' });\n        return res.redirect('/forgot');\n      }\n      res.render('account/reset', {\n        title: 'Password Reset'\n      });\n    });\n};\n\n/**\n * POST /reset/:token\n * Process the reset password request.\n */\n\nexports.postReset = function(req, res, next) {\n  req.assert('password', 'Password must be at least 4 characters long.').len(4);\n  req.assert('confirm', 'Passwords must match.').equals(req.body.password);\n\n  var errors = req.validationErrors();\n\n  if (errors) {\n    req.flash('errors', errors);\n    return res.redirect('back');\n  }\n\n  async.waterfall([\n    function(done) {\n      User\n        .findOne({ resetPasswordToken: req.params.token })\n        .where('resetPasswordExpires').gt(Date.now())\n        .exec(function(err, user) {\n          if (!user) {\n            req.flash('errors', { msg: 'Password reset token is invalid or has expired.' });\n            return res.redirect('back');\n          }\n\n          user.password = req.body.password;\n          user.resetPasswordToken = undefined;\n          user.resetPasswordExpires = undefined;\n\n          user.save(function(err) {\n            if (err) return next(err);\n            req.logIn(user, function(err) {\n              done(err, user);\n            });\n          });\n        });\n    },\n    function(user, done) {\n      var smtpTransport = nodemailer.createTransport('SMTP', {\n        service: 'SendGrid',\n        auth: {\n          user: secrets.sendgrid.user,\n          pass: secrets.sendgrid.password\n        }\n      });\n      var mailOptions = {\n        to: user.email,\n        from: 'hackathon@starter.com',\n        subject: 'Your Hackathon Starter password has been changed',\n        text: 'Hello,\\n\\n' +\n          'This is a confirmation that the password for your account ' + user.email + ' has just been changed.\\n'\n      };\n      smtpTransport.sendMail(mailOptions, function(err) {\n        req.flash('success', { msg: 'Success! Your password has been changed.' });\n        done(err);\n      });\n    }\n  ], function(err) {\n    if (err) return next(err);\n    res.redirect('/');\n  });\n};\n\n/**\n * GET /forgot\n * Forgot Password page.\n */\n\nexports.getForgot = function(req, res) {\n  if (req.isAuthenticated()) {\n    return res.redirect('/');\n  }\n  res.render('account/forgot', {\n    title: 'Forgot Password'\n  });\n};\n\n/**\n * POST /forgot\n * Create a random token, then the send user an email with a reset link.\n * @param email\n */\n\nexports.postForgot = function(req, res, next) {\n  req.assert('email', 'Please enter a valid email address.').isEmail();\n\n  var errors = req.validationErrors();\n\n  if (errors) {\n    req.flash('errors', errors);\n    return res.redirect('/forgot');\n  }\n\n  async.waterfall([\n    function(done) {\n      crypto.randomBytes(16, function(err, buf) {\n        var token = buf.toString('hex');\n        done(err, token);\n      });\n    },\n    function(token, done) {\n      User.findOne({ email: req.body.email.toLowerCase() }, function(err, user) {\n        if (!user) {\n          req.flash('errors', { msg: 'No account with that email address exists.' });\n          return res.redirect('/forgot');\n        }\n\n        user.resetPasswordToken = token;\n        user.resetPasswordExpires = Date.now() + 3600000; // 1 hour\n\n        user.save(function(err) {\n          done(err, token, user);\n        });\n      });\n    },\n    function(token, user, done) {\n      var smtpTransport = nodemailer.createTransport('SMTP', {\n        service: 'SendGrid',\n        auth: {\n          user: secrets.sendgrid.user,\n          pass: secrets.sendgrid.password\n        }\n      });\n      var mailOptions = {\n        to: user.email,\n        from: 'hackathon@starter.com',\n        subject: 'Reset your password on Hackathon Starter',\n        text: 'You are receiving this email because you (or someone else) have requested the reset of the password for your account.\\n\\n' +\n          'Please click on the following link, or paste this into your browser to complete the process:\\n\\n' +\n          'http://' + req.headers.host + '/reset/' + token + '\\n\\n' +\n          'If you did not request this, please ignore this email and your password will remain unchanged.\\n'\n      };\n      smtpTransport.sendMail(mailOptions, function(err) {\n        req.flash('info', { msg: 'An e-mail has been sent to ' + user.email + ' with further instructions.' });\n        done(err, 'done');\n      });\n    }\n  ], function(err) {\n    if (err) return next(err);\n    res.redirect('/forgot');\n  });\n};\n"
  },
  {
    "path": "server/controllers/workspaces.js",
    "content": ""
  },
  {
    "path": "server/models/Session.js",
    "content": ""
  },
  {
    "path": "server/models/User.js",
    "content": "var mongoose = require('mongoose');\nvar bcrypt = require('bcrypt-nodejs');\nvar crypto = require('crypto');\nvar models = require('./Workspace')\n\nvar userSchema = new mongoose.Schema({\n  \n  email: { type: String, unique: true, lowercase: true },\n  password: String,\n\n  facebook: String,\n  twitter: String,\n  google: String,\n  github: String,\n  linkedin: String,\n  tokens: Array,\n\n  profile: {\n    name: { type: String, default: '' },\n    gender: { type: String, default: '' },\n    location: { type: String, default: '' },\n    website: { type: String, default: '' },\n    picture: { type: String, default: '' }\n  },\n\n  resetPasswordToken: String,\n  resetPasswordExpires: Date,\n\n  lastSession: {type: mongoose.Schema.ObjectId, ref: 'Session' },\n  workspaces: [{type: mongoose.Schema.ObjectId, ref: 'Workspace' }]\n\n});\n\n/**\n * Hash the password for security.\n * \"Pre\" is a Mongoose middleware that executes before each user.save() call.\n */\n\nuserSchema.pre('save', function(next) {\n  var user = this;\n\n  if (!user.isModified('password')) return next();\n\n  bcrypt.genSalt(5, function(err, salt) {\n    if (err) return next(err);\n\n    bcrypt.hash(user.password, salt, null, function(err, hash) {\n      if (err) return next(err);\n      user.password = hash;\n      next();\n    });\n  });\n});\n\n/**\n * Validate user's password.\n * Used by Passport-Local Strategy for password validation.\n */\n\nuserSchema.methods.comparePassword = function(candidatePassword, cb) {\n  bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {\n    if (err) return cb(err);\n    cb(null, isMatch);\n  });\n};\n\n/**\n * Get URL to a user's gravatar.\n * Used in Navbar and Account Management page.\n */\n\nuserSchema.methods.gravatar = function(size, defaults) {\n  if (!size) size = 200;\n  if (!defaults) defaults = 'retro';\n\n  if (!this.email) {\n    return 'https://gravatar.com/avatar/?s=' + size + '&d=' + defaults;\n  }\n\n  var md5 = crypto.createHash('md5').update(this.email);\n  return 'https://gravatar.com/avatar/' + md5.digest('hex').toString() + '?s=' + size + '&d=' + defaults;\n};\n\nmodule.exports = mongoose.model('User', userSchema);\n"
  },
  {
    "path": "server/models/Workspace.js",
    "content": "var mongoose = require('mongoose')\n  , Schema = mongoose.Schema;\n\nvar sessionSchema = new Schema({\n  name: { type: String, default: '' }\n  , currentWorkspace: {type: Schema.ObjectId, ref: 'Workspace' }\n  , workspaces: [ {type: Schema.ObjectId, ref: 'Workspace' } ]\n  , lastSaved: Date\n  , isFirstExperience: { type: Boolean, default: true }\n});\n\nvar workspaceSchema = new Schema({\n  name: { type: String, default: '' }\n  , nodes: [ Schema.Types.Mixed ]\n  , connections: [ Schema.Types.Mixed ]\n  , selectedNodes: [ Schema.Types.Mixed ]\n  , isPublic: { type: Boolean, default: false }\n  , zoom: { type: Number, default: 1 }\n  , offset: [{ type: Number }]\n  , lastSaved: Date\n  , maintainers: [{type: Schema.ObjectId, ref: 'User' }]\n  , undoStack: [ Schema.Types.Mixed ]\n  , redoStack: [ Schema.Types.Mixed ]\n  , isEdited: { type: Boolean, default: false }\n  , isCustomNode: { type: Boolean, default: false }\n  , isCustomizer: { type: Boolean, default: false }\n  , workspaceDependencyIds: [{type: Schema.ObjectId, ref: 'Workspace' }]\n});\n\nexports.SessionModel = mongoose.model('Session', sessionSchema);\nexports.WorkspaceModel = mongoose.model('Workspace', workspaceSchema);\n"
  },
  {
    "path": "server/package.json",
    "content": "{\n  \"name\": \"flood-server\",\n  \"version\": \"0.0.0\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"\"\n  },\n  \"scripts\": {\n    \"start\": \"node app.js\",\n    \"test\": \"mocha\"\n  },\n  \"dependencies\": {\n    \"async\": \"^0.7.0\",\n    \"bcrypt-nodejs\": \"^0.0.3\",\n    \"body-parser\": \"^1.0.1\",\n    \"cheerio\": \"^0.15.0\",\n    \"clockwork\": \"^0.1.1\",\n    \"compression\": \"^1.0.1\",\n    \"connect-assets\": \"^3.0.0-beta2\",\n    \"connect-mongo\": \"^0.4.0\",\n    \"cookie-parser\": \"^1.0.1\",\n    \"csso\": \"^1.3.11\",\n    \"csurf\": \"^1.1.0\",\n    \"errorhandler\": \"^1.0.0\",\n    \"express\": \"^4.0.0\",\n    \"express-flash\": \"^0.0.2\",\n    \"express-session\": \"^1.0.2\",\n    \"express-validator\": \"^2.1.1\",\n    \"fbgraph\": \"^0.2.10\",\n    \"github-api\": \"^0.7.0\",\n    \"jade\": \"^1.3.0\",\n    \"lastfm\": \"^0.9.0\",\n    \"less\": \"^1.7.0\",\n    \"method-override\": \"^1.0.0\",\n    \"mongoose\": \"4.0.5\",\n    \"morgan\": \"^1.0.0\",\n    \"node-foursquare\": \"^0.2.0\",\n    \"node-linkedin\": \"^0.1.5\",\n    \"nodemailer\": \"^0.6.1\",\n    \"passport\": \"^0.2.0\",\n    \"passport-facebook\": \"^1.0.3\",\n    \"passport-github\": \"^0.1.5\",\n    \"passport-google-oauth\": \"^0.1.5\",\n    \"passport-linkedin-oauth2\": \"^1.1.1\",\n    \"passport-local\": \"^1.0.0\",\n    \"passport-oauth\": \"^1.0.0\",\n    \"passport-twitter\": \"^1.0.2\",\n    \"paypal-rest-sdk\": \"^0.7.0\",\n    \"request\": \"^2.34.0\",\n    \"static-favicon\": \"^1.0.2\",\n    \"tumblr.js\": \"^0.0.4\",\n    \"twilio\": \"^1.6.0\",\n    \"twit\": \"^1.1.12\",\n    \"uglify-js\": \"^2.4.12\",\n    \"underscore\": \"^1.6.0\",\n    \"validator\": \"^3.8.0\"\n  },\n  \"devDependencies\": {\n    \"mocha\": \"^1.18.2\",\n    \"chai\": \"^1.9.1\",\n    \"supertest\": \"^0.10.0\"\n  }\n}\n"
  },
  {
    "path": "server/public/css/lib/animate.css",
    "content": "@charset \"UTF-8\";\n\n\n/*!\nAnimate.css - http://daneden.me/animate\nLicensed under the MIT license\n\nCopyright (c) 2013 Daniel Eden\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n\n.animated {\n  -webkit-animation-duration: 1s;\n  animation-duration: 1s;\n  -webkit-animation-fill-mode: both;\n  animation-fill-mode: both;\n}\n\n.animated.hinge {\n  -webkit-animation-duration: 2s;\n  animation-duration: 2s;\n}\n\n@-webkit-keyframes bounce {\n  0%, 20%, 50%, 80%, 100% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  40% {\n    -webkit-transform: translateY(-30px);\n    transform: translateY(-30px);\n  }\n\n  60% {\n    -webkit-transform: translateY(-15px);\n    transform: translateY(-15px);\n  }\n}\n\n@keyframes bounce {\n  0%, 20%, 50%, 80%, 100% {\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  40% {\n    -webkit-transform: translateY(-30px);\n    -ms-transform: translateY(-30px);\n    transform: translateY(-30px);\n  }\n\n  60% {\n    -webkit-transform: translateY(-15px);\n    -ms-transform: translateY(-15px);\n    transform: translateY(-15px);\n  }\n}\n\n.bounce {\n  -webkit-animation-name: bounce;\n  animation-name: bounce;\n}\n\n@-webkit-keyframes flash {\n  0%, 50%, 100% {\n    opacity: 1;\n  }\n\n  25%, 75% {\n    opacity: 0;\n  }\n}\n\n@keyframes flash {\n  0%, 50%, 100% {\n    opacity: 1;\n  }\n\n  25%, 75% {\n    opacity: 0;\n  }\n}\n\n.flash {\n  -webkit-animation-name: flash;\n  animation-name: flash;\n}\n\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\n\n@-webkit-keyframes pulse {\n  0% {\n    -webkit-transform: scale(1);\n    transform: scale(1);\n  }\n\n  50% {\n    -webkit-transform: scale(1.1);\n    transform: scale(1.1);\n  }\n\n  100% {\n    -webkit-transform: scale(1);\n    transform: scale(1);\n  }\n}\n\n@keyframes pulse {\n  0% {\n    -webkit-transform: scale(1);\n    -ms-transform: scale(1);\n    transform: scale(1);\n  }\n\n  50% {\n    -webkit-transform: scale(1.1);\n    -ms-transform: scale(1.1);\n    transform: scale(1.1);\n  }\n\n  100% {\n    -webkit-transform: scale(1);\n    -ms-transform: scale(1);\n    transform: scale(1);\n  }\n}\n\n.pulse {\n  -webkit-animation-name: pulse;\n  animation-name: pulse;\n}\n\n@-webkit-keyframes shake {\n  0%, 100% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  10%, 30%, 50%, 70%, 90% {\n    -webkit-transform: translateX(-10px);\n    transform: translateX(-10px);\n  }\n\n  20%, 40%, 60%, 80% {\n    -webkit-transform: translateX(10px);\n    transform: translateX(10px);\n  }\n}\n\n@keyframes shake {\n  0%, 100% {\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  10%, 30%, 50%, 70%, 90% {\n    -webkit-transform: translateX(-10px);\n    -ms-transform: translateX(-10px);\n    transform: translateX(-10px);\n  }\n\n  20%, 40%, 60%, 80% {\n    -webkit-transform: translateX(10px);\n    -ms-transform: translateX(10px);\n    transform: translateX(10px);\n  }\n}\n\n.shake {\n  -webkit-animation-name: shake;\n  animation-name: shake;\n}\n\n@-webkit-keyframes swing {\n  20% {\n    -webkit-transform: rotate(15deg);\n    transform: rotate(15deg);\n  }\n\n  40% {\n    -webkit-transform: rotate(-10deg);\n    transform: rotate(-10deg);\n  }\n\n  60% {\n    -webkit-transform: rotate(5deg);\n    transform: rotate(5deg);\n  }\n\n  80% {\n    -webkit-transform: rotate(-5deg);\n    transform: rotate(-5deg);\n  }\n\n  100% {\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n}\n\n@keyframes swing {\n  20% {\n    -webkit-transform: rotate(15deg);\n    -ms-transform: rotate(15deg);\n    transform: rotate(15deg);\n  }\n\n  40% {\n    -webkit-transform: rotate(-10deg);\n    -ms-transform: rotate(-10deg);\n    transform: rotate(-10deg);\n  }\n\n  60% {\n    -webkit-transform: rotate(5deg);\n    -ms-transform: rotate(5deg);\n    transform: rotate(5deg);\n  }\n\n  80% {\n    -webkit-transform: rotate(-5deg);\n    -ms-transform: rotate(-5deg);\n    transform: rotate(-5deg);\n  }\n\n  100% {\n    -webkit-transform: rotate(0deg);\n    -ms-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n}\n\n.swing {\n  -webkit-transform-origin: top center;\n  -ms-transform-origin: top center;\n  transform-origin: top center;\n  -webkit-animation-name: swing;\n  animation-name: swing;\n}\n\n@-webkit-keyframes tada {\n  0% {\n    -webkit-transform: scale(1);\n    transform: scale(1);\n  }\n\n  10%, 20% {\n    -webkit-transform: scale(0.9) rotate(-3deg);\n    transform: scale(0.9) rotate(-3deg);\n  }\n\n  30%, 50%, 70%, 90% {\n    -webkit-transform: scale(1.1) rotate(3deg);\n    transform: scale(1.1) rotate(3deg);\n  }\n\n  40%, 60%, 80% {\n    -webkit-transform: scale(1.1) rotate(-3deg);\n    transform: scale(1.1) rotate(-3deg);\n  }\n\n  100% {\n    -webkit-transform: scale(1) rotate(0);\n    transform: scale(1) rotate(0);\n  }\n}\n\n@keyframes tada {\n  0% {\n    -webkit-transform: scale(1);\n    -ms-transform: scale(1);\n    transform: scale(1);\n  }\n\n  10%, 20% {\n    -webkit-transform: scale(0.9) rotate(-3deg);\n    -ms-transform: scale(0.9) rotate(-3deg);\n    transform: scale(0.9) rotate(-3deg);\n  }\n\n  30%, 50%, 70%, 90% {\n    -webkit-transform: scale(1.1) rotate(3deg);\n    -ms-transform: scale(1.1) rotate(3deg);\n    transform: scale(1.1) rotate(3deg);\n  }\n\n  40%, 60%, 80% {\n    -webkit-transform: scale(1.1) rotate(-3deg);\n    -ms-transform: scale(1.1) rotate(-3deg);\n    transform: scale(1.1) rotate(-3deg);\n  }\n\n  100% {\n    -webkit-transform: scale(1) rotate(0);\n    -ms-transform: scale(1) rotate(0);\n    transform: scale(1) rotate(0);\n  }\n}\n\n.tada {\n  -webkit-animation-name: tada;\n  animation-name: tada;\n}\n\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\n\n@-webkit-keyframes wobble {\n  0% {\n    -webkit-transform: translateX(0%);\n    transform: translateX(0%);\n  }\n\n  15% {\n    -webkit-transform: translateX(-25%) rotate(-5deg);\n    transform: translateX(-25%) rotate(-5deg);\n  }\n\n  30% {\n    -webkit-transform: translateX(20%) rotate(3deg);\n    transform: translateX(20%) rotate(3deg);\n  }\n\n  45% {\n    -webkit-transform: translateX(-15%) rotate(-3deg);\n    transform: translateX(-15%) rotate(-3deg);\n  }\n\n  60% {\n    -webkit-transform: translateX(10%) rotate(2deg);\n    transform: translateX(10%) rotate(2deg);\n  }\n\n  75% {\n    -webkit-transform: translateX(-5%) rotate(-1deg);\n    transform: translateX(-5%) rotate(-1deg);\n  }\n\n  100% {\n    -webkit-transform: translateX(0%);\n    transform: translateX(0%);\n  }\n}\n\n@keyframes wobble {\n  0% {\n    -webkit-transform: translateX(0%);\n    -ms-transform: translateX(0%);\n    transform: translateX(0%);\n  }\n\n  15% {\n    -webkit-transform: translateX(-25%) rotate(-5deg);\n    -ms-transform: translateX(-25%) rotate(-5deg);\n    transform: translateX(-25%) rotate(-5deg);\n  }\n\n  30% {\n    -webkit-transform: translateX(20%) rotate(3deg);\n    -ms-transform: translateX(20%) rotate(3deg);\n    transform: translateX(20%) rotate(3deg);\n  }\n\n  45% {\n    -webkit-transform: translateX(-15%) rotate(-3deg);\n    -ms-transform: translateX(-15%) rotate(-3deg);\n    transform: translateX(-15%) rotate(-3deg);\n  }\n\n  60% {\n    -webkit-transform: translateX(10%) rotate(2deg);\n    -ms-transform: translateX(10%) rotate(2deg);\n    transform: translateX(10%) rotate(2deg);\n  }\n\n  75% {\n    -webkit-transform: translateX(-5%) rotate(-1deg);\n    -ms-transform: translateX(-5%) rotate(-1deg);\n    transform: translateX(-5%) rotate(-1deg);\n  }\n\n  100% {\n    -webkit-transform: translateX(0%);\n    -ms-transform: translateX(0%);\n    transform: translateX(0%);\n  }\n}\n\n.wobble {\n  -webkit-animation-name: wobble;\n  animation-name: wobble;\n}\n\n@-webkit-keyframes bounceIn {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(.3);\n    transform: scale(.3);\n  }\n\n  50% {\n    opacity: 1;\n    -webkit-transform: scale(1.05);\n    transform: scale(1.05);\n  }\n\n  70% {\n    -webkit-transform: scale(.9);\n    transform: scale(.9);\n  }\n\n  100% {\n    -webkit-transform: scale(1);\n    transform: scale(1);\n  }\n}\n\n@keyframes bounceIn {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(.3);\n    -ms-transform: scale(.3);\n    transform: scale(.3);\n  }\n\n  50% {\n    opacity: 1;\n    -webkit-transform: scale(1.05);\n    -ms-transform: scale(1.05);\n    transform: scale(1.05);\n  }\n\n  70% {\n    -webkit-transform: scale(.9);\n    -ms-transform: scale(.9);\n    transform: scale(.9);\n  }\n\n  100% {\n    -webkit-transform: scale(1);\n    -ms-transform: scale(1);\n    transform: scale(1);\n  }\n}\n\n.bounceIn {\n  -webkit-animation-name: bounceIn;\n  animation-name: bounceIn;\n}\n\n@-webkit-keyframes bounceInDown {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-2000px);\n    transform: translateY(-2000px);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translateY(30px);\n    transform: translateY(30px);\n  }\n\n  80% {\n    -webkit-transform: translateY(-10px);\n    transform: translateY(-10px);\n  }\n\n  100% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n@keyframes bounceInDown {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-2000px);\n    -ms-transform: translateY(-2000px);\n    transform: translateY(-2000px);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translateY(30px);\n    -ms-transform: translateY(30px);\n    transform: translateY(30px);\n  }\n\n  80% {\n    -webkit-transform: translateY(-10px);\n    -ms-transform: translateY(-10px);\n    transform: translateY(-10px);\n  }\n\n  100% {\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n.bounceInDown {\n  -webkit-animation-name: bounceInDown;\n  animation-name: bounceInDown;\n}\n\n@-webkit-keyframes bounceInLeft {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-2000px);\n    transform: translateX(-2000px);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translateX(30px);\n    transform: translateX(30px);\n  }\n\n  80% {\n    -webkit-transform: translateX(-10px);\n    transform: translateX(-10px);\n  }\n\n  100% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n@keyframes bounceInLeft {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-2000px);\n    -ms-transform: translateX(-2000px);\n    transform: translateX(-2000px);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translateX(30px);\n    -ms-transform: translateX(30px);\n    transform: translateX(30px);\n  }\n\n  80% {\n    -webkit-transform: translateX(-10px);\n    -ms-transform: translateX(-10px);\n    transform: translateX(-10px);\n  }\n\n  100% {\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n.bounceInLeft {\n  -webkit-animation-name: bounceInLeft;\n  animation-name: bounceInLeft;\n}\n\n@-webkit-keyframes bounceInRight {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(2000px);\n    transform: translateX(2000px);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translateX(-30px);\n    transform: translateX(-30px);\n  }\n\n  80% {\n    -webkit-transform: translateX(10px);\n    transform: translateX(10px);\n  }\n\n  100% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n@keyframes bounceInRight {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(2000px);\n    -ms-transform: translateX(2000px);\n    transform: translateX(2000px);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translateX(-30px);\n    -ms-transform: translateX(-30px);\n    transform: translateX(-30px);\n  }\n\n  80% {\n    -webkit-transform: translateX(10px);\n    -ms-transform: translateX(10px);\n    transform: translateX(10px);\n  }\n\n  100% {\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n.bounceInRight {\n  -webkit-animation-name: bounceInRight;\n  animation-name: bounceInRight;\n}\n\n@-webkit-keyframes bounceInUp {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(2000px);\n    transform: translateY(2000px);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translateY(-30px);\n    transform: translateY(-30px);\n  }\n\n  80% {\n    -webkit-transform: translateY(10px);\n    transform: translateY(10px);\n  }\n\n  100% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n@keyframes bounceInUp {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(2000px);\n    -ms-transform: translateY(2000px);\n    transform: translateY(2000px);\n  }\n\n  60% {\n    opacity: 1;\n    -webkit-transform: translateY(-30px);\n    -ms-transform: translateY(-30px);\n    transform: translateY(-30px);\n  }\n\n  80% {\n    -webkit-transform: translateY(10px);\n    -ms-transform: translateY(10px);\n    transform: translateY(10px);\n  }\n\n  100% {\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n.bounceInUp {\n  -webkit-animation-name: bounceInUp;\n  animation-name: bounceInUp;\n}\n\n@-webkit-keyframes bounceOut {\n  0% {\n    -webkit-transform: scale(1);\n    transform: scale(1);\n  }\n\n  25% {\n    -webkit-transform: scale(.95);\n    transform: scale(.95);\n  }\n\n  50% {\n    opacity: 1;\n    -webkit-transform: scale(1.1);\n    transform: scale(1.1);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: scale(.3);\n    transform: scale(.3);\n  }\n}\n\n@keyframes bounceOut {\n  0% {\n    -webkit-transform: scale(1);\n    -ms-transform: scale(1);\n    transform: scale(1);\n  }\n\n  25% {\n    -webkit-transform: scale(.95);\n    -ms-transform: scale(.95);\n    transform: scale(.95);\n  }\n\n  50% {\n    opacity: 1;\n    -webkit-transform: scale(1.1);\n    -ms-transform: scale(1.1);\n    transform: scale(1.1);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: scale(.3);\n    -ms-transform: scale(.3);\n    transform: scale(.3);\n  }\n}\n\n.bounceOut {\n  -webkit-animation-name: bounceOut;\n  animation-name: bounceOut;\n}\n\n@-webkit-keyframes bounceOutDown {\n  0% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  20% {\n    opacity: 1;\n    -webkit-transform: translateY(-20px);\n    transform: translateY(-20px);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(2000px);\n    transform: translateY(2000px);\n  }\n}\n\n@keyframes bounceOutDown {\n  0% {\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  20% {\n    opacity: 1;\n    -webkit-transform: translateY(-20px);\n    -ms-transform: translateY(-20px);\n    transform: translateY(-20px);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(2000px);\n    -ms-transform: translateY(2000px);\n    transform: translateY(2000px);\n  }\n}\n\n.bounceOutDown {\n  -webkit-animation-name: bounceOutDown;\n  animation-name: bounceOutDown;\n}\n\n@-webkit-keyframes bounceOutLeft {\n  0% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  20% {\n    opacity: 1;\n    -webkit-transform: translateX(20px);\n    transform: translateX(20px);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(-2000px);\n    transform: translateX(-2000px);\n  }\n}\n\n@keyframes bounceOutLeft {\n  0% {\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  20% {\n    opacity: 1;\n    -webkit-transform: translateX(20px);\n    -ms-transform: translateX(20px);\n    transform: translateX(20px);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(-2000px);\n    -ms-transform: translateX(-2000px);\n    transform: translateX(-2000px);\n  }\n}\n\n.bounceOutLeft {\n  -webkit-animation-name: bounceOutLeft;\n  animation-name: bounceOutLeft;\n}\n\n@-webkit-keyframes bounceOutRight {\n  0% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  20% {\n    opacity: 1;\n    -webkit-transform: translateX(-20px);\n    transform: translateX(-20px);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(2000px);\n    transform: translateX(2000px);\n  }\n}\n\n@keyframes bounceOutRight {\n  0% {\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  20% {\n    opacity: 1;\n    -webkit-transform: translateX(-20px);\n    -ms-transform: translateX(-20px);\n    transform: translateX(-20px);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(2000px);\n    -ms-transform: translateX(2000px);\n    transform: translateX(2000px);\n  }\n}\n\n.bounceOutRight {\n  -webkit-animation-name: bounceOutRight;\n  animation-name: bounceOutRight;\n}\n\n@-webkit-keyframes bounceOutUp {\n  0% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  20% {\n    opacity: 1;\n    -webkit-transform: translateY(20px);\n    transform: translateY(20px);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-2000px);\n    transform: translateY(-2000px);\n  }\n}\n\n@keyframes bounceOutUp {\n  0% {\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  20% {\n    opacity: 1;\n    -webkit-transform: translateY(20px);\n    -ms-transform: translateY(20px);\n    transform: translateY(20px);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-2000px);\n    -ms-transform: translateY(-2000px);\n    transform: translateY(-2000px);\n  }\n}\n\n.bounceOutUp {\n  -webkit-animation-name: bounceOutUp;\n  animation-name: bounceOutUp;\n}\n\n@-webkit-keyframes fadeIn {\n  0% {\n    opacity: 0;\n  }\n\n  100% {\n    opacity: 1;\n  }\n}\n\n@keyframes fadeIn {\n  0% {\n    opacity: 0;\n  }\n\n  100% {\n    opacity: 1;\n  }\n}\n\n.fadeIn {\n  -webkit-animation-name: fadeIn;\n  animation-name: fadeIn;\n}\n\n@-webkit-keyframes fadeInDown {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-20px);\n    transform: translateY(-20px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n@keyframes fadeInDown {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-20px);\n    -ms-transform: translateY(-20px);\n    transform: translateY(-20px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n.fadeInDown {\n  -webkit-animation-name: fadeInDown;\n  animation-name: fadeInDown;\n}\n\n@-webkit-keyframes fadeInDownBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-2000px);\n    transform: translateY(-2000px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n@keyframes fadeInDownBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-2000px);\n    -ms-transform: translateY(-2000px);\n    transform: translateY(-2000px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n.fadeInDownBig {\n  -webkit-animation-name: fadeInDownBig;\n  animation-name: fadeInDownBig;\n}\n\n@-webkit-keyframes fadeInLeft {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-20px);\n    transform: translateX(-20px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n@keyframes fadeInLeft {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-20px);\n    -ms-transform: translateX(-20px);\n    transform: translateX(-20px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n.fadeInLeft {\n  -webkit-animation-name: fadeInLeft;\n  animation-name: fadeInLeft;\n}\n\n@-webkit-keyframes fadeInLeftBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-2000px);\n    transform: translateX(-2000px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n@keyframes fadeInLeftBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-2000px);\n    -ms-transform: translateX(-2000px);\n    transform: translateX(-2000px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n.fadeInLeftBig {\n  -webkit-animation-name: fadeInLeftBig;\n  animation-name: fadeInLeftBig;\n}\n\n@-webkit-keyframes fadeInRight {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(20px);\n    transform: translateX(20px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n@keyframes fadeInRight {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(20px);\n    -ms-transform: translateX(20px);\n    transform: translateX(20px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n.fadeInRight {\n  -webkit-animation-name: fadeInRight;\n  animation-name: fadeInRight;\n}\n\n@-webkit-keyframes fadeInRightBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(2000px);\n    transform: translateX(2000px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n@keyframes fadeInRightBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(2000px);\n    -ms-transform: translateX(2000px);\n    transform: translateX(2000px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n.fadeInRightBig {\n  -webkit-animation-name: fadeInRightBig;\n  animation-name: fadeInRightBig;\n}\n\n@-webkit-keyframes fadeInUp {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(20px);\n    transform: translateY(20px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n@keyframes fadeInUp {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(20px);\n    -ms-transform: translateY(20px);\n    transform: translateY(20px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n.fadeInUp {\n  -webkit-animation-name: fadeInUp;\n  animation-name: fadeInUp;\n}\n\n@-webkit-keyframes fadeInUpBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(2000px);\n    transform: translateY(2000px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n@keyframes fadeInUpBig {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(2000px);\n    -ms-transform: translateY(2000px);\n    transform: translateY(2000px);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n.fadeInUpBig {\n  -webkit-animation-name: fadeInUpBig;\n  animation-name: fadeInUpBig;\n}\n\n@-webkit-keyframes fadeOut {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n  }\n}\n\n@keyframes fadeOut {\n  0% {\n    opacity: 1;\n  }\n\n  100% {\n    opacity: 0;\n  }\n}\n\n.fadeOut {\n  -webkit-animation-name: fadeOut;\n  animation-name: fadeOut;\n}\n\n@-webkit-keyframes fadeOutDown {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(20px);\n    transform: translateY(20px);\n  }\n}\n\n@keyframes fadeOutDown {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(20px);\n    -ms-transform: translateY(20px);\n    transform: translateY(20px);\n  }\n}\n\n.fadeOutDown {\n  -webkit-animation-name: fadeOutDown;\n  animation-name: fadeOutDown;\n}\n\n@-webkit-keyframes fadeOutDownBig {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(2000px);\n    transform: translateY(2000px);\n  }\n}\n\n@keyframes fadeOutDownBig {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(2000px);\n    -ms-transform: translateY(2000px);\n    transform: translateY(2000px);\n  }\n}\n\n.fadeOutDownBig {\n  -webkit-animation-name: fadeOutDownBig;\n  animation-name: fadeOutDownBig;\n}\n\n@-webkit-keyframes fadeOutLeft {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(-20px);\n    transform: translateX(-20px);\n  }\n}\n\n@keyframes fadeOutLeft {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(-20px);\n    -ms-transform: translateX(-20px);\n    transform: translateX(-20px);\n  }\n}\n\n.fadeOutLeft {\n  -webkit-animation-name: fadeOutLeft;\n  animation-name: fadeOutLeft;\n}\n\n@-webkit-keyframes fadeOutLeftBig {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(-2000px);\n    transform: translateX(-2000px);\n  }\n}\n\n@keyframes fadeOutLeftBig {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(-2000px);\n    -ms-transform: translateX(-2000px);\n    transform: translateX(-2000px);\n  }\n}\n\n.fadeOutLeftBig {\n  -webkit-animation-name: fadeOutLeftBig;\n  animation-name: fadeOutLeftBig;\n}\n\n@-webkit-keyframes fadeOutRight {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(20px);\n    transform: translateX(20px);\n  }\n}\n\n@keyframes fadeOutRight {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(20px);\n    -ms-transform: translateX(20px);\n    transform: translateX(20px);\n  }\n}\n\n.fadeOutRight {\n  -webkit-animation-name: fadeOutRight;\n  animation-name: fadeOutRight;\n}\n\n@-webkit-keyframes fadeOutRightBig {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(2000px);\n    transform: translateX(2000px);\n  }\n}\n\n@keyframes fadeOutRightBig {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(2000px);\n    -ms-transform: translateX(2000px);\n    transform: translateX(2000px);\n  }\n}\n\n.fadeOutRightBig {\n  -webkit-animation-name: fadeOutRightBig;\n  animation-name: fadeOutRightBig;\n}\n\n@-webkit-keyframes fadeOutUp {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-20px);\n    transform: translateY(-20px);\n  }\n}\n\n@keyframes fadeOutUp {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-20px);\n    -ms-transform: translateY(-20px);\n    transform: translateY(-20px);\n  }\n}\n\n.fadeOutUp {\n  -webkit-animation-name: fadeOutUp;\n  animation-name: fadeOutUp;\n}\n\n@-webkit-keyframes fadeOutUpBig {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-2000px);\n    transform: translateY(-2000px);\n  }\n}\n\n@keyframes fadeOutUpBig {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-2000px);\n    -ms-transform: translateY(-2000px);\n    transform: translateY(-2000px);\n  }\n}\n\n.fadeOutUpBig {\n  -webkit-animation-name: fadeOutUpBig;\n  animation-name: fadeOutUpBig;\n}\n\n@-webkit-keyframes flip {\n  0% {\n    -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\n    transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\n    -webkit-animation-timing-function: ease-out;\n    animation-timing-function: ease-out;\n  }\n\n  40% {\n    -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\n    transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\n    -webkit-animation-timing-function: ease-out;\n    animation-timing-function: ease-out;\n  }\n\n  50% {\n    -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n    transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n    -webkit-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n  }\n\n  80% {\n    -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\n    -webkit-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n  }\n\n  100% {\n    -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\n    -webkit-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n  }\n}\n\n@keyframes flip {\n  0% {\n    -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\n    -ms-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\n    transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\n    -webkit-animation-timing-function: ease-out;\n    animation-timing-function: ease-out;\n  }\n\n  40% {\n    -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\n    -ms-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\n    transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\n    -webkit-animation-timing-function: ease-out;\n    animation-timing-function: ease-out;\n  }\n\n  50% {\n    -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n    -ms-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n    transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n    -webkit-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n  }\n\n  80% {\n    -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\n    -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\n    -webkit-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n  }\n\n  100% {\n    -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\n    -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\n    -webkit-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n  }\n}\n\n.animated.flip {\n  -webkit-backface-visibility: visible;\n  -ms-backface-visibility: visible;\n  backface-visibility: visible;\n  -webkit-animation-name: flip;\n  animation-name: flip;\n}\n\n@-webkit-keyframes flipInX {\n  0% {\n    -webkit-transform: perspective(400px) rotateX(90deg);\n    transform: perspective(400px) rotateX(90deg);\n    opacity: 0;\n  }\n\n  40% {\n    -webkit-transform: perspective(400px) rotateX(-10deg);\n    transform: perspective(400px) rotateX(-10deg);\n  }\n\n  70% {\n    -webkit-transform: perspective(400px) rotateX(10deg);\n    transform: perspective(400px) rotateX(10deg);\n  }\n\n  100% {\n    -webkit-transform: perspective(400px) rotateX(0deg);\n    transform: perspective(400px) rotateX(0deg);\n    opacity: 1;\n  }\n}\n\n@keyframes flipInX {\n  0% {\n    -webkit-transform: perspective(400px) rotateX(90deg);\n    -ms-transform: perspective(400px) rotateX(90deg);\n    transform: perspective(400px) rotateX(90deg);\n    opacity: 0;\n  }\n\n  40% {\n    -webkit-transform: perspective(400px) rotateX(-10deg);\n    -ms-transform: perspective(400px) rotateX(-10deg);\n    transform: perspective(400px) rotateX(-10deg);\n  }\n\n  70% {\n    -webkit-transform: perspective(400px) rotateX(10deg);\n    -ms-transform: perspective(400px) rotateX(10deg);\n    transform: perspective(400px) rotateX(10deg);\n  }\n\n  100% {\n    -webkit-transform: perspective(400px) rotateX(0deg);\n    -ms-transform: perspective(400px) rotateX(0deg);\n    transform: perspective(400px) rotateX(0deg);\n    opacity: 1;\n  }\n}\n\n.flipInX {\n  -webkit-backface-visibility: visible !important;\n  -ms-backface-visibility: visible !important;\n  backface-visibility: visible !important;\n  -webkit-animation-name: flipInX;\n  animation-name: flipInX;\n}\n\n@-webkit-keyframes flipInY {\n  0% {\n    -webkit-transform: perspective(400px) rotateY(90deg);\n    transform: perspective(400px) rotateY(90deg);\n    opacity: 0;\n  }\n\n  40% {\n    -webkit-transform: perspective(400px) rotateY(-10deg);\n    transform: perspective(400px) rotateY(-10deg);\n  }\n\n  70% {\n    -webkit-transform: perspective(400px) rotateY(10deg);\n    transform: perspective(400px) rotateY(10deg);\n  }\n\n  100% {\n    -webkit-transform: perspective(400px) rotateY(0deg);\n    transform: perspective(400px) rotateY(0deg);\n    opacity: 1;\n  }\n}\n\n@keyframes flipInY {\n  0% {\n    -webkit-transform: perspective(400px) rotateY(90deg);\n    -ms-transform: perspective(400px) rotateY(90deg);\n    transform: perspective(400px) rotateY(90deg);\n    opacity: 0;\n  }\n\n  40% {\n    -webkit-transform: perspective(400px) rotateY(-10deg);\n    -ms-transform: perspective(400px) rotateY(-10deg);\n    transform: perspective(400px) rotateY(-10deg);\n  }\n\n  70% {\n    -webkit-transform: perspective(400px) rotateY(10deg);\n    -ms-transform: perspective(400px) rotateY(10deg);\n    transform: perspective(400px) rotateY(10deg);\n  }\n\n  100% {\n    -webkit-transform: perspective(400px) rotateY(0deg);\n    -ms-transform: perspective(400px) rotateY(0deg);\n    transform: perspective(400px) rotateY(0deg);\n    opacity: 1;\n  }\n}\n\n.flipInY {\n  -webkit-backface-visibility: visible !important;\n  -ms-backface-visibility: visible !important;\n  backface-visibility: visible !important;\n  -webkit-animation-name: flipInY;\n  animation-name: flipInY;\n}\n\n@-webkit-keyframes flipOutX {\n  0% {\n    -webkit-transform: perspective(400px) rotateX(0deg);\n    transform: perspective(400px) rotateX(0deg);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: perspective(400px) rotateX(90deg);\n    transform: perspective(400px) rotateX(90deg);\n    opacity: 0;\n  }\n}\n\n@keyframes flipOutX {\n  0% {\n    -webkit-transform: perspective(400px) rotateX(0deg);\n    -ms-transform: perspective(400px) rotateX(0deg);\n    transform: perspective(400px) rotateX(0deg);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: perspective(400px) rotateX(90deg);\n    -ms-transform: perspective(400px) rotateX(90deg);\n    transform: perspective(400px) rotateX(90deg);\n    opacity: 0;\n  }\n}\n\n.flipOutX {\n  -webkit-animation-name: flipOutX;\n  animation-name: flipOutX;\n  -webkit-backface-visibility: visible !important;\n  -ms-backface-visibility: visible !important;\n  backface-visibility: visible !important;\n}\n\n@-webkit-keyframes flipOutY {\n  0% {\n    -webkit-transform: perspective(400px) rotateY(0deg);\n    transform: perspective(400px) rotateY(0deg);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: perspective(400px) rotateY(90deg);\n    transform: perspective(400px) rotateY(90deg);\n    opacity: 0;\n  }\n}\n\n@keyframes flipOutY {\n  0% {\n    -webkit-transform: perspective(400px) rotateY(0deg);\n    -ms-transform: perspective(400px) rotateY(0deg);\n    transform: perspective(400px) rotateY(0deg);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: perspective(400px) rotateY(90deg);\n    -ms-transform: perspective(400px) rotateY(90deg);\n    transform: perspective(400px) rotateY(90deg);\n    opacity: 0;\n  }\n}\n\n.flipOutY {\n  -webkit-backface-visibility: visible !important;\n  -ms-backface-visibility: visible !important;\n  backface-visibility: visible !important;\n  -webkit-animation-name: flipOutY;\n  animation-name: flipOutY;\n}\n\n@-webkit-keyframes lightSpeedIn {\n  0% {\n    -webkit-transform: translateX(100%) skewX(-30deg);\n    transform: translateX(100%) skewX(-30deg);\n    opacity: 0;\n  }\n\n  60% {\n    -webkit-transform: translateX(-20%) skewX(30deg);\n    transform: translateX(-20%) skewX(30deg);\n    opacity: 1;\n  }\n\n  80% {\n    -webkit-transform: translateX(0%) skewX(-15deg);\n    transform: translateX(0%) skewX(-15deg);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: translateX(0%) skewX(0deg);\n    transform: translateX(0%) skewX(0deg);\n    opacity: 1;\n  }\n}\n\n@keyframes lightSpeedIn {\n  0% {\n    -webkit-transform: translateX(100%) skewX(-30deg);\n    -ms-transform: translateX(100%) skewX(-30deg);\n    transform: translateX(100%) skewX(-30deg);\n    opacity: 0;\n  }\n\n  60% {\n    -webkit-transform: translateX(-20%) skewX(30deg);\n    -ms-transform: translateX(-20%) skewX(30deg);\n    transform: translateX(-20%) skewX(30deg);\n    opacity: 1;\n  }\n\n  80% {\n    -webkit-transform: translateX(0%) skewX(-15deg);\n    -ms-transform: translateX(0%) skewX(-15deg);\n    transform: translateX(0%) skewX(-15deg);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: translateX(0%) skewX(0deg);\n    -ms-transform: translateX(0%) skewX(0deg);\n    transform: translateX(0%) skewX(0deg);\n    opacity: 1;\n  }\n}\n\n.lightSpeedIn {\n  -webkit-animation-name: lightSpeedIn;\n  animation-name: lightSpeedIn;\n  -webkit-animation-timing-function: ease-out;\n  animation-timing-function: ease-out;\n}\n\n@-webkit-keyframes lightSpeedOut {\n  0% {\n    -webkit-transform: translateX(0%) skewX(0deg);\n    transform: translateX(0%) skewX(0deg);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: translateX(100%) skewX(-30deg);\n    transform: translateX(100%) skewX(-30deg);\n    opacity: 0;\n  }\n}\n\n@keyframes lightSpeedOut {\n  0% {\n    -webkit-transform: translateX(0%) skewX(0deg);\n    -ms-transform: translateX(0%) skewX(0deg);\n    transform: translateX(0%) skewX(0deg);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform: translateX(100%) skewX(-30deg);\n    -ms-transform: translateX(100%) skewX(-30deg);\n    transform: translateX(100%) skewX(-30deg);\n    opacity: 0;\n  }\n}\n\n.lightSpeedOut {\n  -webkit-animation-name: lightSpeedOut;\n  animation-name: lightSpeedOut;\n  -webkit-animation-timing-function: ease-in;\n  animation-timing-function: ease-in;\n}\n\n@-webkit-keyframes rotateIn {\n  0% {\n    -webkit-transform-origin: center center;\n    transform-origin: center center;\n    -webkit-transform: rotate(-200deg);\n    transform: rotate(-200deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: center center;\n    transform-origin: center center;\n    -webkit-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n\n@keyframes rotateIn {\n  0% {\n    -webkit-transform-origin: center center;\n    -ms-transform-origin: center center;\n    transform-origin: center center;\n    -webkit-transform: rotate(-200deg);\n    -ms-transform: rotate(-200deg);\n    transform: rotate(-200deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: center center;\n    -ms-transform-origin: center center;\n    transform-origin: center center;\n    -webkit-transform: rotate(0);\n    -ms-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n\n.rotateIn {\n  -webkit-animation-name: rotateIn;\n  animation-name: rotateIn;\n}\n\n@-webkit-keyframes rotateInDownLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate(-90deg);\n    transform: rotate(-90deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n\n@keyframes rotateInDownLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    -ms-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate(-90deg);\n    -ms-transform: rotate(-90deg);\n    transform: rotate(-90deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: left bottom;\n    -ms-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate(0);\n    -ms-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n\n.rotateInDownLeft {\n  -webkit-animation-name: rotateInDownLeft;\n  animation-name: rotateInDownLeft;\n}\n\n@-webkit-keyframes rotateInDownRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(90deg);\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n\n@keyframes rotateInDownRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    -ms-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(90deg);\n    -ms-transform: rotate(90deg);\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    -ms-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(0);\n    -ms-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n\n.rotateInDownRight {\n  -webkit-animation-name: rotateInDownRight;\n  animation-name: rotateInDownRight;\n}\n\n@-webkit-keyframes rotateInUpLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate(90deg);\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n\n@keyframes rotateInUpLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    -ms-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate(90deg);\n    -ms-transform: rotate(90deg);\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: left bottom;\n    -ms-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate(0);\n    -ms-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n\n.rotateInUpLeft {\n  -webkit-animation-name: rotateInUpLeft;\n  animation-name: rotateInUpLeft;\n}\n\n@-webkit-keyframes rotateInUpRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(-90deg);\n    transform: rotate(-90deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n\n@keyframes rotateInUpRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    -ms-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(-90deg);\n    -ms-transform: rotate(-90deg);\n    transform: rotate(-90deg);\n    opacity: 0;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    -ms-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(0);\n    -ms-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n\n.rotateInUpRight {\n  -webkit-animation-name: rotateInUpRight;\n  animation-name: rotateInUpRight;\n}\n\n@-webkit-keyframes rotateOut {\n  0% {\n    -webkit-transform-origin: center center;\n    transform-origin: center center;\n    -webkit-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: center center;\n    transform-origin: center center;\n    -webkit-transform: rotate(200deg);\n    transform: rotate(200deg);\n    opacity: 0;\n  }\n}\n\n@keyframes rotateOut {\n  0% {\n    -webkit-transform-origin: center center;\n    -ms-transform-origin: center center;\n    transform-origin: center center;\n    -webkit-transform: rotate(0);\n    -ms-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: center center;\n    -ms-transform-origin: center center;\n    transform-origin: center center;\n    -webkit-transform: rotate(200deg);\n    -ms-transform: rotate(200deg);\n    transform: rotate(200deg);\n    opacity: 0;\n  }\n}\n\n.rotateOut {\n  -webkit-animation-name: rotateOut;\n  animation-name: rotateOut;\n}\n\n@-webkit-keyframes rotateOutDownLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate(90deg);\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n}\n\n@keyframes rotateOutDownLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    -ms-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate(0);\n    -ms-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: left bottom;\n    -ms-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate(90deg);\n    -ms-transform: rotate(90deg);\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n}\n\n.rotateOutDownLeft {\n  -webkit-animation-name: rotateOutDownLeft;\n  animation-name: rotateOutDownLeft;\n}\n\n@-webkit-keyframes rotateOutDownRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(-90deg);\n    transform: rotate(-90deg);\n    opacity: 0;\n  }\n}\n\n@keyframes rotateOutDownRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    -ms-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(0);\n    -ms-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    -ms-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(-90deg);\n    -ms-transform: rotate(-90deg);\n    transform: rotate(-90deg);\n    opacity: 0;\n  }\n}\n\n.rotateOutDownRight {\n  -webkit-animation-name: rotateOutDownRight;\n  animation-name: rotateOutDownRight;\n}\n\n@-webkit-keyframes rotateOutUpLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n\n  100% {\n    -transform-origin: left bottom;\n    -transform: rotate(-90deg);\n    opacity: 0;\n  }\n}\n\n@keyframes rotateOutUpLeft {\n  0% {\n    -webkit-transform-origin: left bottom;\n    -ms-transform-origin: left bottom;\n    transform-origin: left bottom;\n    -webkit-transform: rotate(0);\n    -ms-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n\n  100% {\n    -transform-origin: left bottom;\n    -transform: rotate(-90deg);\n    opacity: 0;\n  }\n}\n\n.rotateOutUpLeft {\n  -webkit-animation-name: rotateOutUpLeft;\n  animation-name: rotateOutUpLeft;\n}\n\n@-webkit-keyframes rotateOutUpRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(90deg);\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n}\n\n@keyframes rotateOutUpRight {\n  0% {\n    -webkit-transform-origin: right bottom;\n    -ms-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(0);\n    -ms-transform: rotate(0);\n    transform: rotate(0);\n    opacity: 1;\n  }\n\n  100% {\n    -webkit-transform-origin: right bottom;\n    -ms-transform-origin: right bottom;\n    transform-origin: right bottom;\n    -webkit-transform: rotate(90deg);\n    -ms-transform: rotate(90deg);\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n}\n\n.rotateOutUpRight {\n  -webkit-animation-name: rotateOutUpRight;\n  animation-name: rotateOutUpRight;\n}\n\n@-webkit-keyframes slideInDown {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-2000px);\n    transform: translateY(-2000px);\n  }\n\n  100% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n@keyframes slideInDown {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-2000px);\n    -ms-transform: translateY(-2000px);\n    transform: translateY(-2000px);\n  }\n\n  100% {\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n}\n\n.slideInDown {\n  -webkit-animation-name: slideInDown;\n  animation-name: slideInDown;\n}\n\n@-webkit-keyframes slideInLeft {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-2000px);\n    transform: translateX(-2000px);\n  }\n\n  100% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n@keyframes slideInLeft {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-2000px);\n    -ms-transform: translateX(-2000px);\n    transform: translateX(-2000px);\n  }\n\n  100% {\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n.slideInLeft {\n  -webkit-animation-name: slideInLeft;\n  animation-name: slideInLeft;\n}\n\n@-webkit-keyframes slideInRight {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(2000px);\n    transform: translateX(2000px);\n  }\n\n  100% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n@keyframes slideInRight {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(2000px);\n    -ms-transform: translateX(2000px);\n    transform: translateX(2000px);\n  }\n\n  100% {\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n}\n\n.slideInRight {\n  -webkit-animation-name: slideInRight;\n  animation-name: slideInRight;\n}\n\n@-webkit-keyframes slideOutLeft {\n  0% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(-2000px);\n    transform: translateX(-2000px);\n  }\n}\n\n@keyframes slideOutLeft {\n  0% {\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(-2000px);\n    -ms-transform: translateX(-2000px);\n    transform: translateX(-2000px);\n  }\n}\n\n.slideOutLeft {\n  -webkit-animation-name: slideOutLeft;\n  animation-name: slideOutLeft;\n}\n\n@-webkit-keyframes slideOutRight {\n  0% {\n    -webkit-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(2000px);\n    transform: translateX(2000px);\n  }\n}\n\n@keyframes slideOutRight {\n  0% {\n    -webkit-transform: translateX(0);\n    -ms-transform: translateX(0);\n    transform: translateX(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(2000px);\n    -ms-transform: translateX(2000px);\n    transform: translateX(2000px);\n  }\n}\n\n.slideOutRight {\n  -webkit-animation-name: slideOutRight;\n  animation-name: slideOutRight;\n}\n\n@-webkit-keyframes slideOutUp {\n  0% {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-2000px);\n    transform: translateY(-2000px);\n  }\n}\n\n@keyframes slideOutUp {\n  0% {\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-2000px);\n    -ms-transform: translateY(-2000px);\n    transform: translateY(-2000px);\n  }\n}\n\n.slideOutUp {\n  -webkit-animation-name: slideOutUp;\n  animation-name: slideOutUp;\n}\n\n@-webkit-keyframes hinge {\n  0% {\n    -webkit-transform: rotate(0);\n    transform: rotate(0);\n    -webkit-transform-origin: top left;\n    transform-origin: top left;\n    -webkit-animation-timing-function: ease-in-out;\n    animation-timing-function: ease-in-out;\n  }\n\n  20%, 60% {\n    -webkit-transform: rotate(80deg);\n    transform: rotate(80deg);\n    -webkit-transform-origin: top left;\n    transform-origin: top left;\n    -webkit-animation-timing-function: ease-in-out;\n    animation-timing-function: ease-in-out;\n  }\n\n  40% {\n    -webkit-transform: rotate(60deg);\n    transform: rotate(60deg);\n    -webkit-transform-origin: top left;\n    transform-origin: top left;\n    -webkit-animation-timing-function: ease-in-out;\n    animation-timing-function: ease-in-out;\n  }\n\n  80% {\n    -webkit-transform: rotate(60deg) translateY(0);\n    transform: rotate(60deg) translateY(0);\n    opacity: 1;\n    -webkit-transform-origin: top left;\n    transform-origin: top left;\n    -webkit-animation-timing-function: ease-in-out;\n    animation-timing-function: ease-in-out;\n  }\n\n  100% {\n    -webkit-transform: translateY(700px);\n    transform: translateY(700px);\n    opacity: 0;\n  }\n}\n\n@keyframes hinge {\n  0% {\n    -webkit-transform: rotate(0);\n    -ms-transform: rotate(0);\n    transform: rotate(0);\n    -webkit-transform-origin: top left;\n    -ms-transform-origin: top left;\n    transform-origin: top left;\n    -webkit-animation-timing-function: ease-in-out;\n    animation-timing-function: ease-in-out;\n  }\n\n  20%, 60% {\n    -webkit-transform: rotate(80deg);\n    -ms-transform: rotate(80deg);\n    transform: rotate(80deg);\n    -webkit-transform-origin: top left;\n    -ms-transform-origin: top left;\n    transform-origin: top left;\n    -webkit-animation-timing-function: ease-in-out;\n    animation-timing-function: ease-in-out;\n  }\n\n  40% {\n    -webkit-transform: rotate(60deg);\n    -ms-transform: rotate(60deg);\n    transform: rotate(60deg);\n    -webkit-transform-origin: top left;\n    -ms-transform-origin: top left;\n    transform-origin: top left;\n    -webkit-animation-timing-function: ease-in-out;\n    animation-timing-function: ease-in-out;\n  }\n\n  80% {\n    -webkit-transform: rotate(60deg) translateY(0);\n    -ms-transform: rotate(60deg) translateY(0);\n    transform: rotate(60deg) translateY(0);\n    opacity: 1;\n    -webkit-transform-origin: top left;\n    -ms-transform-origin: top left;\n    transform-origin: top left;\n    -webkit-animation-timing-function: ease-in-out;\n    animation-timing-function: ease-in-out;\n  }\n\n  100% {\n    -webkit-transform: translateY(700px);\n    -ms-transform: translateY(700px);\n    transform: translateY(700px);\n    opacity: 0;\n  }\n}\n\n.hinge {\n  -webkit-animation-name: hinge;\n  animation-name: hinge;\n}\n\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\n\n@-webkit-keyframes rollIn {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-100%) rotate(-120deg);\n    transform: translateX(-100%) rotate(-120deg);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0px) rotate(0deg);\n    transform: translateX(0px) rotate(0deg);\n  }\n}\n\n@keyframes rollIn {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-100%) rotate(-120deg);\n    -ms-transform: translateX(-100%) rotate(-120deg);\n    transform: translateX(-100%) rotate(-120deg);\n  }\n\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0px) rotate(0deg);\n    -ms-transform: translateX(0px) rotate(0deg);\n    transform: translateX(0px) rotate(0deg);\n  }\n}\n\n.rollIn {\n  -webkit-animation-name: rollIn;\n  animation-name: rollIn;\n}\n\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\n\n@-webkit-keyframes rollOut {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateX(0px) rotate(0deg);\n    transform: translateX(0px) rotate(0deg);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(100%) rotate(120deg);\n    transform: translateX(100%) rotate(120deg);\n  }\n}\n\n@keyframes rollOut {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateX(0px) rotate(0deg);\n    -ms-transform: translateX(0px) rotate(0deg);\n    transform: translateX(0px) rotate(0deg);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateX(100%) rotate(120deg);\n    -ms-transform: translateX(100%) rotate(120deg);\n    transform: translateX(100%) rotate(120deg);\n  }\n}\n\n.rollOut {\n  -webkit-animation-name: rollOut;\n  animation-name: rollOut;\n}"
  },
  {
    "path": "server/public/css/lib/bootstrap/alerts.less",
    "content": "//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n  padding: @alert-padding;\n  margin-bottom: @line-height-computed;\n  border: 1px solid transparent;\n  border-radius: @alert-border-radius;\n\n  // Headings for larger alerts\n  h4 {\n    margin-top: 0;\n    // Specified for the h4 to prevent conflicts of changing @headings-color\n    color: inherit;\n  }\n  // Provide class for links that match alerts\n  .alert-link {\n    font-weight: @alert-link-font-weight;\n  }\n\n  // Improve alignment and spacing of inner content\n  > p,\n  > ul {\n    margin-bottom: 0;\n  }\n  > p + p {\n    margin-top: 5px;\n  }\n}\n\n// Dismissable alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable {\n padding-right: (@alert-padding + 20);\n\n  // Adjust close link position\n  .close {\n    position: relative;\n    top: -2px;\n    right: -21px;\n    color: inherit;\n  }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n  .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n.alert-info {\n  .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n.alert-warning {\n  .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n.alert-danger {\n  .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/badges.less",
    "content": "//\n// Badges\n// --------------------------------------------------\n\n\n// Base classes\n.badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 3px 7px;\n  font-size: @font-size-small;\n  font-weight: @badge-font-weight;\n  color: @badge-color;\n  line-height: @badge-line-height;\n  vertical-align: baseline;\n  white-space: nowrap;\n  text-align: center;\n  background-color: @badge-bg;\n  border-radius: @badge-border-radius;\n\n  // Empty badges collapse automatically (not available in IE8)\n  &:empty {\n    display: none;\n  }\n\n  // Quick fix for badges in buttons\n  .btn & {\n    position: relative;\n    top: -1px;\n  }\n  .btn-xs & {\n    top: 0;\n    padding: 1px 5px;\n  }\n}\n\n// Hover state, but only for links\na.badge {\n  &:hover,\n  &:focus {\n    color: @badge-link-hover-color;\n    text-decoration: none;\n    cursor: pointer;\n  }\n}\n\n// Account for counters in navs\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n  color: @badge-active-color;\n  background-color: @badge-active-bg;\n}\n.nav-pills > li > a > .badge {\n  margin-left: 3px;\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/bootstrap.less",
    "content": "// Core variables and mixins\n@import \"variables.less\";\n@import \"mixins.less\";\n\n// Reset\n@import \"normalize.less\";\n@import \"print.less\";\n\n// Core CSS\n@import \"scaffolding.less\";\n@import \"type.less\";\n@import \"code.less\";\n@import \"grid.less\";\n@import \"tables.less\";\n@import \"forms.less\";\n@import \"buttons.less\";\n\n// Components\n@import \"component-animations.less\";\n@import \"glyphicons.less\";\n@import \"dropdowns.less\";\n@import \"button-groups.less\";\n@import \"input-groups.less\";\n@import \"navs.less\";\n@import \"navbar.less\";\n@import \"breadcrumbs.less\";\n@import \"pagination.less\";\n@import \"pager.less\";\n@import \"labels.less\";\n@import \"badges.less\";\n@import \"jumbotron.less\";\n@import \"thumbnails.less\";\n@import \"alerts.less\";\n@import \"progress-bars.less\";\n@import \"media.less\";\n@import \"list-group.less\";\n@import \"panels.less\";\n@import \"wells.less\";\n@import \"close.less\";\n\n// Components w/ JavaScript\n@import \"modals.less\";\n@import \"tooltip.less\";\n@import \"popovers.less\";\n@import \"carousel.less\";\n\n// Utility classes\n@import \"utilities.less\";\n@import \"responsive-utilities.less\";\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/breadcrumbs.less",
    "content": "//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n  padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n  margin-bottom: @line-height-computed;\n  list-style: none;\n  background-color: @breadcrumb-bg;\n  border-radius: @border-radius-base;\n\n  > li {\n    display: inline-block;\n\n    + li:before {\n      content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n      padding: 0 5px;\n      color: @breadcrumb-color;\n    }\n  }\n\n  > .active {\n    color: @breadcrumb-active-color;\n  }\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/button-groups.less",
    "content": "//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle; // match .btn alignment given font-size hack above\n  > .btn {\n    position: relative;\n    float: left;\n    // Bring the \"active\" button to the front\n    &:hover,\n    &:focus,\n    &:active,\n    &.active {\n      z-index: 2;\n    }\n    &:focus {\n      // Remove focus outline when dropdown JS adds it after closing the menu\n      outline: none;\n    }\n  }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n  .btn + .btn,\n  .btn + .btn-group,\n  .btn-group + .btn,\n  .btn-group + .btn-group {\n    margin-left: -1px;\n  }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n  margin-left: -5px; // Offset the first child's margin\n  &:extend(.clearfix all)\n;\n\n  .btn-group,\n  .input-group {\n    float: left;\n  }\n  > .btn,\n  > .btn-group,\n  > .input-group {\n    margin-left: 5px;\n  }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  &:not(:last-child):not(.dropdown-toggle) {\n    .border-right-radius(0);\n  }\n}\n\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n  .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n  float: left;\n}\n\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n\n.btn-group > .btn-group:first-child {\n  > .btn:last-child,\n  > .dropdown-toggle {\n    .border-right-radius(0);\n  }\n}\n\n.btn-group > .btn-group:last-child > .btn:first-child {\n  .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn {\n  &:extend(.btn-xs)\n;\n}\n\n.btn-group-sm > .btn {\n  &:extend(.btn-sm)\n;\n}\n\n.btn-group-lg > .btn {\n  &:extend(.btn-lg)\n;\n}\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n  padding-left: 8px;\n  padding-right: 8px;\n}\n\n.btn-group > .btn-lg + .dropdown-toggle {\n  padding-left: 12px;\n  padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n  .box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125));\n\n  // Show no shadow for `.btn-link` since it has no other button styles.\n  &.btn-link {\n    .box-shadow(none);\n  }\n}\n\n// Reposition the caret\n.btn .caret {\n  margin-left: 0;\n}\n\n// Carets in other button sizes\n.btn-lg .caret {\n  border-width: @caret-width-large @caret-width-large 0;\n  border-bottom-width: 0;\n}\n\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n  border-width: 0 @caret-width-large @caret-width-large;\n}\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n  > .btn,\n  > .btn-group,\n  > .btn-group > .btn {\n    display: block;\n    float: none;\n    width: 100%;\n    max-width: 100%;\n  }\n\n  // Clear floats so dropdown menus can be properly placed\n  > .btn-group {\n    &:extend(.clearfix all)\n  ;\n    > .btn {\n      float: none;\n    }\n  }\n\n  > .btn + .btn,\n  > .btn + .btn-group,\n  > .btn-group + .btn,\n  > .btn-group + .btn-group {\n    margin-top: -1px;\n    margin-left: 0;\n  }\n}\n\n.btn-group-vertical > .btn {\n  &:not(:first-child):not(:last-child) {\n    border-radius: 0;\n  }\n  &:first-child:not(:last-child) {\n    border-top-right-radius: @border-radius-base;\n    .border-bottom-radius(0);\n  }\n  &:last-child:not(:first-child) {\n    border-bottom-left-radius: @border-radius-base;\n    .border-top-radius(0);\n  }\n}\n\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n  > .btn:last-child,\n  > .dropdown-toggle {\n    .border-bottom-radius(0);\n  }\n}\n\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n  .border-top-radius(0);\n}\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n  display: table;\n  width: 100%;\n  table-layout: fixed;\n  border-collapse: separate;\n  > .btn,\n  > .btn-group {\n    float: none;\n    display: table-cell;\n    width: 1%;\n  }\n  > .btn-group .btn {\n    width: 100%;\n  }\n}\n\n// Checkbox and radio options\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n  display: none;\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/buttons.less",
    "content": "//\n// Buttons\n// --------------------------------------------------\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n  display: inline-block;\n  margin-bottom: 0; // For input.btn\n  font-weight: @btn-font-weight;\n  text-align: center;\n  vertical-align: middle;\n  cursor: pointer;\n  background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n  border: 1px solid transparent;\n  white-space: nowrap;\n  .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base);\n  .user-select(none);\n\n  &,\n  &:active,\n  &.active {\n    &:focus {\n      .tab-focus();\n    }\n  }\n\n  &:hover,\n  &:focus {\n    color: @btn-default-color;\n    text-decoration: none;\n  }\n\n  &:active,\n  &.active {\n    outline: 0;\n    background-image: none;\n    .box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125));\n  }\n\n  &.disabled,\n  &[disabled],\n  fieldset[disabled] & {\n    cursor: not-allowed;\n    pointer-events: none; // Future-proof disabling of clicks\n    .opacity(.65);\n    .box-shadow(none);\n  }\n}\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n  .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n\n.btn-primary {\n  .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n\n// Success appears as green\n.btn-success {\n  .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n\n// Info appears as blue-green\n.btn-info {\n  .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n\n// Warning appears as orange\n.btn-warning {\n  .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n\n// Danger and error appear as red\n.btn-danger {\n  .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n  color: @link-color;\n  font-weight: normal;\n  cursor: pointer;\n  border-radius: 0;\n\n  &,\n  &:active,\n  &[disabled],\n  fieldset[disabled] & {\n    background-color: transparent;\n    .box-shadow(none);\n  }\n  &,\n  &:hover,\n  &:focus,\n  &:active {\n    border-color: transparent;\n  }\n  &:hover,\n  &:focus {\n    color: @link-hover-color;\n    text-decoration: underline;\n    background-color: transparent;\n  }\n  &[disabled],\n  fieldset[disabled] & {\n    &:hover,\n    &:focus {\n      color: @btn-link-disabled-color;\n      text-decoration: none;\n    }\n  }\n}\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n  // line-height: ensure even-numbered height of button next to large input\n  .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n.btn-sm {\n  // line-height: ensure proper height of button next to small input\n  .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n.btn-xs {\n  .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-left: 0;\n  padding-right: 0;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n  &.btn-block {\n    width: 100%;\n  }\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/carousel.less",
    "content": "//\n// Carousel\n// --------------------------------------------------\n\n// Wrapper for the slide container and indicators\n.carousel {\n  position: relative;\n}\n\n.carousel-inner {\n  position: relative;\n  overflow: hidden;\n  width: 100%;\n\n  > .item {\n    display: none;\n    position: relative;\n    .transition(.6s ease-in-out left);\n\n    // Account for jankitude on images\n    > img,\n    > a > img {\n      &:extend(.img-responsive)\n    ;\n      line-height: 1;\n    }\n  }\n\n  > .active,\n  > .next,\n  > .prev {\n    display: block;\n  }\n\n  > .active {\n    left: 0;\n  }\n\n  > .next,\n  > .prev {\n    position: absolute;\n    top: 0;\n    width: 100%;\n  }\n\n  > .next {\n    left: 100%;\n  }\n  > .prev {\n    left: -100%;\n  }\n  > .next.left,\n  > .prev.right {\n    left: 0;\n  }\n\n  > .active.left {\n    left: -100%;\n  }\n  > .active.right {\n    left: 100%;\n  }\n\n}\n\n// Left/right controls for nav\n// ---------------------------\n\n.carousel-control {\n  position: absolute;\n  top: 0;\n  left: 0;\n  bottom: 0;\n  width: @carousel-control-width;\n  .opacity(@carousel-control-opacity);\n  font-size: @carousel-control-font-size;\n  color: @carousel-control-color;\n  text-align: center;\n  text-shadow: @carousel-text-shadow;\n  // We can't have this transition here because WebKit cancels the carousel\n  // animation if you trip this while in the middle of another animation.\n\n  // Set gradients for backgrounds\n  &.left {\n    #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));\n  }\n  &.right {\n    left: auto;\n    right: 0;\n    #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));\n  }\n\n  // Hover/focus state\n  &:hover,\n  &:focus {\n    outline: none;\n    color: @carousel-control-color;\n    text-decoration: none;\n    .opacity(.9);\n  }\n\n  // Toggles\n  .icon-prev,\n  .icon-next,\n  .glyphicon-chevron-left,\n  .glyphicon-chevron-right {\n    position: absolute;\n    top: 50%;\n    z-index: 5;\n    display: inline-block;\n  }\n  .icon-prev,\n  .glyphicon-chevron-left {\n    left: 50%;\n  }\n  .icon-next,\n  .glyphicon-chevron-right {\n    right: 50%;\n  }\n  .icon-prev,\n  .icon-next {\n    width: 20px;\n    height: 20px;\n    margin-top: -10px;\n    margin-left: -10px;\n    font-family: serif;\n  }\n\n  .icon-prev {\n    &:before {\n      content: '\\2039'; // SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)\n    }\n  }\n  .icon-next {\n    &:before {\n      content: '\\203a'; // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)\n    }\n  }\n}\n\n// Optional indicator pips\n//\n// Add an unordered list with the following class and add a list item for each\n// slide your carousel holds.\n\n.carousel-indicators {\n  position: absolute;\n  bottom: 10px;\n  left: 50%;\n  z-index: 15;\n  width: 60%;\n  margin-left: -30%;\n  padding-left: 0;\n  list-style: none;\n  text-align: center;\n\n  li {\n    display: inline-block;\n    width: 10px;\n    height: 10px;\n    margin: 1px;\n    text-indent: -999px;\n    border: 1px solid @carousel-indicator-border-color;\n    border-radius: 10px;\n    cursor: pointer;\n\n    // IE8-9 hack for event handling\n    //\n    // Internet Explorer 8-9 does not support clicks on elements without a set\n    // `background-color`. We cannot use `filter` since that's not viewed as a\n    // background color by the browser. Thus, a hack is needed.\n    //\n    // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we\n    // set alpha transparency for the best results possible.\n    background-color: #000 \\9; // IE8\n    background-color: rgba(0, 0, 0, 0); // IE9\n  }\n  .active {\n    margin: 0;\n    width: 12px;\n    height: 12px;\n    background-color: @carousel-indicator-active-bg;\n  }\n}\n\n// Optional captions\n// -----------------------------\n// Hidden by default for smaller viewports\n.carousel-caption {\n  position: absolute;\n  left: 15%;\n  right: 15%;\n  bottom: 20px;\n  z-index: 10;\n  padding-top: 20px;\n  padding-bottom: 20px;\n  color: @carousel-caption-color;\n  text-align: center;\n  text-shadow: @carousel-text-shadow;\n  & .btn {\n    text-shadow: none; // No shadow for button elements in carousel-caption\n  }\n}\n\n// Scale up controls for tablets and up\n@media screen and (min-width: @screen-sm-min) {\n\n  // Scale up the controls a smidge\n  .carousel-control {\n    .glyphicon-chevron-left,\n    .glyphicon-chevron-right,\n    .icon-prev,\n    .icon-next {\n      width: 30px;\n      height: 30px;\n      margin-top: -15px;\n      margin-left: -15px;\n      font-size: 30px;\n    }\n  }\n\n  // Show and left align the captions\n  .carousel-caption {\n    left: 20%;\n    right: 20%;\n    padding-bottom: 30px;\n  }\n\n  // Move up the indicators\n  .carousel-indicators {\n    bottom: 20px;\n  }\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/close.less",
    "content": "//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n  float: right;\n  font-size: (@font-size-base * 1.5);\n  font-weight: @close-font-weight;\n  line-height: 1;\n  color: @close-color;\n  text-shadow: @close-text-shadow;\n  .opacity(.2);\n\n  &:hover,\n  &:focus {\n    color: @close-color;\n    text-decoration: none;\n    cursor: pointer;\n    .opacity(.5);\n  }\n\n  // Additional properties for button version\n  // iOS requires the button element instead of an anchor tag.\n  // If you want the anchor version, it requires `href=\"#\"`.\n  button& {\n    padding: 0;\n    cursor: pointer;\n    background: transparent;\n    border: 0;\n    -webkit-appearance: none;\n  }\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/code.less",
    "content": "//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n  font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: @code-color;\n  background-color: @code-bg;\n  white-space: nowrap;\n  border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: @kbd-color;\n  background-color: @kbd-bg;\n  border-radius: @border-radius-small;\n  box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n}\n\n// Blocks of code\npre {\n  display: block;\n  padding: ((@line-height-computed - 1) / 2);\n  margin: 0 0 (@line-height-computed / 2);\n  font-size: (@font-size-base - 1); // 14px to 13px\n  line-height: @line-height-base;\n  word-break: break-all;\n  word-wrap: break-word;\n  color: @pre-color;\n  background-color: @pre-bg;\n  border: 1px solid @pre-border-color;\n  border-radius: @border-radius-base;\n\n  // Account for some code outputs that place code tags in pre tags\n  code {\n    padding: 0;\n    font-size: inherit;\n    color: inherit;\n    white-space: pre-wrap;\n    background-color: transparent;\n    border-radius: 0;\n  }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n  max-height: @pre-scrollable-max-height;\n  overflow-y: scroll;\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/component-animations.less",
    "content": "//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twitter/bootstrap/pull/3552.\n\n.fade {\n  opacity: 0;\n  .transition(opacity .15s linear);\n  &.in {\n    opacity: 1;\n  }\n}\n\n.collapse {\n  display: none;\n  &.in {\n    display: block;\n  }\n}\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  .transition(height .35s ease);\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/dropdowns.less",
    "content": "//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  margin-left: 2px;\n  vertical-align: middle;\n  border-top:   @caret-width-base solid;\n  border-right: @caret-width-base solid transparent;\n  border-left:  @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropdown {\n  position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n  outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: @zindex-dropdown;\n  display: none; // none by default, but block on \"open\" of the menu\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0; // override default ul\n  list-style: none;\n  font-size: @font-size-base;\n  background-color: @dropdown-bg;\n  border: 1px solid @dropdown-fallback-border; // IE8 fallback\n  border: 1px solid @dropdown-border;\n  border-radius: @border-radius-base;\n  .box-shadow(0 6px 12px rgba(0,0,0,.175));\n  background-clip: padding-box;\n\n  // Aligns the dropdown menu to right\n  //\n  // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n  &.pull-right {\n    right: 0;\n    left: auto;\n  }\n\n  // Dividers (basically an hr) within the dropdown\n  .divider {\n    .nav-divider(@dropdown-divider-bg);\n  }\n\n  // Links within the dropdown menu\n  > li > a {\n    display: block;\n    padding: 3px 20px;\n    clear: both;\n    font-weight: normal;\n    line-height: @line-height-base;\n    color: @dropdown-link-color;\n    white-space: nowrap; // prevent links from randomly breaking onto new lines\n  }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n  &:hover,\n  &:focus {\n    text-decoration: none;\n    color: @dropdown-link-hover-color;\n    background-color: @dropdown-link-hover-bg;\n  }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n  &,\n  &:hover,\n  &:focus {\n    color: @dropdown-link-active-color;\n    text-decoration: none;\n    outline: 0;\n    background-color: @dropdown-link-active-bg;\n  }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n  &,\n  &:hover,\n  &:focus {\n    color: @dropdown-link-disabled-color;\n  }\n}\n// Nuke hover/focus effects\n.dropdown-menu > .disabled > a {\n  &:hover,\n  &:focus {\n    text-decoration: none;\n    background-color: transparent;\n    background-image: none; // Remove CSS gradient\n    .reset-filter();\n    cursor: not-allowed;\n  }\n}\n\n// Open state for the dropdown\n.open {\n  // Show the menu\n  > .dropdown-menu {\n    display: block;\n  }\n\n  // Remove the outline when :focus is triggered\n  > a {\n    outline: 0;\n  }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n  left: auto; // Reset the default from `.dropdown-menu`\n  right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n  left: 0;\n  right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: @font-size-small;\n  line-height: @line-height-base;\n  color: @dropdown-header-color;\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n  position: fixed;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  top: 0;\n  z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n  // Reverse the caret\n  .caret {\n    border-top: 0;\n    border-bottom: @caret-width-base solid;\n    content: \"\";\n  }\n  // Different positioning for bottom up menu\n  .dropdown-menu {\n    top: auto;\n    bottom: 100%;\n    margin-bottom: 1px;\n  }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n  .navbar-right {\n    .dropdown-menu {\n      .dropdown-menu-right();\n    }\n    // Necessary for overrides of the default right aligned menu.\n    // Will remove come v4 in all likelihood.\n    .dropdown-menu-left {\n      .dropdown-menu-left();\n    }\n  }\n}\n\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/forms.less",
    "content": "//\n// Forms\n// --------------------------------------------------\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n  // Chrome and Firefox set a `min-width: -webkit-min-content;` on fieldsets,\n  // so we reset that to ensure it behaves more like a standard block element.\n  // See https://github.com/twbs/bootstrap/issues/12359.\n  min-width: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: @line-height-computed;\n  font-size: (@font-size-base * 1.5);\n  line-height: inherit;\n  color: @legend-color;\n  border: 0;\n  border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n  .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9; /* IE8-9 */\n  line-height: normal;\n}\n\n// Set the height of file controls to match text inputs\ninput[type=\"file\"] {\n  display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n  display: block;\n  width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  .tab-focus();\n}\n\n// Adjust output element\noutput {\n  display: block;\n  padding-top: (@padding-base-vertical + 1);\n  font-size: @font-size-base;\n  line-height: @line-height-base;\n  color: @input-color;\n}\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n  display: block;\n  width: 100%;\n  height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n  padding: @padding-base-vertical @padding-base-horizontal;\n  font-size: @font-size-base;\n  line-height: @line-height-base;\n  color: @input-color;\n  background-color: @input-bg;\n  background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n  border: 1px solid @input-border;\n  border-radius: @input-border-radius;\n  .box-shadow(inset 0 1px 1px rgba(0, 0, 0, .075));\n  .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n  // Customize the `:focus` state to imitate native WebKit styles.\n  .form-control-focus();\n\n  // Placeholder\n  .placeholder();\n\n  // Disabled and read-only inputs\n  //\n  // HTML5 says that controls under a fieldset > legend:first-child won't be\n  // disabled if the fieldset is disabled. Due to implementation difficulty, we\n  // don't honor that edge case; we style them as disabled anyway.\n  &[disabled],\n  &[readonly],\n  fieldset[disabled] & {\n    cursor: not-allowed;\n    background-color: @input-bg-disabled;\n    opacity: 1; // iOS fix for unreadable disabled content\n  }\n\n  // Reset height for `textarea`s\n  textarea& {\n    height: auto;\n  }\n}\n\n// Search inputs in iOS\n//\n// This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\ninput[type=\"search\"] {\n  -webkit-appearance: none;\n}\n\n// Special styles for iOS date input\n//\n// In Mobile Safari, date inputs require a pixel line-height that matches the\n// given height of the input.\n\ninput[type=\"date\"] {\n  line-height: @input-height-base;\n}\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n  margin-bottom: 15px;\n}\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n  display: block;\n  min-height: @line-height-computed; // clear the floating input if there is no label text\n  margin-top: 10px;\n  margin-bottom: 10px;\n  padding-left: 20px;\n  label {\n    display: inline;\n    font-weight: normal;\n    cursor: pointer;\n  }\n}\n\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.radio + .radio,\n.checkbox + .checkbox {\n  margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n  display: inline-block;\n  padding-left: 20px;\n  margin-bottom: 0;\n  vertical-align: middle;\n  font-weight: normal;\n  cursor: pointer;\n}\n\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n//\n// Note: Neither radios nor checkboxes can be readonly.\ninput[type=\"radio\"],\ninput[type=\"checkbox\"],\n.radio,\n.radio-inline,\n.checkbox,\n.checkbox-inline {\n  &[disabled],\n  fieldset[disabled] & {\n    cursor: not-allowed;\n  }\n}\n\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n\n.input-sm {\n  .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n.input-lg {\n  .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n// Form control feedback states\n//\n// Apply contextual and semantic states to individual form controls.\n\n.has-feedback {\n  // Enable absolute positioning\n  position: relative;\n\n  // Ensure icons don't overlap text\n  .form-control {\n    padding-right: (@input-height-base * 1.25);\n  }\n\n  // Feedback icon (requires .glyphicon classes)\n  .form-control-feedback {\n    position: absolute;\n    top: (@line-height-computed + 5); // Height of the `label` and its margin\n    right: 0;\n    display: block;\n    width: @input-height-base;\n    height: @input-height-base;\n    line-height: @input-height-base;\n    text-align: center;\n  }\n}\n\n// Feedback states\n.has-success {\n  .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n\n.has-warning {\n  .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n\n.has-error {\n  .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);\n}\n\n// Static form control text\n//\n// Apply class to a `p` element to make any string of text align with labels in\n// a horizontal form layout.\n\n.form-control-static {\n  margin-bottom: 0; // Remove default margin from `p`\n}\n\n// Help text\n//\n// Apply to any element you wish to create light text for placement immediately\n// below a form control. Use for general help, formatting, or instructional text.\n\n.help-block {\n  display: block; // account for any element using help-block\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: lighten(@text-color, 25%); // lighten the text some for contrast\n}\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n//\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\n\n.form-inline {\n\n  // Kick in the inline\n  @media (min-width: @screen-sm-min) {\n    // Inline-block all the things for \"inline\"\n    .form-group {\n      display: inline-block;\n      margin-bottom: 0;\n      vertical-align: middle;\n    }\n\n    // In navbar-form, allow folks to *not* use `.form-group`\n    .form-control {\n      display: inline-block;\n      width: auto; // Prevent labels from stacking above inputs in `.form-group`\n      vertical-align: middle;\n    }\n\n    // Input groups need that 100% width though\n    .input-group > .form-control {\n      width: 100%;\n    }\n\n    .control-label {\n      margin-bottom: 0;\n      vertical-align: middle;\n    }\n\n    // Remove default margin on radios/checkboxes that were used for stacking, and\n    // then undo the floating of radios and checkboxes to match (which also avoids\n    // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969).\n    .radio,\n    .checkbox {\n      display: inline-block;\n      margin-top: 0;\n      margin-bottom: 0;\n      padding-left: 0;\n      vertical-align: middle;\n    }\n\n    .radio input[type=\"radio\"],\n    .checkbox input[type=\"checkbox\"] {\n      float: none;\n      margin-left: 0;\n    }\n\n    // Validation states\n    //\n    // Reposition the icon because it's now within a grid column and columns have\n    // `position: relative;` on them. Also accounts for the grid gutter padding.\n    .has-feedback .form-control-feedback {\n      top: 0;\n    }\n  }\n}\n\n// Horizontal forms\n//\n// Horizontal forms are built on grid classes and allow you to create forms with\n// labels on the left and inputs on the right.\n\n.form-horizontal {\n\n  // Consistent vertical alignment of labels, radios, and checkboxes\n  .control-label,\n  .radio,\n  .checkbox,\n  .radio-inline,\n  .checkbox-inline {\n    margin-top: 0;\n    margin-bottom: 0;\n    padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n  }\n  // Account for padding we're adding to ensure the alignment and of help text\n  // and other content below items\n  .radio,\n  .checkbox {\n    min-height: (@line-height-computed + (@padding-base-vertical + 1));\n  }\n\n  // Make form groups behave like rows\n  .form-group {\n    .make-row();\n  }\n\n  .form-control-static {\n    padding-top: (@padding-base-vertical + 1);\n  }\n\n  // Only right align form labels here when the columns stop stacking\n  @media (min-width: @screen-sm-min) {\n    .control-label {\n      text-align: right;\n    }\n  }\n\n  // Validation states\n  //\n  // Reposition the icon because it's now within a grid column and columns have\n  // `position: relative;` on them. Also accounts for the grid gutter padding.\n  .has-feedback .form-control-feedback {\n    top: 0;\n    right: (@grid-gutter-width / 2);\n  }\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/glyphicons.less",
    "content": "//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// <a href=\"#\"><span class=\"glyphicon glyphicon-star\"></span> Star</a>\n\n// Import the fonts\n@font-face {\n  font-family: 'Glyphicons Halflings';\n  src: ~\"url('@{icon-font-path}@{icon-font-name}.eot')\";\n  src: ~\"url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype')\",\n       ~\"url('@{icon-font-path}@{icon-font-name}.woff') format('woff')\",\n       ~\"url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype')\",\n       ~\"url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg')\";\n}\n\n// Catchall baseclass\n.glyphicon {\n  position: relative;\n  top: 1px;\n  display: inline-block;\n  font-family: 'Glyphicons Halflings';\n  font-style: normal;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk               { &:before { content: \"\\2a\"; } }\n.glyphicon-plus                   { &:before { content: \"\\2b\"; } }\n.glyphicon-euro                   { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus                  { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud                  { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope               { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil                 { &:before { content: \"\\270f\"; } }\n.glyphicon-glass                  { &:before { content: \"\\e001\"; } }\n.glyphicon-music                  { &:before { content: \"\\e002\"; } }\n.glyphicon-search                 { &:before { content: \"\\e003\"; } }\n.glyphicon-heart                  { &:before { content: \"\\e005\"; } }\n.glyphicon-star                   { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty             { &:before { content: \"\\e007\"; } }\n.glyphicon-user                   { &:before { content: \"\\e008\"; } }\n.glyphicon-film                   { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large               { &:before { content: \"\\e010\"; } }\n.glyphicon-th                     { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list                { &:before { content: \"\\e012\"; } }\n.glyphicon-ok                     { &:before { content: \"\\e013\"; } }\n.glyphicon-remove                 { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in                { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out               { &:before { content: \"\\e016\"; } }\n.glyphicon-off                    { &:before { content: \"\\e017\"; } }\n.glyphicon-signal                 { &:before { content: \"\\e018\"; } }\n.glyphicon-cog                    { &:before { content: \"\\e019\"; } }\n.glyphicon-trash                  { &:before { content: \"\\e020\"; } }\n.glyphicon-home                   { &:before { content: \"\\e021\"; } }\n.glyphicon-file                   { &:before { content: \"\\e022\"; } }\n.glyphicon-time                   { &:before { content: \"\\e023\"; } }\n.glyphicon-road                   { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt           { &:before { content: \"\\e025\"; } }\n.glyphicon-download               { &:before { content: \"\\e026\"; } }\n.glyphicon-upload                 { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox                  { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle            { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat                 { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh                { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt               { &:before { content: \"\\e032\"; } }\n.glyphicon-lock                   { &:before { content: \"\\e033\"; } }\n.glyphicon-flag                   { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones             { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off             { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down            { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up              { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode                 { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode                { &:before { content: \"\\e040\"; } }\n.glyphicon-tag                    { &:before { content: \"\\e041\"; } }\n.glyphicon-tags                   { &:before { content: \"\\e042\"; } }\n.glyphicon-book                   { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark               { &:before { content: \"\\e044\"; } }\n.glyphicon-print                  { &:before { content: \"\\e045\"; } }\n.glyphicon-camera                 { &:before { content: \"\\e046\"; } }\n.glyphicon-font                   { &:before { content: \"\\e047\"; } }\n.glyphicon-bold                   { &:before { content: \"\\e048\"; } }\n.glyphicon-italic                 { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height            { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width             { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left             { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center           { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right            { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify          { &:before { content: \"\\e055\"; } }\n.glyphicon-list                   { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left            { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right           { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video         { &:before { content: \"\\e059\"; } }\n.glyphicon-picture                { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker             { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust                 { &:before { content: \"\\e063\"; } }\n.glyphicon-tint                   { &:before { content: \"\\e064\"; } }\n.glyphicon-edit                   { &:before { content: \"\\e065\"; } }\n.glyphicon-share                  { &:before { content: \"\\e066\"; } }\n.glyphicon-check                  { &:before { content: \"\\e067\"; } }\n.glyphicon-move                   { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward          { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward          { &:before { content: \"\\e070\"; } }\n.glyphicon-backward               { &:before { content: \"\\e071\"; } }\n.glyphicon-play                   { &:before { content: \"\\e072\"; } }\n.glyphicon-pause                  { &:before { content: \"\\e073\"; } }\n.glyphicon-stop                   { &:before { content: \"\\e074\"; } }\n.glyphicon-forward                { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward           { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward           { &:before { content: \"\\e077\"; } }\n.glyphicon-eject                  { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left           { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right          { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign              { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign             { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign            { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign                { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign          { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign              { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot             { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle          { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle              { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle             { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left             { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right            { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up               { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down             { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt              { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full            { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small           { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign       { &:before { content: \"\\e101\"; } }\n.glyphicon-gift                   { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf                   { &:before { content: \"\\e103\"; } }\n.glyphicon-fire                   { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open               { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close              { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign           { &:before { content: \"\\e107\"; } }\n.glyphicon-plane                  { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar               { &:before { content: \"\\e109\"; } }\n.glyphicon-random                 { &:before { content: \"\\e110\"; } }\n.glyphicon-comment                { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet                 { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up             { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down           { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet                { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart          { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close           { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open            { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical        { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal      { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd                    { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn               { &:before { content: \"\\e122\"; } }\n.glyphicon-bell                   { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate            { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up              { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down            { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right             { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left              { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up                { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down              { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right     { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left      { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up        { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down      { &:before { content: \"\\e134\"; } }\n.glyphicon-globe                  { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench                 { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks                  { &:before { content: \"\\e137\"; } }\n.glyphicon-filter                 { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase              { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen             { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard              { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip              { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty            { &:before { content: \"\\e143\"; } }\n.glyphicon-link                   { &:before { content: \"\\e144\"; } }\n.glyphicon-phone                  { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin                { &:before { content: \"\\e146\"; } }\n.glyphicon-usd                    { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp                    { &:before { content: \"\\e149\"; } }\n.glyphicon-sort                   { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet       { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt   { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order          { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt      { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes     { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked              { &:before { content: \"\\e157\"; } }\n.glyphicon-expand                 { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down          { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up            { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in                 { &:before { content: \"\\e161\"; } }\n.glyphicon-flash                  { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out                { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window             { &:before { content: \"\\e164\"; } }\n.glyphicon-record                 { &:before { content: \"\\e165\"; } }\n.glyphicon-save                   { &:before { content: \"\\e166\"; } }\n.glyphicon-open                   { &:before { content: \"\\e167\"; } }\n.glyphicon-saved                  { &:before { content: \"\\e168\"; } }\n.glyphicon-import                 { &:before { content: \"\\e169\"; } }\n.glyphicon-export                 { &:before { content: \"\\e170\"; } }\n.glyphicon-send                   { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk            { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved           { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove          { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save            { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open            { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card            { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer               { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery                { &:before { content: \"\\e179\"; } }\n.glyphicon-header                 { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed             { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone               { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt              { &:before { content: \"\\e183\"; } }\n.glyphicon-tower                  { &:before { content: \"\\e184\"; } }\n.glyphicon-stats                  { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video               { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video               { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles              { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo           { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby            { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1              { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1              { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1              { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark         { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark      { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download         { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload           { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer           { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous         { &:before { content: \"\\e200\"; } }\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/grid.less",
    "content": "//\n// Grid system\n// --------------------------------------------------\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n  .container-fixed();\n\n  @media (min-width: @screen-sm-min) {\n    width: @container-sm;\n  }\n  @media (min-width: @screen-md-min) {\n    width: @container-md;\n  }\n  @media (min-width: @screen-lg-min) {\n    width: @container-lg;\n  }\n}\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n  .container-fixed();\n}\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n  .make-row();\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n  .make-grid(sm);\n}\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n  .make-grid(md);\n}\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n  .make-grid(lg);\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/input-groups.less",
    "content": "//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n  position: relative; // For dropdowns\n  display: table;\n  border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n  // Undo padding and float of grid classes\n  &[class*=\"col-\"] {\n    float: none;\n    padding-left: 0;\n    padding-right: 0;\n  }\n\n  .form-control {\n    // Ensure that the input is always above the *appended* addon button for\n    // proper border colors.\n    position: relative;\n    z-index: 2;\n\n    // IE9 fubars the placeholder attribute in text inputs and the arrows on\n    // select elements in input groups. To fix it, we float the input. Details:\n    // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n    float: left;\n\n    width: 100%;\n    margin-bottom: 0;\n  }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n  .input-lg();\n}\n\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n  .input-sm();\n}\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: table-cell;\n\n  &:not(:first-child):not(:last-child) {\n    border-radius: 0;\n  }\n}\n\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n  padding: @padding-base-vertical @padding-base-horizontal;\n  font-size: @font-size-base;\n  font-weight: normal;\n  line-height: 1;\n  color: @input-color;\n  text-align: center;\n  background-color: @input-group-addon-bg;\n  border: 1px solid @input-group-addon-border-color;\n  border-radius: @border-radius-base;\n\n  // Sizing\n  &.input-sm {\n    padding: @padding-small-vertical @padding-small-horizontal;\n    font-size: @font-size-small;\n    border-radius: @border-radius-small;\n  }\n  &.input-lg {\n    padding: @padding-large-vertical @padding-large-horizontal;\n    font-size: @font-size-large;\n    border-radius: @border-radius-large;\n  }\n\n  // Nuke default margins from checkboxes and radios to vertically center within.\n  input[type=\"radio\"],\n  input[type=\"checkbox\"] {\n    margin-top: 0;\n  }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n  .border-right-radius(0);\n}\n\n.input-group-addon:first-child {\n  border-right: 0;\n}\n\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n  .border-left-radius(0);\n}\n\n.input-group-addon:last-child {\n  border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n  position: relative;\n  // Jankily prevent input button groups from wrapping with `white-space` and\n  // `font-size` in combination with `inline-block` on buttons.\n  font-size: 0;\n  white-space: nowrap;\n\n  // Negative margin for spacing, position for bringing hovered/focused/actived\n  // element above the siblings.\n  > .btn {\n    position: relative;\n    + .btn {\n      margin-left: -1px;\n    }\n    // Bring the \"active\" button to the front\n    &:hover,\n    &:focus,\n    &:active {\n      z-index: 2;\n    }\n  }\n\n  // Negative margin to only have a 1px border between the two\n  &:first-child {\n    > .btn,\n    > .btn-group {\n      margin-right: -1px;\n    }\n  }\n  &:last-child {\n    > .btn,\n    > .btn-group {\n      margin-left: -1px;\n    }\n  }\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/jumbotron.less",
    "content": "//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n  padding: @jumbotron-padding;\n  margin-bottom: @jumbotron-padding;\n  color: @jumbotron-color;\n  background-color: @jumbotron-bg;\n\n  h1,\n  .h1 {\n    color: @jumbotron-heading-color;\n  }\n  p {\n    margin-bottom: (@jumbotron-padding / 2);\n    font-size: @jumbotron-font-size;\n    font-weight: 200;\n  }\n\n  .container & {\n    border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n  }\n\n  .container {\n    max-width: 100%;\n  }\n\n  @media screen and (min-width: @screen-sm-min) {\n    padding-top:    (@jumbotron-padding * 1.6);\n    padding-bottom: (@jumbotron-padding * 1.6);\n\n    .container & {\n      padding-left:  (@jumbotron-padding * 2);\n      padding-right: (@jumbotron-padding * 2);\n    }\n\n    h1,\n    .h1 {\n      font-size: (@font-size-base * 4.5);\n    }\n  }\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/labels.less",
    "content": "//\n// Labels\n// --------------------------------------------------\n\n.label {\n  display: inline;\n  padding: .2em .6em .3em;\n  font-size: 75%;\n  font-weight: bold;\n  line-height: 1;\n  color: @label-color;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: .25em;\n\n  // Add hover effects, but only for links\n  &[href] {\n    &:hover,\n    &:focus {\n      color: @label-link-hover-color;\n      text-decoration: none;\n      cursor: pointer;\n    }\n  }\n\n  // Empty labels collapse automatically (not available in IE8)\n  &:empty {\n    display: none;\n  }\n\n  // Quick fix for labels in buttons\n  .btn & {\n    position: relative;\n    top: -1px;\n  }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n  .label-variant(@label-default-bg);\n}\n\n.label-primary {\n  .label-variant(@label-primary-bg);\n}\n\n.label-success {\n  .label-variant(@label-success-bg);\n}\n\n.label-info {\n  .label-variant(@label-info-bg);\n}\n\n.label-warning {\n  .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n  .label-variant(@label-danger-bg);\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/list-group.less",
    "content": "//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on <ul>, <ol>, or <div>.\n\n.list-group {\n  // No need to set list-style: none; since .list-group-item is block level\n  margin-bottom: 20px;\n  padding-left: 0; // reset padding because ul and ol\n}\n\n\n// Individual list items\n//\n// Use on `li`s or `div`s within the `.list-group` parent.\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n  // Place the border on the list items and negative margin up for better styling\n  margin-bottom: -1px;\n  background-color: @list-group-bg;\n  border: 1px solid @list-group-border;\n\n  // Round the first and last items\n  &:first-child {\n    .border-top-radius(@list-group-border-radius);\n  }\n  &:last-child {\n    margin-bottom: 0;\n    .border-bottom-radius(@list-group-border-radius);\n  }\n\n  // Align badges within list items\n  > .badge {\n    float: right;\n  }\n  > .badge + .badge {\n    margin-right: 5px;\n  }\n}\n\n\n// Linked list items\n//\n// Use anchor elements instead of `li`s or `div`s to create linked list items.\n// Includes an extra `.active` modifier class for showing selected items.\n\na.list-group-item {\n  color: @list-group-link-color;\n\n  .list-group-item-heading {\n    color: @list-group-link-heading-color;\n  }\n\n  // Hover state\n  &:hover,\n  &:focus {\n    text-decoration: none;\n    background-color: @list-group-hover-bg;\n  }\n\n  // Active class on item itself, not parent\n  &.active,\n  &.active:hover,\n  &.active:focus {\n    z-index: 2; // Place active items above their siblings for proper border styling\n    color: @list-group-active-color;\n    background-color: @list-group-active-bg;\n    border-color: @list-group-active-border;\n\n    // Force color to inherit for custom content\n    .list-group-item-heading {\n      color: inherit;\n    }\n    .list-group-item-text {\n      color: @list-group-active-text-color;\n    }\n  }\n}\n\n\n// Contextual variants\n//\n// Add modifier classes to change text and background color on individual items.\n// Organizationally, this must come after the `:hover` states.\n\n.list-group-item-variant(success; @state-success-bg; @state-success-text);\n.list-group-item-variant(info; @state-info-bg; @state-info-text);\n.list-group-item-variant(warning; @state-warning-bg; @state-warning-text);\n.list-group-item-variant(danger; @state-danger-bg; @state-danger-text);\n\n\n// Custom content options\n//\n// Extra classes for creating well-formatted content within `.list-group-item`s.\n\n.list-group-item-heading {\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n.list-group-item-text {\n  margin-bottom: 0;\n  line-height: 1.3;\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/media.less",
    "content": "// Media objects\n// Source: http://stubbornella.org/content/?p=497\n// --------------------------------------------------\n\n\n// Common styles\n// -------------------------\n\n// Clear the floats\n.media,\n.media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n\n// Proper spacing between instances of .media\n.media,\n.media .media {\n  margin-top: 15px;\n}\n.media:first-child {\n  margin-top: 0;\n}\n\n// For images and videos, set to block\n.media-object {\n  display: block;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n  margin: 0 0 5px;\n}\n\n\n// Media image alignment\n// -------------------------\n\n.media {\n  > .pull-left {\n    margin-right: 10px;\n  }\n  > .pull-right {\n    margin-left: 10px;\n  }\n}\n\n\n// Media list variation\n// -------------------------\n\n// Undo default ul/ol styles\n.media-list {\n  padding-left: 0;\n  list-style: none;\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/mixins.less",
    "content": "//\n// Mixins\n// --------------------------------------------------\n\n// Utilities\n// -------------------------\n\n// Clearfix\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\n//\n// For modern browsers\n// 1. The space content is one way to avoid an Opera bug when the\n//    contenteditable attribute is included anywhere else in the document.\n//    Otherwise it causes space to appear at the top and bottom of elements\n//    that are clearfixed.\n// 2. The use of `table` rather than `block` is only necessary if using\n//    `:before` to contain the top-margins of child elements.\n.clearfix() {\n  &:before,\n  &:after {\n    content: \" \"; // 1\n    display: table; // 2\n  }\n  &:after {\n    clear: both;\n  }\n}\n\n// WebKit-style focus\n.tab-focus() {\n  // Default\n  outline: thin dotted;\n  // WebKit\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n// Center-align a block level element\n.center-block() {\n  display: block;\n  margin-left: auto;\n  margin-right: auto;\n}\n\n// Sizing shortcuts\n.size(@width; @height) {\n  width: @width;\n  height: @height;\n}\n\n.square(@size) {\n  .size(@size; @size);\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n  &::-moz-placeholder {\n    color: @color; // Firefox\n    opacity: 1;\n  }\n  // See https://github.com/twbs/bootstrap/pull/11526\n  &:-ms-input-placeholder {\n    color: @color;\n  }\n  // Internet Explorer 10+\n  &::-webkit-input-placeholder {\n    color: @color;\n  }\n  // Safari and Chrome\n}\n\n// Text overflow\n// Requires inline-block or block for proper styling\n.text-overflow() {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n// CSS image replacement\n//\n// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. Note\n// that we cannot chain the mixins together in Less, so they are repeated.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (will be removed in v4)\n.hide-text() {\n  font: ~\"0/0\" a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n// New mixin to use as of v3.0.1\n.text-hide() {\n  .hide-text();\n}\n\n// CSS3 PROPERTIES\n// --------------------------------------------------\n\n// Single side border-radius\n.border-top-radius(@radius) {\n  border-top-right-radius: @radius;\n  border-top-left-radius: @radius;\n}\n\n.border-right-radius(@radius) {\n  border-bottom-right-radius: @radius;\n  border-top-right-radius: @radius;\n}\n\n.border-bottom-radius(@radius) {\n  border-bottom-right-radius: @radius;\n  border-bottom-left-radius: @radius;\n}\n\n.border-left-radius(@radius) {\n  border-bottom-left-radius: @radius;\n  border-top-left-radius: @radius;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n//   supported browsers that have box shadow capabilities now support the\n//   standard `box-shadow` property.\n.box-shadow(@shadow) {\n  -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n  box-shadow: @shadow;\n}\n\n// Transitions\n.transition(@transition) {\n  -webkit-transition: @transition;\n  transition: @transition;\n}\n\n.transition-property(@transition-property) {\n  -webkit-transition-property: @transition-property;\n  transition-property: @transition-property;\n}\n\n.transition-delay(@transition-delay) {\n  -webkit-transition-delay: @transition-delay;\n  transition-delay: @transition-delay;\n}\n\n.transition-duration(@transition-duration) {\n  -webkit-transition-duration: @transition-duration;\n  transition-duration: @transition-duration;\n}\n\n.transition-transform(@transition) {\n  -webkit-transition: -webkit-transform @transition;\n  -moz-transition: -moz-transform @transition;\n  -o-transition: -o-transform @transition;\n  transition: transform @transition;\n}\n\n// Transformations\n.rotate(@degrees) {\n  -webkit-transform: rotate(@degrees);\n  -ms-transform: rotate(@degrees); // IE9 only\n  transform: rotate(@degrees);\n}\n\n.scale(@ratio; @ratio-y...) {\n  -webkit-transform: scale(@ratio, @ratio-y);\n  -ms-transform: scale(@ratio, @ratio-y); // IE9 only\n  transform: scale(@ratio, @ratio-y);\n}\n\n.translate(@x; @y) {\n  -webkit-transform: translate(@x, @y);\n  -ms-transform: translate(@x, @y); // IE9 only\n  transform: translate(@x, @y);\n}\n\n.skew(@x; @y) {\n  -webkit-transform: skew(@x, @y);\n  -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n  transform: skew(@x, @y);\n}\n\n.translate3d(@x; @y; @z) {\n  -webkit-transform: translate3d(@x, @y, @z);\n  transform: translate3d(@x, @y, @z);\n}\n\n.rotateX(@degrees) {\n  -webkit-transform: rotateX(@degrees);\n  -ms-transform: rotateX(@degrees); // IE9 only\n  transform: rotateX(@degrees);\n}\n\n.rotateY(@degrees) {\n  -webkit-transform: rotateY(@degrees);\n  -ms-transform: rotateY(@degrees); // IE9 only\n  transform: rotateY(@degrees);\n}\n\n.perspective(@perspective) {\n  -webkit-perspective: @perspective;\n  -moz-perspective: @perspective;\n  perspective: @perspective;\n}\n\n.perspective-origin(@perspective) {\n  -webkit-perspective-origin: @perspective;\n  -moz-perspective-origin: @perspective;\n  perspective-origin: @perspective;\n}\n\n.transform-origin(@origin) {\n  -webkit-transform-origin: @origin;\n  -moz-transform-origin: @origin;\n  -ms-transform-origin: @origin; // IE9 only\n  transform-origin: @origin;\n}\n\n// Animations\n.animation(@animation) {\n  -webkit-animation: @animation;\n  animation: @animation;\n}\n\n.animation-name(@name) {\n  -webkit-animation-name: @name;\n  animation-name: @name;\n}\n\n.animation-duration(@duration) {\n  -webkit-animation-duration: @duration;\n  animation-duration: @duration;\n}\n\n.animation-timing-function(@timing-function) {\n  -webkit-animation-timing-function: @timing-function;\n  animation-timing-function: @timing-function;\n}\n\n.animation-delay(@delay) {\n  -webkit-animation-delay: @delay;\n  animation-delay: @delay;\n}\n\n.animation-iteration-count(@iteration-count) {\n  -webkit-animation-iteration-count: @iteration-count;\n  animation-iteration-count: @iteration-count;\n}\n\n.animation-direction(@direction) {\n  -webkit-animation-direction: @direction;\n  animation-direction: @direction;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n.backface-visibility(@visibility) {\n  -webkit-backface-visibility: @visibility;\n  -moz-backface-visibility: @visibility;\n  backface-visibility: @visibility;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n  -webkit-box-sizing: @boxmodel;\n  -moz-box-sizing: @boxmodel;\n  box-sizing: @boxmodel;\n}\n\n// User select\n// For selecting text on the page\n.user-select(@select) {\n  -webkit-user-select: @select;\n  -moz-user-select: @select;\n  -ms-user-select: @select; // IE10+\n  user-select: @select;\n}\n\n// Resize anything\n.resizable(@direction) {\n  resize: @direction; // Options: horizontal, vertical, both\n  overflow: auto; // Safari fix\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n  -webkit-column-count: @column-count;\n  -moz-column-count: @column-count;\n  column-count: @column-count;\n  -webkit-column-gap: @column-gap;\n  -moz-column-gap: @column-gap;\n  column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n  word-wrap: break-word;\n  -webkit-hyphens: @mode;\n  -moz-hyphens: @mode;\n  -ms-hyphens: @mode; // IE10+\n  -o-hyphens: @mode;\n  hyphens: @mode;\n}\n\n// Opacity\n.opacity(@opacity) {\n  opacity: @opacity;\n  // IE8 filter\n  @opacity-ie: (@opacity * 100);\n  filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n\n// GRADIENTS\n// --------------------------------------------------\n\n#gradient {\n\n  // Horizontal gradient, from left to right\n  //\n  // Creates two color stops, start and end, by specifying a color and position for each color stop.\n  // Color stops are not available in IE9 and below.\n  .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n    background-image: -webkit-linear-gradient(left, color-stop(@start-color @start-percent), color-stop(@end-color @end-percent)); // Safari 5.1-6, Chrome 10+\n    background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n    background-repeat: repeat-x;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color), argb(@end-color))); // IE9 and down\n  }\n\n  // Vertical gradient, from top to bottom\n  //\n  // Creates two color stops, start and end, by specifying a color and position for each color stop.\n  // Color stops are not available in IE9 and below.\n  .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n    background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n    background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n    background-repeat: repeat-x;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color), argb(@end-color))); // IE9 and down\n  }\n\n  .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n    background-repeat: repeat-x;\n    background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n    background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n  }\n  .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n    background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n    background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n    background-repeat: no-repeat;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color), argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n  }\n  .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n    background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-repeat: no-repeat;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color), argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n  }\n  .radial(@inner-color: #555; @outer-color: #333) {\n    background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n    background-image: radial-gradient(circle, @inner-color, @outer-color);\n    background-repeat: no-repeat;\n  }\n  .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n    background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n    background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n  }\n}\n\n// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n.reset-filter() {\n  filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n\n// Retina images\n//\n// Short retina mixin for setting background-image and -size\n\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n  background-image: url(\"@{file-1x}\");\n\n  @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (   min--moz-device-pixel-ratio: 2), only screen and (     -o-min-device-pixel-ratio: 2/1), only screen and (        min-device-pixel-ratio: 2), only screen and (                min-resolution: 192dpi), only screen and (                min-resolution: 2dppx) {\n    background-image: url(\"@{file-2x}\");\n    background-size: @width-1x @height-1x;\n  }\n}\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n\n.img-responsive(@display: block) {\n  display: @display;\n  max-width: 100%; // Part 1: Set a maximum relative to the parent\n  height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n// COMPONENT MIXINS\n// --------------------------------------------------\n\n// Horizontal dividers\n// -------------------------\n// Dividers (basically an hr) within dropdowns and nav lists\n.nav-divider(@color: #e5e5e5) {\n  height: 1px;\n  margin: ((@line-height-computed / 2) - 1) 0;\n  overflow: hidden;\n  background-color: @color;\n}\n\n// Panels\n// -------------------------\n.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {\n  border-color: @border;\n\n  & > .panel-heading {\n    color: @heading-text-color;\n    background-color: @heading-bg-color;\n    border-color: @heading-border;\n\n    + .panel-collapse .panel-body {\n      border-top-color: @border;\n    }\n  }\n  & > .panel-footer {\n    + .panel-collapse .panel-body {\n      border-bottom-color: @border;\n    }\n  }\n}\n\n// Alerts\n// -------------------------\n.alert-variant(@background; @border; @text-color) {\n  background-color: @background;\n  border-color: @border;\n  color: @text-color;\n\n  hr {\n    border-top-color: darken(@border, 5%);\n  }\n  .alert-link {\n    color: darken(@text-color, 10%);\n  }\n}\n\n// Tables\n// -------------------------\n.table-row-variant(@state; @background) {\n  // Exact selectors below required to override `.table-striped` and prevent\n  // inheritance to nested tables.\n  .table > thead > tr,\n  .table > tbody > tr,\n  .table > tfoot > tr {\n    > td.@{state},\n    > th.@{state},\n    &.@{state} > td,\n    &.@{state} > th {\n      background-color: @background;\n    }\n  }\n\n  // Hover states for `.table-hover`\n  // Note: this is not available for cells or rows within `thead` or `tfoot`.\n  .table-hover > tbody > tr {\n    > td.@{state}:hover,\n    > th.@{state}:hover,\n    &.@{state}:hover > td,\n    &.@{state}:hover > th {\n      background-color: darken(@background, 5%);\n    }\n  }\n}\n\n// List Groups\n// -------------------------\n.list-group-item-variant(@state; @background; @color) {\n  .list-group-item-@{state} {\n    color: @color;\n    background-color: @background;\n\n    a& {\n      color: @color;\n\n      .list-group-item-heading {\n        color: inherit;\n      }\n\n      &:hover,\n      &:focus {\n        color: @color;\n        background-color: darken(@background, 5%);\n      }\n      &.active,\n      &.active:hover,\n      &.active:focus {\n        color: #fff;\n        background-color: @color;\n        border-color: @color;\n      }\n    }\n  }\n}\n\n// Button variants\n// -------------------------\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n.button-variant(@color; @background; @border) {\n  color: @color;\n  background-color: @background;\n  border-color: @border;\n\n  &:hover,\n  &:focus,\n  &:active,\n  &.active,\n  .open .dropdown-toggle & {\n    color: @color;\n    background-color: darken(@background, 8%);\n    border-color: darken(@border, 12%);\n  }\n  &:active,\n  &.active,\n  .open .dropdown-toggle & {\n    background-image: none;\n  }\n  &.disabled,\n  &[disabled],\n  fieldset[disabled] & {\n    &,\n    &:hover,\n    &:focus,\n    &:active,\n    &.active {\n      background-color: @background;\n      border-color: @border;\n    }\n  }\n\n  .badge {\n    color: @background;\n    background-color: @color;\n  }\n}\n\n// Button sizes\n// -------------------------\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n  padding: @padding-vertical @padding-horizontal;\n  font-size: @font-size;\n  line-height: @line-height;\n  border-radius: @border-radius;\n}\n\n// Pagination\n// -------------------------\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) {\n  > li {\n    > a,\n    > span {\n      padding: @padding-vertical @padding-horizontal;\n      font-size: @font-size;\n    }\n    &:first-child {\n      > a,\n      > span {\n        .border-left-radius(@border-radius);\n      }\n    }\n    &:last-child {\n      > a,\n      > span {\n        .border-right-radius(@border-radius);\n      }\n    }\n  }\n}\n\n// Labels\n// -------------------------\n.label-variant(@color) {\n  background-color: @color;\n  &[href] {\n    &:hover,\n    &:focus {\n      background-color: darken(@color, 10%);\n    }\n  }\n}\n\n// Contextual backgrounds\n// -------------------------\n.bg-variant(@color) {\n  background-color: @color;\n  a&:hover {\n    background-color: darken(@color, 10%);\n  }\n}\n\n// Typography\n// -------------------------\n.text-emphasis-variant(@color) {\n  color: @color;\n  a&:hover {\n    color: darken(@color, 10%);\n  }\n}\n\n// Navbar vertical align\n// -------------------------\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n.navbar-vertical-align(@element-height) {\n  margin-top: ((@navbar-height - @element-height) / 2);\n  margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n\n// Progress bars\n// -------------------------\n.progress-bar-variant(@color) {\n  background-color: @color;\n  .progress-striped & {\n    #gradient > .striped();\n  }\n}\n\n// Responsive utilities\n// -------------------------\n// More easily include all the states for responsive-utilities.less.\n.responsive-visibility() {\n  display: block !important;\n  table& {\n    display: table;\n  }\n  tr& {\n    display: table-row !important;\n  }\n  th&,\n  td& {\n    display: table-cell !important;\n  }\n}\n\n.responsive-invisibility() {\n  display: none !important;\n}\n\n// Grid System\n// -----------\n\n// Centered container element\n.container-fixed() {\n  margin-right: auto;\n  margin-left: auto;\n  padding-left: (@grid-gutter-width / 2);\n  padding-right: (@grid-gutter-width / 2);\n  &:extend(.clearfix all)\n;\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n  margin-left: (@gutter / -2);\n  margin-right: (@gutter / -2);\n  &:extend(.clearfix all)\n;\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  float: left;\n  width: percentage((@columns / @grid-columns));\n  min-height: 1px;\n  padding-left: (@gutter / 2);\n  padding-right: (@gutter / 2);\n}\n\n.make-xs-column-offset(@columns) {\n  @media (min-width: @screen-xs-min) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n\n.make-xs-column-push(@columns) {\n  @media (min-width: @screen-xs-min) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n\n.make-xs-column-pull(@columns) {\n  @media (min-width: @screen-xs-min) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  min-height: 1px;\n  padding-left: (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  @media (min-width: @screen-sm-min) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n\n.make-sm-column-offset(@columns) {\n  @media (min-width: @screen-sm-min) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n\n.make-sm-column-push(@columns) {\n  @media (min-width: @screen-sm-min) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n\n.make-sm-column-pull(@columns) {\n  @media (min-width: @screen-sm-min) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  min-height: 1px;\n  padding-left: (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  @media (min-width: @screen-md-min) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n\n.make-md-column-offset(@columns) {\n  @media (min-width: @screen-md-min) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n\n.make-md-column-push(@columns) {\n  @media (min-width: @screen-md-min) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n\n.make-md-column-pull(@columns) {\n  @media (min-width: @screen-md-min) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  min-height: 1px;\n  padding-left: (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  @media (min-width: @screen-lg-min) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n\n.make-lg-column-offset(@columns) {\n  @media (min-width: @screen-lg-min) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n\n.make-lg-column-push(@columns) {\n  @media (min-width: @screen-lg-min) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n\n.make-lg-column-pull(@columns) {\n  @media (min-width: @screen-lg-min) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n\n// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n  // Common styles for all sizes of grid columns, widths 1-12\n  .col(@index) when (@index = 1) {\n    // initial\n    @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n    .col((@index + 1), @item);\n  }\n  .col(@index, @list) when (@index =< @grid-columns) {\n    // general; \"=<\" isn't a typo\n    @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n    .col((@index + 1), ~\"@{list}, @{item}\");\n  }\n  .col(@index, @list) when (@index > @grid-columns) {\n    // terminal\n    @{list} {\n      position: relative;\n      // Prevent columns from collapsing when empty\n      min-height: 1px;\n      // Inner gutter via padding\n      padding-left: (@grid-gutter-width / 2);\n      padding-right: (@grid-gutter-width / 2);\n    }\n  }\n  .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n  .col(@index) when (@index = 1) {\n    // initial\n    @item: ~\".col-@{class}-@{index}\";\n    .col((@index + 1), @item);\n  }\n  .col(@index, @list) when (@index =< @grid-columns) {\n    // general\n    @item: ~\".col-@{class}-@{index}\";\n    .col((@index + 1), ~\"@{list}, @{item}\");\n  }\n  .col(@index, @list) when (@index > @grid-columns) {\n    // terminal\n    @{list} {\n      float: left;\n    }\n  }\n  .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n  .col-@{class}-@{index} {\n    width: percentage((@index / @grid-columns));\n  }\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = push) {\n  .col-@{class}-push-@{index} {\n    left: percentage((@index / @grid-columns));\n  }\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = pull) {\n  .col-@{class}-pull-@{index} {\n    right: percentage((@index / @grid-columns));\n  }\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n  .col-@{class}-offset-@{index} {\n    margin-left: percentage((@index / @grid-columns));\n  }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n  .calc-grid-column(@index, @class, @type);\n  // next iteration\n  .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n  .float-grid-columns(@class);\n  .loop-grid-columns(@grid-columns, @class, width);\n  .loop-grid-columns(@grid-columns, @class, pull);\n  .loop-grid-columns(@grid-columns, @class, push);\n  .loop-grid-columns(@grid-columns, @class, offset);\n}\n\n// Form validation states\n//\n// Used in forms.less to generate the form validation CSS for warnings, errors,\n// and successes.\n\n.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {\n  // Color the label and help text\n  .help-block,\n  .control-label,\n  .radio,\n  .checkbox,\n  .radio-inline,\n  .checkbox-inline {\n    color: @text-color;\n  }\n  // Set the border and box shadow on specific inputs to match\n  .form-control {\n    border-color: @border-color;\n    .box-shadow(inset 0 1px 1px rgba(0, 0, 0, .075)); // Redeclare so transitions work\n    &:focus {\n      border-color: darken(@border-color, 10%);\n      @shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px lighten(@border-color, 20%);\n      .box-shadow(@shadow);\n    }\n  }\n  // Set validation states also for addons\n  .input-group-addon {\n    color: @text-color;\n    border-color: @border-color;\n    background-color: @background-color;\n  }\n  // Optional feedback icon\n  .form-control-feedback {\n    color: @text-color;\n  }\n}\n\n// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which defaults to the `@input-focus-border` variable.\n//\n// We highly encourage you to not customize the default value, but instead use\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\n// WebKit's default styles, but applicable to a wider range of browsers. Its\n// usability and accessibility should be taken into account with any change.\n//\n// Example usage: change the default blue border and shadow to white for better\n// contrast against a dark gray background.\n\n.form-control-focus(@color: @input-border-focus) {\n  @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);\n  &:focus {\n    border-color: @color;\n    outline: 0;\n    .box-shadow(~\"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}\");\n  }\n}\n\n// Form control sizing\n//\n// Relative text size, padding, and border-radii changes for form controls. For\n// horizontal sizing, wrap controls in the predefined grid classes. `<select>`\n// element gets special love because it's special, and that's a fact!\n\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n  height: @input-height;\n  padding: @padding-vertical @padding-horizontal;\n  font-size: @font-size;\n  line-height: @line-height;\n  border-radius: @border-radius;\n\n  select& {\n    height: @input-height;\n    line-height: @input-height;\n  }\n\n  textarea&,\n  select[multiple] & {\n    height: auto;\n  }\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/modals.less",
    "content": "//\n// Modals\n// --------------------------------------------------\n\n// .modal-open      - body class for killing the scroll\n// .modal           - container to scroll within\n// .modal-dialog    - positioning shell for the actual modal\n// .modal-content   - actual modal w/ bg and corners and shit\n\n// Kill the scroll on the body\n.modal-open {\n  overflow: hidden;\n}\n\n// Container that the modal scrolls within\n.modal {\n  display: none;\n  overflow: auto;\n  overflow-y: scroll;\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: @zindex-modal;\n  -webkit-overflow-scrolling: touch;\n\n  // Prevent Chrome on Windows from adding a focus outline. For details, see\n  // https://github.com/twbs/bootstrap/pull/10951.\n  outline: 0;\n\n  // When fading in the modal, animate it to slide down\n  &.fade .modal-dialog {\n    .translate(0, -25%);\n    .transition-transform(~\"0.3s ease-out\");\n  }\n  &.in .modal-dialog {\n    .translate(0, 0)\n  }\n}\n\n// Shell div to position the modal with bottom padding\n.modal-dialog {\n  position: relative;\n  width: auto;\n  margin: 10px;\n}\n\n// Actual modal\n.modal-content {\n  position: relative;\n  background-color: @modal-content-bg;\n  border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)\n  border: 1px solid @modal-content-border-color;\n  border-radius: @border-radius-large;\n  .box-shadow(0 3px 9px rgba(0, 0, 0, .5));\n  background-clip: padding-box;\n  // Remove focus outline from opened modal\n  outline: none;\n}\n\n// Modal background\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: @zindex-modal-background;\n  background-color: @modal-backdrop-bg;\n  // Fade for backdrop\n  &.fade {\n    .opacity(0);\n  }\n  &.in {\n    .opacity(@modal-backdrop-opacity);\n  }\n}\n\n// Modal header\n// Top section of the modal w/ title and dismiss\n.modal-header {\n  padding: @modal-title-padding;\n  border-bottom: 1px solid @modal-header-border-color;\n  min-height: (@modal-title-padding + @modal-title-line-height);\n}\n\n// Close icon\n.modal-header .close {\n  margin-top: -2px;\n}\n\n// Title text within header\n.modal-title {\n  margin: 0;\n  line-height: @modal-title-line-height;\n}\n\n// Modal body\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\n.modal-body {\n  position: relative;\n  padding: @modal-inner-padding;\n}\n\n// Footer (for actions)\n.modal-footer {\n  margin-top: 15px;\n  padding: (@modal-inner-padding - 1) @modal-inner-padding @modal-inner-padding;\n  text-align: right; // right align buttons\n  border-top: 1px solid @modal-footer-border-color;\n  &:extend(.clearfix all)\n; // clear it in case folks use .pull-* classes on buttons\n\n  // Properly space out buttons\n  .btn + .btn {\n    margin-left: 5px;\n    margin-bottom: 0; // account for input[type=\"submit\"] which gets the bottom margin like all other inputs\n  }\n  // but override that for button groups\n  .btn-group .btn + .btn {\n    margin-left: -1px;\n  }\n  // and override it for block buttons as well\n  .btn-block + .btn-block {\n    margin-left: 0;\n  }\n}\n\n// Scale up the modal\n@media (min-width: @screen-sm-min) {\n  // Automatically set modal's width for larger viewports\n  .modal-dialog {\n    width: @modal-md;\n    margin: 30px auto;\n  }\n\n  .modal-content {\n    .box-shadow(0 5px 15px rgba(0, 0, 0, .5));\n  }\n\n  // Modal sizes\n  .modal-sm {\n    width: @modal-sm;\n  }\n}\n\n@media (min-width: @screen-md-min) {\n  .modal-lg {\n    width: @modal-lg;\n  }\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/navbar.less",
    "content": "//\n// Navbars\n// --------------------------------------------------\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n  position: relative;\n  min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n  margin-bottom: @navbar-margin-bottom;\n  border: 1px solid transparent;\n\n  // Prevent floats from breaking the navbar\n  &:extend(.clearfix all)\n;\n\n  @media (min-width: @grid-float-breakpoint) {\n    border-radius: @navbar-border-radius;\n  }\n}\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n  &:extend(.clearfix all)\n;\n\n  @media (min-width: @grid-float-breakpoint) {\n    float: left;\n  }\n}\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n  max-height: @navbar-collapse-max-height;\n  overflow-x: visible;\n  padding-right: @navbar-padding-horizontal;\n  padding-left: @navbar-padding-horizontal;\n  border-top: 1px solid transparent;\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);\n  &:extend(.clearfix all)\n;\n  -webkit-overflow-scrolling: touch;\n\n  &.in {\n    overflow-y: auto;\n  }\n\n  @media (min-width: @grid-float-breakpoint) {\n    width: auto;\n    border-top: 0;\n    box-shadow: none;\n\n    &.collapse {\n      display: block !important;\n      height: auto !important;\n      padding-bottom: 0; // Override default setting\n      overflow: visible !important;\n    }\n\n    &.in {\n      overflow-y: visible;\n    }\n\n    // Undo the collapse side padding for navbars with containers to ensure\n    // alignment of right-aligned contents.\n    .navbar-fixed-top &,\n    .navbar-static-top &,\n    .navbar-fixed-bottom & {\n      padding-left: 0;\n      padding-right: 0;\n    }\n  }\n}\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n  > .navbar-header,\n  > .navbar-collapse {\n    margin-right: -@navbar-padding-horizontal;\n    margin-left: -@navbar-padding-horizontal;\n\n    @media (min-width: @grid-float-breakpoint) {\n      margin-right: 0;\n      margin-left: 0;\n    }\n  }\n}\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n  z-index: @zindex-navbar;\n  border-width: 0 0 1px;\n\n  @media (min-width: @grid-float-breakpoint) {\n    border-radius: 0;\n  }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: @zindex-navbar-fixed;\n\n  // Undo the rounded corners\n  @media (min-width: @grid-float-breakpoint) {\n    border-radius: 0;\n  }\n}\n\n.navbar-fixed-top {\n  top: 0;\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0; // override .navbar defaults\n  border-width: 1px 0 0;\n}\n\n// Brand/project name\n\n.navbar-brand {\n  float: left;\n  padding: @navbar-padding-vertical @navbar-padding-horizontal;\n  font-size: @font-size-large;\n  line-height: @line-height-computed;\n  height: @navbar-height;\n\n  &:hover,\n  &:focus {\n    text-decoration: none;\n  }\n\n  @media (min-width: @grid-float-breakpoint) {\n    .navbar > .container &,\n    .navbar > .container-fluid & {\n      margin-left: -@navbar-padding-horizontal;\n    }\n  }\n}\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n  position: relative;\n  float: right;\n  margin-right: @navbar-padding-horizontal;\n  padding: 9px 10px;\n  .navbar-vertical-align(34px);\n  background-color: transparent;\n  background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n  border: 1px solid transparent;\n  border-radius: @border-radius-base;\n\n  // We remove the `outline` here, but later compensate by attaching `:hover`\n  // styles to `:focus`.\n  &:focus {\n    outline: none;\n  }\n\n  // Bars\n  .icon-bar {\n    display: block;\n    width: 22px;\n    height: 2px;\n    border-radius: 1px;\n  }\n  .icon-bar + .icon-bar {\n    margin-top: 4px;\n  }\n\n  @media (min-width: @grid-float-breakpoint) {\n    display: none;\n  }\n}\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n  margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n  > li > a {\n    padding-top: 10px;\n    padding-bottom: 10px;\n    line-height: @line-height-computed;\n  }\n\n  @media (max-width: @grid-float-breakpoint-max) {\n    // Dropdowns get custom display when collapsed\n    .open .dropdown-menu {\n      position: static;\n      float: none;\n      width: auto;\n      margin-top: 0;\n      background-color: transparent;\n      border: 0;\n      box-shadow: none;\n      > li > a,\n      .dropdown-header {\n        padding: 5px 15px 5px 25px;\n      }\n      > li > a {\n        line-height: @line-height-computed;\n        &:hover,\n        &:focus {\n          background-image: none;\n        }\n      }\n    }\n  }\n\n  // Uncollapse the nav\n  @media (min-width: @grid-float-breakpoint) {\n    float: left;\n    margin: 0;\n\n    > li {\n      float: left;\n      > a {\n        padding-top: @navbar-padding-vertical;\n        padding-bottom: @navbar-padding-vertical;\n      }\n    }\n\n    &.navbar-right:last-child {\n      margin-right: -@navbar-padding-horizontal;\n    }\n  }\n}\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n\n@media (min-width: @grid-float-breakpoint) {\n  .navbar-left {\n    .pull-left();\n  }\n\n  .navbar-right {\n    .pull-right();\n  }\n}\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n  margin-left: -@navbar-padding-horizontal;\n  margin-right: -@navbar-padding-horizontal;\n  padding: 10px @navbar-padding-horizontal;\n  border-top: 1px solid transparent;\n  border-bottom: 1px solid transparent;\n  @shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);\n  .box-shadow(@shadow);\n\n  // Mixin behavior for optimum display\n  .form-inline();\n\n  .form-group {\n    @media (max-width: @grid-float-breakpoint-max) {\n      margin-bottom: 5px;\n    }\n  }\n\n  // Vertically center in expanded, horizontal navbar\n  .navbar-vertical-align(@input-height-base);\n\n  // Undo 100% width for pull classes\n  @media (min-width: @grid-float-breakpoint) {\n    width: auto;\n    border: 0;\n    margin-left: 0;\n    margin-right: 0;\n    padding-top: 0;\n    padding-bottom: 0;\n    .box-shadow(none);\n\n    // Outdent the form if last child to line up with content down the page\n    &.navbar-right:last-child {\n      margin-right: -@navbar-padding-horizontal;\n    }\n  }\n}\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  .border-top-radius(0);\n}\n\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  .border-bottom-radius(0);\n}\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n  .navbar-vertical-align(@input-height-base);\n\n  &.btn-sm {\n    .navbar-vertical-align(@input-height-small);\n  }\n  &.btn-xs {\n    .navbar-vertical-align(22);\n  }\n}\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n  .navbar-vertical-align(@line-height-computed);\n\n  @media (min-width: @grid-float-breakpoint) {\n    float: left;\n    margin-left: @navbar-padding-horizontal;\n    margin-right: @navbar-padding-horizontal;\n\n    // Outdent the form if last child to line up with content down the page\n    &.navbar-right:last-child {\n      margin-right: 0;\n    }\n  }\n}\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n  background-color: @navbar-default-bg;\n  border-color: @navbar-default-border;\n\n  .navbar-brand {\n    color: @navbar-default-brand-color;\n    &:hover,\n    &:focus {\n      color: @navbar-default-brand-hover-color;\n      background-color: @navbar-default-brand-hover-bg;\n    }\n  }\n\n  .navbar-text {\n    color: @navbar-default-color;\n  }\n\n  .navbar-nav {\n    > li > a {\n      color: @navbar-default-link-color;\n\n      &:hover,\n      &:focus {\n        color: @navbar-default-link-hover-color;\n        background-color: @navbar-default-link-hover-bg;\n      }\n    }\n    > .active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @navbar-default-link-active-color;\n        background-color: @navbar-default-link-active-bg;\n      }\n    }\n    > .disabled > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @navbar-default-link-disabled-color;\n        background-color: @navbar-default-link-disabled-bg;\n      }\n    }\n  }\n\n  .navbar-toggle {\n    border-color: @navbar-default-toggle-border-color;\n    &:hover,\n    &:focus {\n      background-color: @navbar-default-toggle-hover-bg;\n    }\n    .icon-bar {\n      background-color: @navbar-default-toggle-icon-bar-bg;\n    }\n  }\n\n  .navbar-collapse,\n  .navbar-form {\n    border-color: @navbar-default-border;\n  }\n\n  // Dropdown menu items\n  .navbar-nav {\n    // Remove background color from open dropdown\n    > .open > a {\n      &,\n      &:hover,\n      &:focus {\n        background-color: @navbar-default-link-active-bg;\n        color: @navbar-default-link-active-color;\n      }\n    }\n\n    @media (max-width: @grid-float-breakpoint-max) {\n      // Dropdowns get custom display when collapsed\n      .open .dropdown-menu {\n        > li > a {\n          color: @navbar-default-link-color;\n          &:hover,\n          &:focus {\n            color: @navbar-default-link-hover-color;\n            background-color: @navbar-default-link-hover-bg;\n          }\n        }\n        > .active > a {\n          &,\n          &:hover,\n          &:focus {\n            color: @navbar-default-link-active-color;\n            background-color: @navbar-default-link-active-bg;\n          }\n        }\n        > .disabled > a {\n          &,\n          &:hover,\n          &:focus {\n            color: @navbar-default-link-disabled-color;\n            background-color: @navbar-default-link-disabled-bg;\n          }\n        }\n      }\n    }\n  }\n\n  // Links in navbars\n  //\n  // Add a class to ensure links outside the navbar nav are colored correctly.\n\n  .navbar-link {\n    color: @navbar-default-link-color;\n    &:hover {\n      color: @navbar-default-link-hover-color;\n    }\n  }\n\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n  background-color: @navbar-inverse-bg;\n  border-color: @navbar-inverse-border;\n\n  .navbar-brand {\n    color: @navbar-inverse-brand-color;\n    &:hover,\n    &:focus {\n      color: @navbar-inverse-brand-hover-color;\n      background-color: @navbar-inverse-brand-hover-bg;\n    }\n  }\n\n  .navbar-text {\n    color: @navbar-inverse-color;\n  }\n\n  .navbar-nav {\n    > li > a {\n      color: @navbar-inverse-link-color;\n\n      &:hover,\n      &:focus {\n        color: @navbar-inverse-link-hover-color;\n        background-color: @navbar-inverse-link-hover-bg;\n      }\n    }\n    > .active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @navbar-inverse-link-active-color;\n        background-color: @navbar-inverse-link-active-bg;\n      }\n    }\n    > .disabled > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @navbar-inverse-link-disabled-color;\n        background-color: @navbar-inverse-link-disabled-bg;\n      }\n    }\n  }\n\n  // Darken the responsive nav toggle\n  .navbar-toggle {\n    border-color: @navbar-inverse-toggle-border-color;\n    &:hover,\n    &:focus {\n      background-color: @navbar-inverse-toggle-hover-bg;\n    }\n    .icon-bar {\n      background-color: @navbar-inverse-toggle-icon-bar-bg;\n    }\n  }\n\n  .navbar-collapse,\n  .navbar-form {\n    border-color: darken(@navbar-inverse-bg, 7%);\n  }\n\n  // Dropdowns\n  .navbar-nav {\n    > .open > a {\n      &,\n      &:hover,\n      &:focus {\n        background-color: @navbar-inverse-link-active-bg;\n        color: @navbar-inverse-link-active-color;\n      }\n    }\n\n    @media (max-width: @grid-float-breakpoint-max) {\n      // Dropdowns get custom display\n      .open .dropdown-menu {\n        > .dropdown-header {\n          border-color: @navbar-inverse-border;\n        }\n        .divider {\n          background-color: @navbar-inverse-border;\n        }\n        > li > a {\n          color: @navbar-inverse-link-color;\n          &:hover,\n          &:focus {\n            color: @navbar-inverse-link-hover-color;\n            background-color: @navbar-inverse-link-hover-bg;\n          }\n        }\n        > .active > a {\n          &,\n          &:hover,\n          &:focus {\n            color: @navbar-inverse-link-active-color;\n            background-color: @navbar-inverse-link-active-bg;\n          }\n        }\n        > .disabled > a {\n          &,\n          &:hover,\n          &:focus {\n            color: @navbar-inverse-link-disabled-color;\n            background-color: @navbar-inverse-link-disabled-bg;\n          }\n        }\n      }\n    }\n  }\n\n  .navbar-link {\n    color: @navbar-inverse-link-color;\n    &:hover {\n      color: @navbar-inverse-link-hover-color;\n    }\n  }\n\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/navs.less",
    "content": "//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n  margin-bottom: 0;\n  padding-left: 0; // Override default ul/ol\n  list-style: none;\n  &:extend(.clearfix all);\n\n  > li {\n    position: relative;\n    display: block;\n\n    > a {\n      position: relative;\n      display: block;\n      padding: @nav-link-padding;\n      &:hover,\n      &:focus {\n        text-decoration: none;\n        background-color: @nav-link-hover-bg;\n      }\n    }\n\n    // Disabled state sets text to gray and nukes hover/tab effects\n    &.disabled > a {\n      color: @nav-disabled-link-color;\n\n      &:hover,\n      &:focus {\n        color: @nav-disabled-link-hover-color;\n        text-decoration: none;\n        background-color: transparent;\n        cursor: not-allowed;\n      }\n    }\n  }\n\n  // Open dropdowns\n  .open > a {\n    &,\n    &:hover,\n    &:focus {\n      background-color: @nav-link-hover-bg;\n      border-color: @link-color;\n    }\n  }\n\n  // Nav dividers (deprecated with v3.0.1)\n  //\n  // This should have been removed in v3 with the dropping of `.nav-list`, but\n  // we missed it. We don't currently support this anywhere, but in the interest\n  // of maintaining backward compatibility in case you use it, it's deprecated.\n  .nav-divider {\n    .nav-divider();\n  }\n\n  // Prevent IE8 from misplacing imgs\n  //\n  // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n  > li > a > img {\n    max-width: none;\n  }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n  border-bottom: 1px solid @nav-tabs-border-color;\n  > li {\n    float: left;\n    // Make the list-items overlay the bottom border\n    margin-bottom: -1px;\n\n    // Actual tabs (as links)\n    > a {\n      margin-right: 2px;\n      line-height: @line-height-base;\n      border: 1px solid transparent;\n      border-radius: @border-radius-base @border-radius-base 0 0;\n      &:hover {\n        border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n      }\n    }\n\n    // Active state, and its :hover to override normal :hover\n    &.active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @nav-tabs-active-link-hover-color;\n        background-color: @nav-tabs-active-link-hover-bg;\n        border: 1px solid @nav-tabs-active-link-hover-border-color;\n        border-bottom-color: transparent;\n        cursor: default;\n      }\n    }\n  }\n  // pulling this in mainly for less shorthand\n  &.nav-justified {\n    .nav-justified();\n    .nav-tabs-justified();\n  }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n  > li {\n    float: left;\n\n    // Links rendered as pills\n    > a {\n      border-radius: @nav-pills-border-radius;\n    }\n    + li {\n      margin-left: 2px;\n    }\n\n    // Active state\n    &.active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @nav-pills-active-link-hover-color;\n        background-color: @nav-pills-active-link-hover-bg;\n      }\n    }\n  }\n}\n\n\n// Stacked pills\n.nav-stacked {\n  > li {\n    float: none;\n    + li {\n      margin-top: 2px;\n      margin-left: 0; // no need for this gap between nav items\n    }\n  }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n  width: 100%;\n\n  > li {\n    float: none;\n     > a {\n      text-align: center;\n      margin-bottom: 5px;\n    }\n  }\n\n  > .dropdown .dropdown-menu {\n    top: auto;\n    left: auto;\n  }\n\n  @media (min-width: @screen-sm-min) {\n    > li {\n      display: table-cell;\n      width: 1%;\n      > a {\n        margin-bottom: 0;\n      }\n    }\n  }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n  border-bottom: 0;\n\n  > li > a {\n    // Override margin from .nav-tabs\n    margin-right: 0;\n    border-radius: @border-radius-base;\n  }\n\n  > .active > a,\n  > .active > a:hover,\n  > .active > a:focus {\n    border: 1px solid @nav-tabs-justified-link-border-color;\n  }\n\n  @media (min-width: @screen-sm-min) {\n    > li > a {\n      border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n      border-radius: @border-radius-base @border-radius-base 0 0;\n    }\n    > .active > a,\n    > .active > a:hover,\n    > .active > a:focus {\n      border-bottom-color: @nav-tabs-justified-active-link-border-color;\n    }\n  }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n  > .tab-pane {\n    display: none;\n  }\n  > .active {\n    display: block;\n  }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n  // make dropdown border overlap tab border\n  margin-top: -1px;\n  // Remove the top rounded corners here since there is a hard edge above the menu\n  .border-top-radius(0);\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/normalize.less",
    "content": "/*! normalize.css v3.0.0 | MIT License | git.io/normalize */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS text size adjust after orientation change, without disabling\n//    user zoom.\n//\n\nhtml {\n  font-family: sans-serif; // 1\n  -ms-text-size-adjust: 100%; // 2\n  -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n  margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined in IE 8/9.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n  display: inline-block; // 1\n  vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9.\n// Hide the `template` element in IE, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n  display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n  background: transparent;\n}\n\n//\n// Improve readability when focused and also mouse hovered in all browsers.\n//\n\na:active,\na:hover {\n  outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9, Safari 5, and Chrome.\n//\n\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.\n//\n\nb,\nstrong {\n  font-weight: bold;\n}\n\n//\n// Address styling not present in Safari 5 and Chrome.\n//\n\ndfn {\n  font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari 5, and Chrome.\n//\n\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n  background: #ff0;\n  color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n  font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9.\n//\n\nimg {\n  border: 0;\n}\n\n//\n// Correct overflow displayed oddly in IE 9.\n//\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari 5.\n//\n\nfigure {\n  margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n  overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n//    Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  color: inherit; // 1\n  font: inherit; // 2\n  margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10.\n//\n\nbutton {\n  overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8+, and Opera\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n  text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n//    and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n//    `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button; // 2\n  cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n  line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  box-sizing: border-box; // 1\n  padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome\n//    (include `-moz` to future-proof).\n//\n\ninput[type=\"search\"] {\n  -webkit-appearance: textfield; // 1\n  -moz-box-sizing: content-box;\n  -webkit-box-sizing: content-box; // 2\n  box-sizing: content-box;\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n  border: 0; // 1\n  padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9.\n//\n\ntextarea {\n  overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n  font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\ntd,\nth {\n  padding: 0;\n}"
  },
  {
    "path": "server/public/css/lib/bootstrap/pager.less",
    "content": "//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n  padding-left: 0;\n  margin: @line-height-computed 0;\n  list-style: none;\n  text-align: center;\n  &:extend(.clearfix all);\n  li {\n    display: inline;\n    > a,\n    > span {\n      display: inline-block;\n      padding: 5px 14px;\n      background-color: @pager-bg;\n      border: 1px solid @pager-border;\n      border-radius: @pager-border-radius;\n    }\n\n    > a:hover,\n    > a:focus {\n      text-decoration: none;\n      background-color: @pager-hover-bg;\n    }\n  }\n\n  .next {\n    > a,\n    > span {\n      float: right;\n    }\n  }\n\n  .previous {\n    > a,\n    > span {\n      float: left;\n    }\n  }\n\n  .disabled {\n    > a,\n    > a:hover,\n    > a:focus,\n    > span {\n      color: @pager-disabled-color;\n      background-color: @pager-bg;\n      cursor: not-allowed;\n    }\n  }\n\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/pagination.less",
    "content": "//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: @line-height-computed 0;\n  border-radius: @border-radius-base;\n\n  > li {\n    display: inline; // Remove list-style and block-level defaults\n    > a,\n    > span {\n      position: relative;\n      float: left; // Collapse white-space\n      padding: @padding-base-vertical @padding-base-horizontal;\n      line-height: @line-height-base;\n      text-decoration: none;\n      color: @pagination-color;\n      background-color: @pagination-bg;\n      border: 1px solid @pagination-border;\n      margin-left: -1px;\n    }\n    &:first-child {\n      > a,\n      > span {\n        margin-left: 0;\n        .border-left-radius(@border-radius-base);\n      }\n    }\n    &:last-child {\n      > a,\n      > span {\n        .border-right-radius(@border-radius-base);\n      }\n    }\n  }\n\n  > li > a,\n  > li > span {\n    &:hover,\n    &:focus {\n      color: @pagination-hover-color;\n      background-color: @pagination-hover-bg;\n      border-color: @pagination-hover-border;\n    }\n  }\n\n  > .active > a,\n  > .active > span {\n    &,\n    &:hover,\n    &:focus {\n      z-index: 2;\n      color: @pagination-active-color;\n      background-color: @pagination-active-bg;\n      border-color: @pagination-active-border;\n      cursor: default;\n    }\n  }\n\n  > .disabled {\n    > span,\n    > span:hover,\n    > span:focus,\n    > a,\n    > a:hover,\n    > a:focus {\n      color: @pagination-disabled-color;\n      background-color: @pagination-disabled-bg;\n      border-color: @pagination-disabled-border;\n      cursor: not-allowed;\n    }\n  }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n  .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n  .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @border-radius-small);\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/panels.less",
    "content": "//\n// Panels\n// --------------------------------------------------\n\n// Base class\n.panel {\n  margin-bottom: @line-height-computed;\n  background-color: @panel-bg;\n  border: 1px solid transparent;\n  border-radius: @panel-border-radius;\n  .box-shadow(0 1px 1px rgba(0, 0, 0, .05));\n}\n\n// Panel contents\n.panel-body {\n  padding: @panel-body-padding;\n  &:extend(.clearfix all)\n;\n}\n\n// Optional heading\n.panel-heading {\n  padding: 10px 15px;\n  border-bottom: 1px solid transparent;\n  .border-top-radius((@panel-border-radius - 1));\n\n  > .dropdown .dropdown-toggle {\n    color: inherit;\n  }\n}\n\n// Within heading, strip any `h*` tag of its default margins for spacing.\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: ceil((@font-size-base * 1.125));\n  color: inherit;\n\n  > a {\n    color: inherit;\n  }\n}\n\n// Optional footer (stays gray in every modifier class)\n.panel-footer {\n  padding: 10px 15px;\n  background-color: @panel-footer-bg;\n  border-top: 1px solid @panel-inner-border;\n  .border-bottom-radius((@panel-border-radius - 1));\n}\n\n// List groups in panels\n//\n// By default, space out list group content from panel headings to account for\n// any kind of custom content between the two.\n\n.panel {\n  > .list-group {\n    margin-bottom: 0;\n\n    .list-group-item {\n      border-width: 1px 0;\n      border-radius: 0;\n    }\n\n    // Add border top radius for first one\n    &:first-child {\n      .list-group-item:first-child {\n        border-top: 0;\n        .border-top-radius((@panel-border-radius - 1));\n      }\n    }\n    // Add border bottom radius for last one\n    &:last-child {\n      .list-group-item:last-child {\n        border-bottom: 0;\n        .border-bottom-radius((@panel-border-radius - 1));\n      }\n    }\n  }\n}\n\n// Collapse space between when there's no additional content.\n.panel-heading + .list-group {\n  .list-group-item:first-child {\n    border-top-width: 0;\n  }\n}\n\n// Tables in panels\n//\n// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and\n// watch it go full width.\n\n.panel {\n  > .table,\n  > .table-responsive > .table {\n    margin-bottom: 0;\n  }\n  // Add border top radius for first one\n  > .table:first-child,\n  > .table-responsive:first-child > .table:first-child {\n    .border-top-radius((@panel-border-radius - 1));\n\n    > thead:first-child,\n    > tbody:first-child {\n      > tr:first-child {\n        td:first-child,\n        th:first-child {\n          border-top-left-radius: (@panel-border-radius - 1);\n        }\n        td:last-child,\n        th:last-child {\n          border-top-right-radius: (@panel-border-radius - 1);\n        }\n      }\n    }\n  }\n  // Add border bottom radius for last one\n  > .table:last-child,\n  > .table-responsive:last-child > .table:last-child {\n    .border-bottom-radius((@panel-border-radius - 1));\n\n    > tbody:last-child,\n    > tfoot:last-child {\n      > tr:last-child {\n        td:first-child,\n        th:first-child {\n          border-bottom-left-radius: (@panel-border-radius - 1);\n        }\n        td:last-child,\n        th:last-child {\n          border-bottom-right-radius: (@panel-border-radius - 1);\n        }\n      }\n    }\n  }\n  > .panel-body + .table,\n  > .panel-body + .table-responsive {\n    border-top: 1px solid @table-border-color;\n  }\n  > .table > tbody:first-child > tr:first-child th,\n  > .table > tbody:first-child > tr:first-child td {\n    border-top: 0;\n  }\n  > .table-bordered,\n  > .table-responsive > .table-bordered {\n    border: 0;\n    > thead,\n    > tbody,\n    > tfoot {\n      > tr {\n        > th:first-child,\n        > td:first-child {\n          border-left: 0;\n        }\n        > th:last-child,\n        > td:last-child {\n          border-right: 0;\n        }\n      }\n    }\n    > thead,\n    > tbody {\n      > tr:first-child {\n        > td,\n        > th {\n          border-bottom: 0;\n        }\n      }\n    }\n    > tbody,\n    > tfoot {\n      > tr:last-child {\n        > td,\n        > th {\n          border-bottom: 0;\n        }\n      }\n    }\n  }\n  > .table-responsive {\n    border: 0;\n    margin-bottom: 0;\n  }\n}\n\n// Collapsable panels (aka, accordion)\n//\n// Wrap a series of panels in `.panel-group` to turn them into an accordion with\n// the help of our collapse JavaScript plugin.\n\n.panel-group {\n  margin-bottom: @line-height-computed;\n\n  // Tighten up margin so it's only between panels\n  .panel {\n    margin-bottom: 0;\n    border-radius: @panel-border-radius;\n    overflow: hidden; // crop contents when collapsed\n    + .panel {\n      margin-top: 5px;\n    }\n  }\n\n  .panel-heading {\n    border-bottom: 0;\n    + .panel-collapse .panel-body {\n      border-top: 1px solid @panel-inner-border;\n    }\n  }\n  .panel-footer {\n    border-top: 0;\n    + .panel-collapse .panel-body {\n      border-bottom: 1px solid @panel-inner-border;\n    }\n  }\n}\n\n// Contextual variations\n.panel-default {\n  .panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border);\n}\n\n.panel-primary {\n  .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);\n}\n\n.panel-success {\n  .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);\n}\n\n.panel-info {\n  .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);\n}\n\n.panel-warning {\n  .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);\n}\n\n.panel-danger {\n  .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/popovers.less",
    "content": "//\n// Popovers\n// --------------------------------------------------\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: @zindex-popover;\n  display: none;\n  max-width: @popover-max-width;\n  padding: 1px;\n  text-align: left; // Reset given new insertion method\n  background-color: @popover-bg;\n  background-clip: padding-box;\n  border: 1px solid @popover-fallback-border-color;\n  border: 1px solid @popover-border-color;\n  border-radius: @border-radius-large;\n  .box-shadow(0 5px 10px rgba(0, 0, 0, .2));\n\n  // Overrides for proper insertion\n  white-space: normal;\n\n  // Offset the popover to account for the popover arrow\n  &.top {\n    margin-top: -@popover-arrow-width;\n  }\n  &.right {\n    margin-left: @popover-arrow-width;\n  }\n  &.bottom {\n    margin-top: @popover-arrow-width;\n  }\n  &.left {\n    margin-left: -@popover-arrow-width;\n  }\n}\n\n.popover-title {\n  margin: 0; // reset heading margin\n  padding: 8px 14px;\n  font-size: @font-size-base;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: @popover-title-bg;\n  border-bottom: 1px solid darken(@popover-title-bg, 5%);\n  border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n// Arrows\n//\n// .arrow is outer, .arrow:after is inner\n\n.popover > .arrow {\n  &,\n  &:after {\n    position: absolute;\n    display: block;\n    width: 0;\n    height: 0;\n    border-color: transparent;\n    border-style: solid;\n  }\n}\n\n.popover > .arrow {\n  border-width: @popover-arrow-outer-width;\n}\n\n.popover > .arrow:after {\n  border-width: @popover-arrow-width;\n  content: \"\";\n}\n\n.popover {\n  &.top > .arrow {\n    left: 50%;\n    margin-left: -@popover-arrow-outer-width;\n    border-bottom-width: 0;\n    border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-top-color: @popover-arrow-outer-color;\n    bottom: -@popover-arrow-outer-width;\n    &:after {\n      content: \" \";\n      bottom: 1px;\n      margin-left: -@popover-arrow-width;\n      border-bottom-width: 0;\n      border-top-color: @popover-arrow-color;\n    }\n  }\n  &.right > .arrow {\n    top: 50%;\n    left: -@popover-arrow-outer-width;\n    margin-top: -@popover-arrow-outer-width;\n    border-left-width: 0;\n    border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-right-color: @popover-arrow-outer-color;\n    &:after {\n      content: \" \";\n      left: 1px;\n      bottom: -@popover-arrow-width;\n      border-left-width: 0;\n      border-right-color: @popover-arrow-color;\n    }\n  }\n  &.bottom > .arrow {\n    left: 50%;\n    margin-left: -@popover-arrow-outer-width;\n    border-top-width: 0;\n    border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-bottom-color: @popover-arrow-outer-color;\n    top: -@popover-arrow-outer-width;\n    &:after {\n      content: \" \";\n      top: 1px;\n      margin-left: -@popover-arrow-width;\n      border-top-width: 0;\n      border-bottom-color: @popover-arrow-color;\n    }\n  }\n\n  &.left > .arrow {\n    top: 50%;\n    right: -@popover-arrow-outer-width;\n    margin-top: -@popover-arrow-outer-width;\n    border-right-width: 0;\n    border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-left-color: @popover-arrow-outer-color;\n    &:after {\n      content: \" \";\n      right: 1px;\n      border-right-width: 0;\n      border-left-color: @popover-arrow-color;\n      bottom: -@popover-arrow-width;\n    }\n  }\n\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/print.less",
    "content": "//\n// Basic print styles\n// --------------------------------------------------\n// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css\n\n@media print {\n\n  * {\n    text-shadow: none !important;\n    color: #000 !important; // Black prints faster: h5bp.com/s\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n\n  // Don't show links for images, or javascript/internal links\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n\n  thead {\n    display: table-header-group; // h5bp.com/t\n  }\n\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n\n  img {\n    max-width: 100% !important;\n  }\n\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n\n  // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245\n  // Once fixed, we can just straight up remove this.\n  select {\n    background: #fff !important;\n  }\n\n  // Bootstrap components\n  .navbar {\n    display: none;\n  }\n  .table {\n    td,\n    th {\n      background-color: #fff !important;\n    }\n  }\n  .btn,\n  .dropup > .btn {\n    > .caret {\n      border-top-color: #000 !important;\n    }\n  }\n  .label {\n    border: 1px solid #000;\n  }\n\n  .table {\n    border-collapse: collapse !important;\n  }\n  .table-bordered {\n    th,\n    td {\n      border: 1px solid #ddd !important;\n    }\n  }\n\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/progress-bars.less",
    "content": "//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n  overflow: hidden;\n  height: @line-height-computed;\n  margin-bottom: @line-height-computed;\n  background-color: @progress-bg;\n  border-radius: @border-radius-base;\n  .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n  float: left;\n  width: 0%;\n  height: 100%;\n  font-size: @font-size-small;\n  line-height: @line-height-computed;\n  color: @progress-bar-color;\n  text-align: center;\n  background-color: @progress-bar-bg;\n  .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n  .transition(width .6s ease);\n}\n\n// Striped bars\n.progress-striped .progress-bar {\n  #gradient > .striped();\n  background-size: 40px 40px;\n}\n\n// Call animation for the active one\n.progress.active .progress-bar {\n  .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n  .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n  .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n  .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n  .progress-bar-variant(@progress-bar-danger-bg);\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/responsive-utilities.less",
    "content": "//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n// IE10 in Windows (Phone) 8\n//\n// Support for responsive views via media queries is kind of borked in IE10, for\n// Surface/desktop in split view and for Windows Phone 8. This particular fix\n// must be accompanied by a snippet of JavaScript to sniff the user agent and\n// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at\n// our Getting Started page for more information on this bug.\n//\n// For more information, see the following:\n//\n// Issue: https://github.com/twbs/bootstrap/issues/10497\n// Docs: http://getbootstrap.com/getting-started/#browsers\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n\n@-ms-viewport {\n  width: device-width;\n}\n\n// Visibility utilities\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n  .responsive-invisibility();\n}\n\n.visible-xs {\n  @media (max-width: @screen-xs-max) {\n    .responsive-visibility();\n  }\n}\n\n.visible-sm {\n  @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n    .responsive-visibility();\n  }\n}\n\n.visible-md {\n  @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n    .responsive-visibility();\n  }\n}\n\n.visible-lg {\n  @media (min-width: @screen-lg-min) {\n    .responsive-visibility();\n  }\n}\n\n.hidden-xs {\n  @media (max-width: @screen-xs-max) {\n    .responsive-invisibility();\n  }\n}\n\n.hidden-sm {\n  @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n    .responsive-invisibility();\n  }\n}\n\n.hidden-md {\n  @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n    .responsive-invisibility();\n  }\n}\n\n.hidden-lg {\n  @media (min-width: @screen-lg-min) {\n    .responsive-invisibility();\n  }\n}\n\n// Print utilities\n//\n// Media queries are placed on the inside to be mixin-friendly.\n\n.visible-print {\n  .responsive-invisibility();\n\n  @media print {\n    .responsive-visibility();\n  }\n}\n\n.hidden-print {\n  @media print {\n    .responsive-invisibility();\n  }\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/scaffolding.less",
    "content": "//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n  .box-sizing(border-box);\n}\n*:before,\n*:after {\n  .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n  font-size: 62.5%;\n  -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n  font-family: @font-family-base;\n  font-size: @font-size-base;\n  line-height: @line-height-base;\n  color: @text-color;\n  background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\n\n// Links\n\na {\n  color: @link-color;\n  text-decoration: none;\n\n  &:hover,\n  &:focus {\n    color: @link-hover-color;\n    text-decoration: underline;\n  }\n\n  &:focus {\n    .tab-focus();\n  }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n  margin: 0;\n}\n\n\n// Images\n\nimg {\n  vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n  .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n  border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n  padding: @thumbnail-padding;\n  line-height: @line-height-base;\n  background-color: @thumbnail-bg;\n  border: 1px solid @thumbnail-border;\n  border-radius: @thumbnail-border-radius;\n  .transition(all .2s ease-in-out);\n\n  // Keep them at most 100% wide\n  .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n  border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n  margin-top:    @line-height-computed;\n  margin-bottom: @line-height-computed;\n  border: 0;\n  border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content/\n\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  margin: -1px;\n  padding: 0;\n  overflow: hidden;\n  clip: rect(0,0,0,0);\n  border: 0;\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/tables.less",
    "content": "//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n  max-width: 100%;\n  background-color: @table-bg;\n}\nth {\n  text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n  width: 100%;\n  margin-bottom: @line-height-computed;\n  // Cells\n  > thead,\n  > tbody,\n  > tfoot {\n    > tr {\n      > th,\n      > td {\n        padding: @table-cell-padding;\n        line-height: @line-height-base;\n        vertical-align: top;\n        border-top: 1px solid @table-border-color;\n      }\n    }\n  }\n  // Bottom align for column headings\n  > thead > tr > th {\n    vertical-align: bottom;\n    border-bottom: 2px solid @table-border-color;\n  }\n  // Remove top border from thead by default\n  > caption + thead,\n  > colgroup + thead,\n  > thead:first-child {\n    > tr:first-child {\n      > th,\n      > td {\n        border-top: 0;\n      }\n    }\n  }\n  // Account for multiple tbody instances\n  > tbody + tbody {\n    border-top: 2px solid @table-border-color;\n  }\n\n  // Nesting\n  .table {\n    background-color: @body-bg;\n  }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n  > thead,\n  > tbody,\n  > tfoot {\n    > tr {\n      > th,\n      > td {\n        padding: @table-condensed-cell-padding;\n      }\n    }\n  }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n  border: 1px solid @table-border-color;\n  > thead,\n  > tbody,\n  > tfoot {\n    > tr {\n      > th,\n      > td {\n        border: 1px solid @table-border-color;\n      }\n    }\n  }\n  > thead > tr {\n    > th,\n    > td {\n      border-bottom-width: 2px;\n    }\n  }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n  > tbody > tr:nth-child(odd) {\n    > td,\n    > th {\n      background-color: @table-bg-accent;\n    }\n  }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n  > tbody > tr:hover {\n    > td,\n    > th {\n      background-color: @table-bg-hover;\n    }\n  }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n  position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n  float: none;\n  display: table-column;\n}\ntable {\n  td,\n  th {\n    &[class*=\"col-\"] {\n      position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n      float: none;\n      display: table-cell;\n    }\n  }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n@media (max-width: @screen-xs-max) {\n  .table-responsive {\n    width: 100%;\n    margin-bottom: (@line-height-computed * 0.75);\n    overflow-y: hidden;\n    overflow-x: scroll;\n    -ms-overflow-style: -ms-autohiding-scrollbar;\n    border: 1px solid @table-border-color;\n    -webkit-overflow-scrolling: touch;\n\n    // Tighten up spacing\n    > .table {\n      margin-bottom: 0;\n\n      // Ensure the content doesn't wrap\n      > thead,\n      > tbody,\n      > tfoot {\n        > tr {\n          > th,\n          > td {\n            white-space: nowrap;\n          }\n        }\n      }\n    }\n\n    // Special overrides for the bordered tables\n    > .table-bordered {\n      border: 0;\n\n      // Nuke the appropriate borders so that the parent can handle them\n      > thead,\n      > tbody,\n      > tfoot {\n        > tr {\n          > th:first-child,\n          > td:first-child {\n            border-left: 0;\n          }\n          > th:last-child,\n          > td:last-child {\n            border-right: 0;\n          }\n        }\n      }\n\n      // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n      // chances are there will be only one `tr` in a `thead` and that would\n      // remove the border altogether.\n      > tbody,\n      > tfoot {\n        > tr:last-child {\n          > th,\n          > td {\n            border-bottom: 0;\n          }\n        }\n      }\n\n    }\n  }\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/theme.less",
    "content": "\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n  text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n  @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n  .box-shadow(@shadow);\n\n  // Reset the shadow\n  &:active,\n  &.active {\n    .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n  }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n  #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n  .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners\n  background-repeat: repeat-x;\n  border-color: darken(@btn-color, 14%);\n\n  &:hover,\n  &:focus  {\n    background-color: darken(@btn-color, 12%);\n    background-position: 0 -15px;\n  }\n\n  &:active,\n  &.active {\n    background-color: darken(@btn-color, 12%);\n    border-color: darken(@btn-color, 14%);\n  }\n}\n\n// Common styles\n.btn {\n  // Remove the gradient for the pressed/active state\n  &:active,\n  &.active {\n    background-image: none;\n  }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info    { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger  { .btn-styles(@btn-danger-bg); }\n\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n  .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n  #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n  background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n  background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n  #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n  .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n  border-radius: @navbar-border-radius;\n  @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n  .box-shadow(@shadow);\n\n  .navbar-nav > .active > a {\n    #gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%));\n    .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n  }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n  text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n  #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n  .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n\n  .navbar-nav > .active > a {\n    #gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%));\n    .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n  }\n\n  .navbar-brand,\n  .navbar-nav > li > a {\n    text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n  }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  border-radius: 0;\n}\n\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n  text-shadow: 0 1px 0 rgba(255,255,255,.2);\n  @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n  .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n  #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n  border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success    { .alert-styles(@alert-success-bg); }\n.alert-info       { .alert-styles(@alert-info-bg); }\n.alert-warning    { .alert-styles(@alert-warning-bg); }\n.alert-danger     { .alert-styles(@alert-danger-bg); }\n\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n  #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n  #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar            { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success    { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info       { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning    { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger     { .progress-bar-styles(@progress-bar-danger-bg); }\n\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n  border-radius: @border-radius-base;\n  .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n  text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n  #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n  border-color: darken(@list-group-active-border, 7.5%);\n}\n\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n  .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n  #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading   { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading   { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading   { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading      { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading   { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading    { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n  #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n  border-color: darken(@well-bg, 10%);\n  @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n  .box-shadow(@shadow);\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/thumbnails.less",
    "content": "//\n// Thumbnails\n// --------------------------------------------------\n\n// Mixin and adjust the regular image class\n.thumbnail {\n  display: block;\n  padding: @thumbnail-padding;\n  margin-bottom: @line-height-computed;\n  line-height: @line-height-base;\n  background-color: @thumbnail-bg;\n  border: 1px solid @thumbnail-border;\n  border-radius: @thumbnail-border-radius;\n  .transition(all .2s ease-in-out);\n\n  > img,\n  a > img {\n    &:extend(.img-responsive)\n  ;\n    margin-left: auto;\n    margin-right: auto;\n  }\n\n  // Add a hover state for linked versions only\n  a&:hover,\n  a&:focus,\n  a&.active {\n    border-color: @link-color;\n  }\n\n  // Image captions\n  .caption {\n    padding: @thumbnail-caption-padding;\n    color: @thumbnail-caption-color;\n  }\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/tooltip.less",
    "content": "//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n  position: absolute;\n  z-index: @zindex-tooltip;\n  display: block;\n  visibility: visible;\n  font-size: @font-size-small;\n  line-height: 1.4;\n  .opacity(0);\n\n  &.in     { .opacity(@tooltip-opacity); }\n  &.top    { margin-top:  -3px; padding: @tooltip-arrow-width 0; }\n  &.right  { margin-left:  3px; padding: 0 @tooltip-arrow-width; }\n  &.bottom { margin-top:   3px; padding: @tooltip-arrow-width 0; }\n  &.left   { margin-left: -3px; padding: 0 @tooltip-arrow-width; }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n  max-width: @tooltip-max-width;\n  padding: 3px 8px;\n  color: @tooltip-color;\n  text-align: center;\n  text-decoration: none;\n  background-color: @tooltip-bg;\n  border-radius: @border-radius-base;\n}\n\n// Arrows\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n.tooltip {\n  &.top .tooltip-arrow {\n    bottom: 0;\n    left: 50%;\n    margin-left: -@tooltip-arrow-width;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-top-color: @tooltip-arrow-color;\n  }\n  &.top-left .tooltip-arrow {\n    bottom: 0;\n    left: @tooltip-arrow-width;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-top-color: @tooltip-arrow-color;\n  }\n  &.top-right .tooltip-arrow {\n    bottom: 0;\n    right: @tooltip-arrow-width;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-top-color: @tooltip-arrow-color;\n  }\n  &.right .tooltip-arrow {\n    top: 50%;\n    left: 0;\n    margin-top: -@tooltip-arrow-width;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-right-color: @tooltip-arrow-color;\n  }\n  &.left .tooltip-arrow {\n    top: 50%;\n    right: 0;\n    margin-top: -@tooltip-arrow-width;\n    border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-left-color: @tooltip-arrow-color;\n  }\n  &.bottom .tooltip-arrow {\n    top: 0;\n    left: 50%;\n    margin-left: -@tooltip-arrow-width;\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-bottom-color: @tooltip-arrow-color;\n  }\n  &.bottom-left .tooltip-arrow {\n    top: 0;\n    left: @tooltip-arrow-width;\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-bottom-color: @tooltip-arrow-color;\n  }\n  &.bottom-right .tooltip-arrow {\n    top: 0;\n    right: @tooltip-arrow-width;\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-bottom-color: @tooltip-arrow-color;\n  }\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/type.less",
    "content": "//\n// Typography\n// --------------------------------------------------\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n  font-family: @headings-font-family;\n  font-weight: @headings-font-weight;\n  line-height: @headings-line-height;\n  color: @headings-color;\n\n  small,\n  .small {\n    font-weight: normal;\n    line-height: 1;\n    color: @headings-small-color;\n  }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n  margin-top: @line-height-computed;\n  margin-bottom: (@line-height-computed / 2);\n\n  small,\n  .small {\n    font-size: 65%;\n  }\n}\n\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n  margin-top: (@line-height-computed / 2);\n  margin-bottom: (@line-height-computed / 2);\n\n  small,\n  .small {\n    font-size: 75%;\n  }\n}\n\nh1, .h1 {\n  font-size: @font-size-h1;\n}\n\nh2, .h2 {\n  font-size: @font-size-h2;\n}\n\nh3, .h3 {\n  font-size: @font-size-h3;\n}\n\nh4, .h4 {\n  font-size: @font-size-h4;\n}\n\nh5, .h5 {\n  font-size: @font-size-h5;\n}\n\nh6, .h6 {\n  font-size: @font-size-h6;\n}\n\n// Body text\n// -------------------------\n\np {\n  margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n  margin-bottom: @line-height-computed;\n  font-size: floor((@font-size-base * 1.15));\n  font-weight: 200;\n  line-height: 1.4;\n\n  @media (min-width: @screen-sm-min) {\n    font-size: (@font-size-base * 1.5);\n  }\n}\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: 14px base font * 85% = about 12px\nsmall,\n.small {\n  font-size: 85%;\n}\n\n// Undo browser default styling\ncite {\n  font-style: normal;\n}\n\n// Alignment\n.text-left {\n  text-align: left;\n}\n\n.text-right {\n  text-align: right;\n}\n\n.text-center {\n  text-align: center;\n}\n\n.text-justify {\n  text-align: justify;\n}\n\n// Contextual colors\n.text-muted {\n  color: @text-muted;\n}\n\n.text-primary {\n  .text-emphasis-variant(@brand-primary);\n}\n\n.text-success {\n  .text-emphasis-variant(@state-success-text);\n}\n\n.text-info {\n  .text-emphasis-variant(@state-info-text);\n}\n\n.text-warning {\n  .text-emphasis-variant(@state-warning-text);\n}\n\n.text-danger {\n  .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n  // Given the contrast here, this is the only class to have its color inverted\n  // automatically.\n  color: #fff;\n  .bg-variant(@brand-primary);\n}\n\n.bg-success {\n  .bg-variant(@state-success-bg);\n}\n\n.bg-info {\n  .bg-variant(@state-info-bg);\n}\n\n.bg-warning {\n  .bg-variant(@state-warning-bg);\n}\n\n.bg-danger {\n  .bg-variant(@state-danger-bg);\n}\n\n// Page header\n// -------------------------\n\n.page-header {\n  padding-bottom: ((@line-height-computed / 2) - 1);\n  margin: (@line-height-computed * 2) 0 @line-height-computed;\n  border-bottom: 1px solid @page-header-border-color;\n}\n\n// Lists\n// --------------------------------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n  margin-top: 0;\n  margin-bottom: (@line-height-computed / 2);\n  ul,\n  ol {\n    margin-bottom: 0;\n  }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n  .list-unstyled();\n  margin-left: -5px;\n\n  > li {\n    display: inline-block;\n    padding-left: 5px;\n    padding-right: 5px;\n  }\n}\n\n// Description Lists\ndl {\n  margin-top: 0; // Remove browser default\n  margin-bottom: @line-height-computed;\n}\n\ndt,\ndd {\n  line-height: @line-height-base;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n@media (min-width: @grid-float-breakpoint) {\n  .dl-horizontal {\n    dt {\n      float: left;\n      width: (@component-offset-horizontal - 20);\n      clear: left;\n      text-align: right;\n      .text-overflow();\n    }\n    dd {\n      margin-left: @component-offset-horizontal;\n      &:extend(.clearfix all)\n    ; // Clear the floated `dt` if an empty `dd` is present\n    }\n  }\n}\n\n// MISC\n// ----\n\n// Abbreviations and acronyms\nabbr[title],\n  // Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted @abbr-border-color;\n}\n\n.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\n// Blockquotes\nblockquote {\n  padding: (@line-height-computed / 2) @line-height-computed;\n  margin: 0 0 @line-height-computed;\n  font-size: @blockquote-font-size;\n  border-left: 5px solid @blockquote-border-color;\n\n  p,\n  ul,\n  ol {\n    &:last-child {\n      margin-bottom: 0;\n    }\n  }\n\n  // Note: Deprecated small and .small as of v3.1.0\n  // Context: https://github.com/twbs/bootstrap/issues/11660\n  footer,\n  small,\n  .small {\n    display: block;\n    font-size: 80%; // back to default font-size\n    line-height: @line-height-base;\n    color: @blockquote-small-color;\n\n    &:before {\n      content: '\\2014 \\00A0'; // em dash, nbsp\n    }\n  }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid @blockquote-border-color;\n  border-left: 0;\n  text-align: right;\n\n  // Account for citation\n  footer,\n  small,\n  .small {\n    &:before {\n      content: '';\n    }\n    &:after {\n      content: '\\00A0 \\2014'; // nbsp, em dash\n    }\n  }\n}\n\n// Quotes\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\n// Addresses\naddress {\n  margin-bottom: @line-height-computed;\n  font-style: normal;\n  line-height: @line-height-base;\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/utilities.less",
    "content": "//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n  .clearfix();\n}\n.center-block {\n  .center-block();\n}\n.pull-right {\n  float: right !important;\n}\n.pull-left {\n  float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n  display: none !important;\n}\n.show {\n  display: block !important;\n}\n.invisible {\n  visibility: hidden;\n}\n.text-hide {\n  .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n  display: none !important;\n  visibility: hidden !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/variables.less",
    "content": "//\n// Variables\n// --------------------------------------------------\n\n//== Colors\n//\n//## Gray and brand colors for use across Bootstrap.\n\n@gray-darker: lighten(#000, 13.5%);\n// #222\n@gray-dark: lighten(#000, 20%);\n// #333\n@gray: lighten(#000, 33.5%);\n// #555\n@gray-light: lighten(#000, 60%);\n// #999\n@gray-lighter: lighten(#000, 93.5%);\n// #eee\n\n@brand-primary: #428bca;\n@brand-success: #5cb85c;\n@brand-info: #5bc0de;\n@brand-warning: #f0ad4e;\n@brand-danger: #d9534f;\n\n//== Scaffolding\n//\n// ## Settings for some of the most global styles.\n\n//** Background color for `<body>`.\n@body-bg: #fff;\n//** Global text color on `<body>`.\n@text-color: @gray-dark;\n\n//** Global textual link color.\n@link-color: @brand-primary;\n//** Link hover color set via `darken()` function.\n@link-hover-color: darken(@link-color, 15%);\n\n//== Typography\n//\n//## Font, line-height, and color for body text, headings, and more.\n\n@font-family-sans-serif: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n@font-family-serif: Georgia, \"Times New Roman\", Times, serif;\n//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.\n@font-family-monospace: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n@font-family-base: @font-family-sans-serif;\n\n@font-size-base: 14px;\n@font-size-large: ceil((@font-size-base * 1.25));\n// ~18px\n@font-size-small: ceil((@font-size-base * 0.85));\n// ~12px\n\n@font-size-h1: floor((@font-size-base * 2.6));\n// ~36px\n@font-size-h2: floor((@font-size-base * 2.15));\n// ~30px\n@font-size-h3: ceil((@font-size-base * 1.7));\n// ~24px\n@font-size-h4: ceil((@font-size-base * 1.25));\n// ~18px\n@font-size-h5: @font-size-base;\n@font-size-h6: ceil((@font-size-base * 0.85));\n// ~12px\n\n//** Unit-less `line-height` for use in components like buttons.\n@line-height-base: 1.428571429;\n// 20/14\n//** Computed \"line-height\" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.\n@line-height-computed: floor((@font-size-base * @line-height-base));\n// ~20px\n\n//** By default, this inherits from the `<body>`.\n@headings-font-family: inherit;\n@headings-font-weight: 500;\n@headings-line-height: 1.1;\n@headings-color: inherit;\n\n//-- Iconography\n//\n//## Specify custom locations of the include Glyphicons icon font. Useful for those including Bootstrap via Bower.\n\n@icon-font-path: \"../fonts/\";\n@icon-font-name: \"glyphicons-halflings-regular\";\n@icon-font-svg-id: \"glyphicons_halflingsregular\";\n\n//== Components\n//\n//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).\n\n@padding-base-vertical: 6px;\n@padding-base-horizontal: 12px;\n\n@padding-large-vertical: 10px;\n@padding-large-horizontal: 16px;\n\n@padding-small-vertical: 5px;\n@padding-small-horizontal: 10px;\n\n@padding-xs-vertical: 1px;\n@padding-xs-horizontal: 5px;\n\n@line-height-large: 1.33;\n@line-height-small: 1.5;\n\n@border-radius-base: 4px;\n@border-radius-large: 6px;\n@border-radius-small: 3px;\n\n//** Global color for active items (e.g., navs or dropdowns).\n@component-active-color: #fff;\n//** Global background color for active items (e.g., navs or dropdowns).\n@component-active-bg: @brand-primary;\n\n//** Width of the `border` for generating carets that indicator dropdowns.\n@caret-width-base: 4px;\n//** Carets increase slightly in size for larger components.\n@caret-width-large: 5px;\n\n//== Tables\n//\n//## Customizes the `.table` component with basic values, each used across all table variations.\n\n//** Padding for `<th>`s and `<td>`s.\n@table-cell-padding: 8px;\n//** Padding for cells in `.table-condensed`.\n@table-condensed-cell-padding: 5px;\n\n//** Default background color used for all tables.\n@table-bg: transparent;\n//** Background color used for `.table-striped`.\n@table-bg-accent: #f9f9f9;\n//** Background color used for `.table-hover`.\n@table-bg-hover: #f5f5f5;\n@table-bg-active: @table-bg-hover;\n\n//** Border color for table and cell borders.\n@table-border-color: #ddd;\n\n//== Buttons\n//\n//## For each of Bootstrap's buttons, define text, background and border color.\n\n@btn-font-weight: normal;\n\n@btn-default-color: #333;\n@btn-default-bg: #fff;\n@btn-default-border: #ccc;\n\n@btn-primary-color: #fff;\n@btn-primary-bg: @brand-primary;\n@btn-primary-border: darken(@btn-primary-bg, 5%);\n\n@btn-success-color: #fff;\n@btn-success-bg: @brand-success;\n@btn-success-border: darken(@btn-success-bg, 5%);\n\n@btn-info-color: #fff;\n@btn-info-bg: @brand-info;\n@btn-info-border: darken(@btn-info-bg, 5%);\n\n@btn-warning-color: #fff;\n@btn-warning-bg: @brand-warning;\n@btn-warning-border: darken(@btn-warning-bg, 5%);\n\n@btn-danger-color: #fff;\n@btn-danger-bg: @brand-danger;\n@btn-danger-border: darken(@btn-danger-bg, 5%);\n\n@btn-link-disabled-color: @gray-light;\n\n//== Forms\n//\n//##\n\n//** `<input>` background color\n@input-bg: #fff;\n//** `<input disabled>` background color\n@input-bg-disabled: @gray-lighter;\n\n//** Text color for `<input>`s\n@input-color: @gray;\n//** `<input>` border color\n@input-border: #ccc;\n//** `<input>` border radius\n@input-border-radius: @border-radius-base;\n//** Border color for inputs on focus\n@input-border-focus: #66afe9;\n\n//** Placeholder text color\n@input-color-placeholder: @gray-light;\n\n//** Default `.form-control` height\n@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2);\n//** Large `.form-control` height\n@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);\n//** Small `.form-control` height\n@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);\n\n@legend-color: @gray-dark;\n@legend-border-color: #e5e5e5;\n\n//** Background color for textual input addons\n@input-group-addon-bg: @gray-lighter;\n//** Border color for textual input addons\n@input-group-addon-border-color: @input-border;\n\n//== Dropdowns\n//\n//## Dropdown menu container and contents.\n\n//** Background for the dropdown menu.\n@dropdown-bg: #fff;\n//** Dropdown menu `border-color`.\n@dropdown-border: rgba(0, 0, 0, .15);\n//** Dropdown menu `border-color` **for IE8**.\n@dropdown-fallback-border: #ccc;\n//** Divider color for between dropdown items.\n@dropdown-divider-bg: #e5e5e5;\n\n//** Dropdown link text color.\n@dropdown-link-color: @gray-dark;\n//** Hover color for dropdown links.\n@dropdown-link-hover-color: darken(@gray-dark, 5%);\n//** Hover background for dropdown links.\n@dropdown-link-hover-bg: #f5f5f5;\n\n//** Active dropdown menu item text color.\n@dropdown-link-active-color: @component-active-color;\n//** Active dropdown menu item background color.\n@dropdown-link-active-bg: @component-active-bg;\n\n//** Disabled dropdown menu item background color.\n@dropdown-link-disabled-color: @gray-light;\n\n//** Text color for headers within dropdown menus.\n@dropdown-header-color: @gray-light;\n\n// Note: Deprecated @dropdown-caret-color as of v3.1.0\n@dropdown-caret-color: #000;\n\n//-- Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n//\n// Note: These variables are not generated into the Customizer.\n\n@zindex-navbar: 1000;\n@zindex-dropdown: 1000;\n@zindex-popover: 1010;\n@zindex-tooltip: 1030;\n@zindex-navbar-fixed: 1030;\n@zindex-modal-background: 1040;\n@zindex-modal: 1050;\n\n//== Media queries breakpoints\n//\n//## Define the breakpoints at which your layout will change, adapting to different screen sizes.\n\n// Extra small screen / phone\n// Note: Deprecated @screen-xs and @screen-phone as of v3.0.1\n@screen-xs: 480px;\n@screen-xs-min: @screen-xs;\n@screen-phone: @screen-xs-min;\n\n// Small screen / tablet\n// Note: Deprecated @screen-sm and @screen-tablet as of v3.0.1\n@screen-sm: 768px;\n@screen-sm-min: @screen-sm;\n@screen-tablet: @screen-sm-min;\n\n// Medium screen / desktop\n// Note: Deprecated @screen-md and @screen-desktop as of v3.0.1\n@screen-md: 992px;\n@screen-md-min: @screen-md;\n@screen-desktop: @screen-md-min;\n\n// Large screen / wide desktop\n// Note: Deprecated @screen-lg and @screen-lg-desktop as of v3.0.1\n@screen-lg: 1200px;\n@screen-lg-min: @screen-lg;\n@screen-lg-desktop: @screen-lg-min;\n\n// So media queries don't overlap when required, provide a maximum\n@screen-xs-max: (@screen-sm-min - 1);\n@screen-sm-max: (@screen-md-min - 1);\n@screen-md-max: (@screen-lg-min - 1);\n\n//== Grid system\n//\n//## Define your custom responsive grid.\n\n//** Number of columns in the grid.\n@grid-columns: 12;\n//** Padding between columns. Gets divided in half for the left and right.\n@grid-gutter-width: 30px;\n// Navbar collapse\n//** Point at which the navbar becomes uncollapsed.\n@grid-float-breakpoint: @screen-sm-min;\n//** Point at which the navbar begins collapsing.\n@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);\n\n//== Container sizes\n//\n//## Define the maximum width of `.container` for different screen sizes.\n\n// Small screen / tablet\n@container-tablet: ((720px + @grid-gutter-width));\n//** For `@screen-sm-min` and up.\n@container-sm: @container-tablet;\n\n// Medium screen / desktop\n@container-desktop: ((940px + @grid-gutter-width));\n//** For `@screen-md-min` and up.\n@container-md: @container-desktop;\n\n// Large screen / wide desktop\n@container-large-desktop: ((1140px + @grid-gutter-width));\n//** For `@screen-lg-min` and up.\n@container-lg: @container-large-desktop;\n\n//== Navbar\n//\n//##\n\n// Basics of a navbar\n@navbar-height: 50px;\n@navbar-margin-bottom: @line-height-computed;\n@navbar-border-radius: @border-radius-base;\n@navbar-padding-horizontal: floor((@grid-gutter-width / 2));\n@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2);\n@navbar-collapse-max-height: 340px;\n\n@navbar-default-color: #777;\n@navbar-default-bg: #f8f8f8;\n@navbar-default-border: darken(@navbar-default-bg, 6.5%);\n\n// Navbar links\n@navbar-default-link-color: #777;\n@navbar-default-link-hover-color: #333;\n@navbar-default-link-hover-bg: transparent;\n@navbar-default-link-active-color: #555;\n@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%);\n@navbar-default-link-disabled-color: #ccc;\n@navbar-default-link-disabled-bg: transparent;\n\n// Navbar brand label\n@navbar-default-brand-color: @navbar-default-link-color;\n@navbar-default-brand-hover-color: darken(@navbar-default-brand-color, 10%);\n@navbar-default-brand-hover-bg: transparent;\n\n// Navbar toggle\n@navbar-default-toggle-hover-bg: #ddd;\n@navbar-default-toggle-icon-bar-bg: #888;\n@navbar-default-toggle-border-color: #ddd;\n\n// Inverted navbar\n// Reset inverted navbar basics\n@navbar-inverse-color: @gray-light;\n@navbar-inverse-bg: #222;\n@navbar-inverse-border: darken(@navbar-inverse-bg, 10%);\n\n// Inverted navbar links\n@navbar-inverse-link-color: @gray-light;\n@navbar-inverse-link-hover-color: #fff;\n@navbar-inverse-link-hover-bg: transparent;\n@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color;\n@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%);\n@navbar-inverse-link-disabled-color: #444;\n@navbar-inverse-link-disabled-bg: transparent;\n\n// Inverted navbar brand label\n@navbar-inverse-brand-color: @navbar-inverse-link-color;\n@navbar-inverse-brand-hover-color: #fff;\n@navbar-inverse-brand-hover-bg: transparent;\n\n// Inverted navbar toggle\n@navbar-inverse-toggle-hover-bg: #333;\n@navbar-inverse-toggle-icon-bar-bg: #fff;\n@navbar-inverse-toggle-border-color: #333;\n\n//== Navs\n//\n//##\n\n//=== Shared nav styles\n@nav-link-padding: 10px 15px;\n@nav-link-hover-bg: @gray-lighter;\n\n@nav-disabled-link-color: @gray-light;\n@nav-disabled-link-hover-color: @gray-light;\n\n@nav-open-link-hover-color: #fff;\n\n//== Tabs\n@nav-tabs-border-color: #ddd;\n\n@nav-tabs-link-hover-border-color: @gray-lighter;\n\n@nav-tabs-active-link-hover-bg: @body-bg;\n@nav-tabs-active-link-hover-color: @gray;\n@nav-tabs-active-link-hover-border-color: #ddd;\n\n@nav-tabs-justified-link-border-color: #ddd;\n@nav-tabs-justified-active-link-border-color: @body-bg;\n\n//== Pills\n@nav-pills-border-radius: @border-radius-base;\n@nav-pills-active-link-hover-bg: @component-active-bg;\n@nav-pills-active-link-hover-color: @component-active-color;\n\n//== Pagination\n//\n//##\n\n@pagination-color: @link-color;\n@pagination-bg: #fff;\n@pagination-border: #ddd;\n\n@pagination-hover-color: @link-hover-color;\n@pagination-hover-bg: @gray-lighter;\n@pagination-hover-border: #ddd;\n\n@pagination-active-color: #fff;\n@pagination-active-bg: @brand-primary;\n@pagination-active-border: @brand-primary;\n\n@pagination-disabled-color: @gray-light;\n@pagination-disabled-bg: #fff;\n@pagination-disabled-border: #ddd;\n\n//== Pager\n//\n//##\n\n@pager-bg: @pagination-bg;\n@pager-border: @pagination-border;\n@pager-border-radius: 15px;\n\n@pager-hover-bg: @pagination-hover-bg;\n\n@pager-active-bg: @pagination-active-bg;\n@pager-active-color: @pagination-active-color;\n\n@pager-disabled-color: @pagination-disabled-color;\n\n//== Jumbotron\n//\n//##\n\n@jumbotron-padding: 30px;\n@jumbotron-color: inherit;\n@jumbotron-bg: @gray-lighter;\n@jumbotron-heading-color: inherit;\n@jumbotron-font-size: ceil((@font-size-base * 1.5));\n\n//== Form states and alerts\n//\n//## Define colors for form feedback states and, by default, alerts.\n\n@state-success-text: #3c763d;\n@state-success-bg: #dff0d8;\n@state-success-border: darken(spin(@state-success-bg, -10), 5%);\n\n@state-info-text: #31708f;\n@state-info-bg: #d9edf7;\n@state-info-border: darken(spin(@state-info-bg, -10), 7%);\n\n@state-warning-text: #8a6d3b;\n@state-warning-bg: #fcf8e3;\n@state-warning-border: darken(spin(@state-warning-bg, -10), 5%);\n\n@state-danger-text: #a94442;\n@state-danger-bg: #f2dede;\n@state-danger-border: darken(spin(@state-danger-bg, -10), 5%);\n\n//== Tooltips\n//\n//##\n\n//** Tooltip max width\n@tooltip-max-width: 200px;\n//** Tooltip text color\n@tooltip-color: #fff;\n//** Tooltip background color\n@tooltip-bg: #000;\n@tooltip-opacity: .9;\n\n//** Tooltip arrow width\n@tooltip-arrow-width: 5px;\n//** Tooltip arrow color\n@tooltip-arrow-color: @tooltip-bg;\n\n//== Popovers\n//\n//##\n\n//** Popover body background color\n@popover-bg: #fff;\n//** Popover maximum width\n@popover-max-width: 276px;\n//** Popover border color\n@popover-border-color: rgba(0, 0, 0, .2);\n//** Popover fallback border color\n@popover-fallback-border-color: #ccc;\n\n//** Popover title background color\n@popover-title-bg: darken(@popover-bg, 3%);\n\n//** Popover arrow width\n@popover-arrow-width: 10px;\n//** Popover arrow color\n@popover-arrow-color: #fff;\n\n//** Popover outer arrow width\n@popover-arrow-outer-width: (@popover-arrow-width + 1);\n//** Popover outer arrow color\n@popover-arrow-outer-color: fadein(@popover-border-color, 5%);\n//** Popover outer arrow fallback color\n@popover-arrow-outer-fallback-color: darken(@popover-fallback-border-color, 20%);\n\n//== Labels\n//\n//##\n\n//** Default label background color\n@label-default-bg: @gray-light;\n//** Primary label background color\n@label-primary-bg: @brand-primary;\n//** Success label background color\n@label-success-bg: @brand-success;\n//** Info label background color\n@label-info-bg: @brand-info;\n//** Warning label background color\n@label-warning-bg: @brand-warning;\n//** Danger label background color\n@label-danger-bg: @brand-danger;\n\n//** Default label text color\n@label-color: #fff;\n//** Default text color of a linked label\n@label-link-hover-color: #fff;\n\n//== Modals\n//\n//##\n\n//** Padding applied to the modal body\n@modal-inner-padding: 20px;\n\n//** Padding applied to the modal title\n@modal-title-padding: 15px;\n//** Modal title line-height\n@modal-title-line-height: @line-height-base;\n\n//** Background color of modal content area\n@modal-content-bg: #fff;\n//** Modal content border color\n@modal-content-border-color: rgba(0, 0, 0, .2);\n//** Modal content border color **for IE8**\n@modal-content-fallback-border-color: #999;\n\n//** Modal backdrop background color\n@modal-backdrop-bg: #000;\n//** Modal backdrop opacity\n@modal-backdrop-opacity: .5;\n//** Modal header border color\n@modal-header-border-color: #e5e5e5;\n//** Modal footer border color\n@modal-footer-border-color: @modal-header-border-color;\n\n@modal-lg: 900px;\n@modal-md: 600px;\n@modal-sm: 300px;\n\n//== Alerts\n//\n//## Define alert colors, border radius, and padding.\n\n@alert-padding: 15px;\n@alert-border-radius: @border-radius-base;\n@alert-link-font-weight: bold;\n\n@alert-success-bg: @state-success-bg;\n@alert-success-text: @state-success-text;\n@alert-success-border: @state-success-border;\n\n@alert-info-bg: @state-info-bg;\n@alert-info-text: @state-info-text;\n@alert-info-border: @state-info-border;\n\n@alert-warning-bg: @state-warning-bg;\n@alert-warning-text: @state-warning-text;\n@alert-warning-border: @state-warning-border;\n\n@alert-danger-bg: @state-danger-bg;\n@alert-danger-text: @state-danger-text;\n@alert-danger-border: @state-danger-border;\n\n//== Progress bars\n//\n//##\n\n//** Background color of the whole progress component\n@progress-bg: #f5f5f5;\n//** Progress bar text color\n@progress-bar-color: #fff;\n\n//** Default progress bar color\n@progress-bar-bg: @brand-primary;\n//** Success progress bar color\n@progress-bar-success-bg: @brand-success;\n//** Warning progress bar color\n@progress-bar-warning-bg: @brand-warning;\n//** Danger progress bar color\n@progress-bar-danger-bg: @brand-danger;\n//** Info progress bar color\n@progress-bar-info-bg: @brand-info;\n\n//== List group\n//\n//##\n\n//** Background color on `.list-group-item`\n@list-group-bg: #fff;\n//** `.list-group-item` border color\n@list-group-border: #ddd;\n//** List group border radius\n@list-group-border-radius: @border-radius-base;\n\n//** Background color of single list elements on hover\n@list-group-hover-bg: #f5f5f5;\n//** Text color of active list elements\n@list-group-active-color: @component-active-color;\n//** Background color of active list elements\n@list-group-active-bg: @component-active-bg;\n//** Border color of active list elements\n@list-group-active-border: @list-group-active-bg;\n@list-group-active-text-color: lighten(@list-group-active-bg, 40%);\n\n@list-group-link-color: #555;\n@list-group-link-heading-color: #333;\n\n//== Panels\n//\n//##\n\n@panel-bg: #fff;\n@panel-body-padding: 15px;\n@panel-border-radius: @border-radius-base;\n\n//** Border color for elements within panels\n@panel-inner-border: #ddd;\n@panel-footer-bg: #f5f5f5;\n\n@panel-default-text: @gray-dark;\n@panel-default-border: #ddd;\n@panel-default-heading-bg: #f5f5f5;\n\n@panel-primary-text: #fff;\n@panel-primary-border: @brand-primary;\n@panel-primary-heading-bg: @brand-primary;\n\n@panel-success-text: @state-success-text;\n@panel-success-border: @state-success-border;\n@panel-success-heading-bg: @state-success-bg;\n\n@panel-info-text: @state-info-text;\n@panel-info-border: @state-info-border;\n@panel-info-heading-bg: @state-info-bg;\n\n@panel-warning-text: @state-warning-text;\n@panel-warning-border: @state-warning-border;\n@panel-warning-heading-bg: @state-warning-bg;\n\n@panel-danger-text: @state-danger-text;\n@panel-danger-border: @state-danger-border;\n@panel-danger-heading-bg: @state-danger-bg;\n\n//== Thumbnails\n//\n//##\n\n//** Padding around the thumbnail image\n@thumbnail-padding: 4px;\n//** Thumbnail background color\n@thumbnail-bg: @body-bg;\n//** Thumbnail border color\n@thumbnail-border: #ddd;\n//** Thumbnail border radius\n@thumbnail-border-radius: @border-radius-base;\n\n//** Custom text color for thumbnail captions\n@thumbnail-caption-color: @text-color;\n//** Padding around the thumbnail caption\n@thumbnail-caption-padding: 9px;\n\n//== Wells\n//\n//##\n\n@well-bg: #f5f5f5;\n@well-border: darken(@well-bg, 7%);\n\n//== Badges\n//\n//##\n\n@badge-color: #fff;\n//** Linked badge text color on hover\n@badge-link-hover-color: #fff;\n@badge-bg: @gray-light;\n\n//** Badge text color in active nav link\n@badge-active-color: @link-color;\n//** Badge background color in active nav link\n@badge-active-bg: #fff;\n\n@badge-font-weight: bold;\n@badge-line-height: 1;\n@badge-border-radius: 10px;\n\n//== Breadcrumbs\n//\n//##\n\n@breadcrumb-padding-vertical: 8px;\n@breadcrumb-padding-horizontal: 15px;\n//** Breadcrumb background color\n@breadcrumb-bg: #f5f5f5;\n//** Breadcrumb text color\n@breadcrumb-color: #ccc;\n//** Text color of current page in the breadcrumb\n@breadcrumb-active-color: @gray-light;\n//** Textual separator for between breadcrumb elements\n@breadcrumb-separator: \"/\";\n\n//== Carousel\n//\n//##\n\n@carousel-text-shadow: 0 1px 2px rgba(0, 0, 0, .6);\n\n@carousel-control-color: #fff;\n@carousel-control-width: 15%;\n@carousel-control-opacity: .5;\n@carousel-control-font-size: 20px;\n\n@carousel-indicator-active-bg: #fff;\n@carousel-indicator-border-color: #fff;\n\n@carousel-caption-color: #fff;\n\n//== Close\n//\n//##\n\n@close-font-weight: bold;\n@close-color: #000;\n@close-text-shadow: 0 1px 0 #fff;\n\n//== Code\n//\n//##\n\n@code-color: #c7254e;\n@code-bg: #f9f2f4;\n\n@kbd-color: #fff;\n@kbd-bg: #333;\n\n@pre-bg: #f5f5f5;\n@pre-color: @gray-dark;\n@pre-border-color: #ccc;\n@pre-scrollable-max-height: 340px;\n\n//== Type\n//\n//##\n\n//** Text muted color\n@text-muted: @gray-light;\n//** Abbreviations and acronyms border color\n@abbr-border-color: @gray-light;\n//** Headings small color\n@headings-small-color: @gray-light;\n//** Blockquote small color\n@blockquote-small-color: @gray-light;\n//** Blockquote font size\n@blockquote-font-size: (@font-size-base * 1.25);\n//** Blockquote border color\n@blockquote-border-color: @gray-lighter;\n//** Page header border color\n@page-header-border-color: @gray-lighter;\n\n//== Miscellaneous\n//\n//##\n\n//** Horizontal line color.\n@hr-border: @gray-lighter;\n\n//** Horizontal offset for forms and lists.\n@component-offset-horizontal: 180px;\n"
  },
  {
    "path": "server/public/css/lib/bootstrap/wells.less",
    "content": "//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: @well-bg;\n  border: 1px solid @well-border;\n  border-radius: @border-radius-base;\n  .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));\n  blockquote {\n    border-color: #ddd;\n    border-color: rgba(0,0,0,.15);\n  }\n}\n\n// Sizes\n.well-lg {\n  padding: 24px;\n  border-radius: @border-radius-large;\n}\n.well-sm {\n  padding: 9px;\n  border-radius: @border-radius-small;\n}\n"
  },
  {
    "path": "server/public/css/lib/bootstrap-social.less",
    "content": "/*\n * Social Buttons for Bootstrap\n *\n * Copyright 2013-2014 Panayiotis Lipiridis\n * Licensed under the MIT License\n *\n * https://github.com/lipis/bootstrap-social\n */\n\n.btn-social {\n  @bs-height-base: (@line-height-computed + @padding-base-vertical * 2);\n  @bs-height-lg: (floor(@font-size-large * @line-height-base) + @padding-large-vertical * 2);\n  @bs-height-sm: (floor(@font-size-small * 1.5) + @padding-small-vertical * 2);\n  @bs-height-xs: (floor(@font-size-small * 1.2) + @padding-small-vertical + 1);\n\n  position: relative;\n  padding-left: @bs-height-base + @padding-base-horizontal;\n  text-align: left;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  :first-child {\n    position: absolute;\n    left: 0;\n    top: 0;\n    bottom: 0;\n    width: @bs-height-base;\n    line-height: (@bs-height-base + 2);\n    font-size: 1.6em;\n    text-align: center;\n    border-right: 1px solid rgba(0, 0, 0, 0.2);\n  }\n  &.btn-lg {\n    padding-left: @bs-height-lg + @padding-large-horizontal;\n    :first-child {\n      line-height: @bs-height-lg;\n      width: @bs-height-lg;\n      font-size: 1.8em;\n    }\n  }\n  &.btn-sm {\n    padding-left: @bs-height-sm + @padding-small-horizontal;\n    :first-child {\n      line-height: @bs-height-sm;\n      width: @bs-height-sm;\n      font-size: 1.4em;\n    }\n  }\n  &.btn-xs {\n    padding-left: @bs-height-xs + @padding-small-horizontal;\n    :first-child {\n      line-height: @bs-height-xs;\n      width: @bs-height-xs;\n      font-size: 1.2em;\n    }\n  }\n}\n\n.btn-social-icon {\n  .btn-social;\n  height: (@bs-height-base + 2);\n  width: (@bs-height-base + 2);\n  padding: 0;\n  :first-child {\n    border: none;\n    text-align: center;\n    width: 100% !important;\n  }\n  &.btn-lg {\n    height: @bs-height-lg;\n    width: @bs-height-lg;\n    padding-left: 0;\n    padding-right: 0;\n  }\n  &.btn-sm {\n    height: (@bs-height-sm + 2);\n    width: (@bs-height-sm + 2);\n    padding-left: 0;\n    padding-right: 0;\n  }\n  &.btn-xs {\n    height: (@bs-height-xs + 2);\n    width: (@bs-height-xs + 2);\n    padding-left: 0;\n    padding-right: 0;\n  }\n}\n\n.btn-social(@color-bg, @color: white) {\n  background-color: @color-bg;\n  .button-variant(@color, @color-bg, rgba(0, 0, 0, 0.2));\n}\n\n.btn-bitbucket {\n  .btn-social(#205081);\n}\n\n.btn-dropbox {\n  .btn-social(#1087dd);\n}\n\n.btn-facebook {\n  .btn-social(#3b5998);\n}\n\n.btn-flickr {\n  .btn-social(#ff0084);\n}\n\n.btn-foursquare {\n  .btn-social(#0072b1);\n}\n\n.btn-github {\n  .btn-social(#444444);\n}\n\n.btn-google-plus {\n  .btn-social(#dd4b39);\n}\n\n.btn-instagram {\n  .btn-social(#3f729b);\n}\n\n.btn-linkedin {\n  .btn-social(#007bb6);\n}\n\n.btn-tumblr {\n  .btn-social(#2c4762);\n}\n\n.btn-twitter {\n  .btn-social(#55acee);\n}\n\n.btn-vk {\n  .btn-social(#587ea3);\n}\n"
  },
  {
    "path": "server/public/css/styles.less",
    "content": "@import (less) \"lib/animate.css\";\n@import (less) \"lib/font-awesome.min.css\";\n@import \"lib/bootstrap/bootstrap\";\n@import \"lib/bootstrap-social\";\n@import \"themes/default\";\n\n// Scaffolding\n// -------------------------\n\nhtml, body {\n  height: 100%;\n}\n\nbody {\n  padding-top: 70px;\n}\n\n#wrap {\n  min-height: 100%;\n  height: auto !important;\n  height: 100%;\n  /* Negative indent footer by its height */\n  margin: 0 auto -100px;\n  /* Pad bottom by footer height + (optional) extra spacing */\n  padding: 0 0 140px;\n}\n\n#footer {\n  font-size: 12px;\n  padding-top: 40px;\n  padding-bottom: 40px;\n  height: 100px;\n}\n\n// Navbar\n// -------------------------\n\n@navbar-height: 45px;\n\n.navbar-nav .profile-image {\n  width: 30px;\n  height: 30px;\n  margin: -15px 15px -15px 0;\n}\n\n.navbar-brand {\n  background-image: url('../img/npm-logo.png');\n  background-repeat: no-repeat;\n  background-size: 40px;\n  background-position: left center;\n  padding-left: 50px;\n  margin-left: 15px;\n  height: 45px;\n}\n\n// Social Buttons\n// -------------------------\n\n.btn-social {\n  border-radius: 2px;\n}\n\n// Font Awesome\n// -------------------------\n\n[class^=\"fa-\"],\n[class*=\"fa-\"] {\n  margin-right: 5px;\n}\n\n// API Examples\n// -------------------------\n\n.thumb {\n  padding-left: 0 !important;\n  padding-right: 0 !important;\n}\n\n.thumb img {\n  margin-bottom: 5px;\n  margin-right: 5px;\n  opacity: 0.2;\n  transition: opacity 0.2s;\n}\n\n.thumb:hover img {\n  opacity: 1;\n  box-shadow: 0 0 3px 1px @brand-primary;\n}\n\n.facebook-caption {\n  position: absolute;\n  background-color: rgba(0, 0, 0, 0.5);\n  font-size: 12px;\n  color: #fff;\n  padding: 3px;\n  bottom: 25px;\n}"
  },
  {
    "path": "server/public/css/themes/default.less",
    "content": "@import url(http://fonts.googleapis.com/css?family=Open+Sans:400italic,400,600,300,700,800);\n\n// Brand Colors\n// -------------------------\n\n@brand-primary: #4d90fc;\n@brand-success: #60bf60;\n@brand-warning: #ff9800;\n@brand-danger: #de4b33;\n@brand-info: #5bc0dd;\n\n// Typography\n// -------------------------\n\n// Buttons\n// -------------------------\n\n@btn-primary-border: darken(@btn-primary-bg, 3.2%);\n@btn-success-border: darken(@btn-success-bg, 3.2%);\n@btn-warning-border: darken(@btn-warning-bg, 3.2%);\n@btn-danger-border: darken(@btn-danger-bg, 3.2%);\n@btn-info-border: darken(@btn-info-bg, 3.2%);\n\n.btn {\n  border-radius: 0;\n  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.11), 1px 1px 0 rgba(255, 255, 255, 0.21) inset;\n\n  &:focus {\n    outline: none;\n  }\n}\n\n.btn-default, .btn-default:focus {\n  background-image: linear-gradient(to bottom, #ffffff 60%, #f8f8f8 100%);\n}\n\n.btn-link {\n  box-shadow: none;\n}\n\n// Forms\n// -------------------------\n\n@input-border-radius: 0;\n@input-border-focus: #2598f9;\n\n.form-control:focus {\n  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1) inset;\n}\n\n// Form states and alerts\n// -------------------------\n\n@state-success-text: #569845;\n@state-success-bg: #dbf5d3;\n@state-success-border: #aed3a5;\n\n@state-info-text: #3a87ad;\n@state-info-bg: #d9edf7;\n@state-info-border: #98cce7;\n\n@state-warning-text: #bf9853;\n@state-warning-bg: #fdf8e2;\n@state-warning-border: #f2daab;\n\n@state-danger-text: #b94a48;\n@state-danger-bg: #f2dede;\n@state-danger-border: #e0b1b8;\n\n// Alerts\n// -------------------------\n\n.alert {\n  border-radius: 0;\n  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.10);\n}\n\n// Navbar\n// -------------------------\n\n.navbar-default .navbar-nav > li a {\n  transition: color 0.3s;\n}\n"
  },
  {
    "path": "server/public/css/themes/flatly.less",
    "content": "// Flatly 3.1.1\n// Variables\n// --------------------------------------------------\n\n//== Colors\n//\n//## Gray and brand colors for use across Bootstrap.\n\n@gray-darker:            lighten(#000, 13.5%); // #222\n@gray-dark: #7b8a8b;\n// #333\n@gray: #95a5a6;\n// #555\n@gray-light: #b4bcc2;\n// #999\n@gray-lighter: #ecf0f1;\n// #eee\n\n@brand-primary:         #2C3E50;\n@brand-success:         #18BC9C;\n@brand-info: #3498DB;\n@brand-warning:         #F39C12;\n@brand-danger:          #E74C3C;\n\n//== Scaffolding\n//\n// ## Settings for some of the most global styles.\n\n//** Background color for `<body>`.\n@body-bg:               #fff;\n//** Global text color on `<body>`.\n@text-color:            @brand-primary;\n\n//** Global textual link color.\n@link-color:            @brand-success;\n//** Link hover color set via `darken()` function.\n@link-hover-color:      @link-color;\n\n//== Typography\n//\n//## Font, line-height, and color for body text, headings, and more.\n\n@font-family-sans-serif:  \"Lato\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n@font-family-serif:       Georgia, \"Times New Roman\", Times, serif;\n//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.\n@font-family-monospace:   Menlo, Monaco, Consolas, \"Courier New\", monospace;\n@font-family-base:        @font-family-sans-serif;\n\n@font-size-base:          15px;\n@font-size-large: ceil((@font-size-base * 1.25));\n// ~18px\n@font-size-small: ceil((@font-size-base * 0.85));\n// ~12px\n\n@font-size-h1: floor((@font-size-base * 2.6));\n// ~36px\n@font-size-h2: floor((@font-size-base * 2.15));\n// ~30px\n@font-size-h3: ceil((@font-size-base * 1.7));\n// ~24px\n@font-size-h4: ceil((@font-size-base * 1.25));\n// ~18px\n@font-size-h5:            @font-size-base;\n@font-size-h6: ceil((@font-size-base * 0.85));\n// ~12px\n\n//** Unit-less `line-height` for use in components like buttons.\n@line-height-base:        1.428571429; // 20/14\n//** Computed \"line-height\" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.\n@line-height-computed: floor((@font-size-base * @line-height-base));\n// ~20px\n\n//** By default, this inherits from the `<body>`.\n@headings-font-family:    @font-family-base;\n@headings-font-weight: 400;\n@headings-line-height:    1.1;\n@headings-color:          inherit;\n\n//-- Iconography\n//\n//## Specify custom locations of the include Glyphicons icon font. Useful for those including Bootstrap via Bower.\n\n@icon-font-path:          \"../fonts/\";\n@icon-font-name:          \"glyphicons-halflings-regular\";\n@icon-font-svg-id: \"glyphicons_halflingsregular\";\n\n//== Components\n//\n//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).\n\n@padding-base-vertical: 10px;\n@padding-base-horizontal: 15px;\n\n@padding-large-vertical: 18px;\n@padding-large-horizontal: 27px;\n\n@padding-small-vertical: 6px;\n@padding-small-horizontal: 9px;\n\n@padding-xs-vertical: 1px;\n@padding-xs-horizontal: 5px;\n\n@line-height-large: 1.33;\n@line-height-small: 1.5;\n\n@border-radius-base: 4px;\n@border-radius-large: 6px;\n@border-radius-small: 3px;\n\n//** Global color for active items (e.g., navs or dropdowns).\n@component-active-color: #fff;\n//** Global background color for active items (e.g., navs or dropdowns).\n@component-active-bg: @brand-primary;\n\n//** Width of the `border` for generating carets that indicator dropdowns.\n@caret-width-base: 4px;\n//** Carets increase slightly in size for larger components.\n@caret-width-large: 5px;\n\n//== Tables\n//\n//## Customizes the `.table` component with basic values, each used across all table variations.\n\n//** Padding for `<th>`s and `<td>`s.\n@table-cell-padding: 8px;\n//** Padding for cells in `.table-condensed`.\n@table-condensed-cell-padding: 5px;\n\n//** Default background color used for all tables.\n@table-bg: transparent;\n//** Background color used for `.table-striped`.\n@table-bg-accent: #f9f9f9;\n//** Background color used for `.table-hover`.\n@table-bg-hover: @gray-lighter;\n@table-bg-active: @table-bg-hover;\n\n//** Border color for table and cell borders.\n@table-border-color: @gray-lighter;\n\n//== Buttons\n//\n//## For each of Bootstrap's buttons, define text, background and border color.\n\n@btn-font-weight:                normal;\n\n@btn-default-color:              #fff;\n@btn-default-bg:                 @gray;\n@btn-default-border:             @btn-default-bg;\n\n@btn-primary-color:              @btn-default-color;\n@btn-primary-bg:                 @brand-primary;\n@btn-primary-border:             @btn-primary-bg;\n\n@btn-success-color:              @btn-default-color;\n@btn-success-bg:                 @brand-success;\n@btn-success-border:             @btn-success-bg;\n\n@btn-info-color: @btn-default-color;\n@btn-info-bg: @brand-info;\n@btn-info-border: @btn-info-bg;\n\n@btn-warning-color:              @btn-default-color;\n@btn-warning-bg:                 @brand-warning;\n@btn-warning-border:             @btn-warning-bg;\n\n@btn-danger-color:               @btn-default-color;\n@btn-danger-bg:                  @brand-danger;\n@btn-danger-border:              @btn-danger-bg;\n\n@btn-link-disabled-color:        @gray-light;\n\n//== Forms\n//\n//##\n\n//** `<input>` background color\n@input-bg:                       #fff;\n//** `<input disabled>` background color\n@input-bg-disabled:              @gray-lighter;\n\n//** Text color for `<input>`s\n@input-color:                    @text-color;\n//** `<input>` border color\n@input-border:                   #dce4ec;\n//** `<input>` border radius\n@input-border-radius:            @border-radius-base;\n//** Border color for inputs on focus\n@input-border-focus:             #1abc9c;\n\n//** Placeholder text color\n@input-color-placeholder:        #acb6c0;\n\n//** Default `.form-control` height\n@input-height-base:              (@line-height-computed + (@padding-base-vertical * 2) + 2);\n//** Large `.form-control` height\n@input-height-large:             (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);\n//** Small `.form-control` height\n@input-height-small:             (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);\n\n@legend-color:                   @text-color;\n@legend-border-color:            #e5e5e5;\n\n//** Background color for textual input addons\n@input-group-addon-bg:           @gray-lighter;\n//** Border color for textual input addons\n@input-group-addon-border-color: @input-border;\n\n//== Dropdowns\n//\n//## Dropdown menu container and contents.\n\n//** Background for the dropdown menu.\n@dropdown-bg:                    #fff;\n//** Dropdown menu `border-color`.\n@dropdown-border:                rgba(0,0,0,.15);\n//** Dropdown menu `border-color` **for IE8**.\n@dropdown-fallback-border:       #ccc;\n//** Divider color for between dropdown items.\n@dropdown-divider-bg:            #e5e5e5;\n\n//** Dropdown link text color.\n@dropdown-link-color:            @gray-dark;\n//** Hover color for dropdown links.\n@dropdown-link-hover-color:      #fff;\n//** Hover background for dropdown links.\n@dropdown-link-hover-bg:         @dropdown-link-active-bg;\n\n//** Active dropdown menu item text color.\n@dropdown-link-active-color:     #fff;\n//** Active dropdown menu item background color.\n@dropdown-link-active-bg:        @component-active-bg;\n\n//** Disabled dropdown menu item background color.\n@dropdown-link-disabled-color:   @text-muted;\n\n//** Text color for headers within dropdown menus.\n@dropdown-header-color:          @text-muted;\n\n// Note: Deprecated @dropdown-caret-color as of v3.1.0\n@dropdown-caret-color: #000;\n\n//-- Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n//\n// Note: These variables are not generated into the Customizer.\n\n@zindex-navbar:            1000;\n@zindex-dropdown:          1000;\n@zindex-popover:           1010;\n@zindex-tooltip:           1030;\n@zindex-navbar-fixed:      1030;\n@zindex-modal-background:  1040;\n@zindex-modal:             1050;\n\n//== Media queries breakpoints\n//\n//## Define the breakpoints at which your layout will change, adapting to different screen sizes.\n\n// Extra small screen / phone\n// Note: Deprecated @screen-xs and @screen-phone as of v3.0.1\n@screen-xs:                  480px;\n@screen-xs-min:              @screen-xs;\n@screen-phone:               @screen-xs-min;\n\n// Small screen / tablet\n// Note: Deprecated @screen-sm and @screen-tablet as of v3.0.1\n@screen-sm:                  768px;\n@screen-sm-min:              @screen-sm;\n@screen-tablet:              @screen-sm-min;\n\n// Medium screen / desktop\n// Note: Deprecated @screen-md and @screen-desktop as of v3.0.1\n@screen-md:                  992px;\n@screen-md-min:              @screen-md;\n@screen-desktop:             @screen-md-min;\n\n// Large screen / wide desktop\n// Note: Deprecated @screen-lg and @screen-lg-desktop as of v3.0.1\n@screen-lg:                  1200px;\n@screen-lg-min:              @screen-lg;\n@screen-lg-desktop:          @screen-lg-min;\n\n// So media queries don't overlap when required, provide a maximum\n@screen-xs-max:              (@screen-sm-min - 1);\n@screen-sm-max:              (@screen-md-min - 1);\n@screen-md-max:              (@screen-lg-min - 1);\n\n//== Grid system\n//\n//## Define your custom responsive grid.\n\n//** Number of columns in the grid.\n@grid-columns:              12;\n//** Padding between columns. Gets divided in half for the left and right.\n@grid-gutter-width:         30px;\n// Navbar collapse\n//** Point at which the navbar becomes uncollapsed.\n@grid-float-breakpoint:     @screen-sm-min;\n//** Point at which the navbar begins collapsing.\n@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);\n\n//== Container sizes\n//\n//## Define the maximum width of `.container` for different screen sizes.\n\n// Small screen / tablet\n@container-tablet: ((720px + @grid-gutter-width));\n//** For `@screen-sm-min` and up.\n@container-sm: @container-tablet;\n\n// Medium screen / desktop\n@container-desktop: ((940px + @grid-gutter-width));\n//** For `@screen-md-min` and up.\n@container-md: @container-desktop;\n\n// Large screen / wide desktop\n@container-large-desktop: ((1140px + @grid-gutter-width));\n//** For `@screen-lg-min` and up.\n@container-lg: @container-large-desktop;\n\n//== Navbar\n//\n//##\n\n// Basics of a navbar\n@navbar-height:                    60px;\n@navbar-margin-bottom:             @line-height-computed;\n@navbar-border-radius:             @border-radius-base;\n@navbar-padding-horizontal: floor((@grid-gutter-width / 2));\n@navbar-padding-vertical:          ((@navbar-height - @line-height-computed) / 2);\n@navbar-collapse-max-height: 340px;\n\n@navbar-default-color:             #777;\n@navbar-default-bg:                @brand-primary;\n@navbar-default-border:            darken(@navbar-default-bg, 6.5%);\n\n// Navbar links\n@navbar-default-link-color:                #fff;\n@navbar-default-link-hover-color:          @brand-success;\n@navbar-default-link-hover-bg:             transparent;\n@navbar-default-link-active-color:         #fff;\n@navbar-default-link-active-bg:            darken(@navbar-default-bg, 10%);\n@navbar-default-link-disabled-color:       #ccc;\n@navbar-default-link-disabled-bg:          transparent;\n\n// Navbar brand label\n@navbar-default-brand-color:               @navbar-default-link-color;\n@navbar-default-brand-hover-color:         @navbar-default-link-hover-color;\n@navbar-default-brand-hover-bg:            transparent;\n\n// Navbar toggle\n@navbar-default-toggle-hover-bg:           darken(@navbar-default-bg, 10%);\n@navbar-default-toggle-icon-bar-bg:        #fff;\n@navbar-default-toggle-border-color:       darken(@navbar-default-bg, 10%);\n\n\n// Inverted navbar\n// Reset inverted navbar basics\n@navbar-inverse-color:                      #fff;\n@navbar-inverse-bg:                         @brand-success;\n@navbar-inverse-border:                     darken(@navbar-inverse-bg, 10%);\n\n// Inverted navbar links\n@navbar-inverse-link-color:                 #fff;\n@navbar-inverse-link-hover-color:           @brand-primary;\n@navbar-inverse-link-hover-bg:              transparent;\n@navbar-inverse-link-active-color:          #fff;\n@navbar-inverse-link-active-bg:             darken(@navbar-inverse-bg, 5%);\n@navbar-inverse-link-disabled-color:        #ccc;\n@navbar-inverse-link-disabled-bg:           transparent;\n\n// Inverted navbar brand label\n@navbar-inverse-brand-color:                @navbar-inverse-link-color;\n@navbar-inverse-brand-hover-color:          @navbar-inverse-link-hover-color;\n@navbar-inverse-brand-hover-bg:             transparent;\n\n// Inverted navbar toggle\n@navbar-inverse-toggle-hover-bg:            darken(@navbar-inverse-bg, 10%);\n@navbar-inverse-toggle-icon-bar-bg:         #fff;\n@navbar-inverse-toggle-border-color:        darken(@navbar-inverse-bg, 10%);\n\n//== Navs\n//\n//##\n\n//=== Shared nav styles\n@nav-link-padding:                          10px 15px;\n@nav-link-hover-bg:                         @gray-lighter;\n\n@nav-disabled-link-color:                   @gray-light;\n@nav-disabled-link-hover-color:             @gray-light;\n\n@nav-open-link-hover-color:                 #fff;\n\n//== Tabs\n@nav-tabs-border-color:                     @gray-lighter;\n\n@nav-tabs-link-hover-border-color:          @gray-lighter;\n\n@nav-tabs-active-link-hover-bg:             @body-bg;\n@nav-tabs-active-link-hover-color:          @brand-primary;\n@nav-tabs-active-link-hover-border-color:   @gray-lighter;\n\n@nav-tabs-justified-link-border-color:            @gray-lighter;\n@nav-tabs-justified-active-link-border-color:     @body-bg;\n\n//== Pills\n@nav-pills-border-radius:                   @border-radius-base;\n@nav-pills-active-link-hover-bg:            @component-active-bg;\n@nav-pills-active-link-hover-color:         @component-active-color;\n\n//== Pagination\n//\n//##\n\n@pagination-color: #fff;\n@pagination-bg:                        @brand-success;\n@pagination-border:                    transparent;\n\n@pagination-hover-color: #fff;\n@pagination-hover-bg:                  darken(@brand-success, 15%);\n@pagination-hover-border: transparent;\n\n@pagination-active-color:              #fff;\n@pagination-active-bg: darken(@brand-success, 15%);\n@pagination-active-border: transparent;\n\n@pagination-disabled-color:            @gray-lighter;\n@pagination-disabled-bg: lighten(@brand-success, 15%);\n;\n@pagination-disabled-border: transparent;\n\n//== Pager\n//\n//##\n\n@pager-bg: @pagination-bg;\n@pager-border: @pagination-border;\n@pager-border-radius:                  15px;\n\n@pager-hover-bg: @pagination-hover-bg;\n\n@pager-active-bg: @pagination-active-bg;\n@pager-active-color: @pagination-active-color;\n\n@pager-disabled-color:                 #fff;\n\n//== Jumbotron\n//\n//##\n\n@jumbotron-padding:              30px;\n@jumbotron-color:                inherit;\n@jumbotron-bg:                   @gray-lighter;\n@jumbotron-heading-color:        inherit;\n@jumbotron-font-size: ceil((@font-size-base * 1.5));\n\n//== Form states and alerts\n//\n//## Define colors for form feedback states and, by default, alerts.\n\n@state-success-text:             #fff;\n@state-success-bg:               @brand-success;\n@state-success-border:           @brand-success;\n\n@state-info-text:                #fff;\n@state-info-bg:                  @brand-info;\n@state-info-border:              @brand-info;\n\n@state-warning-text:             #fff;\n@state-warning-bg:               @brand-warning;\n@state-warning-border:           @brand-warning;\n\n@state-danger-text:              #fff;\n@state-danger-bg:                @brand-danger;\n@state-danger-border:            @brand-danger;\n\n//== Tooltips\n//\n//##\n\n//** Tooltip max width\n@tooltip-max-width:           200px;\n//** Tooltip text color\n@tooltip-color:               #fff;\n//** Tooltip background color\n@tooltip-bg:                  rgba(0,0,0,.9);\n@tooltip-opacity: .9;\n\n//** Tooltip arrow width\n@tooltip-arrow-width:         5px;\n//** Tooltip arrow color\n@tooltip-arrow-color:         @tooltip-bg;\n\n//== Popovers\n//\n//##\n\n//** Popover body background color\n@popover-bg:                          #fff;\n//** Popover maximum width\n@popover-max-width:                   276px;\n//** Popover border color\n@popover-border-color:                rgba(0,0,0,.2);\n//** Popover fallback border color\n@popover-fallback-border-color:       #ccc;\n\n//** Popover title background color\n@popover-title-bg:                    darken(@popover-bg, 3%);\n\n//** Popover arrow width\n@popover-arrow-width:                 10px;\n//** Popover arrow color\n@popover-arrow-color:                 #fff;\n\n//** Popover outer arrow width\n@popover-arrow-outer-width:           (@popover-arrow-width + 1);\n//** Popover outer arrow color\n@popover-arrow-outer-color: fadein(@popover-border-color, 5%);\n//** Popover outer arrow fallback color\n@popover-arrow-outer-fallback-color: darken(@popover-fallback-border-color, 20%);\n\n//== Labels\n//\n//##\n\n//** Default label background color\n@label-default-bg:            @btn-default-bg;\n//** Primary label background color\n@label-primary-bg:            @brand-primary;\n//** Success label background color\n@label-success-bg:            @brand-success;\n//** Info label background color\n@label-info-bg:               @brand-info;\n//** Warning label background color\n@label-warning-bg:            @brand-warning;\n//** Danger label background color\n@label-danger-bg:             @brand-danger;\n\n//** Default label text color\n@label-color:                 #fff;\n//** Default text color of a linked label\n@label-link-hover-color:      #fff;\n\n//== Modals\n//\n//##\n\n//** Padding applied to the modal body\n@modal-inner-padding:         20px;\n\n//** Padding applied to the modal title\n@modal-title-padding:         15px;\n//** Modal title line-height\n@modal-title-line-height:     @line-height-base;\n\n//** Background color of modal content area\n@modal-content-bg:                             #fff;\n//** Modal content border color\n@modal-content-border-color:                   rgba(0,0,0,.2);\n//** Modal content border color **for IE8**\n@modal-content-fallback-border-color:          #999;\n\n//** Modal backdrop background color\n@modal-backdrop-bg:           #000;\n//** Modal backdrop opacity\n@modal-backdrop-opacity: .5;\n//** Modal header border color\n@modal-header-border-color:   #e5e5e5;\n//** Modal footer border color\n@modal-footer-border-color:   @modal-header-border-color;\n\n@modal-lg: 900px;\n@modal-md: 600px;\n@modal-sm: 300px;\n\n//== Alerts\n//\n//## Define alert colors, border radius, and padding.\n\n@alert-padding:               15px;\n@alert-border-radius:         @border-radius-base;\n@alert-link-font-weight:      bold;\n\n@alert-success-bg:            @state-success-bg;\n@alert-success-text:          @state-success-text;\n@alert-success-border:        @state-success-border;\n\n@alert-info-bg:               @state-info-bg;\n@alert-info-text:             @state-info-text;\n@alert-info-border:           @state-info-border;\n\n@alert-warning-bg:            @state-warning-bg;\n@alert-warning-text:          @state-warning-text;\n@alert-warning-border:        @state-warning-border;\n\n@alert-danger-bg:             @state-danger-bg;\n@alert-danger-text:           @state-danger-text;\n@alert-danger-border:         @state-danger-border;\n\n//== Progress bars\n//\n//##\n\n//** Background color of the whole progress component\n@progress-bg:                 @gray-lighter;\n//** Progress bar text color\n@progress-bar-color:          #fff;\n\n//** Default progress bar color\n@progress-bar-bg:             @brand-primary;\n//** Success progress bar color\n@progress-bar-success-bg:     @brand-success;\n//** Warning progress bar color\n@progress-bar-warning-bg:     @brand-warning;\n//** Danger progress bar color\n@progress-bar-danger-bg:      @brand-danger;\n//** Info progress bar color\n@progress-bar-info-bg:        @brand-info;\n\n//== List group\n//\n//##\n\n//** Background color on `.list-group-item`\n@list-group-bg: #fff;\n//** `.list-group-item` border color\n@list-group-border: @gray-lighter;\n//** List group border radius\n@list-group-border-radius: @border-radius-base;\n\n//** Background color of single list elements on hover\n@list-group-hover-bg: @gray-lighter;\n//** Text color of active list elements\n@list-group-active-color: @component-active-color;\n//** Background color of active list elements\n@list-group-active-bg: @component-active-bg;\n//** Border color of active list elements\n@list-group-active-border: @list-group-active-bg;\n@list-group-active-text-color: lighten(@list-group-active-bg, 40%);\n\n@list-group-link-color: #555;\n@list-group-link-heading-color: #333;\n\n//== Panels\n//\n//##\n\n@panel-bg:                    #fff;\n@panel-body-padding: 15px;\n@panel-border-radius:         @border-radius-base;\n\n//** Border color for elements within panels\n@panel-inner-border: @gray-lighter;\n@panel-footer-bg:             @gray-lighter;\n\n@panel-default-text:          @text-color;\n@panel-default-border:        @gray-lighter;\n@panel-default-heading-bg:    @gray-lighter;\n\n@panel-primary-text:          #fff;\n@panel-primary-border:        @brand-primary;\n@panel-primary-heading-bg:    @brand-primary;\n\n@panel-success-text:          @state-success-text;\n@panel-success-border:        @state-success-border;\n@panel-success-heading-bg:    @state-success-bg;\n\n@panel-info-text: @state-info-text;\n@panel-info-border: @state-info-border;\n@panel-info-heading-bg: @state-info-bg;\n\n@panel-warning-text:          @state-warning-text;\n@panel-warning-border:        @state-warning-border;\n@panel-warning-heading-bg:    @state-warning-bg;\n\n@panel-danger-text:           @state-danger-text;\n@panel-danger-border:         @state-danger-border;\n@panel-danger-heading-bg:     @state-danger-bg;\n\n//== Thumbnails\n//\n//##\n\n//** Padding around the thumbnail image\n@thumbnail-padding:           4px;\n//** Thumbnail background color\n@thumbnail-bg:                @body-bg;\n//** Thumbnail border color\n@thumbnail-border:            @gray-lighter;\n//** Thumbnail border radius\n@thumbnail-border-radius:     @border-radius-base;\n\n//** Custom text color for thumbnail captions\n@thumbnail-caption-color:     @text-color;\n//** Padding around the thumbnail caption\n@thumbnail-caption-padding:   9px;\n\n//== Wells\n//\n//##\n\n@well-bg:                     @gray-lighter;\n@well-border: transparent;\n\n//== Badges\n//\n//##\n\n@badge-color:                 #fff;\n//** Linked badge text color on hover\n@badge-link-hover-color:      #fff;\n@badge-bg:                    @gray;\n\n//** Badge text color in active nav link\n@badge-active-color:          @link-color;\n//** Badge background color in active nav link\n@badge-active-bg:             #fff;\n\n@badge-font-weight:           bold;\n@badge-line-height:           1;\n@badge-border-radius:         10px;\n\n//== Breadcrumbs\n//\n//##\n\n@breadcrumb-padding-vertical: 8px;\n@breadcrumb-padding-horizontal: 15px;\n//** Breadcrumb background color\n@breadcrumb-bg: @gray-lighter;\n//** Breadcrumb text color\n@breadcrumb-color: #ccc;\n//** Text color of current page in the breadcrumb\n@breadcrumb-active-color: @gray;\n//** Textual separator for between breadcrumb elements\n@breadcrumb-separator: \"/\";\n\n//== Carousel\n//\n//##\n\n@carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6);\n\n@carousel-control-color:                      #fff;\n@carousel-control-width:                      15%;\n@carousel-control-opacity:                    .5;\n@carousel-control-font-size:                  20px;\n\n@carousel-indicator-active-bg:                #fff;\n@carousel-indicator-border-color:             #fff;\n\n@carousel-caption-color:                      #fff;\n\n//== Close\n//\n//##\n\n@close-font-weight:           bold;\n@close-color:                 #000;\n@close-text-shadow:           0 1px 0 #fff;\n\n//== Code\n//\n//##\n\n@code-color:                  #c7254e;\n@code-bg:                     #f9f2f4;\n\n@kbd-color: #fff;\n@kbd-bg: #333;\n\n@pre-bg:                      @gray-lighter;\n@pre-color:                   @gray-dark;\n@pre-border-color:            #ccc;\n@pre-scrollable-max-height:   340px;\n\n//== Type\n//\n//##\n\n//** Text muted color\n@text-muted:                  @gray-light;\n//** Abbreviations and acronyms border color\n@abbr-border-color:           @gray-light;\n//** Headings small color\n@headings-small-color:        @gray-light;\n//** Blockquote small color\n@blockquote-small-color:      @gray-light;\n//** Blockquote font size\n@blockquote-font-size: (@font-size-base * 1.25);\n//** Blockquote border color\n@blockquote-border-color:     @gray-lighter;\n//** Page header border color\n@page-header-border-color:    @gray-lighter;\n\n//== Miscellaneous\n//\n//##\n\n//** Horizontal line color.\n@hr-border:                   @gray-lighter;\n\n//** Horizontal offset for forms and lists.\n@component-offset-horizontal: 180px;\n\n@import url(\"//fonts.googleapis.com/css?family=Lato:400,700,400italic\");\n\n// Navbar =====================================================================\n\n// Buttons ====================================================================\n\n.btn:active {\n  .box-shadow(none);\n}\n\n.btn-group.open .dropdown-toggle {\n  .box-shadow(none);\n}\n\n// Typography =================================================================\n\n.text-primary,\n.text-primary:hover {\n  color: @brand-primary;\n}\n\n.text-success,\n.text-success:hover {\n  color: @brand-success;\n}\n\n.text-danger,\n.text-danger:hover {\n  color: @brand-danger;\n}\n\n.text-warning,\n.text-warning:hover {\n  color: @brand-warning;\n}\n\n.text-info,\n.text-info:hover {\n  color: @brand-info;\n}\n\n// Tables =====================================================================\n\n.table {\n\n  tr.success,\n  tr.warning,\n  tr.danger {\n    color: #fff;\n  }\n\n  > thead > tr > th,\n  > tbody > tr > th,\n  > tfoot > tr > th,\n  > thead > tr > td,\n  > tbody > tr > td,\n  > tfoot > tr > td {\n    border: none;\n  }\n\n  &-bordered > thead > tr > th,\n  &-bordered > tbody > tr > th,\n  &-bordered > tfoot > tr > th,\n  &-bordered > thead > tr > td,\n  &-bordered > tbody > tr > td,\n  &-bordered > tfoot > tr > td {\n    border: 1px solid @table-border-color;\n  }\n}\n\n// Forms ======================================================================\n\n.form-control,textarea.form-control,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  border-width: 2px;\n  .box-shadow(none);\n\n  &:focus {\n    .box-shadow(none);\n  }\n}\n\n.has-warning {\n  .help-block,\n  .control-label {\n    color: @brand-warning;\n  }\n\n  .form-control,\n  .form-control:focus {\n    border: 2px solid @brand-warning;\n  }\n}\n\n.has-error {\n  .help-block,\n  .control-label {\n    color: @brand-danger;\n  }\n\n  .form-control,\n  .form-control:focus {\n    border: 2px solid @brand-danger;\n  }\n}\n\n.has-success {\n  .help-block,\n  .control-label {\n    color: @brand-success;\n  }\n\n  .form-control,\n  .form-control:focus {\n    border: 2px solid @brand-success;\n  }\n}\n\n// Navs =======================================================================\n\n.nav {\n  .open > a,\n  .open > a:hover,\n  .open > a:focus {\n    border-color: transparent;\n  }\n}\n\n.pager {\n  a,\n  a:hover {\n    color: #fff;\n  }\n\n  .disabled {\n    &>a,\n    &>a:hover,\n    &>a:focus,\n    &>span {\n      background-color: @pagination-disabled-bg;\n    }\n  }\n}\n\n// Indicators =================================================================\n\n.alert {\n\n  a,\n  .alert-link {\n    color: #fff;\n    text-decoration: underline;\n  }\n}\n\n// Progress bars ==============================================================\n\n.progress {\n  height: 10px;\n  .box-shadow(none);\n}\n\n// Containers =================================================================\n\n.well {\n  .box-shadow(none);\n}\n\n#footer {\n  color: #3A5169;\n  background-color: #1D2936;\n}"
  },
  {
    "path": "server/public/css/themes/ios7.less",
    "content": "// iOS 7 Bootstrap Theme\n// -----------------------------------------------------\n\n// Variables  =================================================================\n\n\n// Document ===================================================================\n* {\n  outline: 0 !important;\n}\n\nhtml {\n  height: 100%;\n}\n\nh1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {\n  font-weight: 300;\n}\n\n[class^=\"fa-\"],\n[class*=\"fa-\"] {\n  margin-right: 10px;\n}\n\na {\n  color: #007aff;\n\n  &:hover {\n    color: #0062cc;\n    text-decoration: none;\n  }\n}\n\n::-moz-selection {\n  background: #007aff;\n  color: white;\n  text-shadow: none;\n}\n\n::selection {\n  background: #007aff;\n  color: white;\n  text-shadow: none;\n}\n\n// Navbar =====================================================================\n\n.navbar-default,\n.navbar-inverse {\n  background: rgba(255, 255, 255, 0.90);\n  border-color: rgba(238,238,238,0.90);\n\n  .navbar-brand {\n    color: #007aff;\n  }\n\n  .navbar-nav {\n    > li > a {\n      color: #999;\n      transition: all 0.3s;\n\n      &:hover,\n      &:focus {\n        background: rgba(0, 0, 0, 0.05);\n      }\n    }\n\n    > .active > a {\n      &,\n      &:focus {\n        color: #007aff;\n        background-color: transparent;\n      }\n\n      &:hover {\n        color: #007aff;\n        background: rgba(0, 0, 0, 0.05);\n      }\n    }\n  }\n}\n\n\n// Modals ======================================================================\n\n.modal-content {\n  border: 0;\n  border-radius: 0px;\n  box-shadow: none;\n}\n\n.modal-header {\n  background: #f1f1f1;\n}\n\n.modal-body {\n  max-height: 420px;\n  overflow-y: auto;\n}\n\n.modal-footer {\n  border: 0px;\n  margin-top: 0;\n  padding: 15px 20px 5px;\n}\n\n\n// Labels ======================================================================\n.label {\n  display: inline-block;\n  font-size: 85%;\n  font-weight: 300;\n  line-height: 1.4;\n  border-radius: 0px;\n  border: 1px solid transparent;\n  transition: all 0.15s;\n\n  h2 {\n    font-weight: 100;\n  }\n}\n\n.label-block {\n  display: block;\n  width: 100%;\n  padding-left: 0;\n  padding-right: 0;\n}\n\n.label-default {\n  background-color: #999;\n\n  &:hover,\n  &.active {\n    background: transparent;\n    color: #999;\n    border-color: #999;\n  }\n}\n\n.label-success {\n  background-color: #60c560;\n\n  &:hover,\n  &.active {\n    background: transparent;\n    color: #60c560;\n    border-color: #60c560;\n  }\n}\n\n.label-info {\n  background-color: #5bc0de;\n\n  &:hover,\n  &.active {\n    background: transparent;\n    color: #5bc0de;\n    border-color: #5bc0de;\n  }\n}\n\n.label-danger {\n  background-color: #d9534f;\n\n  &:hover,\n  &.active {\n    background: transparent;\n    color: #d9534f;\n    border-color: #d9534f;\n  }\n}\n\n.label-warning {\n  background-color: #f0ad4e;\n\n  &:hover,\n  &.active {\n    background: transparent;\n    color: #f0ad4e;\n    border-color: #f0ad4e;\n  }\n}\n\n.label-primary {\n  background-color: #007aff;\n\n  &:hover,\n  &.active {\n    background: transparent;\n    color: #007aff;\n    border-color: #007aff;\n  }\n}\n\n\n\n\n// Alerts ======================================================================\n.alert {\n  border-radius: 0px;\n}\n\n// Tabs ========================================================================\n\n.nav-tabs-justified {\n  > li > a {\n    border-radius: 0;\n    border-bottom: 1px solid #007aff;\n  }\n\n  > .active > a,\n  > .active > a:hover,\n  > .active > a:focus {\n    border: 1px solid #007aff;\n    border-bottom-color: #fff;\n  }\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #007aff;\n  margin-bottom: 20px;\n\n  > li {\n    > a {\n      color: #555;\n      border-radius: 0;\n      border-bottom: 1px solid #007aff;\n      transition: all 0.3s;\n\n      &:hover {\n        color: #333;\n        border-bottom-color: #007aff;\n        background-color: rgba(0,0,0,0.05);\n      }\n    }\n\n    &.active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: #007aff;\n        border: 1px solid #007aff;\n        border-bottom-color: #fff;\n      }\n    }\n  }\n}\n\n.nav-pills {\n  > li {\n    > a {\n      border: 1px solid #007aff;\n\n      &:hover,\n      &:focus {\n        background-color: transparent;\n      }\n    }\n\n    &.active > a {\n      &,\n      &:hover,\n      &:focus {\n        background-color: #007aff;\n      }\n    }\n  }\n}\n\n\n// Buttons ====================================================================\n.btn {\n  font-weight: 300;\n  transition: all 0.15s;\n  margin: 0 10px 10px 0;\n  &:active,\n  .active {\n    box-shadow: none;\n  }\n}\n\n.btn-default {\n  background: #bbb;\n  border-color: #bbb;\n  color: #fff;\n\n  &:hover,\n  &.active {\n    background: transparent;\n    color: #aaa;\n    border-color: #bbb;\n  }\n}\n\n.btn-primary {\n  background: #007aff;\n  border-color: #007aff;\n\n  &:hover,\n  &.active {\n    background: transparent;\n    color: #007aff;\n    border-color: #007aff;\n  }\n}\n\n.btn-success {\n  background: #60c560;\n  border-color: #60c560;\n\n  &:hover,\n  &.active {\n    background: transparent;\n    color: #60c560;\n    border-color: #60c560;\n  }\n}\n\n.btn-info {\n  background: #5bc0de;\n  border-color: #5bc0de;\n\n  &:hover,\n  &.active {\n    background: transparent;\n    color: #5bc0de;\n    border-color: #5bc0de;\n  }\n}\n\n\n.btn-warning {\n  background: #f0ad4e;\n  border-color: #f0ad4e;\n\n  &:hover,\n  &.active {\n    background: transparent;\n    color: #f0ad4e;\n    border-color: #f0ad4e;\n  }\n}\n\n.btn-danger {\n  background: #d9534f;\n  border-color: #d9534f;\n\n  &:hover,\n  &.active {\n    background: transparent;\n    color: #d9534f;\n    border-color: #d9534f;\n  }\n}\n\n.btn-default-outline {\n  color: #999;\n  border: 1px solid #bbb;\n  background: transparent;\n\n  &:hover,\n  &.active {\n  background: #bbb;\n  color: #fff;\n  }\n}\n\n.btn-primary-outline {\n  color: #007aff;\n  border: 1px solid #007aff;\n  background: transparent;\n\n  &:hover,\n  &.active {\n    background: #007aff;\n    color: #fff;\n  }\n}\n\n.btn-success-outline {\n  color: #60c560;\n  border: 1px solid #60c560;\n  background: transparent;\n\n  &:hover,\n  &.active {\n    background: #60c560;\n    color: #fff;\n  }\n}\n\n.btn-info-outline {\n  color: #5bc0de;\n  border: 1px solid #5bc0de;\n  background: transparent;\n\n  &:hover,\n  &.active {\n    background: #5bc0de;\n    color: #fff;\n  }\n}\n\n.btn-warning-outline {\n  color: #f0ad4e;\n  border: 1px solid #f0ad4e;\n  background: transparent;\n\n  &:hover,\n  &.active {\n    background: #f0ad4e;\n    color: #fff;\n  }\n}\n\n.btn-danger-outline {\n  color: #d9534f;\n  border: 1px solid #d9534f;\n  background: transparent;\n\n  &:hover,\n  &.active {\n    background: #d9534f;\n    color: #fff;\n  }\n}\n\n.btn-group {\n  margin: 0 10px 15px 0;\n}\n\n.btn-group.pull-right {\n  margin-right: 0;\n}\n\n.btn-group > .btn {\n  margin: 0;\n}\n\n.facebook {\n  background-color: #335397;\n  border-color: #335397;\n  &:focus,\n  &:hover {\n    background-color: transparent;\n    color: #335397;\n  }\n}\n\n.twitter {\n  background-color: #00c7f7;\n  border-color: #00c7f7;\n  &:focus,\n  &:hover {\n    background-color: transparent;\n    color: #00c7f7;\n  }\n}\n\n.google {\n  background-color: #d34836;\n  border-color: #d34836;\n  &:focus,\n  &:hover {\n    background-color: transparent;\n    color: #d34836;\n  }\n}\n\n.github {\n  background-color: #666;\n  border-color: #666;\n  &:focus,\n  &:hover {\n    background-color: transparent;\n    color: #666;\n  }\n}\n\n// Panel ======================================================================\n.panel {\n  background-color: #fff;\n  border-radius: 0;\n  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.panel-default {\n  > .panel-heading {\n    background-color: #fff;\n    color: #007aff;\n    font-size: 15px;\n    font-weight: 400;\n    margin: 0;\n\n    &.tabs {\n      background: #f5f5f5;\n      border-bottom: 1px solid #ddd;\n    }\n  }\n}\n\n\n\n\n// Wells =================================================================\n.well {\n  padding: 15px 15px 5px;\n  border: 0;\n  background-color: rgba(0, 0, 0, 0.08);\n  margin-bottom: 0;\n  color: #555;\n\n  strong {\n    font-size: 85%;\n    color: #888;\n    border-bottom: 1px solid #c6c6c6;\n    display: block;\n    padding-bottom: 8px;\n    margin-bottom: 10px;\n  }\n}\n\n\n// Typography =================================================================\n\n.page-header {\n  border: 0;\n}\n\n.text-primary {\n  color: #007aff;\n}\n\n.text-danger {\n  color: #d9534f;\n}\n\n.text-warning {\n  color: #f0ad4e;\n}\n\n.list-inline {\n  margin-bottom: 0;\n}\n\nspan {\n  vertical-align: middle;\n}\n\n.table-hover > tbody > tr:hover {\n  > td,\n  > th {\n    transition: 0.3s all;\n  }\n}\n\n.list {\n  list-style: none;\n  padding-left: 0;\n  margin: 0;\n\n  li {\n    padding: 10px 15px 12px 2px;\n    border-bottom: 1px solid #e2e2e2;\n    margin: 0;\n\n    img {\n      margin-right: 10px;\n    }\n\n    &:last-child {\n      border: 0;\n    }\n\n    &:only-child {\n      border-bottom: 1px solid #e2e2e2;\n    }\n  }\n}\n\n// Datatables ================================================================\n\n// Search field\n.dataTables_filter {\n  float: right;\n\n  input {\n    .form-control;\n    display: inline-block;\n    width: inherit;\n    height: 30px;\n    margin: 0 0 5px 5px;\n\n    &:focus {\n      border-color: #007aff;\n      box-shadow: none;\n    }\n  }\n}\n\n// Show \"X\" entries\n.dataTables_length {\n  float: left;\n}\n\n// Sorting controls\n.dataTable th {\n  position: relative;\n  font-weight: normal;\n\n  &.sorting {\n    color: #007aff;\n    cursor: pointer;\n\n    &:after,\n    &:before {\n      content: \"\";\n      width: 0;\n      height: 0;\n      position: absolute;\n      right: 8px;\n      border-right: 5px solid transparent;\n      border-left: 5px solid transparent;\n    }\n\n    &:after {\n      top: 19px;\n      border-top: 5px solid #007aff;\n    }\n\n    &:before {\n      top: 11px;\n      border-bottom: 5px solid #007aff;\n    }\n  }\n\n  &.sorting_asc {\n    color: #007aff;\n    cursor: pointer;\n\n    &:after {\n      content: \"\";\n      width: 0;\n      height: 0;\n      position: absolute;\n      right: 12px;\n      top: 15px;\n      border-bottom: 5px solid #007aff;\n      border-right: 5px solid transparent;\n      border-left: 5px solid transparent;\n    }\n  }\n\n  &.sorting_desc {\n    color: #007aff;\n    cursor: pointer;\n\n    &:after {\n      content: \"\";\n      width: 0;\n      height: 0;\n      position: absolute;\n      right: 12px;\n      top: 15px;\n      border-top: 5px solid #007aff;\n      border-right: 5px solid transparent;\n      border-left: 5px solid transparent;\n    }\n  }\n}\n\n.dataTables_wrapper {\n  .clearfix;\n}\n\n// Showing 1 to 10 of \"X\" entries\n.dataTables_info {\n  float: left;\n  font-size: 13px;\n}\n\n// Pagination container\n.dataTables_paginate {\n  float: right;\n}\n\n// Pagination buttons\n.dataTables_paginate a {\n  border-radius: 4px;\n  font-size: 13px;\n  cursor: pointer;\n  border: 1px solid #aaa;\n  color: #999;\n  background: #fff;\n  padding: 4px 8px;\n  margin-left:5px;\n\n  &:hover {\n    color: #007aff;\n    border-color: #007aff;\n  }\n\n  &.paginate_active {\n    border-color: #007aff;\n    background: #007aff;\n    color: #fff;\n  }\n\n  &.paginate_button_disabled {\n    border-color: #e3e3e3;\n    color: #ddd;\n    pointer-events: none;\n  }\n}\n\n\n// Forms =================================================================\n.form-horizontal .control-label {\n  text-align: left;\n}\n\n.form-control {\n  transition: all 0.4s;\n  box-shadow: none;\n\n  &:focus {\n    border-color: #007aff;\n    box-shadow: none;\n  }\n}\n\nlabel {\n  font-weight: normal;\n}\n\n// Params: text-color; border-color; background-color\n.has-error {\n  .form-control-validation(#d9534f; #d9534f; #d9534f);\n}\n\n.radio,\n.checkbox {\n  margin: 0 0 10px;\n}\n\n.radio-inline,\n.checkbox-inline {\n  padding-top: 9px;\n  margin-right: 20px;\n}\n\n.radio-inline + .radio-inline,\n.radio-inline + .checkbox-inline,\n.checkbox-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-left: 0;\n}\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  display: none;\n}\n\ninput[type=\"checkbox\"] + span:before,\ninput[type=\"radio\"] + span:before {\n  content: \"\";\n  width: 18px;\n  height: 18px;\n  display: inline-block;\n  vertical-align: middle;\n  margin-right: 10px;\n  margin-left: -20px;\n  background: white;\n  border-radius: 3px;\n  border: 1px solid #c8c8c8;\n}\n\ninput[type=\"checkbox\"]:checked + span:before {\n  background: #007aff url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAACXBIWXMAAAsTAAALEwEAmpwYAAA4GGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS41LWMwMTQgNzkuMTUxNDgxLCAyMDEzLzAzLzEzLTEyOjA5OjE1ICAgICAgICAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgICAgICAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgICAgICAgICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ0MgKE1hY2ludG9zaCk8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHhtcDpDcmVhdGVEYXRlPjIwMTMtMTAtMDJUMjM6MzAtMDQ6MDA8L3htcDpDcmVhdGVEYXRlPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxMy0xMC0wN1QxNDo0MDowMi0wNDowMDwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMTMtMTAtMDdUMTQ6NDA6MDItMDQ6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDxwaG90b3Nob3A6Q29sb3JNb2RlPjM8L3Bob3Rvc2hvcDpDb2xvck1vZGU+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6NWYwOTExMjEtMGI4NC00MWU3LWI1ODItNTYzODE0MTRjY2VjPC94bXBNTTpJbnN0YW5jZUlEPgogICAgICAgICA8eG1wTU06RG9jdW1lbnRJRD54bXAuZGlkOjVmMDkxMTIxLTBiODQtNDFlNy1iNTgyLTU2MzgxNDE0Y2NlYzwveG1wTU06RG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD54bXAuZGlkOjVmMDkxMTIxLTBiODQtNDFlNy1iNTgyLTU2MzgxNDE0Y2NlYzwveG1wTU06T3JpZ2luYWxEb2N1bWVudElEPgogICAgICAgICA8eG1wTU06SGlzdG9yeT4KICAgICAgICAgICAgPHJkZjpTZXE+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPmNyZWF0ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDo1ZjA5MTEyMS0wYjg0LTQxZTctYjU4Mi01NjM4MTQxNGNjZWM8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTMtMTAtMDJUMjM6MzAtMDQ6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAoTWFjaW50b3NoKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC94bXBNTTpIaXN0b3J5PgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj43MjAwMDAvMTAwMDA8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT42NTUzNTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MTQ8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MTQ8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PtCjG+cAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAKtJREFUeNq80j2KAkEQhuEaA2EywR8UEy9gIoLR3mGPqOAlFlYxVNAjGHgEzeXZYGfWZhllNPCDgvroequrm8oQr6gRL+oZcBQRsz+HOjHEHhdMEXWhrV+tCx91oF0BfaNbnqVFn5gkfpDctEIvbVomH7jihDH6CfSFzv9pyqSFRVF4xCGB2lXPSE2OuZtW96Cqz8mxxKZqvDSyipXLI6IZEedH25C9fVd/BgB/3XLZbepLGgAAAABJRU5ErkJggg==) no-repeat center center;\n  border-color: #007aff;\n}\n\n@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx) {\n  input[type=\"checkbox\"]:checked + span:before {\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAACXBIWXMAAAsTAAALEwEAmpwYAAA4GGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS41LWMwMTQgNzkuMTUxNDgxLCAyMDEzLzAzLzEzLTEyOjA5OjE1ICAgICAgICAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgICAgICAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgICAgICAgICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ0MgKE1hY2ludG9zaCk8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHhtcDpDcmVhdGVEYXRlPjIwMTMtMTAtMDJUMjM6MzAtMDQ6MDA8L3htcDpDcmVhdGVEYXRlPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxMy0xMC0wN1QxNDozOTo1Ni0wNDowMDwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMTMtMTAtMDdUMTQ6Mzk6NTYtMDQ6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDxwaG90b3Nob3A6Q29sb3JNb2RlPjM8L3Bob3Rvc2hvcDpDb2xvck1vZGU+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6ZGJjYjMzZmYtYWM4NC00NzUzLTgwMTQtZjNjOWMwNDE0NDc0PC94bXBNTTpJbnN0YW5jZUlEPgogICAgICAgICA8eG1wTU06RG9jdW1lbnRJRD54bXAuZGlkOmRiY2IzM2ZmLWFjODQtNDc1My04MDE0LWYzYzljMDQxNDQ3NDwveG1wTU06RG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD54bXAuZGlkOmRiY2IzM2ZmLWFjODQtNDc1My04MDE0LWYzYzljMDQxNDQ3NDwveG1wTU06T3JpZ2luYWxEb2N1bWVudElEPgogICAgICAgICA8eG1wTU06SGlzdG9yeT4KICAgICAgICAgICAgPHJkZjpTZXE+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPmNyZWF0ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDpkYmNiMzNmZi1hYzg0LTQ3NTMtODAxNC1mM2M5YzA0MTQ0NzQ8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTMtMTAtMDJUMjM6MzAtMDQ6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAoTWFjaW50b3NoKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC94bXBNTTpIaXN0b3J5PgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj43MjAwMDAvMTAwMDA8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT42NTUzNTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+Mjg8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+Mjg8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PuRkB3EAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAKpJREFUeNrs1tEJgCAQBuAzmqaapxvH1mmc9gn+XoKiPLs89ckfhEL0Qy41B4BqpqPKaaAlY02QiWgjIv/qAZC7MYAdV/y9vzSG830qAUoYl1ihCssFqrEc4C8sBg4lMAlczoFzZOCcgoXARTFBMvYEJ8VEJiy0wlhdzJhUQwk1Y7GvNISasa99KKHJmGbjP1ETpj1p+FZDth6FveIyXYXnpLj2m9jAvzkGAKpVsk3K4W7yAAAAAElFTkSuQmCC);\n    background-size: 14px 14px;\n  }\n}\n\ninput[type=\"radio\"] {\n  display: none;\n}\n\ninput[type=\"radio\"] + span {\n  position: relative;\n}\n\ninput[type=\"radio\"] + span:before {\n  border-radius: 50%;\n}\n\ninput[type=\"radio\"]:checked + span:after {\n  content: \"\";\n  width: 10px;\n  height: 10px;\n  position: absolute;\n  top: 4px;\n  left: -16px;\n  background-color: #007aff;\n  border-radius: 50%;\n  display: block;\n}\n\n// Misc ===================================================================\n\n\n\n.login-container {\n  background-color: rgba(255, 255, 255, 0.95);\n  border-radius: 40px;\n  box-shadow: 0 0 50px rgba(0, 0, 0, 0.2);\n  padding: 30px;\n  width: 380px;\n  height: 380px;\n  text-align: center;\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  margin: -190px 0 15px -190px;\n\n  -webkit-animation-duration: 1s;\n  -webkit-animation-delay: 0.5s;\n  -moz-animation-duration: 1s;\n  -moz-animation-delay: 0.5s;\n  animation-duration: 1s;\n  animation-delay: 0.5s;\n\n  &.signup {\n   height: 430px;\n    margin-top: -215px;\n  }\n  .form-group {\n    position: relative;\n    margin-bottom: 0;\n  }\n\n  .form-control {\n    height: 48px;\n    font-size: 15px;\n    box-shadow: none;\n    border-radius: 0;\n    border: 0;\n    border-bottom: 1px solid #d6d6d6;\n    padding-left: 0;\n    padding-right: 0;\n    background: transparent;\n  }\n\n  .form-options {\n    margin: 20px 0 30px;\n\n    .checkbox {\n      display: inline-block;\n      margin: 0 0 10px;\n    }\n  }\n\n  button[type=\"submit\"] {\n    position: absolute;\n    top: 10px;\n    right: 0;\n    opacity: 0.5;\n    font-family: \"FontAwesome\";\n    background: transparent;\n    color: #888;\n    border: 2px solid #888;\n    width: 30px;\n    height: 30px;\n    border-radius: 50%;\n    padding-left: 7px;\n    line-height: 24px;\n\n    &:hover {\n      opacity: 1;\n    }\n\n    [class^=\"fa-\"],\n    [class*=\"fa-\"] {\n      margin-right: 0;\n    }\n  }\n\n}\n\n\n.fileinput-filename {\n  vertical-align: super;\n}\n"
  },
  {
    "path": "server/public/js/application.js",
    "content": "/**\n * This is a manifest file that will be compiled into application.js, which will\n * include all the files listed below.\n *\n * Any JavaScript file within this directory can be referenced here using a\n * relative path.\n *\n * It's not advisable to add code directly here, but if you do, it will appear\n * at the bottom of the compiled file.\n */\n\n//= require lib/jquery-2.1.0.min\n//= require lib/bootstrap.min\n//= require main"
  },
  {
    "path": "server/public/js/main.js",
    "content": "$(document).ready(function() {\n\n  // Place JavaScript code here...\n\n});\n"
  },
  {
    "path": "server/test/app.js",
    "content": "var request = require('supertest');\nvar app = require('../app.js');\n\ndescribe('GET /', function() {\n  it('should return 200 OK', function(done) {\n    request(app)\n      .get('/')\n      .expect(200, done);\n  });\n});\n\ndescribe('GET /login', function() {\n  it('should return 200 OK', function(done) {\n    request(app)\n      .get('/login')\n      .expect(200, done);\n  });\n});\n\ndescribe('GET /signup', function() {\n  it('should return 200 OK', function(done) {\n    request(app)\n      .get('/signup')\n      .expect(200, done);\n  });\n});\n\ndescribe('GET /api', function() {\n  it('should return 200 OK', function(done) {\n    request(app)\n      .get('/api')\n      .expect(200, done);\n  });\n});\n\ndescribe('GET /contact', function() {\n  it('should return 200 OK', function(done) {\n    request(app)\n      .get('/contact')\n      .expect(200, done);\n  });\n});\n\ndescribe('GET /random-url', function() {\n  it('should return 404', function(done) {\n    request(app)\n      .get('/reset')\n      .expect(404, done);\n  });\n});"
  },
  {
    "path": "server/test/mocha.opts",
    "content": "--reporter spec\n--timeout 5000"
  },
  {
    "path": "server/test/models.js",
    "content": "var chai = require('chai');\nvar should = chai.should();\nvar User = require('../models/User');\n\ndescribe('User Model', function() {\n  it('should create a new user', function(done) {\n    var user = new User({\n      email: 'test@gmail.com',\n      password: 'password'\n    });\n    user.save(function(err) {\n      if (err) return done(err);\n      done();\n    })\n  });\n\n  it('should not create a user with the unique email', function(done) {\n    var user = new User({\n      email: 'test@gmail.com',\n      password: 'password'\n    });\n    user.save(function(err) {\n      if (err) err.code.should.equal(11000);\n      done();\n    });\n  });\n\n  it('should find user by email', function(done) {\n    User.findOne({ email: 'test@gmail.com' }, function(err, user) {\n      if (err) return done(err);\n      user.email.should.equal('test@gmail.com');\n      done();\n    });\n  });\n\n  it('should delete a user', function(done) {\n    User.remove({ email: 'test@gmail.com' }, function(err) {\n      if (err) return done(err);\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "server/views/404.jade",
    "content": "doctype html\nhtml\n  head\n    title The page you were looking for doesn't exist (404)\n    style.\n      body {\n        background-color: #EFEFEF;\n        color: #2E2F30;\n        text-align: center;\n        font-family: arial, sans-serif;\n      }\n      div.dialog {\n        width: 25em;\n        margin: 4em auto 0 auto;\n        border: 1px solid #CCC;\n        border-right-color: #999;\n        border-left-color: #999;\n        border-bottom-color: #BBB;\n        border-top: #8CC84B solid 4px;\n        border-radius: 9px;\n        background-color: white;\n        padding: 7px 4em 0 4em;\n      }\n      h1 {\n        font-size: 100%;\n        color: #480;\n        line-height: 1.5em;\n      }\n      body > p {\n        width: 33em;\n        margin: 0 auto 1em;\n        padding: 1em 0;\n        background-color: #F7F7F7;\n        border: 1px solid #CCC;\n        border-right-color: #999;\n        border-bottom-color: #999;\n        border-bottom-left-radius: 4px;\n        border-bottom-right-radius: 4px;\n        border-top-color: #DADADA;\n        color: #666;\n        box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);\n      }\n  body\n    .dialog\n      h1 404 Not Found\n      p The page you were looking for doesn't exist.\n"
  },
  {
    "path": "server/views/account/forgot.jade",
    "content": "extends ../layout\n\nblock content\n  .col-sm-8.col-sm-offset-2\n    form(method='POST')\n      legend Forgot Password\n      input(type='hidden', name='_csrf', value=_csrf)\n      .form-group\n        p Enter your email address below and we will send you password reset instructions.\n        label.control-label(for='email') Email\n        input.form-control(type='email', name='email', id='email', placeholder='Email', autofocus=true)\n      .form-group\n        button.btn.btn-primary(type='submit')\n          i.fa.fa-key\n          | Reset Password\n"
  },
  {
    "path": "server/views/account/login.jade",
    "content": "extends ../layout\n\nblock content\n  form(method='POST')\n    legend Sign In\n    input(type='hidden', name='_csrf', value=_csrf)\n    .col-sm-8.col-sm-offset-2\n      if secrets.localAuth\n        .form-group\n          label.control-label(for='email') Email\n          input.form-control(type='text', name='email', id='email', placeholder='Email', autofocus=true)\n        .form-group\n          label.control-label(for='password') Password\n          input.form-control(type='password', name='password', id='password', placeholder='Password')\n        .form-group\n          button.btn.btn-primary(type='submit')\n            i.fa.fa-unlock-alt\n            | Login\n          a.btn.btn-link(href='/forgot') Forgot your password?\n        hr\n      if secrets.facebookAuth\n        a.btn.btn-block.btn-facebook.btn-social(href='/auth/facebook')\n          i.fa.fa-facebook\n          | Sign in with Facebook\n      if secrets.twitterAuth\n        a.btn.btn-block.btn-twitter.btn-social(href='/auth/twitter')\n          i.fa.fa-twitter\n          | Sign in with Twitter\n      if secrets.googleAuth\n        a.btn.btn-block.btn-google-plus.btn-social(href='/auth/google')\n          i.fa.fa-google-plus\n          | Sign in with Google\n      if secrets.githubAuth\n        a.btn.btn-block.btn-github.btn-social(href='/auth/github')\n          i.fa.fa-github\n          | Sign in with GitHub\n      if secrets.linkedinAuth\n        a.btn.btn-block.btn-linkedin.btn-social(href='/auth/linkedin')\n          i.fa.fa-linkedin\n          | Sign in with LinkedIn\n"
  },
  {
    "path": "server/views/account/profile.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h3 Profile Information\n\n  form.form-horizontal(action='/account/profile', method='POST')\n    input(type='hidden', name='_csrf', value=_csrf)\n    .form-group\n      label.col-sm-2.control-label(for='email') Email\n      .col-sm-4\n        input.form-control(type='email', name='email', id='email', value='#{user.email}')\n    .form-group\n      label.col-sm-2.control-label(for='name') Name\n      .col-sm-4\n        input.form-control(type='text', name='name', id='name', value='#{user.profile.name}')\n    .form-group\n      label.col-sm-2.control-label(for='gender') Gender\n      .col-sm-4\n        label.radio\n          input(type='radio', checked=user.profile.gender=='male', name='gender', value='male', data-toggle='radio')\n          span Male\n        label.radio\n          input(type='radio', checked=user.profile.gender=='female', name='gender', value='female', data-toggle='radio')\n          span Female\n    .form-group\n      label.col-sm-2.control-label(for='location') Location\n      .col-sm-4\n        input.form-control(type='text', name='location', id='location', value='#{user.profile.location}')\n    .form-group\n      label.col-sm-2.control-label(for='website') Website\n      .col-sm-4\n        input.form-control(type='text', name='website', id='website', value='#{user.profile.website}')\n    .form-group\n      label.col-sm-2.control-label(for='gravatar') Gravatar\n      .col-sm-4\n        img(src=\"#{user.gravatar()}\", class='profile', width='100', height='100')\n    .form-group\n      .col-sm-offset-2.col-sm-4\n        button.btn.btn.btn-primary(type='submit')\n          i.fa.fa-magnet\n          | Update Profile\n\n\n  if secrets.localAuth\n    .page-header\n      h3 Change Password\n\n    form.form-horizontal(action='/account/password', method='POST')\n      input(type='hidden', name='_csrf', value=_csrf)\n      .form-group\n        label.col-sm-3.control-label(for='password') New Password\n        .col-sm-4\n          input.form-control(type='password', name='password', id='password')\n      .form-group\n        label.col-sm-3.control-label(for='confirmPassword') Confirm Password\n        .col-sm-4\n          input.form-control(type='password', name='confirmPassword', id='confirmPassword')\n      .form-group\n        .col-sm-offset-3.col-sm-4\n          button.btn.btn.btn-primary(type='submit')\n            i.fa.fa-keyboard-o\n            | Change Password\n\n  .page-header\n    h3 Delete Account\n\n  p You can delete your account, but keep in mind this action is irreversible.\n  form(action='/account/delete', method='POST')\n    input(type='hidden', name='_csrf', value=token)\n    button.btn.btn-danger(type='submit')\n      i.fa.fa-trash-o\n      | Delete my account\n\n  .page-header\n    h3 Linked Accounts\n\n  if secrets.googleAuth\n    if user.google\n      p: a.text-danger(href='/account/unlink/google') Unlink your Google account\n    else\n      p: a(href='/auth/google') Link your Google account\n\n  if secrets.facebookAuth\n    if user.facebook\n      p: a.text-danger(href='/account/unlink/facebook') Unlink your Facebook account\n    else\n      p: a(href='/auth/facebook') Link your Facebook account\n\n  if secrets.twitterAuth\n    if user.twitter\n      p: a.text-danger(href='/account/unlink/twitter') Unlink your Twitter account\n    else\n      p: a(href='/auth/twitter') Link your Twitter account\n\n  if secrets.githubAuth\n    if user.github\n      p: a.text-danger(href='/account/unlink/github') Unlink your GitHub account\n    else\n      p: a(href='/auth/github') Link your GitHub account\n\n  if secrets.linkedinAuth\n    if user.linkedin\n      p: a.text-danger(href='/account/unlink/linkedin') Unlink your LinkedIn account\n    else\n      p: a(href='/auth/linkedin') Link your LinkedIn account\n"
  },
  {
    "path": "server/views/account/reset.jade",
    "content": "extends ../layout\n\nblock content\n  .col-sm-8.col-sm-offset-2\n    form(method='POST')\n      legend Reset Password\n      input(type='hidden', name='_csrf', value=_csrf)\n      .form-group\n        label(for='password') New Password\n        input.form-control(type='password', name='password', value='', placeholder='New password', autofocus=true)\n      .form-group\n        label(for='confirm') Confirm Password\n        input.form-control(type='password', name='confirm', value='', placeholder='Confirm password')\n      .form-group\n        button.btn.btn-primary.btn-reset(type='submit')\n          i.fa.fa-keyboard-o\n          | Change Password\n"
  },
  {
    "path": "server/views/account/signup.jade",
    "content": "extends ../layout\n\nblock content\n  form.form-horizontal(id='signup-form', method='POST')\n    input(type='hidden', name='_csrf', value=_csrf)\n    legend Signup\n    .form-group\n      label.col-sm-3.control-label(for='email') Email\n      .col-sm-7\n        input.form-control(type='email', name='email', id='email', placeholder='Email', autofocus)\n    .form-group\n      label.col-sm-3.control-label(for='password') Password\n      .col-sm-7\n        input.form-control(type='password', name='password', id='password', placeholder='Password')\n    .form-group\n      label.col-sm-3.control-label(for='confirmPassword') Confirm Password\n      .col-sm-7\n        input.form-control(type='password', name='confirmPassword', id='confirmPassword', placeholder='Confirm Password')\n    .form-group\n      .col-sm-offset-3.col-sm-7\n        button.btn.btn-success(type='submit')\n          i.fa.fa-check\n          | Signup\n"
  },
  {
    "path": "server/views/api/aviary.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h2\n      i.fa.fa-picture-o\n      | Aviary API\n  \n  .btn-group.btn-group-justified\n    a.btn.btn-primary(href='http://developers.aviary.com/docs/web/setup-guide#constructor', target='_blank')\n      i.fa.fa-check-square-o\n      | API Overview\n    a.btn.btn-primary(href='http://developers.aviary.com/docs/web/setup-guide#saving', target='_blank')\n      i.fa.fa-save\n      | Saving Images\n    a.btn.btn-primary(href='http://developers.aviary.com/docs/web/setup-guide#styling', target='_blank')\n      i.fa.fa-flask\n      | CSS Styling\n  br\n  p: button.btn.btn-success(onclick='return launchEditor(\"evanescence\", \"http://i.imgur.com/fM7OHvr.png\");')\n    i.fa.fa-magic\n    | Edit Photo\n  img#evanescence(src='http://i.imgur.com/fM7OHvr.png')\n\n  script(src='http://feather.aviary.com/js/feather.js')\n  script.\n    var featherEditor = new Aviary.Feather({\n      apiKey: 'c83c98c0da041785',\n      apiVersion: 3,\n      theme: 'dark',\n      tools: 'all',\n      appendTo: '',\n      onSave: function(imageID, newURL) {\n        var img = document.getElementById(imageID);\n        img.src = newURL;\n      },\n      onError: function(errorObj) {\n        alert(errorObj.message);\n      }\n    });\n    function launchEditor(id, src) {\n      featherEditor.launch({\n        image: id,\n        url: src\n      });\n      return false;\n    }"
  },
  {
    "path": "server/views/api/clockwork.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h2\n      i.fa.fa-phone\n      | Clockwork SMS API\n\n  .btn-group.btn-group-justified\n    a.btn.btn-primary(href='http://github.com/mediaburst/node-clockwork', target='_blank')\n      i.fa.fa-check-square-o\n      | Clockwork Node\n    a.btn.btn-primary(href='http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/', target='_blank')\n      i.fa.fa-code-fork\n      | XML API\n\n  h4 Send a text message\n  .row\n    .col-sm-6\n      form(role='form', method='POST')\n        input(type='hidden', name='_csrf', value=_csrf)\n        .form-group\n          .input-group\n            input.form-control(type='text', name='telephone', placeholder='Phone Number (international format)')\n            span.input-group-btn\n              button.btn.btn-success(type='submit') Send\n"
  },
  {
    "path": "server/views/api/facebook.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h2\n      i.fa.fa-facebook-square(style='color: #335397')\n      | Facebook API\n\n  .btn-group.btn-group-justified\n    a.btn.btn-primary(href='https://developers.facebook.com/docs/graph-api/quickstart/', target='_blank')\n      i.fa.fa-check-square-o\n      | Quickstart\n    a.btn.btn-primary(href='https://developers.facebook.com/tools/explorer', target='_blank')\n      i.fa.fa-facebook\n      | Graph API Explorer\n    a.btn.btn-primary(href='https://developers.facebook.com/docs/graph-api/reference/', target='_blank')\n      i.fa.fa-code-fork\n      | API Reference\n\n  h2 /me\n  img(src='https://graph.facebook.com/#{me.id}/picture?type=large', width='90', height='90')\n  h4= me.name\n  h6 First Name: #{me.first_name}\n  h6 Last Name: #{me.last_name}\n  h6 Gender: #{me.gender}\n  h6 Username: #{me.username}\n  h6 Link: #{me.link}\n  h6 Email: #{me.email}\n  h6 Locale: #{me.locale}\n  h6 Timezone: #{me.timezone}\n\n  h2 /me/friends\n  .row\n    for friend in friends\n      .col-xs-3.col-md-2\n        a.thumbnail(href='http://facebook.com/#{friend.id}')\n          img(src='https://graph.facebook.com/#{friend.id}/picture?width=150&height=150')\n          div.facebook-caption= friend.name\n"
  },
  {
    "path": "server/views/api/foursquare.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h2\n      i.fa.fa-foursquare\n      | Foursquare API\n  \n  .btn-group.btn-group-justified\n    a.btn.btn-primary(href='https://developer.foursquare.com/start', target='_blank')\n      i.fa.fa-check-square-o\n      | Getting Started\n    a.btn.btn-primary(href='https://developer.foursquare.com/docs/explore', target='_blank')\n      i.fa.fa-laptop\n      | API Console\n    a.btn.btn-primary(href='https://developer.foursquare.com/docs/', target='_blank')\n      i.fa.fa-code-fork\n      | API Endpoints\n  h3.text-primary Trending Venues\n  table.table.table-striped.table-bordered\n    thead\n      tr\n        th Name\n        th.hidden-xs.hidden-sm Category\n        th.hidden-xs Checkins\n        th Here Now\n    tbody\n      for venue in trendingVenues.venues\n        tr\n          td= venue.name\n          td.hidden-xs.hidden-sm #{venue.categories[0].name}\n          td.hidden-xs #{venue.stats.checkinsCount}\n          td= venue.hereNow.count\n  br\n  h3.text-primary Venue Detail\n  p\n    img(src='#{venueDetail.venue.photos.groups[0].items[0].prefix}150x150#{venueDetail.venue.photos.groups[0].items[0].suffix}')\n\n  .label.label-primary #{venueDetail.venue.name} (#{venueDetail.venue.categories[0].shortName})\n  .label.label-success #{venueDetail.venue.location.address}, #{venueDetail.venue.location.city}, #{venueDetail.venue.location.state}\n  .label.label-warning #{venueDetail.venue.likes.count} likes, #{venueDetail.venue.rating} rating\n\n  h3.text-primary User Checkins\n  table.table.table-bordered.table-hover\n    thead\n      tr\n        th Name\n        th Location\n        th Category\n        th Checkins\n    tbody\n      for checkin in userCheckins.checkins.items\n        tr\n          td= checkin.venue.name\n          td #{checkin.venue.location.address}, #{checkin.venue.location.city}, #{checkin.venue.location.state}\n          td= checkin.venue.categories[0].shortName\n          td= checkin.venue.stats.checkinsCount\n"
  },
  {
    "path": "server/views/api/github.jade",
    "content": "extends ../layout\n\nblock content\n  h2\n    i.fa.fa-github\n    | GitHub API\n\n  .btn-group.btn-group-justified\n    a.btn.btn-primary(href='http://developer.github.com/guides/getting-started/', target='_blank')\n      i.fa.fa-check-square-o\n      | Getting Started\n    a.btn.btn-primary(href='https://apigee.com/console/github', target='_blank')\n      i.fa.fa-laptop\n      | API Console\n    a.btn.btn-primary(href='http://developer.github.com/v3/', target='_blank')\n      i.fa.fa-file-text-o\n      | Documentation\n  br\n  .panel.panel-primary\n    .panel-heading\n      h3.panel-title Repository Information\n    .panel-body\n      .row\n        .col-xs-4\n          img.img-rounded.img-responsive(src='https://github.global.ssl.fastly.net/images/modules/logos_page/Octocat.png')\n        .col-xs-8\n          h4\n            a(href='#{repo.html_url}') #{repo.name}\n          ul.list-inline\n            li\n              i.fa.fa-eye-slash\n              | Subscribers: #{repo.subscribers_count}\n            li\n              i.fa.fa-star\n              | Starred: #{repo.stargazers_count}\n            li\n              i.fa.fa-code-fork\n              | Forks: #{repo.forks_count}\n            li\n              i.fa.fa-code\n              | #{repo.language}\n          strong DESCRIPTION\n          p= repo.description\n"
  },
  {
    "path": "server/views/api/index.jade",
    "content": "extends ../layout\n\nblock content\n  h2 API Browser\n\n  ol\n    li\n      a(href='/api/aviary') Aviary\n    li\n      a(href='/api/clockwork') Clockwork SMS\n    li\n      a(href='/api/facebook') Facebook\n      small  ⇢ Login Required\n    li\n      a(href='/api/foursquare') Foursquare\n      small  ⇢ Login Required\n    li\n      a(href='/api/github') GitHub\n      small  ⇢ Login Required\n    li\n      a(href='/api/lastfm') Last.fm\n    li\n      a(href='/api/linkedin') LinkedIn\n      small  ⇢ Login Required\n    li\n      a(href='/api/nyt') New York Times\n    li\n      a(href='/api/paypal') PayPal\n    li\n      a(href='/api/steam') Steam\n    li\n      a(href='/api/twilio') Twilio\n    li\n      a(href='/api/tumblr') Tumblr\n      small  ⇢ Login Required\n    li\n      a(href='/api/twitter') Twitter\n      small  ⇢ Login Required\n    li\n      a(href='/api/scraping') Web Scraping\n    li\n      a(href='/api/venmo') Venmo\n      small  ⇢ Login Required\n"
  },
  {
    "path": "server/views/api/lastfm.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h2\n      i.fa.fa-music\n      | Last.fm API\n\n  .btn-group.btn-group-justified\n    a.btn.btn-primary(href='https://github.com/jammus/lastfm-node#lastfm-node', target='_blank')\n      i.fa.fa-check-square-o\n      | Last.fm Node Docs\n    a.btn.btn-primary(href='http://www.last.fm/api/account/create', target='_blank')\n      i.fa.fa-laptop\n      | Create API Account\n    a.btn.btn-primary(href='http://www.last.fm/api', target='_blank')\n      i.fa.fa-code-fork\n      | API Endpoints\n\n  h3.text-primary Artist Information\n\n  h4= artist.name\n  ul.list-inline\n    li\n      small.text-primary\n        i.fa.fa-users\n        | Listeners: #{artist.stats.listeners}\n    li\n      small.text-primary\n        i.fa.fa-headphones\n        | Scrobbles: #{artist.stats.playcount}\n\n  p\n    img(src='#{artist.image}')\n\n  p\n    for tag in artist.tags\n      span.label.label-primary\n        i.fa.fa-tag\n        | #{tag.name}\n      |&nbsp;\n\n  .panel.panel-primary\n    .panel-heading Biography\n    .panel-body\n      != artist.bio\n\n  h4 Top Albums\n  for album in artist.topAlbums\n    img(src='#{album}', width=150, height=150)\n    |&nbsp;\n\n  h4 Similar Artists\n  ul.list-unstyled\n    for similarArtist in artist.similar\n      li\n        a.lead(href='#{similarArtist.url}') #{similarArtist.name}"
  },
  {
    "path": "server/views/api/linkedin.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h2\n      i.fa.fa-linkedin-square\n      | LinkedIn API\n\n  .btn-group.btn-group-justified\n    a.btn.btn-primary(href='https://github.com/Kuew/node-linkedin', target='_blank')\n      i.fa.fa-book\n      | Node LinkedIn Docs\n    a.btn.btn-primary(href='http://developer.linkedin.com/documents/authentication', target='_blank')\n      i.fa.fa-check-square-o\n      | Getting Started\n    a.btn.btn-primary(href='http://developer.linkedin.com/apis', target='_blank')\n      i.fa.fa-code-fork\n      | API Endpoints\n\n  h3.text-primary My LinkedIn Profile\n  .well.well-sm\n    .row\n      .col-sm-12\n        .col-sm-2\n          br\n          img.thumbnail(src='#{profile.pictureUrl}')\n        .col-sm-10\n          h3= profile.formattedName\n          h4= profile.headline\n          span.text-muted #{profile.location.name} | #{profile.industry}\n    br\n    .row\n      .col-sm-12\n        dl.dl-horizontal\n          dt.text-muted Current\n          for company in profile.positions.values\n            if company.isCurrent\n              dd\n                strong= company.title\n                |  at\n                strong  #{company.company.name}\n          dt.text-muted Previous\n            for company in profile.positions.values\n              if !company.isCurrent\n                dd\n                  | #{company.title}\n                  |  at\n                  | #{company.company.name}\n          dt.text-muted Education\n            for education in profile.educations.values\n              dd= education.schoolName\n          dt.text-muted Recommendations\n          dd\n            strong #{profile.numRecommenders}\n            |  recommendation(s) received\n          dt.text-muted Connections\n          dd\n            strong #{profile.numConnections}\n            |  connections\n        .text-center\n          small.text-muted= profile.publicProfileUrl\n\n  h3.text-primary LinkedIn Connections\n  table.table.table-hover.table-striped.table-bordered\n    tbody\n    for connection in profile.connections.values\n      if connection.id != 'private'\n        tr\n          td\n            strong #{connection.firstName} #{connection.lastName}\n            .text-muted #{connection.headline}\n"
  },
  {
    "path": "server/views/api/nyt.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h2\n      i.fa.fa-building-o\n      | New York Times API\n\n  .btn-group.btn-group-justified\n    a.btn.btn-primary(href='http://developer.nytimes.com/page', target='_blank')\n      i.fa.fa-check-square-o\n      | Overview\n    a.btn.btn-primary(href='http://prototype.nytimes.com/gst/apitool/index.html', target='_blank')\n      i.fa.fa-laptop\n      | API Console\n    a.btn.btn-primary(href='http://developer.nytimes.com/docs', target='_blank')\n      i.fa.fa-code-fork\n      | API Endspoints\n\n  h4 Young Adult Best Sellers\n  table.table.table-striped.table-bordered\n    thead\n      tr\n        th Rank\n        th Title\n        th.hidden-xs Description\n        th Author\n        th.hidden-xs ISBN-13\n    tbody\n      for book in books\n        tr\n          td= book.rank\n          td= book.book_details[0].title\n          td.hidden-xs= book.book_details[0].description\n          td= book.book_details[0].author\n          td.hidden-xs= book.book_details[0].primary_isbn13"
  },
  {
    "path": "server/views/api/paypal.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h2\n      i.fa.fa-dollar\n      | PayPal API\n\n  .btn-group.btn-group-justified\n    a.btn.btn-primary(href='https://developer.paypal.com/docs/integration/direct/make-your-first-call/', target='_blank')\n      i.fa.fa-check-square-o\n      | Quickstart\n    a.btn.btn-primary(href='https://developer.paypal.com/docs/api/', target='_blank')\n      i.fa.fa-code\n      | API Reference\n    a.btn.btn-primary(href='https://devtools-paypal.com/hateoas/index.html', target='_blank')\n      i.fa.fa-gear\n      | API Playground\n\n\n  if result\n    if canceled\n      h3 Payment got canceled!\n    if success\n      h3 Payment got executed successfully!\n    a(href='/api/paypal')\n        button.btn.btn-primary New payment\n  else\n    p.lead Redirects to PayPal and allows authorizing the sample payment.\n    a(href=approval_url)\n      button.btn.btn-primary Authorize payment"
  },
  {
    "path": "server/views/api/scraping.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h2\n      i.fa.fa-crop\n      | Web Scraping\n\n  .btn-group.btn-group-justified\n    a.btn.btn-primary(href='http://matthewmueller.github.io/cheerio/', target='_blank')\n      i.fa.fa-info\n      | Cheerio Docs\n    a.btn.btn-primary(href='https://developer.foursquare.com/docs/explore', target='_blank')\n      i.fa.fa-film\n      | Cheerio Screencast\n\n  h3 Hacker News Frontpage\n  table.table.table-condensed\n    thead\n      tr\n        th №\n        th Title\n    tbody\n      each link, index in links\n        tr\n          td= index + 1\n          td!= link\n"
  },
  {
    "path": "server/views/api/steam.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h2\n      i.fa.fa-gamepad\n      | Steam Web API\n\n  .btn-group.btn-group-justified\n    a.btn.btn-primary(href='https://developer.valvesoftware.com/wiki/Steam_Web_API', target='_blank')\n      i.fa.fa-check-square-o\n      | API Overview\n\n  br\n\n  .alert.alert-info\n    strong Steam ID\n    p Displaying public information for Steam ID #{playerSummary.steamid}.\n\n  h3 Profile Information\n  .row\n    .col-sm-2\n      img(src='#{playerSummary.avatarfull}', width='92', height='92')\n    .col-sm-8\n      span.lead #{playerSummary.personaname}\n      div Account since: #{new Date(playerSummary.timecreated * 1000)}\n      div Last Online: #{new Date(playerSummary.lastlogoff * 1000)}\n      div Online Status:\n        if playerSummary.personastate == 1\n          strong.text-success  Online\n        else\n          strong.text-danger  Offline\n\n  h3 #{playerAchievemments.gameName} Achievements\n  ul.lead.list-unstyled\n    for achievement in playerAchievemments.achievements\n      if achievement.achieved\n        li.text-success= achievement.name\n\n  h3 Owned Games\n  ul.list-unstyled.list-inline\n    for game in ownedGames\n      li.thumb\n        a(href='http://store.steampowered.com/app/#{game.appid}/')\n          img(src='http://media.steampowered.com/steamcommunity/public/images/apps/#{game.appid}/#{game.img_logo_url}.jpg' width=\"92\")\n\n"
  },
  {
    "path": "server/views/api/tumblr.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h2\n      i.fa.fa-tumblr-square\n      | Tumblr API\n\n  .btn-group.btn-group-justified\n    a.btn.btn-primary(href='http://www.tumblr.com/docs/en/api/v2#overview', target='_blank')\n      i.fa.fa-check-square-o\n      | Overview\n    a.btn.btn-primary(href='https://api.tumblr.com/console', target='_blank')\n      i.fa.fa-laptop\n      | API Console\n    a.btn.btn-primary(href='http://www.tumblr.com/docs/en/api/v2#blog_methods', target='_blank')\n      i.fa.fa-code-fork\n      | API Endpoints\n\n  h3.text-primary #{blog.name}'s blog\n  .btn.btn-xs.btn-primary-outline\n    i.fa.fa-file-text-o\n    | #{blog.posts} posts\n  h4 Latest Photo Post\n  for photo in photoset\n    img.item(src='#{photo.original_size.url}')"
  },
  {
    "path": "server/views/api/twilio.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h2\n      i.fa.fa-phone\n      | Twilio API\n\n  .btn-group.btn-group-justified\n    a.btn.btn-primary(href='http://twilio.github.io/twilio-node/', target='_blank')\n      i.fa.fa-check-square-o\n      | Twilio Node\n    a.btn.btn-primary(href='https://apigee.com/console/twilio', target='_blank')\n      i.fa.fa-laptop\n      | API Console\n    a.btn.btn-primary(href='https://www.twilio.com/docs/api/rest', target='_blank')\n      i.fa.fa-code-fork\n      | REST API\n\n  h4 Send a text message\n  .row\n    .col-sm-6\n      form(role='form', method='POST')\n        input(type='hidden', name='_csrf', value=_csrf)\n        .form-group\n          .input-group\n            input.form-control(type='text', name='telephone', placeholder='Phone Number')\n            span.input-group-btn\n              button.btn.btn-success(type='submit') Send\n"
  },
  {
    "path": "server/views/api/twitter.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h2\n      i.fa.fa-twitter(style='color: #4099ff')\n      | Twitter API\n\n  .btn-group.btn-group-justified\n    a.btn.btn-success(href='https://github.com/ttezel/twit', target='_blank')\n      i.fa.fa-file-text-o\n      | Twit Library Docs\n    a.btn.btn-success(href='https://dev.twitter.com/docs', target='_blank')\n      i.fa.fa-check-square-o\n      | Overview\n    a.btn.btn-success(href='https://dev.twitter.com/docs/api/1.1', target='_blank')\n      i.fa.fa-code-fork\n      | API Endpoints\n\n  br\n  .lead Latest 50 Tweets containing \"Hackathon\" in NYC within 5 miles\n\n  ul.list-unstyled\n    for tweet in tweets\n      li\n        .panel.panel-default\n          .panel-body\n            .clearfix\n              - var image = tweet.user.profile_image_url.replace('_normal', '');\n              img.pull-left(src='#{image}', width=50, height=50, style='margin-right: 10px')\n\n              =tweet.user.name\n              small.text-muted  @#{tweet.user.screen_name}\n              br\n              small #{tweet.text}"
  },
  {
    "path": "server/views/api/venmo.jade",
    "content": "extends ../layout\n\nblock content\n  .page-header\n    h2\n      i.fa.fa-money\n      | Venmo API\n\n  .btn-group.btn-group-justified\n    a.btn.btn-primary(href='https://developer.venmo.com/docs/quickstart', target='_blank')\n      i.fa.fa-book\n      | Quickstart\n    a.btn.btn-primary(href='https://developer.venmo.com/docs/api-console', target='_blank')\n      i.fa.fa-laptop\n      | API Console\n    a.btn.btn-primary(href='https://developer.venmo.com/docs/endpoints/payments', target='_blank')\n      i.fa.fa-code-fork\n      | API Endspoints\n\n  h3 Venmo Profile\n  .row\n    .col-sm-2\n      img(src='#{profile.user.profile_picture_url}')\n    .col-sm-8\n      .row\n        .col-sm-6\n          strong  #{profile.user.display_name}\n          div Balance:\n            strong  $#{profile.balance}\n          div Friends:\n            strong  #{profile.user.friends_count}\n        .col-sm-6\n          div Email:\n            strong  #{profile.user.email}\n          div Phone:\n            strong  #{profile.user.phone}\n          div ID:\n            strong  #{profile.user.id}\n      p #{profile.user.about}\n\n  .row\n    .col-sm-5\n      h3 Make Payment\n      form(role='form', method='POST')\n        input(type='hidden', name='_csrf', value=_csrf)\n        .form-group\n          label.control-label(for='user') Phone, Email or Venmo User ID\n          input.form-control(type='text', name='user', id='user', placeholder='15555555555', autofocus=true)\n        .form-group\n          label.control-label(for='note') Note\n          input.form-control(type='text', name='note', id='note', placeholder='A message to accompany the payment.')\n        .form-group\n          label.control-label(for='amount') Amount\n          input.form-control(type='text', name='amount', id='amount', placeholder='0.10')\n        .form-group\n          button.btn.btn-primary(type='submit')\n            i.fa.fa-usd\n            | Send\n\n  h3 Recent Payments\n  table.table.table-striped.table-condensed.table-bordered\n    thead\n      tr\n        th To\n        th Amount\n        th Status\n        th Date\n        th Note\n    tbody\n      if recentPayments.length\n        for payment in recentPayments\n          tr\n            td= payment.target.phone || payment.target.email || payment.target.user\n            td $#{payment.amount}\n            td= payment.status\n            td= payment.date_created\n            td= payment.note\n      else\n        tr\n          td(colspan=5) No recent payments.\n"
  },
  {
    "path": "server/views/contact.jade",
    "content": "extends layout\n\nblock content\n  .page-header\n    h3 Contact Form\n\n  form.form-horizontal(role='form', method='POST')\n    input(type='hidden', name='_csrf', value=_csrf)\n    .form-group\n      label(class='col-sm-2 control-label', for='name') Name\n      .col-sm-8\n        input.form-control(type='text', name='name', id='name', autofocus=true)\n    .form-group\n      label(class='col-sm-2 control-label', for='email') Email\n      .col-sm-8\n        input.form-control(type='text', name='email', id='email')\n    .form-group\n      label(class='col-sm-2 control-label', for='message') Body\n      .col-sm-8\n        textarea.form-control(type='text', name='message', id='message', rows='7')\n    .form-group\n      .col-sm-offset-2.col-sm-8\n        button.btn.btn-default(type='submit')\n          i.fa.fa-mail-forward\n          | Send\n"
  },
  {
    "path": "server/views/home.jade",
    "content": "extends layout\n\nblock content\n  h1 Bootstrap starter template\n  p.lead\n    | Use this document as a way to quickly start any new project.\n    br\n    | All you get is this text and a mostly barebones HTML document."
  },
  {
    "path": "server/views/layout.jade",
    "content": "doctype html\nhtml\n  head\n    meta(charset='utf-8')\n    meta(http-equiv='X-UA-Compatible', content='IE=edge')\n    meta(name='viewport', content='width=device-width, initial-scale=1.0')\n    meta(name='description', content='')\n    meta(name='csrf-token', content=_csrf)\n    meta(name='author', content='')\n    title #{title} | Hackathon Starter\n    != css('styles')\n    != js('application')\n  body\n    #wrap\n      include partials/navigation\n      .container\n        include partials/flash\n        block content\n    include partials/footer\n    script.\n      var _gaq = _gaq || [];\n      _gaq.push(['_setAccount', 'UA-XXXXX-X']);\n      _gaq.push(['_trackPageview']);\n\n      (function() {\n        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\n        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n      })();\n"
  },
  {
    "path": "server/views/partials/flash.jade",
    "content": "#flash\n  if messages.errors\n    .alert.alert-danger.animated.fadeIn\n      for error in messages.errors\n        div= error.msg\n  if messages.info\n    .alert.alert-info.animated.fadeIn\n      for info in messages.info\n        div= info.msg\n  if messages.success\n    .alert.alert-success.animated.fadeIn\n      for success in messages.success\n        div= success.msg"
  },
  {
    "path": "server/views/partials/footer.jade",
    "content": "#footer\n  .container\n    ul.list-inline.pull-left\n      li © 2014 Company, Inc.\n    ul.list-inline.pull-right\n      li\n        a(href='#') Terms of Use\n      li\n        a(href='#') Privacy Policy\n      li\n        a(href='https://github.com/sahat/hackathon-starter') GitHub Project\n      li\n        a(href='https://github.com/sahat/hackathon-starter/issues') Issues\n"
  },
  {
    "path": "server/views/partials/navigation.jade",
    "content": ".navbar.navbar-default.navbar-fixed-top\n  .container\n    .navbar-header\n      button.navbar-toggle(type='button', data-toggle='collapse', data-target='.navbar-collapse')\n        span.sr-only Toggle navigation\n        span.icon-bar\n        span.icon-bar\n        span.icon-bar\n      a.navbar-brand(href='/') Project name\n    .collapse.navbar-collapse\n      ul.nav.navbar-nav\n        li(class=title=='Home'?'active':undefined)\n          a(href='/') Home\n        li(class=title=='API Browser'?'active':undefined)\n          a(href='/api') API Browser\n        li(class=title=='Contact'?'active':undefined)\n          a(href='/contact') Contact\n      ul.nav.navbar-nav.navbar-right\n        if !user\n          li(class=title=='Login'?'active':undefined)\n            a(href='/login') Login\n          if secrets.localAuth\n            li(class=title=='Create Account'?'active':undefined)\n              a(href='/signup') Create Account\n        else\n          li.dropdown(class=title=='Account Management'?'active':undefined)\n            a.dropdown-toggle(href='#', data-toggle='dropdown')\n              if user.profile.picture\n                img.profile-image(src='#{user.profile.picture}')\n              else\n                img.profile-image(src='#{user.gravatar(60)}')\n              | #{user.profile.name || user.email || user.id}&nbsp;\n              i.caret\n            ul.dropdown-menu\n              li: a(href='/account') My Account\n              li.divider\n              li: a(href='/logout') Logout"
  },
  {
    "path": "test/index.html",
    "content": "<!doctype html>\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <title>Mocha Spec Runner</title>\n    <link rel=\"stylesheet\" href=\"lib/mocha/mocha.css\">\n</head>\n<body>\n    <div id=\"mocha\"></div>\n    <script src=\"lib/mocha/mocha.js\"></script>\n    <script>mocha.setup('bdd')</script>\n    <!-- assertion framework -->\n    <script src=\"lib/chai.js\"></script>\n    <script>var expect = chai.expect</script>\n\n    <!-- include source files here... -->\n\n    <!-- include spec files here... -->\n    <script src=\"spec/test.js\"></script>\n\n    <script>mocha.run()</script>\n</body>\n</html>\n"
  },
  {
    "path": "test/lib/chai.js",
    "content": "!function (name, context, definition) {\n  if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {\n    module.exports = definition();\n  } else if (typeof define === 'function' && typeof define.amd  === 'object') {\n    define(function () {\n      return definition();\n    });\n  } else {\n    context[name] = definition();\n  }\n}('chai', this, function () {\n\n  function require(p) {\n    var path = require.resolve(p)\n      , mod = require.modules[path];\n    if (!mod) throw new Error('failed to require \"' + p + '\"');\n    if (!mod.exports) {\n      mod.exports = {};\n      mod.call(mod.exports, mod, mod.exports, require.relative(path));\n    }\n    return mod.exports;\n  }\n\n  require.modules = {};\n\n  require.resolve = function (path) {\n    var orig = path\n      , reg = path + '.js'\n      , index = path + '/index.js';\n    return require.modules[reg] && reg\n      || require.modules[index] && index\n      || orig;\n  };\n\n  require.register = function (path, fn) {\n    require.modules[path] = fn;\n  };\n\n  require.relative = function (parent) {\n    return function(p){\n      if ('.' != p.charAt(0)) return require(p);\n\n      var path = parent.split('/')\n        , segs = p.split('/');\n      path.pop();\n\n      for (var i = 0; i < segs.length; i++) {\n        var seg = segs[i];\n        if ('..' == seg) path.pop();\n        else if ('.' != seg) path.push(seg);\n      }\n\n      return require(path.join('/'));\n    };\n  };\n\n  require.alias = function (from, to) {\n    var fn = require.modules[from];\n    require.modules[to] = fn;\n  };\n\n\n  require.register(\"chai.js\", function(module, exports, require){\n    /*!\n     * chai\n     * Copyright(c) 2011-2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    var used = []\n      , exports = module.exports = {};\n\n    /*!\n     * Chai version\n     */\n\n    exports.version = '1.4.2';\n\n    /*!\n     * Primary `Assertion` prototype\n     */\n\n    exports.Assertion = require('./chai/assertion');\n\n    /*!\n     * Assertion Error\n     */\n\n    exports.AssertionError = require('./chai/error');\n\n    /*!\n     * Utils for plugins (not exported)\n     */\n\n    var util = require('./chai/utils');\n\n    /**\n     * # .use(function)\n     *\n     * Provides a way to extend the internals of Chai\n     *\n     * @param {Function}\n     * @returns {this} for chaining\n     * @api public\n     */\n\n    exports.use = function (fn) {\n      if (!~used.indexOf(fn)) {\n        fn(this, util);\n        used.push(fn);\n      }\n\n      return this;\n    };\n\n    /*!\n     * Core Assertions\n     */\n\n    var core = require('./chai/core/assertions');\n    exports.use(core);\n\n    /*!\n     * Expect interface\n     */\n\n    var expect = require('./chai/interface/expect');\n    exports.use(expect);\n\n    /*!\n     * Should interface\n     */\n\n    var should = require('./chai/interface/should');\n    exports.use(should);\n\n    /*!\n     * Assert interface\n     */\n\n    var assert = require('./chai/interface/assert');\n    exports.use(assert);\n\n  }); // module: chai.js\n\n  require.register(\"chai/assertion.js\", function(module, exports, require){\n    /*!\n     * chai\n     * http://chaijs.com\n     * Copyright(c) 2011-2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /*!\n     * Module dependencies.\n     */\n\n    var AssertionError = require('./error')\n      , util = require('./utils')\n      , flag = util.flag;\n\n    /*!\n     * Module export.\n     */\n\n    module.exports = Assertion;\n\n\n    /*!\n     * Assertion Constructor\n     *\n     * Creates object for chaining.\n     *\n     * @api private\n     */\n\n    function Assertion (obj, msg, stack) {\n      flag(this, 'ssfi', stack || arguments.callee);\n      flag(this, 'object', obj);\n      flag(this, 'message', msg);\n    }\n\n    /*!\n      * ### Assertion.includeStack\n      *\n      * User configurable property, influences whether stack trace\n      * is included in Assertion error message. Default of false\n      * suppresses stack trace in the error message\n      *\n      *     Assertion.includeStack = true;  // enable stack on error\n      *\n      * @api public\n      */\n\n    Assertion.includeStack = false;\n\n    Assertion.addProperty = function (name, fn) {\n      util.addProperty(this.prototype, name, fn);\n    };\n\n    Assertion.addMethod = function (name, fn) {\n      util.addMethod(this.prototype, name, fn);\n    };\n\n    Assertion.addChainableMethod = function (name, fn, chainingBehavior) {\n      util.addChainableMethod(this.prototype, name, fn, chainingBehavior);\n    };\n\n    Assertion.overwriteProperty = function (name, fn) {\n      util.overwriteProperty(this.prototype, name, fn);\n    };\n\n    Assertion.overwriteMethod = function (name, fn) {\n      util.overwriteMethod(this.prototype, name, fn);\n    };\n\n    /*!\n     * ### .assert(expression, message, negateMessage, expected, actual)\n     *\n     * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass.\n     *\n     * @name assert\n     * @param {Philosophical} expression to be tested\n     * @param {String} message to display if fails\n     * @param {String} negatedMessage to display if negated expression fails\n     * @param {Mixed} expected value (remember to check for negation)\n     * @param {Mixed} actual (optional) will default to `this.obj`\n     * @api private\n     */\n\n    Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) {\n      var ok = util.test(this, arguments);\n      if (true !== showDiff) showDiff = false;\n\n      if (!ok) {\n        var msg = util.getMessage(this, arguments)\n          , actual = util.getActual(this, arguments);\n        throw new AssertionError({\n            message: msg\n          , actual: actual\n          , expected: expected\n          , stackStartFunction: (Assertion.includeStack) ? this.assert : flag(this, 'ssfi')\n          , showDiff: showDiff\n        });\n      }\n    };\n\n    /*!\n     * ### ._obj\n     *\n     * Quick reference to stored `actual` value for plugin developers.\n     *\n     * @api private\n     */\n\n    Object.defineProperty(Assertion.prototype, '_obj',\n      { get: function () {\n          return flag(this, 'object');\n        }\n      , set: function (val) {\n          flag(this, 'object', val);\n        }\n    });\n\n  }); // module: chai/assertion.js\n\n  require.register(\"chai/core/assertions.js\", function(module, exports, require){\n    /*!\n     * chai\n     * http://chaijs.com\n     * Copyright(c) 2011-2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    module.exports = function (chai, _) {\n      var Assertion = chai.Assertion\n        , toString = Object.prototype.toString\n        , flag = _.flag;\n\n      /**\n       * ### Language Chains\n       *\n       * The following are provide as chainable getters to\n       * improve the readability of your assertions. They\n       * do not provide an testing capability unless they\n       * have been overwritten by a plugin.\n       *\n       * **Chains**\n       *\n       * - to\n       * - be\n       * - been\n       * - is\n       * - that\n       * - and\n       * - have\n       * - with\n       * - at\n       * - of\n       *\n       * @name language chains\n       * @api public\n       */\n\n      [ 'to', 'be', 'been'\n      , 'is', 'and', 'have'\n      , 'with', 'that', 'at'\n      , 'of' ].forEach(function (chain) {\n        Assertion.addProperty(chain, function () {\n          return this;\n        });\n      });\n\n      /**\n       * ### .not\n       *\n       * Negates any of assertions following in the chain.\n       *\n       *     expect(foo).to.not.equal('bar');\n       *     expect(goodFn).to.not.throw(Error);\n       *     expect({ foo: 'baz' }).to.have.property('foo')\n       *       .and.not.equal('bar');\n       *\n       * @name not\n       * @api public\n       */\n\n      Assertion.addProperty('not', function () {\n        flag(this, 'negate', true);\n      });\n\n      /**\n       * ### .deep\n       *\n       * Sets the `deep` flag, later used by the `equal` and\n       * `property` assertions.\n       *\n       *     expect(foo).to.deep.equal({ bar: 'baz' });\n       *     expect({ foo: { bar: { baz: 'quux' } } })\n       *       .to.have.deep.property('foo.bar.baz', 'quux');\n       *\n       * @name deep\n       * @api public\n       */\n\n      Assertion.addProperty('deep', function () {\n        flag(this, 'deep', true);\n      });\n\n      /**\n       * ### .a(type)\n       *\n       * The `a` and `an` assertions are aliases that can be\n       * used either as language chains or to assert a value's\n       * type (as revealed by `Object.prototype.toString`).\n       *\n       *     // typeof\n       *     expect('test').to.be.a('string');\n       *     expect({ foo: 'bar' }).to.be.an('object');\n       *     expect(null).to.be.a('null');\n       *     expect(undefined).to.be.an('undefined');\n       *\n       *     // language chain\n       *     expect(foo).to.be.an.instanceof(Foo);\n       *\n       * @name a\n       * @alias an\n       * @param {String} type\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      function an(type, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object')\n          , klassStart = type.charAt(0).toUpperCase()\n          , klass = klassStart + type.slice(1)\n          , article = ~[ 'A', 'E', 'I', 'O', 'U' ].indexOf(klassStart) ? 'an ' : 'a ';\n\n        this.assert(\n            '[object ' + klass + ']' === toString.call(obj)\n          , 'expected #{this} to be ' + article + type\n          , 'expected #{this} not to be ' + article + type\n        );\n      }\n\n      Assertion.addChainableMethod('an', an);\n      Assertion.addChainableMethod('a', an);\n\n      /**\n       * ### .include(value)\n       *\n       * The `include` and `contain` assertions can be used as either property\n       * based language chains or as methods to assert the inclusion of an object\n       * in an array or a substring in a string. When used as language chains,\n       * they toggle the `contain` flag for the `keys` assertion.\n       *\n       *     expect([1,2,3]).to.include(2);\n       *     expect('foobar').to.contain('foo');\n       *     expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');\n       *\n       * @name include\n       * @alias contain\n       * @param {Object|String|Number} obj\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      function includeChainingBehavior () {\n        flag(this, 'contains', true);\n      }\n\n      function include (val, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object')\n        this.assert(\n            ~obj.indexOf(val)\n          , 'expected #{this} to include ' + _.inspect(val)\n          , 'expected #{this} to not include ' + _.inspect(val));\n      }\n\n      Assertion.addChainableMethod('include', include, includeChainingBehavior);\n      Assertion.addChainableMethod('contain', include, includeChainingBehavior);\n\n      /**\n       * ### .ok\n       *\n       * Asserts that the target is truthy.\n       *\n       *     expect('everthing').to.be.ok;\n       *     expect(1).to.be.ok;\n       *     expect(false).to.not.be.ok;\n       *     expect(undefined).to.not.be.ok;\n       *     expect(null).to.not.be.ok;\n       *\n       * @name ok\n       * @api public\n       */\n\n      Assertion.addProperty('ok', function () {\n        this.assert(\n            flag(this, 'object')\n          , 'expected #{this} to be truthy'\n          , 'expected #{this} to be falsy');\n      });\n\n      /**\n       * ### .true\n       *\n       * Asserts that the target is `true`.\n       *\n       *     expect(true).to.be.true;\n       *     expect(1).to.not.be.true;\n       *\n       * @name true\n       * @api public\n       */\n\n      Assertion.addProperty('true', function () {\n        this.assert(\n            true === flag(this, 'object')\n          , 'expected #{this} to be true'\n          , 'expected #{this} to be false'\n          , this.negate ? false : true\n        );\n      });\n\n      /**\n       * ### .false\n       *\n       * Asserts that the target is `false`.\n       *\n       *     expect(false).to.be.false;\n       *     expect(0).to.not.be.false;\n       *\n       * @name false\n       * @api public\n       */\n\n      Assertion.addProperty('false', function () {\n        this.assert(\n            false === flag(this, 'object')\n          , 'expected #{this} to be false'\n          , 'expected #{this} to be true'\n          , this.negate ? true : false\n        );\n      });\n\n      /**\n       * ### .null\n       *\n       * Asserts that the target is `null`.\n       *\n       *     expect(null).to.be.null;\n       *     expect(undefined).not.to.be.null;\n       *\n       * @name null\n       * @api public\n       */\n\n      Assertion.addProperty('null', function () {\n        this.assert(\n            null === flag(this, 'object')\n          , 'expected #{this} to be null'\n          , 'expected #{this} not to be null'\n        );\n      });\n\n      /**\n       * ### .undefined\n       *\n       * Asserts that the target is `undefined`.\n       *\n       *      expect(undefined).to.be.undefined;\n       *      expect(null).to.not.be.undefined;\n       *\n       * @name undefined\n       * @api public\n       */\n\n      Assertion.addProperty('undefined', function () {\n        this.assert(\n            undefined === flag(this, 'object')\n          , 'expected #{this} to be undefined'\n          , 'expected #{this} not to be undefined'\n        );\n      });\n\n      /**\n       * ### .exist\n       *\n       * Asserts that the target is neither `null` nor `undefined`.\n       *\n       *     var foo = 'hi'\n       *       , bar = null\n       *       , baz;\n       *\n       *     expect(foo).to.exist;\n       *     expect(bar).to.not.exist;\n       *     expect(baz).to.not.exist;\n       *\n       * @name exist\n       * @api public\n       */\n\n      Assertion.addProperty('exist', function () {\n        this.assert(\n            null != flag(this, 'object')\n          , 'expected #{this} to exist'\n          , 'expected #{this} to not exist'\n        );\n      });\n\n\n      /**\n       * ### .empty\n       *\n       * Asserts that the target's length is `0`. For arrays, it checks\n       * the `length` property. For objects, it gets the count of\n       * enumerable keys.\n       *\n       *     expect([]).to.be.empty;\n       *     expect('').to.be.empty;\n       *     expect({}).to.be.empty;\n       *\n       * @name empty\n       * @api public\n       */\n\n      Assertion.addProperty('empty', function () {\n        var obj = flag(this, 'object')\n          , expected = obj;\n\n        if (Array.isArray(obj) || 'string' === typeof object) {\n          expected = obj.length;\n        } else if (typeof obj === 'object') {\n          expected = Object.keys(obj).length;\n        }\n\n        this.assert(\n            !expected\n          , 'expected #{this} to be empty'\n          , 'expected #{this} not to be empty'\n        );\n      });\n\n      /**\n       * ### .arguments\n       *\n       * Asserts that the target is an arguments object.\n       *\n       *     function test () {\n       *       expect(arguments).to.be.arguments;\n       *     }\n       *\n       * @name arguments\n       * @alias Arguments\n       * @api public\n       */\n\n      function checkArguments () {\n        var obj = flag(this, 'object')\n          , type = Object.prototype.toString.call(obj);\n        this.assert(\n            '[object Arguments]' === type\n          , 'expected #{this} to be arguments but got ' + type\n          , 'expected #{this} to not be arguments'\n        );\n      }\n\n      Assertion.addProperty('arguments', checkArguments);\n      Assertion.addProperty('Arguments', checkArguments);\n\n      /**\n       * ### .equal(value)\n       *\n       * Asserts that the target is strictly equal (`===`) to `value`.\n       * Alternately, if the `deep` flag is set, asserts that\n       * the target is deeply equal to `value`.\n       *\n       *     expect('hello').to.equal('hello');\n       *     expect(42).to.equal(42);\n       *     expect(1).to.not.equal(true);\n       *     expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });\n       *     expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });\n       *\n       * @name equal\n       * @alias equals\n       * @alias eq\n       * @alias deep.equal\n       * @param {Mixed} value\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      function assertEqual (val, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object');\n        if (flag(this, 'deep')) {\n          return this.eql(val);\n        } else {\n          this.assert(\n              val === obj\n            , 'expected #{this} to equal #{exp}'\n            , 'expected #{this} to not equal #{exp}'\n            , val\n            , this._obj\n            , true\n          );\n        }\n      }\n\n      Assertion.addMethod('equal', assertEqual);\n      Assertion.addMethod('equals', assertEqual);\n      Assertion.addMethod('eq', assertEqual);\n\n      /**\n       * ### .eql(value)\n       *\n       * Asserts that the target is deeply equal to `value`.\n       *\n       *     expect({ foo: 'bar' }).to.eql({ foo: 'bar' });\n       *     expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);\n       *\n       * @name eql\n       * @param {Mixed} value\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      Assertion.addMethod('eql', function (obj, msg) {\n        if (msg) flag(this, 'message', msg);\n        this.assert(\n            _.eql(obj, flag(this, 'object'))\n          , 'expected #{this} to deeply equal #{exp}'\n          , 'expected #{this} to not deeply equal #{exp}'\n          , obj\n          , this._obj\n          , true\n        );\n      });\n\n      /**\n       * ### .above(value)\n       *\n       * Asserts that the target is greater than `value`.\n       *\n       *     expect(10).to.be.above(5);\n       *\n       * Can also be used in conjunction with `length` to\n       * assert a minimum length. The benefit being a\n       * more informative error message than if the length\n       * was supplied directly.\n       *\n       *     expect('foo').to.have.length.above(2);\n       *     expect([ 1, 2, 3 ]).to.have.length.above(2);\n       *\n       * @name above\n       * @alias gt\n       * @alias greaterThan\n       * @param {Number} value\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      function assertAbove (n, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object');\n        if (flag(this, 'doLength')) {\n          new Assertion(obj, msg).to.have.property('length');\n          var len = obj.length;\n          this.assert(\n              len > n\n            , 'expected #{this} to have a length above #{exp} but got #{act}'\n            , 'expected #{this} to not have a length above #{exp}'\n            , n\n            , len\n          );\n        } else {\n          this.assert(\n              obj > n\n            , 'expected #{this} to be above ' + n\n            , 'expected #{this} to be at most ' + n\n          );\n        }\n      }\n\n      Assertion.addMethod('above', assertAbove);\n      Assertion.addMethod('gt', assertAbove);\n      Assertion.addMethod('greaterThan', assertAbove);\n\n      /**\n       * ### .least(value)\n       *\n       * Asserts that the target is greater than or equal to `value`.\n       *\n       *     expect(10).to.be.at.least(10);\n       *\n       * Can also be used in conjunction with `length` to\n       * assert a minimum length. The benefit being a\n       * more informative error message than if the length\n       * was supplied directly.\n       *\n       *     expect('foo').to.have.length.of.at.least(2);\n       *     expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);\n       *\n       * @name least\n       * @alias gte\n       * @param {Number} value\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      function assertLeast (n, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object');\n        if (flag(this, 'doLength')) {\n          new Assertion(obj, msg).to.have.property('length');\n          var len = obj.length;\n          this.assert(\n              len >= n\n            , 'expected #{this} to have a length at least #{exp} but got #{act}'\n            , 'expected #{this} to not have a length below #{exp}'\n            , n\n            , len\n          );\n        } else {\n          this.assert(\n              obj >= n\n            , 'expected #{this} to be at least ' + n\n            , 'expected #{this} to be below ' + n\n          );\n        }\n      }\n\n      Assertion.addMethod('least', assertLeast);\n      Assertion.addMethod('gte', assertLeast);\n\n      /**\n       * ### .below(value)\n       *\n       * Asserts that the target is less than `value`.\n       *\n       *     expect(5).to.be.below(10);\n       *\n       * Can also be used in conjunction with `length` to\n       * assert a maximum length. The benefit being a\n       * more informative error message than if the length\n       * was supplied directly.\n       *\n       *     expect('foo').to.have.length.below(4);\n       *     expect([ 1, 2, 3 ]).to.have.length.below(4);\n       *\n       * @name below\n       * @alias lt\n       * @alias lessThan\n       * @param {Number} value\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      function assertBelow (n, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object');\n        if (flag(this, 'doLength')) {\n          new Assertion(obj, msg).to.have.property('length');\n          var len = obj.length;\n          this.assert(\n              len < n\n            , 'expected #{this} to have a length below #{exp} but got #{act}'\n            , 'expected #{this} to not have a length below #{exp}'\n            , n\n            , len\n          );\n        } else {\n          this.assert(\n              obj < n\n            , 'expected #{this} to be below ' + n\n            , 'expected #{this} to be at least ' + n\n          );\n        }\n      }\n\n      Assertion.addMethod('below', assertBelow);\n      Assertion.addMethod('lt', assertBelow);\n      Assertion.addMethod('lessThan', assertBelow);\n\n      /**\n       * ### .most(value)\n       *\n       * Asserts that the target is less than or equal to `value`.\n       *\n       *     expect(5).to.be.at.most(5);\n       *\n       * Can also be used in conjunction with `length` to\n       * assert a maximum length. The benefit being a\n       * more informative error message than if the length\n       * was supplied directly.\n       *\n       *     expect('foo').to.have.length.of.at.most(4);\n       *     expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);\n       *\n       * @name most\n       * @alias lte\n       * @param {Number} value\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      function assertMost (n, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object');\n        if (flag(this, 'doLength')) {\n          new Assertion(obj, msg).to.have.property('length');\n          var len = obj.length;\n          this.assert(\n              len <= n\n            , 'expected #{this} to have a length at most #{exp} but got #{act}'\n            , 'expected #{this} to not have a length above #{exp}'\n            , n\n            , len\n          );\n        } else {\n          this.assert(\n              obj <= n\n            , 'expected #{this} to be at most ' + n\n            , 'expected #{this} to be above ' + n\n          );\n        }\n      }\n\n      Assertion.addMethod('most', assertMost);\n      Assertion.addMethod('lte', assertMost);\n\n      /**\n       * ### .within(start, finish)\n       *\n       * Asserts that the target is within a range.\n       *\n       *     expect(7).to.be.within(5,10);\n       *\n       * Can also be used in conjunction with `length` to\n       * assert a length range. The benefit being a\n       * more informative error message than if the length\n       * was supplied directly.\n       *\n       *     expect('foo').to.have.length.within(2,4);\n       *     expect([ 1, 2, 3 ]).to.have.length.within(2,4);\n       *\n       * @name within\n       * @param {Number} start lowerbound inclusive\n       * @param {Number} finish upperbound inclusive\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      Assertion.addMethod('within', function (start, finish, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object')\n          , range = start + '..' + finish;\n        if (flag(this, 'doLength')) {\n          new Assertion(obj, msg).to.have.property('length');\n          var len = obj.length;\n          this.assert(\n              len >= start && len <= finish\n            , 'expected #{this} to have a length within ' + range\n            , 'expected #{this} to not have a length within ' + range\n          );\n        } else {\n          this.assert(\n              obj >= start && obj <= finish\n            , 'expected #{this} to be within ' + range\n            , 'expected #{this} to not be within ' + range\n          );\n        }\n      });\n\n      /**\n       * ### .instanceof(constructor)\n       *\n       * Asserts that the target is an instance of `constructor`.\n       *\n       *     var Tea = function (name) { this.name = name; }\n       *       , Chai = new Tea('chai');\n       *\n       *     expect(Chai).to.be.an.instanceof(Tea);\n       *     expect([ 1, 2, 3 ]).to.be.instanceof(Array);\n       *\n       * @name instanceof\n       * @param {Constructor} constructor\n       * @param {String} message _optional_\n       * @alias instanceOf\n       * @api public\n       */\n\n      function assertInstanceOf (constructor, msg) {\n        if (msg) flag(this, 'message', msg);\n        var name = _.getName(constructor);\n        this.assert(\n            flag(this, 'object') instanceof constructor\n          , 'expected #{this} to be an instance of ' + name\n          , 'expected #{this} to not be an instance of ' + name\n        );\n      };\n\n      Assertion.addMethod('instanceof', assertInstanceOf);\n      Assertion.addMethod('instanceOf', assertInstanceOf);\n\n      /**\n       * ### .property(name, [value])\n       *\n       * Asserts that the target has a property `name`, optionally asserting that\n       * the value of that property is strictly equal to  `value`.\n       * If the `deep` flag is set, you can use dot- and bracket-notation for deep\n       * references into objects and arrays.\n       *\n       *     // simple referencing\n       *     var obj = { foo: 'bar' };\n       *     expect(obj).to.have.property('foo');\n       *     expect(obj).to.have.property('foo', 'bar');\n       *\n       *     // deep referencing\n       *     var deepObj = {\n       *         green: { tea: 'matcha' }\n       *       , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]\n       *     };\n\n       *     expect(deepObj).to.have.deep.property('green.tea', 'matcha');\n       *     expect(deepObj).to.have.deep.property('teas[1]', 'matcha');\n       *     expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');\n       *\n       * You can also use an array as the starting point of a `deep.property`\n       * assertion, or traverse nested arrays.\n       *\n       *     var arr = [\n       *         [ 'chai', 'matcha', 'konacha' ]\n       *       , [ { tea: 'chai' }\n       *         , { tea: 'matcha' }\n       *         , { tea: 'konacha' } ]\n       *     ];\n       *\n       *     expect(arr).to.have.deep.property('[0][1]', 'matcha');\n       *     expect(arr).to.have.deep.property('[1][2].tea', 'konacha');\n       *\n       * Furthermore, `property` changes the subject of the assertion\n       * to be the value of that property from the original object. This\n       * permits for further chainable assertions on that property.\n       *\n       *     expect(obj).to.have.property('foo')\n       *       .that.is.a('string');\n       *     expect(deepObj).to.have.property('green')\n       *       .that.is.an('object')\n       *       .that.deep.equals({ tea: 'matcha' });\n       *     expect(deepObj).to.have.property('teas')\n       *       .that.is.an('array')\n       *       .with.deep.property('[2]')\n       *         .that.deep.equals({ tea: 'konacha' });\n       *\n       * @name property\n       * @alias deep.property\n       * @param {String} name\n       * @param {Mixed} value (optional)\n       * @param {String} message _optional_\n       * @returns value of property for chaining\n       * @api public\n       */\n\n      Assertion.addMethod('property', function (name, val, msg) {\n        if (msg) flag(this, 'message', msg);\n\n        var descriptor = flag(this, 'deep') ? 'deep property ' : 'property '\n          , negate = flag(this, 'negate')\n          , obj = flag(this, 'object')\n          , value = flag(this, 'deep')\n            ? _.getPathValue(name, obj)\n            : obj[name];\n\n        if (negate && undefined !== val) {\n          if (undefined === value) {\n            msg = (msg != null) ? msg + ': ' : '';\n            throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name));\n          }\n        } else {\n          this.assert(\n              undefined !== value\n            , 'expected #{this} to have a ' + descriptor + _.inspect(name)\n            , 'expected #{this} to not have ' + descriptor + _.inspect(name));\n        }\n\n        if (undefined !== val) {\n          this.assert(\n              val === value\n            , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'\n            , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}'\n            , val\n            , value\n          );\n        }\n\n        flag(this, 'object', value);\n      });\n\n\n      /**\n       * ### .ownProperty(name)\n       *\n       * Asserts that the target has an own property `name`.\n       *\n       *     expect('test').to.have.ownProperty('length');\n       *\n       * @name ownProperty\n       * @alias haveOwnProperty\n       * @param {String} name\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      function assertOwnProperty (name, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object');\n        this.assert(\n            obj.hasOwnProperty(name)\n          , 'expected #{this} to have own property ' + _.inspect(name)\n          , 'expected #{this} to not have own property ' + _.inspect(name)\n        );\n      }\n\n      Assertion.addMethod('ownProperty', assertOwnProperty);\n      Assertion.addMethod('haveOwnProperty', assertOwnProperty);\n\n      /**\n       * ### .length(value)\n       *\n       * Asserts that the target's `length` property has\n       * the expected value.\n       *\n       *     expect([ 1, 2, 3]).to.have.length(3);\n       *     expect('foobar').to.have.length(6);\n       *\n       * Can also be used as a chain precursor to a value\n       * comparison for the length property.\n       *\n       *     expect('foo').to.have.length.above(2);\n       *     expect([ 1, 2, 3 ]).to.have.length.above(2);\n       *     expect('foo').to.have.length.below(4);\n       *     expect([ 1, 2, 3 ]).to.have.length.below(4);\n       *     expect('foo').to.have.length.within(2,4);\n       *     expect([ 1, 2, 3 ]).to.have.length.within(2,4);\n       *\n       * @name length\n       * @alias lengthOf\n       * @param {Number} length\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      function assertLengthChain () {\n        flag(this, 'doLength', true);\n      }\n\n      function assertLength (n, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object');\n        new Assertion(obj, msg).to.have.property('length');\n        var len = obj.length;\n\n        this.assert(\n            len == n\n          , 'expected #{this} to have a length of #{exp} but got #{act}'\n          , 'expected #{this} to not have a length of #{act}'\n          , n\n          , len\n        );\n      }\n\n      Assertion.addChainableMethod('length', assertLength, assertLengthChain);\n      Assertion.addMethod('lengthOf', assertLength, assertLengthChain);\n\n      /**\n       * ### .match(regexp)\n       *\n       * Asserts that the target matches a regular expression.\n       *\n       *     expect('foobar').to.match(/^foo/);\n       *\n       * @name match\n       * @param {RegExp} RegularExpression\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      Assertion.addMethod('match', function (re, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object');\n        this.assert(\n            re.exec(obj)\n          , 'expected #{this} to match ' + re\n          , 'expected #{this} not to match ' + re\n        );\n      });\n\n      /**\n       * ### .string(string)\n       *\n       * Asserts that the string target contains another string.\n       *\n       *     expect('foobar').to.have.string('bar');\n       *\n       * @name string\n       * @param {String} string\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      Assertion.addMethod('string', function (str, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object');\n        new Assertion(obj, msg).is.a('string');\n\n        this.assert(\n            ~obj.indexOf(str)\n          , 'expected #{this} to contain ' + _.inspect(str)\n          , 'expected #{this} to not contain ' + _.inspect(str)\n        );\n      });\n\n\n      /**\n       * ### .keys(key1, [key2], [...])\n       *\n       * Asserts that the target has exactly the given keys, or\n       * asserts the inclusion of some keys when using the\n       * `include` or `contain` modifiers.\n       *\n       *     expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']);\n       *     expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar');\n       *\n       * @name keys\n       * @alias key\n       * @param {String...|Array} keys\n       * @api public\n       */\n\n      function assertKeys (keys) {\n        var obj = flag(this, 'object')\n          , str\n          , ok = true;\n\n        keys = keys instanceof Array\n          ? keys\n          : Array.prototype.slice.call(arguments);\n\n        if (!keys.length) throw new Error('keys required');\n\n        var actual = Object.keys(obj)\n          , len = keys.length;\n\n        // Inclusion\n        ok = keys.every(function(key){\n          return ~actual.indexOf(key);\n        });\n\n        // Strict\n        if (!flag(this, 'negate') && !flag(this, 'contains')) {\n          ok = ok && keys.length == actual.length;\n        }\n\n        // Key string\n        if (len > 1) {\n          keys = keys.map(function(key){\n            return _.inspect(key);\n          });\n          var last = keys.pop();\n          str = keys.join(', ') + ', and ' + last;\n        } else {\n          str = _.inspect(keys[0]);\n        }\n\n        // Form\n        str = (len > 1 ? 'keys ' : 'key ') + str;\n\n        // Have / include\n        str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;\n\n        // Assertion\n        this.assert(\n            ok\n          , 'expected #{this} to ' + str\n          , 'expected #{this} to not ' + str\n        );\n      }\n\n      Assertion.addMethod('keys', assertKeys);\n      Assertion.addMethod('key', assertKeys);\n\n      /**\n       * ### .throw(constructor)\n       *\n       * Asserts that the function target will throw a specific error, or specific type of error\n       * (as determined using `instanceof`), optionally with a RegExp or string inclusion test\n       * for the error's message.\n       *\n       *     var err = new ReferenceError('This is a bad function.');\n       *     var fn = function () { throw err; }\n       *     expect(fn).to.throw(ReferenceError);\n       *     expect(fn).to.throw(Error);\n       *     expect(fn).to.throw(/bad function/);\n       *     expect(fn).to.not.throw('good function');\n       *     expect(fn).to.throw(ReferenceError, /bad function/);\n       *     expect(fn).to.throw(err);\n       *     expect(fn).to.not.throw(new RangeError('Out of range.'));\n       *\n       * Please note that when a throw expectation is negated, it will check each\n       * parameter independently, starting with error constructor type. The appropriate way\n       * to check for the existence of a type of error but for a message that does not match\n       * is to use `and`.\n       *\n       *     expect(fn).to.throw(ReferenceError)\n       *        .and.not.throw(/good function/);\n       *\n       * @name throw\n       * @alias throws\n       * @alias Throw\n       * @param {ErrorConstructor} constructor\n       * @param {String|RegExp} expected error message\n       * @param {String} message _optional_\n       * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types\n       * @api public\n       */\n\n      function assertThrows (constructor, errMsg, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object');\n        new Assertion(obj, msg).is.a('function');\n\n        var thrown = false\n          , desiredError = null\n          , name = null\n          , thrownError = null;\n\n        if (arguments.length === 0) {\n          errMsg = null;\n          constructor = null;\n        } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {\n          errMsg = constructor;\n          constructor = null;\n        } else if (constructor && constructor instanceof Error) {\n          desiredError = constructor;\n          constructor = null;\n          errMsg = null;\n        } else if (typeof constructor === 'function') {\n          name = (new constructor()).name;\n        } else {\n          constructor = null;\n        }\n\n        try {\n          obj();\n        } catch (err) {\n          // first, check desired error\n          if (desiredError) {\n            this.assert(\n                err === desiredError\n              , 'expected #{this} to throw ' + _.inspect(desiredError) + ' but ' + _.inspect(err) + ' was thrown'\n              , 'expected #{this} to not throw ' + _.inspect(desiredError)\n            );\n            return this;\n          }\n          // next, check constructor\n          if (constructor) {\n            this.assert(\n                err instanceof constructor\n              , 'expected #{this} to throw ' + name + ' but ' + _.inspect(err) + ' was thrown'\n              , 'expected #{this} to not throw ' + name + ' but ' + _.inspect(err) + ' was thrown');\n            if (!errMsg) return this;\n          }\n          // next, check message\n          if (err.message && errMsg && errMsg instanceof RegExp) {\n            this.assert(\n                errMsg.exec(err.message)\n              , 'expected #{this} to throw error matching ' + errMsg + ' but got ' + _.inspect(err.message)\n              , 'expected #{this} to throw error not matching ' + errMsg\n            );\n            return this;\n          } else if (err.message && errMsg && 'string' === typeof errMsg) {\n            this.assert(\n                ~err.message.indexOf(errMsg)\n              , 'expected #{this} to throw error including #{exp} but got #{act}'\n              , 'expected #{this} to throw error not including #{act}'\n              , errMsg\n              , err.message\n            );\n            return this;\n          } else {\n            thrown = true;\n            thrownError = err;\n          }\n        }\n\n        var expectedThrown = name ? name : desiredError ? _.inspect(desiredError) : 'an error';\n        var actuallyGot = ''\n        if (thrown) {\n          actuallyGot = ' but ' + _.inspect(thrownError) + ' was thrown'\n        }\n\n        this.assert(\n            thrown === true\n          , 'expected #{this} to throw ' + expectedThrown + actuallyGot\n          , 'expected #{this} to not throw ' + expectedThrown + actuallyGot\n        );\n      };\n\n      Assertion.addMethod('throw', assertThrows);\n      Assertion.addMethod('throws', assertThrows);\n      Assertion.addMethod('Throw', assertThrows);\n\n      /**\n       * ### .respondTo(method)\n       *\n       * Asserts that the object or class target will respond to a method.\n       *\n       *     Klass.prototype.bar = function(){};\n       *     expect(Klass).to.respondTo('bar');\n       *     expect(obj).to.respondTo('bar');\n       *\n       * To check if a constructor will respond to a static function,\n       * set the `itself` flag.\n       *\n       *    Klass.baz = function(){};\n       *    expect(Klass).itself.to.respondTo('baz');\n       *\n       * @name respondTo\n       * @param {String} method\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      Assertion.addMethod('respondTo', function (method, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object')\n          , itself = flag(this, 'itself')\n          , context = ('function' === typeof obj && !itself)\n            ? obj.prototype[method]\n            : obj[method];\n\n        this.assert(\n            'function' === typeof context\n          , 'expected #{this} to respond to ' + _.inspect(method)\n          , 'expected #{this} to not respond to ' + _.inspect(method)\n        );\n      });\n\n      /**\n       * ### .itself\n       *\n       * Sets the `itself` flag, later used by the `respondTo` assertion.\n       *\n       *    function Foo() {}\n       *    Foo.bar = function() {}\n       *    Foo.prototype.baz = function() {}\n       *\n       *    expect(Foo).itself.to.respondTo('bar');\n       *    expect(Foo).itself.not.to.respondTo('baz');\n       *\n       * @name itself\n       * @api public\n       */\n\n      Assertion.addProperty('itself', function () {\n        flag(this, 'itself', true);\n      });\n\n      /**\n       * ### .satisfy(method)\n       *\n       * Asserts that the target passes a given truth test.\n       *\n       *     expect(1).to.satisfy(function(num) { return num > 0; });\n       *\n       * @name satisfy\n       * @param {Function} matcher\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      Assertion.addMethod('satisfy', function (matcher, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object');\n        this.assert(\n            matcher(obj)\n          , 'expected #{this} to satisfy ' + _.inspect(matcher)\n          , 'expected #{this} to not satisfy' + _.inspect(matcher)\n          , this.negate ? false : true\n          , matcher(obj)\n        );\n      });\n\n      /**\n       * ### .closeTo(expected, delta)\n       *\n       * Asserts that the target is equal `expected`, to within a +/- `delta` range.\n       *\n       *     expect(1.5).to.be.closeTo(1, 0.5);\n       *\n       * @name closeTo\n       * @param {Number} expected\n       * @param {Number} delta\n       * @param {String} message _optional_\n       * @api public\n       */\n\n      Assertion.addMethod('closeTo', function (expected, delta, msg) {\n        if (msg) flag(this, 'message', msg);\n        var obj = flag(this, 'object');\n        this.assert(\n            Math.abs(obj - expected) <= delta\n          , 'expected #{this} to be close to ' + expected + ' +/- ' + delta\n          , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta\n        );\n      });\n\n    };\n\n  }); // module: chai/core/assertions.js\n\n  require.register(\"chai/error.js\", function(module, exports, require){\n    /*!\n     * chai\n     * Copyright(c) 2011-2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /*!\n     * Main export\n     */\n\n    module.exports = AssertionError;\n\n    /**\n     * # AssertionError (constructor)\n     *\n     * Create a new assertion error based on the Javascript\n     * `Error` prototype.\n     *\n     * **Options**\n     * - message\n     * - actual\n     * - expected\n     * - operator\n     * - startStackFunction\n     *\n     * @param {Object} options\n     * @api public\n     */\n\n    function AssertionError (options) {\n      options = options || {};\n      this.message = options.message;\n      this.actual = options.actual;\n      this.expected = options.expected;\n      this.operator = options.operator;\n      this.showDiff = options.showDiff;\n\n      if (options.stackStartFunction && Error.captureStackTrace) {\n        var stackStartFunction = options.stackStartFunction;\n        Error.captureStackTrace(this, stackStartFunction);\n      }\n    }\n\n    /*!\n     * Inherit from Error\n     */\n\n    AssertionError.prototype = Object.create(Error.prototype);\n    AssertionError.prototype.name = 'AssertionError';\n    AssertionError.prototype.constructor = AssertionError;\n\n    /**\n     * # toString()\n     *\n     * Override default to string method\n     */\n\n    AssertionError.prototype.toString = function() {\n      return this.message;\n    };\n\n  }); // module: chai/error.js\n\n  require.register(\"chai/interface/assert.js\", function(module, exports, require){\n    /*!\n     * chai\n     * Copyright(c) 2011-2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n\n    module.exports = function (chai, util) {\n\n      /*!\n       * Chai dependencies.\n       */\n\n      var Assertion = chai.Assertion\n        , flag = util.flag;\n\n      /*!\n       * Module export.\n       */\n\n      /**\n       * ### assert(expression, message)\n       *\n       * Write your own test expressions.\n       *\n       *     assert('foo' !== 'bar', 'foo is not bar');\n       *     assert(Array.isArray([]), 'empty arrays are arrays');\n       *\n       * @param {Mixed} expression to test for truthiness\n       * @param {String} message to display on error\n       * @name assert\n       * @api public\n       */\n\n      var assert = chai.assert = function (express, errmsg) {\n        var test = new Assertion(null);\n        test.assert(\n            express\n          , errmsg\n          , '[ negation message unavailable ]'\n        );\n      };\n\n      /**\n       * ### .fail(actual, expected, [message], [operator])\n       *\n       * Throw a failure. Node.js `assert` module-compatible.\n       *\n       * @name fail\n       * @param {Mixed} actual\n       * @param {Mixed} expected\n       * @param {String} message\n       * @param {String} operator\n       * @api public\n       */\n\n      assert.fail = function (actual, expected, message, operator) {\n        throw new chai.AssertionError({\n            actual: actual\n          , expected: expected\n          , message: message\n          , operator: operator\n          , stackStartFunction: assert.fail\n        });\n      };\n\n      /**\n       * ### .ok(object, [message])\n       *\n       * Asserts that `object` is truthy.\n       *\n       *     assert.ok('everything', 'everything is ok');\n       *     assert.ok(false, 'this will fail');\n       *\n       * @name ok\n       * @param {Mixed} object to test\n       * @param {String} message\n       * @api public\n       */\n\n      assert.ok = function (val, msg) {\n        new Assertion(val, msg).is.ok;\n      };\n\n      /**\n       * ### .equal(actual, expected, [message])\n       *\n       * Asserts non-strict equality (`==`) of `actual` and `expected`.\n       *\n       *     assert.equal(3, '3', '== coerces values to strings');\n       *\n       * @name equal\n       * @param {Mixed} actual\n       * @param {Mixed} expected\n       * @param {String} message\n       * @api public\n       */\n\n      assert.equal = function (act, exp, msg) {\n        var test = new Assertion(act, msg);\n\n        test.assert(\n            exp == flag(test, 'object')\n          , 'expected #{this} to equal #{exp}'\n          , 'expected #{this} to not equal #{act}'\n          , exp\n          , act\n        );\n      };\n\n      /**\n       * ### .notEqual(actual, expected, [message])\n       *\n       * Asserts non-strict inequality (`!=`) of `actual` and `expected`.\n       *\n       *     assert.notEqual(3, 4, 'these numbers are not equal');\n       *\n       * @name notEqual\n       * @param {Mixed} actual\n       * @param {Mixed} expected\n       * @param {String} message\n       * @api public\n       */\n\n      assert.notEqual = function (act, exp, msg) {\n        var test = new Assertion(act, msg);\n\n        test.assert(\n            exp != flag(test, 'object')\n          , 'expected #{this} to not equal #{exp}'\n          , 'expected #{this} to equal #{act}'\n          , exp\n          , act\n        );\n      };\n\n      /**\n       * ### .strictEqual(actual, expected, [message])\n       *\n       * Asserts strict equality (`===`) of `actual` and `expected`.\n       *\n       *     assert.strictEqual(true, true, 'these booleans are strictly equal');\n       *\n       * @name strictEqual\n       * @param {Mixed} actual\n       * @param {Mixed} expected\n       * @param {String} message\n       * @api public\n       */\n\n      assert.strictEqual = function (act, exp, msg) {\n        new Assertion(act, msg).to.equal(exp);\n      };\n\n      /**\n       * ### .notStrictEqual(actual, expected, [message])\n       *\n       * Asserts strict inequality (`!==`) of `actual` and `expected`.\n       *\n       *     assert.notStrictEqual(3, '3', 'no coercion for strict equality');\n       *\n       * @name notStrictEqual\n       * @param {Mixed} actual\n       * @param {Mixed} expected\n       * @param {String} message\n       * @api public\n       */\n\n      assert.notStrictEqual = function (act, exp, msg) {\n        new Assertion(act, msg).to.not.equal(exp);\n      };\n\n      /**\n       * ### .deepEqual(actual, expected, [message])\n       *\n       * Asserts that `actual` is deeply equal to `expected`.\n       *\n       *     assert.deepEqual({ tea: 'green' }, { tea: 'green' });\n       *\n       * @name deepEqual\n       * @param {Mixed} actual\n       * @param {Mixed} expected\n       * @param {String} message\n       * @api public\n       */\n\n      assert.deepEqual = function (act, exp, msg) {\n        new Assertion(act, msg).to.eql(exp);\n      };\n\n      /**\n       * ### .notDeepEqual(actual, expected, [message])\n       *\n       * Assert that `actual` is not deeply equal to `expected`.\n       *\n       *     assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' });\n       *\n       * @name notDeepEqual\n       * @param {Mixed} actual\n       * @param {Mixed} expected\n       * @param {String} message\n       * @api public\n       */\n\n      assert.notDeepEqual = function (act, exp, msg) {\n        new Assertion(act, msg).to.not.eql(exp);\n      };\n\n      /**\n       * ### .isTrue(value, [message])\n       *\n       * Asserts that `value` is true.\n       *\n       *     var teaServed = true;\n       *     assert.isTrue(teaServed, 'the tea has been served');\n       *\n       * @name isTrue\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isTrue = function (val, msg) {\n        new Assertion(val, msg).is['true'];\n      };\n\n      /**\n       * ### .isFalse(value, [message])\n       *\n       * Asserts that `value` is false.\n       *\n       *     var teaServed = false;\n       *     assert.isFalse(teaServed, 'no tea yet? hmm...');\n       *\n       * @name isFalse\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isFalse = function (val, msg) {\n        new Assertion(val, msg).is['false'];\n      };\n\n      /**\n       * ### .isNull(value, [message])\n       *\n       * Asserts that `value` is null.\n       *\n       *     assert.isNull(err, 'there was no error');\n       *\n       * @name isNull\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isNull = function (val, msg) {\n        new Assertion(val, msg).to.equal(null);\n      };\n\n      /**\n       * ### .isNotNull(value, [message])\n       *\n       * Asserts that `value` is not null.\n       *\n       *     var tea = 'tasty chai';\n       *     assert.isNotNull(tea, 'great, time for tea!');\n       *\n       * @name isNotNull\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isNotNull = function (val, msg) {\n        new Assertion(val, msg).to.not.equal(null);\n      };\n\n      /**\n       * ### .isUndefined(value, [message])\n       *\n       * Asserts that `value` is `undefined`.\n       *\n       *     var tea;\n       *     assert.isUndefined(tea, 'no tea defined');\n       *\n       * @name isUndefined\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isUndefined = function (val, msg) {\n        new Assertion(val, msg).to.equal(undefined);\n      };\n\n      /**\n       * ### .isDefined(value, [message])\n       *\n       * Asserts that `value` is not `undefined`.\n       *\n       *     var tea = 'cup of chai';\n       *     assert.isDefined(tea, 'tea has been defined');\n       *\n       * @name isUndefined\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isDefined = function (val, msg) {\n        new Assertion(val, msg).to.not.equal(undefined);\n      };\n\n      /**\n       * ### .isFunction(value, [message])\n       *\n       * Asserts that `value` is a function.\n       *\n       *     function serveTea() { return 'cup of tea'; };\n       *     assert.isFunction(serveTea, 'great, we can have tea now');\n       *\n       * @name isFunction\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isFunction = function (val, msg) {\n        new Assertion(val, msg).to.be.a('function');\n      };\n\n      /**\n       * ### .isNotFunction(value, [message])\n       *\n       * Asserts that `value` is _not_ a function.\n       *\n       *     var serveTea = [ 'heat', 'pour', 'sip' ];\n       *     assert.isNotFunction(serveTea, 'great, we have listed the steps');\n       *\n       * @name isNotFunction\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isNotFunction = function (val, msg) {\n        new Assertion(val, msg).to.not.be.a('function');\n      };\n\n      /**\n       * ### .isObject(value, [message])\n       *\n       * Asserts that `value` is an object (as revealed by\n       * `Object.prototype.toString`).\n       *\n       *     var selection = { name: 'Chai', serve: 'with spices' };\n       *     assert.isObject(selection, 'tea selection is an object');\n       *\n       * @name isObject\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isObject = function (val, msg) {\n        new Assertion(val, msg).to.be.a('object');\n      };\n\n      /**\n       * ### .isNotObject(value, [message])\n       *\n       * Asserts that `value` is _not_ an object.\n       *\n       *     var selection = 'chai'\n       *     assert.isObject(selection, 'tea selection is not an object');\n       *     assert.isObject(null, 'null is not an object');\n       *\n       * @name isNotObject\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isNotObject = function (val, msg) {\n        new Assertion(val, msg).to.not.be.a('object');\n      };\n\n      /**\n       * ### .isArray(value, [message])\n       *\n       * Asserts that `value` is an array.\n       *\n       *     var menu = [ 'green', 'chai', 'oolong' ];\n       *     assert.isArray(menu, 'what kind of tea do we want?');\n       *\n       * @name isArray\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isArray = function (val, msg) {\n        new Assertion(val, msg).to.be.an('array');\n      };\n\n      /**\n       * ### .isNotArray(value, [message])\n       *\n       * Asserts that `value` is _not_ an array.\n       *\n       *     var menu = 'green|chai|oolong';\n       *     assert.isNotArray(menu, 'what kind of tea do we want?');\n       *\n       * @name isNotArray\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isNotArray = function (val, msg) {\n        new Assertion(val, msg).to.not.be.an('array');\n      };\n\n      /**\n       * ### .isString(value, [message])\n       *\n       * Asserts that `value` is a string.\n       *\n       *     var teaOrder = 'chai';\n       *     assert.isString(teaOrder, 'order placed');\n       *\n       * @name isString\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isString = function (val, msg) {\n        new Assertion(val, msg).to.be.a('string');\n      };\n\n      /**\n       * ### .isNotString(value, [message])\n       *\n       * Asserts that `value` is _not_ a string.\n       *\n       *     var teaOrder = 4;\n       *     assert.isNotString(teaOrder, 'order placed');\n       *\n       * @name isNotString\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isNotString = function (val, msg) {\n        new Assertion(val, msg).to.not.be.a('string');\n      };\n\n      /**\n       * ### .isNumber(value, [message])\n       *\n       * Asserts that `value` is a number.\n       *\n       *     var cups = 2;\n       *     assert.isNumber(cups, 'how many cups');\n       *\n       * @name isNumber\n       * @param {Number} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isNumber = function (val, msg) {\n        new Assertion(val, msg).to.be.a('number');\n      };\n\n      /**\n       * ### .isNotNumber(value, [message])\n       *\n       * Asserts that `value` is _not_ a number.\n       *\n       *     var cups = '2 cups please';\n       *     assert.isNotNumber(cups, 'how many cups');\n       *\n       * @name isNotNumber\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isNotNumber = function (val, msg) {\n        new Assertion(val, msg).to.not.be.a('number');\n      };\n\n      /**\n       * ### .isBoolean(value, [message])\n       *\n       * Asserts that `value` is a boolean.\n       *\n       *     var teaReady = true\n       *       , teaServed = false;\n       *\n       *     assert.isBoolean(teaReady, 'is the tea ready');\n       *     assert.isBoolean(teaServed, 'has tea been served');\n       *\n       * @name isBoolean\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isBoolean = function (val, msg) {\n        new Assertion(val, msg).to.be.a('boolean');\n      };\n\n      /**\n       * ### .isNotBoolean(value, [message])\n       *\n       * Asserts that `value` is _not_ a boolean.\n       *\n       *     var teaReady = 'yep'\n       *       , teaServed = 'nope';\n       *\n       *     assert.isNotBoolean(teaReady, 'is the tea ready');\n       *     assert.isNotBoolean(teaServed, 'has tea been served');\n       *\n       * @name isNotBoolean\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.isNotBoolean = function (val, msg) {\n        new Assertion(val, msg).to.not.be.a('boolean');\n      };\n\n      /**\n       * ### .typeOf(value, name, [message])\n       *\n       * Asserts that `value`'s type is `name`, as determined by\n       * `Object.prototype.toString`.\n       *\n       *     assert.typeOf({ tea: 'chai' }, 'object', 'we have an object');\n       *     assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array');\n       *     assert.typeOf('tea', 'string', 'we have a string');\n       *     assert.typeOf(/tea/, 'regexp', 'we have a regular expression');\n       *     assert.typeOf(null, 'null', 'we have a null');\n       *     assert.typeOf(undefined, 'undefined', 'we have an undefined');\n       *\n       * @name typeOf\n       * @param {Mixed} value\n       * @param {String} name\n       * @param {String} message\n       * @api public\n       */\n\n      assert.typeOf = function (val, type, msg) {\n        new Assertion(val, msg).to.be.a(type);\n      };\n\n      /**\n       * ### .notTypeOf(value, name, [message])\n       *\n       * Asserts that `value`'s type is _not_ `name`, as determined by\n       * `Object.prototype.toString`.\n       *\n       *     assert.notTypeOf('tea', 'number', 'strings are not numbers');\n       *\n       * @name notTypeOf\n       * @param {Mixed} value\n       * @param {String} typeof name\n       * @param {String} message\n       * @api public\n       */\n\n      assert.notTypeOf = function (val, type, msg) {\n        new Assertion(val, msg).to.not.be.a(type);\n      };\n\n      /**\n       * ### .instanceOf(object, constructor, [message])\n       *\n       * Asserts that `value` is an instance of `constructor`.\n       *\n       *     var Tea = function (name) { this.name = name; }\n       *       , chai = new Tea('chai');\n       *\n       *     assert.instanceOf(chai, Tea, 'chai is an instance of tea');\n       *\n       * @name instanceOf\n       * @param {Object} object\n       * @param {Constructor} constructor\n       * @param {String} message\n       * @api public\n       */\n\n      assert.instanceOf = function (val, type, msg) {\n        new Assertion(val, msg).to.be.instanceOf(type);\n      };\n\n      /**\n       * ### .notInstanceOf(object, constructor, [message])\n       *\n       * Asserts `value` is not an instance of `constructor`.\n       *\n       *     var Tea = function (name) { this.name = name; }\n       *       , chai = new String('chai');\n       *\n       *     assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea');\n       *\n       * @name notInstanceOf\n       * @param {Object} object\n       * @param {Constructor} constructor\n       * @param {String} message\n       * @api public\n       */\n\n      assert.notInstanceOf = function (val, type, msg) {\n        new Assertion(val, msg).to.not.be.instanceOf(type);\n      };\n\n      /**\n       * ### .include(haystack, needle, [message])\n       *\n       * Asserts that `haystack` includes `needle`. Works\n       * for strings and arrays.\n       *\n       *     assert.include('foobar', 'bar', 'foobar contains string \"bar\"');\n       *     assert.include([ 1, 2, 3 ], 3, 'array contains value');\n       *\n       * @name include\n       * @param {Array|String} haystack\n       * @param {Mixed} needle\n       * @param {String} message\n       * @api public\n       */\n\n      assert.include = function (exp, inc, msg) {\n        var obj = new Assertion(exp, msg);\n\n        if (Array.isArray(exp)) {\n          obj.to.include(inc);\n        } else if ('string' === typeof exp) {\n          obj.to.contain.string(inc);\n        }\n      };\n\n      /**\n       * ### .match(value, regexp, [message])\n       *\n       * Asserts that `value` matches the regular expression `regexp`.\n       *\n       *     assert.match('foobar', /^foo/, 'regexp matches');\n       *\n       * @name match\n       * @param {Mixed} value\n       * @param {RegExp} regexp\n       * @param {String} message\n       * @api public\n       */\n\n      assert.match = function (exp, re, msg) {\n        new Assertion(exp, msg).to.match(re);\n      };\n\n      /**\n       * ### .notMatch(value, regexp, [message])\n       *\n       * Asserts that `value` does not match the regular expression `regexp`.\n       *\n       *     assert.notMatch('foobar', /^foo/, 'regexp does not match');\n       *\n       * @name notMatch\n       * @param {Mixed} value\n       * @param {RegExp} regexp\n       * @param {String} message\n       * @api public\n       */\n\n      assert.notMatch = function (exp, re, msg) {\n        new Assertion(exp, msg).to.not.match(re);\n      };\n\n      /**\n       * ### .property(object, property, [message])\n       *\n       * Asserts that `object` has a property named by `property`.\n       *\n       *     assert.property({ tea: { green: 'matcha' }}, 'tea');\n       *\n       * @name property\n       * @param {Object} object\n       * @param {String} property\n       * @param {String} message\n       * @api public\n       */\n\n      assert.property = function (obj, prop, msg) {\n        new Assertion(obj, msg).to.have.property(prop);\n      };\n\n      /**\n       * ### .notProperty(object, property, [message])\n       *\n       * Asserts that `object` does _not_ have a property named by `property`.\n       *\n       *     assert.notProperty({ tea: { green: 'matcha' }}, 'coffee');\n       *\n       * @name notProperty\n       * @param {Object} object\n       * @param {String} property\n       * @param {String} message\n       * @api public\n       */\n\n      assert.notProperty = function (obj, prop, msg) {\n        new Assertion(obj, msg).to.not.have.property(prop);\n      };\n\n      /**\n       * ### .deepProperty(object, property, [message])\n       *\n       * Asserts that `object` has a property named by `property`, which can be a\n       * string using dot- and bracket-notation for deep reference.\n       *\n       *     assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green');\n       *\n       * @name deepProperty\n       * @param {Object} object\n       * @param {String} property\n       * @param {String} message\n       * @api public\n       */\n\n      assert.deepProperty = function (obj, prop, msg) {\n        new Assertion(obj, msg).to.have.deep.property(prop);\n      };\n\n      /**\n       * ### .notDeepProperty(object, property, [message])\n       *\n       * Asserts that `object` does _not_ have a property named by `property`, which\n       * can be a string using dot- and bracket-notation for deep reference.\n       *\n       *     assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong');\n       *\n       * @name notDeepProperty\n       * @param {Object} object\n       * @param {String} property\n       * @param {String} message\n       * @api public\n       */\n\n      assert.notDeepProperty = function (obj, prop, msg) {\n        new Assertion(obj, msg).to.not.have.deep.property(prop);\n      };\n\n      /**\n       * ### .propertyVal(object, property, value, [message])\n       *\n       * Asserts that `object` has a property named by `property` with value given\n       * by `value`.\n       *\n       *     assert.propertyVal({ tea: 'is good' }, 'tea', 'is good');\n       *\n       * @name propertyVal\n       * @param {Object} object\n       * @param {String} property\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.propertyVal = function (obj, prop, val, msg) {\n        new Assertion(obj, msg).to.have.property(prop, val);\n      };\n\n      /**\n       * ### .propertyNotVal(object, property, value, [message])\n       *\n       * Asserts that `object` has a property named by `property`, but with a value\n       * different from that given by `value`.\n       *\n       *     assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad');\n       *\n       * @name propertyNotVal\n       * @param {Object} object\n       * @param {String} property\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.propertyNotVal = function (obj, prop, val, msg) {\n        new Assertion(obj, msg).to.not.have.property(prop, val);\n      };\n\n      /**\n       * ### .deepPropertyVal(object, property, value, [message])\n       *\n       * Asserts that `object` has a property named by `property` with value given\n       * by `value`. `property` can use dot- and bracket-notation for deep\n       * reference.\n       *\n       *     assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha');\n       *\n       * @name deepPropertyVal\n       * @param {Object} object\n       * @param {String} property\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.deepPropertyVal = function (obj, prop, val, msg) {\n        new Assertion(obj, msg).to.have.deep.property(prop, val);\n      };\n\n      /**\n       * ### .deepPropertyNotVal(object, property, value, [message])\n       *\n       * Asserts that `object` has a property named by `property`, but with a value\n       * different from that given by `value`. `property` can use dot- and\n       * bracket-notation for deep reference.\n       *\n       *     assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha');\n       *\n       * @name deepPropertyNotVal\n       * @param {Object} object\n       * @param {String} property\n       * @param {Mixed} value\n       * @param {String} message\n       * @api public\n       */\n\n      assert.deepPropertyNotVal = function (obj, prop, val, msg) {\n        new Assertion(obj, msg).to.not.have.deep.property(prop, val);\n      };\n\n      /**\n       * ### .lengthOf(object, length, [message])\n       *\n       * Asserts that `object` has a `length` property with the expected value.\n       *\n       *     assert.lengthOf([1,2,3], 3, 'array has length of 3');\n       *     assert.lengthOf('foobar', 5, 'string has length of 6');\n       *\n       * @name lengthOf\n       * @param {Mixed} object\n       * @param {Number} length\n       * @param {String} message\n       * @api public\n       */\n\n      assert.lengthOf = function (exp, len, msg) {\n        new Assertion(exp, msg).to.have.length(len);\n      };\n\n      /**\n       * ### .throws(function, [constructor/string/regexp], [string/regexp], [message])\n       *\n       * Asserts that `function` will throw an error that is an instance of\n       * `constructor`, or alternately that it will throw an error with message\n       * matching `regexp`.\n       *\n       *     assert.throw(fn, 'function throws a reference error');\n       *     assert.throw(fn, /function throws a reference error/);\n       *     assert.throw(fn, ReferenceError);\n       *     assert.throw(fn, ReferenceError, 'function throws a reference error');\n       *     assert.throw(fn, ReferenceError, /function throws a reference error/);\n       *\n       * @name throws\n       * @alias throw\n       * @alias Throw\n       * @param {Function} function\n       * @param {ErrorConstructor} constructor\n       * @param {RegExp} regexp\n       * @param {String} message\n       * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types\n       * @api public\n       */\n\n      assert.Throw = function (fn, errt, errs, msg) {\n        if ('string' === typeof errt || errt instanceof RegExp) {\n          errs = errt;\n          errt = null;\n        }\n\n        new Assertion(fn, msg).to.Throw(errt, errs);\n      };\n\n      /**\n       * ### .doesNotThrow(function, [constructor/regexp], [message])\n       *\n       * Asserts that `function` will _not_ throw an error that is an instance of\n       * `constructor`, or alternately that it will not throw an error with message\n       * matching `regexp`.\n       *\n       *     assert.doesNotThrow(fn, Error, 'function does not throw');\n       *\n       * @name doesNotThrow\n       * @param {Function} function\n       * @param {ErrorConstructor} constructor\n       * @param {RegExp} regexp\n       * @param {String} message\n       * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types\n       * @api public\n       */\n\n      assert.doesNotThrow = function (fn, type, msg) {\n        if ('string' === typeof type) {\n          msg = type;\n          type = null;\n        }\n\n        new Assertion(fn, msg).to.not.Throw(type);\n      };\n\n      /**\n       * ### .operator(val1, operator, val2, [message])\n       *\n       * Compares two values using `operator`.\n       *\n       *     assert.operator(1, '<', 2, 'everything is ok');\n       *     assert.operator(1, '>', 2, 'this will fail');\n       *\n       * @name operator\n       * @param {Mixed} val1\n       * @param {String} operator\n       * @param {Mixed} val2\n       * @param {String} message\n       * @api public\n       */\n\n      assert.operator = function (val, operator, val2, msg) {\n        if (!~['==', '===', '>', '>=', '<', '<=', '!=', '!=='].indexOf(operator)) {\n          throw new Error('Invalid operator \"' + operator + '\"');\n        }\n        var test = new Assertion(eval(val + operator + val2), msg);\n        test.assert(\n            true === flag(test, 'object')\n          , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2)\n          , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) );\n      };\n\n      /**\n       * ### .closeTo(actual, expected, delta, [message])\n       *\n       * Asserts that the target is equal `expected`, to within a +/- `delta` range.\n       *\n       *     assert.closeTo(1.5, 1, 0.5, 'numbers are close');\n       *\n       * @name closeTo\n       * @param {Number} actual\n       * @param {Number} expected\n       * @param {Number} delta\n       * @param {String} message\n       * @api public\n       */\n\n      assert.closeTo = function (act, exp, delta, msg) {\n        new Assertion(act, msg).to.be.closeTo(exp, delta);\n      };\n\n      /*!\n       * Undocumented / untested\n       */\n\n      assert.ifError = function (val, msg) {\n        new Assertion(val, msg).to.not.be.ok;\n      };\n\n      /*!\n       * Aliases.\n       */\n\n      (function alias(name, as){\n        assert[as] = assert[name];\n        return alias;\n      })\n      ('Throw', 'throw')\n      ('Throw', 'throws');\n    };\n\n  }); // module: chai/interface/assert.js\n\n  require.register(\"chai/interface/expect.js\", function(module, exports, require){\n    /*!\n     * chai\n     * Copyright(c) 2011-2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    module.exports = function (chai, util) {\n      chai.expect = function (val, message) {\n        return new chai.Assertion(val, message);\n      };\n    };\n\n\n  }); // module: chai/interface/expect.js\n\n  require.register(\"chai/interface/should.js\", function(module, exports, require){\n    /*!\n     * chai\n     * Copyright(c) 2011-2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    module.exports = function (chai, util) {\n      var Assertion = chai.Assertion;\n\n      function loadShould () {\n        // modify Object.prototype to have `should`\n        Object.defineProperty(Object.prototype, 'should',\n          {\n            set: function (value) {\n              // See https://github.com/chaijs/chai/issues/86: this makes\n              // `whatever.should = someValue` actually set `someValue`, which is\n              // especially useful for `global.should = require('chai').should()`.\n              //\n              // Note that we have to use [[DefineProperty]] instead of [[Put]]\n              // since otherwise we would trigger this very setter!\n              Object.defineProperty(this, 'should', {\n                value: value,\n                enumerable: true,\n                configurable: true,\n                writable: true\n              });\n            }\n          , get: function(){\n              if (this instanceof String || this instanceof Number) {\n                return new Assertion(this.constructor(this));\n              } else if (this instanceof Boolean) {\n                return new Assertion(this == true);\n              }\n              return new Assertion(this);\n            }\n          , configurable: true\n        });\n\n        var should = {};\n\n        should.equal = function (val1, val2, msg) {\n          new Assertion(val1, msg).to.equal(val2);\n        };\n\n        should.Throw = function (fn, errt, errs, msg) {\n          new Assertion(fn, msg).to.Throw(errt, errs);\n        };\n\n        should.exist = function (val, msg) {\n          new Assertion(val, msg).to.exist;\n        }\n\n        // negation\n        should.not = {}\n\n        should.not.equal = function (val1, val2, msg) {\n          new Assertion(val1, msg).to.not.equal(val2);\n        };\n\n        should.not.Throw = function (fn, errt, errs, msg) {\n          new Assertion(fn, msg).to.not.Throw(errt, errs);\n        };\n\n        should.not.exist = function (val, msg) {\n          new Assertion(val, msg).to.not.exist;\n        }\n\n        should['throw'] = should['Throw'];\n        should.not['throw'] = should.not['Throw'];\n\n        return should;\n      };\n\n      chai.should = loadShould;\n      chai.Should = loadShould;\n    };\n\n  }); // module: chai/interface/should.js\n\n  require.register(\"chai/utils/addChainableMethod.js\", function(module, exports, require){\n    /*!\n     * Chai - addChainingMethod utility\n     * Copyright(c) 2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /*!\n     * Module dependencies\n     */\n\n    var transferFlags = require('./transferFlags');\n\n    /**\n     * ### addChainableMethod (ctx, name, method, chainingBehavior)\n     *\n     * Adds a method to an object, such that the method can also be chained.\n     *\n     *     utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) {\n     *       var obj = utils.flag(this, 'object');\n     *       new chai.Assertion(obj).to.be.equal(str);\n     *     });\n     *\n     * Can also be accessed directly from `chai.Assertion`.\n     *\n     *     chai.Assertion.addChainableMethod('foo', fn, chainingBehavior);\n     *\n     * The result can then be used as both a method assertion, executing both `method` and\n     * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`.\n     *\n     *     expect(fooStr).to.be.foo('bar');\n     *     expect(fooStr).to.be.foo.equal('foo');\n     *\n     * @param {Object} ctx object to which the method is added\n     * @param {String} name of method to add\n     * @param {Function} method function to be used for `name`, when called\n     * @param {Function} chainingBehavior function to be called every time the property is accessed\n     * @name addChainableMethod\n     * @api public\n     */\n\n    module.exports = function (ctx, name, method, chainingBehavior) {\n      if (typeof chainingBehavior !== 'function')\n        chainingBehavior = function () { };\n\n      Object.defineProperty(ctx, name,\n        { get: function () {\n            chainingBehavior.call(this);\n\n            var assert = function () {\n              var result = method.apply(this, arguments);\n              return result === undefined ? this : result;\n            };\n\n            // Re-enumerate every time to better accomodate plugins.\n            var asserterNames = Object.getOwnPropertyNames(ctx);\n            asserterNames.forEach(function (asserterName) {\n              var pd = Object.getOwnPropertyDescriptor(ctx, asserterName)\n                , functionProtoPD = Object.getOwnPropertyDescriptor(Function.prototype, asserterName);\n              // Avoid trying to overwrite things that we can't, like `length` and `arguments`.\n              if (functionProtoPD && !functionProtoPD.configurable) return;\n              if (asserterName === 'arguments') return; // @see chaijs/chai/issues/69\n              Object.defineProperty(assert, asserterName, pd);\n            });\n\n            transferFlags(this, assert);\n            return assert;\n          }\n        , configurable: true\n      });\n    };\n\n  }); // module: chai/utils/addChainableMethod.js\n\n  require.register(\"chai/utils/addMethod.js\", function(module, exports, require){\n    /*!\n     * Chai - addMethod utility\n     * Copyright(c) 2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /**\n     * ### .addMethod (ctx, name, method)\n     *\n     * Adds a method to the prototype of an object.\n     *\n     *     utils.addMethod(chai.Assertion.prototype, 'foo', function (str) {\n     *       var obj = utils.flag(this, 'object');\n     *       new chai.Assertion(obj).to.be.equal(str);\n     *     });\n     *\n     * Can also be accessed directly from `chai.Assertion`.\n     *\n     *     chai.Assertion.addMethod('foo', fn);\n     *\n     * Then can be used as any other assertion.\n     *\n     *     expect(fooStr).to.be.foo('bar');\n     *\n     * @param {Object} ctx object to which the method is added\n     * @param {String} name of method to add\n     * @param {Function} method function to be used for name\n     * @name addMethod\n     * @api public\n     */\n\n    module.exports = function (ctx, name, method) {\n      ctx[name] = function () {\n        var result = method.apply(this, arguments);\n        return result === undefined ? this : result;\n      };\n    };\n\n  }); // module: chai/utils/addMethod.js\n\n  require.register(\"chai/utils/addProperty.js\", function(module, exports, require){\n    /*!\n     * Chai - addProperty utility\n     * Copyright(c) 2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /**\n     * ### addProperty (ctx, name, getter)\n     *\n     * Adds a property to the prototype of an object.\n     *\n     *     utils.addProperty(chai.Assertion.prototype, 'foo', function () {\n     *       var obj = utils.flag(this, 'object');\n     *       new chai.Assertion(obj).to.be.instanceof(Foo);\n     *     });\n     *\n     * Can also be accessed directly from `chai.Assertion`.\n     *\n     *     chai.Assertion.addProperty('foo', fn);\n     *\n     * Then can be used as any other assertion.\n     *\n     *     expect(myFoo).to.be.foo;\n     *\n     * @param {Object} ctx object to which the property is added\n     * @param {String} name of property to add\n     * @param {Function} getter function to be used for name\n     * @name addProperty\n     * @api public\n     */\n\n    module.exports = function (ctx, name, getter) {\n      Object.defineProperty(ctx, name,\n        { get: function () {\n            var result = getter.call(this);\n            return result === undefined ? this : result;\n          }\n        , configurable: true\n      });\n    };\n\n  }); // module: chai/utils/addProperty.js\n\n  require.register(\"chai/utils/eql.js\", function(module, exports, require){\n    // This is (almost) directly from Node.js assert\n    // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/assert.js\n\n    module.exports = _deepEqual;\n\n    // for the browser\n    var Buffer;\n    try {\n      Buffer = require('buffer').Buffer;\n    } catch (ex) {\n      Buffer = {\n        isBuffer: function () { return false; }\n      };\n    }\n\n    function _deepEqual(actual, expected, memos) {\n\n      // 7.1. All identical values are equivalent, as determined by ===.\n      if (actual === expected) {\n        return true;\n\n      } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {\n        if (actual.length != expected.length) return false;\n\n        for (var i = 0; i < actual.length; i++) {\n          if (actual[i] !== expected[i]) return false;\n        }\n\n        return true;\n\n      // 7.2. If the expected value is a Date object, the actual value is\n      // equivalent if it is also a Date object that refers to the same time.\n      } else if (actual instanceof Date && expected instanceof Date) {\n        return actual.getTime() === expected.getTime();\n\n      // 7.3. Other pairs that do not both pass typeof value == 'object',\n      // equivalence is determined by ==.\n      } else if (typeof actual != 'object' && typeof expected != 'object') {\n        return actual === expected;\n\n      // 7.4. For all other Object pairs, including Array objects, equivalence is\n      // determined by having the same number of owned properties (as verified\n      // with Object.prototype.hasOwnProperty.call), the same set of keys\n      // (although not necessarily the same order), equivalent values for every\n      // corresponding key, and an identical 'prototype' property. Note: this\n      // accounts for both named and indexed properties on Arrays.\n      } else {\n        return objEquiv(actual, expected, memos);\n      }\n    }\n\n    function isUndefinedOrNull(value) {\n      return value === null || value === undefined;\n    }\n\n    function isArguments(object) {\n      return Object.prototype.toString.call(object) == '[object Arguments]';\n    }\n\n    function objEquiv(a, b, memos) {\n      if (isUndefinedOrNull(a) || isUndefinedOrNull(b))\n        return false;\n\n      // an identical 'prototype' property.\n      if (a.prototype !== b.prototype) return false;\n\n      // check if we have already compared a and b\n      var i;\n      if (memos) {\n        for(i = 0; i < memos.length; i++) {\n          if ((memos[i][0] === a && memos[i][1] === b) ||\n              (memos[i][0] === b && memos[i][1] === a))\n            return true;\n        }\n      } else {\n        memos = [];\n      }\n\n      //~~~I've managed to break Object.keys through screwy arguments passing.\n      //   Converting to array solves the problem.\n      if (isArguments(a)) {\n        if (!isArguments(b)) {\n          return false;\n        }\n        a = pSlice.call(a);\n        b = pSlice.call(b);\n        return _deepEqual(a, b, memos);\n      }\n      try {\n        var ka = Object.keys(a),\n            kb = Object.keys(b),\n            key;\n      } catch (e) {//happens when one is a string literal and the other isn't\n        return false;\n      }\n\n      // having the same number of owned properties (keys incorporates\n      // hasOwnProperty)\n      if (ka.length != kb.length)\n        return false;\n\n      //the same set of keys (although not necessarily the same order),\n      ka.sort();\n      kb.sort();\n      //~~~cheap key test\n      for (i = ka.length - 1; i >= 0; i--) {\n        if (ka[i] != kb[i])\n          return false;\n      }\n\n      // remember objects we have compared to guard against circular references\n      memos.push([ a, b ]);\n\n      //equivalent values for every corresponding key, and\n      //~~~possibly expensive deep test\n      for (i = ka.length - 1; i >= 0; i--) {\n        key = ka[i];\n        if (!_deepEqual(a[key], b[key], memos)) return false;\n      }\n\n      return true;\n    }\n\n  }); // module: chai/utils/eql.js\n\n  require.register(\"chai/utils/flag.js\", function(module, exports, require){\n    /*!\n     * Chai - flag utility\n     * Copyright(c) 2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /**\n     * ### flag(object ,key, [value])\n     *\n     * Get or set a flag value on an object. If a\n     * value is provided it will be set, else it will\n     * return the currently set value or `undefined` if\n     * the value is not set.\n     *\n     *     utils.flag(this, 'foo', 'bar'); // setter\n     *     utils.flag(this, 'foo'); // getter, returns `bar`\n     *\n     * @param {Object} object (constructed Assertion\n     * @param {String} key\n     * @param {Mixed} value (optional)\n     * @name flag\n     * @api private\n     */\n\n    module.exports = function (obj, key, value) {\n      var flags = obj.__flags || (obj.__flags = Object.create(null));\n      if (arguments.length === 3) {\n        flags[key] = value;\n      } else {\n        return flags[key];\n      }\n    };\n\n  }); // module: chai/utils/flag.js\n\n  require.register(\"chai/utils/getActual.js\", function(module, exports, require){\n    /*!\n     * Chai - getActual utility\n     * Copyright(c) 2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /**\n     * # getActual(object, [actual])\n     *\n     * Returns the `actual` value for an Assertion\n     *\n     * @param {Object} object (constructed Assertion)\n     * @param {Arguments} chai.Assertion.prototype.assert arguments\n     */\n\n    module.exports = function (obj, args) {\n      var actual = args[4];\n      return 'undefined' !== typeof actual ? actual : obj._obj;\n    };\n\n  }); // module: chai/utils/getActual.js\n\n  require.register(\"chai/utils/getMessage.js\", function(module, exports, require){\n    /*!\n     * Chai - message composition utility\n     * Copyright(c) 2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /*!\n     * Module dependancies\n     */\n\n    var flag = require('./flag')\n      , getActual = require('./getActual')\n      , inspect = require('./inspect')\n      , objDisplay = require('./objDisplay');\n\n    /**\n     * ### .getMessage(object, message, negateMessage)\n     *\n     * Construct the error message based on flags\n     * and template tags. Template tags will return\n     * a stringified inspection of the object referenced.\n     *\n     * Messsage template tags:\n     * - `#{this}` current asserted object\n     * - `#{act}` actual value\n     * - `#{exp}` expected value\n     *\n     * @param {Object} object (constructed Assertion)\n     * @param {Arguments} chai.Assertion.prototype.assert arguments\n     * @name getMessage\n     * @api public\n     */\n\n    module.exports = function (obj, args) {\n      var negate = flag(obj, 'negate')\n        , val = flag(obj, 'object')\n        , expected = args[3]\n        , actual = getActual(obj, args)\n        , msg = negate ? args[2] : args[1]\n        , flagMsg = flag(obj, 'message');\n\n      msg = msg || '';\n      msg = msg\n        .replace(/#{this}/g, objDisplay(val))\n        .replace(/#{act}/g, objDisplay(actual))\n        .replace(/#{exp}/g, objDisplay(expected));\n\n      return flagMsg ? flagMsg + ': ' + msg : msg;\n    };\n\n  }); // module: chai/utils/getMessage.js\n\n  require.register(\"chai/utils/getName.js\", function(module, exports, require){\n    /*!\n     * Chai - getName utility\n     * Copyright(c) 2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /**\n     * # getName(func)\n     *\n     * Gets the name of a function, in a cross-browser way.\n     *\n     * @param {Function} a function (usually a constructor)\n     */\n\n    module.exports = function (func) {\n      if (func.name) return func.name;\n\n      var match = /^\\s?function ([^(]*)\\(/.exec(func);\n      return match && match[1] ? match[1] : \"\";\n    };\n\n  }); // module: chai/utils/getName.js\n\n  require.register(\"chai/utils/getPathValue.js\", function(module, exports, require){\n    /*!\n     * Chai - getPathValue utility\n     * Copyright(c) 2012 Jake Luer <jake@alogicalparadox.com>\n     * @see https://github.com/logicalparadox/filtr\n     * MIT Licensed\n     */\n\n    /**\n     * ### .getPathValue(path, object)\n     *\n     * This allows the retrieval of values in an\n     * object given a string path.\n     *\n     *     var obj = {\n     *         prop1: {\n     *             arr: ['a', 'b', 'c']\n     *           , str: 'Hello'\n     *         }\n     *       , prop2: {\n     *             arr: [ { nested: 'Universe' } ]\n     *           , str: 'Hello again!'\n     *         }\n     *     }\n     *\n     * The following would be the results.\n     *\n     *     getPathValue('prop1.str', obj); // Hello\n     *     getPathValue('prop1.att[2]', obj); // b\n     *     getPathValue('prop2.arr[0].nested', obj); // Universe\n     *\n     * @param {String} path\n     * @param {Object} object\n     * @returns {Object} value or `undefined`\n     * @name getPathValue\n     * @api public\n     */\n\n    var getPathValue = module.exports = function (path, obj) {\n      var parsed = parsePath(path);\n      return _getPathValue(parsed, obj);\n    };\n\n    /*!\n     * ## parsePath(path)\n     *\n     * Helper function used to parse string object\n     * paths. Use in conjunction with `_getPathValue`.\n     *\n     *      var parsed = parsePath('myobject.property.subprop');\n     *\n     * ### Paths:\n     *\n     * * Can be as near infinitely deep and nested\n     * * Arrays are also valid using the formal `myobject.document[3].property`.\n     *\n     * @param {String} path\n     * @returns {Object} parsed\n     * @api private\n     */\n\n    function parsePath (path) {\n      var str = path.replace(/\\[/g, '.[')\n        , parts = str.match(/(\\\\\\.|[^.]+?)+/g);\n      return parts.map(function (value) {\n        var re = /\\[(\\d+)\\]$/\n          , mArr = re.exec(value)\n        if (mArr) return { i: parseFloat(mArr[1]) };\n        else return { p: value };\n      });\n    };\n\n    /*!\n     * ## _getPathValue(parsed, obj)\n     *\n     * Helper companion function for `.parsePath` that returns\n     * the value located at the parsed address.\n     *\n     *      var value = getPathValue(parsed, obj);\n     *\n     * @param {Object} parsed definition from `parsePath`.\n     * @param {Object} object to search against\n     * @returns {Object|Undefined} value\n     * @api private\n     */\n\n    function _getPathValue (parsed, obj) {\n      var tmp = obj\n        , res;\n      for (var i = 0, l = parsed.length; i < l; i++) {\n        var part = parsed[i];\n        if (tmp) {\n          if ('undefined' !== typeof part.p)\n            tmp = tmp[part.p];\n          else if ('undefined' !== typeof part.i)\n            tmp = tmp[part.i];\n          if (i == (l - 1)) res = tmp;\n        } else {\n          res = undefined;\n        }\n      }\n      return res;\n    };\n\n  }); // module: chai/utils/getPathValue.js\n\n  require.register(\"chai/utils/index.js\", function(module, exports, require){\n    /*!\n     * chai\n     * Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /*!\n     * Main exports\n     */\n\n    var exports = module.exports = {};\n\n    /*!\n     * test utility\n     */\n\n    exports.test = require('./test');\n\n    /*!\n     * message utility\n     */\n\n    exports.getMessage = require('./getMessage');\n\n    /*!\n     * actual utility\n     */\n\n    exports.getActual = require('./getActual');\n\n    /*!\n     * Inspect util\n     */\n\n    exports.inspect = require('./inspect');\n\n    /*!\n     * Object Display util\n     */\n\n    exports.objDisplay = require('./objDisplay');\n\n    /*!\n     * Flag utility\n     */\n\n    exports.flag = require('./flag');\n\n    /*!\n     * Flag transferring utility\n     */\n\n    exports.transferFlags = require('./transferFlags');\n\n    /*!\n     * Deep equal utility\n     */\n\n    exports.eql = require('./eql');\n\n    /*!\n     * Deep path value\n     */\n\n    exports.getPathValue = require('./getPathValue');\n\n    /*!\n     * Function name\n     */\n\n    exports.getName = require('./getName');\n\n    /*!\n     * add Property\n     */\n\n    exports.addProperty = require('./addProperty');\n\n    /*!\n     * add Method\n     */\n\n    exports.addMethod = require('./addMethod');\n\n    /*!\n     * overwrite Property\n     */\n\n    exports.overwriteProperty = require('./overwriteProperty');\n\n    /*!\n     * overwrite Method\n     */\n\n    exports.overwriteMethod = require('./overwriteMethod');\n\n    /*!\n     * Add a chainable method\n     */\n\n    exports.addChainableMethod = require('./addChainableMethod');\n\n\n  }); // module: chai/utils/index.js\n\n  require.register(\"chai/utils/inspect.js\", function(module, exports, require){\n    // This is (almost) directly from Node.js utils\n    // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js\n\n    var getName = require('./getName');\n\n    module.exports = inspect;\n\n    /**\n     * Echos the value of a value. Trys to print the value out\n     * in the best way possible given the different types.\n     *\n     * @param {Object} obj The object to print out.\n     * @param {Boolean} showHidden Flag that shows hidden (not enumerable)\n     *    properties of objects.\n     * @param {Number} depth Depth in which to descend in object. Default is 2.\n     * @param {Boolean} colors Flag to turn on ANSI escape codes to color the\n     *    output. Default is false (no coloring).\n     */\n    function inspect(obj, showHidden, depth, colors) {\n      var ctx = {\n        showHidden: showHidden,\n        seen: [],\n        stylize: function (str) { return str; }\n      };\n      return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth));\n    }\n\n    // https://gist.github.com/1044128/\n    var getOuterHTML = function(element) {\n      if ('outerHTML' in element) return element.outerHTML;\n      var ns = \"http://www.w3.org/1999/xhtml\";\n      var container = document.createElementNS(ns, '_');\n      var elemProto = (window.HTMLElement || window.Element).prototype;\n      var xmlSerializer = new XMLSerializer();\n      var html;\n      if (document.xmlVersion) {\n        return xmlSerializer.serializeToString(element);\n      } else {\n        container.appendChild(element.cloneNode(false));\n        html = container.innerHTML.replace('><', '>' + element.innerHTML + '<');\n        container.innerHTML = '';\n        return html;\n      }\n    };\n      \n    // Returns true if object is a DOM element.\n    var isDOMElement = function (object) {\n      if (typeof HTMLElement === 'object') {\n        return object instanceof HTMLElement;\n      } else {\n        return object &&\n          typeof object === 'object' &&\n          object.nodeType === 1 &&\n          typeof object.nodeName === 'string';\n      }\n    };\n\n    function formatValue(ctx, value, recurseTimes) {\n      // Provide a hook for user-specified inspect functions.\n      // Check that value is an object with an inspect function on it\n      if (value && typeof value.inspect === 'function' &&\n          // Filter out the util module, it's inspect function is special\n          value.inspect !== exports.inspect &&\n          // Also filter out any prototype objects using the circular check.\n          !(value.constructor && value.constructor.prototype === value)) {\n        return value.inspect(recurseTimes);\n      }\n\n      // Primitive types cannot have properties\n      var primitive = formatPrimitive(ctx, value);\n      if (primitive) {\n        return primitive;\n      }\n\n      // If it's DOM elem, get outer HTML.\n      if (isDOMElement(value)) {\n        return getOuterHTML(value);\n      }\n\n      // Look up the keys of the object.\n      var visibleKeys = Object.keys(value);\n      var keys = ctx.showHidden ? Object.getOwnPropertyNames(value) : visibleKeys;\n\n      // Some type of object without properties can be shortcutted.\n      // In IE, errors have a single `stack` property, or if they are vanilla `Error`,\n      // a `stack` plus `description` property; ignore those for consistency.\n      if (keys.length === 0 || (isError(value) && (\n          (keys.length === 1 && keys[0] === 'stack') ||\n          (keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack')\n         ))) {\n        if (typeof value === 'function') {\n          var name = getName(value);\n          var nameSuffix = name ? ': ' + name : '';\n          return ctx.stylize('[Function' + nameSuffix + ']', 'special');\n        }\n        if (isRegExp(value)) {\n          return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n        }\n        if (isDate(value)) {\n          return ctx.stylize(Date.prototype.toUTCString.call(value), 'date');\n        }\n        if (isError(value)) {\n          return formatError(value);\n        }\n      }\n\n      var base = '', array = false, braces = ['{', '}'];\n\n      // Make Array say that they are Array\n      if (isArray(value)) {\n        array = true;\n        braces = ['[', ']'];\n      }\n\n      // Make functions say that they are functions\n      if (typeof value === 'function') {\n        var name = getName(value);\n        var nameSuffix = name ? ': ' + name : '';\n        base = ' [Function' + nameSuffix + ']';\n      }\n\n      // Make RegExps say that they are RegExps\n      if (isRegExp(value)) {\n        base = ' ' + RegExp.prototype.toString.call(value);\n      }\n\n      // Make dates with properties first say the date\n      if (isDate(value)) {\n        base = ' ' + Date.prototype.toUTCString.call(value);\n      }\n\n      // Make error with message first say the error\n      if (isError(value)) {\n        return formatError(value);\n      }\n\n      if (keys.length === 0 && (!array || value.length == 0)) {\n        return braces[0] + base + braces[1];\n      }\n\n      if (recurseTimes < 0) {\n        if (isRegExp(value)) {\n          return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n        } else {\n          return ctx.stylize('[Object]', 'special');\n        }\n      }\n\n      ctx.seen.push(value);\n\n      var output;\n      if (array) {\n        output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n      } else {\n        output = keys.map(function(key) {\n          return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n        });\n      }\n\n      ctx.seen.pop();\n\n      return reduceToSingleString(output, base, braces);\n    }\n\n\n    function formatPrimitive(ctx, value) {\n      switch (typeof value) {\n        case 'undefined':\n          return ctx.stylize('undefined', 'undefined');\n\n        case 'string':\n          var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                                   .replace(/'/g, \"\\\\'\")\n                                                   .replace(/\\\\\"/g, '\"') + '\\'';\n          return ctx.stylize(simple, 'string');\n\n        case 'number':\n          return ctx.stylize('' + value, 'number');\n\n        case 'boolean':\n          return ctx.stylize('' + value, 'boolean');\n      }\n      // For some reason typeof null is \"object\", so special case here.\n      if (value === null) {\n        return ctx.stylize('null', 'null');\n      }\n    }\n\n\n    function formatError(value) {\n      return '[' + Error.prototype.toString.call(value) + ']';\n    }\n\n\n    function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n      var output = [];\n      for (var i = 0, l = value.length; i < l; ++i) {\n        if (Object.prototype.hasOwnProperty.call(value, String(i))) {\n          output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n              String(i), true));\n        } else {\n          output.push('');\n        }\n      }\n      keys.forEach(function(key) {\n        if (!key.match(/^\\d+$/)) {\n          output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n              key, true));\n        }\n      });\n      return output;\n    }\n\n\n    function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n      var name, str;\n      if (value.__lookupGetter__) {\n        if (value.__lookupGetter__(key)) {\n          if (value.__lookupSetter__(key)) {\n            str = ctx.stylize('[Getter/Setter]', 'special');\n          } else {\n            str = ctx.stylize('[Getter]', 'special');\n          }\n        } else {\n          if (value.__lookupSetter__(key)) {\n            str = ctx.stylize('[Setter]', 'special');\n          }\n        }\n      }\n      if (visibleKeys.indexOf(key) < 0) {\n        name = '[' + key + ']';\n      }\n      if (!str) {\n        if (ctx.seen.indexOf(value[key]) < 0) {\n          if (recurseTimes === null) {\n            str = formatValue(ctx, value[key], null);\n          } else {\n            str = formatValue(ctx, value[key], recurseTimes - 1);\n          }\n          if (str.indexOf('\\n') > -1) {\n            if (array) {\n              str = str.split('\\n').map(function(line) {\n                return '  ' + line;\n              }).join('\\n').substr(2);\n            } else {\n              str = '\\n' + str.split('\\n').map(function(line) {\n                return '   ' + line;\n              }).join('\\n');\n            }\n          }\n        } else {\n          str = ctx.stylize('[Circular]', 'special');\n        }\n      }\n      if (typeof name === 'undefined') {\n        if (array && key.match(/^\\d+$/)) {\n          return str;\n        }\n        name = JSON.stringify('' + key);\n        if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n          name = name.substr(1, name.length - 2);\n          name = ctx.stylize(name, 'name');\n        } else {\n          name = name.replace(/'/g, \"\\\\'\")\n                     .replace(/\\\\\"/g, '\"')\n                     .replace(/(^\"|\"$)/g, \"'\");\n          name = ctx.stylize(name, 'string');\n        }\n      }\n\n      return name + ': ' + str;\n    }\n\n\n    function reduceToSingleString(output, base, braces) {\n      var numLinesEst = 0;\n      var length = output.reduce(function(prev, cur) {\n        numLinesEst++;\n        if (cur.indexOf('\\n') >= 0) numLinesEst++;\n        return prev + cur.length + 1;\n      }, 0);\n\n      if (length > 60) {\n        return braces[0] +\n               (base === '' ? '' : base + '\\n ') +\n               ' ' +\n               output.join(',\\n  ') +\n               ' ' +\n               braces[1];\n      }\n\n      return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n    }\n\n    function isArray(ar) {\n      return Array.isArray(ar) ||\n             (typeof ar === 'object' && objectToString(ar) === '[object Array]');\n    }\n\n    function isRegExp(re) {\n      return typeof re === 'object' && objectToString(re) === '[object RegExp]';\n    }\n\n    function isDate(d) {\n      return typeof d === 'object' && objectToString(d) === '[object Date]';\n    }\n\n    function isError(e) {\n      return typeof e === 'object' && objectToString(e) === '[object Error]';\n    }\n\n    function objectToString(o) {\n      return Object.prototype.toString.call(o);\n    }\n\n  }); // module: chai/utils/inspect.js\n\n  require.register(\"chai/utils/objDisplay.js\", function(module, exports, require){\n    /*!\n     * Chai - flag utility\n     * Copyright(c) 2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /*!\n     * Module dependancies\n     */\n\n    var inspect = require('./inspect');\n\n    /**\n     * ### .objDisplay (object)\n     *\n     * Determines if an object or an array matches\n     * criteria to be inspected in-line for error\n     * messages or should be truncated.\n     *\n     * @param {Mixed} javascript object to inspect\n     * @name objDisplay\n     * @api public\n     */\n\n    module.exports = function (obj) {\n      var str = inspect(obj)\n        , type = Object.prototype.toString.call(obj);\n\n      if (str.length >= 40) {\n        if (type === '[object Array]') {\n          return '[ Array(' + obj.length + ') ]';\n        } else if (type === '[object Object]') {\n          var keys = Object.keys(obj)\n            , kstr = keys.length > 2\n              ? keys.splice(0, 2).join(', ') + ', ...'\n              : keys.join(', ');\n          return '{ Object (' + kstr + ') }';\n        } else {\n          return str;\n        }\n      } else {\n        return str;\n      }\n    };\n\n  }); // module: chai/utils/objDisplay.js\n\n  require.register(\"chai/utils/overwriteMethod.js\", function(module, exports, require){\n    /*!\n     * Chai - overwriteMethod utility\n     * Copyright(c) 2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /**\n     * ### overwriteMethod (ctx, name, fn)\n     *\n     * Overwites an already existing method and provides\n     * access to previous function. Must return function\n     * to be used for name.\n     *\n     *     utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) {\n     *       return function (str) {\n     *         var obj = utils.flag(this, 'object');\n     *         if (obj instanceof Foo) {\n     *           new chai.Assertion(obj.value).to.equal(str);\n     *         } else {\n     *           _super.apply(this, arguments);\n     *         }\n     *       }\n     *     });\n     *\n     * Can also be accessed directly from `chai.Assertion`.\n     *\n     *     chai.Assertion.overwriteMethod('foo', fn);\n     *\n     * Then can be used as any other assertion.\n     *\n     *     expect(myFoo).to.equal('bar');\n     *\n     * @param {Object} ctx object whose method is to be overwritten\n     * @param {String} name of method to overwrite\n     * @param {Function} method function that returns a function to be used for name\n     * @name overwriteMethod\n     * @api public\n     */\n\n    module.exports = function (ctx, name, method) {\n      var _method = ctx[name]\n        , _super = function () { return this; };\n\n      if (_method && 'function' === typeof _method)\n        _super = _method;\n\n      ctx[name] = function () {\n        var result = method(_super).apply(this, arguments);\n        return result === undefined ? this : result;\n      }\n    };\n\n  }); // module: chai/utils/overwriteMethod.js\n\n  require.register(\"chai/utils/overwriteProperty.js\", function(module, exports, require){\n    /*!\n     * Chai - overwriteProperty utility\n     * Copyright(c) 2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /**\n     * ### overwriteProperty (ctx, name, fn)\n     *\n     * Overwites an already existing property getter and provides\n     * access to previous value. Must return function to use as getter.\n     *\n     *     utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) {\n     *       return function () {\n     *         var obj = utils.flag(this, 'object');\n     *         if (obj instanceof Foo) {\n     *           new chai.Assertion(obj.name).to.equal('bar');\n     *         } else {\n     *           _super.call(this);\n     *         }\n     *       }\n     *     });\n     *\n     *\n     * Can also be accessed directly from `chai.Assertion`.\n     *\n     *     chai.Assertion.overwriteProperty('foo', fn);\n     *\n     * Then can be used as any other assertion.\n     *\n     *     expect(myFoo).to.be.ok;\n     *\n     * @param {Object} ctx object whose property is to be overwritten\n     * @param {String} name of property to overwrite\n     * @param {Function} getter function that returns a getter function to be used for name\n     * @name overwriteProperty\n     * @api public\n     */\n\n    module.exports = function (ctx, name, getter) {\n      var _get = Object.getOwnPropertyDescriptor(ctx, name)\n        , _super = function () {};\n\n      if (_get && 'function' === typeof _get.get)\n        _super = _get.get\n\n      Object.defineProperty(ctx, name,\n        { get: function () {\n            var result = getter(_super).call(this);\n            return result === undefined ? this : result;\n          }\n        , configurable: true\n      });\n    };\n\n  }); // module: chai/utils/overwriteProperty.js\n\n  require.register(\"chai/utils/test.js\", function(module, exports, require){\n    /*!\n     * Chai - test utility\n     * Copyright(c) 2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /*!\n     * Module dependancies\n     */\n\n    var flag = require('./flag');\n\n    /**\n     * # test(object, expression)\n     *\n     * Test and object for expression.\n     *\n     * @param {Object} object (constructed Assertion)\n     * @param {Arguments} chai.Assertion.prototype.assert arguments\n     */\n\n    module.exports = function (obj, args) {\n      var negate = flag(obj, 'negate')\n        , expr = args[0];\n      return negate ? !expr : expr;\n    };\n\n  }); // module: chai/utils/test.js\n\n  require.register(\"chai/utils/transferFlags.js\", function(module, exports, require){\n    /*!\n     * Chai - transferFlags utility\n     * Copyright(c) 2012 Jake Luer <jake@alogicalparadox.com>\n     * MIT Licensed\n     */\n\n    /**\n     * ### transferFlags(assertion, object, includeAll = true)\n     *\n     * Transfer all the flags for `assertion` to `object`. If\n     * `includeAll` is set to `false`, then the base Chai\n     * assertion flags (namely `object`, `ssfi`, and `message`)\n     * will not be transferred.\n     *\n     *\n     *     var newAssertion = new Assertion();\n     *     utils.transferFlags(assertion, newAssertion);\n     *\n     *     var anotherAsseriton = new Assertion(myObj);\n     *     utils.transferFlags(assertion, anotherAssertion, false);\n     *\n     * @param {Assertion} assertion the assertion to transfer the flags from\n     * @param {Object} object the object to transfer the flags too; usually a new assertion\n     * @param {Boolean} includeAll\n     * @name getAllFlags\n     * @api private\n     */\n\n    module.exports = function (assertion, object, includeAll) {\n      var flags = assertion.__flags || (assertion.__flags = Object.create(null));\n\n      if (!object.__flags) {\n        object.__flags = Object.create(null);\n      }\n\n      includeAll = arguments.length === 3 ? includeAll : true;\n\n      for (var flag in flags) {\n        if (includeAll ||\n            (flag !== 'object' && flag !== 'ssfi' && flag != 'message')) {\n          object.__flags[flag] = flags[flag];\n        }\n      }\n    };\n\n  }); // module: chai/utils/transferFlags.js\n\n  require.alias(\"./chai.js\", \"chai\");\n\n  return require('chai');\n});"
  },
  {
    "path": "test/lib/expect.js",
    "content": "/*!\n * chai\n * Copyright(c) 2011-2012 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nmodule.exports = function (chai, util) {\n  chai.expect = function (val, message) {\n    return new chai.Assertion(val, message);\n  };\n};\n\n"
  },
  {
    "path": "test/lib/mocha/mocha.css",
    "content": "@charset \"utf-8\";\n\nbody {\n  font: 20px/1.5 \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  padding: 60px 50px;\n}\n\n#mocha ul, #mocha li {\n  margin: 0;\n  padding: 0;\n}\n\n#mocha ul {\n  list-style: none;\n}\n\n#mocha h1, #mocha h2 {\n  margin: 0;\n}\n\n#mocha h1 {\n  margin-top: 15px;\n  font-size: 1em;\n  font-weight: 200;\n}\n\n#mocha h1 a {\n  text-decoration: none;\n  color: inherit;\n}\n\n#mocha h1 a:hover {\n  text-decoration: underline;\n}\n\n#mocha .suite .suite h1 {\n  margin-top: 0;\n  font-size: .8em;\n}\n\n.hidden {\n  display: none;\n}\n\n#mocha h2 {\n  font-size: 12px;\n  font-weight: normal;\n  cursor: pointer;\n}\n\n#mocha .suite {\n  margin-left: 15px;\n}\n\n#mocha .test {\n  margin-left: 15px;\n  overflow: hidden;\n}\n\n#mocha .test.pending:hover h2::after {\n  content: '(pending)';\n  font-family: arial;\n}\n\n#mocha .test.pass.medium .duration {\n  background: #C09853;\n}\n\n#mocha .test.pass.slow .duration {\n  background: #B94A48;\n}\n\n#mocha .test.pass::before {\n  content: '✓';\n  font-size: 12px;\n  display: block;\n  float: left;\n  margin-right: 5px;\n  color: #00d6b2;\n}\n\n#mocha .test.pass .duration {\n  font-size: 9px;\n  margin-left: 5px;\n  padding: 2px 5px;\n  color: white;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);\n  -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);\n  box-shadow: inset 0 1px 1px rgba(0,0,0,.2);\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  -ms-border-radius: 5px;\n  -o-border-radius: 5px;\n  border-radius: 5px;\n}\n\n#mocha .test.pass.fast .duration {\n  display: none;\n}\n\n#mocha .test.pending {\n  color: #0b97c4;\n}\n\n#mocha .test.pending::before {\n  content: '◦';\n  color: #0b97c4;\n}\n\n#mocha .test.fail {\n  color: #c00;\n}\n\n#mocha .test.fail pre {\n  color: black;\n}\n\n#mocha .test.fail::before {\n  content: '✖';\n  font-size: 12px;\n  display: block;\n  float: left;\n  margin-right: 5px;\n  color: #c00;\n}\n\n#mocha .test pre.error {\n  color: #c00;\n  max-height: 300px;\n  overflow: auto;\n}\n\n#mocha .test pre {\n  display: block;\n  float: left;\n  clear: left;\n  font: 12px/1.5 monaco, monospace;\n  margin: 5px;\n  padding: 15px;\n  border: 1px solid #eee;\n  border-bottom-color: #ddd;\n  -webkit-border-radius: 3px;\n  -webkit-box-shadow: 0 1px 3px #eee;\n  -moz-border-radius: 3px;\n  -moz-box-shadow: 0 1px 3px #eee;\n}\n\n#mocha .test h2 {\n  position: relative;\n}\n\n#mocha .test a.replay {\n  position: absolute;\n  top: 3px;\n  right: 0;\n  text-decoration: none;\n  vertical-align: middle;\n  display: block;\n  width: 15px;\n  height: 15px;\n  line-height: 15px;\n  text-align: center;\n  background: #eee;\n  font-size: 15px;\n  -moz-border-radius: 15px;\n  border-radius: 15px;\n  -webkit-transition: opacity 200ms;\n  -moz-transition: opacity 200ms;\n  transition: opacity 200ms;\n  opacity: 0.3;\n  color: #888;\n}\n\n#mocha .test:hover a.replay {\n  opacity: 1;\n}\n\n#mocha-report.pass .test.fail {\n  display: none;\n}\n\n#mocha-report.fail .test.pass {\n  display: none;\n}\n\n#mocha-error {\n  color: #c00;\n  font-size: 1.5  em;\n  font-weight: 100;\n  letter-spacing: 1px;\n}\n\n#mocha-stats {\n  position: fixed;\n  top: 15px;\n  right: 10px;\n  font-size: 12px;\n  margin: 0;\n  color: #888;\n}\n\n#mocha-stats .progress {\n  float: right;\n  padding-top: 0;\n}\n\n#mocha-stats em {\n  color: black;\n}\n\n#mocha-stats a {\n  text-decoration: none;\n  color: inherit;\n}\n\n#mocha-stats a:hover {\n  border-bottom: 1px solid #eee;\n}\n\n#mocha-stats li {\n  display: inline-block;\n  margin: 0 5px;\n  list-style: none;\n  padding-top: 11px;\n}\n\ncode .comment { color: #ddd }\ncode .init { color: #2F6FAD }\ncode .string { color: #5890AD }\ncode .keyword { color: #8A6343 }\ncode .number { color: #2F6FAD }\n"
  },
  {
    "path": "test/lib/mocha/mocha.js",
    "content": ";(function(){\n\n\n// CommonJS require()\n\nfunction require(p){\n    var path = require.resolve(p)\n      , mod = require.modules[path];\n    if (!mod) throw new Error('failed to require \"' + p + '\"');\n    if (!mod.exports) {\n      mod.exports = {};\n      mod.call(mod.exports, mod, mod.exports, require.relative(path));\n    }\n    return mod.exports;\n  }\n\nrequire.modules = {};\n\nrequire.resolve = function (path){\n    var orig = path\n      , reg = path + '.js'\n      , index = path + '/index.js';\n    return require.modules[reg] && reg\n      || require.modules[index] && index\n      || orig;\n  };\n\nrequire.register = function (path, fn){\n    require.modules[path] = fn;\n  };\n\nrequire.relative = function (parent) {\n    return function(p){\n      if ('.' != p.charAt(0)) return require(p);\n      \n      var path = parent.split('/')\n        , segs = p.split('/');\n      path.pop();\n      \n      for (var i = 0; i < segs.length; i++) {\n        var seg = segs[i];\n        if ('..' == seg) path.pop();\n        else if ('.' != seg) path.push(seg);\n      }\n\n      return require(path.join('/'));\n    };\n  };\n\n\nrequire.register(\"browser/debug.js\", function(module, exports, require){\n\nmodule.exports = function(type){\n  return function(){\n    \n  }\n};\n}); // module: browser/debug.js\n\nrequire.register(\"browser/diff.js\", function(module, exports, require){\n/* See license.txt for terms of usage */\n\n/*\n * Text diff implementation.\n * \n * This library supports the following APIS:\n * JsDiff.diffChars: Character by character diff\n * JsDiff.diffWords: Word (as defined by \\b regex) diff which ignores whitespace\n * JsDiff.diffLines: Line based diff\n * \n * JsDiff.diffCss: Diff targeted at CSS content\n * \n * These methods are based on the implementation proposed in\n * \"An O(ND) Difference Algorithm and its Variations\" (Myers, 1986).\n * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927\n */\nvar JsDiff = (function() {\n  function clonePath(path) {\n    return { newPos: path.newPos, components: path.components.slice(0) };\n  }\n  function removeEmpty(array) {\n    var ret = [];\n    for (var i = 0; i < array.length; i++) {\n      if (array[i]) {\n        ret.push(array[i]);\n      }\n    }\n    return ret;\n  }\n  function escapeHTML(s) {\n    var n = s;\n    n = n.replace(/&/g, \"&amp;\");\n    n = n.replace(/</g, \"&lt;\");\n    n = n.replace(/>/g, \"&gt;\");\n    n = n.replace(/\"/g, \"&quot;\");\n\n    return n;\n  }\n\n\n  var fbDiff = function(ignoreWhitespace) {\n    this.ignoreWhitespace = ignoreWhitespace;\n  };\n  fbDiff.prototype = {\n      diff: function(oldString, newString) {\n        // Handle the identity case (this is due to unrolling editLength == 0\n        if (newString == oldString) {\n          return [{ value: newString }];\n        }\n        if (!newString) {\n          return [{ value: oldString, removed: true }];\n        }\n        if (!oldString) {\n          return [{ value: newString, added: true }];\n        }\n\n        newString = this.tokenize(newString);\n        oldString = this.tokenize(oldString);\n\n        var newLen = newString.length, oldLen = oldString.length;\n        var maxEditLength = newLen + oldLen;\n        var bestPath = [{ newPos: -1, components: [] }];\n\n        // Seed editLength = 0\n        var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);\n        if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) {\n          return bestPath[0].components;\n        }\n\n        for (var editLength = 1; editLength <= maxEditLength; editLength++) {\n          for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) {\n            var basePath;\n            var addPath = bestPath[diagonalPath-1],\n                removePath = bestPath[diagonalPath+1];\n            oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;\n            if (addPath) {\n              // No one else is going to attempt to use this value, clear it\n              bestPath[diagonalPath-1] = undefined;\n            }\n\n            var canAdd = addPath && addPath.newPos+1 < newLen;\n            var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;\n            if (!canAdd && !canRemove) {\n              bestPath[diagonalPath] = undefined;\n              continue;\n            }\n\n            // Select the diagonal that we want to branch from. We select the prior\n            // path whose position in the new string is the farthest from the origin\n            // and does not pass the bounds of the diff graph\n            if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) {\n              basePath = clonePath(removePath);\n              this.pushComponent(basePath.components, oldString[oldPos], undefined, true);\n            } else {\n              basePath = clonePath(addPath);\n              basePath.newPos++;\n              this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined);\n            }\n\n            var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath);\n\n            if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) {\n              return basePath.components;\n            } else {\n              bestPath[diagonalPath] = basePath;\n            }\n          }\n        }\n      },\n\n      pushComponent: function(components, value, added, removed) {\n        var last = components[components.length-1];\n        if (last && last.added === added && last.removed === removed) {\n          // We need to clone here as the component clone operation is just\n          // as shallow array clone\n          components[components.length-1] =\n            {value: this.join(last.value, value), added: added, removed: removed };\n        } else {\n          components.push({value: value, added: added, removed: removed });\n        }\n      },\n      extractCommon: function(basePath, newString, oldString, diagonalPath) {\n        var newLen = newString.length,\n            oldLen = oldString.length,\n            newPos = basePath.newPos,\n            oldPos = newPos - diagonalPath;\n        while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) {\n          newPos++;\n          oldPos++;\n          \n          this.pushComponent(basePath.components, newString[newPos], undefined, undefined);\n        }\n        basePath.newPos = newPos;\n        return oldPos;\n      },\n\n      equals: function(left, right) {\n        var reWhitespace = /\\S/;\n        if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) {\n          return true;\n        } else {\n          return left == right;\n        }\n      },\n      join: function(left, right) {\n        return left + right;\n      },\n      tokenize: function(value) {\n        return value;\n      }\n  };\n  \n  var CharDiff = new fbDiff();\n  \n  var WordDiff = new fbDiff(true);\n  WordDiff.tokenize = function(value) {\n    return removeEmpty(value.split(/(\\s+|\\b)/));\n  };\n  \n  var CssDiff = new fbDiff(true);\n  CssDiff.tokenize = function(value) {\n    return removeEmpty(value.split(/([{}:;,]|\\s+)/));\n  };\n  \n  var LineDiff = new fbDiff();\n  LineDiff.tokenize = function(value) {\n    return value.split(/^/m);\n  };\n  \n  return {\n    diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); },\n    diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); },\n    diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); },\n\n    diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); },\n\n    createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) {\n      var ret = [];\n\n      ret.push(\"Index: \" + fileName);\n      ret.push(\"===================================================================\");\n      ret.push(\"--- \" + fileName + (typeof oldHeader === \"undefined\" ? \"\" : \"\\t\" + oldHeader));\n      ret.push(\"+++ \" + fileName + (typeof newHeader === \"undefined\" ? \"\" : \"\\t\" + newHeader));\n\n      var diff = LineDiff.diff(oldStr, newStr);\n      if (!diff[diff.length-1].value) {\n        diff.pop();   // Remove trailing newline add\n      }\n      diff.push({value: \"\", lines: []});   // Append an empty value to make cleanup easier\n\n      function contextLines(lines) {\n        return lines.map(function(entry) { return ' ' + entry; });\n      }\n      function eofNL(curRange, i, current) {\n        var last = diff[diff.length-2],\n            isLast = i === diff.length-2,\n            isLastOfType = i === diff.length-3 && (current.added === !last.added || current.removed === !last.removed);\n\n        // Figure out if this is the last line for the given file and missing NL\n        if (!/\\n$/.test(current.value) && (isLast || isLastOfType)) {\n          curRange.push('\\\\ No newline at end of file');\n        }\n      }\n\n      var oldRangeStart = 0, newRangeStart = 0, curRange = [],\n          oldLine = 1, newLine = 1;\n      for (var i = 0; i < diff.length; i++) {\n        var current = diff[i],\n            lines = current.lines || current.value.replace(/\\n$/, \"\").split(\"\\n\");\n        current.lines = lines;\n\n        if (current.added || current.removed) {\n          if (!oldRangeStart) {\n            var prev = diff[i-1];\n            oldRangeStart = oldLine;\n            newRangeStart = newLine;\n            \n            if (prev) {\n              curRange = contextLines(prev.lines.slice(-4));\n              oldRangeStart -= curRange.length;\n              newRangeStart -= curRange.length;\n            }\n          }\n          curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?\"+\":\"-\") + entry; }));\n          eofNL(curRange, i, current);\n\n          if (current.added) {\n            newLine += lines.length;\n          } else {\n            oldLine += lines.length;\n          }\n        } else {\n          if (oldRangeStart) {\n            // Close out any changes that have been output (or join overlapping)\n            if (lines.length <= 8 && i < diff.length-2) {\n              // Overlapping\n              curRange.push.apply(curRange, contextLines(lines));\n            } else {\n              // end the range and output\n              var contextSize = Math.min(lines.length, 4);\n              ret.push(\n                  \"@@ -\" + oldRangeStart + \",\" + (oldLine-oldRangeStart+contextSize)\n                  + \" +\" + newRangeStart + \",\" + (newLine-newRangeStart+contextSize)\n                  + \" @@\");\n              ret.push.apply(ret, curRange);\n              ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));\n              if (lines.length <= 4) {\n                eofNL(ret, i, current);\n              }\n\n              oldRangeStart = 0;  newRangeStart = 0; curRange = [];\n            }\n          }\n          oldLine += lines.length;\n          newLine += lines.length;\n        }\n      }\n\n      return ret.join('\\n') + '\\n';\n    },\n\n    convertChangesToXML: function(changes){\n      var ret = [];\n      for ( var i = 0; i < changes.length; i++) {\n        var change = changes[i];\n        if (change.added) {\n          ret.push(\"<ins>\");\n        } else if (change.removed) {\n          ret.push(\"<del>\");\n        }\n\n        ret.push(escapeHTML(change.value));\n\n        if (change.added) {\n          ret.push(\"</ins>\");\n        } else if (change.removed) {\n          ret.push(\"</del>\");\n        }\n      }\n      return ret.join(\"\");\n    }\n  };\n})();\n\nif (typeof module !== \"undefined\") {\n    module.exports = JsDiff;\n}\n\n}); // module: browser/diff.js\n\nrequire.register(\"browser/events.js\", function(module, exports, require){\n\n/**\n * Module exports.\n */\n\nexports.EventEmitter = EventEmitter;\n\n/**\n * Check if `obj` is an array.\n */\n\nfunction isArray(obj) {\n  return '[object Array]' == {}.toString.call(obj);\n}\n\n/**\n * Event emitter constructor.\n *\n * @api public\n */\n\nfunction EventEmitter(){};\n\n/**\n * Adds a listener.\n *\n * @api public\n */\n\nEventEmitter.prototype.on = function (name, fn) {\n  if (!this.$events) {\n    this.$events = {};\n  }\n\n  if (!this.$events[name]) {\n    this.$events[name] = fn;\n  } else if (isArray(this.$events[name])) {\n    this.$events[name].push(fn);\n  } else {\n    this.$events[name] = [this.$events[name], fn];\n  }\n\n  return this;\n};\n\nEventEmitter.prototype.addListener = EventEmitter.prototype.on;\n\n/**\n * Adds a volatile listener.\n *\n * @api public\n */\n\nEventEmitter.prototype.once = function (name, fn) {\n  var self = this;\n\n  function on () {\n    self.removeListener(name, on);\n    fn.apply(this, arguments);\n  };\n\n  on.listener = fn;\n  this.on(name, on);\n\n  return this;\n};\n\n/**\n * Removes a listener.\n *\n * @api public\n */\n\nEventEmitter.prototype.removeListener = function (name, fn) {\n  if (this.$events && this.$events[name]) {\n    var list = this.$events[name];\n\n    if (isArray(list)) {\n      var pos = -1;\n\n      for (var i = 0, l = list.length; i < l; i++) {\n        if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {\n          pos = i;\n          break;\n        }\n      }\n\n      if (pos < 0) {\n        return this;\n      }\n\n      list.splice(pos, 1);\n\n      if (!list.length) {\n        delete this.$events[name];\n      }\n    } else if (list === fn || (list.listener && list.listener === fn)) {\n      delete this.$events[name];\n    }\n  }\n\n  return this;\n};\n\n/**\n * Removes all listeners for an event.\n *\n * @api public\n */\n\nEventEmitter.prototype.removeAllListeners = function (name) {\n  if (name === undefined) {\n    this.$events = {};\n    return this;\n  }\n\n  if (this.$events && this.$events[name]) {\n    this.$events[name] = null;\n  }\n\n  return this;\n};\n\n/**\n * Gets all listeners for a certain event.\n *\n * @api public\n */\n\nEventEmitter.prototype.listeners = function (name) {\n  if (!this.$events) {\n    this.$events = {};\n  }\n\n  if (!this.$events[name]) {\n    this.$events[name] = [];\n  }\n\n  if (!isArray(this.$events[name])) {\n    this.$events[name] = [this.$events[name]];\n  }\n\n  return this.$events[name];\n};\n\n/**\n * Emits an event.\n *\n * @api public\n */\n\nEventEmitter.prototype.emit = function (name) {\n  if (!this.$events) {\n    return false;\n  }\n\n  var handler = this.$events[name];\n\n  if (!handler) {\n    return false;\n  }\n\n  var args = [].slice.call(arguments, 1);\n\n  if ('function' == typeof handler) {\n    handler.apply(this, args);\n  } else if (isArray(handler)) {\n    var listeners = handler.slice();\n\n    for (var i = 0, l = listeners.length; i < l; i++) {\n      listeners[i].apply(this, args);\n    }\n  } else {\n    return false;\n  }\n\n  return true;\n};\n}); // module: browser/events.js\n\nrequire.register(\"browser/fs.js\", function(module, exports, require){\n\n}); // module: browser/fs.js\n\nrequire.register(\"browser/path.js\", function(module, exports, require){\n\n}); // module: browser/path.js\n\nrequire.register(\"browser/progress.js\", function(module, exports, require){\n\n/**\n * Expose `Progress`.\n */\n\nmodule.exports = Progress;\n\n/**\n * Initialize a new `Progress` indicator.\n */\n\nfunction Progress() {\n  this.percent = 0;\n  this.size(0);\n  this.fontSize(11);\n  this.font('helvetica, arial, sans-serif');\n}\n\n/**\n * Set progress size to `n`.\n *\n * @param {Number} n\n * @return {Progress} for chaining\n * @api public\n */\n\nProgress.prototype.size = function(n){\n  this._size = n;\n  return this;\n};\n\n/**\n * Set text to `str`.\n *\n * @param {String} str\n * @return {Progress} for chaining\n * @api public\n */\n\nProgress.prototype.text = function(str){\n  this._text = str;\n  return this;\n};\n\n/**\n * Set font size to `n`.\n *\n * @param {Number} n\n * @return {Progress} for chaining\n * @api public\n */\n\nProgress.prototype.fontSize = function(n){\n  this._fontSize = n;\n  return this;\n};\n\n/**\n * Set font `family`.\n *\n * @param {String} family\n * @return {Progress} for chaining\n */\n\nProgress.prototype.font = function(family){\n  this._font = family;\n  return this;\n};\n\n/**\n * Update percentage to `n`.\n *\n * @param {Number} n\n * @return {Progress} for chaining\n */\n\nProgress.prototype.update = function(n){\n  this.percent = n;\n  return this;\n};\n\n/**\n * Draw on `ctx`.\n *\n * @param {CanvasRenderingContext2d} ctx\n * @return {Progress} for chaining\n */\n\nProgress.prototype.draw = function(ctx){\n  var percent = Math.min(this.percent, 100)\n    , size = this._size\n    , half = size / 2\n    , x = half\n    , y = half\n    , rad = half - 1\n    , fontSize = this._fontSize;\n\n  ctx.font = fontSize + 'px ' + this._font;\n\n  var angle = Math.PI * 2 * (percent / 100);\n  ctx.clearRect(0, 0, size, size);\n\n  // outer circle\n  ctx.strokeStyle = '#9f9f9f';\n  ctx.beginPath();\n  ctx.arc(x, y, rad, 0, angle, false);\n  ctx.stroke();\n\n  // inner circle\n  ctx.strokeStyle = '#eee';\n  ctx.beginPath();\n  ctx.arc(x, y, rad - 1, 0, angle, true);\n  ctx.stroke();\n\n  // text\n  var text = this._text || (percent | 0) + '%'\n    , w = ctx.measureText(text).width;\n\n  ctx.fillText(\n      text\n    , x - w / 2 + 1\n    , y + fontSize / 2 - 1);\n\n  return this;\n};\n\n}); // module: browser/progress.js\n\nrequire.register(\"browser/tty.js\", function(module, exports, require){\n\nexports.isatty = function(){\n  return true;\n};\n\nexports.getWindowSize = function(){\n  return [window.innerHeight, window.innerWidth];\n};\n}); // module: browser/tty.js\n\nrequire.register(\"context.js\", function(module, exports, require){\n\n/**\n * Expose `Context`.\n */\n\nmodule.exports = Context;\n\n/**\n * Initialize a new `Context`.\n *\n * @api private\n */\n\nfunction Context(){}\n\n/**\n * Set or get the context `Runnable` to `runnable`.\n *\n * @param {Runnable} runnable\n * @return {Context}\n * @api private\n */\n\nContext.prototype.runnable = function(runnable){\n  if (0 == arguments.length) return this._runnable;\n  this.test = this._runnable = runnable;\n  return this;\n};\n\n/**\n * Set test timeout `ms`.\n *\n * @param {Number} ms\n * @return {Context} self\n * @api private\n */\n\nContext.prototype.timeout = function(ms){\n  this.runnable().timeout(ms);\n  return this;\n};\n\n/**\n * Set test slowness threshold `ms`.\n *\n * @param {Number} ms\n * @return {Context} self\n * @api private\n */\n\nContext.prototype.slow = function(ms){\n  this.runnable().slow(ms);\n  return this;\n};\n\n/**\n * Inspect the context void of `._runnable`.\n *\n * @return {String}\n * @api private\n */\n\nContext.prototype.inspect = function(){\n  return JSON.stringify(this, function(key, val){\n    if ('_runnable' == key) return;\n    if ('test' == key) return;\n    return val;\n  }, 2);\n};\n\n}); // module: context.js\n\nrequire.register(\"hook.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Runnable = require('./runnable');\n\n/**\n * Expose `Hook`.\n */\n\nmodule.exports = Hook;\n\n/**\n * Initialize a new `Hook` with the given `title` and callback `fn`.\n *\n * @param {String} title\n * @param {Function} fn\n * @api private\n */\n\nfunction Hook(title, fn) {\n  Runnable.call(this, title, fn);\n  this.type = 'hook';\n}\n\n/**\n * Inherit from `Runnable.prototype`.\n */\n\nfunction F(){};\nF.prototype = Runnable.prototype;\nHook.prototype = new F;\nHook.prototype.constructor = Hook;\n\n\n/**\n * Get or set the test `err`.\n *\n * @param {Error} err\n * @return {Error}\n * @api public\n */\n\nHook.prototype.error = function(err){\n  if (0 == arguments.length) {\n    var err = this._error;\n    this._error = null;\n    return err;\n  }\n\n  this._error = err;\n};\n\n\n}); // module: hook.js\n\nrequire.register(\"interfaces/bdd.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Suite = require('../suite')\n  , Test = require('../test');\n\n/**\n * BDD-style interface:\n * \n *      describe('Array', function(){\n *        describe('#indexOf()', function(){\n *          it('should return -1 when not present', function(){\n *\n *          });\n *\n *          it('should return the index when present', function(){\n *\n *          });\n *        });\n *      });\n * \n */\n\nmodule.exports = function(suite){\n  var suites = [suite];\n\n  suite.on('pre-require', function(context, file, mocha){\n\n    /**\n     * Execute before running tests.\n     */\n\n    context.before = function(fn){\n      suites[0].beforeAll(fn);\n    };\n\n    /**\n     * Execute after running tests.\n     */\n\n    context.after = function(fn){\n      suites[0].afterAll(fn);\n    };\n\n    /**\n     * Execute before each test case.\n     */\n\n    context.beforeEach = function(fn){\n      suites[0].beforeEach(fn);\n    };\n\n    /**\n     * Execute after each test case.\n     */\n\n    context.afterEach = function(fn){\n      suites[0].afterEach(fn);\n    };\n\n    /**\n     * Describe a \"suite\" with the given `title`\n     * and callback `fn` containing nested suites\n     * and/or tests.\n     */\n  \n    context.describe = context.context = function(title, fn){\n      var suite = Suite.create(suites[0], title);\n      suites.unshift(suite);\n      fn.call(suite);\n      suites.shift();\n      return suite;\n    };\n\n    /**\n     * Pending describe.\n     */\n\n    context.xdescribe =\n    context.xcontext =\n    context.describe.skip = function(title, fn){\n      var suite = Suite.create(suites[0], title);\n      suite.pending = true;\n      suites.unshift(suite);\n      fn.call(suite);\n      suites.shift();\n    };\n\n    /**\n     * Exclusive suite.\n     */\n\n    context.describe.only = function(title, fn){\n      var suite = context.describe(title, fn);\n      mocha.grep(suite.fullTitle());\n    };\n\n    /**\n     * Describe a specification or test-case\n     * with the given `title` and callback `fn`\n     * acting as a thunk.\n     */\n\n    context.it = context.specify = function(title, fn){\n      var suite = suites[0];\n      if (suite.pending) var fn = null;\n      var test = new Test(title, fn);\n      suite.addTest(test);\n      return test;\n    };\n\n    /**\n     * Exclusive test-case.\n     */\n\n    context.it.only = function(title, fn){\n      var test = context.it(title, fn);\n      mocha.grep(test.fullTitle());\n    };\n\n    /**\n     * Pending test case.\n     */\n\n    context.xit =\n    context.xspecify =\n    context.it.skip = function(title){\n      context.it(title);\n    };\n  });\n};\n\n}); // module: interfaces/bdd.js\n\nrequire.register(\"interfaces/exports.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Suite = require('../suite')\n  , Test = require('../test');\n\n/**\n * TDD-style interface:\n * \n *     exports.Array = {\n *       '#indexOf()': {\n *         'should return -1 when the value is not present': function(){\n *           \n *         },\n *\n *         'should return the correct index when the value is present': function(){\n *           \n *         }\n *       }\n *     };\n * \n */\n\nmodule.exports = function(suite){\n  var suites = [suite];\n\n  suite.on('require', visit);\n\n  function visit(obj) {\n    var suite;\n    for (var key in obj) {\n      if ('function' == typeof obj[key]) {\n        var fn = obj[key];\n        switch (key) {\n          case 'before':\n            suites[0].beforeAll(fn);\n            break;\n          case 'after':\n            suites[0].afterAll(fn);\n            break;\n          case 'beforeEach':\n            suites[0].beforeEach(fn);\n            break;\n          case 'afterEach':\n            suites[0].afterEach(fn);\n            break;\n          default:\n            suites[0].addTest(new Test(key, fn));\n        }\n      } else {\n        var suite = Suite.create(suites[0], key);\n        suites.unshift(suite);\n        visit(obj[key]);\n        suites.shift();\n      }\n    }\n  }\n};\n}); // module: interfaces/exports.js\n\nrequire.register(\"interfaces/index.js\", function(module, exports, require){\n\nexports.bdd = require('./bdd');\nexports.tdd = require('./tdd');\nexports.qunit = require('./qunit');\nexports.exports = require('./exports');\n\n}); // module: interfaces/index.js\n\nrequire.register(\"interfaces/qunit.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Suite = require('../suite')\n  , Test = require('../test');\n\n/**\n * QUnit-style interface:\n * \n *     suite('Array');\n *     \n *     test('#length', function(){\n *       var arr = [1,2,3];\n *       ok(arr.length == 3);\n *     });\n *     \n *     test('#indexOf()', function(){\n *       var arr = [1,2,3];\n *       ok(arr.indexOf(1) == 0);\n *       ok(arr.indexOf(2) == 1);\n *       ok(arr.indexOf(3) == 2);\n *     });\n *     \n *     suite('String');\n *     \n *     test('#length', function(){\n *       ok('foo'.length == 3);\n *     });\n * \n */\n\nmodule.exports = function(suite){\n  var suites = [suite];\n\n  suite.on('pre-require', function(context){\n\n    /**\n     * Execute before running tests.\n     */\n\n    context.before = function(fn){\n      suites[0].beforeAll(fn);\n    };\n\n    /**\n     * Execute after running tests.\n     */\n\n    context.after = function(fn){\n      suites[0].afterAll(fn);\n    };\n\n    /**\n     * Execute before each test case.\n     */\n\n    context.beforeEach = function(fn){\n      suites[0].beforeEach(fn);\n    };\n\n    /**\n     * Execute after each test case.\n     */\n\n    context.afterEach = function(fn){\n      suites[0].afterEach(fn);\n    };\n\n    /**\n     * Describe a \"suite\" with the given `title`.\n     */\n  \n    context.suite = function(title){\n      if (suites.length > 1) suites.shift();\n      var suite = Suite.create(suites[0], title);\n      suites.unshift(suite);\n    };\n\n    /**\n     * Describe a specification or test-case\n     * with the given `title` and callback `fn`\n     * acting as a thunk.\n     */\n\n    context.test = function(title, fn){\n      suites[0].addTest(new Test(title, fn));\n    };\n  });\n};\n\n}); // module: interfaces/qunit.js\n\nrequire.register(\"interfaces/tdd.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Suite = require('../suite')\n  , Test = require('../test');\n\n/**\n * TDD-style interface:\n *\n *      suite('Array', function(){\n *        suite('#indexOf()', function(){\n *          suiteSetup(function(){\n *\n *          });\n *          \n *          test('should return -1 when not present', function(){\n *\n *          });\n *\n *          test('should return the index when present', function(){\n *\n *          });\n *\n *          suiteTeardown(function(){\n *\n *          });\n *        });\n *      });\n *\n */\n\nmodule.exports = function(suite){\n  var suites = [suite];\n\n  suite.on('pre-require', function(context, file, mocha){\n\n    /**\n     * Execute before each test case.\n     */\n\n    context.setup = function(fn){\n      suites[0].beforeEach(fn);\n    };\n\n    /**\n     * Execute after each test case.\n     */\n\n    context.teardown = function(fn){\n      suites[0].afterEach(fn);\n    };\n\n    /**\n     * Execute before the suite.\n     */\n\n    context.suiteSetup = function(fn){\n      suites[0].beforeAll(fn);\n    };\n\n    /**\n     * Execute after the suite.\n     */\n\n    context.suiteTeardown = function(fn){\n      suites[0].afterAll(fn);\n    };\n\n    /**\n     * Describe a \"suite\" with the given `title`\n     * and callback `fn` containing nested suites\n     * and/or tests.\n     */\n\n    context.suite = function(title, fn){\n      var suite = Suite.create(suites[0], title);\n      suites.unshift(suite);\n      fn.call(suite);\n      suites.shift();\n      return suite;\n    };\n\n    /**\n     * Exclusive test-case.\n     */\n\n    context.suite.only = function(title, fn){\n      var suite = context.suite(title, fn);\n      mocha.grep(suite.fullTitle());\n    };\n\n    /**\n     * Describe a specification or test-case\n     * with the given `title` and callback `fn`\n     * acting as a thunk.\n     */\n\n    context.test = function(title, fn){\n      var test = new Test(title, fn);\n      suites[0].addTest(test);\n      return test;\n    };\n\n    /**\n     * Exclusive test-case.\n     */\n\n    context.test.only = function(title, fn){\n      var test = context.test(title, fn);\n      mocha.grep(test.fullTitle());\n    };\n\n    /**\n     * Pending test case.\n     */\n\n    context.test.skip = function(title){\n      context.test(title);\n    };\n  });\n};\n\n}); // module: interfaces/tdd.js\n\nrequire.register(\"mocha.js\", function(module, exports, require){\n/*!\n * mocha\n * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>\n * MIT Licensed\n */\n\n/**\n * Module dependencies.\n */\n\nvar path = require('browser/path')\n  , utils = require('./utils');\n\n/**\n * Expose `Mocha`.\n */\n\nexports = module.exports = Mocha;\n\n/**\n * Expose internals.\n */\n\nexports.utils = utils;\nexports.interfaces = require('./interfaces');\nexports.reporters = require('./reporters');\nexports.Runnable = require('./runnable');\nexports.Context = require('./context');\nexports.Runner = require('./runner');\nexports.Suite = require('./suite');\nexports.Hook = require('./hook');\nexports.Test = require('./test');\n\n/**\n * Return image `name` path.\n *\n * @param {String} name\n * @return {String}\n * @api private\n */\n\nfunction image(name) {\n  return __dirname + '/../images/' + name + '.png';\n}\n\n/**\n * Setup mocha with `options`.\n *\n * Options:\n *\n *   - `ui` name \"bdd\", \"tdd\", \"exports\" etc\n *   - `reporter` reporter instance, defaults to `mocha.reporters.Dot`\n *   - `globals` array of accepted globals\n *   - `timeout` timeout in milliseconds\n *   - `bail` bail on the first test failure\n *   - `slow` milliseconds to wait before considering a test slow\n *   - `ignoreLeaks` ignore global leaks\n *   - `grep` string or regexp to filter tests with\n *\n * @param {Object} options\n * @api public\n */\n\nfunction Mocha(options) {\n  options = options || {};\n  this.files = [];\n  this.options = options;\n  this.grep(options.grep);\n  this.suite = new exports.Suite('', new exports.Context);\n  this.ui(options.ui);\n  this.bail(options.bail);\n  this.reporter(options.reporter);\n  if (options.timeout) this.timeout(options.timeout);\n  if (options.slow) this.slow(options.slow);\n}\n\n/**\n * Enable or disable bailing on the first failure.\n *\n * @param {Boolean} [bail]\n * @api public\n */\n\nMocha.prototype.bail = function(bail){\n  if (null == bail) bail = true;\n  this.suite.bail(bail);\n  return this;\n};\n\n/**\n * Add test `file`.\n *\n * @param {String} file\n * @api public\n */\n\nMocha.prototype.addFile = function(file){\n  this.files.push(file);\n  return this;\n};\n\n/**\n * Set reporter to `reporter`, defaults to \"dot\".\n *\n * @param {String|Function} reporter name or constructor\n * @api public\n */\n\nMocha.prototype.reporter = function(reporter){\n  if ('function' == typeof reporter) {\n    this._reporter = reporter;\n  } else {\n    reporter = reporter || 'dot';\n    try {\n      this._reporter = require('./reporters/' + reporter);\n    } catch (err) {\n      this._reporter = require(reporter);\n    }\n    if (!this._reporter) throw new Error('invalid reporter \"' + reporter + '\"');\n  }\n  return this;\n};\n\n/**\n * Set test UI `name`, defaults to \"bdd\".\n *\n * @param {String} bdd\n * @api public\n */\n\nMocha.prototype.ui = function(name){\n  name = name || 'bdd';\n  this._ui = exports.interfaces[name];\n  if (!this._ui) throw new Error('invalid interface \"' + name + '\"');\n  this._ui = this._ui(this.suite);\n  return this;\n};\n\n/**\n * Load registered files.\n *\n * @api private\n */\n\nMocha.prototype.loadFiles = function(fn){\n  var self = this;\n  var suite = this.suite;\n  var pending = this.files.length;\n  this.files.forEach(function(file){\n    file = path.resolve(file);\n    suite.emit('pre-require', global, file, self);\n    suite.emit('require', require(file), file, self);\n    suite.emit('post-require', global, file, self);\n    --pending || (fn && fn());\n  });\n};\n\n/**\n * Enable growl support.\n *\n * @api private\n */\n\nMocha.prototype._growl = function(runner, reporter) {\n  var notify = require('growl');\n\n  runner.on('end', function(){\n    var stats = reporter.stats;\n    if (stats.failures) {\n      var msg = stats.failures + ' of ' + runner.total + ' tests failed';\n      notify(msg, { name: 'mocha', title: 'Failed', image: image('error') });\n    } else {\n      notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', {\n          name: 'mocha'\n        , title: 'Passed'\n        , image: image('ok')\n      });\n    }\n  });\n};\n\n/**\n * Add regexp to grep, if `re` is a string it is escaped.\n *\n * @param {RegExp|String} re\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.grep = function(re){\n  this.options.grep = 'string' == typeof re\n    ? new RegExp(utils.escapeRegexp(re))\n    : re;\n  return this;\n};\n\n/**\n * Invert `.grep()` matches.\n *\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.invert = function(){\n  this.options.invert = true;\n  return this;\n};\n\n/**\n * Ignore global leaks.\n *\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.ignoreLeaks = function(){\n  this.options.ignoreLeaks = true;\n  return this;\n};\n\n/**\n * Enable global leak checking.\n *\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.checkLeaks = function(){\n  this.options.ignoreLeaks = false;\n  return this;\n};\n\n/**\n * Enable growl support.\n *\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.growl = function(){\n  this.options.growl = true;\n  return this;\n};\n\n/**\n * Ignore `globals` array or string.\n *\n * @param {Array|String} globals\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.globals = function(globals){\n  this.options.globals = (this.options.globals || []).concat(globals);\n  return this;\n};\n\n/**\n * Set the timeout in milliseconds.\n *\n * @param {Number} timeout\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.timeout = function(timeout){\n  this.suite.timeout(timeout);\n  return this;\n};\n\n/**\n * Set slowness threshold in milliseconds.\n *\n * @param {Number} slow\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.slow = function(slow){\n  this.suite.slow(slow);\n  return this;\n};\n\n/**\n * Makes all tests async (accepting a callback)\n *\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.asyncOnly = function(){\n  this.options.asyncOnly = true;\n  return this;\n};\n\n/**\n * Run tests and invoke `fn()` when complete.\n *\n * @param {Function} fn\n * @return {Runner}\n * @api public\n */\n\nMocha.prototype.run = function(fn){\n  if (this.files.length) this.loadFiles();\n  var suite = this.suite;\n  var options = this.options;\n  var runner = new exports.Runner(suite);\n  var reporter = new this._reporter(runner);\n  runner.ignoreLeaks = options.ignoreLeaks;\n  runner.asyncOnly = options.asyncOnly;\n  if (options.grep) runner.grep(options.grep, options.invert);\n  if (options.globals) runner.globals(options.globals);\n  if (options.growl) this._growl(runner, reporter);\n  return runner.run(fn);\n};\n\n}); // module: mocha.js\n\nrequire.register(\"ms.js\", function(module, exports, require){\n\n/**\n * Helpers.\n */\n\nvar s = 1000;\nvar m = s * 60;\nvar h = m * 60;\nvar d = h * 24;\n\n/**\n * Parse or format the given `val`.\n *\n * @param {String|Number} val\n * @return {String|Number}\n * @api public\n */\n\nmodule.exports = function(val){\n  if ('string' == typeof val) return parse(val);\n  return format(val);\n}\n\n/**\n * Parse the given `str` and return milliseconds.\n *\n * @param {String} str\n * @return {Number}\n * @api private\n */\n\nfunction parse(str) {\n  var m = /^((?:\\d+)?\\.?\\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);\n  if (!m) return;\n  var n = parseFloat(m[1]);\n  var type = (m[2] || 'ms').toLowerCase();\n  switch (type) {\n    case 'years':\n    case 'year':\n    case 'y':\n      return n * 31557600000;\n    case 'days':\n    case 'day':\n    case 'd':\n      return n * 86400000;\n    case 'hours':\n    case 'hour':\n    case 'h':\n      return n * 3600000;\n    case 'minutes':\n    case 'minute':\n    case 'm':\n      return n * 60000;\n    case 'seconds':\n    case 'second':\n    case 's':\n      return n * 1000;\n    case 'ms':\n      return n;\n  }\n}\n\n/**\n * Format the given `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api public\n */\n\nfunction format(ms) {\n  if (ms == d) return Math.round(ms / d) + ' day';\n  if (ms > d) return Math.round(ms / d) + ' days';\n  if (ms == h) return Math.round(ms / h) + ' hour';\n  if (ms > h) return Math.round(ms / h) + ' hours';\n  if (ms == m) return Math.round(ms / m) + ' minute';\n  if (ms > m) return Math.round(ms / m) + ' minutes';\n  if (ms == s) return Math.round(ms / s) + ' second';\n  if (ms > s) return Math.round(ms / s) + ' seconds';\n  return ms + ' ms';\n}\n}); // module: ms.js\n\nrequire.register(\"reporters/base.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar tty = require('browser/tty')\n  , diff = require('browser/diff')\n  , ms = require('../ms');\n\n/**\n * Save timer references to avoid Sinon interfering (see GH-237).\n */\n\nvar Date = global.Date\n  , setTimeout = global.setTimeout\n  , setInterval = global.setInterval\n  , clearTimeout = global.clearTimeout\n  , clearInterval = global.clearInterval;\n\n/**\n * Check if both stdio streams are associated with a tty.\n */\n\nvar isatty = tty.isatty(1) && tty.isatty(2);\n\n/**\n * Expose `Base`.\n */\n\nexports = module.exports = Base;\n\n/**\n * Enable coloring by default.\n */\n\nexports.useColors = isatty;\n\n/**\n * Default color map.\n */\n\nexports.colors = {\n    'pass': 90\n  , 'fail': 31\n  , 'bright pass': 92\n  , 'bright fail': 91\n  , 'bright yellow': 93\n  , 'pending': 36\n  , 'suite': 0\n  , 'error title': 0\n  , 'error message': 31\n  , 'error stack': 90\n  , 'checkmark': 32\n  , 'fast': 90\n  , 'medium': 33\n  , 'slow': 31\n  , 'green': 32\n  , 'light': 90\n  , 'diff gutter': 90\n  , 'diff added': 42\n  , 'diff removed': 41\n};\n\n/**\n * Default symbol map.\n */\n \nexports.symbols = {\n  ok: '✓',\n  err: '✖',\n  dot: '․'\n};\n\n// With node.js on Windows: use symbols available in terminal default fonts\nif ('win32' == process.platform) {\n  exports.symbols.ok = '\\u221A';\n  exports.symbols.err = '\\u00D7';\n  exports.symbols.dot = '.';\n}\n\n/**\n * Color `str` with the given `type`,\n * allowing colors to be disabled,\n * as well as user-defined color\n * schemes.\n *\n * @param {String} type\n * @param {String} str\n * @return {String}\n * @api private\n */\n\nvar color = exports.color = function(type, str) {\n  if (!exports.useColors) return str;\n  return '\\u001b[' + exports.colors[type] + 'm' + str + '\\u001b[0m';\n};\n\n/**\n * Expose term window size, with some\n * defaults for when stderr is not a tty.\n */\n\nexports.window = {\n  width: isatty\n    ? process.stdout.getWindowSize\n      ? process.stdout.getWindowSize(1)[0]\n      : tty.getWindowSize()[1]\n    : 75\n};\n\n/**\n * Expose some basic cursor interactions\n * that are common among reporters.\n */\n\nexports.cursor = {\n  hide: function(){\n    process.stdout.write('\\u001b[?25l');\n  },\n\n  show: function(){\n    process.stdout.write('\\u001b[?25h');\n  },\n\n  deleteLine: function(){\n    process.stdout.write('\\u001b[2K');\n  },\n\n  beginningOfLine: function(){\n    process.stdout.write('\\u001b[0G');\n  },\n\n  CR: function(){\n    exports.cursor.deleteLine();\n    exports.cursor.beginningOfLine();\n  }\n};\n\n/**\n * Outut the given `failures` as a list.\n *\n * @param {Array} failures\n * @api public\n */\n\nexports.list = function(failures){\n  console.error();\n  failures.forEach(function(test, i){\n    // format\n    var fmt = color('error title', '  %s) %s:\\n')\n      + color('error message', '     %s')\n      + color('error stack', '\\n%s\\n');\n\n    // msg\n    var err = test.err\n      , message = err.message || ''\n      , stack = err.stack || message\n      , index = stack.indexOf(message) + message.length\n      , msg = stack.slice(0, index)\n      , actual = err.actual\n      , expected = err.expected\n      , escape = true;\n\n    // explicitly show diff\n    if (err.showDiff) {\n      escape = false;\n      err.actual = actual = JSON.stringify(actual, null, 2);\n      err.expected = expected = JSON.stringify(expected, null, 2);\n    }\n\n    // actual / expected diff\n    if ('string' == typeof actual && 'string' == typeof expected) {\n      var len = Math.max(actual.length, expected.length);\n\n      if (len < 20) msg = errorDiff(err, 'Chars', escape);\n      else msg = errorDiff(err, 'Words', escape);\n\n      // linenos\n      var lines = msg.split('\\n');\n      if (lines.length > 4) {\n        var width = String(lines.length).length;\n        msg = lines.map(function(str, i){\n          return pad(++i, width) + ' |' + ' ' + str;\n        }).join('\\n');\n      }\n\n      // legend\n      msg = '\\n'\n        + color('diff removed', 'actual')\n        + ' '\n        + color('diff added', 'expected')\n        + '\\n\\n'\n        + msg\n        + '\\n';\n\n      // indent\n      msg = msg.replace(/^/gm, '      ');\n\n      fmt = color('error title', '  %s) %s:\\n%s')\n        + color('error stack', '\\n%s\\n');\n    }\n\n    // indent stack trace without msg\n    stack = stack.slice(index ? index + 1 : index)\n      .replace(/^/gm, '  ');\n\n    console.error(fmt, (i + 1), test.fullTitle(), msg, stack);\n  });\n};\n\n/**\n * Initialize a new `Base` reporter.\n *\n * All other reporters generally\n * inherit from this reporter, providing\n * stats such as test duration, number\n * of tests passed / failed etc.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Base(runner) {\n  var self = this\n    , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }\n    , failures = this.failures = [];\n\n  if (!runner) return;\n  this.runner = runner;\n\n  runner.stats = stats;\n\n  runner.on('start', function(){\n    stats.start = new Date;\n  });\n\n  runner.on('suite', function(suite){\n    stats.suites = stats.suites || 0;\n    suite.root || stats.suites++;\n  });\n\n  runner.on('test end', function(test){\n    stats.tests = stats.tests || 0;\n    stats.tests++;\n  });\n\n  runner.on('pass', function(test){\n    stats.passes = stats.passes || 0;\n\n    var medium = test.slow() / 2;\n    test.speed = test.duration > test.slow()\n      ? 'slow'\n      : test.duration > medium\n        ? 'medium'\n        : 'fast';\n\n    stats.passes++;\n  });\n\n  runner.on('fail', function(test, err){\n    stats.failures = stats.failures || 0;\n    stats.failures++;\n    test.err = err;\n    failures.push(test);\n  });\n\n  runner.on('end', function(){\n    stats.end = new Date;\n    stats.duration = new Date - stats.start;\n  });\n\n  runner.on('pending', function(){\n    stats.pending++;\n  });\n}\n\n/**\n * Output common epilogue used by many of\n * the bundled reporters.\n *\n * @api public\n */\n\nBase.prototype.epilogue = function(){\n  var stats = this.stats\n    , fmt\n    , tests;\n\n  console.log();\n\n  function pluralize(n) {\n    return 1 == n ? 'test' : 'tests';\n  }\n\n  // failure\n  if (stats.failures) {\n    fmt = color('bright fail', '  ' + exports.symbols.err)\n      + color('fail', ' %d of %d %s failed')\n      + color('light', ':')\n\n    console.error(fmt,\n      stats.failures,\n      this.runner.total,\n      pluralize(this.runner.total));\n\n    Base.list(this.failures);\n    console.error();\n    return;\n  }\n\n  // pass\n  fmt = color('bright pass', ' ')\n    + color('green', ' %d %s complete')\n    + color('light', ' (%s)');\n\n  console.log(fmt,\n    stats.tests || 0,\n    pluralize(stats.tests),\n    ms(stats.duration));\n\n  // pending\n  if (stats.pending) {\n    fmt = color('pending', ' ')\n      + color('pending', ' %d %s pending');\n\n    console.log(fmt, stats.pending, pluralize(stats.pending));\n  }\n\n  console.log();\n};\n\n/**\n * Pad the given `str` to `len`.\n *\n * @param {String} str\n * @param {String} len\n * @return {String}\n * @api private\n */\n\nfunction pad(str, len) {\n  str = String(str);\n  return Array(len - str.length + 1).join(' ') + str;\n}\n\n/**\n * Return a character diff for `err`.\n *\n * @param {Error} err\n * @return {String}\n * @api private\n */\n\nfunction errorDiff(err, type, escape) {\n  return diff['diff' + type](err.actual, err.expected).map(function(str){\n    if (escape) {\n      str.value = str.value\n        .replace(/\\t/g, '<tab>')\n        .replace(/\\r/g, '<CR>')\n        .replace(/\\n/g, '<LF>\\n');\n    }\n    if (str.added) return colorLines('diff added', str.value);\n    if (str.removed) return colorLines('diff removed', str.value);\n    return str.value;\n  }).join('');\n}\n\n/**\n * Color lines for `str`, using the color `name`.\n *\n * @param {String} name\n * @param {String} str\n * @return {String}\n * @api private\n */\n\nfunction colorLines(name, str) {\n  return str.split('\\n').map(function(str){\n    return color(name, str);\n  }).join('\\n');\n}\n\n}); // module: reporters/base.js\n\nrequire.register(\"reporters/doc.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , utils = require('../utils');\n\n/**\n * Expose `Doc`.\n */\n\nexports = module.exports = Doc;\n\n/**\n * Initialize a new `Doc` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Doc(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , total = runner.total\n    , indents = 2;\n\n  function indent() {\n    return Array(indents).join('  ');\n  }\n\n  runner.on('suite', function(suite){\n    if (suite.root) return;\n    ++indents;\n    console.log('%s<section class=\"suite\">', indent());\n    ++indents;\n    console.log('%s<h1>%s</h1>', indent(), utils.escape(suite.title));\n    console.log('%s<dl>', indent());\n  });\n\n  runner.on('suite end', function(suite){\n    if (suite.root) return;\n    console.log('%s</dl>', indent());\n    --indents;\n    console.log('%s</section>', indent());\n    --indents;\n  });\n\n  runner.on('pass', function(test){\n    console.log('%s  <dt>%s</dt>', indent(), utils.escape(test.title));\n    var code = utils.escape(utils.clean(test.fn.toString()));\n    console.log('%s  <dd><pre><code>%s</code></pre></dd>', indent(), code);\n  });\n}\n\n}); // module: reporters/doc.js\n\nrequire.register(\"reporters/dot.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , color = Base.color;\n\n/**\n * Expose `Dot`.\n */\n\nexports = module.exports = Dot;\n\n/**\n * Initialize a new `Dot` matrix test reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Dot(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , width = Base.window.width * .75 | 0\n    , n = 0;\n\n  runner.on('start', function(){\n    process.stdout.write('\\n  ');\n  });\n\n  runner.on('pending', function(test){\n    process.stdout.write(color('pending', Base.symbols.dot));\n  });\n\n  runner.on('pass', function(test){\n    if (++n % width == 0) process.stdout.write('\\n  ');\n    if ('slow' == test.speed) {\n      process.stdout.write(color('bright yellow', Base.symbols.dot));\n    } else {\n      process.stdout.write(color(test.speed, Base.symbols.dot));\n    }\n  });\n\n  runner.on('fail', function(test, err){\n    if (++n % width == 0) process.stdout.write('\\n  ');\n    process.stdout.write(color('fail', Base.symbols.dot));\n  });\n\n  runner.on('end', function(){\n    console.log();\n    self.epilogue();\n  });\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nDot.prototype = new F;\nDot.prototype.constructor = Dot;\n\n}); // module: reporters/dot.js\n\nrequire.register(\"reporters/html-cov.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar JSONCov = require('./json-cov')\n  , fs = require('browser/fs');\n\n/**\n * Expose `HTMLCov`.\n */\n\nexports = module.exports = HTMLCov;\n\n/**\n * Initialize a new `JsCoverage` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction HTMLCov(runner) {\n  var jade = require('jade')\n    , file = __dirname + '/templates/coverage.jade'\n    , str = fs.readFileSync(file, 'utf8')\n    , fn = jade.compile(str, { filename: file })\n    , self = this;\n\n  JSONCov.call(this, runner, false);\n\n  runner.on('end', function(){\n    process.stdout.write(fn({\n        cov: self.cov\n      , coverageClass: coverageClass\n    }));\n  });\n}\n\n/**\n * Return coverage class for `n`.\n *\n * @return {String}\n * @api private\n */\n\nfunction coverageClass(n) {\n  if (n >= 75) return 'high';\n  if (n >= 50) return 'medium';\n  if (n >= 25) return 'low';\n  return 'terrible';\n}\n}); // module: reporters/html-cov.js\n\nrequire.register(\"reporters/html.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , utils = require('../utils')\n  , Progress = require('../browser/progress')\n  , escape = utils.escape;\n\n/**\n * Save timer references to avoid Sinon interfering (see GH-237).\n */\n\nvar Date = global.Date\n  , setTimeout = global.setTimeout\n  , setInterval = global.setInterval\n  , clearTimeout = global.clearTimeout\n  , clearInterval = global.clearInterval;\n\n/**\n * Expose `Doc`.\n */\n\nexports = module.exports = HTML;\n\n/**\n * Stats template.\n */\n\nvar statsTemplate = '<ul id=\"mocha-stats\">'\n  + '<li class=\"progress\"><canvas width=\"40\" height=\"40\"></canvas></li>'\n  + '<li class=\"passes\"><a href=\"#\">passes:</a> <em>0</em></li>'\n  + '<li class=\"failures\"><a href=\"#\">failures:</a> <em>0</em></li>'\n  + '<li class=\"duration\">duration: <em>0</em>s</li>'\n  + '</ul>';\n\n/**\n * Initialize a new `Doc` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction HTML(runner, root) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , total = runner.total\n    , stat = fragment(statsTemplate)\n    , items = stat.getElementsByTagName('li')\n    , passes = items[1].getElementsByTagName('em')[0]\n    , passesLink = items[1].getElementsByTagName('a')[0]\n    , failures = items[2].getElementsByTagName('em')[0]\n    , failuresLink = items[2].getElementsByTagName('a')[0]\n    , duration = items[3].getElementsByTagName('em')[0]\n    , canvas = stat.getElementsByTagName('canvas')[0]\n    , report = fragment('<ul id=\"mocha-report\"></ul>')\n    , stack = [report]\n    , progress\n    , ctx\n\n  root = root || document.getElementById('mocha');\n\n  if (canvas.getContext) {\n    var ratio = window.devicePixelRatio || 1;\n    canvas.style.width = canvas.width;\n    canvas.style.height = canvas.height;\n    canvas.width *= ratio;\n    canvas.height *= ratio;\n    ctx = canvas.getContext('2d');\n    ctx.scale(ratio, ratio);\n    progress = new Progress;\n  }\n\n  if (!root) return error('#mocha div missing, add it to your document');\n\n  // pass toggle\n  on(passesLink, 'click', function(){\n    unhide();\n    var name = /pass/.test(report.className) ? '' : ' pass';\n    report.className = report.className.replace(/fail|pass/g, '') + name;\n    if (report.className.trim()) hideSuitesWithout('test pass');\n  });\n\n  // failure toggle\n  on(failuresLink, 'click', function(){\n    unhide();\n    var name = /fail/.test(report.className) ? '' : ' fail';\n    report.className = report.className.replace(/fail|pass/g, '') + name;\n    if (report.className.trim()) hideSuitesWithout('test fail');\n  });\n\n  root.appendChild(stat);\n  root.appendChild(report);\n\n  if (progress) progress.size(40);\n\n  runner.on('suite', function(suite){\n    if (suite.root) return;\n\n    // suite\n    var url = '?grep=' + encodeURIComponent(suite.fullTitle());\n    var el = fragment('<li class=\"suite\"><h1><a href=\"%s\">%s</a></h1></li>', url, escape(suite.title));\n\n    // container\n    stack[0].appendChild(el);\n    stack.unshift(document.createElement('ul'));\n    el.appendChild(stack[0]);\n  });\n\n  runner.on('suite end', function(suite){\n    if (suite.root) return;\n    stack.shift();\n  });\n\n  runner.on('fail', function(test, err){\n    if ('hook' == test.type) runner.emit('test end', test);\n  });\n\n  runner.on('test end', function(test){\n    window.scrollTo(0, document.body.scrollHeight);\n\n    // TODO: add to stats\n    var percent = stats.tests / this.total * 100 | 0;\n    if (progress) progress.update(percent).draw(ctx);\n\n    // update stats\n    var ms = new Date - stats.start;\n    text(passes, stats.passes);\n    text(failures, stats.failures);\n    text(duration, (ms / 1000).toFixed(2));\n\n    // test\n    if ('passed' == test.state) {\n      var el = fragment('<li class=\"test pass %e\"><h2>%e<span class=\"duration\">%ems</span> <a href=\"?grep=%e\" class=\"replay\">‣</a></h2></li>', test.speed, test.title, test.duration, encodeURIComponent(test.fullTitle()));\n    } else if (test.pending) {\n      var el = fragment('<li class=\"test pass pending\"><h2>%e</h2></li>', test.title);\n    } else {\n      var el = fragment('<li class=\"test fail\"><h2>%e <a href=\"?grep=%e\" class=\"replay\">‣</a></h2></li>', test.title, encodeURIComponent(test.fullTitle()));\n      var str = test.err.stack || test.err.toString();\n\n      // FF / Opera do not add the message\n      if (!~str.indexOf(test.err.message)) {\n        str = test.err.message + '\\n' + str;\n      }\n\n      // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we\n      // check for the result of the stringifying.\n      if ('[object Error]' == str) str = test.err.message;\n\n      // Safari doesn't give you a stack. Let's at least provide a source line.\n      if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {\n        str += \"\\n(\" + test.err.sourceURL + \":\" + test.err.line + \")\";\n      }\n\n      el.appendChild(fragment('<pre class=\"error\">%e</pre>', str));\n    }\n\n    // toggle code\n    // TODO: defer\n    if (!test.pending) {\n      var h2 = el.getElementsByTagName('h2')[0];\n\n      on(h2, 'click', function(){\n        pre.style.display = 'none' == pre.style.display\n          ? 'block'\n          : 'none';\n      });\n\n      var pre = fragment('<pre><code>%e</code></pre>', utils.clean(test.fn.toString()));\n      el.appendChild(pre);\n      pre.style.display = 'none';\n    }\n\n    // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack.\n    if (stack[0]) stack[0].appendChild(el);\n  });\n}\n\n/**\n * Display error `msg`.\n */\n\nfunction error(msg) {\n  document.body.appendChild(fragment('<div id=\"mocha-error\">%s</div>', msg));\n}\n\n/**\n * Return a DOM fragment from `html`.\n */\n\nfunction fragment(html) {\n  var args = arguments\n    , div = document.createElement('div')\n    , i = 1;\n\n  div.innerHTML = html.replace(/%([se])/g, function(_, type){\n    switch (type) {\n      case 's': return String(args[i++]);\n      case 'e': return escape(args[i++]);\n    }\n  });\n\n  return div.firstChild;\n}\n\n/**\n * Check for suites that do not have elements\n * with `classname`, and hide them.\n */\n\nfunction hideSuitesWithout(classname) {\n  var suites = document.getElementsByClassName('suite');\n  for (var i = 0; i < suites.length; i++) {\n    var els = suites[i].getElementsByClassName(classname);\n    if (0 == els.length) suites[i].className += ' hidden';\n  }\n}\n\n/**\n * Unhide .hidden suites.\n */\n\nfunction unhide() {\n  var els = document.getElementsByClassName('suite hidden');\n  for (var i = 0; i < els.length; ++i) {\n    els[i].className = els[i].className.replace('suite hidden', 'suite');\n  }\n}\n\n/**\n * Set `el` text to `str`.\n */\n\nfunction text(el, str) {\n  if (el.textContent) {\n    el.textContent = str;\n  } else {\n    el.innerText = str;\n  }\n}\n\n/**\n * Listen on `event` with callback `fn`.\n */\n\nfunction on(el, event, fn) {\n  if (el.addEventListener) {\n    el.addEventListener(event, fn, false);\n  } else {\n    el.attachEvent('on' + event, fn);\n  }\n}\n\n}); // module: reporters/html.js\n\nrequire.register(\"reporters/index.js\", function(module, exports, require){\n\nexports.Base = require('./base');\nexports.Dot = require('./dot');\nexports.Doc = require('./doc');\nexports.TAP = require('./tap');\nexports.JSON = require('./json');\nexports.HTML = require('./html');\nexports.List = require('./list');\nexports.Min = require('./min');\nexports.Spec = require('./spec');\nexports.Nyan = require('./nyan');\nexports.XUnit = require('./xunit');\nexports.Markdown = require('./markdown');\nexports.Progress = require('./progress');\nexports.Landing = require('./landing');\nexports.JSONCov = require('./json-cov');\nexports.HTMLCov = require('./html-cov');\nexports.JSONStream = require('./json-stream');\nexports.Teamcity = require('./teamcity');\n\n}); // module: reporters/index.js\n\nrequire.register(\"reporters/json-cov.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base');\n\n/**\n * Expose `JSONCov`.\n */\n\nexports = module.exports = JSONCov;\n\n/**\n * Initialize a new `JsCoverage` reporter.\n *\n * @param {Runner} runner\n * @param {Boolean} output\n * @api public\n */\n\nfunction JSONCov(runner, output) {\n  var self = this\n    , output = 1 == arguments.length ? true : output;\n\n  Base.call(this, runner);\n\n  var tests = []\n    , failures = []\n    , passes = [];\n\n  runner.on('test end', function(test){\n    tests.push(test);\n  });\n\n  runner.on('pass', function(test){\n    passes.push(test);\n  });\n\n  runner.on('fail', function(test){\n    failures.push(test);\n  });\n\n  runner.on('end', function(){\n    var cov = global._$jscoverage || {};\n    var result = self.cov = map(cov);\n    result.stats = self.stats;\n    result.tests = tests.map(clean);\n    result.failures = failures.map(clean);\n    result.passes = passes.map(clean);\n    if (!output) return;\n    process.stdout.write(JSON.stringify(result, null, 2 ));\n  });\n}\n\n/**\n * Map jscoverage data to a JSON structure\n * suitable for reporting.\n *\n * @param {Object} cov\n * @return {Object}\n * @api private\n */\n\nfunction map(cov) {\n  var ret = {\n      instrumentation: 'node-jscoverage'\n    , sloc: 0\n    , hits: 0\n    , misses: 0\n    , coverage: 0\n    , files: []\n  };\n\n  for (var filename in cov) {\n    var data = coverage(filename, cov[filename]);\n    ret.files.push(data);\n    ret.hits += data.hits;\n    ret.misses += data.misses;\n    ret.sloc += data.sloc;\n  }\n\n  ret.files.sort(function(a, b) {\n    return a.filename.localeCompare(b.filename);\n  });\n\n  if (ret.sloc > 0) {\n    ret.coverage = (ret.hits / ret.sloc) * 100;\n  }\n\n  return ret;\n};\n\n/**\n * Map jscoverage data for a single source file\n * to a JSON structure suitable for reporting.\n *\n * @param {String} filename name of the source file\n * @param {Object} data jscoverage coverage data\n * @return {Object}\n * @api private\n */\n\nfunction coverage(filename, data) {\n  var ret = {\n    filename: filename,\n    coverage: 0,\n    hits: 0,\n    misses: 0,\n    sloc: 0,\n    source: {}\n  };\n\n  data.source.forEach(function(line, num){\n    num++;\n\n    if (data[num] === 0) {\n      ret.misses++;\n      ret.sloc++;\n    } else if (data[num] !== undefined) {\n      ret.hits++;\n      ret.sloc++;\n    }\n\n    ret.source[num] = {\n        source: line\n      , coverage: data[num] === undefined\n        ? ''\n        : data[num]\n    };\n  });\n\n  ret.coverage = ret.hits / ret.sloc * 100;\n\n  return ret;\n}\n\n/**\n * Return a plain-object representation of `test`\n * free of cyclic properties etc.\n *\n * @param {Object} test\n * @return {Object}\n * @api private\n */\n\nfunction clean(test) {\n  return {\n      title: test.title\n    , fullTitle: test.fullTitle()\n    , duration: test.duration\n  }\n}\n\n}); // module: reporters/json-cov.js\n\nrequire.register(\"reporters/json-stream.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , color = Base.color;\n\n/**\n * Expose `List`.\n */\n\nexports = module.exports = List;\n\n/**\n * Initialize a new `List` test reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction List(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , total = runner.total;\n\n  runner.on('start', function(){\n    console.log(JSON.stringify(['start', { total: total }]));\n  });\n\n  runner.on('pass', function(test){\n    console.log(JSON.stringify(['pass', clean(test)]));\n  });\n\n  runner.on('fail', function(test, err){\n    console.log(JSON.stringify(['fail', clean(test)]));\n  });\n\n  runner.on('end', function(){\n    process.stdout.write(JSON.stringify(['end', self.stats]));\n  });\n}\n\n/**\n * Return a plain-object representation of `test`\n * free of cyclic properties etc.\n *\n * @param {Object} test\n * @return {Object}\n * @api private\n */\n\nfunction clean(test) {\n  return {\n      title: test.title\n    , fullTitle: test.fullTitle()\n    , duration: test.duration\n  }\n}\n}); // module: reporters/json-stream.js\n\nrequire.register(\"reporters/json.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , cursor = Base.cursor\n  , color = Base.color;\n\n/**\n * Expose `JSON`.\n */\n\nexports = module.exports = JSONReporter;\n\n/**\n * Initialize a new `JSON` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction JSONReporter(runner) {\n  var self = this;\n  Base.call(this, runner);\n\n  var tests = []\n    , failures = []\n    , passes = [];\n\n  runner.on('test end', function(test){\n    tests.push(test);\n  });\n\n  runner.on('pass', function(test){\n    passes.push(test);\n  });\n\n  runner.on('fail', function(test){\n    failures.push(test);\n  });\n\n  runner.on('end', function(){\n    var obj = {\n        stats: self.stats\n      , tests: tests.map(clean)\n      , failures: failures.map(clean)\n      , passes: passes.map(clean)\n    };\n\n    process.stdout.write(JSON.stringify(obj, null, 2));\n  });\n}\n\n/**\n * Return a plain-object representation of `test`\n * free of cyclic properties etc.\n *\n * @param {Object} test\n * @return {Object}\n * @api private\n */\n\nfunction clean(test) {\n  return {\n      title: test.title\n    , fullTitle: test.fullTitle()\n    , duration: test.duration\n  }\n}\n}); // module: reporters/json.js\n\nrequire.register(\"reporters/landing.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , cursor = Base.cursor\n  , color = Base.color;\n\n/**\n * Expose `Landing`.\n */\n\nexports = module.exports = Landing;\n\n/**\n * Airplane color.\n */\n\nBase.colors.plane = 0;\n\n/**\n * Airplane crash color.\n */\n\nBase.colors['plane crash'] = 31;\n\n/**\n * Runway color.\n */\n\nBase.colors.runway = 90;\n\n/**\n * Initialize a new `Landing` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Landing(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , width = Base.window.width * .75 | 0\n    , total = runner.total\n    , stream = process.stdout\n    , plane = color('plane', '✈')\n    , crashed = -1\n    , n = 0;\n\n  function runway() {\n    var buf = Array(width).join('-');\n    return '  ' + color('runway', buf);\n  }\n\n  runner.on('start', function(){\n    stream.write('\\n  ');\n    cursor.hide();\n  });\n\n  runner.on('test end', function(test){\n    // check if the plane crashed\n    var col = -1 == crashed\n      ? width * ++n / total | 0\n      : crashed;\n\n    // show the crash\n    if ('failed' == test.state) {\n      plane = color('plane crash', '✈');\n      crashed = col;\n    }\n\n    // render landing strip\n    stream.write('\\u001b[4F\\n\\n');\n    stream.write(runway());\n    stream.write('\\n  ');\n    stream.write(color('runway', Array(col).join('⋅')));\n    stream.write(plane)\n    stream.write(color('runway', Array(width - col).join('⋅') + '\\n'));\n    stream.write(runway());\n    stream.write('\\u001b[0m');\n  });\n\n  runner.on('end', function(){\n    cursor.show();\n    console.log();\n    self.epilogue();\n  });\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nLanding.prototype = new F;\nLanding.prototype.constructor = Landing;\n\n}); // module: reporters/landing.js\n\nrequire.register(\"reporters/list.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , cursor = Base.cursor\n  , color = Base.color;\n\n/**\n * Expose `List`.\n */\n\nexports = module.exports = List;\n\n/**\n * Initialize a new `List` test reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction List(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , n = 0;\n\n  runner.on('start', function(){\n    console.log();\n  });\n\n  runner.on('test', function(test){\n    process.stdout.write(color('pass', '    ' + test.fullTitle() + ': '));\n  });\n\n  runner.on('pending', function(test){\n    var fmt = color('checkmark', '  -')\n      + color('pending', ' %s');\n    console.log(fmt, test.fullTitle());\n  });\n\n  runner.on('pass', function(test){\n    var fmt = color('checkmark', '  '+Base.symbols.dot)\n      + color('pass', ' %s: ')\n      + color(test.speed, '%dms');\n    cursor.CR();\n    console.log(fmt, test.fullTitle(), test.duration);\n  });\n\n  runner.on('fail', function(test, err){\n    cursor.CR();\n    console.log(color('fail', '  %d) %s'), ++n, test.fullTitle());\n  });\n\n  runner.on('end', self.epilogue.bind(self));\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nList.prototype = new F;\nList.prototype.constructor = List;\n\n\n}); // module: reporters/list.js\n\nrequire.register(\"reporters/markdown.js\", function(module, exports, require){\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , utils = require('../utils');\n\n/**\n * Expose `Markdown`.\n */\n\nexports = module.exports = Markdown;\n\n/**\n * Initialize a new `Markdown` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Markdown(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , level = 0\n    , buf = '';\n\n  function title(str) {\n    return Array(level).join('#') + ' ' + str;\n  }\n\n  function indent() {\n    return Array(level).join('  ');\n  }\n\n  function mapTOC(suite, obj) {\n    var ret = obj;\n    obj = obj[suite.title] = obj[suite.title] || { suite: suite };\n    suite.suites.forEach(function(suite){\n      mapTOC(suite, obj);\n    });\n    return ret;\n  }\n\n  function stringifyTOC(obj, level) {\n    ++level;\n    var buf = '';\n    var link;\n    for (var key in obj) {\n      if ('suite' == key) continue;\n      if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\\n';\n      if (key) buf += Array(level).join('  ') + link;\n      buf += stringifyTOC(obj[key], level);\n    }\n    --level;\n    return buf;\n  }\n\n  function generateTOC(suite) {\n    var obj = mapTOC(suite, {});\n    return stringifyTOC(obj, 0);\n  }\n\n  generateTOC(runner.suite);\n\n  runner.on('suite', function(suite){\n    ++level;\n    var slug = utils.slug(suite.fullTitle());\n    buf += '<a name=\"' + slug + '\"></a>' + '\\n';\n    buf += title(suite.title) + '\\n';\n  });\n\n  runner.on('suite end', function(suite){\n    --level;\n  });\n\n  runner.on('pass', function(test){\n    var code = utils.clean(test.fn.toString());\n    buf += test.title + '.\\n';\n    buf += '\\n```js\\n';\n    buf += code + '\\n';\n    buf += '```\\n\\n';\n  });\n\n  runner.on('end', function(){\n    process.stdout.write('# TOC\\n');\n    process.stdout.write(generateTOC(runner.suite));\n    process.stdout.write(buf);\n  });\n}\n}); // module: reporters/markdown.js\n\nrequire.register(\"reporters/min.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base');\n\n/**\n * Expose `Min`.\n */\n\nexports = module.exports = Min;\n\n/**\n * Initialize a new `Min` minimal test reporter (best used with --watch).\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Min(runner) {\n  Base.call(this, runner);\n  \n  runner.on('start', function(){\n    // clear screen\n    process.stdout.write('\\u001b[2J');\n    // set cursor position\n    process.stdout.write('\\u001b[1;3H');\n  });\n\n  runner.on('end', this.epilogue.bind(this));\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nMin.prototype = new F;\nMin.prototype.constructor = Min;\n\n}); // module: reporters/min.js\n\nrequire.register(\"reporters/nyan.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , color = Base.color;\n\n/**\n * Expose `Dot`.\n */\n\nexports = module.exports = NyanCat;\n\n/**\n * Initialize a new `Dot` matrix test reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction NyanCat(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , width = Base.window.width * .75 | 0\n    , rainbowColors = this.rainbowColors = self.generateColors()\n    , colorIndex = this.colorIndex = 0\n    , numerOfLines = this.numberOfLines = 4\n    , trajectories = this.trajectories = [[], [], [], []]\n    , nyanCatWidth = this.nyanCatWidth = 11\n    , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth)\n    , scoreboardWidth = this.scoreboardWidth = 5\n    , tick = this.tick = 0\n    , n = 0;\n\n  runner.on('start', function(){\n    Base.cursor.hide();\n    self.draw('start');\n  });\n\n  runner.on('pending', function(test){\n    self.draw('pending');\n  });\n\n  runner.on('pass', function(test){\n    self.draw('pass');\n  });\n\n  runner.on('fail', function(test, err){\n    self.draw('fail');\n  });\n\n  runner.on('end', function(){\n    Base.cursor.show();\n    for (var i = 0; i < self.numberOfLines; i++) write('\\n');\n    self.epilogue();\n  });\n}\n\n/**\n * Draw the nyan cat with runner `status`.\n *\n * @param {String} status\n * @api private\n */\n\nNyanCat.prototype.draw = function(status){\n  this.appendRainbow();\n  this.drawScoreboard();\n  this.drawRainbow();\n  this.drawNyanCat(status);\n  this.tick = !this.tick;\n};\n\n/**\n * Draw the \"scoreboard\" showing the number\n * of passes, failures and pending tests.\n *\n * @api private\n */\n\nNyanCat.prototype.drawScoreboard = function(){\n  var stats = this.stats;\n  var colors = Base.colors;\n\n  function draw(color, n) {\n    write(' ');\n    write('\\u001b[' + color + 'm' + n + '\\u001b[0m');\n    write('\\n');\n  }\n\n  draw(colors.green, stats.passes);\n  draw(colors.fail, stats.failures);\n  draw(colors.pending, stats.pending);\n  write('\\n');\n\n  this.cursorUp(this.numberOfLines);\n};\n\n/**\n * Append the rainbow.\n *\n * @api private\n */\n\nNyanCat.prototype.appendRainbow = function(){\n  var segment = this.tick ? '_' : '-';\n  var rainbowified = this.rainbowify(segment);\n\n  for (var index = 0; index < this.numberOfLines; index++) {\n    var trajectory = this.trajectories[index];\n    if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift();\n    trajectory.push(rainbowified);\n  }\n};\n\n/**\n * Draw the rainbow.\n *\n * @api private\n */\n\nNyanCat.prototype.drawRainbow = function(){\n  var self = this;\n\n  this.trajectories.forEach(function(line, index) {\n    write('\\u001b[' + self.scoreboardWidth + 'C');\n    write(line.join(''));\n    write('\\n');\n  });\n\n  this.cursorUp(this.numberOfLines);\n};\n\n/**\n * Draw the nyan cat with `status`.\n *\n * @param {String} status\n * @api private\n */\n\nNyanCat.prototype.drawNyanCat = function(status) {\n  var self = this;\n  var startWidth = this.scoreboardWidth + this.trajectories[0].length;\n\n  [0, 1, 2, 3].forEach(function(index) {\n    write('\\u001b[' + startWidth + 'C');\n\n    switch (index) {\n      case 0:\n        write('_,------,');\n        write('\\n');\n        break;\n      case 1:\n        var padding = self.tick ? '  ' : '   ';\n        write('_|' + padding + '/\\\\_/\\\\ ');\n        write('\\n');\n        break;\n      case 2:\n        var padding = self.tick ? '_' : '__';\n        var tail = self.tick ? '~' : '^';\n        var face;\n        switch (status) {\n          case 'pass':\n            face = '( ^ .^)';\n            break;\n          case 'fail':\n            face = '( o .o)';\n            break;\n          default:\n            face = '( - .-)';\n        }\n        write(tail + '|' + padding + face + ' ');\n        write('\\n');\n        break;\n      case 3:\n        var padding = self.tick ? ' ' : '  ';\n        write(padding + '\"\"  \"\" ');\n        write('\\n');\n        break;\n    }\n  });\n\n  this.cursorUp(this.numberOfLines);\n};\n\n/**\n * Move cursor up `n`.\n *\n * @param {Number} n\n * @api private\n */\n\nNyanCat.prototype.cursorUp = function(n) {\n  write('\\u001b[' + n + 'A');\n};\n\n/**\n * Move cursor down `n`.\n *\n * @param {Number} n\n * @api private\n */\n\nNyanCat.prototype.cursorDown = function(n) {\n  write('\\u001b[' + n + 'B');\n};\n\n/**\n * Generate rainbow colors.\n *\n * @return {Array}\n * @api private\n */\n\nNyanCat.prototype.generateColors = function(){\n  var colors = [];\n\n  for (var i = 0; i < (6 * 7); i++) {\n    var pi3 = Math.floor(Math.PI / 3);\n    var n = (i * (1.0 / 6));\n    var r = Math.floor(3 * Math.sin(n) + 3);\n    var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3);\n    var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3);\n    colors.push(36 * r + 6 * g + b + 16);\n  }\n\n  return colors;\n};\n\n/**\n * Apply rainbow to the given `str`.\n *\n * @param {String} str\n * @return {String}\n * @api private\n */\n\nNyanCat.prototype.rainbowify = function(str){\n  var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length];\n  this.colorIndex += 1;\n  return '\\u001b[38;5;' + color + 'm' + str + '\\u001b[0m';\n};\n\n/**\n * Stdout helper.\n */\n\nfunction write(string) {\n  process.stdout.write(string);\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nNyanCat.prototype = new F;\nNyanCat.prototype.constructor = NyanCat;\n\n\n}); // module: reporters/nyan.js\n\nrequire.register(\"reporters/progress.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , cursor = Base.cursor\n  , color = Base.color;\n\n/**\n * Expose `Progress`.\n */\n\nexports = module.exports = Progress;\n\n/**\n * General progress bar color.\n */\n\nBase.colors.progress = 90;\n\n/**\n * Initialize a new `Progress` bar test reporter.\n *\n * @param {Runner} runner\n * @param {Object} options\n * @api public\n */\n\nfunction Progress(runner, options) {\n  Base.call(this, runner);\n\n  var self = this\n    , options = options || {}\n    , stats = this.stats\n    , width = Base.window.width * .50 | 0\n    , total = runner.total\n    , complete = 0\n    , max = Math.max;\n\n  // default chars\n  options.open = options.open || '[';\n  options.complete = options.complete || '▬';\n  options.incomplete = options.incomplete || Base.symbols.dot;\n  options.close = options.close || ']';\n  options.verbose = false;\n\n  // tests started\n  runner.on('start', function(){\n    console.log();\n    cursor.hide();\n  });\n\n  // tests complete\n  runner.on('test end', function(){\n    complete++;\n    var incomplete = total - complete\n      , percent = complete / total\n      , n = width * percent | 0\n      , i = width - n;\n\n    cursor.CR();\n    process.stdout.write('\\u001b[J');\n    process.stdout.write(color('progress', '  ' + options.open));\n    process.stdout.write(Array(n).join(options.complete));\n    process.stdout.write(Array(i).join(options.incomplete));\n    process.stdout.write(color('progress', options.close));\n    if (options.verbose) {\n      process.stdout.write(color('progress', ' ' + complete + ' of ' + total));\n    }\n  });\n\n  // tests are complete, output some stats\n  // and the failures if any\n  runner.on('end', function(){\n    cursor.show();\n    console.log();\n    self.epilogue();\n  });\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nProgress.prototype = new F;\nProgress.prototype.constructor = Progress;\n\n\n}); // module: reporters/progress.js\n\nrequire.register(\"reporters/spec.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , cursor = Base.cursor\n  , color = Base.color;\n\n/**\n * Expose `Spec`.\n */\n\nexports = module.exports = Spec;\n\n/**\n * Initialize a new `Spec` test reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Spec(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , indents = 0\n    , n = 0;\n\n  function indent() {\n    return Array(indents).join('  ')\n  }\n\n  runner.on('start', function(){\n    console.log();\n  });\n\n  runner.on('suite', function(suite){\n    ++indents;\n    console.log(color('suite', '%s%s'), indent(), suite.title);\n  });\n\n  runner.on('suite end', function(suite){\n    --indents;\n    if (1 == indents) console.log();\n  });\n\n  runner.on('test', function(test){\n    process.stdout.write(indent() + color('pass', '  ◦ ' + test.title + ': '));\n  });\n\n  runner.on('pending', function(test){\n    var fmt = indent() + color('pending', '  - %s');\n    console.log(fmt, test.title);\n  });\n\n  runner.on('pass', function(test){\n    if ('fast' == test.speed) {\n      var fmt = indent()\n        + color('checkmark', '  ' + Base.symbols.ok)\n        + color('pass', ' %s ');\n      cursor.CR();\n      console.log(fmt, test.title);\n    } else {\n      var fmt = indent()\n        + color('checkmark', '  ' + Base.symbols.ok)\n        + color('pass', ' %s ')\n        + color(test.speed, '(%dms)');\n      cursor.CR();\n      console.log(fmt, test.title, test.duration);\n    }\n  });\n\n  runner.on('fail', function(test, err){\n    cursor.CR();\n    console.log(indent() + color('fail', '  %d) %s'), ++n, test.title);\n  });\n\n  runner.on('end', self.epilogue.bind(self));\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nSpec.prototype = new F;\nSpec.prototype.constructor = Spec;\n\n\n}); // module: reporters/spec.js\n\nrequire.register(\"reporters/tap.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , cursor = Base.cursor\n  , color = Base.color;\n\n/**\n * Expose `TAP`.\n */\n\nexports = module.exports = TAP;\n\n/**\n * Initialize a new `TAP` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction TAP(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , n = 1\n    , passes = 0\n    , failures = 0;\n\n  runner.on('start', function(){\n    var total = runner.grepTotal(runner.suite);\n    console.log('%d..%d', 1, total);\n  });\n\n  runner.on('test end', function(){\n    ++n;\n  });\n\n  runner.on('pending', function(test){\n    console.log('ok %d %s # SKIP -', n, title(test));\n  });\n\n  runner.on('pass', function(test){\n    passes++;\n    console.log('ok %d %s', n, title(test));\n  });\n\n  runner.on('fail', function(test, err){\n    failures++;\n    console.log('not ok %d %s', n, title(test));\n    if (err.stack) console.log(err.stack.replace(/^/gm, '  '));\n  });\n\n  runner.on('end', function(){\n    console.log('# tests ' + (passes + failures));\n    console.log('# pass ' + passes);\n    console.log('# fail ' + failures);\n  });\n}\n\n/**\n * Return a TAP-safe title of `test`\n *\n * @param {Object} test\n * @return {String}\n * @api private\n */\n\nfunction title(test) {\n  return test.fullTitle().replace(/#/g, '');\n}\n\n}); // module: reporters/tap.js\n\nrequire.register(\"reporters/teamcity.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base');\n\n/**\n * Expose `Teamcity`.\n */\n\nexports = module.exports = Teamcity;\n\n/**\n * Initialize a new `Teamcity` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Teamcity(runner) {\n  Base.call(this, runner);\n  var stats = this.stats;\n\n  runner.on('start', function() {\n    console.log(\"##teamcity[testSuiteStarted name='mocha.suite']\");\n  });\n\n  runner.on('test', function(test) {\n    console.log(\"##teamcity[testStarted name='\" + escape(test.fullTitle()) + \"']\");\n  });\n\n  runner.on('fail', function(test, err) {\n    console.log(\"##teamcity[testFailed name='\" + escape(test.fullTitle()) + \"' message='\" + escape(err.message) + \"']\");\n  });\n\n  runner.on('pending', function(test) {\n    console.log(\"##teamcity[testIgnored name='\" + escape(test.fullTitle()) + \"' message='pending']\");\n  });\n\n  runner.on('test end', function(test) {\n    console.log(\"##teamcity[testFinished name='\" + escape(test.fullTitle()) + \"' duration='\" + test.duration + \"']\");\n  });\n\n  runner.on('end', function() {\n    console.log(\"##teamcity[testSuiteFinished name='mocha.suite' duration='\" + stats.duration + \"']\");\n  });\n}\n\n/**\n * Escape the given `str`.\n */\n\nfunction escape(str) {\n  return str\n    .replace(/\\|/g, \"||\")\n    .replace(/\\n/g, \"|n\")\n    .replace(/\\r/g, \"|r\")\n    .replace(/\\[/g, \"|[\")\n    .replace(/\\]/g, \"|]\")\n    .replace(/\\u0085/g, \"|x\")\n    .replace(/\\u2028/g, \"|l\")\n    .replace(/\\u2029/g, \"|p\")\n    .replace(/'/g, \"|'\");\n}\n\n}); // module: reporters/teamcity.js\n\nrequire.register(\"reporters/xunit.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , utils = require('../utils')\n  , escape = utils.escape;\n\n/**\n * Save timer references to avoid Sinon interfering (see GH-237).\n */\n\nvar Date = global.Date\n  , setTimeout = global.setTimeout\n  , setInterval = global.setInterval\n  , clearTimeout = global.clearTimeout\n  , clearInterval = global.clearInterval;\n\n/**\n * Expose `XUnit`.\n */\n\nexports = module.exports = XUnit;\n\n/**\n * Initialize a new `XUnit` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction XUnit(runner) {\n  Base.call(this, runner);\n  var stats = this.stats\n    , tests = []\n    , self = this;\n\n  runner.on('pass', function(test){\n    tests.push(test);\n  });\n  \n  runner.on('fail', function(test){\n    tests.push(test);\n  });\n\n  runner.on('end', function(){\n    console.log(tag('testsuite', {\n        name: 'Mocha Tests'\n      , tests: stats.tests\n      , failures: stats.failures\n      , errors: stats.failures\n      , skip: stats.tests - stats.failures - stats.passes\n      , timestamp: (new Date).toUTCString()\n      , time: stats.duration / 1000\n    }, false));\n\n    tests.forEach(test);\n    console.log('</testsuite>');    \n  });\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nXUnit.prototype = new F;\nXUnit.prototype.constructor = XUnit;\n\n\n/**\n * Output tag for the given `test.`\n */\n\nfunction test(test) {\n  var attrs = {\n      classname: test.parent.fullTitle()\n    , name: test.title\n    , time: test.duration / 1000\n  };\n\n  if ('failed' == test.state) {\n    var err = test.err;\n    attrs.message = escape(err.message);\n    console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack))));\n  } else if (test.pending) {\n    console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));\n  } else {\n    console.log(tag('testcase', attrs, true) );\n  }\n}\n\n/**\n * HTML tag helper.\n */\n\nfunction tag(name, attrs, close, content) {\n  var end = close ? '/>' : '>'\n    , pairs = []\n    , tag;\n\n  for (var key in attrs) {\n    pairs.push(key + '=\"' + escape(attrs[key]) + '\"');\n  }\n\n  tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;\n  if (content) tag += content + '</' + name + end;\n  return tag;\n}\n\n/**\n * Return cdata escaped CDATA `str`.\n */\n\nfunction cdata(str) {\n  return '<![CDATA[' + escape(str) + ']]>';\n}\n\n}); // module: reporters/xunit.js\n\nrequire.register(\"runnable.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar EventEmitter = require('browser/events').EventEmitter\n  , debug = require('browser/debug')('mocha:runnable')\n  , milliseconds = require('./ms');\n\n/**\n * Save timer references to avoid Sinon interfering (see GH-237).\n */\n\nvar Date = global.Date\n  , setTimeout = global.setTimeout\n  , setInterval = global.setInterval\n  , clearTimeout = global.clearTimeout\n  , clearInterval = global.clearInterval;\n\n/**\n * Object#toString().\n */\n\nvar toString = Object.prototype.toString;\n\n/**\n * Expose `Runnable`.\n */\n\nmodule.exports = Runnable;\n\n/**\n * Initialize a new `Runnable` with the given `title` and callback `fn`.\n *\n * @param {String} title\n * @param {Function} fn\n * @api private\n */\n\nfunction Runnable(title, fn) {\n  this.title = title;\n  this.fn = fn;\n  this.async = fn && fn.length;\n  this.sync = ! this.async;\n  this._timeout = 2000;\n  this._slow = 75;\n  this.timedOut = false;\n}\n\n/**\n * Inherit from `EventEmitter.prototype`.\n */\n\nfunction F(){};\nF.prototype = EventEmitter.prototype;\nRunnable.prototype = new F;\nRunnable.prototype.constructor = Runnable;\n\n\n/**\n * Set & get timeout `ms`.\n *\n * @param {Number|String} ms\n * @return {Runnable|Number} ms or self\n * @api private\n */\n\nRunnable.prototype.timeout = function(ms){\n  if (0 == arguments.length) return this._timeout;\n  if ('string' == typeof ms) ms = milliseconds(ms);\n  debug('timeout %d', ms);\n  this._timeout = ms;\n  if (this.timer) this.resetTimeout();\n  return this;\n};\n\n/**\n * Set & get slow `ms`.\n *\n * @param {Number|String} ms\n * @return {Runnable|Number} ms or self\n * @api private\n */\n\nRunnable.prototype.slow = function(ms){\n  if (0 === arguments.length) return this._slow;\n  if ('string' == typeof ms) ms = milliseconds(ms);\n  debug('timeout %d', ms);\n  this._slow = ms;\n  return this;\n};\n\n/**\n * Return the full title generated by recursively\n * concatenating the parent's full title.\n *\n * @return {String}\n * @api public\n */\n\nRunnable.prototype.fullTitle = function(){\n  return this.parent.fullTitle() + ' ' + this.title;\n};\n\n/**\n * Clear the timeout.\n *\n * @api private\n */\n\nRunnable.prototype.clearTimeout = function(){\n  clearTimeout(this.timer);\n};\n\n/**\n * Inspect the runnable void of private properties.\n *\n * @return {String}\n * @api private\n */\n\nRunnable.prototype.inspect = function(){\n  return JSON.stringify(this, function(key, val){\n    if ('_' == key[0]) return;\n    if ('parent' == key) return '#<Suite>';\n    if ('ctx' == key) return '#<Context>';\n    return val;\n  }, 2);\n};\n\n/**\n * Reset the timeout.\n *\n * @api private\n */\n\nRunnable.prototype.resetTimeout = function(){\n  var self = this\n    , ms = this.timeout();\n\n  this.clearTimeout();\n  if (ms) {\n    this.timer = setTimeout(function(){\n      self.callback(new Error('timeout of ' + ms + 'ms exceeded'));\n      self.timedOut = true;\n    }, ms);\n  }\n};\n\n/**\n * Run the test and invoke `fn(err)`.\n *\n * @param {Function} fn\n * @api private\n */\n\nRunnable.prototype.run = function(fn){\n  var self = this\n    , ms = this.timeout()\n    , start = new Date\n    , ctx = this.ctx\n    , finished\n    , emitted;\n\n  if (ctx) ctx.runnable(this);\n\n  // timeout\n  if (this.async) {\n    if (ms) {\n      this.timer = setTimeout(function(){\n        done(new Error('timeout of ' + ms + 'ms exceeded'));\n        self.timedOut = true;\n      }, ms);\n    }\n  }\n\n  // called multiple times\n  function multiple(err) {\n    if (emitted) return;\n    emitted = true;\n    self.emit('error', err || new Error('done() called multiple times'));\n  }\n\n  // finished\n  function done(err) {\n    if (self.timedOut) return;\n    if (finished) return multiple(err);\n    self.clearTimeout();\n    self.duration = new Date - start;\n    finished = true;\n    fn(err);\n  }\n\n  // for .resetTimeout()\n  this.callback = done;\n\n  // async\n  if (this.async) {\n    try {\n      this.fn.call(ctx, function(err){\n        if (err instanceof Error || toString.call(err) === \"[object Error]\") return done(err);\n        if (null != err) return done(new Error('done() invoked with non-Error: ' + err));\n        done();\n      });\n    } catch (err) {\n      done(err);\n    }\n    return;\n  }\n\n  if (this.asyncOnly) {\n    return done(new Error('--async-only option in use without declaring `done()`'));\n  }\n\n  // sync\n  try {\n    if (!this.pending) this.fn.call(ctx);\n    this.duration = new Date - start;\n    fn();\n  } catch (err) {\n    fn(err);\n  }\n};\n\n}); // module: runnable.js\n\nrequire.register(\"runner.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar EventEmitter = require('browser/events').EventEmitter\n  , debug = require('browser/debug')('mocha:runner')\n  , Test = require('./test')\n  , utils = require('./utils')\n  , filter = utils.filter\n  , keys = utils.keys\n  , noop = function(){};\n\n/**\n * Non-enumerable globals.\n */\n\nvar globals = [\n  'setTimeout',\n  'clearTimeout',\n  'setInterval',\n  'clearInterval',\n  'XMLHttpRequest',\n  'Date'\n];\n\n/**\n * Expose `Runner`.\n */\n\nmodule.exports = Runner;\n\n/**\n * Initialize a `Runner` for the given `suite`.\n *\n * Events:\n *\n *   - `start`  execution started\n *   - `end`  execution complete\n *   - `suite`  (suite) test suite execution started\n *   - `suite end`  (suite) all tests (and sub-suites) have finished\n *   - `test`  (test) test execution started\n *   - `test end`  (test) test completed\n *   - `hook`  (hook) hook execution started\n *   - `hook end`  (hook) hook complete\n *   - `pass`  (test) test passed\n *   - `fail`  (test, err) test failed\n *\n * @api public\n */\n\nfunction Runner(suite) {\n  var self = this;\n  this._globals = [];\n  this.suite = suite;\n  this.total = suite.total();\n  this.failures = 0;\n  this.on('test end', function(test){ self.checkGlobals(test); });\n  this.on('hook end', function(hook){ self.checkGlobals(hook); });\n  this.grep(/.*/);\n  this.globals(this.globalProps().concat(['errno']));\n}\n\n/**\n * Inherit from `EventEmitter.prototype`.\n */\n\nfunction F(){};\nF.prototype = EventEmitter.prototype;\nRunner.prototype = new F;\nRunner.prototype.constructor = Runner;\n\n\n/**\n * Run tests with full titles matching `re`. Updates runner.total\n * with number of tests matched.\n *\n * @param {RegExp} re\n * @param {Boolean} invert\n * @return {Runner} for chaining\n * @api public\n */\n\nRunner.prototype.grep = function(re, invert){\n  debug('grep %s', re);\n  this._grep = re;\n  this._invert = invert;\n  this.total = this.grepTotal(this.suite);\n  return this;\n};\n\n/**\n * Returns the number of tests matching the grep search for the\n * given suite.\n *\n * @param {Suite} suite\n * @return {Number}\n * @api public\n */\n\nRunner.prototype.grepTotal = function(suite) {\n  var self = this;\n  var total = 0;\n\n  suite.eachTest(function(test){\n    var match = self._grep.test(test.fullTitle());\n    if (self._invert) match = !match;\n    if (match) total++;\n  });\n\n  return total;\n};\n\n/**\n * Return a list of global properties.\n *\n * @return {Array}\n * @api private\n */\n\nRunner.prototype.globalProps = function() {\n  var props = utils.keys(global);\n\n  // non-enumerables\n  for (var i = 0; i < globals.length; ++i) {\n    if (~utils.indexOf(props, globals[i])) continue;\n    props.push(globals[i]);\n  }\n\n  return props;\n};\n\n/**\n * Allow the given `arr` of globals.\n *\n * @param {Array} arr\n * @return {Runner} for chaining\n * @api public\n */\n\nRunner.prototype.globals = function(arr){\n  if (0 == arguments.length) return this._globals;\n  debug('globals %j', arr);\n  utils.forEach(arr, function(arr){\n    this._globals.push(arr);\n  }, this);\n  return this;\n};\n\n/**\n * Check for global variable leaks.\n *\n * @api private\n */\n\nRunner.prototype.checkGlobals = function(test){\n  if (this.ignoreLeaks) return;\n  var ok = this._globals;\n  var globals = this.globalProps();\n  var isNode = process.kill;\n  var leaks;\n\n  // check length - 2 ('errno' and 'location' globals)\n  if (isNode && 1 == ok.length - globals.length) return\n  else if (2 == ok.length - globals.length) return;\n\n  leaks = filterLeaks(ok, globals);\n  this._globals = this._globals.concat(leaks);\n\n  if (leaks.length > 1) {\n    this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + ''));\n  } else if (leaks.length) {\n    this.fail(test, new Error('global leak detected: ' + leaks[0]));\n  }\n};\n\n/**\n * Fail the given `test`.\n *\n * @param {Test} test\n * @param {Error} err\n * @api private\n */\n\nRunner.prototype.fail = function(test, err){\n  ++this.failures;\n  test.state = 'failed';\n\n  if ('string' == typeof err) {\n    err = new Error('the string \"' + err + '\" was thrown, throw an Error :)');\n  }\n  \n  this.emit('fail', test, err);\n};\n\n/**\n * Fail the given `hook` with `err`.\n *\n * Hook failures (currently) hard-end due\n * to that fact that a failing hook will\n * surely cause subsequent tests to fail,\n * causing jumbled reporting.\n *\n * @param {Hook} hook\n * @param {Error} err\n * @api private\n */\n\nRunner.prototype.failHook = function(hook, err){\n  this.fail(hook, err);\n  this.emit('end');\n};\n\n/**\n * Run hook `name` callbacks and then invoke `fn()`.\n *\n * @param {String} name\n * @param {Function} function\n * @api private\n */\n\nRunner.prototype.hook = function(name, fn){\n  var suite = this.suite\n    , hooks = suite['_' + name]\n    , self = this\n    , timer;\n\n  function next(i) {\n    var hook = hooks[i];\n    if (!hook) return fn();\n    self.currentRunnable = hook;\n\n    self.emit('hook', hook);\n\n    hook.on('error', function(err){\n      self.failHook(hook, err);\n    });\n\n    hook.run(function(err){\n      hook.removeAllListeners('error');\n      var testError = hook.error();\n      if (testError) self.fail(self.test, testError);\n      if (err) return self.failHook(hook, err);\n      self.emit('hook end', hook);\n      next(++i);\n    });\n  }\n\n  process.nextTick(function(){\n    next(0);\n  });\n};\n\n/**\n * Run hook `name` for the given array of `suites`\n * in order, and callback `fn(err)`.\n *\n * @param {String} name\n * @param {Array} suites\n * @param {Function} fn\n * @api private\n */\n\nRunner.prototype.hooks = function(name, suites, fn){\n  var self = this\n    , orig = this.suite;\n\n  function next(suite) {\n    self.suite = suite;\n\n    if (!suite) {\n      self.suite = orig;\n      return fn();\n    }\n\n    self.hook(name, function(err){\n      if (err) {\n        self.suite = orig;\n        return fn(err);\n      }\n\n      next(suites.pop());\n    });\n  }\n\n  next(suites.pop());\n};\n\n/**\n * Run hooks from the top level down.\n *\n * @param {String} name\n * @param {Function} fn\n * @api private\n */\n\nRunner.prototype.hookUp = function(name, fn){\n  var suites = [this.suite].concat(this.parents()).reverse();\n  this.hooks(name, suites, fn);\n};\n\n/**\n * Run hooks from the bottom up.\n *\n * @param {String} name\n * @param {Function} fn\n * @api private\n */\n\nRunner.prototype.hookDown = function(name, fn){\n  var suites = [this.suite].concat(this.parents());\n  this.hooks(name, suites, fn);\n};\n\n/**\n * Return an array of parent Suites from\n * closest to furthest.\n *\n * @return {Array}\n * @api private\n */\n\nRunner.prototype.parents = function(){\n  var suite = this.suite\n    , suites = [];\n  while (suite = suite.parent) suites.push(suite);\n  return suites;\n};\n\n/**\n * Run the current test and callback `fn(err)`.\n *\n * @param {Function} fn\n * @api private\n */\n\nRunner.prototype.runTest = function(fn){\n  var test = this.test\n    , self = this;\n\n  if (this.asyncOnly) test.asyncOnly = true;\n\n  try {\n    test.on('error', function(err){\n      self.fail(test, err);\n    });\n    test.run(fn);\n  } catch (err) {\n    fn(err);\n  }\n};\n\n/**\n * Run tests in the given `suite` and invoke\n * the callback `fn()` when complete.\n *\n * @param {Suite} suite\n * @param {Function} fn\n * @api private\n */\n\nRunner.prototype.runTests = function(suite, fn){\n  var self = this\n    , tests = suite.tests.slice()\n    , test;\n\n  function next(err) {\n    // if we bail after first err\n    if (self.failures && suite._bail) return fn();\n\n    // next test\n    test = tests.shift();\n\n    // all done\n    if (!test) return fn();\n\n    // grep\n    var match = self._grep.test(test.fullTitle());\n    if (self._invert) match = !match;\n    if (!match) return next();\n\n    // pending\n    if (test.pending) {\n      self.emit('pending', test);\n      self.emit('test end', test);\n      return next();\n    }\n\n    // execute test and hook(s)\n    self.emit('test', self.test = test);\n    self.hookDown('beforeEach', function(){\n      self.currentRunnable = self.test;\n      self.runTest(function(err){\n        test = self.test;\n\n        if (err) {\n          self.fail(test, err);\n          self.emit('test end', test);\n          return self.hookUp('afterEach', next);\n        }\n\n        test.state = 'passed';\n        self.emit('pass', test);\n        self.emit('test end', test);\n        self.hookUp('afterEach', next);\n      });\n    });\n  }\n\n  this.next = next;\n  next();\n};\n\n/**\n * Run the given `suite` and invoke the\n * callback `fn()` when complete.\n *\n * @param {Suite} suite\n * @param {Function} fn\n * @api private\n */\n\nRunner.prototype.runSuite = function(suite, fn){\n  var total = this.grepTotal(suite)\n    , self = this\n    , i = 0;\n\n  debug('run suite %s', suite.fullTitle());\n\n  if (!total) return fn();\n\n  this.emit('suite', this.suite = suite);\n\n  function next() {\n    var curr = suite.suites[i++];\n    if (!curr) return done();\n    self.runSuite(curr, next);\n  }\n\n  function done() {\n    self.suite = suite;\n    self.hook('afterAll', function(){\n      self.emit('suite end', suite);\n      fn();\n    });\n  }\n\n  this.hook('beforeAll', function(){\n    self.runTests(suite, next);\n  });\n};\n\n/**\n * Handle uncaught exceptions.\n *\n * @param {Error} err\n * @api private\n */\n\nRunner.prototype.uncaught = function(err){\n  debug('uncaught exception %s', err.message);\n  var runnable = this.currentRunnable;\n  if (!runnable || 'failed' == runnable.state) return;\n  runnable.clearTimeout();\n  err.uncaught = true;\n  this.fail(runnable, err);\n\n  // recover from test\n  if ('test' == runnable.type) {\n    this.emit('test end', runnable);\n    this.hookUp('afterEach', this.next);\n    return;\n  }\n\n  // bail on hooks\n  this.emit('end');\n};\n\n/**\n * Run the root suite and invoke `fn(failures)`\n * on completion.\n *\n * @param {Function} fn\n * @return {Runner} for chaining\n * @api public\n */\n\nRunner.prototype.run = function(fn){\n  var self = this\n    , fn = fn || function(){};\n\n  debug('start');\n\n  // callback\n  this.on('end', function(){\n    debug('end');\n    process.removeListener('uncaughtException', function(err){\n      self.uncaught(err);\n    });\n    fn(self.failures);\n  });\n\n  // run suites\n  this.emit('start');\n  this.runSuite(this.suite, function(){\n    debug('finished running');\n    self.emit('end');\n  });\n\n  // uncaught exception\n  process.on('uncaughtException', function(err){\n    self.uncaught(err);\n  });\n\n  return this;\n};\n\n/**\n * Filter leaks with the given globals flagged as `ok`.\n *\n * @param {Array} ok\n * @param {Array} globals\n * @return {Array}\n * @api private\n */\n\nfunction filterLeaks(ok, globals) {\n  return filter(globals, function(key){\n    var matched = filter(ok, function(ok){\n      if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]);\n      // Opera and IE expose global variables for HTML element IDs (issue #243)\n      if (/^mocha-/.test(key)) return true;\n      return key == ok;\n    });\n    return matched.length == 0 && (!global.navigator || 'onerror' !== key);\n  });\n}\n\n}); // module: runner.js\n\nrequire.register(\"suite.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar EventEmitter = require('browser/events').EventEmitter\n  , debug = require('browser/debug')('mocha:suite')\n  , milliseconds = require('./ms')\n  , utils = require('./utils')\n  , Hook = require('./hook');\n\n/**\n * Expose `Suite`.\n */\n\nexports = module.exports = Suite;\n\n/**\n * Create a new `Suite` with the given `title`\n * and parent `Suite`. When a suite with the\n * same title is already present, that suite\n * is returned to provide nicer reporter\n * and more flexible meta-testing.\n *\n * @param {Suite} parent\n * @param {String} title\n * @return {Suite}\n * @api public\n */\n\nexports.create = function(parent, title){\n  var suite = new Suite(title, parent.ctx);\n  suite.parent = parent;\n  if (parent.pending) suite.pending = true;\n  title = suite.fullTitle();\n  parent.addSuite(suite);\n  return suite;\n};\n\n/**\n * Initialize a new `Suite` with the given\n * `title` and `ctx`.\n *\n * @param {String} title\n * @param {Context} ctx\n * @api private\n */\n\nfunction Suite(title, ctx) {\n  this.title = title;\n  this.ctx = ctx;\n  this.suites = [];\n  this.tests = [];\n  this.pending = false;\n  this._beforeEach = [];\n  this._beforeAll = [];\n  this._afterEach = [];\n  this._afterAll = [];\n  this.root = !title;\n  this._timeout = 2000;\n  this._slow = 75;\n  this._bail = false;\n}\n\n/**\n * Inherit from `EventEmitter.prototype`.\n */\n\nfunction F(){};\nF.prototype = EventEmitter.prototype;\nSuite.prototype = new F;\nSuite.prototype.constructor = Suite;\n\n\n/**\n * Return a clone of this `Suite`.\n *\n * @return {Suite}\n * @api private\n */\n\nSuite.prototype.clone = function(){\n  var suite = new Suite(this.title);\n  debug('clone');\n  suite.ctx = this.ctx;\n  suite.timeout(this.timeout());\n  suite.slow(this.slow());\n  suite.bail(this.bail());\n  return suite;\n};\n\n/**\n * Set timeout `ms` or short-hand such as \"2s\".\n *\n * @param {Number|String} ms\n * @return {Suite|Number} for chaining\n * @api private\n */\n\nSuite.prototype.timeout = function(ms){\n  if (0 == arguments.length) return this._timeout;\n  if ('string' == typeof ms) ms = milliseconds(ms);\n  debug('timeout %d', ms);\n  this._timeout = parseInt(ms, 10);\n  return this;\n};\n\n/**\n * Set slow `ms` or short-hand such as \"2s\".\n *\n * @param {Number|String} ms\n * @return {Suite|Number} for chaining\n * @api private\n */\n\nSuite.prototype.slow = function(ms){\n  if (0 === arguments.length) return this._slow;\n  if ('string' == typeof ms) ms = milliseconds(ms);\n  debug('slow %d', ms);\n  this._slow = ms;\n  return this;\n};\n\n/**\n * Sets whether to bail after first error.\n *\n * @parma {Boolean} bail\n * @return {Suite|Number} for chaining\n * @api private\n */\n\nSuite.prototype.bail = function(bail){\n  if (0 == arguments.length) return this._bail;\n  debug('bail %s', bail);\n  this._bail = bail;\n  return this;\n};\n\n/**\n * Run `fn(test[, done])` before running tests.\n *\n * @param {Function} fn\n * @return {Suite} for chaining\n * @api private\n */\n\nSuite.prototype.beforeAll = function(fn){\n  if (this.pending) return this;\n  var hook = new Hook('\"before all\" hook', fn);\n  hook.parent = this;\n  hook.timeout(this.timeout());\n  hook.slow(this.slow());\n  hook.ctx = this.ctx;\n  this._beforeAll.push(hook);\n  this.emit('beforeAll', hook);\n  return this;\n};\n\n/**\n * Run `fn(test[, done])` after running tests.\n *\n * @param {Function} fn\n * @return {Suite} for chaining\n * @api private\n */\n\nSuite.prototype.afterAll = function(fn){\n  if (this.pending) return this;\n  var hook = new Hook('\"after all\" hook', fn);\n  hook.parent = this;\n  hook.timeout(this.timeout());\n  hook.slow(this.slow());\n  hook.ctx = this.ctx;\n  this._afterAll.push(hook);\n  this.emit('afterAll', hook);\n  return this;\n};\n\n/**\n * Run `fn(test[, done])` before each test case.\n *\n * @param {Function} fn\n * @return {Suite} for chaining\n * @api private\n */\n\nSuite.prototype.beforeEach = function(fn){\n  if (this.pending) return this;\n  var hook = new Hook('\"before each\" hook', fn);\n  hook.parent = this;\n  hook.timeout(this.timeout());\n  hook.slow(this.slow());\n  hook.ctx = this.ctx;\n  this._beforeEach.push(hook);\n  this.emit('beforeEach', hook);\n  return this;\n};\n\n/**\n * Run `fn(test[, done])` after each test case.\n *\n * @param {Function} fn\n * @return {Suite} for chaining\n * @api private\n */\n\nSuite.prototype.afterEach = function(fn){\n  if (this.pending) return this;\n  var hook = new Hook('\"after each\" hook', fn);\n  hook.parent = this;\n  hook.timeout(this.timeout());\n  hook.slow(this.slow());\n  hook.ctx = this.ctx;\n  this._afterEach.push(hook);\n  this.emit('afterEach', hook);\n  return this;\n};\n\n/**\n * Add a test `suite`.\n *\n * @param {Suite} suite\n * @return {Suite} for chaining\n * @api private\n */\n\nSuite.prototype.addSuite = function(suite){\n  suite.parent = this;\n  suite.timeout(this.timeout());\n  suite.slow(this.slow());\n  suite.bail(this.bail());\n  this.suites.push(suite);\n  this.emit('suite', suite);\n  return this;\n};\n\n/**\n * Add a `test` to this suite.\n *\n * @param {Test} test\n * @return {Suite} for chaining\n * @api private\n */\n\nSuite.prototype.addTest = function(test){\n  test.parent = this;\n  test.timeout(this.timeout());\n  test.slow(this.slow());\n  test.ctx = this.ctx;\n  this.tests.push(test);\n  this.emit('test', test);\n  return this;\n};\n\n/**\n * Return the full title generated by recursively\n * concatenating the parent's full title.\n *\n * @return {String}\n * @api public\n */\n\nSuite.prototype.fullTitle = function(){\n  if (this.parent) {\n    var full = this.parent.fullTitle();\n    if (full) return full + ' ' + this.title;\n  }\n  return this.title;\n};\n\n/**\n * Return the total number of tests.\n *\n * @return {Number}\n * @api public\n */\n\nSuite.prototype.total = function(){\n  return utils.reduce(this.suites, function(sum, suite){\n    return sum + suite.total();\n  }, 0) + this.tests.length;\n};\n\n/**\n * Iterates through each suite recursively to find\n * all tests. Applies a function in the format\n * `fn(test)`.\n *\n * @param {Function} fn\n * @return {Suite}\n * @api private\n */\n\nSuite.prototype.eachTest = function(fn){\n  utils.forEach(this.tests, fn);\n  utils.forEach(this.suites, function(suite){\n    suite.eachTest(fn);\n  });\n  return this;\n};\n\n}); // module: suite.js\n\nrequire.register(\"test.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Runnable = require('./runnable');\n\n/**\n * Expose `Test`.\n */\n\nmodule.exports = Test;\n\n/**\n * Initialize a new `Test` with the given `title` and callback `fn`.\n *\n * @param {String} title\n * @param {Function} fn\n * @api private\n */\n\nfunction Test(title, fn) {\n  Runnable.call(this, title, fn);\n  this.pending = !fn;\n  this.type = 'test';\n}\n\n/**\n * Inherit from `Runnable.prototype`.\n */\n\nfunction F(){};\nF.prototype = Runnable.prototype;\nTest.prototype = new F;\nTest.prototype.constructor = Test;\n\n\n}); // module: test.js\n\nrequire.register(\"utils.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar fs = require('browser/fs')\n  , path = require('browser/path')\n  , join = path.join\n  , debug = require('browser/debug')('mocha:watch');\n\n/**\n * Ignored directories.\n */\n\nvar ignore = ['node_modules', '.git'];\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param  {String} html\n * @return {String}\n * @api private\n */\n\nexports.escape = function(html){\n  return String(html)\n    .replace(/&/g, '&amp;')\n    .replace(/\"/g, '&quot;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;');\n};\n\n/**\n * Array#forEach (<=IE8)\n *\n * @param {Array} array\n * @param {Function} fn\n * @param {Object} scope\n * @api private\n */\n\nexports.forEach = function(arr, fn, scope){\n  for (var i = 0, l = arr.length; i < l; i++)\n    fn.call(scope, arr[i], i);\n};\n\n/**\n * Array#indexOf (<=IE8)\n *\n * @parma {Array} arr\n * @param {Object} obj to find index of\n * @param {Number} start\n * @api private\n */\n\nexports.indexOf = function(arr, obj, start){\n  for (var i = start || 0, l = arr.length; i < l; i++) {\n    if (arr[i] === obj)\n      return i;\n  }\n  return -1;\n};\n\n/**\n * Array#reduce (<=IE8)\n * \n * @param {Array} array\n * @param {Function} fn\n * @param {Object} initial value\n * @api private\n */\n\nexports.reduce = function(arr, fn, val){\n  var rval = val;\n\n  for (var i = 0, l = arr.length; i < l; i++) {\n    rval = fn(rval, arr[i], i, arr);\n  }\n\n  return rval;\n};\n\n/**\n * Array#filter (<=IE8)\n *\n * @param {Array} array\n * @param {Function} fn\n * @api private\n */\n\nexports.filter = function(arr, fn){\n  var ret = [];\n\n  for (var i = 0, l = arr.length; i < l; i++) {\n    var val = arr[i];\n    if (fn(val, i, arr)) ret.push(val);\n  }\n\n  return ret;\n};\n\n/**\n * Object.keys (<=IE8)\n *\n * @param {Object} obj\n * @return {Array} keys\n * @api private\n */\n\nexports.keys = Object.keys || function(obj) {\n  var keys = []\n    , has = Object.prototype.hasOwnProperty // for `window` on <=IE8\n\n  for (var key in obj) {\n    if (has.call(obj, key)) {\n      keys.push(key);\n    }\n  }\n\n  return keys;\n};\n\n/**\n * Watch the given `files` for changes\n * and invoke `fn(file)` on modification.\n *\n * @param {Array} files\n * @param {Function} fn\n * @api private\n */\n\nexports.watch = function(files, fn){\n  var options = { interval: 100 };\n  files.forEach(function(file){\n    debug('file %s', file);\n    fs.watchFile(file, options, function(curr, prev){\n      if (prev.mtime < curr.mtime) fn(file);\n    });\n  });\n};\n\n/**\n * Ignored files.\n */\n\nfunction ignored(path){\n  return !~ignore.indexOf(path);\n}\n\n/**\n * Lookup files in the given `dir`.\n *\n * @return {Array}\n * @api private\n */\n\nexports.files = function(dir, ret){\n  ret = ret || [];\n\n  fs.readdirSync(dir)\n  .filter(ignored)\n  .forEach(function(path){\n    path = join(dir, path);\n    if (fs.statSync(path).isDirectory()) {\n      exports.files(path, ret);\n    } else if (path.match(/\\.(js|coffee)$/)) {\n      ret.push(path);\n    }\n  });\n\n  return ret;\n};\n\n/**\n * Compute a slug from the given `str`.\n *\n * @param {String} str\n * @return {String}\n * @api private\n */\n\nexports.slug = function(str){\n  return str\n    .toLowerCase()\n    .replace(/ +/g, '-')\n    .replace(/[^-\\w]/g, '');\n};\n\n/**\n * Strip the function definition from `str`,\n * and re-indent for pre whitespace.\n */\n\nexports.clean = function(str) {\n  str = str\n    .replace(/^function *\\(.*\\) *{/, '')\n    .replace(/\\s+\\}$/, '');\n\n  var spaces = str.match(/^\\n?( *)/)[1].length\n    , re = new RegExp('^ {' + spaces + '}', 'gm');\n\n  str = str.replace(re, '');\n\n  return exports.trim(str);\n};\n\n/**\n * Escape regular expression characters in `str`.\n *\n * @param {String} str\n * @return {String}\n * @api private\n */\n\nexports.escapeRegexp = function(str){\n  return str.replace(/[-\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\");\n};\n\n/**\n * Trim the given `str`.\n *\n * @param {String} str\n * @return {String}\n * @api private\n */\n\nexports.trim = function(str){\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n/**\n * Parse the given `qs`.\n *\n * @param {String} qs\n * @return {Object}\n * @api private\n */\n\nexports.parseQuery = function(qs){\n  return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){\n    var i = pair.indexOf('=')\n      , key = pair.slice(0, i)\n      , val = pair.slice(++i);\n\n    obj[key] = decodeURIComponent(val);\n    return obj;\n  }, {});\n};\n\n/**\n * Highlight the given string of `js`.\n *\n * @param {String} js\n * @return {String}\n * @api private\n */\n\nfunction highlight(js) {\n  return js\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\\/\\/(.*)/gm, '<span class=\"comment\">//$1</span>')\n    .replace(/('.*?')/gm, '<span class=\"string\">$1</span>')\n    .replace(/(\\d+\\.\\d+)/gm, '<span class=\"number\">$1</span>')\n    .replace(/(\\d+)/gm, '<span class=\"number\">$1</span>')\n    .replace(/\\bnew *(\\w+)/gm, '<span class=\"keyword\">new</span> <span class=\"init\">$1</span>')\n    .replace(/\\b(function|new|throw|return|var|if|else)\\b/gm, '<span class=\"keyword\">$1</span>')\n}\n\n/**\n * Highlight the contents of tag `name`.\n *\n * @param {String} name\n * @api private\n */\n\nexports.highlightTags = function(name) {\n  var code = document.getElementsByTagName(name);\n  for (var i = 0, len = code.length; i < len; ++i) {\n    code[i].innerHTML = highlight(code[i].innerHTML);\n  }\n};\n\n}); // module: utils.js\n/**\n * Node shims.\n *\n * These are meant only to allow\n * mocha.js to run untouched, not\n * to allow running node code in\n * the browser.\n */\n\nprocess = {};\nprocess.exit = function(status){};\nprocess.stdout = {};\nglobal = window;\n\n/**\n * next tick implementation.\n */\n\nprocess.nextTick = (function(){\n  // postMessage behaves badly on IE8\n  if (window.ActiveXObject || !window.postMessage) {\n    return function(fn){ fn() };\n  }\n\n  // based on setZeroTimeout by David Baron\n  // - http://dbaron.org/log/20100309-faster-timeouts\n  var timeouts = []\n    , name = 'mocha-zero-timeout'\n\n  window.addEventListener('message', function(e){\n    if (e.source == window && e.data == name) {\n      if (e.stopPropagation) e.stopPropagation();\n      if (timeouts.length) timeouts.shift()();\n    }\n  }, true);\n\n  return function(fn){\n    timeouts.push(fn);\n    window.postMessage(name, '*');\n  }\n})();\n\n/**\n * Remove uncaughtException listener.\n */\n\nprocess.removeListener = function(e){\n  if ('uncaughtException' == e) {\n    window.onerror = null;\n  }\n};\n\n/**\n * Implements uncaughtException listener.\n */\n\nprocess.on = function(e, fn){\n  if ('uncaughtException' == e) {\n    window.onerror = function(err, url, line){\n      fn(new Error(err + ' (' + url + ':' + line + ')'));\n    };\n  }\n};\n\n// boot\n;(function(){\n\n  /**\n   * Expose mocha.\n   */\n\n  var Mocha = window.Mocha = require('mocha'),\n      mocha = window.mocha = new Mocha({ reporter: 'html' });\n\n  /**\n   * Override ui to ensure that the ui functions are initialized.\n   * Normally this would happen in Mocha.prototype.loadFiles.\n   */\n\n  mocha.ui = function(ui){\n    Mocha.prototype.ui.call(this, ui);\n    this.suite.emit('pre-require', window, null, this);\n    return this;\n  };\n\n  /**\n   * Setup mocha with the given setting options.\n   */\n\n  mocha.setup = function(opts){\n    if ('string' == typeof opts) opts = { ui: opts };\n    for (var opt in opts) this[opt](opts[opt]);\n    return this;\n  };\n\n  /**\n   * Run mocha, returning the Runner.\n   */\n\n  mocha.run = function(fn){\n    var options = mocha.options;\n    mocha.globals('location');\n\n    var query = Mocha.utils.parseQuery(window.location.search || '');\n    if (query.grep) mocha.grep(query.grep);\n    if (query.invert) mocha.invert();\n\n    return Mocha.prototype.run.call(mocha, function(){\n      Mocha.utils.highlightTags('code');\n      if (fn) fn();\n    });\n  };\n})();\n})();"
  },
  {
    "path": "test/spec/test.js",
    "content": "/*global describe, it */\n'use strict';\n(function () {\n    describe('Give it some context', function () {\n        describe('maybe a bit more context here', function () {\n            it('should run here few assertions', function () {\n\n            });\n        });\n    });\n})();\n"
  },
  {
    "path": "todo.txt",
    "content": "fix compression issue with codemirror\nfix issue where +/- buttons dont work on script node\nfont-awesome 404\n\ndo not allow dragging node too far\nzoom from center in workspace\nwhy is drag so slow?\ndeletion is too slow\nenter custom node by double clicking on the node instance\npaste should be offset to workspace center\nmove stl export code out of workspacecontrolsview\n\nCUSTOM NODES\n\ndon't show previews in custom node workspaces\n\nWORKSPACES MENU\n\nformula node input should change width based on how much user inputs, allow multiple lines\nformula node does not allow \"quotes\"\ndisable node lacing\nicons for nodes\nshould remember the old 3d orientation\n\nFEATURE\n\nexample workspaces!\nfork a workspace\nshare workspaces\ndescribe workspace\narbitrary javascript node - better than formula\nNURBS in flood\nrun execution in ui thread, make calls to ui thread from worker\n\nTHOUGHTS\n\nverb: \n\tbreps\n\tuse distributed computation\n\tuse a neural network to train system for local or remote exec\nflood: \n\tpromise-based execution would allow multiple execution paths to proceed in parallel if nodes are dispatched async - this is a VERY good idea\n"
  }
]