about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--MatrixRoomUtils.Core/AuthenticatedHomeServer.cs83
-rw-r--r--MatrixRoomUtils.Core/Authentication/MatrixAuth.cs32
-rw-r--r--MatrixRoomUtils.Core/Extensions/DictionaryExtensions.cs10
-rw-r--r--MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs37
-rw-r--r--MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs12
-rw-r--r--MatrixRoomUtils.Core/Extensions/ObjectExtensions.cs13
-rw-r--r--MatrixRoomUtils.Core/Extensions/StringExtensions.cs4
-rw-r--r--MatrixRoomUtils.Core/Interfaces/IHomeServer.cs86
-rw-r--r--MatrixRoomUtils.Core/MatrixException.cs57
-rw-r--r--MatrixRoomUtils.Core/RatelimitedHttpClient.cs7
-rw-r--r--MatrixRoomUtils.Core/RemoteHomeServer.cs35
-rw-r--r--MatrixRoomUtils.Core/Responses/Admin/AdminRoomListingResult.cs6
-rw-r--r--MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs234
-rw-r--r--MatrixRoomUtils.Core/Responses/LoginResponse.cs19
-rw-r--r--MatrixRoomUtils.Core/Responses/ProfileResponse.cs4
-rw-r--r--MatrixRoomUtils.Core/Responses/StateEventResponse.cs24
-rw-r--r--MatrixRoomUtils.Core/Room.cs112
-rw-r--r--MatrixRoomUtils.Core/RuntimeCache.cs119
-rw-r--r--MatrixRoomUtils.Core/StateEvent.cs46
-rw-r--r--MatrixRoomUtils.Core/StateEventStruct.cs3
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/PolicyRuleStateEventData.cs31
-rw-r--r--MatrixRoomUtils.Web.Server/MatrixRoomUtils.Web.Server.csproj28
-rw-r--r--MatrixRoomUtils.Web.Server/Pages/Error.cshtml49
-rw-r--r--MatrixRoomUtils.Web.Server/Pages/Error.cshtml.cs21
-rw-r--r--MatrixRoomUtils.Web.Server/Program.cs8
-rw-r--r--MatrixRoomUtils.Web.Server/Properties/launchSettings.json68
-rw-r--r--MatrixRoomUtils.Web/App.razor7
-rw-r--r--MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs48
-rw-r--r--MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs175
-rw-r--r--MatrixRoomUtils.Web/Classes/RoomCreationTemplates/IRoomCreationTemplate.cs3
-rw-r--r--MatrixRoomUtils.Web/FileUploadTest.razor3
-rw-r--r--MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj12
-rw-r--r--MatrixRoomUtils.Web/Pages/About.razor17
-rw-r--r--MatrixRoomUtils.Web/Pages/DataExportPage.razor31
-rw-r--r--MatrixRoomUtils.Web/Pages/DebugTools.razor48
-rw-r--r--MatrixRoomUtils.Web/Pages/DevOptions.razor44
-rw-r--r--MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor6
-rw-r--r--MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor71
-rw-r--r--MatrixRoomUtils.Web/Pages/Index.razor9
-rw-r--r--MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor84
-rw-r--r--MatrixRoomUtils.Web/Pages/LoginPage.razor30
-rw-r--r--MatrixRoomUtils.Web/Pages/MediaLocator.razor69
-rw-r--r--MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor113
-rw-r--r--MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor68
-rw-r--r--MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor50
-rw-r--r--MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor96
-rw-r--r--MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor69
-rw-r--r--MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerTimeline.razor16
-rw-r--r--MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor62
-rw-r--r--MatrixRoomUtils.Web/Pages/RoomState/RoomStateRoomList.razor25
-rw-r--r--MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor59
-rw-r--r--MatrixRoomUtils.Web/Program.cs5
-rw-r--r--MatrixRoomUtils.Web/Shared/EditablePre.razor10
-rw-r--r--MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor23
-rw-r--r--MatrixRoomUtils.Web/Shared/InlineUserItem.razor22
-rw-r--r--MatrixRoomUtils.Web/Shared/LogView.razor26
-rw-r--r--MatrixRoomUtils.Web/Shared/MainLayout.razor17
-rw-r--r--MatrixRoomUtils.Web/Shared/MainLayout.razor.css24
-rw-r--r--MatrixRoomUtils.Web/Shared/NavMenu.razor12
-rw-r--r--MatrixRoomUtils.Web/Shared/NavMenu.razor.css36
-rw-r--r--MatrixRoomUtils.Web/Shared/PortableDevTools.razor23
-rw-r--r--MatrixRoomUtils.Web/Shared/RoomListItem.razor91
-rw-r--r--MatrixRoomUtils.Web/Shared/RoomListItem.razor.css6
-rw-r--r--MatrixRoomUtils.Web/Shared/SimpleComponents/DictionaryEditor.razor21
-rw-r--r--MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor20
-rw-r--r--MatrixRoomUtils.Web/Shared/SimpleComponents/StringListEditor.razor14
-rw-r--r--MatrixRoomUtils.Web/Shared/SimpleComponents/ToggleSlider.razor6
-rw-r--r--MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor24
-rw-r--r--MatrixRoomUtils.Web/Shared/UserListItem.razor20
-rw-r--r--MatrixRoomUtils.Web/_Imports.razor10
-rw-r--r--MatrixRoomUtils.Web/wwwroot/css/app.css52
-rw-r--r--MatrixRoomUtils.Web/wwwroot/css/open-iconic/README.md11
-rw-r--r--MatrixRoomUtils.Web/wwwroot/css/open-iconic/font/fonts/open-iconic.svg1059
-rw-r--r--MatrixRoomUtils.Web/wwwroot/index.html10
-rw-r--r--MatrixRoomUtils.sln.DotSettings2
75 files changed, 1753 insertions, 2154 deletions
diff --git a/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs b/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs
index 368aa20..ee6be72 100644
--- a/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs
+++ b/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs
@@ -9,63 +9,47 @@ using MatrixRoomUtils.Core.Responses.Admin;
 
 namespace MatrixRoomUtils.Core;
 
-public class AuthenticatedHomeServer : IHomeServer
-{
-    public string UserId { get; set; }
-    public string AccessToken { get; set; }
+public class AuthenticatedHomeServer : IHomeServer {
     public readonly HomeserverAdminApi Admin;
 
-    public AuthenticatedHomeServer(string userId, string accessToken, string canonicalHomeServerDomain)
-    {
+    public AuthenticatedHomeServer(string userId, string accessToken, string canonicalHomeServerDomain) {
         UserId = userId;
         AccessToken = accessToken;
         HomeServerDomain = canonicalHomeServerDomain;
         Admin = new HomeserverAdminApi(this);
-        _httpClient = new HttpClient();
+        _httpClient = new MatrixHttpClient();
     }
 
-    public async Task<AuthenticatedHomeServer> Configure()
-    {
+    public string UserId { get; set; }
+    public string AccessToken { get; set; }
+
+    public async Task<AuthenticatedHomeServer> Configure() {
         FullHomeServerDomain = await ResolveHomeserverFromWellKnown(HomeServerDomain);
         _httpClient.Dispose();
-        _httpClient = new HttpClient { BaseAddress = new Uri(FullHomeServerDomain) };
+        _httpClient = new MatrixHttpClient { BaseAddress = new Uri(FullHomeServerDomain) };
         _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
         Console.WriteLine("[AHS] Finished setting up http client");
 
         return this;
     }
 
-    public async Task<Room> GetRoom(string roomId)
-    {
-        return new Room(_httpClient, roomId);
-    }
+    public async Task<Room> GetRoom(string roomId) => new Room(_httpClient, roomId);
 
-    public async Task<List<Room>> GetJoinedRooms()
-    {
+    public async Task<List<Room>> GetJoinedRooms() {
         var rooms = new List<Room>();
         var roomQuery = await _httpClient.GetAsync("/_matrix/client/v3/joined_rooms");
-        if (!roomQuery.IsSuccessStatusCode)
-        {
-            Console.WriteLine($"Failed to get rooms: {await roomQuery.Content.ReadAsStringAsync()}");
-            throw new InvalidDataException($"Failed to get rooms: {await roomQuery.Content.ReadAsStringAsync()}");
-        }
 
         var roomsJson = await roomQuery.Content.ReadFromJsonAsync<JsonElement>();
-        foreach (var room in roomsJson.GetProperty("joined_rooms").EnumerateArray())
-        {
-            rooms.Add(new Room(_httpClient, room.GetString()));
-        }
+        foreach (var room in roomsJson.GetProperty("joined_rooms").EnumerateArray()) rooms.Add(new Room(_httpClient, room.GetString()));
 
         Console.WriteLine($"Fetched {rooms.Count} rooms");
 
         return rooms;
     }
 
-    public async Task<string> UploadFile(string fileName, Stream fileStream, string contentType = "application/octet-stream")
-    {
+    public async Task<string> UploadFile(string fileName, Stream fileStream, string contentType = "application/octet-stream") {
         var res = await _httpClient.PostAsync($"/_matrix/media/r0/upload?filename={fileName}", new StreamContent(fileStream));
-        if (!res.IsSuccessStatusCode)
-        {
+        if (!res.IsSuccessStatusCode) {
             Console.WriteLine($"Failed to upload file: {await res.Content.ReadAsStringAsync()}");
             throw new InvalidDataException($"Failed to upload file: {await res.Content.ReadAsStringAsync()}");
         }
@@ -74,11 +58,9 @@ public class AuthenticatedHomeServer : IHomeServer
         return resJson.GetProperty("content_uri").GetString()!;
     }
 
-    public async Task<Room> CreateRoom(CreateRoomRequest creationEvent)
-    {
+    public async Task<Room> CreateRoom(CreateRoomRequest creationEvent) {
         var res = await _httpClient.PostAsJsonAsync("/_matrix/client/r0/createRoom", creationEvent);
-        if (!res.IsSuccessStatusCode)
-        {
+        if (!res.IsSuccessStatusCode) {
             Console.WriteLine($"Failed to create room: {await res.Content.ReadAsStringAsync()}");
             throw new InvalidDataException($"Failed to create room: {await res.Content.ReadAsStringAsync()}");
         }
@@ -86,47 +68,34 @@ public class AuthenticatedHomeServer : IHomeServer
         return await GetRoom((await res.Content.ReadFromJsonAsync<JsonObject>())!["room_id"]!.ToString());
     }
 
-    public class HomeserverAdminApi
-    {
+    public class HomeserverAdminApi {
         private readonly AuthenticatedHomeServer _authenticatedHomeServer;
 
-        public HomeserverAdminApi(AuthenticatedHomeServer authenticatedHomeServer)
-        {
-            _authenticatedHomeServer = authenticatedHomeServer;
-        }
+        public HomeserverAdminApi(AuthenticatedHomeServer authenticatedHomeServer) => _authenticatedHomeServer = authenticatedHomeServer;
 
-        public async IAsyncEnumerable<AdminRoomListingResult.AdminRoomListingResultRoom> SearchRoomsAsync(int limit = int.MaxValue, string orderBy = "name", string dir = "f", string? searchTerm = null, string? contentSearch = null)
-        {
+        public async IAsyncEnumerable<AdminRoomListingResult.AdminRoomListingResultRoom> SearchRoomsAsync(int limit = int.MaxValue, string orderBy = "name", string dir = "f", string? searchTerm = null, string? contentSearch = null) {
             AdminRoomListingResult? res = null;
-            int i = 0;
+            var i = 0;
             int? totalRooms = null;
-            do
-            {
+            do {
                 var url = $"/_synapse/admin/v1/rooms?limit={Math.Min(limit, 100)}&dir={dir}&order_by={orderBy}";
-                if (!string.IsNullOrEmpty(searchTerm))
-                {
-                    url += $"&search_term={searchTerm}";
-                }
+                if (!string.IsNullOrEmpty(searchTerm)) url += $"&search_term={searchTerm}";
+
+                if (res?.NextBatch != null) url += $"&from={res.NextBatch}";
 
-                if (res?.NextBatch != null)
-                {
-                    url += $"&from={res.NextBatch}";
-                }
                 Console.WriteLine($"--- ADMIN Querying Room List with URL: {url} - Already have {i} items... ---");
 
                 res = await _authenticatedHomeServer._httpClient.GetFromJsonAsync<AdminRoomListingResult>(url);
                 totalRooms ??= res?.TotalRooms;
-                Console.WriteLine(res.ToJson(indent:false));
-                foreach (var room in res.Rooms)
-                {
+                Console.WriteLine(res.ToJson(false));
+                foreach (var room in res.Rooms) {
                     if (contentSearch != null && !string.IsNullOrEmpty(contentSearch) &&
                         !(
                             room.Name?.Contains(contentSearch, StringComparison.InvariantCultureIgnoreCase) == true ||
                             room.CanonicalAlias?.Contains(contentSearch, StringComparison.InvariantCultureIgnoreCase) == true ||
                             room.Creator?.Contains(contentSearch, StringComparison.InvariantCultureIgnoreCase) == true
                         )
-                       )
-                    {
+                       ) {
                         totalRooms--;
                         continue;
                     }
diff --git a/MatrixRoomUtils.Core/Authentication/MatrixAuth.cs b/MatrixRoomUtils.Core/Authentication/MatrixAuth.cs
index b4b8d19..0f9eb58 100644
--- a/MatrixRoomUtils.Core/Authentication/MatrixAuth.cs
+++ b/MatrixRoomUtils.Core/Authentication/MatrixAuth.cs
@@ -5,35 +5,31 @@ using MatrixRoomUtils.Core.Responses;
 
 namespace MatrixRoomUtils.Core.Authentication;
 
-public class MatrixAuth
-{
-    public static async Task<LoginResponse> Login(string homeserver, string username, string password)
-    {
+public class MatrixAuth {
+    public static async Task<LoginResponse> Login(string homeserver, string username, string password) {
         Console.WriteLine($"Logging in to {homeserver} as {username}...");
         homeserver = (await new RemoteHomeServer(homeserver).Configure()).FullHomeServerDomain;
         var hc = new HttpClient();
-        var payload = new
-        {
+        var payload = new {
             type = "m.login.password",
-            identifier = new
-            {
+            identifier = new {
                 type = "m.id.user",
                 user = username
             },
-            password = password,
+            password,
             initial_device_display_name = "Rory&::MatrixRoomUtils"
         };
         Console.WriteLine($"Sending login request to {homeserver}...");
         var resp = await hc.PostAsJsonAsync($"{homeserver}/_matrix/client/r0/login", payload);
         Console.WriteLine($"Login: {resp.StatusCode}");
         var data = await resp.Content.ReadFromJsonAsync<JsonElement>();
-        if (!resp.IsSuccessStatusCode) Console.WriteLine("Login: " + data.ToString());
-        if (data.TryGetProperty("retry_after_ms", out var retryAfter))
-        {
+        if (!resp.IsSuccessStatusCode) Console.WriteLine("Login: " + data);
+        if (data.TryGetProperty("retry_after_ms", out var retryAfter)) {
             Console.WriteLine($"Login: Waiting {retryAfter.GetInt32()}ms before retrying");
             await Task.Delay(retryAfter.GetInt32());
             return await Login(homeserver, username, password);
         }
+
         Console.WriteLine($"Login: {data.ToJson()}");
         return data.Deserialize<LoginResponse>();
         //var token = data.GetProperty("access_token").GetString();
@@ -41,20 +37,16 @@ public class MatrixAuth
     }
 
     [Obsolete("Migrate to IHomeServer instance")]
-    public static async Task<ProfileResponse> GetProfile(string homeserver, string mxid) => 
-        await (await new RemoteHomeServer(homeserver).Configure()).GetProfile(mxid);
+    public static async Task<ProfileResponse> GetProfile(string homeserver, string mxid) => await (await new RemoteHomeServer(homeserver).Configure()).GetProfile(mxid);
 
-    private static async Task<bool> CheckSuccessStatus(string url)
-    {
+    private static async Task<bool> CheckSuccessStatus(string url) {
         //cors causes failure, try to catch
-        try
-        {
+        try {
             using var hc = new HttpClient();
             var resp = await hc.GetAsync(url);
             return resp.IsSuccessStatusCode;
         }
-        catch (Exception e)
-        {
+        catch (Exception e) {
             Console.WriteLine($"Failed to check success status: {e.Message}");
             return false;
         }
diff --git a/MatrixRoomUtils.Core/Extensions/DictionaryExtensions.cs b/MatrixRoomUtils.Core/Extensions/DictionaryExtensions.cs
index cce71dd..c51baec 100644
--- a/MatrixRoomUtils.Core/Extensions/DictionaryExtensions.cs
+++ b/MatrixRoomUtils.Core/Extensions/DictionaryExtensions.cs
@@ -1,15 +1,13 @@
 namespace MatrixRoomUtils.Core.Extensions;
 
-public static class DictionaryExtensions
-{
-    public static bool ChangeKey<TKey, TValue>(this IDictionary<TKey, TValue> dict, 
-        TKey oldKey, TKey newKey)
-    {
+public static class DictionaryExtensions {
+    public static bool ChangeKey<TKey, TValue>(this IDictionary<TKey, TValue> dict,
+        TKey oldKey, TKey newKey) {
         TValue value;
         if (!dict.Remove(oldKey, out value))
             return false;
 
-        dict[newKey] = value;  // or dict.Add(newKey, value) depending on ur comfort
+        dict[newKey] = value; // or dict.Add(newKey, value) depending on ur comfort
         return true;
     }
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs b/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs
index 8eb0226..47b3121 100644
--- a/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs
+++ b/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs
@@ -1,19 +1,40 @@
+using System.Text.Json;
+
 namespace MatrixRoomUtils.Core.Extensions;
 
-public static class HttpClientExtensions
-{
-    public static async Task<bool> CheckSuccessStatus(this HttpClient hc, string url)
-    {
+public static class HttpClientExtensions {
+    public static async Task<bool> CheckSuccessStatus(this HttpClient hc, string url) {
         //cors causes failure, try to catch
-        try
-        {
+        try {
             var resp = await hc.GetAsync(url);
             return resp.IsSuccessStatusCode;
         }
-        catch (Exception e)
-        {
+        catch (Exception e) {
             Console.WriteLine($"Failed to check success status: {e.Message}");
             return false;
         }
     }
+}
+
+public class MatrixHttpClient : HttpClient {
+    public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
+        var a = await base.SendAsync(request, cancellationToken);
+        if (!a.IsSuccessStatusCode) {
+            Console.WriteLine($"Failed to send request: {a.StatusCode}");
+            var content = await a.Content.ReadAsStringAsync(cancellationToken);
+            if (content.StartsWith('{')) {
+                var ex = JsonSerializer.Deserialize<MatrixException>(content);
+                if (ex?.RetryAfterMs != null) {
+                    await Task.Delay(ex.RetryAfterMs.Value, cancellationToken);
+                    return await SendAsync(request, cancellationToken);
+                }
+
+                throw ex!;
+            }
+
+            throw new InvalidDataException("Encountered invalid data:\n" + content);
+        }
+
+        return a;
+    }
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs b/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs
index 725c832..b007136 100644
--- a/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs
+++ b/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs
@@ -5,18 +5,16 @@ using System.Text.Json.Serialization;
 
 namespace MatrixRoomUtils.Core.Extensions;
 
-public static class JsonElementExtensions
-{
-    public static void FindExtraJsonFields([DisallowNull] this JsonElement? res, Type t)
-    {
+public static class JsonElementExtensions {
+    public static void FindExtraJsonFields([DisallowNull] this JsonElement? res, Type t) {
         var props = t.GetProperties();
         var unknownPropertyFound = false;
-        foreach (var field in res.Value.EnumerateObject())
-        {
+        foreach (var field in res.Value.EnumerateObject()) {
             if (props.Any(x => x.GetCustomAttribute<JsonPropertyNameAttribute>()?.Name == field.Name)) continue;
             Console.WriteLine($"[!!] Unknown property {field.Name} in {t.Name}!");
             unknownPropertyFound = true;
         }
-        if(unknownPropertyFound) Console.WriteLine(res.Value.ToJson());
+
+        if (unknownPropertyFound) Console.WriteLine(res.Value.ToJson());
     }
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Extensions/ObjectExtensions.cs b/MatrixRoomUtils.Core/Extensions/ObjectExtensions.cs
index 5aa9645..812c81c 100644
--- a/MatrixRoomUtils.Core/Extensions/ObjectExtensions.cs
+++ b/MatrixRoomUtils.Core/Extensions/ObjectExtensions.cs
@@ -1,15 +1,14 @@
+using System.Text.Encodings.Web;
 using System.Text.Json;
 
 namespace MatrixRoomUtils.Core.Extensions;
 
-public static class ObjectExtensions
-{
-    public static string ToJson(this object obj, bool indent = true, bool ignoreNull = false, bool unsafeContent = false)
-    {
+public static class ObjectExtensions {
+    public static string ToJson(this object obj, bool indent = true, bool ignoreNull = false, bool unsafeContent = false) {
         var jso = new JsonSerializerOptions();
-        if(indent) jso.WriteIndented = true;
-        if(ignoreNull) jso.IgnoreNullValues = true;
-        if(unsafeContent) jso.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
+        if (indent) jso.WriteIndented = true;
+        if (ignoreNull) jso.IgnoreNullValues = true;
+        if (unsafeContent) jso.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
         return JsonSerializer.Serialize(obj, jso);
     }
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Extensions/StringExtensions.cs b/MatrixRoomUtils.Core/Extensions/StringExtensions.cs
index 8fadc6d..b81d59f 100644
--- a/MatrixRoomUtils.Core/Extensions/StringExtensions.cs
+++ b/MatrixRoomUtils.Core/Extensions/StringExtensions.cs
@@ -1,7 +1,6 @@
 namespace MatrixRoomUtils.Core.Extensions;
 
-public static class StringExtensions
-{
+public static class StringExtensions {
     // public static async Task<string> GetMediaUrl(this string MxcUrl)
     // {
     //     //MxcUrl: mxc://rory.gay/ocRVanZoUTCcifcVNwXgbtTg
@@ -11,5 +10,4 @@ public static class StringExtensions
     //     var mediaId = MxcUrl.Split('/')[3];
     //     return $"{(await new RemoteHomeServer(server).Configure()).FullHomeServerDomain}/_matrix/media/v3/download/{server}/{mediaId}";
     // }
-    
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs b/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs
index 3ae1355..9a9ba7a 100644
--- a/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs
+++ b/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs
@@ -5,35 +5,32 @@ using MatrixRoomUtils.Core.Responses;
 
 namespace MatrixRoomUtils.Core.Interfaces;
 
-public class IHomeServer
-{
-    private Dictionary<string, ProfileResponse?> _profileCache = new();
+public class IHomeServer {
+    private readonly Dictionary<string, ProfileResponse?> _profileCache = new();
     public string HomeServerDomain { get; set; }
     public string FullHomeServerDomain { get; set; }
 
-    private protected HttpClient _httpClient { get; set; } = new();
+    private protected MatrixHttpClient _httpClient { get; set; } = new();
 
-    public async Task<string> ResolveHomeserverFromWellKnown(string homeserver)
-    {
+    public async Task<string> ResolveHomeserverFromWellKnown(string homeserver) {
         var res = await _resolveHomeserverFromWellKnown(homeserver);
-        if(!res.StartsWith("http")) res = "https://" + res;
-        if(res.EndsWith(":443")) res = res.Substring(0, res.Length - 4);
+        if (!res.StartsWith("http")) res = "https://" + res;
+        if (res.EndsWith(":443")) res = res.Substring(0, res.Length - 4);
         return res;
     }
-    private async Task<string> _resolveHomeserverFromWellKnown(string homeserver)
-    {
-        if (RuntimeCache.HomeserverResolutionCache.Count == 0)
-        {
+
+    private async Task<string> _resolveHomeserverFromWellKnown(string homeserver) {
+        if (RuntimeCache.HomeserverResolutionCache.Count == 0) {
             Console.WriteLine("No cached homeservers, resolving...");
             await Task.Delay(Random.Shared.Next(1000, 5000));
-        } 
-        if (RuntimeCache.HomeserverResolutionCache.ContainsKey(homeserver))
-        {
-            if (RuntimeCache.HomeserverResolutionCache[homeserver].ResolutionTime < DateTime.Now.AddHours(1))
-            {
+        }
+
+        if (RuntimeCache.HomeserverResolutionCache.ContainsKey(homeserver)) {
+            if (RuntimeCache.HomeserverResolutionCache[homeserver].ResolutionTime < DateTime.Now.AddHours(1)) {
                 Console.WriteLine($"Found cached homeserver: {RuntimeCache.HomeserverResolutionCache[homeserver].Result}");
                 return RuntimeCache.HomeserverResolutionCache[homeserver].Result;
             }
+
             Console.WriteLine($"Cached homeserver expired, removing: {RuntimeCache.HomeserverResolutionCache[homeserver].Result}");
             RuntimeCache.HomeserverResolutionCache.Remove(homeserver);
         }
@@ -42,29 +39,25 @@ public class IHomeServer
         string result = null;
         Console.WriteLine($"Resolving homeserver: {homeserver}");
         if (!homeserver.StartsWith("http")) homeserver = "https://" + homeserver;
-        if (await _httpClient.CheckSuccessStatus($"{homeserver}/.well-known/matrix/client"))
-        {
-            Console.WriteLine($"Got successful response for client well-known...");
+        if (await _httpClient.CheckSuccessStatus($"{homeserver}/.well-known/matrix/client")) {
+            Console.WriteLine("Got successful response for client well-known...");
             var resp = await _httpClient.GetFromJsonAsync<JsonElement>($"{homeserver}/.well-known/matrix/client");
             Console.WriteLine($"Response: {resp.ToString()}");
             var hs = resp.GetProperty("m.homeserver").GetProperty("base_url").GetString();
             result = hs;
         }
-        else
-        {
-            Console.WriteLine($"No client well-known...");
-            if (await _httpClient.CheckSuccessStatus($"{homeserver}/.well-known/matrix/server"))
-            {
+        else {
+            Console.WriteLine("No client well-known...");
+            if (await _httpClient.CheckSuccessStatus($"{homeserver}/.well-known/matrix/server")) {
                 var resp = await _httpClient.GetFromJsonAsync<JsonElement>($"{homeserver}/.well-known/matrix/server");
                 var hs = resp.GetProperty("m.server").GetString();
                 result = hs;
             }
-            else
-            {
-                Console.WriteLine($"No server well-known...");
-                if (await _httpClient.CheckSuccessStatus($"{homeserver}/_matrix/client/versions")) result = homeserver;
-                else
-                {
+            else {
+                Console.WriteLine("No server well-known...");
+                if (await _httpClient.CheckSuccessStatus($"{homeserver}/_matrix/client/versions"))
+                    result = homeserver;
+                else {
                     Console.WriteLine("No homeserver on shortname...");
                     if (await _httpClient.CheckSuccessStatus($"{homeserver.Replace("//", "//matrix.")}/_matrix/client/versions")) result = homeserver.Replace("//", "//matrix.");
                     else Console.WriteLine($"Failed to resolve homeserver, not on {homeserver}, nor do client or server well-knowns exist!");
@@ -72,30 +65,27 @@ public class IHomeServer
             }
         }
 
-        if (result != null)
-        {
+        if (result != null) {
             Console.WriteLine($"Resolved homeserver: {homeserver} -> {result}");
-            RuntimeCache.HomeserverResolutionCache.TryAdd(homeserver, new()
-            {
+            RuntimeCache.HomeserverResolutionCache.TryAdd(homeserver, new HomeServerResolutionResult {
                 Result = result,
                 ResolutionTime = DateTime.Now
             });
             return result;
         }
+
         throw new InvalidDataException($"Failed to resolve homeserver, not on {homeserver}, nor do client or server well-knowns exist!");
     }
-    public async Task<ProfileResponse> GetProfile(string mxid, bool debounce = false, bool cache = true)
-    {
-        if (cache)
-        {
-            if(debounce) await Task.Delay(Random.Shared.Next(100, 500));
-            if (_profileCache.ContainsKey(mxid))
-            {
-                while (_profileCache[mxid] == null)
-                {
+
+    public async Task<ProfileResponse> GetProfile(string mxid, bool debounce = false, bool cache = true) {
+        if (cache) {
+            if (debounce) await Task.Delay(Random.Shared.Next(100, 500));
+            if (_profileCache.ContainsKey(mxid)) {
+                while (_profileCache[mxid] == null) {
                     Console.WriteLine($"Waiting for profile cache for {mxid}, currently {_profileCache[mxid]?.ToJson() ?? "null"} within {_profileCache.Count} profiles...");
                     await Task.Delay(Random.Shared.Next(50, 500));
                 }
+
                 return _profileCache[mxid];
             }
         }
@@ -103,13 +93,11 @@ public class IHomeServer
         _profileCache.Add(mxid, null);
         var resp = await _httpClient.GetAsync($"/_matrix/client/r0/profile/{mxid}");
         var data = await resp.Content.ReadFromJsonAsync<JsonElement>();
-        if(!resp.IsSuccessStatusCode) Console.WriteLine("Profile: " + data.ToString());
+        if (!resp.IsSuccessStatusCode) Console.WriteLine("Profile: " + data);
         var profile = data.Deserialize<ProfileResponse>();
         _profileCache[mxid] = profile;
         return profile;
     }
-    public string? ResolveMediaUri(string mxc)
-    {
-        return mxc.Replace("mxc://", $"{FullHomeServerDomain}/_matrix/media/r0/download/");
-    }
+
+    public string? ResolveMediaUri(string mxc) => mxc.Replace("mxc://", $"{FullHomeServerDomain}/_matrix/media/r0/download/");
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/MatrixException.cs b/MatrixRoomUtils.Core/MatrixException.cs
new file mode 100644
index 0000000..3df70e1
--- /dev/null
+++ b/MatrixRoomUtils.Core/MatrixException.cs
@@ -0,0 +1,57 @@
+using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.Extensions;
+
+namespace MatrixRoomUtils.Core;
+
+public class MatrixException : Exception {
+    [JsonPropertyName("errcode")]
+    public string ErrorCode { get; set; }
+
+    [JsonPropertyName("error")]
+    public string Error { get; set; }
+
+    [JsonPropertyName("soft_logout")]
+    public bool? SoftLogout { get; set; }
+
+    [JsonPropertyName("retry_after_ms")]
+    public int? RetryAfterMs { get; set; }
+
+    public override string Message =>
+        ErrorCode switch {
+            // common
+            "M_FORBIDDEN" => "You do not have permission to perform this action: " + Error,
+            "M_UNKNOWN_TOKEN" => "The access token specified was not recognised: " + Error + (SoftLogout == true ? " (soft logout)" : ""),
+            "M_MISSING_TOKEN" => "No access token was specified: " + Error,
+            "M_BAD_JSON" => "Request contained valid JSON, but it was malformed in some way: " + Error,
+            "M_NOT_JSON" => "Request did not contain valid JSON: " + Error,
+            "M_NOT_FOUND" => "The requested resource was not found: " + Error,
+            "M_LIMIT_EXCEEDED" => "Too many requests have been sent in a short period of time. Wait a while then try again: " + Error,
+            "M_UNRECOGNISED" => "The server did not recognise the request: " + Error,
+            "M_UNKOWN" => "The server encountered an unexpected error: " + Error,
+            // endpoint specific
+            "M_UNAUTHORIZED" => "The request did not contain valid authentication information for the target of the request: " + Error,
+            "M_USER_DEACTIVATED" => "The user ID associated with the request has been deactivated: " + Error,
+            "M_USER_IN_USE" => "The user ID associated with the request is already in use: " + Error,
+            "M_INVALID_USERNAME" => "The requested user ID is not valid: " + Error,
+            "M_ROOM_IN_USE" => "The room alias requested is already taken: " + Error,
+            "M_INVALID_ROOM_STATE" => "The room associated with the request is not in a valid state to perform the request: " + Error,
+            "M_THREEPID_IN_USE" => "The threepid requested is already associated with a user ID on this server: " + Error,
+            "M_THREEPID_NOT_FOUND" => "The threepid requested is not associated with any user ID: " + Error,
+            "M_THREEPID_AUTH_FAILED" => "The provided threepid and/or token was invalid: " + Error,
+            "M_THREEPID_DENIED" => "The homeserver does not permit the third party identifier in question: " + Error,
+            "M_SERVER_NOT_TRUSTED" => "The homeserver does not trust the identity server: " + Error,
+            "M_UNSUPPORTED_ROOM_VERSION" => "The room version is not supported: " + Error,
+            "M_INCOMPATIBLE_ROOM_VERSION" => "The room version is incompatible: " + Error,
+            "M_BAD_STATE" => "The request was invalid because the state was invalid: " + Error,
+            "M_GUEST_ACCESS_FORBIDDEN" => "Guest access is forbidden: " + Error,
+            "M_CAPTCHA_NEEDED" => "Captcha needed: " + Error,
+            "M_CAPTCHA_INVALID" => "Captcha invalid: " + Error,
+            "M_MISSING_PARAM" => "Missing parameter: " + Error,
+            "M_INVALID_PARAM" => "Invalid parameter: " + Error,
+            "M_TOO_LARGE" => "The request or entity was too large: " + Error,
+            "M_EXCLUSIVE" => "The resource being requested is reserved by an application service, or the application service making the request has not created the resource: " + Error,
+            "M_RESOURCE_LIMIT_EXCEEDED" => "Exceeded resource limit: " + Error,
+            "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM" => "Cannot leave server notice room: " + Error,
+            _ => "Unknown error: " + new { ErrorCode, Error, SoftLogout, RetryAfterMs }.ToJson()
+        };
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/RatelimitedHttpClient.cs b/MatrixRoomUtils.Core/RatelimitedHttpClient.cs
deleted file mode 100644
index 61eab07..0000000
--- a/MatrixRoomUtils.Core/RatelimitedHttpClient.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace MatrixRoomUtils.Core;
-
-public class RatelimitedHttpClient : HttpClient
-{
-    
-    
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/RemoteHomeServer.cs b/MatrixRoomUtils.Core/RemoteHomeServer.cs
index 942f873..3f50d2e 100644
--- a/MatrixRoomUtils.Core/RemoteHomeServer.cs
+++ b/MatrixRoomUtils.Core/RemoteHomeServer.cs
@@ -1,50 +1,39 @@
 using System.Net.Http.Json;
 using System.Text.Json;
+using MatrixRoomUtils.Core.Extensions;
 using MatrixRoomUtils.Core.Interfaces;
 
 namespace MatrixRoomUtils.Core;
 
-public class RemoteHomeServer : IHomeServer
-{
-
-
-    public RemoteHomeServer(string canonicalHomeServerDomain)
-    {
+public class RemoteHomeServer : IHomeServer {
+    public RemoteHomeServer(string canonicalHomeServerDomain) {
         HomeServerDomain = canonicalHomeServerDomain;
-        _httpClient = new HttpClient();
+        _httpClient = new MatrixHttpClient();
         _httpClient.Timeout = TimeSpan.FromSeconds(5);
     }
-    public async Task<RemoteHomeServer> Configure()
-    {
+
+    public async Task<RemoteHomeServer> Configure() {
         FullHomeServerDomain = await ResolveHomeserverFromWellKnown(HomeServerDomain);
         _httpClient.Dispose();
-        _httpClient = new HttpClient { BaseAddress = new Uri(FullHomeServerDomain) };
+        _httpClient = new MatrixHttpClient { BaseAddress = new Uri(FullHomeServerDomain) };
         _httpClient.Timeout = TimeSpan.FromSeconds(5);
         Console.WriteLine("[RHS] Finished setting up http client");
 
         return this;
     }
-    
-    public async Task<Room> GetRoom(string roomId)
-    {
-        return new Room(_httpClient, roomId);
-    }
 
-    public async Task<List<Room>> GetJoinedRooms()
-    {
+    public async Task<Room> GetRoom(string roomId) => new Room(_httpClient, roomId);
+
+    public async Task<List<Room>> GetJoinedRooms() {
         var rooms = new List<Room>();
         var roomQuery = await _httpClient.GetAsync("/_matrix/client/v3/joined_rooms");
-        if (!roomQuery.IsSuccessStatusCode)
-        {
+        if (!roomQuery.IsSuccessStatusCode) {
             Console.WriteLine($"Failed to get rooms: {await roomQuery.Content.ReadAsStringAsync()}");
             throw new InvalidDataException($"Failed to get rooms: {await roomQuery.Content.ReadAsStringAsync()}");
         }
 
         var roomsJson = await roomQuery.Content.ReadFromJsonAsync<JsonElement>();
-        foreach (var room in roomsJson.GetProperty("joined_rooms").EnumerateArray())
-        {
-            rooms.Add(new Room(_httpClient, room.GetString()));
-        }
+        foreach (var room in roomsJson.GetProperty("joined_rooms").EnumerateArray()) rooms.Add(new Room(_httpClient, room.GetString()));
 
         return rooms;
     }
diff --git a/MatrixRoomUtils.Core/Responses/Admin/AdminRoomListingResult.cs b/MatrixRoomUtils.Core/Responses/Admin/AdminRoomListingResult.cs
index 8ec0e4f..37bb3ba 100644
--- a/MatrixRoomUtils.Core/Responses/Admin/AdminRoomListingResult.cs
+++ b/MatrixRoomUtils.Core/Responses/Admin/AdminRoomListingResult.cs
@@ -2,8 +2,7 @@ using System.Text.Json.Serialization;
 
 namespace MatrixRoomUtils.Core.Responses.Admin;
 
-public class AdminRoomListingResult
-{
+public class AdminRoomListingResult {
     [JsonPropertyName("offset")]
     public int Offset { get; set; }
 
@@ -19,8 +18,7 @@ public class AdminRoomListingResult
     [JsonPropertyName("rooms")]
     public List<AdminRoomListingResultRoom> Rooms { get; set; } = new();
 
-    public class AdminRoomListingResultRoom
-    {
+    public class AdminRoomListingResultRoom {
         [JsonPropertyName("room_id")]
         public string RoomId { get; set; }
 
diff --git a/MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs b/MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs
index 5df99f7..da7d569 100644
--- a/MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs
+++ b/MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs
@@ -6,58 +6,56 @@ using MatrixRoomUtils.Core.Extensions;
 
 namespace MatrixRoomUtils.Core.Responses;
 
-public class CreateRoomRequest
-{
-    [JsonPropertyName("name")] public string Name { get; set; } = null!;
+public class CreateRoomRequest {
+    [JsonIgnore] public CreationContentBaseType _creationContentBaseType;
+
+    public CreateRoomRequest() => _creationContentBaseType = new CreationContentBaseType(this);
+
+    [JsonPropertyName("name")]
+    public string Name { get; set; } = null!;
 
-    [JsonPropertyName("room_alias_name")] public string RoomAliasName { get; set; } = null!;
+    [JsonPropertyName("room_alias_name")]
+    public string RoomAliasName { get; set; } = null!;
 
     //we dont want to use this, we want more control
     // [JsonPropertyName("preset")]
     // public string Preset { get; set; } = null!;
-    [JsonPropertyName("initial_state")] public List<StateEvent> InitialState { get; set; } = null!;
-    [JsonPropertyName("visibility")] public string Visibility { get; set; } = null!;
+    [JsonPropertyName("initial_state")]
+    public List<StateEvent> InitialState { get; set; } = null!;
+
+    [JsonPropertyName("visibility")]
+    public string Visibility { get; set; } = null!;
 
     [JsonPropertyName("power_level_content_override")]
     public PowerLevelEvent PowerLevelContentOverride { get; set; } = null!;
 
-    [JsonPropertyName("creation_content")] public JsonObject CreationContent { get; set; } = new();
+    [JsonPropertyName("creation_content")]
+    public JsonObject CreationContent { get; set; } = new();
 
     /// <summary>
-    /// For use only when you can't use the CreationContent property
+    ///     For use only when you can't use the CreationContent property
     /// </summary>
 
-    public StateEvent this[string event_type, string event_key = ""]
-    {
+    public StateEvent this[string event_type, string event_key = ""] {
         get => InitialState.First(x => x.Type == event_type && x.StateKey == event_key);
-        set
-        {
+        set {
             var stateEvent = InitialState.FirstOrDefault(x => x.Type == event_type && x.StateKey == event_key);
             if (stateEvent == null)
-            {
                 InitialState.Add(value);
-            }
             else
-            {
                 InitialState[InitialState.IndexOf(stateEvent)] = value;
-            }
         }
     }
 
     //extra properties
     [JsonIgnore]
-    public string HistoryVisibility
-    {
-        get
-        {
+    public string HistoryVisibility {
+        get {
             var stateEvent = InitialState.FirstOrDefault(x => x.Type == "m.room.history_visibility");
-            if (stateEvent == null)
-            {
-                InitialState.Add(new StateEvent()
-                {
+            if (stateEvent == null) {
+                InitialState.Add(new StateEvent {
                     Type = "m.room.history_visibility",
-                    Content = new JsonObject()
-                    {
+                    Content = new JsonObject {
                         ["history_visibility"] = "shared"
                     }
                 });
@@ -66,22 +64,16 @@ public class CreateRoomRequest
 
             return stateEvent.ContentAsJsonNode["history_visibility"].GetValue<string>();
         }
-        set
-        {
+        set {
             var stateEvent = InitialState.FirstOrDefault(x => x.Type == "m.room.history_visibility");
             if (stateEvent == null)
-            {
-                InitialState.Add(new StateEvent()
-                {
+                InitialState.Add(new StateEvent {
                     Type = "m.room.history_visibility",
-                    Content = new JsonObject()
-                    {
+                    Content = new JsonObject {
                         ["history_visibility"] = value
                     }
                 });
-            }
-            else
-            {
+            else {
                 var v = stateEvent.ContentAsJsonNode;
                 v["history_visibility"] = value;
                 stateEvent.ContentAsJsonNode = v;
@@ -90,18 +82,13 @@ public class CreateRoomRequest
     }
 
     [JsonIgnore]
-    public string RoomIcon
-    {
-        get
-        {
+    public string RoomIcon {
+        get {
             var stateEvent = InitialState.FirstOrDefault(x => x.Type == "m.room.avatar");
-            if (stateEvent == null)
-            {
-                InitialState.Add(new StateEvent()
-                {
+            if (stateEvent == null) {
+                InitialState.Add(new StateEvent {
                     Type = "m.room.avatar",
-                    Content = new JsonObject()
-                    {
+                    Content = new JsonObject {
                         ["url"] = ""
                     }
                 });
@@ -110,22 +97,16 @@ public class CreateRoomRequest
 
             return stateEvent.ContentAsJsonNode["url"].GetValue<string>();
         }
-        set
-        {
+        set {
             var stateEvent = InitialState.FirstOrDefault(x => x.Type == "m.room.avatar");
             if (stateEvent == null)
-            {
-                InitialState.Add(new StateEvent()
-                {
+                InitialState.Add(new StateEvent {
                     Type = "m.room.avatar",
-                    Content = new JsonObject()
-                    {
+                    Content = new JsonObject {
                         ["url"] = value
                     }
                 });
-            }
-            else
-            {
+            else {
                 var v = stateEvent.ContentAsJsonNode;
                 v["url"] = value;
                 stateEvent.ContentAsJsonNode = v;
@@ -177,64 +158,50 @@ public class CreateRoomRequest
     //     }
     // }
 
-    public ServerACL ServerACLs
-    {
-        get
-        {
+    public ServerACL ServerACLs {
+        get {
             var stateEvent = InitialState.FirstOrDefault(x => x.Type == "m.room.server_acl");
-            if (stateEvent == null)
-            {
-                InitialState.Add(new StateEvent()
-                {
+            if (stateEvent == null) {
+                InitialState.Add(new StateEvent {
                     Type = "m.room.server_acl",
-                    Content = new JsonObject()
-                    {
-                        ["allow"] = new JsonArray()
-                        {
+                    Content = new JsonObject {
+                        ["allow"] = new JsonArray {
                             "*"
                         },
                         ["deny"] = new JsonArray()
                     }
                 });
-                return new ServerACL()
-                {
-                    Allow = new List<string>()
-                    {
+                return new ServerACL {
+                    Allow = new List<string> {
                         "*"
                     },
                     Deny = new List<string>(),
                     AllowIpLiterals = true
                 };
             }
-            return new ServerACL()
-            {
-                Allow = JsonSerializer.Deserialize<List<string>>(stateEvent.ContentAsJsonNode["allow"]),
-                Deny = JsonSerializer.Deserialize<List<string>>(stateEvent.ContentAsJsonNode["deny"]),
+
+            return new ServerACL {
+                Allow = stateEvent.ContentAsJsonNode["allow"].Deserialize<List<string>>(),
+                Deny = stateEvent.ContentAsJsonNode["deny"].Deserialize<List<string>>(),
                 AllowIpLiterals = true
             };
         }
-        set
-        {
+        set {
             Console.WriteLine($"Setting server acl to {value.ToJson()}");
             var stateEvent = InitialState.FirstOrDefault(x => x.Type == "m.room.server_acl");
             if (stateEvent == null)
-            {
-                InitialState.Add(new StateEvent()
-                {
+                InitialState.Add(new StateEvent {
                     Type = "m.room.server_acl",
-                    Content = new JsonObject()
-                    {
-                        ["allow"] = JsonArray.Parse(JsonSerializer.Serialize(value.Allow)),
-                        ["deny"] = JsonArray.Parse(JsonSerializer.Serialize(value.Deny))
-                        ["allow_ip_literals"] = value.AllowIpLiterals
+                    Content = new JsonObject {
+                        ["allow"] = JsonNode.Parse(JsonSerializer.Serialize(value.Allow)),
+                        ["deny"] = JsonNode.Parse(JsonSerializer.Serialize(value.Deny))
+                            ["allow_ip_literals"] = value.AllowIpLiterals
                     }
                 });
-            }
-            else
-            {
+            else {
                 var v = stateEvent.ContentAsJsonNode;
-                v["allow"] = JsonArray.Parse(JsonSerializer.Serialize(value.Allow));
-                v["deny"] = JsonArray.Parse(JsonSerializer.Serialize(value.Deny));
+                v["allow"] = JsonNode.Parse(JsonSerializer.Serialize(value.Allow));
+                v["deny"] = JsonNode.Parse(JsonSerializer.Serialize(value.Deny));
                 v["allow_ip_literals"] = value.AllowIpLiterals;
                 stateEvent.ContentAsJsonNode = v;
                 Console.WriteLine($"v={v.ToJson()}");
@@ -243,14 +210,7 @@ public class CreateRoomRequest
         }
     }
 
-
-    [JsonIgnore] public CreationContentBaseType _creationContentBaseType;
-
-    public CreateRoomRequest() => _creationContentBaseType = new(this);
-
-
-    public Dictionary<string, string> Validate()
-    {
+    public Dictionary<string, string> Validate() {
         Dictionary<string, string> errors = new();
         if (!Regex.IsMatch(RoomAliasName, @"[a-zA-Z0-9_\-]+$"))
             errors.Add("room_alias_name", "Room alias name must only contain letters, numbers, underscores, and hyphens.");
@@ -259,49 +219,65 @@ public class CreateRoomRequest
     }
 }
 
-public class CreationContentBaseType
-{
+public class CreationContentBaseType {
     private readonly CreateRoomRequest createRoomRequest;
 
-    public CreationContentBaseType(CreateRoomRequest createRoomRequest)
-    {
-        this.createRoomRequest = createRoomRequest;
-    }
+    public CreationContentBaseType(CreateRoomRequest createRoomRequest) => this.createRoomRequest = createRoomRequest;
 
     [JsonPropertyName("type")]
-    public string Type
-    {
+    public string Type {
         get => (string)createRoomRequest.CreationContent["type"];
-        set
-        {
+        set {
             if (value is "null" or "") createRoomRequest.CreationContent.Remove("type");
             else createRoomRequest.CreationContent["type"] = value;
         }
     }
 }
 
-public class PowerLevelEvent
-{
-    [JsonPropertyName("ban")] public int Ban { get; set; } // = 50;
-    [JsonPropertyName("events_default")] public int EventsDefault { get; set; } // = 0;
-    [JsonPropertyName("events")] public Dictionary<string, int> Events { get; set; } // = null!;
-    [JsonPropertyName("invite")] public int Invite { get; set; } // = 50;
-    [JsonPropertyName("kick")] public int Kick { get; set; } // = 50;
-    [JsonPropertyName("notifications")] public NotificationsPL NotificationsPl { get; set; } // = null!;
-    [JsonPropertyName("redact")] public int Redact { get; set; } // = 50;
-    [JsonPropertyName("state_default")] public int StateDefault { get; set; } // = 50;
-    [JsonPropertyName("users")] public Dictionary<string, int> Users { get; set; } // = null!;
-    [JsonPropertyName("users_default")] public int UsersDefault { get; set; } // = 0;
+public class PowerLevelEvent {
+    [JsonPropertyName("ban")]
+    public int Ban { get; set; } // = 50;
+
+    [JsonPropertyName("events_default")]
+    public int EventsDefault { get; set; } // = 0;
+
+    [JsonPropertyName("events")]
+    public Dictionary<string, int> Events { get; set; } // = null!;
+
+    [JsonPropertyName("invite")]
+    public int Invite { get; set; } // = 50;
+
+    [JsonPropertyName("kick")]
+    public int Kick { get; set; } // = 50;
+
+    [JsonPropertyName("notifications")]
+    public NotificationsPL NotificationsPl { get; set; } // = null!;
+
+    [JsonPropertyName("redact")]
+    public int Redact { get; set; } // = 50;
+
+    [JsonPropertyName("state_default")]
+    public int StateDefault { get; set; } // = 50;
+
+    [JsonPropertyName("users")]
+    public Dictionary<string, int> Users { get; set; } // = null!;
+
+    [JsonPropertyName("users_default")]
+    public int UsersDefault { get; set; } // = 0;
 }
 
-public class NotificationsPL
-{
-    [JsonPropertyName("room")] public int Room { get; set; } = 50;
+public class NotificationsPL {
+    [JsonPropertyName("room")]
+    public int Room { get; set; } = 50;
 }
 
-public class ServerACL
-{
-    [JsonPropertyName("allow")] public List<string> Allow { get; set; } // = null!;
-    [JsonPropertyName("deny")] public List<string> Deny { get; set; } // = null!;
-    [JsonPropertyName("allow_ip_literals")] public bool AllowIpLiterals { get; set; } // = false;
+public class ServerACL {
+    [JsonPropertyName("allow")]
+    public List<string> Allow { get; set; } // = null!;
+
+    [JsonPropertyName("deny")]
+    public List<string> Deny { get; set; } // = null!;
+
+    [JsonPropertyName("allow_ip_literals")]
+    public bool AllowIpLiterals { get; set; } // = false;
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Responses/LoginResponse.cs b/MatrixRoomUtils.Core/Responses/LoginResponse.cs
index 34b42d1..3259e44 100644
--- a/MatrixRoomUtils.Core/Responses/LoginResponse.cs
+++ b/MatrixRoomUtils.Core/Responses/LoginResponse.cs
@@ -4,27 +4,26 @@ using System.Text.Json.Serialization;
 
 namespace MatrixRoomUtils.Core.Responses;
 
-public class LoginResponse
-{
+public class LoginResponse {
     [JsonPropertyName("access_token")]
     public string AccessToken { get; set; }
+
     [JsonPropertyName("device_id")]
     public string DeviceId { get; set; }
+
     [JsonPropertyName("home_server")]
     public string HomeServer { get; set; }
+
     [JsonPropertyName("user_id")]
     public string UserId { get; set; }
-    
-    public async Task<ProfileResponse> GetProfile()
-    {
+
+    public async Task<ProfileResponse> GetProfile() {
         var hc = new HttpClient();
         var resp = await hc.GetAsync($"{HomeServer}/_matrix/client/r0/profile/{UserId}");
         var data = await resp.Content.ReadFromJsonAsync<JsonElement>();
-        if(!resp.IsSuccessStatusCode) Console.WriteLine("Profile: " + data.ToString());
+        if (!resp.IsSuccessStatusCode) Console.WriteLine("Profile: " + data);
         return data.Deserialize<ProfileResponse>();
     }
-    public async Task<string> GetCanonicalHomeserverUrl()
-    {
-        return (await new RemoteHomeServer(HomeServer).Configure()).FullHomeServerDomain;
-    }
+
+    public async Task<string> GetCanonicalHomeserverUrl() => (await new RemoteHomeServer(HomeServer).Configure()).FullHomeServerDomain;
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Responses/ProfileResponse.cs b/MatrixRoomUtils.Core/Responses/ProfileResponse.cs
index 2c0b679..db72386 100644
--- a/MatrixRoomUtils.Core/Responses/ProfileResponse.cs
+++ b/MatrixRoomUtils.Core/Responses/ProfileResponse.cs
@@ -2,10 +2,10 @@ using System.Text.Json.Serialization;
 
 namespace MatrixRoomUtils.Core.Responses;
 
-public class ProfileResponse
-{
+public class ProfileResponse {
     [JsonPropertyName("avatar_url")]
     public string? AvatarUrl { get; set; } = "";
+
     [JsonPropertyName("displayname")]
     public string? DisplayName { get; set; } = "";
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Responses/StateEventResponse.cs b/MatrixRoomUtils.Core/Responses/StateEventResponse.cs
index 670c121..36f0a36 100644
--- a/MatrixRoomUtils.Core/Responses/StateEventResponse.cs
+++ b/MatrixRoomUtils.Core/Responses/StateEventResponse.cs
@@ -2,43 +2,47 @@ using System.Text.Json.Serialization;
 
 namespace MatrixRoomUtils.Core;
 
-public class StateEventResponse : StateEvent
-{
+public class StateEventResponse : StateEvent {
     [JsonPropertyName("origin_server_ts")]
     public ulong OriginServerTs { get; set; }
+
     [JsonPropertyName("room_id")]
     public string RoomId { get; set; }
+
     [JsonPropertyName("sender")]
     public string Sender { get; set; }
+
     [JsonPropertyName("unsigned")]
     public UnsignedData? Unsigned { get; set; }
+
     [JsonPropertyName("event_id")]
     public string EventId { get; set; }
+
     [JsonPropertyName("user_id")]
     public string UserId { get; set; }
+
     [JsonPropertyName("replaces_state")]
     public string ReplacesState { get; set; }
+
     [JsonPropertyName("prev_content")]
     public dynamic PrevContent { get; set; }
-    
-    
-    public class UnsignedData
-    {
+
+    public class UnsignedData {
         [JsonPropertyName("age")]
         public ulong Age { get; set; }
+
         [JsonPropertyName("prev_content")]
         public dynamic? PrevContent { get; set; }
+
         [JsonPropertyName("redacted_because")]
         public dynamic? RedactedBecause { get; set; }
+
         [JsonPropertyName("transaction_id")]
         public string? TransactionId { get; set; }
-        
     }
 }
 
-public class StateEventResponse<T> : StateEventResponse where T : class
-{
-    
+public class StateEventResponse<T> : StateEventResponse where T : class {
     [JsonPropertyName("content")]
     public T Content { get; set; }
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Room.cs b/MatrixRoomUtils.Core/Room.cs
index f228271..a867c0c 100644
--- a/MatrixRoomUtils.Core/Room.cs
+++ b/MatrixRoomUtils.Core/Room.cs
@@ -1,6 +1,4 @@
-using System.Diagnostics.CodeAnalysis;
 using System.Net.Http.Json;
-using System.Reflection;
 using System.Text.Json;
 using System.Text.Json.Serialization;
 using System.Web;
@@ -8,26 +6,23 @@ using MatrixRoomUtils.Core.Extensions;
 
 namespace MatrixRoomUtils.Core;
 
-public class Room
-{
+public class Room {
     private readonly HttpClient _httpClient;
-    public string RoomId { get; set; }
 
-    public Room(HttpClient httpClient, string roomId)
-    {
+    public Room(HttpClient httpClient, string roomId) {
         _httpClient = httpClient;
         RoomId = roomId;
     }
 
-    public async Task<JsonElement?> GetStateAsync(string type, string stateKey = "", bool logOnFailure = true)
-    {
+    public string RoomId { get; set; }
+
+    public async Task<JsonElement?> GetStateAsync(string type, string stateKey = "", bool logOnFailure = true) {
         var url = $"/_matrix/client/v3/rooms/{RoomId}/state";
         if (!string.IsNullOrEmpty(type)) url += $"/{type}";
         if (!string.IsNullOrEmpty(stateKey)) url += $"/{stateKey}";
 
         var res = await _httpClient.GetAsync(url);
-        if (!res.IsSuccessStatusCode)
-        {
+        if (!res.IsSuccessStatusCode) {
             if (logOnFailure) Console.WriteLine($"{RoomId}/{stateKey}/{type} - got status: {res.StatusCode}");
             return null;
         }
@@ -36,20 +31,17 @@ public class Room
         return result;
     }
 
-    public async Task<T?> GetStateAsync<T>(string type, string stateKey = "", bool logOnFailure = false)
-    {
+    public async Task<T?> GetStateAsync<T>(string type, string stateKey = "", bool logOnFailure = false) {
         var res = await GetStateAsync(type, stateKey, logOnFailure);
         if (res == null) return default;
         return res.Value.Deserialize<T>();
     }
-    
-    public async Task<MessagesResponse> GetMessagesAsync(string from = "", int limit = 10, string dir = "b", string filter = "")
-    {
+
+    public async Task<MessagesResponse> GetMessagesAsync(string from = "", int limit = 10, string dir = "b", string filter = "") {
         var url = $"/_matrix/client/r0/rooms/{RoomId}/messages?from={from}&limit={limit}&dir={dir}";
         if (!string.IsNullOrEmpty(filter)) url += $"&filter={filter}";
         var res = await _httpClient.GetAsync(url);
-        if (!res.IsSuccessStatusCode)
-        {
+        if (!res.IsSuccessStatusCode) {
             Console.WriteLine($"Failed to get messages for {RoomId} - got status: {res.StatusCode}");
             throw new Exception($"Failed to get messages for {RoomId} - got status: {res.StatusCode}");
         }
@@ -58,11 +50,9 @@ public class Room
         return result ?? new MessagesResponse();
     }
 
-    public async Task<string> GetNameAsync()
-    {
+    public async Task<string> GetNameAsync() {
         var res = await GetStateAsync("m.room.name");
-        if (!res.HasValue)
-        {
+        if (!res.HasValue) {
             Console.WriteLine($"Room {RoomId} has no name!");
             return RoomId;
         }
@@ -72,22 +62,19 @@ public class Room
         return resn;
     }
 
-    public async Task JoinAsync(string[]? homeservers = null)
-    {
-        string join_url = $"/_matrix/client/r0/join/{HttpUtility.UrlEncode(RoomId)}";
+    public async Task JoinAsync(string[]? homeservers = null) {
+        var join_url = $"/_matrix/client/r0/join/{HttpUtility.UrlEncode(RoomId)}";
         Console.WriteLine($"Calling {join_url} with {homeservers?.Length ?? 0} via's...");
         if (homeservers == null || homeservers.Length == 0) homeservers = new[] { RoomId.Split(':')[1] };
         var fullJoinUrl = $"{join_url}?server_name=" + string.Join("&server_name=", homeservers);
         var res = await _httpClient.PostAsync(fullJoinUrl, null);
     }
 
-    public async Task<List<string>> GetMembersAsync(bool joinedOnly = true)
-    {
+    public async Task<List<string>> GetMembersAsync(bool joinedOnly = true) {
         var res = await GetStateAsync("");
         if (!res.HasValue) return new List<string>();
         var members = new List<string>();
-        foreach (var member in res.Value.EnumerateArray())
-        {
+        foreach (var member in res.Value.EnumerateArray()) {
             if (member.GetProperty("type").GetString() != "m.room.member") continue;
             if (joinedOnly && member.GetProperty("content").GetProperty("membership").GetString() != "join") continue;
             var memberId = member.GetProperty("state_key").GetString();
@@ -97,63 +84,52 @@ public class Room
         return members;
     }
 
-    public async Task<List<string>> GetAliasesAsync()
-    {
+    public async Task<List<string>> GetAliasesAsync() {
         var res = await GetStateAsync("m.room.aliases");
         if (!res.HasValue) return new List<string>();
         var aliases = new List<string>();
-        foreach (var alias in res.Value.GetProperty("aliases").EnumerateArray())
-        {
-            aliases.Add(alias.GetString() ?? "");
-        }
+        foreach (var alias in res.Value.GetProperty("aliases").EnumerateArray()) aliases.Add(alias.GetString() ?? "");
 
         return aliases;
     }
 
-    public async Task<string> GetCanonicalAliasAsync()
-    {
+    public async Task<string> GetCanonicalAliasAsync() {
         var res = await GetStateAsync("m.room.canonical_alias");
         if (!res.HasValue) return "";
         return res.Value.GetProperty("alias").GetString() ?? "";
     }
 
-    public async Task<string> GetTopicAsync()
-    {
+    public async Task<string> GetTopicAsync() {
         var res = await GetStateAsync("m.room.topic");
         if (!res.HasValue) return "";
         return res.Value.GetProperty("topic").GetString() ?? "";
     }
 
-    public async Task<string> GetAvatarUrlAsync()
-    {
+    public async Task<string> GetAvatarUrlAsync() {
         var res = await GetStateAsync("m.room.avatar");
         if (!res.HasValue) return "";
         return res.Value.GetProperty("url").GetString() ?? "";
     }
 
-    public async Task<JoinRules> GetJoinRuleAsync()
-    {
+    public async Task<JoinRules> GetJoinRuleAsync() {
         var res = await GetStateAsync("m.room.join_rules");
         if (!res.HasValue) return new JoinRules();
         return res.Value.Deserialize<JoinRules>() ?? new JoinRules();
     }
 
-    public async Task<string> GetHistoryVisibilityAsync()
-    {
+    public async Task<string> GetHistoryVisibilityAsync() {
         var res = await GetStateAsync("m.room.history_visibility");
         if (!res.HasValue) return "";
         return res.Value.GetProperty("history_visibility").GetString() ?? "";
     }
 
-    public async Task<string> GetGuestAccessAsync()
-    {
+    public async Task<string> GetGuestAccessAsync() {
         var res = await GetStateAsync("m.room.guest_access");
         if (!res.HasValue) return "";
         return res.Value.GetProperty("guest_access").GetString() ?? "";
     }
 
-    public async Task<CreateEvent> GetCreateEventAsync()
-    {
+    public async Task<CreateEvent> GetCreateEventAsync() {
         var res = await GetStateAsync("m.room.create");
         if (!res.HasValue) return new CreateEvent();
 
@@ -163,33 +139,45 @@ public class Room
     }
 }
 
-public class MessagesResponse
-{
+public class MessagesResponse {
     [JsonPropertyName("start")]
     public string Start { get; set; }
+
     [JsonPropertyName("end")]
     public string? End { get; set; }
+
     [JsonPropertyName("chunk")]
     public List<StateEventResponse> Chunk { get; set; } = new();
+
     [JsonPropertyName("state")]
     public List<StateEventResponse> State { get; set; } = new();
 }
 
-public class CreateEvent
-{
-    [JsonPropertyName("creator")] public string Creator { get; set; }
-    [JsonPropertyName("room_version")] public string RoomVersion { get; set; }
-    [JsonPropertyName("type")] public string? Type { get; set; }
-    [JsonPropertyName("predecessor")] public object? Predecessor { get; set; }
-    [JsonPropertyName("m.federate")] public bool Federate { get; set; }
+public class CreateEvent {
+    [JsonPropertyName("creator")]
+    public string Creator { get; set; }
+
+    [JsonPropertyName("room_version")]
+    public string RoomVersion { get; set; }
+
+    [JsonPropertyName("type")]
+    public string? Type { get; set; }
+
+    [JsonPropertyName("predecessor")]
+    public object? Predecessor { get; set; }
+
+    [JsonPropertyName("m.federate")]
+    public bool Federate { get; set; }
 }
 
-public class JoinRules
-{
+public class JoinRules {
     private const string Public = "public";
     private const string Invite = "invite";
     private const string Knock = "knock";
 
-    [JsonPropertyName("join_rule")] public string JoinRule { get; set; }
-    [JsonPropertyName("allow")] public List<string> Allow { get; set; }
+    [JsonPropertyName("join_rule")]
+    public string JoinRule { get; set; }
+
+    [JsonPropertyName("allow")]
+    public List<string> Allow { get; set; }
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/RuntimeCache.cs b/MatrixRoomUtils.Core/RuntimeCache.cs
index 4f73341..a2fcf40 100644
--- a/MatrixRoomUtils.Core/RuntimeCache.cs
+++ b/MatrixRoomUtils.Core/RuntimeCache.cs
@@ -3,9 +3,21 @@ using MatrixRoomUtils.Core.Responses;
 
 namespace MatrixRoomUtils.Core;
 
-public class RuntimeCache
-{
+public class RuntimeCache {
     public static bool WasLoaded = false;
+
+    static RuntimeCache() =>
+        Task.Run(async () => {
+            while (true) {
+                await Task.Delay(1000);
+                foreach (var (key, value) in GenericResponseCache)
+                    if (value.Cache.Any())
+                        SaveObject("rory.matrixroomutils.generic_cache:" + key, value);
+                    else
+                        RemoveObject("rory.matrixroomutils.generic_cache:" + key);
+            }
+        });
+
     public static string? LastUsedToken { get; set; }
     public static AuthenticatedHomeServer CurrentHomeServer { get; set; }
     public static Dictionary<string, UserInfo> LoginSessions { get; set; } = new();
@@ -18,110 +30,69 @@ public class RuntimeCache
     public static Action Save { get; set; } = () => { Console.WriteLine("RuntimeCache.Save() was called, but no callback was set!"); };
     public static Action<string, object> SaveObject { get; set; } = (key, value) => { Console.WriteLine($"RuntimeCache.SaveObject({key}, {value}) was called, but no callback was set!"); };
     public static Action<string> RemoveObject { get; set; } = key => { Console.WriteLine($"RuntimeCache.RemoveObject({key}) was called, but no callback was set!"); };
-
-    static RuntimeCache()
-    {
-        Task.Run(async () =>
-        {
-            while(true)
-            {
-                await Task.Delay(1000);
-                foreach (var (key, value) in GenericResponseCache)
-                {
-                    if (value.Cache.Any())
-                        SaveObject("rory.matrixroomutils.generic_cache:" + key, value);
-                    else
-                    {
-                        RemoveObject("rory.matrixroomutils.generic_cache:" + key);
-                    }
-                }
-            }
-        });
-    }
 }
 
-public class UserInfo
-{
+public class UserInfo {
     public ProfileResponse Profile { get; set; } = new();
     public LoginResponse LoginResponse { get; set; }
 
-    public string AccessToken
-    {
-        get => LoginResponse.AccessToken;
-    }
+    public string AccessToken => LoginResponse.AccessToken;
 }
 
-public class HomeServerResolutionResult
-{
+public class HomeServerResolutionResult {
     public string Result { get; set; }
     public DateTime ResolutionTime { get; set; }
 }
 
-public class ObjectCache<T> where T : class
-{
+public class ObjectCache<T> where T : class {
+    public ObjectCache() =>
+        //expiry timer
+        Task.Run(async () => {
+            while (Cache.Any()) {
+                await Task.Delay(1000);
+                foreach (var x in Cache.Where(x => x.Value.ExpiryTime < DateTime.Now).OrderBy(x => x.Value.ExpiryTime).Take(15).ToList())
+                    // Console.WriteLine($"Removing {x.Key} from cache");
+                    Cache.Remove(x.Key);
+                //RuntimeCache.SaveObject("rory.matrixroomutils.generic_cache:" + Name, this);
+            }
+        });
+
     public Dictionary<string, GenericResult<T>> Cache { get; set; } = new();
     public string Name { get; set; } = null!;
 
-    public GenericResult<T> this[string key]
-    {
-        get
-        {
-            if (Cache.ContainsKey(key))
-            {
+    public GenericResult<T> this[string key] {
+        get {
+            if (Cache.ContainsKey(key)) {
                 // Console.WriteLine($"cache.get({key}): hit");
                 // Console.WriteLine($"Found item in cache: {key} - {Cache[key].Result.ToJson(indent: false)}");
                 if (Cache[key].ExpiryTime < DateTime.Now)
-                    Console.WriteLine($"WARNING: item {key} in cache {Name} expired at {Cache[key].ExpiryTime}:\n{Cache[key].Result.ToJson(indent: false)}");
+                    Console.WriteLine($"WARNING: item {key} in cache {Name} expired at {Cache[key].ExpiryTime}:\n{Cache[key].Result.ToJson(false)}");
                 return Cache[key];
             }
 
             Console.WriteLine($"cache.get({key}): miss");
             return null;
         }
-        set
-        {
-            Cache[key] = value;
-            // Console.WriteLine($"set({key}) = {Cache[key].Result.ToJson(indent:false)}");
-            // Console.WriteLine($"new_state: {this.ToJson(indent:false)}");
-            // Console.WriteLine($"New item in cache: {key} - {Cache[key].Result.ToJson(indent: false)}");
-            // Console.Error.WriteLine("Full cache: " + Cache.ToJson());
-        }
-    }
-
-    public ObjectCache()
-    {
-        //expiry timer
-        Task.Run(async () =>
-        {
-            while (Cache.Any())
-            {
-                await Task.Delay(1000);
-                foreach (var x in Cache.Where(x => x.Value.ExpiryTime < DateTime.Now).OrderBy(x => x.Value.ExpiryTime).Take(15).ToList())
-                {
-                    // Console.WriteLine($"Removing {x.Key} from cache");
-                    Cache.Remove(x.Key);
-                }
-                //RuntimeCache.SaveObject("rory.matrixroomutils.generic_cache:" + Name, this);
-            }
-        });
+        set => Cache[key] = value;
+        // Console.WriteLine($"set({key}) = {Cache[key].Result.ToJson(indent:false)}");
+        // Console.WriteLine($"new_state: {this.ToJson(indent:false)}");
+        // Console.WriteLine($"New item in cache: {key} - {Cache[key].Result.ToJson(indent: false)}");
+        // Console.Error.WriteLine("Full cache: " + Cache.ToJson());
     }
 
     public bool ContainsKey(string key) => Cache.ContainsKey(key);
 }
 
-public class GenericResult<T>
-{
-    public T? Result { get; set; }
-    public DateTime? ExpiryTime { get; set; } = DateTime.Now;
-
-    public GenericResult()
-    {
+public class GenericResult<T> {
+    public GenericResult() {
         //expiry timer
     }
 
-    public GenericResult(T? result, DateTime? expiryTime = null) : this()
-    {
+    public GenericResult(T? result, DateTime? expiryTime = null) : this() {
         Result = result;
         ExpiryTime = expiryTime;
     }
+
+    public T? Result { get; set; }
+    public DateTime? ExpiryTime { get; set; } = DateTime.Now;
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEvent.cs b/MatrixRoomUtils.Core/StateEvent.cs
index 6321fb6..a8c1fac 100644
--- a/MatrixRoomUtils.Core/StateEvent.cs
+++ b/MatrixRoomUtils.Core/StateEvent.cs
@@ -4,52 +4,48 @@ using System.Text.Json.Serialization;
 
 namespace MatrixRoomUtils.Core;
 
-public class StateEvent
-{
-    [JsonPropertyName("content")] public dynamic Content { get; set; } = new { };
+public class StateEvent {
+    [JsonPropertyName("content")]
+    public dynamic Content { get; set; } = new { };
+
+    [JsonPropertyName("state_key")]
+    public string StateKey { get; set; } = "";
 
-    [JsonPropertyName("state_key")] public string StateKey { get; set; } = "";
-    [JsonPropertyName("type")] public string Type { get; set; }
-    [JsonPropertyName("replaces_state")] public string? ReplacesState { get; set; }
+    [JsonPropertyName("type")]
+    public string Type { get; set; }
+
+    [JsonPropertyName("replaces_state")]
+    public string? ReplacesState { get; set; }
 
     //extra properties
     [JsonIgnore]
-    public JsonNode ContentAsJsonNode
-    {
+    public JsonNode ContentAsJsonNode {
         get => JsonSerializer.SerializeToNode(Content);
         set => Content = value;
     }
 
-    public StateEvent<T> As<T>() where T : class
-    {
-        return (StateEvent<T>)this;
-    }
-
-    public string dtype
-    {
-        get
-        {
-            string res = GetType().Name switch
-            {
+    public string dtype {
+        get {
+            var res = GetType().Name switch {
                 "StateEvent`1" => $"StateEvent<{Content.GetType().Name}>",
                 _ => GetType().Name
             };
             return res;
         }
     }
+
+    public StateEvent<T> As<T>() where T : class => (StateEvent<T>)this;
 }
 
-public class StateEvent<T> : StateEvent where T : class
-{
-    public StateEvent()
-    {
+public class StateEvent<T> : StateEvent where T : class {
+    public StateEvent() {
         //import base content if not an empty object
-        if (base.Content.GetType() == typeof(T))
-        {
+        if (base.Content.GetType() == typeof(T)) {
             Console.WriteLine($"StateEvent<{typeof(T)}> created with base content of type {base.Content.GetType()}. Importing base content.");
             Content = base.Content;
         }
     }
+
     [JsonPropertyName("content")]
     public new T Content { get; set; }
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventStruct.cs b/MatrixRoomUtils.Core/StateEventStruct.cs
index bfda594..cd301ac 100644
--- a/MatrixRoomUtils.Core/StateEventStruct.cs
+++ b/MatrixRoomUtils.Core/StateEventStruct.cs
@@ -1,7 +1,6 @@
 namespace MatrixRoomUtils.Core;
 
-public struct StateEventStruct
-{
+public struct StateEventStruct {
     public object content { get; set; }
     public long origin_server_ts { get; set; }
     public string sender { get; set; }
diff --git a/MatrixRoomUtils.Core/StateEventTypes/PolicyRuleStateEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/PolicyRuleStateEventData.cs
index a927ace..6f6d082 100644
--- a/MatrixRoomUtils.Core/StateEventTypes/PolicyRuleStateEventData.cs
+++ b/MatrixRoomUtils.Core/StateEventTypes/PolicyRuleStateEventData.cs
@@ -2,51 +2,50 @@ using System.Text.Json.Serialization;
 
 namespace MatrixRoomUtils.Core.StateEventTypes;
 
-public class PolicyRuleStateEventData
-{
+public class PolicyRuleStateEventData {
     /// <summary>
-    /// Entity this ban applies to, can use * and ? as globs.
+    ///     Entity this ban applies to, can use * and ? as globs.
     /// </summary>
     [JsonPropertyName("entity")]
     public string Entity { get; set; }
+
     /// <summary>
-    /// Reason this user is banned
+    ///     Reason this user is banned
     /// </summary>
     [JsonPropertyName("reason")]
     public string? Reason { get; set; }
+
     /// <summary>
-    /// Suggested action to take
+    ///     Suggested action to take
     /// </summary>
     [JsonPropertyName("recommendation")]
     public string? Recommendation { get; set; }
 
     /// <summary>
-    /// Expiry time in milliseconds since the unix epoch, or null if the ban has no expiry.
+    ///     Expiry time in milliseconds since the unix epoch, or null if the ban has no expiry.
     /// </summary>
     [JsonPropertyName("support.feline.policy.expiry.rev.2")] //stable prefix: expiry, msc pending
     public long? Expiry { get; set; }
-    
-    
+
     //utils
     /// <summary>
-    /// Readable expiry time, provided for easy interaction
+    ///     Readable expiry time, provided for easy interaction
     /// </summary>
     [JsonPropertyName("gay.rory.matrix_room_utils.readable_expiry_time_utc")]
-    public DateTime? ExpiryDateTime
-    {
+    public DateTime? ExpiryDateTime {
         get => Expiry == null ? null : DateTimeOffset.FromUnixTimeMilliseconds(Expiry.Value).DateTime;
-        set => Expiry = ((DateTimeOffset) value).ToUnixTimeMilliseconds();
+        set => Expiry = ((DateTimeOffset)value).ToUnixTimeMilliseconds();
     }
 }
 
-public static class PolicyRecommendationTypes
-{
+public static class PolicyRecommendationTypes {
     /// <summary>
-    /// Ban this user
+    ///     Ban this user
     /// </summary>
     public static string Ban = "m.ban";
+
     /// <summary>
-    /// Mute this user
+    ///     Mute this user
     /// </summary>
     public static string Mute = "support.feline.policy.recommendation_mute"; //stable prefix: m.mute, msc pending
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web.Server/MatrixRoomUtils.Web.Server.csproj b/MatrixRoomUtils.Web.Server/MatrixRoomUtils.Web.Server.csproj
index 71c3d08..a34cd2c 100644
--- a/MatrixRoomUtils.Web.Server/MatrixRoomUtils.Web.Server.csproj
+++ b/MatrixRoomUtils.Web.Server/MatrixRoomUtils.Web.Server.csproj
@@ -1,22 +1,22 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
 
-  <PropertyGroup>
-    <TargetFramework>net7.0</TargetFramework>
-    <Nullable>enable</Nullable>
-    <ImplicitUsings>enable</ImplicitUsings>
-  </PropertyGroup>
+    <PropertyGroup>
+        <TargetFramework>net7.0</TargetFramework>
+        <Nullable>enable</Nullable>
+        <ImplicitUsings>enable</ImplicitUsings>
+    </PropertyGroup>
 
-  <ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="7.0.3" />
-  </ItemGroup>
+    <ItemGroup>
+        <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="7.0.3"/>
+    </ItemGroup>
 
-  <ItemGroup>
-    <ProjectReference Include="..\MatrixRoomUtils.Web\MatrixRoomUtils.Web.csproj" />
-  </ItemGroup>
+    <ItemGroup>
+        <ProjectReference Include="..\MatrixRoomUtils.Web\MatrixRoomUtils.Web.csproj"/>
+    </ItemGroup>
 
-  <ItemGroup>
-    <Folder Include="Controllers" />
-  </ItemGroup>
+    <ItemGroup>
+        <Folder Include="Controllers"/>
+    </ItemGroup>
 
 
 </Project>
diff --git a/MatrixRoomUtils.Web.Server/Pages/Error.cshtml b/MatrixRoomUtils.Web.Server/Pages/Error.cshtml
index 0125c85..04b2c2a 100644
--- a/MatrixRoomUtils.Web.Server/Pages/Error.cshtml
+++ b/MatrixRoomUtils.Web.Server/Pages/Error.cshtml
@@ -5,38 +5,37 @@
 <html lang="en">
 
 <head>
-    <meta charset="utf-8" />
-    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+    <meta charset="utf-8"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
     <title>Error</title>
-    <link href="~/css/bootstrap/bootstrap.min.css" rel="stylesheet" />
-    <link href="~/css/app.css" rel="stylesheet" asp-append-version="true" />
+    <link href="~/css/bootstrap/bootstrap.min.css" rel="stylesheet"/>
+    <link href="~/css/app.css" rel="stylesheet" asp-append-version="true"/>
 </head>
 
 <body>
-    <div class="main">
-        <div class="Content px-4">
-            <h1 class="text-danger">Error.</h1>
-            <h2 class="text-danger">An error occurred while processing your request.</h2>
+<div class="main">
+    <div class="Content px-4">
+        <h1 class="text-danger">Error.</h1>
+        <h2 class="text-danger">An error occurred while processing your request.</h2>
 
-            @if (Model.ShowRequestId)
-            {
-                <p>
-                    <strong>Request ID:</strong> <code>@Model.RequestId</code>
-                </p>
-            }
-
-            <h3>Development Mode</h3>
-            <p>
-                Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
-            </p>
+        @if (Model.ShowRequestId) {
             <p>
-                <strong>The Development environment shouldn't be enabled for deployed applications.</strong>
-                It can result in displaying sensitive information from exceptions to end users.
-                For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
-                and restarting the app.
+                <strong>Request ID:</strong> <code>@Model.RequestId</code>
             </p>
-        </div>
+        }
+
+        <h3>Development Mode</h3>
+        <p>
+            Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
+        </p>
+        <p>
+            <strong>The Development environment shouldn't be enabled for deployed applications.</strong>
+            It can result in displaying sensitive information from exceptions to end users.
+            For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
+            and restarting the app.
+        </p>
     </div>
+</div>
 </body>
 
-</html>
+</html>
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web.Server/Pages/Error.cshtml.cs b/MatrixRoomUtils.Web.Server/Pages/Error.cshtml.cs
index b70d895..4b918c1 100644
--- a/MatrixRoomUtils.Web.Server/Pages/Error.cshtml.cs
+++ b/MatrixRoomUtils.Web.Server/Pages/Error.cshtml.cs
@@ -6,21 +6,14 @@ namespace MatrixRoomUtils.Web.Server.Pages;
 
 [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
 [IgnoreAntiforgeryToken]
-public class ErrorModel : PageModel
-{
-    public string? RequestId { get; set; }
+public class ErrorModel : PageModel {
+    private readonly ILogger<ErrorModel> _logger;
 
-    public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
+    public ErrorModel(ILogger<ErrorModel> logger) => _logger = logger;
 
-    private readonly ILogger<ErrorModel> _logger;
+    public string? RequestId { get; set; }
 
-    public ErrorModel(ILogger<ErrorModel> logger)
-    {
-        _logger = logger;
-    }
+    public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
 
-    public void OnGet()
-    {
-        RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
-    }
-}
+    public void OnGet() => RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web.Server/Program.cs b/MatrixRoomUtils.Web.Server/Program.cs
index a486226..b5c3869 100644
--- a/MatrixRoomUtils.Web.Server/Program.cs
+++ b/MatrixRoomUtils.Web.Server/Program.cs
@@ -9,11 +9,8 @@ var app = builder.Build();
 
 // Configure the HTTP request pipeline.
 if (app.Environment.IsDevelopment())
-{
     app.UseWebAssemblyDebugging();
-}
-else
-{
+else {
     app.UseExceptionHandler("/Error");
     // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
     app.UseHsts();
@@ -26,9 +23,8 @@ app.UseStaticFiles();
 
 app.UseRouting();
 
-
 app.MapRazorPages();
 app.MapControllers();
 app.MapFallbackToFile("index.html");
 
-app.Run();
+app.Run();
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web.Server/Properties/launchSettings.json b/MatrixRoomUtils.Web.Server/Properties/launchSettings.json
index 3dcf07b..ad7ef88 100644
--- a/MatrixRoomUtils.Web.Server/Properties/launchSettings.json
+++ b/MatrixRoomUtils.Web.Server/Properties/launchSettings.json
@@ -1,40 +1,40 @@
 {
-    "iisSettings": {
-      "windowsAuthentication": false,
-      "anonymousAuthentication": true,
-      "iisExpress": {
-        "applicationUrl": "http://localhost:6314",
-        "sslPort": 44318
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:6314",
+      "sslPort": 44318
+    }
+  },
+  "profiles": {
+    "http": {
+      "commandName": "Project",
+      "dotnetRunMessages": true,
+      "launchBrowser": true,
+      "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
+      "applicationUrl": "http://localhost:5167",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "https": {
+      "commandName": "Project",
+      "dotnetRunMessages": true,
+      "launchBrowser": true,
+      "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
+      "applicationUrl": "https://localhost:7235;http://localhost:5167",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
       }
     },
-    "profiles": {
-      "http": {
-        "commandName": "Project",
-        "dotnetRunMessages": true,
-        "launchBrowser": true,
-        "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
-        "applicationUrl": "http://localhost:5167",
-        "environmentVariables": {
-          "ASPNETCORE_ENVIRONMENT": "Development"
-        }
-      },
-      "https": {
-        "commandName": "Project",
-        "dotnetRunMessages": true,
-        "launchBrowser": true,
-        "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
-        "applicationUrl": "https://localhost:7235;http://localhost:5167",
-        "environmentVariables": {
-          "ASPNETCORE_ENVIRONMENT": "Development"
-        }
-      },
-      "IIS Express": {
-        "commandName": "IISExpress",
-        "launchBrowser": true,
-        "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
-        "environmentVariables": {
-          "ASPNETCORE_ENVIRONMENT": "Development"
-        }
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
       }
     }
   }
+}
diff --git a/MatrixRoomUtils.Web/App.razor b/MatrixRoomUtils.Web/App.razor
index 4e2789d..e58212b 100644
--- a/MatrixRoomUtils.Web/App.razor
+++ b/MatrixRoomUtils.Web/App.razor
@@ -12,10 +12,9 @@
 </Router>
 
 @code {
-    protected override async Task OnInitializedAsync()
-    {
-        if (!RuntimeCache.WasLoaded)
-        {
+
+    protected override async Task OnInitializedAsync() {
+        if (!RuntimeCache.WasLoaded) {
             await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
             Console.WriteLine("Loaded from local storage");
             StateHasChanged();
diff --git a/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs b/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs
index f70572b..4e7117d 100644
--- a/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs
+++ b/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs
@@ -3,23 +3,20 @@ using MatrixRoomUtils.Core;
 
 namespace MatrixRoomUtils.Web.Classes;
 
-public partial class LocalStorageWrapper
-{
-    private static SemaphoreSlim _semaphoreSlim = new(1);
+public class LocalStorageWrapper {
+    private static readonly SemaphoreSlim _semaphoreSlim = new(1);
     public static Settings Settings { get; set; } = new();
 
     //some basic logic
-    public static async Task InitialiseRuntimeVariables(ILocalStorageService localStorage)
-    {
+    public static async Task InitialiseRuntimeVariables(ILocalStorageService localStorage) {
         //RuntimeCache stuff
         async void Save() => await SaveToLocalStorage(localStorage);
 
         RuntimeCache.Save = Save;
         RuntimeCache.SaveObject = async (key, obj) => await localStorage.SetItemAsync(key, obj);
-        RuntimeCache.RemoveObject = async (key) => await localStorage.RemoveItemAsync(key);
-        if (RuntimeCache.LastUsedToken != null)
-        {
-            Console.WriteLine($"Access token is not null, creating authenticated home server");
+        RuntimeCache.RemoveObject = async key => await localStorage.RemoveItemAsync(key);
+        if (RuntimeCache.LastUsedToken != null) {
+            Console.WriteLine("Access token is not null, creating authenticated home server");
             Console.WriteLine($"Homeserver cache: {RuntimeCache.HomeserverResolutionCache.Count} entries");
             // Console.WriteLine(RuntimeCache.HomeserverResolutionCache.ToJson());
             RuntimeCache.CurrentHomeServer = await new AuthenticatedHomeServer(RuntimeCache.LoginSessions[RuntimeCache.LastUsedToken].LoginResponse.UserId, RuntimeCache.LastUsedToken,
@@ -28,26 +25,24 @@ public partial class LocalStorageWrapper
         }
     }
 
-    public static async Task LoadFromLocalStorage(ILocalStorageService localStorage)
-    {
+    public static async Task LoadFromLocalStorage(ILocalStorageService localStorage) {
         await _semaphoreSlim.WaitAsync();
-        if (RuntimeCache.WasLoaded)
-        {
+        if (RuntimeCache.WasLoaded) {
             _semaphoreSlim.Release();
             return;
         }
+
         Console.WriteLine("Loading from local storage...");
-        Settings = await localStorage.GetItemAsync<Settings>("rory.matrixroomutils.settings") ?? new();
+        Settings = await localStorage.GetItemAsync<Settings>("rory.matrixroomutils.settings") ?? new Settings();
 
         RuntimeCache.LastUsedToken = await localStorage.GetItemAsync<string>("rory.matrixroomutils.last_used_token");
-        RuntimeCache.LoginSessions = await localStorage.GetItemAsync<Dictionary<string, UserInfo>>("rory.matrixroomutils.login_sessions") ?? new();
-        RuntimeCache.HomeserverResolutionCache = await localStorage.GetItemAsync<Dictionary<string, HomeServerResolutionResult>>("rory.matrixroomutils.homeserver_resolution_cache") ?? new();
+        RuntimeCache.LoginSessions = await localStorage.GetItemAsync<Dictionary<string, UserInfo>>("rory.matrixroomutils.login_sessions") ?? new Dictionary<string, UserInfo>();
+        RuntimeCache.HomeserverResolutionCache = await localStorage.GetItemAsync<Dictionary<string, HomeServerResolutionResult>>("rory.matrixroomutils.homeserver_resolution_cache") ?? new Dictionary<string, HomeServerResolutionResult>();
         Console.WriteLine($"[LocalStorageWrapper] Loaded {RuntimeCache.LoginSessions.Count} login sessions, {RuntimeCache.HomeserverResolutionCache.Count} homeserver resolution cache entries");
 
         //RuntimeCache.GenericResponseCache = await localStorage.GetItemAsync<Dictionary<string, ObjectCache<object>>>("rory.matrixroomutils.generic_cache") ?? new();
 
-        foreach (var s in (await localStorage.KeysAsync()).Where(x => x.StartsWith("rory.matrixroomutils.generic_cache:")).ToList())
-        {
+        foreach (var s in (await localStorage.KeysAsync()).Where(x => x.StartsWith("rory.matrixroomutils.generic_cache:")).ToList()) {
             Console.WriteLine($"Loading generic cache entry {s}");
             RuntimeCache.GenericResponseCache[s.Replace("rory.matrixroomutils.generic_cache:", "")] = await localStorage.GetItemAsync<ObjectCache<object>>(s);
         }
@@ -57,36 +52,31 @@ public partial class LocalStorageWrapper
         _semaphoreSlim.Release();
     }
 
-    public static async Task SaveToLocalStorage(ILocalStorageService localStorage)
-    {
+    public static async Task SaveToLocalStorage(ILocalStorageService localStorage) {
         Console.WriteLine("Saving to local storage...");
         await localStorage.SetItemAsync("rory.matrixroomutils.settings", Settings);
         if (RuntimeCache.LoginSessions != null) await localStorage.SetItemAsync("rory.matrixroomutils.login_sessions", RuntimeCache.LoginSessions);
         if (RuntimeCache.LastUsedToken != null) await localStorage.SetItemAsync("rory.matrixroomutils.last_used_token", RuntimeCache.LastUsedToken);
     }
 
-    public static async Task SaveCacheToLocalStorage(ILocalStorageService localStorage, bool awaitSave = true, bool saveGenericCache = true)
-    {
+    public static async Task SaveCacheToLocalStorage(ILocalStorageService localStorage, bool awaitSave = true, bool saveGenericCache = true) {
         await localStorage.SetItemAsync("rory.matrixroomutils.homeserver_resolution_cache",
             RuntimeCache.HomeserverResolutionCache.DistinctBy(x => x.Key)
                 .ToDictionary(x => x.Key, x => x.Value));
         //await localStorage.SetItemAsync("rory.matrixroomutils.generic_cache", RuntimeCache.GenericResponseCache);
-        if(saveGenericCache)
-            foreach (var s in RuntimeCache.GenericResponseCache.Keys)
-            {
+        if (saveGenericCache)
+            foreach (var s in RuntimeCache.GenericResponseCache.Keys) {
                 var t = localStorage.SetItemAsync($"rory.matrixroomutils.generic_cache:{s}", RuntimeCache.GenericResponseCache[s]);
                 if (awaitSave) await t;
             }
     }
 }
 
-public class Settings
-{
+public class Settings {
     public DeveloperSettings DeveloperSettings { get; set; } = new();
 }
 
-public class DeveloperSettings
-{
+public class DeveloperSettings {
     public bool EnableLogViewers { get; set; } = false;
     public bool EnableConsoleLogging { get; set; } = true;
     public bool EnablePortableDevtools { get; set; } = false;
diff --git a/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs b/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs
index c43bd3c..77c8281 100644
--- a/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs
+++ b/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs
@@ -1,110 +1,89 @@
+using System.Text.Json.Nodes;
 using MatrixRoomUtils.Core;
 using MatrixRoomUtils.Core.Responses;
 
 namespace MatrixRoomUtils.Web.Classes.RoomCreationTemplates;
 
-public class DefaultRoomCreationTemplate : IRoomCreationTemplate
-{
+public class DefaultRoomCreationTemplate : IRoomCreationTemplate {
     public string Name => "Default";
-    public CreateRoomRequest CreateRoomRequest
-    {
-        get
-        {
-            return new()
-            {
-                Name = "My new room",
-                RoomAliasName = "myroom",
-                InitialState = new()
-                {
-                    new()
-                    {
-                        Type = "m.room.history_visibility",
-                        Content = new
-                        {
-                            history_visibility = "world_readable"
-                        }
-                    },
-                    new StateEvent<Pages.RoomManager.RoomManagerCreateRoom.GuestAccessContent>
-                    {
-                        Type = "m.room.guest_access",
-                        Content = new()
-                        {
-                            GuestAccess = "can_join"
-                        }
-                    },
-                    new()
-                    {
-                        Type = "m.room.join_rules",
-                        Content = new
-                        {
-                            join_rule = "public"
-                        }
-                    },
-                    new()
-                    {
-                        Type = "m.room.server_acl",
-                        Content = new
-                        {
-                            allow = new[] { "*" },
-                            deny = Array.Empty<string>(),
-                            allow_ip_literals = false
-                        }
-                    },
-                    new()
-                    {
-                        Type = "m.room.avatar",
-                        Content = new
-                        {
-                            url = "mxc://feline.support/UKNhEyrVsrAbYteVvZloZcFj"
-                        }
+
+    public CreateRoomRequest CreateRoomRequest =>
+        new CreateRoomRequest {
+            Name = "My new room",
+            RoomAliasName = "myroom",
+            InitialState = new List<StateEvent> {
+                new() {
+                    Type = "m.room.history_visibility",
+                    Content = new {
+                        history_visibility = "world_readable"
                     }
                 },
-                Visibility = "public",
-                PowerLevelContentOverride = new()
-                {
-                    UsersDefault = 0,
-                    EventsDefault = 100,
-                    StateDefault = 50,
-                    Invite = 0,
-                    Redact = 50,
-                    Kick = 50,
-                    Ban = 50,
-                    NotificationsPl = new()
-                    {
-                        Room = 50
-                    },
-                    Events = new()
-                    {
-                        { "im.vector.modular.widgets", 50 },
-                        { "io.element.voice_broadcast_info", 50 },
-                        { "m.reaction", 100 },
-                        { "m.room.avatar", 50 },
-                        { "m.room.canonical_alias", 50 },
-                        { "m.room.encryption", 100 },
-                        { "m.room.history_visibility", 100 },
-                        { "m.room.name", 50 },
-                        { "m.room.pinned_events", 50 },
-                        { "m.room.power_levels", 100 },
-                        { "m.room.redaction", 100 },
-                        { "m.room.server_acl", 100 },
-                        { "m.room.tombstone", 100 },
-                        { "m.room.topic", 50 },
-                        { "m.space.child", 50 },
-                        { "org.matrix.msc3401.call", 50 },
-                        { "org.matrix.msc3401.call.member", 50 }
-                    },
-                    Users = new()
-                    {
-                        { RuntimeCache.CurrentHomeServer.UserId, 100 },
-                    },
+                new StateEvent<Pages.RoomManager.RoomManagerCreateRoom.GuestAccessContent> {
+                    Type = "m.room.guest_access",
+                    Content = new Pages.RoomManager.RoomManagerCreateRoom.GuestAccessContent {
+                        GuestAccess = "can_join"
+                    }
                 },
-                CreationContent = new()
-                {
-                    {
-                        "type", null
+                new() {
+                    Type = "m.room.join_rules",
+                    Content = new {
+                        join_rule = "public"
+                    }
+                },
+                new() {
+                    Type = "m.room.server_acl",
+                    Content = new {
+                        allow = new[] { "*" },
+                        deny = Array.Empty<string>(),
+                        allow_ip_literals = false
                     }
+                },
+                new() {
+                    Type = "m.room.avatar",
+                    Content = new {
+                        url = "mxc://feline.support/UKNhEyrVsrAbYteVvZloZcFj"
+                    }
+                }
+            },
+            Visibility = "public",
+            PowerLevelContentOverride = new PowerLevelEvent {
+                UsersDefault = 0,
+                EventsDefault = 100,
+                StateDefault = 50,
+                Invite = 0,
+                Redact = 50,
+                Kick = 50,
+                Ban = 50,
+                NotificationsPl = new NotificationsPL {
+                    Room = 50
+                },
+                Events = new Dictionary<string, int> {
+                    { "im.vector.modular.widgets", 50 },
+                    { "io.element.voice_broadcast_info", 50 },
+                    { "m.reaction", 100 },
+                    { "m.room.avatar", 50 },
+                    { "m.room.canonical_alias", 50 },
+                    { "m.room.encryption", 100 },
+                    { "m.room.history_visibility", 100 },
+                    { "m.room.name", 50 },
+                    { "m.room.pinned_events", 50 },
+                    { "m.room.power_levels", 100 },
+                    { "m.room.redaction", 100 },
+                    { "m.room.server_acl", 100 },
+                    { "m.room.tombstone", 100 },
+                    { "m.room.topic", 50 },
+                    { "m.space.child", 50 },
+                    { "org.matrix.msc3401.call", 50 },
+                    { "org.matrix.msc3401.call.member", 50 }
+                },
+                Users = new Dictionary<string, int> {
+                    { RuntimeCache.CurrentHomeServer.UserId, 100 }
+                }
+            },
+            CreationContent = new JsonObject {
+                {
+                    "type", null
                 }
-            };
-        }
-    }
+            }
+        };
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/IRoomCreationTemplate.cs b/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/IRoomCreationTemplate.cs
index 7f84dc4..bbb09b7 100644
--- a/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/IRoomCreationTemplate.cs
+++ b/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/IRoomCreationTemplate.cs
@@ -2,8 +2,7 @@ using MatrixRoomUtils.Core.Responses;
 
 namespace MatrixRoomUtils.Web.Classes.RoomCreationTemplates;
 
-public interface IRoomCreationTemplate
-{
+public interface IRoomCreationTemplate {
     public CreateRoomRequest CreateRoomRequest { get; }
     public string Name { get; }
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/FileUploadTest.razor b/MatrixRoomUtils.Web/FileUploadTest.razor
index 2e25b54..478a3e4 100644
--- a/MatrixRoomUtils.Web/FileUploadTest.razor
+++ b/MatrixRoomUtils.Web/FileUploadTest.razor
@@ -6,8 +6,7 @@
 
 @code {
 
-    private async void FilePicked(InputFileChangeEventArgs obj)
-    {
+    private async void FilePicked(InputFileChangeEventArgs obj) {
         Console.WriteLine("FilePicked");
         Console.WriteLine(obj.File.Name);
         Console.WriteLine(obj.File.Size);
diff --git a/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj b/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj
index cf6ce87..c76452f 100644
--- a/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj
+++ b/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj
@@ -7,17 +7,17 @@
     </PropertyGroup>
 
     <ItemGroup>
-        <PackageReference Include="Blazored.LocalStorage" Version="4.3.0" />
-        <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.3" />
-        <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.3" PrivateAssets="all" />
+        <PackageReference Include="Blazored.LocalStorage" Version="4.3.0"/>
+        <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.3"/>
+        <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.3" PrivateAssets="all"/>
     </ItemGroup>
 
     <ItemGroup>
-      <ProjectReference Include="..\MatrixRoomUtils.Core\MatrixRoomUtils.Core.csproj" />
+        <ProjectReference Include="..\MatrixRoomUtils.Core\MatrixRoomUtils.Core.csproj"/>
     </ItemGroup>
 
     <ItemGroup>
-      <Folder Include="Shared\TimelineComponents\TimelineMessageComponents" />
+        <Folder Include="Shared\TimelineComponents\TimelineMessageComponents"/>
     </ItemGroup>
-    
+
 </Project>
diff --git a/MatrixRoomUtils.Web/Pages/About.razor b/MatrixRoomUtils.Web/Pages/About.razor
index d47e60b..cf43c4f 100644
--- a/MatrixRoomUtils.Web/Pages/About.razor
+++ b/MatrixRoomUtils.Web/Pages/About.razor
@@ -13,26 +13,23 @@
 <br/><br/>
 <p>You can find the source code on <a href="https://git.rory.gay/MatrixRoomUtils.git/">my git server</a>.<br/></p>
 <p>You can also join the <a href="https://matrix.to/#/%23mru%3Arory.gay?via=rory.gay&via=matrix.org&via=feline.support">Matrix room</a> for this project.</p>
-@if (showBinDownload)
-{
+@if (showBinDownload) {
     <p>This deployment also serves a copy of the compiled, hosting-ready binaries at <a href="MRU-BIN.tar.xz">/MRU-BIN.tar.xz</a>!</p>
 }
-@if (showSrcDownload)
-{
+@if (showSrcDownload) {
     <p>This deployment also serves a copy of the compiled, hosting-ready binaries at <a href="MRU-SRC.tar.xz">/MRU-SRC.tar.xz</a>!</p>
 }
 
 
 @code {
-    private bool showBinDownload { get; set; } = false;
-    private bool showSrcDownload { get; set; } = false;
+    private bool showBinDownload { get; set; }
+    private bool showSrcDownload { get; set; }
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         using var hc = new HttpClient();
-        var hr = await hc.SendAsync(new(HttpMethod.Head, NavigationManager.ToAbsoluteUri("/MRU-BIN.tar.xz").AbsoluteUri));
+        var hr = await hc.SendAsync(new HttpRequestMessage(HttpMethod.Head, NavigationManager.ToAbsoluteUri("/MRU-BIN.tar.xz").AbsoluteUri));
         showBinDownload = hr.StatusCode == HttpStatusCode.OK;
-        hr = await hc.SendAsync(new(HttpMethod.Head, NavigationManager.ToAbsoluteUri("/MRU-SRC.tar.xz").AbsoluteUri));
+        hr = await hc.SendAsync(new HttpRequestMessage(HttpMethod.Head, NavigationManager.ToAbsoluteUri("/MRU-SRC.tar.xz").AbsoluteUri));
         showSrcDownload = hr.StatusCode == HttpStatusCode.OK;
         await base.OnInitializedAsync();
     }
diff --git a/MatrixRoomUtils.Web/Pages/DataExportPage.razor b/MatrixRoomUtils.Web/Pages/DataExportPage.razor
index 49fb700..732cd74 100644
--- a/MatrixRoomUtils.Web/Pages/DataExportPage.razor
+++ b/MatrixRoomUtils.Web/Pages/DataExportPage.razor
@@ -1,5 +1,4 @@
 @page "/Export"
-@using MatrixRoomUtils.Web.Shared.IndexComponents
 @using System.Text.Json
 @inject NavigationManager NavigationManager
 @inject ILocalStorageService LocalStorage
@@ -11,12 +10,10 @@
 <br/><br/>
 <h5>Signed in accounts - <a href="/Login">Add new account</a> or <a href="/ImportUsers">Import from TSV</a></h5>
 <hr/>
-@if (_isLoaded)
-{
-@foreach (var (token, user) in RuntimeCache.LoginSessions)
-{
+@if (_isLoaded) {
+    @foreach (var (token, user) in RuntimeCache.LoginSessions) {
     @* <IndexUserItem User="@user"/> *@
-    <pre>
+        <pre>
 @user.LoginResponse.UserId[1..].Split(":")[0]\auth\access_token=@token
 @user.LoginResponse.UserId[1..].Split(":")[0]\auth\device_id=@user.LoginResponse.DeviceId
 @user.LoginResponse.UserId[1..].Split(":")[0]\auth\home_server=@(RuntimeCache.HomeserverResolutionCache.ContainsKey(user.LoginResponse.HomeServer) ? RuntimeCache.HomeserverResolutionCache[user.LoginResponse.HomeServer].Result : "loading...")
@@ -26,10 +23,9 @@
 @user.LoginResponse.UserId[1..].Split(":")[0]\user\online_key_backup=true
 @user.LoginResponse.UserId[1..].Split(":")[0]\user\only_share_keys_with_verified_users=false
     </pre>
+    }
 }
-}
-else
-{
+else {
     <p>Loading...</p>
     <p>@resolvedHomeservers/@totalHomeservers homeservers resolved...</p>
 }
@@ -39,31 +35,26 @@ else
     private int resolvedHomeservers;
     private int totalHomeservers;
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         await base.OnInitializedAsync();
-        if (!RuntimeCache.WasLoaded)
-        {
+        if (!RuntimeCache.WasLoaded) {
             await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
         }
         var homeservers = RuntimeCache.LoginSessions.Values.Select(x => x.LoginResponse.HomeServer).Distinct();
         totalHomeservers = homeservers.Count();
         StateHasChanged();
-        foreach (var hs in homeservers)
-        {
-            if (RuntimeCache.HomeserverResolutionCache.ContainsKey(hs))
-            {
+        foreach (var hs in homeservers) {
+            if (RuntimeCache.HomeserverResolutionCache.ContainsKey(hs)) {
                 resolvedHomeservers++;
                 continue;
             }
             var resolvedHomeserver = (await new RemoteHomeServer(hs).Configure()).FullHomeServerDomain;
 
-            RuntimeCache.HomeserverResolutionCache.Add(hs, new() { Result = resolvedHomeserver, ResolutionTime = DateTime.Now });
+            RuntimeCache.HomeserverResolutionCache.Add(hs, new HomeServerResolutionResult { Result = resolvedHomeserver, ResolutionTime = DateTime.Now });
             await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage);
 
             Console.WriteLine("Saved to local storage:");
-            Console.WriteLine(JsonSerializer.Serialize(RuntimeCache.HomeserverResolutionCache, new JsonSerializerOptions()
-            {
+            Console.WriteLine(JsonSerializer.Serialize(RuntimeCache.HomeserverResolutionCache, new JsonSerializerOptions {
                 WriteIndented = true
             }));
             resolvedHomeservers++;
diff --git a/MatrixRoomUtils.Web/Pages/DebugTools.razor b/MatrixRoomUtils.Web/Pages/DebugTools.razor
index c8fabaa..da5c172 100644
--- a/MatrixRoomUtils.Web/Pages/DebugTools.razor
+++ b/MatrixRoomUtils.Web/Pages/DebugTools.razor
@@ -1,26 +1,24 @@
 @page "/Debug"
-@using MatrixRoomUtils.Core.Interfaces
-@using MatrixRoomUtils.Core.Extensions
 @using System.Reflection
+@using MatrixRoomUtils.Core.Extensions
+@using MatrixRoomUtils.Core.Interfaces
 @inject ILocalStorageService LocalStorage
 @inject NavigationManager NavigationManager
 <h3>Debug Tools</h3>
 <hr/>
-@if (Rooms.Count == 0)
-{
+@if (Rooms.Count == 0) {
     <p>You are not in any rooms!</p>
     @* <p>Loading progress: @checkedRoomCount/@totalRoomCount</p> *@
 }
-else
-{
+else {
     <details>
         <summary>Room List</summary>
-        @foreach (var room in Rooms)
-        {
-            <a style="color: unset; text-decoration: unset;" href="/RoomStateViewer/@room.Replace('.', '~')"><RoomListItem RoomId="@room"></RoomListItem></a>
+        @foreach (var room in Rooms) {
+            <a style="color: unset; text-decoration: unset;" href="/RoomStateViewer/@room.Replace('.', '~')">
+                <RoomListItem RoomId="@room"></RoomListItem>
+            </a>
         }
     </details>
-    
 }
 
 <details open>
@@ -38,50 +36,44 @@ else
 
 @code {
     public List<string> Rooms { get; set; } = new();
-    protected override async Task OnInitializedAsync()
-    {
+
+    protected override async Task OnInitializedAsync() {
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
         await base.OnInitializedAsync();
-        if (RuntimeCache.CurrentHomeServer == null)
-        {
+        if (RuntimeCache.CurrentHomeServer == null) {
             NavigationManager.NavigateTo("/Login");
             return;
         }
-        Rooms = (await RuntimeCache.CurrentHomeServer.GetJoinedRooms()).Select(x=>x.RoomId).ToList();
+        Rooms = (await RuntimeCache.CurrentHomeServer.GetJoinedRooms()).Select(x => x.RoomId).ToList();
         Console.WriteLine("Fetched joined rooms!");
     }
 
-    
     //send req
     string get_request_url { get; set; } = "";
     string get_request_result { get; set; } = "";
-    private async Task SendGetRequest()
-    {
+
+    private async Task SendGetRequest() {
         var field = typeof(IHomeServer).GetRuntimeFields().First(x => x.ToString().Contains("<_httpClient>k__BackingField"));
         var httpClient = field.GetValue(RuntimeCache.CurrentHomeServer) as HttpClient;
-        try
-        {
+        try {
             var res = await httpClient.GetAsync(get_request_url);
-            if (res.IsSuccessStatusCode)
-            {
-                if(res.Content.Headers.ContentType.MediaType == "application/json")
+            if (res.IsSuccessStatusCode) {
+                if (res.Content.Headers.ContentType.MediaType == "application/json")
                     get_request_result = (await res.Content.ReadFromJsonAsync<object>()).ToJson();
                 else
                     get_request_result = await res.Content.ReadAsStringAsync();
                 StateHasChanged();
                 return;
             }
-            if(res.Content.Headers.ContentType.MediaType == "application/json")
+            if (res.Content.Headers.ContentType.MediaType == "application/json")
                 get_request_result = $"Error: {res.StatusCode}\n" + (await res.Content.ReadFromJsonAsync<object>()).ToJson();
             else
                 get_request_result = $"Error: {res.StatusCode}\n" + await res.Content.ReadAsStringAsync();
-
         }
-        catch (Exception e)
-        {
+        catch (Exception e) {
             get_request_result = $"Error: {e}";
         }
         StateHasChanged();
     }
 
-} 
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Pages/DevOptions.razor b/MatrixRoomUtils.Web/Pages/DevOptions.razor
index 3ca86b4..0843d5f 100644
--- a/MatrixRoomUtils.Web/Pages/DevOptions.razor
+++ b/MatrixRoomUtils.Web/Pages/DevOptions.razor
@@ -19,15 +19,13 @@
     <summary>View caches</summary>
     <p>Generic cache:</p>
     <ul>
-        @foreach (var item in RuntimeCache.GenericResponseCache)
-        {
+        @foreach (var item in RuntimeCache.GenericResponseCache) {
             <li>
                 @item.Key: @item.Value.Cache.Count entries<br/>
-                @if (item.Value.Cache.Count > 0)
-                {
+                @if (item.Value.Cache.Count > 0) {
                     <p>Earliest expiry: @(item.Value.Cache.Min(x => x.Value.ExpiryTime)) (@string.Format("{0:g}", item.Value.Cache.Min(x => x.Value.ExpiryTime).Value.Subtract(DateTime.Now)) from now)</p>
                     @* <p>Average expiry: @(item.Value.Cache.Average(x => x.Value.ExpiryTime.Value))(@item.Value.Cache.Average(x => x.Value.ExpiryTime).Value.Subtract(DateTime.Now) from now)</p> *@
-                    <p>Last expiry: @(item.Value.Cache.Max(x => x.Value.ExpiryTime)) (@string.Format("{0:g}", item.Value.Cache.Max(x => x.Value.ExpiryTime).Value.Subtract(DateTime.Now)) from now)</p> 
+                    <p>Last expiry: @(item.Value.Cache.Max(x => x.Value.ExpiryTime)) (@string.Format("{0:g}", item.Value.Cache.Max(x => x.Value.ExpiryTime).Value.Subtract(DateTime.Now)) from now)</p>
                 }
             </li>
         }
@@ -35,50 +33,42 @@
 </details>
 
 @code {
-    protected override async Task OnInitializedAsync()
-    {
+
+    protected override async Task OnInitializedAsync() {
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
         await base.OnInitializedAsync();
-        Task.Run(async () =>
-        {
-            while (true)
-            {
+        Task.Run(async () => {
+            while (true) {
                 await Task.Delay(1000);
                 StateHasChanged();
             }
         });
     }
 
-    protected async Task LogStuff()
-    {
+    protected async Task LogStuff() {
         await Task.Delay(100);
         Console.WriteLine($"Settings: {LocalStorageWrapper.Settings.ToJson()}");
-        
+
         await LocalStorageWrapper.SaveToLocalStorage(LocalStorage);
     }
 
-    protected async Task DropCaches()
-    {
-        foreach (var (key, value) in RuntimeCache.GenericResponseCache)
-        {
+    protected async Task DropCaches() {
+        foreach (var (key, value) in RuntimeCache.GenericResponseCache) {
             value.Cache.Clear();
         }
-        
-        //RuntimeCache.GenericResponseCache.Clear();
+
+    //RuntimeCache.GenericResponseCache.Clear();
         RuntimeCache.HomeserverResolutionCache.Clear();
         await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage);
     }
 
-    protected async Task RandomiseCacheTimers()
-    {
-        foreach (var keyValuePair in RuntimeCache.GenericResponseCache)
-        {
+    protected async Task RandomiseCacheTimers() {
+        foreach (var keyValuePair in RuntimeCache.GenericResponseCache) {
             Console.WriteLine($"Randomising cache timer for {keyValuePair.Key}");
-            foreach (var cacheItem in keyValuePair.Value.Cache)
-            {
+            foreach (var cacheItem in keyValuePair.Value.Cache) {
                 cacheItem.Value.ExpiryTime = DateTime.Now.AddSeconds(Random.Shared.Next(15, 120));
             }
-            
+
             await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage);
         }
     }
diff --git a/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor b/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor
index b77012b..f972236 100644
--- a/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor
+++ b/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor
@@ -2,6 +2,10 @@
 <h3>Homeserver Admininistration</h3>
 <hr/>
 
+<h4>Synapse tools</h4>
+<hr/>
+<a href="/HSAdmin/RoomQuery">Query rooms</a>
+
 @code {
-    
+
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor b/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor
index 109ad7d..e6f95c7 100644
--- a/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor
+++ b/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor
@@ -1,73 +1,78 @@
-@page "/RoomQuery"
+@page "/HSAdmin/RoomQuery"
 @using MatrixRoomUtils.Core.Extensions
-@using System.Runtime.InteropServices
-@using System.ComponentModel
 @using MatrixRoomUtils.Core.Responses.Admin
 <h3>Homeserver Administration - Room Query</h3>
 
 <label>Search name: </label>
-<InputText @bind-Value="SearchTerm" /><br/>
+<InputText @bind-Value="SearchTerm"/><br/>
 <label>Search id/name/creator (slow!): </label>
-<InputText @bind-Value="ContentSearchTerm" /><br/>
+<InputText @bind-Value="ContentSearchTerm"/><br/>
 <label>Order by: </label>
 <select @bind="OrderBy">
-    @foreach (var item in validOrderBy)
-    {
+    @foreach (var item in validOrderBy) {
         <option value="@item.Key">@item.Value</option>
     }
 </select><br/>
 <label>Ascending: </label>
-<InputCheckbox @bind-Value="Ascending" /><br/>
+<InputCheckbox @bind-Value="Ascending"/><br/>
 <button class="btn btn-primary" @onclick="Search">Search</button>
 <br/>
 
-@foreach (var res in Results)
-{
+@foreach (var res in Results) {
     <div style="background-color: #ffffff11; border-radius: 0.5em; display: block; margin-top: 4px; padding: 4px;">
-        <RoomListItem RoomId="@res.RoomId"></RoomListItem> 
-        <p>@res.CanonicalAlias, created by <InlineUserItem UserId="@res.Creator"></InlineUserItem></p>
+        <RoomListItem RoomName="@res.Name" RoomId="@res.RoomId"></RoomListItem>
+        <p>
+            @res.CanonicalAlias
+            @if (!string.IsNullOrWhiteSpace(res.Creator)) {
+                <span>
+                    , created by <InlineUserItem UserId="@res.Creator"></InlineUserItem>
+                </span>
+            }
+        </p>
         <p>@res.StateEvents state events</p>
         <p>@res.JoinedMembers members, of which @res.JoinedLocalMembers are on this server</p>
     </div>
 }
 
 @code {
-    
-    [Parameter, SupplyParameterFromQuery(Name = "order_by")]
+
+    [Parameter]
+    [SupplyParameterFromQuery(Name = "order_by")]
     public string? OrderBy { get; set; }
-    
-    [Parameter, SupplyParameterFromQuery(Name = "search_term")]
+
+    [Parameter]
+    [SupplyParameterFromQuery(Name = "search_term")]
     public string SearchTerm { get; set; }
-    
-    [Parameter, SupplyParameterFromQuery(Name = "content_search_term")]
+
+    [Parameter]
+    [SupplyParameterFromQuery(Name = "content_search_term")]
     public string ContentSearchTerm { get; set; }
-    
-    [Parameter, SupplyParameterFromQuery(Name = "ascending")]
+
+    [Parameter]
+    [SupplyParameterFromQuery(Name = "ascending")]
     public bool Ascending { get; set; }
 
     public List<AdminRoomListingResult.AdminRoomListingResultRoom> Results { get; set; } = new();
-    
-    protected override async Task OnParametersSetAsync()
-    {
-        if(Ascending == null)
+
+    private string Status { get; set; }
+
+    protected override async Task OnParametersSetAsync() {
+        if (Ascending == null)
             Ascending = true;
         OrderBy ??= "name";
     }
-    
-    private async Task Search()
-    {
+
+    private async Task Search() {
         Results.Clear();
         var searchRooms = RuntimeCache.CurrentHomeServer.Admin.SearchRoomsAsync(orderBy: OrderBy!, dir: Ascending ? "f" : "b", searchTerm: SearchTerm, contentSearch: ContentSearchTerm).GetAsyncEnumerator();
-        while (await searchRooms.MoveNextAsync())
-        {
+        while (await searchRooms.MoveNextAsync()) {
             var room = searchRooms.Current;
-            Console.WriteLine("Hit: " + room.ToJson(indent: false));
+            Console.WriteLine("Hit: " + room.ToJson(false));
             Results.Add(room);
         }
     }
 
-    private Dictionary<string, string> validOrderBy = new Dictionary<string, string>()
-    {
+    private readonly Dictionary<string, string> validOrderBy = new() {
         { "name", "Room name" },
         { "canonical_alias", "Main alias address" },
         { "joined_members", "Number of members (reversed)" },
@@ -80,7 +85,7 @@
         { "join_rules", "Join rules" },
         { "guest_access", "Guest access" },
         { "history_visibility", "Visibility of history" },
-        { "state_events", "Number of state events" },
+        { "state_events", "Number of state events" }
     };
 
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Pages/Index.razor b/MatrixRoomUtils.Web/Pages/Index.razor
index decdb0c..33cca61 100644
--- a/MatrixRoomUtils.Web/Pages/Index.razor
+++ b/MatrixRoomUtils.Web/Pages/Index.razor
@@ -12,18 +12,15 @@ Small collection of tools to do not-so-everyday things.
 <h5>Signed in accounts - <a href="/Login">Add new account</a></h5>
 <hr/>
 <form>
-    @foreach (var (token, user) in RuntimeCache.LoginSessions)
-    {
+    @foreach (var (token, user) in RuntimeCache.LoginSessions) {
         <IndexUserItem User="@user"/>
     }
 </form>
 
 @code
 {
-    protected override async Task OnInitializedAsync()
-    {
-        if (!RuntimeCache.WasLoaded)
-        {
+    protected override async Task OnInitializedAsync() {
+        if (!RuntimeCache.WasLoaded) {
             Console.WriteLine("[INDEX] !!! LOCALSTORAGE WAS NOT LOADED !!!");
             await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
         }
diff --git a/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor b/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor
index 13b717d..92a8445 100644
--- a/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor
+++ b/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor
@@ -5,33 +5,25 @@
 <h3>Known Homeserver List</h3>
 <hr/>
 
-@if (!IsFinished)
-{
+@if (!IsFinished) {
     <p>Loading... Please wait...</p>
     <progress value="@QueryProgress.ProcessedRooms" max="@QueryProgress.TotalRooms"></progress>
     <p>@QueryProgress.ProcessedRooms / @QueryProgress.TotalRooms</p>
-    @foreach (var (room, state) in QueryProgress.ProcessedUsers.Where(x => !x.Value.IsFinished).OrderByDescending(x => x.Value.Total).ToList())
-    {
-        @if (state.Blocked)
-        {
+    @foreach (var (room, state) in QueryProgress.ProcessedUsers.Where(x => !x.Value.IsFinished).OrderByDescending(x => x.Value.Total).ToList()) {
+        @if (state.Blocked) {
             <p>🔒 @room.RoomId - @state.Processed / @state.Total, @state.Timing.Elapsed elapsed...</p>
         }
-        else if (state.Slowmode)
-        {
-            
+        else if (state.Slowmode) {
             <p>🐢 @room.RoomId - @state.Processed / @state.Total, @state.Timing.Elapsed elapsed...</p>
         }
-        else
-        {
+        else {
             <p>@room.RoomId - @state.Processed / @state.Total, @state.Timing.Elapsed elapsed...</p>
         }
         <progress value="@state.Processed" max="@state.Total"></progress>
     }
 }
-else
-{
-    @foreach (var server in HomeServers.OrderByDescending(x => x.KnownUserCount).ThenBy(x => x.Server).ToList())
-    {
+else {
+    @foreach (var server in HomeServers.OrderByDescending(x => x.KnownUserCount).ThenBy(x => x.Server).ToList()) {
         <p>@server.Server - @server.KnownUserCount</p>
     }
 }
@@ -42,15 +34,12 @@ else
     bool IsFinished { get; set; }
     HomeServerInfoQueryProgress QueryProgress { get; set; } = new();
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
 
         var sw = Stopwatch.StartNew();
-        HomeServers = await GetHomeservers(progressCallback: async progress =>
-        {
-            if (sw.ElapsedMilliseconds > 1000)
-            {
+        HomeServers = await GetHomeservers(progressCallback: async progress => {
+            if (sw.ElapsedMilliseconds > 1000) {
                 Console.WriteLine("Progress updated...");
                 QueryProgress = progress;
                 StateHasChanged();
@@ -69,9 +58,7 @@ else
         await base.OnInitializedAsync();
     }
 
-
-    private async Task<List<HomeServerInfo>> GetHomeservers(int memberLimit = 1000, Func<HomeServerInfoQueryProgress, Task<bool>>? progressCallback = null)
-    {
+    private async Task<List<HomeServerInfo>> GetHomeservers(int memberLimit = 1000, Func<HomeServerInfoQueryProgress, Task<bool>>? progressCallback = null) {
         HomeServerInfoQueryProgress progress = new();
         List<HomeServerInfo> homeServers = new();
         var rooms = await RuntimeCache.CurrentHomeServer.GetJoinedRooms();
@@ -79,16 +66,14 @@ else
 
         var semaphore = new SemaphoreSlim(4);
         var semLock = new SemaphoreSlim(1);
-        var tasks = rooms.Select(async room =>
-        {
+        var tasks = rooms.Select(async room => {
             await semaphore.WaitAsync();
-            progress.ProcessedUsers.Add(room, new());
+            progress.ProcessedUsers.Add(room, new HomeServerInfoQueryProgress.State());
             Console.WriteLine($"Fetching states for room ({rooms.IndexOf(room)}/{rooms.Count}) ({room.RoomId})");
             var states = (await room.GetStateAsync("")).Value.Deserialize<List<StateEventResponse>>();
             states.RemoveAll(x => x.Type != "m.room.member" || x.Content.GetProperty("membership").GetString() != "join");
             Console.WriteLine($"Room {room.RoomId} has {states.Count} members");
-            if (states.Count > memberLimit)
-            {
+            if (states.Count > memberLimit) {
                 Console.WriteLine("Skipping!");
                 semaphore.Release();
                 progress.ProcessedUsers.Remove(room);
@@ -97,37 +82,31 @@ else
             }
             progress.ProcessedUsers[room].Total = states.Count;
             var updateInterval = progress.ProcessedUsers[room].Total >= 1000 ? 1000 : 100;
-            while (progress.ProcessedUsers.Any(x => x.Value.Total == 0) && progress.ProcessedUsers[room].Total >= 1000)
-            {
+            while (progress.ProcessedUsers.Any(x => x.Value.Total == 0) && progress.ProcessedUsers[room].Total >= 1000) {
                 progress.ProcessedUsers[room].Blocked = true;
                 await Task.Delay(1000);
-                // if(progressCallback != null)
-                //     await progressCallback.Invoke(progress);
+    // if(progressCallback != null)
+    //     await progressCallback.Invoke(progress);
             }
             progress.ProcessedUsers[room].Blocked = false;
-            int processedStates = 0;
-            foreach (var state in states)
-            {
+            var processedStates = 0;
+            foreach (var state in states) {
                 await semLock.WaitAsync();
                 semLock.Release();
-                if (progress.ProcessedUsers.Count(x => x.Value.Total == 0) > 5 && progress.ProcessedUsers[room].Total >= 200)
-                {
+                if (progress.ProcessedUsers.Count(x => x.Value.Total == 0) > 5 && progress.ProcessedUsers[room].Total >= 200) {
                     progress.ProcessedUsers[room].Slowmode = true;
                     await Task.Delay(progress.ProcessedUsers[room].Total >= 500 ? 1000 : 100);
                 }
-                else
-                {
+                else {
                     progress.ProcessedUsers[room].Slowmode = false;
                 }
-                if (!homeServers.Any(x => x.Server == state.StateKey.Split(':')[1]))
-                {
-                    homeServers.Add(new HomeServerInfo() { Server = state.StateKey.Split(':')[1] });
+                if (!homeServers.Any(x => x.Server == state.StateKey.Split(':')[1])) {
+                    homeServers.Add(new HomeServerInfo { Server = state.StateKey.Split(':')[1] });
                 }
                 var hs = homeServers.First(x => x.Server == state.StateKey.Split(':')[1]);
                 if (!hs.KnownUsers.Contains(state.StateKey.Split(':')[0]))
                     hs.KnownUsers.Add(state.StateKey.Split(':')[0]);
-                if (++progress.ProcessedUsers[room].Processed % updateInterval == 0 && progressCallback != null)
-                {
+                if (++progress.ProcessedUsers[room].Processed % updateInterval == 0 && progressCallback != null) {
                     await semLock.WaitAsync();
                     var _ = await progressCallback.Invoke(progress);
                     semLock.Release();
@@ -148,29 +127,26 @@ else
         return homeServers;
     }
 
-    class HomeServerInfo
-    {
+    class HomeServerInfo {
         public string Server { get; set; }
         public int? KnownUserCount { get; set; }
-        public List<string> KnownUsers { get; set; } = new();
+        public List<string> KnownUsers { get; } = new();
     }
 
-    class HomeServerInfoQueryProgress
-    {
+    class HomeServerInfoQueryProgress {
         public int ProcessedRooms { get; set; }
         public int TotalRooms { get; set; }
-        public Dictionary<Room, State> ProcessedUsers { get; set; } = new();
+        public Dictionary<Room, State> ProcessedUsers { get; } = new();
         public List<HomeServerInfo> CurrentState { get; set; } = new();
 
-        public class State
-        {
+        public class State {
             public int Processed { get; set; }
             public int Total { get; set; }
             public bool Blocked { get; set; }
             public bool Slowmode { get; set; }
             public float Progress => (float)Processed / Total;
             public bool IsFinished { get; set; }
-            public Stopwatch Timing { get; set; } = Stopwatch.StartNew();
+            public Stopwatch Timing { get; } = Stopwatch.StartNew();
         }
     }
 
diff --git a/MatrixRoomUtils.Web/Pages/LoginPage.razor b/MatrixRoomUtils.Web/Pages/LoginPage.razor
index c46dc9a..16fdd24 100644
--- a/MatrixRoomUtils.Web/Pages/LoginPage.razor
+++ b/MatrixRoomUtils.Web/Pages/LoginPage.razor
@@ -1,6 +1,6 @@
 @page "/Login"
-@using System.Text.Json
 @using MatrixRoomUtils.Core.Authentication
+@using System.Text.Json
 @using MatrixRoomUtils.Web.Shared.SimpleComponents
 @inject ILocalStorageService LocalStorage
 @inject IJSRuntime JsRuntime
@@ -27,8 +27,7 @@
 <h4>Parsed records</h4>
 <hr/>
 <table border="1">
-    @foreach (var (homeserver, username, password) in records)
-    {
+    @foreach (var (homeserver, username, password) in records) {
         <tr style="background-color: @(RuntimeCache.LoginSessions.Any(x => x.Value.LoginResponse.UserId == $"@{username}:{homeserver}") ? "green" : "unset")">
             <td style="border-width: 1px;">@username</td>
             <td style="border-width: 1px;">@homeserver</td>
@@ -41,19 +40,16 @@
 <LogView></LogView>
 
 @code {
-    List<(string homeserver, string username, string password)> records = new();
+    readonly List<(string homeserver, string username, string password)> records = new();
     (string homeserver, string username, string password) newRecordInput = ("", "", "");
 
-    async Task Login()
-    {
-        foreach (var (homeserver, username, password) in records)
-        {
+    async Task Login() {
+        foreach (var (homeserver, username, password) in records) {
             if (RuntimeCache.LoginSessions.Any(x => x.Value.LoginResponse.UserId == $"@{username}:{homeserver}")) continue;
             var result = await MatrixAuth.Login(homeserver, username, password);
             Console.WriteLine($"Obtained access token for {result.UserId}!");
 
-            var userinfo = new UserInfo()
-            {
+            var userinfo = new UserInfo {
                 LoginResponse = result
             };
             userinfo.Profile = await (await new AuthenticatedHomeServer(result.UserId, result.AccessToken, result.HomeServer).Configure()).GetProfile(result.UserId);
@@ -66,18 +62,15 @@
         await LocalStorageWrapper.SaveToLocalStorage(LocalStorage);
     }
 
-    private async Task FileChanged(InputFileChangeEventArgs obj)
-    {
-        Console.WriteLine(JsonSerializer.Serialize(obj, new JsonSerializerOptions()
-        {
+    private async Task FileChanged(InputFileChangeEventArgs obj) {
+        Console.WriteLine(JsonSerializer.Serialize(obj, new JsonSerializerOptions {
             WriteIndented = true
         }));
         await using var rs = obj.File.OpenReadStream();
         using var sr = new StreamReader(rs);
-        string TsvData = await sr.ReadToEndAsync();
+        var TsvData = await sr.ReadToEndAsync();
         records.Clear();
-        foreach (var line in TsvData.Split('\n'))
-        {
+        foreach (var line in TsvData.Split('\n')) {
             var parts = line.Split('\t');
             if (parts.Length != 3)
                 continue;
@@ -85,8 +78,7 @@
         }
     }
 
-    private void AddRecord()
-    {
+    private void AddRecord() {
         records.Add(newRecordInput);
         newRecordInput = ("", "", "");
     }
diff --git a/MatrixRoomUtils.Web/Pages/MediaLocator.razor b/MatrixRoomUtils.Web/Pages/MediaLocator.razor
index 19a0d4e..36cd8e6 100644
--- a/MatrixRoomUtils.Web/Pages/MediaLocator.razor
+++ b/MatrixRoomUtils.Web/Pages/MediaLocator.razor
@@ -7,8 +7,7 @@
 <details>
     <summary>Checked homeserver list (@homeservers.Count entries)</summary>
     <ul>
-        @foreach (var hs in homeservers)
-        {
+        @foreach (var hs in homeservers) {
             <li>@hs</li>
         }
     </ul>
@@ -16,26 +15,22 @@
 <button @onclick="addMoreHomeservers">Add more homeservers</button>
 <br/>
 <span>MXC URL: </span>
-<input type="text" @bind="mxcUrl" />
+<input type="text" @bind="mxcUrl"/>
 <button @onclick="executeSearch">Search</button>
 
-@if (successResults.Count > 0)
-{
+@if (successResults.Count > 0) {
     <h4>Successes</h4>
     <ul>
-        @foreach (var result in successResults)
-        {
+        @foreach (var result in successResults) {
             <li>@result</li>
         }
     </ul>
 }
 
-@if (errorResults.Count > 0)
-{
+@if (errorResults.Count > 0) {
     <h4>Errors</h4>
     <ul>
-        @foreach (var result in errorResults)
-        {
+        @foreach (var result in errorResults) {
             <li>@result</li>
         }
     </ul>
@@ -44,15 +39,13 @@
 
 @code {
     string mxcUrl { get; set; }
-    List<string> successResults = new List<string>();
-    List<string> errorResults = new List<string>();
-    List<string> homeservers = new List<string>();
+    readonly List<string> successResults = new();
+    readonly List<string> errorResults = new();
+    readonly List<string> homeservers = new();
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         await base.OnInitializedAsync();
-        homeservers.AddRange(new []
-        {
+        homeservers.AddRange(new[] {
             "matrix.org",
             "feline.support",
             "rory.gay",
@@ -62,70 +55,58 @@
         });
     }
 
-    async Task executeSearch()
-    {
+    async Task executeSearch() {
         var sem = new SemaphoreSlim(128, 128);
-        homeservers.ForEach(async hs =>
-        {
+        homeservers.ForEach(async hs => {
             await sem.WaitAsync();
             var httpClient = new HttpClient { BaseAddress = new Uri(hs) };
             httpClient.Timeout = TimeSpan.FromSeconds(5);
             var rmu = mxcUrl.Replace("mxc://", $"{hs}/_matrix/media/r0/download/");
-            try
-            {
+            try {
                 var res = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, rmu));
-                if (res.IsSuccessStatusCode)
-                {
+                if (res.IsSuccessStatusCode) {
                     successResults.Add($"{hs}: found - {res.Content.Headers.ContentLength} bytes");
                     StateHasChanged();
                     return;
                 }
                 errorResults.Add($"Error: {hs} - {res.StatusCode}\n" + await res.Content.ReadAsStringAsync());
             }
-            catch (Exception e)
-            {
+            catch (Exception e) {
                 errorResults.Add($"Error: {e}");
             }
-            finally
-            {
+            finally {
                 sem.Release();
             }
             StateHasChanged();
         });
     }
 
-
-    async Task addMoreHomeservers()
-    {
+    async Task addMoreHomeservers() {
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
         var res = await Http.GetAsync("/homeservers.txt");
         var content = await res.Content.ReadAsStringAsync();
         homeservers.Clear();
         var lines = content.Split("\n");
-        
+
         var rhs = new RemoteHomeServer("rory.gay");
         var sem = new SemaphoreSlim(128, 128);
-        lines.ToList().ForEach(async line =>
-        {
+        lines.ToList().ForEach(async line => {
             await sem.WaitAsync();
-            try
-            {
+            try {
                 homeservers.Add(await rhs.ResolveHomeserverFromWellKnown(line));
                 StateHasChanged();
-                if(Random.Shared.Next(0,101) == 50) 
+                if (Random.Shared.Next(0, 101) == 50)
                     await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage);
             }
-            catch (Exception e)
-            {
+            catch (Exception e) {
                 Console.WriteLine(e);
             }
-            finally
-            {
+            finally {
                 sem.Release();
             }
         });
 
-
         StateHasChanged();
     }
+
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor
index bf03ee3..b15928a 100644
--- a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor
+++ b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor
@@ -1,7 +1,7 @@
 @page "/PolicyListEditor/{RoomId}"
-@using System.Text.Json
 @using MatrixRoomUtils.Core.Extensions
 @using MatrixRoomUtils.Core.StateEventTypes
+@using System.Text.Json
 @inject ILocalStorageService LocalStorage
 @inject NavigationManager NavigationManager
 <h3>Policy list editor - Editing @RoomId</h3>
@@ -15,12 +15,10 @@
 <InputCheckbox @bind-Value="_enableAvatars" @oninput="GetAllAvatars"></InputCheckbox><label>Enable avatars (WILL EXPOSE YOUR IP TO TARGET HOMESERVERS!)</label>
 
 
-@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.server"))
-{
+@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.server")) {
     <p>No server policies</p>
 }
-else
-{
+else {
     <h3>Server policies</h3>
     <hr/>
     <table class="table table-striped table-hover" style="width: fit-Content;">
@@ -33,8 +31,7 @@ else
         </tr>
         </thead>
         <tbody>
-        @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.server" && x.Content.Entity != null))
-        {
+        @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.server" && x.Content.Entity != null)) {
             <tr>
                 <td>Entity: @policyEvent.Content.Entity<br/>State: @policyEvent.StateKey</td>
                 <td>@policyEvent.Content.Reason</td>
@@ -59,23 +56,20 @@ else
             </tr>
             </thead>
             <tbody>
-            @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.server" && x.Content.Entity == null))
-            {
+            @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.server" && x.Content.Entity == null)) {
                 <tr>
                     <td>@policyEvent.StateKey</td>
-                    <td>@policyEvent.Content.ToJson(indent: false, ignoreNull: true)</td>
+                    <td>@policyEvent.Content.ToJson(false, true)</td>
                 </tr>
             }
             </tbody>
         </table>
     </details>
 }
-@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.room"))
-{
+@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.room")) {
     <p>No room policies</p>
 }
-else
-{
+else {
     <h3>Room policies</h3>
     <hr/>
     <table class="table table-striped table-hover" style="width: fit-Content;">
@@ -88,8 +82,7 @@ else
         </tr>
         </thead>
         <tbody>
-        @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.room" && x.Content.Entity != null))
-        {
+        @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.room" && x.Content.Entity != null)) {
             <tr>
                 <td>Entity: @policyEvent.Content.Entity<br/>State: @policyEvent.StateKey</td>
                 <td>@policyEvent.Content.Reason</td>
@@ -113,30 +106,26 @@ else
             </tr>
             </thead>
             <tbody>
-            @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.room" && x.Content.Entity == null))
-            {
+            @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.room" && x.Content.Entity == null)) {
                 <tr>
                     <td>@policyEvent.StateKey</td>
-                    <td>@policyEvent.Content.ToJson(indent: false, ignoreNull: true)</td>
+                    <td>@policyEvent.Content.ToJson(false, true)</td>
                 </tr>
             }
             </tbody>
         </table>
     </details>
 }
-@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.user"))
-{
+@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.user")) {
     <p>No user policies</p>
 }
-else
-{
+else {
     <h3>User policies</h3>
     <hr/>
     <table class="table table-striped table-hover" style="width: fit-Content;">
         <thead>
         <tr>
-            @if (_enableAvatars)
-            {
+            @if (_enableAvatars) {
                 <th scope="col"></th>
             }
             <th scope="col" style="max-width: 0.2vw; word-wrap: anywhere;">User</th>
@@ -146,12 +135,12 @@ else
         </tr>
         </thead>
         <tbody>
-        @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity != null))
-        {
+        @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity != null)) {
             <tr>
-                @if (_enableAvatars)
-                {
-                    <td scope="col"><img style="width: 48px; height: 48px; aspect-ratio: unset; border-radius: 50%;" src="@(avatars.ContainsKey(policyEvent.Content.Entity) ? avatars[policyEvent.Content.Entity] : "")"/></td>
+                @if (_enableAvatars) {
+                    <td scope="col">
+                        <img style="width: 48px; height: 48px; aspect-ratio: unset; border-radius: 50%;" src="@(avatars.ContainsKey(policyEvent.Content.Entity) ? avatars[policyEvent.Content.Entity] : "")"/>
+                    </td>
                 }
                 <td style="word-wrap: anywhere;">Entity: @string.Join("", policyEvent.Content.Entity.Take(64))<br/>State: @string.Join("", policyEvent.StateKey.Take(64))</td>
                 <td>@policyEvent.Content.Reason</td>
@@ -175,11 +164,10 @@ else
             </tr>
             </thead>
             <tbody>
-            @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity == null))
-            {
+            @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity == null)) {
                 <tr>
                     <td>@policyEvent.StateKey</td>
-                    <td>@policyEvent.Content.ToJson(indent: false, ignoreNull: true)</td>
+                    <td>@policyEvent.Content.ToJson(false, true)</td>
                 </tr>
             }
             </tbody>
@@ -197,21 +185,19 @@ else
 
     [Parameter]
     public string? RoomId { get; set; }
-    
-    private bool _enableAvatars = false;
-    
-    static Dictionary<string, string?> avatars = new Dictionary<string, string?>();
-    static Dictionary<string, RemoteHomeServer> servers = new Dictionary<string, RemoteHomeServer>();
+
+    private bool _enableAvatars;
+
+    static readonly Dictionary<string, string?> avatars = new();
+    static readonly Dictionary<string, RemoteHomeServer> servers = new();
 
     public static List<StateEventResponse<PolicyRuleStateEventData>> PolicyEvents { get; set; } = new();
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
         await base.OnInitializedAsync();
-        // if(RuntimeCache.AccessToken == null || RuntimeCache.CurrentHomeserver == null)
-        if (RuntimeCache.CurrentHomeServer == null)
-        {
+    // if(RuntimeCache.AccessToken == null || RuntimeCache.CurrentHomeserver == null)
+        if (RuntimeCache.CurrentHomeServer == null) {
             NavigationManager.NavigateTo("/Login");
             return;
         }
@@ -220,18 +206,16 @@ else
         Console.WriteLine("Policy list editor initialized!");
     }
 
-    private async Task LoadStatesAsync()
-    {
-        // using var client = new HttpClient();
-        // client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", LocalStorageWrapper.AccessToken);
-        // var response = await client.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/r0/rooms/{RoomId}/state");
-        // var Content = await response.Content.ReadAsStringAsync();
-        // Console.WriteLine(JsonSerializer.Deserialize<object>(Content).ToJson());
-        // var stateEvents = JsonSerializer.Deserialize<List<StateEventResponse>>(Content);
+    private async Task LoadStatesAsync() {
+    // using var client = new HttpClient();
+    // client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", LocalStorageWrapper.AccessToken);
+    // var response = await client.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/r0/rooms/{RoomId}/state");
+    // var Content = await response.Content.ReadAsStringAsync();
+    // Console.WriteLine(JsonSerializer.Deserialize<object>(Content).ToJson());
+    // var stateEvents = JsonSerializer.Deserialize<List<StateEventResponse>>(Content);
         var room = await RuntimeCache.CurrentHomeServer.GetRoom(RoomId);
         var stateEventsQuery = await room.GetStateAsync("");
-        if (stateEventsQuery == null)
-        {
+        if (stateEventsQuery == null) {
             Console.WriteLine("state events query is null!!!");
         }
         var stateEvents = stateEventsQuery.Value.Deserialize<List<StateEventResponse>>();
@@ -239,30 +223,25 @@ else
             .Select(x => JsonSerializer.Deserialize<StateEventResponse<PolicyRuleStateEventData>>(JsonSerializer.Serialize(x))).ToList();
         StateHasChanged();
     }
-    
-    private async Task GetAvatar(string userId)
-    {
-        try
-        {
+
+    private async Task GetAvatar(string userId) {
+        try {
             if (avatars.ContainsKey(userId)) return;
             var hs = userId.Split(':')[1];
-            RemoteHomeServer server = servers.ContainsKey(hs) ? servers[hs] : await new RemoteHomeServer(userId.Split(':')[1]).Configure();
+            var server = servers.ContainsKey(hs) ? servers[hs] : await new RemoteHomeServer(userId.Split(':')[1]).Configure();
             if (!servers.ContainsKey(hs)) servers.Add(hs, server);
             var profile = await server.GetProfile(userId);
             avatars.Add(userId, server.ResolveMediaUri(profile.AvatarUrl));
             servers.Add(userId, server);
             StateHasChanged();
         }
-        catch
-        {
-            // ignored
+        catch {
+    // ignored
         }
     }
-    
-    private async Task GetAllAvatars()
-    {
-        foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity != null))
-        {
+
+    private async Task GetAllAvatars() {
+        foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity != null)) {
             await GetAvatar(policyEvent.Content.Entity);
         }
         StateHasChanged();
diff --git a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor
index e61598a..20eab7a 100644
--- a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor
+++ b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor
@@ -1,29 +1,25 @@
 @page "/PolicyListEditor"
-@using System.Text.Json
 @using MatrixRoomUtils.Core.Extensions
 @inject ILocalStorageService LocalStorage
 @inject NavigationManager NavigationManager
 <h3>Policy list editor - Room list</h3>
 <hr/>
 
-@if (PolicyRoomList.Count == 0)
-{
+@if (PolicyRoomList.Count == 0) {
     <p>No policy rooms found.</p>
     <p>Loading progress: @checkedRoomCount/@totalRoomCount</p>
 }
-else
-{
-    @if (checkedRoomCount != totalRoomCount)
-    {
+else {
+    @if (checkedRoomCount != totalRoomCount) {
         <p>Loading progress: @checkedRoomCount/@totalRoomCount</p>
     }
-    foreach (var s in PolicyRoomList)
-    {
-        
-        <a style="color: unset; text-decoration: unset;" href="/PolicyListEditor/@s.RoomId.Replace('.','~')"><RoomListItem RoomId="@s.RoomId">
-            <br/>
-            <span>Shortcode: @s.Shortcode</span>
-        </RoomListItem></a>
+    foreach (var s in PolicyRoomList) {
+        <a style="color: unset; text-decoration: unset;" href="/PolicyListEditor/@s.RoomId.Replace('.', '~')">
+            <RoomListItem RoomId="@s.RoomId">
+                <br/>
+                <span>Shortcode: @s.Shortcode</span>
+            </RoomListItem>
+        </a>
         @* <a href="@(NavigationManager.Uri + "/" + s.RoomId.Replace('.', '~'))">[@s.Shortcode] @s.Name (@s.RoomId)</a> *@
         @* <br/> *@
     }
@@ -40,15 +36,13 @@ else
 
     public List<PolicyRoomInfo> PolicyRoomList { get; set; } = new();
 
-    private int checkedRoomCount { get; set; } = 0;
-    private int totalRoomCount { get; set; } = 0;
+    private int checkedRoomCount { get; set; }
+    private int totalRoomCount { get; set; }
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
         await base.OnInitializedAsync();
-        if (RuntimeCache.CurrentHomeServer == null)
-        {
+        if (RuntimeCache.CurrentHomeServer == null) {
             NavigationManager.NavigateTo("/Login");
             return;
         }
@@ -56,59 +50,48 @@ else
         Console.WriteLine("Policy list editor initialized!");
     }
 
-    private async Task EnumeratePolicyRooms()
-    {
+    private async Task EnumeratePolicyRooms() {
         var xxxrooms = await RuntimeCache.CurrentHomeServer.GetJoinedRooms();
         totalRoomCount = xxxrooms.Count;
         StateHasChanged();
 
         var xxxsemaphore = new SemaphoreSlim(1000);
         var xxxtasks = new List<Task<PolicyRoomInfo?>>();
-        foreach (var room in xxxrooms)
-        {
+        foreach (var room in xxxrooms) {
             xxxtasks.Add(GetPolicyRoomInfo(room.RoomId, xxxsemaphore));
         }
         var xxxresults = await Task.WhenAll(xxxtasks);
         PolicyRoomList.AddRange(xxxresults.Where(x => x != null).Select(x => x.Value));
 
         Console.WriteLine($"Detected policy lists: {PolicyRoomList.ToJson()}");
-        return;
     }
 
-    private async Task<PolicyRoomInfo?> GetPolicyRoomInfo(string room, SemaphoreSlim semaphore)
-    {
-        try
-        {
+    private async Task<PolicyRoomInfo?> GetPolicyRoomInfo(string room, SemaphoreSlim semaphore) {
+        try {
             await semaphore.WaitAsync();
-            PolicyRoomInfo roomInfo = new()
-            {
+            PolicyRoomInfo roomInfo = new() {
                 RoomId = room
             };
             var r = await RuntimeCache.CurrentHomeServer.GetRoom(room);
             var shortcodeState = await r.GetStateAsync("org.matrix.mjolnir.shortcode");
-            if(!shortcodeState.HasValue) return null;
-            roomInfo.Shortcode = shortcodeState.Value.TryGetProperty("shortcode", out JsonElement shortcode) ? shortcode.GetString() : null;
+            if (!shortcodeState.HasValue) return null;
+            roomInfo.Shortcode = shortcodeState.Value.TryGetProperty("shortcode", out var shortcode) ? shortcode.GetString() : null;
 
-            if (roomInfo.Shortcode != null)
-            {
+            if (roomInfo.Shortcode != null) {
                 roomInfo.Name = await r.GetNameAsync();
                 return roomInfo;
             }
 
             return null;
         }
-        finally
-
-        {
+        finally {
             checkedRoomCount++;
             StateHasChanged();
             semaphore.Release();
         }
     }
 
-    public struct PolicyRoomInfo
-
-    {
+    public struct PolicyRoomInfo {
         public
             string RoomId { get; set; }
 
@@ -118,4 +101,5 @@ else
         public
             string? Name { get; set; }
     }
-    } 
\ No newline at end of file
+
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor
index 5daa97c..9b0bb88 100644
--- a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor
@@ -3,12 +3,10 @@
 @inject NavigationManager NavigationManager
 <h3>Room manager</h3>
 <hr/>
-@if (Rooms.Count == 0)
-{
+@if (Rooms.Count == 0) {
     <p>You are not in any rooms!</p>
 }
-else
-{
+else {
     <p>You are in @Rooms.Count rooms and @Spaces.Count spaces</p>
     <p>
         <a href="/RoomManagerCreateRoom">Create room</a>
@@ -16,8 +14,7 @@ else
 
     <details open>
         <summary>Space List</summary>
-        @foreach (var room in Spaces)
-        {
+        @foreach (var room in Spaces) {
             <a style="color: unset; text-decoration: unset;" href="/RoomManager/Space/@room.RoomId.Replace('.', '~')">
                 <RoomListItem Room="@room" ShowOwnProfile="false"></RoomListItem>
             </a>
@@ -25,8 +22,7 @@ else
     </details>
     <details open>
         <summary>Room List</summary>
-        @foreach (var room in Rooms)
-        {
+        @foreach (var room in Rooms) {
             <a style="color: unset; text-decoration: unset;" href="/RoomManager/Room/@room.RoomId.Replace('.', '~')">
                 <RoomListItem Room="@room" ShowOwnProfile="true"></RoomListItem>
             </a>
@@ -41,15 +37,13 @@ else
     public List<Room> Rooms { get; set; } = new();
     public List<Room> Spaces { get; set; } = new();
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         Console.WriteLine("Initializing room manager");
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
         Console.WriteLine("Loaded from local storage");
         await base.OnInitializedAsync();
         Console.WriteLine("Initialized base");
-        if (RuntimeCache.CurrentHomeServer == null)
-        {
+        if (RuntimeCache.CurrentHomeServer == null) {
             NavigationManager.NavigateTo("/Login");
             return;
         }
@@ -59,8 +53,7 @@ else
         Console.WriteLine($"Got {_rooms.Count} rooms");
         var semaphore = new SemaphoreSlim(10);
         var tasks = new List<Task<Room?>>();
-        foreach (var room in _rooms)
-        {
+        foreach (var room in _rooms) {
             tasks.Add(CheckIfSpace(room, semaphore));
         }
         await Task.WhenAll(tasks);
@@ -68,45 +61,36 @@ else
         Console.WriteLine("Fetched joined rooms!");
     }
 
-    private async Task<Room?> CheckIfSpace(Room room, SemaphoreSlim semaphore)
-    {
+    private async Task<Room?> CheckIfSpace(Room room, SemaphoreSlim semaphore) {
         await semaphore.WaitAsync();
-        // Console.WriteLine($"Checking if {room.RoomId} is a space");
-        try
-        {
+    // Console.WriteLine($"Checking if {room.RoomId} is a space");
+        try {
             var state = await room.GetStateAsync<CreateEvent>("m.room.create");
-            if (state != null)
-            {
+            if (state != null) {
     //Console.WriteLine(state.Value.ToJson());
-                if (state.Type != null)
-                {
-                    if (state.Type == "m.space")
-                    {
+                if (state.Type != null) {
+                    if (state.Type == "m.space") {
                         Console.WriteLine($"Room {room.RoomId} is a space!");
                         Spaces.Add(room);
                         StateHasChanged();
                         return room;
                     }
-                    else
-                    {
+                    else {
                         Console.WriteLine($"Encountered unknown room type {state.Type}");
                     }
                 }
-                else
-                {
+                else {
                     Rooms.Add(room);
     //this is fine, apprently...
     // Console.WriteLine($"Room {room.RoomId} has no Content.type in m.room.create!");
                 }
             }
         }
-        catch (Exception e)
-        {
+        catch (Exception e) {
             Console.WriteLine(e);
             return null;
         }
-        finally
-        {
+        finally {
             semaphore.Release();
         }
         return null;
diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor
index d561eb0..5cfda77 100644
--- a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor
@@ -1,12 +1,13 @@
 @page "/RoomManagerCreateRoom"
-@using System.Text.Json
 @using MatrixRoomUtils.Core.Extensions
 @using MatrixRoomUtils.Core.Responses
-@using MatrixRoomUtils.Web.Shared.SimpleComponents
-@using System.Reflection
-@using System.Runtime.Intrinsics.X86
+@using System.Text.Json
 @using System.Text.Json.Serialization
+@using System.Reflection
 @using MatrixRoomUtils.Web.Classes.RoomCreationTemplates
+@* ReSharper disable once RedundantUsingDirective - Must not remove this, Rider marks this as "unused" when it's not *@
+@using MatrixRoomUtils.Web.Shared.SimpleComponents
+
 <h3>Room Manager - Create Room</h3>
 
 @* <pre Contenteditable="true" @onkeypress="@JsonChanged" ="JsonString">@JsonString</pre> *@
@@ -20,15 +21,13 @@
         <td style="padding-bottom: 16px;">Preset:</td>
         <td style="padding-bottom: 16px;">
             <InputSelect @bind-Value="@RoomPreset">
-                @foreach (var createRoomRequest in Presets)
-                {
+                @foreach (var createRoomRequest in Presets) {
                     <option value="@createRoomRequest.Key">@createRoomRequest.Key</option>
                 }
             </InputSelect>
         </td>
     </tr>
-    @if (creationEvent != null)
-    {
+    @if (creationEvent != null) {
         <tr>
             <td>Room name:</td>
             <td>
@@ -89,8 +88,7 @@
             <td>Permissions:</td>
             <details>
                 <summary>@creationEvent.PowerLevelContentOverride.Users.Count members</summary>
-                @foreach (var user in creationEvent.PowerLevelContentOverride.Events.Keys)
-                {
+                @foreach (var user in creationEvent.PowerLevelContentOverride.Events.Keys) {
                     var _event = user;
                     <tr>
                         <td><FancyTextBox Formatter="@GetPermissionFriendlyName" Value="@_event" ValueChanged="val => { creationEvent.PowerLevelContentOverride.Events.ChangeKey(_event, val); }"></FancyTextBox>:</td>
@@ -99,8 +97,7 @@
                         </td>
                     </tr>
                 }
-                @foreach (var user in creationEvent.PowerLevelContentOverride.Users.Keys)
-                {
+                @foreach (var user in creationEvent.PowerLevelContentOverride.Users.Keys) {
                     var _user = user;
                     <tr>
                         <td><FancyTextBox Value="@_user" ValueChanged="val => { creationEvent.PowerLevelContentOverride.Users.ChangeKey(_user, val); creationEvent.PowerLevelContentOverride.Users = creationEvent.PowerLevelContentOverride.Users.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); }"></FancyTextBox>:</td>
@@ -131,8 +128,7 @@
                 <details>
                     <summary>@creationEvent.InitialState.Count(x => x.Type == "m.room.member") members</summary>
                     <button @onclick="() => { RuntimeCache.LoginSessions.Select(x => x.Value.LoginResponse.UserId).ToList().ForEach(InviteMember); }">Invite all logged in accounts</button>
-                    @foreach (var member in creationEvent.InitialState.Where(x => x.Type == "m.room.member" && x.StateKey != RuntimeCache.CurrentHomeServer.UserId))
-                    {
+                    @foreach (var member in creationEvent.InitialState.Where(x => x.Type == "m.room.member" && x.StateKey != RuntimeCache.CurrentHomeServer.UserId)) {
                         <UserListItem UserId="@member.StateKey"></UserListItem>
                     }
                 </details>
@@ -154,13 +150,11 @@
 
                     <summary>@creationEvent.InitialState.Count(x => !ImplementedStates.Contains(x.Type)) custom states</summary>
                     <table>
-                        @foreach (var initialState in creationEvent.InitialState.Where(x => !ImplementedStates.Contains(x.Type)))
-                        {
+                        @foreach (var initialState in creationEvent.InitialState.Where(x => !ImplementedStates.Contains(x.Type))) {
                             <tr>
                                 <td style="vertical-align: top;">
                                     @(initialState.Type):
-                                    @if (!string.IsNullOrEmpty(initialState.StateKey))
-                                    {
+                                    @if (!string.IsNullOrEmpty(initialState.StateKey)) {
                                         <br/>
                                         <span>(@initialState.StateKey)</span>
                                     }
@@ -176,8 +170,7 @@
                 <details>
                     <summary>@creationEvent.InitialState.Count initial states</summary>
                     <table>
-                        @foreach (var initialState in creationEvent.InitialState)
-                        {
+                        @foreach (var initialState in creationEvent.InitialState) {
                             var _state = initialState;
                             <tr>
                                 <td style="vertical-align: top;">
@@ -214,25 +207,21 @@
 
 @code {
 
-    private string RoomPreset
-    {
-        get
-        {
-            if (Presets.ContainsValue(creationEvent))
-            {
+    private string RoomPreset {
+        get {
+            if (Presets.ContainsValue(creationEvent)) {
                 return Presets.First(x => x.Value == creationEvent).Key;
             }
             return "Not a preset";
         }
-        set
-        {
+        set {
             creationEvent = Presets[value];
             JsonChanged();
             OverwriteWrappedPropertiesFromEvent();
             creationEvent.PowerLevelContentOverride.Events = creationEvent.PowerLevelContentOverride.Events.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value);
             creationEvent.PowerLevelContentOverride.Users = creationEvent.PowerLevelContentOverride.Users.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value);
             guestAccessEvent = creationEvent["m.room.guest_access"].As<GuestAccessContent>().Content;
-            
+
             Console.WriteLine($"Creation event uncasted: {creationEvent["m.room.guest_access"].ToJson()}");
             Console.WriteLine($"Creation event casted: {creationEvent["m.room.guest_access"].As<GuestAccessContent>().ToJson()}");
             creationEvent["m.room.guest_access"].As<GuestAccessContent>().Content.IsGuestAccessEnabled = true;
@@ -251,21 +240,18 @@
 
     private Dictionary<string, CreateRoomRequest> Presets { get; set; } = new();
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
 
     //creationEvent = Presets["Default room"] = 
-        foreach (var x in Assembly.GetExecutingAssembly().GetTypes().Where(x => x.IsClass && !x.IsAbstract && x.GetInterfaces().Contains(typeof(IRoomCreationTemplate))).ToList())
-        {
+        foreach (var x in Assembly.GetExecutingAssembly().GetTypes().Where(x => x.IsClass && !x.IsAbstract && x.GetInterfaces().Contains(typeof(IRoomCreationTemplate))).ToList()) {
             Console.WriteLine($"Found room creation template in class: {x.FullName}");
             var instance = (IRoomCreationTemplate)Activator.CreateInstance(x);
             Presets[instance.Name] = instance.CreateRoomRequest;
         }
         Presets = Presets.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value);
 
-        if (!Presets.ContainsKey("Default"))
-        {
+        if (!Presets.ContainsKey("Default")) {
             Console.WriteLine($"No default room found in {Presets.Count} presets: {string.Join(", ", Presets.Keys)}");
         }
         else RoomPreset = "Default";
@@ -273,30 +259,23 @@
         await base.OnInitializedAsync();
     }
 
-    private void JsonChanged()
-    {
-        Console.WriteLine(creationEvent.ToJson());
-    }
-
+    private void JsonChanged() => Console.WriteLine(creationEvent.ToJson());
 
     //wrappers
     private List<string> ServerACLAllowRules { get; set; } = new();
     private List<string> ServerACLDenyRules { get; set; } = new();
 
-    private void OverwriteWrappedPropertiesFromEvent()
-    {
+    private void OverwriteWrappedPropertiesFromEvent() {
         Console.WriteLine("Overwriting wrapped properties from event");
         ServerACLAllowRules = creationEvent.ServerACLs.Allow;
         ServerACLDenyRules = creationEvent.ServerACLs.Deny;
     }
 
-    private async Task OverwriteWrappedProperties()
-    {
+    private async Task OverwriteWrappedProperties() {
         Console.WriteLine("Overwriting wrapped properties");
         Console.WriteLine($"Allow: {ServerACLAllowRules.Count}: {string.Join(", ", ServerACLAllowRules)}");
         Console.WriteLine($"Deny: {ServerACLDenyRules.Count}: {string.Join(", ", ServerACLDenyRules)}");
-        creationEvent.ServerACLs = new()
-        {
+        creationEvent.ServerACLs = new ServerACL {
             Allow = ServerACLAllowRules,
             Deny = ServerACLDenyRules,
             AllowIpLiterals = creationEvent.ServerACLs.AllowIpLiterals
@@ -305,16 +284,14 @@
         StateHasChanged();
     }
 
-    private async Task RoomIconFilePicked(InputFileChangeEventArgs obj)
-    {
+    private async Task RoomIconFilePicked(InputFileChangeEventArgs obj) {
         var res = await RuntimeCache.CurrentHomeServer.UploadFile(obj.File.Name, obj.File.OpenReadStream(), obj.File.ContentType);
         Console.WriteLine(res);
         creationEvent.RoomIcon = res;
         StateHasChanged();
     }
 
-    private async Task CreateRoom()
-    {
+    private async Task CreateRoom() {
         Console.WriteLine("Create room");
         Console.WriteLine(creationEvent.ToJson());
         creationEvent.CreationContent.Add("rory.gay.created_using", "Rory&::MatrixRoomUtils (https://mru.rory.gay)");
@@ -323,22 +300,18 @@
     // NavigationManager.NavigateTo($"/RoomManager/{id.RoomId.Replace('.','~')}");
     }
 
-    private void InviteMember(string mxid)
-    {
+    private void InviteMember(string mxid) {
         if (!creationEvent.InitialState.Any(x => x.Type == "m.room.member" && x.StateKey == mxid) && RuntimeCache.CurrentHomeServer.UserId != mxid)
-            creationEvent.InitialState.Add(new()
-            {
+            creationEvent.InitialState.Add(new StateEvent {
                 Type = "m.room.member",
                 StateKey = mxid,
-                Content = new
-                {
+                Content = new {
                     membership = "invite",
                     reason = "Automatically invited at room creation time."
                 }
             });
     }
 
-
     private string GetStateFriendlyName(string key) => key switch {
         "m.room.history_visibility" => "History visibility",
         "m.room.guest_access" => "Guest access",
@@ -363,19 +336,14 @@
         _ => key
         };
 
-    public class GuestAccessContent
-    {
+    public class GuestAccessContent {
         [JsonPropertyName("guest_access")]
         public string GuestAccess { get; set; }
 
-        public bool IsGuestAccessEnabled
-        {
+        public bool IsGuestAccessEnabled {
             get => GuestAccess == "can_join";
             set => GuestAccess = value ? "can_join" : "forbidden";
         }
     }
-
-    
     }
 
-
diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor
index 1e7e065..c5e1569 100644
--- a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor
@@ -4,8 +4,7 @@
 <h3>Room manager - Viewing Space</h3>
 
 <button onclick="@JoinAllRooms">Join all rooms</button>
-@foreach (var room in Rooms)
-{
+@foreach (var room in Rooms) {
     <RoomListItem Room="room" ShowOwnProfile="true"></RoomListItem>
 }
 
@@ -13,8 +12,7 @@
 <br/>
 <details style="background: #0002;">
     <summary style="background: #fff1;">State list</summary>
-    @foreach (var stateEvent in States.OrderBy(x => x.StateKey).ThenBy(x => x.Type))
-    {
+    @foreach (var stateEvent in States.OrderBy(x => x.StateKey).ThenBy(x => x.Type)) {
         <p>@stateEvent.StateKey/@stateEvent.Type:</p>
         <pre>@stateEvent.Content.ToJson()</pre>
     }
@@ -24,61 +22,52 @@
 
     [Parameter]
     public string RoomId { get; set; } = "invalid!!!!!!";
-    
+
     private Room? Room { get; set; }
-    
+
     private StateEventResponse<object>[] States { get; set; } = Array.Empty<StateEventResponse<object>>();
-    private List<Room> Rooms { get; set; } = new();
-    private List<string> ServersInSpace { get; set; } = new();
-    
-    protected override async Task OnInitializedAsync()
-    {
+    private List<Room> Rooms { get; } = new();
+    private List<string> ServersInSpace { get; } = new();
+
+    protected override async Task OnInitializedAsync() {
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
         Room = await RuntimeCache.CurrentHomeServer.GetRoom(RoomId.Replace('~', '.'));
         var state = await Room.GetStateAsync("");
-        if (state != null)
-        {
-            // Console.WriteLine(state.Value.ToJson());
+        if (state != null) {
+    // Console.WriteLine(state.Value.ToJson());
             States = state.Value.Deserialize<StateEventResponse<object>[]>()!;
-            
-            foreach (var stateEvent in States)
-            {
-                if (stateEvent.Type == "m.space.child")
-                {
-                    // if (stateEvent.Content.ToJson().Length < 5) return;
+
+            foreach (var stateEvent in States) {
+                if (stateEvent.Type == "m.space.child") {
+    // if (stateEvent.Content.ToJson().Length < 5) return;
                     var roomId = stateEvent.StateKey;
                     var room = await RuntimeCache.CurrentHomeServer.GetRoom(roomId);
-                    if (room != null)
-                    {
+                    if (room != null) {
                         Rooms.Add(room);
                     }
                 }
-                else if (stateEvent.Type == "m.room.member")
-                {
+                else if (stateEvent.Type == "m.room.member") {
                     var serverName = stateEvent.StateKey.Split(':').Last();
-                    if (!ServersInSpace.Contains(serverName))
-                    {
+                    if (!ServersInSpace.Contains(serverName)) {
                         ServersInSpace.Add(serverName);
                     }
                 }
             }
-            
-        // if(state.Value.TryGetProperty("Type", out var Type))
-        // {
-        // }
-        // else
-        // {
-        //     //this is fine, apprently...
-        //     //Console.WriteLine($"Room {room.RoomId} has no Content.Type in m.room.create!");
-        // }
+
+    // if(state.Value.TryGetProperty("Type", out var Type))
+    // {
+    // }
+    // else
+    // {
+    //     //this is fine, apprently...
+    //     //Console.WriteLine($"Room {room.RoomId} has no Content.Type in m.room.create!");
+    // }
         }
         await base.OnInitializedAsync();
     }
-    
-    private async Task JoinAllRooms()
-    {
-        foreach (var room in Rooms)
-        {
+
+    private async Task JoinAllRooms() {
+        foreach (var room in Rooms) {
             room.JoinAsync(ServersInSpace.ToArray());
         }
     }
diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerTimeline.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerTimeline.razor
index a8a7fc2..2db7cab 100644
--- a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerTimeline.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerTimeline.razor
@@ -1,12 +1,10 @@
 @page "/RoomManager/Timeline/{RoomId}"
 @using MatrixRoomUtils.Web.Shared.TimelineComponents
-@using MatrixRoomUtils.Core.Extensions
 <h3>RoomManagerTimeline</h3>
 <hr/>
 <p>Loaded @Events.Count events...</p>
 
-@foreach (var evt in Events)
-{
+@foreach (var evt in Events) {
     <div type="@evt.Type" key="@evt.StateKey" itemid="@evt.EventId">
         <DynamicComponent Type="@ComponentType(evt)" Parameters="@(new Dictionary<string, object> { { "Event", evt }, { "Events", Events } })"></DynamicComponent>
     </div>
@@ -17,18 +15,16 @@
     [Parameter]
     public string RoomId { get; set; } = "invalid!!!!!!";
 
-    private List<MessagesResponse> Messages { get; set; } = new();
-    private List<StateEventResponse> Events { get; set; } = new();
+    private List<MessagesResponse> Messages { get; } = new();
+    private List<StateEventResponse> Events { get; } = new();
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
         RoomId = RoomId.Replace('~', '.');
         Console.WriteLine("RoomId: " + RoomId);
         var room = await RuntimeCache.CurrentHomeServer.GetRoom(RoomId);
         MessagesResponse? msgs = null;
-        do
-        {
+        do {
             msgs = await room.GetMessagesAsync(limit: 250, from: msgs?.End, dir: "b");
             Messages.Add(msgs);
             Console.WriteLine($"Got {msgs.Chunk.Count} messages");
@@ -37,13 +33,11 @@
             StateHasChanged();
         } while (msgs.End != null);
 
-
         await base.OnInitializedAsync();
     }
 
     private StateEventResponse GetProfileEventBefore(StateEventResponse Event) => Events.TakeWhile(x => x != Event).Last(e => e.Type == "m.room.member" && e.StateKey == Event.Sender);
 
-
     private Type ComponentType(StateEventResponse Event) => Event.Type switch {
         "m.room.message" => typeof(TimelineMessageItem),
         "m.room.member" => typeof(TimelineMemberItem),
diff --git a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor
index 3037dcc..74f4f92 100644
--- a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor
@@ -12,8 +12,7 @@
 <br/>
 <InputSelect @bind-Value="shownStateKey">
     <option value="">-- State key --</option>
-    @foreach (var stateEvent in FilteredEvents.Where(x => x.StateKey != "").Select(x => x.StateKey).Distinct().OrderBy(x => x))
-    {
+    @foreach (var stateEvent in FilteredEvents.Where(x => x.StateKey != "").Select(x => x.StateKey).Distinct().OrderBy(x => x)) {
         <option value="@stateEvent">@stateEvent</option>
         Console.WriteLine(stateEvent);
     }
@@ -21,8 +20,7 @@
 <br/>
 <InputSelect @bind-Value="shownType">
     <option value="">-- Type --</option>
-    @foreach (var stateEvent in FilteredEvents.Where(x => x.StateKey != shownStateKey).Select(x => x.Type).Distinct().OrderBy(x => x))
-    {
+    @foreach (var stateEvent in FilteredEvents.Where(x => x.StateKey != shownStateKey).Select(x => x.Type).Distinct().OrderBy(x => x)) {
         <option value="@stateEvent">@stateEvent</option>
     }
 </InputSelect>
@@ -45,12 +43,10 @@
     public List<StateEventResponse> Events { get; set; } = new();
     public string status = "";
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
         await base.OnInitializedAsync();
-        if (RuntimeCache.CurrentHomeServer != null)
-        {
+        if (RuntimeCache.CurrentHomeServer != null) {
             NavigationManager.NavigateTo("/Login");
             return;
         }
@@ -61,34 +57,29 @@
 
     private DateTime _lastUpdate = DateTime.Now;
 
-    private async Task LoadStatesAsync()
-    {
-        int StateLoaded = 0;
+    private async Task LoadStatesAsync() {
+        var StateLoaded = 0;
         using var client = new HttpClient();
-        //TODO: can this be improved?
+    //TODO: can this be improved?
         client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeCache.CurrentHomeServer.AccessToken);
         var response = await client.GetAsync($"{RuntimeCache.CurrentHomeServer.FullHomeServerDomain}/_matrix/client/r0/rooms/{RoomId}/state");
     // var response = await client.GetAsync($"http://localhost:5117/matrix-hq-state.json");
     //var _events = await response.Content.ReadFromJsonAsync<Queue<StateEventStruct>>();
         var _data = await response.Content.ReadAsStreamAsync();
         var __events = JsonSerializer.DeserializeAsyncEnumerable<StateEventResponse>(_data);
-        await foreach (var _ev in __events)
-        {
-            var e = new StateEventResponse()
-            {
+        await foreach (var _ev in __events) {
+            var e = new StateEventResponse {
                 Type = _ev.Type,
                 StateKey = _ev.StateKey,
                 OriginServerTs = _ev.OriginServerTs,
                 Content = _ev.Content
             };
             Events.Add(e);
-            if (string.IsNullOrEmpty(e.StateKey))
-            {
+            if (string.IsNullOrEmpty(e.StateKey)) {
                 FilteredEvents.Add(e);
             }
             StateLoaded++;
-            if ((DateTime.Now - _lastUpdate).TotalMilliseconds > 100)
-            {
+            if ((DateTime.Now - _lastUpdate).TotalMilliseconds > 100) {
                 _lastUpdate = DateTime.Now;
                 status = $"Loaded {StateLoaded} state events";
                 StateHasChanged();
@@ -99,8 +90,7 @@
         StateHasChanged();
     }
 
-    private async Task RebuildFilteredData()
-    {
+    private async Task RebuildFilteredData() {
         status = "Rebuilding filtered data...";
         StateHasChanged();
         await Task.Delay(1);
@@ -112,16 +102,14 @@
         StateHasChanged();
         await Task.Delay(1);
         FilteredEvents = _FilteredEvents;
-        
-        if(_shownType != null)
+
+        if (_shownType != null)
             shownEventJson = _FilteredEvents.Where(x => x.Type == _shownType).First().Content.ToJson(indent: true, ignoreNull: true);
-        
+
         StateHasChanged();
     }
 
-
-    public struct PreRenderedStateEvent
-    {
+    public struct PreRenderedStateEvent {
         public string content { get; set; }
         public long origin_server_ts { get; set; }
         public string state_key { get; set; }
@@ -132,11 +120,9 @@
     // public string ReplacesState { get; set; }
     }
 
-    public bool ShowMembershipEvents
-    {
+    public bool ShowMembershipEvents {
         get => _showMembershipEvents;
-        set
-        {
+        set {
             _showMembershipEvents = value;
             RebuildFilteredData();
         }
@@ -146,21 +132,17 @@
     private string _shownStateKey;
     private string _shownType;
 
-    private string shownStateKey
-    {
+    private string shownStateKey {
         get => _shownStateKey;
-        set
-        {
+        set {
             _shownStateKey = value;
             RebuildFilteredData();
         }
     }
 
-    private string shownType
-    {
+    private string shownType {
         get => _shownType;
-        set
-        {
+        set {
             _shownType = value;
             RebuildFilteredData();
         }
diff --git a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateRoomList.razor b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateRoomList.razor
index c654b13..82b5d75 100644
--- a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateRoomList.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateRoomList.razor
@@ -3,16 +3,15 @@
 @inject NavigationManager NavigationManager
 <h3>Room state viewer - Room list</h3>
 <hr/>
-@if (Rooms.Count == 0)
-{
+@if (Rooms.Count == 0) {
     <p>You are not in any rooms!</p>
     @* <p>Loading progress: @checkedRoomCount/@totalRoomCount</p> *@
 }
-else
-{
-    @foreach (var room in Rooms)
-    {
-        <a style="color: unset; text-decoration: unset;" href="/RoomStateViewer/@room.Replace('.','~')"><RoomListItem RoomId="@room"></RoomListItem></a>
+else {
+    @foreach (var room in Rooms) {
+        <a style="color: unset; text-decoration: unset;" href="/RoomStateViewer/@room.Replace('.', '~')">
+            <RoomListItem RoomId="@room"></RoomListItem>
+        </a>
     }
     <div style="margin-bottom: 4em;"></div>
 }
@@ -21,16 +20,16 @@ else
 
 @code {
     public List<string> Rooms { get; set; } = new();
-    protected override async Task OnInitializedAsync()
-    {
+
+    protected override async Task OnInitializedAsync() {
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
         await base.OnInitializedAsync();
-        if (RuntimeCache.CurrentHomeServer == null)
-        {
+        if (RuntimeCache.CurrentHomeServer == null) {
             NavigationManager.NavigateTo("/Login");
             return;
         }
-        Rooms = (await RuntimeCache.CurrentHomeServer.GetJoinedRooms()).Select(x=>x.RoomId).ToList();
+        Rooms = (await RuntimeCache.CurrentHomeServer.GetJoinedRooms()).Select(x => x.RoomId).ToList();
         Console.WriteLine("Fetched joined rooms!");
     }
-} 
\ No newline at end of file
+
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor
index c7f9f3c..bfd4d10 100644
--- a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor
@@ -1,7 +1,7 @@
 @page "/RoomStateViewer/{RoomId}"
+@using MatrixRoomUtils.Core.Extensions
 @using System.Net.Http.Headers
 @using System.Text.Json
-@using MatrixRoomUtils.Core.Extensions
 @inject ILocalStorageService LocalStorage
 @inject NavigationManager NavigationManager
 <h3>Room state viewer - Viewing @RoomId</h3>
@@ -19,8 +19,7 @@
     </tr>
     </thead>
     <tbody>
-    @foreach (var stateEvent in FilteredEvents.Where(x => x.state_key == "").OrderBy(x => x.origin_server_ts))
-    {
+    @foreach (var stateEvent in FilteredEvents.Where(x => x.state_key == "").OrderBy(x => x.origin_server_ts)) {
         <tr>
             <td>@stateEvent.type</td>
             <td style="max-width: fit-Content;">
@@ -31,8 +30,7 @@
     </tbody>
 </table>
 
-@foreach (var group in FilteredEvents.GroupBy(x => x.state_key).OrderBy(x => x.Key).Where(x => x.Key != ""))
-{
+@foreach (var group in FilteredEvents.GroupBy(x => x.state_key).OrderBy(x => x.Key).Where(x => x.Key != "")) {
     <details>
         <summary>@group.Key</summary>
         <table class="table table-striped table-hover" style="width: fit-Content;">
@@ -43,8 +41,7 @@
             </tr>
             </thead>
             <tbody>
-            @foreach (var stateEvent in group.OrderBy(x => x.origin_server_ts))
-            {
+            @foreach (var stateEvent in group.OrderBy(x => x.origin_server_ts)) {
                 <tr>
                     <td>@stateEvent.type</td>
                     <td style="max-width: fit-Content;">
@@ -72,12 +69,10 @@
     public List<PreRenderedStateEvent> Events { get; set; } = new();
     public string status = "";
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
         await base.OnInitializedAsync();
-        if (RuntimeCache.CurrentHomeServer == null)
-        {
+        if (RuntimeCache.CurrentHomeServer == null) {
             NavigationManager.NavigateTo("/Login");
             return;
         }
@@ -85,56 +80,50 @@
         await LoadStatesAsync();
         Console.WriteLine("Policy list editor initialized!");
     }
+
     private DateTime _lastUpdate = DateTime.Now;
 
-    private async Task LoadStatesAsync()
-    {
-        int StateLoaded = 0;
-        //TODO: can we improve this?
+    private async Task LoadStatesAsync() {
+        var StateLoaded = 0;
+    //TODO: can we improve this?
         using var client = new HttpClient();
         client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeCache.CurrentHomeServer.AccessToken);
-    var response = await client.GetAsync($"{RuntimeCache.CurrentHomeServer.FullHomeServerDomain}/_matrix/client/r0/rooms/{RoomId}/state");
-        // var response = await client.GetAsync($"http://localhost:5117/matrix-hq-state.json");
+        var response = await client.GetAsync($"{RuntimeCache.CurrentHomeServer.FullHomeServerDomain}/_matrix/client/r0/rooms/{RoomId}/state");
+    // var response = await client.GetAsync($"http://localhost:5117/matrix-hq-state.json");
     //var _events = await response.Content.ReadFromJsonAsync<Queue<StateEventStruct>>();
         var _data = await response.Content.ReadAsStreamAsync();
         var __events = JsonSerializer.DeserializeAsyncEnumerable<StateEventStruct>(_data);
-        await foreach (var _ev in __events)
-        {
-            var e = new PreRenderedStateEvent()
-            {
+        await foreach (var _ev in __events) {
+            var e = new PreRenderedStateEvent {
                 type = _ev.type,
                 state_key = _ev.state_key,
                 origin_server_ts = _ev.origin_server_ts,
-                content = _ev.content.ToJson(indent: true, ignoreNull: true),
+                content = _ev.content.ToJson(true, true)
             };
             Events.Add(e);
-            if (string.IsNullOrEmpty(e.state_key))
-            {
+            if (string.IsNullOrEmpty(e.state_key)) {
                 FilteredEvents.Add(e);
             }
             StateLoaded++;
-            if ((DateTime.Now - _lastUpdate).TotalMilliseconds > 100)
-            {
+            if ((DateTime.Now - _lastUpdate).TotalMilliseconds > 100) {
                 _lastUpdate = DateTime.Now;
                 status = $"Loaded {StateLoaded} state events";
                 StateHasChanged();
                 await Task.Delay(0);
             }
-            
         }
 
         StateHasChanged();
     }
 
-    private async Task RebuildFilteredData()
-    {
+    private async Task RebuildFilteredData() {
         status = "Rebuilding filtered data...";
         StateHasChanged();
         await Task.Delay(1);
         var _FilteredEvents = Events;
         if (!ShowMembershipEvents)
             _FilteredEvents = _FilteredEvents.Where(x => x.type != "m.room.member").ToList();
-        
+
         status = "Done, rerendering!";
         StateHasChanged();
         await Task.Delay(1);
@@ -142,9 +131,7 @@
         StateHasChanged();
     }
 
-
-    public struct PreRenderedStateEvent
-    {
+    public struct PreRenderedStateEvent {
         public string content { get; set; }
         public long origin_server_ts { get; set; }
         public string state_key { get; set; }
@@ -155,11 +142,9 @@
     // public string ReplacesState { get; set; }
     }
 
-    public bool ShowMembershipEvents
-    {
+    public bool ShowMembershipEvents {
         get => _showMembershipEvents;
-        set
-        {
+        set {
             _showMembershipEvents = value;
             RebuildFilteredData();
         }
diff --git a/MatrixRoomUtils.Web/Program.cs b/MatrixRoomUtils.Web/Program.cs
index 15c18f7..164f746 100644
--- a/MatrixRoomUtils.Web/Program.cs
+++ b/MatrixRoomUtils.Web/Program.cs
@@ -1,17 +1,16 @@
 using System.Text.Json;
 using System.Text.Json.Serialization;
 using Blazored.LocalStorage;
+using MatrixRoomUtils.Web;
 using Microsoft.AspNetCore.Components.Web;
 using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
-using MatrixRoomUtils.Web;
 
 var builder = WebAssemblyHostBuilder.CreateDefault(args);
 builder.RootComponents.Add<App>("#app");
 builder.RootComponents.Add<HeadOutlet>("head::after");
 
 builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
-builder.Services.AddBlazoredLocalStorage(config =>
-{
+builder.Services.AddBlazoredLocalStorage(config => {
     config.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
     config.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
     config.JsonSerializerOptions.IgnoreReadOnlyProperties = true;
diff --git a/MatrixRoomUtils.Web/Shared/EditablePre.razor b/MatrixRoomUtils.Web/Shared/EditablePre.razor
index 01bea0d..e759015 100644
--- a/MatrixRoomUtils.Web/Shared/EditablePre.razor
+++ b/MatrixRoomUtils.Web/Shared/EditablePre.razor
@@ -1,8 +1,9 @@
 @inherits InputBase<string>
 <pre id="@Id" class="@CssClass" @onkeyup="Callback" contenteditable="true">@CurrentValue</pre>
+
 @code {
-    protected override bool TryParseValueFromString(string? value, out string result, out string? validationErrorMessage)
-    {
+
+    protected override bool TryParseValueFromString(string? value, out string result, out string? validationErrorMessage) {
         result = value;
         validationErrorMessage = null;
         return true;
@@ -10,9 +11,6 @@
 
     public object Id { get; set; }
 
-    private async Task Callback()
-    {
-        Console.WriteLine("beep");
-    }
+    private async Task Callback() => Console.WriteLine("beep");
 
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor b/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor
index 03a7145..1fc70f2 100644
--- a/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor
+++ b/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor
@@ -1,10 +1,4 @@
-@using MatrixRoomUtils.Web.Classes
-@using System.Text.Json
-@using Blazored.LocalStorage
-@using MatrixRoomUtils.Core
 @using MatrixRoomUtils.Core.Extensions
-@using Index = MatrixRoomUtils.Web.Pages.Index
-@using System.ComponentModel.DataAnnotations
 @inject ILocalStorageService LocalStorage
 @inject NavigationManager NavigationManager
 
@@ -27,30 +21,33 @@
     private string? _avatarUrl { get; set; }
     private int _roomCount { get; set; } = 0;
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         var hs = await new AuthenticatedHomeServer(User.LoginResponse.UserId, User.AccessToken, User.LoginResponse.HomeServer).Configure();
         if (User.Profile.AvatarUrl != null && User.Profile.AvatarUrl != "")
             _avatarUrl = hs.ResolveMediaUri(User.Profile.AvatarUrl);
         else _avatarUrl = "https://api.dicebear.com/6.x/identicon/svg?seed=" + User.LoginResponse.UserId;
-        _roomCount = (await hs.GetJoinedRooms()).Count;
+        try {
+            _roomCount = (await hs.GetJoinedRooms()).Count;
+        }
+        catch {
+            _roomCount = -1;
+        }
         await base.OnInitializedAsync();
     }
 
-    private async Task RemoveUser()
-    {
+    private async Task RemoveUser() {
         Console.WriteLine(User.ToJson());
         RuntimeCache.LoginSessions.Remove(User.AccessToken);
 
         StateHasChanged();
     }
 
-    private async Task SetCurrent()
-    {
+    private async Task SetCurrent() {
         RuntimeCache.LastUsedToken = User.AccessToken;
     //RuntimeCache.CurrentHomeserver = await MatrixAuth.ResolveHomeserverFromWellKnown(LocalStorageWrapper.LoginSessions[Token].LoginResponse.HomeServer);
         await LocalStorageWrapper.SaveToLocalStorage(LocalStorage);
         await LocalStorageWrapper.InitialiseRuntimeVariables(LocalStorage);
         StateHasChanged();
     }
+
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/InlineUserItem.razor b/MatrixRoomUtils.Web/Shared/InlineUserItem.razor
index 56131c8..9833c62 100644
--- a/MatrixRoomUtils.Web/Shared/InlineUserItem.razor
+++ b/MatrixRoomUtils.Web/Shared/InlineUserItem.razor
@@ -4,8 +4,7 @@
     <span style="position: relative; top: -5px;">@ProfileName</span>
 
     <div style="display: inline-block;">
-        @if (ChildContent != null)
-        {
+        @if (ChildContent != null) {
             @ChildContent
         }
     </div>
@@ -25,15 +24,13 @@
 
     [Parameter]
     public string? ProfileAvatar { get; set; } = null;
-    
+
     [Parameter]
     public string? ProfileName { get; set; } = null;
 
-
     private static SemaphoreSlim _semaphoreSlim = new(128);
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         await base.OnInitializedAsync();
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
 
@@ -41,19 +38,14 @@
 
         var hs = await new AuthenticatedHomeServer(RuntimeCache.CurrentHomeServer.UserId, RuntimeCache.CurrentHomeServer.AccessToken, RuntimeCache.CurrentHomeServer.HomeServerDomain).Configure();
 
-        if (User == null)
-        {
-            if (UserId == null)
-            {
+        if (User == null) {
+            if (UserId == null) {
                 throw new ArgumentNullException(nameof(UserId));
             }
             User = await hs.GetProfile(UserId);
         }
-        else
-        {
-            // UserId = User.;
-        }
-        
+
+    // UserId = User.;
         ProfileAvatar ??= RuntimeCache.CurrentHomeServer.ResolveMediaUri(User.AvatarUrl);
         ProfileName ??= User.DisplayName;
 
diff --git a/MatrixRoomUtils.Web/Shared/LogView.razor b/MatrixRoomUtils.Web/Shared/LogView.razor
index 80fd355..2f83cb2 100644
--- a/MatrixRoomUtils.Web/Shared/LogView.razor
+++ b/MatrixRoomUtils.Web/Shared/LogView.razor
@@ -1,6 +1,5 @@
 @using System.Text
-@if (LocalStorageWrapper.Settings.DeveloperSettings.EnableLogViewers)
-{
+@if (LocalStorageWrapper.Settings.DeveloperSettings.EnableLogViewers) {
     <u>Logs</u>
     <br/>
     <pre>
@@ -10,11 +9,10 @@
 
 @code {
     StringBuilder _stringBuilder = new();
-    protected override async Task OnInitializedAsync()
-    {
+
+    protected override async Task OnInitializedAsync() {
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
-        if (!LocalStorageWrapper.Settings.DeveloperSettings.EnableConsoleLogging)
-        {
+        if (!LocalStorageWrapper.Settings.DeveloperSettings.EnableConsoleLogging) {
             Console.WriteLine("Console logging disabled!");
             var _sw = new StringWriter();
             Console.SetOut(_sw);
@@ -22,19 +20,16 @@
             return;
         }
         if (!LocalStorageWrapper.Settings.DeveloperSettings.EnableLogViewers) return;
-        //intecept stdout with textwriter to get logs
+    //intecept stdout with textwriter to get logs
         var sw = new StringWriter(_stringBuilder);
         Console.SetOut(sw);
         Console.SetError(sw);
-        //keep updated
-        int length = 0;
-        Task.Run(async () =>
-        {
-            while (true)
-            {
+    //keep updated
+        var length = 0;
+        Task.Run(async () => {
+            while (true) {
                 await Task.Delay(100);
-                if (_stringBuilder.Length != length)
-                {
+                if (_stringBuilder.Length != length) {
                     StateHasChanged();
                     length = _stringBuilder.Length;
                 }
@@ -43,4 +38,5 @@
         });
         await base.OnInitializedAsync();
     }
+
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/MainLayout.razor b/MatrixRoomUtils.Web/Shared/MainLayout.razor
index cdb1205..317f9e6 100644
--- a/MatrixRoomUtils.Web/Shared/MainLayout.razor
+++ b/MatrixRoomUtils.Web/Shared/MainLayout.razor
@@ -11,8 +11,7 @@
             <PortableDevTools></PortableDevTools>
             <a href="https://git.rory.gay/MatrixRoomUtils.git/" target="_blank">Git</a>
             <a href="https://matrix.to/#/%23mru%3Arory.gay?via=rory.gay&via=matrix.org&via=feline.support" target="_blank">Matrix</a>
-            @if (showDownload)
-            {
+            @if (showDownload) {
                 <a href="/MRU.tar.xz" target="_blank">Download</a>
             }
         </div>
@@ -24,24 +23,22 @@
 </div>
 
 @code {
-    private bool showDownload { get; set; } = false;
+    private bool showDownload { get; set; }
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         using var hc = new HttpClient();
-        var hr = await hc.SendAsync(new(HttpMethod.Head, NavigationManager.ToAbsoluteUri("/MRU-BIN.tar.xz").AbsoluteUri));
+        var hr = await hc.SendAsync(new HttpRequestMessage(HttpMethod.Head, NavigationManager.ToAbsoluteUri("/MRU-BIN.tar.xz").AbsoluteUri));
         showDownload = hr.StatusCode == HttpStatusCode.OK;
 
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
-        if (!LocalStorageWrapper.Settings.DeveloperSettings.EnableConsoleLogging)
-        {
+        if (!LocalStorageWrapper.Settings.DeveloperSettings.EnableConsoleLogging) {
             Console.WriteLine("Console logging disabled!");
             var sw = new StringWriter();
             Console.SetOut(sw);
             Console.SetError(sw);
         }
-        
-        await base.OnInitializedAsync();
 
+        await base.OnInitializedAsync();
     }
+
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/MainLayout.razor.css b/MatrixRoomUtils.Web/Shared/MainLayout.razor.css
index c865427..01a5066 100644
--- a/MatrixRoomUtils.Web/Shared/MainLayout.razor.css
+++ b/MatrixRoomUtils.Web/Shared/MainLayout.razor.css
@@ -21,20 +21,20 @@ main {
     align-items: center;
 }
 
-    .top-row ::deep a, .top-row ::deep .btn-link {
-        white-space: nowrap;
-        margin-left: 1.5rem;
-        text-decoration: none;
-    }
+.top-row ::deep a, .top-row ::deep .btn-link {
+    white-space: nowrap;
+    margin-left: 1.5rem;
+    text-decoration: none;
+}
 
-    .top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
-        text-decoration: underline;
-    }
+.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
+    text-decoration: underline;
+}
 
-    .top-row ::deep a:first-child {
-        overflow: hidden;
-        text-overflow: ellipsis;
-    }
+.top-row ::deep a:first-child {
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
 
 @media (max-width: 640.98px) {
     .top-row:not(.auth) {
diff --git a/MatrixRoomUtils.Web/Shared/NavMenu.razor b/MatrixRoomUtils.Web/Shared/NavMenu.razor
index 44dd9df..9ddbd84 100644
--- a/MatrixRoomUtils.Web/Shared/NavMenu.razor
+++ b/MatrixRoomUtils.Web/Shared/NavMenu.razor
@@ -61,6 +61,13 @@
         @*         <span class="oi oi-plus" aria-hidden="true"></span> Media locator *@
         @*     </NavLink> *@
         @* </div> *@
+
+        <div class="nav-item px-3">
+            <NavLink class="nav-link" href="HSAdmin">
+                <span class="oi oi-plus" aria-hidden="true"></span> HS Admin
+            </NavLink>
+        </div>
+
         <div class="nav-item px-3">
             <h5 style="margin-left: 1em;">MRU</h5>
             <hr style="margin-bottom: 0em;"/>
@@ -78,9 +85,6 @@
 
     private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
 
-    private void ToggleNavMenu()
-    {
-        collapseNavMenu = !collapseNavMenu;
-    }
+    private void ToggleNavMenu() => collapseNavMenu = !collapseNavMenu;
 
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/NavMenu.razor.css b/MatrixRoomUtils.Web/Shared/NavMenu.razor.css
index 604b7a1..447f2df 100644
--- a/MatrixRoomUtils.Web/Shared/NavMenu.razor.css
+++ b/MatrixRoomUtils.Web/Shared/NavMenu.razor.css
@@ -4,7 +4,7 @@
 
 .top-row {
     height: 3.5rem;
-    background-color: rgba(0,0,0,0.4);
+    background-color: rgba(0, 0, 0, 0.4);
 }
 
 .navbar-brand {
@@ -23,30 +23,30 @@
     padding-bottom: 0.5rem;
 }
 
-    .nav-item:first-of-type {
-        padding-top: 1rem;
-    }
+.nav-item:first-of-type {
+    padding-top: 1rem;
+}
 
-    .nav-item:last-of-type {
-        padding-bottom: 1rem;
-    }
+.nav-item:last-of-type {
+    padding-bottom: 1rem;
+}
 
-    .nav-item ::deep a {
-        color: #d7d7d7;
-        border-radius: 4px;
-        height: 3rem;
-        display: flex;
-        align-items: center;
-        line-height: 3rem;
-    }
+.nav-item ::deep a {
+    color: #d7d7d7;
+    border-radius: 4px;
+    height: 3rem;
+    display: flex;
+    align-items: center;
+    line-height: 3rem;
+}
 
 .nav-item ::deep a.active {
-    background-color: rgba(255,255,255,0.25);
+    background-color: rgba(255, 255, 255, 0.25);
     color: white;
 }
 
 .nav-item ::deep a:hover {
-    background-color: rgba(255,255,255,0.1);
+    background-color: rgba(255, 255, 255, 0.1);
     color: white;
 }
 
@@ -59,7 +59,7 @@
         /* Never collapse the sidebar for wide screens */
         display: block;
     }
-    
+
     .nav-scrollable {
         /* Allow sidebar to scroll for tall menus */
         height: calc(100vh - 3.5rem);
diff --git a/MatrixRoomUtils.Web/Shared/PortableDevTools.razor b/MatrixRoomUtils.Web/Shared/PortableDevTools.razor
index 84e7791..ffd7082 100644
--- a/MatrixRoomUtils.Web/Shared/PortableDevTools.razor
+++ b/MatrixRoomUtils.Web/Shared/PortableDevTools.razor
@@ -1,9 +1,7 @@
-
-@if (Enabled)
-{
+@if (Enabled) {
     <a href="/DevOptions">Portable devtools (enabled)</a>
     <div id="PortableDevTools" style="position: fixed; bottom: 0; right: 0; min-width: 200px; min-height: 100px; background: #0002;" draggable>
-        <p>Cache size: @RuntimeCache.GenericResponseCache.Sum(x=>x.Value.Cache.Count)</p>
+        <p>Cache size: @RuntimeCache.GenericResponseCache.Sum(x => x.Value.Cache.Count)</p>
     </div>
 }
 else {
@@ -13,19 +11,16 @@ else {
 @code {
     private bool Enabled { get; set; } = LocalStorageWrapper.Settings.DeveloperSettings.EnablePortableDevtools;
 
-    protected override async Task OnInitializedAsync()
-    {
-        // if(!RuntimeCache.WasLoaded)
-            // await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
-        // StateHasChanged();
-        Task.Run(async () =>
-        {
-            while (true)
-            {
+    protected override async Task OnInitializedAsync() =>
+    // if(!RuntimeCache.WasLoaded)
+    // await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
+    // StateHasChanged();
+        Task.Run(async () => {
+            while (true) {
                 await Task.Delay(100);
                 Enabled = LocalStorageWrapper.Settings.DeveloperSettings.EnablePortableDevtools;
                 StateHasChanged();
             }
         });
-    }
+
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/RoomListItem.razor b/MatrixRoomUtils.Web/Shared/RoomListItem.razor
index fb28c3c..f58ab3a 100644
--- a/MatrixRoomUtils.Web/Shared/RoomListItem.razor
+++ b/MatrixRoomUtils.Web/Shared/RoomListItem.razor
@@ -1,18 +1,15 @@
-@using MatrixRoomUtils.Core.Authentication
-@using System.Text.Json
 @using MatrixRoomUtils.Core.Extensions
+@using System.Text.Json
 <div class="roomListItem" style="background-color: #ffffff11; border-radius: 25px; margin: 8px; width: fit-Content; @(hasDangerousRoomVersion ? "border: red 4px solid;" : hasOldRoomVersion ? "border: #FF0 1px solid;" : "")">
-    @if (ShowOwnProfile)
-    {
-        <img class="imageUnloaded @(string.IsNullOrWhiteSpace(profileAvatar) ? "" : "imageLoaded")" style="@(ChildContent != null ? "vertical-align: baseline;":"") width: 32px; height: 32px; border-radius: 50%; @(hasCustomProfileAvatar ? "border-color: red; border-width: 3px; border-style: dashed;" : "")" src="@(profileAvatar ?? "/icon-192.png")" @onload="Callback"/>
+    @if (ShowOwnProfile) {
+        <img class="imageUnloaded @(string.IsNullOrWhiteSpace(profileAvatar) ? "" : "imageLoaded")" style="@(ChildContent != null ? "vertical-align: baseline;" : "") width: 32px; height: 32px; border-radius: 50%; @(hasCustomProfileAvatar ? "border-color: red; border-width: 3px; border-style: dashed;" : "")" src="@(profileAvatar ?? "/icon-192.png")" @onload="Callback"/>
         <span style="vertical-align: middle; margin-right: 8px; border-radius: 75px; @(hasCustomProfileName ? "background-color: red;" : "")">@(profileName ?? "Loading...")</span>
         <span style="vertical-align: middle; padding-right: 8px; padding-left: 0px;">-></span>
     }
-    <img style="@(ChildContent != null ? "vertical-align: baseline;":"") width: 32px; height:  32px; border-radius: 50%;" src="@roomIcon"/>
+    <img style="@(ChildContent != null ? "vertical-align: baseline;" : "") width: 32px; height:  32px; border-radius: 50%;" src="@roomIcon"/>
     <div style="display: inline-block;">
-        <span style="vertical-align: middle; padding-right: 8px;">@roomName</span>
-        @if (ChildContent != null)
-        {
+        <span style="vertical-align: middle; padding-right: 8px;">@RoomName</span>
+        @if (ChildContent != null) {
             @ChildContent
         }
     </div>
@@ -33,103 +30,86 @@
     [Parameter]
     public bool ShowOwnProfile { get; set; } = false;
 
-    private string roomName { get; set; } = "Loading...";
+    [Parameter]
+    public string? RoomName { get; set; }
+
     private string? roomIcon { get; set; } = "/icon-192.png";
 
     private string? profileAvatar { get; set; }
     private string? profileName { get; set; }
     private bool hasCustomProfileAvatar { get; set; } = false;
     private bool hasCustomProfileName { get; set; } = false;
-    
+
     private bool hasOldRoomVersion { get; set; } = false;
     private bool hasDangerousRoomVersion { get; set; } = false;
-    
-    
+
     private static SemaphoreSlim _semaphoreSlim = new(128);
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         await base.OnInitializedAsync();
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
-        
+
         await _semaphoreSlim.WaitAsync();
 
         var hs = RuntimeCache.CurrentHomeServer; //await new AuthenticatedHomeServer(RuntimeCache.CurrentHomeServer.UserId, RuntimeCache.CurrentHomeServer.AccessToken, RuntimeCache.CurrentHomeServer.HomeServerDomain).Configure();
-        
-        if (Room == null)
-        {
-            if (RoomId == null)
-            {
+
+        if (Room == null) {
+            if (RoomId == null) {
                 throw new ArgumentNullException(nameof(RoomId));
             }
             Room = await hs.GetRoom(RoomId);
         }
-        else
-        {
+        else {
             RoomId = Room.RoomId;
         }
 
-        roomName = await Room.GetNameAsync() ?? "Unnamed room: " + RoomId;
+        RoomName ??= await Room.GetNameAsync() ?? "Unnamed room: " + RoomId;
 
         var ce = await Room.GetCreateEventAsync();
-        if (ce != null)
-        {
-            if (int.TryParse(ce.RoomVersion, out int rv) && rv < 10)
-            {
+        if (ce != null) {
+            if (int.TryParse(ce.RoomVersion, out var rv) && rv < 10) {
                 hasOldRoomVersion = true;
             }
-            if (new[] { "1", "8" }.Contains(ce.RoomVersion))
-            {
+            if (new[] { "1", "8" }.Contains(ce.RoomVersion)) {
                 hasDangerousRoomVersion = true;
-                roomName = "Dangerous room: " + roomName;
+                RoomName = "Dangerous room: " + RoomName;
             }
         }
-        
 
         var state = await Room.GetStateAsync("m.room.avatar");
-        if (state != null)
-        {
-            try
-            {
+        if (state != null) {
+            try {
                 var url = state.Value.GetProperty("url").GetString();
-                if (url != null)
-                {
+                if (url != null) {
                     roomIcon = hs.ResolveMediaUri(url);
                     Console.WriteLine($"Got avatar for room {RoomId}: {roomIcon} ({url})");
                 }
             }
-            catch (InvalidOperationException e)
-            {
+            catch (InvalidOperationException e) {
                 Console.WriteLine($"Failed to get avatar for room {RoomId}: {e.Message}\n{state.Value.ToJson()}");
             }
         }
 
-        if (ShowOwnProfile)
-        {
-            var profile = await hs.GetProfile(hs.UserId, debounce: true);
+        if (ShowOwnProfile) {
+            var profile = await hs.GetProfile(hs.UserId, true);
 
             var memberState = await Room.GetStateAsync("m.room.member", hs.UserId);
-            if (memberState.HasValue)
-            {
+            if (memberState.HasValue) {
                 memberState.Value.TryGetProperty("avatar_url", out var _avatar);
-                if (_avatar.ValueKind == JsonValueKind.String)
-                {
+                if (_avatar.ValueKind == JsonValueKind.String) {
                     hasCustomProfileAvatar = _avatar.GetString() != profile.AvatarUrl;
                     profileAvatar = hs.ResolveMediaUri(_avatar.GetString());
                 }
-                else
-                {
+                else {
                     profileAvatar = "/icon-192.png";
                 }
                 memberState.Value.TryGetProperty("displayname", out var _name);
-                if (_name.ValueKind == JsonValueKind.String)
-                {
+                if (_name.ValueKind == JsonValueKind.String) {
                     hasCustomProfileName = _name.GetString() != profile.DisplayName;
                     profileName = _name.GetString();
     // Console.WriteLine($"{profile.DisplayName} - {_name.GetString()}: {hasCustomProfileName}");
                 }
-                else
-                {
+                else {
                     profileName = "Unnamed user";
                 }
             }
@@ -139,9 +119,6 @@
             await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage);
     }
 
-    private void Callback(ProgressEventArgs obj)
-    {
-        Console.WriteLine("prog: " + obj.ToJson(indent: false));
-    }
+    private void Callback(ProgressEventArgs obj) => Console.WriteLine("prog: " + obj.ToJson(false));
 
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/RoomListItem.razor.css b/MatrixRoomUtils.Web/Shared/RoomListItem.razor.css
index 8b9a9f6..da22d38 100644
--- a/MatrixRoomUtils.Web/Shared/RoomListItem.razor.css
+++ b/MatrixRoomUtils.Web/Shared/RoomListItem.razor.css
@@ -5,6 +5,6 @@
 /*}*/
 
 .imageLoaded {
-     opacity: 1;
-     scale: 1;
- }
\ No newline at end of file
+    opacity: 1;
+    scale: 1;
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/SimpleComponents/DictionaryEditor.razor b/MatrixRoomUtils.Web/Shared/SimpleComponents/DictionaryEditor.razor
index 4d90c57..42a5f64 100644
--- a/MatrixRoomUtils.Web/Shared/SimpleComponents/DictionaryEditor.razor
+++ b/MatrixRoomUtils.Web/Shared/SimpleComponents/DictionaryEditor.razor
@@ -1,9 +1,8 @@
 @using MatrixRoomUtils.Core.Extensions
 <table>
-    @foreach(var i in Items.Keys)
-    {
+    @foreach (var i in Items.Keys) {
         var key = i;
-        <input value="@Items[key]" @oninput="(obj) => inputChanged(obj, key)">
+        <input value="@Items[key]" @oninput="obj => inputChanged(obj, key)">
         <button @onclick="() => { Items.Remove(key); ItemsChanged.InvokeAsync(); }">Remove</button>
         <br/>
     }
@@ -11,28 +10,26 @@
 <button @onclick="() => { Items.Add(string.Empty, default); ItemsChanged.InvokeAsync(); }">Add</button>
 
 @code {
-    
+
     [Parameter]
     public Dictionary<string, object> Items { get; set; } = new();
 
-    [Parameter, EditorRequired]
+    [Parameter]
+    [EditorRequired]
     public EventCallback ItemsChanged { get; set; }
 
     [Parameter]
-    public Func<string,string>? KeyFormatter { get; set; }
-    
+    public Func<string, string>? KeyFormatter { get; set; }
+
     [Parameter]
     public Action? OnFocusLost { get; set; }
 
-
-    protected override Task OnInitializedAsync()
-    {
+    protected override Task OnInitializedAsync() {
         Console.WriteLine($"DictionaryEditor initialized with {Items.Count} items: {Items.ToJson()}");
         return base.OnInitializedAsync();
     }
 
-    private void inputChanged(ChangeEventArgs obj, string key)
-    {
+    private void inputChanged(ChangeEventArgs obj, string key) {
         Console.WriteLine($"StringListEditor inputChanged {key} {obj.Value}");
         Items[key] = obj.Value.ToString();
         ItemsChanged.InvokeAsync();
diff --git a/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor b/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor
index 702d41e..d17d0de 100644
--- a/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor
+++ b/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor
@@ -1,35 +1,29 @@
 @inject IJSRuntime JsRuntime
-@if (isVisible)
-{
+@if (isVisible) {
     <input autofocus type="@(IsPassword ? "password" : "text")" @bind="Value" @onfocusout="() => { isVisible = false; ValueChanged.InvokeAsync(Value); }" @ref="elementToFocus"/>
 }
-else
-{
-    <span tabindex="0" style="border-bottom: #ccc solid 1px; height: 1.4em; display: inline-block; @(string.IsNullOrEmpty(Value) ? "min-width: 50px;" : "")" @onfocusin="() => isVisible = true">@(Formatter?.Invoke(Value) ?? (IsPassword ? string.Join("", Value.Select(x=>'*')) : Value))</span>
+else {
+    <span tabindex="0" style="border-bottom: #ccc solid 1px; height: 1.4em; display: inline-block; @(string.IsNullOrEmpty(Value) ? "min-width: 50px;" : "")" @onfocusin="() => isVisible = true">@(Formatter?.Invoke(Value) ?? (IsPassword ? string.Join("", Value.Select(x => '*')) : Value))</span>
 }
 
 @code {
 
     [Parameter]
     public string Value { get; set; }
-    
+
     [Parameter]
     public bool IsPassword { get; set; } = false;
-    
+
     [Parameter]
     public EventCallback<string> ValueChanged { get; set; }
-    
+
     [Parameter]
     public Func<string?, string>? Formatter { get; set; }
-    
 
     private bool isVisible { get; set; } = false;
 
     private ElementReference elementToFocus;
 
-    protected override async Task OnAfterRenderAsync(bool firstRender)
-    {
-        await JsRuntime.InvokeVoidAsync("BlazorFocusElement", elementToFocus);
-    }
+    protected override async Task OnAfterRenderAsync(bool firstRender) => await JsRuntime.InvokeVoidAsync("BlazorFocusElement", elementToFocus);
 
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/SimpleComponents/StringListEditor.razor b/MatrixRoomUtils.Web/Shared/SimpleComponents/StringListEditor.razor
index fe3a938..2bd6ed5 100644
--- a/MatrixRoomUtils.Web/Shared/SimpleComponents/StringListEditor.razor
+++ b/MatrixRoomUtils.Web/Shared/SimpleComponents/StringListEditor.razor
@@ -1,5 +1,4 @@
-@for (int i = 0; i < Items.Count; i++)
-{
+@for (var i = 0; i < Items.Count; i++) {
     var self = i;
     <button @onclick="() => { Items.RemoveAt(self); ItemsChanged.InvokeAsync(); }">Remove</button>
     <FancyTextBox Value="@Items[self]" ValueChanged="@(obj => inputChanged(obj, self))"/>
@@ -10,19 +9,18 @@
 @code {
 
     [Parameter]
-    public List<string> Items { get; set; } = new List<string>();
+    public List<string> Items { get; set; } = new();
 
-    [Parameter, EditorRequired]
+    [Parameter]
+    [EditorRequired]
     public EventCallback ItemsChanged { get; set; }
 
-    protected override Task OnInitializedAsync()
-    {
+    protected override Task OnInitializedAsync() {
         Console.WriteLine($"StringListEditor initialized with {Items.Count} items: {string.Join(",", Items)}");
         return base.OnInitializedAsync();
     }
 
-    private void inputChanged(string obj, int i)
-    {
+    private void inputChanged(string obj, int i) {
         Console.WriteLine($"StringListEditor inputChanged {i} {obj}");
         Items[i] = obj;
         ItemsChanged.InvokeAsync();
diff --git a/MatrixRoomUtils.Web/Shared/SimpleComponents/ToggleSlider.razor b/MatrixRoomUtils.Web/Shared/SimpleComponents/ToggleSlider.razor
index 49a363d..1a38e26 100644
--- a/MatrixRoomUtils.Web/Shared/SimpleComponents/ToggleSlider.razor
+++ b/MatrixRoomUtils.Web/Shared/SimpleComponents/ToggleSlider.razor
@@ -59,12 +59,14 @@
 </style>
 
 @code {
+
     [Parameter]
     public RenderFragment? ChildContent { get; set; }
-    
+
     [Parameter]
     public bool Value { get; set; }
+
     [Parameter]
     public EventCallback<bool> ValueChanged { get; set; }
-    
+
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor
index 3803d38..4fb5596 100644
--- a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor
+++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor
@@ -1,33 +1,25 @@
 @using MatrixRoomUtils.Core.Extensions
-@if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "ban")
-{
+@if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "ban") {
     <i>@Event.StateKey was banned</i>
 }
-else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "invite")
-{
+else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "invite") {
     <i>@Event.StateKey was invited</i>
 }
-else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "join")
-{
-    @if (Event.ReplacesState != null)
-    {
+else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "join") {
+    @if (Event.ReplacesState != null) {
         <i>@Event.StateKey changed their display name to @(Event.ContentAsJsonNode["displayname"]!.GetValue<string>())</i>
     }
-    else
-    {
+    else {
         <i><InlineUserItem UserId="@Event.StateKey"></InlineUserItem> joined</i>
     }
 }
-else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "leave")
-{
+else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "leave") {
     <i>@Event.StateKey left</i>
 }
-else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "knock")
-{
+else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "knock") {
     <i>@Event.StateKey knocked</i>
 }
-else
-{
+else {
     <i>@Event.StateKey has an unknown state:</i>
     <pre>
         @Event.ToJson()
diff --git a/MatrixRoomUtils.Web/Shared/UserListItem.razor b/MatrixRoomUtils.Web/Shared/UserListItem.razor
index d357b0d..43c71ab 100644
--- a/MatrixRoomUtils.Web/Shared/UserListItem.razor
+++ b/MatrixRoomUtils.Web/Shared/UserListItem.razor
@@ -4,8 +4,7 @@
     <span style="vertical-align: middle; margin-right: 8px; border-radius: 75px;">@profileName</span>
 
     <div style="display: inline-block;">
-        @if (ChildContent != null)
-        {
+        @if (ChildContent != null) {
             @ChildContent
         }
     </div>
@@ -26,11 +25,9 @@
     private string? profileAvatar { get; set; } = "/icon-192.png";
     private string? profileName { get; set; } = "Loading...";
 
-
     private static SemaphoreSlim _semaphoreSlim = new(128);
 
-    protected override async Task OnInitializedAsync()
-    {
+    protected override async Task OnInitializedAsync() {
         await base.OnInitializedAsync();
         await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
 
@@ -38,19 +35,14 @@
 
         var hs = await new AuthenticatedHomeServer(RuntimeCache.CurrentHomeServer.UserId, RuntimeCache.CurrentHomeServer.AccessToken, RuntimeCache.CurrentHomeServer.HomeServerDomain).Configure();
 
-        if (User == null)
-        {
-            if (UserId == null)
-            {
+        if (User == null) {
+            if (UserId == null) {
                 throw new ArgumentNullException(nameof(UserId));
             }
             User = await hs.GetProfile(UserId);
         }
-        else
-        {
-            // UserId = User.;
-        }
-        
+
+    // UserId = User.;
         profileAvatar = RuntimeCache.CurrentHomeServer.ResolveMediaUri(User.AvatarUrl);
         profileName = User.DisplayName;
 
diff --git a/MatrixRoomUtils.Web/_Imports.razor b/MatrixRoomUtils.Web/_Imports.razor
index a558b8f..837780e 100644
--- a/MatrixRoomUtils.Web/_Imports.razor
+++ b/MatrixRoomUtils.Web/_Imports.razor
@@ -17,14 +17,12 @@
 
 @code
 {
-    
-    protected override async Task OnInitializedAsync()
-    {
-        if (!RuntimeCache.WasLoaded)
-        {
+
+    protected override async Task OnInitializedAsync() {
+        if (!RuntimeCache.WasLoaded) {
             await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
             Console.WriteLine("Loaded from local storage");
             StateHasChanged();
         }
     }
-}
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/wwwroot/css/app.css b/MatrixRoomUtils.Web/wwwroot/css/app.css
index c6d71d1..245566a 100644
--- a/MatrixRoomUtils.Web/wwwroot/css/app.css
+++ b/MatrixRoomUtils.Web/wwwroot/css/app.css
@@ -15,7 +15,7 @@ html, body {
     border-bottom: none;
 }
 
-.table, .table-striped>tbody>tr:nth-of-type(odd), .table-hover>tbody>tr:hover {
+.table, .table-striped > tbody > tr:nth-of-type(odd), .table-hover > tbody > tr:hover {
     color: unset;
 }
 
@@ -34,7 +34,7 @@ a, .btn-link {
 }
 
 .btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
-  box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
+    box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
 }
 
 .content {
@@ -65,12 +65,12 @@ a, .btn-link {
     z-index: 1000;
 }
 
-    #blazor-error-ui .dismiss {
-        cursor: pointer;
-        position: absolute;
-        right: 0.75rem;
-        top: 0.5rem;
-    }
+#blazor-error-ui .dismiss {
+    cursor: pointer;
+    position: absolute;
+    right: 0.75rem;
+    top: 0.5rem;
+}
 
 .blazor-error-boundary {
     background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
@@ -78,9 +78,9 @@ a, .btn-link {
     color: white;
 }
 
-    .blazor-error-boundary::after {
-        content: "An error has occurred."
-    }
+.blazor-error-boundary::after {
+    content: "An error has occurred."
+}
 
 .loading-progress {
     position: relative;
@@ -90,19 +90,19 @@ a, .btn-link {
     margin: 20vh auto 1rem auto;
 }
 
-    .loading-progress circle {
-        fill: none;
-        stroke: #e0e0e0;
-        stroke-width: 0.6rem;
-        transform-origin: 50% 50%;
-        transform: rotate(-90deg);
-    }
+.loading-progress circle {
+    fill: none;
+    stroke: #e0e0e0;
+    stroke-width: 0.6rem;
+    transform-origin: 50% 50%;
+    transform: rotate(-90deg);
+}
 
-        .loading-progress circle:last-child {
-            stroke: #1b6ec2;
-            stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
-            transition: stroke-dasharray 0.05s ease-in-out;
-        }
+.loading-progress circle:last-child {
+    stroke: #1b6ec2;
+    stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
+    transition: stroke-dasharray 0.05s ease-in-out;
+}
 
 .loading-progress-text {
     position: absolute;
@@ -111,6 +111,6 @@ a, .btn-link {
     inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
 }
 
-    .loading-progress-text:after {
-        content: var(--blazor-load-percentage-text, "Loading");
-    }
+.loading-progress-text:after {
+    content: var(--blazor-load-percentage-text, "Loading");
+}
diff --git a/MatrixRoomUtils.Web/wwwroot/css/open-iconic/README.md b/MatrixRoomUtils.Web/wwwroot/css/open-iconic/README.md
index e34bd86..3ee3279 100644
--- a/MatrixRoomUtils.Web/wwwroot/css/open-iconic/README.md
+++ b/MatrixRoomUtils.Web/wwwroot/css/open-iconic/README.md
@@ -3,8 +3,6 @@
 
 ### Open Iconic is the open source sibling of [Iconic](https://github.com/iconic/open-iconic). It is a hyper-legible collection of 223 icons with a tiny footprint&mdash;ready to use with Bootstrap and Foundation. [View the collection](https://github.com/iconic/open-iconic)
 
-
-
 ## What's in Open Iconic?
 
 * 223 icons designed to be legible down to 8 pixels
@@ -14,7 +12,6 @@
 * Webfont stylesheets (including versions for Bootstrap and Foundation) in CSS, LESS, SCSS and Stylus formats
 * PNG and WebP raster images in 8px, 16px, 24px, 32px, 48px and 64px.
 
-
 ## Getting Started
 
 #### For code samples and everything else you need to get started with Open Iconic, check out our [Icons](https://github.com/iconic/open-iconic) and [Reference](https://github.com/iconic/open-iconic) sections.
@@ -33,7 +30,8 @@ We like SVGs and we think they're the way to display icons on the web. Since Ope
 
 Open Iconic also comes in a SVG sprite which allows you to display all the icons in the set with a single request. It's like an icon font, without being a hack.
 
-Adding an icon from an SVG sprite is a little different than what you're used to, but it's still a piece of cake. *Tip: To make your icons easily style able, we suggest adding a general class to the* `<svg>` *tag and a unique class name for each different icon in the* `<use>` *tag.*
+Adding an icon from an SVG sprite is a little different than what you're used to, but it's still a piece of cake. *Tip: To make your icons easily style able, we suggest adding a general class to the* `<svg>` *tag and a unique class name for
+each different icon in the* `<use>` *tag.*
 
 ```
 <svg class="icon">
@@ -62,17 +60,14 @@ To learn more about SVG Sprites, read [Chris Coyier's guide](http://css-tricks.c
 
 #### Using Open Iconic's Icon Font...
 
-
 ##### …with Bootstrap
 
 You can find our Bootstrap stylesheets in `font/css/open-iconic-bootstrap.{css, less, scss, styl}`
 
-
 ```
 <link href="/open-iconic/font/css/open-iconic-bootstrap.css" rel="stylesheet">
 ```
 
-
 ```
 <span class="oi oi-icon-name" title="icon name" aria-hidden="true"></span>
 ```
@@ -85,7 +80,6 @@ You can find our Foundation stylesheets in `font/css/open-iconic-foundation.{css
 <link href="/open-iconic/font/css/open-iconic-foundation.css" rel="stylesheet">
 ```
 
-
 ```
 <span class="fi-icon-name" title="icon name" aria-hidden="true"></span>
 ```
@@ -102,7 +96,6 @@ You can find our default stylesheets in `font/css/open-iconic.{css, less, scss,
 <span class="oi" data-glyph="icon-name" title="icon name" aria-hidden="true"></span>
 ```
 
-
 ## License
 
 ### Icons
diff --git a/MatrixRoomUtils.Web/wwwroot/css/open-iconic/font/fonts/open-iconic.svg b/MatrixRoomUtils.Web/wwwroot/css/open-iconic/font/fonts/open-iconic.svg
index 32b2c4e..9d1833e 100644
--- a/MatrixRoomUtils.Web/wwwroot/css/open-iconic/font/fonts/open-iconic.svg
+++ b/MatrixRoomUtils.Web/wwwroot/css/open-iconic/font/fonts/open-iconic.svg
@@ -4,540 +4,541 @@
 2014-7-1: Created.
 -->
 <svg xmlns="http://www.w3.org/2000/svg">
-<metadata>
-Created by FontForge 20120731 at Tue Jul  1 20:39:22 2014
- By P.J. Onori
-Created by P.J. Onori with FontForge 2.0 (http://fontforge.sf.net)
-</metadata>
-<defs>
-<font id="open-iconic" horiz-adv-x="800" >
-  <font-face 
-    font-family="Icons"
-    font-weight="400"
-    font-stretch="normal"
-    units-per-em="800"
-    panose-1="2 0 5 3 0 0 0 0 0 0"
-    ascent="800"
-    descent="0"
-    bbox="-0.5 -101 802 800.126"
-    underline-thickness="50"
-    underline-position="-100"
-    unicode-range="U+E000-E0DE"
-  />
-    <missing-glyph />
-    <glyph glyph-name="" unicode="&#xe000;" 
-d="M300 700h500v-700h-500v100h400v500h-400v100zM400 500l200 -150l-200 -150v100h-400v100h400v100z" />
-    <glyph glyph-name="1" unicode="&#xe001;" 
-d="M300 700h500v-700h-500v100h400v500h-400v100zM200 500v-100h400v-100h-400v-100l-200 150z" />
-    <glyph glyph-name="2" unicode="&#xe002;" 
-d="M350 700c193 0 350 -157 350 -350v-50h100l-200 -200l-200 200h100v50c0 138 -112 250 -250 250s-250 -112 -250 -250c0 193 157 350 350 350z" />
-    <glyph glyph-name="3" unicode="&#xe003;" 
-d="M450 700c193 0 350 -157 350 -350c0 138 -112 250 -250 250s-250 -112 -250 -250v-50h100l-200 -200l-200 200h100v50c0 193 157 350 350 350z" />
-    <glyph glyph-name="4" unicode="&#xe004;" 
-d="M0 700h800v-100h-800v100zM100 500h600v-100h-600v100zM0 300h800v-100h-800v100zM100 100h600v-100h-600v100z" />
-    <glyph glyph-name="5" unicode="&#xe005;" 
-d="M0 700h800v-100h-800v100zM0 500h600v-100h-600v100zM0 300h800v-100h-800v100zM0 100h600v-100h-600v100z" />
-    <glyph glyph-name="6" unicode="&#xe006;" 
-d="M0 700h800v-100h-800v100zM200 500h600v-100h-600v100zM0 300h800v-100h-800v100zM200 100h600v-100h-600v100z" />
-    <glyph glyph-name="7" unicode="&#xe007;" 
-d="M400 700c75 0 146 -23 206 -59l-75 -225l-322 234c57 31 122 50 191 50zM125 588l191 -138l-310 -222c-4 24 -6 47 -6 72c0 114 49 215 125 288zM688 575c69 -72 112 -168 112 -275c0 -35 -8 -68 -16 -100h-218zM216 253l112 -347c-128 23 -232 109 -287 222zM372 100
-h372c-64 -109 -177 -185 -310 -197z" />
-    <glyph glyph-name="8" unicode="&#xe008;" horiz-adv-x="600" 
-d="M200 800h100v-500h200l-247 -300l-253 300h200v500z" />
-    <glyph glyph-name="9" unicode="&#xe009;" 
-d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM300 700v-300h-200l300 -300l300 300h-200v300h-200z" />
-    <glyph glyph-name="a" unicode="&#xe00a;" 
-d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700l-300 -300l300 -300v200h300v200h-300v200z" />
-    <glyph glyph-name="b" unicode="&#xe00b;" 
-d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700v-200h-300v-200h300v-200l300 300z" />
-    <glyph glyph-name="c" unicode="&#xe00c;" 
-d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700l-300 -300h200v-300h200v300h200z" />
-    <glyph glyph-name="d" unicode="&#xe00d;" 
-d="M300 600v-200h500v-100h-500v-200l-300 247z" />
-    <glyph glyph-name="e" unicode="&#xe00e;" 
-d="M500 600l300 -247l-300 -253v200h-500v100h500v200z" />
-    <glyph glyph-name="f" unicode="&#xe00f;" horiz-adv-x="600" 
-d="M200 800h200v-500h200l-297 -300l-303 300h200v500z" />
-    <glyph glyph-name="10" unicode="&#xe010;" 
-d="M300 700v-200h500v-200h-500v-200l-300 297z" />
-    <glyph glyph-name="11" unicode="&#xe011;" 
-d="M500 700l300 -297l-300 -303v200h-500v200h500v200z" />
-    <glyph glyph-name="12" unicode="&#xe012;" horiz-adv-x="600" 
-d="M297 800l303 -300h-200v-500h-200v500h-200z" />
-    <glyph glyph-name="13" unicode="&#xe013;" horiz-adv-x="600" 
-d="M247 800l253 -300h-200v-500h-100v500h-200z" />
-    <glyph glyph-name="14" unicode="&#xe014;" 
-d="M400 800h100v-800h-100v800zM200 700h100v-600h-100v600zM600 600h100v-400h-100v400zM0 500h100v-200h-100v200z" />
-    <glyph glyph-name="15" unicode="&#xe015;" 
-d="M116 600l72 -72c-54 -54 -88 -126 -88 -209s34 -159 88 -213l-72 -72c-72 72 -116 175 -116 285s44 209 116 281zM684 600c72 -72 116 -171 116 -281s-44 -213 -116 -285l-72 72c54 54 88 130 88 213s-34 155 -88 209zM259 460l69 -72c-18 -18 -28 -41 -28 -69
-s10 -54 28 -72l-69 -72c-36 36 -59 89 -59 144s23 105 59 141zM541 459c36 -36 59 -85 59 -140s-23 -108 -59 -144l-69 72c18 18 28 44 28 72s-10 51 -28 69z" />
-    <glyph glyph-name="16" unicode="&#xe016;" horiz-adv-x="400" 
-d="M200 800c110 0 200 -90 200 -200s-90 -200 -200 -200s-200 90 -200 200s90 200 200 200zM100 319c31 -11 65 -19 100 -19s68 8 100 19v-319l-100 100l-100 -100v319z" />
-    <glyph glyph-name="17" unicode="&#xe017;" 
-d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300c0 -66 21 -126 56 -175l419 419c-49 35 -109 56 -175 56zM644 575l-419 -419c49 -35 109 -56 175 -56c166 0 300 134 300 300
-c0 66 -21 126 -56 175z" />
-    <glyph glyph-name="18" unicode="&#xe018;" 
-d="M0 700h100v-600h700v-100h-800v700zM500 700h200v-500h-200v500zM200 500h200v-300h-200v300z" />
-    <glyph glyph-name="19" unicode="&#xe019;" 
-d="M397 800c13 1 23 -4 34 -13c2 -2 214 -254 241 -287h128v-100h-100v-366c0 -18 -16 -34 -34 -34h-532c-18 0 -34 16 -34 34v366h-100v100h128l234 281c9 11 22 18 35 19zM400 672l-144 -172h288zM250 300c-28 0 -50 -22 -50 -50v-100c0 -28 22 -50 50 -50s50 22 50 50
-v100c0 28 -22 50 -50 50zM550 300c-28 0 -50 -22 -50 -50v-100c0 -28 22 -50 50 -50s50 22 50 50v100c0 28 -22 50 -50 50z" />
-    <glyph glyph-name="1a" unicode="&#xe01a;" 
-d="M9 700h682c6 0 9 -4 9 -10v-190h100v-200h-100v-191c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v582c0 6 3 9 9 9zM100 600v-400h500v400h-500z" />
-    <glyph glyph-name="1b" unicode="&#xe01b;" 
-d="M9 700h682c6 0 9 -4 9 -10v-190h100v-200h-100v-191c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v582c0 6 3 9 9 9z" />
-    <glyph glyph-name="1c" unicode="&#xe01c;" 
-d="M92 650c0 23 19 50 45 50h3h5h5h500c28 0 50 -22 50 -50s-22 -50 -50 -50h-50v-141c9 -17 120 -231 166 -309c16 -26 34 -61 34 -106c0 -39 -15 -77 -41 -103h-3c-26 -25 -62 -41 -100 -41h-512c-39 0 -77 15 -103 41s-41 64 -41 103c0 46 18 80 34 106
-c46 78 157 292 166 309v141h-50c-2 0 -6 -1 -8 -1c-28 0 -50 23 -50 51zM500 600h-200v-162l-6 -10s-63 -123 -119 -228h450c-56 105 -119 228 -119 228l-6 10v162z" />
-    <glyph glyph-name="1d" unicode="&#xe01d;" 
-d="M400 800c110 0 200 -90 200 -200c0 -104 52 -198 134 -266c41 -34 66 -82 66 -134h-800c0 52 25 100 66 134c82 68 134 162 134 266c0 110 90 200 200 200zM300 100h200c0 -55 -45 -100 -100 -100s-100 45 -100 100z" />
-    <glyph glyph-name="1e" unicode="&#xe01e;" horiz-adv-x="600" 
-d="M150 800h50l350 -250l-225 -147l225 -153l-350 -250h-50v250l-75 -75l-75 75l150 150l-150 150l75 75l75 -75v250zM250 650v-200l150 100zM250 350v-200l150 100z" />
-    <glyph glyph-name="1f" unicode="&#xe01f;" 
-d="M0 800h500c110 0 200 -90 200 -200c0 -47 -17 -91 -44 -125c85 -40 144 -125 144 -225c0 -138 -112 -250 -250 -250h-550v100c55 0 100 45 100 100v400c0 55 -45 100 -100 100v100zM300 700v-200h100c55 0 100 45 100 100s-45 100 -100 100h-100zM300 400v-300h150
-c83 0 150 67 150 150s-67 150 -150 150h-150z" />
-    <glyph glyph-name="20" unicode="&#xe020;" horiz-adv-x="600" 
-d="M300 800v-300h200l-300 -500v300h-200z" />
-    <glyph glyph-name="21" unicode="&#xe021;" 
-d="M100 800h300v-300l100 100l100 -100v300h50c28 0 50 -22 50 -50v-550h-550c-28 0 -50 -22 -50 -50s22 -50 50 -50h550v-100h-550c-83 0 -150 67 -150 150v550l3 19c8 39 39 70 78 78z" />
-    <glyph glyph-name="22" unicode="&#xe022;" horiz-adv-x="400" 
-d="M0 800h400v-800l-200 200l-200 -200v800z" />
-    <glyph glyph-name="23" unicode="&#xe023;" 
-d="M0 800h800v-100h-800v100zM0 600h300v-103h203v103h297v-591c0 -6 -3 -9 -9 -9h-782c-6 0 -9 3 -9 9v591z" />
-    <glyph glyph-name="24" unicode="&#xe024;" 
-d="M300 800h200c55 0 100 -45 100 -100v-100h191c6 0 9 -3 9 -9v-241c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v241c0 6 3 9 9 9h191v100c0 55 45 100 100 100zM300 700v-100h200v100h-200zM0 209c16 -6 32 -9 50 -9h700c18 0 34 3 50 9v-200c0 -6 -3 -9 -9 -9h-782
-c-6 0 -9 3 -9 9v200z" />
-    <glyph glyph-name="25" unicode="&#xe025;" horiz-adv-x="600" 
-d="M300 800c58 0 110 -16 147 -53s53 -89 53 -147h-100c0 39 -11 61 -25 75s-36 25 -75 25c-35 0 -55 -10 -72 -31s-28 -55 -28 -94c0 -51 20 -107 28 -175h172v-100h-178c-14 -60 -49 -127 -113 -200h491v-100h-600v122l16 12c69 69 95 121 106 166h-122v100h125
-c-8 50 -25 106 -25 175c0 58 16 114 50 156c34 43 88 69 150 69z" />
-    <glyph glyph-name="26" unicode="&#xe026;" 
-d="M34 700h4h3h4h5h700c28 0 50 -22 50 -50v-700c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v700v2c0 20 15 42 34 48zM150 600c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50zM350 600c-28 0 -50 -22 -50 -50s22 -50 50 -50h300c28 0 50 22 50 50
-s-22 50 -50 50h-300zM100 400v-400h600v400h-600z" />
-    <glyph glyph-name="27" unicode="&#xe027;" 
-d="M744 797l6 -3l44 -44c4 -4 3 -8 0 -12l-266 -375l-15 -13l-25 -12c-23 72 -78 127 -150 150l12 25l13 15l375 266zM266 400c74 0 134 -60 134 -134c0 -147 -119 -266 -266 -266c-48 0 -95 12 -134 34c80 46 134 133 134 232c0 74 58 134 132 134z" />
-    <glyph glyph-name="28" unicode="&#xe028;" 
-d="M9 451c0 23 19 50 46 50c8 0 19 -3 26 -7l131 -66l29 22c-79 81 -1 250 118 250s197 -167 119 -250l28 -22l131 66c6 4 12 7 21 7c28 0 50 -22 50 -50c0 -17 -12 -37 -27 -45l-115 -56c9 -16 19 -33 25 -50h68c28 0 50 -22 50 -50s-22 -50 -50 -50h-50
+    <metadata>
+        Created by FontForge 20120731 at Tue Jul 1 20:39:22 2014
+        By P.J. Onori
+        Created by P.J. Onori with FontForge 2.0 (http://fontforge.sf.net)
+    </metadata>
+    <defs>
+        <font id="open-iconic" horiz-adv-x="800">
+            <font-face
+                    font-family="Icons"
+                    font-weight="400"
+                    font-stretch="normal"
+                    units-per-em="800"
+                    panose-1="2 0 5 3 0 0 0 0 0 0"
+                    ascent="800"
+                    descent="0"
+                    bbox="-0.5 -101 802 800.126"
+                    underline-thickness="50"
+                    underline-position="-100"
+                    unicode-range="U+E000-E0DE"
+            />
+            <missing-glyph/>
+            <glyph glyph-name="" unicode="&#xe000;"
+                   d="M300 700h500v-700h-500v100h400v500h-400v100zM400 500l200 -150l-200 -150v100h-400v100h400v100z"/>
+            <glyph glyph-name="1" unicode="&#xe001;"
+                   d="M300 700h500v-700h-500v100h400v500h-400v100zM200 500v-100h400v-100h-400v-100l-200 150z"/>
+            <glyph glyph-name="2" unicode="&#xe002;"
+                   d="M350 700c193 0 350 -157 350 -350v-50h100l-200 -200l-200 200h100v50c0 138 -112 250 -250 250s-250 -112 -250 -250c0 193 157 350 350 350z"/>
+            <glyph glyph-name="3" unicode="&#xe003;"
+                   d="M450 700c193 0 350 -157 350 -350c0 138 -112 250 -250 250s-250 -112 -250 -250v-50h100l-200 -200l-200 200h100v50c0 193 157 350 350 350z"/>
+            <glyph glyph-name="4" unicode="&#xe004;"
+                   d="M0 700h800v-100h-800v100zM100 500h600v-100h-600v100zM0 300h800v-100h-800v100zM100 100h600v-100h-600v100z"/>
+            <glyph glyph-name="5" unicode="&#xe005;"
+                   d="M0 700h800v-100h-800v100zM0 500h600v-100h-600v100zM0 300h800v-100h-800v100zM0 100h600v-100h-600v100z"/>
+            <glyph glyph-name="6" unicode="&#xe006;"
+                   d="M0 700h800v-100h-800v100zM200 500h600v-100h-600v100zM0 300h800v-100h-800v100zM200 100h600v-100h-600v100z"/>
+            <glyph glyph-name="7" unicode="&#xe007;"
+                   d="M400 700c75 0 146 -23 206 -59l-75 -225l-322 234c57 31 122 50 191 50zM125 588l191 -138l-310 -222c-4 24 -6 47 -6 72c0 114 49 215 125 288zM688 575c69 -72 112 -168 112 -275c0 -35 -8 -68 -16 -100h-218zM216 253l112 -347c-128 23 -232 109 -287 222zM372 100
+h372c-64 -109 -177 -185 -310 -197z"/>
+            <glyph glyph-name="8" unicode="&#xe008;" horiz-adv-x="600"
+                   d="M200 800h100v-500h200l-247 -300l-253 300h200v500z"/>
+            <glyph glyph-name="9" unicode="&#xe009;"
+                   d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM300 700v-300h-200l300 -300l300 300h-200v300h-200z"/>
+            <glyph glyph-name="a" unicode="&#xe00a;"
+                   d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700l-300 -300l300 -300v200h300v200h-300v200z"/>
+            <glyph glyph-name="b" unicode="&#xe00b;"
+                   d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700v-200h-300v-200h300v-200l300 300z"/>
+            <glyph glyph-name="c" unicode="&#xe00c;"
+                   d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700l-300 -300h200v-300h200v300h200z"/>
+            <glyph glyph-name="d" unicode="&#xe00d;"
+                   d="M300 600v-200h500v-100h-500v-200l-300 247z"/>
+            <glyph glyph-name="e" unicode="&#xe00e;"
+                   d="M500 600l300 -247l-300 -253v200h-500v100h500v200z"/>
+            <glyph glyph-name="f" unicode="&#xe00f;" horiz-adv-x="600"
+                   d="M200 800h200v-500h200l-297 -300l-303 300h200v500z"/>
+            <glyph glyph-name="10" unicode="&#xe010;"
+                   d="M300 700v-200h500v-200h-500v-200l-300 297z"/>
+            <glyph glyph-name="11" unicode="&#xe011;"
+                   d="M500 700l300 -297l-300 -303v200h-500v200h500v200z"/>
+            <glyph glyph-name="12" unicode="&#xe012;" horiz-adv-x="600"
+                   d="M297 800l303 -300h-200v-500h-200v500h-200z"/>
+            <glyph glyph-name="13" unicode="&#xe013;" horiz-adv-x="600"
+                   d="M247 800l253 -300h-200v-500h-100v500h-200z"/>
+            <glyph glyph-name="14" unicode="&#xe014;"
+                   d="M400 800h100v-800h-100v800zM200 700h100v-600h-100v600zM600 600h100v-400h-100v400zM0 500h100v-200h-100v200z"/>
+            <glyph glyph-name="15" unicode="&#xe015;"
+                   d="M116 600l72 -72c-54 -54 -88 -126 -88 -209s34 -159 88 -213l-72 -72c-72 72 -116 175 -116 285s44 209 116 281zM684 600c72 -72 116 -171 116 -281s-44 -213 -116 -285l-72 72c54 54 88 130 88 213s-34 155 -88 209zM259 460l69 -72c-18 -18 -28 -41 -28 -69
+s10 -54 28 -72l-69 -72c-36 36 -59 89 -59 144s23 105 59 141zM541 459c36 -36 59 -85 59 -140s-23 -108 -59 -144l-69 72c18 18 28 44 28 72s-10 51 -28 69z"/>
+            <glyph glyph-name="16" unicode="&#xe016;" horiz-adv-x="400"
+                   d="M200 800c110 0 200 -90 200 -200s-90 -200 -200 -200s-200 90 -200 200s90 200 200 200zM100 319c31 -11 65 -19 100 -19s68 8 100 19v-319l-100 100l-100 -100v319z"/>
+            <glyph glyph-name="17" unicode="&#xe017;"
+                   d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300c0 -66 21 -126 56 -175l419 419c-49 35 -109 56 -175 56zM644 575l-419 -419c49 -35 109 -56 175 -56c166 0 300 134 300 300
+c0 66 -21 126 -56 175z"/>
+            <glyph glyph-name="18" unicode="&#xe018;"
+                   d="M0 700h100v-600h700v-100h-800v700zM500 700h200v-500h-200v500zM200 500h200v-300h-200v300z"/>
+            <glyph glyph-name="19" unicode="&#xe019;"
+                   d="M397 800c13 1 23 -4 34 -13c2 -2 214 -254 241 -287h128v-100h-100v-366c0 -18 -16 -34 -34 -34h-532c-18 0 -34 16 -34 34v366h-100v100h128l234 281c9 11 22 18 35 19zM400 672l-144 -172h288zM250 300c-28 0 -50 -22 -50 -50v-100c0 -28 22 -50 50 -50s50 22 50 50
+v100c0 28 -22 50 -50 50zM550 300c-28 0 -50 -22 -50 -50v-100c0 -28 22 -50 50 -50s50 22 50 50v100c0 28 -22 50 -50 50z"/>
+            <glyph glyph-name="1a" unicode="&#xe01a;"
+                   d="M9 700h682c6 0 9 -4 9 -10v-190h100v-200h-100v-191c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v582c0 6 3 9 9 9zM100 600v-400h500v400h-500z"/>
+            <glyph glyph-name="1b" unicode="&#xe01b;"
+                   d="M9 700h682c6 0 9 -4 9 -10v-190h100v-200h-100v-191c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v582c0 6 3 9 9 9z"/>
+            <glyph glyph-name="1c" unicode="&#xe01c;"
+                   d="M92 650c0 23 19 50 45 50h3h5h5h500c28 0 50 -22 50 -50s-22 -50 -50 -50h-50v-141c9 -17 120 -231 166 -309c16 -26 34 -61 34 -106c0 -39 -15 -77 -41 -103h-3c-26 -25 -62 -41 -100 -41h-512c-39 0 -77 15 -103 41s-41 64 -41 103c0 46 18 80 34 106
+c46 78 157 292 166 309v141h-50c-2 0 -6 -1 -8 -1c-28 0 -50 23 -50 51zM500 600h-200v-162l-6 -10s-63 -123 -119 -228h450c-56 105 -119 228 -119 228l-6 10v162z"/>
+            <glyph glyph-name="1d" unicode="&#xe01d;"
+                   d="M400 800c110 0 200 -90 200 -200c0 -104 52 -198 134 -266c41 -34 66 -82 66 -134h-800c0 52 25 100 66 134c82 68 134 162 134 266c0 110 90 200 200 200zM300 100h200c0 -55 -45 -100 -100 -100s-100 45 -100 100z"/>
+            <glyph glyph-name="1e" unicode="&#xe01e;" horiz-adv-x="600"
+                   d="M150 800h50l350 -250l-225 -147l225 -153l-350 -250h-50v250l-75 -75l-75 75l150 150l-150 150l75 75l75 -75v250zM250 650v-200l150 100zM250 350v-200l150 100z"/>
+            <glyph glyph-name="1f" unicode="&#xe01f;"
+                   d="M0 800h500c110 0 200 -90 200 -200c0 -47 -17 -91 -44 -125c85 -40 144 -125 144 -225c0 -138 -112 -250 -250 -250h-550v100c55 0 100 45 100 100v400c0 55 -45 100 -100 100v100zM300 700v-200h100c55 0 100 45 100 100s-45 100 -100 100h-100zM300 400v-300h150
+c83 0 150 67 150 150s-67 150 -150 150h-150z"/>
+            <glyph glyph-name="20" unicode="&#xe020;" horiz-adv-x="600"
+                   d="M300 800v-300h200l-300 -500v300h-200z"/>
+            <glyph glyph-name="21" unicode="&#xe021;"
+                   d="M100 800h300v-300l100 100l100 -100v300h50c28 0 50 -22 50 -50v-550h-550c-28 0 -50 -22 -50 -50s22 -50 50 -50h550v-100h-550c-83 0 -150 67 -150 150v550l3 19c8 39 39 70 78 78z"/>
+            <glyph glyph-name="22" unicode="&#xe022;" horiz-adv-x="400"
+                   d="M0 800h400v-800l-200 200l-200 -200v800z"/>
+            <glyph glyph-name="23" unicode="&#xe023;"
+                   d="M0 800h800v-100h-800v100zM0 600h300v-103h203v103h297v-591c0 -6 -3 -9 -9 -9h-782c-6 0 -9 3 -9 9v591z"/>
+            <glyph glyph-name="24" unicode="&#xe024;"
+                   d="M300 800h200c55 0 100 -45 100 -100v-100h191c6 0 9 -3 9 -9v-241c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v241c0 6 3 9 9 9h191v100c0 55 45 100 100 100zM300 700v-100h200v100h-200zM0 209c16 -6 32 -9 50 -9h700c18 0 34 3 50 9v-200c0 -6 -3 -9 -9 -9h-782
+c-6 0 -9 3 -9 9v200z"/>
+            <glyph glyph-name="25" unicode="&#xe025;" horiz-adv-x="600"
+                   d="M300 800c58 0 110 -16 147 -53s53 -89 53 -147h-100c0 39 -11 61 -25 75s-36 25 -75 25c-35 0 -55 -10 -72 -31s-28 -55 -28 -94c0 -51 20 -107 28 -175h172v-100h-178c-14 -60 -49 -127 -113 -200h491v-100h-600v122l16 12c69 69 95 121 106 166h-122v100h125
+c-8 50 -25 106 -25 175c0 58 16 114 50 156c34 43 88 69 150 69z"/>
+            <glyph glyph-name="26" unicode="&#xe026;"
+                   d="M34 700h4h3h4h5h700c28 0 50 -22 50 -50v-700c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v700v2c0 20 15 42 34 48zM150 600c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50zM350 600c-28 0 -50 -22 -50 -50s22 -50 50 -50h300c28 0 50 22 50 50
+s-22 50 -50 50h-300zM100 400v-400h600v400h-600z"/>
+            <glyph glyph-name="27" unicode="&#xe027;"
+                   d="M744 797l6 -3l44 -44c4 -4 3 -8 0 -12l-266 -375l-15 -13l-25 -12c-23 72 -78 127 -150 150l12 25l13 15l375 266zM266 400c74 0 134 -60 134 -134c0 -147 -119 -266 -266 -266c-48 0 -95 12 -134 34c80 46 134 133 134 232c0 74 58 134 132 134z"/>
+            <glyph glyph-name="28" unicode="&#xe028;"
+                   d="M9 451c0 23 19 50 46 50c8 0 19 -3 26 -7l131 -66l29 22c-79 81 -1 250 118 250s197 -167 119 -250l28 -22l131 66c6 4 12 7 21 7c28 0 50 -22 50 -50c0 -17 -12 -37 -27 -45l-115 -56c9 -16 19 -33 25 -50h68c28 0 50 -22 50 -50s-22 -50 -50 -50h-50
 c0 -23 -2 -45 -6 -66l78 -40c21 -5 37 -28 37 -49c0 -28 -22 -50 -50 -50c-10 0 -23 5 -31 11l-65 35c-24 -46 -62 -86 -103 -110c-35 19 -60 45 -60 72v135v4v5v6v5v5v87c0 28 -22 50 -50 50c-24 0 -45 -17 -50 -40c1 -3 1 -8 1 -11s0 -8 -1 -11v-82v-4v-5v-144
-c0 -28 -24 -53 -59 -72c-41 25 -79 64 -103 110l-66 -35c-8 -6 -21 -11 -31 -11c-28 0 -50 22 -50 50c0 21 16 44 37 49l78 40c-4 21 -6 43 -6 66h-50h-5c-28 0 -50 22 -50 50c0 26 22 50 50 50h5h69c6 17 16 34 25 50l-116 56c-16 7 -28 27 -28 45z" />
-    <glyph glyph-name="29" unicode="&#xe029;" 
-d="M600 700h91c6 0 9 -3 9 -9v-582c0 -6 -3 -9 -9 -9h-91v600zM210 503l290 147v-500l-250 125v-3c-15 0 -25 -8 -28 -22l75 -178c11 -25 0 -58 -25 -69s-58 0 -69 25l-103 272h-91c-6 0 -9 3 -9 9v182c0 6 3 9 9 9h182z" />
-    <glyph glyph-name="2a" unicode="&#xe02a;" 
-d="M9 800h682c6 0 9 -3 9 -9v-782c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v782c0 6 3 9 9 9zM100 700v-200h500v200h-500zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400v-300h100v300h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100z" />
-    <glyph glyph-name="2b" unicode="&#xe02b;" 
-d="M0 800h700v-200h-700v200zM0 500h700v-491c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v491zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100z" />
-    <glyph glyph-name="2c" unicode="&#xe02c;" 
-d="M409 800h182c6 0 10 -4 12 -9l94 -182c2 -5 6 -9 12 -9h82c6 0 9 -3 9 -9v-582c0 -6 -3 -9 -9 -9h-782c-6 0 -9 3 -9 9v441c0 83 67 150 150 150h141c6 0 10 4 12 9l94 182c2 5 6 9 12 9zM150 500c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z
-M500 500c-110 0 -200 -90 -200 -200s90 -200 200 -200s200 90 200 200s-90 200 -200 200zM500 400c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100s45 100 100 100z" />
-    <glyph glyph-name="2d" unicode="&#xe02d;" 
-d="M0 600h800l-400 -400z" />
-    <glyph glyph-name="2e" unicode="&#xe02e;" horiz-adv-x="400" 
-d="M400 800v-800l-400 400z" />
-    <glyph glyph-name="2f" unicode="&#xe02f;" horiz-adv-x="400" 
-d="M0 800l400 -400l-400 -400v800z" />
-    <glyph glyph-name="30" unicode="&#xe030;" 
-d="M400 600l400 -400h-800z" />
-    <glyph glyph-name="31" unicode="&#xe031;" 
-d="M0 550c0 23 20 50 46 50h3h5h4h200c17 0 37 -13 44 -28l38 -72h444c14 0 19 -12 15 -25l-81 -250c-4 -13 -21 -25 -35 -25h-350c-14 0 -30 12 -34 25c-27 83 -54 167 -81 250l-10 25h-150c-2 0 -5 -1 -7 -1c-28 0 -51 23 -51 51zM358 100c28 0 50 -22 50 -50
-s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM658 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z" />
-    <glyph glyph-name="32" unicode="&#xe032;" 
-d="M0 700h500v-100h-300v-300h-100l-100 -100v500zM300 500h500v-500l-100 100h-400v400z" />
-    <glyph glyph-name="33" unicode="&#xe033;" 
-d="M641 700l143 -141l-493 -493c-71 76 -146 148 -219 222l-72 71l141 141c50 -51 101 -101 153 -150c116 117 234 231 347 350z" />
-    <glyph glyph-name="34" unicode="&#xe034;" 
-d="M150 600l250 -250l250 250l150 -150l-400 -400l-400 400z" />
-    <glyph glyph-name="35" unicode="&#xe035;" horiz-adv-x="600" 
-d="M400 800l150 -150l-250 -250l250 -250l-150 -150l-400 400z" />
-    <glyph glyph-name="36" unicode="&#xe036;" horiz-adv-x="600" 
-d="M150 800l400 -400l-400 -400l-150 150l250 250l-250 250z" />
-    <glyph glyph-name="37" unicode="&#xe037;" 
-d="M400 600l400 -400l-150 -150l-250 250l-250 -250l-150 150z" />
-    <glyph glyph-name="38" unicode="&#xe038;" 
-d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM600 622l-250 -250l-100 100l-72 -72l172 -172l322 322z" />
-    <glyph glyph-name="39" unicode="&#xe039;" 
-d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM250 622l-72 -72l150 -150l-150 -150l72 -72l150 150l150 -150l72 72l-150 150l150 150l-72 72l-150 -150z" />
-    <glyph glyph-name="3a" unicode="&#xe03a;" 
-d="M350 800c28 0 50 -22 50 -50v-50h75c14 0 25 -11 25 -25v-75h-300v75c0 14 11 25 25 25h75v50c0 28 22 50 50 50zM25 700h75v-200h500v200h75c14 0 25 -11 25 -25v-650c0 -14 -11 -25 -25 -25h-650c-14 0 -25 11 -25 25v650c0 14 11 25 25 25z" />
-    <glyph glyph-name="3b" unicode="&#xe03b;" 
-d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM350 600h100v-181c23 -24 47 -47 72 -69l-72 -72c-27 30 -55 59 -84 88l-16 12
-v222z" />
-    <glyph glyph-name="3c" unicode="&#xe03c;" 
-d="M450 800c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -18 -3 -34 -9 -50h-191v50c0 83 -67 150 -150 150s-150 -67 -150 -150v-50h-272c-17 30 -28 63 -28 100c0 110 90 200 200 200c23 114 129 200 250 200zM434 400h3h4c3 0 6 1 9 1c28 0 50 -22 50 -50v-1
-v-150h150l-200 -200l-200 200h150v150v2c0 20 15 42 34 48z" />
-    <glyph glyph-name="3d" unicode="&#xe03d;" 
-d="M450 800c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -18 -3 -34 -9 -50h-141l-200 200l-200 -200h-222c-17 30 -28 63 -28 100c0 110 90 200 200 200c23 114 129 200 250 200zM450 350l250 -250h-200v-50c0 -28 -22 -50 -50 -50s-50 22 -50 50v50h-200z" />
-    <glyph glyph-name="3e" unicode="&#xe03e;" 
-d="M450 700c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -83 -67 -150 -150 -150h-450c-110 0 -200 90 -200 200s90 200 200 200c23 114 129 200 250 200z" />
-    <glyph glyph-name="3f" unicode="&#xe03f;" 
-d="M250 800c82 0 154 -40 200 -100c-143 0 -270 -85 -325 -209c-36 -10 -70 -25 -100 -47c-16 33 -25 67 -25 106c0 138 112 250 250 250zM450 600c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -83 -67 -150 -150 -150h-450c-110 0 -200 90 -200 200
-s90 200 200 200c23 114 129 200 250 200z" />
-    <glyph glyph-name="40" unicode="&#xe040;" 
-d="M500 700h100l-300 -600h-100zM100 600h100l-100 -200l100 -200h-100l-100 200zM600 600h100l100 -200l-100 -200h-100l100 200z" />
-    <glyph glyph-name="41" unicode="&#xe041;" 
-d="M350 800h100l50 -119l28 -12l119 50l72 -72l-50 -119l12 -28l119 -50v-100l-119 -50l-12 -28l50 -119l-72 -72l-119 50l-28 -12l-50 -119h-100l-50 119l-28 12l-119 -50l-72 72l50 119l-12 28l-119 50v100l119 50l12 28l-50 119l72 72l119 -50l28 12zM400 550
-c-83 0 -150 -67 -150 -150s67 -150 150 -150s150 67 150 150s-67 150 -150 150z" />
-    <glyph glyph-name="42" unicode="&#xe042;" 
-d="M0 800h800v-200h-800v200zM200 500h400l-200 -200zM0 100h800v-100h-800v100z" />
-    <glyph glyph-name="43" unicode="&#xe043;" 
-d="M0 800h100v-800h-100v800zM600 800h200v-800h-200v800zM500 600v-400l-200 200z" />
-    <glyph glyph-name="44" unicode="&#xe044;" 
-d="M0 800h200v-800h-200v800zM700 800h100v-800h-100v800zM300 600l200 -200l-200 -200v400z" />
-    <glyph glyph-name="45" unicode="&#xe045;" 
-d="M0 800h800v-100h-800v100zM400 500l200 -200h-400zM0 200h800v-200h-800v200z" />
-    <glyph glyph-name="46" unicode="&#xe046;" 
-d="M150 700c83 0 150 -67 150 -150v-50h100v50c0 83 67 150 150 150s150 -67 150 -150s-67 -150 -150 -150h-50v-100h50c83 0 150 -67 150 -150s-67 -150 -150 -150s-150 67 -150 150v50h-100v-50c0 -83 -67 -150 -150 -150s-150 67 -150 150s67 150 150 150h50v100h-50
+c0 -28 -24 -53 -59 -72c-41 25 -79 64 -103 110l-66 -35c-8 -6 -21 -11 -31 -11c-28 0 -50 22 -50 50c0 21 16 44 37 49l78 40c-4 21 -6 43 -6 66h-50h-5c-28 0 -50 22 -50 50c0 26 22 50 50 50h5h69c6 17 16 34 25 50l-116 56c-16 7 -28 27 -28 45z"/>
+            <glyph glyph-name="29" unicode="&#xe029;"
+                   d="M600 700h91c6 0 9 -3 9 -9v-582c0 -6 -3 -9 -9 -9h-91v600zM210 503l290 147v-500l-250 125v-3c-15 0 -25 -8 -28 -22l75 -178c11 -25 0 -58 -25 -69s-58 0 -69 25l-103 272h-91c-6 0 -9 3 -9 9v182c0 6 3 9 9 9h182z"/>
+            <glyph glyph-name="2a" unicode="&#xe02a;"
+                   d="M9 800h682c6 0 9 -3 9 -9v-782c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v782c0 6 3 9 9 9zM100 700v-200h500v200h-500zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400v-300h100v300h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100z"/>
+            <glyph glyph-name="2b" unicode="&#xe02b;"
+                   d="M0 800h700v-200h-700v200zM0 500h700v-491c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v491zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100z"/>
+            <glyph glyph-name="2c" unicode="&#xe02c;"
+                   d="M409 800h182c6 0 10 -4 12 -9l94 -182c2 -5 6 -9 12 -9h82c6 0 9 -3 9 -9v-582c0 -6 -3 -9 -9 -9h-782c-6 0 -9 3 -9 9v441c0 83 67 150 150 150h141c6 0 10 4 12 9l94 182c2 5 6 9 12 9zM150 500c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z
+M500 500c-110 0 -200 -90 -200 -200s90 -200 200 -200s200 90 200 200s-90 200 -200 200zM500 400c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100s45 100 100 100z"/>
+            <glyph glyph-name="2d" unicode="&#xe02d;"
+                   d="M0 600h800l-400 -400z"/>
+            <glyph glyph-name="2e" unicode="&#xe02e;" horiz-adv-x="400"
+                   d="M400 800v-800l-400 400z"/>
+            <glyph glyph-name="2f" unicode="&#xe02f;" horiz-adv-x="400"
+                   d="M0 800l400 -400l-400 -400v800z"/>
+            <glyph glyph-name="30" unicode="&#xe030;"
+                   d="M400 600l400 -400h-800z"/>
+            <glyph glyph-name="31" unicode="&#xe031;"
+                   d="M0 550c0 23 20 50 46 50h3h5h4h200c17 0 37 -13 44 -28l38 -72h444c14 0 19 -12 15 -25l-81 -250c-4 -13 -21 -25 -35 -25h-350c-14 0 -30 12 -34 25c-27 83 -54 167 -81 250l-10 25h-150c-2 0 -5 -1 -7 -1c-28 0 -51 23 -51 51zM358 100c28 0 50 -22 50 -50
+s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM658 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z"/>
+            <glyph glyph-name="32" unicode="&#xe032;"
+                   d="M0 700h500v-100h-300v-300h-100l-100 -100v500zM300 500h500v-500l-100 100h-400v400z"/>
+            <glyph glyph-name="33" unicode="&#xe033;"
+                   d="M641 700l143 -141l-493 -493c-71 76 -146 148 -219 222l-72 71l141 141c50 -51 101 -101 153 -150c116 117 234 231 347 350z"/>
+            <glyph glyph-name="34" unicode="&#xe034;"
+                   d="M150 600l250 -250l250 250l150 -150l-400 -400l-400 400z"/>
+            <glyph glyph-name="35" unicode="&#xe035;" horiz-adv-x="600"
+                   d="M400 800l150 -150l-250 -250l250 -250l-150 -150l-400 400z"/>
+            <glyph glyph-name="36" unicode="&#xe036;" horiz-adv-x="600"
+                   d="M150 800l400 -400l-400 -400l-150 150l250 250l-250 250z"/>
+            <glyph glyph-name="37" unicode="&#xe037;"
+                   d="M400 600l400 -400l-150 -150l-250 250l-250 -250l-150 150z"/>
+            <glyph glyph-name="38" unicode="&#xe038;"
+                   d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM600 622l-250 -250l-100 100l-72 -72l172 -172l322 322z"/>
+            <glyph glyph-name="39" unicode="&#xe039;"
+                   d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM250 622l-72 -72l150 -150l-150 -150l72 -72l150 150l150 -150l72 72l-150 150l150 150l-72 72l-150 -150z"/>
+            <glyph glyph-name="3a" unicode="&#xe03a;"
+                   d="M350 800c28 0 50 -22 50 -50v-50h75c14 0 25 -11 25 -25v-75h-300v75c0 14 11 25 25 25h75v50c0 28 22 50 50 50zM25 700h75v-200h500v200h75c14 0 25 -11 25 -25v-650c0 -14 -11 -25 -25 -25h-650c-14 0 -25 11 -25 25v650c0 14 11 25 25 25z"/>
+            <glyph glyph-name="3b" unicode="&#xe03b;"
+                   d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM350 600h100v-181c23 -24 47 -47 72 -69l-72 -72c-27 30 -55 59 -84 88l-16 12
+v222z"/>
+            <glyph glyph-name="3c" unicode="&#xe03c;"
+                   d="M450 800c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -18 -3 -34 -9 -50h-191v50c0 83 -67 150 -150 150s-150 -67 -150 -150v-50h-272c-17 30 -28 63 -28 100c0 110 90 200 200 200c23 114 129 200 250 200zM434 400h3h4c3 0 6 1 9 1c28 0 50 -22 50 -50v-1
+v-150h150l-200 -200l-200 200h150v150v2c0 20 15 42 34 48z"/>
+            <glyph glyph-name="3d" unicode="&#xe03d;"
+                   d="M450 800c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -18 -3 -34 -9 -50h-141l-200 200l-200 -200h-222c-17 30 -28 63 -28 100c0 110 90 200 200 200c23 114 129 200 250 200zM450 350l250 -250h-200v-50c0 -28 -22 -50 -50 -50s-50 22 -50 50v50h-200z"/>
+            <glyph glyph-name="3e" unicode="&#xe03e;"
+                   d="M450 700c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -83 -67 -150 -150 -150h-450c-110 0 -200 90 -200 200s90 200 200 200c23 114 129 200 250 200z"/>
+            <glyph glyph-name="3f" unicode="&#xe03f;"
+                   d="M250 800c82 0 154 -40 200 -100c-143 0 -270 -85 -325 -209c-36 -10 -70 -25 -100 -47c-16 33 -25 67 -25 106c0 138 112 250 250 250zM450 600c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -83 -67 -150 -150 -150h-450c-110 0 -200 90 -200 200
+s90 200 200 200c23 114 129 200 250 200z"/>
+            <glyph glyph-name="40" unicode="&#xe040;"
+                   d="M500 700h100l-300 -600h-100zM100 600h100l-100 -200l100 -200h-100l-100 200zM600 600h100l100 -200l-100 -200h-100l100 200z"/>
+            <glyph glyph-name="41" unicode="&#xe041;"
+                   d="M350 800h100l50 -119l28 -12l119 50l72 -72l-50 -119l12 -28l119 -50v-100l-119 -50l-12 -28l50 -119l-72 -72l-119 50l-28 -12l-50 -119h-100l-50 119l-28 12l-119 -50l-72 72l50 119l-12 28l-119 50v100l119 50l12 28l-50 119l72 72l119 -50l28 12zM400 550
+c-83 0 -150 -67 -150 -150s67 -150 150 -150s150 67 150 150s-67 150 -150 150z"/>
+            <glyph glyph-name="42" unicode="&#xe042;"
+                   d="M0 800h800v-200h-800v200zM200 500h400l-200 -200zM0 100h800v-100h-800v100z"/>
+            <glyph glyph-name="43" unicode="&#xe043;"
+                   d="M0 800h100v-800h-100v800zM600 800h200v-800h-200v800zM500 600v-400l-200 200z"/>
+            <glyph glyph-name="44" unicode="&#xe044;"
+                   d="M0 800h200v-800h-200v800zM700 800h100v-800h-100v800zM300 600l200 -200l-200 -200v400z"/>
+            <glyph glyph-name="45" unicode="&#xe045;"
+                   d="M0 800h800v-100h-800v100zM400 500l200 -200h-400zM0 200h800v-200h-800v200z"/>
+            <glyph glyph-name="46" unicode="&#xe046;"
+                   d="M150 700c83 0 150 -67 150 -150v-50h100v50c0 83 67 150 150 150s150 -67 150 -150s-67 -150 -150 -150h-50v-100h50c83 0 150 -67 150 -150s-67 -150 -150 -150s-150 67 -150 150v50h-100v-50c0 -83 -67 -150 -150 -150s-150 67 -150 150s67 150 150 150h50v100h-50
 c-83 0 -150 67 -150 150s67 150 150 150zM150 600c-28 0 -50 -22 -50 -50s22 -50 50 -50h50v50c0 28 -22 50 -50 50zM550 600c-28 0 -50 -22 -50 -50v-50h50c28 0 50 22 50 50s-22 50 -50 50zM300 400v-100h100v100h-100zM150 200c-28 0 -50 -22 -50 -50s22 -50 50 -50
-s50 22 50 50v50h-50zM500 200v-50c0 -28 22 -50 50 -50s50 22 50 50s-22 50 -50 50h-50z" />
-    <glyph glyph-name="47" unicode="&#xe047;" 
-d="M0 791c0 5 4 9 9 9h782c6 0 9 -4 9 -10v-790l-200 200h-591c-6 0 -9 3 -9 9v582z" />
-    <glyph glyph-name="48" unicode="&#xe048;" 
-d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM600 600l-100 -300l-300 -100l100 300zM400 450c-28 0 -50 -22 -50 -50
-s22 -50 50 -50s50 22 50 50s-22 50 -50 50z" />
-    <glyph glyph-name="49" unicode="&#xe049;" 
-d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700v-600c166 0 300 134 300 300s-134 300 -300 300z" />
-    <glyph glyph-name="4a" unicode="&#xe04a;" 
-d="M0 800h800v-100h-800v100zM0 600h500v-100h-500v100zM0 300h800v-100h-800v100zM0 100h600v-100h-600v100zM750 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z" />
-    <glyph glyph-name="4b" unicode="&#xe04b;" 
-d="M25 700h750c14 0 25 -11 25 -25v-75h-800v75c0 14 11 25 25 25zM0 500h800v-375c0 -14 -11 -25 -25 -25h-750c-14 0 -25 11 -25 25v375zM100 300v-100h100v100h-100zM300 300v-100h100v100h-100z" />
-    <glyph glyph-name="4c" unicode="&#xe04c;" 
-d="M100 800h100v-100h450l100 100l50 -50l-100 -100v-450h100v-100h-100v-100h-100v100h-500v500h-100v100h100v100zM200 600v-350l350 350h-350zM600 550l-350 -350h350v350z" />
-    <glyph glyph-name="4d" unicode="&#xe04d;" 
-d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM400 600c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z
-M200 452c0 20 15 42 34 48h3h3h8c12 0 28 -7 36 -16l91 -90l25 6c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100l6 25l-90 91c-9 8 -16 24 -16 36zM550 500c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z" />
-    <glyph glyph-name="4e" unicode="&#xe04e;" 
-d="M300 800h200v-300h200l-300 -300l-300 300h200v300zM0 100h800v-100h-800v100z" />
-    <glyph glyph-name="4f" unicode="&#xe04f;" 
-d="M0 800h800v-100h-800v100zM400 600l300 -300h-200v-300h-200v300h-200z" />
-    <glyph glyph-name="50" unicode="&#xe050;" 
-d="M200 700h600v-600h-600l-200 300zM350 622l-72 -72l150 -150l-150 -150l72 -72l150 150l150 -150l72 72l-150 150l150 150l-72 72l-150 -150z" />
-    <glyph glyph-name="51" unicode="&#xe051;" 
-d="M400 700c220 0 400 -180 400 -400h-100c0 166 -134 300 -300 300s-300 -134 -300 -300h-100c0 220 180 400 400 400zM341 491l59 -88l59 88c81 -25 141 -101 141 -191c0 -110 -90 -200 -200 -200s-200 90 -200 200c0 90 60 166 141 191z" />
-    <glyph glyph-name="52" unicode="&#xe052;" 
-d="M0 800h300v-400h400v-400h-700v800zM400 800l300 -300h-300v300zM100 600v-100h100v100h-100zM100 400v-100h100v100h-100zM100 200v-100h400v100h-400z" />
-    <glyph glyph-name="53" unicode="&#xe053;" horiz-adv-x="600" 
-d="M200 700h100v-100h75c30 0 58 -6 81 -22s44 -44 44 -78v-100h-100v94c-4 3 -13 6 -25 6h-250c-14 0 -25 -11 -25 -25v-50c0 -15 20 -40 34 -44l257 -65c66 -16 109 -73 109 -141v-50c0 -68 -57 -125 -125 -125h-75v-100h-100v100h-75c-30 0 -58 6 -81 22s-44 44 -44 78
-v100h100v-94c4 -3 13 -6 25 -6h250c14 0 25 11 25 25v50c0 15 -20 40 -34 44l-257 65c-66 16 -109 73 -109 141v50c0 68 57 125 125 125h75v100z" />
-    <glyph glyph-name="54" unicode="&#xe054;" 
-d="M0 700h300v-300l-300 -300v600zM500 700h300v-300l-300 -300v600z" />
-    <glyph glyph-name="55" unicode="&#xe055;" 
-d="M300 700v-600h-300v300zM800 700v-600h-300v300z" />
-    <glyph glyph-name="56" unicode="&#xe056;" 
-d="M300 700v-100c-111 0 -200 -89 -200 -200h200v-300h-300v300c0 165 135 300 300 300zM800 700v-100c-111 0 -200 -89 -200 -200h200v-300h-300v300c0 165 135 300 300 300z" />
-    <glyph glyph-name="57" unicode="&#xe057;" 
-d="M0 700h300v-300c0 -165 -135 -300 -300 -300v100c111 0 200 89 200 200h-200v300zM500 700h300v-300c0 -165 -135 -300 -300 -300v100c111 0 200 89 200 200h-200v300z" />
-    <glyph glyph-name="58" unicode="&#xe058;" horiz-adv-x="600" 
-d="M300 800l34 -34c11 -11 266 -270 266 -488c0 -165 -135 -300 -300 -300s-300 135 -300 300c0 218 255 477 266 488zM150 328c-28 0 -50 -22 -50 -50c0 -110 90 -200 200 -200c28 0 50 22 50 50s-22 50 -50 50c-55 0 -100 45 -100 100c0 28 -22 50 -50 50z" />
-    <glyph glyph-name="59" unicode="&#xe059;" 
-d="M400 800l400 -500h-800zM0 200h800v-200h-800v200z" />
-    <glyph glyph-name="5a" unicode="&#xe05a;" horiz-adv-x="600" 
-d="M300 800l300 -300h-600zM0 300h600l-300 -300z" />
-    <glyph glyph-name="5b" unicode="&#xe05b;" 
-d="M0 500h200v-200h-200v200zM300 500h200v-200h-200v200zM600 500h200v-200h-200v200z" />
-    <glyph glyph-name="5c" unicode="&#xe05c;" 
-d="M0 700h800v-100l-400 -200l-400 200v100zM0 500l400 -200l400 200v-400h-800v400z" />
-    <glyph glyph-name="5d" unicode="&#xe05d;" 
-d="M400 800l400 -200v-600h-800v600zM400 688l-300 -150v-188l300 -150l300 150v188zM200 500h400v-100l-200 -100l-200 100v100z" />
-    <glyph glyph-name="5e" unicode="&#xe05e;" 
-d="M600 700c69 0 134 -19 191 -50l-16 -106c-49 35 -109 56 -175 56c-131 0 -240 -84 -281 -200h331l-16 -100h-334c0 -36 8 -68 19 -100h297l-16 -100h-222c55 -61 133 -100 222 -100c78 0 147 30 200 78v-122c-59 -35 -127 -56 -200 -56c-147 0 -274 82 -344 200h-256
-l19 100h197c-8 32 -16 66 -16 100h-200l25 100h191c45 172 198 300 384 300z" />
-    <glyph glyph-name="5f" unicode="&#xe05f;" 
-d="M0 700h700v-100h-700v100zM0 500h500v-100h-500v100zM0 300h800v-100h-800v100zM0 100h100v-100h-100v100zM200 100h100v-100h-100v100zM400 100h100v-100h-100v100z" />
-    <glyph glyph-name="60" unicode="&#xe060;" 
-d="M0 800h800v-100h-800v100zM200 600h400l-200 -200zM0 200h800v-200h-800v200z" />
-    <glyph glyph-name="61" unicode="&#xe061;" 
-d="M0 800h100v-800h-100v800zM600 800h200v-800h-200v800zM200 600l200 -200l-200 -200v400z" />
-    <glyph glyph-name="62" unicode="&#xe062;" 
-d="M0 800h200v-800h-200v800zM700 800h100v-800h-100v800zM600 600v-400l-200 200z" />
-    <glyph glyph-name="63" unicode="&#xe063;" 
-d="M0 800h800v-200h-800v200zM400 400l200 -200h-400zM0 100h800v-100h-800v100z" />
-    <glyph glyph-name="64" unicode="&#xe064;" 
-d="M0 800h200v-100h-100v-600h600v100h100v-200h-800v800zM400 800h400v-400l-150 150l-250 -250l-100 100l250 250z" />
-    <glyph glyph-name="65" unicode="&#xe065;" 
-d="M403 700c247 0 397 -300 397 -300s-150 -300 -397 -300c-253 0 -403 300 -403 300s150 300 403 300zM400 600c-110 0 -200 -90 -200 -200s90 -200 200 -200s200 90 200 200s-90 200 -200 200zM400 500c10 0 19 -3 28 -6c-16 -8 -28 -24 -28 -44c0 -28 22 -50 50 -50
-c20 0 36 12 44 28c3 -9 6 -18 6 -28c0 -55 -45 -100 -100 -100s-100 45 -100 100s45 100 100 100z" />
-    <glyph glyph-name="66" unicode="&#xe066;" horiz-adv-x="900" 
-d="M331 700h3h3c3 1 7 1 10 1c12 0 29 -8 37 -17l94 -93l66 65c57 57 155 57 212 0c58 -58 58 -154 0 -212l-65 -66l93 -94c10 -8 18 -25 18 -38c0 -28 -22 -50 -50 -50c-13 0 -32 9 -40 20l-62 65l-381 -381h-269v272l375 381l-63 63c-9 8 -16 24 -16 36c0 20 16 42 35 48z
-M447 481l-313 -315l128 -132l316 316z" />
-    <glyph glyph-name="67" unicode="&#xe067;" 
-d="M0 800h300v-400h400v-400h-700v800zM400 800l300 -300h-300v300z" />
-    <glyph glyph-name="68" unicode="&#xe068;" 
-d="M200 800c0 0 200 -100 200 -300s-298 -302 -200 -500c0 0 -200 100 -200 300s300 300 200 500zM500 500c0 0 200 -100 200 -300c0 -150 -60 -200 -100 -200h-300c0 200 300 300 200 500z" />
-    <glyph glyph-name="69" unicode="&#xe069;" 
-d="M0 800h100v-800h-100v800zM200 800h300v-100h300l-200 -203l200 -197h-400v100h-200v400z" />
-    <glyph glyph-name="6a" unicode="&#xe06a;" horiz-adv-x="400" 
-d="M150 800h150l-100 -200h200l-150 -300h150l-300 -300l-100 300h134l66 200h-200z" />
-    <glyph glyph-name="6b" unicode="&#xe06b;" 
-d="M0 800h300v-100h500v-100h-800v200zM0 500h800v-450c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v450z" />
-    <glyph glyph-name="6c" unicode="&#xe06c;" 
-d="M150 800c83 0 150 -67 150 -150c0 -66 -41 -121 -100 -141v-118c15 5 33 9 50 9h200c28 0 50 22 50 50v59c-59 20 -100 75 -100 141c0 83 67 150 150 150s150 -67 150 -150c0 -66 -41 -121 -100 -141v-59c0 -82 -68 -150 -150 -150h-200c-14 0 -25 -7 -34 -16
-c50 -24 84 -74 84 -134c0 -83 -67 -150 -150 -150s-150 67 -150 150c0 66 41 121 100 141v218c-59 20 -100 75 -100 141c0 83 67 150 150 150z" />
-    <glyph glyph-name="6d" unicode="&#xe06d;" 
-d="M0 800h400l-150 -150l150 -150l-100 -100l-150 150l-150 -150v400zM500 400l150 -150l150 150v-400h-400l150 150l-150 150z" />
-    <glyph glyph-name="6e" unicode="&#xe06e;" 
-d="M100 800l150 -150l150 150v-400h-400l150 150l-150 150zM400 400h400l-150 -150l150 -150l-100 -100l-150 150l-150 -150v400z" />
-    <glyph glyph-name="6f" unicode="&#xe06f;" 
-d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700c-56 0 -108 -17 -153 -44l22 -19c33 -18 13 -48 -13 -59c-30 -13 -77 10 -65 -41c13 -55 -27 -3 -47 -15c-42 -26 49 -152 31 -156l-59 34c-8 0 -13 -5 -16 -10
+s50 22 50 50v50h-50zM500 200v-50c0 -28 22 -50 50 -50s50 22 50 50s-22 50 -50 50h-50z"/>
+            <glyph glyph-name="47" unicode="&#xe047;"
+                   d="M0 791c0 5 4 9 9 9h782c6 0 9 -4 9 -10v-790l-200 200h-591c-6 0 -9 3 -9 9v582z"/>
+            <glyph glyph-name="48" unicode="&#xe048;"
+                   d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM600 600l-100 -300l-300 -100l100 300zM400 450c-28 0 -50 -22 -50 -50
+s22 -50 50 -50s50 22 50 50s-22 50 -50 50z"/>
+            <glyph glyph-name="49" unicode="&#xe049;"
+                   d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700v-600c166 0 300 134 300 300s-134 300 -300 300z"/>
+            <glyph glyph-name="4a" unicode="&#xe04a;"
+                   d="M0 800h800v-100h-800v100zM0 600h500v-100h-500v100zM0 300h800v-100h-800v100zM0 100h600v-100h-600v100zM750 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z"/>
+            <glyph glyph-name="4b" unicode="&#xe04b;"
+                   d="M25 700h750c14 0 25 -11 25 -25v-75h-800v75c0 14 11 25 25 25zM0 500h800v-375c0 -14 -11 -25 -25 -25h-750c-14 0 -25 11 -25 25v375zM100 300v-100h100v100h-100zM300 300v-100h100v100h-100z"/>
+            <glyph glyph-name="4c" unicode="&#xe04c;"
+                   d="M100 800h100v-100h450l100 100l50 -50l-100 -100v-450h100v-100h-100v-100h-100v100h-500v500h-100v100h100v100zM200 600v-350l350 350h-350zM600 550l-350 -350h350v350z"/>
+            <glyph glyph-name="4d" unicode="&#xe04d;"
+                   d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM400 600c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z
+M200 452c0 20 15 42 34 48h3h3h8c12 0 28 -7 36 -16l91 -90l25 6c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100l6 25l-90 91c-9 8 -16 24 -16 36zM550 500c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z"/>
+            <glyph glyph-name="4e" unicode="&#xe04e;"
+                   d="M300 800h200v-300h200l-300 -300l-300 300h200v300zM0 100h800v-100h-800v100z"/>
+            <glyph glyph-name="4f" unicode="&#xe04f;"
+                   d="M0 800h800v-100h-800v100zM400 600l300 -300h-200v-300h-200v300h-200z"/>
+            <glyph glyph-name="50" unicode="&#xe050;"
+                   d="M200 700h600v-600h-600l-200 300zM350 622l-72 -72l150 -150l-150 -150l72 -72l150 150l150 -150l72 72l-150 150l150 150l-72 72l-150 -150z"/>
+            <glyph glyph-name="51" unicode="&#xe051;"
+                   d="M400 700c220 0 400 -180 400 -400h-100c0 166 -134 300 -300 300s-300 -134 -300 -300h-100c0 220 180 400 400 400zM341 491l59 -88l59 88c81 -25 141 -101 141 -191c0 -110 -90 -200 -200 -200s-200 90 -200 200c0 90 60 166 141 191z"/>
+            <glyph glyph-name="52" unicode="&#xe052;"
+                   d="M0 800h300v-400h400v-400h-700v800zM400 800l300 -300h-300v300zM100 600v-100h100v100h-100zM100 400v-100h100v100h-100zM100 200v-100h400v100h-400z"/>
+            <glyph glyph-name="53" unicode="&#xe053;" horiz-adv-x="600"
+                   d="M200 700h100v-100h75c30 0 58 -6 81 -22s44 -44 44 -78v-100h-100v94c-4 3 -13 6 -25 6h-250c-14 0 -25 -11 -25 -25v-50c0 -15 20 -40 34 -44l257 -65c66 -16 109 -73 109 -141v-50c0 -68 -57 -125 -125 -125h-75v-100h-100v100h-75c-30 0 -58 6 -81 22s-44 44 -44 78
+v100h100v-94c4 -3 13 -6 25 -6h250c14 0 25 11 25 25v50c0 15 -20 40 -34 44l-257 65c-66 16 -109 73 -109 141v50c0 68 57 125 125 125h75v100z"/>
+            <glyph glyph-name="54" unicode="&#xe054;"
+                   d="M0 700h300v-300l-300 -300v600zM500 700h300v-300l-300 -300v600z"/>
+            <glyph glyph-name="55" unicode="&#xe055;"
+                   d="M300 700v-600h-300v300zM800 700v-600h-300v300z"/>
+            <glyph glyph-name="56" unicode="&#xe056;"
+                   d="M300 700v-100c-111 0 -200 -89 -200 -200h200v-300h-300v300c0 165 135 300 300 300zM800 700v-100c-111 0 -200 -89 -200 -200h200v-300h-300v300c0 165 135 300 300 300z"/>
+            <glyph glyph-name="57" unicode="&#xe057;"
+                   d="M0 700h300v-300c0 -165 -135 -300 -300 -300v100c111 0 200 89 200 200h-200v300zM500 700h300v-300c0 -165 -135 -300 -300 -300v100c111 0 200 89 200 200h-200v300z"/>
+            <glyph glyph-name="58" unicode="&#xe058;" horiz-adv-x="600"
+                   d="M300 800l34 -34c11 -11 266 -270 266 -488c0 -165 -135 -300 -300 -300s-300 135 -300 300c0 218 255 477 266 488zM150 328c-28 0 -50 -22 -50 -50c0 -110 90 -200 200 -200c28 0 50 22 50 50s-22 50 -50 50c-55 0 -100 45 -100 100c0 28 -22 50 -50 50z"/>
+            <glyph glyph-name="59" unicode="&#xe059;"
+                   d="M400 800l400 -500h-800zM0 200h800v-200h-800v200z"/>
+            <glyph glyph-name="5a" unicode="&#xe05a;" horiz-adv-x="600"
+                   d="M300 800l300 -300h-600zM0 300h600l-300 -300z"/>
+            <glyph glyph-name="5b" unicode="&#xe05b;"
+                   d="M0 500h200v-200h-200v200zM300 500h200v-200h-200v200zM600 500h200v-200h-200v200z"/>
+            <glyph glyph-name="5c" unicode="&#xe05c;"
+                   d="M0 700h800v-100l-400 -200l-400 200v100zM0 500l400 -200l400 200v-400h-800v400z"/>
+            <glyph glyph-name="5d" unicode="&#xe05d;"
+                   d="M400 800l400 -200v-600h-800v600zM400 688l-300 -150v-188l300 -150l300 150v188zM200 500h400v-100l-200 -100l-200 100v100z"/>
+            <glyph glyph-name="5e" unicode="&#xe05e;"
+                   d="M600 700c69 0 134 -19 191 -50l-16 -106c-49 35 -109 56 -175 56c-131 0 -240 -84 -281 -200h331l-16 -100h-334c0 -36 8 -68 19 -100h297l-16 -100h-222c55 -61 133 -100 222 -100c78 0 147 30 200 78v-122c-59 -35 -127 -56 -200 -56c-147 0 -274 82 -344 200h-256
+l19 100h197c-8 32 -16 66 -16 100h-200l25 100h191c45 172 198 300 384 300z"/>
+            <glyph glyph-name="5f" unicode="&#xe05f;"
+                   d="M0 700h700v-100h-700v100zM0 500h500v-100h-500v100zM0 300h800v-100h-800v100zM0 100h100v-100h-100v100zM200 100h100v-100h-100v100zM400 100h100v-100h-100v100z"/>
+            <glyph glyph-name="60" unicode="&#xe060;"
+                   d="M0 800h800v-100h-800v100zM200 600h400l-200 -200zM0 200h800v-200h-800v200z"/>
+            <glyph glyph-name="61" unicode="&#xe061;"
+                   d="M0 800h100v-800h-100v800zM600 800h200v-800h-200v800zM200 600l200 -200l-200 -200v400z"/>
+            <glyph glyph-name="62" unicode="&#xe062;"
+                   d="M0 800h200v-800h-200v800zM700 800h100v-800h-100v800zM600 600v-400l-200 200z"/>
+            <glyph glyph-name="63" unicode="&#xe063;"
+                   d="M0 800h800v-200h-800v200zM400 400l200 -200h-400zM0 100h800v-100h-800v100z"/>
+            <glyph glyph-name="64" unicode="&#xe064;"
+                   d="M0 800h200v-100h-100v-600h600v100h100v-200h-800v800zM400 800h400v-400l-150 150l-250 -250l-100 100l250 250z"/>
+            <glyph glyph-name="65" unicode="&#xe065;"
+                   d="M403 700c247 0 397 -300 397 -300s-150 -300 -397 -300c-253 0 -403 300 -403 300s150 300 403 300zM400 600c-110 0 -200 -90 -200 -200s90 -200 200 -200s200 90 200 200s-90 200 -200 200zM400 500c10 0 19 -3 28 -6c-16 -8 -28 -24 -28 -44c0 -28 22 -50 50 -50
+c20 0 36 12 44 28c3 -9 6 -18 6 -28c0 -55 -45 -100 -100 -100s-100 45 -100 100s45 100 100 100z"/>
+            <glyph glyph-name="66" unicode="&#xe066;" horiz-adv-x="900"
+                   d="M331 700h3h3c3 1 7 1 10 1c12 0 29 -8 37 -17l94 -93l66 65c57 57 155 57 212 0c58 -58 58 -154 0 -212l-65 -66l93 -94c10 -8 18 -25 18 -38c0 -28 -22 -50 -50 -50c-13 0 -32 9 -40 20l-62 65l-381 -381h-269v272l375 381l-63 63c-9 8 -16 24 -16 36c0 20 16 42 35 48z
+M447 481l-313 -315l128 -132l316 316z"/>
+            <glyph glyph-name="67" unicode="&#xe067;"
+                   d="M0 800h300v-400h400v-400h-700v800zM400 800l300 -300h-300v300z"/>
+            <glyph glyph-name="68" unicode="&#xe068;"
+                   d="M200 800c0 0 200 -100 200 -300s-298 -302 -200 -500c0 0 -200 100 -200 300s300 300 200 500zM500 500c0 0 200 -100 200 -300c0 -150 -60 -200 -100 -200h-300c0 200 300 300 200 500z"/>
+            <glyph glyph-name="69" unicode="&#xe069;"
+                   d="M0 800h100v-800h-100v800zM200 800h300v-100h300l-200 -203l200 -197h-400v100h-200v400z"/>
+            <glyph glyph-name="6a" unicode="&#xe06a;" horiz-adv-x="400"
+                   d="M150 800h150l-100 -200h200l-150 -300h150l-300 -300l-100 300h134l66 200h-200z"/>
+            <glyph glyph-name="6b" unicode="&#xe06b;"
+                   d="M0 800h300v-100h500v-100h-800v200zM0 500h800v-450c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v450z"/>
+            <glyph glyph-name="6c" unicode="&#xe06c;"
+                   d="M150 800c83 0 150 -67 150 -150c0 -66 -41 -121 -100 -141v-118c15 5 33 9 50 9h200c28 0 50 22 50 50v59c-59 20 -100 75 -100 141c0 83 67 150 150 150s150 -67 150 -150c0 -66 -41 -121 -100 -141v-59c0 -82 -68 -150 -150 -150h-200c-14 0 -25 -7 -34 -16
+c50 -24 84 -74 84 -134c0 -83 -67 -150 -150 -150s-150 67 -150 150c0 66 41 121 100 141v218c-59 20 -100 75 -100 141c0 83 67 150 150 150z"/>
+            <glyph glyph-name="6d" unicode="&#xe06d;"
+                   d="M0 800h400l-150 -150l150 -150l-100 -100l-150 150l-150 -150v400zM500 400l150 -150l150 150v-400h-400l150 150l-150 150z"/>
+            <glyph glyph-name="6e" unicode="&#xe06e;"
+                   d="M100 800l150 -150l150 150v-400h-400l150 150l-150 150zM400 400h400l-150 -150l150 -150l-100 -100l-150 150l-150 -150v400z"/>
+            <glyph glyph-name="6f" unicode="&#xe06f;"
+                   d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700c-56 0 -108 -17 -153 -44l22 -19c33 -18 13 -48 -13 -59c-30 -13 -77 10 -65 -41c13 -55 -27 -3 -47 -15c-42 -26 49 -152 31 -156l-59 34c-8 0 -13 -5 -16 -10
 c1 -30 10 -57 19 -84c28 -11 77 -2 100 -25c47 -28 97 -115 75 -159c34 -13 68 -22 106 -22c101 0 193 48 247 125c3 24 -8 44 -50 44c-69 0 -156 13 -153 97c2 46 101 108 66 143c-30 30 12 39 12 66c0 37 -65 32 -69 50s20 36 41 56c-30 10 -60 19 -94 19zM631 591
-c-38 -11 -94 -35 -87 -53c6 -15 52 -1 65 -13c11 -10 16 -59 44 -31l22 22v3c-11 26 -26 50 -44 72z" />
-    <glyph glyph-name="70" unicode="&#xe070;" 
-d="M703 800l97 -100l-400 -400l-100 100l-200 -203l-100 100l300 303l100 -100zM0 100h800v-100h-800v100z" />
-    <glyph glyph-name="71" unicode="&#xe071;" 
-d="M0 700h100v-100h-100v100zM200 700h100v-100h-100v100zM400 700h100v-100h-100v100zM600 700h100v-100h-100v100zM0 500h100v-100h-100v100zM200 500h100v-100h-100v100zM400 500h100v-100h-100v100zM600 500h100v-100h-100v100zM0 300h100v-100h-100v100zM200 300h100
-v-100h-100v100zM400 300h100v-100h-100v100zM600 300h100v-100h-100v100zM0 100h100v-100h-100v100zM200 100h100v-100h-100v100zM400 100h100v-100h-100v100zM600 100h100v-100h-100v100z" />
-    <glyph glyph-name="72" unicode="&#xe072;" 
-d="M0 800h200v-200h-200v200zM300 800h200v-200h-200v200zM600 800h200v-200h-200v200zM0 500h200v-200h-200v200zM300 500h200v-200h-200v200zM600 500h200v-200h-200v200zM0 200h200v-200h-200v200zM300 200h200v-200h-200v200zM600 200h200v-200h-200v200z" />
-    <glyph glyph-name="73" unicode="&#xe073;" 
-d="M0 800h300v-300h-300v300zM500 800h300v-300h-300v300zM0 300h300v-300h-300v300zM500 300h300v-300h-300v300z" />
-    <glyph glyph-name="74" unicode="&#xe074;" 
-d="M19 800h662c11 0 19 -8 19 -19v-331c0 -28 -22 -50 -50 -50h-600c-28 0 -50 22 -50 50v331c0 11 8 19 19 19zM0 309c16 -6 32 -9 50 -9h600c18 0 34 3 50 9v-290c0 -11 -8 -19 -19 -19h-662c-11 0 -19 8 -19 19v290zM550 200c-28 0 -50 -22 -50 -50s22 -50 50 -50
-s50 22 50 50s-22 50 -50 50z" />
-    <glyph glyph-name="75" unicode="&#xe075;" 
-d="M0 700h300v-100h-50c-28 0 -50 -22 -50 -50v-150h300v150c0 28 -22 50 -50 50h-50v100h300v-100h-50c-28 0 -50 -22 -50 -50v-400c0 -28 22 -50 50 -50h50v-100h-300v100h50c28 0 50 22 50 50v150h-300v-150c0 -28 22 -50 50 -50h50v-100h-300v100h50c28 0 50 22 50 50
-v400c0 28 -22 50 -50 50h-50v100z" />
-    <glyph glyph-name="76" unicode="&#xe076;" 
-d="M400 700c165 0 300 -135 300 -300v-100h50c28 0 50 -22 50 -50v-200c0 -28 -22 -50 -50 -50h-100c-28 0 -50 22 -50 50v350c0 111 -89 200 -200 200s-200 -89 -200 -200v-350c0 -28 -22 -50 -50 -50h-100c-28 0 -50 22 -50 50v200c0 28 22 50 50 50h50v100
-c0 165 135 300 300 300z" />
-    <glyph glyph-name="77" unicode="&#xe077;" 
-d="M0 500c0 109 91 200 200 200s200 -91 200 -200c0 109 91 200 200 200s200 -91 200 -200c0 -55 -23 -105 -59 -141l-341 -340l-341 340c-36 36 -59 86 -59 141z" />
-    <glyph glyph-name="78" unicode="&#xe078;" 
-d="M400 700l400 -300l-100 3v-403h-200v200h-200v-200h-200v400h-100z" />
-    <glyph glyph-name="79" unicode="&#xe079;" 
-d="M0 800h800v-800h-800v800zM100 700v-300l100 100l400 -400h100v100l-200 200l100 100l100 -100v300h-600z" />
-    <glyph glyph-name="7a" unicode="&#xe07a;" 
-d="M19 800h762c11 0 19 -8 19 -19v-762c0 -11 -8 -19 -19 -19h-762c-11 0 -19 8 -19 19v762c0 11 8 19 19 19zM100 600v-300h100l100 -100h200l100 100h100v300h-600z" />
-    <glyph glyph-name="7b" unicode="&#xe07b;" 
-d="M200 600c80 0 142 -56 200 -122c58 66 119 122 200 122c131 0 200 -101 200 -200s-69 -200 -200 -200c-81 0 -142 56 -200 122c-58 -66 -121 -122 -200 -122c-131 0 -200 101 -200 200s69 200 200 200zM200 500c-74 0 -100 -54 -100 -100s26 -100 100 -100
-c42 0 88 47 134 100c-46 53 -92 100 -134 100zM600 500c-43 0 -88 -47 -134 -100c46 -53 91 -100 134 -100c74 0 100 54 100 100s-26 100 -100 100z" />
-    <glyph glyph-name="7c" unicode="&#xe07c;" horiz-adv-x="400" 
-d="M300 800c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100s45 100 100 100zM150 550c83 0 150 -69 150 -150c0 -66 -100 -214 -100 -250c0 -28 22 -50 50 -50s50 22 50 50h100c0 -83 -67 -150 -150 -150s-150 64 -150 150s100 222 100 250s-22 50 -50 50
-s-50 -22 -50 -50h-100c0 83 67 150 150 150z" />
-    <glyph glyph-name="7d" unicode="&#xe07d;" 
-d="M200 800h500v-100h-122c-77 -197 -156 -392 -234 -588l-6 -12h162v-100h-500v100h122c77 197 156 392 234 588l7 12h-163v100z" />
-    <glyph glyph-name="7e" unicode="&#xe07e;" 
-d="M0 700h800v-100h-800v100zM0 500h800v-100h-800v100zM0 300h800v-100h-800v100zM100 100h600v-100h-600v100z" />
-    <glyph glyph-name="7f" unicode="&#xe07f;" 
-d="M0 700h800v-100h-800v100zM0 500h800v-100h-800v100zM0 300h800v-100h-800v100zM0 100h600v-100h-600v100z" />
-    <glyph glyph-name="80" unicode="&#xe080;" 
-d="M0 700h800v-100h-800v100zM0 500h800v-100h-800v100zM0 300h800v-100h-800v100zM200 100h600v-100h-600v100z" />
-    <glyph glyph-name="81" unicode="&#xe081;" 
-d="M550 800c138 0 250 -112 250 -250s-112 -250 -250 -250c-16 0 -32 0 -47 3l-3 -3v-100h-200v-200h-300v200l303 303c-3 15 -3 31 -3 47c0 138 112 250 250 250zM600 700c-55 0 -100 -45 -100 -100s45 -100 100 -100s100 45 100 100s-45 100 -100 100z" />
-    <glyph glyph-name="82" unicode="&#xe082;" 
-d="M134 600h3h4h4h5h500c28 0 50 -22 50 -50v-350h100v-150c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v150h100v350v2c0 20 15 42 34 48zM200 500v-300h100v-100h200v100h100v300h-400z" />
-    <glyph glyph-name="83" unicode="&#xe083;" 
-d="M0 800h400v-400h-400v400zM500 600h100v-400h-400v100h300v300zM700 400h100v-400h-400v100h300v300z" />
-    <glyph glyph-name="84" unicode="&#xe084;" horiz-adv-x="600" 
-d="M337 694c6 4 12 7 21 7c28 0 50 -22 50 -50c0 -17 -12 -37 -27 -45l-300 -150c-8 -6 -21 -11 -31 -11c-28 0 -50 22 -50 50c0 21 16 44 37 49zM437 544c6 4 12 7 21 7c28 0 50 -22 50 -50c0 -17 -12 -37 -27 -45l-400 -200c-8 -6 -21 -11 -31 -11c-28 0 -50 22 -50 50
+c-38 -11 -94 -35 -87 -53c6 -15 52 -1 65 -13c11 -10 16 -59 44 -31l22 22v3c-11 26 -26 50 -44 72z"/>
+            <glyph glyph-name="70" unicode="&#xe070;"
+                   d="M703 800l97 -100l-400 -400l-100 100l-200 -203l-100 100l300 303l100 -100zM0 100h800v-100h-800v100z"/>
+            <glyph glyph-name="71" unicode="&#xe071;"
+                   d="M0 700h100v-100h-100v100zM200 700h100v-100h-100v100zM400 700h100v-100h-100v100zM600 700h100v-100h-100v100zM0 500h100v-100h-100v100zM200 500h100v-100h-100v100zM400 500h100v-100h-100v100zM600 500h100v-100h-100v100zM0 300h100v-100h-100v100zM200 300h100
+v-100h-100v100zM400 300h100v-100h-100v100zM600 300h100v-100h-100v100zM0 100h100v-100h-100v100zM200 100h100v-100h-100v100zM400 100h100v-100h-100v100zM600 100h100v-100h-100v100z"/>
+            <glyph glyph-name="72" unicode="&#xe072;"
+                   d="M0 800h200v-200h-200v200zM300 800h200v-200h-200v200zM600 800h200v-200h-200v200zM0 500h200v-200h-200v200zM300 500h200v-200h-200v200zM600 500h200v-200h-200v200zM0 200h200v-200h-200v200zM300 200h200v-200h-200v200zM600 200h200v-200h-200v200z"/>
+            <glyph glyph-name="73" unicode="&#xe073;"
+                   d="M0 800h300v-300h-300v300zM500 800h300v-300h-300v300zM0 300h300v-300h-300v300zM500 300h300v-300h-300v300z"/>
+            <glyph glyph-name="74" unicode="&#xe074;"
+                   d="M19 800h662c11 0 19 -8 19 -19v-331c0 -28 -22 -50 -50 -50h-600c-28 0 -50 22 -50 50v331c0 11 8 19 19 19zM0 309c16 -6 32 -9 50 -9h600c18 0 34 3 50 9v-290c0 -11 -8 -19 -19 -19h-662c-11 0 -19 8 -19 19v290zM550 200c-28 0 -50 -22 -50 -50s22 -50 50 -50
+s50 22 50 50s-22 50 -50 50z"/>
+            <glyph glyph-name="75" unicode="&#xe075;"
+                   d="M0 700h300v-100h-50c-28 0 -50 -22 -50 -50v-150h300v150c0 28 -22 50 -50 50h-50v100h300v-100h-50c-28 0 -50 -22 -50 -50v-400c0 -28 22 -50 50 -50h50v-100h-300v100h50c28 0 50 22 50 50v150h-300v-150c0 -28 22 -50 50 -50h50v-100h-300v100h50c28 0 50 22 50 50
+v400c0 28 -22 50 -50 50h-50v100z"/>
+            <glyph glyph-name="76" unicode="&#xe076;"
+                   d="M400 700c165 0 300 -135 300 -300v-100h50c28 0 50 -22 50 -50v-200c0 -28 -22 -50 -50 -50h-100c-28 0 -50 22 -50 50v350c0 111 -89 200 -200 200s-200 -89 -200 -200v-350c0 -28 -22 -50 -50 -50h-100c-28 0 -50 22 -50 50v200c0 28 22 50 50 50h50v100
+c0 165 135 300 300 300z"/>
+            <glyph glyph-name="77" unicode="&#xe077;"
+                   d="M0 500c0 109 91 200 200 200s200 -91 200 -200c0 109 91 200 200 200s200 -91 200 -200c0 -55 -23 -105 -59 -141l-341 -340l-341 340c-36 36 -59 86 -59 141z"/>
+            <glyph glyph-name="78" unicode="&#xe078;"
+                   d="M400 700l400 -300l-100 3v-403h-200v200h-200v-200h-200v400h-100z"/>
+            <glyph glyph-name="79" unicode="&#xe079;"
+                   d="M0 800h800v-800h-800v800zM100 700v-300l100 100l400 -400h100v100l-200 200l100 100l100 -100v300h-600z"/>
+            <glyph glyph-name="7a" unicode="&#xe07a;"
+                   d="M19 800h762c11 0 19 -8 19 -19v-762c0 -11 -8 -19 -19 -19h-762c-11 0 -19 8 -19 19v762c0 11 8 19 19 19zM100 600v-300h100l100 -100h200l100 100h100v300h-600z"/>
+            <glyph glyph-name="7b" unicode="&#xe07b;"
+                   d="M200 600c80 0 142 -56 200 -122c58 66 119 122 200 122c131 0 200 -101 200 -200s-69 -200 -200 -200c-81 0 -142 56 -200 122c-58 -66 -121 -122 -200 -122c-131 0 -200 101 -200 200s69 200 200 200zM200 500c-74 0 -100 -54 -100 -100s26 -100 100 -100
+c42 0 88 47 134 100c-46 53 -92 100 -134 100zM600 500c-43 0 -88 -47 -134 -100c46 -53 91 -100 134 -100c74 0 100 54 100 100s-26 100 -100 100z"/>
+            <glyph glyph-name="7c" unicode="&#xe07c;" horiz-adv-x="400"
+                   d="M300 800c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100s45 100 100 100zM150 550c83 0 150 -69 150 -150c0 -66 -100 -214 -100 -250c0 -28 22 -50 50 -50s50 22 50 50h100c0 -83 -67 -150 -150 -150s-150 64 -150 150s100 222 100 250s-22 50 -50 50
+s-50 -22 -50 -50h-100c0 83 67 150 150 150z"/>
+            <glyph glyph-name="7d" unicode="&#xe07d;"
+                   d="M200 800h500v-100h-122c-77 -197 -156 -392 -234 -588l-6 -12h162v-100h-500v100h122c77 197 156 392 234 588l7 12h-163v100z"/>
+            <glyph glyph-name="7e" unicode="&#xe07e;"
+                   d="M0 700h800v-100h-800v100zM0 500h800v-100h-800v100zM0 300h800v-100h-800v100zM100 100h600v-100h-600v100z"/>
+            <glyph glyph-name="7f" unicode="&#xe07f;"
+                   d="M0 700h800v-100h-800v100zM0 500h800v-100h-800v100zM0 300h800v-100h-800v100zM0 100h600v-100h-600v100z"/>
+            <glyph glyph-name="80" unicode="&#xe080;"
+                   d="M0 700h800v-100h-800v100zM0 500h800v-100h-800v100zM0 300h800v-100h-800v100zM200 100h600v-100h-600v100z"/>
+            <glyph glyph-name="81" unicode="&#xe081;"
+                   d="M550 800c138 0 250 -112 250 -250s-112 -250 -250 -250c-16 0 -32 0 -47 3l-3 -3v-100h-200v-200h-300v200l303 303c-3 15 -3 31 -3 47c0 138 112 250 250 250zM600 700c-55 0 -100 -45 -100 -100s45 -100 100 -100s100 45 100 100s-45 100 -100 100z"/>
+            <glyph glyph-name="82" unicode="&#xe082;"
+                   d="M134 600h3h4h4h5h500c28 0 50 -22 50 -50v-350h100v-150c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v150h100v350v2c0 20 15 42 34 48zM200 500v-300h100v-100h200v100h100v300h-400z"/>
+            <glyph glyph-name="83" unicode="&#xe083;"
+                   d="M0 800h400v-400h-400v400zM500 600h100v-400h-400v100h300v300zM700 400h100v-400h-400v100h300v300z"/>
+            <glyph glyph-name="84" unicode="&#xe084;" horiz-adv-x="600"
+                   d="M337 694c6 4 12 7 21 7c28 0 50 -22 50 -50c0 -17 -12 -37 -27 -45l-300 -150c-8 -6 -21 -11 -31 -11c-28 0 -50 22 -50 50c0 21 16 44 37 49zM437 544c6 4 12 7 21 7c28 0 50 -22 50 -50c0 -17 -12 -37 -27 -45l-400 -200c-8 -6 -21 -11 -31 -11c-28 0 -50 22 -50 50
 c0 21 16 44 37 49zM437 344c6 4 12 7 21 7c28 0 50 -22 50 -50c0 -17 -12 -37 -27 -45l-106 -56c24 -4 43 -26 43 -50c0 -28 -23 -51 -51 -51c-2 0 -6 1 -8 1h-200c-26 1 -48 24 -48 50c0 16 12 36 26 44zM151 -50c0 23 20 50 46 50h3h4h5h100c28 0 50 -22 50 -50
-s-22 -50 -50 -50h-100c-2 0 -6 -1 -8 -1c-28 0 -50 23 -50 51z" />
-    <glyph glyph-name="85" unicode="&#xe085;" 
-d="M199 800h100v-200h-200v100h100v100zM586 797h1c18 1 38 1 56 -3c36 -8 69 -26 97 -54c78 -78 78 -203 0 -281l-150 -150c-8 -13 -28 -24 -43 -24c-28 0 -50 22 -50 50c0 15 11 35 24 43l150 150c40 40 39 105 0 144c-41 41 -110 34 -144 0l-44 -44
+s-22 -50 -50 -50h-100c-2 0 -6 -1 -8 -1c-28 0 -50 23 -50 51z"/>
+            <glyph glyph-name="85" unicode="&#xe085;"
+                   d="M199 800h100v-200h-200v100h100v100zM586 797h1c18 1 38 1 56 -3c36 -8 69 -26 97 -54c78 -78 78 -203 0 -281l-150 -150c-8 -13 -28 -24 -43 -24c-28 0 -50 22 -50 50c0 15 11 35 24 43l150 150c40 40 39 105 0 144c-41 41 -110 34 -144 0l-44 -44
 c-8 -13 -27 -24 -42 -24c-28 0 -50 22 -50 50c0 15 11 35 24 43l43 44c32 33 72 53 128 56zM208 490c4 5 14 16 22 16h3c2 0 6 1 8 1c28 0 50 -22 50 -50c0 -11 -6 -27 -14 -35l-150 -150c-40 -40 -39 -105 0 -144c41 -41 110 -34 144 0l44 44c8 13 27 24 42 24
-c28 0 50 -22 50 -50c0 -15 -11 -35 -24 -43l-43 -44c-22 -22 -48 -37 -75 -47c-70 -25 -151 -9 -207 47c-78 78 -78 203 0 281zM499 200h200v-100h-100v-100h-100v200z" />
-    <glyph glyph-name="86" unicode="&#xe086;" 
-d="M586 797c18 1 39 1 57 -3c36 -8 69 -26 97 -54c78 -78 78 -203 0 -281l-150 -150c-62 -62 -132 -81 -182 -78s-69 17 -84 25s-26 27 -26 44c0 28 22 51 50 51c8 0 19 -3 26 -7c0 0 15 -11 41 -13s62 3 106 47l150 150c40 40 39 105 0 144c-41 41 -110 34 -144 0
+c28 0 50 -22 50 -50c0 -15 -11 -35 -24 -43l-43 -44c-22 -22 -48 -37 -75 -47c-70 -25 -151 -9 -207 47c-78 78 -78 203 0 281zM499 200h200v-100h-100v-100h-100v200z"/>
+            <glyph glyph-name="86" unicode="&#xe086;"
+                   d="M586 797c18 1 39 1 57 -3c36 -8 69 -26 97 -54c78 -78 78 -203 0 -281l-150 -150c-62 -62 -132 -81 -182 -78s-69 17 -84 25s-26 27 -26 44c0 28 22 51 50 51c8 0 19 -3 26 -7c0 0 15 -11 41 -13s62 3 106 47l150 150c40 40 39 105 0 144c-41 41 -110 34 -144 0
 c-8 -13 -28 -24 -43 -24c-28 0 -50 22 -50 50c0 15 11 35 24 43c32 33 72 53 128 56zM386 566c50 -2 64 -17 85 -22s37 -28 37 -49c0 -28 -22 -50 -50 -50c-10 0 -23 5 -31 11c0 0 -19 9 -47 10s-63 -4 -103 -44l-150 -150c-40 -40 -39 -105 0 -144c41 -41 110 -34 144 0
-c8 13 27 24 42 24c28 0 50 -22 50 -50c0 -15 -10 -35 -23 -43c-22 -22 -48 -37 -75 -47c-70 -25 -151 -9 -207 47c-78 78 -78 203 0 281l150 150c60 60 128 78 178 76z" />
-    <glyph glyph-name="87" unicode="&#xe087;" 
-d="M0 700h300v-300h-300v300zM400 700h400v-100h-400v100zM400 500h300v-100h-300v100zM0 300h300v-300h-300v300zM400 300h400v-100h-400v100zM400 100h300v-100h-300v100z" />
-    <glyph glyph-name="88" unicode="&#xe088;" 
-d="M50 700c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM200 700h600v-100h-600v100zM50 500c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM200 500h600v-100h-600v100zM50 300c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50
-s22 50 50 50zM200 300h600v-100h-600v100zM50 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM200 100h600v-100h-600v100z" />
-    <glyph glyph-name="89" unicode="&#xe089;" 
-d="M800 800l-400 -800l-100 300l-300 100z" />
-    <glyph glyph-name="8a" unicode="&#xe08a;" horiz-adv-x="600" 
-d="M300 700c110 0 200 -90 200 -200v-100h100v-400h-600v400h100v100c0 110 90 200 200 200zM300 600c-56 0 -100 -44 -100 -100v-100h200v100c0 56 -44 100 -100 100z" />
-    <glyph glyph-name="8b" unicode="&#xe08b;" horiz-adv-x="600" 
-d="M300 800c110 0 200 -90 200 -200v-200h100v-400h-600v400h400v200c0 56 -44 100 -100 100s-100 -44 -100 -100h-100c0 110 90 200 200 200z" />
-    <glyph glyph-name="8c" unicode="&#xe08c;" 
-d="M400 700v-100c-111 0 -200 -89 -200 -200h100l-150 -200l-150 200h100c0 165 135 300 300 300zM650 600l150 -200h-100c0 -165 -135 -300 -300 -300v100c111 0 200 89 200 200h-100z" />
-    <glyph glyph-name="8d" unicode="&#xe08d;" 
-d="M100 800h600v-300h100l-150 -250l-150 250h100v200h-400v-100h-100v200zM150 550l150 -250h-100v-200h400v100h100v-200h-600v300h-100z" />
-    <glyph glyph-name="8e" unicode="&#xe08e;" 
-d="M600 700l200 -150l-200 -150v100h-500v-100h-100v100c0 55 45 100 100 100h500v100zM200 300v-100h500v100h100v-100c0 -55 -45 -100 -100 -100h-500v-100l-200 150z" />
-    <glyph glyph-name="8f" unicode="&#xe08f;" horiz-adv-x="900" 
-d="M350 800c193 0 350 -157 350 -350c0 -60 -17 -117 -44 -166c5 -3 12 -8 16 -12l100 -100c16 -16 30 -49 30 -72c0 -56 -46 -102 -102 -102c-23 0 -56 14 -72 30l-100 100c-4 3 -9 9 -12 13c-49 -26 -107 -41 -166 -41c-193 0 -350 157 -350 350s157 350 350 350zM350 200
-c142 0 250 108 250 250c0 139 -111 250 -250 250s-250 -111 -250 -250s111 -250 250 -250z" />
-    <glyph glyph-name="90" unicode="&#xe090;" horiz-adv-x="600" 
-d="M300 800c166 0 300 -134 300 -300c0 -200 -300 -500 -300 -500s-300 300 -300 500c0 166 134 300 300 300zM300 700c-110 0 -200 -90 -200 -200s90 -200 200 -200s200 90 200 200s-90 200 -200 200z" />
-    <glyph glyph-name="91" unicode="&#xe091;" horiz-adv-x="900" 
-d="M0 800h800v-541c1 -3 1 -8 1 -11s0 -7 -1 -10v-238h-800v800zM495 250c0 26 22 50 50 50h5h150v400h-600v-600h600v100h-150h-5c-28 0 -50 22 -50 50zM350 600c83 0 150 -67 150 -150c0 -100 -150 -250 -150 -250s-150 150 -150 250c0 83 67 150 150 150zM350 500
-c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z" />
-    <glyph glyph-name="92" unicode="&#xe092;" horiz-adv-x="600" 
-d="M0 700h200v-600h-200v600zM400 700h200v-600h-200v600z" />
-    <glyph glyph-name="93" unicode="&#xe093;" horiz-adv-x="600" 
-d="M0 700l600 -300l-600 -300v600z" />
-    <glyph glyph-name="94" unicode="&#xe094;" horiz-adv-x="600" 
-d="M300 700c166 0 300 -134 300 -300s-134 -300 -300 -300s-300 134 -300 300s134 300 300 300z" />
-    <glyph glyph-name="95" unicode="&#xe095;" 
-d="M400 700v-600l-400 300zM400 400l400 300v-600z" />
-    <glyph glyph-name="96" unicode="&#xe096;" 
-d="M0 700l400 -300l-400 -300v600zM400 100v600l400 -300z" />
-    <glyph glyph-name="97" unicode="&#xe097;" 
-d="M0 700h200v-600h-200v600zM200 400l500 300v-600z" />
-    <glyph glyph-name="98" unicode="&#xe098;" 
-d="M0 700l500 -300l-500 -300v600zM500 100v600h200v-600h-200z" />
-    <glyph glyph-name="99" unicode="&#xe099;" horiz-adv-x="600" 
-d="M0 700h600v-600h-600v600z" />
-    <glyph glyph-name="9a" unicode="&#xe09a;" 
-d="M200 800h400v-200h200v-400h-200v-200h-400v200h-200v400h200v200z" />
-    <glyph glyph-name="9b" unicode="&#xe09b;" 
-d="M0 700h800v-100h-800v100zM0 403h800v-100h-800v100zM0 103h800v-100h-800v100z" />
-    <glyph glyph-name="9c" unicode="&#xe09c;" horiz-adv-x="600" 
-d="M278 700c7 2 13 4 22 4c55 0 100 -45 100 -100v-4v-200c0 -55 -45 -100 -100 -100s-100 45 -100 100v200v2c0 44 35 88 78 98zM34 500h4h3c3 0 6 1 9 1c28 0 50 -22 50 -50v-1v-50c0 -111 89 -200 200 -200s200 89 200 200v50c0 28 22 50 50 50s50 -22 50 -50v-50
-c0 -148 -109 -270 -250 -294v-106h50c55 0 100 -45 100 -100h-400c0 55 45 100 100 100h50v106c-141 24 -250 146 -250 294v50v2c0 20 15 42 34 48z" />
-    <glyph glyph-name="9d" unicode="&#xe09d;" 
-d="M0 500h800v-200h-800v200z" />
-    <glyph glyph-name="9e" unicode="&#xe09e;" 
-d="M34 700h4h3h4h5h700c28 0 50 -22 50 -50v-500c0 -28 -22 -50 -50 -50h-250v-100h100c55 0 100 -45 100 -100h-600c0 55 45 100 100 100h100v100h-250c-28 0 -50 22 -50 50v500v2c0 20 15 42 34 48zM100 600v-400h600v400h-600z" />
-    <glyph glyph-name="9f" unicode="&#xe09f;" 
-d="M272 700c-14 -40 -22 -83 -22 -128c0 -221 179 -400 400 -400c45 0 88 8 128 22c-53 -158 -202 -272 -378 -272c-221 0 -400 179 -400 400c0 176 114 325 272 378z" />
-    <glyph glyph-name="a0" unicode="&#xe0a0;" 
-d="M350 700l150 -150h-100v-150h150v100l150 -150l-150 -150v100h-150v-150h100l-150 -150l-150 150h100v150h-150v-100l-150 150l150 150v-100h150v150h-100z" />
-    <glyph glyph-name="a1" unicode="&#xe0a1;" 
-d="M800 800v-550c0 -83 -67 -150 -150 -150s-150 67 -150 150s67 150 150 150c17 0 35 -4 50 -9v206c-201 -6 -327 -27 -400 -50v-397c0 -83 -67 -150 -150 -150s-150 67 -150 150s67 150 150 150c17 0 35 -4 50 -9v409s100 100 600 100z" />
-    <glyph glyph-name="a2" unicode="&#xe0a2;" horiz-adv-x="700" 
-d="M499 700c51 0 102 -20 141 -59c78 -78 78 -203 0 -281l-250 -244c-48 -48 -127 -48 -175 0s-48 127 0 175l96 97l69 -69l-90 -94l-7 -3c-10 -10 -10 -28 0 -38s28 -10 38 0l250 247c37 40 39 102 0 141s-104 40 -144 0l-278 -275c-66 -69 -68 -179 0 -247
-c69 -69 181 -69 250 0l9 12l116 113l69 -69l-125 -125c-107 -107 -281 -107 -388 0s-107 281 0 388l278 272c39 39 90 59 141 59z" />
-    <glyph glyph-name="a3" unicode="&#xe0a3;" 
-d="M600 800l200 -200l-100 -100l-200 200zM400 600l200 -200l-400 -400h-200v200z" />
-    <glyph glyph-name="a4" unicode="&#xe0a4;" 
-d="M550 800c83 0 150 -90 150 -200s-67 -200 -150 -200c-22 0 -40 8 -59 19c6 26 9 52 9 81c0 84 -27 158 -72 212c27 52 71 88 122 88zM250 700c83 0 150 -90 150 -200s-67 -200 -150 -200s-150 90 -150 200s67 200 150 200zM725 384c44 -22 75 -66 75 -118v-166h-200v66
-c0 50 -17 96 -44 134c66 2 126 33 169 84zM75 284c45 -53 106 -84 175 -84s130 31 175 84c44 -22 75 -66 75 -118v-166h-500v166c0 52 31 96 75 118z" />
-    <glyph glyph-name="a5" unicode="&#xe0a5;" 
-d="M400 800c110 0 200 -112 200 -250s-90 -250 -200 -250s-200 112 -200 250s90 250 200 250zM191 300c54 -61 128 -100 209 -100s155 39 209 100c106 -5 191 -92 191 -200v-100h-800v100c0 108 85 195 191 200z" />
-    <glyph glyph-name="a6" unicode="&#xe0a6;" horiz-adv-x="600" 
-d="M19 800h462c11 0 19 -8 19 -19v-762c0 -11 -8 -19 -19 -19h-462c-11 0 -19 8 -19 19v762c0 11 8 19 19 19zM100 700v-500h300v500h-300zM250 150c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z" />
-    <glyph glyph-name="a7" unicode="&#xe0a7;" 
-d="M350 800c17 0 34 -1 50 -3v-397l-297 297c63 64 150 103 247 103zM500 694c169 -25 300 -168 300 -344c0 -193 -157 -350 -350 -350c-85 0 -161 31 -222 81l272 272v341zM91 562l237 -234l-212 -212c-70 55 -116 138 -116 234c0 84 35 158 91 212z" />
-    <glyph glyph-name="a8" unicode="&#xe0a8;" 
-d="M92 650c0 23 20 50 46 50h3h4h5h400c28 0 50 -22 50 -50s-22 -50 -50 -50h-50v-200h100c55 0 100 -45 100 -100h-300v-300l-56 -100l-44 100v300h-300c0 55 45 100 100 100h100v200h-50c-2 0 -6 -1 -8 -1c-28 0 -50 23 -50 51z" />
-    <glyph glyph-name="a9" unicode="&#xe0a9;" 
-d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM300 600v-400l300 200z" />
-    <glyph glyph-name="aa" unicode="&#xe0aa;" 
-d="M300 800h200v-300h300v-200h-300v-300h-200v300h-300v200h300v300z" />
-    <glyph glyph-name="ab" unicode="&#xe0ab;" 
-d="M300 800h100v-400h-100v400zM172 656l62 -78l-40 -31c-58 -46 -94 -117 -94 -197c0 -139 111 -250 250 -250s250 111 250 250c0 80 -39 151 -97 197l-37 31l62 78l38 -31c82 -64 134 -164 134 -275c0 -193 -157 -350 -350 -350s-350 157 -350 350c0 111 53 211 134 275z
-" />
-    <glyph glyph-name="ac" unicode="&#xe0ac;" 
-d="M200 800h400v-200h-400v200zM9 500h782c6 0 9 -3 9 -9v-282c0 -6 -3 -9 -9 -9h-91v200h-600v-200h-91c-6 0 -9 3 -9 9v282c0 6 3 9 9 9zM200 300h400v-300h-400v300z" />
-    <glyph glyph-name="ad" unicode="&#xe0ad;" 
-d="M0 700h100v-700h-100v700zM700 700h100v-700h-100v700zM200 600h200v-100h-200v100zM300 400h200v-100h-200v100zM400 200h200v-100h-200v100z" />
-    <glyph glyph-name="ae" unicode="&#xe0ae;" 
-d="M325 700c42 -141 87 -280 131 -419c29 74 59 148 88 222c30 -57 58 -114 87 -172h169v-100h-231l-13 28c-37 -92 -74 -184 -112 -275c-38 129 -79 257 -119 385c-42 -133 -83 -267 -125 -400c-28 88 -56 175 -84 262h-116v100h188l9 -34l3 -6c42 137 83 273 125 409z" />
-    <glyph glyph-name="af" unicode="&#xe0af;" 
-d="M200 600c0 57 43 100 100 100s100 -43 100 -100c0 -28 -18 -48 -28 -72c-3 -6 -3 -16 -3 -28h231v-231c12 0 22 0 28 3c24 10 44 28 72 28c57 0 100 -43 100 -100s-43 -100 -100 -100c-28 0 -48 18 -72 28c-6 3 -16 3 -28 3v-231h-231c0 12 0 22 3 28c10 24 28 44 28 72
-c0 57 -43 100 -100 100s-100 -43 -100 -100c0 -28 18 -48 28 -72c3 -6 3 -16 3 -28h-231v600h231c0 12 0 22 -3 28c-10 24 -28 44 -28 72z" />
-    <glyph glyph-name="b0" unicode="&#xe0b0;" horiz-adv-x="500" 
-d="M247 700c84 0 148 -20 191 -59s59 -93 59 -141c0 -117 -69 -181 -119 -225s-81 -67 -81 -150v-25h-100v25c0 117 65 181 115 225s85 67 85 150c0 25 -8 48 -28 66s-56 34 -122 34s-97 -18 -116 -37s-27 -43 -31 -69l-100 12c5 38 19 88 59 128s103 66 188 66zM197 0h100
-v-100h-100v100z" />
-    <glyph glyph-name="b1" unicode="&#xe0b1;" 
-d="M450 800c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -69 -48 -127 -112 -144c-22 55 -75 94 -138 94c-20 0 -39 -5 -56 -12c-17 64 -75 112 -144 112s-127 -48 -144 -112c-17 7 -36 12 -56 12c-37 0 -71 -12 -97 -34c-33 36 -53 82 -53 134
+c8 13 27 24 42 24c28 0 50 -22 50 -50c0 -15 -10 -35 -23 -43c-22 -22 -48 -37 -75 -47c-70 -25 -151 -9 -207 47c-78 78 -78 203 0 281l150 150c60 60 128 78 178 76z"/>
+            <glyph glyph-name="87" unicode="&#xe087;"
+                   d="M0 700h300v-300h-300v300zM400 700h400v-100h-400v100zM400 500h300v-100h-300v100zM0 300h300v-300h-300v300zM400 300h400v-100h-400v100zM400 100h300v-100h-300v100z"/>
+            <glyph glyph-name="88" unicode="&#xe088;"
+                   d="M50 700c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM200 700h600v-100h-600v100zM50 500c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM200 500h600v-100h-600v100zM50 300c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50
+s22 50 50 50zM200 300h600v-100h-600v100zM50 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM200 100h600v-100h-600v100z"/>
+            <glyph glyph-name="89" unicode="&#xe089;"
+                   d="M800 800l-400 -800l-100 300l-300 100z"/>
+            <glyph glyph-name="8a" unicode="&#xe08a;" horiz-adv-x="600"
+                   d="M300 700c110 0 200 -90 200 -200v-100h100v-400h-600v400h100v100c0 110 90 200 200 200zM300 600c-56 0 -100 -44 -100 -100v-100h200v100c0 56 -44 100 -100 100z"/>
+            <glyph glyph-name="8b" unicode="&#xe08b;" horiz-adv-x="600"
+                   d="M300 800c110 0 200 -90 200 -200v-200h100v-400h-600v400h400v200c0 56 -44 100 -100 100s-100 -44 -100 -100h-100c0 110 90 200 200 200z"/>
+            <glyph glyph-name="8c" unicode="&#xe08c;"
+                   d="M400 700v-100c-111 0 -200 -89 -200 -200h100l-150 -200l-150 200h100c0 165 135 300 300 300zM650 600l150 -200h-100c0 -165 -135 -300 -300 -300v100c111 0 200 89 200 200h-100z"/>
+            <glyph glyph-name="8d" unicode="&#xe08d;"
+                   d="M100 800h600v-300h100l-150 -250l-150 250h100v200h-400v-100h-100v200zM150 550l150 -250h-100v-200h400v100h100v-200h-600v300h-100z"/>
+            <glyph glyph-name="8e" unicode="&#xe08e;"
+                   d="M600 700l200 -150l-200 -150v100h-500v-100h-100v100c0 55 45 100 100 100h500v100zM200 300v-100h500v100h100v-100c0 -55 -45 -100 -100 -100h-500v-100l-200 150z"/>
+            <glyph glyph-name="8f" unicode="&#xe08f;" horiz-adv-x="900"
+                   d="M350 800c193 0 350 -157 350 -350c0 -60 -17 -117 -44 -166c5 -3 12 -8 16 -12l100 -100c16 -16 30 -49 30 -72c0 -56 -46 -102 -102 -102c-23 0 -56 14 -72 30l-100 100c-4 3 -9 9 -12 13c-49 -26 -107 -41 -166 -41c-193 0 -350 157 -350 350s157 350 350 350zM350 200
+c142 0 250 108 250 250c0 139 -111 250 -250 250s-250 -111 -250 -250s111 -250 250 -250z"/>
+            <glyph glyph-name="90" unicode="&#xe090;" horiz-adv-x="600"
+                   d="M300 800c166 0 300 -134 300 -300c0 -200 -300 -500 -300 -500s-300 300 -300 500c0 166 134 300 300 300zM300 700c-110 0 -200 -90 -200 -200s90 -200 200 -200s200 90 200 200s-90 200 -200 200z"/>
+            <glyph glyph-name="91" unicode="&#xe091;" horiz-adv-x="900"
+                   d="M0 800h800v-541c1 -3 1 -8 1 -11s0 -7 -1 -10v-238h-800v800zM495 250c0 26 22 50 50 50h5h150v400h-600v-600h600v100h-150h-5c-28 0 -50 22 -50 50zM350 600c83 0 150 -67 150 -150c0 -100 -150 -250 -150 -250s-150 150 -150 250c0 83 67 150 150 150zM350 500
+c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z"/>
+            <glyph glyph-name="92" unicode="&#xe092;" horiz-adv-x="600"
+                   d="M0 700h200v-600h-200v600zM400 700h200v-600h-200v600z"/>
+            <glyph glyph-name="93" unicode="&#xe093;" horiz-adv-x="600"
+                   d="M0 700l600 -300l-600 -300v600z"/>
+            <glyph glyph-name="94" unicode="&#xe094;" horiz-adv-x="600"
+                   d="M300 700c166 0 300 -134 300 -300s-134 -300 -300 -300s-300 134 -300 300s134 300 300 300z"/>
+            <glyph glyph-name="95" unicode="&#xe095;"
+                   d="M400 700v-600l-400 300zM400 400l400 300v-600z"/>
+            <glyph glyph-name="96" unicode="&#xe096;"
+                   d="M0 700l400 -300l-400 -300v600zM400 100v600l400 -300z"/>
+            <glyph glyph-name="97" unicode="&#xe097;"
+                   d="M0 700h200v-600h-200v600zM200 400l500 300v-600z"/>
+            <glyph glyph-name="98" unicode="&#xe098;"
+                   d="M0 700l500 -300l-500 -300v600zM500 100v600h200v-600h-200z"/>
+            <glyph glyph-name="99" unicode="&#xe099;" horiz-adv-x="600"
+                   d="M0 700h600v-600h-600v600z"/>
+            <glyph glyph-name="9a" unicode="&#xe09a;"
+                   d="M200 800h400v-200h200v-400h-200v-200h-400v200h-200v400h200v200z"/>
+            <glyph glyph-name="9b" unicode="&#xe09b;"
+                   d="M0 700h800v-100h-800v100zM0 403h800v-100h-800v100zM0 103h800v-100h-800v100z"/>
+            <glyph glyph-name="9c" unicode="&#xe09c;" horiz-adv-x="600"
+                   d="M278 700c7 2 13 4 22 4c55 0 100 -45 100 -100v-4v-200c0 -55 -45 -100 -100 -100s-100 45 -100 100v200v2c0 44 35 88 78 98zM34 500h4h3c3 0 6 1 9 1c28 0 50 -22 50 -50v-1v-50c0 -111 89 -200 200 -200s200 89 200 200v50c0 28 22 50 50 50s50 -22 50 -50v-50
+c0 -148 -109 -270 -250 -294v-106h50c55 0 100 -45 100 -100h-400c0 55 45 100 100 100h50v106c-141 24 -250 146 -250 294v50v2c0 20 15 42 34 48z"/>
+            <glyph glyph-name="9d" unicode="&#xe09d;"
+                   d="M0 500h800v-200h-800v200z"/>
+            <glyph glyph-name="9e" unicode="&#xe09e;"
+                   d="M34 700h4h3h4h5h700c28 0 50 -22 50 -50v-500c0 -28 -22 -50 -50 -50h-250v-100h100c55 0 100 -45 100 -100h-600c0 55 45 100 100 100h100v100h-250c-28 0 -50 22 -50 50v500v2c0 20 15 42 34 48zM100 600v-400h600v400h-600z"/>
+            <glyph glyph-name="9f" unicode="&#xe09f;"
+                   d="M272 700c-14 -40 -22 -83 -22 -128c0 -221 179 -400 400 -400c45 0 88 8 128 22c-53 -158 -202 -272 -378 -272c-221 0 -400 179 -400 400c0 176 114 325 272 378z"/>
+            <glyph glyph-name="a0" unicode="&#xe0a0;"
+                   d="M350 700l150 -150h-100v-150h150v100l150 -150l-150 -150v100h-150v-150h100l-150 -150l-150 150h100v150h-150v-100l-150 150l150 150v-100h150v150h-100z"/>
+            <glyph glyph-name="a1" unicode="&#xe0a1;"
+                   d="M800 800v-550c0 -83 -67 -150 -150 -150s-150 67 -150 150s67 150 150 150c17 0 35 -4 50 -9v206c-201 -6 -327 -27 -400 -50v-397c0 -83 -67 -150 -150 -150s-150 67 -150 150s67 150 150 150c17 0 35 -4 50 -9v409s100 100 600 100z"/>
+            <glyph glyph-name="a2" unicode="&#xe0a2;" horiz-adv-x="700"
+                   d="M499 700c51 0 102 -20 141 -59c78 -78 78 -203 0 -281l-250 -244c-48 -48 -127 -48 -175 0s-48 127 0 175l96 97l69 -69l-90 -94l-7 -3c-10 -10 -10 -28 0 -38s28 -10 38 0l250 247c37 40 39 102 0 141s-104 40 -144 0l-278 -275c-66 -69 -68 -179 0 -247
+c69 -69 181 -69 250 0l9 12l116 113l69 -69l-125 -125c-107 -107 -281 -107 -388 0s-107 281 0 388l278 272c39 39 90 59 141 59z"/>
+            <glyph glyph-name="a3" unicode="&#xe0a3;"
+                   d="M600 800l200 -200l-100 -100l-200 200zM400 600l200 -200l-400 -400h-200v200z"/>
+            <glyph glyph-name="a4" unicode="&#xe0a4;"
+                   d="M550 800c83 0 150 -90 150 -200s-67 -200 -150 -200c-22 0 -40 8 -59 19c6 26 9 52 9 81c0 84 -27 158 -72 212c27 52 71 88 122 88zM250 700c83 0 150 -90 150 -200s-67 -200 -150 -200s-150 90 -150 200s67 200 150 200zM725 384c44 -22 75 -66 75 -118v-166h-200v66
+c0 50 -17 96 -44 134c66 2 126 33 169 84zM75 284c45 -53 106 -84 175 -84s130 31 175 84c44 -22 75 -66 75 -118v-166h-500v166c0 52 31 96 75 118z"/>
+            <glyph glyph-name="a5" unicode="&#xe0a5;"
+                   d="M400 800c110 0 200 -112 200 -250s-90 -250 -200 -250s-200 112 -200 250s90 250 200 250zM191 300c54 -61 128 -100 209 -100s155 39 209 100c106 -5 191 -92 191 -200v-100h-800v100c0 108 85 195 191 200z"/>
+            <glyph glyph-name="a6" unicode="&#xe0a6;" horiz-adv-x="600"
+                   d="M19 800h462c11 0 19 -8 19 -19v-762c0 -11 -8 -19 -19 -19h-462c-11 0 -19 8 -19 19v762c0 11 8 19 19 19zM100 700v-500h300v500h-300zM250 150c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z"/>
+            <glyph glyph-name="a7" unicode="&#xe0a7;"
+                   d="M350 800c17 0 34 -1 50 -3v-397l-297 297c63 64 150 103 247 103zM500 694c169 -25 300 -168 300 -344c0 -193 -157 -350 -350 -350c-85 0 -161 31 -222 81l272 272v341zM91 562l237 -234l-212 -212c-70 55 -116 138 -116 234c0 84 35 158 91 212z"/>
+            <glyph glyph-name="a8" unicode="&#xe0a8;"
+                   d="M92 650c0 23 20 50 46 50h3h4h5h400c28 0 50 -22 50 -50s-22 -50 -50 -50h-50v-200h100c55 0 100 -45 100 -100h-300v-300l-56 -100l-44 100v300h-300c0 55 45 100 100 100h100v200h-50c-2 0 -6 -1 -8 -1c-28 0 -50 23 -50 51z"/>
+            <glyph glyph-name="a9" unicode="&#xe0a9;"
+                   d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM300 600v-400l300 200z"/>
+            <glyph glyph-name="aa" unicode="&#xe0aa;"
+                   d="M300 800h200v-300h300v-200h-300v-300h-200v300h-300v200h300v300z"/>
+            <glyph glyph-name="ab" unicode="&#xe0ab;"
+                   d="M300 800h100v-400h-100v400zM172 656l62 -78l-40 -31c-58 -46 -94 -117 -94 -197c0 -139 111 -250 250 -250s250 111 250 250c0 80 -39 151 -97 197l-37 31l62 78l38 -31c82 -64 134 -164 134 -275c0 -193 -157 -350 -350 -350s-350 157 -350 350c0 111 53 211 134 275z
+"/>
+            <glyph glyph-name="ac" unicode="&#xe0ac;"
+                   d="M200 800h400v-200h-400v200zM9 500h782c6 0 9 -3 9 -9v-282c0 -6 -3 -9 -9 -9h-91v200h-600v-200h-91c-6 0 -9 3 -9 9v282c0 6 3 9 9 9zM200 300h400v-300h-400v300z"/>
+            <glyph glyph-name="ad" unicode="&#xe0ad;"
+                   d="M0 700h100v-700h-100v700zM700 700h100v-700h-100v700zM200 600h200v-100h-200v100zM300 400h200v-100h-200v100zM400 200h200v-100h-200v100z"/>
+            <glyph glyph-name="ae" unicode="&#xe0ae;"
+                   d="M325 700c42 -141 87 -280 131 -419c29 74 59 148 88 222c30 -57 58 -114 87 -172h169v-100h-231l-13 28c-37 -92 -74 -184 -112 -275c-38 129 -79 257 -119 385c-42 -133 -83 -267 -125 -400c-28 88 -56 175 -84 262h-116v100h188l9 -34l3 -6c42 137 83 273 125 409z"/>
+            <glyph glyph-name="af" unicode="&#xe0af;"
+                   d="M200 600c0 57 43 100 100 100s100 -43 100 -100c0 -28 -18 -48 -28 -72c-3 -6 -3 -16 -3 -28h231v-231c12 0 22 0 28 3c24 10 44 28 72 28c57 0 100 -43 100 -100s-43 -100 -100 -100c-28 0 -48 18 -72 28c-6 3 -16 3 -28 3v-231h-231c0 12 0 22 3 28c10 24 28 44 28 72
+c0 57 -43 100 -100 100s-100 -43 -100 -100c0 -28 18 -48 28 -72c3 -6 3 -16 3 -28h-231v600h231c0 12 0 22 -3 28c-10 24 -28 44 -28 72z"/>
+            <glyph glyph-name="b0" unicode="&#xe0b0;" horiz-adv-x="500"
+                   d="M247 700c84 0 148 -20 191 -59s59 -93 59 -141c0 -117 -69 -181 -119 -225s-81 -67 -81 -150v-25h-100v25c0 117 65 181 115 225s85 67 85 150c0 25 -8 48 -28 66s-56 34 -122 34s-97 -18 -116 -37s-27 -43 -31 -69l-100 12c5 38 19 88 59 128s103 66 188 66zM197 0h100
+v-100h-100v100z"/>
+            <glyph glyph-name="b1" unicode="&#xe0b1;"
+                   d="M450 800c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -69 -48 -127 -112 -144c-22 55 -75 94 -138 94c-20 0 -39 -5 -56 -12c-17 64 -75 112 -144 112s-127 -48 -144 -112c-17 7 -36 12 -56 12c-37 0 -71 -12 -97 -34c-33 36 -53 82 -53 134
 c0 110 90 200 200 200c23 114 129 200 250 200zM334 300h4h3c3 0 6 1 9 1c28 0 50 -22 50 -50v-1v-200c0 -28 -22 -50 -50 -50s-50 22 -50 50v200v2c0 20 15 42 34 48zM134 200h4h3c3 0 6 1 9 1c28 0 50 -22 50 -50v-1v-100c0 -28 -22 -50 -50 -50s-50 22 -50 50v100v2
-c0 20 15 42 34 48zM534 200h3h4c3 0 6 1 9 1c28 0 50 -22 50 -50v-1v-100c0 -28 -22 -50 -50 -50s-50 22 -50 50v100v2c0 20 15 42 34 48z" />
-    <glyph glyph-name="b2" unicode="&#xe0b2;" 
-d="M600 800l200 -150l-200 -150v100h-50l-153 -191l175 -206l6 -3h22v100l200 -150l-200 -150v100h-25c-35 0 -56 12 -78 38l-166 190l-153 -190c-22 -27 -43 -38 -78 -38h-100v100h100l166 206l-163 191l-3 3h-100v100h100c34 0 56 -12 78 -38l153 -178l141 178
-c22 27 43 38 78 38h50v100z" />
-    <glyph glyph-name="b3" unicode="&#xe0b3;" 
-d="M400 800c110 0 209 -47 281 -119l119 119v-300h-300l109 109c-54 55 -126 91 -209 91c-166 0 -300 -134 -300 -300s134 -300 300 -300c83 0 158 34 212 88l72 -72c-72 -72 -174 -116 -284 -116c-220 0 -400 180 -400 400s180 400 400 400z" />
-    <glyph glyph-name="b4" unicode="&#xe0b4;" 
-d="M400 800h400v-400l-166 166l-400 -400l166 -166h-400v400l166 -166l400 400z" />
-    <glyph glyph-name="b5" unicode="&#xe0b5;" horiz-adv-x="600" 
-d="M250 800l250 -300h-200v-200h200l-250 -300l-250 300h200v200h-200z" />
-    <glyph glyph-name="b6" unicode="&#xe0b6;" 
-d="M300 600v-200h200v200l300 -250l-300 -250v200h-200v-200l-300 250z" />
-    <glyph glyph-name="b7" unicode="&#xe0b7;" 
-d="M0 800c441 0 800 -359 800 -800h-200c0 333 -267 600 -600 600v200zM0 500c275 0 500 -225 500 -500h-200c0 167 -133 300 -300 300v200zM0 200c110 0 200 -90 200 -200h-200v200z" />
-    <glyph glyph-name="b8" unicode="&#xe0b8;" 
-d="M100 800c386 0 700 -314 700 -700h-100c0 332 -268 600 -600 600v100zM100 600c276 0 500 -224 500 -500h-100c0 222 -178 400 -400 400v100zM100 400c165 0 300 -135 300 -300h-100c0 111 -89 200 -200 200v100zM100 200c55 0 100 -45 100 -100s-45 -100 -100 -100
-s-100 45 -100 100s45 100 100 100z" />
-    <glyph glyph-name="b9" unicode="&#xe0b9;" 
-d="M300 800h400c55 0 100 -45 100 -100v-200h-400v150c0 28 -22 50 -50 50s-50 -22 -50 -50v-250h400v-300c0 -55 -45 -100 -100 -100h-500c-55 0 -100 45 -100 100v200h100v-150c0 -28 22 -50 50 -50s50 22 50 50v550c0 55 45 100 100 100z" />
-    <glyph glyph-name="ba" unicode="&#xe0ba;" 
-d="M75 700h225v-100h-200v-500h400v100h100v-125c0 -41 -34 -75 -75 -75h-450c-41 0 -75 34 -75 75v550c0 41 34 75 75 75zM600 700l200 -200l-200 -200v100h-200c-94 0 -173 -65 -194 -153c23 199 189 353 394 353v100z" />
-    <glyph glyph-name="bb" unicode="&#xe0bb;" 
-d="M500 700l300 -284l-300 -316v200h-100c-200 0 -348 -102 -400 -300c0 295 100 500 500 500v200z" />
-    <glyph glyph-name="bc" unicode="&#xe0bc;" 
-d="M381 791l19 9l19 -9c127 -53 253 -108 381 -160v-31c0 -166 -67 -313 -147 -419c-40 -53 -83 -97 -125 -128s-82 -53 -128 -53s-86 22 -128 53s-85 75 -125 128c-80 107 -147 253 -147 419v31c128 52 254 107 381 160zM400 100v591l-294 -122c8 -126 58 -243 122 -328
-c35 -46 73 -86 106 -110s62 -31 66 -31z" />
-    <glyph glyph-name="bd" unicode="&#xe0bd;" 
-d="M600 800h100v-800h-100v800zM400 700h100v-700h-100v700zM200 500h100v-500h-100v500zM0 300h100v-300h-100v300z" />
-    <glyph glyph-name="be" unicode="&#xe0be;" 
-d="M300 800h100v-200h200l100 -100l-100 -100h-200v-400h-100v500h-200l-100 100l100 100h200v100z" />
-    <glyph glyph-name="bf" unicode="&#xe0bf;" 
-d="M200 800h100v-600h200l-250 -200l-250 200h200v600zM400 800h200v-100h-200v100zM400 600h300v-100h-300v100zM400 400h400v-100h-400v100z" />
-    <glyph glyph-name="c0" unicode="&#xe0c0;" 
-d="M200 800h100v-600h200l-250 -200l-250 200h200v600zM400 800h400v-100h-400v100zM400 600h300v-100h-300v100zM400 400h200v-100h-200v100z" />
-    <glyph glyph-name="c1" unicode="&#xe0c1;" 
-d="M75 700h650c41 0 75 -34 75 -75v-550c0 -41 -34 -75 -75 -75h-650c-41 0 -75 34 -75 75v550c0 41 34 75 75 75zM100 600v-100h100v100h-100zM300 600v-100h400v100h-400zM100 400v-100h100v100h-100zM300 400v-100h400v100h-400zM100 200v-100h100v100h-100zM300 200
-v-100h400v100h-400z" />
-    <glyph glyph-name="c2" unicode="&#xe0c2;" 
-d="M400 800l100 -300h300l-250 -200l100 -300l-250 200l-250 -200l100 300l-250 200h300z" />
-    <glyph glyph-name="c3" unicode="&#xe0c3;" 
-d="M400 800c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM150 700c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM650 700c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM400 600c110 0 200 -90 200 -200
+c0 20 15 42 34 48zM534 200h3h4c3 0 6 1 9 1c28 0 50 -22 50 -50v-1v-100c0 -28 -22 -50 -50 -50s-50 22 -50 50v100v2c0 20 15 42 34 48z"/>
+            <glyph glyph-name="b2" unicode="&#xe0b2;"
+                   d="M600 800l200 -150l-200 -150v100h-50l-153 -191l175 -206l6 -3h22v100l200 -150l-200 -150v100h-25c-35 0 -56 12 -78 38l-166 190l-153 -190c-22 -27 -43 -38 -78 -38h-100v100h100l166 206l-163 191l-3 3h-100v100h100c34 0 56 -12 78 -38l153 -178l141 178
+c22 27 43 38 78 38h50v100z"/>
+            <glyph glyph-name="b3" unicode="&#xe0b3;"
+                   d="M400 800c110 0 209 -47 281 -119l119 119v-300h-300l109 109c-54 55 -126 91 -209 91c-166 0 -300 -134 -300 -300s134 -300 300 -300c83 0 158 34 212 88l72 -72c-72 -72 -174 -116 -284 -116c-220 0 -400 180 -400 400s180 400 400 400z"/>
+            <glyph glyph-name="b4" unicode="&#xe0b4;"
+                   d="M400 800h400v-400l-166 166l-400 -400l166 -166h-400v400l166 -166l400 400z"/>
+            <glyph glyph-name="b5" unicode="&#xe0b5;" horiz-adv-x="600"
+                   d="M250 800l250 -300h-200v-200h200l-250 -300l-250 300h200v200h-200z"/>
+            <glyph glyph-name="b6" unicode="&#xe0b6;"
+                   d="M300 600v-200h200v200l300 -250l-300 -250v200h-200v-200l-300 250z"/>
+            <glyph glyph-name="b7" unicode="&#xe0b7;"
+                   d="M0 800c441 0 800 -359 800 -800h-200c0 333 -267 600 -600 600v200zM0 500c275 0 500 -225 500 -500h-200c0 167 -133 300 -300 300v200zM0 200c110 0 200 -90 200 -200h-200v200z"/>
+            <glyph glyph-name="b8" unicode="&#xe0b8;"
+                   d="M100 800c386 0 700 -314 700 -700h-100c0 332 -268 600 -600 600v100zM100 600c276 0 500 -224 500 -500h-100c0 222 -178 400 -400 400v100zM100 400c165 0 300 -135 300 -300h-100c0 111 -89 200 -200 200v100zM100 200c55 0 100 -45 100 -100s-45 -100 -100 -100
+s-100 45 -100 100s45 100 100 100z"/>
+            <glyph glyph-name="b9" unicode="&#xe0b9;"
+                   d="M300 800h400c55 0 100 -45 100 -100v-200h-400v150c0 28 -22 50 -50 50s-50 -22 -50 -50v-250h400v-300c0 -55 -45 -100 -100 -100h-500c-55 0 -100 45 -100 100v200h100v-150c0 -28 22 -50 50 -50s50 22 50 50v550c0 55 45 100 100 100z"/>
+            <glyph glyph-name="ba" unicode="&#xe0ba;"
+                   d="M75 700h225v-100h-200v-500h400v100h100v-125c0 -41 -34 -75 -75 -75h-450c-41 0 -75 34 -75 75v550c0 41 34 75 75 75zM600 700l200 -200l-200 -200v100h-200c-94 0 -173 -65 -194 -153c23 199 189 353 394 353v100z"/>
+            <glyph glyph-name="bb" unicode="&#xe0bb;"
+                   d="M500 700l300 -284l-300 -316v200h-100c-200 0 -348 -102 -400 -300c0 295 100 500 500 500v200z"/>
+            <glyph glyph-name="bc" unicode="&#xe0bc;"
+                   d="M381 791l19 9l19 -9c127 -53 253 -108 381 -160v-31c0 -166 -67 -313 -147 -419c-40 -53 -83 -97 -125 -128s-82 -53 -128 -53s-86 22 -128 53s-85 75 -125 128c-80 107 -147 253 -147 419v31c128 52 254 107 381 160zM400 100v591l-294 -122c8 -126 58 -243 122 -328
+c35 -46 73 -86 106 -110s62 -31 66 -31z"/>
+            <glyph glyph-name="bd" unicode="&#xe0bd;"
+                   d="M600 800h100v-800h-100v800zM400 700h100v-700h-100v700zM200 500h100v-500h-100v500zM0 300h100v-300h-100v300z"/>
+            <glyph glyph-name="be" unicode="&#xe0be;"
+                   d="M300 800h100v-200h200l100 -100l-100 -100h-200v-400h-100v500h-200l-100 100l100 100h200v100z"/>
+            <glyph glyph-name="bf" unicode="&#xe0bf;"
+                   d="M200 800h100v-600h200l-250 -200l-250 200h200v600zM400 800h200v-100h-200v100zM400 600h300v-100h-300v100zM400 400h400v-100h-400v100z"/>
+            <glyph glyph-name="c0" unicode="&#xe0c0;"
+                   d="M200 800h100v-600h200l-250 -200l-250 200h200v600zM400 800h400v-100h-400v100zM400 600h300v-100h-300v100zM400 400h200v-100h-200v100z"/>
+            <glyph glyph-name="c1" unicode="&#xe0c1;"
+                   d="M75 700h650c41 0 75 -34 75 -75v-550c0 -41 -34 -75 -75 -75h-650c-41 0 -75 34 -75 75v550c0 41 34 75 75 75zM100 600v-100h100v100h-100zM300 600v-100h400v100h-400zM100 400v-100h100v100h-100zM300 400v-100h400v100h-400zM100 200v-100h100v100h-100zM300 200
+v-100h400v100h-400z"/>
+            <glyph glyph-name="c2" unicode="&#xe0c2;"
+                   d="M400 800l100 -300h300l-250 -200l100 -300l-250 200l-250 -200l100 300l-250 200h300z"/>
+            <glyph glyph-name="c3" unicode="&#xe0c3;"
+                   d="M400 800c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM150 700c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM650 700c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM400 600c110 0 200 -90 200 -200
 s-90 -200 -200 -200s-200 90 -200 200s90 200 200 200zM50 450c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM750 450c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM150 200c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50
-s22 50 50 50zM650 200c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM400 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z" />
-    <glyph glyph-name="c4" unicode="&#xe0c4;" 
-d="M34 800h632c18 0 34 -16 34 -34v-732c0 -18 -16 -34 -34 -34h-632c-18 0 -34 16 -34 34v732c0 18 16 34 34 34zM100 700v-500h500v500h-500zM350 150c-38 0 -63 -42 -44 -75s69 -33 88 0s-6 75 -44 75z" />
-    <glyph glyph-name="c5" unicode="&#xe0c5;" 
-d="M0 800h300l500 -500l-300 -300l-500 500v300zM200 700c-55 0 -100 -45 -100 -100s45 -100 100 -100s100 45 100 100s-45 100 -100 100z" />
-    <glyph glyph-name="c6" unicode="&#xe0c6;" 
-d="M0 600h200l300 -300l-200 -200l-300 300v200zM340 600h160l300 -300l-200 -200l-78 78l119 122zM150 500c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z" />
-    <glyph glyph-name="c7" unicode="&#xe0c7;" 
-d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM400 600c110 0 200 -90 200 -200s-90 -200 -200 -200s-200 90 -200 200
-s90 200 200 200zM400 500c-56 0 -100 -44 -100 -100s44 -100 100 -100s100 44 100 100s-44 100 -100 100z" />
-    <glyph glyph-name="c8" unicode="&#xe0c8;" 
-d="M0 700h559l-100 -100h-359v-500h500v159l100 100v-359h-700v700zM700 700l100 -100l-400 -400l-200 200l100 100l100 -100z" />
-    <glyph glyph-name="c9" unicode="&#xe0c9;" 
-d="M9 800h782c6 0 9 -3 9 -9v-782c0 -6 -3 -9 -9 -9h-782c-6 0 -9 3 -9 9v782c0 6 3 9 9 9zM150 722l-72 -72l100 -100l-100 -100l72 -72l172 172zM400 500v-100h300v100h-300z" />
-    <glyph glyph-name="ca" unicode="&#xe0ca;" 
-d="M0 800h800v-200h-50c0 55 -45 100 -100 100h-150v-550c0 -28 22 -50 50 -50h50v-100h-400v100h50c28 0 50 22 50 50v550h-150c-55 0 -100 -45 -100 -100h-50v200z" />
-    <glyph glyph-name="cb" unicode="&#xe0cb;" 
-d="M0 700h100v-400h-100v400zM200 700h350c21 0 39 -13 47 -31c0 0 103 -291 103 -319s-22 -50 -50 -50h-150c-28 0 -50 -25 -50 -50s39 -158 47 -184s-5 -55 -31 -63s-52 5 -66 31s-109 219 -128 238s-44 28 -72 28v400z" />
-    <glyph glyph-name="cc" unicode="&#xe0cc;" 
-d="M400 666c10 19 28 32 47 34l19 -3c26 -8 39 -37 31 -63s-47 -159 -47 -184s22 -50 50 -50h150c28 0 50 -22 50 -50s-103 -319 -103 -319c-8 -18 -26 -31 -47 -31h-350v400c28 0 53 9 72 28s114 212 128 238zM0 400h100v-400h-100v400z" />
-    <glyph glyph-name="cd" unicode="&#xe0cd;" 
-d="M200 700h300v-100h-100v-6c25 -4 50 -8 72 -16l-34 -94c-28 11 -58 16 -88 16c-139 0 -250 -111 -250 -250s111 -250 250 -250s250 111 250 250c0 31 -5 60 -16 88l91 37c14 -38 25 -81 25 -125c0 -193 -157 -350 -350 -350s-350 157 -350 350c0 176 130 323 300 347v3
-h-100v100zM700 584c0 0 -296 -348 -316 -368s-48 -20 -68 0s-20 48 0 68s384 300 384 300z" />
-    <glyph glyph-name="ce" unicode="&#xe0ce;" 
-d="M600 700l200 -150l-200 -150v100h-600v100h600v100zM200 300v-100h600v-100h-600v-100l-200 150z" />
-    <glyph glyph-name="cf" unicode="&#xe0cf;" 
-d="M300 800h100c55 0 100 -45 100 -100h100c55 0 100 -45 100 -100h-700c0 55 45 100 100 100h100c0 55 45 100 100 100zM100 500h100v-350c0 -28 22 -50 50 -50s50 22 50 50v350h100v-350c0 -28 22 -50 50 -50s50 22 50 50v350h100v-481c0 -11 -8 -19 -19 -19h-462
-c-11 0 -19 8 -19 19v481z" />
-    <glyph glyph-name="d0" unicode="&#xe0d0;" 
-d="M100 800h200v-400c0 -55 45 -100 100 -100s100 45 100 100v400h100v-400c0 -110 -90 -200 -200 -200h-50c-138 0 -250 90 -250 200v400zM0 100h700v-100h-700v100z" />
-    <glyph glyph-name="d1" unicode="&#xe0d1;" 
-d="M9 700h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v482c0 6 3 9 9 9zM609 700h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v482c0 6 3 9 9 9zM309 500h182c6 0 9 -3 9 -9v-282c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v282
-c0 6 3 9 9 9zM0 100h800v-100h-800v100z" />
-    <glyph glyph-name="d2" unicode="&#xe0d2;" 
-d="M10 700h181c6 0 9 -3 9 -9v-191h-200v191c0 6 4 9 10 9zM610 700h181c6 0 9 -3 9 -9v-191h-200v191c0 6 5 9 10 9zM310 600h181c6 0 9 -3 9 -9v-91h-200v91c0 6 4 9 10 9zM0 400h800v-100h-800v100zM0 200h200v-191c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v191zM300 200
-h200v-91c0 -6 -3 -9 -9 -9h-181c-6 0 -10 3 -10 9v91zM600 200h200v-191c0 -6 -3 -9 -9 -9h-181c-6 0 -10 3 -10 9v191z" />
-    <glyph glyph-name="d3" unicode="&#xe0d3;" 
-d="M0 700h800v-100h-800v100zM9 500h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v482c0 6 3 9 9 9zM309 500h182c6 0 9 -3 9 -9v-282c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v282c0 6 3 9 9 9zM609 500h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182
-c-6 0 -9 3 -9 9v482c0 6 3 9 9 9z" />
-    <glyph glyph-name="d4" unicode="&#xe0d4;" 
-d="M50 600h500c28 0 50 -22 50 -50v-150l100 100h100v-300h-100l-100 100v-150c0 -28 -22 -50 -50 -50h-500c-28 0 -50 22 -50 50v400c0 28 22 50 50 50z" />
-    <glyph glyph-name="d5" unicode="&#xe0d5;" 
-d="M334 800h66v-800h-66l-134 200h-200v400h200zM500 600v100c26 0 52 -4 75 -10c130 -33 225 -150 225 -290s-95 -258 -225 -291h-3c-23 -6 -47 -9 -72 -9v100c17 0 34 2 50 6c86 22 150 100 150 194s-64 172 -150 194c-16 4 -33 6 -50 6zM500 500l25 -3
-c44 -11 75 -51 75 -97s-32 -86 -75 -97l-25 -3v200z" />
-    <glyph glyph-name="d6" unicode="&#xe0d6;" horiz-adv-x="600" 
-d="M334 800h66v-800h-66l-134 200h-200v400h200zM500 500l25 -3c44 -11 75 -51 75 -97s-32 -86 -75 -97l-25 -3v200z" />
-    <glyph glyph-name="d7" unicode="&#xe0d7;" horiz-adv-x="400" 
-d="M334 800h66v-800h-66l-134 200h-200v400h200z" />
-    <glyph glyph-name="d8" unicode="&#xe0d8;" 
-d="M309 800h82c6 0 10 -4 12 -9l294 -682l3 -19v-81c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v81l3 19l294 682c2 5 6 9 12 9zM300 500v-200h100v200h-100zM300 200v-100h100v100h-100z" />
-    <glyph glyph-name="d9" unicode="&#xe0d9;" 
-d="M375 800c138 0 269 -39 378 -109l-53 -82c-93 60 -205 91 -325 91c-119 0 -229 -32 -322 -91l-53 82c109 70 237 109 375 109zM375 500c78 0 154 -23 216 -62l-53 -85c-46 30 -104 47 -163 47c-60 0 -112 -17 -159 -47l-54 85c62 40 134 62 213 62zM375 200
-c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100s45 100 100 100z" />
-    <glyph glyph-name="da" unicode="&#xe0da;" horiz-adv-x="900" 
-d="M551 800c16 0 32 0 47 -3l-97 -97v-200h200l97 97c3 -15 3 -31 3 -47c0 -138 -112 -250 -250 -250c-32 0 -62 8 -90 19l-288 -291c-20 -20 -46 -28 -72 -28s-52 8 -72 28c-39 39 -39 105 0 144l291 287c-11 28 -19 59 -19 91c0 138 112 250 250 250zM101 150
-c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z" />
-    <glyph glyph-name="db" unicode="&#xe0db;" 
-d="M141 700c84 -84 169 -167 253 -250c82 83 167 165 247 250l143 -141l-253 -253c84 -82 167 -166 253 -247l-143 -143c-81 86 -165 169 -247 253l-253 -253l-141 143c85 80 167 164 250 247c-83 84 -166 169 -250 253z" />
-    <glyph glyph-name="dc" unicode="&#xe0dc;" 
-d="M0 800h100l231 -300h38l231 300h100l-225 -300h225v-100h-300v-100h300v-100h-300v-200h-100v200h-300v100h300v100h-300v100h225z" />
-    <glyph glyph-name="dd" unicode="&#xe0dd;" horiz-adv-x="900" 
-d="M350 800c193 0 350 -157 350 -350c0 -61 -17 -119 -44 -169c4 -2 10 -6 13 -9l103 -100c16 -16 30 -49 30 -72c0 -56 -46 -102 -102 -102c-23 0 -56 14 -72 30l-100 103c-3 3 -7 9 -9 13c-50 -28 -108 -44 -169 -44c-193 0 -350 157 -350 350s157 350 350 350zM350 700
-c-139 0 -250 -111 -250 -250s111 -250 250 -250c62 0 119 23 163 60c7 11 19 25 31 31l3 3c34 43 53 97 53 156c0 139 -111 250 -250 250zM300 600h100v-100h100v-100h-100v-100h-100v100h-100v100h100v100z" />
-    <glyph glyph-name="de" unicode="&#xe0de;" horiz-adv-x="900" 
-d="M350 800c193 0 350 -157 350 -350c0 -61 -17 -119 -44 -169c4 -2 10 -6 13 -9l103 -100c16 -16 30 -49 30 -72c0 -56 -46 -102 -102 -102c-23 0 -56 14 -72 30l-100 103c-3 3 -7 9 -9 13c-50 -28 -108 -44 -169 -44c-193 0 -350 157 -350 350s157 350 350 350zM350 700
-c-139 0 -250 -111 -250 -250s111 -250 250 -250c62 0 119 23 163 60c7 11 19 25 31 31l3 3c34 43 53 97 53 156c0 139 -111 250 -250 250zM200 500h300v-100h-300v100z" />
-  </font>
-</defs></svg>
+s22 50 50 50zM650 200c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM400 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z"/>
+            <glyph glyph-name="c4" unicode="&#xe0c4;"
+                   d="M34 800h632c18 0 34 -16 34 -34v-732c0 -18 -16 -34 -34 -34h-632c-18 0 -34 16 -34 34v732c0 18 16 34 34 34zM100 700v-500h500v500h-500zM350 150c-38 0 -63 -42 -44 -75s69 -33 88 0s-6 75 -44 75z"/>
+            <glyph glyph-name="c5" unicode="&#xe0c5;"
+                   d="M0 800h300l500 -500l-300 -300l-500 500v300zM200 700c-55 0 -100 -45 -100 -100s45 -100 100 -100s100 45 100 100s-45 100 -100 100z"/>
+            <glyph glyph-name="c6" unicode="&#xe0c6;"
+                   d="M0 600h200l300 -300l-200 -200l-300 300v200zM340 600h160l300 -300l-200 -200l-78 78l119 122zM150 500c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z"/>
+            <glyph glyph-name="c7" unicode="&#xe0c7;"
+                   d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM400 600c110 0 200 -90 200 -200s-90 -200 -200 -200s-200 90 -200 200
+s90 200 200 200zM400 500c-56 0 -100 -44 -100 -100s44 -100 100 -100s100 44 100 100s-44 100 -100 100z"/>
+            <glyph glyph-name="c8" unicode="&#xe0c8;"
+                   d="M0 700h559l-100 -100h-359v-500h500v159l100 100v-359h-700v700zM700 700l100 -100l-400 -400l-200 200l100 100l100 -100z"/>
+            <glyph glyph-name="c9" unicode="&#xe0c9;"
+                   d="M9 800h782c6 0 9 -3 9 -9v-782c0 -6 -3 -9 -9 -9h-782c-6 0 -9 3 -9 9v782c0 6 3 9 9 9zM150 722l-72 -72l100 -100l-100 -100l72 -72l172 172zM400 500v-100h300v100h-300z"/>
+            <glyph glyph-name="ca" unicode="&#xe0ca;"
+                   d="M0 800h800v-200h-50c0 55 -45 100 -100 100h-150v-550c0 -28 22 -50 50 -50h50v-100h-400v100h50c28 0 50 22 50 50v550h-150c-55 0 -100 -45 -100 -100h-50v200z"/>
+            <glyph glyph-name="cb" unicode="&#xe0cb;"
+                   d="M0 700h100v-400h-100v400zM200 700h350c21 0 39 -13 47 -31c0 0 103 -291 103 -319s-22 -50 -50 -50h-150c-28 0 -50 -25 -50 -50s39 -158 47 -184s-5 -55 -31 -63s-52 5 -66 31s-109 219 -128 238s-44 28 -72 28v400z"/>
+            <glyph glyph-name="cc" unicode="&#xe0cc;"
+                   d="M400 666c10 19 28 32 47 34l19 -3c26 -8 39 -37 31 -63s-47 -159 -47 -184s22 -50 50 -50h150c28 0 50 -22 50 -50s-103 -319 -103 -319c-8 -18 -26 -31 -47 -31h-350v400c28 0 53 9 72 28s114 212 128 238zM0 400h100v-400h-100v400z"/>
+            <glyph glyph-name="cd" unicode="&#xe0cd;"
+                   d="M200 700h300v-100h-100v-6c25 -4 50 -8 72 -16l-34 -94c-28 11 -58 16 -88 16c-139 0 -250 -111 -250 -250s111 -250 250 -250s250 111 250 250c0 31 -5 60 -16 88l91 37c14 -38 25 -81 25 -125c0 -193 -157 -350 -350 -350s-350 157 -350 350c0 176 130 323 300 347v3
+h-100v100zM700 584c0 0 -296 -348 -316 -368s-48 -20 -68 0s-20 48 0 68s384 300 384 300z"/>
+            <glyph glyph-name="ce" unicode="&#xe0ce;"
+                   d="M600 700l200 -150l-200 -150v100h-600v100h600v100zM200 300v-100h600v-100h-600v-100l-200 150z"/>
+            <glyph glyph-name="cf" unicode="&#xe0cf;"
+                   d="M300 800h100c55 0 100 -45 100 -100h100c55 0 100 -45 100 -100h-700c0 55 45 100 100 100h100c0 55 45 100 100 100zM100 500h100v-350c0 -28 22 -50 50 -50s50 22 50 50v350h100v-350c0 -28 22 -50 50 -50s50 22 50 50v350h100v-481c0 -11 -8 -19 -19 -19h-462
+c-11 0 -19 8 -19 19v481z"/>
+            <glyph glyph-name="d0" unicode="&#xe0d0;"
+                   d="M100 800h200v-400c0 -55 45 -100 100 -100s100 45 100 100v400h100v-400c0 -110 -90 -200 -200 -200h-50c-138 0 -250 90 -250 200v400zM0 100h700v-100h-700v100z"/>
+            <glyph glyph-name="d1" unicode="&#xe0d1;"
+                   d="M9 700h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v482c0 6 3 9 9 9zM609 700h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v482c0 6 3 9 9 9zM309 500h182c6 0 9 -3 9 -9v-282c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v282
+c0 6 3 9 9 9zM0 100h800v-100h-800v100z"/>
+            <glyph glyph-name="d2" unicode="&#xe0d2;"
+                   d="M10 700h181c6 0 9 -3 9 -9v-191h-200v191c0 6 4 9 10 9zM610 700h181c6 0 9 -3 9 -9v-191h-200v191c0 6 5 9 10 9zM310 600h181c6 0 9 -3 9 -9v-91h-200v91c0 6 4 9 10 9zM0 400h800v-100h-800v100zM0 200h200v-191c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v191zM300 200
+h200v-91c0 -6 -3 -9 -9 -9h-181c-6 0 -10 3 -10 9v91zM600 200h200v-191c0 -6 -3 -9 -9 -9h-181c-6 0 -10 3 -10 9v191z"/>
+            <glyph glyph-name="d3" unicode="&#xe0d3;"
+                   d="M0 700h800v-100h-800v100zM9 500h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v482c0 6 3 9 9 9zM309 500h182c6 0 9 -3 9 -9v-282c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v282c0 6 3 9 9 9zM609 500h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182
+c-6 0 -9 3 -9 9v482c0 6 3 9 9 9z"/>
+            <glyph glyph-name="d4" unicode="&#xe0d4;"
+                   d="M50 600h500c28 0 50 -22 50 -50v-150l100 100h100v-300h-100l-100 100v-150c0 -28 -22 -50 -50 -50h-500c-28 0 -50 22 -50 50v400c0 28 22 50 50 50z"/>
+            <glyph glyph-name="d5" unicode="&#xe0d5;"
+                   d="M334 800h66v-800h-66l-134 200h-200v400h200zM500 600v100c26 0 52 -4 75 -10c130 -33 225 -150 225 -290s-95 -258 -225 -291h-3c-23 -6 -47 -9 -72 -9v100c17 0 34 2 50 6c86 22 150 100 150 194s-64 172 -150 194c-16 4 -33 6 -50 6zM500 500l25 -3
+c44 -11 75 -51 75 -97s-32 -86 -75 -97l-25 -3v200z"/>
+            <glyph glyph-name="d6" unicode="&#xe0d6;" horiz-adv-x="600"
+                   d="M334 800h66v-800h-66l-134 200h-200v400h200zM500 500l25 -3c44 -11 75 -51 75 -97s-32 -86 -75 -97l-25 -3v200z"/>
+            <glyph glyph-name="d7" unicode="&#xe0d7;" horiz-adv-x="400"
+                   d="M334 800h66v-800h-66l-134 200h-200v400h200z"/>
+            <glyph glyph-name="d8" unicode="&#xe0d8;"
+                   d="M309 800h82c6 0 10 -4 12 -9l294 -682l3 -19v-81c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v81l3 19l294 682c2 5 6 9 12 9zM300 500v-200h100v200h-100zM300 200v-100h100v100h-100z"/>
+            <glyph glyph-name="d9" unicode="&#xe0d9;"
+                   d="M375 800c138 0 269 -39 378 -109l-53 -82c-93 60 -205 91 -325 91c-119 0 -229 -32 -322 -91l-53 82c109 70 237 109 375 109zM375 500c78 0 154 -23 216 -62l-53 -85c-46 30 -104 47 -163 47c-60 0 -112 -17 -159 -47l-54 85c62 40 134 62 213 62zM375 200
+c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100s45 100 100 100z"/>
+            <glyph glyph-name="da" unicode="&#xe0da;" horiz-adv-x="900"
+                   d="M551 800c16 0 32 0 47 -3l-97 -97v-200h200l97 97c3 -15 3 -31 3 -47c0 -138 -112 -250 -250 -250c-32 0 -62 8 -90 19l-288 -291c-20 -20 -46 -28 -72 -28s-52 8 -72 28c-39 39 -39 105 0 144l291 287c-11 28 -19 59 -19 91c0 138 112 250 250 250zM101 150
+c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z"/>
+            <glyph glyph-name="db" unicode="&#xe0db;"
+                   d="M141 700c84 -84 169 -167 253 -250c82 83 167 165 247 250l143 -141l-253 -253c84 -82 167 -166 253 -247l-143 -143c-81 86 -165 169 -247 253l-253 -253l-141 143c85 80 167 164 250 247c-83 84 -166 169 -250 253z"/>
+            <glyph glyph-name="dc" unicode="&#xe0dc;"
+                   d="M0 800h100l231 -300h38l231 300h100l-225 -300h225v-100h-300v-100h300v-100h-300v-200h-100v200h-300v100h300v100h-300v100h225z"/>
+            <glyph glyph-name="dd" unicode="&#xe0dd;" horiz-adv-x="900"
+                   d="M350 800c193 0 350 -157 350 -350c0 -61 -17 -119 -44 -169c4 -2 10 -6 13 -9l103 -100c16 -16 30 -49 30 -72c0 -56 -46 -102 -102 -102c-23 0 -56 14 -72 30l-100 103c-3 3 -7 9 -9 13c-50 -28 -108 -44 -169 -44c-193 0 -350 157 -350 350s157 350 350 350zM350 700
+c-139 0 -250 -111 -250 -250s111 -250 250 -250c62 0 119 23 163 60c7 11 19 25 31 31l3 3c34 43 53 97 53 156c0 139 -111 250 -250 250zM300 600h100v-100h100v-100h-100v-100h-100v100h-100v100h100v100z"/>
+            <glyph glyph-name="de" unicode="&#xe0de;" horiz-adv-x="900"
+                   d="M350 800c193 0 350 -157 350 -350c0 -61 -17 -119 -44 -169c4 -2 10 -6 13 -9l103 -100c16 -16 30 -49 30 -72c0 -56 -46 -102 -102 -102c-23 0 -56 14 -72 30l-100 103c-3 3 -7 9 -9 13c-50 -28 -108 -44 -169 -44c-193 0 -350 157 -350 350s157 350 350 350zM350 700
+c-139 0 -250 -111 -250 -250s111 -250 250 -250c62 0 119 23 163 60c7 11 19 25 31 31l3 3c34 43 53 97 53 156c0 139 -111 250 -250 250zM200 500h300v-100h-300v100z"/>
+        </font>
+    </defs>
+</svg>
diff --git a/MatrixRoomUtils.Web/wwwroot/index.html b/MatrixRoomUtils.Web/wwwroot/index.html
index eeac69b..f268ac4 100644
--- a/MatrixRoomUtils.Web/wwwroot/index.html
+++ b/MatrixRoomUtils.Web/wwwroot/index.html
@@ -3,27 +3,27 @@
 
 <head>
     <meta charset="utf-8"/>
-    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
+    <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
     <title>MatrixRoomUtils.Web</title>
     <base href="/"/>
     <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet"/>
     <link href="css/app.css" rel="stylesheet"/>
-    <link rel="icon" type="image/png" href="favicon.png"/>
+    <link href="favicon.png" rel="icon" type="image/png"/>
     <link href="MatrixRoomUtils.Web.styles.css" rel="stylesheet"/>
 </head>
 
 <body>
 <div id="app">
     <svg class="loading-progress">
-        <circle r="40%" cx="50%" cy="50%"/>
-        <circle r="40%" cx="50%" cy="50%"/>
+        <circle cx="50%" cy="50%" r="40%"/>
+        <circle cx="50%" cy="50%" r="40%"/>
     </svg>
     <div class="loading-progress-text"></div>
 </div>
 
 <div id="blazor-error-ui">
     An unhandled error has occurred.
-    <a href="" class="reload">Reload</a>
+    <a class="reload" href="">Reload</a>
     <a class="dismiss">🗙</a>
 </div>
 <script>
diff --git a/MatrixRoomUtils.sln.DotSettings b/MatrixRoomUtils.sln.DotSettings
new file mode 100644
index 0000000..4ac5b79
--- /dev/null
+++ b/MatrixRoomUtils.sln.DotSettings
@@ -0,0 +1,2 @@
+<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+	<s:String x:Key="/Default/CustomTools/CustomToolsData/@EntryValue"></s:String></wpf:ResourceDictionary>
\ No newline at end of file