diff --git a/osu.Android.props b/osu.Android.props
index 85d154f2e2..71d4e5aacf 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -51,7 +51,7 @@
     <Reference Include="Java.Interop" />
   </ItemGroup>
   <ItemGroup>
-    <PackageReference Include="ppy.osu.Game.Resources" Version="2020.714.0" />
+    <PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" />
     <PackageReference Include="ppy.osu.Framework.Android" Version="2020.714.1" />
   </ItemGroup>
 </Project>
diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs
new file mode 100644
index 0000000000..f15da29993
--- /dev/null
+++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs
@@ -0,0 +1,56 @@
+// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Collections.Generic;
+using System.Linq;
+using NUnit.Framework;
+using osu.Framework.Allocation;
+using osu.Framework.Testing;
+using osu.Game.Beatmaps;
+using osu.Game.Configuration;
+using osu.Game.Rulesets.Catch.Mods;
+using osu.Game.Rulesets.Catch.Objects;
+using osu.Game.Rulesets.Catch.Objects.Drawables;
+using osu.Game.Rulesets.Catch.UI;
+using osu.Game.Rulesets.Objects;
+using osu.Game.Rulesets.Objects.Types;
+using osu.Game.Tests.Visual;
+using osuTK;
+
+namespace osu.Game.Rulesets.Catch.Tests
+{
+    public class TestSceneCatchModHidden : ModTestScene
+    {
+        [BackgroundDependencyLoader]
+        private void load()
+        {
+            LocalConfig.Set(OsuSetting.IncreaseFirstObjectVisibility, false);
+        }
+
+        [Test]
+        public void TestJuiceStream()
+        {
+            CreateModTest(new ModTestData
+            {
+                Beatmap = new Beatmap
+                {
+                    HitObjects = new List<HitObject>
+                    {
+                        new JuiceStream
+                        {
+                            StartTime = 1000,
+                            Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, new Vector2(0, -192) }),
+                            X = CatchPlayfield.WIDTH / 2
+                        }
+                    }
+                },
+                Mod = new CatchModHidden(),
+                PassCondition = () => Player.Results.Count > 0
+                                      && Player.ChildrenOfType<DrawableJuiceStream>().Single().Alpha > 0
+                                      && Player.ChildrenOfType<DrawableFruit>().Last().Alpha > 0
+            });
+        }
+
+        protected override Ruleset CreatePlayerRuleset() => new CatchRuleset();
+    }
+}
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs
index 0be949650e..4743317fdd 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs
@@ -11,6 +11,7 @@ using osu.Game.Rulesets.Scoring;
 using osu.Game.Screens.Play;
 using osu.Game.Screens.Play.Break;
 using osu.Game.Screens.Ranking;
+using osuTK.Input;
 
 namespace osu.Game.Tests.Visual.Gameplay
 {
@@ -35,6 +36,18 @@ namespace osu.Game.Tests.Visual.Gameplay
             AddStep("rewind", () => Player.GameplayClockContainer.Seek(-80000));
             AddUntilStep("key counter reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
 
+            double? time = null;
+
+            AddStep("store time", () => time = Player.GameplayClockContainer.GameplayClock.CurrentTime);
+
+            // test seek via keyboard
+            AddStep("seek with right arrow key", () => press(Key.Right));
+            AddAssert("time seeked forward", () => Player.GameplayClockContainer.GameplayClock.CurrentTime > time + 2000);
+
+            AddStep("store time", () => time = Player.GameplayClockContainer.GameplayClock.CurrentTime);
+            AddStep("seek with left arrow key", () => press(Key.Left));
+            AddAssert("time seeked backward", () => Player.GameplayClockContainer.GameplayClock.CurrentTime < time);
+
             seekToBreak(0);
             seekToBreak(1);
 
@@ -54,5 +67,11 @@ namespace osu.Game.Tests.Visual.Gameplay
 
             BreakPeriod destBreak() => Beatmap.Value.Beatmap.Breaks.ElementAt(breakIndex);
         }
+
+        private void press(Key key)
+        {
+            InputManager.PressKey(key);
+            InputManager.ReleaseKey(key);
+        }
     }
 }
diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs
index a3b102dc76..ee109189c7 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs
@@ -15,6 +15,7 @@ using osu.Game.Rulesets.Catch;
 using osu.Framework.Allocation;
 using osu.Game.Graphics.UserInterface;
 using osu.Game.Overlays;
+using osu.Game.Overlays.Rankings;
 
 namespace osu.Game.Tests.Visual.Online
 {
@@ -105,7 +106,7 @@ namespace osu.Game.Tests.Visual.Online
         {
             onLoadStarted();
 
-            request = new GetSpotlightRankingsRequest(ruleset, spotlight);
+            request = new GetSpotlightRankingsRequest(ruleset, spotlight, RankingsSortCriteria.All);
             ((GetSpotlightRankingsRequest)request).Success += rankings => Schedule(() =>
             {
                 var table = new ScoresTable(1, rankings.Users);
diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
new file mode 100644
index 0000000000..c2ac5179c9
--- /dev/null
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
@@ -0,0 +1,67 @@
+// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Game.Overlays.Comments.Buttons;
+using osu.Framework.Graphics;
+using osu.Framework.Allocation;
+using osu.Game.Overlays;
+using osu.Framework.Graphics.Containers;
+using osuTK;
+using NUnit.Framework;
+using System.Linq;
+using osu.Framework.Graphics.Sprites;
+using osu.Framework.Testing;
+
+namespace osu.Game.Tests.Visual.UserInterface
+{
+    public class TestSceneCommentRepliesButton : OsuTestScene
+    {
+        [Cached]
+        private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
+
+        private readonly TestButton button;
+
+        public TestSceneCommentRepliesButton()
+        {
+            Child = new FillFlowContainer
+            {
+                Anchor = Anchor.Centre,
+                Origin = Anchor.Centre,
+                AutoSizeAxes = Axes.Both,
+                Direction = FillDirection.Vertical,
+                Spacing = new Vector2(0, 10),
+                Children = new Drawable[]
+                {
+                    button = new TestButton(),
+                    new LoadRepliesButton
+                    {
+                        Action = () => { }
+                    },
+                    new ShowRepliesButton(1),
+                    new ShowRepliesButton(2)
+                }
+            };
+        }
+
+        [Test]
+        public void TestArrowDirection()
+        {
+            AddStep("Set upwards", () => button.SetIconDirection(true));
+            AddAssert("Icon facing upwards", () => button.Icon.Scale.Y == -1);
+            AddStep("Set downwards", () => button.SetIconDirection(false));
+            AddAssert("Icon facing downwards", () => button.Icon.Scale.Y == 1);
+        }
+
+        private class TestButton : CommentRepliesButton
+        {
+            public SpriteIcon Icon => this.ChildrenOfType<SpriteIcon>().First();
+
+            public TestButton()
+            {
+                Text = "sample text";
+            }
+
+            public new void SetIconDirection(bool upwards) => base.SetIconDirection(upwards);
+        }
+    }
+}
diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHueAnimation.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHueAnimation.cs
new file mode 100644
index 0000000000..9c5888d072
--- /dev/null
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHueAnimation.cs
@@ -0,0 +1,46 @@
+// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using NUnit.Framework;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Textures;
+using osu.Game.Graphics;
+using osu.Game.Graphics.Sprites;
+
+namespace osu.Game.Tests.Visual.UserInterface
+{
+    [TestFixture]
+    public class TestSceneHueAnimation : OsuTestScene
+    {
+        [BackgroundDependencyLoader]
+        private void load(LargeTextureStore textures)
+        {
+            HueAnimation anim2;
+
+            Add(anim2 = new HueAnimation
+            {
+                RelativeSizeAxes = Axes.Both,
+                FillMode = FillMode.Fit,
+                Texture = textures.Get("Intro/Triangles/logo-highlight"),
+                Colour = Colour4.White,
+            });
+
+            HueAnimation anim;
+
+            Add(anim = new HueAnimation
+            {
+                RelativeSizeAxes = Axes.Both,
+                FillMode = FillMode.Fit,
+                Texture = textures.Get("Intro/Triangles/logo-background"),
+                Colour = OsuColour.Gray(0.6f),
+            });
+
+            AddSliderStep("Progress", 0f, 1f, 0f, newValue =>
+            {
+                anim2.AnimationProgress = newValue;
+                anim.AnimationProgress = newValue;
+            });
+        }
+    }
+}
diff --git a/osu.Game/Graphics/Sprites/HueAnimation.cs b/osu.Game/Graphics/Sprites/HueAnimation.cs
new file mode 100644
index 0000000000..8ad68ace05
--- /dev/null
+++ b/osu.Game/Graphics/Sprites/HueAnimation.cs
@@ -0,0 +1,69 @@
+// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.OpenGL.Vertices;
+using osu.Framework.Graphics.Shaders;
+using osu.Framework.Graphics.Sprites;
+using osu.Framework.Graphics.Textures;
+
+namespace osu.Game.Graphics.Sprites
+{
+    public class HueAnimation : Sprite
+    {
+        [BackgroundDependencyLoader]
+        private void load(ShaderManager shaders, TextureStore textures)
+        {
+            TextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, @"HueAnimation");
+            RoundedTextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, @"HueAnimation"); // Masking isn't supported for now
+        }
+
+        private float animationProgress;
+
+        public float AnimationProgress
+        {
+            get => animationProgress;
+            set
+            {
+                if (animationProgress == value) return;
+
+                animationProgress = value;
+                Invalidate(Invalidation.DrawInfo);
+            }
+        }
+
+        public override bool IsPresent => true;
+
+        protected override DrawNode CreateDrawNode() => new HueAnimationDrawNode(this);
+
+        private class HueAnimationDrawNode : SpriteDrawNode
+        {
+            private HueAnimation source => (HueAnimation)Source;
+
+            private float progress;
+
+            public HueAnimationDrawNode(HueAnimation source)
+                : base(source)
+            {
+            }
+
+            public override void ApplyState()
+            {
+                base.ApplyState();
+
+                progress = source.animationProgress;
+            }
+
+            protected override void Blit(Action<TexturedVertex2D> vertexAction)
+            {
+                Shader.GetUniform<float>("progress").UpdateValue(ref progress);
+
+                base.Blit(vertexAction);
+            }
+
+            protected override bool CanDrawOpaqueInterior => false;
+        }
+    }
+}
diff --git a/osu.Game/Online/API/Requests/GetSpotlightRankingsRequest.cs b/osu.Game/Online/API/Requests/GetSpotlightRankingsRequest.cs
index a279db134f..25e6b3f1af 100644
--- a/osu.Game/Online/API/Requests/GetSpotlightRankingsRequest.cs
+++ b/osu.Game/Online/API/Requests/GetSpotlightRankingsRequest.cs
@@ -2,6 +2,7 @@
 // See the LICENCE file in the repository root for full licence text.
 
 using osu.Framework.IO.Network;
+using osu.Game.Overlays.Rankings;
 using osu.Game.Rulesets;
 
 namespace osu.Game.Online.API.Requests
@@ -9,11 +10,13 @@ namespace osu.Game.Online.API.Requests
     public class GetSpotlightRankingsRequest : GetRankingsRequest<GetSpotlightRankingsResponse>
     {
         private readonly int spotlight;
+        private readonly RankingsSortCriteria sort;
 
-        public GetSpotlightRankingsRequest(RulesetInfo ruleset, int spotlight)
+        public GetSpotlightRankingsRequest(RulesetInfo ruleset, int spotlight, RankingsSortCriteria sort)
             : base(ruleset, 1)
         {
             this.spotlight = spotlight;
+            this.sort = sort;
         }
 
         protected override WebRequest CreateWebRequest()
@@ -21,6 +24,7 @@ namespace osu.Game.Online.API.Requests
             var req = base.CreateWebRequest();
 
             req.AddParameter("spotlight", spotlight.ToString());
+            req.AddParameter("filter", sort.ToString().ToLower());
 
             return req;
         }
diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index 47a7c2ae11..618049e72c 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -573,7 +573,9 @@ namespace osu.Game
                             Origin = Anchor.BottomLeft,
                             Action = () =>
                             {
-                                if ((ScreenStack.CurrentScreen as IOsuScreen)?.AllowBackButton == true)
+                                var currentScreen = ScreenStack.CurrentScreen as IOsuScreen;
+
+                                if (currentScreen?.AllowBackButton == true && !currentScreen.OnBackButton())
                                     ScreenStack.Exit();
                             }
                         },
diff --git a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
new file mode 100644
index 0000000000..f7e0cb0a6c
--- /dev/null
+++ b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
@@ -0,0 +1,117 @@
+// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using osu.Framework.Graphics.Sprites;
+using osu.Framework.Input.Events;
+using osu.Game.Graphics;
+using osu.Game.Graphics.Sprites;
+using osu.Game.Graphics.UserInterface;
+using osuTK;
+
+namespace osu.Game.Overlays.Comments.Buttons
+{
+    public abstract class CommentRepliesButton : CompositeDrawable
+    {
+        protected string Text
+        {
+            get => text.Text;
+            set => text.Text = value;
+        }
+
+        [Resolved]
+        private OverlayColourProvider colourProvider { get; set; }
+
+        private readonly SpriteIcon icon;
+        private readonly Box background;
+        private readonly OsuSpriteText text;
+
+        protected CommentRepliesButton()
+        {
+            AutoSizeAxes = Axes.Both;
+            Margin = new MarginPadding
+            {
+                Vertical = 2
+            };
+            InternalChildren = new Drawable[]
+            {
+                new CircularContainer
+                {
+                    AutoSizeAxes = Axes.Both,
+                    Masking = true,
+                    Children = new Drawable[]
+                    {
+                        background = new Box
+                        {
+                            RelativeSizeAxes = Axes.Both
+                        },
+                        new Container
+                        {
+                            AutoSizeAxes = Axes.Both,
+                            Margin = new MarginPadding
+                            {
+                                Vertical = 5,
+                                Horizontal = 10,
+                            },
+                            Child = new FillFlowContainer
+                            {
+                                AutoSizeAxes = Axes.Both,
+                                Direction = FillDirection.Horizontal,
+                                Spacing = new Vector2(15, 0),
+                                Anchor = Anchor.Centre,
+                                Origin = Anchor.Centre,
+                                Children = new Drawable[]
+                                {
+                                    text = new OsuSpriteText
+                                    {
+                                        Anchor = Anchor.CentreLeft,
+                                        Origin = Anchor.CentreLeft,
+                                        AlwaysPresent = true,
+                                        Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold)
+                                    },
+                                    icon = new SpriteIcon
+                                    {
+                                        Anchor = Anchor.CentreLeft,
+                                        Origin = Anchor.CentreLeft,
+                                        Size = new Vector2(7.5f),
+                                        Icon = FontAwesome.Solid.ChevronDown
+                                    }
+                                }
+                            }
+                        }
+                    }
+                },
+                new HoverClickSounds(),
+            };
+        }
+
+        [BackgroundDependencyLoader]
+        private void load()
+        {
+            background.Colour = colourProvider.Background2;
+            icon.Colour = colourProvider.Foreground1;
+        }
+
+        protected void SetIconDirection(bool upwards) => icon.ScaleTo(new Vector2(1, upwards ? -1 : 1));
+
+        public void ToggleTextVisibility(bool visible) => text.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint);
+
+        protected override bool OnHover(HoverEvent e)
+        {
+            base.OnHover(e);
+            background.FadeColour(colourProvider.Background1, 200, Easing.OutQuint);
+            icon.FadeColour(colourProvider.Light1, 200, Easing.OutQuint);
+            return true;
+        }
+
+        protected override void OnHoverLost(HoverLostEvent e)
+        {
+            base.OnHoverLost(e);
+            background.FadeColour(colourProvider.Background2, 200, Easing.OutQuint);
+            icon.FadeColour(colourProvider.Foreground1, 200, Easing.OutQuint);
+        }
+    }
+}
diff --git a/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs
new file mode 100644
index 0000000000..4998e5391e
--- /dev/null
+++ b/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs
@@ -0,0 +1,32 @@
+// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Framework.Graphics;
+using osu.Game.Graphics.UserInterface;
+
+namespace osu.Game.Overlays.Comments.Buttons
+{
+    public class LoadRepliesButton : LoadingButton
+    {
+        private ButtonContent content;
+
+        public LoadRepliesButton()
+        {
+            AutoSizeAxes = Axes.Both;
+        }
+
+        protected override Drawable CreateContent() => content = new ButtonContent();
+
+        protected override void OnLoadStarted() => content.ToggleTextVisibility(false);
+
+        protected override void OnLoadFinished() => content.ToggleTextVisibility(true);
+
+        private class ButtonContent : CommentRepliesButton
+        {
+            public ButtonContent()
+            {
+                Text = "load replies";
+            }
+        }
+    }
+}
diff --git a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
new file mode 100644
index 0000000000..04e7e25cc5
--- /dev/null
+++ b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
@@ -0,0 +1,31 @@
+// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Humanizer;
+using osu.Framework.Bindables;
+using osu.Framework.Input.Events;
+
+namespace osu.Game.Overlays.Comments.Buttons
+{
+    public class ShowRepliesButton : CommentRepliesButton
+    {
+        public readonly BindableBool Expanded = new BindableBool(true);
+
+        public ShowRepliesButton(int count)
+        {
+            Text = "reply".ToQuantity(count);
+        }
+
+        protected override void LoadComplete()
+        {
+            base.LoadComplete();
+            Expanded.BindValueChanged(expanded => SetIconDirection(expanded.NewValue), true);
+        }
+
+        protected override bool OnClick(ClickEvent e)
+        {
+            Expanded.Toggle();
+            return true;
+        }
+    }
+}
diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs
index 46f600615a..3cdc0a0cbd 100644
--- a/osu.Game/Overlays/Comments/DrawableComment.cs
+++ b/osu.Game/Overlays/Comments/DrawableComment.cs
@@ -16,12 +16,12 @@ using System.Linq;
 using osu.Game.Graphics.Sprites;
 using osu.Game.Online.Chat;
 using osu.Framework.Allocation;
-using osuTK.Graphics;
 using System.Collections.Generic;
 using System;
 using osu.Framework.Graphics.Shapes;
 using osu.Framework.Extensions.IEnumerableExtensions;
 using System.Collections.Specialized;
+using osu.Game.Overlays.Comments.Buttons;
 
 namespace osu.Game.Overlays.Comments
 {
@@ -46,9 +46,9 @@ namespace osu.Game.Overlays.Comments
 
         private FillFlowContainer childCommentsVisibilityContainer;
         private FillFlowContainer childCommentsContainer;
-        private LoadMoreCommentsButton loadMoreCommentsButton;
+        private LoadRepliesButton loadRepliesButton;
         private ShowMoreButton showMoreButton;
-        private RepliesButton repliesButton;
+        private ShowRepliesButton showRepliesButton;
         private ChevronButton chevronButton;
         private DeletedCommentsCounter deletedCommentsCounter;
 
@@ -81,7 +81,7 @@ namespace osu.Game.Overlays.Comments
                         {
                             RelativeSizeAxes = Axes.X,
                             AutoSizeAxes = Axes.Y,
-                            Padding = new MarginPadding(margin) { Left = margin + 5 },
+                            Padding = new MarginPadding(margin) { Left = margin + 5, Top = Comment.IsTopLevel ? 10 : 0 },
                             Child = content = new GridContainer
                             {
                                 RelativeSizeAxes = Axes.X,
@@ -163,26 +163,34 @@ namespace osu.Game.Overlays.Comments
                                                     AutoSizeAxes = Axes.Y,
                                                     Padding = new MarginPadding { Right = 40 }
                                                 },
-                                                info = new FillFlowContainer
+                                                new FillFlowContainer
                                                 {
                                                     AutoSizeAxes = Axes.Both,
-                                                    Direction = FillDirection.Horizontal,
-                                                    Spacing = new Vector2(10, 0),
+                                                    Direction = FillDirection.Vertical,
                                                     Children = new Drawable[]
                                                     {
-                                                        new OsuSpriteText
+                                                        info = new FillFlowContainer
                                                         {
-                                                            Anchor = Anchor.CentreLeft,
-                                                            Origin = Anchor.CentreLeft,
-                                                            Font = OsuFont.GetFont(size: 12),
-                                                            Colour = OsuColour.Gray(0.7f),
-                                                            Text = HumanizerUtils.Humanize(Comment.CreatedAt)
+                                                            AutoSizeAxes = Axes.Both,
+                                                            Direction = FillDirection.Horizontal,
+                                                            Spacing = new Vector2(10, 0),
+                                                            Children = new Drawable[]
+                                                            {
+                                                                new OsuSpriteText
+                                                                {
+                                                                    Anchor = Anchor.CentreLeft,
+                                                                    Origin = Anchor.CentreLeft,
+                                                                    Font = OsuFont.GetFont(size: 12),
+                                                                    Colour = OsuColour.Gray(0.7f),
+                                                                    Text = HumanizerUtils.Humanize(Comment.CreatedAt)
+                                                                },
+                                                            }
                                                         },
-                                                        repliesButton = new RepliesButton(Comment.RepliesCount)
+                                                        showRepliesButton = new ShowRepliesButton(Comment.RepliesCount)
                                                         {
                                                             Expanded = { BindTarget = childrenExpanded }
                                                         },
-                                                        loadMoreCommentsButton = new LoadMoreCommentsButton
+                                                        loadRepliesButton = new LoadRepliesButton
                                                         {
                                                             Action = () => RepliesRequested(this, ++currentPage)
                                                         }
@@ -339,14 +347,14 @@ namespace osu.Game.Overlays.Comments
             var loadedReplesCount = loadedReplies.Count;
             var hasUnloadedReplies = loadedReplesCount != Comment.RepliesCount;
 
-            loadMoreCommentsButton.FadeTo(hasUnloadedReplies && loadedReplesCount == 0 ? 1 : 0);
+            loadRepliesButton.FadeTo(hasUnloadedReplies && loadedReplesCount == 0 ? 1 : 0);
             showMoreButton.FadeTo(hasUnloadedReplies && loadedReplesCount > 0 ? 1 : 0);
-            repliesButton.FadeTo(loadedReplesCount != 0 ? 1 : 0);
+            showRepliesButton.FadeTo(loadedReplesCount != 0 ? 1 : 0);
 
             if (Comment.IsTopLevel)
                 chevronButton.FadeTo(loadedReplesCount != 0 ? 1 : 0);
 
-            showMoreButton.IsLoading = loadMoreCommentsButton.IsLoading = false;
+            showMoreButton.IsLoading = loadRepliesButton.IsLoading = false;
         }
 
         private class ChevronButton : ShowChildrenButton
@@ -367,38 +375,6 @@ namespace osu.Game.Overlays.Comments
             }
         }
 
-        private class RepliesButton : ShowChildrenButton
-        {
-            private readonly SpriteText text;
-            private readonly int count;
-
-            public RepliesButton(int count)
-            {
-                this.count = count;
-
-                Child = text = new OsuSpriteText
-                {
-                    Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold),
-                };
-            }
-
-            protected override void OnExpandedChanged(ValueChangedEvent<bool> expanded)
-            {
-                text.Text = $@"{(expanded.NewValue ? "[-]" : "[+]")} replies ({count})";
-            }
-        }
-
-        private class LoadMoreCommentsButton : GetCommentRepliesButton
-        {
-            public LoadMoreCommentsButton()
-            {
-                IdleColour = OsuColour.Gray(0.7f);
-                HoverColour = Color4.White;
-            }
-
-            protected override string GetText() => @"[+] load replies";
-        }
-
         private class ShowMoreButton : GetCommentRepliesButton
         {
             [BackgroundDependencyLoader]
diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs
index 3d0ad1a594..8a5e4d2683 100644
--- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs
+++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs
@@ -19,6 +19,7 @@ using osu.Game.Graphics.Backgrounds;
 using osu.Game.Graphics.Containers;
 using osu.Game.Graphics.Sprites;
 using osu.Game.Graphics.UserInterface;
+using osu.Game.Input.Bindings;
 using osu.Game.Overlays.Mods.Sections;
 using osu.Game.Rulesets.Mods;
 using osu.Game.Screens;
@@ -403,6 +404,8 @@ namespace osu.Game.Overlays.Mods
             return base.OnKeyDown(e);
         }
 
+        public override bool OnPressed(GlobalAction action) => false; // handled by back button
+
         private void availableModsChanged(ValueChangedEvent<Dictionary<ModType, IReadOnlyList<Mod>>> mods)
         {
             if (mods.NewValue == null) return;
diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs
index f019b50ae8..f112c1ec43 100644
--- a/osu.Game/Overlays/Rankings/SpotlightSelector.cs
+++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs
@@ -22,10 +22,8 @@ namespace osu.Game.Overlays.Rankings
     {
         private const int duration = 300;
 
-        private readonly Box background;
-        private readonly SpotlightsDropdown dropdown;
-
         private readonly BindableWithCurrent<APISpotlight> current = new BindableWithCurrent<APISpotlight>();
+        public readonly Bindable<RankingsSortCriteria> Sort = new Bindable<RankingsSortCriteria>();
 
         public Bindable<APISpotlight> Current
         {
@@ -41,19 +39,22 @@ namespace osu.Game.Overlays.Rankings
 
         protected override bool StartHidden => true;
 
+        private readonly Box background;
+        private readonly Container content;
+        private readonly SpotlightsDropdown dropdown;
         private readonly InfoColumn startDateColumn;
         private readonly InfoColumn endDateColumn;
         private readonly InfoColumn mapCountColumn;
         private readonly InfoColumn participantsColumn;
-        private readonly Container content;
 
         public SpotlightSelector()
         {
             RelativeSizeAxes = Axes.X;
-            Height = 100;
+            AutoSizeAxes = Axes.Y;
             Add(content = new Container
             {
-                RelativeSizeAxes = Axes.Both,
+                RelativeSizeAxes = Axes.X,
+                AutoSizeAxes = Axes.Y,
                 Children = new Drawable[]
                 {
                     background = new Box
@@ -62,31 +63,55 @@ namespace osu.Game.Overlays.Rankings
                     },
                     new Container
                     {
-                        RelativeSizeAxes = Axes.Both,
-                        Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 },
-                        Children = new Drawable[]
+                        RelativeSizeAxes = Axes.X,
+                        AutoSizeAxes = Axes.Y,
+                        Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN },
+                        Child = new FillFlowContainer
                         {
-                            dropdown = new SpotlightsDropdown
+                            RelativeSizeAxes = Axes.X,
+                            AutoSizeAxes = Axes.Y,
+                            Direction = FillDirection.Vertical,
+                            Children = new Drawable[]
                             {
-                                Anchor = Anchor.TopCentre,
-                                Origin = Anchor.TopCentre,
-                                RelativeSizeAxes = Axes.X,
-                                Current = Current,
-                                Depth = -float.MaxValue
-                            },
-                            new FillFlowContainer
-                            {
-                                Anchor = Anchor.BottomRight,
-                                Origin = Anchor.BottomRight,
-                                AutoSizeAxes = Axes.Both,
-                                Direction = FillDirection.Horizontal,
-                                Spacing = new Vector2(15, 0),
-                                Children = new Drawable[]
+                                new Container
                                 {
-                                    startDateColumn = new InfoColumn(@"Start Date"),
-                                    endDateColumn = new InfoColumn(@"End Date"),
-                                    mapCountColumn = new InfoColumn(@"Map Count"),
-                                    participantsColumn = new InfoColumn(@"Participants")
+                                    Margin = new MarginPadding { Vertical = 20 },
+                                    RelativeSizeAxes = Axes.X,
+                                    Height = 40,
+                                    Depth = -float.MaxValue,
+                                    Child = dropdown = new SpotlightsDropdown
+                                    {
+                                        RelativeSizeAxes = Axes.X,
+                                        Current = Current
+                                    }
+                                },
+                                new Container
+                                {
+                                    RelativeSizeAxes = Axes.X,
+                                    AutoSizeAxes = Axes.Y,
+                                    Children = new Drawable[]
+                                    {
+                                        new FillFlowContainer
+                                        {
+                                            AutoSizeAxes = Axes.Both,
+                                            Direction = FillDirection.Horizontal,
+                                            Spacing = new Vector2(10, 0),
+                                            Margin = new MarginPadding { Bottom = 5 },
+                                            Children = new Drawable[]
+                                            {
+                                                startDateColumn = new InfoColumn(@"Start Date"),
+                                                endDateColumn = new InfoColumn(@"End Date"),
+                                                mapCountColumn = new InfoColumn(@"Map Count"),
+                                                participantsColumn = new InfoColumn(@"Participants")
+                                            }
+                                        },
+                                        new RankingsSortTabControl
+                                        {
+                                            Anchor = Anchor.CentreRight,
+                                            Origin = Anchor.CentreRight,
+                                            Current = Sort
+                                        }
+                                    }
                                 }
                             }
                         }
@@ -128,12 +153,13 @@ namespace osu.Game.Overlays.Rankings
             {
                 AutoSizeAxes = Axes.Both;
                 Direction = FillDirection.Vertical;
+                Margin = new MarginPadding { Vertical = 10 };
                 Children = new Drawable[]
                 {
                     new OsuSpriteText
                     {
                         Text = name,
-                        Font = OsuFont.GetFont(size: 10),
+                        Font = OsuFont.GetFont(size: 10, weight: FontWeight.Regular),
                     },
                     new Container
                     {
@@ -143,7 +169,7 @@ namespace osu.Game.Overlays.Rankings
                         {
                             Anchor = Anchor.BottomLeft,
                             Origin = Anchor.BottomLeft,
-                            Font = OsuFont.GetFont(size: 18, weight: FontWeight.Light),
+                            Font = OsuFont.GetFont(size: 20, weight: FontWeight.Light),
                         }
                     }
                 };
diff --git a/osu.Game/Overlays/Rankings/SpotlightsLayout.cs b/osu.Game/Overlays/Rankings/SpotlightsLayout.cs
index 917509e842..0f9b07bf89 100644
--- a/osu.Game/Overlays/Rankings/SpotlightsLayout.cs
+++ b/osu.Game/Overlays/Rankings/SpotlightsLayout.cs
@@ -24,6 +24,7 @@ namespace osu.Game.Overlays.Rankings
         public readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
 
         private readonly Bindable<APISpotlight> selectedSpotlight = new Bindable<APISpotlight>();
+        private readonly Bindable<RankingsSortCriteria> sort = new Bindable<RankingsSortCriteria>();
 
         [Resolved]
         private IAPIProvider api { get; set; }
@@ -72,6 +73,8 @@ namespace osu.Game.Overlays.Rankings
                     }
                 }
             };
+
+            sort.BindTo(selector.Sort);
         }
 
         protected override void LoadComplete()
@@ -80,7 +83,8 @@ namespace osu.Game.Overlays.Rankings
 
             selector.Show();
 
-            selectedSpotlight.BindValueChanged(onSpotlightChanged);
+            selectedSpotlight.BindValueChanged(_ => onSpotlightChanged());
+            sort.BindValueChanged(_ => onSpotlightChanged());
             Ruleset.BindValueChanged(onRulesetChanged);
 
             getSpotlights();
@@ -101,14 +105,14 @@ namespace osu.Game.Overlays.Rankings
             selectedSpotlight.TriggerChange();
         }
 
-        private void onSpotlightChanged(ValueChangedEvent<APISpotlight> spotlight)
+        private void onSpotlightChanged()
         {
             loading.Show();
 
             cancellationToken?.Cancel();
             getRankingsRequest?.Cancel();
 
-            getRankingsRequest = new GetSpotlightRankingsRequest(Ruleset.Value, spotlight.NewValue.Id);
+            getRankingsRequest = new GetSpotlightRankingsRequest(Ruleset.Value, selectedSpotlight.Value.Id, sort.Value);
             getRankingsRequest.Success += onSuccess;
             api.Queue(getRankingsRequest);
         }
diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
index 44afb7a227..b633cb0860 100644
--- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
+++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
@@ -147,8 +147,9 @@ namespace osu.Game.Rulesets.Objects.Drawables
             samplesBindable = HitObject.SamplesBindable.GetBoundCopy();
             samplesBindable.CollectionChanged += (_, __) => loadSamples();
 
-            updateState(ArmedState.Idle, true);
             apply(HitObject);
+
+            updateState(ArmedState.Idle, true);
         }
 
         private void loadSamples()
diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs
index 22fe0ad816..761f842c22 100644
--- a/osu.Game/Screens/IOsuScreen.cs
+++ b/osu.Game/Screens/IOsuScreen.cs
@@ -56,5 +56,14 @@ namespace osu.Game.Screens
         /// Whether mod rate adjustments are allowed to be applied.
         /// </summary>
         bool AllowRateAdjustments { get; }
+
+        /// <summary>
+        /// Invoked when the back button has been pressed to close any overlays before exiting this <see cref="IOsuScreen"/>.
+        /// </summary>
+        /// <remarks>
+        /// Return <c>true</c> to block this <see cref="IOsuScreen"/> from being exited after closing an overlay.
+        /// Return <c>false</c> if this <see cref="IOsuScreen"/> should continue exiting.
+        /// </remarks>
+        bool OnBackButton();
     }
 }
diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs
index 9be74a0fd9..b56ba6c8a4 100644
--- a/osu.Game/Screens/Menu/IntroTriangles.cs
+++ b/osu.Game/Screens/Menu/IntroTriangles.cs
@@ -3,7 +3,6 @@
 
 using System;
 using System.Collections.Generic;
-using System.IO;
 using osu.Framework.Allocation;
 using osu.Framework.Audio;
 using osu.Framework.Audio.Sample;
@@ -12,7 +11,6 @@ using osu.Framework.Graphics;
 using osu.Framework.Graphics.Containers;
 using osu.Framework.Graphics.Shapes;
 using osu.Framework.Graphics.Textures;
-using osu.Framework.Graphics.Video;
 using osu.Framework.Utils;
 using osu.Framework.Timing;
 using osu.Game.Graphics;
@@ -88,7 +86,7 @@ namespace osu.Game.Screens.Menu
             private RulesetFlow rulesets;
             private Container rulesetsScale;
             private Container logoContainerSecondary;
-            private Drawable lazerLogo;
+            private LazerLogo lazerLogo;
 
             private GlitchingTriangles triangles;
 
@@ -139,10 +137,10 @@ namespace osu.Game.Screens.Menu
                         RelativeSizeAxes = Axes.Both,
                         Anchor = Anchor.Centre,
                         Origin = Anchor.Centre,
-                        Child = lazerLogo = new LazerLogo(textures.GetStream("Menu/logo-triangles.mp4"))
+                        Child = lazerLogo = new LazerLogo
                         {
                             Anchor = Anchor.Centre,
-                            Origin = Anchor.Centre,
+                            Origin = Anchor.Centre
                         }
                     },
                 };
@@ -218,6 +216,9 @@ namespace osu.Game.Screens.Menu
 
                         // matching flyte curve y = 0.25x^2 + (max(0, x - 0.7) / 0.3) ^ 5
                         lazerLogo.FadeIn().ScaleTo(scale_start).Then().Delay(logo_scale_duration * 0.7f).ScaleTo(scale_start - scale_adjust, logo_scale_duration * 0.3f, Easing.InQuint);
+
+                        lazerLogo.TransformTo(nameof(LazerLogo.Progress), 1f, logo_scale_duration);
+
                         logoContainerSecondary.ScaleTo(scale_start).Then().ScaleTo(scale_start - scale_adjust * 0.25f, logo_scale_duration, Easing.InQuad);
                     }
 
@@ -259,20 +260,40 @@ namespace osu.Game.Screens.Menu
 
             private class LazerLogo : CompositeDrawable
             {
-                private readonly Stream videoStream;
+                private HueAnimation highlight, background;
 
-                public LazerLogo(Stream videoStream)
+                public float Progress
+                {
+                    get => background.AnimationProgress;
+                    set
+                    {
+                        background.AnimationProgress = value;
+                        highlight.AnimationProgress = value;
+                    }
+                }
+
+                public LazerLogo()
                 {
-                    this.videoStream = videoStream;
                     Size = new Vector2(960);
                 }
 
                 [BackgroundDependencyLoader]
-                private void load()
+                private void load(TextureStore textures)
                 {
-                    InternalChild = new Video(videoStream)
+                    InternalChildren = new Drawable[]
                     {
-                        RelativeSizeAxes = Axes.Both,
+                        highlight = new HueAnimation
+                        {
+                            RelativeSizeAxes = Axes.Both,
+                            Texture = textures.Get(@"Intro/Triangles/logo-highlight"),
+                            Colour = Color4.White,
+                        },
+                        background = new HueAnimation
+                        {
+                            RelativeSizeAxes = Axes.Both,
+                            Texture = textures.Get(@"Intro/Triangles/logo-background"),
+                            Colour = OsuColour.Gray(0.6f),
+                        },
                     };
                 }
             }
diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs
index 3178e35581..269eab5772 100644
--- a/osu.Game/Screens/Multi/Multiplayer.cs
+++ b/osu.Game/Screens/Multi/Multiplayer.cs
@@ -250,12 +250,6 @@ namespace osu.Game.Screens.Multi
         {
             roomManager.PartRoom();
 
-            if (screenStack.CurrentScreen != null && !(screenStack.CurrentScreen is LoungeSubScreen))
-            {
-                screenStack.Exit();
-                return true;
-            }
-
             waves.Hide();
 
             this.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut();
@@ -269,6 +263,20 @@ namespace osu.Game.Screens.Multi
             return false;
         }
 
+        public override bool OnBackButton()
+        {
+            if ((screenStack.CurrentScreen as IMultiplayerSubScreen)?.OnBackButton() == true)
+                return true;
+
+            if (screenStack.CurrentScreen != null && !(screenStack.CurrentScreen is LoungeSubScreen))
+            {
+                screenStack.Exit();
+                return true;
+            }
+
+            return false;
+        }
+
         protected override void LogoExiting(OsuLogo logo)
         {
             base.LogoExiting(logo);
diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs
index 35bb4fa34f..872a1cd39a 100644
--- a/osu.Game/Screens/OsuScreen.cs
+++ b/osu.Game/Screens/OsuScreen.cs
@@ -258,5 +258,7 @@ namespace osu.Game.Screens
         /// Note that the instance created may not be the used instance if it matches the BackgroundMode equality clause.
         /// </summary>
         protected virtual BackgroundScreen CreateBackground() => null;
+
+        public virtual bool OnBackButton() => false;
     }
 }
diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs
index 5052b32335..939b5fad1f 100644
--- a/osu.Game/Screens/Play/SongProgressBar.cs
+++ b/osu.Game/Screens/Play/SongProgressBar.cs
@@ -57,6 +57,8 @@ namespace osu.Game.Screens.Play
             set => CurrentNumber.Value = value;
         }
 
+        protected override bool AllowKeyboardInputWhenNotHovered => true;
+
         public SongProgressBar(float barHeight, float handleBarHeight, Vector2 handleSize)
         {
             CurrentNumber.MinValue = 0;
diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankText.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankText.cs
index 8343716e7e..cc732382f4 100644
--- a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankText.cs
+++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankText.cs
@@ -77,11 +77,10 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
                     Origin = Anchor.Centre,
                     BlurSigma = new Vector2(35),
                     BypassAutoSizeAxes = Axes.Both,
-                    RelativeSizeAxes = Axes.Both,
+                    Size = new Vector2(200),
                     CacheDrawnFrameBuffer = true,
                     Blending = BlendingParameters.Additive,
                     Alpha = 0,
-                    Size = new Vector2(2f), // increase buffer size to allow for scale
                     Scale = new Vector2(1.8f),
                     Children = new[]
                     {
@@ -122,15 +121,18 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
             }
 
             flash.Colour = OsuColour.ForRank(rank);
-            flash.FadeIn().Then().FadeOut(1200, Easing.OutQuint);
 
             if (rank >= ScoreRank.S)
                 rankText.ScaleTo(1.05f).ScaleTo(1, 3000, Easing.OutQuint);
 
             if (rank >= ScoreRank.X)
             {
-                flash.FadeIn().Then().FadeOut(3000);
-                superFlash.FadeIn().Then().FadeOut(800, Easing.OutQuint);
+                flash.FadeOutFromOne(3000);
+                superFlash.FadeOutFromOne(800, Easing.OutQuint);
+            }
+            else
+            {
+                flash.FadeOutFromOne(1200, Easing.OutQuint);
             }
         }
     }
diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs
index 49ce07b708..44458d8c8e 100644
--- a/osu.Game/Screens/Ranking/ResultsScreen.cs
+++ b/osu.Game/Screens/Ranking/ResultsScreen.cs
@@ -194,6 +194,13 @@ namespace osu.Game.Screens.Ranking
         }
 
         public override bool OnExiting(IScreen next)
+        {
+            Background.FadeTo(1, 250);
+
+            return base.OnExiting(next);
+        }
+
+        public override bool OnBackButton()
         {
             if (statisticsPanel.State.Value == Visibility.Visible)
             {
@@ -201,9 +208,7 @@ namespace osu.Game.Screens.Ranking
                 return true;
             }
 
-            Background.FadeTo(1, 250);
-
-            return base.OnExiting(next);
+            return false;
         }
 
         private void addScore(ScoreInfo score)
diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs
index e3705b15fa..74a5ee8309 100644
--- a/osu.Game/Screens/Select/SongSelect.cs
+++ b/osu.Game/Screens/Select/SongSelect.cs
@@ -599,12 +599,6 @@ namespace osu.Game.Screens.Select
 
         public override bool OnExiting(IScreen next)
         {
-            if (ModSelect.State.Value == Visibility.Visible)
-            {
-                ModSelect.Hide();
-                return true;
-            }
-
             if (base.OnExiting(next))
                 return true;
 
@@ -620,6 +614,17 @@ namespace osu.Game.Screens.Select
             return false;
         }
 
+        public override bool OnBackButton()
+        {
+            if (ModSelect.State.Value == Visibility.Visible)
+            {
+                ModSelect.Hide();
+                return true;
+            }
+
+            return false;
+        }
+
         protected override void Dispose(bool isDisposing)
         {
             base.Dispose(isDisposing);
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index b8e73262c4..2f3d08c528 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -25,7 +25,7 @@
     <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
     <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
     <PackageReference Include="ppy.osu.Framework" Version="2020.714.1" />
-    <PackageReference Include="ppy.osu.Game.Resources" Version="2020.714.0" />
+    <PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" />
     <PackageReference Include="Sentry" Version="2.1.4" />
     <PackageReference Include="SharpCompress" Version="0.25.1" />
     <PackageReference Include="NUnit" Version="3.12.0" />
diff --git a/osu.iOS.props b/osu.iOS.props
index 1faf60b1d9..2bb3914c25 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -71,7 +71,7 @@
   </ItemGroup>
   <ItemGroup Label="Package References">
     <PackageReference Include="ppy.osu.Framework.iOS" Version="2020.714.1" />
-    <PackageReference Include="ppy.osu.Game.Resources" Version="2020.714.0" />
+    <PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" />
   </ItemGroup>
   <!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
   <ItemGroup Label="Transitive Dependencies">