diff --git a/src/assets.lua b/src/assets.lua
index 972b732..11da147 100644
--- a/src/assets.lua
+++ b/src/assets.lua
@@ -28,6 +28,8 @@ TomatoSprite = playdate.graphics.image.new("assets/images/TomatoSprite.png")
 
 -- !!(dirLookup('assets/sounds', 'wav', 'playdate.sound.sampleplayer.new', 'pd_sampleplayer'))
 -- !!(dirLookup('assets/music', 'wav', 'playdate.sound.sampleplayer.new', 'pd_sampleplayer'))
--- !!(dirLookup('assets/fonts', 'fnt', 'playdate.graphics.font.new', 'pd_font', nil, nil, function(varName, value)
---     return varName:gsub("[- ]", "") .. " = " .. value:gsub("fnt", "pft")
--- end))
+-- luacheck: ignore
+---@type pd_font
+AshevilleSans14Bold = playdate.graphics.font.new("assets/fonts/Asheville-Sans-14-Bold.pft")
+
+
diff --git a/src/assets.lua2p b/src/assets.lua2p
index 99a0f6c..d200829 100644
--- a/src/assets.lua2p
+++ b/src/assets.lua2p
@@ -28,6 +28,6 @@ end)!!(generatedFileWarning())
 !!(dirLookup('assets/images', 'png', 'playdate.graphics.image.new', 'pd_image'))
 -- !!(dirLookup('assets/sounds', 'wav', 'playdate.sound.sampleplayer.new', 'pd_sampleplayer'))
 -- !!(dirLookup('assets/music', 'wav', 'playdate.sound.sampleplayer.new', 'pd_sampleplayer'))
--- !!(dirLookup('assets/fonts', 'fnt', 'playdate.graphics.font.new', 'pd_font', nil, nil, function(varName, value)
---     return varName:gsub("[- ]", "") .. " = " .. value:gsub("fnt", "pft")
--- end))
+!!(dirLookup('assets/fonts', 'fnt', 'playdate.graphics.font.new', 'pd_font', nil, nil, function(varName, value)
+    return varName:gsub("[- ]", "") .. " = " .. value:gsub("fnt", "pft")
+end))
diff --git a/src/assets/fonts/Asheville-Sans-14-Bold-table-20-20.png b/src/assets/fonts/Asheville-Sans-14-Bold-table-20-20.png
new file mode 100755
index 0000000..2b3c6a8
Binary files /dev/null and b/src/assets/fonts/Asheville-Sans-14-Bold-table-20-20.png differ
diff --git a/src/assets/fonts/Asheville-Sans-14-Bold.fnt b/src/assets/fonts/Asheville-Sans-14-Bold.fnt
new file mode 100755
index 0000000..3ee7fa3
--- /dev/null
+++ b/src/assets/fonts/Asheville-Sans-14-Bold.fnt
@@ -0,0 +1,295 @@
+tracking=1
+space	3
+!		2
+"		5
+#		9
+$		8
+%		12
+&		11
+'		3
+(		5
+)		5
+*		8
++		8
+,		3
+-		6
+.		2
+/		6
+0		9
+1		4
+2		9
+3		9
+4		9
+5		9
+6		9
+7		9
+8		10
+9		9
+:		2
+;		2
+<		7
+=		7
+>		7
+?		9
+@		11
+A		10
+B		9
+C		9
+D		9
+E		8
+F		8
+G		9
+H		9
+I		2
+J		8
+K		10
+L		9
+M		12
+N		9
+O		9
+P		9
+Q		9
+R		9
+S		9
+T		10
+U		9
+V		10
+W		14
+X		8
+Y		8
+Z		8
+[		3
+\		6
+]		3
+^		6
+_		8
+`		3
+a		8
+b		8
+c		8
+d		8
+e		8
+f		6
+g		8
+h		8
+i		2
+j		4
+k		8
+l		2
+m		12
+n		8
+o		8
+p		8
+q		8
+r		6
+s		8
+t		6
+u		8
+v		8
+w		12
+x		9
+y		8
+z		8
+{		6
+|		2
+}		6
+~		10
+…		8
+¥		8
+‼		5
+™		8
+©		11
+®		11
+。	16
+、	16
+ぁ	16
+あ	16
+ぃ	16
+い	16
+ぅ	16
+う	16
+ぇ	16
+え	16
+ぉ	16
+お	16
+か	16
+が	16
+き	16
+ぎ	16
+く	16
+ぐ	16
+け	16
+げ	16
+こ	16
+ご	16
+さ	16
+ざ	16
+し	16
+じ	16
+す	16
+ず	16
+せ	16
+ぜ	16
+そ	16
+ぞ	16
+た	16
+だ	16
+ち	16
+ぢ	16
+っ	16
+つ	16
+づ	16
+て	16
+で	16
+と	16
+ど	16
+な	16
+に	16
+ぬ	16
+ね	16
+の	16
+は	16
+ば	16
+ぱ	16
+ひ	16
+び	16
+ぴ	16
+ふ	16
+ぶ	16
+ぷ	16
+へ	16
+べ	16
+ぺ	16
+ほ	16
+ぼ	16
+ぽ	16
+ま	16
+み	16
+む	16
+め	16
+も	16
+ゃ	16
+や	16
+ゅ	16
+ゆ	16
+ょ	16
+よ	16
+ら	16
+り	16
+る	16
+れ	16
+ろ	16
+ゎ	16
+わ	16
+ゐ	16
+ゑ	16
+を	16
+ん	16
+ゔ	16
+ゕ	16
+ゖ	16
+゛	1
+゜	0
+ゝ	16
+ゞ	16
+ゟ	16
+゠	16
+ァ	16
+ア	16
+ィ	16
+イ	16
+ゥ	16
+ウ	16
+ェ	16
+エ	16
+ォ	16
+オ	16
+カ	16
+ガ	16
+キ	16
+ギ	16
+ク	16
+グ	16
+ケ	16
+ゲ	16
+コ	16
+ゴ	16
+サ	16
+ザ	16
+シ	16
+ジ	16
+ス	16
+ズ	16
+セ	16
+ゼ	16
+ソ	16
+ゾ	16
+タ	16
+ダ	16
+チ	16
+ヂ	16
+ッ	16
+ツ	16
+ヅ	16
+テ	16
+デ	16
+ト	16
+ド	16
+ナ	16
+ニ	16
+ヌ	16
+ネ	16
+ノ	16
+ハ	16
+バ	16
+パ	16
+ヒ	16
+ビ	16
+ピ	16
+フ	16
+ブ	16
+プ	16
+ヘ	16
+ベ	16
+ペ	16
+ホ	16
+ボ	16
+ポ	16
+マ	16
+ミ	16
+ム	16
+メ	16
+モ	16
+ャ	16
+ヤ	16
+ュ	16
+ユ	16
+ョ	16
+ヨ	16
+ラ	16
+リ	16
+ル	16
+レ	16
+ロ	16
+ヮ	16
+ワ	16
+ヰ	16
+ヱ	16
+ヲ	16
+ン	16
+ヴ	16
+ヵ	16
+ヶ	16
+ヷ	16
+ヸ	16
+ヹ	16
+ヺ	16
+・	16
+ー	16
+ヽ	16
+ヾ	16
+ヿ	16
+「	16
+」	16
+円	16
+�	13
\ No newline at end of file
diff --git a/src/main.lua b/src/main.lua
index 529c20b..3b31cf4 100644
--- a/src/main.lua
+++ b/src/main.lua
@@ -15,15 +15,19 @@ world = tiny.world()
 import("tiny-tools.lua")
 import("assets.lua")
 import("systems/filter-types.lua")
-import("systems/camera-pan.lua")
-import("systems/collision-detection.lua")
-import("systems/collision-resolution.lua")
-import("systems/draw.lua")
 import("systems/gravity.lua")
 import("systems/move-toward.lua")
+import("systems/velocity.lua")
 import("systems/rounds.lua")
 import("systems/spawner.lua")
-import("systems/velocity.lua")
+import("systems/camera-pan.lua")
+import("systems/collision-resolution.lua")
+import("systems/collision-detection.lua")
+
+import("systems/draw.lua")
+import("systems/input.lua")
+import("systems/menu.lua")
+
 import("ingredients/ingredients.lua")
 import("cart.lua")
 import("utils.lua")
@@ -79,7 +83,7 @@ function playdate.update()
 
     floor.position.x = Camera.pan.x - 600
 
-    world:update(deltaSeconds)
+    world:update(math.min(1 / 40, deltaSeconds))
 
     gfx.setDrawOffset(0, 0)
     Score:draw()
diff --git a/src/systems/draw.lua b/src/systems/draw.lua
index e683fdf..89c6020 100644
--- a/src/systems/draw.lua
+++ b/src/systems/draw.lua
@@ -4,10 +4,46 @@ drawRectanglesSystem = filteredSystem({ position = T.XyPair, drawAsRectangle = {
     gfx.fillRect(e.position.x, e.position.y, e.drawAsRectangle.size.x, e.drawAsRectangle.size.y)
 end)
 
-drawTextSystem = filteredSystem({ position = T.XyPair, drawAsText = { text = T.str } }, function(e, dt)
-    gfx.drawTextAligned(e.drawAsText.text, e.position.x, e.position.y, gfx.kAlignCenter)
-end)
-
 drawSpriteSystem = filteredSystem({ position = T.XyPair, drawAsSprite = T.PdImage }, function(e, dt, system)
     e.drawAsSprite:draw(e.position.x, e.position.y)
 end)
+
+local textHeight = AshevilleSans14Bold:getHeight()
+local xMargin = 4
+
+drawTextSystem = filteredSystem(
+    { position = T.XyPair, drawAsText = { text = T.str, style = Maybe(T.str) } },
+    function(e, dt)
+        local textWidth = AshevilleSans14Bold:getTextWidth(e.drawAsText.text)
+        if e.drawAsText.style == TextStyle.Inverted then
+            gfx.fillRect(
+                e.position.x - xMargin - textWidth / 2,
+                e.position.y - 2,
+                textWidth + (xMargin * 2),
+                textHeight + 2
+            )
+            gfx.setImageDrawMode(gfx.kDrawModeInverted)
+        end
+        if e.drawAsText.style == TextStyle.Bordered then
+            gfx.setColor(gfx.kColorWhite)
+            gfx.fillRect(
+                e.position.x - xMargin - textWidth / 2,
+                e.position.y - 2,
+                textWidth + (xMargin * 2),
+                textHeight + 2
+            )
+            gfx.setColor(gfx.kColorBlack)
+            gfx.setImageDrawMode(gfx.kDrawModeCopy)
+            gfx.drawRect(
+                e.position.x - xMargin - textWidth / 2,
+                e.position.y - 2,
+                textWidth + (xMargin * 2),
+                textHeight + 2
+            )
+        end
+        AshevilleSans14Bold:drawTextAligned(e.drawAsText.text, e.position.x, e.position.y, kTextAlignment.center)
+        if e.drawAsText.style == TextStyle.Inverted then
+            gfx.setImageDrawMode(gfx.kDrawModeCopy)
+        end
+    end
+)
diff --git a/src/systems/filter-types.lua b/src/systems/filter-types.lua
index cadb85d..2667283 100644
--- a/src/systems/filter-types.lua
+++ b/src/systems/filter-types.lua
@@ -18,6 +18,8 @@ local XyPair = { x = 1, y = 1 }
 
 ---@alias CanSpawn { entity: Entity }
 
+---@alias InRelations Entity[]
+
 T = {
     XyPair = XyPair,
     bool = true,
@@ -49,6 +51,10 @@ T = {
     RoundStateAction = "start",
     ---@type CanSpawn
     CanSpawn = {},
+    ---@type InRelations
+    InRelations = {},
+    ---@type InputState
+    InputState = {},
 }
 
 ---@generic T
@@ -57,3 +63,9 @@ T = {
 function Maybe(t)
     return { maybe = t }
 end
+
+TextStyle = {
+    Inverted = "INVERTED",
+    Bordered = "BORDERED",
+    None = "None",
+}
diff --git a/src/systems/input.lua b/src/systems/input.lua
new file mode 100644
index 0000000..a226204
--- /dev/null
+++ b/src/systems/input.lua
@@ -0,0 +1,18 @@
+---@alias InputState { upJustPressed: boolean, downJustPressed: boolean, rightJustPressed: boolean, leftJustPressed: boolean, aJustPressed: boolean, bJustPressed: boolean }
+
+local buttonJustPressed = playdate.buttonJustPressed
+local inputState = {}
+
+inputSystem = filteredSystem({ canReceiveInput = T.marker }, function(e, _, system)
+    e.inputState = inputState
+    system.world:addEntity(e)
+end)
+
+function inputSystem:preProcess()
+    inputState.upJustPressed = buttonJustPressed(playdate.kButtonUp)
+    inputState.downJustPressed = buttonJustPressed(playdate.kButtonDown)
+    inputState.rightJustPressed = buttonJustPressed(playdate.kButtonRight)
+    inputState.leftJustPressed = buttonJustPressed(playdate.kButtonLeft)
+    inputState.aJustPressed = buttonJustPressed(playdate.kButtonA)
+    inputState.bJustPressed = buttonJustPressed(playdate.kButtonB)
+end
diff --git a/src/systems/menu.lua b/src/systems/menu.lua
new file mode 100644
index 0000000..d226fc1
--- /dev/null
+++ b/src/systems/menu.lua
@@ -0,0 +1,26 @@
+menuController = filteredSystem({ menuItems = T.InRelations, inputState = T.InputState }, function(e, _, _)
+    for _, menuItem in pairs(e.menuItems) do
+        if menuItem.highlighted then
+            if e.inputState.aJustPressed then
+                menuItem.onSelect()
+            end
+            if e.inputState.downJustPressed and menuItem.navigateDown then
+                menuItem.highlighted = false
+                menuItem.navigateDown.highlighted = true
+                return
+            end
+            if e.inputState.upJustPressed and menuItem.navigateUp then
+                menuItem.highlighted = false
+                menuItem.navigateUp.highlighted = true
+                return
+            end
+        end
+    end
+    for _, menuItem in pairs(e.menuItems) do
+        if menuItem.highlighted then
+            menuItem.drawAsText.style = TextStyle.Inverted
+        else
+            menuItem.drawAsText.style = TextStyle.Bordered
+        end
+    end
+end)
diff --git a/src/systems/move-toward.lua b/src/systems/move-toward.lua
index bb0ece1..3777c09 100644
--- a/src/systems/move-toward.lua
+++ b/src/systems/move-toward.lua
@@ -15,27 +15,24 @@ local function normalizeVector(xy1, xy2)
     return x / distance, y / distance, distance
 end
 
-moveTowardSystem = filteredSystem(
-    { moveToward = MoveToward, position = T.XyPair },
-    function(e, dt, system)
-        local xNorm, yNorm, distance = normalizeVector(e.position, e.moveToward.target)
-        if distance > e.moveToward.range then
-            return
-        end
-
-        -- TODO May be incorrect when signs are mismatched between vel and diff
-        local xVel = xNorm * e.moveToward.speed * dt
-        if abs(e.position.x - e.moveToward.target.x) < abs(xVel) then
-            e.position.x = e.moveToward.target.x
-        else
-            e.position.x = e.position.x + xVel
-        end
-
-        local yVel = yNorm * e.moveToward.speed * dt
-        if abs(e.position.y - e.moveToward.target.y) < abs(yVel) then
-            e.position.y = e.moveToward.target.y
-        else
-            e.position.y = e.position.y + yVel
-        end
+moveTowardSystem = filteredSystem({ moveToward = MoveToward, position = T.XyPair }, function(e, dt, system)
+    local xNorm, yNorm, distance = normalizeVector(e.position, e.moveToward.target)
+    if distance > e.moveToward.range then
+        return
     end
-)
+
+    -- TODO May be incorrect when signs are mismatched between vel and diff
+    local xVel = xNorm * e.moveToward.speed * dt
+    if abs(e.position.x - e.moveToward.target.x) < abs(xVel) then
+        e.position.x = e.moveToward.target.x
+    else
+        e.position.x = e.position.x + xVel
+    end
+
+    local yVel = yNorm * e.moveToward.speed * dt
+    if abs(e.position.y - e.moveToward.target.y) < abs(yVel) then
+        e.position.y = e.moveToward.target.y
+    else
+        e.position.y = e.position.y + yVel
+    end
+end)
diff --git a/src/systems/rounds.lua b/src/systems/rounds.lua
index 344f1f3..3a5ec37 100644
--- a/src/systems/rounds.lua
+++ b/src/systems/rounds.lua
@@ -22,6 +22,8 @@ roundSystem = filteredSystem({ roundAction = T.RoundStateAction, position = Mayb
             stopMovingOnCollision = true,
         })
 
+        -- TODO: Big ol' numbers displaying how many ingredients were collected?
+        -- TODO: Could layer ingredients in rows of three? Maybe just when it's higher?
         local delayPerDrop = 150
         local delay = 0
         for i, collectable in ipairs(collectedEntities.entities) do
@@ -48,30 +50,51 @@ roundSystem = filteredSystem({ roundAction = T.RoundStateAction, position = Mayb
         end
 
         local availableUpgrades = Utils.getNDifferentValues(getAvailableSpawnerUpgrades(), 3)
+        -- Sorting from shortest to longest sort of makes them look like a bun?
+        table.sort(availableUpgrades, function(a, b)
+            return #a.name > #b.name
+        end)
 
         y = y - 50
+        local menuEntity = {
+            menuItems = {},
+            canReceiveInput = T.marker,
+        }
+        local upgradeBelow
         for _, upgrade in ipairs(availableUpgrades) do
-            printTable(upgrade)
-            local collX, collY = 75, 30
+            local collX, collY = 75, 21
             y = y - collY - 15
-            playdate.timer.new(delay, function(ee, ccollX, ccollY, yy, ii, ssystem, ccollectable)
-                ssystem.world:addEntity({
-                    drawAsText = {
-                        text = upgrade.name,
-                    },
-                    size = { x = ccollX, y = ccollY / 2 },
-                    mass = 0.5,
-                    velocity = { x = 0, y = 0 },
-                    position = { x = ee.position.x - (ccollX / 2), y = yy },
-                    canCollideWith = 2,
-                    canBeCollidedBy = 2,
-                    isSolid = true,
-                    stopMovingOnCollision = true,
-                    onCollidingRemove = onCollidingRemove,
-                    focusOnCollide = ii,
-                })
-            end, e, collX, collY, y, i, system, collectable)
+            local upgradeEntity = {
+                onSelect = upgrade.apply,
+                drawAsText = {
+                    text = upgrade.name,
+                    style = TextStyle.Inverted,
+                },
+                size = { x = collX, y = collY },
+                mass = 0.5,
+                velocity = { x = 0, y = 0 },
+                position = { x = e.position.x, y = y },
+                canCollideWith = 2,
+                canBeCollidedBy = 2,
+                isSolid = true,
+                stopMovingOnCollision = true,
+                onCollidingRemove = onCollidingRemove,
+                focusOnCollide = i,
+                navigateDown = upgradeBelow,
+                highlighted = true,
+            }
+            if upgradeBelow then
+                upgradeBelow.navigateUp = upgradeEntity
+                upgradeBelow.highlighted = false
+                upgradeBelow.drawAsText.style = TextStyle.Bordered
+            end
+            upgradeBelow = upgradeEntity
+            menuEntity.menuItems[#menuEntity.menuItems + 1] = upgradeEntity
+            playdate.timer.new(delay, function(_system, _upgradeEntity)
+                _system.world:addEntity(_upgradeEntity)
+            end, system, upgradeEntity)
             delay = delay + delayPerDrop
+            system.world:addEntity(menuEntity)
         end
         system.world:removeEntity(e)
     end
diff --git a/src/systems/spawner.lua b/src/systems/spawner.lua
index 3ff3efb..ed01416 100644
--- a/src/systems/spawner.lua
+++ b/src/systems/spawner.lua
@@ -109,7 +109,7 @@ function getAvailableSpawnerUpgrades()
     local upgrades = {}
     for _, spawner in pairs(spawnerSystem.entities) do
         if spawner.hasUpgradeSpeed then
-            upgrades[#upgrades + 1] = { hasUpgradeSpeed = spawner.hasUpgradeSpeed }
+            -- upgrades[#upgrades + 1] = { hasUpgradeSpeed = spawner.hasUpgradeSpeed }
         end
 
         if spawner.canSpawn.entity.score then
@@ -117,7 +117,7 @@ function getAvailableSpawnerUpgrades()
                 name = "Double " .. spawner.name .. " value",
                 apply = function()
                     spawner.canSpawn.entity.score = spawner.canSpawn.entity.score * 2
-                end
+                end,
             }
         end
 
@@ -126,7 +126,8 @@ function getAvailableSpawnerUpgrades()
             name = "Double " .. spawner.name .. " frequency",
             apply = function()
                 spawner.odds = spawner.odds * 2
-            end
+                -- addEntity({ roundAction = "NEXT_ROUND" })
+            end,
         }
 
         -- if not spawner.canSpawn.entity.velocity then
diff --git a/src/systems/velocity.lua b/src/systems/velocity.lua
index 8e2ed74..7de745d 100644
--- a/src/systems/velocity.lua
+++ b/src/systems/velocity.lua
@@ -1,10 +1,7 @@
 local sqrt = math.sqrt
 
 velocitySystem = filteredSystem({ position = T.XyPair, velocity = T.XyPair }, function(e, dt, system)
-    if not e.velocity then
-        return
-    end
-    if sqrt((e.velocity.x * e.velocity.x) + (e.velocity.y * e.velocity.y)) < 1.5 then
+    if sqrt((e.velocity.x * e.velocity.x) + (e.velocity.y * e.velocity.y)) < 2 then
         e.velocity = nil
         if e.spawnEntitiesWhenStopped then
             e:spawnEntitiesWhenStopped(system.world)
diff --git a/src/utils.lua b/src/utils.lua
index 189eaef..6281b04 100644
--- a/src/utils.lua
+++ b/src/utils.lua
@@ -25,4 +25,4 @@ function Utils.getNDifferentValues(fromArr, n)
         randoms[#randoms + 1] = fromArr[i]
     end
     return randoms
-end
\ No newline at end of file
+end