diff --git a/.travis.yml b/.travis.yml
index e2fe43667..3486ab76b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,7 +25,7 @@ before_script:
   - export DISPLAY=:99.0
   - sh -e /etc/init.d/xvfb start
   - "node index.js --unittest &"
-  - "sleep 10" # to give node a chance to start
+  - "sleep 15" # to give node a chance to start
 
 script:
   - "./node_modules/karma/bin/karma start --browsers Firefox --single-run --reporters progress"
diff --git a/app/assets/docs/CodeCombatCoursesGettingStartedGuide.pdf b/app/assets/docs/CodeCombatCoursesGettingStartedGuide.pdf
old mode 100644
new mode 100755
index 97f5b2ddb..9e6241dd5
Binary files a/app/assets/docs/CodeCombatCoursesGettingStartedGuide.pdf and b/app/assets/docs/CodeCombatCoursesGettingStartedGuide.pdf differ
diff --git a/app/assets/docs/CodeCombatTeacherGuideCourse2.pdf b/app/assets/docs/CodeCombatTeacherGuideCourse2.pdf
new file mode 100644
index 000000000..32dbae708
Binary files /dev/null and b/app/assets/docs/CodeCombatTeacherGuideCourse2.pdf differ
diff --git a/app/assets/images/Adobe_PDF_file_icon_32x32.png b/app/assets/images/Adobe_PDF_file_icon_32x32.png
index c24f66c04..b8037de23 100644
Binary files a/app/assets/images/Adobe_PDF_file_icon_32x32.png and b/app/assets/images/Adobe_PDF_file_icon_32x32.png differ
diff --git a/app/assets/images/achievements/achievement_background.png b/app/assets/images/achievements/achievement_background.png
index c74ff1bf2..69bfad33b 100644
Binary files a/app/assets/images/achievements/achievement_background.png and b/app/assets/images/achievements/achievement_background.png differ
diff --git a/app/assets/images/achievements/achievement_background_light.png b/app/assets/images/achievements/achievement_background_light.png
index 53e09e62d..685d763cb 100644
Binary files a/app/assets/images/achievements/achievement_background_light.png and b/app/assets/images/achievements/achievement_background_light.png differ
diff --git a/app/assets/images/achievements/achievement_background_locked.png b/app/assets/images/achievements/achievement_background_locked.png
index 94a300b12..5af8bf3d7 100644
Binary files a/app/assets/images/achievements/achievement_background_locked.png and b/app/assets/images/achievements/achievement_background_locked.png differ
diff --git a/app/assets/images/achievements/bar_border.png b/app/assets/images/achievements/bar_border.png
index 9ad03ef20..8d1997e5e 100644
Binary files a/app/assets/images/achievements/bar_border.png and b/app/assets/images/achievements/bar_border.png differ
diff --git a/app/assets/images/achievements/border_diamond.png b/app/assets/images/achievements/border_diamond.png
index a2e10f8f0..80d56674b 100644
Binary files a/app/assets/images/achievements/border_diamond.png and b/app/assets/images/achievements/border_diamond.png differ
diff --git a/app/assets/images/achievements/border_diamond_locked.png b/app/assets/images/achievements/border_diamond_locked.png
index bc56fbc75..47aadf5ac 100644
Binary files a/app/assets/images/achievements/border_diamond_locked.png and b/app/assets/images/achievements/border_diamond_locked.png differ
diff --git a/app/assets/images/achievements/border_gold.png b/app/assets/images/achievements/border_gold.png
index 7a46157c1..b60af78da 100644
Binary files a/app/assets/images/achievements/border_gold.png and b/app/assets/images/achievements/border_gold.png differ
diff --git a/app/assets/images/achievements/border_gold_locked.png b/app/assets/images/achievements/border_gold_locked.png
index f1ee95e3d..3a07cf0b2 100644
Binary files a/app/assets/images/achievements/border_gold_locked.png and b/app/assets/images/achievements/border_gold_locked.png differ
diff --git a/app/assets/images/achievements/border_silver.png b/app/assets/images/achievements/border_silver.png
index 016d48b00..17fe84230 100644
Binary files a/app/assets/images/achievements/border_silver.png and b/app/assets/images/achievements/border_silver.png differ
diff --git a/app/assets/images/achievements/border_silver_locked.png b/app/assets/images/achievements/border_silver_locked.png
index 44bcc7e84..e1885b8f1 100644
Binary files a/app/assets/images/achievements/border_silver_locked.png and b/app/assets/images/achievements/border_silver_locked.png differ
diff --git a/app/assets/images/achievements/border_stone.png b/app/assets/images/achievements/border_stone.png
index 7d13718ce..8e216f529 100644
Binary files a/app/assets/images/achievements/border_stone.png and b/app/assets/images/achievements/border_stone.png differ
diff --git a/app/assets/images/achievements/border_stone_locked.png b/app/assets/images/achievements/border_stone_locked.png
index 66f92b2b4..4ce368aca 100644
Binary files a/app/assets/images/achievements/border_stone_locked.png and b/app/assets/images/achievements/border_stone_locked.png differ
diff --git a/app/assets/images/achievements/border_wood.png b/app/assets/images/achievements/border_wood.png
index 368878c20..67eb09390 100644
Binary files a/app/assets/images/achievements/border_wood.png and b/app/assets/images/achievements/border_wood.png differ
diff --git a/app/assets/images/achievements/border_wood_locked.png b/app/assets/images/achievements/border_wood_locked.png
index 167e87421..216d7e40a 100644
Binary files a/app/assets/images/achievements/border_wood_locked.png and b/app/assets/images/achievements/border_wood_locked.png differ
diff --git a/app/assets/images/achievements/cross-01.png b/app/assets/images/achievements/cross-01.png
index 6a2ab02ef..6090d9ae0 100644
Binary files a/app/assets/images/achievements/cross-01.png and b/app/assets/images/achievements/cross-01.png differ
diff --git a/app/assets/images/achievements/cup-01.png b/app/assets/images/achievements/cup-01.png
index 3b4c4c40b..b3ffa884e 100644
Binary files a/app/assets/images/achievements/cup-01.png and b/app/assets/images/achievements/cup-01.png differ
diff --git a/app/assets/images/achievements/cup-02.png b/app/assets/images/achievements/cup-02.png
index 0eba69463..680c1159b 100644
Binary files a/app/assets/images/achievements/cup-02.png and b/app/assets/images/achievements/cup-02.png differ
diff --git a/app/assets/images/achievements/default.png b/app/assets/images/achievements/default.png
index adc2d5be4..0ccd6ccb0 100644
Binary files a/app/assets/images/achievements/default.png and b/app/assets/images/achievements/default.png differ
diff --git a/app/assets/images/achievements/level-bg.png b/app/assets/images/achievements/level-bg.png
index 9a23c0a6b..76173054e 100644
Binary files a/app/assets/images/achievements/level-bg.png and b/app/assets/images/achievements/level-bg.png differ
diff --git a/app/assets/images/achievements/message-01.png b/app/assets/images/achievements/message-01.png
index 8fe3dac44..f067440a5 100644
Binary files a/app/assets/images/achievements/message-01.png and b/app/assets/images/achievements/message-01.png differ
diff --git a/app/assets/images/achievements/patch-01.png b/app/assets/images/achievements/patch-01.png
index dba898f40..a55d50c57 100644
Binary files a/app/assets/images/achievements/patch-01.png and b/app/assets/images/achievements/patch-01.png differ
diff --git a/app/assets/images/achievements/pendant-01.png b/app/assets/images/achievements/pendant-01.png
index 0d0b8fc00..c143737b6 100644
Binary files a/app/assets/images/achievements/pendant-01.png and b/app/assets/images/achievements/pendant-01.png differ
diff --git a/app/assets/images/achievements/scroll-01.png b/app/assets/images/achievements/scroll-01.png
index a7ab56721..95995007a 100644
Binary files a/app/assets/images/achievements/scroll-01.png and b/app/assets/images/achievements/scroll-01.png differ
diff --git a/app/assets/images/achievements/star.png b/app/assets/images/achievements/star.png
index 22f86961d..d9a8acfbc 100644
Binary files a/app/assets/images/achievements/star.png and b/app/assets/images/achievements/star.png differ
diff --git a/app/assets/images/achievements/swords-01.png b/app/assets/images/achievements/swords-01.png
index 3d7b5170d..bc86de54a 100644
Binary files a/app/assets/images/achievements/swords-01.png and b/app/assets/images/achievements/swords-01.png differ
diff --git a/app/assets/images/common/button-background-active-border.png b/app/assets/images/common/button-background-active-border.png
index 42dec5b5a..bc9d8e7ab 100644
Binary files a/app/assets/images/common/button-background-active-border.png and b/app/assets/images/common/button-background-active-border.png differ
diff --git a/app/assets/images/common/button-background-active.png b/app/assets/images/common/button-background-active.png
index aae72bb00..ca6757724 100644
Binary files a/app/assets/images/common/button-background-active.png and b/app/assets/images/common/button-background-active.png differ
diff --git a/app/assets/images/common/button-background-danger-active-border.png b/app/assets/images/common/button-background-danger-active-border.png
index 30ed218dd..41f69383a 100644
Binary files a/app/assets/images/common/button-background-danger-active-border.png and b/app/assets/images/common/button-background-danger-active-border.png differ
diff --git a/app/assets/images/common/button-background-danger-active.png b/app/assets/images/common/button-background-danger-active.png
index b198ed621..f34da444c 100644
Binary files a/app/assets/images/common/button-background-danger-active.png and b/app/assets/images/common/button-background-danger-active.png differ
diff --git a/app/assets/images/common/button-background-danger-disabled-border.png b/app/assets/images/common/button-background-danger-disabled-border.png
index eabd86d3f..3a3c1f934 100644
Binary files a/app/assets/images/common/button-background-danger-disabled-border.png and b/app/assets/images/common/button-background-danger-disabled-border.png differ
diff --git a/app/assets/images/common/button-background-danger-disabled.png b/app/assets/images/common/button-background-danger-disabled.png
index 494f85869..bc979e335 100644
Binary files a/app/assets/images/common/button-background-danger-disabled.png and b/app/assets/images/common/button-background-danger-disabled.png differ
diff --git a/app/assets/images/common/button-background-danger-pressed-border.png b/app/assets/images/common/button-background-danger-pressed-border.png
index eadb03397..df027ad3d 100644
Binary files a/app/assets/images/common/button-background-danger-pressed-border.png and b/app/assets/images/common/button-background-danger-pressed-border.png differ
diff --git a/app/assets/images/common/button-background-danger-pressed.png b/app/assets/images/common/button-background-danger-pressed.png
index 2438ad3ee..0a989cd02 100644
Binary files a/app/assets/images/common/button-background-danger-pressed.png and b/app/assets/images/common/button-background-danger-pressed.png differ
diff --git a/app/assets/images/common/button-background-disabled-border.png b/app/assets/images/common/button-background-disabled-border.png
index dbbe537cc..3b0e0709f 100644
Binary files a/app/assets/images/common/button-background-disabled-border.png and b/app/assets/images/common/button-background-disabled-border.png differ
diff --git a/app/assets/images/common/button-background-disabled.png b/app/assets/images/common/button-background-disabled.png
index 78fae8539..d2459735e 100644
Binary files a/app/assets/images/common/button-background-disabled.png and b/app/assets/images/common/button-background-disabled.png differ
diff --git a/app/assets/images/common/button-background-pressed-border.png b/app/assets/images/common/button-background-pressed-border.png
index d9c173d64..55cbba14b 100644
Binary files a/app/assets/images/common/button-background-pressed-border.png and b/app/assets/images/common/button-background-pressed-border.png differ
diff --git a/app/assets/images/common/button-background-pressed.png b/app/assets/images/common/button-background-pressed.png
index b1433c3ff..d7a3c9d9c 100644
Binary files a/app/assets/images/common/button-background-pressed.png and b/app/assets/images/common/button-background-pressed.png differ
diff --git a/app/assets/images/common/button-background-primary-active-border.png b/app/assets/images/common/button-background-primary-active-border.png
index 140858b50..b5a1451c8 100644
Binary files a/app/assets/images/common/button-background-primary-active-border.png and b/app/assets/images/common/button-background-primary-active-border.png differ
diff --git a/app/assets/images/common/button-background-primary-active.png b/app/assets/images/common/button-background-primary-active.png
index 7e054911c..6dc209141 100644
Binary files a/app/assets/images/common/button-background-primary-active.png and b/app/assets/images/common/button-background-primary-active.png differ
diff --git a/app/assets/images/common/button-background-primary-disabled-border.png b/app/assets/images/common/button-background-primary-disabled-border.png
index b3a0fedcf..98392fc1a 100644
Binary files a/app/assets/images/common/button-background-primary-disabled-border.png and b/app/assets/images/common/button-background-primary-disabled-border.png differ
diff --git a/app/assets/images/common/button-background-primary-disabled.png b/app/assets/images/common/button-background-primary-disabled.png
index adb402464..53e11c2c2 100644
Binary files a/app/assets/images/common/button-background-primary-disabled.png and b/app/assets/images/common/button-background-primary-disabled.png differ
diff --git a/app/assets/images/common/button-background-primary-pressed-border.png b/app/assets/images/common/button-background-primary-pressed-border.png
index 2cb8f9059..48413e6a7 100644
Binary files a/app/assets/images/common/button-background-primary-pressed-border.png and b/app/assets/images/common/button-background-primary-pressed-border.png differ
diff --git a/app/assets/images/common/button-background-primary-pressed.png b/app/assets/images/common/button-background-primary-pressed.png
index cc7ab716a..b26df6dbd 100644
Binary files a/app/assets/images/common/button-background-primary-pressed.png and b/app/assets/images/common/button-background-primary-pressed.png differ
diff --git a/app/assets/images/common/button-background-success-active-border.png b/app/assets/images/common/button-background-success-active-border.png
index b64df9e49..df198bb1d 100644
Binary files a/app/assets/images/common/button-background-success-active-border.png and b/app/assets/images/common/button-background-success-active-border.png differ
diff --git a/app/assets/images/common/button-background-success-active.png b/app/assets/images/common/button-background-success-active.png
index bb6850e8b..8a41992ee 100644
Binary files a/app/assets/images/common/button-background-success-active.png and b/app/assets/images/common/button-background-success-active.png differ
diff --git a/app/assets/images/common/button-background-success-inactive-border.png b/app/assets/images/common/button-background-success-inactive-border.png
index cf1dfc217..e59a83470 100644
Binary files a/app/assets/images/common/button-background-success-inactive-border.png and b/app/assets/images/common/button-background-success-inactive-border.png differ
diff --git a/app/assets/images/common/button-background-success-inactive.png b/app/assets/images/common/button-background-success-inactive.png
index 0e02036c2..1fd16f038 100644
Binary files a/app/assets/images/common/button-background-success-inactive.png and b/app/assets/images/common/button-background-success-inactive.png differ
diff --git a/app/assets/images/common/button-background-success-pressed-border.png b/app/assets/images/common/button-background-success-pressed-border.png
index c12979058..9d2a01989 100644
Binary files a/app/assets/images/common/button-background-success-pressed-border.png and b/app/assets/images/common/button-background-success-pressed-border.png differ
diff --git a/app/assets/images/common/button-background-success-pressed.png b/app/assets/images/common/button-background-success-pressed.png
index 41c23a01f..6a5c3ae62 100644
Binary files a/app/assets/images/common/button-background-success-pressed.png and b/app/assets/images/common/button-background-success-pressed.png differ
diff --git a/app/assets/images/common/button-background-warning-active-border.png b/app/assets/images/common/button-background-warning-active-border.png
index 8a666e47b..01d099b12 100644
Binary files a/app/assets/images/common/button-background-warning-active-border.png and b/app/assets/images/common/button-background-warning-active-border.png differ
diff --git a/app/assets/images/common/button-background-warning-active.png b/app/assets/images/common/button-background-warning-active.png
index eeff76f4f..357458cd1 100644
Binary files a/app/assets/images/common/button-background-warning-active.png and b/app/assets/images/common/button-background-warning-active.png differ
diff --git a/app/assets/images/common/button-background-warning-disabled-border.png b/app/assets/images/common/button-background-warning-disabled-border.png
index 62f12be18..f22d6ec54 100644
Binary files a/app/assets/images/common/button-background-warning-disabled-border.png and b/app/assets/images/common/button-background-warning-disabled-border.png differ
diff --git a/app/assets/images/common/button-background-warning-disabled.png b/app/assets/images/common/button-background-warning-disabled.png
index a0e743222..d0d8a50bc 100644
Binary files a/app/assets/images/common/button-background-warning-disabled.png and b/app/assets/images/common/button-background-warning-disabled.png differ
diff --git a/app/assets/images/common/button-background-warning-pressed-border.png b/app/assets/images/common/button-background-warning-pressed-border.png
index ca2134e18..9e1fb3bd5 100644
Binary files a/app/assets/images/common/button-background-warning-pressed-border.png and b/app/assets/images/common/button-background-warning-pressed-border.png differ
diff --git a/app/assets/images/common/button-background-warning-pressed.png b/app/assets/images/common/button-background-warning-pressed.png
index 21e6bd380..3503601b0 100644
Binary files a/app/assets/images/common/button-background-warning-pressed.png and b/app/assets/images/common/button-background-warning-pressed.png differ
diff --git a/app/assets/images/common/code_languages/c_icon.png b/app/assets/images/common/code_languages/c_icon.png
index 99cd55241..1f8d29ef0 100755
Binary files a/app/assets/images/common/code_languages/c_icon.png and b/app/assets/images/common/code_languages/c_icon.png differ
diff --git a/app/assets/images/common/code_languages/c_small.png b/app/assets/images/common/code_languages/c_small.png
index 23ba119bb..6fc455605 100644
Binary files a/app/assets/images/common/code_languages/c_small.png and b/app/assets/images/common/code_languages/c_small.png differ
diff --git a/app/assets/images/common/code_languages/clojure_icon.png b/app/assets/images/common/code_languages/clojure_icon.png
index 7152f84c0..e96e75840 100755
Binary files a/app/assets/images/common/code_languages/clojure_icon.png and b/app/assets/images/common/code_languages/clojure_icon.png differ
diff --git a/app/assets/images/common/code_languages/clojure_small.png b/app/assets/images/common/code_languages/clojure_small.png
index 606af0433..1e6a066e3 100644
Binary files a/app/assets/images/common/code_languages/clojure_small.png and b/app/assets/images/common/code_languages/clojure_small.png differ
diff --git a/app/assets/images/common/code_languages/coffeescript_icon.png b/app/assets/images/common/code_languages/coffeescript_icon.png
index 502db9b06..289fb1a3e 100755
Binary files a/app/assets/images/common/code_languages/coffeescript_icon.png and b/app/assets/images/common/code_languages/coffeescript_icon.png differ
diff --git a/app/assets/images/common/code_languages/coffeescript_small.png b/app/assets/images/common/code_languages/coffeescript_small.png
index 86e49ea1c..b6c5f97b3 100644
Binary files a/app/assets/images/common/code_languages/coffeescript_small.png and b/app/assets/images/common/code_languages/coffeescript_small.png differ
diff --git a/app/assets/images/common/code_languages/cpp_icon.png b/app/assets/images/common/code_languages/cpp_icon.png
index c3067378c..362fd2600 100755
Binary files a/app/assets/images/common/code_languages/cpp_icon.png and b/app/assets/images/common/code_languages/cpp_icon.png differ
diff --git a/app/assets/images/common/code_languages/cpp_small.png b/app/assets/images/common/code_languages/cpp_small.png
index df701f002..915bb96cf 100644
Binary files a/app/assets/images/common/code_languages/cpp_small.png and b/app/assets/images/common/code_languages/cpp_small.png differ
diff --git a/app/assets/images/common/code_languages/csharp_icon.png b/app/assets/images/common/code_languages/csharp_icon.png
index d3eff9260..086e3ac55 100755
Binary files a/app/assets/images/common/code_languages/csharp_icon.png and b/app/assets/images/common/code_languages/csharp_icon.png differ
diff --git a/app/assets/images/common/code_languages/csharp_small.png b/app/assets/images/common/code_languages/csharp_small.png
index 86c26aea3..66c7cce60 100644
Binary files a/app/assets/images/common/code_languages/csharp_small.png and b/app/assets/images/common/code_languages/csharp_small.png differ
diff --git a/app/assets/images/common/code_languages/go_icon.png b/app/assets/images/common/code_languages/go_icon.png
index ecbfb0d6a..142b5039f 100755
Binary files a/app/assets/images/common/code_languages/go_icon.png and b/app/assets/images/common/code_languages/go_icon.png differ
diff --git a/app/assets/images/common/code_languages/go_small.png b/app/assets/images/common/code_languages/go_small.png
index 7ff974e07..c4886eeff 100644
Binary files a/app/assets/images/common/code_languages/go_small.png and b/app/assets/images/common/code_languages/go_small.png differ
diff --git a/app/assets/images/common/code_languages/io_icon.png b/app/assets/images/common/code_languages/io_icon.png
index 14f04afc3..eb56cdbdd 100755
Binary files a/app/assets/images/common/code_languages/io_icon.png and b/app/assets/images/common/code_languages/io_icon.png differ
diff --git a/app/assets/images/common/code_languages/io_small.png b/app/assets/images/common/code_languages/io_small.png
index 2bbd5c51e..721b879da 100644
Binary files a/app/assets/images/common/code_languages/io_small.png and b/app/assets/images/common/code_languages/io_small.png differ
diff --git a/app/assets/images/common/code_languages/java_icon.png b/app/assets/images/common/code_languages/java_icon.png
index e39879cae..e04aff83a 100755
Binary files a/app/assets/images/common/code_languages/java_icon.png and b/app/assets/images/common/code_languages/java_icon.png differ
diff --git a/app/assets/images/common/code_languages/java_small.png b/app/assets/images/common/code_languages/java_small.png
index 76126650c..420094d2f 100644
Binary files a/app/assets/images/common/code_languages/java_small.png and b/app/assets/images/common/code_languages/java_small.png differ
diff --git a/app/assets/images/common/code_languages/javascript_icon.png b/app/assets/images/common/code_languages/javascript_icon.png
index 085dbe523..fe866dfe7 100755
Binary files a/app/assets/images/common/code_languages/javascript_icon.png and b/app/assets/images/common/code_languages/javascript_icon.png differ
diff --git a/app/assets/images/common/code_languages/javascript_small.png b/app/assets/images/common/code_languages/javascript_small.png
index 4472bea9d..b2c8f18f2 100644
Binary files a/app/assets/images/common/code_languages/javascript_small.png and b/app/assets/images/common/code_languages/javascript_small.png differ
diff --git a/app/assets/images/common/code_languages/lua_icon.png b/app/assets/images/common/code_languages/lua_icon.png
index e97873a33..92c4b4483 100755
Binary files a/app/assets/images/common/code_languages/lua_icon.png and b/app/assets/images/common/code_languages/lua_icon.png differ
diff --git a/app/assets/images/common/code_languages/lua_small.png b/app/assets/images/common/code_languages/lua_small.png
index c1f183c58..582386e4d 100644
Binary files a/app/assets/images/common/code_languages/lua_small.png and b/app/assets/images/common/code_languages/lua_small.png differ
diff --git a/app/assets/images/common/code_languages/php_icon.png b/app/assets/images/common/code_languages/php_icon.png
index 35757de0b..43116f09d 100755
Binary files a/app/assets/images/common/code_languages/php_icon.png and b/app/assets/images/common/code_languages/php_icon.png differ
diff --git a/app/assets/images/common/code_languages/php_small.png b/app/assets/images/common/code_languages/php_small.png
index 62a5010f3..a3904dc8c 100644
Binary files a/app/assets/images/common/code_languages/php_small.png and b/app/assets/images/common/code_languages/php_small.png differ
diff --git a/app/assets/images/common/code_languages/python_icon.png b/app/assets/images/common/code_languages/python_icon.png
index b8575c4f8..e45ef22a2 100755
Binary files a/app/assets/images/common/code_languages/python_icon.png and b/app/assets/images/common/code_languages/python_icon.png differ
diff --git a/app/assets/images/common/code_languages/python_small.png b/app/assets/images/common/code_languages/python_small.png
index aa303a518..16acb2dcf 100644
Binary files a/app/assets/images/common/code_languages/python_small.png and b/app/assets/images/common/code_languages/python_small.png differ
diff --git a/app/assets/images/common/code_languages/ruby_icon.png b/app/assets/images/common/code_languages/ruby_icon.png
index 7e1192d7a..dc44a1de7 100755
Binary files a/app/assets/images/common/code_languages/ruby_icon.png and b/app/assets/images/common/code_languages/ruby_icon.png differ
diff --git a/app/assets/images/common/code_languages/ruby_small.png b/app/assets/images/common/code_languages/ruby_small.png
index 9839340f7..c5d0d8411 100644
Binary files a/app/assets/images/common/code_languages/ruby_small.png and b/app/assets/images/common/code_languages/ruby_small.png differ
diff --git a/app/assets/images/common/code_languages/swift_icon.png b/app/assets/images/common/code_languages/swift_icon.png
index e789c1516..ba6a3a730 100755
Binary files a/app/assets/images/common/code_languages/swift_icon.png and b/app/assets/images/common/code_languages/swift_icon.png differ
diff --git a/app/assets/images/common/code_languages/swift_small.png b/app/assets/images/common/code_languages/swift_small.png
index 95d9c049a..90470a560 100644
Binary files a/app/assets/images/common/code_languages/swift_small.png and b/app/assets/images/common/code_languages/swift_small.png differ
diff --git a/app/assets/images/common/gem.png b/app/assets/images/common/gem.png
index 9598f6bef..a29f074c6 100644
Binary files a/app/assets/images/common/gem.png and b/app/assets/images/common/gem.png differ
diff --git a/app/assets/images/common/particles/bullet.png b/app/assets/images/common/particles/bullet.png
index 8310ac5b9..f40cf568d 100644
Binary files a/app/assets/images/common/particles/bullet.png and b/app/assets/images/common/particles/bullet.png differ
diff --git a/app/assets/images/common/particles/bullet2.png b/app/assets/images/common/particles/bullet2.png
index 651fd98c2..12024deaf 100644
Binary files a/app/assets/images/common/particles/bullet2.png and b/app/assets/images/common/particles/bullet2.png differ
diff --git a/app/assets/images/common/particles/cloud.png b/app/assets/images/common/particles/cloud.png
index c79d87506..9495f07c7 100644
Binary files a/app/assets/images/common/particles/cloud.png and b/app/assets/images/common/particles/cloud.png differ
diff --git a/app/assets/images/common/particles/cloud_small.png b/app/assets/images/common/particles/cloud_small.png
index 974e8ea21..c6ec0b815 100644
Binary files a/app/assets/images/common/particles/cloud_small.png and b/app/assets/images/common/particles/cloud_small.png differ
diff --git a/app/assets/images/common/particles/smoke.png b/app/assets/images/common/particles/smoke.png
index 7bad8c685..1a7f58e19 100644
Binary files a/app/assets/images/common/particles/smoke.png and b/app/assets/images/common/particles/smoke.png differ
diff --git a/app/assets/images/common/particles/star.png b/app/assets/images/common/particles/star.png
index 5e6f2a12f..8da309b60 100644
Binary files a/app/assets/images/common/particles/star.png and b/app/assets/images/common/particles/star.png differ
diff --git a/app/assets/images/generic-icon.png b/app/assets/images/generic-icon.png
index bd0ccdcbb..564639093 100644
Binary files a/app/assets/images/generic-icon.png and b/app/assets/images/generic-icon.png differ
diff --git a/app/assets/images/jquery.minicolors.png b/app/assets/images/jquery.minicolors.png
index 8fa1e9d90..ef834eac3 100644
Binary files a/app/assets/images/jquery.minicolors.png and b/app/assets/images/jquery.minicolors.png differ
diff --git a/app/assets/images/level/code_editor_background.png b/app/assets/images/level/code_editor_background.png
index daa5d7600..2f5941582 100644
Binary files a/app/assets/images/level/code_editor_background.png and b/app/assets/images/level/code_editor_background.png differ
diff --git a/app/assets/images/level/code_editor_background_border.png b/app/assets/images/level/code_editor_background_border.png
index 9c860168f..621179c86 100644
Binary files a/app/assets/images/level/code_editor_background_border.png and b/app/assets/images/level/code_editor_background_border.png differ
diff --git a/app/assets/images/level/code_editor_error_background.png b/app/assets/images/level/code_editor_error_background.png
index b6fbc72ea..fe4862bdd 100644
Binary files a/app/assets/images/level/code_editor_error_background.png and b/app/assets/images/level/code_editor_error_background.png differ
diff --git a/app/assets/images/level/code_editor_error_background_arrow.png b/app/assets/images/level/code_editor_error_background_arrow.png
index bb2396a69..74b78e91d 100644
Binary files a/app/assets/images/level/code_editor_error_background_arrow.png and b/app/assets/images/level/code_editor_error_background_arrow.png differ
diff --git a/app/assets/images/level/code_editor_info_background.png b/app/assets/images/level/code_editor_info_background.png
index cfbe5a98b..106319bd5 100644
Binary files a/app/assets/images/level/code_editor_info_background.png and b/app/assets/images/level/code_editor_info_background.png differ
diff --git a/app/assets/images/level/code_editor_top_bar_hinge.png b/app/assets/images/level/code_editor_top_bar_hinge.png
index 852df87fc..af639838e 100644
Binary files a/app/assets/images/level/code_editor_top_bar_hinge.png and b/app/assets/images/level/code_editor_top_bar_hinge.png differ
diff --git a/app/assets/images/level/code_editor_top_bar_wood_background.png b/app/assets/images/level/code_editor_top_bar_wood_background.png
index 15d625b08..6468b833e 100644
Binary files a/app/assets/images/level/code_editor_top_bar_wood_background.png and b/app/assets/images/level/code_editor_top_bar_wood_background.png differ
diff --git a/app/assets/images/level/code_palette_wood_background.png b/app/assets/images/level/code_palette_wood_background.png
index dbdda5af6..d6040dbbb 100644
Binary files a/app/assets/images/level/code_palette_wood_background.png and b/app/assets/images/level/code_palette_wood_background.png differ
diff --git a/app/assets/images/level/code_toolbar_background.png b/app/assets/images/level/code_toolbar_background.png
index f05972b5c..59cf36112 100644
Binary files a/app/assets/images/level/code_toolbar_background.png and b/app/assets/images/level/code_toolbar_background.png differ
diff --git a/app/assets/images/level/code_toolbar_run_button_active.png b/app/assets/images/level/code_toolbar_run_button_active.png
index ff3748d39..d056c02ed 100644
Binary files a/app/assets/images/level/code_toolbar_run_button_active.png and b/app/assets/images/level/code_toolbar_run_button_active.png differ
diff --git a/app/assets/images/level/code_toolbar_run_button_active_pressed.png b/app/assets/images/level/code_toolbar_run_button_active_pressed.png
index b9c87d1ba..ee8dda0b6 100644
Binary files a/app/assets/images/level/code_toolbar_run_button_active_pressed.png and b/app/assets/images/level/code_toolbar_run_button_active_pressed.png differ
diff --git a/app/assets/images/level/code_toolbar_run_button_zazz.png b/app/assets/images/level/code_toolbar_run_button_zazz.png
index 8b0e94225..71239be06 100644
Binary files a/app/assets/images/level/code_toolbar_run_button_zazz.png and b/app/assets/images/level/code_toolbar_run_button_zazz.png differ
diff --git a/app/assets/images/level/code_toolbar_run_button_zazz_pressed.png b/app/assets/images/level/code_toolbar_run_button_zazz_pressed.png
index b6d173515..347096dd2 100644
Binary files a/app/assets/images/level/code_toolbar_run_button_zazz_pressed.png and b/app/assets/images/level/code_toolbar_run_button_zazz_pressed.png differ
diff --git a/app/assets/images/level/code_toolbar_submit_button_active.png b/app/assets/images/level/code_toolbar_submit_button_active.png
index 0913c4e28..86d35f78f 100644
Binary files a/app/assets/images/level/code_toolbar_submit_button_active.png and b/app/assets/images/level/code_toolbar_submit_button_active.png differ
diff --git a/app/assets/images/level/code_toolbar_submit_button_active_pressed.png b/app/assets/images/level/code_toolbar_submit_button_active_pressed.png
index 100f085f4..699bafefd 100644
Binary files a/app/assets/images/level/code_toolbar_submit_button_active_pressed.png and b/app/assets/images/level/code_toolbar_submit_button_active_pressed.png differ
diff --git a/app/assets/images/level/code_toolbar_submit_button_zazz.png b/app/assets/images/level/code_toolbar_submit_button_zazz.png
index ff9eeac0c..ef935228a 100644
Binary files a/app/assets/images/level/code_toolbar_submit_button_zazz.png and b/app/assets/images/level/code_toolbar_submit_button_zazz.png differ
diff --git a/app/assets/images/level/code_toolbar_submit_button_zazz_pressed.png b/app/assets/images/level/code_toolbar_submit_button_zazz_pressed.png
index 4875b697b..613919f62 100644
Binary files a/app/assets/images/level/code_toolbar_submit_button_zazz_pressed.png and b/app/assets/images/level/code_toolbar_submit_button_zazz_pressed.png differ
diff --git a/app/assets/images/level/control_bar_background.png b/app/assets/images/level/control_bar_background.png
index 06a150c20..f2656bed5 100644
Binary files a/app/assets/images/level/control_bar_background.png and b/app/assets/images/level/control_bar_background.png differ
diff --git a/app/assets/images/level/control_bar_cap_left.png b/app/assets/images/level/control_bar_cap_left.png
index be927198b..ddf9c06b6 100644
Binary files a/app/assets/images/level/control_bar_cap_left.png and b/app/assets/images/level/control_bar_cap_left.png differ
diff --git a/app/assets/images/level/control_bar_cap_right.png b/app/assets/images/level/control_bar_cap_right.png
index a1362e0d9..224a7f9a5 100644
Binary files a/app/assets/images/level/control_bar_cap_right.png and b/app/assets/images/level/control_bar_cap_right.png differ
diff --git a/app/assets/images/level/control_bar_chain_center.png b/app/assets/images/level/control_bar_chain_center.png
index 420d631a0..cc637629f 100644
Binary files a/app/assets/images/level/control_bar_chain_center.png and b/app/assets/images/level/control_bar_chain_center.png differ
diff --git a/app/assets/images/level/control_bar_chain_right.png b/app/assets/images/level/control_bar_chain_right.png
index b618cb6b8..328083c81 100644
Binary files a/app/assets/images/level/control_bar_chain_right.png and b/app/assets/images/level/control_bar_chain_right.png differ
diff --git a/app/assets/images/level/control_bar_level_name_background.png b/app/assets/images/level/control_bar_level_name_background.png
index 0babffd28..2c935f3bc 100644
Binary files a/app/assets/images/level/control_bar_level_name_background.png and b/app/assets/images/level/control_bar_level_name_background.png differ
diff --git a/app/assets/images/level/csedweek-logo-final-small.jpg b/app/assets/images/level/csedweek-logo-final-small.jpg
index e3fbe384e..be5b1d8e0 100644
Binary files a/app/assets/images/level/csedweek-logo-final-small.jpg and b/app/assets/images/level/csedweek-logo-final-small.jpg differ
diff --git a/app/assets/images/level/dialogue_background.png b/app/assets/images/level/dialogue_background.png
index 79ec8ab35..5190093bc 100644
Binary files a/app/assets/images/level/dialogue_background.png and b/app/assets/images/level/dialogue_background.png differ
diff --git a/app/assets/images/level/footer_background.jpg b/app/assets/images/level/footer_background.jpg
index 97f24c48a..d56e03bc1 100644
Binary files a/app/assets/images/level/footer_background.jpg and b/app/assets/images/level/footer_background.jpg differ
diff --git a/app/assets/images/level/goals_background.png b/app/assets/images/level/goals_background.png
index fe066853a..e48146136 100644
Binary files a/app/assets/images/level/goals_background.png and b/app/assets/images/level/goals_background.png differ
diff --git a/app/assets/images/level/gold_background.png b/app/assets/images/level/gold_background.png
index 738b3592c..93e535e13 100644
Binary files a/app/assets/images/level/gold_background.png and b/app/assets/images/level/gold_background.png differ
diff --git a/app/assets/images/level/gold_icon.png b/app/assets/images/level/gold_icon.png
index a8988a2ef..7e084eac9 100644
Binary files a/app/assets/images/level/gold_icon.png and b/app/assets/images/level/gold_icon.png differ
diff --git a/app/assets/images/level/hud_background.png b/app/assets/images/level/hud_background.png
index e76950a8c..68b9b0c8b 100644
Binary files a/app/assets/images/level/hud_background.png and b/app/assets/images/level/hud_background.png differ
diff --git a/app/assets/images/level/hud_hinge.png b/app/assets/images/level/hud_hinge.png
index bfbd5bc64..24dee2256 100644
Binary files a/app/assets/images/level/hud_hinge.png and b/app/assets/images/level/hud_hinge.png differ
diff --git a/app/assets/images/level/hud_info_icons.png b/app/assets/images/level/hud_info_icons.png
index bff087119..b5aa51229 100644
Binary files a/app/assets/images/level/hud_info_icons.png and b/app/assets/images/level/hud_info_icons.png differ
diff --git a/app/assets/images/level/hud_wood_background.png b/app/assets/images/level/hud_wood_background.png
index 3745a4d6b..53c1e64d9 100644
Binary files a/app/assets/images/level/hud_wood_background.png and b/app/assets/images/level/hud_wood_background.png differ
diff --git a/app/assets/images/level/loading_bar_back.png b/app/assets/images/level/loading_bar_back.png
index 140d90d9c..d59de9a99 100644
Binary files a/app/assets/images/level/loading_bar_back.png and b/app/assets/images/level/loading_bar_back.png differ
diff --git a/app/assets/images/level/loading_bar_fill.png b/app/assets/images/level/loading_bar_fill.png
index 47e9770a7..344e58366 100644
Binary files a/app/assets/images/level/loading_bar_fill.png and b/app/assets/images/level/loading_bar_fill.png differ
diff --git a/app/assets/images/level/loading_bar_rim.png b/app/assets/images/level/loading_bar_rim.png
index b5155e62d..0ae7f91a2 100644
Binary files a/app/assets/images/level/loading_bar_rim.png and b/app/assets/images/level/loading_bar_rim.png differ
diff --git a/app/assets/images/level/loading_left_wing_1366.jpg b/app/assets/images/level/loading_left_wing_1366.jpg
index 29fe67e9c..5ed9564d8 100644
Binary files a/app/assets/images/level/loading_left_wing_1366.jpg and b/app/assets/images/level/loading_left_wing_1366.jpg differ
diff --git a/app/assets/images/level/loading_left_wing_1920.jpg b/app/assets/images/level/loading_left_wing_1920.jpg
index 73aab0978..dc0ffb3aa 100644
Binary files a/app/assets/images/level/loading_left_wing_1920.jpg and b/app/assets/images/level/loading_left_wing_1920.jpg differ
diff --git a/app/assets/images/level/loading_right_wing_1366.jpg b/app/assets/images/level/loading_right_wing_1366.jpg
index 963feba9b..cfb9c82ae 100644
Binary files a/app/assets/images/level/loading_right_wing_1366.jpg and b/app/assets/images/level/loading_right_wing_1366.jpg differ
diff --git a/app/assets/images/level/loading_right_wing_1920.jpg b/app/assets/images/level/loading_right_wing_1920.jpg
index 2fe4465ce..088080b93 100644
Binary files a/app/assets/images/level/loading_right_wing_1920.jpg and b/app/assets/images/level/loading_right_wing_1920.jpg differ
diff --git a/app/assets/images/level/pointer.png b/app/assets/images/level/pointer.png
index af721f635..776f987d6 100644
Binary files a/app/assets/images/level/pointer.png and b/app/assets/images/level/pointer.png differ
diff --git a/app/assets/images/level/popover_background.png b/app/assets/images/level/popover_background.png
index f87ea6d4b..104349ffe 100644
Binary files a/app/assets/images/level/popover_background.png and b/app/assets/images/level/popover_background.png differ
diff --git a/app/assets/images/level/popover_border_background.png b/app/assets/images/level/popover_border_background.png
index a8414487b..cfd5ea5eb 100644
Binary files a/app/assets/images/level/popover_border_background.png and b/app/assets/images/level/popover_border_background.png differ
diff --git a/app/assets/images/level/scrubber_background.png b/app/assets/images/level/scrubber_background.png
index 517a4c8c4..54f2133b1 100644
Binary files a/app/assets/images/level/scrubber_background.png and b/app/assets/images/level/scrubber_background.png differ
diff --git a/app/assets/images/level/scrubber_groove.png b/app/assets/images/level/scrubber_groove.png
index ab5affbcd..cac6e8ca7 100644
Binary files a/app/assets/images/level/scrubber_groove.png and b/app/assets/images/level/scrubber_groove.png differ
diff --git a/app/assets/images/level/scrubber_knob.png b/app/assets/images/level/scrubber_knob.png
index 191b75638..ccf9f40b5 100644
Binary files a/app/assets/images/level/scrubber_knob.png and b/app/assets/images/level/scrubber_knob.png differ
diff --git a/app/assets/images/level/thang_avatar_frame.png b/app/assets/images/level/thang_avatar_frame.png
index 1b4fcc3d5..b6755283c 100644
Binary files a/app/assets/images/level/thang_avatar_frame.png and b/app/assets/images/level/thang_avatar_frame.png differ
diff --git a/app/assets/images/level/victory.png b/app/assets/images/level/victory.png
index e220c19ff..49f1b9ef4 100644
Binary files a/app/assets/images/level/victory.png and b/app/assets/images/level/victory.png differ
diff --git a/app/assets/images/level/wood_texture.png b/app/assets/images/level/wood_texture.png
index 3c33773cb..a2f771592 100644
Binary files a/app/assets/images/level/wood_texture.png and b/app/assets/images/level/wood_texture.png differ
diff --git a/app/assets/images/pages/about/carlos_small.png b/app/assets/images/pages/about/carlos_small.png
index 2f62eaf0e..180223e4d 100644
Binary files a/app/assets/images/pages/about/carlos_small.png and b/app/assets/images/pages/about/carlos_small.png differ
diff --git a/app/assets/images/pages/about/cat_small.png b/app/assets/images/pages/about/cat_small.png
index 312607708..2e74d5011 100644
Binary files a/app/assets/images/pages/about/cat_small.png and b/app/assets/images/pages/about/cat_small.png differ
diff --git a/app/assets/images/pages/about/coco_comic.jpg b/app/assets/images/pages/about/coco_comic.jpg
index 87ff27a54..0cf405379 100644
Binary files a/app/assets/images/pages/about/coco_comic.jpg and b/app/assets/images/pages/about/coco_comic.jpg differ
diff --git a/app/assets/images/pages/about/george_small.png b/app/assets/images/pages/about/george_small.png
index b55fd733d..8ac3c39b8 100644
Binary files a/app/assets/images/pages/about/george_small.png and b/app/assets/images/pages/about/george_small.png differ
diff --git a/app/assets/images/pages/about/jose_small.png b/app/assets/images/pages/about/jose_small.png
index 01bb440a9..c32c819f1 100644
Binary files a/app/assets/images/pages/about/jose_small.png and b/app/assets/images/pages/about/jose_small.png differ
diff --git a/app/assets/images/pages/about/josh_c_small.png b/app/assets/images/pages/about/josh_c_small.png
index 6a04f9e2e..8105ddbc0 100644
Binary files a/app/assets/images/pages/about/josh_c_small.png and b/app/assets/images/pages/about/josh_c_small.png differ
diff --git a/app/assets/images/pages/about/josh_small.png b/app/assets/images/pages/about/josh_small.png
index 80daa5c2a..5164f8359 100644
Binary files a/app/assets/images/pages/about/josh_small.png and b/app/assets/images/pages/about/josh_small.png differ
diff --git a/app/assets/images/pages/about/maka_small.png b/app/assets/images/pages/about/maka_small.png
index ca34a99cf..7501b6229 100644
Binary files a/app/assets/images/pages/about/maka_small.png and b/app/assets/images/pages/about/maka_small.png differ
diff --git a/app/assets/images/pages/about/matt_small.png b/app/assets/images/pages/about/matt_small.png
index 660b2e0db..b74872444 100644
Binary files a/app/assets/images/pages/about/matt_small.png and b/app/assets/images/pages/about/matt_small.png differ
diff --git a/app/assets/images/pages/about/michael_small.png b/app/assets/images/pages/about/michael_small.png
index 84d56d4c3..becf7c60e 100644
Binary files a/app/assets/images/pages/about/michael_small.png and b/app/assets/images/pages/about/michael_small.png differ
diff --git a/app/assets/images/pages/about/nick_small.png b/app/assets/images/pages/about/nick_small.png
index 53a0ccc07..fe9ae1bd8 100644
Binary files a/app/assets/images/pages/about/nick_small.png and b/app/assets/images/pages/about/nick_small.png differ
diff --git a/app/assets/images/pages/about/oleg_small.png b/app/assets/images/pages/about/oleg_small.png
index 4690ed5cc..d7e088f4e 100644
Binary files a/app/assets/images/pages/about/oleg_small.png and b/app/assets/images/pages/about/oleg_small.png differ
diff --git a/app/assets/images/pages/about/pavel_small.png b/app/assets/images/pages/about/pavel_small.png
index 336e3e6e6..357c8d901 100644
Binary files a/app/assets/images/pages/about/pavel_small.png and b/app/assets/images/pages/about/pavel_small.png differ
diff --git a/app/assets/images/pages/about/placeholder.png b/app/assets/images/pages/about/placeholder.png
index 997286b61..b3ed24c55 100644
Binary files a/app/assets/images/pages/about/placeholder.png and b/app/assets/images/pages/about/placeholder.png differ
diff --git a/app/assets/images/pages/about/rob_small.png b/app/assets/images/pages/about/rob_small.png
index afba34d7d..a0b35a16f 100644
Binary files a/app/assets/images/pages/about/rob_small.png and b/app/assets/images/pages/about/rob_small.png differ
diff --git a/app/assets/images/pages/about/robin_small.png b/app/assets/images/pages/about/robin_small.png
index c1ce3331a..dd16eca0f 100644
Binary files a/app/assets/images/pages/about/robin_small.png and b/app/assets/images/pages/about/robin_small.png differ
diff --git a/app/assets/images/pages/about/scott_small.png b/app/assets/images/pages/about/scott_small.png
index fa1e4a023..f08d637e7 100644
Binary files a/app/assets/images/pages/about/scott_small.png and b/app/assets/images/pages/about/scott_small.png differ
diff --git a/app/assets/images/pages/account/profile/education.png b/app/assets/images/pages/account/profile/education.png
index dad4914c6..bd4624c16 100644
Binary files a/app/assets/images/pages/account/profile/education.png and b/app/assets/images/pages/account/profile/education.png differ
diff --git a/app/assets/images/pages/account/profile/icon_facebook.png b/app/assets/images/pages/account/profile/icon_facebook.png
index b775c18fa..76aec3820 100644
Binary files a/app/assets/images/pages/account/profile/icon_facebook.png and b/app/assets/images/pages/account/profile/icon_facebook.png differ
diff --git a/app/assets/images/pages/account/profile/icon_github.png b/app/assets/images/pages/account/profile/icon_github.png
index fc1801abc..376a9c217 100644
Binary files a/app/assets/images/pages/account/profile/icon_github.png and b/app/assets/images/pages/account/profile/icon_github.png differ
diff --git a/app/assets/images/pages/account/profile/icon_gplus.png b/app/assets/images/pages/account/profile/icon_gplus.png
index c2343eb50..ca772c7ac 100644
Binary files a/app/assets/images/pages/account/profile/icon_gplus.png and b/app/assets/images/pages/account/profile/icon_gplus.png differ
diff --git a/app/assets/images/pages/account/profile/icon_linkedin.png b/app/assets/images/pages/account/profile/icon_linkedin.png
index cdd0ff6c2..17af2f66e 100644
Binary files a/app/assets/images/pages/account/profile/icon_linkedin.png and b/app/assets/images/pages/account/profile/icon_linkedin.png differ
diff --git a/app/assets/images/pages/account/profile/icon_twitter.png b/app/assets/images/pages/account/profile/icon_twitter.png
index 1280ad6df..82a2862e4 100644
Binary files a/app/assets/images/pages/account/profile/icon_twitter.png and b/app/assets/images/pages/account/profile/icon_twitter.png differ
diff --git a/app/assets/images/pages/account/profile/sample_profile.png b/app/assets/images/pages/account/profile/sample_profile.png
index b61294854..9e7765ef8 100644
Binary files a/app/assets/images/pages/account/profile/sample_profile.png and b/app/assets/images/pages/account/profile/sample_profile.png differ
diff --git a/app/assets/images/pages/account/profile/sample_profile_thumb.png b/app/assets/images/pages/account/profile/sample_profile_thumb.png
index bc1e63e13..061d0c64e 100644
Binary files a/app/assets/images/pages/account/profile/sample_profile_thumb.png and b/app/assets/images/pages/account/profile/sample_profile_thumb.png differ
diff --git a/app/assets/images/pages/account/profile/sample_project.png b/app/assets/images/pages/account/profile/sample_project.png
index feecec3c7..d8422135d 100644
Binary files a/app/assets/images/pages/account/profile/sample_project.png and b/app/assets/images/pages/account/profile/sample_project.png differ
diff --git a/app/assets/images/pages/account/profile/work.png b/app/assets/images/pages/account/profile/work.png
index 72e659071..3242a2b28 100644
Binary files a/app/assets/images/pages/account/profile/work.png and b/app/assets/images/pages/account/profile/work.png differ
diff --git a/app/assets/images/pages/account/subscription/teacher-banner.png b/app/assets/images/pages/account/subscription/teacher-banner.png
index 445456ea9..6ee445ccd 100644
Binary files a/app/assets/images/pages/account/subscription/teacher-banner.png and b/app/assets/images/pages/account/subscription/teacher-banner.png differ
diff --git a/app/assets/images/pages/base/background.jpg b/app/assets/images/pages/base/background.jpg
index c924faf89..db0bd47ba 100644
Binary files a/app/assets/images/pages/base/background.jpg and b/app/assets/images/pages/base/background.jpg differ
diff --git a/app/assets/images/pages/base/firebase.png b/app/assets/images/pages/base/firebase.png
index 5ecfb5e2d..284ddb865 100644
Binary files a/app/assets/images/pages/base/firebase.png and b/app/assets/images/pages/base/firebase.png differ
diff --git a/app/assets/images/pages/base/glyphicons-halflings-white.png b/app/assets/images/pages/base/glyphicons-halflings-white.png
index 9167abf53..7507bf61f 100644
Binary files a/app/assets/images/pages/base/glyphicons-halflings-white.png and b/app/assets/images/pages/base/glyphicons-halflings-white.png differ
diff --git a/app/assets/images/pages/base/glyphicons-halflings.png b/app/assets/images/pages/base/glyphicons-halflings.png
index 5b67ffda5..f241c76f9 100644
Binary files a/app/assets/images/pages/base/glyphicons-halflings.png and b/app/assets/images/pages/base/glyphicons-halflings.png differ
diff --git a/app/assets/images/pages/base/logo.png b/app/assets/images/pages/base/logo.png
index e7a97eb3c..0640f4147 100644
Binary files a/app/assets/images/pages/base/logo.png and b/app/assets/images/pages/base/logo.png differ
diff --git a/app/assets/images/pages/base/logo_square_120.png b/app/assets/images/pages/base/logo_square_120.png
index 08f3c3eff..b94043c2b 100644
Binary files a/app/assets/images/pages/base/logo_square_120.png and b/app/assets/images/pages/base/logo_square_120.png differ
diff --git a/app/assets/images/pages/base/logo_square_250.png b/app/assets/images/pages/base/logo_square_250.png
index 7f2b50e3b..7cabb0b2d 100644
Binary files a/app/assets/images/pages/base/logo_square_250.png and b/app/assets/images/pages/base/logo_square_250.png differ
diff --git a/app/assets/images/pages/base/modal_background.png b/app/assets/images/pages/base/modal_background.png
index ae67e9460..a79eb60dc 100644
Binary files a/app/assets/images/pages/base/modal_background.png and b/app/assets/images/pages/base/modal_background.png differ
diff --git a/app/assets/images/pages/base/nav_background.png b/app/assets/images/pages/base/nav_background.png
index d9df28f57..d5f314a16 100644
Binary files a/app/assets/images/pages/base/nav_background.png and b/app/assets/images/pages/base/nav_background.png differ
diff --git a/app/assets/images/pages/base/play_button.png b/app/assets/images/pages/base/play_button.png
index 7d4c74966..d8d8e08e5 100644
Binary files a/app/assets/images/pages/base/play_button.png and b/app/assets/images/pages/base/play_button.png differ
diff --git a/app/assets/images/pages/base/recruitment_logo.png b/app/assets/images/pages/base/recruitment_logo.png
index 6e107540b..828da070c 100644
Binary files a/app/assets/images/pages/base/recruitment_logo.png and b/app/assets/images/pages/base/recruitment_logo.png differ
diff --git a/app/assets/images/pages/careers/recruiting.png b/app/assets/images/pages/careers/recruiting.png
index 6ea355237..270f11588 100644
Binary files a/app/assets/images/pages/careers/recruiting.png and b/app/assets/images/pages/careers/recruiting.png differ
diff --git a/app/assets/images/pages/clans/dashboard_preview.png b/app/assets/images/pages/clans/dashboard_preview.png
index d45f8911f..9fffdd0e3 100644
Binary files a/app/assets/images/pages/clans/dashboard_preview.png and b/app/assets/images/pages/clans/dashboard_preview.png differ
diff --git a/app/assets/images/pages/community/adventurer.png b/app/assets/images/pages/community/adventurer.png
index 6b7553a60..99a1e2912 100644
Binary files a/app/assets/images/pages/community/adventurer.png and b/app/assets/images/pages/community/adventurer.png differ
diff --git a/app/assets/images/pages/community/ambassador.png b/app/assets/images/pages/community/ambassador.png
index 462f7c8de..508a0cdc8 100644
Binary files a/app/assets/images/pages/community/ambassador.png and b/app/assets/images/pages/community/ambassador.png differ
diff --git a/app/assets/images/pages/community/archmage.png b/app/assets/images/pages/community/archmage.png
index 4bdae4b03..6f107c306 100644
Binary files a/app/assets/images/pages/community/archmage.png and b/app/assets/images/pages/community/archmage.png differ
diff --git a/app/assets/images/pages/community/article.png b/app/assets/images/pages/community/article.png
index fcc391939..263dc860f 100644
Binary files a/app/assets/images/pages/community/article.png and b/app/assets/images/pages/community/article.png differ
diff --git a/app/assets/images/pages/community/artisan.png b/app/assets/images/pages/community/artisan.png
index c3a5d1680..b1a3ce83a 100644
Binary files a/app/assets/images/pages/community/artisan.png and b/app/assets/images/pages/community/artisan.png differ
diff --git a/app/assets/images/pages/community/diplomat.png b/app/assets/images/pages/community/diplomat.png
index eaaf21b37..fe6e02ff9 100644
Binary files a/app/assets/images/pages/community/diplomat.png and b/app/assets/images/pages/community/diplomat.png differ
diff --git a/app/assets/images/pages/community/level.png b/app/assets/images/pages/community/level.png
index b5bb78f03..7934f6601 100644
Binary files a/app/assets/images/pages/community/level.png and b/app/assets/images/pages/community/level.png differ
diff --git a/app/assets/images/pages/community/logo_discourse.png b/app/assets/images/pages/community/logo_discourse.png
index 75be80ecc..11d218961 100644
Binary files a/app/assets/images/pages/community/logo_discourse.png and b/app/assets/images/pages/community/logo_discourse.png differ
diff --git a/app/assets/images/pages/community/logo_facebook.png b/app/assets/images/pages/community/logo_facebook.png
index 0575c3e70..be09a2e0f 100644
Binary files a/app/assets/images/pages/community/logo_facebook.png and b/app/assets/images/pages/community/logo_facebook.png differ
diff --git a/app/assets/images/pages/community/logo_g+.png b/app/assets/images/pages/community/logo_g+.png
index 1ca939a39..8cd24a9ee 100644
Binary files a/app/assets/images/pages/community/logo_g+.png and b/app/assets/images/pages/community/logo_g+.png differ
diff --git a/app/assets/images/pages/community/logo_github.png b/app/assets/images/pages/community/logo_github.png
index a7c81809f..8c5c9e20b 100644
Binary files a/app/assets/images/pages/community/logo_github.png and b/app/assets/images/pages/community/logo_github.png differ
diff --git a/app/assets/images/pages/community/logo_hipchat.png b/app/assets/images/pages/community/logo_hipchat.png
index aa47b8010..b3d0e0d0f 100644
Binary files a/app/assets/images/pages/community/logo_hipchat.png and b/app/assets/images/pages/community/logo_hipchat.png differ
diff --git a/app/assets/images/pages/community/logo_sett.png b/app/assets/images/pages/community/logo_sett.png
index 38c0aa7bc..96d7e588c 100644
Binary files a/app/assets/images/pages/community/logo_sett.png and b/app/assets/images/pages/community/logo_sett.png differ
diff --git a/app/assets/images/pages/community/logo_twitter.png b/app/assets/images/pages/community/logo_twitter.png
index a65889262..35dc8a41b 100644
Binary files a/app/assets/images/pages/community/logo_twitter.png and b/app/assets/images/pages/community/logo_twitter.png differ
diff --git a/app/assets/images/pages/community/scribe.png b/app/assets/images/pages/community/scribe.png
index b44a8835a..30df40abc 100644
Binary files a/app/assets/images/pages/community/scribe.png and b/app/assets/images/pages/community/scribe.png differ
diff --git a/app/assets/images/pages/community/thang.png b/app/assets/images/pages/community/thang.png
index 1d6ef69fa..b7e52be24 100644
Binary files a/app/assets/images/pages/community/thang.png and b/app/assets/images/pages/community/thang.png differ
diff --git a/app/assets/images/pages/contribute/adventurer.png b/app/assets/images/pages/contribute/adventurer.png
index c23e10b9e..fa3ed67cb 100644
Binary files a/app/assets/images/pages/contribute/adventurer.png and b/app/assets/images/pages/contribute/adventurer.png differ
diff --git a/app/assets/images/pages/contribute/ambassador.png b/app/assets/images/pages/contribute/ambassador.png
index 177e6deeb..3d212e1de 100644
Binary files a/app/assets/images/pages/contribute/ambassador.png and b/app/assets/images/pages/contribute/ambassador.png differ
diff --git a/app/assets/images/pages/contribute/archmage.png b/app/assets/images/pages/contribute/archmage.png
index 6679c69e8..10c235078 100644
Binary files a/app/assets/images/pages/contribute/archmage.png and b/app/assets/images/pages/contribute/archmage.png differ
diff --git a/app/assets/images/pages/contribute/artisan.png b/app/assets/images/pages/contribute/artisan.png
index db357cddf..6a6db3613 100644
Binary files a/app/assets/images/pages/contribute/artisan.png and b/app/assets/images/pages/contribute/artisan.png differ
diff --git a/app/assets/images/pages/contribute/class_detail_adventurer.png b/app/assets/images/pages/contribute/class_detail_adventurer.png
index 2e738ae2d..11dd43372 100644
Binary files a/app/assets/images/pages/contribute/class_detail_adventurer.png and b/app/assets/images/pages/contribute/class_detail_adventurer.png differ
diff --git a/app/assets/images/pages/contribute/class_detail_ambassador.png b/app/assets/images/pages/contribute/class_detail_ambassador.png
index 632cb527b..3211000a4 100644
Binary files a/app/assets/images/pages/contribute/class_detail_ambassador.png and b/app/assets/images/pages/contribute/class_detail_ambassador.png differ
diff --git a/app/assets/images/pages/contribute/class_detail_archmage.png b/app/assets/images/pages/contribute/class_detail_archmage.png
index 25b0145bd..2575d2878 100644
Binary files a/app/assets/images/pages/contribute/class_detail_archmage.png and b/app/assets/images/pages/contribute/class_detail_archmage.png differ
diff --git a/app/assets/images/pages/contribute/class_detail_artisan.png b/app/assets/images/pages/contribute/class_detail_artisan.png
index 9d4f001e3..06cd17511 100644
Binary files a/app/assets/images/pages/contribute/class_detail_artisan.png and b/app/assets/images/pages/contribute/class_detail_artisan.png differ
diff --git a/app/assets/images/pages/contribute/class_detail_diplomat.png b/app/assets/images/pages/contribute/class_detail_diplomat.png
index d79d59bdf..6ceb08bf1 100644
Binary files a/app/assets/images/pages/contribute/class_detail_diplomat.png and b/app/assets/images/pages/contribute/class_detail_diplomat.png differ
diff --git a/app/assets/images/pages/contribute/class_detail_scribe.png b/app/assets/images/pages/contribute/class_detail_scribe.png
index a9378b41c..1801975ae 100644
Binary files a/app/assets/images/pages/contribute/class_detail_scribe.png and b/app/assets/images/pages/contribute/class_detail_scribe.png differ
diff --git a/app/assets/images/pages/contribute/counselor.png b/app/assets/images/pages/contribute/counselor.png
index 4f97d1939..f16e7e8c8 100644
Binary files a/app/assets/images/pages/contribute/counselor.png and b/app/assets/images/pages/contribute/counselor.png differ
diff --git a/app/assets/images/pages/contribute/tile_adventurer.png b/app/assets/images/pages/contribute/tile_adventurer.png
index 6b6a8b5eb..cf00fc20d 100644
Binary files a/app/assets/images/pages/contribute/tile_adventurer.png and b/app/assets/images/pages/contribute/tile_adventurer.png differ
diff --git a/app/assets/images/pages/contribute/tile_ambassador.png b/app/assets/images/pages/contribute/tile_ambassador.png
index a36b2ca5b..0d1e2cc58 100644
Binary files a/app/assets/images/pages/contribute/tile_ambassador.png and b/app/assets/images/pages/contribute/tile_ambassador.png differ
diff --git a/app/assets/images/pages/contribute/tile_archmage.png b/app/assets/images/pages/contribute/tile_archmage.png
index bb7659713..75d91de50 100644
Binary files a/app/assets/images/pages/contribute/tile_archmage.png and b/app/assets/images/pages/contribute/tile_archmage.png differ
diff --git a/app/assets/images/pages/contribute/tile_artisan.png b/app/assets/images/pages/contribute/tile_artisan.png
index 53b00e73a..90d4a13c0 100644
Binary files a/app/assets/images/pages/contribute/tile_artisan.png and b/app/assets/images/pages/contribute/tile_artisan.png differ
diff --git a/app/assets/images/pages/contribute/tile_diplomat.png b/app/assets/images/pages/contribute/tile_diplomat.png
index 46704bc0a..09308c8a9 100644
Binary files a/app/assets/images/pages/contribute/tile_diplomat.png and b/app/assets/images/pages/contribute/tile_diplomat.png differ
diff --git a/app/assets/images/pages/contribute/tile_scribe.png b/app/assets/images/pages/contribute/tile_scribe.png
index 3ee5a429a..8f7aa3ef9 100644
Binary files a/app/assets/images/pages/contribute/tile_scribe.png and b/app/assets/images/pages/contribute/tile_scribe.png differ
diff --git a/app/assets/images/pages/courses/101_info.png b/app/assets/images/pages/courses/101_info.png
index a2759a3ad..6a73381a9 100644
Binary files a/app/assets/images/pages/courses/101_info.png and b/app/assets/images/pages/courses/101_info.png differ
diff --git a/app/assets/images/pages/courses/102_info.png b/app/assets/images/pages/courses/102_info.png
index 91d3f02d7..4a94f7889 100644
Binary files a/app/assets/images/pages/courses/102_info.png and b/app/assets/images/pages/courses/102_info.png differ
diff --git a/app/assets/images/pages/courses/103_info.png b/app/assets/images/pages/courses/103_info.png
index 666b89080..54339ac1a 100644
Binary files a/app/assets/images/pages/courses/103_info.png and b/app/assets/images/pages/courses/103_info.png differ
diff --git a/app/assets/images/pages/courses/104_info.png b/app/assets/images/pages/courses/104_info.png
index 3695b60b4..4b73c4548 100644
Binary files a/app/assets/images/pages/courses/104_info.png and b/app/assets/images/pages/courses/104_info.png differ
diff --git a/app/assets/images/pages/courses/105_info.png b/app/assets/images/pages/courses/105_info.png
index d19e38e3b..063769b8a 100644
Binary files a/app/assets/images/pages/courses/105_info.png and b/app/assets/images/pages/courses/105_info.png differ
diff --git a/app/assets/images/pages/courses/106_info.png b/app/assets/images/pages/courses/106_info.png
index 5e7aa3a65..11396dbfa 100644
Binary files a/app/assets/images/pages/courses/106_info.png and b/app/assets/images/pages/courses/106_info.png differ
diff --git a/app/assets/images/pages/courses/107_info.png b/app/assets/images/pages/courses/107_info.png
index fa0e92b14..f2b5ce55e 100644
Binary files a/app/assets/images/pages/courses/107_info.png and b/app/assets/images/pages/courses/107_info.png differ
diff --git a/app/assets/images/pages/courses/coco_complab.png b/app/assets/images/pages/courses/coco_complab.png
index 35e6d7c68..531ab2be1 100644
Binary files a/app/assets/images/pages/courses/coco_complab.png and b/app/assets/images/pages/courses/coco_complab.png differ
diff --git a/app/assets/images/pages/editor/level/preset_dungeon_large.jpg b/app/assets/images/pages/editor/level/preset_dungeon_large.jpg
index b39f3558e..a5b6a59df 100644
Binary files a/app/assets/images/pages/editor/level/preset_dungeon_large.jpg and b/app/assets/images/pages/editor/level/preset_dungeon_large.jpg differ
diff --git a/app/assets/images/pages/editor/level/preset_dungeon_small.jpg b/app/assets/images/pages/editor/level/preset_dungeon_small.jpg
index a8fea9c5c..d3c1ee363 100644
Binary files a/app/assets/images/pages/editor/level/preset_dungeon_small.jpg and b/app/assets/images/pages/editor/level/preset_dungeon_small.jpg differ
diff --git a/app/assets/images/pages/editor/level/preset_grassy_large.jpg b/app/assets/images/pages/editor/level/preset_grassy_large.jpg
index 53c8bc2a7..33a844908 100644
Binary files a/app/assets/images/pages/editor/level/preset_grassy_large.jpg and b/app/assets/images/pages/editor/level/preset_grassy_large.jpg differ
diff --git a/app/assets/images/pages/editor/level/preset_grassy_small.jpg b/app/assets/images/pages/editor/level/preset_grassy_small.jpg
index ed9356944..6ff2c9aca 100644
Binary files a/app/assets/images/pages/editor/level/preset_grassy_small.jpg and b/app/assets/images/pages/editor/level/preset_grassy_small.jpg differ
diff --git a/app/assets/images/pages/editor/level/preset_indoor_large.jpg b/app/assets/images/pages/editor/level/preset_indoor_large.jpg
index 0ea8b6907..e4e0e13a5 100644
Binary files a/app/assets/images/pages/editor/level/preset_indoor_large.jpg and b/app/assets/images/pages/editor/level/preset_indoor_large.jpg differ
diff --git a/app/assets/images/pages/editor/level/preset_indoor_small.jpg b/app/assets/images/pages/editor/level/preset_indoor_small.jpg
index e172b56bd..1db2c9966 100644
Binary files a/app/assets/images/pages/editor/level/preset_indoor_small.jpg and b/app/assets/images/pages/editor/level/preset_indoor_small.jpg differ
diff --git a/app/assets/images/pages/employer/anon_user.png b/app/assets/images/pages/employer/anon_user.png
index 7191d604f..f4e24c0ed 100644
Binary files a/app/assets/images/pages/employer/anon_user.png and b/app/assets/images/pages/employer/anon_user.png differ
diff --git a/app/assets/images/pages/employer/artisanal_claim.png b/app/assets/images/pages/employer/artisanal_claim.png
index 4a4918ff7..8ba5cdd8b 100644
Binary files a/app/assets/images/pages/employer/artisanal_claim.png and b/app/assets/images/pages/employer/artisanal_claim.png differ
diff --git a/app/assets/images/pages/employer/briefcase.png b/app/assets/images/pages/employer/briefcase.png
index 66e605a47..0bc6cae5f 100644
Binary files a/app/assets/images/pages/employer/briefcase.png and b/app/assets/images/pages/employer/briefcase.png differ
diff --git a/app/assets/images/pages/employer/education.png b/app/assets/images/pages/employer/education.png
index 6c4d5b63c..d9c249ea6 100644
Binary files a/app/assets/images/pages/employer/education.png and b/app/assets/images/pages/employer/education.png differ
diff --git a/app/assets/images/pages/employer/employer_icon1.png b/app/assets/images/pages/employer/employer_icon1.png
index 1b58ce8dd..53f0ab199 100644
Binary files a/app/assets/images/pages/employer/employer_icon1.png and b/app/assets/images/pages/employer/employer_icon1.png differ
diff --git a/app/assets/images/pages/employer/employer_icon2.png b/app/assets/images/pages/employer/employer_icon2.png
index 3ea5b571d..220d36b94 100644
Binary files a/app/assets/images/pages/employer/employer_icon2.png and b/app/assets/images/pages/employer/employer_icon2.png differ
diff --git a/app/assets/images/pages/employer/employer_icon3.png b/app/assets/images/pages/employer/employer_icon3.png
index d29b0e609..d2ff87223 100644
Binary files a/app/assets/images/pages/employer/employer_icon3.png and b/app/assets/images/pages/employer/employer_icon3.png differ
diff --git a/app/assets/images/pages/employer/employer_icon4.png b/app/assets/images/pages/employer/employer_icon4.png
index df5c40222..8657a3154 100644
Binary files a/app/assets/images/pages/employer/employer_icon4.png and b/app/assets/images/pages/employer/employer_icon4.png differ
diff --git a/app/assets/images/pages/employer/employer_icon5.png b/app/assets/images/pages/employer/employer_icon5.png
index 85d94b04c..ed231d159 100644
Binary files a/app/assets/images/pages/employer/employer_icon5.png and b/app/assets/images/pages/employer/employer_icon5.png differ
diff --git a/app/assets/images/pages/employer/employer_icon6.png b/app/assets/images/pages/employer/employer_icon6.png
index bf3bb9e90..e7f401f34 100644
Binary files a/app/assets/images/pages/employer/employer_icon6.png and b/app/assets/images/pages/employer/employer_icon6.png differ
diff --git a/app/assets/images/pages/employer/location.png b/app/assets/images/pages/employer/location.png
index 3a21f6422..75ab1d091 100644
Binary files a/app/assets/images/pages/employer/location.png and b/app/assets/images/pages/employer/location.png differ
diff --git a/app/assets/images/pages/employer/tag.png b/app/assets/images/pages/employer/tag.png
index 0b022ce92..db88dabf3 100644
Binary files a/app/assets/images/pages/employer/tag.png and b/app/assets/images/pages/employer/tag.png differ
diff --git a/app/assets/images/pages/game-menu/lock-processed.png b/app/assets/images/pages/game-menu/lock-processed.png
index bb038b4b0..2444a9735 100644
Binary files a/app/assets/images/pages/game-menu/lock-processed.png and b/app/assets/images/pages/game-menu/lock-processed.png differ
diff --git a/app/assets/images/pages/game-menu/lock.png b/app/assets/images/pages/game-menu/lock.png
index c7d71ea7e..6aae22484 100644
Binary files a/app/assets/images/pages/game-menu/lock.png and b/app/assets/images/pages/game-menu/lock.png differ
diff --git a/app/assets/images/pages/game-menu/save-load-history-stub.png b/app/assets/images/pages/game-menu/save-load-history-stub.png
index 885db7010..914e2c6be 100644
Binary files a/app/assets/images/pages/game-menu/save-load-history-stub.png and b/app/assets/images/pages/game-menu/save-load-history-stub.png differ
diff --git a/app/assets/images/pages/game-menu/save-load-stub.png b/app/assets/images/pages/game-menu/save-load-stub.png
index ee201430e..e93b1b853 100644
Binary files a/app/assets/images/pages/game-menu/save-load-stub.png and b/app/assets/images/pages/game-menu/save-load-stub.png differ
diff --git a/app/assets/images/pages/game-menu/slot-icons.png b/app/assets/images/pages/game-menu/slot-icons.png
index b7ad722b1..ce6019df0 100644
Binary files a/app/assets/images/pages/game-menu/slot-icons.png and b/app/assets/images/pages/game-menu/slot-icons.png differ
diff --git a/app/assets/images/pages/home/boy_coding.png b/app/assets/images/pages/home/boy_coding.png
index 474d8c958..1ad50d1e0 100644
Binary files a/app/assets/images/pages/home/boy_coding.png and b/app/assets/images/pages/home/boy_coding.png differ
diff --git a/app/assets/images/pages/home/girl_coding.png b/app/assets/images/pages/home/girl_coding.png
index 4d587c31a..810d1cd60 100644
Binary files a/app/assets/images/pages/home/girl_coding.png and b/app/assets/images/pages/home/girl_coding.png differ
diff --git a/app/assets/images/pages/home/play_button.png b/app/assets/images/pages/home/play_button.png
index 7d4c74966..d8d8e08e5 100644
Binary files a/app/assets/images/pages/home/play_button.png and b/app/assets/images/pages/home/play_button.png differ
diff --git a/app/assets/images/pages/modal/auth/extra-pane.png b/app/assets/images/pages/modal/auth/extra-pane.png
index 83c8d6ee5..70ba6d0e1 100644
Binary files a/app/assets/images/pages/modal/auth/extra-pane.png and b/app/assets/images/pages/modal/auth/extra-pane.png differ
diff --git a/app/assets/images/pages/modal/auth/github_icon.png b/app/assets/images/pages/modal/auth/github_icon.png
index c4d3bb43b..908cd5141 100644
Binary files a/app/assets/images/pages/modal/auth/github_icon.png and b/app/assets/images/pages/modal/auth/github_icon.png differ
diff --git a/app/assets/images/pages/modal/auth/login-background.png b/app/assets/images/pages/modal/auth/login-background.png
index 00ee8341f..8e9b6c626 100644
Binary files a/app/assets/images/pages/modal/auth/login-background.png and b/app/assets/images/pages/modal/auth/login-background.png differ
diff --git a/app/assets/images/pages/modal/auth/signup-background.png b/app/assets/images/pages/modal/auth/signup-background.png
index add84857b..21fa8d204 100644
Binary files a/app/assets/images/pages/modal/auth/signup-background.png and b/app/assets/images/pages/modal/auth/signup-background.png differ
diff --git a/app/assets/images/pages/not_found/404_1.png b/app/assets/images/pages/not_found/404_1.png
index 0eab89857..cf443d8b4 100644
Binary files a/app/assets/images/pages/not_found/404_1.png and b/app/assets/images/pages/not_found/404_1.png differ
diff --git a/app/assets/images/pages/not_found/404_2.png b/app/assets/images/pages/not_found/404_2.png
index 156de14e1..77bd7dd21 100644
Binary files a/app/assets/images/pages/not_found/404_2.png and b/app/assets/images/pages/not_found/404_2.png differ
diff --git a/app/assets/images/pages/not_found/404_3.png b/app/assets/images/pages/not_found/404_3.png
index a990d55dd..66fde0e05 100644
Binary files a/app/assets/images/pages/not_found/404_3.png and b/app/assets/images/pages/not_found/404_3.png differ
diff --git a/app/assets/images/pages/play/campaign-banner.png b/app/assets/images/pages/play/campaign-banner.png
index 0ad6af9a0..34cf414ee 100644
Binary files a/app/assets/images/pages/play/campaign-banner.png and b/app/assets/images/pages/play/campaign-banner.png differ
diff --git a/app/assets/images/pages/play/ladder/easy_button.png b/app/assets/images/pages/play/ladder/easy_button.png
index c75dc83f9..35d91ef23 100644
Binary files a/app/assets/images/pages/play/ladder/easy_button.png and b/app/assets/images/pages/play/ladder/easy_button.png differ
diff --git a/app/assets/images/pages/play/ladder/hard_button.png b/app/assets/images/pages/play/ladder/hard_button.png
index 880b42442..1403f4cc9 100644
Binary files a/app/assets/images/pages/play/ladder/hard_button.png and b/app/assets/images/pages/play/ladder/hard_button.png differ
diff --git a/app/assets/images/pages/play/ladder/humans_ladder_easy.png b/app/assets/images/pages/play/ladder/humans_ladder_easy.png
index 095b57688..df3af194a 100644
Binary files a/app/assets/images/pages/play/ladder/humans_ladder_easy.png and b/app/assets/images/pages/play/ladder/humans_ladder_easy.png differ
diff --git a/app/assets/images/pages/play/ladder/humans_ladder_hard.png b/app/assets/images/pages/play/ladder/humans_ladder_hard.png
index 90afbd048..9e64ac0ad 100644
Binary files a/app/assets/images/pages/play/ladder/humans_ladder_hard.png and b/app/assets/images/pages/play/ladder/humans_ladder_hard.png differ
diff --git a/app/assets/images/pages/play/ladder/humans_ladder_medium.png b/app/assets/images/pages/play/ladder/humans_ladder_medium.png
index 4d5570ebf..b321f250f 100644
Binary files a/app/assets/images/pages/play/ladder/humans_ladder_medium.png and b/app/assets/images/pages/play/ladder/humans_ladder_medium.png differ
diff --git a/app/assets/images/pages/play/ladder/humans_ladder_tutorial.png b/app/assets/images/pages/play/ladder/humans_ladder_tutorial.png
index d4f1ffffe..eb9a8fec7 100644
Binary files a/app/assets/images/pages/play/ladder/humans_ladder_tutorial.png and b/app/assets/images/pages/play/ladder/humans_ladder_tutorial.png differ
diff --git a/app/assets/images/pages/play/ladder/medium_button.png b/app/assets/images/pages/play/ladder/medium_button.png
index 41f87572e..0ec3466a2 100644
Binary files a/app/assets/images/pages/play/ladder/medium_button.png and b/app/assets/images/pages/play/ladder/medium_button.png differ
diff --git a/app/assets/images/pages/play/ladder/multiplayer_notext.jpg b/app/assets/images/pages/play/ladder/multiplayer_notext.jpg
index b4657d397..aba55f233 100644
Binary files a/app/assets/images/pages/play/ladder/multiplayer_notext.jpg and b/app/assets/images/pages/play/ladder/multiplayer_notext.jpg differ
diff --git a/app/assets/images/pages/play/ladder/ogres_ladder_easy.png b/app/assets/images/pages/play/ladder/ogres_ladder_easy.png
index ae82c36ca..b09c7ac4b 100644
Binary files a/app/assets/images/pages/play/ladder/ogres_ladder_easy.png and b/app/assets/images/pages/play/ladder/ogres_ladder_easy.png differ
diff --git a/app/assets/images/pages/play/ladder/ogres_ladder_hard.png b/app/assets/images/pages/play/ladder/ogres_ladder_hard.png
index 36204caf5..9b33c9347 100644
Binary files a/app/assets/images/pages/play/ladder/ogres_ladder_hard.png and b/app/assets/images/pages/play/ladder/ogres_ladder_hard.png differ
diff --git a/app/assets/images/pages/play/ladder/ogres_ladder_medium.png b/app/assets/images/pages/play/ladder/ogres_ladder_medium.png
index a86ac9585..52607b498 100644
Binary files a/app/assets/images/pages/play/ladder/ogres_ladder_medium.png and b/app/assets/images/pages/play/ladder/ogres_ladder_medium.png differ
diff --git a/app/assets/images/pages/play/ladder/ogres_ladder_tutorial.png b/app/assets/images/pages/play/ladder/ogres_ladder_tutorial.png
index 939a534c7..b56123054 100644
Binary files a/app/assets/images/pages/play/ladder/ogres_ladder_tutorial.png and b/app/assets/images/pages/play/ladder/ogres_ladder_tutorial.png differ
diff --git a/app/assets/images/pages/play/ladder/prize_aws.png b/app/assets/images/pages/play/ladder/prize_aws.png
index 65facdf8f..d5a86731b 100644
Binary files a/app/assets/images/pages/play/ladder/prize_aws.png and b/app/assets/images/pages/play/ladder/prize_aws.png differ
diff --git a/app/assets/images/pages/play/ladder/prize_cash1.png b/app/assets/images/pages/play/ladder/prize_cash1.png
index 2508a7e3c..bf6a01358 100644
Binary files a/app/assets/images/pages/play/ladder/prize_cash1.png and b/app/assets/images/pages/play/ladder/prize_cash1.png differ
diff --git a/app/assets/images/pages/play/ladder/prize_cash2.png b/app/assets/images/pages/play/ladder/prize_cash2.png
index 2b13bcc3d..13682cad1 100644
Binary files a/app/assets/images/pages/play/ladder/prize_cash2.png and b/app/assets/images/pages/play/ladder/prize_cash2.png differ
diff --git a/app/assets/images/pages/play/ladder/prize_cash3.png b/app/assets/images/pages/play/ladder/prize_cash3.png
index c70f428ab..31fa6824c 100644
Binary files a/app/assets/images/pages/play/ladder/prize_cash3.png and b/app/assets/images/pages/play/ladder/prize_cash3.png differ
diff --git a/app/assets/images/pages/play/ladder/prize_custom_avatar.png b/app/assets/images/pages/play/ladder/prize_custom_avatar.png
index fae6cf950..762443435 100644
Binary files a/app/assets/images/pages/play/ladder/prize_custom_avatar.png and b/app/assets/images/pages/play/ladder/prize_custom_avatar.png differ
diff --git a/app/assets/images/pages/play/ladder/prize_custom_wizard.png b/app/assets/images/pages/play/ladder/prize_custom_wizard.png
index 108a31e69..9629a1e80 100644
Binary files a/app/assets/images/pages/play/ladder/prize_custom_wizard.png and b/app/assets/images/pages/play/ladder/prize_custom_wizard.png differ
diff --git a/app/assets/images/pages/play/ladder/prize_digital_ocean.png b/app/assets/images/pages/play/ladder/prize_digital_ocean.png
index e9c0406c1..b33662fe9 100644
Binary files a/app/assets/images/pages/play/ladder/prize_digital_ocean.png and b/app/assets/images/pages/play/ladder/prize_digital_ocean.png differ
diff --git a/app/assets/images/pages/play/ladder/prize_firebase.png b/app/assets/images/pages/play/ladder/prize_firebase.png
index 3aec861c6..49d2f2f88 100644
Binary files a/app/assets/images/pages/play/ladder/prize_firebase.png and b/app/assets/images/pages/play/ladder/prize_firebase.png differ
diff --git a/app/assets/images/pages/play/ladder/prize_heap.png b/app/assets/images/pages/play/ladder/prize_heap.png
index 2770d0456..03bf8c5d0 100644
Binary files a/app/assets/images/pages/play/ladder/prize_heap.png and b/app/assets/images/pages/play/ladder/prize_heap.png differ
diff --git a/app/assets/images/pages/play/ladder/prize_one_month.png b/app/assets/images/pages/play/ladder/prize_one_month.png
index be2942a09..b4e66fee4 100644
Binary files a/app/assets/images/pages/play/ladder/prize_one_month.png and b/app/assets/images/pages/play/ladder/prize_one_month.png differ
diff --git a/app/assets/images/pages/play/ladder/prize_oreilly.png b/app/assets/images/pages/play/ladder/prize_oreilly.png
index f0430a695..354aab1d9 100644
Binary files a/app/assets/images/pages/play/ladder/prize_oreilly.png and b/app/assets/images/pages/play/ladder/prize_oreilly.png differ
diff --git a/app/assets/images/pages/play/ladder/prize_webstorm.png b/app/assets/images/pages/play/ladder/prize_webstorm.png
index dba0a30dc..a8f06ea0a 100644
Binary files a/app/assets/images/pages/play/ladder/prize_webstorm.png and b/app/assets/images/pages/play/ladder/prize_webstorm.png differ
diff --git a/app/assets/images/pages/play/ladder/warmup_button.png b/app/assets/images/pages/play/ladder/warmup_button.png
index ccc6503b2..707414699 100644
Binary files a/app/assets/images/pages/play/ladder/warmup_button.png and b/app/assets/images/pages/play/ladder/warmup_button.png differ
diff --git a/app/assets/images/pages/play/level-banner-complete.png b/app/assets/images/pages/play/level-banner-complete.png
index 4ea601195..282fb1f96 100644
Binary files a/app/assets/images/pages/play/level-banner-complete.png and b/app/assets/images/pages/play/level-banner-complete.png differ
diff --git a/app/assets/images/pages/play/level-banner-started.png b/app/assets/images/pages/play/level-banner-started.png
index c84d89526..841f02fd2 100644
Binary files a/app/assets/images/pages/play/level-banner-started.png and b/app/assets/images/pages/play/level-banner-started.png differ
diff --git a/app/assets/images/pages/play/level-info-background.png b/app/assets/images/pages/play/level-info-background.png
index 6b4c847ee..3857532ae 100644
Binary files a/app/assets/images/pages/play/level-info-background.png and b/app/assets/images/pages/play/level-info-background.png differ
diff --git a/app/assets/images/pages/play/level-info-status-spritesheet.png b/app/assets/images/pages/play/level-info-status-spritesheet.png
index 1f6b1f30c..93b808192 100644
Binary files a/app/assets/images/pages/play/level-info-status-spritesheet.png and b/app/assets/images/pages/play/level-info-status-spritesheet.png differ
diff --git a/app/assets/images/pages/play/level/modal/reward_icon_gems.png b/app/assets/images/pages/play/level/modal/reward_icon_gems.png
index 3cdc24894..65c4940b1 100644
Binary files a/app/assets/images/pages/play/level/modal/reward_icon_gems.png and b/app/assets/images/pages/play/level/modal/reward_icon_gems.png differ
diff --git a/app/assets/images/pages/play/level/modal/reward_icon_xp.png b/app/assets/images/pages/play/level/modal/reward_icon_xp.png
index 3644b1fe9..ac42cbb62 100644
Binary files a/app/assets/images/pages/play/level/modal/reward_icon_xp.png and b/app/assets/images/pages/play/level/modal/reward_icon_xp.png differ
diff --git a/app/assets/images/pages/play/level/modal/reward_plate.png b/app/assets/images/pages/play/level/modal/reward_plate.png
index 0a0a7b6e7..d6d5592ae 100644
Binary files a/app/assets/images/pages/play/level/modal/reward_plate.png and b/app/assets/images/pages/play/level/modal/reward_plate.png differ
diff --git a/app/assets/images/pages/play/level/modal/reward_plate_wide.png b/app/assets/images/pages/play/level/modal/reward_plate_wide.png
index d99ae8fac..426b770f4 100644
Binary files a/app/assets/images/pages/play/level/modal/reward_plate_wide.png and b/app/assets/images/pages/play/level/modal/reward_plate_wide.png differ
diff --git a/app/assets/images/pages/play/level/modal/victory_hero.png b/app/assets/images/pages/play/level/modal/victory_hero.png
index 068af4688..fcff611a2 100644
Binary files a/app/assets/images/pages/play/level/modal/victory_hero.png and b/app/assets/images/pages/play/level/modal/victory_hero.png differ
diff --git a/app/assets/images/pages/play/level/modal/victory_modal_background.png b/app/assets/images/pages/play/level/modal/victory_modal_background.png
index 7ed30bcb4..8b6270488 100644
Binary files a/app/assets/images/pages/play/level/modal/victory_modal_background.png and b/app/assets/images/pages/play/level/modal/victory_modal_background.png differ
diff --git a/app/assets/images/pages/play/level/modal/victory_modal_border_background.png b/app/assets/images/pages/play/level/modal/victory_modal_border_background.png
index 00657032c..f9ea8eaa9 100644
Binary files a/app/assets/images/pages/play/level/modal/victory_modal_border_background.png and b/app/assets/images/pages/play/level/modal/victory_modal_border_background.png differ
diff --git a/app/assets/images/pages/play/level/modal/victory_modal_shelf.png b/app/assets/images/pages/play/level/modal/victory_modal_shelf.png
index bd8586443..f9c38e066 100644
Binary files a/app/assets/images/pages/play/level/modal/victory_modal_shelf.png and b/app/assets/images/pages/play/level/modal/victory_modal_shelf.png differ
diff --git a/app/assets/images/pages/play/level/modal/victory_word.png b/app/assets/images/pages/play/level/modal/victory_word.png
index 0ead423a1..4e5995f2c 100644
Binary files a/app/assets/images/pages/play/level/modal/victory_word.png and b/app/assets/images/pages/play/level/modal/victory_word.png differ
diff --git a/app/assets/images/pages/play/level/modal/xp_gems_parchment.png b/app/assets/images/pages/play/level/modal/xp_gems_parchment.png
index 917db106f..f41be971a 100644
Binary files a/app/assets/images/pages/play/level/modal/xp_gems_parchment.png and b/app/assets/images/pages/play/level/modal/xp_gems_parchment.png differ
diff --git a/app/assets/images/pages/play/menu_icons.png b/app/assets/images/pages/play/menu_icons.png
index 37cd5fc03..585e52c88 100644
Binary files a/app/assets/images/pages/play/menu_icons.png and b/app/assets/images/pages/play/menu_icons.png differ
diff --git a/app/assets/images/pages/play/modal/buy-gems-background.png b/app/assets/images/pages/play/modal/buy-gems-background.png
index 59b61d07f..1c82ffe17 100644
Binary files a/app/assets/images/pages/play/modal/buy-gems-background.png and b/app/assets/images/pages/play/modal/buy-gems-background.png differ
diff --git a/app/assets/images/pages/play/modal/confirm-button.png b/app/assets/images/pages/play/modal/confirm-button.png
index 73c02f19d..21bf7b0a4 100644
Binary files a/app/assets/images/pages/play/modal/confirm-button.png and b/app/assets/images/pages/play/modal/confirm-button.png differ
diff --git a/app/assets/images/pages/play/modal/equip-buttons.png b/app/assets/images/pages/play/modal/equip-buttons.png
index 0c3eaf15b..397e9b0ec 100644
Binary files a/app/assets/images/pages/play/modal/equip-buttons.png and b/app/assets/images/pages/play/modal/equip-buttons.png differ
diff --git a/app/assets/images/pages/play/modal/game-menu-background.png b/app/assets/images/pages/play/modal/game-menu-background.png
index aa7a5ec28..f5d57b832 100644
Binary files a/app/assets/images/pages/play/modal/game-menu-background.png and b/app/assets/images/pages/play/modal/game-menu-background.png differ
diff --git a/app/assets/images/pages/play/modal/hero-portrait-selected.png b/app/assets/images/pages/play/modal/hero-portrait-selected.png
index a1c2cfebb..73209948e 100644
Binary files a/app/assets/images/pages/play/modal/hero-portrait-selected.png and b/app/assets/images/pages/play/modal/hero-portrait-selected.png differ
diff --git a/app/assets/images/pages/play/modal/hero-portrait.png b/app/assets/images/pages/play/modal/hero-portrait.png
index 49b79c1b0..21f08d200 100644
Binary files a/app/assets/images/pages/play/modal/hero-portrait.png and b/app/assets/images/pages/play/modal/hero-portrait.png differ
diff --git a/app/assets/images/pages/play/modal/heroes-background.png b/app/assets/images/pages/play/modal/heroes-background.png
index 612dbfda6..89e0bc56b 100644
Binary files a/app/assets/images/pages/play/modal/heroes-background.png and b/app/assets/images/pages/play/modal/heroes-background.png differ
diff --git a/app/assets/images/pages/play/modal/hr.png b/app/assets/images/pages/play/modal/hr.png
index 47ed3904f..f8a351b46 100644
Binary files a/app/assets/images/pages/play/modal/hr.png and b/app/assets/images/pages/play/modal/hr.png differ
diff --git a/app/assets/images/pages/play/modal/inventory-background.png b/app/assets/images/pages/play/modal/inventory-background.png
index 9217b51d9..b052d524e 100644
Binary files a/app/assets/images/pages/play/modal/inventory-background.png and b/app/assets/images/pages/play/modal/inventory-background.png differ
diff --git a/app/assets/images/pages/play/modal/item-box-background-selected.png b/app/assets/images/pages/play/modal/item-box-background-selected.png
index a32e32596..105b0192b 100644
Binary files a/app/assets/images/pages/play/modal/item-box-background-selected.png and b/app/assets/images/pages/play/modal/item-box-background-selected.png differ
diff --git a/app/assets/images/pages/play/modal/item-box-background.png b/app/assets/images/pages/play/modal/item-box-background.png
index 11ea27c2c..cf504f5d1 100644
Binary files a/app/assets/images/pages/play/modal/item-box-background.png and b/app/assets/images/pages/play/modal/item-box-background.png differ
diff --git a/app/assets/images/pages/play/modal/item-icon-accessories.png b/app/assets/images/pages/play/modal/item-icon-accessories.png
index 07c321f5b..82b083fa9 100644
Binary files a/app/assets/images/pages/play/modal/item-icon-accessories.png and b/app/assets/images/pages/play/modal/item-icon-accessories.png differ
diff --git a/app/assets/images/pages/play/modal/item-icon-armor.png b/app/assets/images/pages/play/modal/item-icon-armor.png
index 0be834a85..6b20e288c 100644
Binary files a/app/assets/images/pages/play/modal/item-icon-armor.png and b/app/assets/images/pages/play/modal/item-icon-armor.png differ
diff --git a/app/assets/images/pages/play/modal/item-icon-books.png b/app/assets/images/pages/play/modal/item-icon-books.png
index 2f60882bd..bc63f218a 100644
Binary files a/app/assets/images/pages/play/modal/item-icon-books.png and b/app/assets/images/pages/play/modal/item-icon-books.png differ
diff --git a/app/assets/images/pages/play/modal/item-icon-misc.png b/app/assets/images/pages/play/modal/item-icon-misc.png
index 4a1240b83..964a06c85 100644
Binary files a/app/assets/images/pages/play/modal/item-icon-misc.png and b/app/assets/images/pages/play/modal/item-icon-misc.png differ
diff --git a/app/assets/images/pages/play/modal/item-icon-primary.png b/app/assets/images/pages/play/modal/item-icon-primary.png
index f6348d4ae..cac3d8460 100644
Binary files a/app/assets/images/pages/play/modal/item-icon-primary.png and b/app/assets/images/pages/play/modal/item-icon-primary.png differ
diff --git a/app/assets/images/pages/play/modal/item-icon-secondary.png b/app/assets/images/pages/play/modal/item-icon-secondary.png
index 616588e41..740c0b00a 100644
Binary files a/app/assets/images/pages/play/modal/item-icon-secondary.png and b/app/assets/images/pages/play/modal/item-icon-secondary.png differ
diff --git a/app/assets/images/pages/play/modal/items-background-narrow.png b/app/assets/images/pages/play/modal/items-background-narrow.png
index facca4861..b6e0fcb03 100644
Binary files a/app/assets/images/pages/play/modal/items-background-narrow.png and b/app/assets/images/pages/play/modal/items-background-narrow.png differ
diff --git a/app/assets/images/pages/play/modal/items-background.png b/app/assets/images/pages/play/modal/items-background.png
index 991b1eaa2..81c8d8607 100644
Binary files a/app/assets/images/pages/play/modal/items-background.png and b/app/assets/images/pages/play/modal/items-background.png differ
diff --git a/app/assets/images/pages/play/modal/k-means.gif b/app/assets/images/pages/play/modal/k-means.gif
index 862df3aa1..d16608e72 100644
Binary files a/app/assets/images/pages/play/modal/k-means.gif and b/app/assets/images/pages/play/modal/k-means.gif differ
diff --git a/app/assets/images/pages/play/modal/leaderboard-background.png b/app/assets/images/pages/play/modal/leaderboard-background.png
index 28d3a8260..4a9182831 100644
Binary files a/app/assets/images/pages/play/modal/leaderboard-background.png and b/app/assets/images/pages/play/modal/leaderboard-background.png differ
diff --git a/app/assets/images/pages/play/modal/menu-tab-selected.png b/app/assets/images/pages/play/modal/menu-tab-selected.png
index fbef30685..a6cc079d8 100644
Binary files a/app/assets/images/pages/play/modal/menu-tab-selected.png and b/app/assets/images/pages/play/modal/menu-tab-selected.png differ
diff --git a/app/assets/images/pages/play/modal/menu-tab.png b/app/assets/images/pages/play/modal/menu-tab.png
index 185a47d6a..76cbb0830 100644
Binary files a/app/assets/images/pages/play/modal/menu-tab.png and b/app/assets/images/pages/play/modal/menu-tab.png differ
diff --git a/app/assets/images/pages/play/modal/parental_nudge_wizard.png b/app/assets/images/pages/play/modal/parental_nudge_wizard.png
index cf98ead1a..75212ee3a 100644
Binary files a/app/assets/images/pages/play/modal/parental_nudge_wizard.png and b/app/assets/images/pages/play/modal/parental_nudge_wizard.png differ
diff --git a/app/assets/images/pages/play/modal/parental_prompt_modal_background.png b/app/assets/images/pages/play/modal/parental_prompt_modal_background.png
index bab86a3ca..3cf40b992 100644
Binary files a/app/assets/images/pages/play/modal/parental_prompt_modal_background.png and b/app/assets/images/pages/play/modal/parental_prompt_modal_background.png differ
diff --git a/app/assets/images/pages/play/modal/random-gems-background.png b/app/assets/images/pages/play/modal/random-gems-background.png
index 6ca966d12..dd7899fdf 100644
Binary files a/app/assets/images/pages/play/modal/random-gems-background.png and b/app/assets/images/pages/play/modal/random-gems-background.png differ
diff --git a/app/assets/images/pages/play/modal/subscribe-background-blank.png b/app/assets/images/pages/play/modal/subscribe-background-blank.png
index 8c13a3534..86e46fecd 100644
Binary files a/app/assets/images/pages/play/modal/subscribe-background-blank.png and b/app/assets/images/pages/play/modal/subscribe-background-blank.png differ
diff --git a/app/assets/images/pages/play/modal/subscribe-background.png b/app/assets/images/pages/play/modal/subscribe-background.png
index eab6b42ac..2c2a503f2 100644
Binary files a/app/assets/images/pages/play/modal/subscribe-background.png and b/app/assets/images/pages/play/modal/subscribe-background.png differ
diff --git a/app/assets/images/pages/play/modal/subscribe-gems.png b/app/assets/images/pages/play/modal/subscribe-gems.png
index 9f22df75c..bb1d3ab95 100644
Binary files a/app/assets/images/pages/play/modal/subscribe-gems.png and b/app/assets/images/pages/play/modal/subscribe-gems.png differ
diff --git a/app/assets/images/pages/play/modal/subscribe-heroes.png b/app/assets/images/pages/play/modal/subscribe-heroes.png
index bd55cf02b..852062fd5 100644
Binary files a/app/assets/images/pages/play/modal/subscribe-heroes.png and b/app/assets/images/pages/play/modal/subscribe-heroes.png differ
diff --git a/app/assets/images/pages/play/play-spritesheet.png b/app/assets/images/pages/play/play-spritesheet.png
index 7d40446b5..f0c78f2ca 100644
Binary files a/app/assets/images/pages/play/play-spritesheet.png and b/app/assets/images/pages/play/play-spritesheet.png differ
diff --git a/app/assets/images/pages/play/portal-background.png b/app/assets/images/pages/play/portal-background.png
index 4a9d33933..0a774aab1 100644
Binary files a/app/assets/images/pages/play/portal-background.png and b/app/assets/images/pages/play/portal-background.png differ
diff --git a/app/assets/images/pages/play/portal-campaigns.png b/app/assets/images/pages/play/portal-campaigns.png
index 3d9806dd1..ce26f1633 100644
Binary files a/app/assets/images/pages/play/portal-campaigns.png and b/app/assets/images/pages/play/portal-campaigns.png differ
diff --git a/app/assets/images/pages/sales/chat_icon.png b/app/assets/images/pages/sales/chat_icon.png
index 82cf47824..2070f59e9 100644
Binary files a/app/assets/images/pages/sales/chat_icon.png and b/app/assets/images/pages/sales/chat_icon.png differ
diff --git a/app/assets/images/pages/sales/classroom1.png b/app/assets/images/pages/sales/classroom1.png
index d742252dc..78d654d0a 100644
Binary files a/app/assets/images/pages/sales/classroom1.png and b/app/assets/images/pages/sales/classroom1.png differ
diff --git a/app/assets/images/pages/sales/classroom2.png b/app/assets/images/pages/sales/classroom2.png
index 8a2834b52..79c15941b 100644
Binary files a/app/assets/images/pages/sales/classroom2.png and b/app/assets/images/pages/sales/classroom2.png differ
diff --git a/app/assets/images/pages/sales/classroom3.png b/app/assets/images/pages/sales/classroom3.png
index cce4cd068..5669e0259 100644
Binary files a/app/assets/images/pages/sales/classroom3.png and b/app/assets/images/pages/sales/classroom3.png differ
diff --git a/app/assets/images/pages/sales/classroom4.png b/app/assets/images/pages/sales/classroom4.png
index 89e75b3fc..e1c64a7b0 100644
Binary files a/app/assets/images/pages/sales/classroom4.png and b/app/assets/images/pages/sales/classroom4.png differ
diff --git a/app/assets/images/pages/sales/classroom5.png b/app/assets/images/pages/sales/classroom5.png
index 6de5927cb..75752cda1 100644
Binary files a/app/assets/images/pages/sales/classroom5.png and b/app/assets/images/pages/sales/classroom5.png differ
diff --git a/app/assets/images/pages/sales/classroom6.png b/app/assets/images/pages/sales/classroom6.png
index 723d27337..05d42a441 100644
Binary files a/app/assets/images/pages/sales/classroom6.png and b/app/assets/images/pages/sales/classroom6.png differ
diff --git a/app/assets/images/pages/sales/content_table.png b/app/assets/images/pages/sales/content_table.png
index d10574807..a60fa0a2f 100644
Binary files a/app/assets/images/pages/sales/content_table.png and b/app/assets/images/pages/sales/content_table.png differ
diff --git a/app/assets/images/pages/sales/down_arrow.png b/app/assets/images/pages/sales/down_arrow.png
index 2ebe8ef15..6e265ca35 100644
Binary files a/app/assets/images/pages/sales/down_arrow.png and b/app/assets/images/pages/sales/down_arrow.png differ
diff --git a/app/assets/images/pages/sales/hero_background.png b/app/assets/images/pages/sales/hero_background.png
index 1fde05f6a..cf819050f 100644
Binary files a/app/assets/images/pages/sales/hero_background.png and b/app/assets/images/pages/sales/hero_background.png differ
diff --git a/app/assets/images/pages/sales/quote1.png b/app/assets/images/pages/sales/quote1.png
index 3aa52f3af..6b106a7f5 100644
Binary files a/app/assets/images/pages/sales/quote1.png and b/app/assets/images/pages/sales/quote1.png differ
diff --git a/app/assets/images/pages/sales/quote2.png b/app/assets/images/pages/sales/quote2.png
index 19f66af11..f6399dea7 100644
Binary files a/app/assets/images/pages/sales/quote2.png and b/app/assets/images/pages/sales/quote2.png differ
diff --git a/app/assets/images/pages/sales/screen1.png b/app/assets/images/pages/sales/screen1.png
index b778b173a..85bb9827c 100644
Binary files a/app/assets/images/pages/sales/screen1.png and b/app/assets/images/pages/sales/screen1.png differ
diff --git a/app/assets/images/pages/sales/screen2.png b/app/assets/images/pages/sales/screen2.png
index 237d7673b..c6ef953fd 100644
Binary files a/app/assets/images/pages/sales/screen2.png and b/app/assets/images/pages/sales/screen2.png differ
diff --git a/app/assets/images/pages/user/adventurer.png b/app/assets/images/pages/user/adventurer.png
index 2729d87b8..78ef01d8d 100644
Binary files a/app/assets/images/pages/user/adventurer.png and b/app/assets/images/pages/user/adventurer.png differ
diff --git a/app/assets/images/pages/user/ambassador.png b/app/assets/images/pages/user/ambassador.png
index f30002b33..ce3acea91 100644
Binary files a/app/assets/images/pages/user/ambassador.png and b/app/assets/images/pages/user/ambassador.png differ
diff --git a/app/assets/images/pages/user/archmage.png b/app/assets/images/pages/user/archmage.png
index dad621ee0..49b1fbeb5 100644
Binary files a/app/assets/images/pages/user/archmage.png and b/app/assets/images/pages/user/archmage.png differ
diff --git a/app/assets/images/pages/user/artisan.png b/app/assets/images/pages/user/artisan.png
index 351b1eace..1f01b621e 100644
Binary files a/app/assets/images/pages/user/artisan.png and b/app/assets/images/pages/user/artisan.png differ
diff --git a/app/assets/images/pages/user/diplomat.png b/app/assets/images/pages/user/diplomat.png
index 76c1cb6a7..e7c59841f 100644
Binary files a/app/assets/images/pages/user/diplomat.png and b/app/assets/images/pages/user/diplomat.png differ
diff --git a/app/assets/images/pages/user/general.png b/app/assets/images/pages/user/general.png
index f57cf15d6..7217bfd28 100644
Binary files a/app/assets/images/pages/user/general.png and b/app/assets/images/pages/user/general.png differ
diff --git a/app/assets/images/pages/user/scribe.png b/app/assets/images/pages/user/scribe.png
index 8c19f22ba..2f9ee231b 100644
Binary files a/app/assets/images/pages/user/scribe.png and b/app/assets/images/pages/user/scribe.png differ
diff --git a/app/assets/images/twitter_icon.png b/app/assets/images/twitter_icon.png
index 61054bd30..ba4018b91 100644
Binary files a/app/assets/images/twitter_icon.png and b/app/assets/images/twitter_icon.png differ
diff --git a/app/assets/main.html b/app/assets/main.html
index 765fe89ce..8d3018d5f 100644
--- a/app/assets/main.html
+++ b/app/assets/main.html
@@ -47,6 +47,10 @@
       (window,document,"script","51a79585ee207206390002a2");
   </script>
 
+<!-- start Mixpanel --><script type="text/javascript">(function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!==typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable time_event track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.union people.track_charge people.clear_charges people.delete_user".split(" ");
+for(g=0;g<i.length;g++)f(c,i[g]);b._i.push([a,e,d])};b.__SV=1.2;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src="undefined"!==typeof MIXPANEL_CUSTOM_LIB_URL?MIXPANEL_CUSTOM_LIB_URL:"file:"===e.location.protocol&&"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\/\//)?"https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js":"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f)}})(document,window.mixpanel||[]);
+mixpanel.init("e71a4e60db7e1dc5e685be96776280f9");</script><!-- end Mixpanel -->
+
   <script src="https://checkout.stripe.com/checkout.js"></script>
 
   <!-- IE9 doesn't support defer attribute: https://github.com/h5bp/lazyweb-requests/issues/42 -->
diff --git a/app/collections/AchievementCollection.coffee b/app/collections/Achievements.coffee
similarity index 57%
rename from app/collections/AchievementCollection.coffee
rename to app/collections/Achievements.coffee
index d3bbe0343..a25a77a47 100644
--- a/app/collections/AchievementCollection.coffee
+++ b/app/collections/Achievements.coffee
@@ -4,3 +4,8 @@ Achievement = require 'models/Achievement'
 module.exports = class AchievementCollection extends CocoCollection
   url: '/db/achievement'
   model: Achievement
+  
+  fetchRelatedToLevel: (levelOriginal, options) ->
+    options = _.extend({data: {}}, options)
+    options.data.related = levelOriginal
+    @fetch(options)
diff --git a/app/collections/LevelSessions.coffee b/app/collections/LevelSessions.coffee
new file mode 100644
index 000000000..7f69e64fb
--- /dev/null
+++ b/app/collections/LevelSessions.coffee
@@ -0,0 +1,12 @@
+CocoCollection = require 'collections/CocoCollection'
+LevelSession = require 'models/LevelSession'
+
+module.exports = class LevelSessionCollection extends CocoCollection
+  url: '/db/level.session'
+  model: LevelSession
+
+  fetchForCourseInstance: (courseInstanceID, options) ->
+    options = _.extend({
+      url: "/db/course_instance/#{courseInstanceID}/my-course-level-sessions"
+    }, options)
+    @fetch(options)
diff --git a/app/collections/ThangTypes.coffee b/app/collections/ThangTypes.coffee
new file mode 100644
index 000000000..8dd041307
--- /dev/null
+++ b/app/collections/ThangTypes.coffee
@@ -0,0 +1,6 @@
+CocoCollection = require 'collections/CocoCollection'
+ThangType = require 'models/ThangType'
+
+module.exports = class ThangTypeCollection extends CocoCollection
+  url: '/db/thang.type'
+  model: ThangType
\ No newline at end of file
diff --git a/app/core/ModuleLoader.coffee b/app/core/ModuleLoader.coffee
index f11a5591d..401b35735 100644
--- a/app/core/ModuleLoader.coffee
+++ b/app/core/ModuleLoader.coffee
@@ -21,6 +21,7 @@ module.exports = ModuleLoader = class ModuleLoader extends CocoClass
       # vendor libraries aren't actually wrapped with common.js, so short circuit those requires
       return {} if _.string.startsWith(name, 'vendor/')
       return {} if name is 'tests'
+      return {} if name is 'demo-app'
       name = 'core/auth' if name is 'lib/auth' # proxy for iPad until it's been updated to use the new, refactored location. TODO: remove this
       return func(name, loaderPath)
     _.extend wrapped, window.require # for functions like 'list'
diff --git a/app/core/Router.coffee b/app/core/Router.coffee
index 6e6bcb5df..e4025a118 100644
--- a/app/core/Router.coffee
+++ b/app/core/Router.coffee
@@ -27,6 +27,7 @@ module.exports = class CocoRouter extends Backbone.Router
 
     'admin': go('admin/MainAdminView')
     'admin/clas': go('admin/CLAsView')
+    'admin/design-elements': go('admin/DesignElementsView')
     'admin/files': go('admin/FilesView')
     'admin/analytics': go('admin/AnalyticsView')
     'admin/analytics/subscriptions': go('admin/AnalyticsSubscriptionsView')
diff --git a/app/core/Tracker.coffee b/app/core/Tracker.coffee
index 3e11d1180..3679e664e 100644
--- a/app/core/Tracker.coffee
+++ b/app/core/Tracker.coffee
@@ -62,9 +62,9 @@ module.exports = class Tracker
     @explicitTraits ?= {}
     @explicitTraits[key] = value for key, value of traits
 
-    for userTrait in ['email', 'anonymous', 'dateCreated', 'name', 'testGroupNumber', 'gender', 'lastLevel', 'siteref', 'ageRange']
+    for userTrait in ['email', 'anonymous', 'dateCreated', 'name', 'testGroupNumber', 'gender', 'lastLevel', 'siteref', 'ageRange', 'schoolName', 'coursePrepaidID']
       traits[userTrait] ?= me.get(userTrait)
-    console.log 'Would identify', traits if debugAnalytics
+    console.log 'Would identify', me.id, traits if debugAnalytics
     return unless @isProduction and not me.isAdmin()
 
     # Errorception
@@ -76,19 +76,29 @@ module.exports = class Tracker
     __insp?.push ['identify', me.id]
     __insp?.push ['tagSession', traits]
 
+    # Mixpanel
+    # https://mixpanel.com/help/reference/javascript
+    mixpanel.identify(me.id)
+    mixpanel.register(traits)
+
   trackPageView: ->
     name = Backbone.history.getFragment()
-    console.log "Would track analytics pageview: '/#{name}'" if debugAnalytics
+    url = "/#{name}"
+    console.log "Would track analytics pageview: #{url}" if debugAnalytics
     @trackEventInternal 'Pageview', url: name unless me?.isAdmin() and @isProduction
     return unless @isProduction and not me.isAdmin()
 
     # Google Analytics
     # https://developers.google.com/analytics/devguides/collection/analyticsjs/pages
-    ga? 'send', 'pageview', "/#{name}"
+    ga? 'send', 'pageview', url
 
-  trackEvent: (action, properties={}) =>
+    # Mixpanel
+    mixpanelIncludes = ['', 'courses', 'courses/purchase', 'courses/teachers', 'courses/students', 'schools', 'teachers', 'teachers/freetrial']
+    mixpanel.track('page viewed', 'page name' : name, url : url) if name in mixpanelIncludes
+
+  trackEvent: (action, properties={}, includeIntegrations=[]) =>
     @trackEventInternal action, _.cloneDeep properties unless me?.isAdmin() and @isProduction
-    console.log 'Tracking external analytics event:', action, properties if debugAnalytics
+    console.log 'Tracking external analytics event:', action, properties, includeIntegrations if debugAnalytics
     return unless me and @isProduction and not me.isAdmin()
 
     # Google Analytics
@@ -105,6 +115,10 @@ module.exports = class Tracker
     # http://www.inspectlet.com/docs#tagging
     __insp?.push ['tagSession', action: action, properies: properties]
 
+    # Mixpanel
+    # Only log explicit events for now
+    mixpanel.track(action, properties) if 'Mixpanel' in includeIntegrations
+
   trackEventInternal: (event, properties) =>
     # Skipping heavily logged actions we don't use internally
     unless event in ['Simulator Result', 'Started Level Load', 'Finished Level Load']
@@ -128,7 +142,7 @@ module.exports = class Tracker
         $.post("#{window.location.protocol or 'http:'}//analytics.codecombat.com/analytics", dataToSend).fail ->
           console.error "Analytics post failed!"
       else
-        request = @supermodel.addRequestResource 'log_event', {
+        request = @supermodel.addRequestResource {
           url: '/db/analytics.log.event/-/log_event'
           data: {event: event, properties: properties}
           method: 'POST'
diff --git a/app/core/services/stripe.coffee b/app/core/services/stripe.coffee
index 7bdab0231..8a77e5dca 100644
--- a/app/core/services/stripe.coffee
+++ b/app/core/services/stripe.coffee
@@ -7,7 +7,6 @@ if StripeCheckout?
     email: me.get('email')
     image: "https://codecombat.com/images/pages/base/logo_square_250.png"
     token: (token) ->
-      console.log 'trigger?', handler.trigger
       handler.trigger 'received-token', { token: token }
       Backbone.Mediator.publish 'stripe:received-token', { token: token }
     locale: 'auto'
@@ -15,4 +14,4 @@ if StripeCheckout?
 else
   module.exports = {}
   console.error "Failure loading StripeCheckout API, returning empty object."
-_.extend(handler, Backbone.Events)
\ No newline at end of file
+_.extend(handler, Backbone.Events)
diff --git a/app/core/social-handlers/FacebookHandler.coffee b/app/core/social-handlers/FacebookHandler.coffee
index c53d5f0d2..d6cac7811 100644
--- a/app/core/social-handlers/FacebookHandler.coffee
+++ b/app/core/social-handlers/FacebookHandler.coffee
@@ -15,7 +15,7 @@ userPropsToSave =
 module.exports = FacebookHandler = class FacebookHandler extends CocoClass
   subscriptions:
     'auth:logged-in-with-facebook': 'onFacebookLoggedIn'
-  
+
   loggedIn: false
 
   onFacebookLoggedIn: (e) ->
@@ -27,21 +27,24 @@ module.exports = FacebookHandler = class FacebookHandler extends CocoClass
       unless me.get(userProp)
         @loggedIn = true
         break
-        
+
     if @waitingForLogin and @loggedIn
       @fetchMeForLogin()
-    
+
   loginThroughFacebook: ->
     if @loggedIn
       @fetchMeForLogin()
     else
-      FB.login()
+      FB.login ((response) ->
+        console.log 'Received FB login response:', response
+      ), scope: 'email'
       @waitingForLogin = true
-      
+
   fetchMeForLogin: ->
-    FB.api('/me', @onReceiveMeInfo)
+    FB.api('/me', {fields: 'email,last_name,first_name,gender'}, @onReceiveMeInfo)
 
   onReceiveMeInfo: (r) =>
+    console.log "Got Facebook user info:", r
     unless r.email
       console.error('could not get data, since no email provided')
       return
diff --git a/app/lib/LevelBus.coffee b/app/lib/LevelBus.coffee
index 2a796cb12..16a4e9b48 100644
--- a/app/lib/LevelBus.coffee
+++ b/app/lib/LevelBus.coffee
@@ -125,7 +125,7 @@ module.exports = class LevelBus extends Bus
 
   onWinnabilityUpdated: (e) ->
     return unless @onPoint() and e.winnable
-    return unless e.level.get('slug') in ['ace-of-coders']  # Mirror matches don't otherwise show victory, so we win here.
+    return unless e.level.get('slug') in ['ace-of-coders', 'elemental-wars']  # Mirror matches don't otherwise show victory, so we win here.
     return if @session.get('state')?.complete
     @onVictory()
 
diff --git a/app/lib/LevelSetupManager.coffee b/app/lib/LevelSetupManager.coffee
index 9e40444a1..a7cb843ba 100644
--- a/app/lib/LevelSetupManager.coffee
+++ b/app/lib/LevelSetupManager.coffee
@@ -64,7 +64,7 @@ module.exports = class LevelSetupManager extends CocoClass
       @session.set 'heroConfig', {"thangType":sorcerer,"inventory":{"misc-0":"53e2396a53457600003e3f0f","programming-book":"546e266e9df4a17d0d449be5","minion":"54eb5dbc49fa2d5c905ddf56","feet":"53e214f153457600003e3eab","right-hand":"54eab7f52b7506e891ca7202","left-hand":"5463758f3839c6e02811d30f","wrists":"54693797a2b1f53ce79443e9","gloves":"5469425ca2b1f53ce7944421","torso":"546d4a549df4a17d0d449a97","neck":"54693274a2b1f53ce79443c9","eyes":"546941fda2b1f53ce794441d","head":"546d4ca19df4a17d0d449abf"}}
       @onInventoryModalPlayClicked()
       return
-    if @level.get('slug') is 'ace-of-coders'
+    if @level.get('slug') in ['ace-of-coders', 'elemental-wars']
       goliath = '55e1a6e876cb0948c96af9f8'
       @session.set 'heroConfig', {"thangType":goliath,"inventory":{"eyes":"53eb99f41a100989a40ce46e","neck":"54693274a2b1f53ce79443c9","wrists":"54693797a2b1f53ce79443e9","feet":"546d4d8e9df4a17d0d449acd","minion":"54eb5bf649fa2d5c905ddf4a","programming-book":"557871261ff17fef5abee3ee"}}
       @onInventoryModalPlayClicked()
diff --git a/app/lib/surface/Label.coffee b/app/lib/surface/Label.coffee
index 1f134ef2b..e4b6f1f2d 100644
--- a/app/lib/surface/Label.coffee
+++ b/app/lib/surface/Label.coffee
@@ -15,7 +15,7 @@ module.exports = class Label extends CocoClass
     @sprite = options.sprite
     @camera = options.camera
     @layer = options.layer
-    @style = options.style ? Label.STYLE_SAY
+    @style = options.style ? (@sprite?.thang?.labelStyle || Label.STYLE_SAY)
     console.error @toString(), 'needs a sprite.' unless @sprite
     console.error @toString(), 'needs a camera.' unless @camera
     console.error @toString(), 'needs a layer.' unless @layer
diff --git a/app/lib/surface/Lank.coffee b/app/lib/surface/Lank.coffee
index a606054e1..a116f3fa2 100644
--- a/app/lib/surface/Lank.coffee
+++ b/app/lib/surface/Lank.coffee
@@ -684,7 +684,10 @@ module.exports = Lank = class Lank extends CocoClass
     return unless @thang
     blurb = if @thang.health <= 0 then null else @thang.sayMessage  # Dead men tell no tales
     blurb = null if blurb in ['For Thoktar!', 'Bones!', 'Behead!', 'Destroy!', 'Die, humans!']  # Let's just hear, not see, these ones.
-    labelStyle = if /Hero Placeholder/.test(@thang.id) then Label.STYLE_DIALOGUE else Label.STYLE_SAY
+    if /Hero Placeholder/.test(@thang.id)
+      labelStyle = Label.STYLE_DIALOGUE
+    else
+      labelStyle = @thang.labelStyle ? Label.STYLE_SAY
     @addLabel 'say', labelStyle if blurb
     if @labels.say?.setText blurb
       @notifySpeechUpdated blurb: blurb
diff --git a/app/lib/surface/LankBoss.coffee b/app/lib/surface/LankBoss.coffee
index bcf014ac4..ca8e1c71e 100644
--- a/app/lib/surface/LankBoss.coffee
+++ b/app/lib/surface/LankBoss.coffee
@@ -82,7 +82,7 @@ module.exports = class LankBoss extends CocoClass
     console.error 'Lank collision! Already have:', id if @lanks[id]
     @lanks[id] = lank
     @lankArray.push lank
-    layer ?= @layerAdapters['Obstacle'] if lank.thang?.spriteName.search(/(dungeon|indoor|ice).wall/i) isnt -1
+    layer ?= @layerAdapters['Obstacle'] if lank.thang?.spriteName.search(/(dungeon|indoor|ice|classroom).wall/i) isnt -1
     layer ?= @layerForChild lank.sprite, lank
     layer.addLank lank
     layer.updateLayerOrder()
@@ -204,7 +204,7 @@ module.exports = class LankBoss extends CocoClass
   cacheObstacles: (updatedObstacles=null) ->
     return if @cachedObstacles and not updatedObstacles
     lankArray = @lankArray
-    wallLanks = (lank for lank in lankArray when lank.thangType?.get('name').search(/(dungeon|indoor|ice).wall/i) isnt -1)
+    wallLanks = (lank for lank in lankArray when lank.thangType?.get('name').search(/(dungeon|indoor|ice|classroom).wall/i) isnt -1)
     return if _.any (s.stillLoading for s in wallLanks)
     walls = (lank.thang for lank in wallLanks)
     @world.calculateBounds()
diff --git a/app/lib/surface/SingularSprite.coffee b/app/lib/surface/SingularSprite.coffee
index 0fed6c824..c136a5283 100644
--- a/app/lib/surface/SingularSprite.coffee
+++ b/app/lib/surface/SingularSprite.coffee
@@ -1,6 +1,6 @@
 SpriteBuilder = require 'lib/sprites/SpriteBuilder'
 
-floors = ['Dungeon Floor', 'Indoor Floor', 'Grass', 'Grass01', 'Grass02', 'Grass03', 'Grass04', 'Grass05', 'Goal Trigger', 'Obstacle', 'Sand 01', 'Sand 02', 'Sand 03', 'Sand 04', 'Sand 05', 'Sand 06', 'Talus 1', 'Talus 2', 'Talus 3', 'Talus 4', 'Talus 5', 'Talus 6', 'Firn 1', 'Firn 2', 'Firn 3', 'Firn 4', 'Firn 5', 'Firn 6', 'Ice Rink 1', 'Ice Rink 2', 'Ice Rink 3', 'Firn Cliff']
+floors = ['Dungeon Floor', 'Indoor Floor', 'Grass', 'Grass01', 'Grass02', 'Grass03', 'Grass04', 'Grass05', 'Goal Trigger', 'Obstacle', 'Sand 01', 'Sand 02', 'Sand 03', 'Sand 04', 'Sand 05', 'Sand 06', 'Talus 1', 'Talus 2', 'Talus 3', 'Talus 4', 'Talus 5', 'Talus 6', 'Firn 1', 'Firn 2', 'Firn 3', 'Firn 4', 'Firn 5', 'Firn 6', 'Ice Rink 1', 'Ice Rink 2', 'Ice Rink 3', 'Firn Cliff', 'VR Floor', 'Classroom Floor']
 
 cliffs = ['Dungeon Pit', 'Grass Cliffs']
 
@@ -79,7 +79,6 @@ module.exports = class SingularSprite extends createjs.Sprite
         @baseScaleY *= @camera.y2x * 0.85
       else
         @baseScaleY *= @camera.y2x / 0.85
-      console.log 'it is a cliff!', actionName, @baseScaleX, @baseScaleY
     @currentAnimation = actionName
     return
 
diff --git a/app/lib/world/names.coffee b/app/lib/world/names.coffee
index 48cdc51d2..451be76ba 100644
--- a/app/lib/world/names.coffee
+++ b/app/lib/world/names.coffee
@@ -98,6 +98,7 @@ module.exports.thangNames = thangNames =
     # Female
     'Vyrryx'
     'Yzzrith'
+    'Xith'
   ]
   'Ogre Chieftain': [
     # Female
@@ -146,6 +147,8 @@ module.exports.thangNames = thangNames =
     # Animal
     'Nevermore'
     'Baltimore'
+    'Columbia'
+    'Dawnstar'
   ]
   'Cougar': [
     # Animal
@@ -368,6 +371,7 @@ module.exports.thangNames = thangNames =
   'Goliath': [
     # Male
     'Okar'
+    'Ivan'
   ]
   'Guardian': [
     # Female
diff --git a/app/locale/ar.coffee b/app/locale/ar.coffee
index 335720934..45801a8fe 100644
--- a/app/locale/ar.coffee
+++ b/app/locale/ar.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
 #    prompt_body: "Do you want to get more?"
     prompt_button: "أدخل متجر"
     recovered: "الأحجار الكريمة السابقة أون استردادها. يرجى تحديث الصفحة."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/bg.coffee b/app/locale/bg.coffee
index cd08c0899..c4feb19ad 100644
--- a/app/locale/bg.coffee
+++ b/app/locale/bg.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "български език", englishDescri
     prompt_body: "Искате ли още?"
     prompt_button: "Влез в Магазина"
     recovered: "Предишните покупки на скъпоценни камъни са възстановени. Моля опреснете страницата."
-    price: "x3500 / месец"
+    price: "x{{gems}} / месец"
 
   subscribe:
     comparison_blurb: "Изостри уменията си в CodeCombat с абонамент!"
     feature1: "110+ основни нива в 4 свята"
     feature2: "10 силни <strong>нови герои</strong> с уникални умения!"
     feature3: "70+ бонус нива" # {change}
-    feature4: "<strong>3500 скъпоценни камъни бонус</strong> всеки месец!"
+    feature4: "<strong>{{gems}} скъпоценни камъни бонус</strong> всеки месец!"
     feature5: "Видео уроци"
     feature6: "Премиум email поддръжка"
     feature7: "Частни <strong>Кланове</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "български език", englishDescri
     press_paragraph_1_link: "прес пакет"
     press_paragraph_1_suffix: "Всички логота и икони могат да бъдат използвани без да се свържете с нас директно."
     team: "Отбор"
-    george_title: "Съосновател"
-#    george_blurb: "Businesser"
-    scott_title: "Съосновател"
-    scott_blurb: "Разумният"
-    nick_title: "Съосновател"
+    nick_title: "Съосновател" # {change}
     nick_blurb: "Гуру на Мотивациите"
-    michael_title: "Програмист"
-    michael_blurb: "Системен Администратор"
-    matt_title: "Съосновател"
+    matt_title: "Съосновател" # {change}
     matt_blurb: "Колоездач"
-    cat_title: "Главен Артист"
+    cat_title: "Главен Артист" # {change}
     cat_blurb: "Повелителят на въздуха"
-    josh_title: "Дизайнер на играта"
-    josh_blurb: "Подът е Лава"
-    jose_title: "Музика"
-    jose_blurb: "Стартирам"
-    retrostyle_title: "Илюстрация"
-    retrostyle_blurb: "Игра Ретро Стил"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Съосновател" # {change}
+    scott_blurb: "Разумният"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "Дизайнер на играта"
+    josh_blurb: "Подът е Лава"
+    retrostyle_title: "Илюстрация"
+    retrostyle_blurb: "Игра Ретро Стил"
+    jose_title: "Музика"
+    jose_blurb: "Стартирам"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "български език", englishDescri
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "български език", englishDescri
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/ca.coffee b/app/locale/ca.coffee
index 0f3f967c9..ded12b2fc 100644
--- a/app/locale/ca.coffee
+++ b/app/locale/ca.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
     prompt_body: "En vols més?"
     prompt_button: "Entrar a la botiga"
     recovered: "S'han recuperat les anteriors compres de gemmes. Si us plaus, recarrega al pàgina."
-    price: "x3500 / més"
+    price: "x{{gems}} / més"
 
   subscribe:
     comparison_blurb: "Afina les teves habilitats amb una subscripció a CodeCombat!"
     feature1: "Més de 60 nivells bàsics a traves de 4 móns" # {change}
     feature2: "10 <strong>nous herois</strong> poderosos amb habilitats úniques!"
     feature3: "Més de 80 nivells bonus"
-    feature4: "<strong>3500 gemmes bonus</strong> cada mes!"
+    feature4: "<strong>{{gems}} gemmes bonus</strong> cada mes!"
     feature5: "Vídeo tutorials"
     feature6: "Suport Premium per correu electrònic"
     feature7: "Privat <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
     press_paragraph_1_link: "paquet de premsa"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
     team: "Equip"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-    scott_title: "Programador" # {change}
-#    scott_blurb: "Reasonable One"
     nick_title: "Programador" # {change}
 #    nick_blurb: "Motivation Guru"
-    michael_title: "Programador"
-#    michael_blurb: "Sys Admin"
     matt_title: "Programador" # {change}
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Programador" # {change}
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
     cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/cs.coffee b/app/locale/cs.coffee
index 495232d55..4b7efd933 100644
--- a/app/locale/cs.coffee
+++ b/app/locale/cs.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
     prompt_body: "Chcete získat více?"
     prompt_button: "Vstoupit do obchodu"
     recovered: "Obnovení již zakoupených drahokamů proběhlo úspěšně. Aktualizujte stránku prosím."
-    price: "x3500 / měs."
+    price: "x{{gems}} / měs."
 
   subscribe:
     comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
     feature1: "60+ základních úrovní napříč 4 světy" # {change}
     feature2: "7 silných <strong>nových hrdinů</strong> s jedinečnými dovednostmi!" # {change}
     feature3: "30+ bonusových úrovní" # {change}
-    feature4: "<strong>3500 bonusových drahokamů</strong> každý měsíc!"
+    feature4: "<strong>{{gems}} bonusových drahokamů</strong> každý měsíc!"
     feature5: "Video tutoriály"
     feature6: "Premiová e-mailová podpora"
     feature7: "Soukromé <strong>Klany</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
     press_paragraph_1_link: "balíčku pro tisk"
     press_paragraph_1_suffix: ". Všechny loga a obrázky mohou být použity bez toho, abyste nás museli přímo kontaktovat."
     team: "Tým"
-    george_title: "Výkonný ředitel" # {change}
-    george_blurb: "Obchodník"
-    scott_title: "Programátor" # {change}
-    scott_blurb: "Ten potřebný"
     nick_title: "Programátor" # {change}
     nick_blurb: "Motivační guru"
-    michael_title: "Programátor"
-    michael_blurb: "Systémový administrátor"
     matt_title: "Programátor" # {change}
     matt_blurb: "Cyklista"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Programátor" # {change}
+    scott_blurb: "Ten potřebný"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
     email_settings_url: " nastavení emailu"
     email_description_suffix: "nebo skrze odkazy v odeslaných emailech si můžete nastavit nebo se kdykoliv odhlásit z naší korespondence."
     cost_title: "Cena"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Copyrights a Licence"
     contributor_title: "Licenční ujednání přispívatelů (CLA)"
     contributor_description_prefix: "Všichni přispívatelé jak na webu tak do projektu na GitHubu spadají pod naše "
diff --git a/app/locale/da.coffee b/app/locale/da.coffee
index 0808d06f7..19b463a9d 100644
--- a/app/locale/da.coffee
+++ b/app/locale/da.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/de-AT.coffee b/app/locale/de-AT.coffee
index 23cd22f54..73b8b5e0f 100644
--- a/app/locale/de-AT.coffee
+++ b/app/locale/de-AT.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription:
     prompt_body: "Möchtest du mehr?"
     prompt_button: "Shop betreten"
     recovered: "Voriger Juwelenkauf wiederhergestellt. Bitte die Seite neu laden."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription:
     press_paragraph_1_link: "Presse-Paket"
     press_paragraph_1_suffix: ". Alle Logos und Bilder können ohne unsere vorherige Zustimmung verwendet werden."
     team: "Team"
-    george_title: "CEO" # {change}
-    george_blurb: "Businesser"
-    scott_title: "Programmierer" # {change}
-    scott_blurb: "Der Vernünftige"
     nick_title: "Programmierer" # {change}
     nick_blurb: "Motivationsguru"
-    michael_title: "Programmierer"
-    michael_blurb: "Sys Admin"
     matt_title: "Programmierer" # {change}
     matt_blurb: "Radfahrer"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Programmierer" # {change}
+    scott_blurb: "Der Vernünftige"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription:
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription:
     email_settings_url: "deiner Emaileinstellungen"
     email_description_suffix: "oder durch von uns gesendete Links kannst du jederzeit deine Einstellungen ändern und Abonnements kündigen."
     cost_title: "Kosten"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Copyrights und Lizenzen"
     contributor_title: "Contributor License Agreement"
     contributor_description_prefix: "Alle Beiträge, sowohl auf unserer Webseite als auch in unserem GitHub Repository, unterliegen unserer"
diff --git a/app/locale/de-CH.coffee b/app/locale/de-CH.coffee
index d6335082f..0cf345791 100644
--- a/app/locale/de-CH.coffee
+++ b/app/locale/de-CH.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Dütsch (Schwiiz)", englishDescription: "Ge
     prompt_body: "Wetsch mee chaufe?"
     prompt_button: "zum Shop"
     recovered: "Früenere Ichauf zruggerstatet. Bitte dSite neu lade!"
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
   subscribe:
     comparison_blurb: "Verschärf dins Chönne midme CodeCombat Abonement."
     feature1: "80+ basis levels in 4 Weltete!" # {change}
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
     feature3: "50+ bonus levels" # {change}
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
     feature5: "Video Aleitige"
     feature6: "Premium Email Hilf"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Dütsch (Schwiiz)", englishDescription: "Ge
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-    michael_title: "Programmierer"
-    michael_blurb: "System Admin"
     matt_title: "Programmierer" # {change}
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
     cat_blurb: "Luftbändiger"
-    josh_title: "Game Designer"
-    josh_blurb: "De Bode isch Lava"
-    jose_title: "Musig"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "Game Designer"
+    josh_blurb: "De Bode isch Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+    jose_title: "Musig"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Dütsch (Schwiiz)", englishDescription: "Ge
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Dütsch (Schwiiz)", englishDescription: "Ge
     email_settings_url: "E-Mail Istellige"
     email_description_suffix: "oder dur d Links i de E-Mails wo mir schicked, chasch du jederziit dini Preferänze ändere und dich ganz eifach us de Mailing-Liste neh."
     cost_title: "Chöste"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/de-DE.coffee b/app/locale/de-DE.coffee
index 1c0127355..8448d9af2 100644
--- a/app/locale/de-DE.coffee
+++ b/app/locale/de-DE.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
     prompt_body: "Benötigst du mehr?"
     prompt_button: "Laden betreten"
     recovered: "Vorangegangener Edelsteinkauf rückgängig gemacht. Aktualisiere bitte die Seite."
-    price: "x3500 / Monat"
+    price: "x{{gems}} / Monat"
 
   subscribe:
     comparison_blurb: "Verbessere deine Fähigkeiten mit einem CodeCombat Abonnement"
     feature1: "60+ Basislevel in 4 Gebieten" # {change}
     feature2: "7 mächtige <strong>neue Helden</strong> mit einzigartigen Fertigkeiten" # {change}
     feature3: "30+ Bonuslevel" # {change}
-    feature4: "<strong>3500 Bonusedelsteine</strong> jeden Monat!"
+    feature4: "<strong>{{gems}} Bonusedelsteine</strong> jeden Monat!"
     feature5: "Videoanleitungen"
     feature6: "Premium Emailsupport"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
     press_paragraph_1_link: "Presse-Paket"
     press_paragraph_1_suffix: ". Alle Logos und Bilder können ohne unsere vorherige Zustimmung verwendet werden."
     team: "Team"
-    george_title: "CEO"
-    george_blurb: "Vertriebler"
-    scott_title: "Programmierer"
-    scott_blurb: "Der Vernünftige"
-    nick_title: "Programmierer"
+    nick_title: "Programmierer" # {change}
     nick_blurb: "Motivationsguru"
-    michael_title: "Programmierer"
-    michael_blurb: "Sys Admin"
     matt_title: "Programmierer" # {change}
     matt_blurb: "Radfahrer"
-    cat_title: "Chief Artisan"
+    cat_title: "Chief Artisan" # {change}
     cat_blurb: "Luftbändiger"
-    josh_title: "Spiel Designer"
-    josh_blurb: "Boden ist Lava"
-    jose_title: "Musik"
-    jose_blurb: "Taking Off"
-    retrostyle_title: "Illustration"
-    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Programmierer" # {change}
+    scott_blurb: "Der Vernünftige"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "Spiel Designer"
+    josh_blurb: "Boden ist Lava"
+    retrostyle_title: "Illustration"
+    retrostyle_blurb: "RetroStyle Games"
+    jose_title: "Musik"
+    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
   teachers:
     who_for_title: "An wen richtet sich CodeCombat?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
diff --git a/app/locale/el.coffee b/app/locale/el.coffee
index 75226b459..040f978e6 100644
--- a/app/locale/el.coffee
+++ b/app/locale/el.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
     prompt_body: "Θέλεις να πάρεις περισσότερα;"
     prompt_button: "Μπες στο κατάστημα"
     recovered: "Ανακτήθηκε η προηγούμενη αγορά πετραδιών. Παρακαλώ ανανέωσε τη σελίδα."
-    price: "x3500 / μήνα"
+    price: "x{{gems}} / μήνα"
 
   subscribe:
     comparison_blurb: "Ακόνησε τις ικανότητές σου με μια συνδρομή στο CodeCombat!"
     feature1: "110+ βασικά επίπεδα που εκτείνονται σε 4 κόσμους"
     feature2: "10 παντοδύναμοι <strong>νέοι ήρωες</strong> με μοναδικές ικανότητες!"
     feature3: "80+ επίπεδα δώρο"
-    feature4: "<strong>3500 πετράδια δώρο</strong> κάθε μήνα!"
+    feature4: "<strong>{{gems}} πετράδια δώρο</strong> κάθε μήνα!"
     feature5: "Βίντεο Βοηθήματα"
     feature6: "Προνομιακή υποστήριξη μέσω ηλεκτρονικού ταχυδρομείου"
     feature7: "Ιδιωτικές <strong>Φατρίες</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
     press_paragraph_1_link: "πακέτο τύπου"
     press_paragraph_1_suffix: ". Όλα τα λογότυπα και οι εικόνες μπορούν χρησιμοποιηθούν χωρίς να επικοινωνήσετε με εμάς άμεσα."
     team: "Ομάδα"
-    george_title: "Συνιδρυτής"
-    george_blurb: " Ο Επιχειρηματικός"
-    scott_title: "Συνιδρυτής"
-    scott_blurb: "Ο Λογικός"
-    nick_title: "Συνιδρυτής"
+    nick_title: "Συνιδρυτής" # {change}
     nick_blurb: "Γκουρού της Παρακίνησης"
-    michael_title: "Προγραμματιστής"
-    michael_blurb: "Διαχειριστής Συστήματος"
-    matt_title: "Συνιδρυτής"
+    matt_title: "Συνιδρυτής" # {change}
     matt_blurb: "Ποδηλάτης"
-    cat_title: "Κύριος Σχεδιαστής Επιπέδων"
+    cat_title: "Κύριος Σχεδιαστής Επιπέδων" # {change}
 #    cat_blurb: "Airbender"
-    josh_title: "Σχεδιαστής Παιχνιδιού"
-    josh_blurb: "Το Πάτωμα Είναι Λάβα"
-    jose_title: "Μουσική"
-    jose_blurb: "Απογείωση"
-    retrostyle_title: "Εικονογράφηση"
-    retrostyle_blurb: "Ρετρό Παιχνίδια"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Συνιδρυτής" # {change}
+    scott_blurb: "Ο Λογικός"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "Σχεδιαστής Παιχνιδιού"
+    josh_blurb: "Το Πάτωμα Είναι Λάβα"
+    retrostyle_title: "Εικονογράφηση"
+    retrostyle_blurb: "Ρετρό Παιχνίδια"
+    jose_title: "Μουσική"
+    jose_blurb: "Απογείωση"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
   teachers:
     who_for_title: "Για ποιον είναι το CodeCombat;"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
     additional_resources_1_mid: "Οδηγός Εκπαιδευτικού για Μάθημα 1"
     additional_resources_1_suff: "Επεξηγήσεις και λύσεις για το κάθε επίπεδο."
     additional_resources_2_pref: "Συμπλήρωσε την"
-    additional_resources_2_suff: "για να κερδίσεις 15 ακόμα ώρες υλικού Δωρεάν για 2 μήνες."
+    additional_resources_2_suff: "για να κερδίσεις 15 ακόμα ώρες υλικού Δωρεάν για 2 μήνες." # {change}
     additional_resources_3_pref: "Επισκέψη"
     additional_resources_3_mid: "στα Forums των εκπαιδευτικών"
     additional_resources_3_suff: "για να επικοινωνήσεις με άλλους συναδέρφους που χρησιμοποιούν το CodeCombat."
diff --git a/app/locale/en-GB.coffee b/app/locale/en-GB.coffee
index 100b6a2c0..9115bbef3 100644
--- a/app/locale/en-GB.coffee
+++ b/app/locale/en-GB.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Copyrights and Licences"
     contributor_title: "Contributor Licence Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/en-US.coffee b/app/locale/en-US.coffee
index 36acdef83..91c675385 100644
--- a/app/locale/en-US.coffee
+++ b/app/locale/en-US.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index 2b26d42b1..6b14b20f7 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -34,6 +34,11 @@
     twitter_follow: "Follow"
     teachers: "Teachers"
     careers: "Careers"
+    facebook: "Facebook"
+    twitter: "Twitter"
+    create_a_class: "Create a Class"
+    other: "Other"
+    learn_to_code: "Learn to Code!"
 
   modal:
     close: "Close"
@@ -397,14 +402,14 @@
     prompt_body: "Do you want to get more?"
     prompt_button: "Enter Shop"
     recovered: "Previous gems purchase recovered. Please refresh the page."
-    price: "x3500 / mo"
+    price: "x{{gems}} / mo"
 
   subscribe:
     comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
     feature1: "110+ basic levels across 4 worlds"
     feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
     feature3: "80+ bonus levels"
-    feature4: "<strong>3500 bonus gems</strong> every month!"
+    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
     feature5: "Video tutorials"
     feature6: "Premium email support"
     feature7: "Private <strong>Clans</strong>"
@@ -553,34 +558,30 @@
     press_paragraph_1_link: "press packet"
     press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
     team: "Team"
-    george_title: "Cofounder"
-    george_blurb: "Businesser"
-    scott_title: "Cofounder"
-    scott_blurb: "Reasonable One"
-    nick_title: "Cofounder"
+    nick_title: "Cofounder, CEO"
     nick_blurb: "Motivation Guru"
-    michael_title: "Programmer"
-    michael_blurb: "Sys Admin"
-    matt_title: "Cofounder"
+    matt_title: "Cofounder, CTO"
     matt_blurb: "Bicyclist"
-    cat_title: "Chief Artisan"
+    cat_title: "Game Designer"
     cat_blurb: "Airbender"
-    josh_title: "Game Designer"
-    josh_blurb: "Floor Is Lava"
-    jose_title: "Music"
-    jose_blurb: "Taking Off"
-    retrostyle_title: "Illustration"
-    retrostyle_blurb: "RetroStyle Games"
-    rob_title: "Compiler Engineer"
+    scott_title: "Cofounder, Software Engineer"
+    scott_blurb: "Reasonable One"
+    maka_title: "Customer Advocate"
+    maka_blurb: "Storyteller"
+    rob_title: "Software Engineer"
     rob_blurb: "Codes things and stuff"
     josh_c_title: "Game Designer"
     josh_c_blurb: "Designs games"
-    carlos_title: "Region Manager, Brazil"
-    carlos_blurb: "Celery Man"
-    maka_title: "Customer Advocate"
-    maka_blurb: "Storyteller"
     robin_title: "UX Design & Research"
     robin_blurb: "Scaffolding"
+    josh_title: "Game Designer"
+    josh_blurb: "Floor Is Lava"
+    retrostyle_title: "Illustration"
+    retrostyle_blurb: "RetroStyle Games"
+    jose_title: "Music"
+    jose_blurb: "Taking Off"
+    carlos_title: "Region Manager, Brazil"
+    carlos_blurb: "Celery Man"
 
   teachers:
     who_for_title: "Who is CodeCombat for?"
@@ -994,16 +995,21 @@
     getting_started_3: "You'll see student's progress below as they sign up and join your class."
     additional_resources: "Additional Resources"
     additional_resources_1_pref: "Download/print our"
-    additional_resources_1_mid: "Course 1 Teacher's Guide"
-    additional_resources_1_suff: "explanations and solutions to each level."
+    additional_resources_1_mid: "Course 1" # {change}
+    additional_resources_1_mid2: "and"
+    additional_resources_1_mid3: "Course 2"
+    additional_resources_1_suff: "teacher's guides with solutions for each level." # {change}
     additional_resources_2_pref: "Complete our"
-    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
     additional_resources_3_pref: "Visit our"
     additional_resources_3_mid: "Teacher Forums"
     additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
     additional_resources_4_pref: "Check out our"
     additional_resources_4_mid: "Schools Page"
     additional_resources_4_suff: "to learn more about CodeCombat's classroom offerings."
+    educator_wiki_pref: "Or check out our new"
+    educator_wiki_mid: "educator wiki"
+    educator_wiki_suff: "to browse the guide online."
     your_classes: "Your Classes"
     no_classes: "No classes yet!"
     create_new_class1: "create new class"
@@ -1036,6 +1042,7 @@
     ambassador_title: "Ambassador"
     ambassador_title_description: "(Support)"
     ambassador_summary: "Tame our forum users and provide direction for those with questions. Our ambassadors represent CodeCombat to the world."
+    teacher_title: "Teacher"
 
   editor:
     main_title: "CodeCombat Editors"
@@ -1192,6 +1199,7 @@
     ambassador_join_note_strong: "Note"
     ambassador_join_note_desc: "One of our top priorities is to build multiplayer where players having difficulty solving levels can summon higher level wizards to help them. This will be a great way for ambassadors to do their thing. We'll keep you posted!"
     ambassador_subscribe_desc: "Get emails on support updates and multiplayer developments."
+    teacher_subscribe_desc: "Get emails on updates and announcements for teachers."
     changes_auto_save: "Changes are saved automatically when you toggle checkboxes."
     diligent_scribes: "Our Diligent Scribes:"
     powerful_archmages: "Our Powerful Archmages:"
@@ -1349,78 +1357,34 @@
 
   loading_error:
     could_not_load: "Error loading from server"
-    connection_failure: "Connection failed."
+    connection_failure: "Connection Failed" # {change}
+    connection_failure_desc: "It doesn’t look like you’re connected to the internet! Check your network connection and then reload this page."
+    login_required: "Login Required"
+    login_required_desc: "You need to be logged in to access this page."
     unauthorized: "You need to be signed in. Do you have cookies disabled?"
-    forbidden: "You do not have the permissions."
-    not_found: "Not found."
+    forbidden: "Forbidden" # {change}
+    forbidden_desc: "Oh no, there’s nothing we can show you here! Make sure you’re logged into the correct account, or visit one of the links below to get back to programming!"
+    not_found: "Not Found" # {change}
+    not_found_desc: "Hm, there’s nothing here. Visit one of the following links to get back to programming!"
     not_allowed: "Method not allowed."
-    timeout: "Server timeout."
+    timeout: "Server Timeout" # {change}
     conflict: "Resource conflict."
     bad_input: "Bad input."
     server_error: "Server error."
-    unknown: "Unknown error."
+    unknown: "Unknown Error" # {change}
     error: "ERROR"
+    general_desc: "Something went wrong, and it’s probably our fault. Try waiting a bit and then refreshing the page, or visit one of the following links to get back to programming!"
 
   resources:
-    sessions: "Sessions"
-    your_sessions: "Your Sessions"
     level: "Level"
-    social_network_apis: "Social Network APIs"
-    facebook_status: "Facebook Status"
-    facebook_friends: "Facebook Friends"
-    facebook_friend_sessions: "Facebook Friend Sessions"
-    gplus_friends: "G+ Friends"
-    gplus_friend_sessions: "G+ Friend Sessions"
-    leaderboard: "Leaderboard"
-    user_schema: "User Schema"
-    user_profile: "User Profile"
     patch: "Patch"
     patches: "Patches"
-    patched_model: "Source Document"
-    model: "Model"
     system: "System"
     systems: "Systems"
     component: "Component"
     components: "Components"
-    thang: "Thang"
-    thangs: "Thangs"
-    level_session: "Your Session"
-    opponent_session: "Opponent Session"
-    article: "Article"
-    user_names: "User Names"
-    thang_names: "Thang Names"
-    files: "Files"
-    top_simulators: "Top Simulators"
-    source_document: "Source Document"
-    document: "Document"
-    sprite_sheet: "Sprite Sheet"
-    employers: "Employers"
-    candidates: "Candidates"
-    candidate_sessions: "Candidate Sessions"
-    user_remark: "User Remark"
-    user_remarks: "User Remarks"
-    versions: "Versions"
-    items: "Items"
     hero: "Hero"
-    heroes: "Heroes"
-    achievement: "Achievement"
-    clas: "CLAs"
-    play_counts: "Play Counts"
-    feedback: "Feedback"
-    payment_info: "Payment Info"
     campaigns: "Campaigns"
-    poll: "Poll"
-    user_polls_record: "Poll Voting History"
-    course: "Course"
-    courses: "Courses"
-    course_instance: "Course Instance"
-    course_instances: "Course Instances"
-    classroom: "Classroom"
-    classrooms: "Classrooms"
-    clan: "Clan"
-    clans: "Clans"
-    members: "Members"
-    users: "Users"
 
   concepts:
     advanced_strings: "Advanced Strings"
diff --git a/app/locale/eo.coffee b/app/locale/eo.coffee
index 6fcde6626..930c4705e 100644
--- a/app/locale/eo.coffee
+++ b/app/locale/eo.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Esperanto", englishDescription: "Esperanto"
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Esperanto", englishDescription: "Esperanto"
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Esperanto", englishDescription: "Esperanto"
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Esperanto", englishDescription: "Esperanto"
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/es-419.coffee b/app/locale/es-419.coffee
index 9a1236826..23bb19470 100644
--- a/app/locale/es-419.coffee
+++ b/app/locale/es-419.coffee
@@ -116,7 +116,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     login_switch: "¿Ya tienes una cuenta?"
     school_name: "Nombre de Escuela y Ciudad"
     optional: "opcional"
-#    school_name_placeholder: "Example High School, Springfield, IL"
+    school_name_placeholder: "Ejemplo: High School, Springfield, IL"
 
   recover:
     recover_account_title: "recuperar cuenta"
@@ -251,7 +251,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     victory_title_suffix: " Completo!"
     victory_sign_up: "Regístrate para recibir actualizaciones"
     victory_sign_up_poke: "¿Quieres recibir las ultimas noticias por correo? ¡Crea una cuenta gratuita y te mantendremos informado!"
-    victory_rate_the_level: "Valora el nivel: " # {change}
+    victory_rate_the_level: "¿Cómo de divertido estuvo este nivel?"
     victory_return_to_ladder: "Volver a la escalera"
     victory_saving_progress: "Guardando Progreso"
     victory_go_home: "Ir al Inicio"
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     prompt_body: "¿Quieres obtener más?"
     prompt_button: "Entrar al mercado"
     recovered: "Se recuperaron las anteriores compras de gemas. Por favor recarga la página"
-    price: "x3500 / mes"
+    price: "x{{gems}} / mes"
 
   subscribe:
     comparison_blurb: "Agudiza tus habilidades con la suscripción a CodeCombat!"
     feature1: "Más de 110 niveles basicos a lo largo de 4 mundos"
     feature2: "10 poderosos <strong>nuevos heroés</strong> con habilidades unicas!"
-    feature3: "Más de 70 niveles extras" # {change}
-    feature4: "<strong>3500 gemas de bono</strong> cada mes!"
+    feature3: "+80 niveles extras"
+    feature4: "<strong>{{gems}} gemas de bono</strong> cada mes!"
     feature5: "Video tutoriales"
     feature6: "Soporte Premium vía email"
     feature7: "<strong>Clan</strong> Privado"
@@ -436,12 +436,12 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     parents_blurb3: "Sin Riesgo: Garantía de 100% de devolución, fácil 1-click y des- suscribirse."
     payment_methods: "Metodos de pago"
     payment_methods_title: "Metodos de pago aceptados."
-    payment_methods_blurb1: "Actualmente aceptamos tarjetas de credito y Alipay." # {change}
+    payment_methods_blurb1: "Actualmente aceptamos tarjetas de credito y Alipay. Tambíen puedes usar PayPal, enviando a nick@codecombat tu correo electrónico, y pudiendo adquirir por {{three_month_price}} USD una suscripción de tres meses y gemas, o por ${{year_price}} una de un año."
     payment_methods_blurb2: "Si necesitas una forma alternativa de pago, por favor contactarse"
     sale_button: "Venta!"
-    sale_button_title: "Ahorra ${{discount}} al adquirir una suscripción por 1 año" # {change}
+    sale_button_title: "Ahorre $21 al adquirir una suscripción por 1 año"
     stripe_description: "Suscripción Mensual"
-    stripe_description_year_sale: "Suscripción por 1 año (${{discount}} descuento)" # {change}
+    stripe_description_year_sale: "Suscripción por 1 año (${{discount}} de descuento)"
     subscription_required_to_play: "Necesitas una suscripción para jugar este nivel."
     unlock_help_videos: "Suscríbete para desbloquear todos los video tutoriales."
     personal_sub: "Suscripción Personal" # Accounts Subscription View below
@@ -454,7 +454,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     managed_subs: "Suscripciones administradas"
     subscribing: "Suscribiendo..."
     current_recipients: "Recipientes actuales"
-    unsubscribing: "Desuscribiendo..." # {change}
+    unsubscribing: "Dando de baja..."
     subscribe_prepaid: "Click en suscribirse para utlizar un código prepago"
     using_prepaid: "Usar código prepago para una suscribción mensual"
 
@@ -552,37 +552,35 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     press_paragraph_1_link: "paquete de prensa"
     press_paragraph_1_suffix: ". Todos los logos e imágenes pueden ser usados sin contactarnos directamente."
     team: "Equipo"
-    george_title: "Cofundador"
-    george_blurb: "Negociante"
-    scott_title: "Cofundador"
-    scott_blurb: "Razonable"
-    nick_title: "Cofundador"
+    nick_title: "Cofundador, CEO"
     nick_blurb: "Gurú motivacional"
-    michael_title: "Programador"
-    michael_blurb: "Sys Admin"
-    matt_title: "Cofundador"
+    matt_title: "Cofundador, CTO"
     matt_blurb: "Bicicletero"
-    cat_title: "Jefe Artesano"
+    cat_title: "Diseñadora de Juegos"
     cat_blurb: "Maestro del Aire"
-    josh_title: "Diseñador de Juegos"
-    josh_blurb: "El piso es Lava"
-    jose_title: "Música"
-    jose_blurb: "Despegar"
-    retrostyle_title: "Ilustración"
-    retrostyle_blurb: "Juegos con estilo Retro"
-    rob_title: "Ingeniero de Compilación"
+    scott_title: "Cofundador, Ingeniero de Software"
+    scott_blurb: "Razonable"
+    maka_title: "Defensor del Consumidor"
+    maka_blurb: "Cuentista"
+    rob_title: "Ingeniero de Software"
     rob_blurb: "Hace código y demás"
     josh_c_title: "Diseñador de Juegos"
     josh_c_blurb: "Diseña juegos"
+    robin_title: "Diseñadora de UX & Investigadora"
+    robin_blurb: "Scaffolding"
+    josh_title: "Diseñador de Juegos"
+    josh_blurb: "El piso es Lava"
+    retrostyle_title: "Ilustración"
+    retrostyle_blurb: "Juegos con estilo Retro"
+    jose_title: "Música"
+    jose_blurb: "Despegar"
     carlos_title: "Manager de Región, Brasil"
     carlos_blurb: "Hombre apio"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
   teachers:
     who_for_title: "¿Para quienes es CodeCombat?"
-    who_for_1: "Recomendamos CodeCombat para estudiantes de edades 9 y arriba. No se require experiencia en programación." # {change}
-    who_for_2: "Hemos diseñado a CodeCombat para atraer a niños y niñas." # {change}
+    who_for_1: "Recomendamos CodeCombat para estudiantes con +9 años de edad. No se require experiencia en programación. Diseñamos CodeCombat para que sea atractivo tanto para los chicos como para las chicas."
+    who_for_2: "Nuestro sistema de Cursos permite a los maestros configurar las clases, monitorizar el progreso y asignar contenido adicional a los estudiantes a través de una interfaz dedicada."
     more_info_title: "¿Dónde puedo encontrar más información?"
     more_info_1: "Nuestro"
     more_info_2: "el foro de profesores"
@@ -592,14 +590,14 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     title: "Encuesta de Maestros"
     must_be_logged: "Debes ingresar primero. Por favor, crea una cuenta o ingresa desde el menú de arriba."
     retrieving: "Obteniendo información..."
-    being_reviewed_1: "Su aplicación a una suscripción gratuita está siendo" # {change}
+    being_reviewed_1: "Su aplicación a una suscripción gratuita está siendo"
     being_reviewed_2: "revisada."
-    approved_1: "Su aplicación a una suscripción gratuita fue" # {change}
-    approved_2: "aprobada." # {change}
-#    approved_4: "You can now enroll your students on the"
+    approved_1: "Su aplicación para una prueba gratuita está siendo"
+    approved_2: "revisada."
+    approved_4: "Ahora puedes inscribir a tus estudiantes en los"
     approved_5: "cursos"
-#    approved_6: "page."
-    denied_1: "Su aplicación a una suscripción gratuita ha sido" # {change}
+    approved_6: "página."
+    denied_1: "Su aplicación para una prueba gratuita ha sido"
     denied_2: "denegada."
     contact_1: "Por favor contactarse"
     contact_2: "si tiene más preguntas."
@@ -662,7 +660,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     password_tab: "Contraseña"
     emails_tab: "Correos"
     admin: "Admin"
-#    manage_subscription: "Click here to manage your subscription."
+    manage_subscription: "Click aquí para administrar tu subscripción"
     new_password: "Nueva Contraseña"
     new_password_verify: "Verificar"
     type_in_email: "Ingrese su correo electrónico para confirmar la eliminación de su cuenta."
@@ -738,7 +736,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     subs_only: "solo suscriptores"
     create_clan: "Crear nuevo clan"
     private_preview: "Vista previa"
-#    private_clans: "Private Clans"
+    private_clans: "Clanes Privados"
     public_clans: "Clanes publicos"
     my_clans: "Mis Clanes"
     clan_name: "Nombre del clan"
@@ -858,7 +856,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     see_the: "Vea la"
     more_info: "para más información."
     choose_course: "Elige tu Curso:"
-    enter_code: "Introducir un código de desbloqueo" # {change}
+    enter_code: "Introducir un código de desbloqueo para ingresar a una clase"
     enter_code1: "Introducir código de desbloqueo"
     enroll: "Inscribirse"
     pick_from_classes: "Elije de tus clases actuales"
@@ -867,47 +865,47 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     topics: "Tópicos"
     hours_content: "Horas de contenido:"
     get_free: "Obtenga curso GRATIS"
-#    enroll_paid: "Enroll Students in Paid Courses"
+    enroll_paid: "Anotar estudiantes en cursos pagos."
     you_have1: "Tiene"
-#    you_have2: "unused paid enrollments"
-#    use_one: "Use 1 paid enrollment for"
-#    use_multiple: "Use paid enrollments for the following students:"
-#    already_enrolled: "already enrolled"
-#    licenses_remaining: "licenses remaining:"
-#    insufficient_enrollments: "insufficient paid enrollments"
-#    enroll_students: "Enroll Students"
-#    get_enrollments: "Get More Enrollments"
-#    change_language: "Change Course Language"
+    you_have2: "matrículas pagadas no utilizadas"
+    use_one: "Utilizar 1 matrícula pagada para"
+    use_multiple: "Utilizar matrículas pagadas para los siguientes estudiantes:"
+    already_enrolled: "ya matriculados"
+    licenses_remaining: "licencias restantes:"
+    insufficient_enrollments: "matrículas pagas insuficientes"
+    enroll_students: "Matricular Estudiantes"
+    get_enrollments: "Obtener Más Matrículas"
+    change_language: "Cambiar idioma del curso"
     keep_using: "Seguir Usando"
     switch_to: "Cambiar a"
     greetings: "Saludos!"
     learn_p: "Aprender Python"
     learn_j: "Aprender JavaScript"
-#    language_cannot_change: "Language cannot be changed once students join a class."
-#    back_classrooms: "Back to my classrooms"
-#    back_courses: "Back to my courses"
-#    edit_details: "Edit class details"
-#    enrolled_courses: "enrolled in paid courses:"
-#    purchase_enrollments: "Purchase Enrollments"
+    language_cannot_change: "El lenguaje no puede ser cambiado una vez que el estudiante ingreso a la clase."
+    back_classrooms: "Volver a mis aulas"
+    back_courses: "Volver a mis cursos"
+    edit_details: "Editar detallesde clase"
+    enrolled_courses: "matriculados en cursos pagos:"
+    purchase_enrollments: "Comprar Matrículas"
     remove_student: "Quitar alumno"
     assign: "Asignar"
-#    to_assign: "to assign paid courses."
+    to_assign: "para asignar cursos pagos."
     teacher: "Maestro"
     complete: "Completado"
-#    none: "None"
+    none: "Ninguno"
     save: "Guardar"
     play_campaign_title: "Jugar Campaña"
     play_campaign_description: "Estas listo para dar el siguiente paso! Explora cientos de desafiantes niveles, aprende habilidades avanzadas de programación, y compite en arenas multijugador!"
     create_account_title: "Crea una Cuenta"
     create_account_description: "Registrate gratis con una cuenta CodeCombat y obten acceso a mas niveles, mas habilidades de programacion, y mas diversion!"
-#    preview_campaign_title: "Preview Campaign"
-#    preview_campaign_description: "Take a sneak peek at all that CodeCombat has to offer before signing up for your FREE account."
+    preview_campaign_title: "Previsualizar campaña"
+    preview_campaign_description: "Echa un vistazo a todo lo que CodeCombat tiene para ofrecer antes de registrarse con una cuenta GRATUITA."
     arena: "Arena"
-#    arena_soon_title: "Arena Coming Soon"
-#    arena_soon_description: "We are working on a multiplayer arena for classrooms at the end of"
+    arena_soon_title: "Arena pronto disponible"
+    arena_soon_description: "Estamos trabajando en una arena multijugador para las aulas para finales de"
     not_enrolled1: "No inscrito"
-#    not_enrolled2: "Ask your teacher to enroll you in the next course."
-#    next_course: "Next Course"
+    not_enrolled2: "Preguntale a tu maestro para anotarte en el proximo curso."
+    next_course: "Próximo curso"
     coming_soon1: "Próximamente"
     coming_soon2: "Estamos trabajando duro para hacer mas cursos para ti!"
     available_levels: "Niveles Disponibles"
@@ -916,103 +914,103 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     start_new_game: "Iniciar un Nuevo Juego"
     play_now_learn_header: "Juega y Aprende"
     play_now_learn_1: "Sintaxis básica para controlar a tu personaje"
-#    play_now_learn_2: "while loops to solve pesky puzzles"
+    play_now_learn_2: "bucles while para resolver rompecabezas molestos"
     play_now_learn_3: "cadenas & variables para personalizar acciones"
     play_now_learn_4: "como vencer a un ogro (habilidades importantes en la vida!)"
-#    welcome_to_page: "Welcome to your Courses page!"
-#    completed_hoc: "Amazing! You've completed the Hour of Code course!"
+    welcome_to_page: "¡Bienvenido a tu página de cursose!"
+    completed_hoc: "¡Asombroso! ¡Has completado el curso de la hora de código!"
     ready_for_more_header: "Listo para mas? Juega el modo campaña!"
     ready_for_more_1: "Usa las gemas para desbloquear nuevos objetos!"
-#    ready_for_more_2: "Play through brand new worlds and challenges"
-#    ready_for_more_3: "Learn even more programming!"
+    ready_for_more_2: "Juega atravez de nuevos mundos y desafios"
+    ready_for_more_3: "¡Aprendé todavía más programando!"
     saved_games: "Juegos Guardados"
-#    hoc: "Hour of Code"
+    hoc: "Hora del código"
     my_classes: "Mis Clases"
-#    class_added: "Class successfully added!"
-#    view_class: "view class"
+    class_added: "Clase añadida satisfactoriamente!"
+    view_class: "ver clase"
     view_levels: "ver niveles"
-#    join_class: "Join A Class"
-#    ask_teacher_for_code: "Ask your teacher if you have a CodeCombat class code! If so, enter it below:"
-#    enter_c_code: "<Enter Class Code>"
-#    join: "Join"
-#    joining: "Joining class"
-#    course_complete: "Course Complete"
-#    play_arena: "Play Arena"
+    join_class: "Unirse a clase"
+    ask_teacher_for_code:  "Preguntalé a tu profesor si tu tienes un código de CodeCombat! Si lo tiene, ingresalo debajo:"
+    enter_c_code: "<Ingresar Código de la Clase>"
+    join: "Unirse"
+    joining: "Uniendose a claseJoining class"
+    course_complete: "Curso completo"
+    play_arena: "Jugar Arena"   
     start: "Iniciar"
-#    last_level: "Last Level"
-#    welcome_to_hoc: "Adventurers, welcome to our Hour of Code!"
-#    logged_in_as: "Logged in as:"
-#    not_you: "Not you?"
-#    welcome_back: "Hi adventurer, welcome back!"
-#    continue_playing: "Continue Playing"
-#    more_options: "More options:"
-#    option1_header: "Option 1: Invite students via email"
-#    option1_body: "Students will automatically be sent an invitation to join this class, and will need to create an account with a username and password."
-#    option2_header: "Option 2: Send URL to your students"
-#    option2_body: "Students will be asked to enter an email address, username and password to create an account."
-#    option3_header: "Option 3: Direct students to codecombat.com/courses"
-#    option3_body: "Give students the following passcode to enter along with an email address, username and password when they create an account."
-#    thank_you_pref: "Thank you for your purchase! You can now assign"
-#    thank_you_suff: "more students to paid courses."
-#    return_to_class: "Return to classroom"
-#    return_to_course_man: "Return to course management."
-#    students_not_enrolled: "students not enrolled"
-#    total_all_classes: "Total Across All Classes"
-#    how_many_enrollments: "How many additional paid enrollments do you need?"
-#    each_student_access: "Each student in a class will get access to Courses 2-4 once they are enrolled in paid courses. You may assign each course to each student individually."
-#    purchase_now: "Purchase Now"
-#    enrollments: "enrollments"
+    last_level: "Último nivel"
+    welcome_to_hoc: "Aventureros, bienvenidos a su Hora del Código!!"
+    logged_in_as: "Logeado como:"
+    not_you: "No eres tú?"
+    welcome_back: "Hola aventurero, bienvenido nuevamente!"
+    continue_playing: "Seguir jugando"
+    more_options: "Másopciones:"
+    option1_header: "Opción 1: Invitar estudiantes vía email"
+    option1_body: "Se enviará automaticamente una invitación a los estudiantes para unirse a esta clase, y tendrán que crear una cuenta con un nombre de usuario y una contraseña."
+    option2_header: "Opción 2: Enviarles la URL a tus estudiantes"
+    option2_body: "Se pedirá a los estudiantes que ingresen un correo electrónico, un nombre de usuario y una contraseña para crear una cuenta."
+    option3_header: "Opción 3: Dirigir estudiantes a to codecombat.com/courses"
+    option3_body: "Dar a los estudiantes el siguiente código de acceso para ingresar junto con el correo electrónico, el nombre de usuario y la contraseña cuando creen una cuenta."
+    thank_you_pref: "Gracias por tu compra! Ahora puedes asignar"
+    thank_you_suff: "más estudiantes a cursos pagos."
+    return_to_class: "Regresar al aula"
+    return_to_course_man: "Regresar a la administración del curso."
+    students_not_enrolled: "estudiantes no matriculados"
+    total_all_classes: "Total Por Todas las Clases"
+    how_many_enrollments: "¿Cuántas matriculas pagas adicionales necesitas?"
+    each_student_access: "Cada estudiante en una clase obtendrá acceso a los Cursos 2-4 una vez que esten matriculados en los cursos pagos. Puedes asignar cada curso a cada estudiante de forma individual."
+    purchase_now: "Comprar Ahora"
+    enrollments: "matrículas"
     remove_student1: "Quitar alumno"
-#    are_you_sure: "Are you sure you want to remove this student from this class?"
-#    remove_description1: "Student will lose access to this classroom and assigned classes. Progress and gameplay is NOT lost, and the student can be added back to the classroom at any time."
-#    remove_description2: "The activated paid license will not be returned."
+    are_you_sure: "¿Estás seguro que quieres quitar este alumno de tu clase?"
+    remove_description1: "El estudiante perderá acceso a esta aula y a sus clases asignadas. El progreso y la experiencia del juego NO se pierde, y el estudiante puede ser agregado de vuelta al aula en cualquier momento."
+    remove_description2: "La matrícula paga activada no será devuelta."
     keep_student: "Mantener alumno"
-#    removing_user: "Removing user"
-#    to_join_ask: "To join a class, ask your teacher for an unlock code."
-#    join_this_class: "Join Class"
-#    enter_here: "<enter unlock code here>"
-#    successfully_joined: "Successfully joined"
-#    click_to_start: "Click here to start taking"
-#    my_courses: "My Courses"
-#    classroom: "Classroom"
-#    use_school_email: "use your school email if you have one"
-#    unique_name: "a unique name no one has chosen"
+    removing_user: "Removiendo usuario"
+    to_join_ask: "Para ingresar a una clase, preguntale a tu maestro por un código de acceso."
+    join_this_class: "Ingresar clase"
+    enter_here: "<Ingresar el código aquí>"
+    successfully_joined: "Ingresado exitosamente"
+    click_to_start: "Click aquí para comenzar a hablar"
+    my_courses: "Mis Cursos"
+    classroom: "Aulas"
+    use_school_email: "utilize su correo electrónico de la escuela si tiene uno"
+    unique_name: "un nombre único, no uno que ya esté escogido"
     pick_something: "Escoge algo que recuerdes"
-#    class_code: "Class Code"
-#    optional_ask: "optional - ask your teacher to give you one!"
+    class_code: "Código de acceso"
+    optional_ask: "opcional - pregunta a tu maestro para que te de uno!"
     optional_school: "opcional - a qué escuela vas?"
     start_playing: "Comienza a Jugar"
     skip_this: "Saltar esto, Crearé una cuenta mas tarde!"
     welcome: "Bienvenido"
-#    getting_started: "Getting Started with Courses"
-#    download_getting_started: "Download Getting Started Guide [PDF]"
-#    getting_started_1: "Create a new class by clicking the green 'Create New Class' button below."
-#    getting_started_2: "Once you've created a class, click the blue 'Add Students' button."
-#    getting_started_3: "You'll see student's progress below as they sign up and join your class."
-#    additional_resources: "Additional Resources"
-#    additional_resources_1_pref: "Download/print our"
-#    additional_resources_1_mid: "Course 1 Teacher's Guide"
-#    additional_resources_1_suff: "explanations and solutions to each level."
-#    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
-#    additional_resources_3_pref: "Visit our"
-#    additional_resources_3_mid: "Teacher Forums"
-#    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
-#    additional_resources_4_pref: "Check out our"
-#    additional_resources_4_mid: "Schools Page"
-#    additional_resources_4_suff: "to learn more about CodeCombat's classroom offerings."
-#    your_classes: "Your Classes"
-#    no_classes: "No classes yet!"
-#    create_new_class1: "create new class"
+    getting_started: "Cómo empezar con los Cursos"
+    download_getting_started: "Descargar Guía de Introducción [PDF]"
+    getting_started_1: "Crea una nueva clase haciendo click en el botón verde 'Crear Nueva Clase' de más abajo."
+    getting_started_2: "Una vez que creaste una clase, haz click en el botón azul 'Añadir Estudiantes'"
+    getting_started_3: "Verás los progresos de los estudiantes más abajo cuando se registren e ingresen a tu clase."
+    additional_resources: "Recursos Adicionales"
+    additional_resources_1_pref: "Descargar/imprimir nuestra"
+    additional_resources_1_mid: "Guía para maestros: Curso 1"
+    additional_resources_1_suff: "explicaciones y soluciones para cada nivel."
+    additional_resources_2_pref: "Complete nuestro"
+    additional_resources_2_suff: "para obtener dos matrículas gratuitas para el resto de nuestros cursos pagos."
+    additional_resources_3_pref: "Visite nuestro"
+    additional_resources_3_mid: "Foro de Maestros"
+    additional_resources_3_suff: "para relacionarse con sus colegas educadores que están usando CodeCombat."
+    additional_resources_4_pref: "Consulte nuestra"
+    additional_resources_4_mid: "Página de Escuelas"
+    additional_resources_4_suff: "para aprender más sobre la oferta para el aula de CodeCombat."
+    your_classes: "Tus Clases"
+    no_classes: "Aún no hay clases!"
+    create_new_class1: "crear nueva clase"
     available_courses: "Cursos Disponibles"
-#    unused_enrollments: "Unused enrollments available:"
-#    students_access: "All students get access to Introduction to Computer Science for free. One enrollment per student is required to assign them to paid CodeCombat courses. A single student does not need multiple enrollments to access all paid courses."
-#    active_courses: "active courses"
+    unused_enrollments: "Matrículas no utilizadas disponibles:"
+    students_access: "Todos los estudiantes obtienen acceso gratuito a Introducción a la Informática. Una matrícula por estudiante es necesaria para asignarles los cursos pagos de CodeCombat. Un solo estudiante no necesita múltiples matrículas para acceder a todos los cursos pagos."
+    active_courses: "cursos activos"
     no_students: "Aún no hay alumnos!"
     add_students1: "añadir alumnos"
     view_edit: "ver/editar"
-#    students_enrolled: "students enrolled"
-#    length: "Length:"
+    students_enrolled: "estudiantes matriculados"
+    length: "Duración:"
 
   classes:
     archmage_title: "Archimago"
@@ -1234,7 +1232,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     tutorial_skip: "Saltar Tutorial"
     tutorial_not_sure: "¿No estás seguro de que sucede?"
     tutorial_play_first: "Juega el Tutorial primero."
-    simple_ai: "IA Simple" # {change}
+    simple_ai: "IA Simple"
     warmup: "Calentamiento"
     friends_playing: "Amigos Jugando"
     log_in_for_friends: "Ingresa para jugar con tus amigos!"
@@ -1257,7 +1255,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     winners: "Ganadores"
     league: "Liga"
     red_ai: "IA Roja" # "Red AI Wins", at end of multiplayer match playback
-    blue_ai: "IA Azul" # {change}
+    blue_ai: "IA Azul"
     wins: "Gana" # At end of multiplayer match playback
     humans: "Rojo" # Ladder page display team name
     ogres: "Azul"
@@ -1331,7 +1329,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     months: "Meses"
     purchase_total: "Total"
     purchase_button: "Enviar Adquisición"
-    your_codes: "Tus Códigos:" # {change}
+    your_codes: "Tus Códigos:"
     redeem_codes: "Reclamar un Código de Suscripción"
     prepaid_code: "Código Prepagado"
     lookup_code: "Buscar código prepagado"
@@ -1410,8 +1408,8 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     user_polls_record: "Historia de Visitas de Encuestas"
     course: "Curso"
     courses: "Cursos"
-#    course_instance: "Course Instance"
-#    course_instances: "Course Instances"
+    course_instance: "Muestra del Curso"
+    course_instances: "Muestras del Curso"
     classroom: "Salón"
     classrooms: "Salones"
     clan: "Clan"
@@ -1518,8 +1516,8 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
     nutshell_title: "En una palabra"
     nutshell_description: "Cualquier recurso que te proveamos en el Editor de Niveles es gratis de usar como te plazca para la creación de Niveles. Sin embargo, nos reservamos el derecho de restringir la distribución de los niveles por sí mismos (aquellos creados en codecombat.com) para así poder cobrar por ellos en el futuro, si es que eso es lo que termina pasando."
     canonical: "La versión en inglés de este documento es la versión canónica y definitiva. Si hay alguna discrepancia entre las traducciones, la versión en inglés toma precedencia."
-#    third_party_title: "Third Party Services"
-#    third_party_description: "CodeCombat uses the following third party services (among others):"
+    third_party_title: "Servicios de Terceros"
+    third_party_description: "CodeCombat utiliza los siguientes servicios de terceros (entre otros):"
 
   ladder_prizes:
     title: "Premios de Torneos" # This section was for an old tournament and doesn't need new translations now.
diff --git a/app/locale/es-ES.coffee b/app/locale/es-ES.coffee
index 4354cef5b..18090b69f 100644
--- a/app/locale/es-ES.coffee
+++ b/app/locale/es-ES.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
     prompt_body: "¿Quieres obtener más?"
     prompt_button: "Ingresa a la tienda"
     recovered: "Las gemas compradas con anterioridad han sido recuperadas. Por favor, actualiza la página."
-    price: "x3500 / mes"
+    price: "x{{gems}} / mes"
 
   subscribe:
     comparison_blurb: "¡Mejora tus habilidades con una suscripción a CodeCombat!"
     feature1: "Más de 110 niveles básicos pasando por 4 mundos"
     feature2: "¡10 <strong>héroes nuevos</strong> con poderes únicos!"
     feature3: "Más de 70 niveles extra" # {change}
-    feature4: "¡<strong>3500 gemas extra</strong> cada mes!"
+    feature4: "¡<strong>{{gems}} gemas extra</strong> cada mes!"
     feature5: "Vídeo tutoriales"
     feature6: "Soporte electrónico Premium"
     feature7: "<strong>Clanes</strong> privados"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
     press_paragraph_1_link: "paquete de prensa"
     press_paragraph_1_suffix: ". Todos los logos y las imagenes pueden ser usados sin necesidad de contactarnos directamente."
     team: "Equipo"
-    george_title: "Co-Fundador"
-    george_blurb: "Hombre de Negocios"
-    scott_title: "Co-Fundador"
-    scott_blurb: "Razonable"
-    nick_title: "Co-Fundador"
+    nick_title: "Co-Fundador" # {change}
     nick_blurb: "Guru Motivacional"
-    michael_title: "Programador"
-    michael_blurb: "Administrador de Sistemas"
-    matt_title: "Co-Fundador"
+    matt_title: "Co-Fundador" # {change}
     matt_blurb: "Ciclista"
-    cat_title: "Jefe Artesano"
+    cat_title: "Jefe Artesano" # {change}
 #    cat_blurb: "Airbender"
-    josh_title: "Diseñador de Videojuegos"
-#    josh_blurb: "Floor Is Lava"
-    jose_title: "Música"
-#    jose_blurb: "Taking Off"
-    retrostyle_title: "Illustración"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Co-Fundador" # {change}
+    scott_blurb: "Razonable"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "Diseñador de Videojuegos"
+#    josh_blurb: "Floor Is Lava"
+    retrostyle_title: "Illustración"
+#    retrostyle_blurb: "RetroStyle Games"
+    jose_title: "Música"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
     email_settings_url: "tus ajustes de correo electrónico"
     email_description_suffix: "o a través de los enlaces en los correos que te enviemos, puedes cambiar tus preferencias y darte de baja fácilmente en cualquier momento."
     cost_title: "Precio"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Copyrights y Licencias"
     contributor_title: "Acuerdo de Licencia del Colaborador"
     contributor_description_prefix: "Todas las colaboraciones, tanto en la web como en nuestro repositorio de GitHub, están sujetas a nuestro"
diff --git a/app/locale/et.coffee b/app/locale/et.coffee
index 88de4f113..612791cfe 100644
--- a/app/locale/et.coffee
+++ b/app/locale/et.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Eesti", englishDescription: "Estonian", tra
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Eesti", englishDescription: "Estonian", tra
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Eesti", englishDescription: "Estonian", tra
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Eesti", englishDescription: "Estonian", tra
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/fa.coffee b/app/locale/fa.coffee
index ca2857b65..292820bf0 100644
--- a/app/locale/fa.coffee
+++ b/app/locale/fa.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/fi.coffee b/app/locale/fi.coffee
index 99057722d..4427a344a 100644
--- a/app/locale/fi.coffee
+++ b/app/locale/fi.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
     prompt_body: "Haluatko ostaa lisää?"
     prompt_button: "Siirry kauppaan"
     recovered: "Aiempi jalokiviostos palautettu. Ole hyvä ja päivitä sivu."
-    price: "x3500 / kk"
+    price: "x{{gems}} / kk"
 
   subscribe:
     comparison_blurb: "Teroita kykyjäsi CodeCombat kuukausitilauksella!"
     feature1: "110+ perustasoa 4:ssä maailmassa"
     feature2: "10 mahtavaa <strong>uutta sankaria</strong> erilaisine kykyineen!"
     feature3: "70+ lisätasoa" # {change}
-    feature4: "<strong>3500 jalokiveä</strong> joka kuukausi!"
+    feature4: "<strong>{{gems}} jalokiveä</strong> joka kuukausi!"
     feature5: "Video-oppaat"
     feature6: "Premium sähköpostituki"
     feature7: "<strong>Yksityisklaanit</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
   teachers:
     who_for_title: "Kenelle CodeCombat on tarkoitettu?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/fr.coffee b/app/locale/fr.coffee
index 09c8224c4..5ce4332cd 100644
--- a/app/locale/fr.coffee
+++ b/app/locale/fr.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     prompt_body: "En voulez-vous plus ?"
     prompt_button: "Entrer dans la boutique"
     recovered: "Gemmes précédemment achetées récupérées. Merci de rafraîchir la page."
-    price: "x3500 / mo"
+    price: "x{{gems}} / mo"
 
   subscribe:
     comparison_blurb: "Aiguisez vos compétences avec un abonnement CodeCombat !"
     feature1: "Plus de 60 niveaux au travers de 4 mondes" # {change}
     feature2: "7 puissants <strong>nouveaux héros</strong> avec des compétences uniques !" # {change}
     feature3: "Plus de 30 niveaux bonus" # {change}
-    feature4: "<strong>3500 gemmes bonus</strong> tous les mois !"
+    feature4: "<strong>{{gems}} gemmes bonus</strong> tous les mois !"
     feature5: "Tutoriels vidéo"
     feature6: "Assitance par e-mail dédiée"
     feature7: "<strong>Clans</strong> privés"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     press_paragraph_1_link: "paquet de presse"
     press_paragraph_1_suffix: ". Tous les logos et images peuvent être utilisés sans nous contacter directement."
     team: "Équipe"
-    george_title: "PDG" # {change}
-    george_blurb: "Homme d'affaires"
-    scott_title: "Programmeur" # {change}
-    scott_blurb: "Raisonable"
     nick_title: "Programmeur" # {change}
     nick_blurb: "Gourou de Motivation"
-    michael_title: "Programmeur"
-    michael_blurb: "Sys Admin"
     matt_title: "Programmeur" # {change}
     matt_blurb: "Bicycliste"
-    cat_title: "Chef Artisan"
+    cat_title: "Chef Artisan" # {change}
     cat_blurb: "Seigneur de l'air"
-    josh_title: "Game Designer"
-    josh_blurb: "Le plancher est de la lave"
-    jose_title: "Musique"
-    jose_blurb: "Décollage"
-    retrostyle_title: "Illustration"
-    retrostyle_blurb: "Jeux RetroStyle"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Programmeur" # {change}
+    scott_blurb: "Raisonable"
+    maka_title: "Responsable clientèle"
+    maka_blurb: "Conteur"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
     josh_c_title: "Game Designer"
     josh_c_blurb: "Conçoit des jeux"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "Game Designer"
+    josh_blurb: "Le plancher est de la lave"
+    retrostyle_title: "Illustration"
+    retrostyle_blurb: "Jeux RetroStyle"
+    jose_title: "Musique"
+    jose_blurb: "Décollage"
     carlos_title: "Manager de la région Brésil"
     carlos_blurb: "Homme-céleri"
-    maka_title: "Responsable clientèle"
-    maka_blurb: "Conteur"
 
   teachers:
     who_for_title: "A qui CodeCombat est-il destiné ?"
@@ -793,24 +791,24 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     course: "Cours"
     courses: "cours"
     create_new_class: "Créer une Nouvelle Classe"
-#    not_enrolled: "You are not enrolled in this course."
-#    visit_pref: "Please visit the"
-#    visit_suf: "page to enroll."
+    not_enrolled: "Vous n'êtes pas inscrit à ce cours."
+    visit_pref: "Veuillez visiter la"
+    visit_suf: "page d'inscription."
     select_class: "Selectionnez l'une de vos classes"
 #    unnamed: "*unnamed*"
     select: "Selectionner"
-#    unnamed_class: "Unnamed Class"
+    unnamed_class: "Classe sans nom"
     edit_settings: "modifier les réglages de la classe"
     edit_settings1: "Modifier les Réglages de la Classe"
     progress: "Evolution de la Classe"
     add_students: "Ajouter des Elèves"
     stats: "Statistiques"
-    total_students: "Nom total d'élèves:"
+    total_students: "Nombre total d'élèves:"
     average_time: "Temps moyen de jeu par niveau:"
     total_time: "Temps total de jeu:"
     average_levels: "Nombre de niveaux moyen complétés:"
     total_levels: "Total de niveaux complétés:"
-#    furthest_level: "Furthest level completed:"
+    furthest_level: "Meilleur niveau complété:"
     concepts_covered: "Conceptes Couverts"
     students: "Elèves"
     students1: "éleves"
@@ -818,14 +816,14 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     levels: "niveaux"
     played: "Joué"
     play_time: "Temps de jeu:"
-#    completed: "Completed:"
+    completed: "Complété:"
     invite_students: "Inviter des élèves à rejoindre cette classe."
     invite_link_header: "Lien pour rejoindre le cours"
     invite_link_p_1: "Partagez ce lien aux élèves voulant rejoindre le cours."
-#    invite_link_p_2: "Or have us email them directly:"
+    invite_link_p_2: "Ou laissez-nous leur envoyer un email directement:"
 #    capacity_used: "Course slots used:"
-    enter_emails: "Entrez les emails des élèves à inviter, à raisin d'un par ligne"
-    send_invites: "Envoyer les nvitations"
+    enter_emails: "Entrez les adresses emails des élèves à inviter, à raison d'une par ligne"
+    send_invites: "Envoyer les invitations"
     title: "Titre"
     description: "Description"
     creating_class: "Creation de la classe..."
@@ -845,7 +843,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     for: "pour" # Like in 'for 30 students'
 #    receive_code: "Afterwards you will receive an unlock code to distribute to your students, which they can use to enroll in your class."
     free_trial: "Essai gratuit pour les professeurs!"
-#    get_access: "to get individual access to all courses for evalutaion purposes."
+    get_access: "pour obtenir un accès individuel à tous les cours pour évaluation."
     questions: "Questions?"
     teachers_click: "Professeurs, Clickez Ici"
     students_click: "Elèves, Clickez Ici"
@@ -854,31 +852,31 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     more_in_less: "Apprenez plus en moins de temps"
     no_experience: "Aucune expérience en développement requise"
     easy_monitor: "Suivez facilement la progression des élèves"
-#    purchase_for_class: "Purchase a course for your entire class. It's easy to sign up your students!"
+    purchase_for_class: "Achetez un cours pour votre classe. C'est très simple de rajouter vos élèves!"
 #    see_the: "See the"
     more_info: "pour plus d'informations."
     choose_course: "Choisissez votre cours:"
     enter_code: "Entrez un code de déverouillage pour rejoindre une classe existante"
     enter_code1: "Entrez le code de déverouillage"
-#    enroll: "Enroll"
-#    pick_from_classes: "Pick from your current classes"
+    enroll: "Inscription"
+    pick_from_classes: "Sélectionnez depuis vos classes actuelles"
     enter: "Entrer"
     or: "Ou"
     topics: "Sujets"
-#    hours_content: "Hours of content:"
+    hours_content: "Heures de contenu:"
     get_free: "Obtenez des cours GRATUITS"
-#    enroll_paid: "Enroll Students in Paid Courses"
+    enroll_paid: "Inscrire des élèves aux cours payants"
     you_have1: "Vous avez"
-#    you_have2: "unused paid enrollments"
-#    use_one: "Use 1 paid enrollment for"
-#    use_multiple: "Use paid enrollments for the following students:"
-#    already_enrolled: "already enrolled"
+    you_have2: "inscriptions payantes non utilisées"
+    use_one: "Utilisez 1 inscription payante pour"
+    use_multiple: "Utilisez des inscriptions payantes pour les élèves suivants:"
+    already_enrolled: "déjà inscrit"
     licenses_remaining: "licenses restantes:"
-#    insufficient_enrollments: "insufficient paid enrollments"
-#    enroll_students: "Enroll Students"
-#    get_enrollments: "Get More Enrollments"
+    insufficient_enrollments: "inscriptions payantes insuffisantes"
+    enroll_students: "Inscrire des élèves"
+    get_enrollments: "Obtenir plus d'inscriptions"
     change_language: "Changez la langue du cours"
-#    keep_using: "Keep Using"
+    keep_using: "Continuer à utiliser"
     switch_to: "Changer"
 #    greetings: "Greetings!"
     learn_p: "Apprendre Python"
@@ -887,8 +885,8 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     back_classrooms: "Retour à mes classes"
     back_courses: "Retour à mes cours"
     edit_details: "Modifier les informations de la classe"
-#    enrolled_courses: "enrolled in paid courses:"
-#    purchase_enrollments: "Purchase Enrollments"
+    enrolled_courses: "inscrit aux cours payants:"
+    purchase_enrollments: "Acheter des inscriptions"
     remove_student: "enlever l'élève"
     assign: "Assigner"
 #    to_assign: "to assign paid courses."
@@ -899,17 +897,17 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     play_campaign_title: "Jouer la Campagne"
     play_campaign_description: "Vous êtes prêts pour la prochaine étape! Explorez des centaines de niveaux stimulants, apprenez al programmation avancée, et rivalisez avec d'autres dans les arènes multijoueurs!"
     create_account_title: "Créer un compte"
-#    create_account_description: "Sign up for a FREE CodeCombat account and gain access to more levels, more programming skills, and more fun!"
+    create_account_description: "Inscrivez-vous GRATUITEMENT à CodeCombat et accédez à plus de niveaux, plus de compétences de programmation et plus de fun!"
     preview_campaign_title: "Campagne de démonstration"
     preview_campaign_description: "Ayez un aperçu de tout ce dont CodeCombat a à offrir avant de s'enregistrer GRATUITEMENT."
     arena: "Arène"
     arena_soon_title: "L'Arene arrive prochainement"
     arena_soon_description: "Nous travaillons sur une arene multijoueur pour les classes à la fin de"
-#    not_enrolled1: "Not enrolled"
-#    not_enrolled2: "Ask your teacher to enroll you in the next course."
+    not_enrolled1: "Non inscrit"
+    not_enrolled2: "Demandez à votre professeur de vous inscrire au cours suivant."
     next_course: "Cours suivant"
     coming_soon1: "Prochainement"
-#    coming_soon2: "We are hard at work making more courses for you!"
+    coming_soon2: "Nous travaillons dur pour faire plus de nouveaux cours!"
     available_levels: "Niveaux disponibles"
     welcome_to_courses: "Aventurier, bienvenu dans les leçons!"
     ready_to_play: "Prêt à jouer?"
@@ -932,10 +930,10 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     view_class: "voir la classe"
     view_levels: "voir les niveaux"
     join_class: "Rejoindre une classe"
-#    ask_teacher_for_code: "Ask your teacher if you have a CodeCombat class code! If so, enter it below:"
+    ask_teacher_for_code: "Demandez à votre professeur si vous avez un code de classe CodeComabt! Si c'est le cas, veuillez l'entrer ci-dessous:"
     enter_c_code: "<Entrer le Code de la Classe>"
     join: "Rejoindre"
-#    joining: "Joining class"
+    joining: "En train de rejoindre la classe"
     course_complete: "Cours Terminé"
     play_arena: "Jouer à l'Arene"
     start: "Démarrer"
@@ -956,22 +954,22 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     thank_you_suff: "plus d'élèves à des cours payants."
     return_to_class: "Retourner à la classe"
     return_to_course_man: "Retourn à la gestion des cours."
-#    students_not_enrolled: "students not enrolled"
+    students_not_enrolled: "élève non inscrits"
     total_all_classes: "Total Dans Toutes Les Classes"
-#    how_many_enrollments: "How many additional paid enrollments do you need?"
-#    each_student_access: "Each student in a class will get access to Courses 2-4 once they are enrolled in paid courses. You may assign each course to each student individually."
+    how_many_enrollments: "De combien d'inscriptions payantes supplémentaire avez-vous besoin?"
+    each_student_access: "Chaque élève dans une classe aura accès aux cours 2 à 4 une fois qu'ils sont inscrits dans les cours payants. Vous pouvez assignez chaque cours à chacun des élèves individuellement."
     purchase_now: "Achetez Maintenant"
-#    enrollments: "enrollments"
+    enrollments: "inscriptions"
     remove_student1: "Supprimer l'Elève"
     are_you_sure: "Etes-vous certain de vouloir supprimer cet élève de cette classe?"
     remove_description1: "L'élève n'aura plus accès à cette classe et les classes associées. L'évolution et les personnages ne seront pas supprimés, et l'élève pourra de nouveau rejoindre la classe n'importe quand."
-#    remove_description2: "The activated paid license will not be returned."
+    remove_description2: "Une licence payante activée ne sera pas remboursée."
     keep_student: "Conserver l'Elève"
     removing_user: "Suppression de l'utilisateur"
     to_join_ask: "Pour rejoindre une classe, veuillez demander un code de déverouillage à votre professeur."
     join_this_class: "Rejoindre cette classe"
     enter_here: "<entrer le code de déverouillage>"
-#    successfully_joined: "Successfully joined"
+    successfully_joined: "Inscription avec succès"
     click_to_start: "Cliquer ici pour démarrer"
     my_courses: "Mes Cours"
     classroom: "Classe"
@@ -994,24 +992,24 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     additional_resources_1_mid: "Guide Professeur du Premier Cours"
     additional_resources_1_suff: "explications et solutions pour chaque niveaux."
     additional_resources_2_pref: "Complétez notre"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+    additional_resources_2_suff: "pour obtenir 15 heures de contenu supplémentaire! Pour une durée limitée, inscrivez autant d'élèves que vous voulez dans nos trois cours payant." # {change}
     additional_resources_3_pref: "Visitez notre"
     additional_resources_3_mid: "Forum des Professeurs"
     additional_resources_3_suff: "pour être mis en relations avec vos confrères qui utilisent CodeCombat."
-#    additional_resources_4_pref: "Check out our"
+    additional_resources_4_pref: "Faites un tour sur la"
     additional_resources_4_mid: "Page des Ecoles"
     additional_resources_4_suff: "pour en apprendre plus sur les offres CodeCombat à destination des classes."
     your_classes: "Vos Classes"
     no_classes: "Aucune classe pour le moment!"
     create_new_class1: "créer une nouvelle classe"
     available_courses: "Cours Disponibles"
-#    unused_enrollments: "Unused enrollments available:"
-#    students_access: "All students get access to Introduction to Computer Science for free. One enrollment per student is required to assign them to paid CodeCombat courses. A single student does not need multiple enrollments to access all paid courses."
+    unused_enrollments: "Inscriptions non utilisées disponibles:"
+    students_access: "Tous les élèves peuvent accéder gratuitement à l'Introduction aux Sciences Informations. Une inscription par élève est nécessaire pour rejoindre les cours payants de CodeCombat. Une seule inscription est nécessaire par élève pour accéder à tous les cours payants."
     active_courses: "cours actifs"
     no_students: "Aucun élève pour le moment!"
     add_students1: "ajouter des élèves"
     view_edit: "voir/modifier"
-#    students_enrolled: "students enrolled"
+    students_enrolled: "élèves inscrits"
     length: "Durée:"
 
   classes:
@@ -1267,7 +1265,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     singleplayer_title: "Niveaux solo"
     multiplayer_title: "Niveaux multijoueurs"
     achievements_title: "Succès"
-    last_played: "Dernièrement joués"
+    last_played: "Dernier niveau joué"
     status: "Statut"
     status_completed: "Terminé"
     status_unfinished: "Non terminé"
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     email_settings_url: "vos paramètres d'e-mail "
     email_description_suffix: "ou avec des liens disponibles dans nos e-mails, vous pouvez changer vos préférences ou vous désinscrire à tout moment."
     cost_title: "Coût"
-    cost_description_a: "CodeCombat est gratuit sur tous ses niveaux principaux, avec un abonnement de {{price}}$/mois pour l'accès à de nouveaux niveaux et {{gems}} gemmes bonus par mois. Vous pouvez annuler en un clic, et nous vous garantissons un remboursement intégral."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Copyrights et Licences"
     contributor_title: "Contributor License Agreement"
     contributor_description_prefix: "Toute contribution, sur le site et sur le répertoire GitHub, est sujette à nos"
diff --git a/app/locale/gl.coffee b/app/locale/gl.coffee
index b0bd20e8e..754eb073e 100644
--- a/app/locale/gl.coffee
+++ b/app/locale/gl.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Galego", englishDescription: "Galician", tr
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Galego", englishDescription: "Galician", tr
     press_paragraph_1_link: "paquete de prensa"
     press_paragraph_1_suffix: ". Todos os logos e as imaxes poden ser usadas sen necesidade de contactarnos directamente."
     team: "Equipo"
-    george_title: "CEO" # {change}
-    george_blurb: "Sección de Negocios"
-    scott_title: "Programador" # {change}
-    scott_blurb: "Razoable"
     nick_title: "Programador" # {change}
     nick_blurb: "Gurú Motivacional"
-    michael_title: "Programador"
-    michael_blurb: "Administrador de Sistemas"
     matt_title: "Programador" # {change}
     matt_blurb: "Ciclista"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Programador" # {change}
+    scott_blurb: "Razoable"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Galego", englishDescription: "Galician", tr
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Galego", englishDescription: "Galician", tr
     email_settings_url: "os teus axustes de correo electrónico"
     email_description_suffix: "ou a través das ligazóns nos correos que te enviemos, podes cambiar as túas preferencias e darte de baixa doadamente en calquera momento."
     cost_title: "Prezo"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Copyrights e Licenzas"
     contributor_title: "Acordo de Licenza do Colaborador"
     contributor_description_prefix: "Todas as colaboracións, tanto na web como no noso repositorio de GitHub, están suxeitas ao noso"
diff --git a/app/locale/he.coffee b/app/locale/he.coffee
index a825925b1..b50d74801 100644
--- a/app/locale/he.coffee
+++ b/app/locale/he.coffee
@@ -4,7 +4,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
     no_ie: "המשחק לא עובד באקפלורר 8 וישן יותר. סליחה!" # Warning that only shows up in IE8 and older
     no_mobile: "המשחק לא עוצב לטלפונים ואולי לא יעבוד" # Warning that shows up on mobile devices
     play: "שחק" # The big play button that opens up the campaign view.
-#    play_campaign_version: "Play Campaign Version" # Shows up under big play button if you only play /courses
+    play_campaign_version: "שחק בגרסת המסע" # Shows up under big play button if you only play /courses
     old_browser: "או או, נראה כי הדפדפן שלך יותר מידי ישן כדי להריץ את המשחק. סליחה!" # Warning that shows up on really old Firefox/Chrome/Safari
     old_browser_suffix: "אתה יכול לנסות בכול מקרה אבל זה כנראה לא יעבוד."
     ipad_browser: "חדשות רעות: CodeCombat לא עובד בדפדפן של הiPad-. חדשות טובות: גרסת הiPad של המשחק ממתינה לאישור מחברת Apple."
@@ -17,7 +17,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
   nav:
     play: "שלבים" # The top nav bar entry where players choose which levels to play
     community: "קהילה"
-#    courses: "Courses"
+    courses: "מסלולים"
     editor: "עורך"
     blog: "בלוג"
     forum: "פורום"
@@ -33,7 +33,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
     contact: "צור קשר"
     twitter_follow: "עקוב אחרינו בטוויטר"
     teachers: "מורים"
-#    careers: "Careers"
+    careers: "קריירות"
 
   modal:
     close: "סגור"
@@ -52,7 +52,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
 
   play:
     play_as: "שחק בתור " # Ladder page
-#    compete: "Compete!" # Course details page
+    compete: "הושלם!" # Course details page
     spectate: "צופה" # Ladder page
     players: "שחקנים" # Hover over a level on /play
     hours_played: "שעות משחק" # Hover over a level on /play
@@ -75,7 +75,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
     subscription_required: "יש צורך במנוי"
     anonymous: "משתמש אנונימי"
     level_difficulty: "רמת קושי: "
-#    play_classroom_version: "Play Classroom Version" # Choose a level in campaign version that you also can play in one of your courses
+    play_classroom_version: "שיק בגרסה הכיתתית" # Choose a level in campaign version that you also can play in one of your courses
     campaign_beginner: "מסע המתחילים"
     awaiting_levels_adventurer_prefix: ".אנחנו מוסיפים חמישה שלבים בכל שבוע" # {change}
     awaiting_levels_adventurer: "הירשם כהרפתקן"
@@ -83,7 +83,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
     adjust_volume: "שנה ווליום"
     campaign_multiplayer: "זירות רב-המשתתפים"
     campaign_multiplayer_description: "..."
-#    campaign_old_multiplayer: "(Deprecated) Old Multiplayer Arenas"
+    campaign_old_multiplayer: "(לא מומלץ) זירות מרובי משתתפים ישנות"
 #    campaign_old_multiplayer_description: "Relics of a more civilized age. No simulations are run for these older, hero-less multiplayer arenas."
 
   share_progress_modal:
@@ -114,9 +114,9 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
     log_in: "כנס עם סיסמה"
     required: ".יש להתחבר על מנת לגשת לשלב זה"
     login_switch: "? כבר יש לך משתמש"
-#    school_name: "School Name and City"
-#    optional: "optional"
-#    school_name_placeholder: "Example High School, Springfield, IL"
+    school_name: "שם בית ספר ועיר"
+    optional: "רשות"
+    school_name_placeholder: "לדוגמה: תיכון עירוני X, תל אביב."
 
   recover:
     recover_account_title: "שחזר סיסמה"
@@ -157,15 +157,15 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
   general:
     and: "וגם"
     name: "שם"
-    date: "Date"
+    date: "תאריך"
     body: "גוף"
     version: "גרסה"
     pending: "ממתין"
     accepted: "התקבל"
     rejected: "נדחה"
     withdrawn: "האוייב נסוג"
-#    accept: "Accept"
-#    reject: "Reject"
+    accept: "מסכים"
+    reject: "דחה"
 #    withdraw: "Withdraw"
     submitter: "מוסר"
     submitted: "נמסר"
@@ -221,12 +221,12 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
     years: "שנים"
 
   play_level:
-#    completed_level: "Completed Level:"
-#    course: "Course:"
+    completed_level: "שלב שהושלם:"
+    course: "מסלול:"
     done: "סיים"
-#    next_level: "Next Level:"
-#    next_game: "Next game"
-#    show_menu: "Show game menu"
+    next_level: "השלב הבא:"
+    next_game: "המשחק הבא"
+    show_menu: "הצג תפריט משחק"
     home: "בית" # Not used any more, will be removed soon.
     level: "שלב" # Like "Level: Dungeons of Kithgard"
     skip: "דלג"
@@ -256,13 +256,13 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
     victory_saving_progress: "שומר התקדמות"
     victory_go_home: "חזור הביתה"
     victory_review: "!ספר לנו עוד"
-#    victory_review_placeholder: "How was the level?"
+    victory_review_placeholder: "איך היה השלב?"
     victory_hour_of_code_done: "?סיימת"
     victory_hour_of_code_done_yes: "שלי Hour of Code™! כן, סיימתי עם ה"
     victory_experience_gained: "שנצבר XP"
     victory_gems_gained: "אבני חן שנצברו"
     victory_new_item: "חפץ חדש"
-#    victory_viking_code_school: "Holy smokes, that was a hard level you just beat! If you aren't already a software developer, you should be. You just got fast-tracked for acceptance with Viking Code School, where you can take your skills to the next level and become a professional web developer in 14 weeks."
+    victory_viking_code_school: "אבוקדו קדוש, זה היה שלב קשה שסיימת! אם אתה עדיין לא מפתח תוכנה, אתה צריך להיות אחד. בדיוק עלית על הכביש המהיר בכדי להתקבל ל Viking Code School, שם תוכל לשאת את כישוריך לרמה הבאה ותוכל להפוך למפתח רשת מקצועי תוך 14 שבועות בלבד."
     victory_become_a_viking: "הפוך לוויקינג"
     guide_title: "מדריך"
     tome_cast_button_run: "הפעל"
@@ -297,7 +297,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
     tip_scrub_shortcut: "Ctrl+[ ו Ctrl+] האץ אחורה וקדימה באמצעות" # {change}
     tip_guide_exists: ".לחץ על המדריך, בתוך תפריט המשחק (למעלה בקצה העמוד), למידע שימושי"
     tip_open_source: "!הוא 100% קוד פתוח CodeCombat"
-#    tip_tell_friends: "Enjoying CodeCombat? Tell your friends about us!"
+    tip_tell_friends: "נהנה מCodeCombat? ספר לחבריךעלינו!"
     tip_beta_launch: ".הפיץ את גרסת הבטא באוקטובר, 2013 CodeCombat"
     tip_think_solution: ".תחשוב על הפתרון, לא על הבעיה"
     tip_theory_practice: "תיאורטית, אין הבדל בין התאוריה לאימון. אבל באימון, יש. - יוגי ברה"
@@ -307,7 +307,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
     tip_baby_coders: ".בעתיד, אפילו תינוקות יהיו כשפי על"
     tip_morale_improves: ".הטעינה תמשיך עד שהמורל ישתפר"
     tip_all_species: ".אנחנו מאמינים בשוויון הזדמנויות לכל היצורים בלמידת תכנות"
-#    tip_reticulating: "Reticulating spines."
+    tip_reticulating: "Reticulating spines."
     tip_harry: " ,תה' מכשף"
     tip_great_responsibility: "עם כישרון גדול בתכנות באה גם אחריות דיבאגינג גדולה."
     tip_munchkin: "אם לא תאכל את הירקות, מאצ'קין יבוא אליך בלילה כשאתה ישן."
@@ -397,20 +397,20 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
     prompt_body: "?רוצה לקבל עוד"
     prompt_button: "היכנס לחנות"
     recovered: ".רכישה אחרונה שוחזרה. טען את הדף מחדש בבקשה"
-    price: "x3500  לחודש"
+    price: "x{{gems}}  לחודש"
 
   subscribe:
     comparison_blurb: ".CodeCombatחדד את כישוריך עם מנוי ל"
     feature1: "60+ שלבים בסיסיים ב 4 עולמות שונים." # {change}
     feature2: "!עם כישורים מיוחדים <strong>גיבורים עוצמתיים חדשים</strong> 7" # {change}
     feature3: "30+ שלבי בונוס" # {change}
-    feature4: "!בחינם כל חודש <strong>3500 אבני חן</strong>"
+    feature4: "!בחינם כל חודש <strong>{{gems}} אבני חן</strong>"
     feature5: "הדרכות וידאו"
     feature6: "תמיכת מייל בעדיפות ראשונה"
     feature7: "פרטיים <strong>שבטים</strong>"
     free: "חינם"
     month: "חודש"
-#    must_be_logged: "You must be logged in first. Please create an account or log in from the menu above."
+    must_be_logged: "עליך להיות מחובר תחילה. אנא צור חשבון חדש או היכנס לחשבונך באמצעות התפריט למעלה."
     subscribe_title: "רכוש מנוי"
     unsubscribe: "הסר מנוי"
     confirm_unsubscribe: "אשר הסרת מנוי"
@@ -484,10 +484,10 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
     blocks: "הגנה" # As in "this shield blocks this much damage"
     backstab: "פגיעה בגב" # As in "this dagger does this much backstab damage"
     skills: "מיומנויות"
-#    attack_1: "Deals"
+    attack_1: "מבצעים"
 #    attack_2: "of listed"
 #    attack_3: "weapon damage."
-#    health_1: "Gains"
+    health_1: "רווחים"
 #    health_2: "of listed"
 #    health_3: "armor health."
     speed_1: "זז במהירות של"
@@ -499,8 +499,8 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
   skill_docs:
     writable: "ניתן לכתיבה" # Hover over "attack" in Your Skills while playing a level to see most of this
     read_only: "לקריאה בלבד"
-#    action: "Action"
-#    spell: "Spell"
+    action: "פעולה"
+    spell: "כישוף"
     action_name: "שם"
     action_cooldown: "לוקח"
     action_specific_cooldown: ":זמן להתקררות"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
     team: "צוות"
-    george_title: "מנכ\"ל" # {change}
-    george_blurb: "ביזנסר"
-    scott_title: "מתכנת" # {change}
-    scott_blurb: "אחד סביר"
     nick_title: "מתכנת" # {change}
     nick_blurb: "גורו מוטיבציה"
-    michael_title: "מתכנת"
-    michael_blurb: "מנהל מערכת"
     matt_title: "מתכנת" # {change}
     matt_blurb: "רוכב אופניים"
-    cat_title: "צ'יף אמן"
+    cat_title: "צ'יף אמן" # {change}
     cat_blurb: "כשף אוויר"
-    josh_title: "מעצב משחק"
-    josh_blurb: "ארצפה היא לבה"
-    jose_title: "מוזיקה"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "מתכנת" # {change}
+    scott_blurb: "אחד סביר"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "מעצב משחק"
+    josh_blurb: "ארצפה היא לבה"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+    jose_title: "מוזיקה"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/hi.coffee b/app/locale/hi.coffee
index 4f3b10258..e26c39130 100644
--- a/app/locale/hi.coffee
+++ b/app/locale/hi.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/hu.coffee b/app/locale/hu.coffee
index 1d4446a9c..765b1fc3f 100644
--- a/app/locale/hu.coffee
+++ b/app/locale/hu.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
     prompt_body: "Szeretnél többet?"
     prompt_button: "Lépj be a boltba"
     recovered: "Az előző drágakő vásárlás helyreállt. Kérlek frissítsd az oldalt."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
   subscribe:
     comparison_blurb: "Élesítsd képességeid CodeCombat feliratkozással!"
     feature1: "60+ alap pálya, 4 világon át" # {change}
     feature2: "7 erőteljes <strong>új hős</strong> egyedi képességekkel!" # {change}
     feature3: "30+ bónusz pálya" # {change}
-    feature4: "<strong>3500 bónusz drágakő</strong> minden hónapban!"
+    feature4: "<strong>{{gems}} bónusz drágakő</strong> minden hónapban!"
     feature5: "Videó oktatóanyagok"
     feature6: "Prémium email támogatás"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
     team: "Csapat"
-    george_title: "Főigazgató" # {change}
-    george_blurb: "Üzletelő"
-    scott_title: "Programozó" # {change}
-    scott_blurb: "Megfontolt"
     nick_title: "Programozó" # {change}
     nick_blurb: "Motivátor"
-    michael_title: "Programozó"
-    michael_blurb: "Rendszer Admin"
     matt_title: "Programozó" # {change}
     matt_blurb: "Bringás"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Programozó" # {change}
+    scott_blurb: "Megfontolt"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
   teachers:
     who_for_title: "Kinek való a CodeCombat?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/id.coffee b/app/locale/id.coffee
index 4e9fb5488..d3bb7cf4c 100644
--- a/app/locale/id.coffee
+++ b/app/locale/id.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/it.coffee b/app/locale/it.coffee
index 4a59f0b15..4dd7a2875 100644
--- a/app/locale/it.coffee
+++ b/app/locale/it.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
     prompt_body: "Ne vuoi comprare altre?"
     prompt_button: "Entra nel negozio"
     recovered: "Acquisto precedente recuperato. Ricaricare la pagina."
-    price: "x3500 / mese"
+    price: "x{{gems}} / mese"
 
   subscribe:
     comparison_blurb: "Aumenta le tue competenze con un abbonamento a CodeCombat!"
     feature1: "80+ livelli base in 4 mondi" # {change}
     feature2: "7 potenti <strong>nuovi eroi</strong> con capacità uniche!" # {change}
     feature3: "50+ livelli bonus" # {change}
-    feature4: "<strong>3500 gemme bonus</strong> ogni mese!"
+    feature4: "<strong>{{gems}} gemme bonus</strong> ogni mese!"
     feature5: "Video tutorial"
     feature6: "Supporto via email premium"
     feature7: "Clan <strong>privati</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
     press_paragraph_1_link: "pacchetto per la stampa"
     press_paragraph_1_suffix: ". Tutti i loghi e le immagini possono essere usate senza contattarci direttamente."
     team: "Team"
-    george_title: "Co-fondatore"
-    george_blurb: "Imprenditore"
-    scott_title: "Programmatore" # {change}
-    scott_blurb: "Un Tipo Ragionevole"
     nick_title: "Programmatore" # {change}
     nick_blurb: "Guru motivatore"
-    michael_title: "Programmatore"
-    michael_blurb: "Amministratore di sistema"
     matt_title: "Programmatore" # {change}
     matt_blurb: "Ciclista"
-    cat_title: "Mastro artigiano"
+    cat_title: "Mastro artigiano" # {change}
     cat_blurb: "Manipolatore dell'aria"
-    josh_title: "Game Designer"
-    josh_blurb: "Il pavimento è lava"
-    jose_title: "Musicista"
-    jose_blurb: "Prendiamo il volo"
-    retrostyle_title: "Illustratore"
-    retrostyle_blurb: "Giochi retrò"
-    rob_title: "Ingegnere compilazione"
+    scott_title: "Programmatore" # {change}
+    scott_blurb: "Un Tipo Ragionevole"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+    rob_title: "Ingegnere compilazione" # {change}
     rob_blurb: "Programmi, fatti e cose"
     josh_c_title: "Game Designer"
     josh_c_blurb: "Progettista giochi"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "Game Designer"
+    josh_blurb: "Il pavimento è lava"
+    retrostyle_title: "Illustratore"
+    retrostyle_blurb: "Giochi retrò"
+    jose_title: "Musicista"
+    jose_blurb: "Prendiamo il volo"
     carlos_title: "Manager Regionale, Brasile"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
   teachers:
     who_for_title: "A chi è indirizzato CodeCombat?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
diff --git a/app/locale/ja.coffee b/app/locale/ja.coffee
index fac55c734..a4cbdedb6 100644
--- a/app/locale/ja.coffee
+++ b/app/locale/ja.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
     prompt_body: "もっと購入しますか?"
     prompt_button: "ショップに入る"
     recovered: "前のジェム購入をリカバリーしました。ページを更新してください。"
-    price: "x3500 / 月"
+    price: "x{{gems}} / 月"
 
   subscribe:
     comparison_blurb: "CodeCombatへ課金してスキルを磨きましょう!"
     feature1: "110以上の基本レベルが4つの世界に" # {change}
     feature2: "10人のパワフルな <strong>ニューヒーロー</strong> とユニークなスキル!" # {change}
     feature3: "70以上のボーナスレベル" # {change}
-    feature4: "<strong>3500のジェム</strong>が毎月ボーナス!"
+    feature4: "<strong>{{gems}}のジェム</strong>が毎月ボーナス!"
     feature5: "ビデオチュートリアル"
     feature6: "プレミアムメールサポート"
     feature7: "プライベート<strong>クラン</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
     press_paragraph_1_link: "プレスパケットをダウンロード"
     press_paragraph_1_suffix: "。全てのロゴやイメージは、私達に連絡することなく使用することができます。"
     team: "開発チーム"
-    george_title: "コーファウンダー" # {change}
-    george_blurb: "ビジネスの達人"
-    scott_title: "コーファウンダー" # {change}
-    scott_blurb: "リーズナブルな奴"
     nick_title: "コーファウンダー" # {change}
     nick_blurb: "モチベーションの達人"
-    michael_title: "プログラマー"
-    michael_blurb: "システム管理者"
     matt_title: "プログラマー" # {change}
     matt_blurb: "サイクリスト"
-    cat_title: "チーフアルティザン"
+    cat_title: "チーフアルティザン" # {change}
     cat_blurb: "エアベンダー"
-    josh_title: "ゲームデザイナー"
-    josh_blurb: "床は溶岩"
-    jose_title: "ミュージック"
-    jose_blurb: "テークオフ"
-    retrostyle_title: "イラスト"
-    retrostyle_blurb: "レトロスタイルのゲーム"
-    rob_title: "コンパイラーエンジニアー"
+    scott_title: "コーファウンダー" # {change}
+    scott_blurb: "リーズナブルな奴"
+    maka_title: "顧客主義"
+    maka_blurb: "ストーリーテラー"
+    rob_title: "コンパイラーエンジニアー" # {change}
     rob_blurb: "コードの道具と材料"
     josh_c_title: "ゲームデザイナー"
     josh_c_blurb: "ゲームのデザイン"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "ゲームデザイナー"
+    josh_blurb: "床は溶岩"
+    retrostyle_title: "イラスト"
+    retrostyle_blurb: "レトロスタイルのゲーム"
+    jose_title: "ミュージック"
+    jose_blurb: "テークオフ"
     carlos_title: "地域部長, ブラジル"
     carlos_blurb: "サラリーマン"
-    maka_title: "顧客主義"
-    maka_blurb: "ストーリーテラー"
 
   teachers:
     who_for_title: "CodeCombat が必要なひと"
@@ -589,35 +587,35 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
     more_info_3: "でCodeCombatを使っている教育者の仲間とつながりましょう。"
 
   teachers_survey:
-#    title: "Teacher Survey"
-#    must_be_logged: "You must be logged in first. Please create an account or log in from the menu above."
-#    retrieving: "Retrieving information..."
-#    being_reviewed_1: "Your application for a free trial is being"
-#    being_reviewed_2: "reviewed."
-#    approved_1: "Your application for a free trial was"
-#    approved_2: "approved!"
-#    approved_4: "You can now enroll your students on the"
-#    approved_5: "courses"
-#    approved_6: "page."
-#    denied_1: "Your application for a free trial has been"
-#    denied_2: "denied."
-#    contact_1: "Please contact"
-#    contact_2: "if you have further questions."
-#    description_1: "We offer free trials to teachers.  You will be given 2 free enrollments which can be used to enroll students in paid courses."
-#    description_1b: "You can find more information on our"
-#    description_2: "teachers"
-#    description_3: "page."
-#    description_4: "Please fill out this quick survey and we’ll email you setup instructions."
-#    email: "Email Address"
+    title: "教師用アンケート"
+    must_be_logged: "最初にログインしてください。アカウントを作成するか、上記のメニューからログインしてください。"
+    retrieving: "情報を取得しています..."
+    being_reviewed_1: "無料トライアルの申し込みが"
+    being_reviewed_2: "レビューされています。"
+    approved_1: "無料トライアルの申し込みが"
+    approved_2: "承認されました!"
+    approved_4: "以下のページで生徒を入会させることができます:"
+    approved_5: "コース"
+    approved_6: "ページ。"
+    denied_1: "無料トライアルの申し込みが"
+    denied_2: "拒否されました。"
+    contact_1: "お問い合わせください"
+    contact_2: "ご質問がある場合は"
+    description_1: "教師の方に無料トライアルを提供しています。有料コースで生徒さんを入会させるのに使用できる、2つの無料入会権が与えられます。"
+    description_1b: "詳細は以下のページで参照してください:"
+    description_2: "教師用"
+    description_3: "ページ。"
+    description_4: "この簡易アンケートに記入をお願いします。設定手順をメールにてお送りします。"
+    email: "電子メールアドレス"
     school: "学校名"
     location: "市町村"
-#    age_students: "How old are your students?"
-#    under: "Under"
-#    other: "Other:"
-#    amount_students: "How many students do you teach?"
-#    hear_about: "How did you hear about CodeCombat?"
-#    fill_fields: "Please fill out all fields."
-#    thanks: "Thanks! We'll send you setup instructions shortly."
+    age_students: "生徒さんの年齢を教えてください。"
+    under: "未満"
+    other: "その他:"
+    amount_students: "何人の生徒さんをお持ちですか?"
+    hear_about: "CodeCombatをどのようにお知りなりましたか?"
+    fill_fields: "全てのフィールドを記入してください。"
+    thanks: "ありがとうございます。設定の手順を追ってお送りします。"
 
   versions:
     save_version_title: "新しいバージョンをセーブ"
@@ -625,9 +623,9 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
     submitting_patch: "パッチを送信中..."
     cla_prefix: "変更を適用するには, 私達のCLAに同意する必要があります。"
     cla_url: "CLA"
-#    cla_suffix: "."
+    cla_suffix: "。"
     cla_agree: "同意する"
-#    owner_approve: "An owner will need to approve it before your changes will become visible."
+    owner_approve: "ユーザーは変更が実際に表示される前に同意する必要があります。"
 
   contact:
     contact_us: "お問い合わせ"
@@ -662,23 +660,23 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
     password_tab: "パスワード"
     emails_tab: "メール"
     admin: "管理者"
-#    manage_subscription: "Click here to manage your subscription."
+    manage_subscription: "購読を管理するにはここをクリックしてください。"
     new_password: "新パスワード"
     new_password_verify: "新パスワードを再入力"
     type_in_email: "アカウントの削除を確認するために、メールアドレスを入力して下さい。"
     type_in_email_progress: "進捗を消すために、メールアドレスを入力してください。"
     type_in_password: "そして、パスワードを入力してください。"
     email_subscriptions: "ニュースレターの購読"
-    email_subscriptions_none: "No Email Subscriptions."
+    email_subscriptions_none: "ニュースレターの購読はありません。"
     email_announcements: "お知らせ"
     email_announcements_description: "CodeCombatの最新のニュースや進展をメールで受け取る"
     email_notifications: "通知"
-#    email_notifications_summary: "Controls for personalized, automatic email notifications related to your CodeCombat activity."
-#    email_any_notes: "Any Notifications"
-#    email_any_notes_description: "Disable to stop all activity notification emails."
+    email_notifications_summary: "CodeCombatアクティビティに関する自動電子メール通知の管理。"
+    email_any_notes: "すべての通知"
+    email_any_notes_description: "アクティビティすべての通知メールを停止することを無効にします。"
     email_news: "ニュース"
     email_recruit_notes: "求人"
-#    email_recruit_notes_description: "If you play really well, we may contact you about getting you a (better) job."
+    email_recruit_notes_description: "上手にプレイしてくれる場合、(更に良い)仕事を紹介するためにこちらから連絡を差し上げる場合があります。"
     contributor_emails: "開発を手伝ってくれる人向けのメール"
     contribute_prefix: "私達は開発を手伝ってくれる人を探しています。 詳しくは "
     contribute_page: "こちらのページ"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/ko.coffee b/app/locale/ko.coffee
index 5b5c955db..c17323a56 100644
--- a/app/locale/ko.coffee
+++ b/app/locale/ko.coffee
@@ -4,20 +4,20 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     no_ie: "죄송하지만 코드컴뱃은 인터넷 익스플로러 8에서는 동작하지 않습니다." # Warning that only shows up in IE8 and older
     no_mobile: "코드 컴뱃은 모바일 기기용으로 제작되지 않았습니다. 아마 동작하지 않을 가능성이 높습니다." # Warning that shows up on mobile devices
     play: "시작" # The big play button that opens up the campaign view.
-#    play_campaign_version: "Play Campaign Version" # Shows up under big play button if you only play /courses
+    play_campaign_version: "캠페인 버전 플레이" # Shows up under big play button if you only play /courses
     old_browser: "브라우저가 너무 오래된 버전이라 코드 컴뱃을 실행할 수 없습니다." # Warning that shows up on really old Firefox/Chrome/Safari
     old_browser_suffix: "시도해볼 수는 있겠지만..안될 수도 있습니다."
-#    ipad_browser: "Bad news: CodeCombat doesn't run on iPad in the browser. Good news: our native iPad app is awaiting Apple approval."
+    ipad_browser: "슬픈 소식: 코드컴뱃은 아이패드의 브라우저에서 구동되지않습니다. 좋은 소식: 우리의 아이패드 앱은 애플의 승인을 기다리고있습니다 ."
     campaign: "캠페인"
     for_beginners: "초보자용"
     multiplayer: "멀티플레이어" # Not currently shown on home page
     for_developers: "개발자용" # Not currently shown on home page.
-#    or_ipad: "Or download for iPad"
+    or_ipad: "또는 아이패드의 다운로드"
 
   nav:
     play: "레벨" # The top nav bar entry where players choose which levels to play
     community: "커뮤니티"
-#    courses: "Courses"
+    courses: "코스"
     editor: "에디터"
     blog: "블로그"
     forum: "포럼"
@@ -33,7 +33,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     contact: "문의"
     twitter_follow: "팔로우"
     teachers: "선생님들"
-#    careers: "Careers"
+    careers: "채용"
 
   modal:
     close: "닫기"
@@ -52,7 +52,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
 
   play:
     play_as: "Play As " # Ladder page
-#    compete: "Compete!" # Course details page
+    compete: "경쟁!" # Course details page
     spectate: "관중모드" # Ladder page
     players: "플레이어" # Hover over a level on /play
     hours_played: "플레이한 시간" # Hover over a level on /play
@@ -68,14 +68,14 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     achievements: "성취한 목표" # Tooltip on achievement list button from /play
     account: "계정" # Tooltip on account button from /play
     settings: "설정" # Tooltip on settings button from /play
-#    poll: "Poll" # Tooltip on poll button from /play
+    poll: "투표" # Tooltip on poll button from /play
     next: "다음" # Go from choose hero to choose inventory before playing a level
     change_hero: "영웅 교체" # Go back from choose inventory to choose hero
     buy_gems: "젬 구매"
-#    subscription_required: "Subscription Required"
+    subscription_required: "가입 필수"
     anonymous: "이름없는 플레이어"
     level_difficulty: "난이도: "
-#    play_classroom_version: "Play Classroom Version" # Choose a level in campaign version that you also can play in one of your courses
+    play_classroom_version: "교실 버전 플레이" # Choose a level in campaign version that you also can play in one of your courses
     campaign_beginner: "초보자 캠페인"
     awaiting_levels_adventurer_prefix: "매주 마다 새로운 레벨이 생깁니다."
     awaiting_levels_adventurer: "모험자로 등록 하세요!"
@@ -83,16 +83,16 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     adjust_volume: "소리 조절"
     campaign_multiplayer: "멀티 플레이어 전투장"
     campaign_multiplayer_description: "... 이곳에서 당신은 다른 인간 플레이어들과 직접 결투할 수 있습니다."
-#    campaign_old_multiplayer: "(Deprecated) Old Multiplayer Arenas"
-#    campaign_old_multiplayer_description: "Relics of a more civilized age. No simulations are run for these older, hero-less multiplayer arenas."
+    campaign_old_multiplayer: "(추천하지 않습니다) 숙련된 멀티플레이어 경쟁"
+    campaign_old_multiplayer_description: "더 문명화 된 시대의 유물. 어떤 시뮬레이션은 이러한 이전, 영웅없는 멀티 경기장에 대해 실행되지 않습니다."
 
   share_progress_modal:
-#    blurb: "You’re making great progress! Tell your parent how much you've learned with CodeCombat."
+    blurb: "당신은 큰 진전을 보이고있습니다! 당신이 코드컴뱃으로 얼마나 많이 배웠는지 부모님게 말하십시오."
     email_invalid: "이메일 주소가 올바르지 않습니다."
-#    form_blurb: "Enter your parent's email below and we’ll show them!"
+    form_blurb: "아래에 부모님의 이메일을 입력하고 우리는 그것들을 보여줍니다!"
     form_label: "이메일"
     placeholder: "이메일"
-#    title: "Excellent Work, Apprentice"
+    title: "우수한, 초심자"
 
   login:
     sign_up: "계정 생성"
@@ -100,8 +100,8 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     logging_in: "로그인 중"
     log_out: "로그아웃"
     forgot_password: "비밀번호를 잊으셨나요?"
-#    authenticate_gplus: "Authenticate G+"
-#    load_profile: "Load G+ Profile"
+    authenticate_gplus: "G+ 인증"
+    load_profile: "G+ 프로필 불러오기"
     finishing: "완료중.."
     sign_in_with_facebook: "Facebook으로 로그인"
     sign_in_with_gplus: "G+로 로그인"
@@ -114,9 +114,9 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     log_in: "비밀번호로 로그인"
     required: "진행하기 전에 로그인이 필요합니다."
     login_switch: "이미 계정이 있으신가요?"
-#    school_name: "School Name and City"
-#    optional: "optional"
-#    school_name_placeholder: "Example High School, Springfield, IL"
+    school_name: "학교 이름과 도시"
+    optional: "옵션"
+    school_name_placeholder: "예시 고등학교, 스프링필드, IL"
 
   recover:
     recover_account_title: "계정 복구"
@@ -142,7 +142,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     save: "저장"
     publish: "내보내기"
     create: "생성"
-    fork: "Fork"
+    fork: "포크"
     play: "시작" # When used as an action verb, like "Play next level"
     retry: "재시도"
     actions: "행동"
@@ -164,20 +164,20 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     accepted: "적용됨"
     rejected: "거부됨"
     withdrawn: "취소됨"
-#    accept: "Accept"
-#    reject: "Reject"
-#    withdraw: "Withdraw"
+    accept: "승인"
+    reject: "보류"
+    withdraw: "철수"
     submitter: "제출자"
     submitted: "제출됨"
     commit_msg: "커밋 메세지"
     version_history: "버전 히스토리"
     version_history_for: "버전 히스토리 : "
-#    select_changes: "Select two changes below to see the difference."
-#    undo_prefix: "Undo"
+    select_changes: "차이를 보기위해 두 가지 사항을 변경하도록 선택합니다."
+    undo_prefix: "되돌리기"
     undo_shortcut: "(Ctrl+Z)"
-#    redo_prefix: "Redo"
+    redo_prefix: "다시하기"
     redo_shortcut: "(Ctrl+Shift+Z)"
-#    play_preview: "Play preview of current level"
+    play_preview: "현재 수준의 미리보기 재생"
     result: "결과"
     results: "결과들"
     description: "설명"
@@ -221,12 +221,12 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     years: "년"
 
   play_level:
-#    completed_level: "Completed Level:"
-#    course: "Course:"
+    completed_level: "완료된 레벨:"
+    course: "코스:"
     done: "완료"
-#    next_level: "Next Level:"
-#    next_game: "Next game"
-#    show_menu: "Show game menu"
+    next_level: "다음 레벨:"
+    next_game: "다음 게임"
+    show_menu: "게임 매뉴 보이기"
     home: "홈" # Not used any more, will be removed soon.
     level: "레벨" # Like "Level: Dungeons of Kithgard"
     skip: "넘어가기"
@@ -256,40 +256,40 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     victory_saving_progress: "저장하기"
     victory_go_home: "홈으로"
     victory_review: "리뷰를 남겨주세요"
-#    victory_review_placeholder: "How was the level?"
+    victory_review_placeholder: "어떤 레벨입니까?"
     victory_hour_of_code_done: "정말 종료합니까?"
     victory_hour_of_code_done_yes: "네 내 Hour of Code™ 완료했습니다!"
     victory_experience_gained: "획득한 경험치"
     victory_gems_gained: "획득한 젬"
     victory_new_item: "새로운 아이템"
-#    victory_viking_code_school: "Holy smokes, that was a hard level you just beat! If you aren't already a software developer, you should be. You just got fast-tracked for acceptance with Viking Code School, where you can take your skills to the next level and become a professional web developer in 14 weeks."
+    victory_viking_code_school: "놀랍습니다, 당신은 그냥 이길 힘든 수준이었습니다! 이미 소프트웨어 개발자가 아닌 경우, 당신은 비이킹 코드 학교에서 빠르게 이해할것입니다, 당신이 다음 레벨에서 자신의 능력을 14주 동안 전문 웹 개발자가 될 수있는 곳입니다."
     victory_become_a_viking: "바이킹이 되세요"
     guide_title: "가이드"
-#    tome_cast_button_run: "Run"
-#    tome_cast_button_running: "Running"
-#    tome_cast_button_ran: "Ran"
-#    tome_submit_button: "Submit"
-#    tome_reload_method: "Reload original code for this method" # Title text for individual method reload button.
-#    tome_select_method: "Select a Method"
-#    tome_see_all_methods: "See all methods you can edit" # Title text for method list selector (shown when there are multiple programmable methods).
+    tome_cast_button_run: "실행"
+    tome_cast_button_running: "실행중"
+    tome_cast_button_ran: "실행됨"
+    tome_submit_button: "적용"
+    tome_reload_method: "이 방법에 대한 원래의 코드를 다시불러오기" # Title text for individual method reload button.
+    tome_select_method: "방법 선택"
+    tome_see_all_methods: "편집 할 수있는 모든 방법을 참조하십시오" # Title text for method list selector (shown when there are multiple programmable methods).
     tome_select_a_thang: "누군가를 선택하세요. "
     tome_available_spells: "사용 가능한 마법"
-#    tome_your_skills: "Your Skills"
-#    tome_current_method: "Current Method"
-#    code_saved: "Code Saved"
+    tome_your_skills: "당신의 스킬"
+    tome_current_method: "최근 방법"
+    code_saved: "코드가 저장됨"
     skip_tutorial: "넘기기 (esc)"
     keyboard_shortcuts: "단축키"
     loading_ready: "준비!"
-#    loading_start: "Start Level"
+    loading_start: "레벨 시작"
     problem_alert_title: "코드를 수정하세요"
     time_current: "현재:"
     time_total: "최대:"
-#    time_goto: "Go to:"
-#    non_user_code_problem_title: "Unable to Load Level"
-#    infinite_loop_title: "Infinite Loop Detected"
-#    infinite_loop_description: "The initial code to build the world never finished running. It's probably either really slow or has an infinite loop. Or there might be a bug. You can either try running this code again or reset the code to the default state. If that doesn't fix it, please let us know."
-#    check_dev_console: "You can also open the developer console to see what might be going wrong."
-#    check_dev_console_link: "(instructions)"
+    time_goto: "가기:"
+    non_user_code_problem_title: "레벨을 로드 할 수 없습니다"
+    infinite_loop_title: "무한 루프 감지"
+    infinite_loop_description: "세계를 구축하는 초기 코드는 결코 실행이 완료되지 않습니다. 아마도 하나의 정말 느리거나 또는 무한 루프가 있습니다. 혹은 버그일수있습니다. 당신은 다시 이 코드를 실행하려고하거나 기본 상태로 코드를 재설정 할 수 있습니다. 그게 해결되지 않으면, 저희에게 알려 주시기 바랍니다."
+    check_dev_console: "또한 잘못 갈 수를 알기 위해 개발자 콘솔을 열 수 있습니다."
+    check_dev_console_link: "(명령어)"
     infinite_loop_try_again: "다시 시도해보세요."
     infinite_loop_reset_level: "레벨 리셋"
     infinite_loop_comment_out: "내 코드를 일시적 주석처리하기"
@@ -297,7 +297,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     tip_scrub_shortcut: "Ctrl+[, Ctrl+] 를 이용해 실행 속도를 빠르게 할 수 있어요"
     tip_guide_exists: "화면 상단의 가이드를 클릭해보세요. 유용한 정보를 얻을 수 있습니다."
     tip_open_source: "코드 컴뱃은 100% 오픈 소스 기반입니다!"
-#    tip_tell_friends: "Enjoying CodeCombat? Tell your friends about us!"
+    tip_tell_friends: "코드 컴뱃을 즐기셨나요? 친구에게 알려주십시오"
     tip_beta_launch: "코드 컴뱃은 2013년 10월에 베타 서비스를 출시했습니다."
     tip_think_solution: "해결 방법을 고민해보세요, 문제를 고민하지 말구요"
 #    tip_theory_practice: "In theory, there is no difference between theory and practice. But in practice, there is. - Yogi Berra"
@@ -326,7 +326,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
 #    tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
 #    tip_superpower: "Coding is the closest thing we have to a superpower."
 #    tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
-#    tip_no_code: "No code is faster than no code."
+    tip_no_code: "코드가 없는것보다 빠른것은 없습니다."
     tip_code_never_lies: "코드는 절대로 거짓말을 하지 않는다. 주석은 가끔 하지만.  — Ron Jeffries"
 #    tip_reusable_software: "Before software can be reusable it first has to be usable."
 #    tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is ‘//’"
@@ -341,8 +341,8 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
 #    tip_recurse: "To iterate is human, to recurse divine. - L. Peter Deutsch"
 #    tip_free_your_mind: "You have to let it all go, Neo. Fear, doubt, and disbelief. Free your mind. - Morpheus"
 #    tip_strong_opponents: "Even the strongest of opponents always has a weakness. - Itachi Uchiha"
-#    tip_paper_and_pen: "Before you start coding, you can always plan with a sheet of paper and a pen."
-#    tip_solve_then_write: "First, solve the problem. Then, write the code. - John Johnson"
+    tip_paper_and_pen: "코딩을 하기전에, 당신은 항상 종이와 펜으로 계획을 지니고 있어야합니다."
+    tip_solve_then_write: "먼저, 문제를 해결하세요. 그러고, 코드를 쓰는겁니다. - John Johnson"
 
   game_menu:
     inventory_tab: "인벤토리"
@@ -355,24 +355,24 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     auth_tab: "가입하기"
     inventory_caption: "장비 장착"
     choose_hero_caption: "영웅 및 언어 선택 "
-#    save_load_caption: "... and view history"
+    save_load_caption: "... 그리고 기록보기"
     options_caption: "설정들을 바꾸기"
     guide_caption: "문서들과 팁들"
     multiplayer_caption: "친구들과 플레이 하세요!"
     auth_caption: "진행사항을 저장하세요"
 
   leaderboard:
-#    view_other_solutions: "View Leaderboards"
+    view_other_solutions: "리더보드 보기"
     scores: "점수"
     top_players: "상위 플레이어"
     day: "오늘"
     week: "이번 주"
-#    all: "All-Time"
-#    time: "Time"
-#    damage_taken: "Damage Taken"
-#    damage_dealt: "Damage Dealt"
-#    difficulty: "Difficulty"
-#    gold_collected: "Gold Collected"
+    all: "모든-시간"
+    time: "시간"
+    damage_taken: "데미지 정도"
+    damage_dealt: "죽음을 맞은 데미지"
+    difficulty: "난이도"
+    gold_collected: "수집된 골드"
 
   inventory:
     equipped_item: "장착됨"
@@ -391,33 +391,33 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     pile_gems: "gem 묶음"
     chest_gems: "gem 상자"
     purchasing: "구매중..."
-    declined: "Your card was declined"
+    declined: "귀하의 카드가 거부되었습니다"
     retrying: "서버에러, 다시 시도하세요."
     prompt_title: "gem 부족"
     prompt_body: "gem이 더 필요하신가요?"
-    prompt_button: "Enter Shop"
+    prompt_button: "샵 앤터"
     recovered: "gem 구매후 브라우져를 새로고침 하세요."
-    price: "x3500 / 한달"
+    price: "x{{gems}} / 한달"
 
-#  subscribe:
+  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
-#    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
-#    feature5: "Video tutorials"
-#    feature6: "Premium email support"
+    feature3: "80+ 보너스 레벨들"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
+    feature5: "영상 튜토리얼"
+    feature6: "프리미엄 이메일 지원"
 #    feature7: "Private <strong>Clans</strong>"
-#    free: "Free"
-#    month: "month"
+    free: "프리"
+    month: "달"
 #    must_be_logged: "You must be logged in first. Please create an account or log in from the menu above."
-#    subscribe_title: "Subscribe"
-#    unsubscribe: "Unsubscribe"
-#    confirm_unsubscribe: "Confirm Unsubscribe"
+    subscribe_title: "구독"
+    unsubscribe: "구독 해제"
+    confirm_unsubscribe: "구독 해제 확인"
 #    never_mind: "Never Mind, I Still Love You"
 #    thank_you_months_prefix: "Thank you for supporting us these last"
 #    thank_you_months_suffix: "months."
-#    thank_you: "Thank you for supporting CodeCombat."
+    thank_you: "CodeCombat을 도와주셔서 감사합니다."
 #    sorry_to_see_you_go: "Sorry to see you go! Please let us know what we could have done better."
 #    unsubscribe_feedback_placeholder: "O, what have we done?"
 #    parent_button: "Ask your parent"
@@ -496,29 +496,29 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
 #    level_to_unlock: "Level to unlock:" # Label for which level you have to beat to unlock a particular hero (click a locked hero in the store to see)
 #    restricted_to_certain_heroes: "Only certain heroes can play this level."
 
-#  skill_docs:
+  skill_docs:
 #    writable: "writable" # Hover over "attack" in Your Skills while playing a level to see most of this
 #    read_only: "read-only"
 #    action: "Action"
 #    spell: "Spell"
-#    action_name: "name"
+    action_name: "이름"
 #    action_cooldown: "Takes"
 #    action_specific_cooldown: "Cooldown"
-#    action_damage: "Damage"
-#    action_range: "Range"
+    action_damage: "데미지"
+    action_range: "사거리"
 #    action_radius: "Radius"
 #    action_duration: "Duration"
-#    example: "Example"
-#    ex: "ex" # Abbreviation of "example"
+    example: "예제"
+    ex: "예시" # Abbreviation of "example"
 #    current_value: "Current Value"
 #    default_value: "Default value"
 #    parameters: "Parameters"
-#    returns: "Returns"
+    returns: "뒤로가기"
 #    granted_by: "Granted by"
 
-#  save_load:
-#    granularity_saved_games: "Saved"
-#    granularity_change_history: "History"
+  save_load:
+    granularity_saved_games: "저장됨"
+    granularity_change_history: "기록"
 
   options:
 #    general_options: "General Options" # Check out the Options tab in the Game Menu while playing a level
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
     team: "팀"
-    george_title: "최고경영자" # {change}
-#    george_blurb: "Businesser"
-    scott_title: "프로그래머" # {change}
-#    scott_blurb: "Reasonable One"
     nick_title: "프로그래머" # {change}
 #    nick_blurb: "Motivation Guru"
-    michael_title: "프로그래머"
-#    michael_blurb: "Sys Admin"
     matt_title: "프로그래머" # {change}
     matt_blurb: "자전거 타는 사람"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "프로그래머" # {change}
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -588,20 +586,20 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
 #    more_info_2: "teachers forum"
 #    more_info_3: "is a good place to connect with fellow educators who are using CodeCombat."
 
-#  teachers_survey:
+  teachers_survey:
 #    title: "Teacher Survey"
 #    must_be_logged: "You must be logged in first. Please create an account or log in from the menu above."
 #    retrieving: "Retrieving information..."
 #    being_reviewed_1: "Your application for a free trial is being"
-#    being_reviewed_2: "reviewed."
+    being_reviewed_2: "검토됨."
 #    approved_1: "Your application for a free trial was"
 #    approved_2: "approved!"
 #    approved_4: "You can now enroll your students on the"
 #    approved_5: "courses"
-#    approved_6: "page."
+    approved_6: "페이지."
 #    denied_1: "Your application for a free trial has been"
-#    denied_2: "denied."
-#    contact_1: "Please contact"
+    denied_2: "거절됨."
+    contact_1: "연락해주세요."
 #    contact_2: "if you have further questions."
 #    description_1: "We offer free trials to teachers.  You will be given 2 free enrollments which can be used to enroll students in paid courses."
 #    description_1b: "You can find more information on our"
@@ -622,7 +620,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
   versions:
     save_version_title: "새로운 버전을 저장합니다"
     new_major_version: "신규 버전"
-#    submitting_patch: "Submitting Patch..."
+    submitting_patch: "패치 적용중..."
     cla_prefix: "변경사항을 저장하기 위해서는, 먼저 계약사항에 동의 하셔야 합니다."
     cla_url: "CLA"
     cla_suffix: "."
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     email_settings_url: "이메일 설정"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/lt.coffee b/app/locale/lt.coffee
index d68cdefea..c348495d1 100644
--- a/app/locale/lt.coffee
+++ b/app/locale/lt.coffee
@@ -1,23 +1,23 @@
 module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lithuanian", translation:
   home:
     slogan: "Išmok programuoti žaisdamas!"
-    no_ie: "CodeCombat su naršykle Internet Explorer 8 arba senesne. Atleiskite!" # Warning that only shows up in IE8 and older
-    no_mobile: "CodeCombat neskirtas mobiliems įrenginiams ir gali veikti neteisingai!" # Warning that shows up on mobile devices
+    no_ie: "Atsiprašome! CodeCombat neveikia su Internet Explorer 8 arba senesne naršyklės versija." # Warning that only shows up in IE8 and older
+    no_mobile: "CodeCombat neskirtas mobiliems įrenginiams ir gali neveikti!" # Warning that shows up on mobile devices
     play: "Žaisti" # The big play button that opens up the campaign view.
-#    play_campaign_version: "Play Campaign Version" # Shows up under big play button if you only play /courses
-#    old_browser: "Uh oh, your browser is too old to run CodeCombat. Sorry!" # Warning that shows up on really old Firefox/Chrome/Safari
-#    old_browser_suffix: "You can try anyway, but it probably won't work."
-#    ipad_browser: "Bad news: CodeCombat doesn't run on iPad in the browser. Good news: our native iPad app is awaiting Apple approval."
+    play_campaign_version: "Žaisti Kampanijos Versiją" # Shows up under big play button if you only play /courses
+    old_browser: "Atsiprašome! Jūsų naršyklės versija per sena, kad galėtumėt žaisti CodeCombat." # Warning that shows up on really old Firefox/Chrome/Safari
+    old_browser_suffix: "Galite bandyti, bet greičiausiai žaisti nepavyks."
+    ipad_browser: "Bloga žinia: CodeCombat neveikia iPad naršyklėje. Gera žinia: mūsų iPad žaidimo versija laukia Apple patvirtinimo."
     campaign: "Kampanija"
     for_beginners: "Naujokams"
 #    multiplayer: "Multiplayer" # Not currently shown on home page
-#    for_developers: "For Developers" # Not currently shown on home page.
+    for_developers: "Programuotojams" # Not currently shown on home page.
     or_ipad: "Arba atsisiųskite iPad'ui"
 
   nav:
     play: "Lygiai" # The top nav bar entry where players choose which levels to play
     community: "Bendruomenė"
-#    courses: "Courses"
+    courses: "Kursai"
     editor: "Redaktorius"
     blog: "Blog'as"
     forum: "Forumas"
@@ -43,17 +43,17 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
     page_not_found: "Puslapis nerastas"
 
   diplomat_suggestion:
-#    title: "Help translate CodeCombat!" # This shows up when a player switches to a non-English language using the language selector.
-#    sub_heading: "We need your language skills."
-    pitch_body: "We develop CodeCombat in English, but we already have players all over the world. Many of them want to play in Lithuanian but don't speak English, so if you can speak both, please consider signing up to be a Diplomat and help translate both the CodeCombat website and all the levels into Lithuanian."
-    missing_translations: "Until we can translate everything into Lithuanian, you'll see English when Lithuanian isn't available."
-#    learn_more: "Learn more about being a Diplomat"
-#    subscribe_as_diplomat: "Subscribe as a Diplomat"
+    title: "Padėkite išversti CodeCombat!" # This shows up when a player switches to a non-English language using the language selector.
+    sub_heading: "Mums reikia jūsų kalbos įgudžių."
+    pitch_body: "Mes kuriame CodeCombat Angliškai, bet mes turime žaidėjų visame pasaulyje. Daugelis jų norėtų žaisti Lietuvoje, tačiau nesupranta Angliškai. Jei tu gerai moki abi kalbas, prašom užsiregistruoti ir tapti Diplomatu. Taip galėsi padėti išversti CodeCombat interneto svetainę ir visus lygius į Lietuvių kalbą."
+    missing_translations: "Kol viską išversime į Lietuvių kalbą, dar neišverstą tekstą matysite užrašytą Anglų kalba."
+    learn_more: "Sužinoti daugiau apie tapimą Diplomatu"
+    subscribe_as_diplomat: "Noriu tapti Diplomatu"
 
   play:
     play_as: "Žaisti kaip" # Ladder page
-#    compete: "Compete!" # Course details page
-    spectate: "Stebėtojas" # Ladder page
+    compete: "Varžytis!" # Course details page
+    spectate: "Stebėti" # Ladder page
     players: "žaidėjai" # Hover over a level on /play
     hours_played: "valandų žaista" # Hover over a level on /play
     items: "Daiktai" # Tooltip on item shop button from /play
@@ -72,7 +72,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
     next: "Kitas" # Go from choose hero to choose inventory before playing a level
     change_hero: "Keisti Herojų" # Go back from choose inventory to choose hero
     buy_gems: "Pirkti Deimantus"
-#    subscription_required: "Subscription Required"
+    subscription_required: "Reikalingas patvirtinimas"
     anonymous: "Anoniminis Žaidėjas"
     level_difficulty: "Sudėtingumas: "
 #    play_classroom_version: "Play Classroom Version" # Choose a level in campaign version that you also can play in one of your courses
@@ -86,13 +86,13 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
 #    campaign_old_multiplayer: "(Deprecated) Old Multiplayer Arenas"
 #    campaign_old_multiplayer_description: "Relics of a more civilized age. No simulations are run for these older, hero-less multiplayer arenas."
 
-#  share_progress_modal:
-#    blurb: "You’re making great progress! Tell your parent how much you've learned with CodeCombat."
-#    email_invalid: "Email address invalid."
-#    form_blurb: "Enter your parent's email below and we’ll show them!"
-#    form_label: "Email Address"
-#    placeholder: "email address"
-#    title: "Excellent Work, Apprentice"
+  share_progress_modal:
+    blurb: "Tau puikiai sekasi! Parodyk tėvams kiek jau išmokai su CodeCombat."
+    email_invalid: "Neteisingas el. pašto adresas."
+    form_blurb: "Įvesk tėvų el. pašto adresą ir mes jiems parodysim!"
+    form_label: "El. pašto adresas"
+    placeholder: "el. pašto adresas"
+    title: "Puikiai padirbėta, Mokinį!"
 
   login:
     sign_up: "Sukurti paskyrą"
@@ -114,14 +114,14 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
     log_in: "prisijungti slaptažodžio pagalba"
     required: "PRieš tęsiant kelią turite prisijungti."
     login_switch: "Jau turite paskyrą?"
-#    school_name: "School Name and City"
-#    optional: "optional"
-#    school_name_placeholder: "Example High School, Springfield, IL"
+    school_name: "Mokyklos pavadinimas ir miestas"
+    optional: "nebūtinas"
+    school_name_placeholder: "Pavyzdžiui: Šiaulių Kolegija, Šiauliai"
 
-#  recover:
-#    recover_account_title: "Recover Account"
-#    send_password: "Send Recovery Password"
-#    recovery_sent: "Recovery email sent."
+  recover:
+    recover_account_title: "Susigrąžinti paskyrą"
+    send_password: "Siųsti susigrąžinimo slaptažodį"
+    recovery_sent: "Susigražinimo laiškas išsiųstas."
 
   items:
     primary: "Pagrindiniai"
@@ -148,50 +148,50 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
     actions: "Veiksmai"
     info: "Informacija"
     help: "Pagalba"
-#    watch: "Watch"
-#    unwatch: "Unwatch"
-#    submit_patch: "Submit Patch"
-#    submit_changes: "Submit Changes"
-#    save_changes: "Save Changes"
+    watch: "Žiūrėti"
+    unwatch: "Nebežiūrėti"
+    submit_patch: "Pateikti pataisymą"
+    submit_changes: "Išsaugoti pakeitimus"
+    save_changes: "Saugoti pakeitimus"
 
   general:
     and: "ir"
     name: "Vardas"
     date: "Data"
 #    body: "Body"
-#    version: "Version"
-#    pending: "Pending"
-#    accepted: "Accepted"
-#    rejected: "Rejected"
-#    withdrawn: "Withdrawn"
+    version: "Versija"
+    pending: "Laukiama"
+    accepted: "Priimtas"
+    rejected: "Atmestas"
+    withdrawn: "Pasitraukęs"
     accept: "Priimti"
     reject: "Atmesti"
-#    withdraw: "Withdraw"
-#    submitter: "Submitter"
-#    submitted: "Submitted"
-#    commit_msg: "Commit Message"
-#    version_history: "Version History"
-#    version_history_for: "Version History for: "
-#    select_changes: "Select two changes below to see the difference."
-#    undo_prefix: "Undo"
-#    undo_shortcut: "(Ctrl+Z)"
-#    redo_prefix: "Redo"
-#    redo_shortcut: "(Ctrl+Shift+Z)"
-#    play_preview: "Play preview of current level"
-#    result: "Result"
-#    results: "Results"
-#    description: "Description"
+    withdraw: "Pasitraukti"
+    submitter: "Teikėjas"
+    submitted: "Pateikta"
+    commit_msg: "Patvirtinti Žinutę"
+    version_history: "Versijų Istorija"
+    version_history_for: "Versijos istorija: "
+    select_changes: "Kad pamatytum skirtumą, pažymėk du pakeitimus žemiau."
+    undo_prefix: "Atgal"
+    undo_shortcut: "(Ctrl+Z)"
+    redo_prefix: "Pirmyn"
+    redo_shortcut: "(Ctrl+Shift+Z)"
+    play_preview: "Esamo žaidimo lygio peržiūra"
+    result: "Rezultatas"
+    results: "Rezultatai"
+    description: "Aprašymas"
     or: "arba"
-#    subject: "Subject"
-#    email: "Email"
+    subject: "Tema"
+    email: "El. paštas"
     password: "Slaptažodis"
-#    message: "Message"
+    message: "Žinutė"
     code: "Kodas"
 #    ladder: "Ladder"
-#    when: "When"
-#    opponent: "Opponent"
+    when: "Kai"
+    opponent: "Priešininkas"
     rank: "Rangas"
-#    score: "Score"
+    score: "Taškai"
     win: "Pergalė"
     loss: "Pralaimėjimas"
     tie: "Lygiosios"
@@ -221,10 +221,10 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
     years: "metai"
 
   play_level:
-#    completed_level: "Completed Level:"
-#    course: "Course:"
+    completed_level: "Įveiktas Lygis:"
+    course: "Kursas:"
     done: "Gerai"
-#    next_level: "Next Level:"
+    next_level: "Kitas Lygis:"
     next_game: "Kitas žaidimas"
     show_menu: "Parodyti žaidimo meniu"
 #    home: "Home" # Not used any more, will be removed soon.
@@ -242,34 +242,34 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
     failing: "Nesėkmingai"
     control_bar_multiplayer: "Žaidimas keliese"
     control_bar_join_game: "Prisijungti prie žaidimo"
-    reload: "Perkrauti"
-    reload_title: "Perkrauti visą kodą?"
+    reload: "Atstatyti"
+    reload_title: "Atstatyti visą kodą?"
     reload_really: "Ar tikrai norite atsukti visą lygį į pradžią?"
-    reload_confirm: "Perkrauti viską"
+    reload_confirm: "Atstatyti viską"
     victory: "Pergalė"
     victory_title_prefix: ""
     victory_title_suffix: " baigta"
     victory_sign_up: "Užsiregistruokite, kad išsaugotumėte pažangą"
     victory_sign_up_poke: "Norite išsaugoti savo kodą? Sukurkite paskyrą nemokamai!"
-#    victory_rate_the_level: "How fun was this level?"
+    victory_rate_the_level: "Ar patiko šis lygis?"
 #    victory_return_to_ladder: "Return to Ladder"
     victory_saving_progress: "Išsaugoma pažanga"
     victory_go_home: "Į Pradžią"
-#    victory_review: "Tell us more!"
+    victory_review: "Papasakok daugiau!"
     victory_review_placeholder: "Ar Jums patiko lygis?"
     victory_hour_of_code_done: "Ar pabaigėte?"
-#    victory_hour_of_code_done_yes: "Yes, I'm finished with my Hour of Code™!"
+    victory_hour_of_code_done_yes: "Taip, aš užbaigiau savo Kodo Valandą™!"
     victory_experience_gained: "Gauta XP"
     victory_gems_gained: "Gauta Deimantų"
     victory_new_item: "Naujas Daiktas"
-#    victory_viking_code_school: "Holy smokes, that was a hard level you just beat! If you aren't already a software developer, you should be. You just got fast-tracked for acceptance with Viking Code School, where you can take your skills to the next level and become a professional web developer in 14 weeks."
-#    victory_become_a_viking: "Become a Viking"
+    victory_viking_code_school: "Po paraliais, tu katik įveikei sunkujį lygį! Jei tu dar nesi programuotojas, tai bent turėtum būti. Tu katik paspartinai priėmimą į Vikingų Kodo Mokyklą, kur savo įgudžius gali perkelti į naują lygį ir, per 14 sąvaičių, gali tapti profesionaliu internetinių sistemų programuotoju."
+    victory_become_a_viking: "Tapk Vikingu"
     guide_title: "Vedlys"
     tome_cast_button_run: "Paleisti"
     tome_cast_button_running: "Leidžiama"
     tome_cast_button_ran: "Paleista"
     tome_submit_button: "Pateikti"
-#    tome_reload_method: "Reload original code for this method" # Title text for individual method reload button.
+    tome_reload_method: "Atstatyti originalų kodą šiam metodui" # Title text for individual method reload button.
     tome_select_method: "Pasirinkti Metodą"
     tome_see_all_methods: "Visi metodai, kuriuos galite keisti" # Title text for method list selector (shown when there are multiple programmable methods).
 #    tome_select_a_thang: "Select Someone for "
@@ -284,15 +284,15 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
     problem_alert_title: "Taisyti kodą"
     time_current: "Dabar:"
     time_total: "Max:"
-#    time_goto: "Go to:"
+    time_goto: "Eiti į:"
     non_user_code_problem_title: "Nepavyko pakrauti lygio"
     infinite_loop_title: "Pastebėtas begalinis ciklas!"
 #    infinite_loop_description: "The initial code to build the world never finished running. It's probably either really slow or has an infinite loop. Or there might be a bug. You can either try running this code again or reset the code to the default state. If that doesn't fix it, please let us know."
 #    check_dev_console: "You can also open the developer console to see what might be going wrong."
-#    check_dev_console_link: "(instructions)"
-#    infinite_loop_try_again: "Try Again"
-#    infinite_loop_reset_level: "Reset Level"
-#    infinite_loop_comment_out: "Comment Out My Code"
+    check_dev_console_link: "(instrukcijos)"
+    infinite_loop_try_again: "Bandyk dar kartą"
+    infinite_loop_reset_level: "Pradėti lygi išnaujo"
+    infinite_loop_comment_out: "Užkomentuoti mano kodą"
     tip_toggle_play: "Įjunkite ir išjunkite Pauzę spaudžiant Ctrl+P."
     tip_scrub_shortcut: "Naudokite Ctrl+[ ir Ctrl+] persukimui pirmyn ir atgal."
     tip_guide_exists: "Pasirinkite punktą Vedlys žaidimo meniu (puslapio viršuje), jame rasite naudingos informacijos."
@@ -301,14 +301,14 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
     tip_beta_launch: "CodeCombat Beta versija startavo 2013 m. spalio mėnesį."
     tip_think_solution: "Galvok ne apie problemą, o apie sprendimą."
     tip_theory_practice: "Teoriškai nėra skirtuma tarp teorijos ir praktikos. Praktiškai - yra. - Yogi Berra"
-#    tip_error_free: "There are two ways to write error-free programs; only the third one works. - Alan Perlis"
-#    tip_debugging_program: "If debugging is the process of removing bugs, then programming must be the process of putting them in. - Edsger W. Dijkstra"
+    tip_error_free: "Yra du būdai parašyti programą be klaidų; tik trečiasis suveikia. - Alan Perlis"
+    tip_debugging_program: "Jei derinimas yra procesas klaidoms šalinti, tai programavimas turėtų būti procesas klaidoms padaryti. - Edsger W. Dijkstra"
     tip_forums: "Aplankykite forumą ir parašykite mums Jūsų nuomonę!"
-#    tip_baby_coders: "In the future, even babies will be Archmages."
+    tip_baby_coders: "Ateityje ir kūdikiai bus Arkimagais."
 #    tip_morale_improves: "Loading will continue until morale improves."
 #    tip_all_species: "We believe in equal opportunities to learn programming for all species."
 #    tip_reticulating: "Reticulating spines."
-#    tip_harry: "Yer a Wizard, "
+    tip_harry: "Tu esi Burtininkas, "
 #    tip_great_responsibility: "With great coding skill comes great debug responsibility."
 #    tip_munchkin: "If you don't eat your vegetables, a munchkin will come after you while you're asleep."
 #    tip_binary: "There are only 10 types of people in the world: those who understand binary, and those who don't."
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
     prompt_body: "Ar norite gauti daugiau?"
     prompt_button: "Į Parduotuvę"
     recovered: "Atstatyta deimantų pirkimo operacija. Prašome pakraukite puslapį iš naujo."
-    price: "x3500 / mėn"
+    price: "x{{gems}} / mėn"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -463,7 +463,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
     programming_language: "Programavimo kalba"
     programming_language_description: "Kokią programavimo kalbą norėtum naudoti?"
     default: "Numatytasis"
-#    experimental: "Experimental"
+    experimental: "Eksperimentinis"
     python_blurb: "Paprasta bet galinga. Puikiai tinka ir naujokams ir ekspertams."
     javascript_blurb: "WWW tinklo kalba. (Nepainiokite su Java.)"
     coffeescript_blurb: "JavaScript su malonesne sintakse."
@@ -516,9 +516,9 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
 #    returns: "Returns"
 #    granted_by: "Granted by"
 
-#  save_load:
-#    granularity_saved_games: "Saved"
-#    granularity_change_history: "History"
+  save_load:
+    granularity_saved_games: "Išsaugotas"
+    granularity_change_history: "Istorija"
 
   options:
     general_options: "Bendri nustatymai" # Check out the Options tab in the Game Menu while playing a level
@@ -552,142 +552,140 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
-#  teachers:
-#    who_for_title: "Who is CodeCombat for?"
-#    who_for_1: "We recommend CodeCombat for students aged 9 and up. No prior programming experience is needed. We've designed CodeCombat to appeal to both boys and girls."
-#    who_for_2: "Our Courses system allows teachers to set up classrooms, track progress and assign additional content to students through a dedicated interface."
-#    more_info_title: "Where can I find more information?"
-#    more_info_1: "Our"
-#    more_info_2: "teachers forum"
-#    more_info_3: "is a good place to connect with fellow educators who are using CodeCombat."
+  teachers:
+    who_for_title: "Kam skirtas CodeCombat?"
+    who_for_1: "Mes rekomenduojame CodeCombat mokiniams nuo 9-erių metų. Nereikia turėti jokios programavimo patirties. Mes sukūrėme CodeCombat taip, kad patiktų ir berniukams ir mergaitėms."
+    who_for_2: "Mūsų Kursų sistema, suteikia galimybę pasiruošti pamokų užduotims, stebėti mokinių pasiekimus ir priskirti papildomą turinį mokiniams, per patogią sąsają."
+    more_info_title: "Kur galėčiau rasti daugiau informacijos?"
+    more_info_1: "Mūsų"
+    more_info_2: "mokytojų forumas"
+    more_info_3: "patogi vieta susisiekti su kolegomis mokytojais kurie naudoja CodeCombat."
 
-#  teachers_survey:
-#    title: "Teacher Survey"
-#    must_be_logged: "You must be logged in first. Please create an account or log in from the menu above."
-#    retrieving: "Retrieving information..."
-#    being_reviewed_1: "Your application for a free trial is being"
-#    being_reviewed_2: "reviewed."
-#    approved_1: "Your application for a free trial was"
-#    approved_2: "approved!"
-#    approved_4: "You can now enroll your students on the"
-#    approved_5: "courses"
-#    approved_6: "page."
-#    denied_1: "Your application for a free trial has been"
-#    denied_2: "denied."
-#    contact_1: "Please contact"
-#    contact_2: "if you have further questions."
-#    description_1: "We offer free trials to teachers.  You will be given 2 free enrollments which can be used to enroll students in paid courses."
-#    description_1b: "You can find more information on our"
-#    description_2: "teachers"
-#    description_3: "page."
-#    description_4: "Please fill out this quick survey and we’ll email you setup instructions."
-#    email: "Email Address"
-#    school: "Name of School"
-#    location: "Name of City"
-#    age_students: "How old are your students?"
-#    under: "Under"
-#    other: "Other:"
-#    amount_students: "How many students do you teach?"
-#    hear_about: "How did you hear about CodeCombat?"
-#    fill_fields: "Please fill out all fields."
-#    thanks: "Thanks! We'll send you setup instructions shortly."
+  teachers_survey:
+    title: "Mokytojo Apklausa"
+    must_be_logged: "Turite būti prisijungę. Prašom susikurti paskyrą arba prisijungti viršutinėje meniu juostoje."
+    retrieving: "Renkama informacija..."
+    being_reviewed_1: "Jūsų prašymas nemokamai bandomajai versijai gauti"
+    being_reviewed_2: "peržiūrimas."
+    approved_1: "Jūsų prašymas nemokamai bandomajai versijai gauti"
+    approved_2: "patvirtintas!"
+    approved_4: "Dabar galite nukreipti savo mokinius į"
+    approved_5: "kursų"
+    approved_6: "puslapį."
+    denied_1: "Jūsų prašymas nemokamai bandomajai versijai gauti"
+    denied_2: "atmestas."
+    contact_1: "Prašome susisiekti"
+    contact_2: "jei turite daugiau klausimų."
+    description_1: "Mokytojams mes siūlome, nemokamai išbandyti bandomają versiją.  Jūs gausite 2 nemokamus pakvietimus, kuriuos galite panaudoti savo mokiniams mokamuose kursuose."
+    description_1b: "Daugiau informacijos rasite mūsų"
+    description_2: "mokytojų"
+    description_3: "puslapyje."
+    description_4: "Prašome užpildyti šią trumpą apklausos formą ir mes atsiųsime paruošimo instrukcijas el. paštu."
+    email: "El. pašto adresas"
+    school: "Mokyklos pavadinimas"
+    location: "Miestas"
+    age_students: "Kokio amžiaus jūsų mokiniai?"
+    under: "Mažiau nei"
+    other: "Kita:"
+    amount_students: "Kiek mokinių mokote?"
+    hear_about: "Iš kur sužinojote apie CodeCombat?"
+    fill_fields: "Prašome užpildyti visus laukus."
+    thanks: "Dėkojame! Netrukus atsiųsime paruošimo instrukcijas."
 
-#  versions:
-#    save_version_title: "Save New Version"
-#    new_major_version: "New Major Version"
-#    submitting_patch: "Submitting Patch..."
-#    cla_prefix: "To save changes, first you must agree to our"
-#    cla_url: "CLA"
-#    cla_suffix: "."
-#    cla_agree: "I AGREE"
-#    owner_approve: "An owner will need to approve it before your changes will become visible."
+  versions:
+    save_version_title: "Išsaugoti Naują Versiją"
+    new_major_version: "Nauja Pagrindinė Versija"
+    submitting_patch: "Pateikiamas Pataisymas..."
+    cla_prefix: "Kad išsaugoti pakeitimus, turite sutikti su mūsų"
+    cla_url: "PLS" # In Lithuanian language full translation (Pagalbininko Licensinė Sutartis - PLS). If no translation needed here, just remove changes :)
+    cla_suffix: "."
+    cla_agree: "AŠ SUTINKU"
+    owner_approve: "Sąvininkas pirmiausiai turi patvirtinti, kad jūsų pakeitimai būtų matomi."
 
-#  contact:
-#    contact_us: "Contact CodeCombat"
-#    welcome: "Good to hear from you! Use this form to send us email. "
-#    forum_prefix: "For anything public, please try "
-#    forum_page: "our forum"
-#    forum_suffix: " instead."
-#    faq_prefix: "There's also a"
-#    faq: "FAQ"
-#    subscribe_prefix: "If you need help figuring out a level, please"
-#    subscribe: "buy a CodeCombat subscription"
-#    subscribe_suffix: "and we'll be happy to help you with your code."
-#    subscriber_support: "Since you're a CodeCombat subscriber, your email will get our priority support."
-#    screenshot_included: "Screenshot included."
-#    where_reply: "Where should we reply?"
-#    send: "Send Feedback"
+  contact:
+    contact_us: "Susisiekti su CodeCombat"
+    welcome: "Maloniai jus išklausysime! Naudokitės šia forma, kad išsiųstumėte mus elektroninį laišką."
+    forum_prefix: "Norint pasisakyti viešai, naudokitės "
+    forum_page: "mūsų forumu."
+    forum_suffix: ""
+    faq_prefix: "Taip pat turime vietą"
+    faq: "DUK"
+    subscribe_prefix: "Jei reikalinga pagalbos įveikiant lygį, prašome"
+    subscribe: "įsigyti CodeCombat abonementą"
+    subscribe_suffix: "ir męs mielai jums padėsime."
+    subscriber_support: "Kadangi turite CodeCombat abonementą, jūsų elektroniniai laiškai mums tampa įpatingai svarbūs."
+    screenshot_included: "Ekrano kopija pridėta."
+    where_reply: "Kur mums atsakyti?"
+    send: "Siųsti užklausą"
 
-#  account_settings:
-#    title: "Account Settings"
-#    not_logged_in: "Log in or create an account to change your settings."
-#    autosave: "Changes Save Automatically"
-#    me_tab: "Me"
-#    picture_tab: "Picture"
-#    delete_account_tab: "Delete Your Account"
-#    wrong_email: "Wrong Email"
-#    wrong_password: "Wrong Password"
-#    upload_picture: "Upload a picture"
-#    delete_this_account: "Delete this account permanently"
-#    reset_progress_tab: "Reset All Progress"
-#    reset_your_progress: "Clear all your progress and start over"
-#    god_mode: "God Mode"
-#    password_tab: "Password"
-#    emails_tab: "Emails"
-#    admin: "Admin"
-#    manage_subscription: "Click here to manage your subscription."
-#    new_password: "New Password"
-#    new_password_verify: "Verify"
-#    type_in_email: "Type in your email to confirm account deletion."
-#    type_in_email_progress: "Type in your email to confirm deleting your progress."
-#    type_in_password: "Also, type in your password."
-#    email_subscriptions: "Email Subscriptions"
-#    email_subscriptions_none: "No Email Subscriptions."
-#    email_announcements: "Announcements"
-#    email_announcements_description: "Get emails on the latest news and developments at CodeCombat."
-#    email_notifications: "Notifications"
-#    email_notifications_summary: "Controls for personalized, automatic email notifications related to your CodeCombat activity."
-#    email_any_notes: "Any Notifications"
-#    email_any_notes_description: "Disable to stop all activity notification emails."
-#    email_news: "News"
-#    email_recruit_notes: "Job Opportunities"
-#    email_recruit_notes_description: "If you play really well, we may contact you about getting you a (better) job."
-#    contributor_emails: "Contributor Class Emails"
-#    contribute_prefix: "We're looking for people to join our party! Check out the "
-#    contribute_page: "contribute page"
-#    contribute_suffix: " to find out more."
-#    email_toggle: "Toggle All"
-#    error_saving: "Error Saving"
-#    saved: "Changes Saved"
-#    password_mismatch: "Password does not match."
-#    password_repeat: "Please repeat your password."
+  account_settings:
+    title: "Paskyros Nustatymai"
+    not_logged_in: "Norint pakeisti paskyros nustatymus turite prisijungti arba susikurti paskyrą."
+    autosave: "Pakeitimai Išsaugomi Automatiškai"
+    me_tab: "Aš"
+    picture_tab: "Nuotrauka"
+    delete_account_tab: "Pašalinti Mano Paskyrą"
+    wrong_email: "Neteisingas el. pašto adresas"
+    wrong_password: "Neteisingas slaptažodis"
+    upload_picture: "Įkelti nuotrauką"
+    delete_this_account: "Tuoj pat pašalinti šią paskyrą"
+    reset_progress_tab: "Atstatyti Viską Išnaujo"
+    reset_your_progress: "Viską išvalyti ir pradėti išnaujo"
+    god_mode: "God Mode(Dievo Režimas)"
+    password_tab: "Slaptažodis"
+    emails_tab: "Pranešimai"
+    admin: "Administratorius"
+    manage_subscription: "Abonemento valdymas, spauskite čia."
+    new_password: "Naujas slaptažodis"
+    new_password_verify: "Patvirtinimas"
+    type_in_email: "Paskyros pašalinimo patvirtinimui, įveskite el. pašto adresą."
+    type_in_email_progress: "Norint pradėti išnaujo įveskite el. pašto adresą."
+    type_in_password: "Taip pat, įveskite slaptažodį."
+    email_subscriptions: "El. pašto abonementai"
+    email_subscriptions_none: "Nėra el. pašto abonementų."
+    email_announcements: "Skelbimai"
+    email_announcements_description: "Gauk svarbiausią informaciją apie naujienas ir projekto vystymo eigą tiesiai iš CodeCombat."
+    email_notifications: "Pranešimai"
+    email_notifications_summary: "Automatinių pranešimų, susijusių su CodeCombat veikla, valdymas."
+    email_any_notes: "Visi pranešimai"
+    email_any_notes_description: "Nuimkite varnelę, kad nebegautumėte jokių pranešimų."
+    email_news: "Naujienos"
+    email_recruit_notes: "Darbo Pasiūlymai"
+    email_recruit_notes_description: "Jei viską atliksite tikrai gerai, mes galime pasiūlyti (geresnį) darbą."
+    contributor_emails: "Pranešimai Pagalbininkų Kategorijai"
+    contribute_prefix: "Mes ieškome norinčių prisijungti prie mūsų grupės! Ieškantiems daugiau informacijos siūlome apsilankykti "
+    contribute_page: "pagalbininkų puslapyje."
+    contribute_suffix: ""
+    email_toggle: "Perjungti visus"
+    error_saving: "Klaida Išsaugant"
+    saved: "Pakeitimai Išsaugoti"
+    password_mismatch: "Slaptažodžiai nesutampa."
+    password_repeat: "Pakartokite slaptažodį."
 
   keyboard_shortcuts:
     keyboard_shortcuts: "Mygtukai"
@@ -729,65 +727,65 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
 #    social_hipchat: "Chat with us in the public CodeCombat Slack channel"
 #    contribute_to_the_project: "Contribute to the project"
 
-#  clans:
-#    clan: "Clan"
-#    clans: "Clans"
-#    new_name: "New clan name"
-#    new_description: "New clan description"
-#    make_private: "Make clan private"
-#    subs_only: "subscribers only"
-#    create_clan: "Create New Clan"
-#    private_preview: "Preview"
-#    private_clans: "Private Clans"
-#    public_clans: "Public Clans"
-#    my_clans: "My Clans"
-#    clan_name: "Clan Name"
-#    name: "Name"
-#    chieftain: "Chieftain"
-#    type: "Type"
-#    edit_clan_name: "Edit Clan Name"
-#    edit_clan_description: "Edit Clan Description"
-#    edit_name: "edit name"
-#    edit_description: "edit description"
-#    private: "(private)"
-#    summary: "Summary"
-#    average_level: "Average Level"
-#    average_achievements: "Average Achievements"
-#    delete_clan: "Delete Clan"
-#    leave_clan: "Leave Clan"
-#    join_clan: "Join Clan"
-#    invite_1: "Invite:"
-#    invite_2: "*Invite players to this Clan by sending them this link."
-#    members: "Members"
-#    progress: "Progress"
-#    not_started_1: "not started"
-#    started_1: "started"
-#    complete_1: "complete"
-#    exp_levels: "Expand levels"
-#    rem_hero: "Remove Hero"
-#    status: "Status"
-#    complete_2: "Complete"
-#    started_2: "Started"
-#    not_started_2: "Not Started"
-#    view_solution: "Click to view solution."
-#    view_attempt: "Click to view attempt."
-#    latest_achievement: "Latest Achievement"
-#    playtime: "Playtime"
-#    last_played: "Last played"
-#    leagues_explanation: "Play in a league against other clan members in these multiplayer arena instances."
-#    track_concepts1: "Track concepts"
-#    track_concepts2a: "learned by each student"
-#    track_concepts2b: "learned by each member"
-#    track_concepts3a: "Track levels completed for each student"
-#    track_concepts3b: "Track levels completed for each member"
-#    track_concepts4a: "See your students'"
-#    track_concepts4b: "See your members'"
-#    track_concepts5: "solutions"
-#    track_concepts6a: "Sort students by name or progress"
-#    track_concepts6b: "Sort members by name or progress"
-#    track_concepts7: "Requires invitation"
-#    track_concepts8: "to join"
-#    private_require_sub: "Private clans require a subscription to create or join."
+  clans:
+    clan: "Klanas"
+    clans: "Klanai"
+    new_name: "Klano pavadinimas"
+    new_description: "Klano aprašymas"
+    make_private: "Privatus klanas"
+    subs_only: "tik abonentams"
+    create_clan: "Sukurti Klaną"
+    private_preview: "Peržiūra"
+    private_clans: "Privatūs Klanai"
+    public_clans: "Vieši Klanai"
+    my_clans: "Mano Klanai"
+    clan_name: "Klano Pavadinimas"
+    name: "Vardas"
+    chieftain: "Vadas"
+    type: "Tipas"
+    edit_clan_name: "Keisti Klano Pavadinimą"
+    edit_clan_description: "Keisti Klano Aprašymą"
+    edit_name: "keisti pavadinimą"
+    edit_description: "keisti aprašymą"
+    private: "(privatus)"
+    summary: "Suvestinė"
+    average_level: "Lygių vidurkis"
+    average_achievements: "Pasiekimų vidurkis"
+    delete_clan: "Pašalinti klaną"
+    leave_clan: "Išeiti iš klano"
+    join_clan: "Prisijungti prie klano"
+    invite_1: "Pakvietimas:"
+    invite_2: "*Kvieskite žaidėjus į klaną nusiųsdami šią nuorodą."
+    members: "Nariai"
+    progress: "Pažanga"
+    not_started_1: "nepradėta"
+    started_1: "pradėta"
+    complete_1: "pabaigta"
+    exp_levels: "Išplėsti lygius"
+    rem_hero: "Pašalinti Herojų"
+    status: "Būsena"
+    complete_2: "Pabaigta"
+    started_2: "Pradėta"
+    not_started_2: "Nepradėta"
+    view_solution: "Peržiūrėti sprendimą."
+    view_attempt: "Peržiūrėti bandymą."
+    latest_achievement: "Naujausias Pasiekimas"
+    playtime: "Viso žaista"
+    last_played: "Paskutinį kartą žaista"
+    leagues_explanation: "Pasirink lygą ir varžykis su kitų klanų nariais."
+    track_concepts1: "Sekite "
+    track_concepts2a: "kitų mokinių idėjas"
+    track_concepts2b: "kitų narių idėjas"
+    track_concepts3a: "Stebėkite kitų mokinių įveiktus lygius"
+    track_concepts3b: "Stebėkite kitų narių įveiktus lygius"
+    track_concepts4a: "Peržiūrėkite mokinių"
+    track_concepts4b: "Peržiūrėkite narių"
+    track_concepts5: "sprendimus"
+    track_concepts6a: "Išrikiuokite mokinius pagal vardą arba pažangą"
+    track_concepts6b: "Išrikiuokite narius pagal vardą arba pažangą"
+    track_concepts7: "Norint tapti nariu"
+    track_concepts8: "reikalingas kvietimas"
+    private_require_sub: "Norint sukurti privatų ar prisijungti prie privataus klano, reikalingas abonementas."
 
 #  courses:
 #    course: "Course"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1017,22 +1015,22 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
   classes:
     archmage_title: "Arkimagas"
     archmage_title_description: "(Koderis)"
-#    archmage_summary: "If you are a developer interested in coding educational games, become an archmage to help us build CodeCombat!"
-    artisan_title: "Menininkas"
+    archmage_summary: "Jei tu esi programuotojas ir norėtum programuoti mokomuosius žiadimus, tapk Arkimagu ir padėk mums kurti CodeCombat!"
+    artisan_title: "Meistras"
     artisan_title_description: "(Lygių architektas)"
-#    artisan_summary: "Build and share levels for you and your friends to play. Become an Artisan to learn the art of teaching others to program."
+    artisan_summary: "Kurk ir dalinkis lygiais su savo draugais. Tapk Meistru ir mokykis meno mokyti kitus programuoti."
     adventurer_title: "Nuotykių ieškotojas"
     adventurer_title_description: "(Lygių bandytojas)"
-#    adventurer_summary: "Get our new levels (even our subscriber content) for free one week early and help us work out bugs before our public release."
+    adventurer_summary: "Gauk naujausius lygius nemokamai. Net savaitę anksčiau ir padėk mums ištaisyti klaidas prieš oficialų pristatymą."
     scribe_title: "Raštininkas"
     scribe_title_description: "(Straipsnių redaktorius)"
-#    scribe_summary: "Good code needs good documentation. Write, edit, and improve the docs read by millions of players across the globe."
+    scribe_summary: "Geram kodui reikia geros dokumentacijos. Kurk, redaguok ir tobulink dokumentus, kuriuos skaito milijonai žaidėjų visame pasaulyje."
     diplomat_title: "Diplomatas"
     diplomat_title_description: "(Vertėjas)"
-#    diplomat_summary: "CodeCombat is localized in 45+ languages by our Diplomats. Help us out and contribute translations."
+    diplomat_summary: "Diplomatų dėka CodeCombat yra verčiamas į daugiau kaip 45 kalbas. Tu gali mums padėti tapdamas vertėju."
     ambassador_title: "Ambasadorius"
     ambassador_title_description: "(Palaikymas)"
-#    ambassador_summary: "Tame our forum users and provide direction for those with questions. Our ambassadors represent CodeCombat to the world."
+    ambassador_summary: "Nuramink mūsų forumo naudotojus ir suteik pagalbą tiems kas turi klausimų. Mūsų Ambasadoriai atstovauja CodeCombat visam pasauliui."
 
 #  editor:
 #    main_title: "CodeCombat Editors"
@@ -1122,12 +1120,12 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
 #    add_system_title: "Add Systems to Level"
 #    done_adding: "Done Adding"
 
-#  article:
-#    edit_btn_preview: "Preview"
-#    edit_article_title: "Edit Article"
+  article:
+    edit_btn_preview: "Peržiūra"
+    edit_article_title: "Redaguoti straipsnį"
 
-#  polls:
-#    priority: "Priority"
+  polls:
+    priority: "Prioritetas"
 
 #  contribute:
 #    page_title: "Contributing"
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/mk-MK.coffee b/app/locale/mk-MK.coffee
index 14a12f73d..a889b6e9a 100644
--- a/app/locale/mk-MK.coffee
+++ b/app/locale/mk-MK.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Македонски", englishDescription:
     prompt_body: "Дали сакаш да земеш повеќе?"
     prompt_button: "Влези во продавницата"
     recovered: "Претходното купување на скапоцени камења е вратено од загуба. Те молам 'освежи' ја страната."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
   subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Македонски", englishDescription:
     press_paragraph_1_link: "пакет за печат"
     press_paragraph_1_suffix: ". Сите логоа и слики можат да бидат користени без да не контактираш директно."
     team: "Тим"
-    george_title: "(CEO) Извршен директор" # {change}
-    george_blurb: "Бизнисер"
-    scott_title: "Програмер" # {change}
-    scott_blurb: "Оној разумниот"
     nick_title: "Програмер" # {change}
     nick_blurb: "Мотивациски гуру"
-    michael_title: "Програмер"
-    michael_blurb: "Систем администратор"
     matt_title: "Програмер" # {change}
     matt_blurb: "Бициклист"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Програмер" # {change}
+    scott_blurb: "Оној разумниот"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Македонски", englishDescription:
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Македонски", englishDescription:
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/ms.coffee b/app/locale/ms.coffee
index 245b294ba..7e404187e 100644
--- a/app/locale/ms.coffee
+++ b/app/locale/ms.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Hakcipta dan Pemelesenan"
     contributor_title: "Persetujuan Lesen Penyumbang"
     contributor_description_prefix: "Kesemua sumbangan, termasuk di dalam laman dan di dalam repositiri GitHub, tertakluk kepada"
diff --git a/app/locale/my.coffee b/app/locale/my.coffee
index 4085985f1..1b27655f2 100644
--- a/app/locale/my.coffee
+++ b/app/locale/my.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "မြန်မာစကား", englishDes
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "မြန်မာစကား", englishDes
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "မြန်မာစကား", englishDes
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "မြန်မာစကား", englishDes
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/nb.coffee b/app/locale/nb.coffee
index 3668ab100..9e526b693 100644
--- a/app/locale/nb.coffee
+++ b/app/locale/nb.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
     prompt_body: "Har du lyst på flere?"
     prompt_button: "Til Butikken"
     recovered: "Tidligere juvelkjøp hentet. Vennligst last siden på nytt"
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
   subscribe:
     comparison_blurb: "Spiss dine kunnskaper med et CodeCombat abonnement!"
     feature1: "60+ grunnleggende brett fordelt på 4 verdener" # {change}
     feature2: "7 kraftfulle <strong>nye helter</strong> med unike ferdigheter!" # {change}
     feature3: "30+ bonusbrett" # {change}
-    feature4: "<strong>3500 bonusjuveler</strong> hver måned!"
+    feature4: "<strong>{{gems}} bonusjuveler</strong> hver måned!"
     feature5: "Videoveiledninger"
     feature6: "Premium e-poststøtte"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
     press_paragraph_1_link: "pressepakke"
     press_paragraph_1_suffix: ". Alle logoer og bilder kan brukes uten å kontakte oss direkte."
     team: "Teamet"
-    george_title: "Adm.dir." # {change}
-    george_blurb: "Business-nisse"
-    scott_title: "Programmerer" # {change}
-    scott_blurb: "Den fornuftige"
     nick_title: "Programmerer" # {change}
     nick_blurb: "Motivasjonsguru"
-    michael_title: "Programmerer"
-    michael_blurb: "Systemadministrator"
     matt_title: "Programmerer" # {change}
     matt_blurb: "Syklist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Programmerer" # {change}
+    scott_blurb: "Den fornuftige"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
     email_settings_url: "epost-innstillingene dine"
     email_description_suffix: "eller via linker i epostene vi sender til deg, kan du endre hvilke eposter du ønsker å motta og enkelt avslutte abonnementet når som helst."
     cost_title: "Pris"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Kopirettigheter og lisenser"
     contributor_title: "Lisensavtale for bidragsytere"
     contributor_description_prefix: "Alle bidrag, både gjort gjennom brukergrensesnittet og i kodelageret på GitHub, er underlagt vår"
diff --git a/app/locale/nl-BE.coffee b/app/locale/nl-BE.coffee
index 535da218b..d775ba6f3 100644
--- a/app/locale/nl-BE.coffee
+++ b/app/locale/nl-BE.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
     prompt_body: "Wil je er meer verkrijgen?"
     prompt_button: "Ga binnen in de winkel"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
   subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
     email_settings_url: "jouw e-mail instellingen"
     email_description_suffix: "of via urls in de emails die wij verzenden, kan je jouw instellingen wijzigen en ten allen tijden uitschrijven."
     cost_title: "Kosten"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Auteursrechten en licenties"
     contributor_title: "Licentieovereenkomst voor vrijwilligers"
     contributor_description_prefix: "Alle bijdragen, zowel op de website als op onze GitHub repository, vallen onder onze"
diff --git a/app/locale/nl-NL.coffee b/app/locale/nl-NL.coffee
index 840003ade..976141b5e 100644
--- a/app/locale/nl-NL.coffee
+++ b/app/locale/nl-NL.coffee
@@ -52,7 +52,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
 
   play:
     play_as: "Speel als " # Ladder page
-    compete: "Compleet!" # Course details page //in English it says 'complete', so translated that instead.
+    compete: "Compleet!" # Course details page
     spectate: "Toeschouwen" # Ladder page
     players: "Spelers" # Hover over a level on /play
     hours_played: "Speeltijd" # Hover over a level on /play
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
     prompt_body: "Wil je meer krijgen?"
     prompt_button: "Naar de winkel"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
   subscribe:
     comparison_blurb: "Verbeter je vaardigheden met een abonement op CodeCombat!"
     feature1: "meer dan 110+ basislevels over 4 werelden"
     feature2: "10 sterke <strong>nieuwe helden</strong> met unieke vaardigheden!"
     feature3: "70+ bonuslevels" # {change}
-    feature4: "<strong>3500 bonus edelstenen</strong> elke maand!"
+    feature4: "<strong>{{gems}} bonus edelstenen</strong> elke maand!"
     feature5: "Video cursussen"
     feature6: "Hoogwaardige e-mail ondersteuning"
     feature7: "Besloten <strong>Clans</strong>"
@@ -484,8 +484,8 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
     blocks: "Blokkeert" # As in "this shield blocks this much damage"
 #    backstab: "Backstab" # As in "this dagger does this much backstab damage"
     skills: "Vaardigheden"
-#   attack_1: "brengt [x damge] toe" # In Dutch we say 'brings [x damge] to...' Alternative: 'veroorzaakt [x damage] (causes [x damage])
-#    attack_2: "of listed" # what is the context?
+#    attack_1: "Deals"
+#    attack_2: "of listed"
     attack_3: "Wapen schade."
 #    health_1: "Gains"
 #    health_2: "of listed"
@@ -502,8 +502,8 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
     action: "Actie"
     spell: "toverspreuk"
     action_name: "naam"
-    action_cooldown: "Duurt" # As in duration
-    action_specific_cooldown: "Afkoeling" # This literally means cooldown/coolingdown. If it needs to include a time element, it should be 'afkoeltijd'.
+    action_cooldown: "Duurt"
+    action_specific_cooldown: "Afkoeling"
     action_damage: "Schade"
     action_range: "Bereik"
     action_radius: "Straal"
@@ -513,7 +513,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
     current_value: "Huidige waarde"
     default_value: "Standaard waarde"
     parameters: "Parameters"
-#    returns: "Returns" 
+#    returns: "Returns"
     granted_by: "Verleend door"
 
   save_load:
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
     press_paragraph_1_link: "journalistieke pakket"
     press_paragraph_1_suffix: ". Alle logo's en afbeeldingen mogen worden gebruikt zonder direct contact met ons op te nemen."
     team: "Team"
-    george_title: "CEO" # {change}
-    george_blurb: "Zaken type"
-    scott_title: "Programmeur" # {change}
-    scott_blurb: "de Redelijke"
     nick_title: "Programmeur" # {change}
     nick_blurb: "Motivatie Goeroe"
-    michael_title: "Programmeur"
-    michael_blurb: "Systeembeheerder"
     matt_title: "Programmeur" # {change}
     matt_blurb: "Fietser"
-    cat_title: "Hoofd Ambachtsman"
+    cat_title: "Hoofd Ambachtsman" # {change}
 #    cat_blurb: "Airbender"
-    josh_title: "Game Designer" # In Dutch people would use the english term.
-    josh_blurb: "Vloer Is Lava"
-    jose_title: "Muziek"
-#    jose_blurb: "Taking Off"
-    retrostyle_title: "Illustraties"
-    retrostyle_blurb: "RetroStijl Games"
-    rob_title: "Compiler Ontwerper"
+    scott_title: "Programmeur" # {change}
+    scott_blurb: "de Redelijke"
+    maka_title: "Klanten Ombudsman"
+    maka_blurb: "VerhalenVerteller"
+    rob_title: "Compiler Ontwerper" # {change}
     rob_blurb: "Programmeert dingen en spullen"
     josh_c_title: "Game Designer"
     josh_c_blurb: "Ontwikkeld games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "Game Designer"
+    josh_blurb: "Vloer Is Lava"
+    retrostyle_title: "Illustraties"
+    retrostyle_blurb: "RetroStijl Games"
+    jose_title: "Muziek"
+#    jose_blurb: "Taking Off"
     carlos_title: "Regio Manager, Brazilië"
     carlos_blurb: "Selderij Man"
-    maka_title: "Klanten Ombudsman"
-    maka_blurb: "VerhalenVerteller"
 
   teachers:
     who_for_title: "Voor wie is CodeCombat?"
@@ -664,14 +662,14 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
     admin: "Beheerder"
     manage_subscription: "Klik hier om je abonnement te beheren."
     new_password: "Nieuw Wachtwoord"
-    new_password_verify: "Controleer" # Controleer means 'check'. Verifieer also means check, but it is very formal. Children wouldn't know what it means.
+    new_password_verify: "Controleer"
     type_in_email: "Typ je e-mail in om de verwijdering te bevestigen."
     type_in_email_progress: "Vul je e-mail in om te bevestigen dat je jouw voortgang wilt verwijderen."
     type_in_password: "Typ ook je wachtwoord in."
     email_subscriptions: "E-mail Abonnementen"
     email_subscriptions_none: "Geen E-mail Abonnementen."
     email_announcements: "Aankondigingen"
-    email_announcements_description: "Ontvang e-mails over het laatste nieuws en de ontwikkelingen bij CodeCombat." 
+    email_announcements_description: "Ontvang e-mails over het laatste nieuws en de ontwikkelingen bij CodeCombat."
     email_notifications: "Notificaties"
     email_notifications_summary: "Instellingen voor gepersonaliseerde, automatische meldingen via e-mail omtrent je activiteit op CodeCombat."
     email_any_notes: "Alle Meldingen"
@@ -704,7 +702,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
 #    scrub_playback: "Scrub back and forward through time."
 #    single_scrub_playback: "Scrub back and forward through time by a single frame."
 #    scrub_execution: "Scrub through current spell execution."
-    toggle_debug: "Toggle debug display." # This already is correct Dutch.
+    toggle_debug: "Toggle debug display."
     toggle_grid: "Toggle rooster weergave."
     toggle_pathfinding: "Toggle padvind weergave."
     beautify: "Verfraai je code door de opmaak overal gelijk te maken."
@@ -755,7 +753,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
     average_achievements: "Gemiddelde Prestaties"
     delete_clan: "Delete Clan"
     leave_clan: "Verlaat Clan"
-    join_clan: "Ga bij een Clan" # Now it says 'join a clan', like: "click here to join a clan". If the context is more like: join THIS clan. Then the current translation is wrong.
+    join_clan: "Ga bij een Clan"
     invite_1: "Uitnodigen:"
     invite_2: "*Nodig spelers uit in deze clan door hen deze link te sturen."
     members: "Leden"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
     email_settings_url: "jouw e-mail instellingen"
     email_description_suffix: "of via urls in de emails die wij verzenden, kan je jouw instellingen wijzigen en ten allen tijden uitschrijven."
     cost_title: "Kosten"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Auteursrechten en licenties"
     contributor_title: "Licentieovereenkomst voor vrijwilligers"
     contributor_description_prefix: "Alle bijdragen, zowel op de website als op onze GitHub repository, vallen onder onze"
diff --git a/app/locale/nn.coffee b/app/locale/nn.coffee
index 5dceee316..a8193dd04 100644
--- a/app/locale/nn.coffee
+++ b/app/locale/nn.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Norsk Nynorsk", englishDescription: "Norweg
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Norsk Nynorsk", englishDescription: "Norweg
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Norsk Nynorsk", englishDescription: "Norweg
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Norsk Nynorsk", englishDescription: "Norweg
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/pl.coffee b/app/locale/pl.coffee
index b6b113a54..f760d646f 100644
--- a/app/locale/pl.coffee
+++ b/app/locale/pl.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "polski", englishDescription: "Polish", tran
     prompt_body: "Chcesz zdobyć więcej?"
     prompt_button: "Wejdź do sklepu"
     recovered: "Przywrócono poprzednie zakupy. Prosze odświeżyć stronę."
-    price: "x3500 / mieś."
+    price: "x{{gems}} / mieś."
 
   subscribe:
     comparison_blurb: "Popraw swoje umiejętności z subskrypcją CodeCombat!"
     feature1: "Ponad 100 poziomów w 4 różnych śwoatach" # {change}
     feature2: "10 potężnych, <strong>nowych bohaterów</strong> z unikalnymi umiejętnościami!" # {change}
     feature3: "Ponad 70 bonusowych poziomów" # {change}
-    feature4: "Dodatkowe <strong>3500 klejnotów</strong> co miesiąc!"
+    feature4: "Dodatkowe <strong>{{gems}} klejnotów</strong> co miesiąc!"
     feature5: "Poradniki wideo"
     feature6: "Priorytetowe wsparcie przez e-mail"
     feature7: "Prywatne <strong>Klany</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "polski", englishDescription: "Polish", tran
     press_paragraph_1_link: "pakiecie prasowym "
     press_paragraph_1_suffix: ". Wszystkie loga i obrazki mogą zostać wykorzystane bez naszej wiedzy."
     team: "Zespół"
-    george_title: "Współzałożyciel"
-    george_blurb: "Pan Prezes"
-    scott_title: "Współzałożyciel"
-    scott_blurb: "Jedyny Rozsądny"
-    nick_title: "Współzałożyciel"
+    nick_title: "Współzałożyciel" # {change}
     nick_blurb: "Guru Motywacji"
-    michael_title: "Programista"
-    michael_blurb: "Sys Admin"
-    matt_title: "Programista"
+    matt_title: "Programista" # {change}
     matt_blurb: "Rowerzysta"
-    cat_title: "Główny Rzemieślnik"
+    cat_title: "Główny Rzemieślnik" # {change}
     cat_blurb: "Airbender"
-    josh_title: "Projektant Gier"
-    josh_blurb: "Podłoga to lawa"
-    jose_title: "Muzyka"
-    jose_blurb: "Odnosi Sukces"
-    retrostyle_title: "Ilustracje"
-    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Współzałożyciel" # {change}
+    scott_blurb: "Jedyny Rozsądny"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "Projektant Gier"
+    josh_blurb: "Podłoga to lawa"
+    retrostyle_title: "Ilustracje"
+    retrostyle_blurb: "RetroStyle Games"
+    jose_title: "Muzyka"
+    jose_blurb: "Odnosi Sukces"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "polski", englishDescription: "Polish", tran
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "polski", englishDescription: "Polish", tran
     email_settings_url: "twoje ustawienia e-mail"
     email_description_suffix: "lub poprzez linki w e-mailach, które wysyłamy, możesz zmienić swoje ustawienia i w prosty sposób wypisać się z subskrypcji w dowolnym momencie."
     cost_title: "Koszty"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Prawa autorskie i licencje"
     contributor_title: "Umowa licencyjna dla współtwórców (CLA)"
     contributor_description_prefix: "Wszyscy współtwórcy, zarówno ci ze strony jak i ci z GitHuba, podlegają naszemu"
diff --git a/app/locale/pt-BR.coffee b/app/locale/pt-BR.coffee
index 0c6a29815..cfc71cd13 100644
--- a/app/locale/pt-BR.coffee
+++ b/app/locale/pt-BR.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Português do Brasil", englishDescription:
     prompt_body: "Você quer adquirir mais gemas?"
     prompt_button: "Entrar na loja"
     recovered: "Gemas das compras anteriores recuperadas. Por favor atualize a pagina."
-    price: "x3500 / mês"
+    price: "x{{gems}} / mês"
 
   subscribe:
     comparison_blurb: "Afine suas habilidades com uma assinatura CodeCombat!"
     feature1: "Mais de 60 níveis básicos entre 4 mundos" # {change}
     feature2: "7 poderosos <strong>novos heróis</strong> com habilidades únicas!" # {change}
     feature3: "Mais de 30 níveis bônus" # {change}
-    feature4: "<strong>3500 gemas bônus</strong> todo mês!"
+    feature4: "<strong>{{gems}} gemas bônus</strong> todo mês!"
     feature5: "Vídeo tutorials"
     feature6: "Suporte via e-mail Premium"
     feature7: "<strong>Clãs</strong> Privados"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Português do Brasil", englishDescription:
     press_paragraph_1_link: "Midia Kit"
     press_paragraph_1_suffix: ". Todas as logomarcas e imagens podem ser usadas sem nos contactar previamente."
     team: "Time"
-    george_title: "Cofundador"
-    george_blurb: "Administrador"
-    scott_title: "Cofundador"
-    scott_blurb: "O Sensato"
-    nick_title: "Cofundador"
+    nick_title: "Cofundador" # {change}
     nick_blurb: "Guru Motivacional"
-    michael_title: "Programador"
-    michael_blurb: "Administrador de Sistemas"
-    matt_title: "Cofundador"
+    matt_title: "Cofundador" # {change}
     matt_blurb: "O Ciclista"
-    cat_title: "Chefe Artesão"
+    cat_title: "Chefe Artesão" # {change}
     cat_blurb: "Corta-vento"
-    josh_title: "Game Designer"
-    josh_blurb: "O chão vai tremer"
-    jose_title: "Músico"
-    jose_blurb: "Sou descolado"
-    retrostyle_title: "Ilustração"
-    retrostyle_blurb: "Games estilo Retrô"
-    rob_title: "Engenheiro Compilador"
+    scott_title: "Cofundador" # {change}
+    scott_blurb: "O Sensato"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+    rob_title: "Engenheiro Compilador" # {change}
     rob_blurb: "Os paranauês dos códigos"
     josh_c_title: "Game Designer"
     josh_c_blurb: "Desenha jogos"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "Game Designer"
+    josh_blurb: "O chão vai tremer"
+    retrostyle_title: "Ilustração"
+    retrostyle_blurb: "Games estilo Retrô"
+    jose_title: "Músico"
+    jose_blurb: "Sou descolado"
     carlos_title: "Gerente Regional, Brasil"
     carlos_blurb: "O Homem Célere"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
   teachers:
     who_for_title: "Para quem é indicado o CodeCombat?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Português do Brasil", englishDescription:
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Português do Brasil", englishDescription:
     email_settings_url: "das suas configurações de email"
     email_description_suffix: "ou através de links nos emails que enviarmos, você pode trocar as preferências e facilmente se desinscrever a qualquer hora."
     cost_title: "Custo"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Direitos Autorais e Licenças"
     contributor_title: "Contrato de Licença de Colaborador"
     contributor_description_prefix: "Todos os colaboradores, tanto no nosso site quando no nosso repositório no GitHub estão sujeitos ao nosso"
diff --git a/app/locale/pt-PT.coffee b/app/locale/pt-PT.coffee
index 475b8a38d..64be8d8f3 100644
--- a/app/locale/pt-PT.coffee
+++ b/app/locale/pt-PT.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
     prompt_body: "Queres obter mais?"
     prompt_button: "Entra na Loja"
     recovered: "A compra de gemas anterior foi recuperada. Por favor atualiza a página."
-    price: "x3500 / mês"
+    price: "x{{gems}} / mês"
 
   subscribe:
     comparison_blurb: "Aperfeiçoa as tuas habilidades com uma subscrição do CodeCombat!"
     feature1: "110+ níveis básicos dispersos por 4 mundos"
     feature2: "10 <strong>heróis novos</strong> e poderosos com habilidades únicas!"
     feature3: "80+ níveis de bónus"
-    feature4: "<strong>3500 gemas de bónus</strong> por mês!"
+    feature4: "<strong>{{gems}} gemas de bónus</strong> por mês!"
     feature5: "Tutoriais em vídeo"
     feature6: "Apoio por e-mail prioritário"
     feature7: "<strong>Clãs</strong> Privados"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
     press_paragraph_1_link: "pacote de imprensa"
     press_paragraph_1_suffix: ". Todos os logótipos e imagens podem ser usados sem sermos contactados diretamente."
     team: "Equipa"
-    george_title: "Co-fundador"
-    george_blurb: "Homem de Negócios"
-    scott_title: "Co-fundador"
-    scott_blurb: "O Sensato"
-    nick_title: "Co-fundador"
+    nick_title: "Co-fundador, CEO"
     nick_blurb: "Guru da Motivação"
-    michael_title: "Programador"
-    michael_blurb: "Administrador de Sistemas"
-    matt_title: "Co-fundador"
+    matt_title: "Co-fundador, CTO"
     matt_blurb: "Ciclista"
-    cat_title: "Artesã Chefe"
+    cat_title: "'Designer' de Jogos"
     cat_blurb: "Mágica"
-    josh_title: "'Designer' de Jogos"
-    josh_blurb: "'Floor Is Lava'"
-    jose_title: "Música"
-    jose_blurb: "'Taking Off'"
-    retrostyle_title: "Ilustração"
-    retrostyle_blurb: "'RetroStyle Games'"
-    rob_title: "Engenheiro de Compilação"
+    scott_title: "Co-fundador, Engenheiro de 'Software'"
+    scott_blurb: "O Sensato"
+    maka_title: "Defensor dos Clientes"
+    maka_blurb: "Contador de Histórias"
+    rob_title: "Engenheiro de 'Software'"
     rob_blurb: "Programa Muitas Coisas"
     josh_c_title: "'Designer' de Jogos"
     josh_c_blurb: "Projeta Jogos"
+    robin_title: "Pesquisa e Projeção de 'UX'"
+    robin_blurb: "'Scaffolding'"
+    josh_title: "'Designer' de Jogos"
+    josh_blurb: "'Floor Is Lava'"
+    retrostyle_title: "Ilustração"
+    retrostyle_blurb: "'RetroStyle Games'"
+    jose_title: "Música"
+    jose_blurb: "'Taking Off'"
     carlos_title: "Gestor Regional, Brasil"
     carlos_blurb: "Homem do Dinheiro"
-    maka_title: "Defensor dos Clientes"
-    maka_blurb: "Contador de Histórias"
 
   teachers:
     who_for_title: "Para quem é o CodeCombat?"
@@ -867,9 +865,9 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
     topics: "Tópicos"
     hours_content: "Horas de conteúdo:"
     get_free: "Obter curso GRÁTIS"
-#    enroll_paid: "Enroll Students in Paid Courses"
-#    you_have1: "You have"
-#    you_have2: "unused paid enrollments"
+    enroll_paid: "Inscrever Estudantes em Cursos Pagos"
+    you_have1: "Tens"
+    you_have2: "inscrições pagas por usar"
 #    use_one: "Use 1 paid enrollment for"
 #    use_multiple: "Use paid enrollments for the following students:"
 #    already_enrolled: "already enrolled"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
diff --git a/app/locale/ro.coffee b/app/locale/ro.coffee
index bd09656e0..73f61ac9f 100644
--- a/app/locale/ro.coffee
+++ b/app/locale/ro.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
     prompt_body: "Vrei mai multe?"
     prompt_button: "Intră în magazin."
     recovered: "Pietre Prețioase cumpărate anterior recuperate.Va rugăm să dați refresh la pagină."
-    price: "x3500 / mo"
+    price: "x{{gems}} / mo"
 
   subscribe:
     comparison_blurb: "Îmbunătățeșteți abilitățile cu abonamentul CodeCombat"
     feature1: "80+ de nivele de bază în 4 lumi diferite!" # {change}
     feature2: "7 <strong>Eroi Noi</strong> puternici, cu skilluri unice!" # {change}
     feature3: "60+ nivele bonus" # {change}
-    feature4: "<strong>3500 de Pietre Prețioase bonus</strong> în fiecare lună!"
+    feature4: "<strong>{{gems}} de Pietre Prețioase bonus</strong> în fiecare lună!"
     feature5: "Tutoriale Video"
     feature6: "Suport e-mail premium"
     feature7: "<strong>Clanuri</strong> private"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
     press_paragraph_1_link: "pachetul pentru presă"
     press_paragraph_1_suffix: ". Toate logourile si imaginile pot fi folosite fără să ne contactezi direct."
     team: "Echipa"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
   teachers:
     who_for_title: "Pentru cine este CodeCombat?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
     email_settings_url: "setările tale de email"
     email_description_suffix: " sau prin link-urile din email-urile care vi le trimitem, puteți să schimbați preferințele și să vâ dezabonați oricând."
     cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Drepturi de autor și licențe"
     contributor_title: "Acord de licență Contributor"
     contributor_description_prefix: "Toți contribuitorii, atât pe site cât și pe GitHub-ul nostru, sunt supuși la"
diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 0926a5bdd..8c372138e 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -4,7 +4,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     no_ie: "CodeCombat не работает в IE8 или более старых версиях. Нам очень жаль!" # Warning that only shows up in IE8 and older
     no_mobile: "CodeCombat не приспособлен для работы на мобильных устройствах и может не работать!" # Warning that shows up on mobile devices
     play: "Играть" # The big play button that opens up the campaign view.
-#    play_campaign_version: "Play Campaign Version" # Shows up under big play button if you only play /courses
+    play_campaign_version: "Играть в кампанию" # Shows up under big play button if you only play /courses
     old_browser: "Ой, ваш браузер слишком стар для запуска CodeCombat. Извините!" # Warning that shows up on really old Firefox/Chrome/Safari
     old_browser_suffix: "Вы всё равно можете попробовать, но, скорее всего, это не будет работать."
     ipad_browser: "Плохие новости: CodeCombat не запускается в браузере IPad. Хорошие новости: наше нативное приложение для IPad ожидает одобрения от Apple."
@@ -17,7 +17,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
   nav:
     play: "Уровни" # The top nav bar entry where players choose which levels to play
     community: "Сообщество"
-#    courses: "Courses"
+    courses: "Курсы"
     editor: "Редактор"
     blog: "Блог"
     forum: "Форум"
@@ -52,7 +52,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
 
   play:
     play_as: "Играть за " # Ladder page
-#    compete: "Compete!" # Course details page
+    compete: "Соревноваться!" # Course details page
     spectate: "Наблюдать" # Ladder page
     players: "игроки" # Hover over a level on /play
     hours_played: "часов сыграно" # Hover over a level on /play
@@ -75,7 +75,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     subscription_required: "Требуется подписка"
     anonymous: "Неизвестный игрок"
     level_difficulty: "Сложность: "
-#    play_classroom_version: "Play Classroom Version" # Choose a level in campaign version that you also can play in one of your courses
+    play_classroom_version: "Играть в версию для работы в классе" # Choose a level in campaign version that you also can play in one of your courses
     campaign_beginner: "Кампания для новичков"
     awaiting_levels_adventurer_prefix: "Мы выпускаем новые уровни каждую неделю."
     awaiting_levels_adventurer: "Зарегистрируйтесь в качестве Искателя приключений"
@@ -83,7 +83,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     adjust_volume: "Регулировать громкость"
     campaign_multiplayer: "Арены для мультиплеера"
     campaign_multiplayer_description: "... в которых вы соревнуетесь в программировании с другими игроками."
-#    campaign_old_multiplayer: "(Deprecated) Old Multiplayer Arenas"
+    campaign_old_multiplayer: "(Устаревшее) Старые многопользовательские арены"
 #    campaign_old_multiplayer_description: "Relics of a more civilized age. No simulations are run for these older, hero-less multiplayer arenas."
 
   share_progress_modal:
@@ -114,9 +114,9 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     log_in: "вход с паролем"
     required: "Войдите для того, чтобы продолжить."
     login_switch: "Уже есть аккаунт?"
-#    school_name: "School Name and City"
-#    optional: "optional"
-#    school_name_placeholder: "Example High School, Springfield, IL"
+    school_name: "Название школы and город"
+    optional: "не обязательно"
+    school_name_placeholder: "Школа № 2, город Электросталь, Московская область"
 
   recover:
     recover_account_title: "Восстановить аккаунт"
@@ -166,7 +166,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     withdrawn: "Отозвано"
     accept: "Принять"
     reject: "Отклонить"
-#    withdraw: "Withdraw"
+    withdraw: "Изъять"
     submitter: "Податель"
     submitted: "Представлено"
     commit_msg: "Сопроводительное сообщение"
@@ -221,10 +221,10 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     years: "лет"
 
   play_level:
-#    completed_level: "Completed Level:"
-#    course: "Course:"
+    completed_level: "Завершённый уровень:"
+    course: "Курс:"
     done: "Готово"
-#    next_level: "Next Level:"
+    next_level: "Следующий уровень:"
     next_game: "Следующая игра"
     show_menu: "Показать меню игры"
     home: "На главную" # Not used any more, will be removed soon.
@@ -342,7 +342,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     tip_free_your_mind: "Отвлекись от всего, Нео. Страх, неверие, сомнения отбрось — очисти свой разум. - Morpheus"
     tip_strong_opponents: "Даже сильнейший противник имеет слабость. - Itachi Uchiha"
     tip_paper_and_pen: "Прежде чем начать программировать, вы всегда можете попробовать с листом бумаги и ручкой."
-#    tip_solve_then_write: "First, solve the problem. Then, write the code. - John Johnson"
+    tip_solve_then_write: "Сперва реши задачу, затем пиши код. - Джон Джонсон"
 
   game_menu:
     inventory_tab: "Инвентарь"
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     prompt_body: "Хотите еще?"
     prompt_button: "Войти в магазин"
     recovered: "Предыдущие покупки самоцветов восстановлены. Пожалуйста, обновите страницу."
-    price: "x3500 / месяц"
+    price: "x{{gems}} / месяц"
 
   subscribe:
     comparison_blurb: "Отточите свое мастерство благодаря подписке на CodeCombat!"
     feature1: "80+ основных уровней на просторах 4-х миров" # {change}
     feature2: "7 могущественных <strong>новых героев</strong> с уникальными способностями!" # {change}
     feature3: "60+ дополнительных уровней" # {change}
-    feature4: "<strong>3500 бонусных самоцветов</strong> каждый месяц!"
+    feature4: "<strong>{{gems}} бонусных самоцветов</strong> каждый месяц!"
     feature5: "Обучающие видеоролики"
     feature6: "Эксклюзивная поддержка по электронной почте"
     feature7: "Частные <strong>Кланы</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     press_paragraph_1_link: "пресс-пакет"
     press_paragraph_1_suffix: ". Все изображения могут быть использованы без предварительного уведомления."
     team: "Команда"
-    george_title: "Сооснователь"
-    george_blurb: "Деловой"
-    scott_title: "Сооснователь"
-    scott_blurb: "Разумный"
-    nick_title: "Сооснователь"
+    nick_title: "Сооснователь" # {change}
     nick_blurb: "Гуру мотивации"
-    michael_title: "Программист"
-    michael_blurb: "Сисадмин"
-    matt_title: "Сооснователь"
+    matt_title: "Сооснователь" # {change}
     matt_blurb: "Велосипедист"
-    cat_title: "Главный ремесленник"
+    cat_title: "Главный ремесленник" # {change}
     cat_blurb: "Повелитель стихий"
-    josh_title: "Дизайнер игры"
-    josh_blurb: "Пол - это лава"
-    jose_title: "Музыка"
-    jose_blurb: "На взлет"
-    retrostyle_title: "Иллюстрирование"
-    retrostyle_blurb: "Игры в стиле ретро"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Сооснователь" # {change}
+    scott_blurb: "Разумный"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "Дизайнер игры"
+    josh_blurb: "Пол - это лава"
+    retrostyle_title: "Иллюстрирование"
+    retrostyle_blurb: "Игры в стиле ретро"
+    jose_title: "Музыка"
+    jose_blurb: "На взлет"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
   teachers:
     who_for_title: "Для кого предназначен CodeCombat?"
@@ -596,15 +594,15 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     being_reviewed_2: "на рассмотрении." # {change}
     approved_1: "Ваша заявка на бесплатную пробную подписку была" # {change}
     approved_2: "утверждена." # {change}
-#    approved_4: "You can now enroll your students on the"
-#    approved_5: "courses"
-#    approved_6: "page."
+    approved_4: "Теперь вы можете регистрировать ваших учеников на"
+    approved_5: "курсы"
+    approved_6: "страница."
     denied_1: "Ваша заявка на бесплатную пробную подписку была" # {change}
     denied_2: "отклонена." # {change}
     contact_1: "Пожалуйста, свяжитесь с"
     contact_2: ", если у вас остались вопросы."
     description_1: "Мы предлагаем бесплатные подписки учителям в целях ознакомления. Вы можете найти больше информации на нашей странице"
-#    description_1b: "You can find more information on our"
+    description_1b: "Вы можете найти больше информации на"
     description_2: "учителей"
     description_3: ""
     description_4: "Пожалуйста, заполните эту маленькую анкету и мы вышлем вам инструкции по установке на email."
@@ -738,7 +736,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     subs_only: "только для подписчиков"
     create_clan: "Создать новый клан"
     private_preview: "Превью"
-#    private_clans: "Private Clans"
+    private_clans: "Тайные кланы"
     public_clans: "Публичные кланы"
     my_clans: "Мои кланы"
     clan_name: "Имя клана"
@@ -770,7 +768,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     started_2: "Начат"
     not_started_2: "Не начат"
     view_solution: "Нажмите, чтобы увидеть решение."
-#    view_attempt: "Click to view attempt."
+    view_attempt: "Нажмите чтобы посмотреть попытку."
     latest_achievement: "Последнее достижение"
     playtime: "Время игры"
     last_played: "Последняя игра"
@@ -782,17 +780,17 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
 #    track_concepts3b: "Track levels completed for each member"
 #    track_concepts4a: "See your students'"
 #    track_concepts4b: "See your members'"
-#    track_concepts5: "solutions"
-#    track_concepts6a: "Sort students by name or progress"
-#    track_concepts6b: "Sort members by name or progress"
-#    track_concepts7: "Requires invitation"
-#    track_concepts8: "to join"
-#    private_require_sub: "Private clans require a subscription to create or join."
+    track_concepts5: "решения"
+    track_concepts6a: "Сортировать студентов по имени или прогрессу"
+    track_concepts6b: "Сортировать членов по имени или прогрессу"
+    track_concepts7: "Требуется приглашение"
+    track_concepts8: "вступить"
+    private_require_sub: "Требуется подписка чтобы создать тайный клан или вступить в него."
 
   courses:
     course: "Курс"
     courses: "Курсы"
-#    create_new_class: "Create New Class"
+    create_new_class: "Создать новый класс"
     not_enrolled: "Вы не записаны на этот курс."
     visit_pref: "Пожалуйста, зайдите на"
     visit_suf: "страницу для записи."
@@ -867,152 +865,152 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     topics: "Темы"
     hours_content: "Много часов материала:"
     get_free: "Получить бесплатный курс"
-#    enroll_paid: "Enroll Students in Paid Courses"
-#    you_have1: "You have"
+    enroll_paid: "Записать учеников на платные курсы"
+    you_have1: "У вас есть"
 #    you_have2: "unused paid enrollments"
 #    use_one: "Use 1 paid enrollment for"
 #    use_multiple: "Use paid enrollments for the following students:"
-#    already_enrolled: "already enrolled"
+    already_enrolled: "уже зачислен"
 #    licenses_remaining: "licenses remaining:"
 #    insufficient_enrollments: "insufficient paid enrollments"
 #    enroll_students: "Enroll Students"
 #    get_enrollments: "Get More Enrollments"
-#    change_language: "Change Course Language"
-#    keep_using: "Keep Using"
-#    switch_to: "Switch To"
-#    greetings: "Greetings!"
-#    learn_p: "Learn Python"
-#    learn_j: "Learn JavaScript"
-#    language_cannot_change: "Language cannot be changed once students join a class."
-#    back_classrooms: "Back to my classrooms"
-#    back_courses: "Back to my courses"
-#    edit_details: "Edit class details"
+    change_language: "Изменить язык программирования курса"
+    keep_using: "Продолжить использовать"
+    switch_to: "Переключить на"
+    greetings: "Поздравления!"
+    learn_p: "Изучать Python"
+    learn_j: "Изучать JavaScript"
+    language_cannot_change: "Язык не может быть изменён после того как ученик присоединился к классу."
+    back_classrooms: "Назад к моим классам"
+    back_courses: "Назад к моим курсам"
+    edit_details: "Редактировать описание класса"
 #    enrolled_courses: "enrolled in paid courses:"
 #    purchase_enrollments: "Purchase Enrollments"
-#    remove_student: "remove student"
+    remove_student: "удалить ученика"
 #    assign: "Assign"
 #    to_assign: "to assign paid courses."
-#    teacher: "Teacher"
-#    complete: "Complete"
+    teacher: "Учитель"
+    complete: "Завершить"
 #    none: "None"
-#    save: "Save"
-#    play_campaign_title: "Play the Campaign"
+    save: "Сохранить"
+    play_campaign_title: "Играть в кампанию"
 #    play_campaign_description: "You’re ready to take the next step! Explore hundreds of challenging levels, learn advanced programming skills, and compete in multiplayer arenas!"
-#    create_account_title: "Create an Account"
+    create_account_title: "Создать учётную запись"
 #    create_account_description: "Sign up for a FREE CodeCombat account and gain access to more levels, more programming skills, and more fun!"
 #    preview_campaign_title: "Preview Campaign"
 #    preview_campaign_description: "Take a sneak peek at all that CodeCombat has to offer before signing up for your FREE account."
-#    arena: "Arena"
-#    arena_soon_title: "Arena Coming Soon"
+    arena: "Арена"
+    arena_soon_title: "Арена скоро появится"
 #    arena_soon_description: "We are working on a multiplayer arena for classrooms at the end of"
 #    not_enrolled1: "Not enrolled"
-#    not_enrolled2: "Ask your teacher to enroll you in the next course."
-#    next_course: "Next Course"
-#    coming_soon1: "Coming soon"
+    not_enrolled2: "Попросите учителя зачислить вас на следующий курс."
+    next_course: "Следующий курс"
+    coming_soon1: "Скоро появится"
 #    coming_soon2: "We are hard at work making more courses for you!"
-#    available_levels: "Available Levels"
-#    welcome_to_courses: "Adventurers, welcome to Courses!"
-#    ready_to_play: "Ready to play?"
-#    start_new_game: "Start New Game"
-#    play_now_learn_header: "Play now to learn"
-#    play_now_learn_1: "basic syntax to control your character"
-#    play_now_learn_2: "while loops to solve pesky puzzles"
-#    play_now_learn_3: "strings & variables to customize actions"
-#    play_now_learn_4: "how to defeat an ogre (important life skills!)"
-#    welcome_to_page: "Welcome to your Courses page!"
-#    completed_hoc: "Amazing! You've completed the Hour of Code course!"
-#    ready_for_more_header: "Ready for more? Play the campaign mode!"
-#    ready_for_more_1: "Use gems to unlock new items!"
+    available_levels: "Доступные уровни"
+    welcome_to_courses: "Искатели приключений, добро пожаловать на курсы!"
+    ready_to_play: "Готовы приступить к игре?"
+    start_new_game: "Начать новую игру"
+    play_now_learn_header: "Начать обучающую игру"
+    play_now_learn_1: "базовый синтаксис управления персонажем"
+    play_now_learn_2: "циклы while чтобы решать противные головоломки"
+    play_now_learn_3: "строки и переменные чтобы настраивать действия"
+    play_now_learn_4: "Как победить огра (важные жизненные навыки!)"
+    welcome_to_page: "Добро пожаловать на вашу страницу курсов!"
+    completed_hoc: "Изумительно! Вы прошли курс Час кода!"
+    ready_for_more_header: "Хотите продолжить? Играйте в режиме кампании!"
+    ready_for_more_1: "Используйте самоцветы чтобы разблокировать новые предметы!"
 #    ready_for_more_2: "Play through brand new worlds and challenges"
-#    ready_for_more_3: "Learn even more programming!"
-#    saved_games: "Saved Games"
-#    hoc: "Hour of Code"
-#    my_classes: "My Classes"
-#    class_added: "Class successfully added!"
-#    view_class: "view class"
-#    view_levels: "view levels"
-#    join_class: "Join A Class"
-#    ask_teacher_for_code: "Ask your teacher if you have a CodeCombat class code! If so, enter it below:"
-#    enter_c_code: "<Enter Class Code>"
-#    join: "Join"
+    ready_for_more_3: "Учитесь программировнию дальше!"
+    saved_games: "Сохранённые игры"
+    hoc: "Час кода"
+    my_classes: "Мои классы"
+    class_added: "Класс успешно добавлен!"
+    view_class: "смотреть класс"
+    view_levels: "смотреть уровни"
+    join_class: "Присоединиться к классу"
+    ask_teacher_for_code: "Спросите у вашего учителя код класса для CodeCombat! Введите его ниже:"
+    enter_c_code: "<Введите Код Класса>"
+    join: "Присоединиться"
 #    joining: "Joining class"
-#    course_complete: "Course Complete"
-#    play_arena: "Play Arena"
-#    start: "Start"
-#    last_level: "Last Level"
-#    welcome_to_hoc: "Adventurers, welcome to our Hour of Code!"
-#    logged_in_as: "Logged in as:"
-#    not_you: "Not you?"
-#    welcome_back: "Hi adventurer, welcome back!"
-#    continue_playing: "Continue Playing"
-#    more_options: "More options:"
-#    option1_header: "Option 1: Invite students via email"
+    course_complete: "Курс завершён"
+    play_arena: "Играть Арену"
+    start: "Старт"
+    last_level: "Последний уровень"
+    welcome_to_hoc: "Искатели приключений, добро пожаловать на Час кода!"
+    logged_in_as: "Вошли как:"
+    not_you: "Не вы?"
+    welcome_back: "Привет, искатель приключений, добро пожаловать!"
+    continue_playing: "Играть Дальше"
+    more_options: "Другие варианты:"
+    option1_header: "Вариант 1: Пригласить учеников по email"
 #    option1_body: "Students will automatically be sent an invitation to join this class, and will need to create an account with a username and password."
-#    option2_header: "Option 2: Send URL to your students"
+    option2_header: "Вариант 2: Послать URL вашим ученикам"
 #    option2_body: "Students will be asked to enter an email address, username and password to create an account."
-#    option3_header: "Option 3: Direct students to codecombat.com/courses"
+    option3_header: "Вариант 3: Направить учеников на codecombat.com/courses"
 #    option3_body: "Give students the following passcode to enter along with an email address, username and password when they create an account."
 #    thank_you_pref: "Thank you for your purchase! You can now assign"
 #    thank_you_suff: "more students to paid courses."
-#    return_to_class: "Return to classroom"
-#    return_to_course_man: "Return to course management."
+    return_to_class: "Вернуться в класс"
+    return_to_course_man: "Вернуться к управлению курсом."
 #    students_not_enrolled: "students not enrolled"
-#    total_all_classes: "Total Across All Classes"
+    total_all_classes: "Общее по всем классам"
 #    how_many_enrollments: "How many additional paid enrollments do you need?"
 #    each_student_access: "Each student in a class will get access to Courses 2-4 once they are enrolled in paid courses. You may assign each course to each student individually."
 #    purchase_now: "Purchase Now"
 #    enrollments: "enrollments"
-#    remove_student1: "Remove Student"
+    remove_student1: "Удалить ученика"
 #    are_you_sure: "Are you sure you want to remove this student from this class?"
 #    remove_description1: "Student will lose access to this classroom and assigned classes. Progress and gameplay is NOT lost, and the student can be added back to the classroom at any time."
 #    remove_description2: "The activated paid license will not be returned."
-#    keep_student: "Keep Student"
+    keep_student: "Оставить ученика"
 #    removing_user: "Removing user"
 #    to_join_ask: "To join a class, ask your teacher for an unlock code."
 #    join_this_class: "Join Class"
-#    enter_here: "<enter unlock code here>"
+    enter_here: "<Ввести здесь код разблокировки>"
 #    successfully_joined: "Successfully joined"
 #    click_to_start: "Click here to start taking"
-#    my_courses: "My Courses"
-#    classroom: "Classroom"
+    my_courses: "Мои курсы"
+    classroom: "Класс"
 #    use_school_email: "use your school email if you have one"
 #    unique_name: "a unique name no one has chosen"
 #    pick_something: "pick something you can remember"
-#    class_code: "Class Code"
-#    optional_ask: "optional - ask your teacher to give you one!"
-#    optional_school: "optional - what school do you go to?"
-#    start_playing: "Start Playing"
-#    skip_this: "Skip this, I'll create an account later!"
-#    welcome: "Welcome"
-#    getting_started: "Getting Started with Courses"
+    class_code: "Код класса"
+    optional_ask: "Как вариант - попросите учителя дать вам какой-нибудь!"
+    optional_school: "Не обязательное - в какую школу вы ходите?"
+    start_playing: "Начать играть"
+    skip_this: "Пропустить это, я создам учетную запись позже!"
+    welcome: "Добро пожаловать"
+    getting_started: "Начать проходить курсы"
 #    download_getting_started: "Download Getting Started Guide [PDF]"
 #    getting_started_1: "Create a new class by clicking the green 'Create New Class' button below."
 #    getting_started_2: "Once you've created a class, click the blue 'Add Students' button."
 #    getting_started_3: "You'll see student's progress below as they sign up and join your class."
-#    additional_resources: "Additional Resources"
-#    additional_resources_1_pref: "Download/print our"
+    additional_resources: "Дополнительные ресурсы"
+    additional_resources_1_pref: "Скачать/распечатать наш"
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
-#    additional_resources_3_pref: "Visit our"
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
+    additional_resources_3_pref: "Посетить наш"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
 #    additional_resources_4_pref: "Check out our"
 #    additional_resources_4_mid: "Schools Page"
 #    additional_resources_4_suff: "to learn more about CodeCombat's classroom offerings."
-#    your_classes: "Your Classes"
-#    no_classes: "No classes yet!"
-#    create_new_class1: "create new class"
-#    available_courses: "Available Courses"
+    your_classes: "Ваши классы"
+    no_classes: "Ещё нет классов!"
+    create_new_class1: "создать новый класс"
+    available_courses: "Доступные курсы"
 #    unused_enrollments: "Unused enrollments available:"
 #    students_access: "All students get access to Introduction to Computer Science for free. One enrollment per student is required to assign them to paid CodeCombat courses. A single student does not need multiple enrollments to access all paid courses."
-#    active_courses: "active courses"
-#    no_students: "No students yet!"
-#    add_students1: "add students"
-#    view_edit: "view/edit"
-#    students_enrolled: "students enrolled"
-#    length: "Length:"
+    active_courses: "активные курсы"
+    no_students: "Ещё нет учеников!"
+    add_students1: "добавить учеников"
+    view_edit: "смотреть/редактировать"
+    students_enrolled: "учеников зачислено"
+    length: "Длительность:"
 
   classes:
     archmage_title: "Архимаг"
@@ -1256,11 +1254,11 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     rules: "Правила"
     winners: "Победители"
     league: "Лига"
-#    red_ai: "Red CPU" # "Red AI Wins", at end of multiplayer match playback
-#    blue_ai: "Blue CPU"
-#    wins: "Wins" # At end of multiplayer match playback
-#    humans: "Red" # Ladder page display team name
-#    ogres: "Blue"
+    red_ai: "CPU красного" # "Red AI Wins", at end of multiplayer match playback
+    blue_ai: "CPU синего"
+    wins: "Побеждает" # At end of multiplayer match playback
+    humans: "Красный" # Ladder page display team name
+    ogres: "Синий"
 
   user:
     stats: "Характеристики"
@@ -1408,16 +1406,16 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     campaigns: "Кампании"
     poll: "Опрос"
     user_polls_record: "История опросов"
-#    course: "Course"
-#    courses: "Courses"
-#    course_instance: "Course Instance"
-#    course_instances: "Course Instances"
-#    classroom: "Classroom"
-#    classrooms: "Classrooms"
-#    clan: "Clan"
-#    clans: "Clans"
-#    members: "Members"
-#    users: "Users"
+    course: "Курс"
+    courses: "Курсы"
+    course_instance: "Экземпляр курса"
+    course_instances: "Экземпляры курса"
+    classroom: "Класс"
+    classrooms: "Классы"
+    clan: "Клан"
+    clans: "Кланы"
+    members: "Члены"
+    users: "пользователи"
 
   concepts:
     advanced_strings: "Продвинутые строки"
diff --git a/app/locale/sk.coffee b/app/locale/sk.coffee
index 1e2e2f92e..7994911b3 100644
--- a/app/locale/sk.coffee
+++ b/app/locale/sk.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
     prompt_body: "Chcete získať viac?"
     prompt_button: "Vstúpiť do obchodu"
     recovered: "Obnovenie už zakúpených drahokamov prebehlo úspěšne. Aktualizujte stránku prosím."
-    price: "x3500 / mesiac"
+    price: "x{{gems}} / mesiac"
 
   subscribe:
     comparison_blurb: "Uč sa dôkladnejšie vďaka predplatnému !"
     feature1: "60+ základných úrovní v štyroch svetoch" # {change}
     feature2: "7 mocných <strong>new hrdinov</strong> s jedinečnými schopnosťami!" # {change}
     feature3: "30+ bonusových úrovní" # {change}
-    feature4: "<strong>3500 bonusových diamantov</strong> každý mesiac !"
+    feature4: "<strong>{{gems}} bonusových diamantov</strong> každý mesiac !"
     feature5: "Video tutoriály"
     feature6: "Prémiová emailová podpora"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
     press_paragraph_1_link: "tlačovom balíčku"
     press_paragraph_1_suffix: ". Všetky logá a obrázky môžeš použiť bez toho, aby si nás priamo kontaktoval."
     team: "Tím"
-    george_title: "Spoluzakladateľ"
-    george_blurb: "Podnikateľ"
-    scott_title: "Spoluzakladateľ"
-    scott_blurb: "Ten rozumný"
-    nick_title: "Spoluzakladateľ"
+    nick_title: "Spoluzakladateľ" # {change}
     nick_blurb: "Motivačný Guru"
-    michael_title: "Programátor"
-    michael_blurb: "Systémový administrátor"
     matt_title: "Programátor" # {change}
     matt_blurb: "Bicyklista"
-    cat_title: "Najvyššia remeselníčka"
+    cat_title: "Najvyššia remeselníčka" # {change}
     cat_blurb: "Ohýbačka vzduchu"
-    josh_title: "Dizajnér hier"
-    josh_blurb: "Podlaha je láva"
-    jose_title: "Hudba"
-    jose_blurb: "Vzlet"
-    retrostyle_title: "Ilustrácia"
-    retrostyle_blurb: "Retro hry"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Spoluzakladateľ" # {change}
+    scott_blurb: "Ten rozumný"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "Dizajnér hier"
+    josh_blurb: "Podlaha je láva"
+    retrostyle_title: "Ilustrácia"
+    retrostyle_blurb: "Retro hry"
+    jose_title: "Hudba"
+    jose_blurb: "Vzlet"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
   teachers:
     who_for_title: "Pre koho je určený CodeComabt ?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/sl.coffee b/app/locale/sl.coffee
index e3ffe7511..377a1356b 100644
--- a/app/locale/sl.coffee
+++ b/app/locale/sl.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/sr.coffee b/app/locale/sr.coffee
index aaa29c26c..14fa1fcd8 100644
--- a/app/locale/sr.coffee
+++ b/app/locale/sr.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/sv.coffee b/app/locale/sv.coffee
index 35a9eeee5..088662a3a 100644
--- a/app/locale/sv.coffee
+++ b/app/locale/sv.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
     prompt_body: "Vill du skaffa flera?"
     prompt_button: "Gå till affären"
     recovered: "Föregående köp av ädelstenar återskapat. Var vänlig och uppdatera sidan."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
     press_paragraph_1_link: "presspaket"
     press_paragraph_1_suffix: ". Alla loggor och bilder kan användas utan att kontakta oss direkt."
     team: "Team"
-    george_title: "Medgrundare"
-    george_blurb: "Businesser"
-    scott_title: "Medgrundare"
-#    scott_blurb: "Reasonable One"
-    nick_title: "Medgrundare"
+    nick_title: "Medgrundare" # {change}
 #    nick_blurb: "Motivation Guru"
-    michael_title: "Programmerare"
-    michael_blurb: "Sys Admin"
-    matt_title: "Medgrundare"
+    matt_title: "Medgrundare" # {change}
     matt_blurb: "Cyklist"
-    cat_title: "Chefshantverkare"
+    cat_title: "Chefshantverkare" # {change}
 #    cat_blurb: "Airbender"
-    josh_title: "Speldesigner"
-#    josh_blurb: "Floor Is Lava"
-    jose_title: "Musik"
-#    jose_blurb: "Taking Off"
-    retrostyle_title: "Illustration"
-    retrostyle_blurb: "RetroStyle Games"
-    rob_title: "Kompileringsingenjör"
+    scott_title: "Medgrundare" # {change}
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+    rob_title: "Kompileringsingenjör" # {change}
     rob_blurb: "Kodar saker"
     josh_c_title: "Speldesigner"
     josh_c_blurb: "Designar spel"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "Speldesigner"
+#    josh_blurb: "Floor Is Lava"
+    retrostyle_title: "Illustration"
+    retrostyle_blurb: "RetroStyle Games"
+    jose_title: "Musik"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
   teachers:
     who_for_title: "Vem är CodeCombat för?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
     email_settings_url: "dina mejlinställningar"
     email_description_suffix: "eller genom länkar i mejlen vi skickar kan du ändra dina inställningar och lätt avprenumerera när som helst."
     cost_title: "Kostnad"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Upphovsrätt och licenser"
     contributor_title: "Överenskommelse för bidragarlicens"
     contributor_description_prefix: "Alla bidrag, både på sajten och på vårt GitHub-repo, faller under vår"
diff --git a/app/locale/th.coffee b/app/locale/th.coffee
index 8027a476a..d94b41795 100644
--- a/app/locale/th.coffee
+++ b/app/locale/th.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
   subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-    george_title: "ผู้ร่วมก่อตั้ง"
-#    george_blurb: "Businesser"
-    scott_title: "ผู้ร่วมก่อตั้ง"
-#    scott_blurb: "Reasonable One"
-    nick_title: "ผู้ร่วมก่อตั้ง"
+    nick_title: "ผู้ร่วมก่อตั้ง" # {change}
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-    matt_title: "ผู้ร่วมก่อตั้งผู้ร่วมก่อตั้ง"
+    matt_title: "ผู้ร่วมก่อตั้งผู้ร่วมก่อตั้ง" # {change}
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "ผู้ร่วมก่อตั้ง" # {change}
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/tr.coffee b/app/locale/tr.coffee
index 372164084..3ea210089 100644
--- a/app/locale/tr.coffee
+++ b/app/locale/tr.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
 #    press_paragraph_1_link: "press packet"
     press_paragraph_1_suffix: ". Tüm logolar bizimle iletişime geçilmeden kullanılabilir."
     team: "Takım"
-    george_title: "CEO" # {change}
-#    george_blurb: "Businesser"
-    scott_title: "Programcı" # {change}
-#    scott_blurb: "Reasonable One"
     nick_title: "Programcı" # {change}
 #    nick_blurb: "Motivation Guru"
-    michael_title: "Programcı"
-#    michael_blurb: "Sys Admin"
     matt_title: "Programcı" # {change}
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Programcı" # {change}
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
     email_settings_url: "eposta ayarları sayfasından,"
     email_description_suffix: "ister size gönderdiğimiz epostadaki linklerden, tercihlerinizi değiştirebilir ve aboneliğinizi anında iptal edebilirsiniz."
     cost_title: "Ücret"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Telif Hakları ve Lisanslar"
     contributor_title: "Katılımcı Lisans Sözleşmesi"
     contributor_description_prefix: "GitHub ve siteye yapılan tüm katılımlar, devam etmeden önce kabul etmeniz gereken"
diff --git a/app/locale/uk.coffee b/app/locale/uk.coffee
index c3ac2d8f7..87597cb98 100644
--- a/app/locale/uk.coffee
+++ b/app/locale/uk.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Українська", englishDescription:
     prompt_body: "Хочете отримати ще?"
     prompt_button: "Увійти до крамниці"
     recovered: "Попередні покупки самоцвітів відновлені. Будь ласка, поновіть сторінку."
-    price: "x3500 / міс"
+    price: "x{{gems}} / міс"
 
   subscribe:
     comparison_blurb: "Відточіть свої навички завдяки підписці на CodeCombat!"
     feature1: "Більше 110 основних рівней на просторах 4 світів"
     feature2: "10 могутніх <strong>нових героїв</strong> з унікальними здібностями!"
     feature3: "Більше 80-ти бонусних рівнів"
-    feature4: "<strong>3500 бонусних самоцвітів</strong> кожного місяця!"
+    feature4: "<strong>{{gems}} бонусних самоцвітів</strong> кожного місяця!"
     feature5: "Навчальні відеоролики"
     feature6: "Екслюзивна підтримка по електронній пошті"
     feature7: "Приватні <strong>клани</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Українська", englishDescription:
     press_paragraph_1_link: "набору-для-преси"
     press_paragraph_1_suffix: ". Всі логотипи та зображення можна використовувати, не зв'язуючись із нами напряму."
     team: "Команда"
-    george_title: "Співзасновник"
-    george_blurb: "Бізнесмен"
-    scott_title: "Співзасновник"
-    scott_blurb: "Розумник"
-    nick_title: "Співзасновник"
+    nick_title: "Співзасновник" # {change}
     nick_blurb: "Ґуру мотивації"
-    michael_title: "Програміст"
-    michael_blurb: "Сисадмін"
-    matt_title: "Співзасновник"
+    matt_title: "Співзасновник" # {change}
     matt_blurb: "Велосипедист"
-    cat_title: "Головний ремісник"
+    cat_title: "Головний ремісник" # {change}
     cat_blurb: "Маг повітря"
-    josh_title: "Дизайнер гри"
-    josh_blurb: "Підлога - це лава"
-    jose_title: "Музика"
-    jose_blurb: "Hа зліт"
-    retrostyle_title: "Ілюстрація"
-    retrostyle_blurb: "Ігри в стилі ретро"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Співзасновник" # {change}
+    scott_blurb: "Розумник"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "Дизайнер гри"
+    josh_blurb: "Підлога - це лава"
+    retrostyle_title: "Ілюстрація"
+    retrostyle_blurb: "Ігри в стилі ретро"
+    jose_title: "Музика"
+    jose_blurb: "Hа зліт"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
   teachers:
     who_for_title: "Для кого призначений CodeCombat?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
     email_settings_url: "налаштування Вашого email"
     email_description_suffix: "або через посилання в повідомленнях, котрі ми присилаємо, Ви можете змінити свої уподобання і легко відмовитись від підписки в будь-який час."
     cost_title: "Вартість"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "Авторські права та ліцензії"
     contributor_title: "Авторська ліцензійна згода"
     contributor_description_prefix: "Усі права, як на сайті так і у нашому сховищі GitHub, є у відповідності з нашими"
diff --git a/app/locale/ur.coffee b/app/locale/ur.coffee
index 83ef0ba44..d579d7194 100644
--- a/app/locale/ur.coffee
+++ b/app/locale/ur.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/uz.coffee b/app/locale/uz.coffee
index b5c883eaf..14d8a82d1 100644
--- a/app/locale/uz.coffee
+++ b/app/locale/uz.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "O'zbekcha", englishDescription: "Uzbek", tr
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "O'zbekcha", englishDescription: "Uzbek", tr
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "O'zbekcha", englishDescription: "Uzbek", tr
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "O'zbekcha", englishDescription: "Uzbek", tr
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/vi.coffee b/app/locale/vi.coffee
index 516524119..ecca57abb 100644
--- a/app/locale/vi.coffee
+++ b/app/locale/vi.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
     prompt_body: "Ban có muốn nhiều ngọc hơn không ?"
     prompt_button: "Vào cửa hàng"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
   subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
     feature2: "7 <strong>nhât vật mới</strong> mạnh mẽ với những kĩ năng đặc biệt!" # {change}
 #    feature3: "80+ bonus levels"
-    feature4: "<strong>Được thưởng thêm 3500 ngọc</strong> mỗi tháng!"
+    feature4: "<strong>Được thưởng thêm {{gems}} ngọc</strong> mỗi tháng!"
     feature5: "Những video hướng dẫn qua bàn"
     feature6: "Sự hỗ trợ tận tình qua email"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-    george_title: "Tổng giám đốc điều hành" # {change}
-#    george_blurb: "Businesser"
-    scott_title: "Lập trình viên" # {change}
-    scott_blurb: "Một người có lý trí, biết suy luận"
     nick_title: "Lập trình viên" # {change}
 #    nick_blurb: "Motivation Guru"
-    michael_title: "Lập trình viên"
-#    michael_blurb: "Sys Admin"
     matt_title: "Lập trình viên" # {change}
     matt_blurb: "Một người thích đi xe đạp"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+    scott_title: "Lập trình viên" # {change}
+    scott_blurb: "Một người có lý trí, biết suy luận"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
   teachers:
     who_for_title: "CodeCombat dành cho ai ?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/zh-HANS.coffee b/app/locale/zh-HANS.coffee
index afcf533b9..05033d934 100644
--- a/app/locale/zh-HANS.coffee
+++ b/app/locale/zh-HANS.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     prompt_body: "还需要更多吗?"
     prompt_button: "进入商店"
     recovered: "之前购买的宝石已恢复。请刷新页面。"
-    price: "x3500 / 月"
+    price: "x{{gems}} / 月"
 
   subscribe:
     comparison_blurb: "亲,订阅CodeCombat,大力的提升您的技能!"
     feature1: "110+ 基本关卡(4个世界)"
     feature2: "10 个强大 <strong>英雄</strong>以及各式非凡技能!"
     feature3: "80+ 奖励关卡"
-    feature4: "每月享有3500额外宝石"
+    feature4: "每月享有{{gems}}额外宝石"
     feature5: "视频教学"
     feature6: "专业邮件支援"
     feature7: "私人 <strong>部落</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     press_paragraph_1_link: "成套宣传包"
     press_paragraph_1_suffix: "里的所有材料。 所有商标和图像的使用都不必事先联系我们。"
     team: "团队"
-    george_title: "共同创始人"
-    george_blurb: "商人"
-    scott_title: "共同创始人"
-    scott_blurb: "理性至上"
-    nick_title: "共同创始人"
+    nick_title: "共同创始人" # {change}
     nick_blurb: "充满动力的大牛"
-    michael_title: "程序员"
-    michael_blurb: "系统管理员"
-    matt_title: "共同创始人"
+    matt_title: "共同创始人" # {change}
     matt_blurb: "自行车爱好者"
-    cat_title: "首席关卡设计师"
+    cat_title: "首席关卡设计师" # {change}
     cat_blurb: "气宗"
-    josh_title: "游戏设计师"
-    josh_blurb: "地面是熔岩"
-    jose_title: "音乐"
-    jose_blurb: "放轻松"
-    retrostyle_title: "插画师"
-    retrostyle_blurb: "复古风格的游戏"
-    rob_title: "编译器工程师"
+    scott_title: "共同创始人" # {change}
+    scott_blurb: "理性至上"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+    rob_title: "编译器工程师" # {change}
     rob_blurb: "编代码之类的"
     josh_c_title: "游戏设计师"
     josh_c_blurb: "设计游戏"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "游戏设计师"
+    josh_blurb: "地面是熔岩"
+    retrostyle_title: "插画师"
+    retrostyle_blurb: "复古风格的游戏"
+    jose_title: "音乐"
+    jose_blurb: "放轻松"
     carlos_title: "地区经理, 巴西"
     carlos_blurb: "食草男"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
   teachers:
     who_for_title: "谁是CodeCombat的使用对象呢?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     email_settings_url: "您的电子邮件设置"
     email_description_suffix: "或者我们发送的邮件中的链接,您可以随时更改您的偏好设置或者随时取消订阅。"
     cost_title: "花费"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "版权与许可"
     contributor_title: "贡献者许可协议"
     contributor_description_prefix: "所有对本网站或是GitHub代码库的贡献都依照我们的"
diff --git a/app/locale/zh-HANT.coffee b/app/locale/zh-HANT.coffee
index e44d7d277..52e773049 100644
--- a/app/locale/zh-HANT.coffee
+++ b/app/locale/zh-HANT.coffee
@@ -2,10 +2,10 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
   home:
     slogan: "玩遊戲學程式"
     no_ie: "抱歉!Internet Explorer 8 等舊的瀏覽器打不開此網站" # Warning that only shows up in IE8 and older
-    no_mobile: "CodeCombat不是針對手機設備設計的,所以可能會出問題!" # Warning that shows up on mobile devices
+    no_mobile: "CodeCombat不是針對行動裝置設計的,所以可能會出問題!" # Warning that shows up on mobile devices
     play: "開始遊戲" # The big play button that opens up the campaign view.
 #    play_campaign_version: "Play Campaign Version" # Shows up under big play button if you only play /courses
-    old_browser: "嗯... 您的瀏覽器太老了跑不動CodeCombat,抱歉!" # Warning that shows up on really old Firefox/Chrome/Safari
+    old_browser: "嗯…您的瀏覽器太老了跑不動CodeCombat,抱歉!" # Warning that shows up on really old Firefox/Chrome/Safari
     old_browser_suffix: "您還是可以試試看,但它應該不能運行。"
     ipad_browser: "抱歉,CodeCombat不能在iPad上的瀏覽器運行,但好消息是我們的iPad App正在等待蘋果公司審核。"
     campaign: "戰役"
@@ -71,35 +71,35 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     poll: "投票" # Tooltip on poll button from /play
     next: "下一步" # Go from choose hero to choose inventory before playing a level
     change_hero: "更換英雄" # Go back from choose inventory to choose hero
-    buy_gems: "購買鑽石"
+    buy_gems: "購買寶石"
     subscription_required: "需要訂購"
     anonymous: "匿名玩家"
     level_difficulty: "難度"
 #    play_classroom_version: "Play Classroom Version" # Choose a level in campaign version that you also can play in one of your courses
     campaign_beginner: "新手指南"
-    awaiting_levels_adventurer_prefix: "我們每周將釋出新的關卡。" # {change}
+    awaiting_levels_adventurer_prefix: "我們每週將釋出新的關卡。" # {change}
     awaiting_levels_adventurer: "註冊成為冒險家"
-    awaiting_levels_adventurer_suffix: "成為第一個挑戰新關卡的冒險家吧!"
+    awaiting_levels_adventurer_suffix: "成為第一個挑戰新關卡的冒險家吧!"
     adjust_volume: "調整音量"
     campaign_multiplayer: "多人競技場"
-    campaign_multiplayer_description: "...在這裡您可以和其他玩家進行對戰。"
+    campaign_multiplayer_description: "…在這裡您可以和其他玩家進行對戰。"
     campaign_old_multiplayer: "(過時的)舊多人競技場"
     campaign_old_multiplayer_description: "多個文明時代的遺跡。已沒有模擬運行這些陳舊、英雄蕪絕的多人競技場。"
 
   share_progress_modal:
-    blurb: "您正在建立優秀的進度! 告訴您的家長, 您從CodeCombat學到了什麼!" # {change}
-    email_invalid: "郵件地址無效."
-    form_blurb: "在底下輸入他們的郵件並且我們將秀給他們!"
+    blurb: "您正在建立優秀的進度!告訴您的家長,您從CodeCombat學到了什麼!" # {change}
+    email_invalid: "郵件地址無效"
+    form_blurb: "在底下輸入他們的郵件並且我們將秀給他們!"
     form_label: "郵件地址"
     placeholder: "郵件地址"
-    title: "出色的作品, 學徒"
+    title: "出色的作品,學徒"
 
   login:
     sign_up: "註冊"
     log_in: "登入"
     logging_in: "登入中"
     log_out: "登出"
-    forgot_password: "忘記密碼?"
+    forgot_password: "忘記密碼?"
     authenticate_gplus: "以 Google+ 帳號登入"
     load_profile: "讀取 Google+ 個人簡介"
     finishing: "結束"
@@ -109,19 +109,19 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
 
   signup:
     email_announcements: "通過郵件接收通知"
-    creating: "帳號建立中..."
+    creating: "帳號建立中…"
     sign_up: "註冊"
     log_in: "登入"
     required: "在這麼做之前必須先登入。"
     login_switch: "已經有申請帳號了嗎?"
     school_name: "就讀學校及所在城市"
     optional: "選填"
-    school_name_placeholder: "範例: XX中學, 台北"
+    school_name_placeholder: "範例:XX中學,台北"
 
   recover:
     recover_account_title: "復原帳號"
     send_password: "送出新密碼"
-    recovery_sent: "密碼重置的信件已寄出."
+    recovery_sent: "密碼重置的信件已寄出"
 
   items:
     primary: "主要武器"
@@ -134,9 +134,9 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
   common:
     back: "向後瀏覽" # When used as an action verb, like "Navigate backward"
     continue: "繼續前進" # When used as an action verb, like "Continue forward"
-    loading: "載入中..."
-    saving: "儲存中..."
-    sending: "發送中...."
+    loading: "載入中…"
+    saving: "儲存中…"
+    sending: "發送中…"
     send: "送出"
     cancel: "取消"
     save: "存檔"
@@ -186,7 +186,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     email: "郵件"
     password: "密碼"
     message: "訊息"
-    code: "代碼"
+    code: "程式碼"
     ladder: "升級比賽"
     when: "當"
     opponent: "對手"
@@ -213,18 +213,18 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     hours: "小時"
     day: "日"
     days: "日"
-    week: "周"
-    weeks: "周"
+    week: "週"
+    weeks: "週"
     month: "個月"
     months: "個月"
     year: "年"
     years: "年"
 
   play_level:
-    completed_level: "完成關卡:"
-    course: "課程:"
+    completed_level: "完成關卡:"
+    course: "課程:"
     done: "完成"
-    next_level: "下一個關卡:"
+    next_level: "下一個關卡:"
     next_game: "下一個遊戲"
     show_menu: "顯示遊戲菜單"
     home: "首頁" # Not used any more, will be removed soon.
@@ -235,8 +235,8 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     restart: "重新開始"
     goals: "目標"
     goal: "目標"
-    running: "執行中..."
-    success: "成功!"
+    running: "執行中…"
+    success: "成功!"
     incomplete: "未完成"
     timed_out: "時間用盡"
     failing: "失敗"
@@ -251,25 +251,25 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     victory_title_suffix: "完成"
     victory_sign_up: "保存進度"
     victory_sign_up_poke: "想保存您的程式碼?建立一個免費帳號吧!"
-    victory_rate_the_level: "評估關卡: " # {change}
+    victory_rate_the_level: "評估關卡:" # {change}
     victory_return_to_ladder: "返回升級比賽模式"
     victory_saving_progress: "儲存進度"
     victory_go_home: "返回首頁"
     victory_review: "給我們回饋!"
-    victory_review_placeholder: "關卡如何?"
+    victory_review_placeholder: "關卡如何?"
     victory_hour_of_code_done: "您完成了嗎?"
     victory_hour_of_code_done_yes: "是的,我完成了我的程式碼!"
     victory_experience_gained: "取得經驗值"
     victory_gems_gained: "取得寶石"
     victory_new_item: "新的物品"
-    victory_viking_code_school: "太厲害了, 您剛完成了非常困難的關卡! 如果您想成為一個軟件開發人員,您就應該去試一下Viking Code School。在這裡您可以把您的知識增長到另一個台階。只需要14個星期您就能成為一個專業的網頁開發人員。"
+    victory_viking_code_school: "太厲害了,您剛完成了非常困難的關卡!如果您想成為一個軟體開發人員,您就應該去試一下Viking Code School。在這裡您可以把您的知識增長到另一個台階。只需要14個星期您就能成為一個專業的網頁開發人員。"
     victory_become_a_viking: "成為一個維京人。"
     guide_title: "指南"
     tome_cast_button_run: "運作"
     tome_cast_button_running: "運作中"
     tome_cast_button_ran: "已運作"
     tome_submit_button: "送出"
-    tome_reload_method: "重新載入該方法的原代碼" # Title text for individual method reload button.
+    tome_reload_method: "重新載入該方法的原程式碼" # Title text for individual method reload button.
     tome_select_method: "選擇一個方法"
     tome_see_all_methods: "查看所有可編輯的方法" # Title text for method list selector (shown when there are multiple programmable methods).
     tome_select_a_thang: "選擇一個人物來施放"
@@ -282,67 +282,67 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     loading_ready: "準備!"
     loading_start: "開始戰役"
     problem_alert_title: "修正您的程式碼"
-    time_current: "現在:"
-    time_total: "最大值:"
-    time_goto: "前往:"
+    time_current: "現在:"
+    time_total: "最大值:"
+    time_goto: "前往:"
     non_user_code_problem_title: "無法加載關卡"
-    infinite_loop_title: "檢測到無限循環"
-    infinite_loop_description: "建立世界的初始代碼還沒有運行完畢。這可能是真的很慢或出現無限循環,或者存在一個bug。您可以嘗試再次運行這段代碼,或重置代碼為默認狀態。如果還是解決不了問題,請聯繫我們。"
+    infinite_loop_title: "檢測到無限迴圈"
+    infinite_loop_description: "建立世界的初始程式碼還沒有運行完畢。這可能是真的很慢或出現無限迴圈,或者存在一個bug。您可以嘗試再次運行這段程式碼,或重置程式碼為默認狀態。如果還是解決不了問題,請聯繫我們。"
     check_dev_console: "您也可以打開開發者界面看一下有什麼可能出錯了。"
     check_dev_console_link: "(說明)"
     infinite_loop_try_again: "再試一次"
     infinite_loop_reset_level: "重置關卡"
     infinite_loop_comment_out: "在我的程式碼中加入注解"
     tip_toggle_play: "使用 Ctrl+P 切換 播放/暫停。"
-    tip_scrub_shortcut: "Ctrl+[ 快退; Ctrl+] 快進。"
+    tip_scrub_shortcut: "Ctrl+[ 快退;Ctrl+] 快進。"
     tip_guide_exists: "點擊頁面上方的指南,可獲得更多有用的訊息。"
-    tip_open_source: "「CodeCombat」100% 開源!"
-    tip_tell_friends: "喜歡Codecombat?那就把它介紹給朋友!"
+    tip_open_source: "「CodeCombat」100% 開源!"
+    tip_tell_friends: "喜歡Codecombat?那就把它介紹給朋友!"
     tip_beta_launch: "「CodeCombat」在2013年10月進入 BETA 測試。"
-    tip_think_solution: "思考解決方法而不是問題."
-    tip_theory_practice: "理論上, 理論和實作之間是沒有區別. 但是實作上, 這兩者是有區別的. - Yogi Berra"
-    tip_error_free: "有兩種方式可以寫出沒有錯誤的程式; 但只有第三種可以達到預期效果. - Alan Perlis"
-    tip_debugging_program: "如果除錯是一種清除錯誤的過程, 那麼編寫程式就是一種放置錯誤的過程. - Edsger W. Dijkstra"
-    tip_forums: "前往論壇並且告訴我們您所思考的!"
-    tip_baby_coders: "在未來, 就算小孩也能成為大法師."
-    tip_morale_improves: "直到士氣提升之前,載入的動作將持續."
+    tip_think_solution: "思考解決方法而不是問題。"
+    tip_theory_practice: "理論上,理論和實作之間是沒有區別。但是實作上,這兩者是有區別的。 - Yogi Berra"
+    tip_error_free: "有兩種方式可以寫出沒有錯誤的程式;但只有第三種可以達到預期效果。 - Alan Perlis"
+    tip_debugging_program: "如果除錯是一種清除錯誤的過程,那麼編寫程式就是一種放置錯誤的過程。 - Edsger W. Dijkstra"
+    tip_forums: "前往論壇並且告訴我們您所思考的!"
+    tip_baby_coders: "在未來,就算小孩也能成為大法師。"
+    tip_morale_improves: "直到士氣提升之前,載入的動作將持續。"
     tip_all_species: "我們相信所有民族都有平等的機會學習編寫程式"
     tip_reticulating: "網格狀鋸齒(指卡頓現象)"
-    tip_harry: "巫師, "
-    tip_great_responsibility: "隨著擁有強大的編程技巧,除錯的責任將越大."
-    tip_munchkin: "如果您不吃掉您的蔬菜,那小矮人將在您沈睡時找到您."
-    tip_binary: "只有2種人在這世上: 那些懂2進位的,和哪些不懂得."
-    tip_commitment_yoda: "一個程序員必須擁有強烈的責任感和一顆認真的心. ~ Yoda《星球大戰》"
-    tip_no_try: "做,或者不做。這邊不存在嘗試的選項. - Yoda《星球大戰》"
-    tip_patience: "年輕的學徒,您必須擁有耐心. - Yoda《星球大戰》"
-    tip_documented_bug: "一個寫在文件裡的錯誤不是錯誤;它是功能."
-    tip_impossible: "事情總是看起來不可能直到它成真那刻. - Nelson Mandela"
-    tip_talk_is_cheap: "多說無益,放「碼」過來. - Linus Torvalds"
-    tip_first_language: "您經歷的第一門程式語言是最慘痛的事情. - Alan Kay"
-    tip_hardware_problem: "Q: 換一顆燈泡需要多少位程序員?  A: 一位也不用,它是個硬體問題。"
-    tip_hofstadters_law: "Hofstadter 定律: 完成一件複雜的事花費的時間總是超乎預期, 甚至您早已知道這個現象( Hofstadter 定律)。"
+    tip_harry: "巫師,"
+    tip_great_responsibility: "隨著擁有強大的編程技巧,除錯的責任將越大。"
+    tip_munchkin: "如果您不吃掉您的蔬菜,那小矮人將在您沉睡時找到您。"
+    tip_binary: "只有2種人在這世上:那些懂2進位的,和哪些不懂得。"
+    tip_commitment_yoda: "一個程式員必須擁有強烈的責任感和一顆認真的心。 ~ Yoda《星際大戰》"
+    tip_no_try: "做,或者不做。這邊不存在嘗試的選項。 - Yoda《星際大戰》"
+    tip_patience: "年輕的學徒,您必須擁有耐心。 - Yoda《星際大戰》"
+    tip_documented_bug: "一個寫在文件裡的錯誤不是錯誤;它是功能。"
+    tip_impossible: "事情總是看起來不可能直到它成真那刻。 - Nelson Mandela"
+    tip_talk_is_cheap: "多說無益,放「碼」過來。 - Linus Torvalds"
+    tip_first_language: "您經歷的第一門程式語言是最慘痛的事情。 - Alan Kay"
+    tip_hardware_problem: "Q: 換一顆燈泡需要多少位程式員?  A: 一位也不用,它是個硬體問題。"
+    tip_hofstadters_law: "Hofstadter 定律:完成一件複雜的事花費的時間總是超乎預期,甚至您早已知道這個現象( Hofstadter 定律)。"
     tip_premature_optimization: "過早的優化是萬惡之源。 - Donald Knuth"
-    tip_brute_force: "當您游移不定時, 就是用暴力解。 - Ken Thompson"
-    tip_extrapolation: "只有 2 種人在這世上: 一種人是能夠根據不完整資訊而推斷..."
+    tip_brute_force: "當您游移不定時,就是用暴力解。 - Ken Thompson"
+    tip_extrapolation: "只有 2 種人在這世上:一種人是能夠根據不完整資訊而推斷…"
     tip_superpower: "編程讓我們最接近擁有超能力。"
-    tip_control_destiny: "在真正的開源, 您有權利控制自己的命運。 - Linus Torvalds"
-    tip_no_code: "在速度上,沒有任何代碼可以超過無代碼"
-    tip_code_never_lies: "代碼從不說謊, 但註釋偶爾會。 — Ron Jeffries"
+    tip_control_destiny: "在真正的開源,您有權利控制自己的命運。 - Linus Torvalds"
+    tip_no_code: "在速度上,沒有任何程式碼可以超過無程式碼"
+    tip_code_never_lies: "程式碼從不說謊,但註釋偶爾會。 — Ron Jeffries"
     tip_reusable_software: "在軟體被重複使用前,它必須能用。"
-    tip_optimization_operator: "每種語言都有一個優化的運算符號. 對大部份而言,那符號是‘//’"
-    tip_lines_of_code: "使用代碼行數來管理開發進度就好像使用秤重器來管理建造飛機。 — Bill Gates"
-    tip_source_code: "我想改變世界但他們不給我源代碼"
+    tip_optimization_operator: "每種語言都有一個優化的運算符號。對大部份而言,那符號是‘//’"
+    tip_lines_of_code: "使用程式碼行數來管理開發進度就好像使用秤重器來管理建造飛機。 — Bill Gates"
+    tip_source_code: "我想改變世界但他們不給我原始碼"
     tip_javascript_java: "Java 和 JavaScript 的關係就好比馬和馬雲。 - Chris Heilmann"
-    tip_move_forward: "不論做什麼, 保持前進. - Martin Luther King Jr."
-    tip_google: "擁有一個您不能解決的問題? Google它!"
+    tip_move_forward: "不論做什麼,保持前進。 - Martin Luther King Jr."
+    tip_google: "擁有一個您不能解決的問題?Google它!"
     tip_adding_evil: "增加一個邪惡掐揑。"
-    tip_hate_computers: "關於自我覺得恨透電腦的那群人. 其實他們真正應該恨的事情是糟糕的程序員。 - Larry Niven"
+    tip_hate_computers: "關於自我覺得恨透電腦的那群人。其實他們真正應該恨的事情是糟糕的程式員。 - Larry Niven"
     tip_open_source_contribute: "您可以幫助「CodeCombat」提高!"
     tip_recurse: "迭代者人也,遞歸者神也 - L. Peter Deutsch"
     tip_free_your_mind: "放下一切私心雜念,丟棄害怕、疑問和拒信,解放您的思維。 - 莫菲斯《駭客任務》"
-    tip_strong_opponents: "即使是最强大的對手也有弱点的。 - 宇智波鼬《火影忍者》"
+    tip_strong_opponents: "即使是最强大的對手也有弱點的。 - 宇智波鼬《火影忍者》"
     tip_paper_and_pen: "在您開始編碼之前,您可以隨時用一張紙和一支筆作計劃。"
-    tip_solve_then_write: "要先想清楚問題如何解決, 再進行編碼的動作. - John Johnson"
+    tip_solve_then_write: "要先想清楚問題如何解決,再進行編碼的動作。 - John Johnson"
 
   game_menu:
     inventory_tab: "倉庫"
@@ -354,19 +354,19 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     multiplayer_tab: "多人遊戲"
     auth_tab: "註冊"
     inventory_caption: "裝備您的英雄"
-    choose_hero_caption: "選擇英雄, 語言"
-    save_load_caption: "... 觀看歷史紀錄"
+    choose_hero_caption: "選擇英雄,語言"
+    save_load_caption: "…觀看歷史紀錄"
     options_caption: "設置設定"
     guide_caption: "文件與小撇步"
-    multiplayer_caption: "跟朋友一起玩!"
-    auth_caption: "儲存進度."
+    multiplayer_caption: "跟朋友一起玩!"
+    auth_caption: "儲存進度"
 
   leaderboard:
     view_other_solutions: "查看其他解法"
     scores: "分數"
     top_players: "頂級玩家由"
     day: "今天"
-    week: "這周"
+    week: "這週"
     all: "長期以來"
     time: "時間"
     damage_taken: "遭受的攻擊"
@@ -390,24 +390,24 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     few_gems: "一些寶石"
     pile_gems: "一堆寶石"
     chest_gems: "一箱寶石"
-    purchasing: "購買中..."
+    purchasing: "購買中…"
     declined: "您的信用卡被拒絕"
-    retrying: "伺服器錯誤, 正在重試。"
+    retrying: "伺服器錯誤,正在重試。"
     prompt_title: "寶石不足"
-    prompt_body: "想要取得更多?"
+    prompt_body: "想要取得更多?"
     prompt_button: "進入商店"
     recovered: "先前購買的寶石已回復,請重新載入頁面。"
-    price: "x3500 / 月"
+    price: "x{{gems}} / 月"
 
   subscribe:
-    comparison_blurb: "訂閱 CodeCombat 來磨練您的技巧!"
+    comparison_blurb: "訂閱 CodeCombat 來磨練您的技巧!"
     feature1: "110 個以上的基本關卡散佈在4張地圖中"
-    feature2: "10 個強壯的<strong>新英雄</strong>並每隻都有不同技巧!"
+    feature2: "10 個強壯的<strong>新英雄</strong>並每位都有不同技巧!"
     feature3: "80 個以上的額外關卡"
-    feature4: "每個月<strong>3500顆額外寶石</strong>!"
-    feature5: "視頻教學"
+    feature4: "每個月<strong>{{gems}}顆額外寶石</strong>!"
+    feature5: "影片教學"
     feature6: "頂級信箱支援"
-    feature7: "私人 <strong>部落</strong>"
+    feature7: "私密<strong>部落</strong>"
     free: "免費"
     month: "月"
     must_be_logged: "您需要先登入。請先註冊或者在上方的目錄中點擊登入。"
@@ -417,27 +417,27 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     never_mind: "沒關係,我仍然愛您"
     thank_you_months_prefix: "感謝您這幾個"
     thank_you_months_suffix: "月來的支持"
-    thank_you: "感謝您支持CodeCombat."
-    sorry_to_see_you_go: "捨不得您離開! 請讓我們知道我們如何做得更好."
-    unsubscribe_feedback_placeholder: "我們做錯事了嗎?"
+    thank_you: "感謝您支持CodeCombat"
+    sorry_to_see_you_go: "捨不得您離開!請讓我們知道我們如何做得更好。"
+    unsubscribe_feedback_placeholder: "我們做錯事了嗎?"
     parent_button: "詢問您的父母"
-    parent_email_description: "我們將寄信向他們說明,所以他們能放心幫您訂閱 CodeCombat."
-    parent_email_input_invalid: "信箱位址無效."
+    parent_email_description: "我們將寄信向他們說明,所以他們能放心幫您訂閱 CodeCombat。"
+    parent_email_input_invalid: "信箱位址無效"
     parent_email_input_label: "父母信箱位址"
     parent_email_input_placeholder: "輸入父母信箱"
     parent_email_send: "寄信"
-    parent_email_sent: "已寄信!"
-    parent_email_title: "您父母信箱是?"
+    parent_email_sent: "已寄信!"
+    parent_email_title: "您父母信箱是?"
     parents: "致家長"
-    parents_title: "親愛的家長: 您的孩子將要學習編程. 您會支持孩子發展嗎?"
+    parents_title: "親愛的家長:您的孩子將要學習編程。您會支持孩子發展嗎?"
     parents_blurb1: "您的孩子已經玩了 __nLevels__ 關,並且學習了編程基礎。請您為了培養他們的興趣而給他們訂閱,他們能繼續玩下去。"
-    parents_blurb1a: "不要懷疑計算機編程能力將是您的孩子作為一個成年人的基本技能。到2020年,77%的工作將會需要編碼能力,並且軟件工程師將在世界各地成為高需求職業。您知道要計算機科學是收入最高的大學學位。"
-    parents_blurb2: "每月支付 ${{price}} 美金, 他們每週獲得新挑戰以及使用信件取得專業程式員的幫助。"
-    parents_blurb3: "沒有風險: 保證 100% 退費, 一步取消訂閱。"
+    parents_blurb1a: "不要懷疑計算機編程能力將是您的孩子作為一個成年人的基本技能。到2020年,77%的工作將會需要編碼能力,並且軟體工程師將在世界各地成為高需求職業。您知道要計算機科學是收入最高的大學學位。"
+    parents_blurb2: "每月支付 ${{price}} 美金,他們每週獲得新挑戰以及使用信件取得專業程式員的幫助。"
+    parents_blurb3: "沒有風險:保證 100% 退費,一步取消訂閱。"
     payment_methods: "付費方法"
     payment_methods_title: "可接受的付款方式"
     payment_methods_blurb1: "我們現有的付費方式有信用卡和支付寶" # {change}
-    payment_methods_blurb2: "如果您想用其他付費方式,請聯繫我們"
+    payment_methods_blurb2: "如果您想用其他付費方式,請聯繫我們"
     sale_button: "促銷!"
     sale_button_title: "年費訂閱能節省 ${{discount}} 的費用"
     stripe_description: "每月訂閱"
@@ -445,16 +445,16 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     subscription_required_to_play: "您將需要訂閱來開啟這關。"
     unlock_help_videos: "訂閱來解開所有鎖住得教學影片。"
     personal_sub: "個人訂閱" # Accounts Subscription View below
-    loading_info: "正在加載訂閱內容···"
+    loading_info: "正在加載訂閱內容…"
     managed_by: "管理"
     will_be_cancelled: "將被取消"
     currently_free: "您目前有一個免費訂閱"
     currently_free_until: "您目前有一個訂閱,直到"
     was_free_until: "您有過一個免費訂閱,直到"
     managed_subs: "管理訂閱"
-    subscribing: "訂閱中・・・"
+    subscribing: "訂閱中…"
     current_recipients: "當前收件人"
-    unsubscribing: "取消訂閱中・・・" # {change}
+    unsubscribing: "取消訂閱中…" # {change}
     subscribe_prepaid: "點擊訂閱來使用預付代碼"
     using_prepaid: "使用預付費代碼進行每月訂閱"
 
@@ -474,8 +474,8 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     hero_type: "種類"
     weapons: "武器"
     weapons_warrior: "刀劍 - 短距離、非魔法"
-    weapons_ranger: "十字弓, 槍砲 - 長距離、非魔法"
-    weapons_wizard: "魔杖, 法杖 - 長距離、魔法"
+    weapons_ranger: "十字弓、槍砲 - 長距離、非魔法"
+    weapons_wizard: "魔杖、法杖 - 長距離、魔法"
     attack: "傷害" # Can also translate as "Attack"
     health: "血量"
     speed: "速度"
@@ -493,7 +493,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     speed_1: "移動速度"
     speed_2: "公尺每秒。"
     available_for_purchase: "可以購買" # Shows up when you have unlocked, but not purchased, a hero in the hero store
-    level_to_unlock: "解鎖關卡:" # Label for which level you have to beat to unlock a particular hero (click a locked hero in the store to see)
+    level_to_unlock: "解鎖關卡:" # Label for which level you have to beat to unlock a particular hero (click a locked hero in the store to see)
     restricted_to_certain_heroes: "特定英雄才可遊玩此關卡。"
 
   skill_docs:
@@ -539,11 +539,11 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     editor_config_behaviors_description: "自動填入小括號、大括號以及引號。"
 
   about:
-    why_codecombat: "為什麼使用CodeCombat?"
-    why_paragraph_1: "想學程式嗎? 您不需要課程。您需要的只是大量的時間去\"玩\"程式。"
+    why_codecombat: "為什麼使用CodeCombat?"
+    why_paragraph_1: "想學程式嗎?您不需要課程。您需要的只是大量的時間去\"玩\"程式。"
     why_paragraph_2_prefix: "寫程式應該是有趣的。當然不是"
     why_paragraph_2_italic: "「耶!拿到獎章了。」"
-    why_paragraph_2_center: "的有趣, 而是"
+    why_paragraph_2_center: "的有趣,而是"
     why_paragraph_2_italic_caps: "「媽我不要出去玩,我要寫完這段!」"
     why_paragraph_2_suffix: "般引人入勝。這是為甚麼CodeCombat被設計成多人對戰「遊戲」,而不是遊戲化「課程」。在您對這遊戲無法自拔之前,我們是不會放棄的─當然,這個遊戲,將是有益於您的。"
     why_paragraph_3: "如果您要沉迷遊戲的話,就來沉迷CodeCombat,成為科技時代的魔法師吧!"
@@ -552,38 +552,36 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     press_paragraph_1_link: "新聞稿懶人包"
     press_paragraph_1_suffix: ",裡面所有的LOGO和圖片都可以使用,並且不必另外知會我們。"
     team: "製作團隊"
-    george_title: "共同創辦人"
-    george_blurb: "商人"
-    scott_title: "共同創辦人"
-    scott_blurb: "理性至上"
-    nick_title: "程式員"
+    nick_title: "程式員" # {change}
     nick_blurb: "亢奮的Guru"
-    michael_title: "共同創辦人"
-    michael_blurb: "系統管理員"
-    matt_title: "共同創辦人"
+    matt_title: "共同創辦人" # {change}
     matt_blurb: "競速單車玩家"
-    cat_title: "首席開卡設計師"
+    cat_title: "首席開卡設計師" # {change}
     cat_blurb: "氣宗"
-    josh_title: "遊戲設計師"
-    josh_blurb: "地面是熔岩"
-    jose_title: "音樂"
-    jose_blurb: "放輕鬆"
-    retrostyle_title: "插畫師"
-    retrostyle_blurb: "復古風格的遊戲"
-    rob_title: "編譯工程師"
-    rob_blurb: "編寫一些的代碼"
-    josh_c_title: "遊戲設計師"
-    josh_c_blurb: "設計遊戲"
-    carlos_title: "區經理 - 巴西"
-#    carlos_blurb: "Celery Man"
+    scott_title: "共同創辦人" # {change}
+    scott_blurb: "理性至上"
 #    maka_title: "Customer Advocate"
 #    maka_blurb: "Storyteller"
+    rob_title: "編譯工程師" # {change}
+    rob_blurb: "編寫一些的程式碼"
+    josh_c_title: "遊戲設計師"
+    josh_c_blurb: "設計遊戲"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+    josh_title: "遊戲設計師"
+    josh_blurb: "地面是熔岩"
+    retrostyle_title: "插畫師"
+    retrostyle_blurb: "復古風格的遊戲"
+    jose_title: "音樂"
+    jose_blurb: "放輕鬆"
+    carlos_title: "區經理 - 巴西"
+#    carlos_blurb: "Celery Man"
 
   teachers:
     who_for_title: "誰是CodeCombat的使用對象呢?"
     who_for_1: "我們建議讓9歲及以上的學生使用CodeCombat。無需任何編程經驗。" # {change}
     who_for_2: "我們設計CodeCombat來吸引男生女生。" # {change}
-    more_info_title: "我可以在哪裡找到更多信息?"
+    more_info_title: "我可以在哪裡找到更多訊息?"
     more_info_1: "我們的"
     more_info_2: "教師論壇"
     more_info_3: "是個與其他使用CodeCombat的教育工作者聯繫的良好平台。"
@@ -591,7 +589,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
   teachers_survey:
     title: "教師調查"
     must_be_logged: "您需要先登入。請先註冊或者在上方的目錄中點擊登入。"
-    retrieving: "檢索信息中..."
+    retrieving: "檢索資料中…"
     being_reviewed_1: "您的免費訂閱試用申請正在" # {change}
     being_reviewed_2: "審核。"
     approved_1: "您的免費訂閱試用申請已被" # {change}
@@ -603,7 +601,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     denied_2: "拒絕。"
     contact_1: "請聯繫"
     contact_2: "如果您有更多的疑問。"
-    description_1: "我們為教師提供免費訂閱用評估的目的。您可以找到更多的信息在我們的"
+    description_1: "我們為教師提供免費訂閱用評估的目的。您可以找到更多的訊息在我們的"
 #    description_1b: "You can find more information on our"
     description_2: "教師"
     description_3: "頁面。"
@@ -613,7 +611,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     location: "城市"
     age_students: "您的學生年齡為多少?"
     under: "低於"
-    other: "其他:"
+    other: "其他:"
     amount_students: "請問您有多少學生需要教導?"
     hear_about: "您是怎麼知道CodeCombat的?"
     fill_fields: "請填寫所有問題。"
@@ -622,27 +620,27 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
   versions:
     save_version_title: "保存新版本"
     new_major_version: "新的重要版本"
-    submitting_patch: "正在提交修補..."
-    cla_prefix: "想保存修改, 您必須先保存我們的"
+    submitting_patch: "正在提交修補…"
+    cla_prefix: "想保存修改,您必須先保存我們的"
     cla_url: "貢獻者許可協議"
     cla_suffix: "。"
     cla_agree: "我同意"
-    owner_approve: "您所做出的修改必须经拥有者确认才能生效。"
+    owner_approve: "您所做出的修改必須經擁有者確認才能生效。"
 
   contact:
     contact_us: "聯繫我們"
-    welcome: "很高興收到您的信!用這個表格給我們發電郵。 "
-    forum_prefix: "如果有任何問題, 請至"
+    welcome: "很高興收到您的信!用這個表格給我們發電郵。"
+    forum_prefix: "如果有任何問題,請至"
     forum_page: "論壇"
     forum_suffix: "討論。"
     faq_prefix: "這裡還有一個"
     faq: "FAQ"
-    subscribe_prefix: "如果您需要幫助來解決關卡, 請"
+    subscribe_prefix: "如果您需要幫助來解決關卡,請"
     subscribe: "訂閱CodeCombat"
-    subscribe_suffix: "並且我們樂意提供代碼相關的協助."
-    subscriber_support: "您已經是個CodeCombat訂閱者, 我們將提供優先的協助."
-    screenshot_included: "包含螢幕截圖."
-    where_reply: "我們回覆到?"
+    subscribe_suffix: "並且我們樂意提供程式碼相關的協助。"
+    subscriber_support: "您已經是個CodeCombat訂閱者,我們將提供優先的協助。"
+    screenshot_included: "包含螢幕截圖。"
+    where_reply: "我們回覆到?"
     send: "意見反饋"
 
   account_settings:
@@ -666,7 +664,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     new_password: "新密碼"
     new_password_verify: "確認密碼"
     type_in_email: "輸入您的Email來確認刪除"
-    type_in_email_progress: "輸入您的Email, 確認您真的要刪除進度"
+    type_in_email_progress: "輸入您的Email,確認您真的要刪除進度"
     type_in_password: "還有輸入您的密碼。"
     email_subscriptions: "訂閱"
     email_subscriptions_none: "無Email訂閱"
@@ -682,7 +680,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     contributor_emails: "貢獻者電郵"
     contribute_prefix: "我們在尋找志同道合的人!請到 "
     contribute_page: "貢獻頁面"
-    contribute_suffix: " 查看更多信息。"
+    contribute_suffix: " 查看更多訊息。"
     email_toggle: "全選"
     error_saving: "保存時發生錯誤"
     saved: "修改已儲存"
@@ -707,20 +705,20 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     toggle_debug: "顯示/關閉除錯訊息"
     toggle_grid: "顯示/關閉網格提示"
     toggle_pathfinding: "顯示/關閉路徑尋找提示"
-    beautify: "利用標準格式來美化您的代碼"
-    maximize_editor: "最大化/最小化代碼編輯器"
+    beautify: "利用標準格式來美化您的程式碼"
+    maximize_editor: "最大化/最小化程式碼編輯器"
 
   community:
     main_title: "CodeCombat社群"
-    introduction: "查看您可能可以參與的項目以及選擇最吸引您的項目. 我們期待與您一起工作!"
+    introduction: "查看您可能可以參與的項目以及選擇最吸引您的項目。我們期待與您一起工作!"
     level_editor_prefix: "使用CodeCombat"
-    level_editor_suffix: "來創造和編輯關卡。 許多人已經創造關卡用在課堂或黑客松,或者給予朋友或兄弟姐妹。如果您覺得創建一個全新的關卡非常困難,您可以先從現成的開始做起!"
-    thang_editor_prefix: "我們稱呼遊戲中的單位叫'thangs'。 使用"
-    thang_editor_suffix: "來修改CodeCombat的原材料。 讓遊戲中的東西可以扔砲彈,修改遊戲動畫的方向,調整單位的生命值,或者上傳自製的素材。"
-    article_editor_prefix: "看到有錯誤在我們的文件中嗎? 想要自己設計指令嗎? 查看我們的"
-    article_editor_suffix: "以及幫助CodeCombat玩家獲得更多知識在遊戲中。"
-    find_us: "通過這些網站連繫我們"
-    social_github: "在GitHub上查看我們的代碼"
+    level_editor_suffix: "來創造和編輯關卡。許多人已經創造關卡用在課堂或黑客松,或者給予朋友或兄弟姊妹。如果您覺得創建一個全新的關卡非常困難,您可以先從現成的開始做起!"
+    thang_editor_prefix: "我們稱呼遊戲中的單位叫'thangs'。使用"
+    thang_editor_suffix: "來修改CodeCombat的原材料。讓遊戲中的東西可以扔砲彈,修改遊戲動畫的方向,調整單位的生命值,或者上傳自製的素材。"
+    article_editor_prefix: "看到有錯誤在我們的文件中嗎?想要自己設計指令嗎?查看我們的"
+    article_editor_suffix: "以及幫助CodeCombat玩家在遊戲中獲得更多知識。"
+    find_us: "透過這些網站連繫我們"
+    social_github: "在GitHub上查看我們的程式碼"
     social_blog: "閱讀CodeCombat在Sett上的部落格"
     social_discource: "加入我們在Discourse論壇上的討論"
     social_facebook: "關注CodeCombat的Facebook"
@@ -734,22 +732,22 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     clans: "部落"
     new_name: "新部落的名字"
     new_description: "新部落的描述"
-    make_private: "設定部落為私人"
+    make_private: "設定部落為私密"
     subs_only: "只限訂閱"
-    create_clan: "創建新的部落"
+    create_clan: "建立新的部落"
     private_preview: "預覽"
-#    private_clans: "Private Clans"
+    private_clans: "私密部落"
     public_clans: "公共部落"
     my_clans: "我的部落"
     clan_name: "部落名字"
     name: "名字"
     chieftain: "首領"
     type: "種類"
-    edit_clan_name: "編輯部落的名字"
+    edit_clan_name: "編輯部落的名稱"
     edit_clan_description: "編輯部落的描述"
-    edit_name: "編輯名字"
+    edit_name: "編輯名稱"
     edit_description: "編輯描述"
-    private: "私人"
+    private: "私密"
     summary: "綜述"
     average_level: "平均等級"
     average_achievements: "平均成就"
@@ -787,7 +785,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     track_concepts6b: "按姓名或進度排序成員"
     track_concepts7: "需要邀請"
     track_concepts8: "來加入"
-#    private_require_sub: "Private clans require a subscription to create or join."
+    private_require_sub: "需要訂閱才可以建立或加入私密部落"
 
   courses:
     course: "課程"
@@ -828,8 +826,8 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     send_invites: "發送邀請"
     title: "標題"
     description: "描述"
-    creating_class: "課堂創建中···"
-    purchasing_course: "購買課程中···"
+    creating_class: "課堂創建中…"
+    purchasing_course: "購買課程中…"
     buy_course: "購買課程"
     buy_course1: "購買這個課程"
     create_class: "創建課堂"
@@ -850,7 +848,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     teachers_click: "老師點擊這裡"
     students_click: "學生點擊這裡"
     courses_on_coco: "CodeCombat上的課程"
-    designed_to: "CodeCombat課程的宗旨是在使用CodeCombat生動有趣的環境下教授計算機科學的課目。整個CodeCombat的關卡是圍繞著計算機科學的重點,並激勵學生們自主向上學習在5小時的過程內。"
+    designed_to: "CodeCombat課程的宗旨是在使用CodeCombat生動有趣的環境下教授計算機科學的課目。整個CodeCombat的關卡是圍繞著計算機科學的重點,並激勵學生們在5小時的過程內自主向上學習。"
     more_in_less: "以最少的時間學習最多的知識"
     no_experience: "無需編程經驗"
     easy_monitor: "容易管理學生的進程"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1020,19 +1018,19 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     archmage_summary: "如果您是個在coding教育遊戲有興趣的開發者,成為大法師來幫助我們建立CodeCombat!"
     artisan_title: "工匠"
     artisan_title_description: "(Level Builder)"
-    artisan_summary: "建造遊戲關卡並且分享給您的朋友們。 成為工匠來幫助其他人學習編程。"
+    artisan_summary: "建造遊戲關卡並且分享給您的朋友們。成為工匠來幫助其他人學習編程。"
     adventurer_title: "冒險家"
     adventurer_title_description: "(Level Playtester)"
-    adventurer_summary: "提前一周免費取得我們新的關卡(甚至是訂閱的內容)並且提前在釋出前幫助我們找出錯誤。"
+    adventurer_summary: "提前一週免費取得我們新的關卡(甚至是訂閱的內容)並且提前在釋出前幫助我們找出錯誤。"
     scribe_title: "文書"
     scribe_title_description: "(Article Editor)"
-    scribe_summary: "好的程式需要好的文件。 來自全世界數百萬的玩家一起編寫, 編輯和提升文件的可讀性。"
+    scribe_summary: "好的程式需要好的文件。來自全世界數百萬的玩家一起編寫,編輯和提升文件的可讀性。"
     diplomat_title: "外交官"
     diplomat_title_description: "(Translator)"
-    diplomat_summary: "借由我們的外交官,CodeCombat已翻譯到45種以上的語言。 幫助我們並且貢獻翻譯。"
+    diplomat_summary: "藉由我們的外交官,CodeCombat已翻譯到45種以上的語言。幫助我們並且貢獻翻譯。"
     ambassador_title: "使節"
     ambassador_title_description: "(Support)"
-    ambassador_summary: "安撫我們論壇的用戶並且提供發問者適當的方向。 我們的使節代表CodeCombat面對全世界。"
+    ambassador_summary: "安撫我們論壇的用戶並且提供發問者適當的方向。我們的使節代表CodeCombat面對全世界。"
 
   editor:
     main_title: "CodeCombat編輯器"
@@ -1054,7 +1052,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     small: "小的"
     large: "大的"
     fork_title: "產生新分支"
-    fork_creating: "產生分支中..."
+    fork_creating: "產生分支中…"
     generate_terrain: "產生地形"
     more: "更多"
     wiki: "維基"
@@ -1062,7 +1060,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     thang_main: "主要"
     thang_spritesheets: "圖集"
     thang_colors: "顏色"
-    level_some_options: "有哪些選項?"
+    level_some_options: "有哪些選項?"
     level_tab_thangs: "物體"
     level_tab_scripts: "腳本"
     level_tab_settings: "設定"
@@ -1111,8 +1109,8 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     level_search_title: "在這搜尋關卡"
     achievement_search_title: "搜尋成就"
     poll_search_title: "搜尋投票"
-    read_only_warning2: "注意: 您不能在這儲存任何編輯, 因為您尚未登入."
-    no_achievements: "尚未有任何成就加入到這關卡中."
+    read_only_warning2: "注意:您不能在這儲存任何編輯,因為您尚未登入。"
+    no_achievements: "尚未有任何成就加入到這關卡中。"
     achievement_query_misc: "關閉成就欄的雜項"
     achievement_query_goals: "關閉成就欄的關卡目標"
     level_completion: "關卡完成"
@@ -1131,81 +1129,81 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
 
   contribute:
     page_title: "貢獻"
-    intro_blurb: "CodeCombat 是 100% 開源! 上百位專注的玩家已經幫助我們建造到今天的程度. 加入我們並完成下一章 CodeCombat 的冒險給全世界參與!"
-    alert_account_message_intro: "您好!"
-    alert_account_message: "為了訂閱課程信件, 您將必須先登入."
-    archmage_introduction: "在建造遊戲中,其中一個最美好的事情是需要整合許多不同東西:圖像、 聲音、及時網路和社群網路。以及許多不同層面的編程,從底層數據庫管理,到用戶界面的設計和實現。 這裡有許多事情需要完成, 如果您是個有經驗的程序員並且熱衷于深入處理 CodeCombat 的本質,那麼這職業就是為您打造的。 我們將很高興擁有您的幫助來打造有史以來最優質的編程遊戲。"
+    intro_blurb: "CodeCombat 是 100% 開源!上百位專注的玩家已經幫助我們建造到今天的程度。加入我們並完成下一章 CodeCombat 的冒險給全世界參與!"
+    alert_account_message_intro: "您好!"
+    alert_account_message: "為了訂閱課程信件,您將必須先登入。"
+    archmage_introduction: "在建造遊戲中,其中一個最美好的事情是需要整合許多不同東西:圖像、 聲音、及時網路和社群網路。以及許多不同層面的編程,從底層數據庫管理,到用戶界面的設計和實現。這裡有許多事情需要完成,如果您是個有經驗的程式員並且熱衷於深入處理 CodeCombat 的本質,那麼這職業就是為您打造的。我們將很高興擁有您的幫助來打造有史以來最優質的編程遊戲。"
     class_attributes: "職業說明"
-    archmage_attribute_1_pref: "熟悉于"
-    archmage_attribute_1_suf: ", 或者渴望去學習。 我們大部份的程式以這個語言寫成。 如果您是個 Ruby 或 Python 的粉絲, 您將感覺到歸屬感。 它是個JavaScript, 但是擁有更佳的文法。"
-    archmage_attribute_2: "一些程式經驗和個人的衝勁。 我們將幫助您找到方向, 但是我們不會花費太多時間訓練您。"
+    archmage_attribute_1_pref: "熟悉於"
+    archmage_attribute_1_suf: ",或者渴望去學習。我們大部份的程式以這個語言寫成。如果您是個 Ruby 或 Python 的粉絲,您將感覺到歸屬感。它是個JavaScript,但是擁有更佳的文法。"
+    archmage_attribute_2: "一些程式經驗和個人的衝勁。我們將幫助您找到方向,但是我們不會花費太多時間訓練您。"
     how_to_join: "如何加入"
-    join_desc_1: "任何人都可加入我們! 只需確認我們的"
-    join_desc_2: "來開始, 並且勾選底下的條件來宣告您成為勇敢的大法師和借由郵件獲得我們最新的消息。 想要討論可做的事或者更加深入地參與? "
-    join_desc_3: ", 或者找到我們在"
-    join_desc_4: "讓我們從這開始!"
+    join_desc_1: "任何人都可加入我們!只需確認我們的"
+    join_desc_2: "來開始,並且勾選底下的條件來宣告您成為勇敢的大法師和藉由郵件獲得我們最新的消息。想要討論可做的事或者更加深入地參與?"
+    join_desc_3: ",或者找到我們在"
+    join_desc_4: "讓我們從這開始!"
     join_url_email: "發信給我們"
     join_url_hipchat: "公共的Slack房間"
     archmage_subscribe_desc: "取得郵件關於新的編程機會和公告。"
-    artisan_introduction_pref: "我們必須建造更多的關卡! 大家為了更多的內容在高聲吶喊, 但只靠我們只能建造這麼多。 現在您的工作場所就是一關; 我們的關卡編輯器是勉強可用的, 所以請小心. 只要您有新的靈感,不論從簡單的 for-loops 到"
-    artisan_introduction_suf: ", 那個這職業會適合您。"
-    artisan_attribute_1: "任何的創建內容經驗都是加分的, 例如使用過Blizzard的關卡編輯器。 但不是必須的!"
-    artisan_attribute_2: "渴望去完成許多測試和迭代。 為了製作好關卡, 您需要把它交給別人去玩並且觀察他們如何玩, 之後準備找到一堆東西去修改。"
-    artisan_attribute_3: "暫且擁有探險者般的忍耐力。 我們的關卡編輯器非常的陽春,有些地方非常不易使用。 我們已經提前告知囉!"
-    artisan_join_desc: "按照以下步驟使用關卡編輯器:"
+    artisan_introduction_pref: "我們必須建造更多的關卡!大家為了更多的內容在高聲吶喊,但只靠我們只能建造這麼多。現在您的工作場所就是一關;我們的關卡編輯器是勉強可用的,所以請小心。只要您有新的靈感,不論從簡單的 for-loops 到"
+    artisan_introduction_suf: ",那個這職業會適合您。"
+    artisan_attribute_1: "任何的創建內容經驗都是加分的,例如使用過Blizzard的關卡編輯器。但不是必須的!"
+    artisan_attribute_2: "渴望去完成許多測試和迭代。為了製作好關卡,您需要把它交給別人去玩並且觀察他們如何玩,之後準備找到一堆東西去修改。"
+    artisan_attribute_3: "暫且擁有探險者般的忍耐力。我們的關卡編輯器非常的陽春,有些地方非常不易使用。我們已經提前告知囉!"
+    artisan_join_desc: "按照以下步驟使用關卡編輯器:"
     artisan_join_step1: "閱讀文擋。"
     artisan_join_step2: "創建新的關卡並且探索已存在的關卡。"
     artisan_join_step3: "在公共的Slack房間裡找到我們尋求幫助。"
     artisan_join_step4: "公佈您的關卡到論壇中尋求回饋。"
     artisan_subscribe_desc: "取得郵件關於關卡編輯器更新和公告。"
-    adventurer_introduction: "讓我們清楚的定義您的角色: 您是部坦克。 您將遭受許多傷害。 我們需要玩家來嘗試我們全新的關卡並且幫助我們找出如何讓事情變得更好。 那痛苦將是巨大的; 製作優秀的遊戲是個長遠的過程並且沒有人可以第一次就把事情做對。 如果您可以忍受並且抵抗力高, 那麼這職業也許適合您。"
-    adventurer_attribute_1: "渴望學習。 您想要學習如何編程並且我們想要教導您如何編程。 儘管您將可能在這情況中獨自完成大部分教學。"
-    adventurer_attribute_2: "魅力十足的。 直率但如紳士般的指出需要改進的地方, 並且提供如何改進的建議。"
-    adventurer_join_pref: "無論是與其餘工匠們一起共事, 或者勾選底下的條件來借由郵件獲得我們最新需要測試的關卡。 我們也將公佈需要評估的關卡在我們的網站上,例如:"
+    adventurer_introduction: "讓我們清楚的定義您的角色:您是部坦克。您將遭受許多傷害。我們需要玩家來嘗試我們全新的關卡並且幫助我們找出如何讓事情變得更好。那痛苦將是巨大的;製作優秀的遊戲是個長遠的過程並且沒有人可以第一次就把事情做對。如果您可以忍受並且抵抗力高,那麼這職業也許適合您。"
+    adventurer_attribute_1: "渴望學習。您想要學習如何編程並且我們想要教導您如何編程。儘管您將可能在這情況中獨自完成大部分教學。"
+    adventurer_attribute_2: "魅力十足的。直率但如紳士般的指出需要改進的地方,並且提供如何改進的建議。"
+    adventurer_join_pref: "無論是與其餘工匠們一起共事,或者勾選底下的條件來藉由郵件獲得我們最新需要測試的關卡。我們也將公佈需要評估的關卡在我們的網站上,例如:"
     adventurer_forum_url: "我們的論壇"
-    adventurer_join_suf: "所以如果您更加喜歡借由這方式被通知, 在那些網站上登錄吧!"
+    adventurer_join_suf: "所以如果您更加喜歡藉由這方式被通知,在那些網站上登錄吧!"
     adventurer_subscribe_desc: "當有新關卡需要測試時取得郵件。"
-    scribe_introduction_pref: "CodeCombat不只是將擁有一堆關卡。 它將也包含知識資源, 一種充滿編程概念的wiki並且每道關卡都將蘊含著這樣的概念。 在這概念下, 不只每位工匠必須描述針對每個細節提出講解, 他們製作的關卡還可以簡單地和wiki中的編程概念產生連結。 某些東西已經在"
+    scribe_introduction_pref: "CodeCombat不只是將擁有一堆關卡。它將也包含知識資源,一種充滿編程概念的wiki並且每道關卡都將蘊含著這樣的概念。在這概念下,不只每位工匠必須描述針對每個細節提出講解,他們製作的關卡還可以簡單地和wiki中的編程概念產生連結。某些東西已經在"
     scribe_introduction_url_mozilla: "Mozilla 開發者社群"
-    scribe_introduction_suf: "完成。 如果您的有趣意見是可以在 Markdown 形式下闡述編程概念, 那麼這職業也許適合您。"
-    scribe_attribute_1: "文字的技巧幾乎是您全部所需要的。 不只是文法和拼字, 但還需傳達複雜概念給閱讀的人。"
+    scribe_introduction_suf: "完成。如果您的有趣意見是可以在 Markdown 形式下闡述編程概念,那麼這職業也許適合您。"
+    scribe_attribute_1: "文字的技巧幾乎是您全部所需要的。不只是文法和拼字,但還需傳達複雜概念給閱讀的人。"
     contact_us_url: "聯繫我們"
-    scribe_join_description: "告訴我們更多關於您的資訊, 您的編程經驗和一些您喜歡寫下的東西。 我們將從這些地方開始!"
+    scribe_join_description: "告訴我們更多關於您的資訊,您的編程經驗和一些您喜歡寫下的東西。我們將從這些地方開始!"
     scribe_subscribe_desc: "取得公告關於寫作文章的郵件。"
-    diplomat_introduction_pref: "所以, 如果說我們從"
+    diplomat_introduction_pref: "所以,如果說我們從"
     diplomat_launch_url: " 十月的那次上線 "
-    diplomat_introduction_suf: "中得到了怎樣的啟發: 那就是在許多國家有許多人對CodeCombat產生興趣! 我們正在建立一群翻譯者,急於將一組組的英文翻譯成各國語言讓CodeCombat可以讓全世界更多人都可以接觸。 如果您喜歡搶先閱讀新內容並且讓您的國人都可以儘速的擁有, 那麼這職業也許適合您。"
-    diplomat_attribute_1: "擁有流利的英文並且喜歡翻譯某種語言。 當傳遞複雜想法時, 您必須這兩種語言都是熟悉的!"
-    diplomat_i18n_page_prefix: "您可以開始從我們的"
+    diplomat_introduction_suf: "中得到了怎樣的啟發:那就是在許多國家有許多人對CodeCombat產生興趣!我們正在建立一群翻譯者,急於將一組組的英文翻譯成各國語言讓CodeCombat可以讓全世界更多人都可以接觸。如果您喜歡搶先閱讀新內容並且讓您的國人都可以儘速的擁有,那麼這職業也許適合您。"
+    diplomat_attribute_1: "擁有流利的英文並且精通欲翻譯的語言。當傳遞複雜想法時,您必須融會貫通這兩種語言!"
+    diplomat_i18n_page_prefix: "您可以從我們的"
     diplomat_i18n_page: " 翻譯頁面 "
-    diplomat_i18n_page_suffix: "翻譯我們的關卡, 或者從我們在 GitHub 上的頁面。"
+    diplomat_i18n_page_suffix: "開始翻譯我們的關卡,或者在 GitHub 翻譯我們的介面及網站。"
     diplomat_join_pref_github: "在"
     diplomat_github_url: " GitHub "
-    diplomat_join_suf_github: "找到您的語言文件 (繁體中文的是: codecombat/app/locale/zh-HANT.coffee), 在線編輯它, 並且上傳一個 pull 請求。 另外, 勾選底下的條件來借由郵件獲得及時的國際化開發!"
+    diplomat_join_suf_github: "找到您的語言文件 (繁體中文的是:codecombat/app/locale/zh-HANT.coffee),在線編輯它,並且上傳一個 pull 請求。另外,勾選底下的方框以藉由郵件獲得及時的國際化開發!"
     diplomat_subscribe_desc: "取得國際化開發和待翻譯關卡的郵件。"
-    ambassador_introduction: "這是個我們正在建立的社群, 您將是我們與世界的連接點。 我們在論壇, 郵件, 社群網路上和許多人交談並且幫助彼此熟悉遊戲以及互相學習。 如果您想要幫助其它人參與並且從中獲得許多樂趣, 以及樂於感受CodeCombat的脈搏和我們將前往的地方, 那麼這職業也許適合您。"
-    ambassador_attribute_1: "溝通技巧。 可以找到玩家正面臨的問題並且幫助他們解決。 另外, 保持與我們聯繫玩家們討論的, 喜愛的, 厭惡的以及想要的!"
-    ambassador_join_desc: "告訴我們更多關於您的資訊, 您已完成的事情和您喜歡做的事情。 我們將從這些地方開始!"
+    ambassador_introduction: "這是個我們正在建立的社群,您將是我們與世界的連接點。我們在論壇、郵件、社群網路上和許多人交談並且幫助彼此熟悉遊戲以及互相學習。如果您想要幫助其他人參與並且從中獲得許多樂趣,以及樂於感受CodeCombat的脈搏和我們將前往的地方,那麼這職業也許適合您。"
+    ambassador_attribute_1: "溝通技巧。可以找到玩家正面臨的問題並且幫助他們解決。另外,保持與我們聯繫玩家們討論的、喜愛的、厭惡的以及想要的!"
+    ambassador_join_desc: "告訴我們更多關於您的資訊,您已完成的事情和您喜歡做的事情。我們將從這些地方開始!"
     ambassador_join_note_strong: "注意"
-    ambassador_join_note_desc: "其中一件我們優先要做的事情是建立多人連線, 玩家將面臨獨自難以解決的關卡而且可以招喚更高等級的法師來幫助。 這將對於使節是一個很棒的方式來完成自己的責任。 我們會及時地向大家公佈!"
+    ambassador_join_note_desc: "其中一件我們優先要做的事情是建立多人連線,玩家將面臨難以獨自解決的關卡而且可以招喚更高等級的法師來幫助。這將對於使節是一個很棒的方式來完成自己的責任。我們會及時地向大家公佈!"
     ambassador_subscribe_desc: "取得更新和多人連線開發的郵件。"
-    changes_auto_save: "當您勾選後, 改變將自動儲存。"
-    diligent_scribes: "我們勤奮的文書:"
-    powerful_archmages: "我們強勁的大法師:"
-    creative_artisans: "我們創意的工匠:"
-    brave_adventurers: "我們勇敢的冒險家:"
-    translating_diplomats: "我們翻譯中的外交官:"
-    helpful_ambassadors: "我們善於幫助的使節:"
+    changes_auto_save: "當您勾選後,改變將自動儲存。"
+    diligent_scribes: "我們勤奮的文書:"
+    powerful_archmages: "我們強勁的大法師:"
+    creative_artisans: "我們創意的工匠:"
+    brave_adventurers: "我們勇敢的冒險家:"
+    translating_diplomats: "我們翻譯中的外交官:"
+    helpful_ambassadors: "我們善於幫助的使節:"
 
   ladder:
-    please_login: "在參與對弈前請先登入."
+    please_login: "在參與對弈前請先登入。"
     my_matches: "我的對手"
     simulate: "模擬"
-    simulation_explanation: "通過模擬遊戲,您可以使您的遊戲更快得到評分!"
+    simulation_explanation: "通過模擬遊戲,您可以使您的遊戲更快得到評分!"
     simulation_explanation_leagues: "你會主要給在你的部落或者課程的同伴幫忙模擬遊戲。"
-    simulate_games: "模擬遊戲!"
-    games_simulated_by: "您模擬過的次數:"
-    games_simulated_for: "替您模擬的次數:"
+    simulate_games: "模擬遊戲!"
+    games_simulated_by: "您模擬過的次數:"
+    games_simulated_for: "替您模擬的次數:"
     games_in_queue: "遊戲正在列隊中:"
     games_simulated: "遊戲已模擬"
     games_played: "玩過的遊戲"
@@ -1214,33 +1212,33 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     battle_as: "我要扮演 "
     summary_your: "您的 "
     summary_matches: "對手 - "
-    summary_wins: " 勝利, "
+    summary_wins: " 勝利,"
     summary_losses: " 失敗"
     rank_no_code: "沒有新程式碼可評分"
-    rank_my_game: "對我的遊戲評分!"
-    rank_submitting: "上傳中..."
+    rank_my_game: "對我的遊戲評分!"
+    rank_submitting: "上傳中…"
     rank_submitted: "已上傳以求評分"
     rank_failed: "評分失敗"
     rank_being_ranked: "已評分"
     rank_last_submitted: "已上傳 "
-    help_simulate: "模擬遊戲需要幫助?"
-    code_being_simulated: "您的新代碼正在被其他人模擬評分中. 分數將隨每次新的配對而更新."
-    no_ranked_matches_pre: "對這個隊伍尚未有評分過的配對!"
-    no_ranked_matches_post: " 在別人的戰場上扮演競爭者並且回到這使您的代碼接受評分."
+    help_simulate: "模擬遊戲需要幫助?"
+    code_being_simulated: "您的新程式碼正在被其他人模擬評分中。分數將隨每次新的配對而更新。"
+    no_ranked_matches_pre: "對這個隊伍尚未有評分過的配對!"
+    no_ranked_matches_post: " 在別人的戰場上扮演競爭者並且回到這使您的程式碼接受評分。"
     choose_opponent: "選擇對手"
-    select_your_language: "選擇您的語言!"
+    select_your_language: "選擇您的語言!"
     tutorial_play: "教學"
     tutorial_recommended: "如果您尚未玩過,推薦先嘗試教學"
     tutorial_skip: "略過教學"
-    tutorial_not_sure: "不確定發生啥事?"
-    tutorial_play_first: "先嘗試教學."
+    tutorial_not_sure: "不確定發生啥事?"
+    tutorial_play_first: "先嘗試教學"
     simple_ai: "簡單人工智慧" # {change}
     warmup: "熱身"
     friends_playing: "與朋友連線"
-    log_in_for_friends: "登入與朋友一起玩!"
-    social_connect_blurb: "連線並擊敗您的朋友!"
-    invite_friends_to_battle: "邀請您的朋友加入此戰鬥!"
-    fight: "戰鬥!"
+    log_in_for_friends: "登入與朋友一起玩!"
+    social_connect_blurb: "連線並擊敗您的朋友!"
+    invite_friends_to_battle: "邀請您的朋友加入此戰鬥!"
+    fight: "戰鬥!"
     watch_victory: "觀看您的勝利"
     defeat_the: "擊敗"
     watch_battle: "觀看戰役"
@@ -1248,9 +1246,9 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     tournament_ends: "錦標賽結束"
     tournament_ended: "錦標賽已結束"
     tournament_rules: "錦標賽規則"
-    tournament_blurb: "寫下程式碼, 收集金幣, 建立軍隊, 粉碎敵人, 贏得獎項,在我們價值$40,000的Greed錦標賽中升級您的職業! 查看"
-    tournament_blurb_criss_cross: "贏得競賽, 建造道路, 智勝對手, 收集寶石, 在我們的Criss-Crossand錦標賽中升級您的職業! 查看"
-    tournament_blurb_zero_sum: "在紅方法師和藍方法師的山峰對決中,同時在收集金幣和戰術上發揮你的代碼創造力。競賽在3月27日開始,在4月6日(星期一)的下午5點(PDT太平洋時區)結束。為樂趣和榮耀競賽吧!瀏覽了解更多"
+    tournament_blurb: "寫下程式碼,收集金幣,建立軍隊,粉碎敵人,贏得獎項,在我們價值$40,000的Greed錦標賽中升級您的職業!查看"
+    tournament_blurb_criss_cross: "贏得競賽,建造道路,智勝對手,收集寶石,在我們的Criss-Crossand錦標賽中升級您的職業!查看"
+    tournament_blurb_zero_sum: "在紅方法師和藍方法師的山峰對決中,同時在收集金幣和戰術上發揮你的程式碼創造力。競賽在3月27日開始,在4月6日(星期一)的下午5點(PDT太平洋時區)結束。為樂趣和榮耀競賽吧!瀏覽了解更多"
     tournament_blurb_ace_of_coders: "我的主場我主宰,在寒天雪地的冰原上和自己鏡像大戰一場吧!本次比賽將由9月16日星期三開辦到10月14日下午5點PDT。詳情請查看"
     tournament_blurb_blog: "我們的部落格"
     rules: "規則"
@@ -1267,13 +1265,13 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     singleplayer_title: "單人遊戲等級"
     multiplayer_title: "多人遊戲等級"
     achievements_title: "成就"
-    last_played: "最後游玩"
+    last_played: "最後遊玩"
     status: "狀態"
     status_completed: "已完成"
     status_unfinished: "未完成"
-    no_singleplayer: "還沒有玩過單人遊戲."
-    no_multiplayer: "還沒有玩過多 人遊戲."
-    no_achievements: "還沒有取得成就."
+    no_singleplayer: "還沒有玩過單人遊戲"
+    no_multiplayer: "還沒有玩過多人遊戲"
+    no_achievements: "還沒有取得成就"
     favorite_prefix: "語言喜好為"
     favorite_postfix: "."
     not_member_of_clans: "還不是任何一個部落裡的成員。"
@@ -1292,12 +1290,12 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
 
   account:
     payments: "付款"
-    prepaid_codes: "充值碼"
+    prepaid_codes: "儲值碼"
     purchased: "已購買"
     subscription: "訂閱"
     invoices: "收據"
-    service_apple: "設備: Apple"
-    service_web: "設備: Web"
+    service_apple: "設備:Apple"
+    service_web: "設備:Web"
     paid_on: "支付"
     service: "服務"
     price: "價格"
@@ -1309,8 +1307,8 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     cost: "花費"
     next_payment: "下次付款"
     card: "信用卡"
-    status_unsubscribed_active: "您尚未訂閱並且將不會收到賬單,但是您的帳號現在仍然是有效的."
-    status_unsubscribed: "借由訂閱CodeCombat,取得存取新關卡,新英雄,新物品和額外寶石的資格!"
+    status_unsubscribed_active: "您尚未訂閱並且將不會收到賬單,但是您的帳號現在仍然是有效的。"
+    status_unsubscribed: "藉由訂閱CodeCombat,取得存取新關卡、新英雄、新物品和額外寶石的資格!"
 
   account_invoices:
     amount: "金額(美元)"
@@ -1318,7 +1316,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     invalid_amount: "請輸入美元金額。"
     not_logged_in: "登錄或創建一個帳戶來獲取發票。"
     pay: "付費發票"
-    purchasing: "購買中···"
+    purchasing: "購買中…"
     retrying: "服務器錯誤,重試中。"
     success: "支付成功。謝謝!"
 
@@ -1347,7 +1345,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
   loading_error:
     could_not_load: "從伺服器載入失敗"
     connection_failure: "連線失敗。"
-    unauthorized: "您需要先登錄。 您把cookies禁用了嗎?"
+    unauthorized: "您需要先登錄。您把cookies禁用了嗎?"
     forbidden: "您沒有權限。"
     not_found: "沒找到。"
     not_allowed: "方法不被允許。"
@@ -1370,7 +1368,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     gplus_friend_sessions: "Google+ 朋友會話"
     leaderboard: "排行榜"
     user_schema: "用戶模式"
-    user_profile: "用戶信息"
+    user_profile: "用戶資料"
     patch: "修補"
     patches: "修補"
     patched_model: "資源文擋"
@@ -1420,28 +1418,28 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
 #    users: "Users"
 
   concepts:
-    advanced_strings: "高級字符串"
+    advanced_strings: "進階字串"
     algorithms: "算法"
-    arguments: "參數"
+    arguments: "引數"
     arithmetic: "四則運算"
     arrays: "陣列"
     basic_syntax: "基本語法"
-    boolean_logic: "布爾邏輯"
-    break_statements: "Break語句"
+    boolean_logic: "布林邏輯"
+    break_statements: "break敘述"
     classes: "類"
-    continue_statements: "Continue 語句"
-    for_loops: "For循環"
+    continue_statements: "continue敘述"
+    for_loops: "for迴圈"
     functions: "函數"
     graphics: "圖形"
-    if_statements: "If語句"
+    if_statements: "if敘述"
     input_handling: "輸入處理"
     math_operations: "數學運算"
     object_literals: "對象常量"
     parameters: "參數"
-    strings: "字符串"
-    variables: "變量"
+    strings: "字串"
+    variables: "變數"
     vectors: "向量"
-    while_loops: "循環"
+    while_loops: "while迴圈"
     recursion: "遞歸"
 
   delta:
@@ -1461,73 +1459,73 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     multiplayer_link_description: "把這個連結告訴同伴們,一起玩吧。"
     multiplayer_hint_label: "提示:"
     multiplayer_hint: " 點擊全選,然後按 ⌘-C 或 Ctrl-C 複製連結。"
-    multiplayer_coming_soon: "請期待更多的多人關卡!"
+    multiplayer_coming_soon: "請期待更多的多人關卡!"
     multiplayer_sign_in_leaderboard: "註冊並且登入帳號,就可以將您的成就放在排行榜上。"
 
   legal:
     page_title: "條文"
     opensource_intro: "CodeCombat是完全的開源。"
-    opensource_description_prefix: "查看 "
+    opensource_description_prefix: "查看"
     github_url: "我們的 GitHub"
-    opensource_description_center: "並且如果有興趣也歡迎您的幫助! CodeCombat是建立在許多的開源專案上, 並且我們深愛它們。 查看 "
+    opensource_description_center: "並且如果有興趣也歡迎您的幫助! CodeCombat是建立在許多的開源專案上,並且我們深愛它們。查看"
     archmage_wiki_url: "我們的大法師wiki"
-    opensource_description_suffix: " 尋求創造這款遊戲的相關軟體列表。"
+    opensource_description_suffix: "尋求創造這款遊戲的相關軟體列表。"
     practices_title: "值得尊敬的最佳實踐"
-    practices_description: "這些是我們給您, 給玩家的承諾, 儘管這在法律上略顯不足。"
+    practices_description: "這些是我們給您,給玩家的承諾,儘管這在法律上略顯不足。"
     privacy_title: "隱私"
     privacy_description: "我們將不會賣出任何關於您個人的資訊。"
     security_title: "安全"
-    security_description: "我們渴望保持您的個人資訊是安全的. 身為一個開源的專案, 我們的網站是開放給任何人來檢視並且提升我們的安全系統。"
+    security_description: "我們渴望保持您的個人資訊是安全的。身為一個開源的專案,我們的網站是開放給任何人來檢視並且提升我們的安全系統。"
     email_title: "郵件"
-    email_description_prefix: "我們將不會使您的信箱氾濫的收到垃圾信。 不論"
-    email_settings_url: " 在您的郵件設定 "
-    email_description_suffix: "或在我們送出的信件上都有留著我們的聯結, 您可以更改您的喜好並且輕易的隨時取消訂閱。"
+    email_description_prefix: "我們將不會使您的信箱氾濫的收到垃圾信。不論"
+    email_settings_url: "在您的郵件設定"
+    email_description_suffix: "或在我們送出的信件上都有留著我們的聯結,您可以更改您的喜好並且輕易的隨時取消訂閱。"
     cost_title: "花費"
-    cost_description: "CodeCombat在核心的關卡是全部免費, 但只要花費一個月${{price}}美金來訂閱, 您將在每個月取得額外的關卡和{{gems}}顆寶石。 您可以輕易地取消訂閱並且保證取得100%的退費。"
+    cost_description: "CodeCombat在核心的關卡是全部免費,但只要花費一個月${{price}}美金來訂閱,您將在每個月取得額外的關卡和{{gems}}顆寶石。您可以輕易地取消訂閱並且保證取得100%的退費。"
     copyrights_title: "版權和許可"
     contributor_title: "貢獻者許可協議"
-    contributor_description_prefix: "所有在本網站或是 GitHub 代碼庫上的貢獻都依照我們的"
+    contributor_description_prefix: "所有在本網站或是 GitHub 程式碼庫上的貢獻都依照我們的"
     cla_url: "貢獻者許可協議"
-    contributor_description_suffix: "而這在您貢獻之前就應該已经同意。"
+    contributor_description_suffix: "而這在您貢獻之前就應該已經同意。"
     code_title: "Code - MIT"
-    code_description_prefix: "所有由 CodeCombat 擁有或是托管在 codecombat.com 的代码,在 GitHub 代碼庫或者 codecombat.com 數據庫,以上許可協議都依照"
+    code_description_prefix: "所有由 CodeCombat 擁有或是托管在 codecombat.com 的程式碼,在 GitHub 程式碼庫或者 codecombat.com 數據庫,以上許可協議都依照"
     mit_license_url: "MIT license"
-    code_description_suffix: "這包括所有 CodeCombat 公開製作關卡用的系统和組件代碼。"
+    code_description_suffix: "這包括所有 CodeCombat 公開製作關卡用的系统和組件程式碼。"
     art_title: "藝術/音樂 - Creative Commons "
     art_description_prefix: "所有共通的内容都在"
     cc_license_url: "Creative Commons Attribution 4.0 International License"
-    art_description_suffix: "共通内容是指所有 CodeCombat 發佈出来用于製作關卡的内容。包括:"
+    art_description_suffix: "共通内容是指所有 CodeCombat 發佈出來用於製作關卡的内容。包括:"
     art_music: "音樂"
     art_sound: "聲音"
     art_artwork: "藝術作品"
     art_sprites: "貼圖"
-    art_other: "所有製作關卡時公開的,不是代碼的創造性產品。"
-    art_access: "目前還没有簡便通用的下载素材方式。 一般来說,從網站上使用的URL下载,或者聯繫我们尋求幫助。 當然您也可以幫助我们拓展網站,使這些資源更容易下載。"
-    art_paragraph_1: "為了歸屬, 請在使用處或適當的地方說明, 或者留下一個聯結至codecombat.com. 例如:"
-    use_list_1: "如果使用在電影或者另一款遊戲中, 請在製作人員表中加入codecombat.com"
-    use_list_2: "如果使用在網站上, 請在使用處留下codecombat.com, 例如在圖片下面或一個您專門放置Creative Commons和開源專案的地方. 如果您的内容明確提到關於 CodeCombat, 那您就不需要額外署名."
-    art_paragraph_2: "如果您使用的內容非由CodeCombat製作但由一位codecombat.com中的使用者, 那您應該署名他。 並且如果相對應的頁面上有標記署名指示, 那您應該遵照其指示。"
+    art_other: "所有製作關卡時公開的,不是程式碼的創造性產品。"
+    art_access: "目前還没有簡便通用的下載素材方式。一般來說,從網站上使用的URL下載,或者聯繫我們尋求幫助。當然您也可以幫助我們拓展網站,使這些資源更容易下載。"
+    art_paragraph_1: "為了歸屬,請在使用處或適當的地方說明,或者留下一個聯結至codecombat.com。例如:"
+    use_list_1: "如果使用在電影或者另一款遊戲中,請在製作人員表中加入codecombat.com"
+    use_list_2: "如果使用在網站上,請在使用處留下codecombat.com,例如在圖片下面或一個您專門放置Creative Commons和開源專案的地方。如果您的内容明確提到關於 CodeCombat,那您就不需要額外署名。"
+    art_paragraph_2: "如果您使用的內容非由CodeCombat製作但由一位codecombat.com中的使用者,那您應該署名他。並且如果相對應的頁面上有標記署名指示,那您應該遵照其指示。"
     rights_title: "保留權利"
-    rights_desc: "所有版權由關卡本身擁有, 這包含:"
+    rights_desc: "所有版權由關卡本身擁有,這包含:"
     rights_scripts: "腳本"
     rights_unit: "單元配置"
     rights_description: "描述"
     rights_writings: "寫作"
-    rights_media: "聲音、音樂以及其他專門為某道關卡製作, 而不對其他關卡開放的創造性内容。"
-    rights_clarification: "澄清一下, 所有在關卡编辑器裡公開用於制作關卡的資源都是在CC協議下發佈的, 然而使用關卡编辑器製作,或者在關卡製作過程中上傳的内容则不是."
+    rights_media: "聲音、音樂以及其他專門為某道關卡製作,而不對其他關卡開放的創造性内容。"
+    rights_clarification: "澄清一下,所有在關卡編輯器裡公開用於製作關卡的資源都是在CC協議下發佈的,然而使用關卡編輯器製作,或者在關卡製作過程中上傳的内容則不是。"
     nutshell_title: "簡而言之"
-    nutshell_description: "我们在關卡编辑器里公開的任何資源, 您都可以在製作關卡時隨意使用, 但我们保留在 codecombat.com 之上創建的關卡本身傳播的權利, 因为我们往後可能決定以它們收費."
-    canonical: "我們宣告這篇說明的英文版本是權威版本。 如果各個翻譯版本之間有任何衝突, 以英文版為準。"
-#    third_party_title: "Third Party Services"
+    nutshell_description: "我們在關卡編輯器裡公開的任何資源,您都可以在製作關卡時隨意使用,但我們保留在 codecombat.com 之上創建的關卡本身傳播的權利,因為我們往後可能決定以它們收費。"
+    canonical: "我們宣告這篇說明的英文版本是權威版本。如果各個翻譯版本之間有任何衝突,以英文版為準。"
+    third_party_title: "第三方服務"
 #    third_party_description: "CodeCombat uses the following third party services (among others):"
 
   ladder_prizes:
     title: "錦標賽獎項" # This section was for an old tournament and doesn't need new translations now.
     blurb_1: "依據"
     blurb_2: "錦標賽規則"
-    blurb_3: ", 這些獎項將被頒發給頂尖的人類和怪物玩家."
-    blurb_4: "兩隊意指獎項是兩倍!"
-    blurb_5: "(將有兩個第一名, 兩個第二名, etc.)"
+    blurb_3: ",這些獎項將被頒發給頂尖的人類和怪物玩家。"
+    blurb_4: "兩隊意指獎項是兩倍!"
+    blurb_5: "(將有兩個第一名、兩個第二名,以此類推。)"
     rank: "排名"
     prizes: "獎項"
     total_value: "總價值"
@@ -1536,8 +1534,8 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     custom_avatar: "定制 CodeCombat 頭像"
     heap: "給六個月的\"Startup\"訪問"
     credits: "信譽"
-    one_month_coupon: "優惠: 選擇 Rails 或者 HTML"
-    one_month_discount: "折扣 30% : 選擇 Rails 或者 HTML"
+    one_month_coupon: "優惠:選擇 Rails 或者 HTML"
+    one_month_discount: "折扣 30%:選擇 Rails 或者 HTML"
     license: "許可證"
     oreilly: "您選擇的電子書"
 
@@ -1545,16 +1543,16 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese
     av_espionage: "Espionage" # Really not important to translate /admin controls.
     av_espionage_placeholder: "信箱或用戶名"
     av_usersearch: "用戶搜尋"
-    av_usersearch_placeholder: "信箱, 用戶名, 姓名, 任何東西"
+    av_usersearch_placeholder: "信箱、用戶名、姓名,任何東西"
     av_usersearch_search: "搜尋"
     av_title: "管理員視野"
     av_entities_sub_title: "商業個體"
     av_entities_users_url: "使用者"
     av_entities_active_instances_url: "有效實例"
-    av_entities_user_code_problems_list_url: "用戶代碼問題列表"
+    av_entities_user_code_problems_list_url: "用戶程式碼問題列表"
     av_other_sub_title: "其他"
     av_other_debug_base_url: "Base (用於測試 base.jade)"
     u_title: "用戶列表"
-    ucp_title: "用戶代碼問題"
+    ucp_title: "用戶程式碼問題"
     lg_title: "最新遊戲"
     clas: "貢獻者許可協議"
diff --git a/app/locale/zh-WUU-HANS.coffee b/app/locale/zh-WUU-HANS.coffee
index bc742ddcd..685642553 100644
--- a/app/locale/zh-WUU-HANS.coffee
+++ b/app/locale/zh-WUU-HANS.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "吴语", englishDescription: "Wuu (Simplifi
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "吴语", englishDescription: "Wuu (Simplifi
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "吴语", englishDescription: "Wuu (Simplifi
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "吴语", englishDescription: "Wuu (Simplifi
 #    email_settings_url: "your email settings"
 #    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
 #    cost_title: "Cost"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
 #    copyrights_title: "Copyrights and Licenses"
 #    contributor_title: "Contributor License Agreement"
 #    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
diff --git a/app/locale/zh-WUU-HANT.coffee b/app/locale/zh-WUU-HANT.coffee
index 67617c384..9763f19aa 100644
--- a/app/locale/zh-WUU-HANT.coffee
+++ b/app/locale/zh-WUU-HANT.coffee
@@ -397,14 +397,14 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
 #    prompt_body: "Do you want to get more?"
 #    prompt_button: "Enter Shop"
 #    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    price: "x3500 / mo"
+#    price: "x{{gems}} / mo"
 
 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
 #    feature1: "110+ basic levels across 4 worlds"
 #    feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
 #    feature3: "80+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
+#    feature4: "<strong>{{gems}} bonus gems</strong> every month!"
 #    feature5: "Video tutorials"
 #    feature6: "Premium email support"
 #    feature7: "Private <strong>Clans</strong>"
@@ -552,32 +552,30 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
 #    press_paragraph_1_link: "press packet"
 #    press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
 #    team: "Team"
-#    george_title: "Cofounder"
-#    george_blurb: "Businesser"
-#    scott_title: "Cofounder"
-#    scott_blurb: "Reasonable One"
-#    nick_title: "Cofounder"
+#    nick_title: "Cofounder, CEO"
 #    nick_blurb: "Motivation Guru"
-#    michael_title: "Programmer"
-#    michael_blurb: "Sys Admin"
-#    matt_title: "Cofounder"
+#    matt_title: "Cofounder, CTO"
 #    matt_blurb: "Bicyclist"
-#    cat_title: "Chief Artisan"
+#    cat_title: "Game Designer"
 #    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
-#    retrostyle_blurb: "RetroStyle Games"
-#    rob_title: "Compiler Engineer"
+#    scott_title: "Cofounder, Software Engineer"
+#    scott_blurb: "Reasonable One"
+#    maka_title: "Customer Advocate"
+#    maka_blurb: "Storyteller"
+#    rob_title: "Software Engineer"
 #    rob_blurb: "Codes things and stuff"
 #    josh_c_title: "Game Designer"
 #    josh_c_blurb: "Designs games"
+#    robin_title: "UX Design & Research"
+#    robin_blurb: "Scaffolding"
+#    josh_title: "Game Designer"
+#    josh_blurb: "Floor Is Lava"
+#    retrostyle_title: "Illustration"
+#    retrostyle_blurb: "RetroStyle Games"
+#    jose_title: "Music"
+#    jose_blurb: "Taking Off"
 #    carlos_title: "Region Manager, Brazil"
 #    carlos_blurb: "Celery Man"
-#    maka_title: "Customer Advocate"
-#    maka_blurb: "Storyteller"
 
 #  teachers:
 #    who_for_title: "Who is CodeCombat for?"
@@ -994,7 +992,7 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
 #    additional_resources_1_mid: "Course 1 Teacher's Guide"
 #    additional_resources_1_suff: "explanations and solutions to each level."
 #    additional_resources_2_pref: "Complete our"
-#    additional_resources_2_suff: "to get 15 more hours of content! For a limited time, enroll as many students as you want in our three paid courses."
+#    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
 #    additional_resources_3_pref: "Visit our"
 #    additional_resources_3_mid: "Teacher Forums"
 #    additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."
@@ -1483,7 +1481,7 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
     email_settings_url: "設定爾個電子郵箱"
     email_description_suffix: "要勿我裏發畀爾個信裏向有鏈接,爾随低2都好改偏向設定要勿取消訂閱。"
     cost_title: "花銷"
-#    cost_description_a: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
+#    cost_description: "CodeCombat is free to play for all of its core levels, with a ${{price}} USD/mo subscription for access to extra level branches and {{gems}} bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee."
     copyrights_title: "版權搭許可"
     contributor_title: "貢獻者許可協議"
     contributor_description_prefix: "所有對本網站要勿 GitHub 代碼庫個努力都照我裏個"
diff --git a/app/models/Level.coffee b/app/models/Level.coffee
index df0a1efbf..299f801e4 100644
--- a/app/models/Level.coffee
+++ b/app/models/Level.coffee
@@ -28,7 +28,13 @@ module.exports = class Level extends CocoModel
     # Figure out ThangTypes' Components
     tmap = {}
     tmap[t.thangType] = true for t in o.thangs ? []
-    o.thangTypes = (original: tt.get('original'), name: tt.get('name'), components: $.extend(true, [], tt.get('components')) for tt in supermodel.getModels ThangType when tmap[tt.get('original')] or (tt.get('components') and not tt.notInLevel))
+    sessionHeroes = [session?.get('heroConfig')?.thangType, otherSession?.get('heroConfig')?.thangType]
+    o.thangTypes = []
+    for tt in supermodel.getModels ThangType
+      if tmap[tt.get('original')] or
+        (tt.get('kind') isnt 'Hero' and tt.get('kind')? and tt.get('components') and not tt.notInLevel) or
+        (tt.get('kind') is 'Hero' and ((@get('type', true) in ['course', 'course-ladder']) or tt.get('original') in sessionHeroes))
+          o.thangTypes.push (original: tt.get('original'), name: tt.get('name'), components: $.extend(true, [], tt.get('components')))
     @sortThangComponents o.thangTypes, o.levelComponents, 'ThangType'
     @fillInDefaultComponentConfiguration o.thangTypes, o.levelComponents
 
diff --git a/app/models/SuperModel.coffee b/app/models/SuperModel.coffee
index f381bdfd1..3da8f37e9 100644
--- a/app/models/SuperModel.coffee
+++ b/app/models/SuperModel.coffee
@@ -28,6 +28,10 @@ module.exports = class SuperModel extends Backbone.Model
     unfinished
 
   loadModel: (model, name, fetchOptions, value=1) ->
+    # Deprecating name. Handle if name is not included
+    value = fetchOptions if _.isNumber(fetchOptions)
+    fetchOptions = name if _.isObject(name)
+      
     # hero-ladder levels need remote opponent_session for latest session data (e.g. code)
     # Can't apply to everything since other features rely on cached models being more recent (E.g. level_session)
     # E.g.#2 heroConfig isn't necessarily saved to db in world map inventory modal, so we need to load the cached session on level start
@@ -48,6 +52,10 @@ module.exports = class SuperModel extends Backbone.Model
       return res
 
   loadCollection: (collection, name, fetchOptions, value=1) ->
+    # Deprecating name. Handle if name is not included
+    value = fetchOptions if _.isNumber(fetchOptions)
+    fetchOptions = name if _.isObject(name)
+    
     url = collection.getURL()
     if cachedCollection = @collections[url]
       console.debug 'Collection cache hit', url, 'already loaded', cachedCollection.loaded
@@ -132,9 +140,13 @@ module.exports = class SuperModel extends Backbone.Model
   # Tracking resources being loaded for this supermodel
 
   finished: ->
-    return @progress is 1.0 or not @denom
+    return (@progress is 1.0) or (not @denom) or @failed 
 
   addModelResource: (modelOrCollection, name, fetchOptions, value=1) ->
+    # Deprecating name. Handle if name is not included
+    value = fetchOptions if _.isNumber(fetchOptions)
+    fetchOptions = name if _.isObject(name)
+    
     modelOrCollection.saveBackups = modelOrCollection.saveBackups or @shouldSaveBackups(modelOrCollection)
     @checkName(name)
     res = new ModelResource(modelOrCollection, name, fetchOptions, value)
@@ -145,20 +157,25 @@ module.exports = class SuperModel extends Backbone.Model
     @removeResource _.find(@resources, (resource) -> resource?.model is modelOrCollection)
 
   addRequestResource: (name, jqxhrOptions, value=1) ->
+    # Deprecating name. Handle if name is not included
+    value = jqxhrOptions if _.isNumber(jqxhrOptions)
+    jqxhrOptions = name if _.isObject(name)
+    
     @checkName(name)
     res = new RequestResource(name, jqxhrOptions, value)
     @storeResource(res, value)
     return res
 
   addSomethingResource: (name, value=1) ->
+    value = name if _.isNumber(name)
     @checkName(name)
     res = new SomethingResource(name, value)
     @storeResource(res, value)
     return res
 
   checkName: (name) ->
-    if not name
-      throw new Error('Resource name should not be empty.')
+    if _.isString(name)
+      console.warn("SuperModel name property deprecated. Remove '#{name}' from code.")
 
   storeResource: (resource, value) ->
     @rid++
@@ -186,6 +203,7 @@ module.exports = class SuperModel extends Backbone.Model
 
   onResourceFailed: (r) ->
     return unless @resources[r.rid]
+    @failed = true
     @trigger('failed', resource: r)
     r.clean()
 
diff --git a/app/models/User.coffee b/app/models/User.coffee
index 99e2ad771..4c03a68f1 100644
--- a/app/models/User.coffee
+++ b/app/models/User.coffee
@@ -19,11 +19,11 @@ module.exports = class User extends CocoModel
   broadName: ->
     name = @get('name')
     return name if name
-    name = _.filter([@get('firstName'), @get('lastName')]).join('')
+    name = _.filter([@get('firstName'), @get('lastName')]).join(' ')
     return name if name
     email = @get('email')
     return email if email
-    return ''
+    return 'Anoner'
 
   getPhotoURL: (size=80, useJobProfilePhoto=false, useEmployerPageAvatar=false) ->
     photoURL = if useJobProfilePhoto then @get('jobProfile')?.photoURL else null
diff --git a/app/schemas/models/user.coffee b/app/schemas/models/user.coffee
index 80a822413..c1b1766d5 100644
--- a/app/schemas/models/user.coffee
+++ b/app/schemas/models/user.coffee
@@ -79,6 +79,7 @@ _.extend UserSchema.properties,
     archmageNews: {$ref: '#/definitions/emailSubscription'}
     artisanNews: {$ref: '#/definitions/emailSubscription'}
     diplomatNews: {$ref: '#/definitions/emailSubscription'}
+    teacherNews: {$ref: '#/definitions/emailSubscription'}
     scribeNews: {$ref: '#/definitions/emailSubscription'}
 
     # notifications
diff --git a/app/styles/about.sass b/app/styles/about.sass
index ccb7787f7..d067f2455 100644
--- a/app/styles/about.sass
+++ b/app/styles/about.sass
@@ -23,8 +23,14 @@
       margin: 0px 10px 22px 0px
 
   .team_name
+    font-size: 20px
     margin-top: 0
 
   .team_bio
     width: 150px
-    float: left
\ No newline at end of file
+    float: left
+
+    div
+      font-size: 12px
+      line-height: 14px
+      padding-bottom: 5px
\ No newline at end of file
diff --git a/app/styles/account/profile-view.sass b/app/styles/account/profile-view.sass
deleted file mode 100644
index a122188f3..000000000
--- a/app/styles/account/profile-view.sass
+++ /dev/null
@@ -1,344 +0,0 @@
-@import "app/styles/bootstrap/variables"
-
-#profile-view
-  $sideBackground: rgb(220, 220, 220)
-  #login-message
-    h1, h2, h3, h4
-      font-family: Arial, Helvetica, sans-serif
-      color: #333333
-    width: 100%
-    text-align: center
-    margin-top: 200px
-  .profile-control-bar
-    background-color: $sideBackground
-    width: 100%
-    text-align: center
-
-    .profile-completion-progress
-      width: 100%
-      height: 33px
-      margin-bottom: 0
-      border-radius: 0
-      background-color: darken($sideBackground, 15%)
-  
-      .progress-bar
-        line-height: 33px
-        font-size: 16px
-
-      .progress-text
-        position: absolute
-        width: 100%
-        text-align: center
-        line-height: 33px
-        font-size: 16px
-        color: white
-        text-shadow: 0px 1px 0px black
-  
-    button, a.btn
-      margin: 10px 2px 10px 2px
-      
-      &:disabled
-        border-radius: 0
-        opacity: 1
-
-      i
-        margin-right: 5px
-      
-    .sample-profile
-      position: absolute
-      right: 5px
-  
-  .main-content-area
-    padding: 0
-    background-color: white
-
-    .flat-button
-      width: 100%
-      margin-bottom: 10px
-      background: rgb(78, 78, 78)
-      border: 0
-      border-radius: 0
-      padding: 10px
-
-    .public-profile-container
-      padding: 20px
-
-      img.profile-photo
-        width: 256px
-        border-radius: 6px
-
-    .job-profile-container
-      width: 100%
-      height: 100%
-      min-height: 600px
-      padding: 0
-      display: table
-      
-      h1, h2, h3, h4, h5, h6
-        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif
-        color: #555
-
-      ul.links, ul.projects, ul.sessions
-        margin: 0
-        padding: 0
-    
-        li
-          list-style: none
-
-      .job-profile-row
-        height: 100%
-        display: table-row
-        $side-width: 250px
-        $side-padding: 5px
-        $middle-width: 524px
-        $middle-padding: 20px
-
-        .full-height-column
-          height: 100%
-          padding: $side-padding
-          display: table-cell
-          vertical-align: top
-
-          h3:first-child
-            margin: 5px 0 5px 0
-      
-        .left-column
-          width: $side-width - 2 * $side-padding
-          padding: $side-padding
-          background-color: $sideBackground
-
-          .sub-column
-            width: $side-width - 2 * $side-padding
-            overflow-wrap: break-word
-
-          #profile-photo-container
-            position: relative
-            margin-bottom: 10px
-
-            img.profile-photo
-              width: $side-width - 2 * $side-padding
-              border-radius: 6px
-
-            .profile-caption
-              background-color: rgba(0, 0, 0, 0.5)
-              color: white
-              border-bottom-right-radius: 6px
-              border-bottom-left-radius: 6px
-              position: absolute
-              width: 100%
-              bottom: 0px
-              text-align: center
-
-          ul.links
-            text-align: center
-            li.has-icon
-              display: inline-block
-              img
-                margin: 0 0 10px 0
-            li.has-icon:not(:nth-child(5))
-              img
-                margin: 0 5px 10px 5px
-
-          #contact-candidate
-            margin-top: 20px
-            background-color: rgb(177, 55, 25)
-            padding: 15px
-            font-size: 20px
-
-        .middle-column
-          width: $middle-width - 2 * $middle-padding
-          padding-left: $middle-padding
-          padding-right: $middle-padding
-          background-color: white
-
-          .sub-column
-            width: $middle-width - 2 * $middle-padding
-            overflow-wrap: break-word
-
-          &.double-column
-            width: $middle-width + $side-width + 2 * $side-padding - 2 * $middle-padding
-            $middle-padding-double: 30px
-            padding-left: $middle-padding-double
-            padding-right: $middle-padding-double
-
-            .sub-column
-              width: $middle-width + $side-width + 2 * $side-padding - 2 * $middle-padding - 2 * $middle-padding-double
-              overflow-wrap: break-word
-
-          code
-            background-color: $sideBackground
-            color: #555
-            margin: 2px 0
-            display: inline-block
-            text-transform: lowercase
-
-          .long-description
-            margin-top: 10px
-            img
-              max-width: 524px - 60px
-              max-height: 200px
-
-          .experience-header
-            margin-top: 25px
-
-          .header-icon
-            margin-right: 10px
-            width: 32px
-            height: 32px
-
-          .experience-entry
-            margin-bottom: 15px
-      
-          .duration
-            margin-left: 10px
-            margin-bottom: 10px
-
-          #job-profile-notes
-            width: 100%
-            height: 100px
-
-          #remark-treema
-            background-color: white
-            border: 0
-            padding-top: 0
-
-        .right-column
-          width: $side-width
-          background-color: $sideBackground
-
-          .sub-column
-            width: $side-width - 2 * $side-padding
-            overflow-wrap: break-word
-
-            > h3:first-child
-              background-color: white
-              padding: 5px 5px
-              margin: 5px 2px 5px 2px
-
-          ul.projects
-            li
-              margin-bottom: 10px
-              padding: 5px 3px
-              border: 2px solid $sideBackground
-              transition: .5s ease-in-out
-              position: relative
-              background-color: white
-
-              &:hover
-                border-color: rgb(100, 130, 255)
-
-              a
-                position: relative
-                z-index: 2
-
-              > a
-                position: absolute
-                width: 100%
-                height: 100%
-                top: 0
-                left: 0
-                z-index: 1
-        
-          .project-image
-            width: 230px
-            height: 115px
-            background-size: cover
-            background-repeat: no-repeat
-            background-position: center
-
-            -webkit-filter: grayscale(100%)
-            -webkit-transition: .5s ease-in-out
-            -moz-filter: grayscale(100%) 
-            -moz-transition: .5s ease-in-out
-            -o-filter: grayscale(100%) 
-            -o-transition: .5s ease-in-out
-            filter: grayscale(100%)
-            transition: .5s ease-in-out
-
-          ul.projects li:hover .project-image, .project-image:hover
-            -webkit-filter: grayscale(0%)
-            -moz-filter: grayscale(0%)
-            -o-filter: grayscale(0%)
-            filter: grayscale(0%)
-
-  .main-content-area
-
-    .job-profile-container
-      .editable-section
-        position: relative
-        transition: box-shadow 0.5s easeInOutQuad
-        min-height: 30px
-
-        &.just-saved
-          box-shadow: 0px 0px 20px 0px #080
-          z-index: 1
-
-        .editable-form
-          display: none
-          background-color: white
-          padding: 5px 5px 5px 5px
-
-          .skill-array-item
-            display: inline-block
-
-            input
-              width: 120px
-              margin: 5px
-
-          .project-image
-            width: 210px
-            height: 105px
-            cursor: pointer
-
-      .editable-icon
-        display: none
-  
-    .job-profile-container.editable-profile
-
-      .full-height-column.deemphasized
-        background-color: $sideBackground
-
-      .saving
-        opacity: 0.75
-  
-      .editable-thinner
-        padding-right: 30px
-                
-      .editable-icon
-        display: block
-        position: absolute
-        right: 5px
-        top: 5px
-        font-size: 20px
-        color: $blue
-        opacity: 0.5
-          
-      .edit-label
-        color: $blue
-        font-weight: 300
-
-      .edit-example-button
-        background-color: transparentize($blue, 0.25)
-
-      .edit-example-text
-        color: $blue
-
-      code.edit-example-tag
-        color: $blue
-      
-      .emphasized
-        outline: 1px solid $green
-
-      .editable-section.deemphasized:not(.just-saved), .our-notes-section.deemphasized
-        opacity: 0.5
-
-      .editable-section:hover
-        cursor: pointer
-        outline: 1px solid $blue
-  
-        .editable-icon
-          opacity: 1.0
-          cursor: pointer
-
-        .editable-form
-          cursor: default
diff --git a/app/styles/admin/candidates.sass b/app/styles/admin/candidates.sass
deleted file mode 100644
index 1a34e9f12..000000000
--- a/app/styles/admin/candidates.sass
+++ /dev/null
@@ -1,74 +0,0 @@
-#admin-candidates-view
-
-  h1, h2, h3
-    font: Arial
-
-  .see-candidates-header
-    margin: 30px
-    text-align: center
-
-    #see-candidates
-      cursor: pointer
-
-  .employer_icon
-    width: 125px
-    float: left
-    margin: 0px 15px 15px 0px
-
-  .information_row
-    height: 150px
-    padding-right: 15px
-
-  #leftside
-    width: 500px
-    float: left
-
-  #rightside
-    width: 500px
-    float: left
-
-  .tablesorter
-    //img
-    //  display: none
-
-    .tablesorter-header
-      cursor: pointer
-      &:hover
-        color: black
-
-      &:first-child
-        // Make sure that "Developer #56" doesn't wrap onto second row
-        min-width: 110px
-
-    .tablesorter-headerAsc
-      background-color: #cfc
-
-    .tablesorter-headerDesc
-      background-color: #ccf
-
-    tr
-      cursor: pointer
-
-    tr.expired
-      opacity: 0.5
-
-    code
-      background-color: rgb(220, 220, 220)
-      color: #555
-      margin: 2px 0
-      display: inline-block
-      text-transform: lowercase
-
-    td:nth-child(3) select
-      min-width: 100px
-    td:nth-child(6) select
-      min-width: 50px
-    td:nth-child(7) select
-      min-width: 100px
-
-#employers-view, #profile-view.viewed-by-employer
-  #outer-content-wrapper, #intermediate-content-wrapper, #inner-content-wrapper
-    background: #949494
-
-  .main-content-area
-    background-color: #EAEAEA
\ No newline at end of file
diff --git a/app/styles/common/common.sass b/app/styles/common/common.sass
index 83b3e285f..b23b0654d 100644
--- a/app/styles/common/common.sass
+++ b/app/styles/common/common.sass
@@ -397,3 +397,21 @@ body > iframe[src^="https://apis.google.com"]
 // TODO: update Bootstrap, remove this
 .text-uppercase
   text-transform: uppercase
+
+  
+// Made for new victory modal as temp features. TODO: Replace with static art or make general, sprite versions
+.well-parchment
+  border: 2px solid #14110e
+  background: #c2b695
+  color: #282116
+
+.img-prize
+  border: 4px solid #fef9a3
+  padding: 2px
+  background: #693415
+  
+.label-banner
+  border: 2px solid #350f0d
+  background: #e6251c
+  color: white
+  padding: 0.0em 0.6em 0.1em
\ No newline at end of file
diff --git a/app/styles/core/loading-error.sass b/app/styles/core/loading-error.sass
new file mode 100644
index 000000000..e9a51fc98
--- /dev/null
+++ b/app/styles/core/loading-error.sass
@@ -0,0 +1,15 @@
+#loading-error
+  padding: 20px
+
+  .btn
+    margin-top: 20px
+  
+  .login-btn
+    margin-right: 10px
+  
+  #not-found-img
+    max-width: 20%
+    margin: 20px 0
+    
+  #links-row
+    margin-top: 50px
\ No newline at end of file
diff --git a/app/styles/kinds/search.sass b/app/styles/kinds/search.sass
index 7644e613a..622011580 100644
--- a/app/styles/kinds/search.sass
+++ b/app/styles/kinds/search.sass
@@ -18,9 +18,20 @@
     .name-row
       @extend .body-row
       max-width: 300px
+    .description-row
+      @extend .body-row
+      max-width: 520px
     .small-name-row
       @extend .body-row
       max-width: 200px
+    .watch-row
+      @extend .body-row
+      max-width: 80px
+      text-align: center
+      &.watching
+        opacity: 1.0
+      &.not-watching
+        opacity: 0.5
 
     tr.mine
       background-color: #f8ecaa
diff --git a/app/styles/play/ladder_home.sass b/app/styles/play/ladder_home.sass
index 38eb07af8..451494ac5 100644
--- a/app/styles/play/ladder_home.sass
+++ b/app/styles/play/ladder_home.sass
@@ -1,7 +1,7 @@
 @import "app/styles/mixins"
 @import "app/styles/bootstrap/variables"
 
-#ladder-home-view
+#main-ladder-view
   .level
     width: 100%
     position: relative
diff --git a/app/styles/play/level/modal/course-victory-modal.sass b/app/styles/play/level/modal/course-victory-modal.sass
new file mode 100644
index 000000000..eb6d9ab80
--- /dev/null
+++ b/app/styles/play/level/modal/course-victory-modal.sass
@@ -0,0 +1,72 @@
+@import "app/styles/mixins"
+@import "app/styles/bootstrap/variables"
+
+#course-victory-modal
+
+  //- Top-level modal container
+  .modal-dialog
+    margin-top: 0
+    padding-top: 0
+    width: 750px
+
+    .modal-content
+      position: relative
+      margin-top: -251px
+
+  //- Header
+
+  .background-wrapper
+    width: 750px
+    background: transparent
+    border: 0px solid transparent
+    border-style: solid
+    border-image: url("/images/pages/play/level/modal/victory_modal_border_background.png") 250 0 100 0 fill round
+    border-width: 250px 0 100px 0
+    border-radius: 12px
+
+  .modal-header
+    border: none
+    position: absolute
+    left: 0px
+    width: 100%
+    height: 134px
+    margin: 0
+    padding: 0
+    top: 74px
+
+    text-align: center
+    .well-parchment
+      display: inline-block
+      h1
+        color: inherit
+        margin: 0
+      
+    #close-modal
+      position: absolute
+      right: 174px
+      color: white
+      top: -15px
+      background: #ba1d00
+      padding: 6px 6px 3px
+
+  .modal-body
+    padding: 30px 20px 0
+    position: relative
+    top: 80px
+    margin-top: 80px
+    
+    .well-parchment
+      margin-top: 20px
+    
+  
+    
+  
+html.no-borderimage
+  #course-victory-modal
+    .modal-dialog
+      margin-top: 251px
+    .background-wrapper
+      border: 0
+      background: url("/images/pages/play/level/modal/victory_modal_background.png")
+      height: 713px
+
diff --git a/app/styles/play/level/modal/new-item-view.sass b/app/styles/play/level/modal/new-item-view.sass
new file mode 100644
index 000000000..9f9de1ff7
--- /dev/null
+++ b/app/styles/play/level/modal/new-item-view.sass
@@ -0,0 +1,5 @@
+#new-item-view
+
+  #item-header
+    margin: -5px
+    
\ No newline at end of file
diff --git a/app/styles/play/level/modal/progress-view.sass b/app/styles/play/level/modal/progress-view.sass
new file mode 100644
index 000000000..700933bc8
--- /dev/null
+++ b/app/styles/play/level/modal/progress-view.sass
@@ -0,0 +1,8 @@
+#progress-view
+  h1, h2, h3
+    margin-top: 0
+    color: black
+    margin-bottom: 5px
+    
+  p
+    margin-top: 30px
\ No newline at end of file
diff --git a/app/styles/recruitment_base.sass b/app/styles/recruitment_base.sass
deleted file mode 100644
index 6501c7303..000000000
--- a/app/styles/recruitment_base.sass
+++ /dev/null
@@ -1,52 +0,0 @@
-@import "app/styles/mixins"
-@import "app/styles/bootstrap/variables"
-
-#employers-wrapper
-  background-color: #B4B4B4
-  height: 100%
-  #outer-content-wrapper, #intermediate-content-wrapper, #inner-content-wrapper
-    background: #B4B4B4
-
-  .navbar, #top-nav, .content.clearfix
-    background-color: #B4B4B4
-
-  .footer
-    border-top: none
-    background-color: #B4B4B4
-    padding-bottom: 50px
-   
-
-#employer-content-area
-  margin: auto
-  
-.employer-modal-background-wrapper
-  background-color: white
-  border: 2px #333333 solid
-  border-radius: 4px
-  h1, h2, h3, h4, h5
-    color: black
-    font-family: Arial, Helvetica, sans-serif
-  .input-large
-    font-size: 28px
-    height: 60px
-    border: 2px rgb(231,231,231) solid
-    box-shadow: none
-    width: 70%
-    margin-left: 15%
-  #create-account-button, #contract-agreement-button, #login-button
-    background: #fce232 /* Old browsers */
-    background: -moz-linear-gradient(top, #fce232 0%, #ea8e2b 100%)
-    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fce232), color-stop(100%,#ea8e2b))
-    background: -webkit-linear-gradient(top, #fce232 0%,#ea8e2b 100%)
-    background: -o-linear-gradient(top, #fce232 0%,#ea8e2b 100%)
-    background: -ms-linear-gradient(top, #fce232 0%,#ea8e2b 100%)
-    background: linear-gradient(to bottom, #fce232 0%,#ea8e2b 100%)
-    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fce232', endColorstr='#ea8e2b',GradientType=0 )
-    height: 60px
-    font-size: 24px
-    color: black
-  .login-link
-    text-decoration: underline
-  #login-button
-    margin-left: 40%
-    width: 20%
diff --git a/app/styles/sales-view.sass b/app/styles/sales-view.sass
index decdfbe3d..33dc210c0 100644
--- a/app/styles/sales-view.sass
+++ b/app/styles/sales-view.sass
@@ -147,8 +147,9 @@
     .teacher-quote
       font-family: Merriweather
       font-weight: 300
-      font-size: 18px
+      font-size: 15px
       line-height: 20px
+      padding-top: 5px
 
     .teacher-name
       font-family: Helvetica, sans-serif
@@ -178,7 +179,7 @@
       background-repeat: no-repeat
       background-size: 100% auto
       height: 265px
-      padding: 12px
+      padding: 20px 12px 12px 12px
       margin-left: 10px
 
       .teacher-quote
diff --git a/app/templates/about.jade b/app/templates/about.jade
index e4c139ce0..a420ab3cf 100644
--- a/app/templates/about.jade
+++ b/app/templates/about.jade
@@ -73,67 +73,74 @@ block content
 
           h2(data-i18n="about.team") Team
 
+          // Full time
+
           a(href="http://www.nickwinter.net")
             img(src="/images/pages/about/nick_small.png").img-thumbnail
           .team_bio
             h4.team_name
               a(href="http://www.nickwinter.net") Nick Winter
-            p(data-i18n="about.nick_title")
-              | Cofounder
-            p(data-i18n="about.nick_blurb")
-              | Motivation Guru
+            div(data-i18n="about.nick_title")
+            div(data-i18n="about.nick_blurb")
 
           a(href="http://www.mattlott.com/")
             img(src="/images/pages/about/matt_small.png").img-thumbnail
           .team_bio
             h4.team_name
               a(href="http://www.mattlott.com/") Matt Lott
-            p(data-i18n="about.matt_title")
-              | Cofounder
-            p(data-i18n="about.matt_blurb")
-              | Bicyclist
+            div(data-i18n="about.matt_title")
+            div(data-i18n="about.matt_blurb")
 
         li.row
 
-          a(href="http://www.georgesaines.com/")
-            img(src="/images/pages/about/george_small.png").img-thumbnail
-          .team_bio
-            h4.team_name
-              a(href="http://www.georgesaines.com/") George Saines
-            p(data-i18n="about.george_title")
-              | Cofounder
-            p(data-i18n="about.george_blurb")
-              | Businesser
-
           a(href="http://cat.zdh.com/")
             img(src="/images/pages/about/cat_small.png").img-thumbnail
           .team_bio
             h4.team_name
               a(href="http://cat.zdh.com/") Catherine Weresow
-            p(data-i18n="about.cat_title")
-              | Chief Artisan
-            p(data-i18n="about.cat_blurb")
-              | Airbender
-
-        li.row
+            div(data-i18n="about.cat_title")
+            div(data-i18n="about.cat_blurb")
 
           img(src="/images/pages/about/scott_small.png").img-thumbnail
           .team_bio
             h4.team_name Scott Erickson
-            p(data-i18n="about.scott_title")
-              | Cofounder
-            p(data-i18n="about.scott_blurb")
-              | Reasonable one
+            div(data-i18n="about.scott_title")
+            div(data-i18n="about.scott_blurb")
 
-          a(href="http://michaelschmatz.com")
-            img(src="/images/pages/about/michael_small.png").img-thumbnail
+        li.row
+
+          img(src="/images/pages/about/maka_small.png").img-thumbnail
+          .team_bio
+            h4.team_name Michael 'Maka' Gradin
+            div(data-i18n="about.maka_title")
+            div(data-i18n="about.maka_blurb")
+
+          a(href="http://basicer.com/")
+            img(src="/images/pages/about/rob_small.png").img-thumbnail
           .team_bio
             h4.team_name
-              a(href="http://michaelschmatz.com/") Michael Schmatz
-            p(data-i18n="about.michael_title")
-              | Programmer
-            p(data-i18n="about.michael_blurb")
-              | Sys Admin
+              a(href="http://basicer.com/") Rob Blanckaert
+            div(data-i18n="about.rob_title")
+            div(data-i18n="about.rob_blurb")
+
+        li.row
+
+          img(src="/images/pages/about/josh_c_small.png").img-thumbnail
+          .team_bio
+            h4.team_name Josh Callebaut
+            div(data-i18n="about.josh_c_title")
+            div(data-i18n="about.josh_c_blurb")
+
+          a(href="http://robinyang.com/")
+            img(src="/images/pages/about/robin_small.png").img-thumbnail
+          .team_bio
+            h4.team_name
+              a(href="http://robinyang.com/") Robin Yang
+            div(data-i18n="about.robin_title")
+            div(data-i18n="about.robin_blurb")
+
+
+        // Part time / contract
 
         li.row
 
@@ -142,20 +149,16 @@ block content
           .team_bio
             h4.team_name
               a(href="http://floor.is/lava/") Josh Lee
-            p(data-i18n="about.josh_title")
-              | Game Designer
-            p(data-i18n="about.josh_blurb")
-              | Floor Is Lava
+            div(data-i18n="about.josh_title")
+            div(data-i18n="about.josh_blurb")
 
           a(href="https://soundcloud.com/taking-off")
             img(src="/images/pages/about/jose_small.png").img-thumbnail
           .team_bio
             h4.team_name
               a(href="https://soundcloud.com/taking-off") Jose Antonini
-            p(data-i18n="about.jose_title")
-              | Music
-            p(data-i18n="about.jose_blurb")
-              | Taking Off
+            div(data-i18n="about.jose_title")
+            div(data-i18n="about.jose_blurb")
 
         li.row
 
@@ -164,69 +167,22 @@ block content
           .team_bio
             h4.team_name
               a(href="http://retrostylegames.com/") Pavel Konstantinov
-            p(data-i18n="about.retrostyle_title")
-              | Illustration
-            p(data-i18n="about.retrostyle_blurb")
-              | RetroStyle Games
+            div(data-i18n="about.retrostyle_title")
+            div(data-i18n="about.retrostyle_blurb")
 
           a(href="http://retrostylegames.com/")
             img(src="/images/pages/about/oleg_small.png").img-thumbnail
           .team_bio
             h4.team_name
               a(href="http://retrostylegames.com/") Oleg Ulyanickiy
-            p(data-i18n="about.retrostyle_title")
-              | Illustration
-            p(data-i18n="about.retrostyle_blurb")
-              | RetroStyle Games
-
-        li.row
-
-          a(href="http://basicer.com/")
-            img(src="/images/pages/about/rob_small.png").img-thumbnail
-          .team_bio
-            h4.team_name
-              a(href="http://basicer.com/") Rob Blanckaert
-            p(data-i18n="about.rob_title")
-              | Compiler Engineer
-            p(data-i18n="about.rob_blurb")
-              | Codes things and stuff.
-
-          img(src="/images/pages/about/josh_c_small.png").img-thumbnail
-          .team_bio
-            h4.team_name
-              | Josh Callebaut
-            p(data-i18n="about.josh_c_title")
-              | Game Designer
-            p(data-i18n="about.josh_c_blurb")
-              | Designs games.
+            div(data-i18n="about.retrostyle_title")
+            div(data-i18n="about.retrostyle_blurb")
 
         li.row
 
           img(src="/images/pages/about/carlos_small.png").img-thumbnail
           .team_bio
-            h4.team_name
-              | Carlos Maia
-            p(data-i18n="about.carlos_title")
-              | Region Manager, Brazil
-            p(data-i18n="about.carlos_blurb")
-              | Celery Man
+            h4.team_name Carlos Maia
+            div(data-i18n="about.carlos_title")
+            div(data-i18n="about.carlos_blurb")
 
-          img(src="/images/pages/about/maka_small.png").img-thumbnail
-          .team_bio
-            h4.team_name
-              | Michael 'Maka' Gradin
-            p(data-i18n="about.maka_title")
-              | Customer Advocate
-            p(data-i18n="about.maka_blurb")
-              | Storyteller
-
-        li.row
-
-          img(src="/images/pages/about/robin_small.png").img-thumbnail
-          .team_bio
-            h4.team_name
-              | Robin Yang
-            p(data-i18n="about.robin_title")
-              | UX Design & Research
-            p(data-i18n="about.robin_blurb")
-              | Scaffolding
\ No newline at end of file
diff --git a/app/templates/account/account-settings-view.jade b/app/templates/account/account-settings-view.jade
index cabc1d8c9..adb7f45bc 100644
--- a/app/templates/account/account-settings-view.jade
+++ b/app/templates/account/account-settings-view.jade
@@ -159,7 +159,7 @@ else
                   | (Translator)
               input#email_diplomatNews(name="email_diplomatNews", type="checkbox", checked=subs.diplomatNews)
               span(data-i18n="contribute.diplomat_subscribe_desc").help-block Get emails about i18n developments and, eventually, levels to translate.
-      
+
             .form-group.checkbox
               label.control-label(for="email_ambassadorNews")
                 span(data-i18n="classes.ambassador_title")
@@ -169,7 +169,13 @@ else
                   | (Support)
               input#email_ambassadorNews(name="email_ambassadorNews", type="checkbox", checked=subs.ambassadorNews)
               span(data-i18n="contribute.ambassador_subscribe_desc").help-block Get emails on support updates and multiplayer developments.
-                  
+
+            .form-group.checkbox
+              label.control-label(for="email_teacherNews")
+                span(data-i18n="classes.teacher_title")
+              input#email_teacherNews(name="email_teacherNews", type="checkbox", checked=subs.teacherNews)
+              span(data-i18n="contribute.teacher_subscribe_desc").help-block
+
             button#toggle-all-btn.btn.btn-primary.form-control(data-i18n="account_settings.email_toggle") Toggle All
 
       .panel.panel-default
diff --git a/app/templates/admin.jade b/app/templates/admin.jade
index 864fe1041..795bc9190 100644
--- a/app/templates/admin.jade
+++ b/app/templates/admin.jade
@@ -49,6 +49,8 @@ block content
         ul
           li
             a(href="/admin/analytics/subscriptions") Subscriptions
+    li
+      a(href="/admin/design-elements") Design Elements
 
   if me.isAdmin()
     hr
diff --git a/app/templates/admin/analytics.jade b/app/templates/admin/analytics.jade
index 87de02c12..bc9dc1ff9 100644
--- a/app/templates/admin/analytics.jade
+++ b/app/templates/admin/analytics.jade
@@ -35,6 +35,27 @@ block content
     h3 Active Users 90 days
     .active-users-chart.line-chart-container
 
+    h3 Furthest Course
+    .small Teacher: owner of a course instance
+    .small Student: member of a course instance (assigned to course)
+    .small For course instances created in last #{view.furthestCourseDayRange} days, not Single Player, hourOfCode != true
+    .small Counts are not summed.  I.e. a student or teacher only contributes to the count of one course.
+    if view.teacherCourseDistribution
+      table.table.table-striped.table-condensed
+        tr
+          th Course
+          th Teachers
+          th Students
+          th Avg students per teacher
+        each count, courseIndex in view.teacherCourseDistribution
+          tr
+            td= view.courses.models[courseIndex].get('name')
+            td= count
+            td= view.studentCourseDistribution[courseIndex] || 0
+            td= Math.round((view.studentCourseDistribution[courseIndex] || 0) / count)
+    else
+      div Loading ...
+
     h1 Active Classes
     table.table.table-striped.table-condensed
       tr
diff --git a/app/templates/admin/design-elements-view.jade b/app/templates/admin/design-elements-view.jade
new file mode 100644
index 000000000..5dcf7de48
--- /dev/null
+++ b/app/templates/admin/design-elements-view.jade
@@ -0,0 +1,477 @@
+.well.container-fluid
+  h1 Bootstrap CSS
+  
+  .row
+    .col-sm-6
+      .panel.panel-default
+        .panel-heading
+          a#tables.panel-title(href="#tables") Tables
+
+        .panel-body
+          mixin table-content
+            tr
+              th #
+              th First Name
+              th Last Name
+              th Username
+            tr
+              th 1
+              td Mark
+              td Otto
+              td @mdo
+            tr
+              th 2
+              td Jacob
+              td Thornton
+              td @fat
+            tr
+              th 3
+              td Larry
+              td the Bird
+              td @twitter
+
+          h3 Basic
+          table.table
+            +table-content
+
+          h3 Bordered
+          table.table.table-bordered
+            +table-content
+
+          h3 Striped
+          table.table.table-striped
+            +table-content
+            
+    .col-sm-6
+      .panel.panel-default
+        .panel-heading
+          a#tables.panel-title(href="#tables") Tables
+
+        .panel-body
+
+          h3 Hover
+          table.table.table-hover
+            +table-content
+
+          h3 Condensed
+          table.table.table-condensed
+            +table-content
+
+          h3 Context
+          table.table
+            tr.active
+              td Active
+            tr.success
+              td Success
+            tr.info
+              td Info
+            tr.warning
+              td Warning
+            tr.danger
+              td Danger
+              
+    .col-sm-3
+      .panel.panel-default
+        .panel-heading
+          a#headers.panel-title(href="#headers") Headers
+            
+        .panel-body
+          h1 Header 1
+            small.spl secondary text
+          h2 Header 2
+            small.spl secondary text
+          h3 Header 3
+            small.spl secondary text
+          h4 Header 4
+            small.spl secondary text
+          h5 Header 5
+            small.spl secondary text
+          h6 Header 6
+            small.spl secondary text
+            
+      .panel.panel-default
+        .panel-heading
+          a#user-input.panel-title(href="#user-input") User input
+
+        .panel-body
+          kbd ctrl + ,
+          
+      .panel.panel-default
+        .panel-heading
+          a#horizontal-rule.panel-title(href="#horizontal-rule") Horizontal Rule
+
+        .panel-body
+          div Text above
+          hr
+          div Text below
+          
+    .col-sm-3
+      
+      .panel.panel-default
+        .panel-heading
+          a#forms.panel-title(href="#forms") Forms
+          
+        .panel-body
+          h3 Default
+          .form
+            .form-group
+              label.control-label Input
+              input.form-control
+              
+            .form-group
+              label.control-label Textarea
+              textarea.form-control
+              .help-block Help block
+              
+            .form-group
+              label.control-label Select
+              select.form-control
+                option Option 1
+                option Option 2
+                
+            .form-group
+              label Disabled
+              input.form-control(disabled=true)
+              
+            .form-group.has-error
+              label.control-label Validation error
+              input.form-control
+              
+            .form-group
+              label Large input
+              input.form-control.input-lg
+              
+            .form-group
+              label Small input
+              input.form-control.input-sm
+      
+    .col-sm-3
+      .panel.panel-default
+        .panel-heading
+          a#buttons.panel-title(href="#buttons") Buttons
+          
+        .panel-body
+          div
+            button.btn.btn-default Default
+            span.spr
+            button.btn.btn-primary Primary
+            span.spr
+            button.btn.btn-success Success
+            span.spr
+            button.btn.btn-info Info
+            span.spr
+            button.btn.btn-warning Warning
+            span.spr
+            button.btn.btn-danger Danger
+            span.spr
+            button.btn.btn-default(disabled=true) Disabled
+            
+          
+          hr
+            
+          div
+            button.btn.btn-default.btn-lg Large
+            span.spr
+            button.btn.btn-default Default
+            span.spr
+            button.btn.btn-default.btn-sm Small
+            span.spr
+            button.btn.btn-default.btn-xs Extra small
+            
+          hr
+          
+          div
+            button.btn.btn-default.btn-illustrated Default illustrated
+            span.spr
+            button.btn.btn-primary.btn-illustrated Primary illustrated
+            span.spr
+            button.btn.btn-success.btn-illustrated Success illustrated
+            span.spr
+            button.btn.btn-info.btn-illustrated Info illustrated
+            span.spr
+            button.btn.btn-warning.btn-illustrated Warning illustrated
+            span.spr
+            button.btn.btn-danger.btn-illustrated Danger illustrated
+          
+      .panel.panel-default
+        .panel-heading
+          a#contextual-text.panel-title(href="#contextual-text") Contextual text
+    
+        .panel-body
+          p.text-muted Muted text
+          p.text-primary Primary text
+          p.text-success Success text
+          p.text-info Info text
+          p.text-warning Warning text
+          p.text-danger Danger text
+          
+    .col-sm-3
+      .panel.panel-default
+        .panel-heading
+          a#images.panel-title(href="#images") Images
+          
+        .panel-body
+          div Rounded
+          img.img-rounded(style="width: 140px" src="/images/pages/contribute/tile_adventurer.png")
+          div Circle
+          img.img-circle(style="width: 140px" src="/images/pages/contribute/tile_adventurer.png")
+          div Thumbnail
+          img.img-thumbnail(style="width: 140px" src="/images/pages/contribute/tile_adventurer.png")
+          div Prize
+          img.img-prize(style="width: 140px" src="/images/pages/contribute/adventurer.png")
+          
+      
+  h1 Bootstrap Components
+  
+  .row
+    .col-sm-3
+  
+      .panel.panel-default
+        .panel-heading
+          a#dropdowns.panel-title(href="#dropdowns") Dropdowns
+          
+        .panel-body
+          .btn-group
+            button.btn.btn-default.dropdown-toggle(data-toggle="dropdown") Dropdown Button
+            ul.dropdown-menu
+              li
+                a Action
+              li
+                a Another action
+                
+      .panel.panel-default
+        .panel-heading
+          a#navs.panel-title(href="#navs") Navs
+          
+        .panel-body
+          ul.nav.nav-tabs
+            li.active 
+              a Home
+            li 
+              a Profile
+            li 
+              a Message
+              
+          hr
+          
+          ul.nav.nav-pills
+            li.active
+              a Home
+            li
+              a Profile
+            li
+              a Message
+              
+      .panel.panel-default
+        .panel-heading
+          a#navbars.panel-title(href="#navbars") Navbars
+          
+        .panel-body
+          nav.navbar.navbar-default
+            .container-fluid
+              .navbar-header
+                button.navbar-toggle.collapsed(data-toggle="collapse", data-target="#main-nav")
+                  span.glyphicon.glyphicon-option-horizontal
+                a.navbar-brand Brand
+              
+              .collapse.navbar-collapse#main-nav
+                ul.nav.navbar-nav
+                  li.active
+                    a Link
+                  li
+                    a Link
+                  
+      .panel.panel-default
+        .panel-heading
+          a#breadcrumbs.panel-title(href="#breadcrumbs") Breadcrumbs
+
+        .panel-body
+          ol.breadcrumb
+            li Home
+            li Library
+            li.active Data
+                
+      .panel.panel-default
+        .panel-heading
+          a#labels.panel-title(href="#labels") Labels
+        .panel-body
+          span.label.label-default default
+          span.spr
+          span.label.label-primary primary
+          span.spr
+          span.label.label-success success
+          span.spr
+          span.label.label-info info
+          span.spr
+          span.label.label-warning warning
+          span.spr
+          span.label.label-danger danger
+          span.spr
+          span.label.label-banner banner
+          
+    .col-sm-3
+      .panel.panel-default
+        .panel-heading
+          a#alerts.panel-title(href="#alerts") Alerts
+          
+        .panel-body
+          .alert.alert-success Success
+          .alert.alert-info Info
+          .alert.alert-warning Warning
+          .alert.alert-danger Danger
+            
+      .panel.panel-default
+        .panel-heading
+          a#progress-bars.panel-title(href="#progress-bars") Progress Bars
+    
+        .panel-body
+          strong Default
+          .progress
+            .progress-bar(style="width: 50%")
+    
+          strong Striped Active
+          .progress.progress-striped.active
+            .progress-bar(style="width: 50%")
+    
+          strong Contextual
+          .progress
+            .progress-bar.progress-bar-success(style="width: 25%") Success
+            .progress-bar.progress-bar-info(style="width: 25%") Info
+            .progress-bar.progress-bar-warning(style="width: 25%") Warning
+            .progress-bar.progress-bar-danger(style="width: 25%") Danger
+              
+    .col-sm-3
+      .panel.panel-default
+        .panel-heading
+          a#list-groups.panel-title(href="#list-groups") List Groups
+
+        .panel-body
+          ul.list-group
+            li.list-group-item List group item 1
+            li.list-group-item List group item 2
+            li.list-group-item List group item 3
+            
+      .panel.panel-info
+        .panel-heading
+          .panel-title Info Panel w/Title
+        .panel-body And body
+        .panel-footer And footer
+          
+      .panel.panel-primary
+        .panel-heading
+          .panel-title Primary Panel w/Title
+        .panel-body And body
+        .panel-footer And footer
+          
+      .panel.panel-default
+        .panel-heading
+          .panel-title Default Panel w/Title
+        .panel-body And body
+        .panel-footer And footer
+          
+    .col-sm-3
+      .panel.panel-success
+        .panel-heading
+          .panel-title Success Panel w/Title
+        .panel-body And body
+        .panel-footer And footer
+          
+      .panel.panel-warning
+        .panel-heading
+          .panel-title warning Panel w/Title
+        .panel-body And body
+        .panel-footer And footer
+          
+      .panel.panel-danger
+        .panel-heading
+          .panel-title Danger Panel w/Title
+        .panel-body And body
+        .panel-footer And footer
+          
+    .col-sm-3
+      .panel.panel-default
+        .panel-heading
+          a#wells.panel-title(href="#wells") Wells
+
+        .panel-body
+          .well Well!
+          .well.well-lg Large well!
+          .well.well-sm Small well!
+          .well.well-parchment Parchment well
+            
+  h1 Bootstrap JavaScript
+
+  .row
+    .col-sm-6
+      .panel.panel-default
+        .panel-heading
+          a#modals.panel-title(href="#modals") Default Modal
+          
+        .panel-body(style="background: lightgrey")#modal-1
+          include /templates/core/modal-base
+          
+    .col-sm-6
+      .panel.panel-default
+        .panel-heading
+          a.panel-title Plain Modal
+
+        .panel-body(style="background: lightgrey")#modal-2
+          include /templates/core/modal-base
+              
+  .row
+    .col-sm-3
+      .panel.panel-default
+        .panel-heading
+          a#tooltips.panel-title(href="#tooltips") Tooltips
+
+        .panel-body
+          button#tooltip.btn.btn-default(title="tooltip text!", data-placement="right", data-trigger="click") Button w/Tooltip
+            
+    .col-sm-3
+      .panel.panel-default
+        .panel-heading
+          a#popovers.panel-title(href="#popovers") Popovers
+
+        .panel-body
+          button#popover.btn.btn-default(title="Popover title" data-content="Popover content" data-trigger="click") Button w/Popover
+          
+          
+  h1 jQuery UI
+  
+  .row
+    .col-sm-3
+      .panel.panel-default
+        .panel-heading
+          a#autocomplete.panel-title(href="#autocomplete") Autocomplete
+
+        .panel-body
+          input#tags
+
+    .col-sm-3
+      .panel.panel-default
+        .panel-heading
+          a#slider.panel-title(href="#slider") Slider
+          
+        .panel-body
+          #slider-example
+      
+  h1 Other
+      
+  .row
+    .col-sm-3
+      .panel.panel-default
+        .panel-heading
+          a#gems.panel-title(href="#gems") Gems
+        .panel-body
+          .gem.gem-20
+          .gem.gem-25
+          .gem.gem-30
+          .gem.gem-40
+          .gem.gem-60
+      
+    .col-sm-3
+      .panel.panel-default
+        .panel-heading
+          a#no-border-image.panel-title(href="#no-border-image") No Border Image
+          
+        .panel-body
\ No newline at end of file
diff --git a/app/templates/core/loading-error.jade b/app/templates/core/loading-error.jade
index d0d2ac5ca..7674ba266 100644
--- a/app/templates/core/loading-error.jade
+++ b/app/templates/core/loading-error.jade
@@ -1,28 +1,97 @@
-.alert.alert-danger.loading-error-alert
-  span(data-i18n="loading_error.could_not_load") Error loading from server
-  span  (
-  span(data-i18n="resources.#{name}")
-  span ) 
-  if !responseText
-    strong(data-i18n="loading_error.connection_failure") Connection failed.
-  else if status === 401
-    strong(data-i18n="loading_error.unauthorized") You need to be signed in. Do you have cookies disabled?
-  else if status === 403
-    strong(data-i18n="loading_error.forbidden") You do not have the permissions.
-  else if status === 404
-    strong(data-i18n="loading_error.not_found") Not found.
-  else if status === 405
-    strong(data-i18n="loading_error.not_allowed") Method not allowed.
-  else if status === 408
-    strong(data-i18n="loading_error.timeout") Server timeout.
-  else if status === 409
-    strong(data-i18n="loading_error.conflict") Resource conflict.
-  else if status === 422
-    strong(data-i18n="loading_error.bad_input") Bad input.
-  else if status >= 500
-    strong(data-i18n="loading_error.server_error") Server error.
+#loading-error.text-center
+  if jqxhr.status === 401
+    h1
+      span.spr 401:
+      span(data-i18n="loading_error.login_required")
+    p(data-i18n="loading_error.login_required_desc")
+    button.login-btn.btn.btn-primary(data-i18n="login.log_in")
+    button#create-account-btn.btn.btn-primary(data-i18n="login.sign_up")
+    
+    // 402 currently not in use. TODO: Set it up
+  else if jqxhr.status === 402
+    h2 402: Payment Required
+    
+  else if jqxhr.status === 403
+    h1
+      span.spr 403:
+      span(data-i18n="loading_error.forbidden") Forbidden
+    p(data-i18n="loading_error.forbidden_desc")
+    
+    // this should make no diff... but sometimes the server returns 403 when it should return 401
+    if !me.isAnonymous()
+      button#logout-btn.btn.btn-primary(data-i18n="login.log_out")
+    
+  else if jqxhr.status === 404
+    h1
+      span.spr 404:
+      span(data-i18n="loading_error.not_found")
+    - var num = Math.floor(Math.random() * 3) + 1;
+    img#not-found-img(src="/images/pages/not_found/404_#{num}.png")
+    p(data-i18n="loading_error.not_found_desc")
+    
+  else if !jqxhr.status
+    h1(data-i18n="loading_error.connection_failure")
+    p(data-i18n="loading_error.connection_failure_desc")
+    
   else
-    strong(data-i18n="loading_error.unknown") Unknown error.
+    if jqxhr.status === 408
+      h1
+        span.spr 408:
+        span(data-i18n="loading_error.timeout")
+    else if jqxhr.status >= 500 && jqxhr.status <= 599
+      h1
+        span.spr #{jqxhr.status}:
+        span(data-i18n="loading_error.server_error")
+    else
+      h1(data-i18n="loading_error.unknown")
+      
+    p(data-i18n="loading_error.general_desc")
 
-  button.btn.btn-xs.retry-loading-resource(data-i18n="common.retry", data-resource-index=resourceIndex) Retry
-  button.btn.btn-xs.skip-loading-resource(data-i18n="play_level.skip", data-resource-index=resourceIndex) Skip
+  #links-row.row
+    .col-sm-3
+      ul.list-unstyled
+        li
+          strong(data-i18n="common.help")
+        li
+          a(href="/", data-i18n="nav.home")
+        li
+          a(href=view.forumLink(), data-i18n="nav.forum")
+        li
+          a(tabindex=-1, data-toggle="coco-modal", data-target="core/ContactModal", data-i18n="nav.contact")
+        li
+          a(href='/community', data-i18n="nav.community")
+      
+    .col-sm-3
+      ul.list-unstyled
+        li
+          strong(data-i18n="courses.students")
+        li
+          a(href="/courses/students", data-i18n="nav.learn_to_code")
+        if me.isAnonymous()
+          li
+            a.login-btn(data-i18n="login.log_in")
+        li
+          a(href="/courses", data-i18n="courses.join_class")
+     
+    .col-sm-3
+      ul.list-unstyled
+        li
+          strong(data-i18n="nav.teachers")
+        li
+          a(href="/schools", data-i18n="about.why_codecombat")
+        if me.isAnonymous()
+          li
+            a.login-btn(data-i18n="login.log_in")
+        li
+          a(href="/courses/teachers", data-i18n="nav.create_a_class")
+      
+    .col-sm-3
+      ul.list-unstyled
+        li
+          strong(data-i18n="nav.other")
+        li
+          a(href="http://blog.codecombat.com/", data-i18n="nav.blog")
+        li
+          a(href="https://www.facebook.com/codecombat", data-i18n="nav.facebook")
+        li
+          a(href="https://twitter.com/codecombat", data-i18n="nav.twitter")
\ No newline at end of file
diff --git a/app/templates/core/subscribe-modal.jade b/app/templates/core/subscribe-modal.jade
index 978ca5890..fec7039f7 100644
--- a/app/templates/core/subscribe-modal.jade
+++ b/app/templates/core/subscribe-modal.jade
@@ -53,7 +53,7 @@
             td.center-ok
               span.glyphicon.glyphicon-ok
           tr
-            td.feature-description
+            td.feature-description.gem-amount
               span(data-i18n="[html]subscribe.feature4")
             if !me.isOnPremiumServer()
               td.free-cell
@@ -83,8 +83,10 @@
       #parents-info(data-i18n="subscribe.parents")
       #payment-methods-info(data-i18n="subscribe.payment_methods")
 
-      button.btn.btn-lg.btn-illustrated.parent-button(data-i18n="subscribe.parent_button")
-      button.btn.btn-lg.btn-illustrated.sale-button(data-i18n="[title]subscribe.sale_button_title", data-i18n="subscribe.sale_button")
+      if !me.isOnPremiumServer()
+        button.btn.btn-lg.btn-illustrated.parent-button(data-i18n="subscribe.parent_button")
+      if view.yearProduct
+        button.btn.btn-lg.btn-illustrated.sale-button(data-i18n="[title]subscribe.sale_button_title", data-i18n="subscribe.sale_button")
       button.btn.btn-lg.btn-illustrated.purchase-button(data-i18n="subscribe.subscribe_title")
 
       if view.state === 'declined'
diff --git a/app/templates/courses/classroom-view.jade b/app/templates/courses/classroom-view.jade
index 46da8ee85..0066a3ef1 100644
--- a/app/templates/courses/classroom-view.jade
+++ b/app/templates/courses/classroom-view.jade
@@ -55,7 +55,7 @@ block content
     for user in view.users.models
       .row
         .col-md-6
-          .student-name= user.broadName() || 'Anoner'
+          .student-name= user.broadName()
         .col-md-6
           if view.teacherMode
             a.remove-student-link.pull-right.text-uppercase(data-user-id=user.id)
diff --git a/app/templates/courses/purchase-courses-view.jade b/app/templates/courses/purchase-courses-view.jade
index 3bba3b638..1ee184029 100644
--- a/app/templates/courses/purchase-courses-view.jade
+++ b/app/templates/courses/purchase-courses-view.jade
@@ -78,11 +78,14 @@ block content
     br
 
     p.text-center#price-form-group
-      strong
-        span(data-i18n="account_prepaid.purchase_total")
-        span.spr : #{view.numberOfStudents}
-        span(data-i18n="courses.enrollments")
-        span.spl x $#{(view.pricePerStudent/100).toFixed(2)} = #{view.getPriceString()}
+      if view.numberOfStudentsIsValid()
+        strong
+          span(data-i18n="account_prepaid.purchase_total")
+          span.spr : #{view.numberOfStudents}
+          span(data-i18n="courses.enrollments")
+          span.spl x $#{(view.pricePerStudent/100).toFixed(2)} = #{view.getPriceString()}
+      else
+        strong Invalid number of students
 
     p.text-center
       button#purchase-btn.btn.btn-lg.btn-success.uppercase(data-i18n="courses.purchase_now")
diff --git a/app/templates/courses/teacher-courses-view.jade b/app/templates/courses/teacher-courses-view.jade
index 87a713336..3d656a146 100644
--- a/app/templates/courses/teacher-courses-view.jade
+++ b/app/templates/courses/teacher-courses-view.jade
@@ -34,7 +34,13 @@ block content
             li
               span.spr(data-i18n="courses.additional_resources_1_pref")
               a(href='http://codecombat.com/docs/CodeCombatTeacherGuideCourse1.pdf', data-i18n="courses.additional_resources_1_mid")
-              span.spl(data-i18n="courses.additional_resources_1_suff")
+              span.spl.spr(data-i18n="courses.additional_resources_1_mid2")
+              a(href='http://codecombat.com/docs/CodeCombatTeacherGuideCourse2.pdf', data-i18n="courses.additional_resources_1_mid3")
+              span.spl.spr(data-i18n="courses.additional_resources_1_suff")
+            li
+              span.spr(data-i18n="courses.educator_wiki_pref")
+              a(href='https://sites.google.com/a/codecombat.com/teacher-guides/', data-i18n="courses.educator_wiki_mid")
+              span.spl(data-i18n="courses.educator_wiki_suff")
             li
               span.spr(data-i18n="courses.additional_resources_2_pref")
               a(href='/teachers/freetrial', data-i18n="teachers_survey.title")
diff --git a/app/templates/editor/level/table.jade b/app/templates/editor/level/table.jade
index b936393e4..a6093232f 100755
--- a/app/templates/editor/level/table.jade
+++ b/app/templates/editor/level/table.jade
@@ -1 +1,35 @@
 extends /templates/common/table
+
+block tableResultsHeader
+  tr
+    th(colspan=4)
+      span(data-i18n="general.results")
+        | Results
+      span
+        |: #{documents.length}
+
+block tableHeader
+  tr
+    th(data-i18n="general.name") Name
+    th(data-i18n="general.description") Description
+    th(data-i18n="general.version") Version
+    th(data-i18n="common.watch") Watch
+
+block tableBody
+  for document in documents
+    - var data = document.attributes;
+    tr(class=document.get('creator') == me.id ? 'mine' : '')
+      td(title=data.name).name-row
+        a(href="/editor/#{page}/#{data.slug || data._id}")
+          | #{data.name}
+      td(title=data.description).description-row
+        | #{data.description}
+      td #{data.version.major}.#{data.version.minor}
+      if document.watching()
+        td.watch-row.watching
+          span(aria-hidden="true").glyphicon.glyphicon-eye-open
+          span(data-i18n="common.watch").sr-only Watch
+      else
+        td.watch-row.not-watching
+          span(aria-hidden="true").glyphicon.glyphicon-eye-close
+          span(data-i18n="common.unwatch").sr-only Unwatch
\ No newline at end of file
diff --git a/app/templates/play/level/modal/course-victory-modal.jade b/app/templates/play/level/modal/course-victory-modal.jade
new file mode 100644
index 000000000..b6c381923
--- /dev/null
+++ b/app/templates/play/level/modal/course-victory-modal.jade
@@ -0,0 +1,4 @@
+.modal-dialog
+  .background-wrapper
+    .modal-content
+      .modal-body
diff --git a/app/templates/play/level/modal/new-item-view.jade b/app/templates/play/level/modal/new-item-view.jade
new file mode 100644
index 000000000..8101beb34
--- /dev/null
+++ b/app/templates/play/level/modal/new-item-view.jade
@@ -0,0 +1,19 @@
+.modal-header
+  #close-modal.well.well-sm.well-parchment(data-dismiss="modal")
+    span.glyphicon.glyphicon-remove
+  .well.well-sm.well-parchment
+    h1(data-i18n="play_level.victory_new_item")
+
+.modal-body
+  .container-fluid
+    .row
+      .col-sm-5.text-center
+        img.img-rounded.img-prize(src=view.item.getPortraitURL())
+        h3#item-header
+          #item-label.label.label-banner= i18n(view.item.attributes, 'name')
+      .col-sm-7
+        .well.well-parchment= i18n(view.item.attributes, 'description')
+
+    .row
+      .col-sm-3.col-sm-offset-9
+        button#continue-btn.btn.btn-illustrated.btn-primary.btn-block.btn-lg.text-uppercase Continue
\ No newline at end of file
diff --git a/app/templates/play/level/modal/progress-view.jade b/app/templates/play/level/modal/progress-view.jade
new file mode 100644
index 000000000..a1a787018
--- /dev/null
+++ b/app/templates/play/level/modal/progress-view.jade
@@ -0,0 +1,42 @@
+.modal-header
+  #close-modal.well.well-sm.well-parchment(data-dismiss="modal")
+    span.glyphicon.glyphicon-remove
+  .well.well-sm.well-parchment
+    h1 Level Complete
+
+.modal-body
+  .container-fluid
+    .row
+      - var colClass = view.nextLevel ? 'col-sm-7' : 'col-sm-12'
+      div(class=colClass)
+        .well.well-sm.well-parchment
+          h3.text-uppercase Completed Level:
+          h2.text-uppercase.text-center= i18n(view.level.attributes, 'name')
+        .well.well-sm.well-parchment
+          h3.text-uppercase Course:
+          .row
+            .col-sm-8
+              h3.text-uppercase.text-center= i18n(view.course.attributes, 'name')
+            .col-sm-4
+              - var stats = view.campaign.statsForSessions(view.levelSessions)
+              h1
+                span #{stats.levels.numDone}/#{stats.levels.size}
+          
+        
+      if view.nextLevel
+        .col-sm-5
+          .well.well-sm.well-parchment
+            h3.text-uppercase Next Level:
+            h2.text-uppercase= i18n(view.nextLevel.attributes, 'name')
+            
+            p= i18n(view.nextLevel.attributes, 'description')
+        
+    .row
+      .col-sm-5.col-sm-offset-2
+      // TODO: Add this and rest of campaign functionality
+      //  button#continue-btn.btn.btn-illustrated.btn-default.btn-block.btn-lg.text-uppercase View Leaderboards
+      .col-sm-5
+        if view.nextLevel
+          button#next-level-btn.btn.btn-illustrated.btn-primary.btn-block.btn-lg.text-uppercase Next Level
+        else
+          button#done-btn.btn.btn-illustrated.btn-primary.btn-block.btn-lg.text-uppercase Done
\ No newline at end of file
diff --git a/app/templates/play/modal/buy-gems-modal.jade b/app/templates/play/modal/buy-gems-modal.jade
index 157b6dfb9..c67c31ca0 100644
--- a/app/templates/play/modal/buy-gems-modal.jade
+++ b/app/templates/play/modal/buy-gems-modal.jade
@@ -20,7 +20,7 @@
               span= product.get('priceString')
 
         .product
-          h4(data-i18n="buy_gems.price") x3500 / mo
+          h4.subscription-gem-amount x{{gems}} / mo
           h3(data-i18n="account.subscription")
           if me.isPremium()
             button.disabled.start-subscription-button.btn.btn-lg.btn-illustrated.btn-success
diff --git a/app/templates/recruitment_base.jade b/app/templates/recruitment_base.jade
deleted file mode 100644
index b04d4848d..000000000
--- a/app/templates/recruitment_base.jade
+++ /dev/null
@@ -1,21 +0,0 @@
-body
-  #fb-root
-  #employers-wrapper
-    block header
-      .nav
-        .content.clearfix
-          .navbar-header
-            a.navbar-brand(href='/')
-              img(src="/images/pages/base/recruitment_logo.png", title="CodeCombat - Learn how to code by playing a game", alt="CodeCombat")
-    block outer_content
-      #outer-content-wrapper
-        
-        #intermediate-content-wrapper
-          
-          #inner-content-wrapper
-            .main-content-area#employer-content-area
-              block content
-                p If this is showing, you dun goofed
-  
-    block footer
-      .footer
\ No newline at end of file
diff --git a/app/templates/sales-view.jade b/app/templates/sales-view.jade
index 5c045755a..068c8b3a3 100644
--- a/app/templates/sales-view.jade
+++ b/app/templates/sales-view.jade
@@ -47,13 +47,13 @@ block content
         .col-md-5
           img#img-game(src='/images/pages/sales/screen1.png')
           .text-center
-            i 
+            i
               small Students learn by writing code to complete levels in the game.
         .col-md-7
           #blurb1
             //- TODO: why don't jade inline tags work here?
             //- http://stackoverflow.com/questions/10953326/what-is-a-concise-way-to-create-inline-elements-in-jade
-            p 
+            p
               strong.spr CodeCombat
               span.spr is a platform for students to learn programming all while playing a game with their classmates.  We believe in encouraging
               strong.spr real, typed code
@@ -83,7 +83,7 @@ block content
         .col-md-5
           img.img-game(src='/images/pages/sales/screen2.png')
           .text-center
-            i 
+            i
               small Teachers can monitor progress, manage classrooms and more.
 
       if me.isAnonymous()
@@ -102,13 +102,14 @@ block content
           td
             #quote1-container
               .teacher-quote
-                span.spr "My class had been struggling with the basics of Python all year. Today they were having fun and getting into it
-                strong - I think they actually forgot that they were actually learning something."
+                span.spr &ldquo;My class had been struggling with the basics of Python all year. Today they were having fun and getting into it
+                strong - I think they forgot that they were actually learning something.&rdquo;
               .row
                 .col-md-4
                 .col-md-8
                   .hero-quote-attribution
                     .teacher-name Tim M.
+                    a(href='https://twitter.com/timmaki',target='_blank') @timmaki
                     .teacher-location Director of Technology, Tilton School
           td
             #quote2-container
@@ -120,8 +121,8 @@ block content
                     .teacher-location.text-right Global Learning Charter Public School
                 .col-md-4
               .teacher-quote
-                span.spr "My girls, who were apprehensive about taking a coding class, are some of my top students.
-                strong They work together and explain the code to each other to make sure each understands."
+                span.spr &ldquo;My girls, who were apprehensive about taking a coding class, are some of my top students.
+                strong They work together and explain the code to each other to make sure each understands.&rdquo;
       br
 
       .text-center.section-subheader Students play CodeCombat during #HourOfCode 2015
@@ -192,7 +193,7 @@ block content
           p Per-student pricing allows us to better support flexibility for both large and small schools. Contact us if you are interested in purchasing paid course enrollments for your classroom or school.  Free trials are also available upon request.
 
         .col-md-4
-          .well 
+          .well
             p.text-center.blurb-subtitle Resources for Teachers
             p
               a(href='http://codecombat.com/docs/CodeCombatHourofCodeGettingStartedGuide.pdf')
diff --git a/app/templates/teachers-free-trial.jade b/app/templates/teachers-free-trial.jade
index 133ebd98b..0dbb89113 100644
--- a/app/templates/teachers-free-trial.jade
+++ b/app/templates/teachers-free-trial.jade
@@ -31,9 +31,6 @@ block content
       span.spl(data-i18n="teachers_survey.contact_2")
   else
     p(data-i18n="teachers_survey.description_1")
-    p 
-      strong.spr Hour of Code Special!
-      span Complete the survey by December 31st and enroll all your students in the paid courses for 2 months.
     p
       span.spr(data-i18n="teachers_survey.description_1b")
       a(href='/teachers', data-i18n="teachers_survey.description_2")
diff --git a/app/templates/test-view.jade b/app/templates/test-view.jade
index 9851af483..edc9cf0f8 100644
--- a/app/templates/test-view.jade
+++ b/app/templates/test-view.jade
@@ -6,10 +6,17 @@ ol.breadcrumb
       a(href=path.url)= path.name
   li.active= currentFolder
 
-.well.pull-left#test-wrapper
+#test-wrapper.well.pull-left
+  #demo-area
   #testing-area
     
 .nav.nav-pills.nav-stacked.pull-right.well#test-nav
+  if view.demosOn
+    button#hide-demos-btn.btn.btn-danger.btn-block Hide Demos
+  else
+    button#show-demos-btn.btn.btn-info.btn-block Show Demos
+    
+  hr
   for child in children
     li(class=child.type)
       a(href=child.url).small
diff --git a/app/views/DemoView.coffee b/app/views/DemoView.coffee
index b59ccdcb3..c250ea355 100644
--- a/app/views/DemoView.coffee
+++ b/app/views/DemoView.coffee
@@ -6,6 +6,9 @@ requireUtils = require 'lib/requireUtils'
 DEMO_REQUIRE_PREFIX = 'test/demo/'
 DEMO_URL_PREFIX = '/demo/'
 
+require 'vendor/jasmine-bundle'
+require 'demo-app'
+
 ###
   What are demo files?
 
@@ -33,24 +36,8 @@ module.exports = DemoView = class DemoView extends RootView
   constructor: (options, @subPath='') ->
     super(options)
     @subPath = @subPath[1..] if @subPath[0] is '/'
-    @loadDemoingLibs() unless DemoView.loaded
-
-  loadDemoingLibs: ->
-    DemoView.loaded = true
-    @queue = new createjs.LoadQueue()
-    @queue.on('complete', @scriptsLoaded, @)
-    window.jasmine = {} # so that mock-ajax properly loads. It expects jasmine to be loaded
-    for f in ['mock-ajax', 'demo-app']
-      @queue.loadFile({
-        src: "/javascripts/#{f}.js"
-        type: createjs.LoadQueue.JAVASCRIPT
-      })
-
-  scriptsLoaded: ->
     @initDemoFiles()
     @children = requireUtils.parseImmediateChildren(@demoFiles, @subPath, DEMO_REQUIRE_PREFIX, DEMO_URL_PREFIX)
-    @render()
-    @runDemo()
 
   # RENDER DATA
 
@@ -61,6 +48,10 @@ module.exports = DemoView = class DemoView extends RootView
     parts = @subPath.split('/')
     c.currentFolder = parts[parts.length-1] or parts[parts.length-2] or 'All'
     c
+    
+  afterInsert: ->
+    super()
+    @runDemo()
 
   # RUNNING DEMOS
 
@@ -82,6 +73,7 @@ module.exports = DemoView = class DemoView extends RootView
     jasmine.Ajax.install()
     view = demoFunc()
     return unless view
+    @ranDemo = true
     if view instanceof ModalView
       @openModalView(view)
     else
@@ -97,4 +89,5 @@ module.exports = DemoView = class DemoView extends RootView
   destroy: ->
     # hack to get jasmine tests to properly run again on clicking links, and make sure if you
     # leave this page (say, back to the main site) that test stuff doesn't follow you.
-    document.location.reload()
+    if @ranDemo
+      document.location.reload()
diff --git a/app/views/SalesView.coffee b/app/views/SalesView.coffee
index ad24217fd..53089c973 100644
--- a/app/views/SalesView.coffee
+++ b/app/views/SalesView.coffee
@@ -21,11 +21,11 @@ module.exports = class SalesView extends RootView
 
   onClickLogin: (e) ->
     @openModalView new AuthModal(mode: 'login') if me.get('anonymous')
-    window.tracker?.trackEvent 'Started Login', category: 'Sales', label: 'Sales Login'
+    window.tracker?.trackEvent 'Started Login', category: 'Sales', label: 'Sales Login', ['Mixpanel']
 
   onClickSignup: (e) ->
     @openModalView new AuthModal() if me.get('anonymous')
-    window.tracker?.trackEvent 'Started Signup', category: 'Sales', label: 'Sales Create'
+    window.tracker?.trackEvent 'Started Signup', category: 'Sales', label: 'Sales Create', ['Mixpanel']
 
   logoutRedirectURL: false
 
diff --git a/app/views/TeachersFreeTrialView.coffee b/app/views/TeachersFreeTrialView.coffee
index 44d15cfc4..8d389f1b4 100644
--- a/app/views/TeachersFreeTrialView.coffee
+++ b/app/views/TeachersFreeTrialView.coffee
@@ -25,6 +25,9 @@ module.exports = class TeachersFreeTrialView extends RootView
     @listenToOnce @existingRequests, 'sync', =>
       @fetchingData = false
       @render?()
+      existingRequest = @existingRequests.at(0)
+      if existingRequest?.get('status') isnt 'submitted' and existingRequest?.get('status') isnt 'approved'
+        window.tracker?.trackEvent 'View Trial Request', category: 'Teachers', label: 'View Trial Request', ['Mixpanel'] 
     @supermodel.loadCollection(@existingRequests, 'own_trial_requests', {cache: false})
 
   onClickTextBox: (e) ->
@@ -82,3 +85,4 @@ module.exports = class TeachersFreeTrialView extends RootView
         console.error 'Error saving trial request', response
       success: (model, response, options) =>
         @refreshData()
+        window.tracker?.trackEvent 'Submit Trial Request', category: 'Teachers', label: 'Trial Request', ['Mixpanel']
diff --git a/app/views/TestView.coffee b/app/views/TestView.coffee
index defeba422..54bfca28b 100644
--- a/app/views/TestView.coffee
+++ b/app/views/TestView.coffee
@@ -1,6 +1,7 @@
 RootView = require 'views/core/RootView'
 template = require 'templates/test-view'
 requireUtils = require 'lib/requireUtils'
+storage = require 'core/storage'
 
 require 'vendor/jasmine-bundle'
 require 'tests'
@@ -13,18 +14,32 @@ module.exports = TestView = class TestView extends RootView
   template: template
   reloadOnClose: true
   loadedFileIDs: []
+  
+  events:
+    'click #show-demos-btn': 'onClickShowDemosButton'
+    'click #hide-demos-btn': 'onClickHideDemosButton'
 
   # INITIALIZE
 
-  constructor: (options, @subPath='') ->
-    super(options)
+  initialize: (options, @subPath='') ->
     @subPath = @subPath[1..] if @subPath[0] is '/'
-    
+    @demosOn = storage.load('demos-on')
+
   afterInsert: ->
     @initSpecFiles()
     @render()
-    TestView.runTests(@specFiles)
+    TestView.runTests(@specFiles, @demosOn)
     window.runJasmine()
+    
+  # EVENTS
+
+  onClickShowDemosButton: ->
+    storage.save('demos-on', true)
+    document.location.reload()
+
+  onClickHideDemosButton: ->
+    storage.remove('demos-on')
+    document.location.reload()
 
   # RENDER DATA
 
@@ -44,8 +59,22 @@ module.exports = TestView = class TestView extends RootView
       prefix = TEST_REQUIRE_PREFIX + @subPath
       @specFiles = (f for f in @specFiles when _.string.startsWith f, prefix)
 
-  @runTests: (specFiles) ->
+  @runTests: (specFiles, demosOn=false) ->
     specFiles ?= @getAllSpecFiles()
+    if demosOn
+      jasmine.demoEl = ($el) ->
+        $el.css({
+          'border': '2px solid black'
+          'background': 'white'
+          'padding': '20px'
+        })
+        $('#demo-area').append($el)
+      jasmine.demoModal = _.once (modal) ->
+        currentView.openModalView(modal)
+    else
+      jasmine.demoEl = _.noop
+      jasmine.demoModal = _.noop
+
     describe 'CodeCombat Client', =>
       jasmine.Ajax.install()
       beforeEach ->
diff --git a/app/views/admin/AnalyticsView.coffee b/app/views/admin/AnalyticsView.coffee
index 17ea76eb0..64542d998 100644
--- a/app/views/admin/AnalyticsView.coffee
+++ b/app/views/admin/AnalyticsView.coffee
@@ -1,3 +1,6 @@
+CocoCollection = require 'collections/CocoCollection'
+Course = require 'models/Course'
+CourseInstance = require 'models/CourseInstance'
 require 'vendor/d3'
 d3Utils = require 'core/d3_utils'
 RootView = require 'views/core/RootView'
@@ -7,6 +10,7 @@ utils = require 'core/utils'
 module.exports = class AnalyticsView extends RootView
   id: 'admin-analytics-view'
   template: template
+  furthestCourseDayRange: 30
   lineColors: ['red', 'blue', 'green', 'purple', 'goldenrod', 'brown', 'darkcyan']
 
   constructor: (options) ->
@@ -114,6 +118,56 @@ module.exports = class AnalyticsView extends RootView
         @updateRevenueChartData()
         @render?()
     }, 0).load()
+    
+    @courses = new CocoCollection([], { url: "/db/course", model: Course})
+    @courses.comparator = "_id" 
+    @listenToOnce @courses, 'sync', @onCoursesSync
+    @supermodel.loadCollection(@courses, 'courses')
+
+  onCoursesSync: ->
+    # Assumes courses retrieved in order
+    @courseOrderMap = {}
+    @courseOrderMap[@courses.models[i].get('_id')] = i for i in [0...@courses.models.length]
+
+    startDay = new Date()
+    startDay.setUTCDate(startDay.getUTCDate() - @furthestCourseDayRange)
+    startDay = startDay.toISOString().substring(0, 10)
+    options =
+      url: '/db/course_instance/-/recent'
+      method: 'POST'
+      data: {startDay: startDay}
+    options.error = (models, response, options) =>
+      return if @destroyed
+      console.error 'Failed to get recent course instances', response
+    options.success = (models) =>
+      @courseInstances = models ? [] 
+      @onCourseInstancesSync()
+      @render?()
+    @supermodel.addRequestResource('get_recent_course_instances', options, 0).load()
+
+  onCourseInstancesSync: ->
+    return unless @courseInstances
+
+    # Find highest course for teachers and students
+    @teacherFurthestCourseMap = {}
+    @studentFurthestCourseMap = {}
+    for courseInstance in @courseInstances
+      courseID = courseInstance.courseID
+      teacherID = courseInstance.ownerID
+      if not @teacherFurthestCourseMap[teacherID] or @teacherFurthestCourseMap[teacherID] < @courseOrderMap[courseID]
+        @teacherFurthestCourseMap[teacherID] = @courseOrderMap[courseID]
+      for studentID in courseInstance.members
+        if not @studentFurthestCourseMap[studentID] or @studentFurthestCourseMap[studentID] < @courseOrderMap[courseID]
+          @studentFurthestCourseMap[studentID] = @courseOrderMap[courseID]
+
+    @teacherCourseDistribution = {}
+    for teacherID, courseIndex of @teacherFurthestCourseMap
+      @teacherCourseDistribution[courseIndex] ?= 0
+      @teacherCourseDistribution[courseIndex]++
+    @studentCourseDistribution = {}
+    for studentID, courseIndex of @studentFurthestCourseMap
+      @studentCourseDistribution[courseIndex] ?= 0
+      @studentCourseDistribution[courseIndex]++
 
   createLineChartPoints: (days, data) ->
     points = []
diff --git a/app/views/admin/DesignElementsView.coffee b/app/views/admin/DesignElementsView.coffee
new file mode 100644
index 000000000..b8e564824
--- /dev/null
+++ b/app/views/admin/DesignElementsView.coffee
@@ -0,0 +1,46 @@
+RootView = require 'views/core/RootView'
+template = require 'templates/admin/design-elements-view'
+
+module.exports = class DesignElementsView extends RootView
+  id: 'design-elements-view'
+  template: template
+  
+  afterInsert: ->
+    super()
+    # hack to get hash links to work. Make this general?
+    hash = document.location.hash
+    document.location.hash = ''
+    setTimeout((-> document.location.hash = hash), 10)
+    @$('#modal-2').find('.background-wrapper').addClass('plain')
+    if hash is '#tooltips'
+      setTimeout((=> @$('#tooltip').tooltip('show')), 20)
+    if hash is '#popovers'
+      setTimeout((=> @$('#popover').popover('show')), 20)
+    tags = [
+      "ActionScript",
+      "AppleScript",
+      "Asp",
+      "BASIC",
+      "C",
+      "C++",
+      "Clojure",
+      "COBOL",
+      "ColdFusion",
+      "Erlang",
+      "Fortran",
+      "Groovy",
+      "Haskell",
+      "Java",
+      "JavaScript",
+      "Lisp",
+      "Perl",
+      "PHP",
+      "Python",
+      "Ruby",
+      "Scala",
+      "Scheme"
+    ]
+    @$('#tags').autocomplete({source: tags})
+    if hash is '#autocomplete'
+      setTimeout((=> @$('#tags').autocomplete("search", "t")), 20)
+    @$('#slider-example').slider()
\ No newline at end of file
diff --git a/app/views/admin/PendingPatchesView.coffee b/app/views/admin/PendingPatchesView.coffee
index f6234db00..1f578f3cb 100644
--- a/app/views/admin/PendingPatchesView.coffee
+++ b/app/views/admin/PendingPatchesView.coffee
@@ -7,7 +7,7 @@ class PendingPatchesCollection extends CocoCollection
   url: '/db/patch?view=pending'
   model: Patch
 
-module.exports = class PatchesView extends RootView
+module.exports = class PendingPatchesView extends RootView
   id: 'pending-patches-view'
   template: template
 
diff --git a/app/views/core/CocoView.coffee b/app/views/core/CocoView.coffee
index ea7d8c602..fd6e7f0d5 100644
--- a/app/views/core/CocoView.coffee
+++ b/app/views/core/CocoView.coffee
@@ -3,6 +3,7 @@ utils = require 'core/utils'
 CocoClass = require 'core/CocoClass'
 loadingScreenTemplate = require 'templates/core/loading'
 loadingErrorTemplate = require 'templates/core/loading-error'
+auth = require 'core/auth'
 
 lastToggleModalCall = 0
 visibleModal = null
@@ -16,8 +17,9 @@ module.exports = class CocoView extends Backbone.View
   template: -> ''
 
   events:
-    'click .retry-loading-resource': 'onRetryResource'
-    'click .skip-loading-resource': 'onSkipResource'
+    'click #loading-error .login-btn': 'onClickLoadingErrorLoginButton'
+    'click #loading-error #create-account-btn': 'onClickLoadingErrorCreateAccountButton'
+    'click #loading-error #logout-btn': 'onClickLoadingErrorLogoutButton'
 
   subscriptions: {}
   shortcuts: {}
@@ -133,6 +135,7 @@ module.exports = class CocoView extends Backbone.View
     context.view = @
     context._ = _
     context.document = document
+    context.i18n = utils.i18n
     context
 
   afterRender: ->
@@ -155,44 +158,27 @@ module.exports = class CocoView extends Backbone.View
   # Error handling for loading
   onResourceLoadFailed: (e) ->
     r = e.resource
+    @stopListening @supermodel
     return if r.jqxhr?.status is 402 # payment-required failures are handled separately
-    if r.jqxhr?.status is 0
-      r.retries ?= 0
-      r.retries += 1
-      if r.retries > 20
-        msg = 'Your computer or our servers appear to be offline. Please try refreshing.'
-        noty text: msg, layout: 'center', type: 'error', killer: true
-        return
-      else
-        @warnConnectionError()
-        return _.delay (=> r.load()), 3000
-
-    @$el.find('.loading-container .errors').append(loadingErrorTemplate({
-      status: r.jqxhr?.status
-      name: r.name
-      resourceIndex: r.rid,
-      responseText: r.jqxhr?.responseText
-    })).i18n()
-    @$el.find('.progress').hide()
+    @showError(r.jqxhr)
 
   warnConnectionError: ->
     msg = $.i18n.t 'loading_error.connection_failure', defaultValue: 'Connection failed.'
     noty text: msg, layout: 'center', type: 'error', killer: true, timeout: 3000
 
-  onRetryResource: (e) ->
-    res = @supermodel.getResource($(e.target).data('resource-index'))
-    # different views may respond to this call, and not all have the resource to reload
-    return unless res and res.isFailed
-    res.load()
-    @$el.find('.progress').show()
-    $(e.target).closest('.loading-error-alert').remove()
-
-  onSkipResource: (e) ->
-    res = @supermodel.getResource($(e.target).data('resource-index'))
-    return unless res and res.isFailed
-    res.markLoaded()
-    @$el.find('.progress').show()
-    $(e.target).closest('.loading-error-alert').remove()
+  onClickLoadingErrorLoginButton: (e) ->
+    e.stopPropagation() # Backbone subviews and superviews will handle this call repeatedly otherwise
+    AuthModal = require 'views/core/AuthModal'
+    @openModalView(new AuthModal({mode: 'login'}))
+  
+  onClickLoadingErrorCreateAccountButton: (e) ->
+    e.stopPropagation()
+    AuthModal = require 'views/core/AuthModal'
+    @openModalView(new AuthModal({mode: 'signup'}))
+  
+  onClickLoadingErrorLogoutButton: (e) ->
+    e.stopPropagation()
+    auth.logoutUser()
 
   # Modals
 
@@ -253,6 +239,23 @@ module.exports = class CocoView extends Backbone.View
     @_lastLoading.find('.loading-screen').remove()
     @_lastLoading.find('>').removeClass('hidden')
     @_lastLoading = null
+    
+  showError: (jqxhr) ->
+    return unless @_lastLoading?
+    context = {
+      jqxhr: jqxhr
+      view: @
+      me: me
+    }
+    @_lastLoading.find('.loading-screen').replaceWith((loadingErrorTemplate(context)))
+    @_lastLoading.i18n()
+
+  forumLink: ->
+    link = 'http://discourse.codecombat.com/'
+    lang = (me.get('preferredLanguage') or 'en-US').split('-')[0]
+    if lang in ['zh', 'ru', 'es', 'fr', 'pt', 'de', 'nl', 'lt']
+      link += "c/other-languages/#{lang}"
+    link
 
   showReadOnly: ->
     return if me.isAdmin() or me.isArtisan()
diff --git a/app/views/core/RootView.coffee b/app/views/core/RootView.coffee
index 632887c9a..5773b14ac 100644
--- a/app/views/core/RootView.coffee
+++ b/app/views/core/RootView.coffee
@@ -100,13 +100,6 @@ module.exports = class RootView extends CocoView
     c.usesSocialMedia = @usesSocialMedia
     c
 
-  forumLink: ->
-    link = 'http://discourse.codecombat.com/'
-    lang = (me.get('preferredLanguage') or 'en-US').split('-')[0]
-    if lang in ['zh', 'ru', 'es', 'fr', 'pt', 'de', 'nl', 'lt']
-      link += "c/other-languages/#{lang}"
-    link
-
   afterRender: ->
     if @$el.find('#site-nav').length # hack...
       @$el.addClass('site-chrome')
diff --git a/app/views/core/SubscribeModal.coffee b/app/views/core/SubscribeModal.coffee
index 0d5316276..a6136b678 100644
--- a/app/views/core/SubscribeModal.coffee
+++ b/app/views/core/SubscribeModal.coffee
@@ -31,6 +31,9 @@ module.exports = class SubscribeModal extends ModalView
   onLoaded: ->
     @basicProduct = @products.findWhere { name: 'basic_subscription' }
     @yearProduct = @products.findWhere { name: 'year_subscription' }
+    if countrySpecificProduct = @products.findWhere { name: "#{me.get('country')}_basic_subscription" }
+      @basicProduct = countrySpecificProduct
+      @yearProduct = @products.findWhere { name: "#{me.get('country')}_year_subscription" }  # probably null
     super()
 
   afterRender: ->
@@ -38,6 +41,9 @@ module.exports = class SubscribeModal extends ModalView
     @setupParentButtonPopover()
     @setupParentInfoPopover()
     @setupPaymentMethodsInfoPopover()
+    if @basicProduct
+      @$el.find('.gem-amount').html $.i18n.t('subscribe.feature4').replace('{{gems}}', @basicProduct.get('gems'))
+    @playSound 'game-menu-open'
 
   setupParentButtonPopover: ->
     popoverTitle = $.i18n.t 'subscribe.parent_email_title'
@@ -62,7 +68,7 @@ module.exports = class SubscribeModal extends ModalView
     popoverContent = "<p>" + $.i18n.t('subscribe.parents_blurb1', nLevels: levelsCompleted) + "</p>"
     popoverContent += "<p>" + $.i18n.t('subscribe.parents_blurb1a') + "</p>"
     popoverContent += "<p>" + $.i18n.t('subscribe.parents_blurb2') + "</p>"
-    price = (@products.findWhere({'name': 'basic_subscription'}).get('amount') / 100).toFixed(2)
+    price = (@basicProduct.get('amount') / 100).toFixed(2)
     # TODO: Update i18next and use its own interpolation system instead
     popoverContent = popoverContent.replace('{{price}}', price)
     popoverContent += "<p>" + $.i18n.t('subscribe.parents_blurb3') + "</p>"
@@ -80,13 +86,16 @@ module.exports = class SubscribeModal extends ModalView
   setupPaymentMethodsInfoPopover: ->
     return unless @products.size()
     popoverTitle = $.i18n.t('subscribe.payment_methods_title')
-    three_month_price = (@products.findWhere({'name': 'basic_subscription'}).get('amount') * 3 / 100).toFixed(2)
-    year_price = (@products.findWhere({name: 'year_subscription'}).get('amount') / 100).toFixed(2)
+    threeMonthPrice = (@basicProduct.get('amount') * 3 / 100).toFixed(2)
+    if @yearProduct
+      yearPrice = (@yearProduct.get('amount') / 100).toFixed(2)
+    else
+      yearPrice = (@basicProduct.get('amount') * 12 / 100).toFixed(2)
     popoverTitle += '<button type="button" class="close" onclick="$(&#39;#payment-methods-info&#39;).popover(&#39;hide&#39;);">&times;</button>'
     popoverContent = "<p>" + $.i18n.t('subscribe.payment_methods_blurb1') + "</p>"
     # TODO: Update i18next and use its own interpolation system instead
-    popoverContent = popoverContent.replace('{{three_month_price}}', three_month_price)
-    popoverContent = popoverContent.replace('{{year_price}}', year_price)
+    popoverContent = popoverContent.replace('{{three_month_price}}', threeMonthPrice)
+    popoverContent = popoverContent.replace('{{year_price}}', yearPrice)
     popoverContent += "<p>" + $.i18n.t('subscribe.payment_methods_blurb2') + " <a href='mailto:support@codecombat.com'>support@codecombat.com</a>."
     @$el.find('#payment-methods-info').popover(
       animation: true
@@ -123,7 +132,7 @@ module.exports = class SubscribeModal extends ModalView
     @$el.find('.parent-button').popover('hide')
 
   onClickPurchaseButton: (e) ->
-    return unless @basicProduct and @yearProduct
+    return unless @basicProduct
     @playSound 'menu-button-click'
     return @openModalView new AuthModal() if me.get('anonymous')
     application.tracker?.trackEvent 'Started subscription purchase'
@@ -134,16 +143,6 @@ module.exports = class SubscribeModal extends ModalView
       alipayReusable: true
     }
 
-    # SALE LOGIC
-    # overwrite amount with sale price
-    # maybe also put in another description with details about how long it lasts, etc
-    # NOTE: Do not change this price without updating the context.price in getRenderData
-    # NOTE: And, the popover content if necessary
-    #options = {
-    #  description: 'Monthly Subscription (HoC sale)'
-    #  amount: 399
-    #}
-
     @purchasedAmount = options.amount
     stripeHandler.open(options)
 
@@ -223,3 +222,7 @@ module.exports = class SubscribeModal extends ModalView
       @state = 'unknown_error'
       @stateMessage = "#{xhr.status}: #{xhr.responseText}"
     @render()
+
+  onHidden: ->
+    super()
+    @playSound 'game-menu-close'
diff --git a/app/views/courses/ClassroomSettingsModal.coffee b/app/views/courses/ClassroomSettingsModal.coffee
index dbad58b90..824973ff8 100644
--- a/app/views/courses/ClassroomSettingsModal.coffee
+++ b/app/views/courses/ClassroomSettingsModal.coffee
@@ -2,7 +2,7 @@ Classroom = require 'models/Classroom'
 ModalView = require 'views/core/ModalView'
 template = require 'templates/courses/classroom-settings-modal'
 
-module.exports = class AddLevelSystemModal extends ModalView
+module.exports = class ClassroomSettingsModal extends ModalView
   id: 'classroom-settings-modal'
   template: template
 
diff --git a/app/views/courses/ClassroomView.coffee b/app/views/courses/ClassroomView.coffee
index 1005e38b3..7175f4805 100644
--- a/app/views/courses/ClassroomView.coffee
+++ b/app/views/courses/ClassroomView.coffee
@@ -32,23 +32,23 @@ module.exports = class ClassroomView extends RootView
   initialize: (options, classroomID) ->
     return if me.isAnonymous()
     @classroom = new Classroom({_id: classroomID})
-    @supermodel.loadModel @classroom, 'classroom'
+    @supermodel.loadModel @classroom
     @courses = new CocoCollection([], { url: "/db/course", model: Course})
     @courses.comparator = '_id'
-    @supermodel.loadCollection(@courses, 'courses')
+    @supermodel.loadCollection(@courses)
     @campaigns = new CocoCollection([], { url: "/db/campaign", model: Campaign })
     @courses.comparator = '_id'
-    @supermodel.loadCollection(@campaigns, 'campaigns', { data: { type: 'course' }})
+    @supermodel.loadCollection(@campaigns, { data: { type: 'course' }})
     @courseInstances = new CocoCollection([], { url: "/db/course_instance", model: CourseInstance})
     @courseInstances.comparator = 'courseID'
-    @supermodel.loadCollection(@courseInstances, 'course_instances', { data: { classroomID: classroomID } })
+    @supermodel.loadCollection(@courseInstances, { data: { classroomID: classroomID } })
     @prepaids = new Prepaids()
     @prepaids.comparator = '_id'
     @prepaids.fetchByCreator(me.id)
-    @supermodel.loadCollection(@prepaids, 'prepaids')
+    @supermodel.loadCollection(@prepaids)
     @users = new CocoCollection([], { url: "/db/classroom/#{classroomID}/members", model: User })
     @users.comparator = (user) => user.broadName().toLowerCase()
-    @supermodel.loadCollection(@users, 'users')
+    @supermodel.loadCollection(@users)
     @listenToOnce @courseInstances, 'sync', @onCourseInstancesSync
     @sessions = new CocoCollection([], { model: LevelSession })
 
@@ -56,7 +56,7 @@ module.exports = class ClassroomView extends RootView
     @sessions = new CocoCollection([], { model: LevelSession })
     for courseInstance in @courseInstances.models
       sessions = new CocoCollection([], { url: "/db/course_instance/#{courseInstance.id}/level_sessions", model: LevelSession })
-      @supermodel.loadCollection(sessions, 'sessions', { data: { project: ['level', 'playtime', 'creator', 'changed', 'state.complete'].join(' ') } })
+      @supermodel.loadCollection(sessions, { data: { project: ['level', 'playtime', 'creator', 'changed', 'state.complete'].join(' ') } })
       courseInstance.sessions = sessions
       sessions.courseInstance = courseInstance
       courseInstance.sessionsByUser = {}
@@ -79,6 +79,7 @@ module.exports = class ClassroomView extends RootView
   onLoaded: ->
     @teacherMode = me.isAdmin() or @classroom.get('ownerID') is me.id
     userSessions = @sessions.groupBy('creator')
+    @users.remove(@users.where({ deleted: true }))
     for user in @users.models
       user.sessions = new CocoCollection(userSessions[user.id], { model: LevelSession })
       user.sessions.comparator = 'changed'
diff --git a/app/views/courses/CoursesView.coffee b/app/views/courses/CoursesView.coffee
index 3de817c28..55e0158e7 100644
--- a/app/views/courses/CoursesView.coffee
+++ b/app/views/courses/CoursesView.coffee
@@ -31,13 +31,13 @@ module.exports = class CoursesView extends RootView
     @courseInstances = new CocoCollection([], { url: "/db/user/#{me.id}/course_instances", model: CourseInstance})
     @courseInstances.comparator = (ci) -> return ci.get('classroomID') + ci.get('courseID')
     @listenToOnce @courseInstances, 'sync', @onCourseInstancesLoaded
-    @supermodel.loadCollection(@courseInstances, 'course_instances')
+    @supermodel.loadCollection(@courseInstances)
     @classrooms = new CocoCollection([], { url: "/db/classroom", model: Classroom })
-    @supermodel.loadCollection(@classrooms, 'classrooms', { data: {memberID: me.id} })
+    @supermodel.loadCollection(@classrooms, { data: {memberID: me.id} })
     @courses = new CocoCollection([], { url: "/db/course", model: Course})
-    @supermodel.loadCollection(@courses, 'courses')
+    @supermodel.loadCollection(@courses)
     @campaigns = new CocoCollection([], { url: "/db/campaign", model: Campaign })
-    @supermodel.loadCollection(@campaigns, 'campaigns', { data: { type: 'course' }})
+    @supermodel.loadCollection(@campaigns, { data: { type: 'course' }})
 
   onCourseInstancesLoaded: ->
     map = {}
@@ -51,7 +51,7 @@ module.exports = class CoursesView extends RootView
         model: LevelSession
       })
       courseInstance.sessions.comparator = 'changed'
-      @supermodel.loadCollection(courseInstance.sessions, 'sessions', { data: { project: 'state.complete level.original playtime changed' }})
+      @supermodel.loadCollection(courseInstance.sessions, { data: { project: 'state.complete level.original playtime changed' }})
 
     @hocCourseInstance = @courseInstances.findWhere({hourOfCode: true})
     if @hocCourseInstance
diff --git a/app/views/courses/PurchaseCoursesView.coffee b/app/views/courses/PurchaseCoursesView.coffee
index a97c32cd9..bf721b031 100644
--- a/app/views/courses/PurchaseCoursesView.coffee
+++ b/app/views/courses/PurchaseCoursesView.coffee
@@ -72,10 +72,12 @@ module.exports = class PurchaseCoursesView extends RootView
 
   updatePrice: ->
     @renderSelectors '#price-form-group'
+    
+  numberOfStudentsIsValid: -> @numberOfStudents > 0 and @numberOfStudents < 100000 
 
   onClickPurchaseButton: ->
     return @openModalView new AuthModal() if me.isAnonymous()
-    if @numberOfStudents < 1 or not _.isFinite(@numberOfStudents)
+    unless @numberOfStudentsIsValid()
       alert("Please enter the maximum number of students needed for your class.")
       return
 
diff --git a/app/views/courses/StudentLogInModal.coffee b/app/views/courses/StudentLogInModal.coffee
index ffebbab8e..91c2d86fc 100644
--- a/app/views/courses/StudentLogInModal.coffee
+++ b/app/views/courses/StudentLogInModal.coffee
@@ -4,7 +4,7 @@ auth = require 'core/auth'
 forms = require 'core/forms'
 User = require 'models/User'
 
-module.exports = class StudentSignInModal extends ModalView
+module.exports = class StudentLogInModal extends ModalView
   id: 'student-log-in-modal'
   template: template
 
diff --git a/app/views/editor/component/ThangComponentConfigView.coffee b/app/views/editor/component/ThangComponentConfigView.coffee
index 8f8580043..f0322df81 100644
--- a/app/views/editor/component/ThangComponentConfigView.coffee
+++ b/app/views/editor/component/ThangComponentConfigView.coffee
@@ -104,13 +104,11 @@ class SolutionsNode extends TreemaArrayNode
 
   onClickFillDefaults: (e) =>
     e.preventDefault()
-    sources = {}
-    if source = @parent.data.source
-      sources.javascript = source
-    
+
     sources = { javascript: @parent.data.source }
     _.extend sources, @parent.data.languages or {}
     solutions = _.clone(@data)
+    solutions = _.filter(solutions, (solution) -> not _.isEmpty(solution) )
     for language in _.keys(sources)
       source = sources[language]
       solution = _.findWhere(solutions, {language: language})
@@ -120,5 +118,5 @@ class SolutionsNode extends TreemaArrayNode
         language: language
         passes: true
       })
-      
+
     @set('/', solutions)
\ No newline at end of file
diff --git a/app/views/editor/level/LevelSearchView.coffee b/app/views/editor/level/LevelSearchView.coffee
index e7b2ecf87..c384a848c 100644
--- a/app/views/editor/level/LevelSearchView.coffee
+++ b/app/views/editor/level/LevelSearchView.coffee
@@ -6,6 +6,7 @@ module.exports = class LevelSearchView extends SearchView
   model: require 'models/Level'
   modelURL: '/db/level'
   tableTemplate: require 'templates/editor/level/table'
+  projection: ['slug', 'name', 'description', 'version', 'watchers', 'creator']
   page: 'level'
 
   getRenderData: ->
diff --git a/app/views/i18n/I18NEditThangTypeView.coffee b/app/views/i18n/I18NEditThangTypeView.coffee
index 52c058e9b..00f67aeee 100644
--- a/app/views/i18n/I18NEditThangTypeView.coffee
+++ b/app/views/i18n/I18NEditThangTypeView.coffee
@@ -1,8 +1,8 @@
 I18NEditModelView = require './I18NEditModelView'
 ThangType = require 'models/ThangType'
 
-module.exports = class ThangTypeI18NView extends I18NEditModelView
-  id: 'thang-type-i18n-view'
+module.exports = class I18NEditThangTypeView extends I18NEditModelView
+  id: 'i18n-thang-type-view'
   modelClass: ThangType
 
   buildTranslationList: ->
diff --git a/app/views/ladder/MainLadderView.coffee b/app/views/ladder/MainLadderView.coffee
index 66cc9c373..ebd2eca0c 100644
--- a/app/views/ladder/MainLadderView.coffee
+++ b/app/views/ladder/MainLadderView.coffee
@@ -11,8 +11,8 @@ class LevelSessionsCollection extends CocoCollection
     super()
     @url = "/db/user/#{me.id}/level.sessions?project=state.complete,levelID"
 
-module.exports = class LadderHomeView extends RootView
-  id: 'ladder-home-view'
+module.exports = class MainLadderView extends RootView
+  id: 'main-ladder-view'
   template: template
 
   constructor: (options) ->
diff --git a/app/views/ladder/MyMatchesTabView.coffee b/app/views/ladder/MyMatchesTabView.coffee
index 023c1b40b..78237e2e4 100644
--- a/app/views/ladder/MyMatchesTabView.coffee
+++ b/app/views/ladder/MyMatchesTabView.coffee
@@ -117,7 +117,7 @@ module.exports = class MyMatchesTabView extends CocoView
       placeholder = $(el)
       sessionID = placeholder.data('session-id')
       session = _.find @sessions.models, {id: sessionID}
-      if @level.get('slug') in ['ace-of-coders']
+      if @level.get('slug') in ['ace-of-coders', 'elemental-wars']
         mirrorSession = (s for s in @sessions.models when s.get('team') isnt session.get('team'))[0]
       ladderSubmissionView = new LadderSubmissionView session: session, level: @level, mirrorSession: mirrorSession
       @insertSubView ladderSubmissionView, placeholder
diff --git a/app/views/modal/SignupModal.coffee b/app/views/modal/SignupModal.coffee
deleted file mode 100644
index d8311dce5..000000000
--- a/app/views/modal/SignupModal.coffee
+++ /dev/null
@@ -1,4 +0,0 @@
-AuthModal = require 'views/core/AuthModal'
-
-module.exports = class SignupModalView extends AuthModal
-  mode: 'signup'
diff --git a/app/views/play/level/PlayLevelView.coffee b/app/views/play/level/PlayLevelView.coffee
index aa581c10f..ac8af7888 100644
--- a/app/views/play/level/PlayLevelView.coffee
+++ b/app/views/play/level/PlayLevelView.coffee
@@ -36,6 +36,7 @@ GoldView = require './LevelGoldView'
 DuelStatsView = require './DuelStatsView'
 VictoryModal = require './modal/VictoryModal'
 HeroVictoryModal = require './modal/HeroVictoryModal'
+CourseVictoryModal = require './modal/CourseVictoryModal'
 InfiniteLoopModal = require './modal/InfiniteLoopModal'
 LevelSetupManager = require 'lib/LevelSetupManager'
 ContactModal = require 'views/core/ContactModal'
@@ -283,7 +284,7 @@ module.exports = class PlayLevelView extends RootView
       if e.session.get('creator') is '532dbc73a622924444b68ed9'  # Wizard Dude gets his own avatar
         sorcerer = '53e126a4e06b897606d38bef'
       e.session.set 'heroConfig', {"thangType":sorcerer,"inventory":{"misc-0":"53e2396a53457600003e3f0f","programming-book":"546e266e9df4a17d0d449be5","minion":"54eb5dbc49fa2d5c905ddf56","feet":"53e214f153457600003e3eab","right-hand":"54eab7f52b7506e891ca7202","left-hand":"5463758f3839c6e02811d30f","wrists":"54693797a2b1f53ce79443e9","gloves":"5469425ca2b1f53ce7944421","torso":"546d4a549df4a17d0d449a97","neck":"54693274a2b1f53ce79443c9","eyes":"546941fda2b1f53ce794441d","head":"546d4ca19df4a17d0d449abf"}}
-    else if e.level.get('slug') is 'ace-of-coders'
+    else if e.level.get('slug') in ['ace-of-coders', 'elemental-wars']
       goliath = '55e1a6e876cb0948c96af9f8'
       e.session.set 'heroConfig', {"thangType":goliath,"inventory":{"eyes":"53eb99f41a100989a40ce46e","neck":"54693274a2b1f53ce79443c9","wrists":"54693797a2b1f53ce79443e9","feet":"546d4d8e9df4a17d0d449acd","minion":"54eb5bf649fa2d5c905ddf4a","programming-book":"557871261ff17fef5abee3ee"}}
     else if e.level.get('slug') is 'assembly-speed'
@@ -533,6 +534,7 @@ module.exports = class PlayLevelView extends RootView
     @endHighlight()
     options = {level: @level, supermodel: @supermodel, session: @session, hasReceivedMemoryWarning: @hasReceivedMemoryWarning, courseID: @courseID, courseInstanceID: @courseInstanceID}
     ModalClass = if @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder'] then HeroVictoryModal else VictoryModal
+    ModalClass = CourseVictoryModal if @courseID and @courseInstanceID
     victoryModal = new ModalClass(options)
     @openModalView(victoryModal)
     if me.get('anonymous')
diff --git a/app/views/play/level/modal/CourseVictoryModal.coffee b/app/views/play/level/modal/CourseVictoryModal.coffee
new file mode 100644
index 000000000..6b63f0faa
--- /dev/null
+++ b/app/views/play/level/modal/CourseVictoryModal.coffee
@@ -0,0 +1,170 @@
+ModalView = require 'views/core/ModalView'
+template = require 'templates/play/level/modal/course-victory-modal'
+Achievements = require 'collections/Achievements'
+Level = require 'models/Level'
+Campaign = require 'models/Campaign'
+Course = require 'models/Course'
+ThangType = require 'models/ThangType'
+ThangTypes = require 'collections/ThangTypes'
+LevelSessions = require 'collections/LevelSessions'
+EarnedAchievement = require 'models/EarnedAchievement'
+LocalMongo = require 'lib/LocalMongo'
+ProgressView = require './ProgressView'
+NewItemView = require './NewItemView'
+
+module.exports = class CourseVictoryModal extends ModalView
+  id: 'course-victory-modal'
+  template: template
+  closesOnClickOutside: false
+
+  
+  initialize: (options) ->
+    @courseID = options.courseID
+    @courseInstanceID = options.courseInstanceID
+    @views = []
+
+    @session = options.session
+    @level = options.level
+    @newItems = new ThangTypes()
+    @newHeroes = new ThangTypes()
+    
+    @achievements = options.achievements
+    if not @achievements
+      @achievements = new Achievements()
+      @achievements.fetchRelatedToLevel(@session.get('level').original)
+      @achievements = @supermodel.loadCollection(@achievements, 'achievements').model
+      @listenToOnce @achievements, 'sync', @onAchievementsLoaded
+    else
+      @onAchievementsLoaded()
+    
+    @playSound 'victory'
+    @nextLevel = options.nextLevel
+    if (nextLevel = @level.get('nextLevel')) and not @nextLevel
+      @nextLevel = new Level().setURL "/db/level/#{nextLevel.original}/version/#{nextLevel.majorVersion}"
+      @nextLevel = @supermodel.loadModel(@nextLevel, 'level').model
+      
+    @campaign = new Campaign()
+    @course = options.course
+    if @courseID and not @course
+      @course = new Course().setURL "/db/course/#{@courseID}"
+      @course = @supermodel.loadModel(@course, 'course').model
+      if @course.loading
+        @listenToOnce @course, 'sync', @onCourseLoaded
+      else
+        @onCourseLoaded()
+    else if @course
+      @onCourseLoaded()
+
+    if @courseInstanceID
+      @levelSessions = new LevelSessions()
+      @levelSessions.fetchForCourseInstance(@courseInstanceID)
+      @levelSessions = @supermodel.loadCollection(@levelSessions, 'sessions', { 
+        data: { project: 'state.complete level.original playtime changed' }
+      }).model
+
+
+  onCourseLoaded: ->
+    @campaign.set('_id', @course.get('campaignID'))
+    @campaign = @supermodel.loadModel(@campaign, 'campaign').model
+
+      
+  onAchievementsLoaded: ->
+    @achievements.models = _.filter @achievements.models, (m) -> not m.get('query')?.ladderAchievementDifficulty  # Don't show higher AI difficulty achievements
+    itemOriginals = []
+    heroOriginals = []
+    achievementIDs = []
+    for achievement in @achievements.models
+      rewards = achievement.get('rewards') or {}
+      heroOriginals.push rewards.heroes or []
+      itemOriginals.push rewards.items or []
+      achievement.completed = LocalMongo.matchesQuery(@session.attributes, achievement.get('query'))
+      achievementIDs.push(achievement.id) if achievement.completed
+
+    itemOriginals = _.uniq _.flatten itemOriginals
+    heroOriginals = _.uniq _.flatten heroOriginals
+    #project = ['original', 'rasterIcon', 'name', 'soundTriggers', 'i18n']  # This is what we need, but the PlayHeroesModal needs more, and so we load more to fill up the supermodel.
+    project = ['original', 'rasterIcon', 'name', 'slug', 'soundTriggers', 'featureImages', 'gems', 'heroClass', 'description', 'components', 'extendedName', 'unlockLevelName', 'i18n']
+    for [newThangTypeCollection, originals] in [[@newItems, itemOriginals], [@newHeroes, heroOriginals]]
+      for original in originals
+        thang= new ThangType()
+        thang.url = "/db/thang.type/#{original}/version"
+        thang.project = project
+        @supermodel.loadModel(thang, 'thang')
+        newThangTypeCollection.add(thang)
+      
+    @newEarnedAchievements = []
+    for achievement in @achievements.models
+      continue unless achievement.completed
+      ea = new EarnedAchievement({
+        collection: achievement.get('collection')
+        triggeredBy: @session.id
+        achievement: achievement.id
+      })
+      ea.save()
+      # Can't just add models to supermodel because each ea has the same url
+      ea.sr = @supermodel.addSomethingResource(ea.cid)
+      @newEarnedAchievements.push ea
+      @listenToOnce ea, 'sync', (model) ->
+        model.sr.markLoaded()
+        if _.all((ea.id for ea in @newEarnedAchievements))
+          unless me.loading
+            @supermodel.loadModel(me, 'user', {cache: false})
+          @newEarnedAchievementsResource.markLoaded()
+
+    
+    # have to use a something resource because addModelResource doesn't handle models being upserted/fetched via POST like we're doing here
+    @newEarnedAchievementsResource = @supermodel.addSomethingResource('earned achievements') if @newEarnedAchievements.length
+
+  
+  onLoaded: ->
+    super()
+    @views = []
+    
+    # TODO: Add main victory view
+    # TODO: Add level up view
+    # TODO: Add new hero view?
+    
+    for newItem in @newItems.models
+      @views.push(new NewItemView({item: newItem}))
+    
+    progressView = new ProgressView({
+      level: @level
+      nextLevel: @nextLevel
+      course: @course
+      campaign: @campaign
+      levelSessions: @levelSessions
+    })
+    
+    progressView.once 'done', @onDone, @
+    progressView.once 'next-level', @onNextLevel, @
+    for view in @views
+      view.on 'continue', @onViewContinue, @
+    @views.push(progressView)
+    
+    @showView(_.first(@views))
+  
+  afterRender: ->
+    super()
+    @showView(@currentView)
+
+  showView: (view) ->
+    return unless view
+    view.setElement(@$('.modal-content'))
+    view.$el.attr('id', view.id)
+    view.$el.addClass(view.className)
+    view.render()
+    @currentView = view
+
+  onViewContinue: ->
+    index = _.indexOf(@views, @currentView)
+    @showView(@views[index+1])
+
+  onNextLevel: ->
+    link = "/play/level/#{@nextLevel.get('slug')}?course=#{@courseID}&course-instance=#{@courseInstanceID}"
+    application.router.navigate(link, {trigger: true})
+
+  onDone: ->
+    link = "/courses/#{@courseID}/#{@courseInstanceID}"
+    application.router.navigate(link, {trigger: true})
+    
+    
\ No newline at end of file
diff --git a/app/views/play/level/modal/NewItemView.coffee b/app/views/play/level/modal/NewItemView.coffee
new file mode 100644
index 000000000..e79864541
--- /dev/null
+++ b/app/views/play/level/modal/NewItemView.coffee
@@ -0,0 +1,20 @@
+CocoView = require 'views/core/CocoView'
+
+module.exports = class NewItemView extends CocoView
+  id: 'new-item-view'
+  className: 'modal-content' 
+  template: require('templates/play/level/modal/new-item-view')
+  
+  events:
+    'click #continue-btn': 'onClickContinueButton'
+    
+  afterRender: ->
+    super()
+    # TODO: Animate icon
+    
+  initialize: (options) ->
+    @item = options.item
+    super()
+
+  onClickContinueButton: ->
+    @trigger 'continue'
\ No newline at end of file
diff --git a/app/views/play/level/modal/ProgressView.coffee b/app/views/play/level/modal/ProgressView.coffee
new file mode 100644
index 000000000..ba0e5e1c7
--- /dev/null
+++ b/app/views/play/level/modal/ProgressView.coffee
@@ -0,0 +1,24 @@
+CocoView = require 'views/core/CocoView'
+
+module.exports = class ProgressView extends CocoView
+  
+  id: 'progress-view'
+  className: 'modal-content'
+  template: require 'templates/play/level/modal/progress-view'
+
+  events:
+    'click #done-btn': 'onClickDoneButton'
+    'click #next-level-btn': 'onClickNextLevelButton'
+
+  initialize: (options) ->
+    @level = options.level
+    @course = options.course
+    @nextLevel = options.nextLevel
+    @campaign = options.campaign
+    @levelSessions = options.levelSessions
+
+  onClickDoneButton: ->
+    @trigger 'done'
+
+  onClickNextLevelButton: ->
+    @trigger 'next-level'
\ No newline at end of file
diff --git a/app/views/play/level/tome/CastButtonView.coffee b/app/views/play/level/tome/CastButtonView.coffee
index 5ec22690d..251484f8d 100644
--- a/app/views/play/level/tome/CastButtonView.coffee
+++ b/app/views/play/level/tome/CastButtonView.coffee
@@ -31,7 +31,7 @@ module.exports = class CastButtonView extends CocoView
     @castShortcut = '⇧↵'
     @updateReplayabilityInterval = setInterval @updateReplayability, 1000
     @observing = options.session.get('creator') isnt me.id
-    @loadMirrorSession() if @options.level.get('slug') in ['ace-of-coders']
+    @loadMirrorSession() if @options.level.get('slug') in ['ace-of-coders', 'elemental-wars']
     @autoSubmitsToLadder = @options.level.get('slug') in ['wakka-maul']
 
   destroy: ->
diff --git a/app/views/play/level/tome/DocFormatter.coffee b/app/views/play/level/tome/DocFormatter.coffee
index 72644029d..94122cd20 100644
--- a/app/views/play/level/tome/DocFormatter.coffee
+++ b/app/views/play/level/tome/DocFormatter.coffee
@@ -154,7 +154,10 @@ module.exports = class DocFormatter
     content = popoverTemplate doc: @doc, docName: docName, language: @options.language, value: @formatValue(), marked: marked, argumentExamples: argumentExamples, writable: @options.writable, selectedMethod: @options.selectedMethod, cooldowns: @inferCooldowns(), item: @options.item
     owner = if @doc.owner is 'this' then @options.thang else window[@doc.owner]
     content = @replaceSpriteName content
-    content.replace /\#\{(.*?)\}/g, (s, properties) => @formatValue downTheChain(owner, properties.split('.'))
+    content = content.replace /\#\{(.*?)\}/g, (s, properties) => @formatValue downTheChain(owner, properties.split('.'))
+    content = content.replace /{([a-z]+)}([^]*?){\/\1}/g, (s, language, text) =>
+      if language is @options.language then return text
+      return ''
 
   replaceSpriteName: (s) ->
     # Prefer type, and excluded the quotes we'd get with @formatValue
diff --git a/app/views/play/menu/GameMenuModal.coffee b/app/views/play/menu/GameMenuModal.coffee
index 1f0238c3c..6ac4f54bf 100644
--- a/app/views/play/menu/GameMenuModal.coffee
+++ b/app/views/play/menu/GameMenuModal.coffee
@@ -34,7 +34,7 @@ module.exports = class GameMenuModal extends ModalView
     submenus = ['guide', 'options', 'save-load', 'multiplayer']
     submenus = _.without submenus, 'guide' unless docs.specificArticles?.length or docs.generalArticles?.length
     submenus = _.without submenus, 'save-load' unless me.isAdmin() or /https?:\/\/localhost/.test(window.location.href)
-    submenus = _.without submenus, 'multiplayer' unless me.isAdmin() or (@level?.get('type') in ['ladder', 'hero-ladder', 'course-ladder'] and @level.get('slug') not in ['ace-of-coders'])
+    submenus = _.without submenus, 'multiplayer' unless me.isAdmin() or (@level?.get('type') in ['ladder', 'hero-ladder', 'course-ladder'] and @level.get('slug') not in ['ace-of-coders', 'elemental-wars'])
     @includedSubmenus = submenus
     context.showTab = @options.showTab ? submenus[0]
     context.submenus = submenus
@@ -47,7 +47,7 @@ module.exports = class GameMenuModal extends ModalView
 
   showsChooseHero: ->
     return false if @level?.get('type') in ['course', 'course-ladder']
-    return false if @options.levelID in ['zero-sum', 'ace-of-coders']
+    return false if @options.levelID in ['zero-sum', 'ace-of-coders', 'elemental-wars']
     return true
 
   afterRender: ->
diff --git a/app/views/play/modal/BuyGemsModal.coffee b/app/views/play/modal/BuyGemsModal.coffee
index 2cdea7a75..0f153a7f9 100644
--- a/app/views/play/modal/BuyGemsModal.coffee
+++ b/app/views/play/modal/BuyGemsModal.coffee
@@ -37,6 +37,9 @@ module.exports = class BuyGemsModal extends ModalView
           @render()
 
   onLoaded: ->
+    @basicProduct = @products.findWhere { name: 'basic_subscription' }
+    if countrySpecificProduct = @products.findWhere { name: "#{me.get('country')}_basic_subscription" }
+      @basicProduct = countrySpecificProduct
     @products.reset @products.filter (product) -> _.string.startsWith(product.get('name'), 'gems_')
     super()
 
@@ -44,6 +47,8 @@ module.exports = class BuyGemsModal extends ModalView
     super()
     return unless @supermodel.finished()
     @playSound 'game-menu-open'
+    if @basicProduct
+      @$el.find('.subscription-gem-amount').text $.i18n.t('buy_gems.price').replace('{{gems}}', @basicProduct.get('gems'))
 
   onHidden: ->
     super()
diff --git a/app/views/play/modal/ShareProgressModal.coffee b/app/views/play/modal/ShareProgressModal.coffee
index 4b3c34943..4ea07b376 100644
--- a/app/views/play/modal/ShareProgressModal.coffee
+++ b/app/views/play/modal/ShareProgressModal.coffee
@@ -2,7 +2,7 @@ ModalView = require 'views/core/ModalView'
 template = require 'templates/play/modal/share-progress-modal'
 storage = require 'core/storage'
 
-module.exports = class SubscribeModal extends ModalView
+module.exports = class ShareProgressModal extends ModalView
   id: 'share-progress-modal'
   template: template
   plain: true
diff --git a/bin/coco-mongodb b/bin/coco-mongodb
index e9e3d78f3..1d5a6f378 100755
--- a/bin/coco-mongodb
+++ b/bin/coco-mongodb
@@ -71,7 +71,7 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None):
 
 
 current_directory = os.path.dirname(os.path.realpath(sys.argv[0]))
-allowedMongoVersions = ["v2.6", "v3.0"]
+allowedMongoVersions = ["v2.6", "v3.0", "v3.2"]
 if which("mongod") and any(i in subprocess.check_output("mongod --version",shell=True) for i in allowedMongoVersions):
     mongo_executable = "mongod"
 else:
diff --git a/config.coffee b/config.coffee
index 8edc4f604..3085e53d9 100644
--- a/config.coffee
+++ b/config.coffee
@@ -130,7 +130,7 @@ exports.config =
 
         #- test, demo libraries
         'javascripts/app/tests.js': regJoin('^test/app/')
-        'javascripts/demo-app.js': regJoin('^test/demo/')
+        'javascripts/app/demo-app.js': regJoin('^test/demo/')
 
         #- More output files are generated at the below
 
diff --git a/package.json b/package.json
index 5b66726d2..18de44f0f 100644
--- a/package.json
+++ b/package.json
@@ -55,7 +55,7 @@
     "aether": "~0.4.0",
     "async": "0.2.x",
     "aws-sdk": "~2.0.0",
-    "bayesian-battle": "0.0.x",
+    "bayesian-battle": "0.0.7",
     "coffee-script": "1.9.x",
     "connect": "2.7.x",
     "express": "~3.0.6",
@@ -98,7 +98,7 @@
     "css-brunch": "^1.7.0",
     "fs-extra": "^0.26.2",
     "jade-brunch": "1.7.5",
-    "jasmine": "^2.3.2",
+    "jasmine": "^2.4.1",
     "javascript-brunch": "> 1.0 < 1.8",
     "karma": "~0.13",
     "karma-chrome-launcher": "~0.1.2",
diff --git a/scripts/analytics/mongodb/queries/exportTrialRequests.js b/scripts/analytics/mongodb/queries/exportTrialRequests.js
new file mode 100644
index 000000000..44624a858
--- /dev/null
+++ b/scripts/analytics/mongodb/queries/exportTrialRequests.js
@@ -0,0 +1,11 @@
+// Latest approved teacher trial requests
+
+// Usage:
+// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
+
+var requests = db.trial.requests.find().toArray();
+function format(r) { 
+  var p = r.properties;
+  return [r.created.getFullYear() + '-' + (r.created.getMonth() + 1) + '-' + r.created.getDate(), r.status, r.type, p.email, p.school, p.location, p.age, p.numStudents, p.heardAbout].join('\t').replace(/[\n\r]/g, '     ');
+}
+print(requests.map(format).join('\n'));
diff --git a/scripts/analytics/mongodb/queries/latestTeacherTrials.js b/scripts/analytics/mongodb/queries/latestTeacherTrials.js
index bef22472c..528b50ba1 100644
--- a/scripts/analytics/mongodb/queries/latestTeacherTrials.js
+++ b/scripts/analytics/mongodb/queries/latestTeacherTrials.js
@@ -1,17 +1,108 @@
-// Latest teacher trial requests
+/* global ISODate */
+// Latest approved teacher trial requests
 
 // Usage:
 // mongo <address>:<port>/<database> <script file> -u <username> -p <password>
 
-var startDay = '2015-10-01';
-var endDay = '2016-10-01';
-print('Date range:', startDay, endDay);
-var userIDs = getTrialRequestApplicants(startDay, endDay);
-print('Trial request applicants found:', userIDs.length);
-var userEmails = getUserEmails(userIDs);
-print('User emails found:', userEmails.length);
-for (var i = 0; i < userEmails.length; i++) {
-  print(userEmails[i]);
+var startDay = '2015-11-01';
+var endDay = '2016-01-01';
+print('Date range:', startDay, 'up to', endDay);
+
+var users = getUsers(startDay, endDay);
+print('Teachers found:', users.length);
+print("User Id\tStudent Count\tTrial Type\tEmail\tName\tSchool");
+for (var i = 0; i < users.length; i++) {
+  if (users[i].schoolName) {
+    print(users[i].id, '\t', users[i].studentCount, '\t', users[i].type, '\t', users[i].email, '\t', users[i].name, '\t', users[i].schoolName);
+  }
+}
+
+function getUsers(startDay, endDay) {
+  var cursor, doc, userID;
+  
+  // Find approved trial requests
+  var startObj = objectIdWithTimestamp(ISODate(startDay + "T00:00:00.000Z"));
+  var endObj = objectIdWithTimestamp(ISODate(endDay + "T00:00:00.000Z"))
+  cursor = db['trial.requests'].find(
+    {$and:
+      [
+        {_id: {$gte: startObj}},
+        {_id: {$lt: endObj}},
+        {status: 'approved'}
+      ]
+    },
+    {applicant: 1, type: 1}
+  );
+
+  var userIDs = [];
+  var userTrialTypeMap = {};
+  var orphanedTrialRequests = [];
+  while (cursor.hasNext()) {
+    doc = cursor.next();
+    if (doc.applicant) {
+      userIDs.push(doc.applicant);
+      userID = doc.applicant.valueOf();
+      if (!userTrialTypeMap[userID] || userTrialTypeMap[userID] !== 'course') userTrialTypeMap[userID] = doc.type;
+    }
+    else {
+      orphanedTrialRequests.push(doc._id);
+    }
+  }
+
+  // May have orphaned trial requests due to previous external import of requests from Google form
+  if (orphanedTrialRequests.length > 0) {
+    cursor = db.prepaids.find({'properties.trialRequestID': {$in: orphanedTrialRequests}}, {creator: 1});
+    while (cursor.hasNext()) {
+      doc = cursor.next();
+      if (doc.creator) {
+        userIDs.push(doc.creator);
+        userID = doc.creator.valueOf();
+        if (!userTrialTypeMap[userID] || userTrialTypeMap[userID] !== 'course') userTrialTypeMap[userID] = doc.type;
+      }
+      else {
+        print('No creator!');
+        printjson(doc);
+        break;
+      }
+    }
+  }
+
+  // Find user class sizes
+  var userClassroomStudentsMap = {};
+  cursor = db.classrooms.find({ownerID: {$in: userIDs}}, {members: 1, ownerID: 1});
+  while (cursor.hasNext()) {
+    doc = cursor.next();
+    if (doc.members) {
+      userID = doc.ownerID.valueOf();
+      if (!userClassroomStudentsMap[userID]) userClassroomStudentsMap[userID] = 0;
+      userClassroomStudentsMap[userID] = doc.members.length;
+    }
+  }
+
+  // Build user data
+  var users = [];
+  cursor = db['users'].find({$and: [{_id: {$in: userIDs}}, {deleted: {$exists: false}}, {anonymous: false}]}, {emailLower: 1, name: 1, schoolName: 1});
+  while (cursor.hasNext()) {
+    doc = cursor.next();
+    userID = doc._id.valueOf();
+    var userData = {
+      id: userID,
+      email: doc.emailLower,
+      name: doc.name || "",
+      schoolName: doc.schoolName || "",
+      studentCount: userClassroomStudentsMap[userID] || 0,
+      type: userTrialTypeMap[userID]
+    };
+    users.push(userData);
+  }
+
+  users.sort(function(a, b) {
+    if (a.studentCount > b.studentCount) return -1;
+    else if (a.studentCount === b.studentCount) return a.email.localeCompare(b.email);
+    return 1;
+  });
+
+  return users;
 }
 
 function objectIdWithTimestamp(timestamp) {
@@ -24,60 +115,3 @@ function objectIdWithTimestamp(timestamp) {
   return constructedObjectId
 }
 
-function getTrialRequestApplicants(startDay, endDay) {
-  var startObj = objectIdWithTimestamp(ISODate(startDay + "T00:00:00.000Z"));
-  var endObj = objectIdWithTimestamp(ISODate(endDay + "T00:00:00.000Z"))
-  var cursor = db['trial.requests'].find(
-    {$and:
-      [
-        {_id: {$gte: startObj}},
-        {_id: {$lt: endObj}}
-      ]
-    },
-    {applicant: 1}
-  );
-
-  var applicantIDs = [];
-  var orphanedTrialRequests = [];
-  while (cursor.hasNext()) {
-    var myDoc = cursor.next();
-    if (myDoc.applicant) {
-      applicantIDs.push(myDoc.applicant);
-    }
-    else {
-      orphanedTrialRequests.push(myDoc._id);
-    }
-  }
-
-  // May have orphaned trial requests due to previous external import of requests from Google form
-  if (orphanedTrialRequests.length > 0) {
-    cursor = db.prepaids.find({'properties.trialRequestID': {$in: orphanedTrialRequests}}, {creator: 1});
-    while (cursor.hasNext()) {
-      var myDoc = cursor.next();
-      if (myDoc.creator) {
-        applicantIDs.push(myDoc.creator);
-      }
-      else {
-        print('No creator!');
-        printjson(myDoc);
-        break;
-      }
-    }
-  }
-
-  return applicantIDs;
-}
-
-function getUserEmails(userIDs) {
-  var cursor = db['users'].find({_id: {$in: userIDs}}, {emailLower: 1});
-
-  var userEmails = [];
-  while (cursor.hasNext()) {
-    var myDoc = cursor.next();
-    if (myDoc.emailLower) {
-      userEmails.push(myDoc.emailLower);
-    }
-  }
-  userEmails.sort()
-  return userEmails;
-}
diff --git a/scripts/analytics/mongodb/queries/schoolCounts.js b/scripts/analytics/mongodb/queries/schoolCounts.js
new file mode 100644
index 000000000..b8aa2f054
--- /dev/null
+++ b/scripts/analytics/mongodb/queries/schoolCounts.js
@@ -0,0 +1,43 @@
+// Print out school user counts 
+
+// Usage:
+// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
+
+
+var scriptStartTime = new Date();
+
+var cursor = db.users.find({
+    $and: [
+    {anonymous: false},
+    {schoolName: {$exists: true}},
+    {schoolName: {$ne: ''}}
+    ]
+}, {schoolName: 1});
+
+var schoolCountMap = {};
+while (cursor.hasNext()) {
+    var doc = cursor.next();
+    if (!schoolCountMap[doc.schoolName]) schoolCountMap[doc.schoolName] = 0;
+    schoolCountMap[doc.schoolName]++;
+}
+
+var schoolCounts = [];
+for (var schoolName in schoolCountMap) {
+  schoolCounts.push({schoolName: schoolName, count: schoolCountMap[schoolName]});
+}
+schoolCounts.sort(function(a, b) {
+  if (a.count > b.count) return -1;
+  else if (a.count === b.count) return 0;
+  return 1; 
+});
+
+for (var i = 0; i < schoolCounts.length; i++) {
+  if (schoolCounts[i].count >= 10)
+    print(schoolCounts[i].count, schoolCounts[i].schoolName);
+}
+
+log("Script runtime: " + (new Date() - scriptStartTime));
+
+function log(str) {
+  print(new Date().toISOString() + " " + str);
+}
diff --git a/scripts/analytics/mongodb/queries/subscribersByCountry.js b/scripts/analytics/mongodb/queries/subscribersByCountry.js
new file mode 100644
index 000000000..a255877b6
--- /dev/null
+++ b/scripts/analytics/mongodb/queries/subscribersByCountry.js
@@ -0,0 +1,22 @@
+// Print out subscribers by special country (China, Brazil)
+
+// Usage:
+// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
+
+var countries = ['brazil', 'china'];
+countries.forEach(function(country) {
+  print('---' + country.toUpperCase() + '---');
+  var cursor = db.users.find({country: country, stripe: {$exists: true}}, {email: 1, country: 1, stripe: 1, name: 1});
+  var users = [];
+  var inactiveUsers = [];
+  while (cursor.hasNext()) {
+    var user = cursor.next();
+    if (!user.stripe.subscriptionID) {
+      inactiveUsers.push(user);
+      continue;
+    }
+    users.push(user);
+    print([user._id, user.country, user.email, user.name, JSON.stringify(user.stripe, null, 0)].join('\t'));
+  }
+  print('Had', users.length, 'active subscribers and', inactiveUsers.length, 'possible former subscribers in', country, '\n');
+});
diff --git a/scripts/analytics/mongodb/queries/userTypesBySchool.js b/scripts/analytics/mongodb/queries/userTypesBySchool.js
new file mode 100644
index 000000000..317eaa134
--- /dev/null
+++ b/scripts/analytics/mongodb/queries/userTypesBySchool.js
@@ -0,0 +1,182 @@
+/* global printjson */
+/* global db */
+// Find user type counts by school
+
+// Usage:
+// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
+
+// TODO: include data for users with unknown school
+
+var scriptStartTime = new Date();
+
+var toString = Object.prototype.toString;
+var _ = {
+  isString: function (obj) {
+    return toString.call(obj) == '[object String]';
+  }
+};
+
+var printLineMax = 40;
+
+var schoolTypes = ['courses paid', 'courses trial', 'courses free', 'campaign paid', 'campaign trial', 'campaign free'];
+
+var schoolTypeCounts = getSchoolTypeCounts();
+
+schoolTypeCounts.sort(function(a, b) {
+  if (a['courses paid'] > b['courses paid']) return -1;
+  else if (a['courses paid'] === b['courses paid'] && a['courses trial'] > b['courses trial']) return -1;
+  else if (a['courses paid'] === b['courses paid'] && a['courses trial'] == b['courses trial'] && a['courses free'] > b['courses free']) return -1;
+  else if (a['courses paid'] === b['courses paid'] && a['courses trial'] == b['courses trial'] && a['courses free'] === b['courses free'] && a['campaign paid'] > b['campaign paid']) return -1;
+  else if (a['courses paid'] === b['courses paid'] && a['courses trial'] == b['courses trial'] && a['courses free'] === b['courses free'] && a['campaign paid'] === b['campaign paid'] && a['campaign trial'] > b['campaign trial']) return -1;
+  else if (a['courses paid'] === b['courses paid'] && a['courses trial'] == b['courses trial'] && a['courses free'] === b['courses free'] && a['campaign paid'] === b['campaign paid'] && a['campaign trial'] === b['campaign trial'] && a['campaign free'] > b['campaign free']) return -1;
+  else if (a['courses paid'] === b['courses paid'] && a['courses trial'] == b['courses trial'] && a['courses free'] === b['courses free'] && a['campaign paid'] === b['campaign paid'] && a['campaign trial'] === b['campaign trial'] && a['campaign free'] === b['campaign free']) return 0;
+  return 1;
+});
+
+
+print('total\tcourses paid\tcourses trial\tcourses free\tcampaign paid\tcampaign trial\tcampaign free\tschool');
+for (var i = 0; i < schoolTypeCounts.length; i++) {
+  var schoolData = schoolTypeCounts[i]; 
+  print(schoolData['total'], '\t', schoolData['courses paid'], '\t', schoolData['courses trial'], '\t', schoolData['courses free'], '\t', schoolData['campaign paid'], '\t', schoolData['campaign trial'], '\t', schoolData['campaign free'], '\t', schoolData.schoolName);
+  if (i >= printLineMax - 1) break;
+}
+
+schoolTypeCounts.sort(function(a, b) {
+  if (a.total > b.total) return -1;
+  else if (a.total === b.total) return 0;
+  return 1;
+});
+
+print('total\tcourses paid\tcourses trial\tcourses free\tcampaign paid\tcampaign trial\tcampaign free\tschool');
+for (var i = 0; i < schoolTypeCounts.length; i++) {
+  var schoolData = schoolTypeCounts[i]; 
+  print(schoolData['total'], '\t', schoolData['courses paid'], '\t', schoolData['courses trial'], '\t', schoolData['courses free'], '\t', schoolData['campaign paid'], '\t', schoolData['campaign trial'], '\t', schoolData['campaign free'], '\t', schoolData.schoolName);
+  if (i >= printLineMax - 1) break;
+}
+
+log("Script runtime: " + (new Date() - scriptStartTime));
+
+
+function getSchoolTypeCounts() {
+  // Find users with school data
+  log("Finding users with a school name..");
+  var prepaidIDs = [];
+  var userIDs = [];
+  var prepaidUserMap = {};
+  var userSchoolMap = {};
+  var userSubscriptionMap = {};
+  var cursor = db.users.find({
+      $and: [
+      {anonymous: false},
+      {schoolName: {$exists: true}},
+      {schoolName: {$ne: ''}}
+      ]
+    }, {coursePrepaidID: 1, schoolName: 1, stripe: 1});
+  while (cursor.hasNext()) {
+      var doc = cursor.next();
+      var userID = doc._id.valueOf();
+      if (doc.coursePrepaidID) {
+        prepaidIDs.push(doc.coursePrepaidID);
+        var prepaidID = doc.coursePrepaidID.valueOf();
+        if (!prepaidUserMap[prepaidID]) prepaidUserMap[prepaidID] = [];
+        prepaidUserMap[prepaidID].push(userID);
+      }
+      if (doc.stripe && (doc.stripe.sponsorID || doc.stripe.subscriptionID || _.isString(doc.stripe.free) && new Date() < new Date(doc.stripe.free))) {
+        userSubscriptionMap[userID] = true; 
+      }
+      userIDs.push(userID);
+      userSchoolMap[userID] = doc.schoolName;
+  }
+  log("Users with schools: " + userIDs.length);
+  // printjson(userSubscriptionMap);
+
+  // Find user types
+  var userTypeMap = {};
+
+  // courses paid: coursePrepaidID set, prepaid not trial
+  // courses trial: coursePrepaidID set, prepaid has trialRequestID set
+  log("Finding courses prepaids..");
+  var cursor = db.prepaids.find({_id: {$in: prepaidIDs}}, {properties: 1});
+  while (cursor.hasNext()) {
+      var doc = cursor.next();
+      var prepaidID = doc._id.valueOf();
+      if (prepaidUserMap[prepaidID]) {
+        var type = doc.properties && doc.properties.trialRequestID ? 'courses trial' : 'courses paid';
+        for (var i = 0; i < prepaidUserMap[prepaidID].length; i++) {
+          userTypeMap[prepaidUserMap[prepaidID][i]] = type;
+        }
+      }
+      else {
+        print("ERROR");
+        printjson(doc);
+        break;
+      }
+  }
+  // printjson(userTypeMap);
+
+  // courses free: class member, no coursePrepaidID not set
+  log("Finding classrooms..");
+  var userClassroomMap = {};
+  var cursor = db.classrooms.find({}, {members: 1});
+  while (cursor.hasNext()) {
+    var doc = cursor.next();
+    if (doc.members) {
+      for (var i = 0; i < doc.members.length; i++) {
+        userClassroomMap[doc.members[i].valueOf()] = true;
+      }
+    }
+  }
+  for (var i = 0; i < userIDs.length; i++) {
+    if (!userTypeMap[userIDs[i]] && userClassroomMap[userIDs[i]]) {
+      userTypeMap[userIDs[i]] = 'courses free';
+    }
+  }
+
+  // campaign trial: has subscription and trial request
+  log("Finding trial requests..");
+  var cursor = db.trial.requests.find({status: 'approved'}, {applicant: 1});
+  while (cursor.hasNext()) {
+    var doc = cursor.next();
+    if (doc.applicant) {
+      var userID = doc.applicant.valueOf();
+      if (!userTypeMap[userID] && userSubscriptionMap[userID]) userTypeMap[userID] = 'campaign trial';
+    }
+  }
+
+  // campaign paid: has subscription, no approved trial request
+  // campaign free: no other matches
+  log("Setting remaining user types to campaign paid or free..");
+  for (var i = 0; i < userIDs.length; i++) {
+    if (!userTypeMap[userIDs[i]]) userTypeMap[userIDs[i]] = userSubscriptionMap[userIDs[i]] ? 'campaign paid' : 'campaign free';
+  }
+
+  // Tally user types per school
+  var schoolTypeCountMap = {};
+  for (var userID in userTypeMap) {
+    var schoolName = userSchoolMap[userID];
+    var type = userTypeMap[userID];
+    if (!schoolTypeCountMap[schoolName]) schoolTypeCountMap[schoolName] = {};
+    if (!schoolTypeCountMap[schoolName][type]) schoolTypeCountMap[schoolName][type] = 0;
+    schoolTypeCountMap[schoolName][type]++;
+  }
+
+  var schoolTypeCounts = [];
+  for (var schoolName in schoolTypeCountMap) {
+    var schoolData = {schoolName: schoolName, total: 0};
+    for (var type in schoolTypeCountMap[schoolName]) {
+      schoolData[type] = schoolTypeCountMap[schoolName][type];
+      schoolData.total += schoolTypeCountMap[schoolName][type];
+    }
+    for (var i = 0; i < schoolTypes.length; i++) {
+      if (!schoolData[schoolTypes[i]]) schoolData[schoolTypes[i]] = 0;
+    }
+    schoolTypeCounts.push(schoolData);
+  }
+  log("School count: " + schoolTypeCounts.length);
+
+  return schoolTypeCounts;
+}
+
+function log(str) {
+  print(new Date().toISOString() + " " + str);
+}
diff --git a/scripts/mongodb/updateCourses.js b/scripts/mongodb/updateCourses.js
index ab475d26d..e1c5d6f53 100644
--- a/scripts/mongodb/updateCourses.js
+++ b/scripts/mongodb/updateCourses.js
@@ -12,10 +12,8 @@ var courses =
     name: "Introduction to Computer Science",
     slug: "introduction-to-computer-science",
     campaignID: ObjectId("55b29efd1cd6abe8ce07db0d"),
-    concepts: ['basic_syntax', 'arguments', 'while_loops', 'strings', 'variables'],
     description: "Learn basic syntax, while loops, and the CodeCombat environment.",
     duration: NumberInt(1),
-    pricePerSeat: NumberInt(0),
     free: true,
     screenshot: "/images/pages/courses/101_info.png"
   },
@@ -23,10 +21,8 @@ var courses =
     name: "Computer Science 2",
     slug: "computer-science-2",
     campaignID: ObjectId("562f88e84df18473073c74e2"),
-    concepts: ['basic_syntax', 'arguments', 'while_loops', 'strings', 'variables', 'if_statements'],
     description: "Introduce Arguments, Variables, If Statements, and Arithmetic.",
     duration: NumberInt(5),
-    pricePerSeat: NumberInt(400),
     free: false,
     screenshot: "/images/pages/courses/102_info.png"
   },
@@ -34,10 +30,8 @@ var courses =
     name: "Computer Science 3",
     slug: "computer-science-3",
     campaignID: ObjectId("56462ac4410c528505e1160a"),
-    concepts: ['if_statements', 'arithmetic'],
     description: "Introduces arithmetic, counters, advanced while loops, break, continue, arrays.",
     duration: NumberInt(5),
-    pricePerSeat: NumberInt(400),
     free: false,
     screenshot: "/images/pages/courses/103_info.png"
   },
@@ -45,12 +39,19 @@ var courses =
     name: "Computer Science 4",
     slug: "computer-science-4",
     campaignID: ObjectId("56462c1133f1478605ebd018"),
-    concepts: ['if_statements', 'arithmetic'],
     description: "Introduces object literals, for loops, function definitions, drawing, and modulo.",
     duration: NumberInt(5),
-    pricePerSeat: NumberInt(400),
     free: false,
     screenshot: "/images/pages/courses/104_info.png"
+  },
+  {
+    name: "Computer Science 5",
+    slug: "computer-science-5",
+    campaignID: ObjectId("568ad069a6584820004437f2"),
+    description: "Introduces function parameters, function return values and algorithms.",
+    duration: NumberInt(5),
+    free: false,
+    screenshot: "/images/pages/courses/105_info.png"
   }
 ];
 
diff --git a/server/classrooms/Classroom.coffee b/server/classrooms/Classroom.coffee
index c33fceb41..daaad2741 100644
--- a/server/classrooms/Classroom.coffee
+++ b/server/classrooms/Classroom.coffee
@@ -4,6 +4,7 @@ config = require '../../server_config'
 plugins = require '../plugins/plugins'
 User = require '../users/User'
 jsonSchema = require '../../app/schemas/models/classroom.schema'
+utils = require '../lib/utils'
 
 ClassroomSchema = new mongoose.Schema {}, {strict: false, minimize: false, read:config.mongo.readpref}
 
@@ -18,12 +19,10 @@ ClassroomSchema.statics.editableProperties = [
   'aceConfig'
 ]
 
-# 250 words; will want to use 4 code words once we get past 10M classrooms.
-words = 'angry apple arm army art baby back bad bag ball bath bean bear bed bell best big bird bite blue boat book box boy bread burn bus cake car cat chair city class clock cloud coat coin cold cook cool corn crash cup dark day deep desk dish dog door down draw dream drink drop dry duck dust east eat egg enemy eye face false farm fast fear fight find fire flag floor fly food foot fork fox free fruit full fun funny game gate gift glass goat gold good green hair half hand happy heart heavy help hide hill home horse house ice idea iron jelly job jump key king lamp large last late lazy leaf left leg life light lion lock long luck map mean milk mix moon more most mouth music name neck net new next nice night north nose old only open page paint pan paper park party path pig pin pink place plane plant plate play point pool power pull push queen rain ready red rest rice ride right ring road rock room run sad safe salt same sand sell shake shape share sharp sheep shelf ship shirt shoe shop short show sick side silly sing sink sit size sky sleep slow small snow sock soft soup south space speed spell spoon star start step stone stop sweet swim sword table team thick thin thing think today tooth top town tree true turn type under want warm watch water west wide win word yes zoo'.split(' ')
-
 ClassroomSchema.statics.generateNewCode = (done) ->
   tryCode = ->
-    codeCamel = _.map(_.sample(words, 3), (s) -> s[0].toUpperCase() + s.slice(1)).join('')
+    # Use 4 code words once we get past 10M classrooms
+    codeCamel = utils.getCodeCamel(3)
     code = codeCamel.toLowerCase()
     Classroom.findOne code: code, (err, classroom) ->
       return done() if err
@@ -31,8 +30,6 @@ ClassroomSchema.statics.generateNewCode = (done) ->
       tryCode()
   tryCode()
 
-#ClassroomSchema.plugin plugins.NamedPlugin
-
 ClassroomSchema.pre('save', (next) ->
   return next() if @get('code')
   Classroom.generateNewCode (code, codeCamel) =>
diff --git a/server/commons/mail.coffee b/server/commons/mail.coffee
index 432441060..02642e44d 100644
--- a/server/commons/mail.coffee
+++ b/server/commons/mail.coffee
@@ -3,6 +3,6 @@ config = require '../../server_config'
 module.exports.MAILCHIMP_LIST_ID = 'e9851239eb'
 module.exports.MAILCHIMP_GROUP_ID = '4529'
 
-# these two need to be parallel
-module.exports.MAILCHIMP_GROUPS = ['Announcements', 'Adventurers', 'Artisans', 'Archmages', 'Scribes', 'Diplomats', 'Ambassadors']
-module.exports.NEWS_GROUPS = ['generalNews', 'adventurerNews', 'artisanNews', 'archmageNews', 'scribeNews', 'diplomatNews', 'ambassadorNews']
+# These two need to be parallel
+module.exports.MAILCHIMP_GROUPS = ['Announcements', 'Adventurers', 'Artisans', 'Archmages', 'Scribes', 'Diplomats', 'Ambassadors', 'Teachers']
+module.exports.NEWS_GROUPS = ['generalNews', 'adventurerNews', 'artisanNews', 'archmageNews', 'scribeNews', 'diplomatNews', 'ambassadorNews', 'teacherNews']
diff --git a/server/courses/course_instance_handler.coffee b/server/courses/course_instance_handler.coffee
index e28bf2835..374a5e358 100644
--- a/server/courses/course_instance_handler.coffee
+++ b/server/courses/course_instance_handler.coffee
@@ -11,6 +11,7 @@ PrepaidHandler = require '../prepaids/prepaid_handler'
 User = require '../users/User'
 UserHandler = require '../users/user_handler'
 utils = require '../../app/core/utils'
+{objectIdFromTimestamp} = require '../lib/utils'
 sendwithus = require '../sendwithus'
 mongoose = require 'mongoose'
 
@@ -38,6 +39,7 @@ CourseInstanceHandler = class CourseInstanceHandler extends Handler
     return @removeMember(req, res, args[0]) if req.method is 'DELETE' and args[1] is 'members'
     return @getMembersAPI(req, res, args[0]) if args[1] is 'members'
     return @inviteStudents(req, res, args[0]) if relationship is 'invite_students'
+    return @getRecentAPI(req, res) if relationship is 'recent'
     return @redeemPrepaidCodeAPI(req, res) if args[1] is 'redeem_prepaid'
     return @getMyCourseLevelSessionsAPI(req, res, args[0]) if args[1] is 'my-course-level-sessions'
     return @findByLevel(req, res, args[2]) if args[1] is 'find_by_level'
@@ -193,6 +195,15 @@ CourseInstanceHandler = class CourseInstanceHandler extends Handler
         cleandocs = (UserHandler.formatEntity(req, doc) for doc in users)
         @sendSuccess(res, cleandocs)
 
+  getRecentAPI: (req, res) ->
+    return @sendUnauthorizedError(res) unless req.user?.isAdmin()
+    query = {$and: [{name: {$ne: 'Single Player'}}, {hourOfCode: {$ne: true}}]}
+    query["$and"].push(_id: {$gte: objectIdFromTimestamp(req.body.startDay + "T00:00:00.000Z")}) if req.body.startDay?
+    query["$and"].push(_id: {$lt: objectIdFromTimestamp(req.body.endDay + "T00:00:00.000Z")}) if req.body.endDay?
+    CourseInstance.find query, (err, courseInstances) =>
+      return @sendDatabaseError(res, err) if err
+      @sendSuccess(res, courseInstances)
+
   inviteStudents: (req, res, courseInstanceID) ->
     return @sendUnauthorizedError(res) if not req.user?
     if not req.body.emails
diff --git a/server/levels/sessions/level_session_handler.coffee b/server/levels/sessions/level_session_handler.coffee
index 5e4780d89..5ce45af02 100644
--- a/server/levels/sessions/level_session_handler.coffee
+++ b/server/levels/sessions/level_session_handler.coffee
@@ -37,7 +37,7 @@ class LevelSessionHandler extends Handler
     return @sendForbiddenError(res) unless req.user?.isAdmin()
 
     levelSlug = req.query.slug or req.body.slug
-    limit = req.query.limit or req.body.limit or 7
+    limit = parseInt req.query.limit or req.body.limit or 7
 
     return @sendSuccess res, [] unless levelSlug?
 
diff --git a/server/lib/utils.coffee b/server/lib/utils.coffee
index 2bae86c09..b0b20c1e7 100644
--- a/server/lib/utils.coffee
+++ b/server/lib/utils.coffee
@@ -6,6 +6,11 @@ config = require '../../server_config'
 module.exports =
   isID: (id) -> _.isString(id) and id.length is 24 and id.match(/[a-f0-9]/gi)?.length is 24
 
+  getCodeCamel: (numWords=3) ->
+    # 250 words
+    words = 'angry apple arm army art baby back bad bag ball bath bean bear bed bell best big bird bite blue boat book box boy bread burn bus cake car cat chair city class clock cloud coat coin cold cook cool corn crash cup dark day deep desk dish dog door down draw dream drink drop dry duck dust east eat egg enemy eye face false farm fast fear fight find fire flag floor fly food foot fork fox free fruit full fun funny game gate gift glass goat gold good green hair half hand happy heart heavy help hide hill home horse house ice idea iron jelly job jump key king lamp large last late lazy leaf left leg life light lion lock long luck map mean milk mix moon more most mouth music name neck net new next nice night north nose old only open page paint pan paper park party path pig pin pink place plane plant plate play point pool power pull push queen rain ready red rest rice ride right ring road rock room run sad safe salt same sand sell shake shape share sharp sheep shelf ship shirt shoe shop short show sick side silly sing sink sit size sky sleep slow small snow sock soft soup south space speed spell spoon star start step stone stop sweet swim sword table team thick thin thing think today tooth top town tree true turn type under want warm watch water west wide win word yes zoo'.split(' ')
+    _.map(_.sample(words, numWords), (s) -> s[0].toUpperCase() + s.slice(1)).join('')
+
   objectIdFromTimestamp: (timestamp) ->
     # mongoDB ObjectId contains creation date in first 4 bytes
     # So, it can be used instead of a redundant created field
diff --git a/server/payments/subscription_handler.coffee b/server/payments/subscription_handler.coffee
index e4cb53d88..de351c550 100644
--- a/server/payments/subscription_handler.coffee
+++ b/server/payments/subscription_handler.coffee
@@ -139,28 +139,28 @@ class SubscriptionHandler extends Handler
           if err
             @logSubscriptionError(user, "Purchase year sale Stripe cancel subscription error: #{JSON.stringify(err)}")
             return @sendDatabaseError(res, err)
-            
+
           Product.findOne({name: 'year_subscription'}).exec (err, product) =>
             return @sendDatabaseError(res, err) if err
             return @sendNotFoundError(res, 'year_subscription product not found') if not product
-            
+
             metadata =
               type: req.body.type
               userID: req.user._id + ''
               gems: product.get('gems')
               timestamp: parseInt(req.body.stripe?.timestamp)
               description: req.body.description
-  
+
             StripeUtils.createCharge req.user, product.get('amount'), metadata, (err, charge) =>
               if err
                 @logSubscriptionError(req.user, "Purchase year sale create charge: #{JSON.stringify(err)}")
                 return @sendDatabaseError(res, err)
-  
+
               StripeUtils.createPayment req.user, charge, (err, payment) =>
                 if err
                   @logSubscriptionError(req.user, "Purchase year sale create payment: #{JSON.stringify(err)}")
                   return @sendDatabaseError(res, err)
-  
+
                 # Add terminal subscription to User with extensions for existing subscriptions
                 stripeInfo = _.cloneDeep(req.user.get('stripe') ? {})
                 endDate = new Date()
@@ -171,14 +171,14 @@ class SubscriptionHandler extends Handler
                 endDate.setUTCFullYear(endDate.getUTCFullYear() + 1)
                 stripeInfo.free = endDate.toISOString().substring(0, 10)
                 req.user.set('stripe', stripeInfo)
-  
+
                 # Add year's worth of gems to User
                 purchased = _.clone(req.user.get('purchased'))
                 purchased ?= {}
                 purchased.gems ?= 0
                 purchased.gems += parseInt(charge.metadata.gems)
                 req.user.set('purchased', purchased)
-  
+
                 req.user.save (err, user) =>
                   if err
                     @logSubscriptionError(req.user, "User save error: #{JSON.stringify(err)}")
@@ -248,18 +248,18 @@ class SubscriptionHandler extends Handler
               endDate = new moment(stripeSubscriptionPeriodEndDate)
             else if _.isString(stripeInfo.free) and new moment().isBefore(new moment(stripeInfo.free))
               endDate = new moment(stripeInfo.free)
-  
+
             endDate = endDate.add(months, 'months')
             stripeInfo.free = endDate.toISOString().substring(0, 10)
             req.user.set('stripe', stripeInfo)
-  
+
             # Add gems to User
             purchased = _.clone(req.user.get('purchased'))
             purchased ?= {}
             purchased.gems ?= 0
             purchased.gems += product.get('gems') * months
             req.user.set('purchased', purchased)
-  
+
             req.user.save (err, user) =>
               if err
                 @logSubscriptionError(req.user, "User save error: #{JSON.stringify(err)}")
@@ -366,6 +366,8 @@ class SubscriptionHandler extends Handler
 
     else
       couponID = user.get('stripe')?.couponID
+      if user.get('country') is 'brazil'
+        couponID ?= 'brazil'
       # SALE LOGIC
       # overwrite couponID with another for everyone-sales
       #couponID = 'hoc_399' if not couponID
@@ -426,7 +428,11 @@ class SubscriptionHandler extends Handler
     req.body.stripe = stripeInfo
     user.set('stripe', stripeInfo)
 
-    Product.findOne({name: 'basic_subscription'}).exec (err, product) =>
+    productName = 'basic_subscription'
+    if user.get('country') in ['brazil']
+      productName = "#{user.get('country')}_basic_subscription"
+
+    Product.findOne({name: productName}).exec (err, product) =>
       return @sendDatabaseError(res, err) if err
       return @sendNotFoundError(res, 'basic_subscription product not found') if not product
 
@@ -434,9 +440,9 @@ class SubscriptionHandler extends Handler
         purchased = _.clone(user.get('purchased'))
         purchased ?= {}
         purchased.gems ?= 0
-        purchased.gems += product.get('gems') # TODO: Put actual subscription amount here
+        purchased.gems += product.get('gems')
         user.set('purchased', purchased)
-  
+
       user.save (err) =>
         if err
           @logSubscriptionError(user, 'Stripe user plan saving error. ' + err)
@@ -551,11 +557,11 @@ class SubscriptionHandler extends Handler
                 @logSubscriptionError(user, 'Stripe user saving stripe error. ' + err)
                 return done({res: 'Database error.', code: 500})
               done()
-  
+
         tasks = []
         for sub in stripeRecipients
           tasks.push createUpdateFn(sub.recipient, sub.increment)
-  
+
         async.parallel tasks, (err, results) =>
           return done(err) if err
           @updateStripeSponsorSubscription(req, user, customer, product, done)
@@ -673,13 +679,13 @@ class SubscriptionHandler extends Handler
           if err
             @logSubscriptionError(user, 'Recipient user save unsubscribe error. ' + err)
             return done({res: 'Database error.', code: 500})
-  
+
           # Cancel Stripe subscription
           stripe.customers.cancelSubscription stripeInfo.customerID, sponsoredEntry.subscriptionID, (err) =>
             if err
               @logSubscriptionError(user, "Stripe cancel sponsored subscription failed. " + err)
               return done({res: 'Database error.', code: 500})
-  
+
             # Update sponsor user
             _.remove(stripeInfo.recipients, (s) -> s.userID is recipient.id)
             delete stripeInfo.unsubscribeEmail
@@ -689,9 +695,9 @@ class SubscriptionHandler extends Handler
               if err
                 @logSubscriptionError(user, 'Sponsor user save unsubscribe error. ' + err)
                 return done({res: 'Database error.', code: 500})
-  
+
               return done() unless stripeInfo.sponsorSubscriptionID?
-  
+
               # Update sponsored subscription quantity
               options =
                 quantity: getSponsoredSubsAmount(product.get('amount'), stripeInfo.recipients.length, stripeInfo.subscriptionID?)
diff --git a/server/queues/scoring/scoringUtils.coffee b/server/queues/scoring/scoringUtils.coffee
index f6c655c7e..1324feafd 100644
--- a/server/queues/scoring/scoringUtils.coffee
+++ b/server/queues/scoring/scoringUtils.coffee
@@ -41,16 +41,13 @@ module.exports.formatSessionInformation = (session) ->
   shouldUpdateLastOpponentSubmitDateForLeague: session.shouldUpdateLastOpponentSubmitDateForLeague
 
 module.exports.calculateSessionScores = (callback) ->
-  sessionIDs = _.pluck @clientResponseObject.sessions, 'sessionID'
+  sessionIDs = _.map @clientResponseObject.sessions, 'sessionID'
   async.map sessionIDs, retrieveOldSessionData.bind(@), (err, oldScores) =>
     if err? then return callback err, {error: 'There was an error retrieving the old scores'}
-    try
-      oldScoreArray = _.toArray putRankingFromMetricsIntoScoreObject @clientResponseObject, oldScores
-      newScoreArray = updatePlayerSkills oldScoreArray
-      createSessionScoreUpdate.call @, scoreObject for scoreObject in newScoreArray
-      callback err, newScoreArray
-    catch e
-      callback e
+    oldScoreArray = _.toArray putRankingFromMetricsIntoScoreObject @clientResponseObject, oldScores
+    newScoreArray = updatePlayerSkills oldScoreArray
+    createSessionScoreUpdate.call @, scoreObject for scoreObject in newScoreArray
+    callback null, newScoreArray
 
 retrieveOldSessionData = (sessionID, callback) ->
   formatOldScoreObject = (session) =>
@@ -151,7 +148,7 @@ module.exports.addMatchToSessionsAndUpdate = (newScoreObject, callback) ->
   #log.info "Match object computed, result: #{JSON.stringify(matchObject, null, 2)}"
   #log.info 'Writing match object to database...'
   #use bind with async to do the writes
-  sessionIDs = _.pluck @clientResponseObject.sessions, 'sessionID'
+  sessionIDs = _.map @clientResponseObject.sessions, 'sessionID'
   async.each sessionIDs, updateMatchesInSession.bind(@, matchObject), (err) ->
     callback err
 
diff --git a/server/routes/auth.coffee b/server/routes/auth.coffee
index d70090c45..a8ad2ba12 100644
--- a/server/routes/auth.coffee
+++ b/server/routes/auth.coffee
@@ -8,6 +8,7 @@ errors = require '../commons/errors'
 languages = require '../routes/languages'
 sendwithus = require '../sendwithus'
 log = require 'winston'
+utils = require '../lib/utils'
 
 module.exports.setup = (app) ->
   authentication.serializeUser((user, done) -> done(null, user._id))
@@ -101,7 +102,10 @@ module.exports.setup = (app) ->
       if not user
         return errors.notFound(res, [{message: 'not found', property: 'email'}])
 
-      user.set('passwordReset', Math.random().toString(36).slice(2, 7).toUpperCase())
+      user.set('passwordReset', utils.getCodeCamel())
+      emailContent = "<h3>Your temporary password: <b>#{user.get('passwordReset')}</b></h3>"
+      emailContent += "<p>Reset your password at <a href=\"http://codecombat.com/account/settings\">http://codecombat.com/account/settings</a></p>"
+      emailContent += "<p>Your old password cannot be retrieved.</p>"
       user.save (err) =>
         return errors.serverError(res) if err
         unless config.unittest
@@ -111,8 +115,8 @@ module.exports.setup = (app) ->
               address: req.body.email
             email_data:
               subject: 'CodeCombat Recovery Password'
-              title: 'Recovery Password'
-              content: "<p>Your CodeCombat recovery password for email #{req.body.email} is: #{user.get('passwordReset')}</p><p>Log in at <a href=\"http://codecombat.com/account/settings\">http://codecombat.com/account/settings</a> and change it.</p><p>Hope this helps!</p>"
+              title: ''
+              content: emailContent
           sendwithus.api.send context, (err, result) ->
             if err
               console.error "Error sending password reset email: #{err.message or err}"
@@ -198,7 +202,7 @@ module.exports.loginUser = loginUser = (req, res, user, send=true, next=null) ->
   )
 
 module.exports.idCounter = 0
-  
+
 module.exports.makeNewUser = makeNewUser = (req) ->
   user = new User({anonymous: true})
   if global.testing
diff --git a/server/routes/db/product.coffee b/server/routes/db/product.coffee
index eefd89e11..c1b854aea 100644
--- a/server/routes/db/product.coffee
+++ b/server/routes/db/product.coffee
@@ -17,7 +17,7 @@ module.exports.get = (req, res) ->
 
 ###
 Stub data, used in tests and dev environment.
-  
+
 These values are only upserted when the test/dev db does not already contain them.
 If you are testing products and need to change them, you'll need to edit the db values directly.
 ###
@@ -76,4 +76,11 @@ initProducts = [
     name: 'course'
     amount: 100
   }
-]
\ No newline at end of file
+
+  {
+    name: 'brazil_basic_subscription'
+    amount: 0
+    gems: 1500
+    planID: 'basic'
+  }
+]
diff --git a/server/routes/stripe.coffee b/server/routes/stripe.coffee
index 27330411e..1541ca672 100644
--- a/server/routes/stripe.coffee
+++ b/server/routes/stripe.coffee
@@ -49,8 +49,9 @@ module.exports.setup = (app) ->
       if err
         logStripeWebhookError("Retrieve invoice error: #{JSON.stringify(err)}")
         return res.send(500, '')
-      unless invoice.total or invoice.discount?.coupon?.id is 'free'
+      unless invoice.total or invoice.discount?.coupon?.id in ['free', 'brazil']
         # invoices made when trialing, probably given for people who resubscribe after unsubscribing
+        # also I can't change the test-mode brazil coupon to not end up with a zero price now
         return res.send(200, '')
       return res.send(200, '') unless invoice.lines?.data?.length > 0
 
@@ -85,7 +86,11 @@ module.exports.setup = (app) ->
                 subscriptionID: subscriptionID
               }
             })
-            payment.set 'gems', 3500 if invoice.lines.data[0].plan?.id is 'basic'
+            # TODO: load gems from correct Product
+            productGems = 3500
+            if recipient.get('country') is 'brazil'
+              productGems = 1500
+            payment.set 'gems', productGems if invoice.lines.data[0].plan?.id is 'basic'
 
             payment.save (err) =>
               if err
diff --git a/server/sendwithus.coffee b/server/sendwithus.coffee
index 121090628..a43c53834 100644
--- a/server/sendwithus.coffee
+++ b/server/sendwithus.coffee
@@ -22,5 +22,5 @@ module.exports.templates =
   plain_text_email: 'tem_85UvKDCCNPXsFckERTig6Y'
   next_steps_email: 'tem_RDHhTG5inXQi8pthyqWr5D'
   course_invite_email: 'tem_u6D2EFWYC5Ptk38bSykjsU'
-  teacher_free_trial: 'tem_sqdvLCZRwoDQc6jAf5RrQE'
+  teacher_free_trial: 'tem_R7d9Hpoba9SceQNiYSXBak'
   teacher_free_trial_hoc: 'tem_4ZSY9wsA9Qwn4wBFmZgPdc'
diff --git a/server/trial_requests/TrialRequest.coffee b/server/trial_requests/TrialRequest.coffee
index 079a8f100..1dc0ecf9d 100644
--- a/server/trial_requests/TrialRequest.coffee
+++ b/server/trial_requests/TrialRequest.coffee
@@ -5,6 +5,7 @@ hipchat = require '../hipchat'
 sendwithus = require '../sendwithus'
 Prepaid = require '../prepaids/Prepaid'
 jsonSchema = require '../../app/schemas/models/trial_request.schema'
+User = require '../users/User'
 
 TrialRequestSchema = new mongoose.Schema {}, {strict: false, minimize: false, read:config.mongo.readpref}
 
@@ -21,35 +22,30 @@ TrialRequestSchema.pre 'save', (next) ->
   prepaid.save (err) =>
     if err
       log.error "Trial request prepaid creation error: #{err}"
-
-    # Special HoC trial: Add 500 course headcount with end date
-    endDate = new Date()
-    endDate.setUTCMonth(endDate.getUTCMonth() + 2)
-    prepaid = new Prepaid
-      creator: @get('applicant')
-      type: 'course'
-      maxRedeemers: 500
-      properties:
-        endDate: endDate
-        trialRequestID: @get('_id')
-    prepaid.save (err) =>
-      if err
-        log.error "Trial request prepaid creation error: #{err}"
-      next()
+    next()
 
 TrialRequestSchema.post 'save', (doc) ->
   if doc.get('status') is 'approved'
-    endDate = new Date()
-    endDate.setUTCMonth(endDate.getUTCMonth() + 2)
     emailParams =
       recipient:
         address: doc.get('properties')?.email
-      email_id: sendwithus.templates.teacher_free_trial_hoc
-      email_data:
-        endDate: endDate.toDateString()
+      email_id: sendwithus.templates.teacher_free_trial
     sendwithus.api.send emailParams, (err, result) =>
       log.error "sendwithus trial request approved error: #{err}, result: #{result}" if err
 
+    # Subscribe to teacher news group
+    User.findById doc.get('applicant'), (err, user) =>
+      if err
+        log.error "Trial request user find error: #{err}"
+        return
+      emails = _.cloneDeep(user.get('emails') ? {})
+      emails.teacherNews ?= {}
+      emails.teacherNews.enabled = true
+      user.update {$set: {emails: emails}}, {}, (err) =>
+        if err
+          log.error "Trial request user update error: #{err}"
+          return
+
 TrialRequestSchema.statics.privateProperties = []
 TrialRequestSchema.statics.editableProperties = [
   'created'
diff --git a/server/users/User.coffee b/server/users/User.coffee
index c5b46dcf1..62953b0cd 100644
--- a/server/users/User.coffee
+++ b/server/users/User.coffee
@@ -31,6 +31,7 @@ UserSchema.index({'slug': 1}, {name: 'slug index', sparse: true, unique: true})
 UserSchema.index({'stripe.subscriptionID': 1}, {unique: true, sparse: true})
 UserSchema.index({'siteref': 1}, {name: 'siteref index', sparse: true})
 UserSchema.index({'schoolName': 1}, {name: 'schoolName index', sparse: true})
+UserSchema.index({'country': 1}, {name: 'country index', sparse: true})
 
 UserSchema.post('init', ->
   @set('anonymous', false) if @get('email')
@@ -75,6 +76,7 @@ emailNameMap =
   diplomatNews: 'translator'
   ambassadorNews: 'support'
   anyNotes: 'notification'
+  teacherNews: 'teacher'
 
 UserSchema.methods.setEmailSubscription = (newName, enabled) ->
   oldSubs = _.clone @get('emailSubscriptions')
diff --git a/spec/fixtures/sub-test-41.json b/spec/fixtures/sub-test-41.json
new file mode 100644
index 000000000..a1ffde3b4
--- /dev/null
+++ b/spec/fixtures/sub-test-41.json
@@ -0,0 +1,362 @@
+[
+    {
+        "scope": "https://api.stripe.com:443",
+        "method": "POST",
+        "path": "/v1/tokens",
+        "status": 200,
+        "response": {
+            "id": "tok_17SYfcKaReE7xLUdYjNZZzl4",
+            "card": {
+                "id": "card_17SYfcKaReE7xLUdQAQATTm4"
+            },
+            "type": "card"
+        }
+    },
+    {
+        "scope": "https://api.stripe.com:443",
+        "method": "POST",
+        "path": "/v1/customers",
+        "status": 200,
+        "response": {
+            "id": "cus_7hyc7Vrhs9hrFd",
+            "alipay_accounts": {
+                "has_more": false
+            },
+            "email": "user219@me.com",
+            "metadata": {
+                "id": "0000000000000000000186e5"
+            },
+            "sources": {
+                "data": [
+                    {
+                        "id": "card_17SYfcKaReE7xLUdQAQATTm4",
+                        "customer": "cus_7hyc7Vrhs9hrFd"
+                    }
+                ],
+                "has_more": false
+            },
+            "subscriptions": {
+                "has_more": false
+            }
+        }
+    },
+    {
+        "scope": "https://api.stripe.com:443",
+        "method": "POST",
+        "path": "/v1/customers/cus_7hyc7Vrhs9hrFd/subscriptions",
+        "status": 200,
+        "response": {
+            "id": "sub_7hycAhun9MsBGL",
+            "cancel_at_period_end": false,
+            "current_period_end": 1455308593,
+            "current_period_start": 1452630193,
+            "customer": "cus_7hyc7Vrhs9hrFd",
+            "discount": {
+                "coupon": {
+                    "id": "brazil"
+                },
+                "customer": "cus_7hyc7Vrhs9hrFd",
+                "subscription": "sub_7hycAhun9MsBGL"
+            },
+            "metadata": {
+                "id": "0000000000000000000186e5"
+            },
+            "plan": {
+                "id": "basic",
+                "amount": 100
+            },
+            "quantity": 1
+        }
+    },
+    {
+        "scope": "https://api.stripe.com:443",
+        "method": "POST",
+        "path": "/v1/customers/cus_7hyc7Vrhs9hrFd",
+        "status": 200,
+        "response": {
+            "id": "cus_7hyc7Vrhs9hrFd",
+            "alipay_accounts": {
+                "has_more": false
+            },
+            "email": "user219@me.com",
+            "metadata": {
+                "id": "0000000000000000000186e5"
+            },
+            "sources": {
+                "data": [
+                    {
+                        "id": "card_17SYfcKaReE7xLUdQAQATTm4",
+                        "customer": "cus_7hyc7Vrhs9hrFd"
+                    }
+                ],
+                "has_more": false
+            },
+            "subscriptions": {
+                "data": [
+                    {
+                        "id": "sub_7hycAhun9MsBGL",
+                        "cancel_at_period_end": false,
+                        "current_period_end": 1455308593,
+                        "current_period_start": 1452630193,
+                        "customer": "cus_7hyc7Vrhs9hrFd",
+                        "discount": {
+                            "coupon": {
+                                "id": "brazil"
+                            },
+                            "customer": "cus_7hyc7Vrhs9hrFd",
+                            "subscription": "sub_7hycAhun9MsBGL"
+                        },
+                        "metadata": {
+                            "id": "0000000000000000000186e5"
+                        },
+                        "plan": {
+                            "id": "basic",
+                            "amount": 100
+                        },
+                        "quantity": 1
+                    }
+                ],
+                "has_more": false
+            }
+        }
+    },
+    {
+        "scope": "https://api.stripe.com:443",
+        "method": "GET",
+        "path": "/v1/invoices",
+        "status": 200,
+        "response": {
+            "data": [
+                {
+                    "id": "in_17SYfdKaReE7xLUdVctB1XaE",
+                    "customer": "cus_7hyc7Vrhs9hrFd",
+                    "discount": {
+                        "coupon": {
+                            "id": "brazil"
+                        },
+                        "customer": "cus_7hyc7Vrhs9hrFd",
+                        "subscription": "sub_7hycAhun9MsBGL"
+                    },
+                    "lines": {
+                        "data": [
+                            {
+                                "id": "sub_7hycAhun9MsBGL",
+                                "amount": 100,
+                                "metadata": {
+                                    "id": "0000000000000000000186e5"
+                                },
+                                "plan": {
+                                    "id": "basic",
+                                    "amount": 100
+                                },
+                                "proration": false,
+                                "quantity": 1,
+                                "type": "subscription"
+                            }
+                        ],
+                        "has_more": false
+                    },
+                    "paid": true,
+                    "subscription": "sub_7hycAhun9MsBGL",
+                    "total": 0
+                }
+            ],
+            "has_more": false
+        }
+    },
+    {
+        "scope": "https://api.stripe.com:443",
+        "method": "POST",
+        "path": "/v1/customers/cus_7hyc7Vrhs9hrFd",
+        "status": 200,
+        "response": {
+            "id": "cus_7hyc7Vrhs9hrFd",
+            "alipay_accounts": {
+                "has_more": false
+            },
+            "email": "user219@me.com",
+            "metadata": {
+                "id": "0000000000000000000186e5"
+            },
+            "sources": {
+                "data": [
+                    {
+                        "id": "card_17SYfcKaReE7xLUdQAQATTm4",
+                        "customer": "cus_7hyc7Vrhs9hrFd"
+                    }
+                ],
+                "has_more": false
+            },
+            "subscriptions": {
+                "data": [
+                    {
+                        "id": "sub_7hycAhun9MsBGL",
+                        "cancel_at_period_end": false,
+                        "current_period_end": 1455308593,
+                        "current_period_start": 1452630193,
+                        "customer": "cus_7hyc7Vrhs9hrFd",
+                        "discount": {
+                            "coupon": {
+                                "id": "brazil"
+                            },
+                            "customer": "cus_7hyc7Vrhs9hrFd",
+                            "subscription": "sub_7hycAhun9MsBGL"
+                        },
+                        "metadata": {
+                            "id": "0000000000000000000186e5"
+                        },
+                        "plan": {
+                            "id": "basic",
+                            "amount": 100
+                        },
+                        "quantity": 1
+                    }
+                ],
+                "has_more": false
+            }
+        }
+    },
+    {
+        "scope": "https://api.stripe.com:443",
+        "method": "POST",
+        "path": "/v1/customers/cus_7hyc7Vrhs9hrFd",
+        "status": 200,
+        "response": {
+            "id": "cus_7hyc7Vrhs9hrFd",
+            "alipay_accounts": {
+                "has_more": false
+            },
+            "email": "user219@me.com",
+            "metadata": {
+                "id": "0000000000000000000186e5"
+            },
+            "sources": {
+                "data": [
+                    {
+                        "id": "card_17SYfcKaReE7xLUdQAQATTm4",
+                        "customer": "cus_7hyc7Vrhs9hrFd"
+                    }
+                ],
+                "has_more": false
+            },
+            "subscriptions": {
+                "data": [
+                    {
+                        "id": "sub_7hycAhun9MsBGL",
+                        "cancel_at_period_end": false,
+                        "current_period_end": 1455308593,
+                        "current_period_start": 1452630193,
+                        "customer": "cus_7hyc7Vrhs9hrFd",
+                        "discount": {
+                            "coupon": {
+                                "id": "brazil"
+                            },
+                            "customer": "cus_7hyc7Vrhs9hrFd",
+                            "subscription": "sub_7hycAhun9MsBGL"
+                        },
+                        "metadata": {
+                            "id": "0000000000000000000186e5"
+                        },
+                        "plan": {
+                            "id": "basic",
+                            "amount": 100
+                        },
+                        "quantity": 1
+                    }
+                ],
+                "has_more": false
+            }
+        }
+    },
+    {
+        "scope": "https://api.stripe.com:443",
+        "method": "GET",
+        "path": "/v1/invoices/in_17SYfdKaReE7xLUdVctB1XaE",
+        "status": 200,
+        "response": {
+            "id": "in_17SYfdKaReE7xLUdVctB1XaE",
+            "customer": "cus_7hyc7Vrhs9hrFd",
+            "discount": {
+                "coupon": {
+                    "id": "brazil"
+                },
+                "customer": "cus_7hyc7Vrhs9hrFd",
+                "subscription": "sub_7hycAhun9MsBGL"
+            },
+            "lines": {
+                "data": [
+                    {
+                        "id": "sub_7hycAhun9MsBGL",
+                        "amount": 100,
+                        "metadata": {
+                            "id": "0000000000000000000186e5"
+                        },
+                        "plan": {
+                            "id": "basic",
+                            "amount": 100
+                        },
+                        "proration": false,
+                        "quantity": 1,
+                        "type": "subscription"
+                    }
+                ],
+                "has_more": false
+            },
+            "paid": true,
+            "subscription": "sub_7hycAhun9MsBGL",
+            "total": 0
+        }
+    },
+    {
+        "scope": "https://api.stripe.com:443",
+        "method": "GET",
+        "path": "/v1/customers/cus_7hyc7Vrhs9hrFd",
+        "status": 200,
+        "response": {
+            "id": "cus_7hyc7Vrhs9hrFd",
+            "alipay_accounts": {
+                "has_more": false
+            },
+            "email": "user219@me.com",
+            "metadata": {
+                "id": "0000000000000000000186e5"
+            },
+            "sources": {
+                "data": [
+                    {
+                        "id": "card_17SYfcKaReE7xLUdQAQATTm4",
+                        "customer": "cus_7hyc7Vrhs9hrFd"
+                    }
+                ],
+                "has_more": false
+            },
+            "subscriptions": {
+                "data": [
+                    {
+                        "id": "sub_7hycAhun9MsBGL",
+                        "cancel_at_period_end": false,
+                        "current_period_end": 1455308593,
+                        "current_period_start": 1452630193,
+                        "customer": "cus_7hyc7Vrhs9hrFd",
+                        "discount": {
+                            "coupon": {
+                                "id": "brazil"
+                            },
+                            "customer": "cus_7hyc7Vrhs9hrFd",
+                            "subscription": "sub_7hycAhun9MsBGL"
+                        },
+                        "metadata": {
+                            "id": "0000000000000000000186e5"
+                        },
+                        "plan": {
+                            "id": "basic",
+                            "amount": 100
+                        },
+                        "quantity": 1
+                    }
+                ],
+                "has_more": false
+            }
+        }
+    }
+]
\ No newline at end of file
diff --git a/spec/helpers/helper.js b/spec/helpers/helper.js
index 4ad741bb7..7184ad9c3 100644
--- a/spec/helpers/helper.js
+++ b/spec/helpers/helper.js
@@ -38,43 +38,58 @@ if (database.generateMongoConnectionString() !== dbString) {
 
 jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 120; // for long Stripe tests
 
-describe('Server Test Helper', function() {
-  it('starts the test server', function(done) {
-    var server = require('../../server');
-    server.startServer(done);
+var initialized = false;
+beforeEach(function(done) {
+  if (initialized) {
+    return done();
+  }
+
+  var async = require('async');
+  async.series([
+    function(cb) {
+      // Start the server
+      var server = require('../../server');
+      server.startServer(cb);
+    },
+    function(cb) {
+      // 5. Check actual database
+      var User = require('../../server/users/User');
+      User.find({}).count(function(err, count) {
+        // For this to serve as a line of defense against testing with the
+        // production DB, tests must be run with 
+        expect(err).toBeNull();
+        expect(count).toBeLessThan(100);
+        if(err || count >= 100) {
+          // the only way to be sure we don't keep going with the tests
+          process.exit(1);
+        }
+        GLOBAL.mc.lists.subscribe = _.noop;
+        cb()
+      });
+    },
+    function(cb) {
+      // Clear db
+      var mongoose = require('mongoose');
+      mongoose.connection.db.command({dropDatabase:1}, function(err, result) {
+        if (err) { console.log(err); }
+        cb(err);
+      });
+    },
+    function(cb) {
+      // Initialize products
+      var request = require('request');
+      request.get(getURL('/db/products'), function(err, res, body) {
+        expect(err).toBe(null);
+        expect(res.statusCode).toBe(200);
+        cb(err);
+      });
+    }
+  ],
+  function(err) {
+    if (err) {
+      process.exit(1);
+    }
+    initialized = true;
+    done();
   });
-  
-  it('checks the db is fairly empty', function(done) {
-    // 5. Check actual database.
-    var User = require('../../server/users/User');
-    User.find({}).count(function(err, count) {
-      // For this to serve as a line of defense against testing with the
-      // production DB, tests must be run with 
-      expect(err).toBeNull();
-      expect(count).toBeLessThan(100);
-      if(err || count >= 100) {
-        // the only way to be sure we don't keep going with the tests
-        process.exit(1);
-      }
-      GLOBAL.mc.lists.subscribe = _.noop;
-      done()
-    });
-  });
-  
-  it('clears the db', function(done) {
-    var mongoose = require('mongoose');
-    mongoose.connection.db.command({dropDatabase:1}, function(err, result) {
-      if (err) { console.log(err); }
-      done(); 
-    });
-  });
-    
-  it('initializes products', function(done) {
-    var request = require('request');
-    request.get(getURL('/db/products'), function(err, res, body) {
-      expect(err).toBe(null);
-      expect(res.statusCode).toBe(200);
-      done();
-    });
-  })
 });
\ No newline at end of file
diff --git a/spec/server/functional/subscription.spec.coffee b/spec/server/functional/subscription.spec.coffee
index fe8fa5143..44b562665 100644
--- a/spec/server/functional/subscription.spec.coffee
+++ b/spec/server/functional/subscription.spec.coffee
@@ -6,6 +6,9 @@ mongoose = require 'mongoose'
 TRAVIS = process.env.COCO_TRAVIS_TEST
 nockUtils = require '../nock-utils'
 
+subPrice = 100
+subGems = 3500
+subGemsBrazil = 1500
 
 # sample data that comes in through the webhook when you subscribe
 invoiceChargeSampleEvent = {
@@ -143,7 +146,7 @@ describe '/db/user, editing stripe property', ->
           request.put {uri: userURL, json: joeData, headers: headers }, (err, res, body) ->
             joeData = body
             expect(res.statusCode).toBe(200)
-            expect(joeData.purchased.gems).toBe(3500)
+            expect(joeData.purchased.gems).toBe(subGems)
             expect(joeData.stripe.customerID).toBeDefined()
             expect(firstSubscriptionID = joeData.stripe.subscriptionID).toBeDefined()
             expect(joeData.stripe.planID).toBe('basic')
@@ -158,13 +161,13 @@ describe '/db/user, editing stripe property', ->
         expect(invoices.data.length).toBe(1)
         event = _.cloneDeep(invoiceChargeSampleEvent)
         event.data.object = invoices.data[0]
-  
+
         request.post {uri: webhookURL, json: event}, (err, res, body) ->
           expect(res.statusCode).toBe(201)
           Payment.find {}, (err, payments) ->
             expect(payments.length).toBe(1)
             User.findById joeData._id, (err, user) ->
-              expect(user.get('purchased').gems).toBe(3500)
+              expect(user.get('purchased').gems).toBe(subGems)
               nockDone()
               done()
 
@@ -188,7 +191,7 @@ describe '/db/user, editing stripe property', ->
       joeData.stripe.planID = 'basic'
       request.put {uri: userURL, json: joeData, headers: headers }, (err, res, body) ->
         joeData = body
-  
+
         expect(res.statusCode).toBe(200)
         expect(joeData.stripe.customerID).toBeDefined()
         expect(joeData.stripe.subscriptionID).toBeDefined()
@@ -204,13 +207,13 @@ describe '/db/user, editing stripe property', ->
         expect(invoices.data[0].total).toBe(0)
         event = _.cloneDeep(invoiceChargeSampleEvent)
         event.data.object = invoices.data[0]
-  
+
         request.post {uri: webhookURL, json: event}, (err, res, body) ->
           expect(res.statusCode).toBe(200)
           Payment.find {}, (err, payments) ->
             expect(payments.length).toBe(1)
             User.findById joeData._id, (err, user) ->
-              expect(user.get('purchased').gems).toBe(3500)
+              expect(user.get('purchased').gems).toBe(subGems)
               nockDone()
               done()
 
@@ -221,7 +224,7 @@ describe '/db/user, editing stripe property', ->
         event.data.object = subscription
         request.post {uri: webhookURL, json: event}, (err, res, body) ->
           User.findById joeData._id, (err, user) ->
-            expect(user.get('purchased').gems).toBe(3500)
+            expect(user.get('purchased').gems).toBe(subGems)
             expect(user.get('stripe').subscriptionID).toBeUndefined()
             expect(user.get('stripe').planID).toBeUndefined()
             nockDone()
@@ -246,8 +249,6 @@ describe 'Subscriptions', ->
   userURL = getURL('/db/user')
   webhookURL = getURL('/stripe/webhook')
   headers = {'X-Change-Plan': 'true'}
-  subPrice = 100
-  subGems = 3500
   invoicesWebHooked = {}
   afterEach nockUtils.teardownNock
 
@@ -620,7 +621,7 @@ describe 'Subscriptions', ->
                         expect(stripeInfo.prepaidCode).toEqual(prepaid.get('code'))
                         expect(stripeInfo.subscriptionID).toBeDefined()
                         return done() unless stripeInfo.subscriptionID
-  
+
                         # Delete subscription
                         stripe.customers.retrieveSubscription stripeInfo.customerID, stripeInfo.subscriptionID, (err, subscription) ->
                           expect(err).toBeNull()
@@ -843,7 +844,7 @@ describe 'Subscriptions', ->
                   nockDone()
                   done()
 
-    
+
     it 'Recipient user delete unsubscribes', (done) ->
       nockUtils.setupNock 'sub-test-14.json', (err, nockDone) ->
         stripe.tokens.create {
@@ -942,7 +943,7 @@ describe 'Subscriptions', ->
                       verifyNotRecipient user2.id, ->
                         nockDone()
                         done()
-                      
+
 
     it 'Unsubscribed user1 immediately resubscribes user2, one token', (done) ->
       nockUtils.setupNock 'sub-test-18.json', (err, nockDone) ->
@@ -1318,25 +1319,25 @@ describe 'Subscriptions', ->
           recipientCount = 2
           recipientsToVerify = [0, 1]
           recipients = new SubbedRecipients recipientCount, recipientsToVerify
-  
+
           # Create recipients
           recipients.createRecipients ->
             expect(recipients.length()).toEqual(recipientCount)
-  
+
             stripe.tokens.create {
               card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
             }, (err, token) ->
-  
+
               # Create sponsor user
               loginNewUser (user1) ->
                 subscribeUser user1, token, null, (updatedUser) ->
                   User.findById user1.id, (err, user1) ->
                     expect(err).toBeNull()
-  
+
                     # Subscribe recipients
                     recipients.subRecipients user1, null, ->
                       User.findById user1.id, (err, user1) ->
-  
+
                         # Unsubscribe recipient0
                         unsubscribeRecipient user1, recipients.get(0), ->
                           User.findById user1.id, (err, user1) ->
@@ -1348,7 +1349,7 @@ describe 'Subscriptions', ->
                                   expect(err).toBeNull()
                                   expect(subscription).not.toBeNull()
                                   expect(subscription?.quantity).toEqual(getSubscribedQuantity(1))
-  
+
                                   # Unsubscribe recipient1
                                   unsubscribeRecipient user1, recipients.get(1), ->
                                     User.findById user1.id, (err, user1) ->
@@ -1519,11 +1520,11 @@ describe 'Subscriptions', ->
                 endDate.setUTCFullYear(endDate.getUTCFullYear() + 1)
                 expect(stripeInfo.free).toEqual(endDate.toISOString().substring(0, 10))
                 expect(stripeInfo.customerID).toBeDefined()
-                expect(user1.get('purchased')?.gems).toEqual(3500*12)
+                expect(user1.get('purchased')?.gems).toEqual(subGems*12)
                 Payment.findOne 'stripe.customerID': stripeInfo.customerID, (err, payment) ->
                   expect(err).toBeNull()
-                  expect(payment).toBeDefined()
-                  expect(payment.get('gems')).toEqual(3500*12)
+                  expect(payment).toBeTruthy()
+                  expect(payment.get('gems')).toEqual(subGems*12)
                   nockDone()
                   done()
 
@@ -1553,11 +1554,11 @@ describe 'Subscriptions', ->
                   endDate.setUTCFullYear(endDate.getUTCFullYear() + 1)
                   expect(stripeInfo.free).toEqual(endDate.toISOString().substring(0, 10))
                   expect(stripeInfo.customerID).toBeDefined()
-                  expect(user1.get('purchased')?.gems).toEqual(3500*12)
+                  expect(user1.get('purchased')?.gems).toEqual(subGems*12)
                   Payment.findOne 'stripe.customerID': stripeInfo.customerID, (err, payment) ->
                     expect(err).toBeNull()
-                    expect(payment).toBeDefined()
-                    expect(payment.get('gems')).toEqual(3500*12)
+                    expect(payment).toBeTruthy()
+                    expect(payment.get('gems')).toEqual(subGems*12)
                     nockDone()
                     done()
 
@@ -1589,11 +1590,11 @@ describe 'Subscriptions', ->
                   endDate.setUTCFullYear(endDate.getUTCFullYear() + 1)
                   expect(stripeInfo.free).toEqual(endDate.toISOString().substring(0, 10))
                   expect(stripeInfo.customerID).toBeDefined()
-                  expect(user1.get('purchased')?.gems).toEqual(3500*12)
+                  expect(user1.get('purchased')?.gems).toEqual(subGems*12)
                   Payment.findOne 'stripe.customerID': stripeInfo.customerID, (err, payment) ->
                     expect(err).toBeNull()
-                    expect(payment).toBeDefined()
-                    expect(payment.get('gems')).toEqual(3500*12)
+                    expect(payment).toBeTruthy()
+                    expect(payment.get('gems')).toEqual(subGems*12)
                     nockDone()
                     done()
 
@@ -1626,11 +1627,11 @@ describe 'Subscriptions', ->
                   endDate.setUTCDate(endDate.getUTCDate() + 5)
                   expect(stripeInfo.free).toEqual(endDate.toISOString().substring(0, 10))
                   expect(stripeInfo.customerID).toBeDefined()
-                  expect(user1.get('purchased')?.gems).toEqual(3500*12)
+                  expect(user1.get('purchased')?.gems).toEqual(subGems*12)
                   Payment.findOne 'stripe.customerID': stripeInfo.customerID, (err, payment) ->
                     expect(err).toBeNull()
-                    expect(payment).toBeDefined()
-                    expect(payment.get('gems')).toEqual(3500*12)
+                    expect(payment).toBeTruthy()
+                    expect(payment.get('gems')).toEqual(subGems*12)
                     nockDone()
                     done()
 
@@ -1667,11 +1668,11 @@ describe 'Subscriptions', ->
                         endDate.setUTCFullYear(endDate.getUTCFullYear() + 1)
                         expect(stripeInfo.free).toEqual(endDate.toISOString().substring(0, 10))
                         expect(stripeInfo.customerID).toBeDefined()
-                        expect(user1.get('purchased')?.gems).toEqual(3500+3500*12)
+                        expect(user1.get('purchased')?.gems).toEqual(subGems+subGems*12)
                         Payment.findOne 'stripe.customerID': stripeInfo.customerID, (err, payment) ->
                           expect(err).toBeNull()
-                          expect(payment).toBeDefined()
-                          expect(payment.get('gems')).toEqual(3500*12)
+                          expect(payment).toBeTruthy()
+                          expect(payment.get('gems')).toEqual(subGems*12)
                           nockDone()
                           done()
 
@@ -1693,3 +1694,47 @@ describe 'Subscriptions', ->
                 expect(err).toBeNull()
                 nockDone()
                 done()
+
+  describe 'Countries', ->
+    it 'Brazil users get Brazil coupon', (done) ->
+      nockUtils.setupNock 'sub-test-41.json', (err, nockDone) ->
+        stripe.tokens.create {
+          card: { number: '4242424242424242', exp_month: 12, exp_year: 2030, cvc: '123' }
+        }, (err, token) ->
+          loginNewUser (user1) ->
+            user1.set('country', 'brazil')
+            user1.save (err, user1) ->
+              requestBody = user1.toObject()
+              requestBody.stripe =
+                planID: 'basic'
+                token: token.id
+              request.put {uri: userURL, json: requestBody, headers: headers }, (err, res, updatedUser) ->
+                expect(err).toBeNull()
+                expect(res.statusCode).toBe(200)
+                expect(updatedUser.country).toBe('brazil')
+                expect(updatedUser.purchased.gems).toBe(subGemsBrazil)
+                expect(updatedUser.stripe.planID).toBe('basic')
+                expect(updatedUser.stripe.customerID).toBeTruthy()
+
+                stripe.invoices.list {customer: updatedUser.stripe.customerID}, (err, invoices) ->
+                  expect(err).toBeNull()
+                  expect(invoices).not.toBeNull()
+                  expect(invoices.data.length).toBe(1)
+                  expect(invoices.data[0].discount?.coupon).toBeTruthy()
+                  expect(invoices.data[0].discount?.coupon?.id).toBe('brazil')
+                  expect(invoices.data[0].total).toBeLessThan(subPrice)
+
+                  # Now we hit our webhook to see if the right Payment is made.
+                  event = _.cloneDeep(invoiceChargeSampleEvent)
+                  event.data.object = invoices.data[0]
+                  request.post {uri: webhookURL, json: event}, (err, res, body) ->
+                    expect(err).toBeNull()
+                    expect(res.statusCode).toBe(201)
+                    Payment.findOne 'stripe.customerID': updatedUser.stripe.customerID, (err, payment) ->
+                      expect(err).toBeNull()
+                      expect(payment).toBeTruthy()
+                      return done() unless payment
+                      expect(payment.get('gems')).toEqual(subGemsBrazil)
+                      expect(payment.get('amount')).toBeLessThan(subPrice)
+                      nockDone()
+                      done()
diff --git a/spec/server/functional/trial_request.spec.coffee b/spec/server/functional/trial_request.spec.coffee
index 8077fd2d0..c34b7ec3e 100644
--- a/spec/server/functional/trial_request.spec.coffee
+++ b/spec/server/functional/trial_request.spec.coffee
@@ -129,16 +129,16 @@ describe 'Trial Requests', ->
                 Prepaid.find {'properties.trialRequestID': doc.get('_id')}, (err, prepaids) ->
                   expect(err).toBeNull()
                   return done(err) if err
-                  expect(prepaids.length).toEqual(2)
-                  for prepaid in prepaids
-                    expect(prepaid.get('type')).toEqual('course')
-                    expect(prepaid.get('creator')).toEqual(user.get('_id'))
-                    if prepaid.get('properties').endDate
-                      expect(prepaid.get('maxRedeemers')).toEqual(500)
-                      expect(prepaid.get('properties').endDate).toBeGreaterThan(new Date())
-                    else
-                      expect(prepaid.get('maxRedeemers')).toEqual(2)
-                  done()
+                  expect(prepaids.length).toEqual(1)
+                  prepaid = prepaids[0]
+                  expect(prepaid.get('type')).toEqual('course')
+                  expect(prepaid.get('creator')).toEqual(user.get('_id'))
+                  expect(prepaid.get('maxRedeemers')).toEqual(2)
+                  User.findById user._id, (err, user) =>
+                    expect(err).toBeNull()
+                    return done(err) if err
+                    expect(user.get('emails')?.teacherNews?.enabled).toEqual(true)
+                    done()
 
   it 'Deny trial request', (done) ->
     loginNewUser (user) ->
diff --git a/test/app/core/social-handlers/FacebookHandler.spec.coffee b/test/app/core/social-handlers/FacebookHandler.spec.coffee
index 24b2dbefc..201c6e8ce 100644
--- a/test/app/core/social-handlers/FacebookHandler.spec.coffee
+++ b/test/app/core/social-handlers/FacebookHandler.spec.coffee
@@ -69,7 +69,7 @@ describe 'lib/FacebookHandler.coffee', ->
     expect(FB.api).toHaveBeenCalled()
     apiArgs = FB.api.calls.argsFor(0)
     expect(apiArgs[0]).toBe('/me')
-    apiArgs[1](mockMe) # sending the 'response'
+    apiArgs[2](mockMe) # sending the 'response'
     request = jasmine.Ajax.requests.mostRecent()
     expect(request).toBeDefined()
     params = JSON.parse request.params
diff --git a/test/app/views/core/CocoView.spec.coffee b/test/app/views/core/CocoView.spec.coffee
new file mode 100644
index 000000000..50b03c777
--- /dev/null
+++ b/test/app/views/core/CocoView.spec.coffee
@@ -0,0 +1,150 @@
+CocoView = require 'views/core/CocoView'
+User = require 'models/User'
+
+BlandView = class BlandView extends CocoView
+  template: ->
+    return if @specialMessage then '<div id="content">custom message</div>' else '<div id="content">normal message</div>'
+    
+  initialize: ->
+    @user1 = new User({_id: _.uniqueId()})
+    @supermodel.loadModel(@user1)
+    @user2 = new User({_id: _.uniqueId()})
+    @supermodel.loadModel(@user2)
+
+  onResourceLoadFailed: (e) ->
+    resource = e.resource
+    if resource.jqxhr.status is 400 and resource.model is @user1
+      @specialMessage = true
+      @render()
+    else
+      super(arguments...)
+    
+
+describe 'CocoView', ->
+  describe 'network error handling', ->
+    view = null
+    respond = (code, index=0) ->
+      view.render()
+      requests = jasmine.Ajax.requests.all()
+      requests[index].respondWith({status: code, responseText: JSON.stringify({})})
+    
+    beforeEach ->
+      view = new BlandView()
+      
+    
+    describe 'when the view overrides onResourceLoadFailed', ->
+      beforeEach ->
+        view.render()
+        expect(view.$('#content').hasClass('hidden')).toBe(true)
+        respond(400)
+        
+      it 'can show a custom message for a given error and model', ->
+        expect(view.$('#content').hasClass('hidden')).toBe(false)
+        expect(view.$('#content').text()).toBe('custom message')
+        respond(200, 1)
+        expect(view.$('#content').hasClass('hidden')).toBe(false)
+        expect(view.$('#content').text()).toBe('custom message')
+
+      it '(demo)', -> jasmine.demoEl(view.$el)
+      
+      
+    describe 'when the server returns 401', ->
+      beforeEach ->
+        me.set('anonymous', true)
+        respond(401)
+      
+      it 'shows a login button which opens the AuthModal', ->
+        button = view.$el.find('.login-btn')
+        expect(button.length).toBe(3) # including the two in the links section
+        spyOn(view, 'openModalView').and.callFake (modal) -> expect(modal.mode).toBe('login')
+        button.click()
+        expect(view.openModalView).toHaveBeenCalled()
+        
+      it 'shows a create account button which opens the AuthModal', ->
+        button = view.$el.find('#create-account-btn')
+        expect(button.length).toBe(1)
+        spyOn(view, 'openModalView').and.callFake (modal) -> expect(modal.mode).toBe('signup')
+        button.click()
+        expect(view.openModalView).toHaveBeenCalled()
+
+      it 'says "Login Required"', ->
+        expect(view.$('[data-i18n="loading_error.login_required"]').length).toBeTruthy()
+
+      it '(demo)', -> jasmine.demoEl(view.$el)
+      
+
+
+    describe 'when the server returns 402', ->
+
+      beforeEach -> respond(402)
+
+      it 'does nothing, because it is up to the view to handle payment next steps'
+
+    
+    describe 'when the server returns 403', ->
+
+      beforeEach ->
+        me.set('anonymous', false)
+        respond(403)
+      
+      it 'includes a logout button which logs out the account', ->
+        button = view.$el.find('#logout-btn')
+        expect(button.length).toBe(1)
+        button.click()
+        request = jasmine.Ajax.requests.mostRecent()
+        expect(request.url).toBe('/auth/logout')
+
+      it '(demo)', -> jasmine.demoEl(view.$el)
+
+        
+    describe 'when the server returns 404', ->
+
+      beforeEach -> respond(404)
+
+      it 'includes one of the 404 images', ->
+        img = view.$el.find('#not-found-img')
+        expect(img.length).toBe(1)
+
+      it '(demo)', -> jasmine.demoEl(view.$el)
+
+
+    describe 'when the server returns 408', ->
+
+      beforeEach -> respond(408)
+      
+      it 'includes "Server Timeout" in the header', ->
+        expect(view.$('[data-i18n="loading_error.timeout"]').length).toBeTruthy()
+      
+      it 'shows a message encouraging refreshing the page or following links', ->
+        expect(view.$('[data-i18n="loading_error.general_desc"]').length).toBeTruthy()
+
+      it '(demo)', -> jasmine.demoEl(view.$el)
+
+
+    describe 'when no connection is made', ->
+
+      beforeEach ->
+        respond()
+
+      it 'shows "Connection Failed"', ->
+        expect(view.$('[data-i18n="loading_error.connection_failure"]').length).toBeTruthy()
+
+      it '(demo)', -> jasmine.demoEl(view.$el)
+
+
+    describe 'when the server returns any other number >= 400', ->
+
+      beforeEach -> respond(9001)
+
+      it 'includes "Unknown Error" in the header', ->
+        expect(view.$('[data-i18n="loading_error.unknown"]').length).toBeTruthy()
+
+      it 'shows a message encouraging refreshing the page or following links', ->
+        expect(view.$('[data-i18n="loading_error.general_desc"]').length).toBeTruthy()
+
+      it '(demo)', -> jasmine.demoEl(view.$el)
+        
+       
+            
+        
+      
\ No newline at end of file
diff --git a/test/app/views/editor/level/EditorLevelView.spec.coffee b/test/app/views/editor/level/EditorLevelView.spec.coffee
index 35beea837..521630d93 100644
--- a/test/app/views/editor/level/EditorLevelView.spec.coffee
+++ b/test/app/views/editor/level/EditorLevelView.spec.coffee
@@ -8,6 +8,7 @@ describe 'LevelEditView', ->
       view = new LevelEditView({}, 'something')
       request = jasmine.Ajax.requests.first()
       request.respondWith {status: 200, responseText: JSON.stringify(emptyLevel)}
+      me.set('anonymous', false) # otherwise button may be disabled an not fire
       view.render()
       spyOn(view, 'openModalView')
       view.$el.find('#revert-button').click()
diff --git a/test/app/views/play/level/modal/CourseVictoryModal.fixtures.coffee b/test/app/views/play/level/modal/CourseVictoryModal.fixtures.coffee
new file mode 100644
index 000000000..e7faee7af
--- /dev/null
+++ b/test/app/views/play/level/modal/CourseVictoryModal.fixtures.coffee
@@ -0,0 +1,1477 @@
+module.exports = {
+  achievements: [
+    {
+      "_id": "541a23431ccc8eaae19f3bf6",
+      "slug": "gems-in-the-deep-completed",
+      "related": "54173c90844506ae0195a0b4",
+      "userField": "creator",
+      "description": "You completed Gems in the Deep.",
+      "collection": "level.sessions",
+      "query": {
+        "state.complete": true,
+        "level.original": "54173c90844506ae0195a0b4"
+      },
+      "name": "Gems in the Deep Completed",
+      "__v": 32,
+      "rewards": {
+        "levels": [
+          "54174347844506ae0195a0b8"
+        ],
+        "gems": 18
+#        "items":[
+#          "53e4108204c00d4607a89f78"
+#        ]
+      },
+      "worth": 11,
+      "i18n": {},
+      "i18nCoverage": [],
+      "patches": []
+    },
+    {
+      "_id": "5452e14006a59e000067e501",
+      "slug": "gems-in-the-deep-clean-code",
+      "i18nCoverage": [],
+      "i18n": {},
+      "related": "54173c90844506ae0195a0b4",
+      "userField": "creator",
+      "description": "Clean code: no code errors or warnings.",
+      "collection": "level.sessions",
+      "query": {
+        "level.original": "54173c90844506ae0195a0b4",
+        "state.goalStates.clean-code.status": "success",
+        "state.complete": true
+      },
+      "name": "Gems in the Deep Clean Code",
+      "__v": 29,
+      "rewards": {
+        "gems": 9
+      },
+      "worth": 5,
+      "patches": []
+    }
+  ]
+  
+  
+  campaign: {
+    "_id": "55b29efd1cd6abe8ce07db0d",
+    "slug": "intro",
+    "name": "Intro",
+    "watchers": [
+      "512ef4805a67a8c507000001"
+    ],
+    "__v": 30,
+    "adjacentCampaigns": {
+      "549f0801e21e041139ef28c8": {
+        "name": "Forest",
+        "slug": "forest",
+        "position": {
+          "x": 94.5,
+          "y": 7
+        },
+        "rotation": -35,
+        "color": "purple",
+        "showIfUnlocked": "541b67f71ccc8eaae19f3c62",
+        "i18n": {}
+      }
+    },
+    "ambientSound": {
+      "mp3": "db/campaign/549f07f7e21e041139ef28c7/ambient-dungeon.mp3",
+      "ogg": "db/campaign/549f07f7e21e041139ef28c7/ambient-dungeon.ogg"
+    },
+    "backgroundColor": "rgba(68, 54, 45, 1)",
+    "backgroundColorTransparent": "rgba(68, 54, 45, 0)",
+    "backgroundImage": [
+      {
+        "image": "db/campaign/549f07f7e21e041139ef28c7/map_dungeon_1920.jpg",
+        "width": 1920
+      },
+      {
+        "image": "db/campaign/549f07f7e21e041139ef28c7/map_dungeon_1366.jpg",
+        "width": 1366
+      }
+    ],
+    "description": "1 hour: syntax, methods, parameters, strings, loops, variables",
+    "fullName": "Introduction to Computer Science",
+    "i18n": {},
+    "i18nCoverage": [],
+    "levels": {
+      "5411cb3769152f1707be029c": {
+        "campaignIndex": 0,
+        "rewards": [
+          {
+            "achievement": "541a198a1ccc8eaae19f3be4",
+            "level": "54173c90844506ae0195a0b4"
+          },
+          {
+            "achievement": "541a198a1ccc8eaae19f3be4",
+            "level": "55525bcaaf92058705a94c02"
+          }
+        ],
+        "name": "Dungeons of Kithgard",
+        "description": "Grab the gem, but touch nothing else. In this level you'll learn basic movement for your hero.",
+        "i18n": {},
+        "type": "hero",
+        "slug": "dungeons-of-kithgard",
+        "original": "5411cb3769152f1707be029c",
+        "disableSpaces": 3,
+        "hidesSubmitUntilRun": true,
+        "hidesPlayButton": true,
+        "hidesRunShortcut": true,
+        "hidesHUD": true,
+        "hidesSay": true,
+        "hidesCodeToolbar": true,
+        "hidesRealTimePlayback": true,
+        "backspaceThrottle": true,
+        "lockDefaultCode": false,
+        "autocompleteFontSizePx": 20,
+        "requiredCode": [
+          "moveRight"
+        ],
+        "requiredGear": {},
+        "restrictedGear": {
+          "feet": [
+            "53e2384453457600003e3f07"
+          ]
+        },
+        "campaign": "dungeon",
+        "tasks": [],
+        "concepts": [
+          "basic_syntax"
+        ],
+        "position": {
+          "x": 19.209888199437682,
+          "y": 12.51725346209055
+        }
+      },
+      "54173c90844506ae0195a0b4": {
+        "position": {
+          "y": 12.117739757859558,
+          "x": 28.059445721561577
+        },
+        "concepts": [
+          "basic_syntax"
+        ],
+        "tasks": [],
+        "campaign": "dungeon",
+        "restrictedGear": {
+          "feet": [
+            "53e2384453457600003e3f07"
+          ]
+        },
+        "requiredGear": {},
+        "autocompleteFontSizePx": 20,
+        "lockDefaultCode": false,
+        "backspaceThrottle": true,
+        "hidesRealTimePlayback": true,
+        "hidesCodeToolbar": true,
+        "hidesSay": true,
+        "hidesHUD": true,
+        "hidesRunShortcut": true,
+        "hidesPlayButton": true,
+        "hidesSubmitUntilRun": true,
+        "disableSpaces": 4,
+        "original": "54173c90844506ae0195a0b4",
+        "slug": "gems-in-the-deep",
+        "type": "hero",
+        "i18n": {},
+        "description": "Quickly collect the gems; you will need them.",
+        "name": "Gems in the Deep",
+        "rewards": [
+          {
+            "achievement": "541a23431ccc8eaae19f3bf6",
+            "level": "54174347844506ae0195a0b8"
+          }
+        ],
+        "campaignIndex": 1
+      },
+      "54174347844506ae0195a0b8": {
+        "campaignIndex": 2,
+        "rewards": [
+          {
+            "achievement": "54253cfb5d84cd00002e7f62",
+            "level": "544a98f62d002f0000fe331a"
+          },
+          {
+            "achievement": "54253cfb5d84cd00002e7f62",
+            "level": "54cfc6e2d06e8152051eb8a4"
+          }
+        ],
+        "name": "Shadow Guard",
+        "description": "Evade the ogre.",
+        "i18n": {},
+        "type": "hero",
+        "slug": "shadow-guard",
+        "original": "54174347844506ae0195a0b8",
+        "disableSpaces": 4,
+        "hidesSubmitUntilRun": true,
+        "hidesPlayButton": true,
+        "hidesRunShortcut": true,
+        "hidesHUD": true,
+        "hidesSay": true,
+        "hidesCodeToolbar": true,
+        "hidesRealTimePlayback": true,
+        "backspaceThrottle": true,
+        "lockDefaultCode": false,
+        "autocompleteFontSizePx": 20,
+        "requiredGear": {},
+        "restrictedGear": {
+          "right-hand": [
+            "53e218d853457600003e3ebe"
+          ],
+          "feet": [
+            "53e2384453457600003e3f07"
+          ]
+        },
+        "campaign": "dungeon",
+        "tasks": [],
+        "concepts": [
+          "basic_syntax"
+        ],
+        "position": {
+          "x": 33.762835987432396,
+          "y": 11.364727709666788
+        }
+      },
+      "54ca592de4983255055a5478": {
+        "concepts": [
+          "basic_syntax",
+          "arguments"
+        ],
+        "tasks": [],
+        "campaign": "dungeon",
+        "restrictedGear": {
+          "feet": [
+            "53e2384453457600003e3f07",
+            "546d4d259df4a17d0d449ac5",
+            "546d4d589df4a17d0d449ac9"
+          ],
+          "right-hand": [
+            "53e218d853457600003e3ebe",
+            "544d7d918494308424f564a7",
+            "544d7deb8494308424f564ab",
+            "544d7ffd8494308424f564c3",
+            "544d80598494308424f564c7",
+            "544d80928494308424f564cb",
+            "544d87188494308424f564f1",
+            "544d874f8494308424f564f5",
+            "544d877d8494308424f564f9"
+          ],
+          "programming-book": [
+            "53e4108204c00d4607a89f78"
+          ]
+        },
+        "requiredGear": {},
+        "autocompleteFontSizePx": 20,
+        "lockDefaultCode": false,
+        "backspaceThrottle": true,
+        "hidesRealTimePlayback": true,
+        "hidesCodeToolbar": true,
+        "hidesSay": true,
+        "hidesHUD": true,
+        "hidesRunShortcut": true,
+        "hidesPlayButton": true,
+        "adminOnly": false,
+        "practice": true,
+        "adventurer": false,
+        "original": "54ca592de4983255055a5478",
+        "slug": "enemy-mine",
+        "type": "hero",
+        "requiresSubscription": true,
+        "i18n": {},
+        "description": "Tread carefully, danger is afoot!",
+        "name": "Enemy Mine",
+        "rewards": [
+          {
+            "achievement": "54caa165fcf7f1540532890b",
+            "level": "54caa542e1bd9a4f054648b0"
+          }
+        ],
+        "campaignIndex": 3,
+        "position": {
+          "x": 40.39966204407879,
+          "y": 11.364727709666788
+        }
+      },
+      "541875da4c16460000ab990f": {
+        "campaignIndex": 4,
+        "rewards": [
+          {
+            "achievement": "541b15561ccc8eaae19f3c07",
+            "level": "5418aec24c16460000ab9aa6"
+          },
+          {
+            "achievement": "541b15561ccc8eaae19f3c07",
+            "level": "54527a6257e83800009730c7"
+          },
+          {
+            "achievement": "541b15561ccc8eaae19f3c07",
+            "level": "5452972f57e83800009730de"
+          }
+        ],
+        "name": "True Names",
+        "description": "Learn an enemy's true name to defeat it.",
+        "i18n": {},
+        "type": "hero",
+        "slug": "true-names",
+        "original": "541875da4c16460000ab990f",
+        "disableSpaces": 6,
+        "hidesPlayButton": true,
+        "hidesRunShortcut": true,
+        "hidesHUD": true,
+        "hidesSay": true,
+        "hidesCodeToolbar": true,
+        "hidesRealTimePlayback": true,
+        "backspaceThrottle": true,
+        "lockDefaultCode": false,
+        "autocompleteFontSizePx": 20,
+        "requiredCode": [
+          "Brak"
+        ],
+        "requiredGear": {},
+        "restrictedGear": {
+          "programming-book": [
+            "53e4108204c00d4607a89f78"
+          ],
+          "feet": [
+            "53e2384453457600003e3f07"
+          ]
+        },
+        "campaign": "dungeon",
+        "tasks": [],
+        "concepts": [
+          "basic_syntax",
+          "strings"
+        ],
+        "position": {
+          "x": 47.92144985442785,
+          "y": 10.462675898908136
+        }
+      },
+      "55ca293b9bc1892c835b0136": {
+        "position": {
+          "x": 53.50629543094496,
+          "y": 11.712539745627982
+        },
+        "concepts": [
+          "basic_syntax",
+          "while_loops"
+        ],
+        "tasks": [],
+        "campaign": "dungeon",
+        "restrictedGear": {
+          "feet": [
+            "53e2384453457600003e3f07",
+            "546d4d8e9df4a17d0d449acd",
+            "546d4d589df4a17d0d449ac9",
+            "546d4d259df4a17d0d449ac5"
+          ]
+        },
+        "requiredGear": {},
+        "autocompleteFontSizePx": 20,
+        "moveRightLoopSnippet": true,
+        "lockDefaultCode": false,
+        "backspaceThrottle": true,
+        "hidesRealTimePlayback": true,
+        "hidesCodeToolbar": true,
+        "hidesSay": true,
+        "hidesHUD": true,
+        "hidesRunShortcut": true,
+        "original": "55ca293b9bc1892c835b0136",
+        "slug": "fire-dancing",
+        "type": "hero",
+        "i18n": {},
+        "description": "Save typing (and your hero) with loops!",
+        "name": "Fire Dancing",
+        "rewards": [
+          {
+            "achievement": "55ca43609bc1892c835b0144",
+            "level": "565ce2291b940587057366dd"
+          }
+        ],
+        "campaignIndex": 5,
+        "suspectCode": [
+          {
+            "name": "double-while",
+            "pattern": "while(.|\\n|\\r)*while"
+          }
+        ]
+      },
+      "565ce2291b940587057366dd": {
+        "campaignIndex": 6,
+        "rewards": [
+          {
+            "achievement": "565f86219a120c86055496b3",
+            "level": "545a5914d820eb0000f6dc0a"
+          }
+        ],
+        "name": "Loop Da Loop",
+        "description": "Loops are a life saver!",
+        "i18n": {},
+        "type": "hero",
+        "slug": "loop-da-loop",
+        "original": "565ce2291b940587057366dd",
+        "adventurer": true,
+        "hidesRunShortcut": true,
+        "hidesHUD": true,
+        "hidesSay": true,
+        "hidesCodeToolbar": true,
+        "hidesRealTimePlayback": true,
+        "backspaceThrottle": true,
+        "autocompleteFontSizePx": 20,
+        "requiredGear": {},
+        "campaign": "dungeon",
+        "tasks": [],
+        "concepts": [
+          "basic_syntax",
+          "while_loops"
+        ],
+        "position": {
+          "x": 60.674649532710276,
+          "y": 11.953497615262322
+        }
+      },
+      "545a5914d820eb0000f6dc0a": {
+        "campaignIndex": 7,
+        "rewards": [
+          {
+            "achievement": "545a6d67d820eb0000f6dc21",
+            "level": "5452a84d57e83800009730e4"
+          },
+          {
+            "achievement": "545a6d67d820eb0000f6dc21",
+            "level": "5418cf256bae62f707c7e1c3"
+          }
+        ],
+        "name": "Haunted Kithmaze",
+        "description": "A maze constructed to confuse travelers.",
+        "i18n": {},
+        "type": "hero",
+        "slug": "haunted-kithmaze",
+        "original": "545a5914d820eb0000f6dc0a",
+        "hidesRunShortcut": true,
+        "hidesHUD": true,
+        "hidesSay": true,
+        "hidesCodeToolbar": true,
+        "hidesRealTimePlayback": true,
+        "backspaceThrottle": true,
+        "lockDefaultCode": false,
+        "moveRightLoopSnippet": true,
+        "autocompleteFontSizePx": 20,
+        "requiredCode": [
+          "loop"
+        ],
+        "requiredGear": {},
+        "restrictedGear": {
+          "feet": [
+            "53e2384453457600003e3f07"
+          ]
+        },
+        "campaign": "dungeon",
+        "tasks": [],
+        "concepts": [
+          "basic_syntax",
+          "while_loops"
+        ],
+        "position": {
+          "x": 66.94834061194076,
+          "y": 11.215687947100905
+        }
+      },
+      "5418cf256bae62f707c7e1c3": {
+        "concepts": [
+          "basic_syntax",
+          "while_loops"
+        ],
+        "tasks": [],
+        "campaign": "dungeon",
+        "restrictedGear": {
+          "feet": [
+            "53e2384453457600003e3f07"
+          ]
+        },
+        "requiredGear": {},
+        "autocompleteFontSizePx": 20,
+        "moveRightLoopSnippet": true,
+        "lockDefaultCode": false,
+        "backspaceThrottle": true,
+        "hidesRealTimePlayback": true,
+        "hidesCodeToolbar": true,
+        "hidesSay": true,
+        "hidesHUD": true,
+        "original": "5418cf256bae62f707c7e1c3",
+        "slug": "the-second-kithmaze",
+        "type": "hero",
+        "i18n": {},
+        "description": "Many have tried, few have found their way through this maze.",
+        "name": "The Second Kithmaze",
+        "rewards": [
+          {
+            "achievement": "54253d5c5d84cd00002e7f63",
+            "level": "5418d40f4c16460000ab9ac2"
+          },
+          {
+            "achievement": "54253d5c5d84cd00002e7f63",
+            "item": "5441c2be4e9aeb727cc97105"
+          }
+        ],
+        "campaignIndex": 8,
+        "position": {
+          "x": 80.63272271770526,
+          "y": 12.770871081984192
+        }
+      },
+      "5418d40f4c16460000ab9ac2": {
+        "campaignIndex": 9,
+        "rewards": [
+          {
+            "achievement": "541b22b21ccc8eaae19f3c19",
+            "level": "5452adea57e83800009730ee"
+          },
+          {
+            "achievement": "541b22b21ccc8eaae19f3c19",
+            "level": "54e0cdefe308cb510555a7f5"
+          }
+        ],
+        "name": "Dread Door",
+        "description": "Behind a dread door lies a chest full of riches.",
+        "i18n": {},
+        "type": "hero",
+        "slug": "dread-door",
+        "original": "5418d40f4c16460000ab9ac2",
+        "hidesHUD": true,
+        "hidesSay": true,
+        "hidesCodeToolbar": true,
+        "hidesRealTimePlayback": true,
+        "backspaceThrottle": true,
+        "lockDefaultCode": 9,
+        "autocompleteFontSizePx": 20,
+        "requiredGear": {},
+        "restrictedGear": {
+          "feet": [
+            "53e2384453457600003e3f07"
+          ],
+          "right-hand": [
+            "53f4e6e3d822c23505b74f42",
+            "54694ba3a2b1f53ce794444d"
+          ]
+        },
+        "campaign": "dungeon",
+        "tasks": [],
+        "concepts": [
+          "basic_syntax",
+          "while_loops",
+          "strings"
+        ],
+        "position": {
+          "x": 88.25112251874386,
+          "y": 19.244678910956324
+        }
+      },
+      "54e0cdefe308cb510555a7f5": {
+        "position": {
+          "y": 26.728260086243417,
+          "x": 81.15679685579524
+        },
+        "campaignIndex": 10,
+        "rewards": [
+          {
+            "achievement": "54e2ab6e0f6efa5005600737",
+            "level": "54e8e4047578d754057f852b"
+          }
+        ],
+        "name": "Cupboards of Kithgard",
+        "description": "Who knows what horrors lurk in the Cupboards of Kithgard?",
+        "i18n": {},
+        "requiresSubscription": true,
+        "type": "hero",
+        "slug": "cupboards-of-kithgard",
+        "original": "54e0cdefe308cb510555a7f5",
+        "adventurer": false,
+        "adminOnly": false,
+        "hidesHUD": true,
+        "hidesSay": true,
+        "hidesCodeToolbar": true,
+        "hidesRealTimePlayback": true,
+        "backspaceThrottle": true,
+        "lockDefaultCode": false,
+        "autocompleteFontSizePx": 20,
+        "requiredGear": {},
+        "restrictedGear": {
+          "feet": [
+            "53e2384453457600003e3f07",
+            "546d4d8e9df4a17d0d449acd",
+            "546d4d589df4a17d0d449ac9",
+            "546d4d259df4a17d0d449ac5"
+          ]
+        },
+        "campaign": "dungeon",
+        "tasks": [],
+        "concepts": [
+          "basic_syntax",
+          "while_loops",
+          "strings"
+        ]
+      },
+      "54f0e074a375e47f055d619c": {
+        "position": {
+          "y": 30.34167921686747,
+          "x": 73.73231720900935
+        },
+        "concepts": [
+          "basic_syntax",
+          "while_loops",
+          "strings"
+        ],
+        "tasks": [],
+        "campaign": "dungeon",
+        "restrictedGear": {
+          "feet": [
+            "53e2384453457600003e3f07",
+            "546d4d8e9df4a17d0d449acd",
+            "546d4d589df4a17d0d449ac9",
+            "546d4d259df4a17d0d449ac5"
+          ]
+        },
+        "requiredGear": {},
+        "autocompleteFontSizePx": 20,
+        "lockDefaultCode": false,
+        "backspaceThrottle": true,
+        "hidesRealTimePlayback": true,
+        "hidesCodeToolbar": true,
+        "hidesSay": true,
+        "hidesHUD": true,
+        "adminOnly": false,
+        "adventurer": false,
+        "original": "54f0e074a375e47f055d619c",
+        "slug": "breakout",
+        "type": "hero",
+        "requiresSubscription": true,
+        "i18n": {},
+        "description": "Munchkins are chasing you, and the way ahead is blocked!",
+        "name": "Breakout",
+        "rewards": [],
+        "campaignIndex": 11
+      },
+      "5452adea57e83800009730ee": {
+        "campaignIndex": 12,
+        "rewards": [
+          {
+            "achievement": "5452bb6757e83800009730f4",
+            "item": "53e238df53457600003e3f0b"
+          },
+          {
+            "achievement": "5452bb6757e83800009730f4",
+            "level": "5452c3ce57e83800009730f7"
+          }
+        ],
+        "name": "Known Enemy",
+        "description": "Using your first variable to achieve victory.",
+        "i18n": {},
+        "type": "hero",
+        "slug": "known-enemy",
+        "original": "5452adea57e83800009730ee",
+        "hidesHUD": true,
+        "hidesSay": true,
+        "hidesCodeToolbar": true,
+        "hidesRealTimePlayback": true,
+        "backspaceThrottle": true,
+        "lockDefaultCode": false,
+        "autocompleteFontSizePx": 20,
+        "suspectCode": [
+          {
+            "name": "enemy-in-quotes",
+            "pattern": "['\"]enemy"
+          }
+        ],
+        "requiredGear": {},
+        "restrictedGear": {
+          "feet": [
+            "53e2384453457600003e3f07"
+          ]
+        },
+        "campaign": "dungeon",
+        "tasks": [],
+        "concepts": [
+          "variables",
+          "basic_syntax",
+          "strings"
+        ],
+        "position": {
+          "x": 69.65270816049042,
+          "y": 25.67195662532944
+        }
+      },
+      "5452c3ce57e83800009730f7": {
+        "position": {
+          "y": 26.387842017483997,
+          "x": 56.47568004086775
+        },
+        "concepts": [
+          "basic_syntax",
+          "variables"
+        ],
+        "tasks": [],
+        "campaign": "dungeon",
+        "restrictedGear": {
+          "feet": [
+            "53e2384453457600003e3f07"
+          ]
+        },
+        "requiredGear": {},
+        "suspectCode": [
+          {
+            "name": "lone-find-nearest-enemy",
+            "pattern": "^[ ]*(self|this|@)?[:.]?findNearestEnemy()"
+          }
+        ],
+        "requiredCode": [
+          "findNearestEnemy"
+        ],
+        "autocompleteFontSizePx": 20,
+        "lockDefaultCode": false,
+        "backspaceThrottle": true,
+        "hidesRealTimePlayback": true,
+        "hidesCodeToolbar": true,
+        "hidesSay": true,
+        "hidesHUD": true,
+        "original": "5452c3ce57e83800009730f7",
+        "slug": "master-of-names",
+        "type": "hero",
+        "i18n": {},
+        "description": "Use your new coding powers to target nameless enemies.",
+        "name": "Master of Names",
+        "rewards": [
+          {
+            "achievement": "5452e88a06a59e000067e50e",
+            "level": "541b24511ccc8eaae19f3c1f"
+          }
+        ],
+        "campaignIndex": 13
+      },
+      "55ca29439bc1892c835b0137": {
+        "campaignIndex": 14,
+        "rewards": [
+          {
+            "achievement": "55ca45629bc1892c835b014c",
+            "level": "541b434e1ccc8eaae19f3c33"
+          }
+        ],
+        "name": "A Mayhem of Munchkins",
+        "description": "Survive a neverending stream of ogres with mentorship from two experienced heroes!",
+        "i18n": {},
+        "type": "hero",
+        "slug": "a-mayhem-of-munchkins",
+        "original": "55ca29439bc1892c835b0137",
+        "hidesHUD": true,
+        "hidesSay": true,
+        "hidesCodeToolbar": true,
+        "hidesRealTimePlayback": true,
+        "backspaceThrottle": true,
+        "lockDefaultCode": false,
+        "autocompleteFontSizePx": 20,
+        "suspectCode": [
+          {
+            "name": "lone-find-nearest-enemy",
+            "pattern": "^[ ]*(self|this|@)?[:.]?findNearestEnemy()"
+          }
+        ],
+        "requiredGear": {},
+        "campaign": "dungeon",
+        "tasks": [],
+        "concepts": [
+          "basic_syntax",
+          "variables",
+          "arguments",
+          "while_loops"
+        ],
+        "position": {
+          "x": 61.29479872441925,
+          "y": 34.55907063311842
+        }
+      },
+      "5452d8b906a59e000067e4fa": {
+        "position": {
+          "y": 40.53034954760448,
+          "x": 68.66942399136555
+        },
+        "concepts": [
+          "basic_syntax",
+          "variables",
+          "while_loops"
+        ],
+        "tasks": [],
+        "campaign": "dungeon",
+        "restrictedGear": {
+          "right-hand": [
+            "53f4e6e3d822c23505b74f42"
+          ],
+          "feet": [
+            "53e2384453457600003e3f07"
+          ]
+        },
+        "requiredGear": {},
+        "suspectCode": [
+          {
+            "name": "lone-find-nearest-enemy",
+            "pattern": "^[ ]*(self|this|@)?[:.]?findNearestEnemy()"
+          }
+        ],
+        "autocompleteFontSizePx": 20,
+        "lockDefaultCode": false,
+        "backspaceThrottle": true,
+        "hidesRealTimePlayback": true,
+        "hidesCodeToolbar": true,
+        "hidesSay": true,
+        "hidesHUD": true,
+        "practice": true,
+        "original": "5452d8b906a59e000067e4fa",
+        "slug": "the-gauntlet",
+        "type": "hero",
+        "requiresSubscription": true,
+        "i18n": {},
+        "description": "Use all of your skills to survive the gauntlet.",
+        "name": "The Gauntlet",
+        "rewards": [
+          {
+            "achievement": "5452db0106a59e000067e4fc",
+            "level": "54d24c49bf87255405a8f834"
+          }
+        ],
+        "campaignIndex": 15
+      },
+      "541b434e1ccc8eaae19f3c33": {
+        "campaignIndex": 16,
+        "rewards": [
+          {
+            "achievement": "54253e065d84cd00002e7f65",
+            "level": "541c9a30c6362edfb0f34479"
+          },
+          {
+            "achievement": "54253e065d84cd00002e7f65",
+            "level": "5452d8b906a59e000067e4fa"
+          },
+          {
+            "achievement": "54253e065d84cd00002e7f65",
+            "item": "53f4e6e3d822c23505b74f42"
+          }
+        ],
+        "name": "The Final Kithmaze",
+        "description": "To escape you must find your way through an elder Kithman's maze.",
+        "i18n": {},
+        "type": "hero",
+        "slug": "the-final-kithmaze",
+        "original": "541b434e1ccc8eaae19f3c33",
+        "hidesHUD": true,
+        "hidesSay": true,
+        "hidesCodeToolbar": true,
+        "hidesRealTimePlayback": true,
+        "backspaceThrottle": true,
+        "lockDefaultCode": false,
+        "autocompleteFontSizePx": 20,
+        "suspectCode": [
+          {
+            "name": "lone-find-nearest-enemy",
+            "pattern": "^[ ]*(self|this|@)?[:.]?findNearestEnemy()"
+          }
+        ],
+        "requiredGear": {},
+        "campaign": "dungeon",
+        "tasks": [],
+        "concepts": [
+          "basic_syntax",
+          "while_loops",
+          "variables"
+        ],
+        "position": {
+          "x": 74.56912900611479,
+          "y": 46.45561310182135
+        }
+      },
+      "541c9a30c6362edfb0f34479": {
+        "position": {
+          "y": 54.939545780779376,
+          "x": 80.71431897968904
+        },
+        "concepts": [
+          "basic_syntax",
+          "arguments",
+          "strings"
+        ],
+        "tasks": [],
+        "campaign": "dungeon",
+        "restrictedGear": {},
+        "requiredGear": {},
+        "autocompleteFontSizePx": 20,
+        "lockDefaultCode": false,
+        "backspaceThrottle": true,
+        "hidesRealTimePlayback": true,
+        "hidesCodeToolbar": true,
+        "hidesSay": true,
+        "original": "541c9a30c6362edfb0f34479",
+        "slug": "kithgard-gates",
+        "type": "hero",
+        "i18n": {},
+        "description": "Escape the Kithgard dungeons, and don't let the guardians get you.",
+        "name": "Kithgard Gates",
+        "rewards": [
+          {
+            "achievement": "541c9cf0c6362edfb0f3447a",
+            "level": "541b67f71ccc8eaae19f3c62"
+          },
+          {
+            "achievement": "541c9cf0c6362edfb0f3447a",
+            "level": "5578843e5cda3d8905654190"
+          }
+        ],
+        "campaignIndex": 17
+      },
+      "5630eab0c0fcbd86057cc2f8": {
+        "hidesRealTimePlayback": true,
+        "rewards": [],
+        "name": "Wakka Maul",
+        "description": "![Nov17 wakka maul](/file/db/level/5630eab0c0fcbd86057cc2f8/NOV17-Wakka Maul.png)\n\nBattle your classmates while gobbling up gems! Use your programming skills and creative thinking to gain an edge over your friends.",
+        "i18n": {},
+        "type": "course-ladder",
+        "slug": "wakka-maul",
+        "original": "5630eab0c0fcbd86057cc2f8",
+        "hidesCodeToolbar": true,
+        "backspaceThrottle": true,
+        "autocompleteFontSizePx": 20,
+        "campaign": "intro",
+        "tasks": [],
+        "concepts": [
+          "basic_syntax",
+          "algorithms",
+          "arguments",
+          "strings",
+          "while_loops"
+        ],
+        "position": {
+          "x": 17.481313926042485,
+          "y": 78.3938778580024
+        },
+        "campaignIndex": 18,
+        "requiredGear": {}
+      }
+    },
+    "patches": [],
+    "type": "course"
+  }  
+  
+  course: {
+    "_id": "560f1a9f22961295f9427742",
+    "name": "Introduction to Computer Science",
+    "slug": "introduction-to-computer-science",
+    "campaignID": "55b29efd1cd6abe8ce07db0d",
+    "concepts": [
+      "basic_syntax",
+      "arguments",
+      "strings",
+      "while_loops",
+      "variables"
+    ],
+    "description": "Learn basic syntax, while loops, and the CodeCombat environment.",
+    "duration": 1,
+    "pricePerSeat": 0,
+    "free": true,
+    "screenshot": "/images/pages/courses/101_info.png"
+  }
+  
+  
+  courseInstanceSessions: [
+    {
+      "_id": "542c78d49ba93600003ee6d3",
+      "changed": "2016-01-11T18:45:07.927Z",
+      "level": {
+        "original": "5411cb3769152f1707be029c"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 1609
+    },
+    {
+      "_id": "54380da36e7af40021bf5155",
+      "changed": "2016-01-11T23:33:09.763Z",
+      "level": {
+        "original": "54173c90844506ae0195a0b4"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 724
+    },
+    {
+      "_id": "542ef2c480d9aa104e81272f",
+      "changed": "2016-01-11T18:48:40.722Z",
+      "level": {
+        "original": "54174347844506ae0195a0b8"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 409
+    },
+    {
+      "_id": "542edae22d8c150000019128",
+      "changed": "2016-01-11T18:31:36.932Z",
+      "level": {
+        "original": "541875da4c16460000ab990f"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 1659
+    },
+    {
+      "_id": "543c3dd43eb2580000d33045",
+      "changed": "2015-11-19T17:56:04.522Z",
+      "level": {
+        "original": "5418cf256bae62f707c7e1c3"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 93
+    },
+    {
+      "_id": "542ecadc2d8c150000019125",
+      "changed": "2015-11-29T19:23:11.133Z",
+      "level": {
+        "original": "5418d40f4c16460000ab9ac2"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 117
+    },
+    {
+      "_id": "5463e15d6f4cc40000b14f3a",
+      "changed": "2015-11-29T19:28:33.799Z",
+      "level": {
+        "original": "541b434e1ccc8eaae19f3c33"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 59
+    },
+    {
+      "_id": "547e0c62e19f8e58056bf872",
+      "changed": "2015-11-29T19:29:18.715Z",
+      "level": {
+        "original": "541c9a30c6362edfb0f34479"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 42
+    },
+    {
+      "_id": "545ae2504425d30000ee7db6",
+      "changed": "2015-11-29T19:25:47.361Z",
+      "level": {
+        "original": "5452adea57e83800009730ee"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 1259
+    },
+    {
+      "_id": "565b513dd458ab9219b9527b",
+      "changed": "2015-11-29T19:26:19.521Z",
+      "level": {
+        "original": "5452c3ce57e83800009730f7"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 29
+    },
+    {
+      "_id": "565b5188d458ab9219b9528a",
+      "changed": "2015-12-27T23:34:21.144Z",
+      "level": {
+        "original": "5452d8b906a59e000067e4fa"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 26
+    },
+    {
+      "_id": "546badf73470fc1104015f50",
+      "changed": "2015-11-29T19:48:44.660Z",
+      "level": {
+        "original": "545a5914d820eb0000f6dc0a"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 57
+    },
+    {
+      "_id": "55dfd5d592e9cfb607cabc2c",
+      "changed": "2015-12-03T20:06:32.309Z",
+      "level": {
+        "original": "54ca592de4983255055a5478"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 42
+    },
+    {
+      "_id": "565b50a4d458ab9219b95260",
+      "changed": "2015-11-29T19:23:52.221Z",
+      "level": {
+        "original": "54e0cdefe308cb510555a7f5"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 34
+    },
+    {
+      "_id": "565b50cad458ab9219b9526c",
+      "changed": "2015-11-29T19:25:23.814Z",
+      "level": {
+        "original": "54f0e074a375e47f055d619c"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 88
+    },
+    {
+      "_id": "55f4570530825985054b0260",
+      "changed": "2015-11-29T19:48:39.224Z",
+      "level": {
+        "original": "55ca293b9bc1892c835b0136"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 207
+    },
+    {
+      "_id": "565b515dd458ab9219b95282",
+      "changed": "2015-12-27T23:38:34.709Z",
+      "level": {
+        "original": "55ca29439bc1892c835b0137"
+      },
+      "state": {
+        "complete": true
+      },
+      "playtime": 113
+    }
+  ]
+  
+  
+  earnedAchievements: [
+    {
+      "collection": "level.sessions",
+      "triggeredBy": "54380da36e7af40021bf5155",
+      "achievement": "541a23431ccc8eaae19f3bf6",
+      "_id": "543c21473eb2580000d3303c",
+      "user": "5162fab9c92b4c751e000274",
+      "achievementName": "Gems in the Deep Completed",
+      "earnedRewarsd": {
+        "gems": 5,
+        "levels": [
+          "54174347844506ae0195a0b8"
+        ]
+      },
+      "earnedPoints": 11,
+      "changed": "2015-04-02T21:18:27.994Z",
+      "created": "2014-10-13T19:00:23.833Z",
+      "__v": 0,
+      "earnedRewards": {
+        "gems": 18,
+        "levels": [
+          "54174347844506ae0195a0b8"
+        ]
+        "items":[
+          "53e4108204c00d4607a89f78"
+        ]
+      },
+      "notified": true
+    },
+    {
+      "collection": "level.sessions",
+      "triggeredBy": "54380da36e7af40021bf5155",
+      "achievement": "5452e14006a59e000067e501",
+      "_id": "5453164e60cfd0188a82a52d",
+      "user": "5162fab9c92b4c751e000274",
+      "earnedRewards": {
+        "gems": 9
+      },
+      "earnedPoints": 5,
+      "achievementName": "Gems in the Deep Clean Code",
+      "changed": "2015-04-02T21:18:38.200Z",
+      "notified": true
+    }
+  ]
+
+  
+  level: {
+    "_id": "568d3143b38ab75c00c2a4e5",
+    "slug": "gems-in-the-deep",
+    "name": "Gems in the Deep",
+    "creator": "568d15a28d909b2500464181",
+    "original": "54173c90844506ae0195a0b4",
+    "watchers": [
+    ],
+    "__v": 0,
+    "thangs": [],
+    "systems": [],
+    "goals": [],
+    "commitMessage": "",
+    "parent": "56898f85450ac83600d8c945",
+    "scripts": [],
+    "type": "hero",
+    "description": "Quickly collect the gems; you will need them.",
+    "victory": {
+      "body": "You will find a use for these gems soon.",
+      "i18n": []
+    },
+    "nextLevel": {
+      "original": "54174347844506ae0195a0b8",
+      "majorVersion": 0
+    },
+    "terrain": "Dungeon",
+    "patches": [],
+    "i18n": [],
+    "documentation": []
+    "i18nCoverage": [],
+    "index": true,
+    "buildTime": 14891,
+    "concepts": [
+      "basic_syntax"
+    ],
+    "campaignIndex": 1,
+    "created": "2016-01-06T15:22:43.033Z",
+    "version": {
+      "isLatestMinor": true,
+      "isLatestMajor": true,
+      "minor": 123,
+      "major": 0
+    },
+    "permissions": [
+      {
+        "access": "owner",
+        "target": "51538fdb812dd9af02000001"
+      },
+      {
+        "access": "read",
+        "target": "public"
+      }
+    ]
+  }
+  
+  
+  nextLevel: {
+    "_id": "568127b67e81751f00de45f7",
+    "slug": "shadow-guard",
+    "name": "Shadow Guard",
+    "creator": "53b54cda7e17883a0575767a",
+    "original": "54174347844506ae0195a0b8",
+    "watchers": [],
+    "__v": 0,
+    "scripts": [],
+    "thangs": [],
+    "systems": [],
+    "commitMessage": "i18n patch",
+    "parent": "566fc0cb66f91c2500c38f0a",
+    "type": "hero",
+    "description": "Evade the ogre.",
+    "victory": {},
+    "nextLevel": {
+      "original": "54ca592de4983255055a5478",
+      "majorVersion": 0
+    },
+    "terrain": "Dungeon",
+    "goals": [],
+    "patches": [],
+    "i18n": {},
+    "i18nCoverage": [],
+    "loadingTip": "We automatically save your code every few seconds.",
+    "documentation": {},
+    "requiredGear": {},
+    "restrictedGear": {},
+    "helpVideos": [],
+    "campaign": "dungeon",
+    "tasks": [],
+    "buildTime": 1923,
+    "scoreTypes": ["time"],
+    "index": true,
+    "concepts": ["basic_syntax"],
+    "campaignIndex": 2,
+    "created": "2015-12-28T12:14:46.362Z",
+    "version": {
+      "isLatestMinor": true,
+      "isLatestMajor": true,
+      "minor": 123,
+      "major": 0
+    },
+    "permissions": [
+      {
+        "access": "owner",
+        "target": "51538fdb812dd9af02000001"
+      },
+      {
+        "access": "read",
+        "target": "public"
+      }
+    ]
+  }
+  
+  
+  session: {
+    "_id": "54380da36e7af40021bf5155",
+    "changed": "2016-01-08T19:01:18.508Z",
+    "level": {
+      "original": "54173c90844506ae0195a0b4",
+      "majorVersion": 0
+    },
+    "creator": "5162fab9c92b4c751e000274",
+    "state": {
+      "topScores": [
+        {
+          "type": "time",
+          "date": "2015-10-26T17:46:17.508Z",
+          "score": -13.600000000000001
+        }
+      ],
+      "playing": true,
+      "selected": "Hero Placeholder",
+      "complete": true,
+      "scripts": {
+        "ended": {
+          "Real-Time Submission": 6,
+          "Debugging Victory": 5,
+          "First Code Run": 4,
+          "First Code Preload": 3,
+          "First Code Edit": 2,
+          "Introduction": 1,
+          "Taking Too Long": 7
+        },
+        "currentScriptOffset": 0,
+        "currentScript": null
+      },
+      "goalStates": {
+        "humans-survive": {
+          "status": "success",
+          "keyFrame": "end",
+          "killed": {
+            "Hero Placeholder": false
+          }
+        },
+        "collect-gems": {
+          "collected": {
+            "Gem 4": true,
+            "Gem 3": true,
+            "Gem 2": true,
+            "Gem 1": true,
+            "Gem": true
+          },
+          "keyFrame": 118,
+          "status": "success"
+        },
+        "clean-code": {
+          "problems": {
+            "Hero Placeholder": false
+          },
+          "optional": false,
+          "keyFrame": "end",
+          "status": "success"
+        }
+      },
+      "frame": 0,
+      "flagHistory": []
+    },
+    "codeLanguage": "python",
+    "__v": 1,
+    "heroConfig": {
+      "inventory": {
+        "programming-book": "53e4108204c00d4607a89f78",
+        "feet": "53e237bf53457600003e3f05",
+        "waist": "5437002a7beba4a82024a97d",
+        "right-hand": "53e218d853457600003e3ebe",
+        "gloves": "5469425ca2b1f53ce7944421",
+        "torso": "53e22eac53457600003e3efc",
+        "eyes": "53e238df53457600003e3f0b",
+        "head": "5441c2be4e9aeb727cc97105"
+      },
+      "thangType": "529ffbf1cf1818f2be000001"
+    },
+    "code": {
+      "hero-placeholder": {
+        "plan": "# Grab all the gems using your movement commands.\n\nself.moveRight()\nself.moveUp()\nself.moveRight()\nself.moveDown()\nself.moveLeft()\nself.moveDown()\nself.moveUp()\n\n"
+      }
+    },
+    "playtime": 698,
+    "teamSpells": {
+      "humans": [
+        "hero-placeholder/plan"
+      ]
+    },
+    "creatorName": "Scott",
+    "levelID": "gems-in-the-deep",
+    "levelName": "Gems in the Deep",
+    "multiplayer": false,
+    "browser": {
+      "version": "47.0.2526.106",
+      "platform": "mac",
+      "name": "chrome",
+      "desktop": true
+    },
+    "permissions": [
+      {
+        "target": "5162fab9c92b4c751e000274",
+        "access": "owner"
+      }
+    ],
+    "created": "2014-10-10T16:47:31.077Z"
+  }
+  
+
+  thangType: {
+    "_id": "568fe842cc51432f0036beb6",
+    "slug": "programmaticon-i",
+    "name": "Programmaticon I",
+    "original": "53e4108204c00d4607a89f78",
+    "components": [
+      {
+        "original": "524b4150ff92f1f4f8000024",
+        "majorVersion": 0
+      },
+      {
+        "original": "53e12043b82921000051cdf9",
+        "majorVersion": 0,
+        "config": {
+          "slots": [
+            "programming-book"
+          ]
+        }
+      },
+      {
+        "original": "524c81cab8bb087aaf000069",
+        "majorVersion": 0,
+        "config": {
+          "programmableSnippets": [
+            "loop"
+          ]
+        }
+      }
+    ],
+    "description": "Grants access to loops.",
+    "version": {
+      "isLatestMinor": true,
+      "isLatestMajor": true,
+      "minor": 56,
+      "major": 0
+    }
+  }
+}
\ No newline at end of file
diff --git a/test/app/views/play/level/modal/CourseVictoryModal.spec.coffee b/test/app/views/play/level/modal/CourseVictoryModal.spec.coffee
new file mode 100644
index 000000000..75ae097be
--- /dev/null
+++ b/test/app/views/play/level/modal/CourseVictoryModal.spec.coffee
@@ -0,0 +1,124 @@
+
+Course = require 'models/Course'
+Level = require 'models/Level'
+LevelSession = require 'models/LevelSession'
+Achievements = require 'collections/Achievements'
+CourseVictoryModal = require 'views/play/level/modal/CourseVictoryModal'
+fixtures = require './CourseVictoryModal.fixtures'
+NewItemView = require 'views/play/level/modal/NewItemView'
+ProgressView = require 'views/play/level/modal/ProgressView'
+
+describe 'CourseVictoryModal', ->
+
+  it 'will eventually be the only victory modal'
+  
+  makeViewOptions = ->
+    {
+      course: new Course(fixtures.course)
+      level: new Level(fixtures.level)
+      session: new LevelSession(fixtures.session)
+      achievements: new Achievements(fixtures.achievements)
+      nextLevel: new Level(fixtures.nextLevel)
+      courseInstanceID: '56414c3868785b5f152424f1'
+      courseID: '560f1a9f22961295f9427742'
+    }
+    
+  handleRequests = ->
+    requests = jasmine.Ajax.requests.all()
+    thangRequest = _.find(requests, (r) -> _.string.startsWith(r.url, '/db/thang.type'))
+    thangRequest?.respondWith({status: 200, responseText: JSON.stringify(fixtures.thangType)})
+
+    earnedAchievementRequests = _.where(requests, {url: '/db/earned_achievement'})
+    for [request, response] in _.zip(earnedAchievementRequests, fixtures.earnedAchievements)
+      request.respondWith({status: 200, responseText: JSON.stringify(response)})
+
+    sessionsRequest = _.find(requests, (r) -> _.string.startsWith(r.url, '/db/course_instance'))
+    sessionsRequest.respondWith({status: 200, responseText: JSON.stringify(fixtures.courseInstanceSessions)})
+
+    campaignRequest = _.findWhere(requests, {url: '/db/campaign/55b29efd1cd6abe8ce07db0d'})
+    campaignRequest.respondWith({status: 200, responseText: JSON.stringify(fixtures.campaign)})
+    
+  describe 'given a course level with a next level and no item or hero rewards', ->
+    modal = null
+
+    beforeEach (done) ->
+      options = makeViewOptions()
+      modal = new CourseVictoryModal(options)
+      handleRequests()
+      _.defer done
+
+    it 'only shows the ProgressView', ->
+      expect(_.size(modal.views)).toBe(1)
+      expect(modal.views[0] instanceof ProgressView).toBe(true)
+
+    it '(demo)', -> jasmine.demoModal(modal)
+    
+    describe 'its ProgressView', ->
+      it 'has a next level button which navigates to the next level on click', ->
+        spyOn(application.router, 'navigate')
+        button = modal.$el.find('#next-level-btn')
+        expect(button.length).toBe(1)
+        button.click()
+        expect(application.router.navigate).toHaveBeenCalled()
+        
+      it 'has two columns', ->
+        expect(modal.$('.row:first .col-sm-12').length).toBe(0)
+        expect(modal.$('.row:first .col-sm-5').length).toBe(1)
+        expect(modal.$('.row:first .col-sm-7').length).toBe(1)
+        
+  describe 'given a course level without a next level', ->
+    modal = null
+
+    beforeEach (done) ->
+      options = makeViewOptions()
+
+      # make the level not have a next level
+      level = options.level
+      level.unset('nextLevel')
+      delete options.nextLevel
+      modal = new CourseVictoryModal(options)
+      handleRequests()
+      _.defer done
+      
+    describe 'its ProgressView', ->
+      it 'has a single large column, since there is no next level to display', ->
+        expect(modal.$('.row:first .col-sm-12').length).toBe(1)
+        expect(modal.$('.row:first .col-sm-5').length).toBe(0)
+        expect(modal.$('.row:first .col-sm-7').length).toBe(0)
+        
+      it 'has a done button which navigates to the CourseDetailsView for the given course instance', ->
+        spyOn(application.router, 'navigate')
+        button = modal.$el.find('#done-btn')
+        expect(button.length).toBe(1)
+        button.click()
+        expect(application.router.navigate).toHaveBeenCalled()
+
+    it '(demo)', -> jasmine.demoModal(modal)
+      
+
+  describe 'given a course level with a new item', ->
+    modal = null
+    
+    beforeEach (done) ->
+      options = makeViewOptions()
+      
+      # insert new item into achievement properties
+      achievement = options.achievements.first()
+      rewards = _.cloneDeep(achievement.get('rewards'))
+      rewards.items = ["53e4108204c00d4607a89f78"]
+      achievement.set('rewards', rewards)
+      
+      modal = new CourseVictoryModal(options)
+      handleRequests()
+      _.defer done
+      
+    it 'includes a NewItemView when the level rewards a new item', ->
+      expect(_.size(modal.views)).toBe(2)
+      expect(modal.views[0] instanceof NewItemView).toBe(true)
+      
+    it 'continues to the ProgressView when you click the continue button', ->
+      expect(modal.currentView instanceof NewItemView).toBe(true)
+      modal.$el.find('#continue-btn').click()
+      expect(modal.currentView instanceof ProgressView).toBe(true)
+
+    it '(demo)', -> jasmine.demoModal(modal)
diff --git a/test/demo/views/achievement/AchievementGet.demo.coffee b/test/demo/views/achievement/AchievementGet.demo.coffee
index 697843c2e..661f20fb6 100644
--- a/test/demo/views/achievement/AchievementGet.demo.coffee
+++ b/test/demo/views/achievement/AchievementGet.demo.coffee
@@ -1,6 +1,6 @@
 CocoModel = require 'models/CocoModel'
-RootView = require 'views/kinds/RootView'
-utils = require 'lib/utils'
+RootView = require 'views/core/RootView'
+utils = require 'core/utils'
 Achievement = require 'models/Achievement'
 EarnedAchievement = require 'models/EarnedAchievement'
 fixtures = require '../../fixtures/achievements'
diff --git a/test/demo/views/common/LevelSessionCodeView.demo.coffee b/test/demo/views/common/LevelSessionCodeView.demo.coffee
index a7aa3810e..11648ac02 100644
--- a/test/demo/views/common/LevelSessionCodeView.demo.coffee
+++ b/test/demo/views/common/LevelSessionCodeView.demo.coffee
@@ -1,13 +1,13 @@
 LevelSessionCodeView = require 'views/common/LevelSessionCodeView'
 LevelSession = require 'models/LevelSession'
 
-levelSessionData = {"_id":"5317ad4909098828ed071f4d","level":{"original":"53173f76c269d400000543c2","majorVersion":0},"team":"humans","levelID":"dungeon-arena","levelName":"Dungeon Arena","submitted":true,"totalScore":38.4584087145667,"code":{"programmable-librarian":{"chooseAction":"// The Librarian is a spellcaster with a fireball attack\n// plus three useful spells: 'slow', 'regen', and 'haste'.\n// Slow makes a target move and attack at half speed for 5s.\n// Regen makes a target heal 10 hp/s for 10s.\n// Haste speeds up a target by 4x for 5s, once per match.\n\nvar enemies = this.getEnemies();\nif (enemies.length === 0) return;  // Chill if all enemies are dead.\nvar enemy = this.getNearest(enemies);\nif (this.canCast('slow', enemy)) {\n    // Slow the enemy, or chase if out of range (30m).\n    this.castSlow(enemy);\n    if (this.distance(enemy) <= 50)\n        this.say(\"Not so fast, \" + enemy.type + \" \" + enemy.id);\n}\nelse {\n    this.attack(enemy);\n}\nvar base = this.getFriends()[0];\nvar d = base.distance(enemy);\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 30, y: 30}}));\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 50, y: 40});\n"},"human-base":{"chooseAction":"// This is the code for your base. Decide which unit to build each frame.\n// Units you build will go into the this.built array.\n// Destroy the enemy base within 60 seconds!\n// Check out the Guide at the top for more info.\n\n// CHOOSE YOUR HERO! You can only build one hero.\nvar hero;\n//hero = 'tharin';  // A fierce knight with battlecry abilities.\nhero = 'hushbaum';  // A fiery spellcaster hero.\n\nif(hero && !this.builtHero) {\n    this.builtHero = this.build(hero);\n    return;\n}\n\n// Soldiers are hard-to-kill, low damage melee units with 2s build cooldown.\n// Archers are fragile but deadly ranged units with 2.5s build cooldown.\nvar buildOrder = ['soldier', 'soldier', 'soldier', 'soldier', 'archer'];\nvar type = buildOrder[this.built.length % buildOrder.length];\n//this.say('Unit #' + this.built.length + ' will be a ' + type);\nthis.build(type);"},"hushbaum":{"chooseAction":"var enemy = this.getNearestEnemy();\nif (enemy) {\n    if (!enemy.hasEffect('slow')) {\n        this.say(\"Not so fast, \" + enemy.type + \" \" + enemy.id);\n        this.castSlow(enemy);\n    }\n    else {\n        this.attack(enemy);\n    }\n}\nelse {\n    this.move({x: 70, y: 30});\n}\n"},"tharin":{"chooseAction":"var enemies = this.getEnemies();\nvar enemy = this.getNearest(enemies);\nif (!this.getCooldown('warcry')) {\n    this.warcry();\n}\nelse if (enemy) {\n    this.attack(enemy);\n}\nelse {\n    this.move({x: 10, y: 30});\n}\n"},"tharin-1":{"chooseAction":"var __interceptThis=(function(){var G=this;return function($this,sandbox){if($this==G){return sandbox;}return $this;};})();\nreturn (function (__global) {\n    var tmp0, tmp1;\n    tmp1 = function () {\n        _aether.logCallStart(this._aetherUserInfo); var enemies, enemy, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17, tmp18, tmp19, tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26;\n        tmp2 = 'use strict';\n        tmp3 = __interceptThis(this, __global);\n        tmp4 = 'getEnemies';\n        _aether.logStatementStart([{ofs: 0, row: 0, col: 0}, {ofs: 32, row: 0, col: 32}]); enemies = tmp3[tmp4](); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 0, row: 0, col: 0}, {ofs: 32, row: 0, col: 32}], \"var enemies = this.getEnemies();\", this._aetherUserInfo);\n        tmp5 = __interceptThis(this, __global);\n        tmp6 = 'getNearest';\n        tmp7 = enemies;\n        _aether.logStatementStart([{ofs: 33, row: 1, col: 0}, {ofs: 70, row: 1, col: 37}]); enemy = tmp5[tmp6](tmp7); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 33, row: 1, col: 0}, {ofs: 70, row: 1, col: 37}], \"var enemy = this.getNearest(enemies);\", this._aetherUserInfo);\n        tmp10 = __interceptThis(this, __global);\n        tmp11 = 'getCooldown';\n        _aether.logStatementStart([{ofs: 93, row: 2, col: 22}, {ofs: 101, row: 2, col: 30}]); tmp12 = 'warcry'; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 93, row: 2, col: 22}, {ofs: 101, row: 2, col: 30}], \"'warcry'\", this._aetherUserInfo);\n        _aether.logStatementStart([{ofs: 76, row: 2, col: 5}, {ofs: 102, row: 2, col: 31}]); tmp9 = tmp10[tmp11](tmp12); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 76, row: 2, col: 5}, {ofs: 102, row: 2, col: 31}], \"this.getCooldown('warcry')\", this._aetherUserInfo);\n        _aether.logStatementStart([{ofs: 75, row: 2, col: 4}, {ofs: 102, row: 2, col: 31}]); tmp8 = !tmp9; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 75, row: 2, col: 4}, {ofs: 102, row: 2, col: 31}], \"!this.getCooldown('warcry')\", this._aetherUserInfo);\n        if (tmp8) {\n            tmp13 = __interceptThis(this, __global);\n            tmp14 = 'warcry';\n            _aether.logStatementStart([{ofs: 110, row: 3, col: 4}, {ofs: 123, row: 3, col: 17}]); tmp15 = tmp13[tmp14](); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 110, row: 3, col: 4}, {ofs: 123, row: 3, col: 17}], \"this.warcry()\", this._aetherUserInfo);\n        } else {\n            tmp16 = enemy;\n            if (tmp16) {\n                tmp17 = __interceptThis(this, __global);\n                tmp18 = 'attack';\n                tmp19 = enemy;\n                _aether.logStatementStart([{ofs: 149, row: 6, col: 4}, {ofs: 167, row: 6, col: 22}]); tmp20 = tmp17[tmp18](tmp19); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 149, row: 6, col: 4}, {ofs: 167, row: 6, col: 22}], \"this.attack(enemy)\", this._aetherUserInfo);\n            } else {\n                tmp21 = __interceptThis(this, __global);\n                tmp22 = 'move';\n                _aether.logStatementStart([{ofs: 196, row: 9, col: 18}, {ofs: 198, row: 9, col: 20}]); tmp24 = 10; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 196, row: 9, col: 18}, {ofs: 198, row: 9, col: 20}], \"10\", this._aetherUserInfo);\n                _aether.logStatementStart([{ofs: 203, row: 9, col: 25}, {ofs: 205, row: 9, col: 27}]); tmp25 = 30; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 203, row: 9, col: 25}, {ofs: 205, row: 9, col: 27}], \"30\", this._aetherUserInfo);\n                _aether.logStatementStart([{ofs: 192, row: 9, col: 14}, {ofs: 206, row: 9, col: 28}]); tmp23 = {\n                    x: tmp24,\n                    y: tmp25\n                }; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 192, row: 9, col: 14}, {ofs: 206, row: 9, col: 28}], \"{x: 10, y: 30}\", this._aetherUserInfo);\n                _aether.logStatementStart([{ofs: 182, row: 9, col: 4}, {ofs: 207, row: 9, col: 29}]); tmp26 = tmp21[tmp22](tmp23); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 182, row: 9, col: 4}, {ofs: 207, row: 9, col: 29}], \"this.move({x: 10, y: 30})\", this._aetherUserInfo);\n            }\n        }\n        _aether.logCallEnd(); return;\n    };\n    tmp0 = 'chooseAction';\n    __global[tmp0] = tmp1;\n}(this));"},"programmable-tharin":{"chooseAction":"/*this.getFriends();\nthis.attack(this.getEnemies()[0]);\nreturn;\n*/\n \n\n/* TODO:\n   If they fully base race us, we actually do want to produce archers since they DPS faster\n   The effective DPS on soldiers is better if they attack us\n   but worse if they straight race us\n\n   //not sure if this is good but...\n   if they're attacking our base with a small number of units\n   we should make archers and get them to defend\n*/\n/*\nreturn;\n// Tharin is a melee fighter with shield, warcry, and terrify skills.\n// this.shield() lets him take one-third damage while defending.\n// this.warcry() gives allies within 10m 30% haste for 5s, every 10s.\n// this.terrify() sends foes within 30m fleeing for 5s, once per match.\nvar friends = this.getFriends();\nvar enemies = this.getEnemies();\nif (enemies.length === 0) return;  // Chill if all enemies are dead.\nvar enemy = this.getNearest(enemies);\nvar furthestFriendX = 30;\nfor (var i = 0; i < friends.length; ++i) {\n    var friend = friends[i];\n    furthestFriendX = Math.max(friend.pos.x, furthestFriendX);\n}  \nif (!this.getCooldown('warcry') && friends.length > 5) {\n    this.warcry();\n}  \nelse if ((this.now() > 15 || this.health < 150) && !this.getCooldown('terrify')) {\n    this.terrify();\n}\nelse if (this.health < 75 && this.pos.x > furthestFriendX - 5) {\n    this.move({x: 10, y: 27});\n}\nelse if (this.pos.x > furthestFriendX - 1 && this.now() < 50) {\n    this.shield();\n}\nelse {\n    this.attack(enemy);\n}\nthis.say(\"Defend!\", {targetPos: {x: 30, y: Infinity}});\n\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 30, y: 30}}));\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 40, y: 40});\n\n// You can store state on this across frames:\n//this.lastHealth = this.health;\n*/"}},"teamSpells":{"ogres":["programmable-brawler/chooseAction","programmable-shaman/chooseAction","ogre-base/chooseAction"],"humans":["programmable-librarian/chooseAction","programmable-tharin/chooseAction","human-base/chooseAction"]},"submittedCodeLanguage":"javascript","playtime":9753,"codeLanguage":"javascript"}
-levelData = {"_id":"53c997066567c600002a43d0","name":"Dungeon Arena","icon":"db/level/53173f76c269d400000543c2/11_dungeon.png","banner":"db/level/53173f76c269d400000543c2/dungeon_arena.png","employerDescription":"Players:\n* Attempt to destroy the enemy base.\n* Choose and control heroes to attack with.\n* Choose which types of lesser units to build and have limited control over them.\n* Try to write strategies that counter other enemy strategies.\n* Play on a small map.","systems":[],"thangs":[],"scripts":[],"documentation":{"generalArticles":[],"specificArticles":[]},"description":"This level is indescribably flarmy!","version":{"minor":0,"major":0,"isLatestMajor":true,"isLatestMinor":true}};
+levelSessionData = require './level-session.fixture'
+levelData = require './level.fixture';
 
 module.exports = ->
   session = new LevelSession(levelSessionData)
   v = new LevelSessionCodeView({session:session})
   request = jasmine.Ajax.requests.mostRecent()
-  request.response({status: 200, responseText: JSON.stringify(levelData)})
-  console.log 'okay should be fine'
+  request.respondWith({status: 200, responseText: JSON.stringify(levelData)})
+  v.render()
   v
diff --git a/test/demo/views/common/level-session.fixture.coffee b/test/demo/views/common/level-session.fixture.coffee
new file mode 100644
index 000000000..cf2eeb197
--- /dev/null
+++ b/test/demo/views/common/level-session.fixture.coffee
@@ -0,0 +1,47 @@
+module.exports = {
+  "_id": "5317ad4909098828ed071f4d",
+  "level": {
+    "original": "53173f76c269d400000543c2",
+    "majorVersion": 0
+  },
+  "team": "humans",
+  "levelID": "dungeon-arena",
+  "levelName": "Dungeon Arena",
+  "submitted": true,
+  "totalScore": 38.4584087145667,
+  "code": {
+    "programmable-librarian": {
+      "chooseAction": "// The Librarian is a spellcaster with a fireball attack\n// plus three useful spells: 'slow', 'regen', and 'haste'.\n// Slow makes a target move and attack at half speed for 5s.\n// Regen makes a target heal 10 hp/s for 10s.\n// Haste speeds up a target by 4x for 5s, once per match.\n\nvar enemies = this.getEnemies();\nif (enemies.length === 0) return;  // Chill if all enemies are dead.\nvar enemy = this.getNearest(enemies);\nif (this.canCast('slow', enemy)) {\n    // Slow the enemy, or chase if out of range (30m).\n    this.castSlow(enemy);\n    if (this.distance(enemy) <= 50)\n        this.say(\"Not so fast, \" + enemy.type + \" \" + enemy.id);\n}\nelse {\n    this.attack(enemy);\n}\nvar base = this.getFriends()[0];\nvar d = base.distance(enemy);\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 30, y: 30}}));\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 50, y: 40});\n"
+    },
+    "human-base": {
+      "chooseAction": "// This is the code for your base. Decide which unit to build each frame.\n// Units you build will go into the this.built array.\n// Destroy the enemy base within 60 seconds!\n// Check out the Guide at the top for more info.\n\n// CHOOSE YOUR HERO! You can only build one hero.\nvar hero;\n//hero = 'tharin';  // A fierce knight with battlecry abilities.\nhero = 'hushbaum';  // A fiery spellcaster hero.\n\nif(hero && !this.builtHero) {\n    this.builtHero = this.build(hero);\n    return;\n}\n\n// Soldiers are hard-to-kill, low damage melee units with 2s build cooldown.\n// Archers are fragile but deadly ranged units with 2.5s build cooldown.\nvar buildOrder = ['soldier', 'soldier', 'soldier', 'soldier', 'archer'];\nvar type = buildOrder[this.built.length % buildOrder.length];\n//this.say('Unit #' + this.built.length + ' will be a ' + type);\nthis.build(type);"
+    },
+    "hushbaum": {
+      "chooseAction": "var enemy = this.getNearestEnemy();\nif (enemy) {\n    if (!enemy.hasEffect('slow')) {\n        this.say(\"Not so fast, \" + enemy.type + \" \" + enemy.id);\n        this.castSlow(enemy);\n    }\n    else {\n        this.attack(enemy);\n    }\n}\nelse {\n    this.move({x: 70, y: 30});\n}\n"
+    },
+    "tharin": {
+      "chooseAction": "var enemies = this.getEnemies();\nvar enemy = this.getNearest(enemies);\nif (!this.getCooldown('warcry')) {\n    this.warcry();\n}\nelse if (enemy) {\n    this.attack(enemy);\n}\nelse {\n    this.move({x: 10, y: 30});\n}\n"
+    },
+    "tharin-1": {
+      "chooseAction": "var __interceptThis=(function(){var G=this;return function($this,sandbox){if($this==G){return sandbox;}return $this;};})();\nreturn (function (__global) {\n    var tmp0, tmp1;\n    tmp1 = function () {\n        _aether.logCallStart(this._aetherUserInfo); var enemies, enemy, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17, tmp18, tmp19, tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26;\n        tmp2 = 'use strict';\n        tmp3 = __interceptThis(this, __global);\n        tmp4 = 'getEnemies';\n        _aether.logStatementStart([{ofs: 0, row: 0, col: 0}, {ofs: 32, row: 0, col: 32}]); enemies = tmp3[tmp4](); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 0, row: 0, col: 0}, {ofs: 32, row: 0, col: 32}], \"var enemies = this.getEnemies();\", this._aetherUserInfo);\n        tmp5 = __interceptThis(this, __global);\n        tmp6 = 'getNearest';\n        tmp7 = enemies;\n        _aether.logStatementStart([{ofs: 33, row: 1, col: 0}, {ofs: 70, row: 1, col: 37}]); enemy = tmp5[tmp6](tmp7); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 33, row: 1, col: 0}, {ofs: 70, row: 1, col: 37}], \"var enemy = this.getNearest(enemies);\", this._aetherUserInfo);\n        tmp10 = __interceptThis(this, __global);\n        tmp11 = 'getCooldown';\n        _aether.logStatementStart([{ofs: 93, row: 2, col: 22}, {ofs: 101, row: 2, col: 30}]); tmp12 = 'warcry'; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 93, row: 2, col: 22}, {ofs: 101, row: 2, col: 30}], \"'warcry'\", this._aetherUserInfo);\n        _aether.logStatementStart([{ofs: 76, row: 2, col: 5}, {ofs: 102, row: 2, col: 31}]); tmp9 = tmp10[tmp11](tmp12); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 76, row: 2, col: 5}, {ofs: 102, row: 2, col: 31}], \"this.getCooldown('warcry')\", this._aetherUserInfo);\n        _aether.logStatementStart([{ofs: 75, row: 2, col: 4}, {ofs: 102, row: 2, col: 31}]); tmp8 = !tmp9; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 75, row: 2, col: 4}, {ofs: 102, row: 2, col: 31}], \"!this.getCooldown('warcry')\", this._aetherUserInfo);\n        if (tmp8) {\n            tmp13 = __interceptThis(this, __global);\n            tmp14 = 'warcry';\n            _aether.logStatementStart([{ofs: 110, row: 3, col: 4}, {ofs: 123, row: 3, col: 17}]); tmp15 = tmp13[tmp14](); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 110, row: 3, col: 4}, {ofs: 123, row: 3, col: 17}], \"this.warcry()\", this._aetherUserInfo);\n        } else {\n            tmp16 = enemy;\n            if (tmp16) {\n                tmp17 = __interceptThis(this, __global);\n                tmp18 = 'attack';\n                tmp19 = enemy;\n                _aether.logStatementStart([{ofs: 149, row: 6, col: 4}, {ofs: 167, row: 6, col: 22}]); tmp20 = tmp17[tmp18](tmp19); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 149, row: 6, col: 4}, {ofs: 167, row: 6, col: 22}], \"this.attack(enemy)\", this._aetherUserInfo);\n            } else {\n                tmp21 = __interceptThis(this, __global);\n                tmp22 = 'move';\n                _aether.logStatementStart([{ofs: 196, row: 9, col: 18}, {ofs: 198, row: 9, col: 20}]); tmp24 = 10; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 196, row: 9, col: 18}, {ofs: 198, row: 9, col: 20}], \"10\", this._aetherUserInfo);\n                _aether.logStatementStart([{ofs: 203, row: 9, col: 25}, {ofs: 205, row: 9, col: 27}]); tmp25 = 30; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 203, row: 9, col: 25}, {ofs: 205, row: 9, col: 27}], \"30\", this._aetherUserInfo);\n                _aether.logStatementStart([{ofs: 192, row: 9, col: 14}, {ofs: 206, row: 9, col: 28}]); tmp23 = {\n                    x: tmp24,\n                    y: tmp25\n                }; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 192, row: 9, col: 14}, {ofs: 206, row: 9, col: 28}], \"{x: 10, y: 30}\", this._aetherUserInfo);\n                _aether.logStatementStart([{ofs: 182, row: 9, col: 4}, {ofs: 207, row: 9, col: 29}]); tmp26 = tmp21[tmp22](tmp23); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 182, row: 9, col: 4}, {ofs: 207, row: 9, col: 29}], \"this.move({x: 10, y: 30})\", this._aetherUserInfo);\n            }\n        }\n        _aether.logCallEnd(); return;\n    };\n    tmp0 = 'chooseAction';\n    __global[tmp0] = tmp1;\n}(this));"
+    },
+    "programmable-tharin": {
+      "chooseAction": "/*this.getFriends();\nthis.attack(this.getEnemies()[0]);\nreturn;\n*/\n \n\n/* TODO:\n   If they fully base race us, we actually do want to produce archers since they DPS faster\n   The effective DPS on soldiers is better if they attack us\n   but worse if they straight race us\n\n   //not sure if this is good but...\n   if they're attacking our base with a small number of units\n   we should make archers and get them to defend\n*/\n/*\nreturn;\n// Tharin is a melee fighter with shield, warcry, and terrify skills.\n// this.shield() lets him take one-third damage while defending.\n// this.warcry() gives allies within 10m 30% haste for 5s, every 10s.\n// this.terrify() sends foes within 30m fleeing for 5s, once per match.\nvar friends = this.getFriends();\nvar enemies = this.getEnemies();\nif (enemies.length === 0) return;  // Chill if all enemies are dead.\nvar enemy = this.getNearest(enemies);\nvar furthestFriendX = 30;\nfor (var i = 0; i < friends.length; ++i) {\n    var friend = friends[i];\n    furthestFriendX = Math.max(friend.pos.x, furthestFriendX);\n}  \nif (!this.getCooldown('warcry') && friends.length > 5) {\n    this.warcry();\n}  \nelse if ((this.now() > 15 || this.health < 150) && !this.getCooldown('terrify')) {\n    this.terrify();\n}\nelse if (this.health < 75 && this.pos.x > furthestFriendX - 5) {\n    this.move({x: 10, y: 27});\n}\nelse if (this.pos.x > furthestFriendX - 1 && this.now() < 50) {\n    this.shield();\n}\nelse {\n    this.attack(enemy);\n}\nthis.say(\"Defend!\", {targetPos: {x: 30, y: Infinity}});\n\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 30, y: 30}}));\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 40, y: 40});\n\n// You can store state on this across frames:\n//this.lastHealth = this.health;\n*/"
+    }
+  },
+  "teamSpells": {
+    "ogres": [
+      "programmable-brawler/chooseAction",
+      "programmable-shaman/chooseAction",
+      "ogre-base/chooseAction"
+    ],
+    "humans": [
+      "programmable-librarian/chooseAction",
+      "programmable-tharin/chooseAction",
+      "human-base/chooseAction"
+    ]
+  },
+  "submittedCodeLanguage": "javascript",
+  "playtime": 9753,
+  "codeLanguage": "javascript"
+}
\ No newline at end of file
diff --git a/test/demo/views/common/level.fixture.coffee b/test/demo/views/common/level.fixture.coffee
new file mode 100644
index 000000000..b08950d16
--- /dev/null
+++ b/test/demo/views/common/level.fixture.coffee
@@ -0,0 +1,21 @@
+module.exports = {
+  "_id": "53c997066567c600002a43d0",
+  "name": "Dungeon Arena",
+  "icon": "db/level/53173f76c269d400000543c2/11_dungeon.png",
+  "banner": "db/level/53173f76c269d400000543c2/dungeon_arena.png",
+  "employerDescription": "Players:\n* Attempt to destroy the enemy base.\n* Choose and control heroes to attack with.\n* Choose which types of lesser units to build and have limited control over them.\n* Try to write strategies that counter other enemy strategies.\n* Play on a small map.",
+  "systems": [],
+  "thangs": [],
+  "scripts": [],
+  "documentation": {
+    "generalArticles": [],
+    "specificArticles": []
+  },
+  "description": "This level is indescribably flarmy!",
+  "version": {
+    "minor": 0,
+    "major": 0,
+    "isLatestMajor": true,
+    "isLatestMinor": true
+  }
+}
\ No newline at end of file
diff --git a/test/demo/views/editor/component/AddThangComponentsModal.demo.coffee b/test/demo/views/editor/component/AddThangComponentsModal.demo.coffee
index a2d5be343..3f0c0d99f 100644
--- a/test/demo/views/editor/component/AddThangComponentsModal.demo.coffee
+++ b/test/demo/views/editor/component/AddThangComponentsModal.demo.coffee
@@ -155,6 +155,6 @@ response =
 module.exports = ->
   view = new AddThangComponentsModal({skipOriginals:['52437c851d9e25b8dc000008']}) # FollowsNearest original
   console.log jasmine.Ajax.requests.all()
-  jasmine.Ajax.requests.mostRecent().response({status: 200, responseText: JSON.stringify(response)})
+  jasmine.Ajax.requests.mostRecent().respondWith({status: 200, responseText: JSON.stringify(response)})
   view.render()
   return view
\ No newline at end of file
diff --git a/vendor/scripts/jasmine-boot.js b/vendor/scripts/jasmine-boot.js
index 47b125211..17ec5589a 100755
--- a/vendor/scripts/jasmine-boot.js
+++ b/vendor/scripts/jasmine-boot.js
@@ -1,5 +1,29 @@
+// Changes made to this file from the default are marked with CHANGE comment
+
+/*
+ Copyright (c) 2008-2015 Pivotal Labs
+
+ Permission 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:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE 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.
+ */
 /**
- Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
+ Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
 
  If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
 
@@ -32,77 +56,12 @@
    *
    * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
    */
-  var jasmineInterface = {
-    describe: function(description, specDefinitions) {
-      return env.describe(description, specDefinitions);
-    },
-
-    xdescribe: function(description, specDefinitions) {
-      return env.xdescribe(description, specDefinitions);
-    },
-
-    it: function(desc, func) {
-      return env.it(desc, func);
-    },
-
-    xit: function(desc, func) {
-      return env.xit(desc, func);
-    },
-
-    beforeEach: function(beforeEachFunction) {
-      return env.beforeEach(beforeEachFunction);
-    },
-
-    afterEach: function(afterEachFunction) {
-      return env.afterEach(afterEachFunction);
-    },
-
-    expect: function(actual) {
-      return env.expect(actual);
-    },
-
-    pending: function() {
-      return env.pending();
-    },
-
-    spyOn: function(obj, methodName) {
-      return env.spyOn(obj, methodName);
-    },
-
-    jsApiReporter: new jasmine.JsApiReporter({
-      timer: new jasmine.Timer()
-    })
-  };
+  var jasmineInterface = jasmineRequire.interface(jasmine, env);
 
   /**
-   * Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
+   * Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
    */
-  if (typeof window == "undefined" && typeof exports == "object") {
-    extend(exports, jasmineInterface);
-  } else {
-    extend(window, jasmineInterface);
-  }
-
-  /**
-   * Expose the interface for adding custom equality testers.
-   */
-  jasmine.addCustomEqualityTester = function(tester) {
-    env.addCustomEqualityTester(tester);
-  };
-
-  /**
-   * Expose the interface for adding custom expectation matchers
-   */
-  jasmine.addMatchers = function(matchers) {
-    return env.addMatchers(matchers);
-  };
-
-  /**
-   * Expose the mock interface for the JavaScript timeout functions
-   */
-  jasmine.clock = function() {
-    return env.clock;
-  };
+  extend(window, jasmineInterface);
 
   /**
    * ## Runner Parameters
@@ -114,16 +73,32 @@
     getWindowLocation: function() { return window.location; }
   });
 
-  var catchingExceptions = false; // Setting to false always for CodeCombat, because Jasmine-HTML's reporter doesn't do source maps, and Chrome console does.
+  // CHANGE: Setting to false always, because Jasmine-HTML's reporter doesn't do source maps, and Chrome console does.
+  var catchingExceptions = false;
   env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
 
+  var throwingExpectationFailures = queryString.getParam("throwFailures");
+  env.throwOnExpectationFailure(throwingExpectationFailures);
+
+  var random = queryString.getParam("random");
+  env.randomizeTests(random);
+
+  var seed = queryString.getParam("seed");
+  if (seed) {
+    env.seed(seed);
+  }
+
   /**
    * ## Reporters
    * The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
    */
   var htmlReporter = new jasmine.HtmlReporter({
     env: env,
-    onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
+    onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); },
+    onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); },
+    onRandomClick: function() { queryString.navigateWithNewParam("random", !env.randomTests()); },
+    addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
+    // CHANGE: put #testing-area, not body
     getContainer: function() { return $('#testing-area')[0]; },
     createElement: function() { return document.createElement.apply(document, arguments); },
     createTextNode: function() { return document.createTextNode.apply(document, arguments); },
@@ -160,6 +135,7 @@
    *
    * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
    */
+  // CHANGE: give start control to testing page
   window.runJasmine = function() {
     htmlReporter.initialize();
     env.execute();
@@ -173,4 +149,4 @@
     return destination;
   }
 
-}());
+}());
\ No newline at end of file
diff --git a/vendor/scripts/jasmine.js b/vendor/scripts/jasmine.js
index 24463ecb8..ad63dff7c 100755
--- a/vendor/scripts/jasmine.js
+++ b/vendor/scripts/jasmine.js
@@ -1,83 +1,107 @@
 /*
-Copyright (c) 2008-2013 Pivotal Labs
+ Copyright (c) 2008-2015 Pivotal Labs
 
-Permission 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:
+ Permission 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:
 
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
 
-THE 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.
-*/
-function getJasmineRequireObj() {
-  if (typeof module !== "undefined" && module.exports) {
-    return exports;
+ THE 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.
+ */
+var getJasmineRequireObj = (function (jasmineGlobal) {
+  var jasmineRequire;
+
+  if (typeof module !== 'undefined' && module.exports) {
+    if (typeof global !== 'undefined') {
+      jasmineGlobal = global;
+    } else {
+      jasmineGlobal = {};
+    }
+    jasmineRequire = exports;
   } else {
-    window.jasmineRequire = window.jasmineRequire || {};
-    return window.jasmineRequire;
+    if (typeof window !== 'undefined' && typeof window.toString === 'function' && window.toString() === '[object GjsGlobal]') {
+      jasmineGlobal = window;
+    }
+    jasmineRequire = jasmineGlobal.jasmineRequire = jasmineGlobal.jasmineRequire || {};
   }
-}
 
-getJasmineRequireObj().core = function(jRequire) {
-  var j$ = {};
+  function getJasmineRequire() {
+    return jasmineRequire;
+  }
 
-  jRequire.base(j$);
-  j$.util = jRequire.util();
-  j$.Any = jRequire.Any();
-  j$.CallTracker = jRequire.CallTracker();
-  j$.Clock = jRequire.Clock();
-  j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
-  j$.Env = jRequire.Env(j$);
-  j$.ExceptionFormatter = jRequire.ExceptionFormatter();
-  j$.Expectation = jRequire.Expectation();
-  j$.buildExpectationResult = jRequire.buildExpectationResult();
-  j$.JsApiReporter = jRequire.JsApiReporter();
-  j$.matchersUtil = jRequire.matchersUtil(j$);
-  j$.ObjectContaining = jRequire.ObjectContaining(j$);
-  j$.pp = jRequire.pp(j$);
-  j$.QueueRunner = jRequire.QueueRunner();
-  j$.ReportDispatcher = jRequire.ReportDispatcher();
-  j$.Spec = jRequire.Spec(j$);
-  j$.SpyStrategy = jRequire.SpyStrategy();
-  j$.Suite = jRequire.Suite();
-  j$.Timer = jRequire.Timer();
-  j$.version = jRequire.version();
+  getJasmineRequire().core = function(jRequire) {
+    var j$ = {};
 
-  j$.matchers = jRequire.requireMatchers(jRequire, j$);
+    jRequire.base(j$, jasmineGlobal);
+    j$.util = jRequire.util();
+    j$.errors = jRequire.errors();
+    j$.Any = jRequire.Any(j$);
+    j$.Anything = jRequire.Anything(j$);
+    j$.CallTracker = jRequire.CallTracker();
+    j$.MockDate = jRequire.MockDate();
+    j$.Clock = jRequire.Clock();
+    j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
+    j$.Env = jRequire.Env(j$);
+    j$.ExceptionFormatter = jRequire.ExceptionFormatter();
+    j$.Expectation = jRequire.Expectation();
+    j$.buildExpectationResult = jRequire.buildExpectationResult();
+    j$.JsApiReporter = jRequire.JsApiReporter();
+    j$.matchersUtil = jRequire.matchersUtil(j$);
+    j$.ObjectContaining = jRequire.ObjectContaining(j$);
+    j$.ArrayContaining = jRequire.ArrayContaining(j$);
+    j$.pp = jRequire.pp(j$);
+    j$.QueueRunner = jRequire.QueueRunner(j$);
+    j$.ReportDispatcher = jRequire.ReportDispatcher();
+    j$.Spec = jRequire.Spec(j$);
+    j$.SpyRegistry = jRequire.SpyRegistry(j$);
+    j$.SpyStrategy = jRequire.SpyStrategy();
+    j$.StringMatching = jRequire.StringMatching(j$);
+    j$.Suite = jRequire.Suite(j$);
+    j$.Timer = jRequire.Timer();
+    j$.TreeProcessor = jRequire.TreeProcessor();
+    j$.version = jRequire.version();
+    j$.Order = jRequire.Order();
 
-  return j$;
-};
+    j$.matchers = jRequire.requireMatchers(jRequire, j$);
+
+    return j$;
+  };
+
+  return getJasmineRequire;
+})(this);
 
 getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
   var availableMatchers = [
-      "toBe",
-      "toBeCloseTo",
-      "toBeDefined",
-      "toBeFalsy",
-      "toBeGreaterThan",
-      "toBeLessThan",
-      "toBeNaN",
-      "toBeNull",
-      "toBeTruthy",
-      "toBeUndefined",
-      "toContain",
-      "toEqual",
-      "toHaveBeenCalled",
-      "toHaveBeenCalledWith",
-      "toMatch",
-      "toThrow",
-      "toThrowError"
+      'toBe',
+      'toBeCloseTo',
+      'toBeDefined',
+      'toBeFalsy',
+      'toBeGreaterThan',
+      'toBeLessThan',
+      'toBeNaN',
+      'toBeNull',
+      'toBeTruthy',
+      'toBeUndefined',
+      'toContain',
+      'toEqual',
+      'toHaveBeenCalled',
+      'toHaveBeenCalledWith',
+      'toHaveBeenCalledTimes',
+      'toMatch',
+      'toThrow',
+      'toThrowError'
     ],
     matchers = {};
 
@@ -89,20 +113,18 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
   return matchers;
 };
 
-getJasmineRequireObj().base = function(j$) {
+getJasmineRequireObj().base = function(j$, jasmineGlobal) {
   j$.unimplementedMethod_ = function() {
-    throw new Error("unimplemented method");
+    throw new Error('unimplemented method');
   };
 
   j$.MAX_PRETTY_PRINT_DEPTH = 40;
+  j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100;
   j$.DEFAULT_TIMEOUT_INTERVAL = 5000;
 
-  j$.getGlobal = (function() {
-    var jasmineGlobal = eval.call(null, "this");
-    return function() {
-      return jasmineGlobal;
-    };
-  })();
+  j$.getGlobal = function() {
+    return jasmineGlobal;
+  };
 
   j$.getEnv = function(options) {
     var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options);
@@ -111,15 +133,15 @@ getJasmineRequireObj().base = function(j$) {
   };
 
   j$.isArray_ = function(value) {
-    return j$.isA_("Array", value);
+    return j$.isA_('Array', value);
   };
 
   j$.isString_ = function(value) {
-    return j$.isA_("String", value);
+    return j$.isA_('String', value);
   };
 
   j$.isNumber_ = function(value) {
-    return j$.isA_("Number", value);
+    return j$.isA_('Number', value);
   };
 
   j$.isA_ = function(typeName, value) {
@@ -130,14 +152,30 @@ getJasmineRequireObj().base = function(j$) {
     return obj.nodeType > 0;
   };
 
+  j$.fnNameFor = function(func) {
+    return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1];
+  };
+
   j$.any = function(clazz) {
     return new j$.Any(clazz);
   };
 
+  j$.anything = function() {
+    return new j$.Anything();
+  };
+
   j$.objectContaining = function(sample) {
     return new j$.ObjectContaining(sample);
   };
 
+  j$.stringMatching = function(expected) {
+    return new j$.StringMatching(expected);
+  };
+
+  j$.arrayContaining = function(sample) {
+    return new j$.ArrayContaining(sample);
+  };
+
   j$.createSpy = function(name, originalFn) {
 
     var spyStrategy = new j$.SpyStrategy({
@@ -147,16 +185,21 @@ getJasmineRequireObj().base = function(j$) {
       }),
       callTracker = new j$.CallTracker(),
       spy = function() {
-        callTracker.track({
+        var callData = {
           object: this,
           args: Array.prototype.slice.apply(arguments)
-        });
-        return spyStrategy.exec.apply(this, arguments);
+        };
+
+        callTracker.track(callData);
+        var returnValue = spyStrategy.exec.apply(this, arguments);
+        callData.returnValue = returnValue;
+
+        return returnValue;
       };
 
     for (var prop in originalFn) {
       if (prop === 'and' || prop === 'calls') {
-        throw new Error("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon");
+        throw new Error('Jasmine spies would overwrite the \'and\' and \'calls\' properties on the object being spied upon');
       }
 
       spy[prop] = originalFn[prop];
@@ -177,8 +220,13 @@ getJasmineRequireObj().base = function(j$) {
   };
 
   j$.createSpyObj = function(baseName, methodNames) {
+    if (j$.isArray_(baseName) && j$.util.isUndefined(methodNames)) {
+      methodNames = baseName;
+      baseName = 'unknown';
+    }
+
     if (!j$.isArray_(methodNames) || methodNames.length === 0) {
-      throw "createSpyObj requires a non-empty array of method names to create spies for";
+      throw 'createSpyObj requires a non-empty array of method names to create spies for';
     }
     var obj = {};
     for (var i = 0; i < methodNames.length; i++) {
@@ -220,6 +268,31 @@ getJasmineRequireObj().util = function() {
     return obj === void 0;
   };
 
+  util.arrayContains = function(array, search) {
+    var i = array.length;
+    while (i--) {
+      if (array[i] === search) {
+        return true;
+      }
+    }
+    return false;
+  };
+
+  util.clone = function(obj) {
+    if (Object.prototype.toString.apply(obj) === '[object Array]') {
+      return obj.slice();
+    }
+
+    var cloned = {};
+    for (var prop in obj) {
+      if (obj.hasOwnProperty(prop)) {
+        cloned[prop] = obj[prop];
+      }
+    }
+
+    return cloned;
+  };
+
   return util;
 };
 
@@ -229,19 +302,17 @@ getJasmineRequireObj().Spec = function(j$) {
     this.resultCallback = attrs.resultCallback || function() {};
     this.id = attrs.id;
     this.description = attrs.description || '';
-    this.fn = attrs.fn;
-    this.beforeFns = attrs.beforeFns || function() { return []; };
-    this.afterFns = attrs.afterFns || function() { return []; };
+    this.queueableFn = attrs.queueableFn;
+    this.beforeAndAfterFns = attrs.beforeAndAfterFns || function() { return {befores: [], afters: []}; };
+    this.userContext = attrs.userContext || function() { return {}; };
     this.onStart = attrs.onStart || function() {};
-    this.exceptionFormatter = attrs.exceptionFormatter || function() {};
     this.getSpecName = attrs.getSpecName || function() { return ''; };
     this.expectationResultFactory = attrs.expectationResultFactory || function() { };
     this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
     this.catchingExceptions = attrs.catchingExceptions || function() { return true; };
+    this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
 
-    this.timer = attrs.timer || {setTimeout: setTimeout, clearTimeout: clearTimeout};
-
-    if (!this.fn) {
+    if (!this.queueableFn.fn) {
       this.pend();
     }
 
@@ -249,84 +320,51 @@ getJasmineRequireObj().Spec = function(j$) {
       id: this.id,
       description: this.description,
       fullName: this.getFullName(),
-      failedExpectations: []
+      failedExpectations: [],
+      passedExpectations: [],
+      pendingReason: ''
     };
   }
 
-  Spec.prototype.addExpectationResult = function(passed, data) {
+  Spec.prototype.addExpectationResult = function(passed, data, isError) {
+    var expectationResult = this.expectationResultFactory(data);
     if (passed) {
-      return;
+      this.result.passedExpectations.push(expectationResult);
+    } else {
+      this.result.failedExpectations.push(expectationResult);
+
+      if (this.throwOnExpectationFailure && !isError) {
+        throw new j$.errors.ExpectationFailed();
+      }
     }
-    this.result.failedExpectations.push(this.expectationResultFactory(data));
   };
 
   Spec.prototype.expect = function(actual) {
     return this.expectationFactory(actual, this);
   };
 
-  Spec.prototype.execute = function(onComplete) {
-    var self = this,
-        timeout;
+  Spec.prototype.execute = function(onComplete, enabled) {
+    var self = this;
 
     this.onStart(this);
 
-    if (this.markedPending || this.disabled) {
-      complete();
+    if (!this.isExecutable() || this.markedPending || enabled === false) {
+      complete(enabled);
       return;
     }
 
-    function timeoutable(fn) {
-      return function(done) {
-        timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
-          onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
-          done();
-        }, j$.DEFAULT_TIMEOUT_INTERVAL]]);
-
-        var callDone = function() {
-          clearTimeoutable();
-          done();
-        };
-
-        fn.call(this, callDone); //TODO: do we care about more than 1 arg?
-      };
-    }
-
-    function clearTimeoutable() {
-      Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
-      timeout = void 0;
-    }
-
-    var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns()),
-      allTimeoutableFns = [];
-    for (var i = 0; i < allFns.length; i++) {
-      var fn = allFns[i];
-      allTimeoutableFns.push(fn.length > 0 ? timeoutable(fn) : fn);
-    }
+    var fns = this.beforeAndAfterFns();
+    var allFns = fns.befores.concat(this.queueableFn).concat(fns.afters);
 
     this.queueRunnerFactory({
-      fns: allTimeoutableFns,
-      onException: onException,
-      onComplete: complete
+      queueableFns: allFns,
+      onException: function() { self.onException.apply(self, arguments); },
+      onComplete: complete,
+      userContext: this.userContext()
     });
 
-    function onException(e) {
-      clearTimeoutable();
-      if (Spec.isPendingSpecException(e)) {
-        self.pend();
-        return;
-      }
-
-      self.addExpectationResult(false, {
-        matcherName: "",
-        passed: false,
-        expected: "",
-        actual: "",
-        error: e
-      });
-    }
-
-    function complete() {
-      self.result.status = self.status();
+    function complete(enabledAgain) {
+      self.result.status = self.status(enabledAgain);
       self.resultCallback(self.result);
 
       if (onComplete) {
@@ -335,16 +373,43 @@ getJasmineRequireObj().Spec = function(j$) {
     }
   };
 
+  Spec.prototype.onException = function onException(e) {
+    if (Spec.isPendingSpecException(e)) {
+      this.pend(extractCustomPendingMessage(e));
+      return;
+    }
+
+    if (e instanceof j$.errors.ExpectationFailed) {
+      return;
+    }
+
+    this.addExpectationResult(false, {
+      matcherName: '',
+      passed: false,
+      expected: '',
+      actual: '',
+      error: e
+    }, true);
+  };
+
   Spec.prototype.disable = function() {
     this.disabled = true;
   };
 
-  Spec.prototype.pend = function() {
+  Spec.prototype.pend = function(message) {
     this.markedPending = true;
+    if (message) {
+      this.result.pendingReason = message;
+    }
   };
 
-  Spec.prototype.status = function() {
-    if (this.disabled) {
+  Spec.prototype.getResult = function() {
+    this.result.status = this.status();
+    return this.result;
+  };
+
+  Spec.prototype.status = function(enabled) {
+    if (this.disabled || enabled === false) {
       return 'disabled';
     }
 
@@ -359,23 +424,82 @@ getJasmineRequireObj().Spec = function(j$) {
     }
   };
 
+  Spec.prototype.isExecutable = function() {
+    return !this.disabled;
+  };
+
   Spec.prototype.getFullName = function() {
     return this.getSpecName(this);
   };
 
-  Spec.pendingSpecExceptionMessage = "=> marked Pending";
+  var extractCustomPendingMessage = function(e) {
+    var fullMessage = e.toString(),
+      boilerplateStart = fullMessage.indexOf(Spec.pendingSpecExceptionMessage),
+      boilerplateEnd = boilerplateStart + Spec.pendingSpecExceptionMessage.length;
+
+    return fullMessage.substr(boilerplateEnd);
+  };
+
+  Spec.pendingSpecExceptionMessage = '=> marked Pending';
 
   Spec.isPendingSpecException = function(e) {
-    return e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1;
+    return !!(e && e.toString && e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1);
   };
 
   return Spec;
 };
 
-if (typeof window == void 0 && typeof exports == "object") {
+if (typeof window == void 0 && typeof exports == 'object') {
   exports.Spec = jasmineRequire.Spec;
 }
 
+/*jshint bitwise: false*/
+
+getJasmineRequireObj().Order = function() {
+  function Order(options) {
+    this.random = 'random' in options ? options.random : true;
+    var seed = this.seed = options.seed || generateSeed();
+    this.sort = this.random ? randomOrder : naturalOrder;
+
+    function naturalOrder(items) {
+      return items;
+    }
+
+    function randomOrder(items) {
+      var copy = items.slice();
+      copy.sort(function(a, b) {
+        return jenkinsHash(seed + a.id) - jenkinsHash(seed + b.id);
+      });
+      return copy;
+    }
+
+    function generateSeed() {
+      return String(Math.random()).slice(-5);
+    }
+
+    // Bob Jenkins One-at-a-Time Hash algorithm is a non-cryptographic hash function
+    // used to get a different output when the key changes slighly.
+    // We use your return to sort the children randomly in a consistent way when
+    // used in conjunction with a seed
+
+    function jenkinsHash(key) {
+      var hash, i;
+      for(hash = i = 0; i < key.length; ++i) {
+        hash += key.charCodeAt(i);
+        hash += (hash << 10);
+        hash ^= (hash >> 6);
+      }
+      hash += (hash << 3);
+      hash ^= (hash >> 11);
+      hash += (hash << 15);
+      return hash;
+    }
+
+  }
+
+  return Order;
+};
+
 getJasmineRequireObj().Env = function(j$) {
   function Env(options) {
     options = options || {};
@@ -389,33 +513,54 @@ getJasmineRequireObj().Env = function(j$) {
 
     var realSetTimeout = j$.getGlobal().setTimeout;
     var realClearTimeout = j$.getGlobal().clearTimeout;
-    this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler());
+    this.clock = new j$.Clock(global, function () { return new j$.DelayedFunctionScheduler(); }, new j$.MockDate(global));
 
     var runnableLookupTable = {};
-
-    var spies = [];
+    var runnableResources = {};
 
     var currentSpec = null;
-    var currentSuite = null;
+    var currentlyExecutingSuites = [];
+    var currentDeclarationSuite = null;
+    var throwOnExpectationFailure = false;
+    var random = false;
+    var seed = null;
+
+    var currentSuite = function() {
+      return currentlyExecutingSuites[currentlyExecutingSuites.length - 1];
+    };
+
+    var currentRunnable = function() {
+      return currentSpec || currentSuite();
+    };
 
     var reporter = new j$.ReportDispatcher([
-      "jasmineStarted",
-      "jasmineDone",
-      "suiteStarted",
-      "suiteDone",
-      "specStarted",
-      "specDone"
+      'jasmineStarted',
+      'jasmineDone',
+      'suiteStarted',
+      'suiteDone',
+      'specStarted',
+      'specDone'
     ]);
 
     this.specFilter = function() {
       return true;
     };
 
-    var equalityTesters = [];
-
-    var customEqualityTesters = [];
     this.addCustomEqualityTester = function(tester) {
-      customEqualityTesters.push(tester);
+      if(!currentRunnable()) {
+        throw new Error('Custom Equalities must be added in a before function or a spec');
+      }
+      runnableResources[currentRunnable().id].customEqualityTesters.push(tester);
+    };
+
+    this.addMatchers = function(matchersToAdd) {
+      if(!currentRunnable()) {
+        throw new Error('Matchers must be added in a before function or a spec');
+      }
+      var customMatchers = runnableResources[currentRunnable().id].customMatchers;
+      for (var matcherName in matchersToAdd) {
+        customMatchers[matcherName] = matchersToAdd[matcherName];
+      }
     };
 
     j$.Expectation.addCoreMatchers(j$.matchers);
@@ -433,7 +578,8 @@ getJasmineRequireObj().Env = function(j$) {
     var expectationFactory = function(actual, spec) {
       return j$.Expectation.Factory({
         util: j$.matchersUtil,
-        customEqualityTesters: customEqualityTesters,
+        customEqualityTesters: runnableResources[spec.id].customEqualityTesters,
+        customMatchers: runnableResources[spec.id].customMatchers,
         actual: actual,
         addExpectationResult: addExpectationResult
       });
@@ -443,30 +589,38 @@ getJasmineRequireObj().Env = function(j$) {
       }
     };
 
-    var specStarted = function(spec) {
-      currentSpec = spec;
-      reporter.specStarted(spec.result);
+    var defaultResourcesForRunnable = function(id, parentRunnableId) {
+      var resources = {spies: [], customEqualityTesters: [], customMatchers: {}};
+
+      if(runnableResources[parentRunnableId]){
+        resources.customEqualityTesters = j$.util.clone(runnableResources[parentRunnableId].customEqualityTesters);
+        resources.customMatchers = j$.util.clone(runnableResources[parentRunnableId].customMatchers);
+      }
+
+      runnableResources[id] = resources;
     };
 
-    var beforeFns = function(suite) {
+    var clearResourcesForRunnable = function(id) {
+      spyRegistry.clearSpies();
+      delete runnableResources[id];
+    };
+
+    var beforeAndAfterFns = function(suite) {
       return function() {
-        var befores = [];
+        var befores = [],
+          afters = [];
+
         while(suite) {
           befores = befores.concat(suite.beforeFns);
-          suite = suite.parentSuite;
-        }
-        return befores.reverse();
-      };
-    };
-
-    var afterFns = function(suite) {
-      return function() {
-        var afters = [];
-        while(suite) {
           afters = afters.concat(suite.afterFns);
+
           suite = suite.parentSuite;
         }
-        return afters;
+
+        return {
+          befores: befores.reverse(),
+          afters: afters
+        };
       };
     };
 
@@ -476,13 +630,13 @@ getJasmineRequireObj().Env = function(j$) {
 
     // TODO: we may just be able to pass in the fn instead of wrapping here
     var buildExpectationResult = j$.buildExpectationResult,
-        exceptionFormatter = new j$.ExceptionFormatter(),
-        expectationResultFactory = function(attrs) {
-          attrs.messageFormatter = exceptionFormatter.message;
-          attrs.stackFormatter = exceptionFormatter.stack;
+      exceptionFormatter = new j$.ExceptionFormatter(),
+      expectationResultFactory = function(attrs) {
+        attrs.messageFormatter = exceptionFormatter.message;
+        attrs.stackFormatter = exceptionFormatter.stack;
 
-          return buildExpectationResult(attrs);
-        };
+        return buildExpectationResult(attrs);
+      };
 
     // TODO: fix this naming, and here's where the value comes in
     this.catchExceptions = function(value) {
@@ -511,9 +665,34 @@ getJasmineRequireObj().Env = function(j$) {
       return j$.Spec.isPendingSpecException(e) || catchExceptions;
     };
 
+    this.throwOnExpectationFailure = function(value) {
+      throwOnExpectationFailure = !!value;
+    };
+
+    this.throwingExpectationFailures = function() {
+      return throwOnExpectationFailure;
+    };
+
+    this.randomizeTests = function(value) {
+      random = !!value;
+    };
+
+    this.randomTests = function() {
+      return random;
+    };
+
+    this.seed = function(value) {
+      if (value) {
+        seed = value;
+      }
+      return seed;
+    };
+
     var queueRunnerFactory = function(options) {
       options.catchException = catchException;
       options.clearStack = options.clearStack || clearStack;
+      options.timeout = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout};
+      options.fail = self.fail;
 
       new j$.QueueRunner(options).execute();
     };
@@ -522,66 +701,79 @@ getJasmineRequireObj().Env = function(j$) {
       env: this,
       id: getNextSuiteId(),
       description: 'Jasmine__TopLevel__Suite',
-      queueRunner: queueRunnerFactory,
-      resultCallback: function() {} // TODO - hook this up
+      queueRunner: queueRunnerFactory
     });
     runnableLookupTable[topSuite.id] = topSuite;
-    currentSuite = topSuite;
+    defaultResourcesForRunnable(topSuite.id);
+    currentDeclarationSuite = topSuite;
 
     this.topSuite = function() {
       return topSuite;
     };
 
     this.execute = function(runnablesToRun) {
-      runnablesToRun = runnablesToRun || [topSuite.id];
+      if(!runnablesToRun) {
+        if (focusedRunnables.length) {
+          runnablesToRun = focusedRunnables;
+        } else {
+          runnablesToRun = [topSuite.id];
+        }
+      }
 
-      var allFns = [];
-      for(var i = 0; i < runnablesToRun.length; i++) {
-        var runnable = runnableLookupTable[runnablesToRun[i]];
-        allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable));
+      var order = new j$.Order({
+        random: random,
+        seed: seed
+      });
+
+      var processor = new j$.TreeProcessor({
+        tree: topSuite,
+        runnableIds: runnablesToRun,
+        queueRunnerFactory: queueRunnerFactory,
+        nodeStart: function(suite) {
+          currentlyExecutingSuites.push(suite);
+          defaultResourcesForRunnable(suite.id, suite.parentSuite.id);
+          reporter.suiteStarted(suite.result);
+        },
+        nodeComplete: function(suite, result) {
+          if (!suite.disabled) {
+            clearResourcesForRunnable(suite.id);
+          }
+          currentlyExecutingSuites.pop();
+          reporter.suiteDone(result);
+        },
+        orderChildren: function(node) {
+          return order.sort(node.children);
+        }
+      });
+
+      if(!processor.processTree().valid) {
+        throw new Error('Invalid order: would cause a beforeAll or afterAll to be run multiple times');
       }
 
       reporter.jasmineStarted({
         totalSpecsDefined: totalSpecsDefined
       });
 
-      queueRunnerFactory({fns: allFns, onComplete: reporter.jasmineDone});
+      processor.execute(function() {
+        reporter.jasmineDone({
+          order: order
+        });
+      });
     };
 
     this.addReporter = function(reporterToAdd) {
       reporter.addReporter(reporterToAdd);
     };
 
-    this.addMatchers = function(matchersToAdd) {
-      j$.Expectation.addMatchers(matchersToAdd);
-    };
-
-    this.spyOn = function(obj, methodName) {
-      if (j$.util.isUndefined(obj)) {
-        throw new Error("spyOn could not find an object to spy upon for " + methodName + "()");
+    var spyRegistry = new j$.SpyRegistry({currentSpies: function() {
+      if(!currentRunnable()) {
+        throw new Error('Spies must be created in a before function or a spec');
       }
+      return runnableResources[currentRunnable().id].spies;
+    }});
 
-      if (j$.util.isUndefined(obj[methodName])) {
-        throw new Error(methodName + '() method does not exist');
-      }
-
-      if (obj[methodName] && j$.isSpy(obj[methodName])) {
-        //TODO?: should this return the current spy? Downside: may cause user confusion about spy state
-        throw new Error(methodName + ' has already been spied upon');
-      }
-
-      var spy = j$.createSpy(methodName, obj[methodName]);
-
-      spies.push({
-        spy: spy,
-        baseObj: obj,
-        methodName: methodName,
-        originalValue: obj[methodName]
-      });
-
-      obj[methodName] = spy;
-
-      return spy;
+    this.spyOn = function() {
+      return spyRegistry.spyOn.apply(spyRegistry, arguments);
     };
 
     var suiteFactory = function(description) {
@@ -589,12 +781,10 @@ getJasmineRequireObj().Env = function(j$) {
         env: self,
         id: getNextSuiteId(),
         description: description,
-        parentSuite: currentSuite,
-        queueRunner: queueRunnerFactory,
-        onStart: suiteStarted,
-        resultCallback: function(attrs) {
-          reporter.suiteDone(attrs);
-        }
+        parentSuite: currentDeclarationSuite,
+        expectationFactory: expectationFactory,
+        expectationResultFactory: expectationResultFactory,
+        throwOnExpectationFailure: throwOnExpectationFailure
       });
 
       runnableLookupTable[suite.id] = suite;
@@ -603,10 +793,40 @@ getJasmineRequireObj().Env = function(j$) {
 
     this.describe = function(description, specDefinitions) {
       var suite = suiteFactory(description);
+      if (specDefinitions.length > 0) {
+        throw new Error('describe does not expect a done parameter');
+      }
+      if (currentDeclarationSuite.markedPending) {
+        suite.pend();
+      }
+      addSpecsToSuite(suite, specDefinitions);
+      return suite;
+    };
 
-      var parentSuite = currentSuite;
+    this.xdescribe = function(description, specDefinitions) {
+      var suite = suiteFactory(description);
+      suite.pend();
+      addSpecsToSuite(suite, specDefinitions);
+      return suite;
+    };
+
+    var focusedRunnables = [];
+
+    this.fdescribe = function(description, specDefinitions) {
+      var suite = suiteFactory(description);
+      suite.isFocused = true;
+
+      focusedRunnables.push(suite.id);
+      unfocusAncestor();
+      addSpecsToSuite(suite, specDefinitions);
+
+      return suite;
+    };
+
+    function addSpecsToSuite(suite, specDefinitions) {
+      var parentSuite = currentDeclarationSuite;
       parentSuite.addChild(suite);
-      currentSuite = suite;
+      currentDeclarationSuite = suite;
 
       var declarationError = null;
       try {
@@ -616,31 +836,43 @@ getJasmineRequireObj().Env = function(j$) {
       }
 
       if (declarationError) {
-        this.it("encountered a declaration exception", function() {
+        self.it('encountered a declaration exception', function() {
           throw declarationError;
         });
       }
 
-      currentSuite = parentSuite;
+      currentDeclarationSuite = parentSuite;
+    }
 
-      return suite;
-    };
+    function findFocusedAncestor(suite) {
+      while (suite) {
+        if (suite.isFocused) {
+          return suite.id;
+        }
+        suite = suite.parentSuite;
+      }
 
-    this.xdescribe = function(description, specDefinitions) {
-      var suite = this.describe(description, specDefinitions);
-      suite.disable();
-      return suite;
-    };
+      return null;
+    }
 
-    var specFactory = function(description, fn, suite) {
+    function unfocusAncestor() {
+      var focusedAncestor = findFocusedAncestor(currentDeclarationSuite);
+      if (focusedAncestor) {
+        for (var i = 0; i < focusedRunnables.length; i++) {
+          if (focusedRunnables[i] === focusedAncestor) {
+            focusedRunnables.splice(i, 1);
+            break;
+          }
+        }
+      }
+    }
+
+    var specFactory = function(description, fn, suite, timeout) {
       totalSpecsDefined++;
-
       var spec = new j$.Spec({
         id: getNextSpecId(),
-        beforeFns: beforeFns(suite),
-        afterFns: afterFns(suite),
+        beforeAndAfterFns: beforeAndAfterFns(suite),
         expectationFactory: expectationFactory,
-        exceptionFormatter: exceptionFormatter,
         resultCallback: specResultCallback,
         getSpecName: function(spec) {
           return getSpecName(spec, suite);
@@ -649,8 +881,12 @@ getJasmineRequireObj().Env = function(j$) {
         description: description,
         expectationResultFactory: expectationResultFactory,
         queueRunnerFactory: queueRunnerFactory,
-        fn: fn,
-        timer: {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}
+        userContext: function() { return suite.clonedSharedUserContext(); },
+        queueableFn: {
+          fn: fn,
+          timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
+        },
+        throwOnExpectationFailure: throwOnExpectationFailure
       });
 
       runnableLookupTable[spec.id] = spec;
@@ -661,53 +897,101 @@ getJasmineRequireObj().Env = function(j$) {
 
       return spec;
 
-      function removeAllSpies() {
-        for (var i = 0; i < spies.length; i++) {
-          var spyEntry = spies[i];
-          spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
-        }
-        spies = [];
-      }
-
       function specResultCallback(result) {
-        removeAllSpies();
-        j$.Expectation.resetMatchers();
-        customEqualityTesters = [];
+        clearResourcesForRunnable(spec.id);
         currentSpec = null;
         reporter.specDone(result);
       }
+
+      function specStarted(spec) {
+        currentSpec = spec;
+        defaultResourcesForRunnable(spec.id, suite.id);
+        reporter.specStarted(spec.result);
+      }
     };
 
-    var suiteStarted = function(suite) {
-      reporter.suiteStarted(suite.result);
-    };
-
-    this.it = function(description, fn) {
-      var spec = specFactory(description, fn, currentSuite);
-      currentSuite.addChild(spec);
+    this.it = function(description, fn, timeout) {
+      var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
+      if (currentDeclarationSuite.markedPending) {
+        spec.pend();
+      }
+      currentDeclarationSuite.addChild(spec);
       return spec;
     };
 
-    this.xit = function(description, fn) {
-      var spec = this.it(description, fn);
-      spec.pend();
+    this.xit = function() {
+      var spec = this.it.apply(this, arguments);
+      spec.pend('Temporarily disabled with xit');
+      return spec;
+    };
+
+    this.fit = function(description, fn, timeout){
+      var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
+      currentDeclarationSuite.addChild(spec);
+      focusedRunnables.push(spec.id);
+      unfocusAncestor();
       return spec;
     };
 
     this.expect = function(actual) {
-      return currentSpec.expect(actual);
+      if (!currentRunnable()) {
+        throw new Error('\'expect\' was used when there was no current spec, this could be because an asynchronous test timed out');
+      }
+
+      return currentRunnable().expect(actual);
     };
 
-    this.beforeEach = function(beforeEachFunction) {
-      currentSuite.beforeEach(beforeEachFunction);
+    this.beforeEach = function(beforeEachFunction, timeout) {
+      currentDeclarationSuite.beforeEach({
+        fn: beforeEachFunction,
+        timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
+      });
     };
 
-    this.afterEach = function(afterEachFunction) {
-      currentSuite.afterEach(afterEachFunction);
+    this.beforeAll = function(beforeAllFunction, timeout) {
+      currentDeclarationSuite.beforeAll({
+        fn: beforeAllFunction,
+        timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
+      });
     };
 
-    this.pending = function() {
-      throw j$.Spec.pendingSpecExceptionMessage;
+    this.afterEach = function(afterEachFunction, timeout) {
+      currentDeclarationSuite.afterEach({
+        fn: afterEachFunction,
+        timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
+      });
+    };
+
+    this.afterAll = function(afterAllFunction, timeout) {
+      currentDeclarationSuite.afterAll({
+        fn: afterAllFunction,
+        timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
+      });
+    };
+
+    this.pending = function(message) {
+      var fullMessage = j$.Spec.pendingSpecExceptionMessage;
+      if(message) {
+        fullMessage += message;
+      }
+      throw fullMessage;
+    };
+
+    this.fail = function(error) {
+      var message = 'Failed';
+      if (error) {
+        message += ': ';
+        message += error.message || error;
+      }
+
+      currentRunnable().addExpectationResult(false, {
+        matcherName: '',
+        passed: false,
+        expected: '',
+        actual: '',
+        message: message,
+        error: error && error.message ? error : null
+      });
     };
   }
 
@@ -723,10 +1007,11 @@ getJasmineRequireObj().JsApiReporter = function() {
 
   function JsApiReporter(options) {
     var timer = options.timer || noopTimer,
-        status = "loaded";
+      status = 'loaded';
 
     this.started = false;
     this.finished = false;
+    this.runDetails = {};
 
     this.jasmineStarted = function() {
       this.started = true;
@@ -736,8 +1021,9 @@ getJasmineRequireObj().JsApiReporter = function() {
 
     var executionTime;
 
-    this.jasmineDone = function() {
+    this.jasmineDone = function(runDetails) {
       this.finished = true;
+      this.runDetails = runDetails;
       executionTime = timer.elapsed();
       status = 'done';
     };
@@ -746,26 +1032,31 @@ getJasmineRequireObj().JsApiReporter = function() {
       return status;
     };
 
-    var suites = {};
+    var suites = [],
+      suites_hash = {};
 
     this.suiteStarted = function(result) {
-      storeSuite(result);
+      suites_hash[result.id] = result;
     };
 
     this.suiteDone = function(result) {
       storeSuite(result);
     };
 
+    this.suiteResults = function(index, length) {
+      return suites.slice(index, index + length);
+    };
+
     function storeSuite(result) {
-      suites[result.id] = result;
+      suites.push(result);
+      suites_hash[result.id] = result;
     }
 
     this.suites = function() {
-      return suites;
+      return suites_hash;
     };
 
     var specs = [];
-    this.specStarted = function(result) { };
 
     this.specDone = function(result) {
       specs.push(result);
@@ -788,43 +1079,6 @@ getJasmineRequireObj().JsApiReporter = function() {
   return JsApiReporter;
 };
 
-getJasmineRequireObj().Any = function() {
-
-  function Any(expectedObject) {
-    this.expectedObject = expectedObject;
-  }
-
-  Any.prototype.jasmineMatches = function(other) {
-    if (this.expectedObject == String) {
-      return typeof other == 'string' || other instanceof String;
-    }
-
-    if (this.expectedObject == Number) {
-      return typeof other == 'number' || other instanceof Number;
-    }
-
-    if (this.expectedObject == Function) {
-      return typeof other == 'function' || other instanceof Function;
-    }
-
-    if (this.expectedObject == Object) {
-      return typeof other == 'object';
-    }
-    
-    if (this.expectedObject == Boolean) {
-      return typeof other == 'boolean';
-    }
-
-    return other instanceof this.expectedObject;
-  };
-
-  Any.prototype.jasmineToString = function() {
-    return '<jasmine.any(' + this.expectedClass + ')>';
-  };
-
-  return Any;
-};
-
 getJasmineRequireObj().CallTracker = function() {
 
   function CallTracker() {
@@ -877,7 +1131,7 @@ getJasmineRequireObj().CallTracker = function() {
 };
 
 getJasmineRequireObj().Clock = function() {
-  function Clock(global, delayedFunctionScheduler) {
+  function Clock(global, delayedFunctionSchedulerFactory, mockDate) {
     var self = this,
       realTimingFunctions = {
         setTimeout: global.setTimeout,
@@ -892,25 +1146,48 @@ getJasmineRequireObj().Clock = function() {
         clearInterval: clearInterval
       },
       installed = false,
+      delayedFunctionScheduler,
       timer;
 
+
     self.install = function() {
+      if(!originalTimingFunctionsIntact()) {
+        throw new Error('Jasmine Clock was unable to install over custom global timer functions. Is the clock already installed?');
+      }
       replace(global, fakeTimingFunctions);
       timer = fakeTimingFunctions;
+      delayedFunctionScheduler = delayedFunctionSchedulerFactory();
       installed = true;
+
+      return self;
     };
 
     self.uninstall = function() {
-      delayedFunctionScheduler.reset();
+      delayedFunctionScheduler = null;
+      mockDate.uninstall();
       replace(global, realTimingFunctions);
+
       timer = realTimingFunctions;
       installed = false;
     };
 
+    self.withMock = function(closure) {
+      this.install();
+      try {
+        closure();
+      } finally {
+        this.uninstall();
+      }
+    };
+
+    self.mockDate = function(initialDate) {
+      mockDate.install(initialDate);
+    };
+
     self.setTimeout = function(fn, delay, params) {
       if (legacyIE()) {
         if (arguments.length > 2) {
-          throw new Error("IE < 9 cannot support extra params to setTimeout without a polyfill");
+          throw new Error('IE < 9 cannot support extra params to setTimeout without a polyfill');
         }
         return timer.setTimeout(fn, delay);
       }
@@ -920,7 +1197,7 @@ getJasmineRequireObj().Clock = function() {
     self.setInterval = function(fn, delay, params) {
       if (legacyIE()) {
         if (arguments.length > 2) {
-          throw new Error("IE < 9 cannot support extra params to setInterval without a polyfill");
+          throw new Error('IE < 9 cannot support extra params to setInterval without a polyfill');
         }
         return timer.setInterval(fn, delay);
       }
@@ -937,14 +1214,21 @@ getJasmineRequireObj().Clock = function() {
 
     self.tick = function(millis) {
       if (installed) {
-        delayedFunctionScheduler.tick(millis);
+        delayedFunctionScheduler.tick(millis, function(millis) { mockDate.tick(millis); });
       } else {
-        throw new Error("Mock clock is not installed, use jasmine.clock().install()");
+        throw new Error('Mock clock is not installed, use jasmine.clock().install()');
       }
     };
 
     return self;
 
+    function originalTimingFunctionsIntact() {
+      return global.setTimeout === realTimingFunctions.setTimeout &&
+        global.clearTimeout === realTimingFunctions.clearTimeout &&
+        global.setInterval === realTimingFunctions.setInterval &&
+        global.clearInterval === realTimingFunctions.clearInterval;
+    }
+
     function legacyIE() {
       //if these methods are polyfilled, apply will be present
       return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply;
@@ -973,7 +1257,7 @@ getJasmineRequireObj().Clock = function() {
     }
 
     function argSlice(argsObj, n) {
-      return Array.prototype.slice.call(argsObj, 2);
+      return Array.prototype.slice.call(argsObj, n);
     }
   }
 
@@ -988,11 +1272,11 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
     var currentTime = 0;
     var delayedFnCount = 0;
 
-    self.tick = function(millis) {
+    self.tick = function(millis, tickDate) {
       millis = millis || 0;
       var endTime = currentTime + millis;
 
-      runScheduledFunctions(endTime);
+      runScheduledFunctions(endTime, tickDate);
       currentTime = endTime;
     };
 
@@ -1054,13 +1338,6 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
       }
     };
 
-    self.reset = function() {
-      currentTime = 0;
-      scheduledLookup = [];
-      scheduledFunctions = {};
-      delayedFnCount = 0;
-    };
-
     return self;
 
     function indexOfFirstToPass(array, testFn) {
@@ -1096,30 +1373,42 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
         scheduledFn.runAtMillis + scheduledFn.millis);
     }
 
-    function runScheduledFunctions(endTime) {
+    function forEachFunction(funcsToRun, callback) {
+      for (var i = 0; i < funcsToRun.length; ++i) {
+        callback(funcsToRun[i]);
+      }
+    }
+
+    function runScheduledFunctions(endTime, tickDate) {
+      tickDate = tickDate || function() {};
       if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) {
+        tickDate(endTime);
         return;
       }
 
       do {
-        currentTime = scheduledLookup.shift();
+        var newCurrentTime = scheduledLookup.shift();
+        tickDate(newCurrentTime - currentTime);
+
+        currentTime = newCurrentTime;
 
         var funcsToRun = scheduledFunctions[currentTime];
         delete scheduledFunctions[currentTime];
 
-        for (var i = 0; i < funcsToRun.length; ++i) {
-          var funcToRun = funcsToRun[i];
-          funcToRun.funcToCall.apply(null, funcToRun.params || []);
-
+        forEachFunction(funcsToRun, function(funcToRun) {
           if (funcToRun.recurring) {
             reschedule(funcToRun);
           }
-        }
+        });
+
+        forEachFunction(funcsToRun, function(funcToRun) {
+          funcToRun.funcToCall.apply(null, funcToRun.params || []);
+        });
       } while (scheduledLookup.length > 0 &&
-              // checking first if we're out of time prevents setTimeout(0)
-              // scheduled in a funcToRun from forcing an extra iteration
-                 currentTime !== endTime  &&
-                 scheduledLookup[0] <= endTime);
+        // checking first if we're out of time prevents setTimeout(0)
+        // scheduled in a funcToRun from forcing an extra iteration
+      currentTime !== endTime  &&
+      scheduledLookup[0] <= endTime);
     }
   }
 
@@ -1129,16 +1418,20 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
 getJasmineRequireObj().ExceptionFormatter = function() {
   function ExceptionFormatter() {
     this.message = function(error) {
-      var message = error.name +
-        ': ' +
-        error.message;
+      var message = '';
+
+      if (error.name && error.message) {
+        message += error.name + ': ' + error.message;
+      } else {
+        message += error.toString() + ' thrown';
+      }
 
       if (error.fileName || error.sourceURL) {
-        message += " in " + (error.fileName || error.sourceURL);
+        message += ' in ' + (error.fileName || error.sourceURL);
       }
 
       if (error.line || error.lineNumber) {
-        message += " (line " + (error.line || error.lineNumber) + ")";
+        message += ' (line ' + (error.line || error.lineNumber) + ')';
       }
 
       return message;
@@ -1154,8 +1447,6 @@ getJasmineRequireObj().ExceptionFormatter = function() {
 
 getJasmineRequireObj().Expectation = function() {
 
-  var matchers = {};
-
   function Expectation(options) {
     this.util = options.util || { buildFailureMessage: function() {} };
     this.customEqualityTesters = options.customEqualityTesters || [];
@@ -1163,8 +1454,9 @@ getJasmineRequireObj().Expectation = function() {
     this.addExpectationResult = options.addExpectationResult || function(){};
     this.isNot = options.isNot;
 
-    for (var matcherName in matchers) {
-      this[matcherName] = matchers[matcherName];
+    var customMatchers = options.customMatchers || {};
+    for (var matcherName in customMatchers) {
+      this[matcherName] = Expectation.prototype.wrapCompare(matcherName, customMatchers[matcherName]);
     }
   }
 
@@ -1172,12 +1464,12 @@ getJasmineRequireObj().Expectation = function() {
     return function() {
       var args = Array.prototype.slice.call(arguments, 0),
         expected = args.slice(0),
-        message = "";
+        message = '';
 
       args.unshift(this.actual);
 
       var matcher = matcherFactory(this.util, this.customEqualityTesters),
-          matcherCompare = matcher.compare;
+        matcherCompare = matcher.compare;
 
       function defaultNegativeCompare() {
         var result = matcher.compare.apply(null, args);
@@ -1197,7 +1489,11 @@ getJasmineRequireObj().Expectation = function() {
           args.unshift(name);
           message = this.util.buildFailureMessage.apply(null, args);
         } else {
-          message = result.message;
+          if (Object.prototype.toString.apply(result.message) === '[object Function]') {
+            message = result.message();
+          } else {
+            message = result.message;
+          }
         }
       }
 
@@ -1227,19 +1523,6 @@ getJasmineRequireObj().Expectation = function() {
     }
   };
 
-  Expectation.addMatchers = function(matchersToAdd) {
-    for (var name in matchersToAdd) {
-      var matcher = matchersToAdd[name];
-      matchers[name] = Expectation.prototype.wrapCompare(name, matcher);
-    }
-  };
-
-  Expectation.resetMatchers = function() {
-    for (var name in matchers) {
-      delete matchers[name];
-    }
-  };
-
   Expectation.Factory = function(options) {
     options = options || {};
 
@@ -1262,29 +1545,34 @@ getJasmineRequireObj().buildExpectationResult = function() {
     var messageFormatter = options.messageFormatter || function() {},
       stackFormatter = options.stackFormatter || function() {};
 
-    return {
+    var result = {
       matcherName: options.matcherName,
-      expected: options.expected,
-      actual: options.actual,
       message: message(),
       stack: stack(),
       passed: options.passed
     };
 
+    if(!result.passed) {
+      result.expected = options.expected;
+      result.actual = options.actual;
+    }
+
+    return result;
+
     function message() {
       if (options.passed) {
-        return "Passed.";
+        return 'Passed.';
       } else if (options.message) {
         return options.message;
       } else if (options.error) {
         return messageFormatter(options.error);
       }
-      return "";
+      return '';
     }
 
     function stack() {
       if (options.passed) {
-        return "";
+        return '';
       }
 
       var error = options.error;
@@ -1302,45 +1590,94 @@ getJasmineRequireObj().buildExpectationResult = function() {
   return buildExpectationResult;
 };
 
-getJasmineRequireObj().ObjectContaining = function(j$) {
+getJasmineRequireObj().MockDate = function() {
+  function MockDate(global) {
+    var self = this;
+    var currentTime = 0;
 
-  function ObjectContaining(sample) {
-    this.sample = sample;
-  }
+    if (!global || !global.Date) {
+      self.install = function() {};
+      self.tick = function() {};
+      self.uninstall = function() {};
+      return self;
+    }
 
-  ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
-    if (typeof(this.sample) !== "object") { throw new Error("You must provide an object to objectContaining, not '"+this.sample+"'."); }
+    var GlobalDate = global.Date;
 
-    mismatchKeys = mismatchKeys || [];
-    mismatchValues = mismatchValues || [];
+    self.install = function(mockDate) {
+      if (mockDate instanceof GlobalDate) {
+        currentTime = mockDate.getTime();
+      } else {
+        currentTime = new GlobalDate().getTime();
+      }
 
-    var hasKey = function(obj, keyName) {
-      return obj !== null && !j$.util.isUndefined(obj[keyName]);
+      global.Date = FakeDate;
     };
 
-    for (var property in this.sample) {
-      if (!hasKey(other, property) && hasKey(this.sample, property)) {
-        mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
-      }
-      else if (!j$.matchersUtil.equals(this.sample[property], other[property])) {
-        mismatchValues.push("'" + property + "' was '" + (other[property] ? j$.util.htmlEscape(other[property].toString()) : other[property]) + "' in actual, but was '" + (this.sample[property] ? j$.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in expected.");
+    self.tick = function(millis) {
+      millis = millis || 0;
+      currentTime = currentTime + millis;
+    };
+
+    self.uninstall = function() {
+      currentTime = 0;
+      global.Date = GlobalDate;
+    };
+
+    createDateProperties();
+
+    return self;
+
+    function FakeDate() {
+      switch(arguments.length) {
+        case 0:
+          return new GlobalDate(currentTime);
+        case 1:
+          return new GlobalDate(arguments[0]);
+        case 2:
+          return new GlobalDate(arguments[0], arguments[1]);
+        case 3:
+          return new GlobalDate(arguments[0], arguments[1], arguments[2]);
+        case 4:
+          return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3]);
+        case 5:
+          return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3],
+            arguments[4]);
+        case 6:
+          return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3],
+            arguments[4], arguments[5]);
+        default:
+          return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3],
+            arguments[4], arguments[5], arguments[6]);
       }
     }
 
-    return (mismatchKeys.length === 0 && mismatchValues.length === 0);
-  };
+    function createDateProperties() {
+      FakeDate.prototype = GlobalDate.prototype;
 
-  ObjectContaining.prototype.jasmineToString = function() {
-    return "<jasmine.objectContaining(" + j$.pp(this.sample) + ")>";
-  };
+      FakeDate.now = function() {
+        if (GlobalDate.now) {
+          return currentTime;
+        } else {
+          throw new Error('Browser does not support Date.now()');
+        }
+      };
 
-  return ObjectContaining;
+      FakeDate.toSource = GlobalDate.toSource;
+      FakeDate.toString = GlobalDate.toString;
+      FakeDate.parse = GlobalDate.parse;
+      FakeDate.UTC = GlobalDate.UTC;
+    }
+  }
+
+  return MockDate;
 };
 
 getJasmineRequireObj().pp = function(j$) {
 
   function PrettyPrinter() {
     this.ppNestLevel_ = 0;
+    this.seen = [];
   }
 
   PrettyPrinter.prototype.format = function(value) {
@@ -1350,6 +1687,8 @@ getJasmineRequireObj().pp = function(j$) {
         this.emitScalar('undefined');
       } else if (value === null) {
         this.emitScalar('null');
+      } else if (value === 0 && 1/value === -Infinity) {
+        this.emitScalar('-0');
       } else if (value === j$.getGlobal()) {
         this.emitScalar('<global>');
       } else if (value.jasmineToString) {
@@ -1357,7 +1696,7 @@ getJasmineRequireObj().pp = function(j$) {
       } else if (typeof value === 'string') {
         this.emitString(value);
       } else if (j$.isSpy(value)) {
-        this.emitScalar("spy on " + value.and.identity());
+        this.emitScalar('spy on ' + value.and.identity());
       } else if (value instanceof RegExp) {
         this.emitScalar(value.toString());
       } else if (typeof value === 'function') {
@@ -1366,16 +1705,18 @@ getJasmineRequireObj().pp = function(j$) {
         this.emitScalar('HTMLNode');
       } else if (value instanceof Date) {
         this.emitScalar('Date(' + value + ')');
-      } else if (value.__Jasmine_been_here_before__) {
+      } else if (value.toString && typeof value === 'object' && !(value instanceof Array) && value.toString !== Object.prototype.toString) {
+        this.emitScalar(value.toString());
+      } else if (j$.util.arrayContains(this.seen, value)) {
         this.emitScalar('<circular reference: ' + (j$.isArray_(value) ? 'Array' : 'Object') + '>');
       } else if (j$.isArray_(value) || j$.isA_('Object', value)) {
-        value.__Jasmine_been_here_before__ = true;
+        this.seen.push(value);
         if (j$.isArray_(value)) {
           this.emitArray(value);
         } else {
           this.emitObject(value);
         }
-        delete value.__Jasmine_been_here_before__;
+        this.seen.pop();
       } else {
         this.emitScalar(value.toString());
       }
@@ -1386,10 +1727,9 @@ getJasmineRequireObj().pp = function(j$) {
 
   PrettyPrinter.prototype.iterateObject = function(obj, fn) {
     for (var property in obj) {
-      if (!obj.hasOwnProperty(property)) { continue; }
-      if (property == '__Jasmine_been_here_before__') { continue; }
+      if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; }
       fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) &&
-          obj.__lookupGetter__(property) !== null) : false);
+      obj.__lookupGetter__(property) !== null) : false);
     }
   };
 
@@ -1411,33 +1751,55 @@ getJasmineRequireObj().pp = function(j$) {
   };
 
   StringPrettyPrinter.prototype.emitString = function(value) {
-    this.append("'" + value + "'");
+    this.append('\'' + value + '\'');
   };
 
   StringPrettyPrinter.prototype.emitArray = function(array) {
     if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
-      this.append("Array");
+      this.append('Array');
       return;
     }
-
+    var length = Math.min(array.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH);
     this.append('[ ');
-    for (var i = 0; i < array.length; i++) {
+    for (var i = 0; i < length; i++) {
       if (i > 0) {
         this.append(', ');
       }
       this.format(array[i]);
     }
+    if(array.length > length){
+      this.append(', ...');
+    }
+
+    var self = this;
+    var first = array.length === 0;
+    this.iterateObject(array, function(property, isGetter) {
+      if (property.match(/^\d+$/)) {
+        return;
+      }
+
+      if (first) {
+        first = false;
+      } else {
+        self.append(', ');
+      }
+
+      self.formatProperty(array, property, isGetter);
+    });
+
     this.append(' ]');
   };
 
   StringPrettyPrinter.prototype.emitObject = function(obj) {
+    var constructorName = obj.constructor ? j$.fnNameFor(obj.constructor) : 'null';
+    this.append(constructorName);
+
     if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
-      this.append("Object");
       return;
     }
 
     var self = this;
-    this.append('{ ');
+    this.append('({ ');
     var first = true;
 
     this.iterateObject(obj, function(property, isGetter) {
@@ -1447,16 +1809,20 @@ getJasmineRequireObj().pp = function(j$) {
         self.append(', ');
       }
 
-      self.append(property);
-      self.append(' : ');
-      if (isGetter) {
-        self.append('<getter>');
-      } else {
-        self.format(obj[property]);
-      }
+      self.formatProperty(obj, property, isGetter);
     });
 
-    this.append(' }');
+    this.append(' })');
+  };
+
+  StringPrettyPrinter.prototype.formatProperty = function(obj, property, isGetter) {
+    this.append(property);
+    this.append(': ');
+    if (isGetter) {
+      this.append('<getter>');
+    } else {
+      this.format(obj[property]);
+    }
   };
 
   StringPrettyPrinter.prototype.append = function(value) {
@@ -1470,32 +1836,46 @@ getJasmineRequireObj().pp = function(j$) {
   };
 };
 
-getJasmineRequireObj().QueueRunner = function() {
+getJasmineRequireObj().QueueRunner = function(j$) {
+
+  function once(fn) {
+    var called = false;
+    return function() {
+      if (!called) {
+        called = true;
+        fn();
+      }
+    };
+  }
 
   function QueueRunner(attrs) {
-    this.fns = attrs.fns || [];
+    this.queueableFns = attrs.queueableFns || [];
     this.onComplete = attrs.onComplete || function() {};
     this.clearStack = attrs.clearStack || function(fn) {fn();};
     this.onException = attrs.onException || function() {};
     this.catchException = attrs.catchException || function() { return true; };
-    this.userContext = {};
+    this.userContext = attrs.userContext || {};
+    this.timeout = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout};
+    this.fail = attrs.fail || function() {};
   }
 
   QueueRunner.prototype.execute = function() {
-    this.run(this.fns, 0);
+    this.run(this.queueableFns, 0);
   };
 
-  QueueRunner.prototype.run = function(fns, recursiveIndex) {
-    var length = fns.length,
-        self = this,
-        iterativeIndex;
+  QueueRunner.prototype.run = function(queueableFns, recursiveIndex) {
+    var length = queueableFns.length,
+      self = this,
+      iterativeIndex;
+
 
     for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
-      var fn = fns[iterativeIndex];
-      if (fn.length > 0) {
-        return attemptAsync(fn);
+      var queueableFn = queueableFns[iterativeIndex];
+      if (queueableFn.fn.length > 0) {
+        attemptAsync(queueableFn);
+        return;
       } else {
-        attemptSync(fn);
+        attemptSync(queueableFn);
       }
     }
 
@@ -1505,27 +1885,51 @@ getJasmineRequireObj().QueueRunner = function() {
       this.clearStack(this.onComplete);
     }
 
-    function attemptSync(fn) {
+    function attemptSync(queueableFn) {
       try {
-        fn.call(self.userContext);
+        queueableFn.fn.call(self.userContext);
       } catch (e) {
-        handleException(e);
+        handleException(e, queueableFn);
       }
     }
 
-    function attemptAsync(fn) {
-      var next = function () { self.run(fns, iterativeIndex + 1); };
+    function attemptAsync(queueableFn) {
+      var clearTimeout = function () {
+          Function.prototype.apply.apply(self.timeout.clearTimeout, [j$.getGlobal(), [timeoutId]]);
+        },
+        next = once(function () {
+          clearTimeout(timeoutId);
+          self.run(queueableFns, iterativeIndex + 1);
+        }),
+        timeoutId;
+
+      next.fail = function() {
+        self.fail.apply(null, arguments);
+        next();
+      };
+
+      if (queueableFn.timeout) {
+        timeoutId = Function.prototype.apply.apply(self.timeout.setTimeout, [j$.getGlobal(), [function() {
+          var error = new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.');
+          onException(error);
+          next();
+        }, queueableFn.timeout()]]);
+      }
 
       try {
-        fn.call(self.userContext, next);
+        queueableFn.fn.call(self.userContext, next);
       } catch (e) {
-        handleException(e);
+        handleException(e, queueableFn);
         next();
       }
     }
 
-    function handleException(e) {
+    function onException(e) {
       self.onException(e);
+    }
+
+    function handleException(e, queueableFn) {
+      onException(e);
       if (!self.catchException(e)) {
         //TODO: set a var when we catch an exception and
         //use a finally block to close the loop in a nice way..
@@ -1573,15 +1977,76 @@ getJasmineRequireObj().ReportDispatcher = function() {
 };
 
 
+getJasmineRequireObj().SpyRegistry = function(j$) {
+
+  function SpyRegistry(options) {
+    options = options || {};
+    var currentSpies = options.currentSpies || function() { return []; };
+
+    this.spyOn = function(obj, methodName) {
+      if (j$.util.isUndefined(obj)) {
+        throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()');
+      }
+
+      if (j$.util.isUndefined(methodName)) {
+        throw new Error('No method name supplied');
+      }
+
+      if (j$.util.isUndefined(obj[methodName])) {
+        throw new Error(methodName + '() method does not exist');
+      }
+
+      if (obj[methodName] && j$.isSpy(obj[methodName])) {
+        //TODO?: should this return the current spy? Downside: may cause user confusion about spy state
+        throw new Error(methodName + ' has already been spied upon');
+      }
+
+      var descriptor;
+      try {
+        descriptor = Object.getOwnPropertyDescriptor(obj, methodName);
+      } catch(e) {
+        // IE 8 doesn't support `definePropery` on non-DOM nodes
+      }
+
+      if (descriptor && !(descriptor.writable || descriptor.set)) {
+        throw new Error(methodName + ' is not declared writable or has no setter');
+      }
+
+      var spy = j$.createSpy(methodName, obj[methodName]);
+
+      currentSpies().push({
+        spy: spy,
+        baseObj: obj,
+        methodName: methodName,
+        originalValue: obj[methodName]
+      });
+
+      obj[methodName] = spy;
+
+      return spy;
+    };
+
+    this.clearSpies = function() {
+      var spies = currentSpies();
+      for (var i = 0; i < spies.length; i++) {
+        var spyEntry = spies[i];
+        spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
+      }
+    };
+  }
+
+  return SpyRegistry;
+};
+
 getJasmineRequireObj().SpyStrategy = function() {
 
   function SpyStrategy(options) {
     options = options || {};
 
-    var identity = options.name || "unknown",
-        originalFn = options.fn || function() {},
-        getSpy = options.getSpy || function() {},
-        plan = function() {};
+    var identity = options.name || 'unknown',
+      originalFn = options.fn || function() {},
+      getSpy = options.getSpy || function() {},
+      plan = function() {};
 
     this.identity = function() {
       return identity;
@@ -1603,6 +2068,14 @@ getJasmineRequireObj().SpyStrategy = function() {
       return getSpy();
     };
 
+    this.returnValues = function() {
+      var values = Array.prototype.slice.call(arguments);
+      plan = function () {
+        return values.shift();
+      };
+      return getSpy();
+    };
+
     this.throwError = function(something) {
       var error = (something instanceof Error) ? something : new Error(something);
       plan = function() {
@@ -1625,31 +2098,36 @@ getJasmineRequireObj().SpyStrategy = function() {
   return SpyStrategy;
 };
 
-getJasmineRequireObj().Suite = function() {
+getJasmineRequireObj().Suite = function(j$) {
   function Suite(attrs) {
     this.env = attrs.env;
     this.id = attrs.id;
     this.parentSuite = attrs.parentSuite;
     this.description = attrs.description;
-    this.onStart = attrs.onStart || function() {};
-    this.resultCallback = attrs.resultCallback || function() {};
-    this.clearStack = attrs.clearStack || function(fn) {fn();};
+    this.expectationFactory = attrs.expectationFactory;
+    this.expectationResultFactory = attrs.expectationResultFactory;
+    this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
 
     this.beforeFns = [];
     this.afterFns = [];
-    this.queueRunner = attrs.queueRunner || function() {};
+    this.beforeAllFns = [];
+    this.afterAllFns = [];
     this.disabled = false;
 
     this.children = [];
 
     this.result = {
       id: this.id,
-      status: this.disabled ? 'disabled' : '',
       description: this.description,
-      fullName: this.getFullName()
+      fullName: this.getFullName(),
+      failedExpectations: []
     };
   }
 
+  Suite.prototype.expect = function(actual) {
+    return this.expectationFactory(actual, this);
+  };
+
   Suite.prototype.getFullName = function() {
     var fullName = this.description;
     for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
@@ -1664,64 +2142,148 @@ getJasmineRequireObj().Suite = function() {
     this.disabled = true;
   };
 
+  Suite.prototype.pend = function(message) {
+    this.markedPending = true;
+  };
+
   Suite.prototype.beforeEach = function(fn) {
     this.beforeFns.unshift(fn);
   };
 
+  Suite.prototype.beforeAll = function(fn) {
+    this.beforeAllFns.push(fn);
+  };
+
   Suite.prototype.afterEach = function(fn) {
     this.afterFns.unshift(fn);
   };
 
+  Suite.prototype.afterAll = function(fn) {
+    this.afterAllFns.push(fn);
+  };
+
   Suite.prototype.addChild = function(child) {
     this.children.push(child);
   };
 
-  Suite.prototype.execute = function(onComplete) {
-    var self = this;
+  Suite.prototype.status = function() {
     if (this.disabled) {
-      complete();
+      return 'disabled';
+    }
+
+    if (this.markedPending) {
+      return 'pending';
+    }
+
+    if (this.result.failedExpectations.length > 0) {
+      return 'failed';
+    } else {
+      return 'finished';
+    }
+  };
+
+  Suite.prototype.isExecutable = function() {
+    return !this.disabled;
+  };
+
+  Suite.prototype.canBeReentered = function() {
+    return this.beforeAllFns.length === 0 && this.afterAllFns.length === 0;
+  };
+
+  Suite.prototype.getResult = function() {
+    this.result.status = this.status();
+    return this.result;
+  };
+
+  Suite.prototype.sharedUserContext = function() {
+    if (!this.sharedContext) {
+      this.sharedContext = this.parentSuite ? clone(this.parentSuite.sharedUserContext()) : {};
+    }
+
+    return this.sharedContext;
+  };
+
+  Suite.prototype.clonedSharedUserContext = function() {
+    return clone(this.sharedUserContext());
+  };
+
+  Suite.prototype.onException = function() {
+    if (arguments[0] instanceof j$.errors.ExpectationFailed) {
       return;
     }
 
-    var allFns = [];
-
-    for (var i = 0; i < this.children.length; i++) {
-      allFns.push(wrapChildAsAsync(this.children[i]));
+    if(isAfterAll(this.children)) {
+      var data = {
+        matcherName: '',
+        passed: false,
+        expected: '',
+        actual: '',
+        error: arguments[0]
+      };
+      this.result.failedExpectations.push(this.expectationResultFactory(data));
+    } else {
+      for (var i = 0; i < this.children.length; i++) {
+        var child = this.children[i];
+        child.onException.apply(child, arguments);
+      }
     }
+  };
 
-    this.onStart(this);
+  Suite.prototype.addExpectationResult = function () {
+    if(isAfterAll(this.children) && isFailure(arguments)){
+      var data = arguments[1];
+      this.result.failedExpectations.push(this.expectationResultFactory(data));
+      if(this.throwOnExpectationFailure) {
+        throw new j$.errors.ExpectationFailed();
+      }
+    } else {
+      for (var i = 0; i < this.children.length; i++) {
+        var child = this.children[i];
+        try {
+          child.addExpectationResult.apply(child, arguments);
+        } catch(e) {
+          // keep going
+        }
+      }
+    }
+  };
 
-    this.queueRunner({
-      fns: allFns,
-      onComplete: complete
-    });
+  function isAfterAll(children) {
+    return children && children[0].result.status;
+  }
 
-    function complete() {
-      self.resultCallback(self.result);
+  function isFailure(args) {
+    return !args[0];
+  }
 
-      if (onComplete) {
-        onComplete();
+  function clone(obj) {
+    var clonedObj = {};
+    for (var prop in obj) {
+      if (obj.hasOwnProperty(prop)) {
+        clonedObj[prop] = obj[prop];
       }
     }
 
-    function wrapChildAsAsync(child) {
-      return function(done) { child.execute(done); };
-    }
-  };
+    return clonedObj;
+  }
 
   return Suite;
 };
 
-if (typeof window == void 0 && typeof exports == "object") {
+if (typeof window == void 0 && typeof exports == 'object') {
   exports.Suite = jasmineRequire.Suite;
 }
 
 getJasmineRequireObj().Timer = function() {
+  var defaultNow = (function(Date) {
+    return function() { return new Date().getTime(); };
+  })(Date);
+
   function Timer(options) {
     options = options || {};
 
-    var now = options.now || function() { return new Date().getTime(); },
-        startTime;
+    var now = options.now || defaultNow,
+      startTime;
 
     this.start = function() {
       startTime = now();
@@ -1735,6 +2297,378 @@ getJasmineRequireObj().Timer = function() {
   return Timer;
 };
 
+getJasmineRequireObj().TreeProcessor = function() {
+  function TreeProcessor(attrs) {
+    var tree = attrs.tree,
+      runnableIds = attrs.runnableIds,
+      queueRunnerFactory = attrs.queueRunnerFactory,
+      nodeStart = attrs.nodeStart || function() {},
+      nodeComplete = attrs.nodeComplete || function() {},
+      orderChildren = attrs.orderChildren || function(node) { return node.children; },
+      stats = { valid: true },
+      processed = false,
+      defaultMin = Infinity,
+      defaultMax = 1 - Infinity;
+
+    this.processTree = function() {
+      processNode(tree, false);
+      processed = true;
+      return stats;
+    };
+
+    this.execute = function(done) {
+      if (!processed) {
+        this.processTree();
+      }
+
+      if (!stats.valid) {
+        throw 'invalid order';
+      }
+
+      var childFns = wrapChildren(tree, 0);
+
+      queueRunnerFactory({
+        queueableFns: childFns,
+        userContext: tree.sharedUserContext(),
+        onException: function() {
+          tree.onException.apply(tree, arguments);
+        },
+        onComplete: done
+      });
+    };
+
+    function runnableIndex(id) {
+      for (var i = 0; i < runnableIds.length; i++) {
+        if (runnableIds[i] === id) {
+          return i;
+        }
+      }
+    }
+
+    function processNode(node, parentEnabled) {
+      var executableIndex = runnableIndex(node.id);
+
+      if (executableIndex !== undefined) {
+        parentEnabled = true;
+      }
+
+      parentEnabled = parentEnabled && node.isExecutable();
+
+      if (!node.children) {
+        stats[node.id] = {
+          executable: parentEnabled && node.isExecutable(),
+          segments: [{
+            index: 0,
+            owner: node,
+            nodes: [node],
+            min: startingMin(executableIndex),
+            max: startingMax(executableIndex)
+          }]
+        };
+      } else {
+        var hasExecutableChild = false;
+
+        var orderedChildren = orderChildren(node);
+
+        for (var i = 0; i < orderedChildren.length; i++) {
+          var child = orderedChildren[i];
+
+          processNode(child, parentEnabled);
+
+          if (!stats.valid) {
+            return;
+          }
+
+          var childStats = stats[child.id];
+
+          hasExecutableChild = hasExecutableChild || childStats.executable;
+        }
+
+        stats[node.id] = {
+          executable: hasExecutableChild
+        };
+
+        segmentChildren(node, orderedChildren, stats[node.id], executableIndex);
+
+        if (!node.canBeReentered() && stats[node.id].segments.length > 1) {
+          stats = { valid: false };
+        }
+      }
+    }
+
+    function startingMin(executableIndex) {
+      return executableIndex === undefined ? defaultMin : executableIndex;
+    }
+
+    function startingMax(executableIndex) {
+      return executableIndex === undefined ? defaultMax : executableIndex;
+    }
+
+    function segmentChildren(node, orderedChildren, nodeStats, executableIndex) {
+      var currentSegment = { index: 0, owner: node, nodes: [], min: startingMin(executableIndex), max: startingMax(executableIndex) },
+        result = [currentSegment],
+        lastMax = defaultMax,
+        orderedChildSegments = orderChildSegments(orderedChildren);
+
+      function isSegmentBoundary(minIndex) {
+        return lastMax !== defaultMax && minIndex !== defaultMin && lastMax < minIndex - 1;
+      }
+
+      for (var i = 0; i < orderedChildSegments.length; i++) {
+        var childSegment = orderedChildSegments[i],
+          maxIndex = childSegment.max,
+          minIndex = childSegment.min;
+
+        if (isSegmentBoundary(minIndex)) {
+          currentSegment = {index: result.length, owner: node, nodes: [], min: defaultMin, max: defaultMax};
+          result.push(currentSegment);
+        }
+
+        currentSegment.nodes.push(childSegment);
+        currentSegment.min = Math.min(currentSegment.min, minIndex);
+        currentSegment.max = Math.max(currentSegment.max, maxIndex);
+        lastMax = maxIndex;
+      }
+
+      nodeStats.segments = result;
+    }
+
+    function orderChildSegments(children) {
+      var specifiedOrder = [],
+        unspecifiedOrder = [];
+
+      for (var i = 0; i < children.length; i++) {
+        var child = children[i],
+          segments = stats[child.id].segments;
+
+        for (var j = 0; j < segments.length; j++) {
+          var seg = segments[j];
+
+          if (seg.min === defaultMin) {
+            unspecifiedOrder.push(seg);
+          } else {
+            specifiedOrder.push(seg);
+          }
+        }
+      }
+
+      specifiedOrder.sort(function(a, b) {
+        return a.min - b.min;
+      });
+
+      return specifiedOrder.concat(unspecifiedOrder);
+    }
+
+    function executeNode(node, segmentNumber) {
+      if (node.children) {
+        return {
+          fn: function(done) {
+            nodeStart(node);
+
+            queueRunnerFactory({
+              onComplete: function() {
+                nodeComplete(node, node.getResult());
+                done();
+              },
+              queueableFns: wrapChildren(node, segmentNumber),
+              userContext: node.sharedUserContext(),
+              onException: function() {
+                node.onException.apply(node, arguments);
+              }
+            });
+          }
+        };
+      } else {
+        return {
+          fn: function(done) { node.execute(done, stats[node.id].executable); }
+        };
+      }
+    }
+
+    function wrapChildren(node, segmentNumber) {
+      var result = [],
+        segmentChildren = stats[node.id].segments[segmentNumber].nodes;
+
+      for (var i = 0; i < segmentChildren.length; i++) {
+        result.push(executeNode(segmentChildren[i].owner, segmentChildren[i].index));
+      }
+
+      if (!stats[node.id].executable) {
+        return result;
+      }
+
+      return node.beforeAllFns.concat(result).concat(node.afterAllFns);
+    }
+  }
+
+  return TreeProcessor;
+};
+
+getJasmineRequireObj().Any = function(j$) {
+
+  function Any(expectedObject) {
+    if (typeof expectedObject === 'undefined') {
+      throw new TypeError(
+        'jasmine.any() expects to be passed a constructor function. ' +
+        'Please pass one or use jasmine.anything() to match any object.'
+      );
+    }
+    this.expectedObject = expectedObject;
+  }
+
+  Any.prototype.asymmetricMatch = function(other) {
+    if (this.expectedObject == String) {
+      return typeof other == 'string' || other instanceof String;
+    }
+
+    if (this.expectedObject == Number) {
+      return typeof other == 'number' || other instanceof Number;
+    }
+
+    if (this.expectedObject == Function) {
+      return typeof other == 'function' || other instanceof Function;
+    }
+
+    if (this.expectedObject == Object) {
+      return typeof other == 'object';
+    }
+
+    if (this.expectedObject == Boolean) {
+      return typeof other == 'boolean';
+    }
+
+    return other instanceof this.expectedObject;
+  };
+
+  Any.prototype.jasmineToString = function() {
+    return '<jasmine.any(' + j$.fnNameFor(this.expectedObject) + ')>';
+  };
+
+  return Any;
+};
+
+getJasmineRequireObj().Anything = function(j$) {
+
+  function Anything() {}
+
+  Anything.prototype.asymmetricMatch = function(other) {
+    return !j$.util.isUndefined(other) && other !== null;
+  };
+
+  Anything.prototype.jasmineToString = function() {
+    return '<jasmine.anything>';
+  };
+
+  return Anything;
+};
+
+getJasmineRequireObj().ArrayContaining = function(j$) {
+  function ArrayContaining(sample) {
+    this.sample = sample;
+  }
+
+  ArrayContaining.prototype.asymmetricMatch = function(other) {
+    var className = Object.prototype.toString.call(this.sample);
+    if (className !== '[object Array]') { throw new Error('You must provide an array to arrayContaining, not \'' + this.sample + '\'.'); }
+
+    for (var i = 0; i < this.sample.length; i++) {
+      var item = this.sample[i];
+      if (!j$.matchersUtil.contains(other, item)) {
+        return false;
+      }
+    }
+
+    return true;
+  };
+
+  ArrayContaining.prototype.jasmineToString = function () {
+    return '<jasmine.arrayContaining(' + jasmine.pp(this.sample) +')>';
+  };
+
+  return ArrayContaining;
+};
+
+getJasmineRequireObj().ObjectContaining = function(j$) {
+
+  function ObjectContaining(sample) {
+    this.sample = sample;
+  }
+
+  function getPrototype(obj) {
+    if (Object.getPrototypeOf) {
+      return Object.getPrototypeOf(obj);
+    }
+
+    if (obj.constructor.prototype == obj) {
+      return null;
+    }
+
+    return obj.constructor.prototype;
+  }
+
+  function hasProperty(obj, property) {
+    if (!obj) {
+      return false;
+    }
+
+    if (Object.prototype.hasOwnProperty.call(obj, property)) {
+      return true;
+    }
+
+    return hasProperty(getPrototype(obj), property);
+  }
+
+  ObjectContaining.prototype.asymmetricMatch = function(other) {
+    if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); }
+
+    for (var property in this.sample) {
+      if (!hasProperty(other, property) ||
+        !j$.matchersUtil.equals(this.sample[property], other[property])) {
+        return false;
+      }
+    }
+
+    return true;
+  };
+
+  ObjectContaining.prototype.jasmineToString = function() {
+    return '<jasmine.objectContaining(' + j$.pp(this.sample) + ')>';
+  };
+
+  return ObjectContaining;
+};
+
+getJasmineRequireObj().StringMatching = function(j$) {
+
+  function StringMatching(expected) {
+    if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) {
+      throw new Error('Expected is not a String or a RegExp');
+    }
+
+    this.regexp = new RegExp(expected);
+  }
+
+  StringMatching.prototype.asymmetricMatch = function(other) {
+    return this.regexp.test(other);
+  };
+
+  StringMatching.prototype.jasmineToString = function() {
+    return '<jasmine.stringMatching(' + this.regexp + ')>';
+  };
+
+  return StringMatching;
+};
+
+getJasmineRequireObj().errors = function() {
+  function ExpectationFailed() {}
+
+  ExpectationFailed.prototype = new Error();
+  ExpectationFailed.prototype.constructor = ExpectationFailed;
+
+  return {
+    ExpectationFailed: ExpectationFailed
+  };
+};
 getJasmineRequireObj().matchersUtil = function(j$) {
   // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter?
 
@@ -1748,7 +2682,9 @@ getJasmineRequireObj().matchersUtil = function(j$) {
     contains: function(haystack, needle, customTesters) {
       customTesters = customTesters || [];
 
-      if (Object.prototype.toString.apply(haystack) === "[object Array]") {
+      if ((Object.prototype.toString.apply(haystack) === '[object Array]') ||
+        (!!haystack && !haystack.indexOf))
+      {
         for (var i = 0; i < haystack.length; i++) {
           if (eq(haystack[i], needle, [], [], customTesters)) {
             return true;
@@ -1756,7 +2692,8 @@ getJasmineRequireObj().matchersUtil = function(j$) {
         }
         return false;
       }
-      return haystack.indexOf(needle) >= 0;
+
+      return !!haystack && haystack.indexOf(needle) >= 0;
     },
 
     buildFailureMessage: function() {
@@ -1767,29 +2704,55 @@ getJasmineRequireObj().matchersUtil = function(j$) {
         expected = args.slice(3),
         englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
 
-      var message = "Expected " +
+      var message = 'Expected ' +
         j$.pp(actual) +
-        (isNot ? " not " : " ") +
+        (isNot ? ' not ' : ' ') +
         englishyPredicate;
 
       if (expected.length > 0) {
         for (var i = 0; i < expected.length; i++) {
           if (i > 0) {
-            message += ",";
+            message += ',';
           }
-          message += " " + j$.pp(expected[i]);
+          message += ' ' + j$.pp(expected[i]);
         }
       }
 
-      return message + ".";
+      return message + '.';
     }
   };
 
+  function isAsymmetric(obj) {
+    return obj && j$.isA_('Function', obj.asymmetricMatch);
+  }
+
+  function asymmetricMatch(a, b) {
+    var asymmetricA = isAsymmetric(a),
+      asymmetricB = isAsymmetric(b);
+
+    if (asymmetricA && asymmetricB) {
+      return undefined;
+    }
+
+    if (asymmetricA) {
+      return a.asymmetricMatch(b);
+    }
+
+    if (asymmetricB) {
+      return b.asymmetricMatch(a);
+    }
+  }
+
   // Equality function lovingly adapted from isEqual in
   //   [Underscore](http://underscorejs.org)
   function eq(a, b, aStack, bStack, customTesters) {
     var result = true;
 
+    var asymmetricResult = asymmetricMatch(a, b);
+    if (!j$.util.isUndefined(asymmetricResult)) {
+      return asymmetricResult;
+    }
+
     for (var i = 0; i < customTesters.length; i++) {
       var customTesterResult = customTesters[i](a, b);
       if (!j$.util.isUndefined(customTesterResult)) {
@@ -1797,27 +2760,6 @@ getJasmineRequireObj().matchersUtil = function(j$) {
       }
     }
 
-    if (a instanceof j$.Any) {
-      result = a.jasmineMatches(b);
-      if (result) {
-        return true;
-      }
-    }
-
-    if (b instanceof j$.Any) {
-      result = b.jasmineMatches(a);
-      if (result) {
-        return true;
-      }
-    }
-
-    if (b instanceof j$.ObjectContaining) {
-      result = b.jasmineMatches(a);
-      if (result) {
-        return true;
-      }
-    }
-
     if (a instanceof Error && b instanceof Error) {
       return a.message == b.message;
     }
@@ -1853,6 +2795,29 @@ getJasmineRequireObj().matchersUtil = function(j$) {
           a.ignoreCase == b.ignoreCase;
     }
     if (typeof a != 'object' || typeof b != 'object') { return false; }
+
+    var aIsDomNode = j$.isDomNode(a);
+    var bIsDomNode = j$.isDomNode(b);
+    if (aIsDomNode && bIsDomNode) {
+      // At first try to use DOM3 method isEqualNode
+      if (a.isEqualNode) {
+        return a.isEqualNode(b);
+      }
+      // IE8 doesn't support isEqualNode, try to use outerHTML && innerText
+      var aIsElement = a instanceof Element;
+      var bIsElement = b instanceof Element;
+      if (aIsElement && bIsElement) {
+        return a.outerHTML == b.outerHTML;
+      }
+      if (aIsElement || bIsElement) {
+        return false;
+      }
+      return a.innerText == b.innerText && a.textContent == b.textContent;
+    }
+    if (aIsDomNode || bIsDomNode) {
+      return false;
+    }
+
     // Assume equality for cyclic structures. The algorithm for detecting cyclic
     // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
     var length = aStack.length;
@@ -1866,23 +2831,20 @@ getJasmineRequireObj().matchersUtil = function(j$) {
     bStack.push(b);
     var size = 0;
     // Recursively compare objects and arrays.
-    if (className == '[object Array]') {
-      // Compare array lengths to determine if a deep comparison is necessary.
-      size = a.length;
-      result = size == b.length;
-      if (result) {
-        // Deep compare the contents, ignoring non-numeric properties.
-        while (size--) {
-          if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) { break; }
-        }
-      }
-    } else {
+    // Compare array lengths to determine if a deep comparison is necessary.
+    if (className == '[object Array]' && a.length !== b.length) {
+      result = false;
+    }
+
+    if (result) {
       // Objects with different constructors are not equivalent, but `Object`s
-      // from different frames are.
-      var aCtor = a.constructor, bCtor = b.constructor;
-      if (aCtor !== bCtor && !(isFunction(aCtor) && (aCtor instanceof aCtor) &&
-        isFunction(bCtor) && (bCtor instanceof bCtor))) {
-        return false;
+      // or `Array`s from different frames are.
+      if (className !== '[object Array]') {
+        var aCtor = a.constructor, bCtor = b.constructor;
+        if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor &&
+          isFunction(bCtor) && bCtor instanceof bCtor)) {
+          return false;
+        }
       }
       // Deep compare objects.
       for (var key in a) {
@@ -1908,7 +2870,7 @@ getJasmineRequireObj().matchersUtil = function(j$) {
     return result;
 
     function has(obj, key) {
-      return obj.hasOwnProperty(key);
+      return Object.prototype.hasOwnProperty.call(obj, key);
     }
 
     function isFunction(obj) {
@@ -2018,9 +2980,9 @@ getJasmineRequireObj().toBeNaN = function(j$) {
         };
 
         if (result.pass) {
-          result.message = "Expected actual not to be NaN.";
+          result.message = 'Expected actual not to be NaN.';
         } else {
-          result.message = "Expected " + j$.pp(actual) + " to be NaN.";
+          result.message = function() { return 'Expected ' + j$.pp(actual) + ' to be NaN.'; };
         }
 
         return result;
@@ -2132,8 +3094,8 @@ getJasmineRequireObj().toHaveBeenCalled = function(j$) {
         result.pass = actual.calls.any();
 
         result.message = result.pass ?
-          "Expected spy " + actual.and.identity() + " not to have been called." :
-          "Expected spy " + actual.and.identity() + " to have been called.";
+        'Expected spy ' + actual.and.identity() + ' not to have been called.' :
+        'Expected spy ' + actual.and.identity() + ' to have been called.';
 
         return result;
       }
@@ -2143,9 +3105,40 @@ getJasmineRequireObj().toHaveBeenCalled = function(j$) {
   return toHaveBeenCalled;
 };
 
+getJasmineRequireObj().toHaveBeenCalledTimes = function(j$) {
+
+  function toHaveBeenCalledTimes() {
+    return {
+      compare: function(actual, expected) {
+        if (!j$.isSpy(actual)) {
+          throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
+        }
+
+        var args = Array.prototype.slice.call(arguments, 0),
+          result = { pass: false };
+
+        if(!expected){
+          throw new Error('Expected times failed is required as an argument.');
+        }
+
+        actual = args[0];
+        var calls = actual.calls.count();
+        var timesMessage = expected === 1 ? 'once' : expected + ' times';
+        result.pass = calls === expected;
+        result.message = result.pass ?
+        'Expected spy ' + actual.and.identity() + ' not to have been called ' + timesMessage + '. It was called ' +  calls + ' times.' :
+        'Expected spy ' + actual.and.identity() + ' to have been called ' + timesMessage + '. It was called ' +  calls + ' times.';
+        return result;
+      }
+    };
+  }
+
+  return toHaveBeenCalledTimes;
+};
+
 getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
 
-  function toHaveBeenCalledWith(util) {
+  function toHaveBeenCalledWith(util, customEqualityTesters) {
     return {
       compare: function() {
         var args = Array.prototype.slice.call(arguments, 0),
@@ -2158,15 +3151,15 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
         }
 
         if (!actual.calls.any()) {
-          result.message = "Expected spy " + actual.and.identity() + " to have been called with " + j$.pp(expectedArgs) + " but it was never called.";
+          result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but it was never called.'; };
           return result;
         }
 
-        if (util.contains(actual.calls.allArgs(), expectedArgs)) {
+        if (util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) {
           result.pass = true;
-          result.message = "Expected spy " + actual.and.identity() + " not to have been called with " + j$.pp(expectedArgs) + " but it was.";
+          result.message = function() { return 'Expected spy ' + actual.and.identity() + ' not to have been called with ' + j$.pp(expectedArgs) + ' but it was.'; };
         } else {
-          result.message = "Expected spy " + actual.and.identity() + " to have been called with " + j$.pp(expectedArgs) + " but actual calls were " + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + ".";
+          result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but actual calls were ' + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + '.'; };
         }
 
         return result;
@@ -2177,11 +3170,15 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
   return toHaveBeenCalledWith;
 };
 
-getJasmineRequireObj().toMatch = function() {
+getJasmineRequireObj().toMatch = function(j$) {
 
   function toMatch() {
     return {
       compare: function(actual, expected) {
+        if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) {
+          throw new Error('Expected is not a String or a RegExp');
+        }
+
         var regexp = new RegExp(expected);
 
         return {
@@ -2203,8 +3200,8 @@ getJasmineRequireObj().toThrow = function(j$) {
           threw = false,
           thrown;
 
-        if (typeof actual != "function") {
-          throw new Error("Actual is not a Function");
+        if (typeof actual != 'function') {
+          throw new Error('Actual is not a Function');
         }
 
         try {
@@ -2215,22 +3212,22 @@ getJasmineRequireObj().toThrow = function(j$) {
         }
 
         if (!threw) {
-          result.message = "Expected function to throw an exception.";
+          result.message = 'Expected function to throw an exception.';
           return result;
         }
 
         if (arguments.length == 1) {
           result.pass = true;
-          result.message = "Expected function not to throw, but it threw " + j$.pp(thrown) + ".";
+          result.message = function() { return 'Expected function not to throw, but it threw ' + j$.pp(thrown) + '.'; };
 
           return result;
         }
 
         if (util.equals(thrown, expected)) {
           result.pass = true;
-          result.message = "Expected function not to throw " + j$.pp(expected) + ".";
+          result.message = function() { return 'Expected function not to throw ' + j$.pp(expected) + '.'; };
         } else {
-          result.message = "Expected function to throw " + j$.pp(expected) + ", but it threw " +  j$.pp(thrown) + ".";
+          result.message = function() { return 'Expected function to throw ' + j$.pp(expected) + ', but it threw ' +  j$.pp(thrown) + '.'; };
         }
 
         return result;
@@ -2242,22 +3239,19 @@ getJasmineRequireObj().toThrow = function(j$) {
 };
 
 getJasmineRequireObj().toThrowError = function(j$) {
-  function toThrowError (util) {
+  function toThrowError () {
     return {
       compare: function(actual) {
         var threw = false,
-          thrown,
-          errorType,
-          message,
-          regexp,
-          name,
-          constructorName;
+          pass = {pass: true},
+          fail = {pass: false},
+          thrown;
 
-        if (typeof actual != "function") {
-          throw new Error("Actual is not a Function");
+        if (typeof actual != 'function') {
+          throw new Error('Actual is not a Function');
         }
 
-        extractExpectedParams.apply(null, arguments);
+        var errorMatcher = getMatcher.apply(null, arguments);
 
         try {
           actual();
@@ -2267,136 +3261,198 @@ getJasmineRequireObj().toThrowError = function(j$) {
         }
 
         if (!threw) {
-          return fail("Expected function to throw an Error.");
+          fail.message = 'Expected function to throw an Error.';
+          return fail;
         }
 
         if (!(thrown instanceof Error)) {
-          return fail("Expected function to throw an Error, but it threw " + thrown + ".");
+          fail.message = function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; };
+          return fail;
         }
 
-        if (arguments.length == 1) {
-          return pass("Expected function not to throw an Error, but it threw " + fnNameFor(thrown) + ".");
+        if (errorMatcher.hasNoSpecifics()) {
+          pass.message = 'Expected function not to throw an Error, but it threw ' + j$.fnNameFor(thrown) + '.';
+          return pass;
         }
 
-        if (errorType) {
-          name = fnNameFor(errorType);
-          constructorName = fnNameFor(thrown.constructor);
-        }
-
-        if (errorType && message) {
-          if (thrown.constructor == errorType && util.equals(thrown.message, message)) {
-            return pass("Expected function not to throw " + name + " with message \"" + message + "\".");
-          } else {
-            return fail("Expected function to throw " + name + " with message \"" + message +
-                        "\", but it threw " + constructorName + " with message \"" + thrown.message + "\".");
-          }
-        }
-
-        if (errorType && regexp) {
-          if (thrown.constructor == errorType && regexp.test(thrown.message)) {
-            return pass("Expected function not to throw " + name + " with message matching " + regexp + ".");
-          } else {
-            return fail("Expected function to throw " + name + " with message matching " + regexp +
-                        ", but it threw " + constructorName + " with message \"" + thrown.message + "\".");
-          }
-        }
-
-        if (errorType) {
-          if (thrown.constructor == errorType) {
-            return pass("Expected function not to throw " + name + ".");
-          } else {
-            return fail("Expected function to throw " + name + ", but it threw " + constructorName + ".");
-          }
-        }
-
-        if (message) {
-          if (thrown.message == message) {
-            return pass("Expected function not to throw an exception with message " + j$.pp(message) + ".");
-          } else {
-            return fail("Expected function to throw an exception with message " + j$.pp(message) +
-                        ", but it threw an exception with message " + j$.pp(thrown.message) + ".");
-          }
-        }
-
-        if (regexp) {
-          if (regexp.test(thrown.message)) {
-            return pass("Expected function not to throw an exception with a message matching " + j$.pp(regexp) + ".");
-          } else {
-            return fail("Expected function to throw an exception with a message matching " + j$.pp(regexp) +
-                        ", but it threw an exception with message " + j$.pp(thrown.message) + ".");
-          }
-        }
-
-        function fnNameFor(func) {
-            return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1];
-        }
-
-        function pass(notMessage) {
-          return {
-            pass: true,
-            message: notMessage
+        if (errorMatcher.matches(thrown)) {
+          pass.message = function() {
+            return 'Expected function not to throw ' + errorMatcher.errorTypeDescription + errorMatcher.messageDescription() + '.';
           };
-        }
-
-        function fail(message) {
-          return {
-            pass: false,
-            message: message
+          return pass;
+        } else {
+          fail.message = function() {
+            return 'Expected function to throw ' + errorMatcher.errorTypeDescription + errorMatcher.messageDescription() +
+              ', but it threw ' + errorMatcher.thrownDescription(thrown) + '.';
           };
-        }
-
-        function extractExpectedParams() {
-          if (arguments.length == 1) {
-            return;
-          }
-
-          if (arguments.length == 2) {
-            var expected = arguments[1];
-
-            if (expected instanceof RegExp) {
-              regexp = expected;
-            } else if (typeof expected == "string") {
-              message = expected;
-            } else if (checkForAnErrorType(expected)) {
-              errorType = expected;
-            }
-
-            if (!(errorType || message || regexp)) {
-              throw new Error("Expected is not an Error, string, or RegExp.");
-            }
-          } else {
-            if (checkForAnErrorType(arguments[1])) {
-              errorType = arguments[1];
-            } else {
-              throw new Error("Expected error type is not an Error.");
-            }
-
-            if (arguments[2] instanceof RegExp) {
-              regexp = arguments[2];
-            } else if (typeof arguments[2] == "string") {
-              message = arguments[2];
-            } else {
-              throw new Error("Expected error message is not a string or RegExp.");
-            }
-          }
-        }
-
-        function checkForAnErrorType(type) {
-          if (typeof type !== "function") {
-            return false;
-          }
-
-          var Surrogate = function() {};
-          Surrogate.prototype = type.prototype;
-          return (new Surrogate()) instanceof Error;
+          return fail;
         }
       }
     };
+
+    function getMatcher() {
+      var expected = null,
+        errorType = null;
+
+      if (arguments.length == 2) {
+        expected = arguments[1];
+        if (isAnErrorType(expected)) {
+          errorType = expected;
+          expected = null;
+        }
+      } else if (arguments.length > 2) {
+        errorType = arguments[1];
+        expected = arguments[2];
+        if (!isAnErrorType(errorType)) {
+          throw new Error('Expected error type is not an Error.');
+        }
+      }
+
+      if (expected && !isStringOrRegExp(expected)) {
+        if (errorType) {
+          throw new Error('Expected error message is not a string or RegExp.');
+        } else {
+          throw new Error('Expected is not an Error, string, or RegExp.');
+        }
+      }
+
+      function messageMatch(message) {
+        if (typeof expected == 'string') {
+          return expected == message;
+        } else {
+          return expected.test(message);
+        }
+      }
+
+      return {
+        errorTypeDescription: errorType ? j$.fnNameFor(errorType) : 'an exception',
+        thrownDescription: function(thrown) {
+          var thrownName = errorType ? j$.fnNameFor(thrown.constructor) : 'an exception',
+            thrownMessage = '';
+
+          if (expected) {
+            thrownMessage = ' with message ' + j$.pp(thrown.message);
+          }
+
+          return thrownName + thrownMessage;
+        },
+        messageDescription: function() {
+          if (expected === null) {
+            return '';
+          } else if (expected instanceof RegExp) {
+            return ' with a message matching ' + j$.pp(expected);
+          } else {
+            return ' with message ' + j$.pp(expected);
+          }
+        },
+        hasNoSpecifics: function() {
+          return expected === null && errorType === null;
+        },
+        matches: function(error) {
+          return (errorType === null || error instanceof errorType) &&
+            (expected === null || messageMatch(error.message));
+        }
+      };
+    }
+
+    function isStringOrRegExp(potential) {
+      return potential instanceof RegExp || (typeof potential == 'string');
+    }
+
+    function isAnErrorType(type) {
+      if (typeof type !== 'function') {
+        return false;
+      }
+
+      var Surrogate = function() {};
+      Surrogate.prototype = type.prototype;
+      return (new Surrogate()) instanceof Error;
+    }
   }
 
   return toThrowError;
 };
 
-getJasmineRequireObj().version = function() {
-  return "2.0.0";
+getJasmineRequireObj().interface = function(jasmine, env) {
+  var jasmineInterface = {
+    describe: function(description, specDefinitions) {
+      return env.describe(description, specDefinitions);
+    },
+
+    xdescribe: function(description, specDefinitions) {
+      return env.xdescribe(description, specDefinitions);
+    },
+
+    fdescribe: function(description, specDefinitions) {
+      return env.fdescribe(description, specDefinitions);
+    },
+
+    it: function() {
+      return env.it.apply(env, arguments);
+    },
+
+    xit: function() {
+      return env.xit.apply(env, arguments);
+    },
+
+    fit: function() {
+      return env.fit.apply(env, arguments);
+    },
+
+    beforeEach: function() {
+      return env.beforeEach.apply(env, arguments);
+    },
+
+    afterEach: function() {
+      return env.afterEach.apply(env, arguments);
+    },
+
+    beforeAll: function() {
+      return env.beforeAll.apply(env, arguments);
+    },
+
+    afterAll: function() {
+      return env.afterAll.apply(env, arguments);
+    },
+
+    expect: function(actual) {
+      return env.expect(actual);
+    },
+
+    pending: function() {
+      return env.pending.apply(env, arguments);
+    },
+
+    fail: function() {
+      return env.fail.apply(env, arguments);
+    },
+
+    spyOn: function(obj, methodName) {
+      return env.spyOn(obj, methodName);
+    },
+
+    jsApiReporter: new jasmine.JsApiReporter({
+      timer: new jasmine.Timer()
+    }),
+
+    jasmine: jasmine
+  };
+
+  jasmine.addCustomEqualityTester = function(tester) {
+    env.addCustomEqualityTester(tester);
+  };
+
+  jasmine.addMatchers = function(matchers) {
+    return env.addMatchers(matchers);
+  };
+
+  jasmine.clock = function() {
+    return env.clock;
+  };
+
+  return jasmineInterface;
 };
+
+getJasmineRequireObj().version = function() {
+  return '2.4.1';
+};
\ No newline at end of file