diff --git a/app/assets/images/common/button-background-success-active-border.png b/app/assets/images/common/button-background-success-active-border.png
new file mode 100644
index 000000000..b64df9e49
Binary files /dev/null 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
new file mode 100644
index 000000000..bb6850e8b
Binary files /dev/null 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
new file mode 100644
index 000000000..cf1dfc217
Binary files /dev/null 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
new file mode 100644
index 000000000..0e02036c2
Binary files /dev/null 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
new file mode 100644
index 000000000..c12979058
Binary files /dev/null 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
new file mode 100644
index 000000000..41c23a01f
Binary files /dev/null and b/app/assets/images/common/button-background-success-pressed.png differ
diff --git a/app/assets/images/pages/play/level/modal/achievement_plate.png b/app/assets/images/pages/play/level/modal/achievement_plate.png
deleted file mode 100644
index 1ab5a60b3..000000000
Binary files a/app/assets/images/pages/play/level/modal/achievement_plate.png and /dev/null 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
new file mode 100644
index 000000000..068af4688
Binary files /dev/null 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 11f8ad8f1..7ed30bcb4 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_blue_banner.png b/app/assets/images/pages/play/level/modal/victory_modal_blue_banner.png
deleted file mode 100644
index 0c87583bf..000000000
Binary files a/app/assets/images/pages/play/level/modal/victory_modal_blue_banner.png and /dev/null 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
new file mode 100644
index 000000000..00657032c
Binary files /dev/null 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
new file mode 100644
index 000000000..bd8586443
Binary files /dev/null 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 60563a588..0ead423a1 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
new file mode 100644
index 000000000..917db106f
Binary files /dev/null and b/app/assets/images/pages/play/level/modal/xp_gems_parchment.png differ
diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index e88f1503a..aac19b3e9 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -222,6 +222,7 @@
     reload_title: "Reload All Code?"
     reload_really: "Are you sure you want to reload this level back to the beginning?"
     reload_confirm: "Reload All"
+    victory: "Victory"
     victory_title_prefix: ""
     victory_title_suffix: " Complete"
     victory_sign_up: "Sign Up to Save Progress"
@@ -234,6 +235,8 @@
     victory_review: "Tell us more!"  # Only in old-style levels.
     victory_hour_of_code_done: "Are You Done?"
     victory_hour_of_code_done_yes: "Yes, I'm finished with my Hour of Codeā„¢!"
+    victory_experience_gained: "XP Gained"
+    victory_gems_gained: "Gems Gained"
     guide_title: "Guide"
     tome_minion_spells: "Your Minions' Spells"  # Only in old-style levels.
     tome_read_only_spells: "Read-Only Spells"  # Only in old-style levels.
diff --git a/app/styles/common/common.sass b/app/styles/common/common.sass
index b54695b29..0cb17cf71 100644
--- a/app/styles/common/common.sass
+++ b/app/styles/common/common.sass
@@ -253,13 +253,19 @@ kbd
     border-image-source: url(/images/common/button-background-primary-active-border.png)
   &.btn-success
     border-image-source: url(/images/common/button-background-success-active-border.png)
+    color: darken(white, 5%)
   &.btn-warning
     border-image-source: url(/images/common/button-background-warning-active-border.png)
+    color: darken(white, 5%)
   &.btn-danger
     border-image-source: url(/images/common/button-background-danger-active-border.png)
 
   &:hover
     color: lighten(rgb(248, 197, 146), 5%)
+    &.btn-success
+      color: white
+    &.btn-warning
+      color: white
 
   &:active
     &.btn-lg
diff --git a/app/styles/play/level/modal/hero-victory-modal.sass b/app/styles/play/level/modal/hero-victory-modal.sass
index 468bef75e..6344b42cb 100644
--- a/app/styles/play/level/modal/hero-victory-modal.sass
+++ b/app/styles/play/level/modal/hero-victory-modal.sass
@@ -2,55 +2,89 @@
 @import "app/styles/bootstrap/variables"
 
 #hero-victory-modal
+  $hero-yellow-text: rgb(252, 201, 53)
+
   //- Top-level modal container
   .modal-dialog
-    margin-top: 15px
+    margin-top: 0
     padding-top: 0
+    width: 750px
+
+    .modal-content
+      position: relative
+      margin-top: -251px
+
+  &.full-achievements
+    @media only screen and (max-height: 720px)
+      .modal-dialog
+        margin-top: -76px
+        #victory-header
+          background: transparent
+    @media only screen and (max-height: 640px)
+      .modal-dialog
+        margin-top: -130px
+        #victory-header
+          display: none
   
   //- Header
   
   .background-wrapper
     //background: url("/images/pages/play/level/modal/victory_modal_background.png")
-    width: 550px
-    background-color: transparent
+    width: 750px
+    background: transparent
     border: 0px solid transparent
-    border-width: 25px
-    border-image: url("/images/pages/play/level/modal/victory_modal_background.png") 25 fill round
+    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
 
-  #victory-banner
-    position: absolute
-    left: -30px
-    z-index: 0
-
-  #victory-header
-    position: absolute
-    left: 135px
-    display: block
-    margin: 10px auto 0
-    // http://easings.net/#easeOutBack plus tweaked a bit: http://cubic-bezier.com/#.18,.68,.75,2
-    @include transition(0.5s cubic-bezier(0.18, 0.68, 0.75, 2))
-    z-index: 1
-
-    &.out
-      @include scale(0)
-    
   .modal-header
-    height: 85px
     border: none
+    position: absolute
+    left: 188px
+    width: 378px
+    height: 134px
+    margin: 0
+    padding: 0
+
+    #victory-header
+      position: relative
+      // http://easings.net/#easeOutBack plus tweaked a bit: http://cubic-bezier.com/#.18,.68,.75,2
+      @include transition(0.5s cubic-bezier(0.18, 0.68, 0.75, 2))
+      z-index: 1
+      width: 100%
+      height: 100%
+      text-align: center
+      background: transparent url(/images/pages/play/level/modal/victory_hero.png/) no-repeat
+      background-position: center -88px
   
+      &.out
+        @include scale(0)
+    
+      #victory-title
+        display: inline-block
+        margin-top: 74px
+
+        h1
+          text-transform: uppercase
+          text-align: center
+          color: $hero-yellow-text
+          font-size: 80px
+          margin: 0
+          padding: 0
+          text-shadow: black 8px 8px 0, black -8px -8px 0, black 8px -8px 0, black -8px 8px 0, black 8px 0px 0, black 0px -8px 0, black -8px 0px 0, black 0px 8px 0
     
   //- Achievement panels
   
   .modal-body
     padding: 0 20px
     min-height: 30px
+    margin-top: 160px
   
   .achievement-panel
-    background: url("/images/pages/play/level/modal/achievement_plate.png")
-    width: 451px
-    height: 144px
-    margin: 5px auto
+    background: transparent url("/images/pages/play/level/modal/victory_modal_shelf.png") no-repeat center 73px
+    width: 824px
+    height: 127px
+    margin: 0px -37px 0px -57px
     position: relative
 
     @include transition-duration(1s)
@@ -71,12 +105,16 @@
 
   .achievement-description
     @include opacity(0.75)
+    z-index: 1
     position: absolute
     text-align: center
     left: 95px
     right: 98px
-    top: 10px
-    color: white
+    top: 86px
+    color: $hero-yellow-text
+    font-weight: bold
+    text-transform: uppercase
+    font-family: 'Open Sans Condensed'
     white-space: nowrap
     overflow: hidden
     text-overflow: ellipsis
@@ -85,8 +123,7 @@
     position: absolute
     left: 25px
     right: 23px
-    top: 41px
-    bottom: 18px
+    top: 0
     @include flexbox()
     @include flex-justify-center()
     
@@ -102,7 +139,7 @@
     z-index: 1
     @include transition(0.25s ease)
 
-    &.hero, &.item
+    &.hero, &.item, &.xp, &.gems
       background: url("/images/pages/play/level/modal/reward_plate_wide.png")
       width: 120px
       height: 83px
@@ -185,28 +222,112 @@
   .gems .pulse
     @include animation(rewardPulse 0.25s infinite)
     
-  //- Footer
-  
-  .modal-footer
-    padding-bottom: 0
-    
-  p.sign-up-poke
-    color: white
 
-    .sign-up-button
-      float: right
-      margin: 2px 10px
+  //- Footer - totals
 
   #totals
-    color: white
+    width: 709px
+    height: 96px
+    background: transparent url(/images/pages/play/level/modal/xp_gems_parchment.png)
+    position: relative
+    text-align: left
+
+    .total-wrapper
+      position: absolute
+      top: 18px
+
+      &#xp-wrapper
+        left: 117px
+        width: 300px
+
+      &#gem-wrapper
+        left: 529px
+
+        .total-label
+          width: 90px
+
+      .total-count
+        float: left
+        font-size: 45px
+        font-weight: bold
+        color: rgb(40, 33, 22)
+        margin-right: 12px
+
+      .total-label
+        float: left
+        color: rgb(103, 92, 76)
+        text-transform: uppercase
+        font-weight: bold
+        font-family: 'Open Sans Condensed'
+        font-size: 18px
+        margin-top: 13px
+        line-height: 18px
+
+      .xp-bar-outer
+        background-color: rgb(40, 33, 22)
+        border: 4px solid rgb(40, 33, 22)
+        border-radius: 8px
+        width: 150px
+        height: 16px
+        margin-top: 3px
+        position: relative
+        float: left
+      
+        .xp-bar-already-achieved
+          background-color: rgb(166, 213, 88)
+          //background-color: white
+          border-radius: 8px
+          height: 100%
+          position: absolute
+          z-index: 1
+      
+        .xp-bar-total
+          background-color: rgb(253, 171, 45)
+          border: 1px solid rgb(239, 177, 73)
+          border-radius: 8px
+          height: 100%
+          position: absolute
+
+
+  //- Footer - other stuff
+  
+  .modal-footer
+    // Negative bottom margin counteracts most of the extra the border image height.
+    margin: 0 0 -80px 0
+    padding: 0 20px
+    text-align: center
+    
+  .sign-up-poke
+    width: 430px
+
+    .sign-up-blurb
+      width: 175px
+      font-family: 'Open Sans Condensed'
+      font-weight: bold
+      text-transform: uppercase
+      font-size: 18px
+      line-height: 18px
+      text-align: left
+      float: left
+      margin: 5px 0 0 5px
+      color: rgb(160, 150, 126)
+
+    .sign-up-button
+      width: 250px
+      height: 60px
+      line-height: 30px
+      margin: 0
+      float: left
+    
 
   .next-level-buttons
     float: right
 
-    .next-level-button
-      display: block
-      margin: 8px 10px
-      width: 150px
+    .next-level-button, .return-to-ladder-button
+      width: 258px
+      height: 60px
+      line-height: 30px
+      margin: 0 10px
 
     .ladder-submission-view
       display: inline-block
@@ -223,7 +344,11 @@
 
   .hour-of-code-done
     clear: both
-    padding-top: 10px
+    margin: 5px auto 0 auto
+    padding: 10px
+    background-color: rgba(22, 34, 30, 0.5)
+    border-radius: 8px
+    display: inline-block
 
     strong
       color: white
@@ -241,23 +366,25 @@
 
 html.no-borderimage
   #hero-victory-modal
+    .modal-dialog
+      margin-top: 251px
     .background-wrapper
       border: 0
       background: url("/images/pages/play/level/modal/victory_modal_background.png")
-      height: 650px
-    #victory-header
-      margin-top: 40px
-      left: 160px
-    #victory-banner
-      left: 0px
-      top: 40px
-    .modal-header
-      height: 110px
-    .modal-content
-      height: 650px
-      padding-bottom: 0
-    .modal-footer
-      bottom: 20px
+      height: 713px
+
+    &.full-achievements
+      @media only screen and (max-height: 720px)
+        .modal-dialog
+          margin-top: 175px
+          #victory-header
+            background: transparent
+      @media only screen and (max-height: 640px)
+        .modal-dialog
+          margin-top: 121px
+          #victory-header
+            display: none
+
 
 body.ipad
   #hero-victory-modal
diff --git a/app/templates/play/level/modal/hero-victory-modal.jade b/app/templates/play/level/modal/hero-victory-modal.jade
index 0537a7aee..986d5ecb4 100644
--- a/app/templates/play/level/modal/hero-victory-modal.jade
+++ b/app/templates/play/level/modal/hero-victory-modal.jade
@@ -1,7 +1,11 @@
 extends /templates/core/modal-base
 block modal-header-content
-  img(src="/images/pages/play/level/modal/victory_modal_blue_banner.png")#victory-banner
-  img(src="/images/pages/play/level/modal/victory_word.png")#victory-header.out
+  #victory-header.out
+    #victory-title
+      if me.get('preferredLanguage').split('-')[0] == 'en'
+        img(src="/images/pages/play/level/modal/victory_word.png", draggable="false")
+      else
+        h1(data-i18n="play_level.victory") Victory
 
 block modal-body-content
   
@@ -43,33 +47,41 @@ block modal-body-content
               .reward-text= animate ? 'New Item' : item.get('name')
 
 block modal-footer-content
+  #totals
+    .total-wrapper#xp-wrapper
+      .total-count#xp-total 0
+      .total-label
+        span.spr(data-i18n="play_level.victory_experience_gained") XP Gained
+        | -
+        span.spl.spr(data-i18n="general.player_level") Level
+        span.level= me.level()
+      .xp-bar-outer
+        .xp-bar-already-achieved
+        .xp-bar-total
+    .total-wrapper#gem-wrapper
+      .total-count#gem-total 0
+      .total-label(data-i18n="play_level.victory_gems_gained") Gems Gained
+
   if me.get('anonymous')
-    p.sign-up-poke.hide
-      button.btn.btn-success.sign-up-button.btn-large(data-toggle="coco-modal", data-target="core/AuthModal", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress
-      span(data-i18n="play_level.victory_sign_up_poke") Want to save your code? Create a free account!
+    .sign-up-poke.hide
+      .sign-up-blurb(data-i18n="play_level.victory_sign_up_poke") Want to save your code? Create a free account!
+      button.btn.btn-illustrated.btn-warning.sign-up-button.btn-lg(data-toggle="coco-modal", data-target="core/AuthModal", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress
 
-  div#totals.pull-left
-    span.spr Experience Gained:
-    span#xp-total +0
-    br
-    span.spr Gems Gained:
-    span#gem-total +0
-
-  button.btn.btn-warning.hide#saving-progress-label(disabled, data-i18n="play_level.victory_saving_progress") Saving Progress
+  button.btn.btn-illustrated.btn-lg.btn-warning.hide#saving-progress-label(disabled, data-i18n="play_level.victory_saving_progress") Saving Progress
 
   .next-level-buttons
     if readyToRank
       .ladder-submission-view
     else if level.get('type') === 'hero-ladder'
-      button.btn.btn-primary.return-to-ladder-button(data-href="/play/ladder/#{level.get('slug')}#my-matches", data-dismiss="modal", data-i18n="play_level.victory_return_to_ladder") Return to Ladder
+      button.btn.btn-illustrated.btn-primary.btn-lg.return-to-ladder-button(data-href="/play/ladder/#{level.get('slug')}#my-matches", data-dismiss="modal", data-i18n="play_level.victory_return_to_ladder") Return to Ladder
     else
-      button.btn.btn-success.world-map-button.next-level-button.hide#continue-button(data-i18n="play_level.victory_play_continue") Continue
+      button.btn.btn-illustrated.btn-success.btn-lg.world-map-button.next-level-button.hide#continue-button(data-i18n="play_level.victory_play_continue") Continue
 
   if showHourOfCodeDoneButton
     .hour-of-code-done
-      hr
       a.image-link(href="http://code.org/api/hour/finish")
         img(src="/images/level/csedweek-logo-final-small.jpg", alt="CS Ed Week Hour of Code", title="I'm finished with my Hour of Code", width=80)
       strong(data-i18n="play_level.victory_hour_of_code_done") Are You Done?
       a.text-link(href="http://code.org/api/hour/finish")
         span(data-i18n="play_level.victory_hour_of_code_done_yes") Yes, I'm finished with my Hour of Code!
+      .clearfix
\ No newline at end of file
diff --git a/app/views/play/level/modal/HeroVictoryModal.coffee b/app/views/play/level/modal/HeroVictoryModal.coffee
index 7f4ac26a3..d316a96ea 100644
--- a/app/views/play/level/modal/HeroVictoryModal.coffee
+++ b/app/views/play/level/modal/HeroVictoryModal.coffee
@@ -9,6 +9,8 @@ ThangType = require 'models/ThangType'
 LadderSubmissionView = require 'views/play/common/LadderSubmissionView'
 AudioPlayer = require 'lib/AudioPlayer'
 CampaignOptions = require 'lib/CampaignOptions'
+User = require 'models/User'
+utils = require 'core/utils'
 
 module.exports = class HeroVictoryModal extends ModalView
   id: 'hero-victory-modal'
@@ -36,6 +38,8 @@ module.exports = class HeroVictoryModal extends ModalView
     @listenToOnce @achievements, 'sync', @onAchievementsLoaded
     @readyToContinue = false
     @waitingToContinueSince = new Date()
+    @previousXP = me.get 'points', true
+    @previousLevel = me.level()
     Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'victory'
 
   destroy: ->
@@ -47,6 +51,7 @@ module.exports = class HeroVictoryModal extends ModalView
     super()
 
   onAchievementsLoaded: ->
+    @$el.toggleClass 'full-achievements', @achievements.models.length is 3
     thangTypeOriginals = []
     achievementIDs = []
     for achievement in @achievements.models
@@ -133,6 +138,7 @@ module.exports = class HeroVictoryModal extends ModalView
     return unless @supermodel.finished()
     @playSelectionSound hero, true for original, hero of @thangTypes  # Preload them
     @updateSavingProgressStatus()
+    @updateXPBars 0
     @$el.find('#victory-header').delay(250).queue(->
       $(@).removeClass('out').dequeue()
       Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'victory-title-appear'  # TODO: actually add this
@@ -196,7 +202,8 @@ module.exports = class HeroVictoryModal extends ModalView
       totalXP = @totalXPAnimated + newXP
       if totalXP isnt @lastTotalXP
         panel.textEl.text('+' + newXP)
-        @XPEl.text('+' + totalXP)
+        @XPEl.text(totalXP)
+        @updateXPBars(totalXP)
         xpTrigger = 'xp-' + (totalXP % 6)  # 6 xp sounds
         Backbone.Mediator.publish 'audio-player:play-sound', trigger: xpTrigger, volume: 0.5 + ratio / 2
         @lastTotalXP = totalXP
@@ -205,7 +212,7 @@ module.exports = class HeroVictoryModal extends ModalView
       totalGems = @totalGemsAnimated + newGems
       if totalGems isnt @lastTotalGems
         panel.textEl.text('+' + newGems)
-        @gemEl.text('+' + totalGems)
+        @gemEl.text(totalGems)
         gemTrigger = 'gem-' + (parseInt(panel.number * ratio) % 4)  # 4 gem sounds
         Backbone.Mediator.publish 'audio-player:play-sound', trigger: gemTrigger, volume: 0.5 + ratio / 2
         @lastTotalGems = totalGems
@@ -237,6 +244,32 @@ module.exports = class HeroVictoryModal extends ModalView
     --t
     -0.5 * (t * (t - 2) - 1)
 
+  updateXPBars: (achievedXP) ->
+    previousXP = @previousXP
+    previousLevel = @previousLevel
+
+    currentXP = previousXP + achievedXP
+    currentLevel = User.levelFromExp currentXP
+    currentLevelXP = User.expForLevel currentLevel
+
+    nextLevel = currentLevel + 1
+    nextLevelXP = User.expForLevel nextLevel
+
+    leveledUp = currentLevel > previousLevel
+    totalXPNeeded = nextLevelXP - currentLevelXP
+    alreadyAchievedPercentage = 100 * (previousXP - currentLevelXP) / totalXPNeeded
+    alreadyAchievedPercentage = 0 if alreadyAchievedPercentage < 0  # In case of level up
+    if leveledUp
+      newlyAchievedPercentage = 100 * (currentXP - currentLevelXP) / totalXPNeeded
+    else
+      newlyAchievedPercentage = 100 * achievedXP / totalXPNeeded
+
+    xpEl = $('#xp-wrapper')
+    xpBarJustEarned = xpEl.find('.xp-bar-already-achieved').css('width', alreadyAchievedPercentage + '%')
+    xpBarTotal = xpEl.find('.xp-bar-total').css('width', (alreadyAchievedPercentage + newlyAchievedPercentage) + '%')
+    levelLabel = xpEl.find('.level')
+    utils.replaceText levelLabel, currentLevel
+
   endSequentialAnimations: ->
     clearInterval @sequentialAnimationInterval
     @animationComplete = true
diff --git a/app/views/play/menu/InventoryModal.coffee b/app/views/play/menu/InventoryModal.coffee
index a6ba6e20a..f83edf1a4 100644
--- a/app/views/play/menu/InventoryModal.coffee
+++ b/app/views/play/menu/InventoryModal.coffee
@@ -446,7 +446,7 @@ module.exports = class InventoryModal extends ModalView
     patchSession = patchMe = false
     patchSession ||= not _.isEqual inventory, sessionHeroConfig.inventory
     sessionHeroConfig.inventory = inventory
-    if hero = @selectedHero.get('original')
+    if hero = @selectedHero?.get('original')
       patchSession ||= not _.isEqual hero, sessionHeroConfig.thangType
       sessionHeroConfig.thangType = hero
     patchMe ||= not _.isEqual inventory, lastHeroConfig.inventory
@@ -527,8 +527,8 @@ module.exports = class InventoryModal extends ModalView
   onClickedSomewhere: (e) ->
     return if @destroyed
     @$el.find('.unlock-button').popover 'destroy'
-    
-    
+
+
   #- Dynamic portrait loading
 
   onScrollUnequipped: ->