diff --git a/app/models/ThangType.coffee b/app/models/ThangType.coffee
index add003f56..4a31875c0 100644
--- a/app/models/ThangType.coffee
+++ b/app/models/ThangType.coffee
@@ -294,7 +294,11 @@ module.exports = class ThangType extends CocoModel
     itemComponentRef = _.find(
       @get('components') or [],
       (compRef) -> compRef.original is LevelComponent.ItemID)
-    return itemComponentRef?.config?.slots or []
+    return itemComponentRef?.config?.slots or ['right-hand']  # ['right-hand'] is default
+
+  getAllowedHeroClasses: ->
+    return [heroClass] if heroClass = @get 'heroClass'
+    ['Warrior', 'Ranger', 'Wizard']
 
   getFrontFacingStats: ->
     components = @get('components') or []
@@ -341,3 +345,10 @@ module.exports = class ThangType extends CocoModel
     display = display.join ', '
     display = display.replace /9001m?/, 'Infinity'
     name: name, display: display
+
+  isSilhouettedItem: ->
+    # TODO: have items have actual levels instead of just going by their gem count
+    return console.error "Trying to determine whether #{@get('name')} should be a silhouetted item, but it has no gem cost." unless @get 'gems'
+    points = me.get('points')
+    expectedTotalGems = (points ? 0) * 1.5   # Not actually true, but roughly kinda close for tier 0, kinda tier 1
+    @get('gems') > (100 + expectedTotalGems) * 2
diff --git a/app/styles/game-menu/inventory-view.sass b/app/styles/game-menu/inventory-view.sass
index eb7084142..165c1d0f4 100644
--- a/app/styles/game-menu/inventory-view.sass
+++ b/app/styles/game-menu/inventory-view.sass
@@ -14,6 +14,11 @@ $selectedAreaHeight: 150px
 $stashMargin: 20px
 $stashWidth: $totalWidth - $equippedWidth - $stashMargin
 
+.ui-effects-transfer
+  outline: 2px solid #28f
+  @include box-shadow(0 0 10px #28f)
+  z-index: 9001
+
 #inventory-view
   position: relative
   height: $inventoryHeight
@@ -200,6 +205,11 @@ $stashWidth: $totalWidth - $equippedWidth - $stashMargin
     padding: 4px
     background-color: white
 
+  &.Warrior .list-group-item:not(.Warrior), &.Ranger .list-group-item:not(.Ranger), &.Wizard .list-group-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)
@@ -244,6 +254,18 @@ $stashWidth: $totalWidth - $equippedWidth - $stashMargin
         .item-info:after
           content: ' (locked)'
 
+      &.silhouette
+        h4
+          visibility: hidden
+          position: absolute
+        h4:before
+          content: '???'
+          visibility: visible
+        .item-info:after
+          display: none
+        img
+          @include filter(contrast(25%) brightness(25%))
+
   .item-view
     cursor: pointer
     
diff --git a/app/templates/game-menu/inventory-view.jade b/app/templates/game-menu/inventory-view.jade
index 3e5d3bd19..2b3248cae 100644
--- a/app/templates/game-menu/inventory-view.jade
+++ b/app/templates/game-menu/inventory-view.jade
@@ -55,5 +55,5 @@
   h4#locked-description
   ul.list-group
     for item in lockedItems
-      li.list-group-item(class=item.classes, data-item-id=item.get('original'))
+      li.list-group-item(class=item.classes, data-item-id=item.get('original'), style="display: none")
       
diff --git a/app/views/game-menu/InventoryView.coffee b/app/views/game-menu/InventoryView.coffee
index 51ab7f6a1..c2cdb0d07 100644
--- a/app/views/game-menu/InventoryView.coffee
+++ b/app/views/game-menu/InventoryView.coffee
@@ -48,15 +48,24 @@ module.exports = class InventoryView extends CocoView
     context.equipped = _.values(@equipment)
     context.items = @items.models
 
-    context.unlockedItems = []
-    context.lockedItems = []
     for item in @items.models
       item.classes = item.getAllowedSlots()
       item.classes.push 'equipped' if item.get('original') in context.equipped
       locked = @allowedItems and not (item.get('original') in @allowedItems)
-      item.classes.push 'locked' if locked
-      (if locked then context.lockedItems else context.unlockedItems).push item
-    @items.models.sort (a, b) -> ('locked' in a.classes) - ('locked' in b.classes)
+      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()
+
+    @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.slots = @slots
     context.equipment = _.clone @equipment
@@ -184,6 +193,7 @@ module.exports = class InventoryView extends CocoView
     @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)
     @onSelectionChanged()
@@ -261,9 +271,9 @@ module.exports = class InventoryView extends CocoView
         @hideSelectedSlotItem()
     else
       unlockedCount = @$el.find('#available-equipment .list-group-item:not(.locked)').show().length
-      lockedCount = @$el.find('#available-equipment .list-group-item.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").toggle lockedCount > 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')
@@ -327,30 +337,30 @@ module.exports = class InventoryView extends CocoView
     # This is temporary, until we have a more general way of awarding items and configuring needed/locked items per level.
     gear =
       'simple-boots': '53e237bf53457600003e3f05'
-      'longsword': '53e218d853457600003e3ebe'
+      'simple-sword': '53e218d853457600003e3ebe'
       'leather-tunic': '53e22eac53457600003e3efc'
       'leather-boots': '53e2384453457600003e3f07'
       'programmaticon-i': '53e4108204c00d4607a89f78'
-      'crude-glasses': '53e238df53457600003e3f0b'
+      'crude-wooden-glasses': '53e238df53457600003e3f0b'
       'builders-hammer': '53f4e6e3d822c23505b74f42'
     gearByLevel =
       'dungeons-of-kithgard': {feet: 'simple-boots'}
       'gems-in-the-deep': {feet: 'simple-boots'}
       'forgetful-gemsmith': {feet: 'simple-boots'}
       'shadow-guard': {feet: 'simple-boots'}
-      'true-names': {feet: 'simple-boots', 'right-hand': 'longsword'}
-      'the-raised-sword': {feet: 'simple-boots', 'right-hand': 'longsword', torso: 'leather-tunic'}
+      'true-names': {feet: 'simple-boots', 'right-hand': 'simple-sword'}
+      'the-raised-sword': {feet: 'simple-boots', 'right-hand': 'simple-sword', torso: 'leather-tunic'}
       'the-first-kithmaze': {feet: 'simple-boots', 'programming-book': 'programmaticon-i'}
       'the-second-kithmaze': {feet: 'simple-boots', 'programming-book': 'programmaticon-i'}
-      'new-sight': {'right-hand': 'longsword', 'programming-book': 'programmaticon-i'}
-      'lowly-kithmen': {feet: 'simple-boots', 'right-hand': 'longsword', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
-      'closing-the-distance': {feet: 'simple-boots', 'right-hand': 'longsword', torso: 'leather-tunic', eyes: 'crude-glasses'}
-      'the-final-kithmaze': {feet: 'simple-boots', 'right-hand': 'longsword', torso: 'leather-tunic', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
+      'new-sight': {'right-hand': 'simple-sword', 'programming-book': 'programmaticon-i'}
+      'lowly-kithmen': {feet: 'simple-boots', 'right-hand': 'simple-sword', 'programming-book': 'programmaticon-i', eyes: 'crude-wooden-glasses'}
+      'closing-the-distance': {feet: 'simple-boots', 'right-hand': 'simple-sword', torso: 'leather-tunic', eyes: 'crude-wooden-glasses'}
+      'the-final-kithmaze': {feet: 'simple-boots', 'right-hand': 'simple-sword', torso: 'leather-tunic', 'programming-book': 'programmaticon-i', eyes: 'crude-wooden-glasses'}
       'kithgard-gates': {feet: 'simple-boots', 'right-hand': 'builders-hammer', torso: 'leather-tunic'}
       'defense-of-plainswood': {feet: 'simple-boots', 'right-hand': 'builders-hammer'}
       'winding-trail': {feet: 'leather-boots', 'right-hand': 'builders-hammer'}
-      'thornbush-farm': {feet: 'leather-boots', 'right-hand': 'builders-hammer', eyes: 'crude-glasses'}
-      'a-fiery-trap': {feet: 'leather-boots', 'right-hand': 'builders-hammer', eyes: 'crude-glasses'}
+      'thornbush-farm': {feet: 'leather-boots', 'right-hand': 'builders-hammer', eyes: 'crude-wooden-glasses'}
+      'a-fiery-trap': {feet: 'leather-boots', 'right-hand': 'builders-hammer', eyes: 'crude-wooden-glasses'}
     return unless necessaryGear = gearByLevel[@options.levelID]
     if @inserted
       if @supermodel.finished()
@@ -363,7 +373,7 @@ module.exports = class InventoryView extends CocoView
       inWorldMap = $('#world-map-view').length
       for slot, item of necessaryGear
         continue if item is 'leather-tunic' and inWorldMap  # Don't tell them they need it until they need it in the level
-        continue if equipment[slot] and not ((item is 'builders-hammer' and equipment[slot] is gear.longsword) or (item is 'leather-boots' and equipment[slot] is gear['simple-boots']))
+        continue if equipment[slot] and not ((item is 'builders-hammer' and equipment[slot] is gear['simple-sword']) or (item is 'leather-boots' and equipment[slot] is gear['simple-boots']))
         availableSlotSelector = "#available-equipment li[data-item-id='#{gear[item]}']"
         @highlightElement availableSlotSelector, delay: 500, sides: ['right'], rotation: Math.PI / 2
         @$el.find(availableSlotSelector).addClass 'should-equip'
@@ -386,6 +396,7 @@ module.exports = class InventoryView extends CocoView
   onHeroSelectionUpdated: (e) ->
     @selectedHero = e.hero
     @loadHero()
+    @$el.removeClass('Warrior Ranger Wizard').addClass(@selectedHero.get('heroClass'))
 
   loadHero: ->
     return unless @supermodel.finished() and @selectedHero and not @$el.hasClass 'secret'
diff --git a/server/commons/Handler.coffee b/server/commons/Handler.coffee
index 5cbd3e4d6..15ecc3b11 100644
--- a/server/commons/Handler.coffee
+++ b/server/commons/Handler.coffee
@@ -46,9 +46,9 @@ module.exports = class Handler
     omissions = ['original'].concat(deltasLib.DOC_SKIP_PATHS)
     delta = differ.diff(_.omit(document.toObject(), omissions), _.omit(req.body, omissions))
     flattened = deltasLib.flattenDelta(delta)
-    _.all(flattened, (delta) ->
+    _.all flattened, (delta) ->
       # sometimes coverage gets moved around... allow other changes to happen to i18nCoverage
-      return _.isArray(delta.o) and (('i18n' in delta.dataPath and delta.o.length is 1) or 'i18nCoverage' in delta.dataPath))
+      return _.isArray(delta.o) and (('i18n' in delta.dataPath and delta.o.length is 1) or 'i18nCoverage' in delta.dataPath)
 
   formatEntity: (req, document) -> document?.toObject()
   getEditableProperties: (req, document) ->
diff --git a/server/levels/thangs/thang_type_handler.coffee b/server/levels/thangs/thang_type_handler.coffee
index 69c663c1e..8013197dd 100644
--- a/server/levels/thangs/thang_type_handler.coffee
+++ b/server/levels/thangs/thang_type_handler.coffee
@@ -60,6 +60,7 @@ ThangTypeHandler = class ThangTypeHandler extends Handler
       query = slug: {$exists: true}
       if req.query.view is 'items'
         query.kind = 'Item'
+        query.gems = {$exists: true}  # Items without gems don't show up anywhere
       else if req.query.view is 'heroes'
         #query.kind = 'Hero'  # TODO: when all the heroes are tagged, just use this
         query.original = {$in: _.values heroes}  # TODO: when all the heroes are tagged, don't do this