diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index 66416dc08..afcffb0f8 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -301,10 +301,13 @@
     choose_inventory: "Equip Items"
     equipped_item: "Equipped"
     available_item: "Available"
+    restricted_title: "Restricted"
     should_equip: "(double-click to equip)"
     equipped: "(equipped)"
     locked: "(locked)"
     restricted: "(restricted in this level)"
+    equip: "Equip"
+    unequip: "Unequip"
 
   choose_hero:
     choose_hero: "Choose Your Hero"
diff --git a/app/styles/game-menu/inventory-modal.sass b/app/styles/game-menu/inventory-modal.sass
index e3d022a80..be8bd00cd 100644
--- a/app/styles/game-menu/inventory-modal.sass
+++ b/app/styles/game-menu/inventory-modal.sass
@@ -1,18 +1,8 @@
 @import "app/styles/mixins"
 
-$totalWidth: 706px - 2 * 20px
-$inventoryHeight: 445px
-$equippedWidth: 450px
-$itemSlotMargin: 5px
-$itemSlotSize: ($equippedWidth - 6 * 2 * $itemSlotMargin) / 6
-$itemSlotSizeWithMargin: $itemSlotSize + 2 * $itemSlotMargin
-$itemSlotBorderWidth: 2px
-$itemSlotInnerWidth: $itemSlotSize - 2 * $itemSlotBorderWidth
-$heroContainerWidth: 4 * $itemSlotSizeWithMargin
-$heroContainerHeight: $inventoryHeight - $itemSlotSizeWithMargin
-$selectedAreaHeight: 150px
-$stashMargin: 20px
-$stashWidth: $totalWidth - $equippedWidth - $stashMargin
+$itemSlotSize: 55px
+$itemSlotInnerWidth: $itemSlotSize - 4
+$itemSlotGridHeight: 70px
 
 .ui-effects-transfer
   outline: 2px solid #28f
@@ -20,318 +10,434 @@ $stashWidth: $totalWidth - $equippedWidth - $stashMargin
   z-index: 9001
 
 #inventory-modal
+  
+  //- Overall modal structure
   .modal-dialog
     margin: 30px auto 0 auto
-    width: 720px
+    width: 1017px
+    height: 660px
+    
+  .modal-content
+    height: 100%
+    width: 100%
 
-    .modal-body
-      height: 450px
-      margin: 0
-
-  +user-select(none)
-  
-  h3
+  .modal-body
+    height: 450px
     margin: 0
 
-  .draggable-item
-    width: $itemSlotSize
-    height: $itemSlotSize
+  +user-select(none)
+
   
+  //- Background
+
+  #play-items-modal-narrow-bg
+    position: absolute
+    top: -69px
+    left: -8px
+
+
+  //- Gems count
+
+  #gems-count-container
+    position: absolute
+    left: 213px
+    top: 10px
+    width: 160px
+    height: 66px
+    @include rotate(5deg)
+
+    #gems-count
+      position: absolute
+      left: 75px
+      top: 17px
+      font-size: 25px
+      color: rgb(1,64,91)
+
+
+  //- Close modal button
+
+  #close-modal
+    position: absolute
+    left: 390px
+    top: 23px
+    width: 60px
+    height: 60px
+    color: white
+    text-align: center
+    font-size: 30px
+    padding-top: 7px
+    cursor: pointer
+    @include rotate(-3deg)
+
+    &:hover
+      color: yellow
+
+
+  //- Equipped area
+
   #equipped
-    width: $equippedWidth
+    width: 330px
+    background: white
+    border: 3px solid black
     position: absolute
     left: 20px
-    top: 0
-    bottom: 0
-    //bottom: $selectedAreaHeight + 10
-    right: 0
+    top: 112px
+    height: 450px
     overflow: hidden
 
-    .item-slot-row
-      //background-color: rgba(35, 112, 124, 0.5)
-      height: $itemSlotSizeWithMargin
-      clear: both
-      margin: 0px auto
+    #hero-image
+      @include filter(contrast(0%) brightness(0%))
+      opacity: 0.4
+      width: 225px
+      height: 410px
+      position: absolute
+      left: 10px
+      top: 20px
 
-      &.row-4
-        width: 4 * $itemSlotSizeWithMargin
-
-    .item-slot-column
-      //background-color: rgba(112, 124, 35, 0.5)
-      width: $itemSlotSizeWithMargin
-      height: 5 * $itemSlotSizeWithMargin
-      float: left
-      //margin-top: 30px
-      
     .item-slot
       width: $itemSlotSize
       height: $itemSlotSize
-      margin: $itemSlotMargin
-      background-color: white
-      float: left
+      margin: 5px
+      background-color: rgba(255,255,255,0.4)
+      border: 2px dashed rgb(100,100,150)
       position: relative
       cursor: pointer
       @include transition(0.5s ease)
-      
-      &.selected
-        .placeholder, .item-container .item-view img
-          border-color: #28f
-          @include box-shadow(0 0 10px #28f)
 
+      //&.disabled
+      //  opacity: 0.5
+
+      &.selected
+        .placeholder, img.item
+          border-color: rgb(81,153,236)
+          background-color: rgb(81,153,236)
+          @include box-shadow(0 0 10px rgb(81,153,236))
+        img.item
+          background: rgb(81,153,236)
+  
       &.should-equip
         background-color: #8fa
         outline: 2px solid #8af
         @include box-shadow(2px 2px 4px black)
-
+  
       &.droppable
         outline: 2px solid blue
         @include box-shadow(4px 4px 6px black)
-
+  
       &.droppable-hover
         outline: 4px solid blue
         @include box-shadow(6px 6px 8px black)
-
+  
       .placeholder
         width: 100%
         height: 100%
         background-size: cover
-        border: $itemSlotBorderWidth solid #888
-        @include opacity(0.4)
+        @include opacity(0.7)
         background-image: url(/images/pages/game-menu/slot-icons.png)
+  
 
-      &[data-slot="misc-1"] .placeholder
-        background-position: (-0 * $itemSlotInnerWidth) 0px
+      // A terrible awful bit of styling, but will be gone or messed around with soon anyway
 
-      &[data-slot="minion"] .placeholder
-        background-position: (-1 * $itemSlotInnerWidth) 0px
+      &[data-slot="misc-1"]
+        display: none // hiding for now
+        position: absolute
+        left: 250px
+        top: 20px + ($itemSlotGridHeight * 3)
+        .placeholder
+          background-position: (-0 * $itemSlotInnerWidth) 0px
+  
+      &[data-slot="misc-0"]
+        display: none // hiding for now
+        position: absolute
+        left: 250px
+        top: 20px + ($itemSlotGridHeight * 2)
+        .placeholder
+          background-position: (-4 * $itemSlotInnerWidth) 0px
 
-      &[data-slot="programming-book"] .placeholder
-        background-position: (-3 * $itemSlotInnerWidth) 0px
 
+      &[data-slot="minion"]
+        position: absolute
+        left: 250px
+        top: 20px + ($itemSlotGridHeight * 1)
+        .placeholder
+          background-position: (-1 * $itemSlotInnerWidth) 0px
+  
+      &[data-slot="programming-book"]
+        position: absolute
+        left: 250px
+        top: 20px + ($itemSlotGridHeight * 4)
+        .placeholder
+          background-position: (-3 * $itemSlotInnerWidth) 0px
+  
       // Only for wizards...
       //&[data-slot="spellbook"] .placeholder
       //  background-position: (-2 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="misc-0"] .placeholder
-        background-position: (-4 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="wrists"] .placeholder
-        background-position: (-5 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="left-ring"] .placeholder
-        background-position: (-6 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="right-ring"] .placeholder
-        background-position: (-7 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="torso"] .placeholder
-        background-position: (-8 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="feet"] .placeholder
-        background-position: (-9 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="neck"] .placeholder
-        background-position: (-10 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="waist"] .placeholder
-        background-position: (-11 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="eyes"] .placeholder
-        background-position: (-12 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="head"] .placeholder
-        background-position: (-13 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="pet"] .placeholder
-        background-position: (-14 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="gloves"] .placeholder
-        background-position: (-15 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="left-hand"] .placeholder
-        background-position: (-16 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="right-hand"] .placeholder
-        background-position: (-17 * $itemSlotInnerWidth) 0px
-
-      &[data-slot="flag"] .placeholder
-        //background-position: (-18 * $itemSlotInnerWidth) 0px
-        background-position: (-2 * $itemSlotInnerWidth) 0px
-
-      .item-container
+  
+      &[data-slot="wrists"]
         position: absolute
-        left: 0
-        top: 0
+        left: 20px
+        top: 20px + ($itemSlotGridHeight * 2.5)
+        .placeholder
+          background-position: (-5 * $itemSlotInnerWidth) 0px
+  
+      &[data-slot="left-ring"]
+        position: absolute
+        left: 250px
+        top: 20px + ($itemSlotGridHeight * 2)
+        .placeholder
+          background-position: (-6 * $itemSlotInnerWidth) 0px
+  
+      &[data-slot="right-ring"]
+        position: absolute
+        left: 250px
+        top: 20px + ($itemSlotGridHeight * 3)
+        .placeholder
+          background-position: (-7 * $itemSlotInnerWidth) 0px
+  
+      &[data-slot="torso"]
+        position: absolute
+        left: 90px
+        top: 20px + ($itemSlotGridHeight * 3)
+        .placeholder
+          background-position: (-8 * $itemSlotInnerWidth) 0px
+  
+      &[data-slot="feet"]
+        position: absolute
+        left: 90px
+        top: 20px + ($itemSlotGridHeight * 5)
+        .placeholder
+          background-position: (-9 * $itemSlotInnerWidth) 0px
+  
+      &[data-slot="neck"]
+        position: absolute
+        left: 90px
+        top: 20px + ($itemSlotGridHeight * 2)
+        .placeholder
+          background-position: (-10 * $itemSlotInnerWidth) 0px
+  
+      &[data-slot="waist"]
+        position: absolute
+        left: 90px
+        top: 20px + ($itemSlotGridHeight * 4)
+        .placeholder
+          background-position: (-11 * $itemSlotInnerWidth) 0px
+  
+      &[data-slot="eyes"]
+        position: absolute
+        left: 90px
+        top: 20px + $itemSlotGridHeight
+        .placeholder
+          background-position: (-12 * $itemSlotInnerWidth) 0px
+  
+      &[data-slot="head"]
+        position: absolute
+        left: 90px
+        top: 20px
+        .placeholder
+          background-position: (-13 * $itemSlotInnerWidth) 0px
+        
+      &[data-slot="pet"]
+        position: absolute
+        left: 250px
+        top: 20px
+        .placeholder
+          background-position: (-14 * $itemSlotInnerWidth) 0px
+  
+      &[data-slot="gloves"]
+        position: absolute
+        left: 160px
+        top: 20px + ($itemSlotGridHeight * 2.5)
+        .placeholder
+          background-position: (-15 * $itemSlotInnerWidth) 0px
+  
+      &[data-slot="left-hand"]
+        position: absolute
+        left: 160px
+        top: 20px + ($itemSlotGridHeight * 3.5)
+        .placeholder
+          background-position: (-16 * $itemSlotInnerWidth) 0px
+  
+      &[data-slot="right-hand"]
+        position: absolute
+        left: 20px
+        top: 20px + ($itemSlotGridHeight * 3.5)
+        .placeholder
+          background-position: (-17 * $itemSlotInnerWidth) 0px
+  
+      &[data-slot="flag"]
+        position: absolute
+        left: 250px
+        top: 20px + ($itemSlotGridHeight * 5)
+        .placeholder
+          background-position: (-2 * $itemSlotInnerWidth) 0px
+  
+      img.item
+        position: absolute
+        left: -2px
+        top: -2px
 
-        .item-view
-          img
-            width: $itemSlotSize
-            height: $itemSlotSize
-            border: 2px solid black
-            background-color: white
+        width: $itemSlotSize
+        height: $itemSlotSize
+        border: 2px solid black
+        background-color: white
 
-          .item-info
-            display: none
+      
+  //- dragging styling 
+      
+  #equipped
     
-    .item-slot.disabled
-      opacity: 0.5
+    &.droppable
+      outline: 2px solid blue
+      @include box-shadow(4px 4px 6px black)
 
-    .hero-container
-      //background-color: rgba(31, 0, 200, 0.25)
-      float: left
-      position: relative
-      @include transition(0.5s ease)
+    &.droppable-hover
+      outline: 4px solid blue
+      @include box-shadow(6px 6px 8px black)
+    
+  .draggable-item
+    width: $itemSlotSize * 1.2
+    height: $itemSlotSize * 1.2
 
-      &.droppable
-        outline: 2px solid blue
-        @include box-shadow(4px 4px 6px black)
-
-      &.droppable-hover
-        outline: 4px solid blue
-        @include box-shadow(6px 6px 8px black)
-
-      .equipped-hero-canvas, .hero-feature-image
-        width: $heroContainerWidth
-        height: $heroContainerHeight
-
-      .hero-feature-image
-        text-align: center
-
-        img
-          height: $heroContainerHeight
-
-  #available-equipment
-    width: $stashWidth
-    position: absolute
-    right: 20px
-    top: 0 
-    bottom: 0
-    overflow-y: scroll
-    border: 2px solid #ccc
-    padding: 4px
-    background-color: white
-
-  &.Warrior .list-group-item:not(.Warrior), &.Ranger .list-group-item:not(.Ranger), &.Wizard .list-group-item:not(.Wizard)
+    
+  //- Available equipment
+   
+  &.Warrior #unequipped img.item:not(.Warrior), &.Ranger #unequipped img.item:not(.Ranger), &.Wizard #unequipped img.item:not(.Wizard)
     // Our code hides and shows (modifies display), but we can be invisible this other way.
     visibility: hidden
     position: absolute
 
-  .list-group-item
-    padding: 4px 0
-    @include transition(0.5s ease)
-
-    &.active
-      background-color: #e0f0f5
-
-      .status-message .should-equip-message
-        display: inline
-    
-    &.should-equip
-      background-color: #8fa
-      outline: 2px solid #8af
-      @include box-shadow(4px 4px 6px black)
-      z-index: 1
-
-      .status-message .should-equip-message
-        display: inline
-        font-weight: bold
-      
-    &.equipped
-      background-color: #ff5
-
-      .item-view
-        cursor: default
-
-      .status-message .equipped-message
-        display: inline
-
-    &.restricted
-      background-color: rgba(255, 80, 67, 0.25)
-
-      .item-view
-        cursor: default
-
-      .status-message .restricted-message
-        display: inline
-
-    &.locked
-      background-image: url(/images/pages/game-menu/lock.png)
-      background-size: 25px 25px
-      background-repeat: no-repeat
-      background-position: 98% 90%
-
-      .item-view
-        cursor: default
-  
-        h4, img
-          //@include filter(contrast(50%) brightness(65%))
-          @include opacity(0.6)
-  
-        .status-message .locked-message
-          display: inline
-
-      &.silhouette
-        h4
-          visibility: hidden
-          position: absolute
-        h4:before
-          content: '???'
-          visibility: visible
-        .item-view .status-message .locked-message
-          display: none
-        img
-          @include filter(contrast(25%) brightness(25%))
-
-  .item-view
-    cursor: pointer
-    
-  #selected-items
-    $selectedItemsContainerMargin: 20px
-    $selectedItemMargin: 10px
-    $selectedItemImageSize: 75px
-
+  #unequipped
+    width: 222px
     position: absolute
-    top: $selectedItemsContainerMargin
-    right: $selectedItemsContainerMargin
-    bottom: $selectedItemsContainerMargin
-    left: $selectedItemsContainerMargin
-    text-align: center
+    left: 370px
+    top: 112px
+    height: 450px
+    border: 3px solid black
+    padding: 9px 0 9px 9px
+    background-color: white
 
-    #selected-equipped-item, #selected-available-item
-      text-align: left
-      overflow-y: scroll
-      margin: 0
-      height: 48.4%
-      height: -webkit-calc(50% - $selectedItemMargin / 2)
-      height: calc(50% - $selectedItemMargin / 2)
-      width: 100%
-      padding: 10px 5px 10px 10px
-      position: relative
-      display: none
+    #double-click-hint
+      margin: 20px 0 70px
+    
+    h4
+      clear: both
+      margin-bottom: 10px
+      margin-top: 20px
+      font-size: 24px
+      text-transform: uppercase
+      font-weight: bold
+ 
+    img.item
+      float: left
+      border: 1px solid black
+      margin: 3px
+      padding: 1px
+      width: 60px
+      height: 60px
+      cursor: pointer
+
+      &.active
+        background-color: rgb(81,153,236)
+    
+        //.status-message .should-equip-message
+        //  display: inline
       
-      img
-        margin-top: 21px
-        width: $selectedItemImageSize
-        height: $selectedItemImageSize
-        margin-right: 10px
+      &.should-equip
+        background-color: #8fa
+        outline: 2px solid #8af
+        @include box-shadow(4px 4px 6px black)
+        z-index: 1
+    
+        //.status-message .should-equip-message
+        //  display: inline
+        //  font-weight: bold
         
-      .item-info
-        width: 110px
-        width: -webkit-calc(100% - 75px - 10px)
-        width: calc(100% - 75px - 10px)
+      &.equipped
+        background-color: #ff5
+        display: none
+        cursor: default
+    
+        //.item-view
+        //  cursor: default
+        //
+        //.status-message .equipped-message
+        //  display: inline
+    
+      &.restricted
+        background-color: rgba(255, 80, 67, 0.25)
+        cursor: default
+    
+        //.item-view
+        //  cursor: default
+        //
+        //.status-message .restricted-message
+        //  display: inline
+    
+      &.locked
+        cursor: default
+        //background-color: gray
+        
+      &.silhouette
+        cursor: default
+        pointer-events: none
+        @include filter(contrast(25%) brightness(25%))
+        opacity: 0.5
+      
+    
+  //- Hero/Play buttons
 
-      > h3
-        position: absolute
-        left: 0px
-        top: 0px
-        padding: 5px
+  #choose-hero-button, #play-level-button
+    top: 572px
+    position: absolute
+    background: url(/images/pages/play/modal/confirm-button.png)
+    width: 209px
+    height: 65px
+    background-size: 209px 65px
+    border: 0
 
-    #selected-equipped-item
-      margin-bottom: $selectedItemMargin
-      padding-bottom: 20px
-      background-color: #ff5
+    &:disabled
+      opacity: 1
+      @include filter(grayscale(100%))
+    
+    
+  #choose-hero-button
+    left: 20px
+    
+  #play-level-button
+    right: 414px
 
-    #selected-available-item
-      padding-top: 15px
-      background-color: #e0f0f5
-      bottom: 0
+      
+  //- Item details. Non-specific item-details-view styling is in item-details-view.sass.
+
+  #item-details-view
+
+    #item-title
+      left: 698px
+      top: 56px
+  
+    #item-details-body
+      left: 650px
+  
+    #selected-item-unlock-button
+      left: 646px
+
+
+  //- Equip/unequip/extra
+
+  #item-details-extra
+    position: absolute
+    left: 644px
+    top: 589px
+    
+    & > *
+      width: 338px
+      height: 50px
+      
+    .alert
+      text-align: center
+      font-weight: bold
+
+    button
+      border: 3px solid rgb(46,46,46)
+      background: white
+      font-size: 16px
diff --git a/app/styles/play/modal/item-details-view.sass b/app/styles/play/modal/item-details-view.sass
new file mode 100644
index 000000000..0d523e518
--- /dev/null
+++ b/app/styles/play/modal/item-details-view.sass
@@ -0,0 +1,82 @@
+#item-details-view
+
+  .nano-content
+    padding: 10px
+
+  #item-title
+    position: absolute
+    width: 228px
+    height: 50px
+    left: 910px
+    top: 60px
+    z-index: 2
+    
+    h2
+      font-size: 20px
+      margin: 12px 20px
+      text-align: center
+      color: rgb(53,40,25)
+
+  #item-details-body
+    position: absolute
+    left: 860px
+    top: 126px
+    width: 330px
+    height: 449px
+    //background: rgba(100,100,100,0.5)
+
+    #item-container
+      height: 163px
+      width: 100%
+
+    .item-img, .item-shadow
+      width: 130px
+      height: 130px
+
+    .item-img
+      top: 15px
+
+    .item-shadow
+      top: 25px
+
+    img.hr
+      width: 80%
+      margin: 0 10% -3px
+      
+      &.faded
+        opacity: 0.4
+      
+    .stat-row
+      height: 24px
+      position: relative
+      font-size: 20px
+      font-weight: bold
+      
+      .stat-label
+        position: absolute
+        left: 54px
+        color: rgb(93,73,52)
+        
+      .stat
+        position: absolute
+        left: 150px
+        color: rgb(42,38,28)
+      
+    #skills
+      margin: 25px
+      
+      h3
+        color: rgb(41,35,25)
+        
+      strong
+        color: rgb(50,50,30)
+      
+  #selected-item-unlock-button
+    left: 856px
+    top: 594px
+    width: 337px
+    height: 41px
+    font-size: 16px
+    
+    img
+      height: 16px
diff --git a/app/styles/play/modal/play-items-modal.sass b/app/styles/play/modal/play-items-modal.sass
index 8c798c988..19e5dd548 100644
--- a/app/styles/play/modal/play-items-modal.sass
+++ b/app/styles/play/modal/play-items-modal.sass
@@ -123,8 +123,8 @@
   .tab-pane
     height: 100%
     
-  .nano-content
-    padding: 26px 51px 26px 26px
+    .nano-content
+      padding: 26px 51px 26px 26px
 
 
   //- Item box
@@ -222,6 +222,23 @@
       background: url(/images/pages/play/modal/item-box-background-selected.png)
 
     
+  //- Item details. Non-specific item-details-view styling is in item-details-view.sass.
+
+  #item-details-view
+  
+    #item-title
+      left: 910px
+      top: 60px
+      
+    #item-details-body
+      left: 860px
+  
+    #selected-item-unlock-button
+      left: 856px
+
+
+#play-items-modal, #inventory-modal
+
   //- Item list scrollbar
   
   .nano-pane
@@ -236,86 +253,6 @@
     margin-left: -3px
     margin-right: -3px
     
-  //  color: red
-    
-    
-  //- Item details
-
-  #item-title
-    position: absolute
-    width: 228px
-    height: 50px
-    left: 910px
-    top: 60px
-    z-index: 2
-    
-    h2
-      font-size: 20px
-      margin: 12px 20px
-      text-align: center
-      color: rgb(53,40,25)
-
-  #item-details-body
-    position: absolute
-    left: 860px
-    top: 126px
-    width: 330px
-    height: 449px
-    //background: rgba(100,100,100,0.5)
-
-    #item-container
-      height: 163px
-      width: 100%
-
-    .item-img, .item-shadow
-      width: 130px
-      height: 130px
-
-    .item-img
-      top: 15px
-
-    .item-shadow
-      top: 25px
-
-    img.hr
-      width: 80%
-      margin: 0 10% -3px
-      
-      &.faded
-        opacity: 0.4
-      
-    .stat-row
-      height: 24px
-      position: relative
-      font-size: 20px
-      font-weight: bold
-      
-      .stat-label
-        position: absolute
-        left: 54px
-        color: rgb(93,73,52)
-        
-      .stat
-        position: absolute
-        left: 150px
-        color: rgb(42,38,28)
-      
-    #skills
-      margin: 25px
-      
-      h3
-        color: rgb(41,35,25)
-        
-      strong
-        color: rgb(50,50,30)
-      
-  #selected-item-unlock-button
-    left: 856px
-    top: 594px
-    width: 337px
-    height: 41px
-    font-size: 16px
-
 
   //- Item icons w/shadows (both in list and details areas)
 
@@ -355,6 +292,9 @@
       opacity: 1
       color: rgba(255,255,255, 0.4)
 
+
+//- Use the two-column layout and background image if we are on a narrow screen.
+
 @media only screen and (max-width: 1300px)
   #play-items-modal
     overflow-x: hidden
diff --git a/app/templates/game-menu/inventory-modal.jade b/app/templates/game-menu/inventory-modal.jade
index 9bd81e4a8..846d23173 100644
--- a/app/templates/game-menu/inventory-modal.jade
+++ b/app/templates/game-menu/inventory-modal.jade
@@ -1,68 +1,52 @@
-extends /templates/modal/modal_base
+.modal-dialog
+  .modal-content
+    img(src="/images/pages/play/modal/items-background-narrow.png")#play-items-modal-narrow-bg
 
-block modal-header-content
-  h1#choose-inventory-header.choose-inventory-active(data-i18n="inventory.choose_inventory") Equip Items
+    div#gems-count-container
+      span#gems-count.big-font= gems
 
-block modal-body-content
-  #equipped
-    .item-slot-row
-      for slot in ['left-ring', 'neck', 'eyes', 'head', 'wrists', 'right-ring']
+    div#close-modal
+      span.glyphicon.glyphicon-remove
+
+    #equipped
+      if selectedHero
+        img(src="/file/"+selectedHero.get('featureImage'))#hero-image
+
+      for slot in ['head', 'eyes', 'neck', 'torso', 'gloves', 'wrists', 'left-hand', 'right-hand', 'waist', 'feet', 'left-ring', 'right-ring', 'minion', 'flag', 'pet', 'programming-book', 'misc-0', 'misc-1']
         .item-slot(data-slot=slot)
           .placeholder
-          .item-container
-            if equipment[slot]
-              .replace-me(data-item-id=equipment[slot].get('original'))
-  
-    .item-slot-column.pull-left
-      // TODO: add in 'misc-0' again somehow? Used to be where 'flag' is now.
-      for slot in ['minion', 'torso', 'gloves', 'left-hand', 'flag']
-        .item-slot(data-slot=slot)
-          .placeholder
-          .item-container
-            if equipment[slot]
-              .replace-me(data-item-id=equipment[slot].get('original'))
-  
-    .hero-container
-      canvas.equipped-hero-canvas
-      .hero-feature-image
-        img
-      #selected-items
-        #selected-equipped-item.well
-          h3(data-i18n="inventory.equipped_item") Equipped
-          .item-view-stub
-        #selected-available-item.well
-          h3(data-i18n="inventory.available_item") Available
-          .item-view-stub
-  
-    .item-slot-column.pull-right
-      for slot in ['pet', 'waist', 'feet', 'right-hand', 'programming-book']
-        .item-slot(data-slot=slot)
-          .placeholder
-          .item-container
-            if equipment[slot]
-              .replace-me(data-item-id=equipment[slot].get('original'))
-  
-    // TODO: work in misc 1 again
-    //hr.slot-row-separator
-    //
-    //.item-slot-row.row-4
-    //  for slot in ['misc-1']
-    //    .item-slot(data-slot=slot)
-    //      .placeholder
-    //      .item-container
-    //        if equipment[slot]
-    //          .replace-me(data-item-id=equipment[slot].get('original'))
-  
-  #available-equipment
-    h4#unlocked-description
-    ul.list-group
-      for item in unlockedItems
-        li.list-group-item(class=item.classes, data-item-id=item.get('original'))
-    h4#locked-description
-    ul.list-group
-      for item in lockedItems
-        li.list-group-item(class=item.classes, data-item-id=item.get('original'), style="display: none")
+          if equipment[slot]
+            img.item(src=equipment[slot].getPortraitURL(), data-item-id=equipment[slot].id)
 
-block modal-footer-content
-  button#choose-hero-button.btn.btn-lg.btn-primary.choose-inventory-active.pull-left(data-i18n="play.change_hero") Change Hero
-  button#play-level-button.btn.btn-lg.btn-success.choose-inventory-active(data-i18n="common.play") Play
+    #unequipped
+      .nano
+        .nano-content
+          if itemGroups
+            if itemGroups.availableItems.models.length
+              h4#available-description(data-i18n="inventory.available_item")
+              for item in itemGroups.availableItems.models
+                img.item(src=item.getPortraitURL(), class=item.classes, data-item-id=item.id)
+              .clearfix
+            
+            #double-click-hint.alert.alert-info.secret(data-i18n="inventory.should_equip")
+            
+            if itemGroups.restrictedItems.models.length
+              h4#restricted-description(data-i18n="inventory.restricted_title")
+              for item in itemGroups.restrictedItems.models
+                img.item(src=item.getPortraitURL(), class=item.classes, data-item-id=item.id)
+              .clearfix
+      
+            if itemGroups.lockedItems.models.length
+              h4#locked-description(data-i18n="play.locked")
+              for item in itemGroups.lockedItems.models
+                img.item(src=item.getPortraitURL(), class=item.classes, data-item-id=item.id)
+              .clearfix
+
+    #item-details-view
+    #item-details-extra
+      button#equip-item-viewed.btn.secret(data-i18n="inventory.equip")
+      button#unequip-item-viewed.btn.secret(data-i18n="inventory.unequip")
+      .alert.alert-danger#restricted-item-viewed.secret(data-i18n="inventory.restricted")
+    
+    button#choose-hero-button.btn.btn-lg.btn-primary.choose-inventory-active(data-i18n="play.change_hero") Change Hero
+    button#play-level-button.btn.btn-lg.btn-success.choose-inventory-active(data-i18n="common.play") Play
diff --git a/app/templates/play/modal/item-details-view.jade b/app/templates/play/modal/item-details-view.jade
index 7b30b32b8..9d7f4c598 100644
--- a/app/templates/play/modal/item-details-view.jade
+++ b/app/templates/play/modal/item-details-view.jade
@@ -33,4 +33,9 @@
              p Only admins will see it for now.
 
 if item && !item.owned
-  button#selected-item-unlock-button.btn.big-font.unlock-button(disabled=!item.affordable, data-item-id=item.id, data-i18n="play.unlock") Unlock
\ No newline at end of file
+  button#selected-item-unlock-button.btn.big-font.unlock-button(disabled=!item.affordable, data-item-id=item.id)
+    span(data-i18n="play.unlock") Unlock
+    span.spl= '('+item.get('gems')
+    img(src="/images/common/gem.png")
+    span )
+    
\ No newline at end of file
diff --git a/app/views/HomeView.coffee b/app/views/HomeView.coffee
index 725905bed..7b5064e10 100644
--- a/app/views/HomeView.coffee
+++ b/app/views/HomeView.coffee
@@ -4,6 +4,8 @@ WizardLank = require 'lib/surface/WizardLank'
 ThangType = require 'models/ThangType'
 Simulator = require 'lib/simulator/Simulator'
 
+InventoryModal = require 'views/game-menu/InventoryModal'
+
 {me} = require '/lib/auth'
 
 module.exports = class HomeView extends RootView
@@ -34,4 +36,8 @@ module.exports = class HomeView extends RootView
     e.preventDefault()
     e.stopImmediatePropagation()
     window.tracker?.trackEvent 'Homepage', Action: 'Play'
-    window.open '/play', '_blank'
\ No newline at end of file
+    window.open '/play', '_blank'
+
+  afterInsert: ->
+    super(arguments...)
+    @openModalView(new InventoryModal({levelID: 'the-raised-sword'}))
\ No newline at end of file
diff --git a/app/views/game-menu/InventoryModal.coffee b/app/views/game-menu/InventoryModal.coffee
index cb6bfe6d8..3da689a25 100644
--- a/app/views/game-menu/InventoryModal.coffee
+++ b/app/views/game-menu/InventoryModal.coffee
@@ -5,6 +5,8 @@ ThangType = require 'models/ThangType'
 CocoCollection = require 'collections/CocoCollection'
 ItemView = require './ItemView'
 SpriteBuilder = require 'lib/sprites/SpriteBuilder'
+ItemDetailsView = require 'views/play/modal/ItemDetailsView'
+Purchase = require 'models/Purchase'
 LevelOptions = require 'lib/LevelOptions'
 
 hasGoneFullScreenOnce = false
@@ -14,101 +16,130 @@ module.exports = class InventoryModal extends ModalView
   className: 'modal fade play-modal'
   template: template
   slots: ['head', 'eyes', 'neck', 'torso', 'wrists', 'gloves', 'left-ring', 'right-ring', 'right-hand', 'left-hand', 'waist', 'feet', 'programming-book', 'pet', 'minion', 'flag']  #, 'misc-0', 'misc-1']  # TODO: bring in misc slot(s) again when we have space
+  closesOnClickOutside: false # because draggable somehow triggers hide when you don't drag onto a draggable
 
   events:
     'click .item-slot': 'onItemSlotClick'
-    'click #available-equipment .list-group-item:not(.equipped)': 'onAvailableItemClick'
-    'dblclick #available-equipment .list-group-item:not(.equipped)': 'onAvailableItemDoubleClick'
-    'doubletap #available-equipment .list-group-item:not(.equipped)': 'onAvailableItemDoubleClick'
-    'dblclick .item-slot .item-view': 'onEquippedItemDoubleClick'
-    'doubletap .item-slot .item-view': 'onEquippedItemDoubleClick'
+    'click #unequipped img.item': 'onUnequippedItemClick'
+    'doubletap #unequipped img.item': 'onUnequippedItemDoubleClick'
+    'doubletap .item-slot img.item': 'onEquippedItemDoubleClick'
     'shown.bs.modal': 'onShown'
     'click #choose-hero-button': 'onClickChooseHero'
     'click #play-level-button': 'onClickPlayLevel'
+    'click .unlock-button': 'onUnlockButtonClicked'
+    'click #equip-item-viewed': 'onClickEquipItemViewed'
+    'click #unequip-item-viewed': 'onClickUnequipItemViewed'
+    'click #close-modal': 'hide'
 
   shortcuts:
     'esc': 'clearSelection'
     'enter': 'onClickPlayLevel'
 
+
+  #- Setup
+
   initialize: (options) ->
     super(arguments...)
     @items = new CocoCollection([], {model: ThangType})
-    @items.url = '/db/thang.type?view=items&project=name,slug,components,original,rasterIcon,gems,description,heroClass'
+    # TODO: switch to item store loading system?
+    @items.url = '/db/thang.type?view=items'
+    @items.setProjection [
+      'name',
+      'slug',
+      'components',
+      'original',
+      'rasterIcon',
+      'gems',
+      'description',
+      'heroClass',
+      'i18n'
+    ]
     @supermodel.loadCollection(@items, 'items')
-    @equipment = {}  # Assign for real when we have loaded the session
+    @equipment = {}  # Assign for real when we have loaded the session and items.
 
-  destroy: ->
-    @stage?.removeAllChildren()
-    super()
-
-  onLoaded: ->
+  onItemsLoaded: ->
     item.notInLevel = true for item in @items.models
     @equipment = @options.equipment or @options.session?.get('heroConfig')?.inventory or me.get('heroConfig')?.inventory or {}
     @equipment = $.extend true, {}, @equipment
     @requireLevelEquipment()
+    @itemGroups = {}
+    @itemGroups.availableItems = new Backbone.Collection()
+    @itemGroups.restrictedItems = new Backbone.Collection()
+    @itemGroups.lockedItems = new Backbone.Collection()
+    itemGroup.comparator = 'gems' for itemGroup in _.values @itemGroups
+
+    equipped = _.values(@equipment)
+    @sortItem(item, equipped) for item in @items.models
+
+  sortItem: (item, equipped) ->
+    equipped ?= _.values(@equipment)
+
+    # general starting classes
+    item.classes = _.clone(item.getAllowedSlots())
+    for heroClass in item.getAllowedHeroClasses()
+      item.classes.push heroClass
+    item.classes.push 'equipped' if item.get('original') in equipped
+
+    # sort into one of the four groups
+    locked = not (item.get('original') in me.items())
+
+    if locked and item.get('slug') isnt 'simple-boots'
+      @itemGroups.lockedItems.add(item)
+      item.classes.push 'locked'
+      item.classes.push 'silhouette' if item.isSilhouettedItem()
+    else if item.get('slug') in _.values(LevelOptions[@options.levelID]?.restrictedGear ? {})
+      @itemGroups.restrictedItems.add(item)
+      item.classes.push 'restricted'
+    else
+      @itemGroups.availableItems.add(item)
+
+  onLoaded: ->
+    # Both items and session have been loaded.
+    @onItemsLoaded()
     super()
 
   getRenderData: (context={}) ->
     context = super(context)
     context.equipped = _.values(@equipment)
     context.items = @items.models
-
-    for item in @items.models
-      item.classes = item.getAllowedSlots()
-      item.classes.push 'equipped' if item.get('original') in context.equipped
-      locked = not (item.get('original') in me.items())
-      item.classes.push 'locked' if locked and item.get('slug') isnt 'simple-boots'
-      for heroClass in item.getAllowedHeroClasses()
-        item.classes.push heroClass
-      item.classes.push 'silhouette' if item.isSilhouettedItem()
-      item.classes.push 'restricted' if item.get('slug') in _.values(LevelOptions[@options.levelID]?.restrictedGear ? {})
-
-    @items.models.sort (a, b) ->
-      lockScore = 90019001 * (('locked' in a.classes) - ('locked' in b.classes))
-      gemScore = a.get('gems') - b.get('gems')
-      lockScore + gemScore
-
-    context.unlockedItems = []
-    context.lockedItems = []
-    for item in @items.models
-      (if 'locked' in item.classes then context.lockedItems else context.unlockedItems).push item
-
+    context.itemGroups = @itemGroups
     context.slots = @slots
+    context.selectedHero = @selectedHero
     context.equipment = _.clone @equipment
-    for slot, itemOriginal of context.equipment
-      item = _.find @items.models, (item) -> item.get('original') is itemOriginal
-      context.equipment[slot] = item
+    context.equipment[slot] = @items.findWhere {original: itemOriginal} for slot, itemOriginal of context.equipment
+    context.gems = me.gems()
     context
 
   afterRender: ->
     super()
-    @$el.find('.modal-footer button').css('visibility', 'hidden')
+    @$el.find('#play-level-button').css('visibility', 'hidden')
     return unless @supermodel.finished()
-    @$el.find('.modal-footer button').css('visibility', 'visible')
+    @$el.find('#play-level-button').css('visibility', 'visible')
 
-    keys = (item.get('original') for item in @items.models)
-    itemMap = _.zipObject keys, @items.models
+    @setUpDraggableEventsForAvailableEquipment()
+    @setUpDraggableEventsForEquippedArea()
+    @delegateEvents()
+    @itemDetailsView = new ItemDetailsView()
+    @insertSubView(@itemDetailsView)
+    @requireLevelEquipment()
+    @$el.find('.nano').nanoScroller()
 
-    # Fill in equipped items
-    for slottedItemStub in @$el.find('.replace-me')
-      itemID = $(slottedItemStub).data('item-id')
-      item = itemMap[itemID]
-      itemView = new ItemView({item: item, includes: {}})
-      itemView.render()
-      $(slottedItemStub).replaceWith(itemView.$el)
-      @registerSubView(itemView)
+  afterInsert: ->
+    super()
+    @canvasWidth = @$el.find('canvas').innerWidth()
+    @canvasHeight = @$el.find('canvas').innerHeight()
+    @inserted = true
+    @requireLevelEquipment()
 
-    for availableItemEl in @$el.find('#available-equipment .list-group-item')
-      itemID = $(availableItemEl).data('item-id')
-      item = itemMap[itemID]
-      itemView = new ItemView({item: item, includes: {name: true}})
-      itemView.render()
-      $(availableItemEl).append(itemView.$el)
-      @registerSubView(itemView)
-      continue if $(availableItemEl).hasClass('locked') or $(availableItemEl).hasClass('restricted')
-      dragHelper = itemView.$el.find('img').clone().addClass('draggable-item')
-      do (dragHelper, itemView) =>
-        itemView.$el.draggable
+  #- Draggable logic
+
+  setUpDraggableEventsForAvailableEquipment: ->
+    for availableItemEl in @$el.find('#unequipped img.item')
+      availableItemEl = $(availableItemEl)
+      continue if availableItemEl.hasClass('locked') or availableItemEl.hasClass('restricted')
+      dragHelper = availableItemEl.clone().addClass('draggable-item')
+      do (dragHelper, availableItemEl) =>
+        availableItemEl.draggable
           revert: 'invalid'
           appendTo: @$el
           cursorAt: {left: 35.5, top: 35.5}
@@ -116,43 +147,32 @@ module.exports = class InventoryModal extends ModalView
           revertDuration: 200
           distance: 10
           scroll: false
-          zIndex: 10000
-        itemView.$el.on 'dragstart', =>
-          @onAvailableItemClick target: itemView.$el.parent() unless itemView.$el.parent().hasClass 'active'
+          zIndex: 1100
+        availableItemEl.on 'dragstart', => @selectUnequippedItem(availableItemEl)
 
+  setUpDraggableEventsForEquippedArea: ->
     for itemSlot in @$el.find '.item-slot'
       slot = $(itemSlot).data 'slot'
       do (slot, itemSlot) =>
         $(itemSlot).droppable
-          drop: (e, ui) => @onAvailableItemDoubleClick()
+          drop: (e, ui) => @equipSelectedItem()
           accept: (el) -> $(el).parent().hasClass slot
           activeClass: 'droppable'
           hoverClass: 'droppable-hover'
           tolerance: 'touch'
         @makeEquippedSlotDraggable $(itemSlot)
 
-    @$el.find('.hero-container').droppable
-      drop: (e, ui) => @onAvailableItemDoubleClick()
+    @$el.find('#equipped').droppable
+      drop: (e, ui) => @equipSelectedItem()
       accept: (el) -> true
       activeClass: 'droppable'
       hoverClass: 'droppable-hover'
       tolerance: 'pointer'
 
-    @$el.find('#selected-items').hide()  # Hide until one is selected
-    @delegateEvents()
-
-    if @selectedHero and not @startedLoadingFirstHero
-      @loadHero()
-    @requireLevelEquipment()
-
-  afterInsert: ->
-    super()
-    @canvasWidth = @$el.find('canvas').innerWidth()
-    @canvasHeight = @$el.find('canvas').innerHeight()
-    @inserted = true
-
   makeEquippedSlotDraggable: (slot) ->
-    unequip = => @unequipItemFromSlot slot
+    unequip = =>
+      @unequipItemFromSlot slot
+      @requireLevelEquipment()
     shouldStayEquippedWhenDropped = (isValidDrop) ->
       pos = $(@).position()
       revert = Math.abs(pos.left) < $(@).outerWidth() and Math.abs(pos.top) < $(@).outerHeight()
@@ -166,179 +186,158 @@ module.exports = class InventoryModal extends ModalView
       revertDuration: 200
       distance: 10
       scroll: false
-      zIndex: 10000
+      zIndex: 100
+    slot.on 'dragstart', => @selectItemSlot(slot)
 
-  clearSelection: ->
-    @$el.find('.item-slot.selected').removeClass 'selected'
-    @$el.find('.list-group-item').removeClass('active')
-    @onSelectionChanged()
+
+  #- Select/equip event handlers
 
   onItemSlotClick: (e) ->
     return if @remainingRequiredEquipment?.length  # Don't let them select a slot if we need them to first equip some require gear.
-    slot = $(e.target).closest('.item-slot')
-    wasActive = slot.hasClass('selected')
-    @unselectAllSlots()
-    @unselectAllAvailableEquipment() if slot.hasClass('disabled')
-    if wasActive
-      @hideSelectedSlotItem()
-      @unselectAllAvailableEquipment()
+    @selectItemSlot($(e.target).closest('.item-slot'))
+
+  onUnequippedItemClick: (e) ->
+    return if @justDoubleClicked
+    itemEl = $(e.target).closest('img.item')
+    @selectUnequippedItem(itemEl)
+
+  onUnequippedItemDoubleClick: (e) ->
+    item = $(e.target).closest('img.item')
+    return if item.hasClass('locked') or item.hasClass('restricted')
+    @equipSelectedItem()
+    @justDoubleClicked = true
+    _.defer => @justDoubleClicked = false
+
+  onEquippedItemDoubleClick: -> @unequipSelectedItem()
+  onClickEquipItemViewed: -> @equipSelectedItem()
+  onClickUnequipItemViewed: -> @unequipSelectedItem()
+
+  onUnlockButtonClicked: (e) ->
+    button = $(e.target).closest('button')
+    if button.hasClass('confirm')
+      item = @items.get($(e.target).data('item-id'))
+      purchase = Purchase.makeFor(item)
+      purchase.save()
+
+      #- set local changes to mimic what should happen on the server...
+      purchased = me.get('purchased') ? {}
+      purchased.items ?= []
+      purchased.items.push(item.get('original'))
+
+      me.set('purchased', purchased)
+      me.set('spent', (me.get('spent') ? 0) + item.get('gems'))
+
+      #- ...then rerender key bits
+      @requireLevelEquipment()
+      @itemGroups.lockedItems.remove(item)
+      @sortItem(item)
+      @renderSelectors("#unequipped", "#gems-count")
+      @delegateEvents()
+      @setUpDraggableEventsForAvailableEquipment()
+      @itemDetailsView.setItem(item)
     else
-      @selectSlot(slot)
+      button.addClass('confirm').text($.i18n.t('play.confirm'))
+      @$el.one 'click', (e) ->
+        button.removeClass('confirm').text($.i18n.t('play.unlock')) if e.target isnt button[0]
+
+
+  #- Select/equip higher-level, all encompassing methods the callbacks all use
+
+  selectItemSlot: (slotEl) ->
+    @clearSelection()
+    slotEl.addClass('selected')
+    selectedSlotItemID = slotEl.find('img.item').data('item-id')
+    item = @items.get(selectedSlotItemID)
+    if item then @showItemDetails(item, 'unequip')
     @onSelectionChanged()
 
-  onAvailableItemClick: (e) ->
-    itemContainer = $(e.target).closest('.list-group-item')
-    return if itemContainer.hasClass('locked') or itemContainer.hasClass('restricted')
-    wasActive = itemContainer.hasClass 'active'
-    @unselectAllAvailableEquipment()
-    @selectAvailableItem(itemContainer) unless wasActive
+  selectUnequippedItem: (itemEl) ->
+    @clearSelection()
+    itemEl.addClass('active')
+    showExtra = if itemEl.hasClass('restricted') then 'restricted' else if not itemEl.hasClass('locked') then 'equip' else ''
+    @showItemDetails(@items.get(itemEl.data('item-id')), showExtra)
     @onSelectionChanged()
 
-  onAvailableItemDoubleClick: (e) ->
-    if e
-      itemContainer = $(e.target).closest('.list-group-item')
-      return if itemContainer.hasClass('locked') or itemContainer.hasClass('restricted')
-      @selectAvailableItem itemContainer
-    @onSelectionChanged()
-    slot = @getSelectedSlot()
-    slot = @$el.find('.item-slot:not(.disabled):first') if not slot.length
-    $(e.target).effect('transfer', to: slot, duration: 500, easing: 'easeOutCubic') if e
-    @unequipItemFromSlot(slot)
-    @equipSelectedItemToSlot(slot)
+  equipSelectedItem: ->
+    selectedItemEl = @getSelectedUnequippedItem()
+    selectedItem = @items.get(selectedItemEl.data('item-id'))
+    return unless selectedItem
+    allowedSlots = selectedItem.getAllowedSlots()
+    slotEl = @$el.find(".item-slot[data-slot='#{allowedSlots[0]}']")
+    selectedItemEl.effect('transfer', to: slotEl, duration: 500, easing: 'easeOutCubic')
+    unequipped = @unequipItemFromSlot(slotEl)
+    selectedItemEl.addClass('equipped')
+    slotEl.append(selectedItemEl.clone())
+    @clearSelection()
+    @showItemDetails(selectedItem, 'unequip')
+    slotEl.addClass('selected')
+    selectedItem.classes.push 'equipped'
+    @makeEquippedSlotDraggable slotEl
+    @requireLevelEquipment()
     @onSelectionChanged()
 
-  onEquippedItemDoubleClick: (e) ->
-    @unselectAllAvailableEquipment()
-    slot = $(e.target).closest('.item-slot')
-    @selectAvailableItem(@unequipItemFromSlot(slot))
+  unequipSelectedItem: ->
+    slotEl = @getSelectedSlot()
+    @clearSelection()
+    itemEl = @unequipItemFromSlot(slotEl)
+    return unless itemEl
+    itemEl.addClass('active')
+    slotEl.effect('transfer', to: itemEl, duration: 500, easing: 'easeOutCubic')
+    selectedSlotItemID = itemEl.data('item-id')
+    item = @items.get(selectedSlotItemID)
+    item.classes = _.without item.classes, 'equipped'
+    @showItemDetails(item, 'equip')
+    @requireLevelEquipment()
     @onSelectionChanged()
 
-  getSelectedSlot: ->
-    @$el.find('#equipped .item-slot.selected')
 
-  unselectAllAvailableEquipment: ->
-    @$el.find('#available-equipment .list-group-item').removeClass('active')
+  #- Select/equip helpers
 
-  unselectAllSlots: ->
+  clearSelection: ->
+    @deselectAllSlots()
+    @deselectAllUnequippedItems()
+    @hideItemDetails()
+
+  unequipItemFromSlot: (slotEl) ->
+    itemEl = slotEl.find('img.item')
+    itemIDToUnequip = itemEl.data('item-id')
+    return unless itemIDToUnequip
+    itemEl.remove()
+    @$el.find("#unequipped img.item[data-item-id=#{itemIDToUnequip}]").removeClass('equipped')
+
+  deselectAllSlots: ->
     @$el.find('#equipped .item-slot.selected').removeClass('selected')
 
-  selectSlot: (slot) ->
-    slot.addClass('selected')
+  deselectAllUnequippedItems: ->
+    @$el.find('#unequipped img.item').removeClass('active')
 
   getSlot: (name) ->
     @$el.find(".item-slot[data-slot=#{name}]")
 
-  getSelectedAvailableItemContainer: ->
-    @$el.find('#available-equipment .list-group-item.active')
+  getSelectedSlot: ->
+    @$el.find('#equipped .item-slot.selected')
 
-  getAvailableItemContainer: (itemID) ->
-    @$el.find("#available-equipment .list-group-item[data-item-id='#{itemID}']")
-
-  selectAvailableItem: (itemContainer) ->
-    itemContainer?.addClass('active')
-
-  unequipItemFromSlot: (slot) ->
-    itemIDToUnequip = slot.find('.item-view').data('item-id')
-    return unless itemIDToUnequip
-    slot.find('.item-view').detach()
-    for el in @$el.find('#available-equipment .list-group-item')
-      itemID = $(el).find('.item-view').data('item-id')
-      if itemID is itemIDToUnequip
-        unequipped = $(el).removeClass('equipped')
-        break
-    if unequipped
-      @clearSelection()
-      @requireLevelEquipment()
-    return unequipped
-
-  equipSelectedItemToSlot: (slot) ->
-    selectedItemContainer = @getSelectedAvailableItemContainer()
-    newItemHTML = selectedItemContainer.html()
-    selectedItemContainer.addClass('equipped')
-    slotContainer = slot.find('.item-container')
-    slotContainer.html(newItemHTML)
-    slotContainer.find('.item-view').data('item-id', selectedItemContainer.find('.item-view').data('item-id'))
-    @$el.find('.list-group-item').removeClass('active')
-    @makeEquippedSlotDraggable slot
-    @requireLevelEquipment()
+  getSelectedUnequippedItem: ->
+    @$el.find('#unequipped img.item.active')
 
   onSelectionChanged: ->
-    @$el.find('.item-slot').show()
-
-    selectedSlot = @$el.find('.item-slot.selected')
-    selectedItem = @$el.find('#available-equipment .list-group-item.active')
-
-    if selectedSlot.length
-      @$el.find('#available-equipment .list-group-item').hide()
-      unlockedCount = @$el.find("#available-equipment .list-group-item.#{selectedSlot.data('slot')}:not(.locked)").show().length
-      lockedCount = @$el.find("#available-equipment .list-group-item.#{selectedSlot.data('slot')}.locked").show().length
-      @$el.find('#unlocked-description').text("#{unlockedCount} #{selectedSlot.data('slot')} items owned").toggle unlockedCount > 0
-      @$el.find('#locked-description').text("#{lockedCount} #{selectedSlot.data('slot')} items locked").toggle lockedCount > 0
-      selectedSlotItemID = selectedSlot.find('.item-view').data('item-id')
-      if selectedSlotItemID
-        item = _.find @items.models, {id: selectedSlotItemID}
-        @showSelectedSlotItem(item)
-      else
-        @hideSelectedSlotItem()
-    else
-      unlockedCount = @$el.find('#available-equipment .list-group-item:not(.locked)').show().length
-      @$el.find('#available-equipment .list-group-item.locked').hide()
-      @$el.find('#unlocked-description').text("#{unlockedCount} items owned").toggle unlockedCount > 0
-      @$el.find('#locked-description').text("#{lockedCount} items locked").hide()
-    #@$el.find('#available-equipment .list-group-item.equipped').hide()
-
-    @$el.find('.item-slot').removeClass('disabled')
-    if selectedItem.length
-      item = _.find @items.models, {id:selectedItem.find('.item-view').data('item-id')}
-      # update which slots are enabled
-      allowedSlots = item.getAllowedSlots()
-      for slotEl in @$el.find('.item-slot')
-        slotName = $(slotEl).data('slot')
-        if slotName not in allowedSlots
-          $(slotEl).addClass('disabled')
-      @showSelectedAvailableItem(item)
-    else
-      @hideSelectedAvailableItem()
-
     @delegateEvents()
 
-  showSelectedSlotItem: (item) ->
-    if not @selectedEquippedItemView
-      @selectedEquippedItemView = new ItemView({
-        item: item, includes: {name: true, stats: true, props: true}})
-      @insertSubView(@selectedEquippedItemView, @$el.find('#selected-equipped-item .item-view-stub'))
-    else
-      @selectedEquippedItemView.$el.show()
-      @selectedEquippedItemView.item = item
-      @selectedEquippedItemView.render()
-    @$el.find('#selected-items').show()
-    @$el.find('#selected-equipped-item').show()
 
-  hideSelectedSlotItem: ->
-    @selectedEquippedItemView?.$el.hide().parent().hide()
-    @$el.find('#selected-items').hide() unless @selectedEquippedItemView?.$el?.is(':visible')
+  showItemDetails: (item, showExtra) ->
+    @itemDetailsView.setItem(item)
+    @$el.find('#item-details-extra > *').addClass('secret')
+    @$el.find("##{showExtra}-item-viewed").removeClass('secret')
 
-  showSelectedAvailableItem: (item) ->
-    if not @selectedAvailableItemView
-      @selectedAvailableItemView = new ItemView({
-        item: item, includes: {name: true, stats: true, props: true}})
-      @insertSubView(@selectedAvailableItemView, @$el.find('#selected-available-item .item-view-stub'))
-    else
-      @selectedAvailableItemView.$el.show()
-      @selectedAvailableItemView.item = item
-      @selectedAvailableItemView.render()
-    @$el.find('#selected-items').show()
-    @$el.find('#selected-available-item').show()
-
-  hideSelectedAvailableItem: ->
-    @selectedAvailableItemView?.$el.hide().parent().hide()
-    @$el.find('#selected-items').hide() unless @selectedEquippedItemView?.$el?.is(':visible')
+  hideItemDetails: ->
+    @itemDetailsView.setItem(null)
+    @$el.find('#item-details-extra > *').addClass('secret')
 
   getCurrentEquipmentConfig: ->
     config = {}
     for slot in @$el.find('.item-slot')
       slotName = $(slot).data('slot')
-      slotItemID = $(slot).find('.item-view').data('item-id')
+      slotItemID = $(slot).find('img.item').data('item-id')
       continue unless slotItemID
       item = _.find @items.models, {id:slotItemID}
       config[slotName] = item.get('original')
@@ -371,10 +370,13 @@ module.exports = class InventoryModal extends ModalView
           (item is 'leather-boots' and equipped is gear['simple-boots']) or
           (item is 'simple-boots' and equipped is gear['leather-boots'])
         )
-        availableSlotSelector = "#available-equipment li[data-item-id='#{gear[item]}']"
+        itemModel = @items.findWhere {slug: item}
+        continue unless itemModel
+        availableSlotSelector = "#unequipped .item[data-item-id='#{itemModel.id}']"
         @highlightElement availableSlotSelector, delay: 500, sides: ['right'], rotation: Math.PI / 2
         @$el.find(availableSlotSelector).addClass 'should-equip'
         @$el.find("#equipped div[data-slot='#{slot}']").addClass 'should-equip'
+        @$el.find('#double-click-hint').removeClass('secret')
         @remainingRequiredEquipment.push slot: slot, item: gear[item]
       if hadRequired and not @remainingRequiredEquipment.length
         @endHighlight()
@@ -382,54 +384,12 @@ module.exports = class InventoryModal extends ModalView
       $('#play-level-button').prop('disabled', @remainingRequiredEquipment.length > 0)
 
   setHero: (@selectedHero) ->
-    @loadHero()
     @$el.removeClass('Warrior Ranger Wizard').addClass(@selectedHero.get('heroClass'))
-
-  loadHero: ->
-    return unless @supermodel.finished() and @selectedHero and not @$el.hasClass 'secret'
-    @startedLoadingFirstHero = true
-    @stage?.removeAllChildren()
-    if featureImage = @selectedHero.get 'featureImage'
-      @$el.find(".equipped-hero-canvas").hide()
-      @$el.find(".hero-feature-image").show().find('img').prop('src', '/file/' + featureImage)
-      return
-    if @selectedHero.loaded and movieClip = @movieClips?[@selectedHero.get('original')]
-      @stage.addChild(movieClip)
-      @stage.update()
-      return
-    onLoaded = =>
-      return unless canvas = @$el.find(".equipped-hero-canvas")
-      @canvasWidth ||= canvas.width()
-      @canvasHeight ||= canvas.height()
-      canvas.prop width: @canvasWidth, height: @canvasHeight
-      builder = new SpriteBuilder(@selectedHero)
-      movieClip = builder.buildMovieClip(@selectedHero.get('actions').attack?.animation ? @selectedHero.get('actions').idle.animation)
-      movieClip.scaleX = movieClip.scaleY = canvas.prop('height') / 120  # Average hero height is ~110px at normal resolution
-      if @selectedHero.get('name') in ['Knight', 'Robot Walker']  # These are too big, so shrink them.
-        movieClip.scaleX *= 0.7
-        movieClip.scaleY *= 0.7
-      movieClip.regX = -@selectedHero.get('positions').registration.x
-      movieClip.regY = -@selectedHero.get('positions').registration.y
-      movieClip.x = canvas.prop('width') * 0.5
-      movieClip.y = canvas.prop('height') * 0.95  # This is where the feet go.
-      movieClip.gotoAndPlay 0
-      @stage ?= new createjs.Stage(canvas[0])
-      @stage.addChild movieClip
-      @stage.update()
-      @movieClips ?= {}
-      @movieClips[@selectedHero.get('original')] = movieClip
-    if @selectedHero.loaded
-      if @selectedHero.isFullyLoaded()
-        _.defer onLoaded
-      else
-        console.error 'Hmm, trying to render a hero we have not loaded...?', @selectedHero
-    else
-      @listenToOnce @selectedHero, 'sync', onLoaded
+    @render()
 
   onShown: ->
     # Called when we switch tabs to this within the modal
     @requireLevelEquipment()
-    @loadHero()
 
   onHidden: ->
     # Called when the modal itself is dismissed
@@ -471,6 +431,13 @@ module.exports = class InventoryModal extends ModalView
     else
       callback?()
 
+  destroy: ->
+    @stage?.removeAllChildren()
+    super()
+
+
+
+
 gear =
   'simple-boots': '53e237bf53457600003e3f05'
   'simple-sword': '53e218d853457600003e3ebe'
diff --git a/app/views/play/modal/ItemDetailsView.coffee b/app/views/play/modal/ItemDetailsView.coffee
new file mode 100644
index 000000000..422a86185
--- /dev/null
+++ b/app/views/play/modal/ItemDetailsView.coffee
@@ -0,0 +1,76 @@
+CocoView = require 'views/kinds/CocoView'
+template = require 'templates/play/modal/item-details-view'
+CocoCollection = require 'collections/CocoCollection'
+LevelComponent = require 'models/LevelComponent'
+
+utils = require 'lib/utils'
+
+module.exports = class ItemDetailsView extends CocoView
+  id: "item-details-view"
+  template: template
+
+  constructor: ->
+    super(arguments...)
+    @propDocs = {}
+
+  setItem: (@item) ->
+    if @item
+      @item.name = utils.i18n @item.attributes, 'name'
+      @item.affordable = me.gems() >= @item.get('gems')
+      @item.owned = me.ownsItem @item.get('original')
+      @item.comingSoon = not @item.getFrontFacingStats().props.length and not _.size @item.getFrontFacingStats().stats  # Temp: while there are placeholder items
+      
+      stats = @item.getFrontFacingStats()
+      props = (p for p in stats.props when not @propDocs[p])
+      if props.length > 0
+
+        docs = new CocoCollection([], {
+          url: '/db/level.component?view=prop-doc-lookup'
+          model: LevelComponent
+          project: [
+            'propertyDocumentation.name'
+            'propertyDocumentation.description'
+            'propertyDocumentation.i18n'
+          ]
+        })
+  
+        docs.fetch({ data: {
+          componentOriginals: [c.original for c in @item.get('components')].join(',')
+          propertyNames: props.join(',')
+        }})
+        @listenToOnce docs, 'sync', @onDocsLoaded
+    
+    @render()
+    @$el.find('.nano:visible').nanoScroller()
+
+  onDocsLoaded: (levelComponents) ->
+    for component in levelComponents.models
+      for propDoc in component.get('propertyDocumentation')
+        @propDocs[propDoc.name] = propDoc
+    @render()
+
+  getRenderData: ->
+    c = super()
+    c.item = @item
+    if @item
+      stats = @item.getFrontFacingStats()
+      c.stats = _.values(stats.stats)
+      _.last(c.stats).isLast = true if c.stats.length
+      c.props = []
+      progLang = (me.get('aceConfig') ? {}).language or 'python'
+      for prop in stats.props
+        description = utils.i18n @propDocs[prop] ? {}, 'description'
+
+        if _.isObject description
+          description = description[progLang] or _.values(description)[0]
+        if _.isString description
+          description = description.replace(/#{spriteName}/g, 'hero')
+          if fact = stats.stats.shieldDefenseFactor
+            description = description.replace(/#{shieldDefensePercent}%/g, fact.display)
+          description = $(marked(description)).html()
+
+        c.props.push {
+          name: prop
+          description: description or '...'
+        }
+    c 
\ No newline at end of file
diff --git a/app/views/play/modal/PlayItemsModal.coffee b/app/views/play/modal/PlayItemsModal.coffee
index 6fac5fc35..2295ed2ad 100644
--- a/app/views/play/modal/PlayItemsModal.coffee
+++ b/app/views/play/modal/PlayItemsModal.coffee
@@ -1,8 +1,6 @@
 ModalView = require 'views/kinds/ModalView'
-CocoView = require 'views/kinds/CocoView'
-
 template = require 'templates/play/modal/play-items-modal'
-itemDetailsTemplate = require 'templates/play/modal/item-details-view'
+ItemDetailsView = require './ItemDetailsView'
 
 CocoCollection = require 'collections/CocoCollection'
 ThangType = require 'models/ThangType'
@@ -139,7 +137,7 @@ module.exports = class PlayItemsModal extends ModalView
     $($(e.target).attr('href')).find('.nano').nanoScroller({alwaysVisible: true})
 
   onUnlockButtonClicked: (e) ->
-    button = $(e.target)
+    button = $(e.target).closest('button')
     if button.hasClass('confirm')
       item = @idToItem[$(e.target).data('item-id')]
       purchase = Purchase.makeFor(item)
@@ -161,67 +159,3 @@ module.exports = class PlayItemsModal extends ModalView
       @$el.one 'click', (e) ->
         button.removeClass('confirm').text($.i18n.t('play.unlock')) if e.target isnt button[0]
 
-class ItemDetailsView extends CocoView
-  id: "item-details-view"
-  template: itemDetailsTemplate
-
-  constructor: ->
-    super(arguments...)
-    @propDocs = {}
-
-  setItem: (@item) ->
-    @render()
-
-    if @item
-      stats = @item.getFrontFacingStats()
-      props = (p for p in stats.props when not @propDocs[p])
-      return if props.length is 0
-
-      docs = new CocoCollection([], {
-        url: '/db/level.component?view=prop-doc-lookup'
-        model: LevelComponent
-        project: [
-          'propertyDocumentation.name'
-          'propertyDocumentation.description'
-          'propertyDocumentation.i18n'
-        ]
-      })
-
-      docs.fetch({ data: {
-        componentOriginals: [c.original for c in @item.get('components')].join(',')
-        propertyNames: props.join(',')
-      }})
-      @listenToOnce docs, 'sync', @onDocsLoaded
-      @$el.find('.nano:visible').nanoScroller()
-
-  onDocsLoaded: (levelComponents) ->
-    for component in levelComponents.models
-      for propDoc in component.get('propertyDocumentation')
-        @propDocs[propDoc.name] = propDoc
-    @render()
-
-  getRenderData: ->
-    c = super()
-    c.item = @item
-    if @item
-      stats = @item.getFrontFacingStats()
-      c.stats = _.values(stats.stats)
-      _.last(c.stats).isLast = true if c.stats.length
-      c.props = []
-      progLang = (me.get('aceConfig') ? {}).language or 'python'
-      for prop in stats.props
-        description = utils.i18n @propDocs[prop] ? {}, 'description'
-
-        if _.isObject description
-          description = description[progLang] or _.values(description)[0]
-        if _.isString description
-          description = description.replace(/#{spriteName}/g, 'hero')
-          if fact = stats.stats.shieldDefenseFactor
-            description = description.replace(/#{shieldDefensePercent}%/g, fact.display)
-          description = $(marked(description)).html()
-
-        c.props.push {
-          name: prop
-          description: description or '...'
-        }
-    c
diff --git a/server/purchases/Purchase.coffee b/server/purchases/Purchase.coffee
index b1f34459a..600abd1af 100644
--- a/server/purchases/Purchase.coffee
+++ b/server/purchases/Purchase.coffee
@@ -4,6 +4,6 @@ log = require 'winston'
 {handlers} = require '../commons/mapping'
 
 PurchaseSchema = new mongoose.Schema({status: String}, {strict: false})
-PurchaseSchema.index({recipient: 1, 'purchase.original': 1}, {unique: true, name: 'unique purchase'})
+PurchaseSchema.index({recipient: 1, 'purchased.original': 1}, {unique: true, name: 'unique purchase'})
 
 module.exports = mongoose.model('purchase', PurchaseSchema)
diff --git a/server/purchases/purchase_handler.coffee b/server/purchases/purchase_handler.coffee
index 7b0e1a7ef..5f1f34560 100644
--- a/server/purchases/purchase_handler.coffee
+++ b/server/purchases/purchase_handler.coffee
@@ -40,7 +40,7 @@ PurchaseHandler = class PurchaseHandler extends Handler
       return @sendDatabaseError(res, err) if err
       return @sendNotFoundError(res) unless purchasedItem
       return @sendBadInputError(res, 'This cannot be purchased.') if not cost = purchasedItem.get('gems')
-      return @sendForbiddenError(res, 'Not enough gems.') if cost > req.user.get('gems')
+      return @sendForbiddenError(res, 'Not enough gems.') if cost > req.user.gems()
       req.purchasedItem = purchasedItem # for safekeeping
 
       criteria = {
@@ -69,7 +69,7 @@ PurchaseHandler = class PurchaseHandler extends Handler
       when 'Hero' then 'heroes'
       else 'levels'
 
-    original = item.get('original')
+    original = item.get('original') + ''
     purchased[group] ?= []
     unless original in purchased[group]
       #- add the purchase to the list of purchases