diff --git a/game/modules/tome/ai/quests.lua b/game/modules/tome/ai/quests.lua
index ec73aefed7354094a06ef9bc6ddb7241ba068336..8324c42b757ad20f3215b8b0889e26b335909ce4 100644
--- a/game/modules/tome/ai/quests.lua
+++ b/game/modules/tome/ai/quests.lua
@@ -41,6 +41,7 @@ newAI("move_quest_limmir", function(self)
 		end
 	else
 		game.level.turn_counter = 370 * 10
+		game.level.max_turn_counter = 370 * 10
 		game.player.changed = true
 		self.ai = "none"
 		self:doEmote("This place is corrupted! I will cleanse it! Protect me while I do it!", 120)
diff --git a/game/modules/tome/class/uiset/Minimalist.lua b/game/modules/tome/class/uiset/Minimalist.lua
index 863986941c6fa53051a819072f57666eba5af943..bd5de83753f4ac7fbd0d12ccdeb5bbb456543cae 100644
--- a/game/modules/tome/class/uiset/Minimalist.lua
+++ b/game/modules/tome/class/uiset/Minimalist.lua
@@ -105,6 +105,11 @@ fshat_psi_dark = {core.display.loadImage("/data/gfx/ui/resources/front_psi_dark.
 fshat_air = {core.display.loadImage("/data/gfx/ui/resources/front_air.png"):glTexture()}
 fshat_air_dark = {core.display.loadImage("/data/gfx/ui/resources/front_air_dark.png"):glTexture()}
 
+fshat_hourglass = {core.display.loadImage("/data/gfx/ui/resources/hourglass_front.png"):glTexture()}
+sshat_hourglass = {core.display.loadImage("/data/gfx/ui/resources/hourglass_shadow.png"):glTexture()}
+shat_hourglass_top = {core.display.loadImage("/data/gfx/ui/resources/hourglass_top.png"):glTexture()}
+shat_hourglass_bottom = {core.display.loadImage("/data/gfx/ui/resources/hourglass_bottom.png"):glTexture()}
+
 ammo_shadow_default = {core.display.loadImage("/data/gfx/ui/resources/ammo_shadow_default.png"):glTexture()}
 ammo_default = {core.display.loadImage("/data/gfx/ui/resources/ammo_default.png"):glTexture()}
 ammo_shadow_arrow = {core.display.loadImage("/data/gfx/ui/resources/ammo_shadow_arrow.png"):glTexture()}
@@ -810,6 +815,36 @@ function _M:displayResources(scale, bx, by)
 			if y > stop then x = x + fshat[6] y = 0 end
 		end
 
+		-----------------------------------------------------------------------------------
+		-- Hourglass
+		if game.level and game.level.turn_counter then
+			sshat_hourglass[1]:toScreenFull(x-6, y+8, sshat_hourglass[6], sshat_hourglass[7], sshat_hourglass[2], sshat_hourglass[3])
+			local c = game.level.turn_counter
+			local m = math.max(game.level.max_turn_counter, c)
+			local p = 1 - c / m
+			shat_hourglass_top[1]:toScreenPrecise(x+11, y+32 + shat_hourglass_top[7] * p, shat_hourglass_top[6], shat_hourglass_top[7] * (1-p), 0, 1/shat_hourglass_top[4], p/shat_hourglass_top[5], 1/shat_hourglass_top[5], save_c[1], save_c[2], save_c[3], 1)
+			shat_hourglass_bottom[1]:toScreenPrecise(x+12, y+72 + shat_hourglass_bottom[7] * (1-p), shat_hourglass_bottom[6], shat_hourglass_bottom[7] * p, 0, 1/shat_hourglass_bottom[4], (1-p)/shat_hourglass_bottom[5], 1/shat_hourglass_bottom[5], save_c[1], save_c[2], save_c[3], 1)
+
+			if not self.res.hourglass or self.res.hourglass.vc ~= c or self.res.hourglass.vm ~= m then
+				self.res.hourglass = {
+					vc = c, vm = m,
+					cur = {core.display.drawStringBlendedNewSurface(font_sha, ("%d"):format(c/10), 255, 255, 255):glTexture()},
+				}
+			end
+			local front = fshat_hourglass
+			local dt = self.res.hourglass.cur
+			dt[1]:toScreenFull(2+x+(front[6]-dt[6])/2, 2+y+90, dt[6], dt[7], dt[2], dt[3], 0, 0, 0, 0.7)
+			dt[1]:toScreenFull(x+(front[6]-dt[6])/2, y+90, dt[6], dt[7], dt[2], dt[3])
+
+			front[1]:toScreenFull(x, y, front[6], front[7], front[2], front[3])
+			y = y + front[7]
+			if y > stop then x = x + fshat[6] y = 0 end
+		end
+
+		-- Compute how much space to reserve on the side
+		self.side_4 = x + fshat[6]
+--		Map.viewport_padding_4 = math.floor(scale * (self.side_4 / Map.tile_w))
+
 		-----------------------------------------------------------------------------------
 		-- Saving
 		if savefile_pipe.saving then
diff --git a/game/modules/tome/data/gfx/ui/resources/hourglass_bottom.png b/game/modules/tome/data/gfx/ui/resources/hourglass_bottom.png
new file mode 100644
index 0000000000000000000000000000000000000000..c943aff96965ed51f5ea455a9d2c58b5a3fad3c9
Binary files /dev/null and b/game/modules/tome/data/gfx/ui/resources/hourglass_bottom.png differ
diff --git a/game/modules/tome/data/gfx/ui/resources/hourglass_front.png b/game/modules/tome/data/gfx/ui/resources/hourglass_front.png
new file mode 100644
index 0000000000000000000000000000000000000000..1a7fb984a35397a0d6a4afcc2c94ff97653d0862
Binary files /dev/null and b/game/modules/tome/data/gfx/ui/resources/hourglass_front.png differ
diff --git a/game/modules/tome/data/gfx/ui/resources/hourglass_shadow.png b/game/modules/tome/data/gfx/ui/resources/hourglass_shadow.png
new file mode 100644
index 0000000000000000000000000000000000000000..a800a8558d963a9b02b9cc0e88b8d82fbb3cb133
Binary files /dev/null and b/game/modules/tome/data/gfx/ui/resources/hourglass_shadow.png differ
diff --git a/game/modules/tome/data/gfx/ui/resources/hourglass_top.png b/game/modules/tome/data/gfx/ui/resources/hourglass_top.png
new file mode 100644
index 0000000000000000000000000000000000000000..535078b316af5e574d29d37489f3e533a335c50a
Binary files /dev/null and b/game/modules/tome/data/gfx/ui/resources/hourglass_top.png differ
diff --git a/game/modules/tome/data/zones/arena/zone.lua b/game/modules/tome/data/zones/arena/zone.lua
index e922d3a06c429a3495c46654fdaefd1fc98ddaa3..d3e2482d26e39d5fc668e81e6299033bc23cc3a3 100644
--- a/game/modules/tome/data/zones/arena/zone.lua
+++ b/game/modules/tome/data/zones/arena/zone.lua
@@ -109,6 +109,7 @@ return {
 		game.player:learnTalent(game.player.T_SHOOT, true, nil, {no_unlearn=true})
 		game.player.changed = true
 		level.turn_counter = 60 --5 turns before action starts.
+		level.max_turn_counter = 60 --5 turns before action starts.
 		--world.arena = nil
 		if not world.arena or not world.arena.ver then
 			local emptyScore = {name = nil, score = 0, perk = nil, wave = 1, sex = nil, race = nil, class = nil}
@@ -418,6 +419,7 @@ return {
 					end
 				end
 				game.level.turn_counter = rest_time * 10
+				game.level.max_turn_counter = rest_time * 10
 				game.level.arena.initWave(val)
 			end,
 			checkPinch = function ()
diff --git a/game/modules/tome/data/zones/charred-scar/zone.lua b/game/modules/tome/data/zones/charred-scar/zone.lua
index bc99a54fab3d072d71e63a59a731479d6079ea78..f95dfd72933658d24f47b7f18d35cc0dc36165bf 100644
--- a/game/modules/tome/data/zones/charred-scar/zone.lua
+++ b/game/modules/tome/data/zones/charred-scar/zone.lua
@@ -59,6 +59,7 @@ return {
 
 	post_process = function(level)
 		level.turn_counter = 600 * 10
+		level.max_turn_counter = 600 * 10
 	end,
 
 	on_enter = function(lev, old_lev, newzone)
diff --git a/game/modules/tome/data/zones/crypt-kryl-feijan/zone.lua b/game/modules/tome/data/zones/crypt-kryl-feijan/zone.lua
index b5998aa4b71627280b544c19a2b91d98079ed47d..773dfd52bde405004ac336f77fdea5cfb9d75235 100644
--- a/game/modules/tome/data/zones/crypt-kryl-feijan/zone.lua
+++ b/game/modules/tome/data/zones/crypt-kryl-feijan/zone.lua
@@ -68,6 +68,7 @@ return {
 			require("engine.ui.Dialog"):simplePopup("Crypt", "The chanting grows louder. You hear a sudden high-pitched scream.")
 		elseif lev == 5 then
 			game.level.turn_counter = 20 * 10
+			game.level.max_turn_counter = 20 * 10
 			game.player:grantQuest("kryl-feijan-escape")
 			game.player:learnLore("kryl-feijan-altar")
 		end