diff --git a/README.md b/README.md index 8ab6a01..7f5144a 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ By incorporating robust offline capabilities, CleanAspire empowers developers to version: '3.8' services: apiservice: - image: blazordevlab/cleanaspire-api:0.0.52 + image: blazordevlab/cleanaspire-api:0.0.53 environment: - ASPNETCORE_ENVIRONMENT=Development - AllowedHosts=* @@ -110,7 +110,7 @@ services: blazorweb: - image: blazordevlab/cleanaspire-webapp:0.0.52 + image: blazordevlab/cleanaspire-webapp:0.0.53 environment: - ASPNETCORE_ENVIRONMENT=Production - AllowedHosts=* diff --git a/src/CleanAspire.Api/Endpoints/ProductEndpointRegistrar.cs b/src/CleanAspire.Api/Endpoints/ProductEndpointRegistrar.cs index cfab96b..1cf9b89 100644 --- a/src/CleanAspire.Api/Endpoints/ProductEndpointRegistrar.cs +++ b/src/CleanAspire.Api/Endpoints/ProductEndpointRegistrar.cs @@ -15,7 +15,7 @@ public class ProductEndpointRegistrar : IEndpointRegistrar { public void RegisterRoutes(IEndpointRouteBuilder routes) { - var group = routes.MapGroup("/products").WithTags("products").AllowAnonymous(); + var group = routes.MapGroup("/products").WithTags("products").RequireAuthorization(); // Get all products group.MapGet("/", async ([FromServices] IMediator mediator) => diff --git a/src/CleanAspire.ClientApp/DependencyInjection.cs b/src/CleanAspire.ClientApp/DependencyInjection.cs index c01e3fe..bbdab52 100644 --- a/src/CleanAspire.ClientApp/DependencyInjection.cs +++ b/src/CleanAspire.ClientApp/DependencyInjection.cs @@ -5,12 +5,25 @@ using CleanAspire.ClientApp.Services.Interfaces; using CleanAspire.ClientApp.Services.UserPreferences; using CleanAspire.ClientApp.Services; +using CleanAspire.ClientApp.Configurations; +using CleanAspire.ClientApp.Services.Identity; +using CleanAspire.ClientApp.Services.JsInterop; +using CleanAspire.ClientApp.Services.Proxies; +using CleanAspire.Api.Client; +using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.Kiota.Abstractions.Authentication; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using Microsoft.Kiota.Serialization.Form; +using Microsoft.Kiota.Serialization.Json; +using Microsoft.Kiota.Serialization.Multipart; +using Microsoft.Kiota.Serialization.Text; namespace CleanAspire.ClientApp; public static class DependencyInjection { - public static void TryAddScopedMudBlazor(this IServiceCollection services, IConfiguration config) + public static void TryAddMudBlazor(this IServiceCollection services, IConfiguration config) { #region register MudBlazor.Services services.AddMudServices(config => @@ -43,39 +56,89 @@ public static void TryAddScopedMudBlazor(this IServiceCollection services, IConf services.AddScoped(); #endregion } - public static void TryAddMudBlazor(this IServiceCollection services, IConfiguration config) + + + public static void AddCoreServices(this IServiceCollection services, IConfiguration configuration) { - #region register MudBlazor.Services - services.AddMudServices(config => - { - MudGlobal.InputDefaults.ShrinkLabel = true; - config.SnackbarConfiguration.PositionClass = Defaults.Classes.Position.BottomCenter; - config.SnackbarConfiguration.NewestOnTop = false; - config.SnackbarConfiguration.ShowCloseIcon = true; - config.SnackbarConfiguration.VisibleStateDuration = 3000; - config.SnackbarConfiguration.HideTransitionDuration = 500; - config.SnackbarConfiguration.ShowTransitionDuration = 500; - config.SnackbarConfiguration.SnackbarVariant = Variant.Filled; + // Cookie and Authentication Handlers + services.AddTransient(); + services.AddTransient(); - // we're currently planning on deprecating `PreventDuplicates`, at least to the end dev. however, - // we may end up wanting to instead set it as internal because the docs project relies on it - // to ensure that the Snackbar always allows duplicates. disabling the warning for now because - // the project is set to treat warnings as errors. -#pragma warning disable 0618 - config.SnackbarConfiguration.PreventDuplicates = false; -#pragma warning restore 0618 + // Singleton Services + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + + // Configuration + var clientAppSettings = configuration.GetSection(ClientAppSettings.KEY).Get(); + services.AddSingleton(clientAppSettings!); + + // MudBlazor Integration + services.TryAddMudBlazor(configuration); + } + + public static void AddHttpClients(this IServiceCollection services, IConfiguration configuration) + { + // HttpClient Registration + services.AddHttpClient("apiservice", (sp, options) => + { + var settings = sp.GetRequiredService(); + options.BaseAddress = new Uri(settings.ServiceBaseUrl); + }).AddHttpMessageHandler(); + + services.AddHttpClient("Webpushr", client => + { + client.BaseAddress = new Uri("https://api.webpushr.com"); + }).AddHttpMessageHandler(); + + // ApiClient + services.AddScoped(sp => + { + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + + var settings = sp.GetRequiredService(); + var httpClientFactory = sp.GetRequiredService(); + var httpClient = httpClientFactory.CreateClient("apiservice"); + var authProvider = new AnonymousAuthenticationProvider(); + var requestAdapter = new HttpClientRequestAdapter(authProvider, httpClient: httpClient); + var apiClient = new ApiClient(requestAdapter); + + if (!string.IsNullOrEmpty(settings.ServiceBaseUrl)) + { + requestAdapter.BaseUrl = settings.ServiceBaseUrl; + } + + return apiClient; }); - services.AddMudPopoverService(); - services.AddMudBlazorSnackbar(); - services.AddMudBlazorDialog(); - services.AddMudLocalization(); - services.AddBlazoredLocalStorageAsSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddScoped(); - #endregion + + // ApiClient Service + services.AddScoped(); } + public static void AddAuthenticationAndLocalization(this IServiceCollection services, IConfiguration configuration) + { + // Authentication and Authorization + services.AddAuthorizationCore(); + services.AddCascadingAuthenticationState(); + services.AddOidcAuthentication(options => + { + configuration.Bind("Local", options.ProviderOptions); + }); + services.AddScoped(); + services.AddScoped(sp => (ISignInManagement)sp.GetRequiredService()); + + // Localization + services.AddLocalization(options => options.ResourcesPath = "Resources"); + } } diff --git a/src/CleanAspire.ClientApp/Program.cs b/src/CleanAspire.ClientApp/Program.cs index c281006..0c75905 100644 --- a/src/CleanAspire.ClientApp/Program.cs +++ b/src/CleanAspire.ClientApp/Program.cs @@ -22,73 +22,9 @@ //builder.RootComponents.Add("head::after"); // register the cookie handler -builder.Services.AddTransient(); -builder.Services.AddTransient(); -builder.Services.AddSingleton(); -builder.Services.AddSingleton(); -builder.Services.AddSingleton(); -builder.Services.AddSingleton(); -builder.Services.AddSingleton(); -builder.Services.AddSingleton(); - -var clientAppSettings = builder.Configuration.GetSection(ClientAppSettings.KEY).Get(); -builder.Services.AddSingleton(clientAppSettings!); - -builder.Services.TryAddMudBlazor(builder.Configuration); - -var httpClientBuilder = builder.Services.AddHttpClient("apiservice", (sp, options) => -{ - var settings = sp.GetRequiredService(); - options.BaseAddress = new Uri(settings.ServiceBaseUrl); - -}).AddHttpMessageHandler(); - -builder.Services.AddSingleton(sp => -{ - ApiClientBuilder.RegisterDefaultSerializer(); - ApiClientBuilder.RegisterDefaultSerializer(); - ApiClientBuilder.RegisterDefaultSerializer(); - ApiClientBuilder.RegisterDefaultSerializer(); - ApiClientBuilder.RegisterDefaultDeserializer(); - ApiClientBuilder.RegisterDefaultDeserializer(); - ApiClientBuilder.RegisterDefaultDeserializer(); - var settings = sp.GetRequiredService(); - var httpClientFactory = sp.GetRequiredService(); - var httpClient = httpClientFactory.CreateClient("apiservice"); - var authProvider = new AnonymousAuthenticationProvider(); - var requestAdapter = new HttpClientRequestAdapter(authProvider, httpClient: httpClient); - var apiClient = new ApiClient(requestAdapter); - if (!string.IsNullOrEmpty(settings.ServiceBaseUrl)) - { - requestAdapter.BaseUrl = settings.ServiceBaseUrl; - } - return apiClient; - -}); -builder.Services.AddHttpClient("Webpushr", client => -{ - client.BaseAddress = new Uri("https://api.webpushr.com"); -}).AddHttpMessageHandler(); -builder.Services.AddSingleton(); - -builder.Services.AddSingleton(); -builder.Services.AddAuthorizationCore(); -builder.Services.AddCascadingAuthenticationState(); -builder.Services.AddOidcAuthentication(options => -{ - // Configure your authentication provider options here. - // For more information, see https://aka.ms/blazor-standalone-auth - builder.Configuration.Bind("Local", options.ProviderOptions); -}); -// register the custom state provider -builder.Services.AddSingleton(); - -// register the account management interface -builder.Services.AddSingleton( - sp => (ISignInManagement)sp.GetRequiredService()); - - -builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); +builder.Services.AddCoreServices(builder.Configuration); +builder.Services.AddHttpClients(builder.Configuration); +builder.Services.AddAuthenticationAndLocalization(builder.Configuration); var app = builder.Build(); diff --git a/src/CleanAspire.ClientApp/wwwroot/appsettings.Development.json b/src/CleanAspire.ClientApp/wwwroot/appsettings.Development.json index 327db12..2b580a1 100644 --- a/src/CleanAspire.ClientApp/wwwroot/appsettings.Development.json +++ b/src/CleanAspire.ClientApp/wwwroot/appsettings.Development.json @@ -7,7 +7,7 @@ }, "ClientAppSettings": { "AppName": "Blazor Aspire", - "Version": "v0.0.52", + "Version": "v0.0.53", "ServiceBaseUrl": "https://localhost:7341" } } diff --git a/src/CleanAspire.ClientApp/wwwroot/appsettings.json b/src/CleanAspire.ClientApp/wwwroot/appsettings.json index b5836ee..5ea1611 100644 --- a/src/CleanAspire.ClientApp/wwwroot/appsettings.json +++ b/src/CleanAspire.ClientApp/wwwroot/appsettings.json @@ -7,7 +7,7 @@ }, "ClientAppSettings": { "AppName": "Blazor Aspire", - "Version": "v0.0.52", + "Version": "v0.0.53", "ServiceBaseUrl": "https://apiservice.blazorserver.com" } } diff --git a/src/CleanAspire.WebApp/Program.cs b/src/CleanAspire.WebApp/Program.cs index b2808eb..8017af8 100644 --- a/src/CleanAspire.WebApp/Program.cs +++ b/src/CleanAspire.WebApp/Program.cs @@ -2,103 +2,21 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using CleanAspire.Api.Client; -using CleanAspire.ClientApp.Configurations; -using CleanAspire.ClientApp.Services; -using CleanAspire.ClientApp.Services.Identity; -using CleanAspire.ClientApp.Services.JsInterop; -using CleanAspire.ClientApp.Services.Proxies; -using Microsoft.AspNetCore.Components.Authorization; -using Microsoft.Kiota.Abstractions; -using Microsoft.Kiota.Abstractions.Authentication; -using Microsoft.Kiota.Http.HttpClientLibrary; -using Microsoft.Kiota.Serialization.Form; -using Microsoft.Kiota.Serialization.Json; -using Microsoft.Kiota.Serialization.Multipart; -using Microsoft.Kiota.Serialization.Text; using CleanAspire.ClientApp; var builder = WebApplication.CreateBuilder(args); builder.AddServiceDefaults(); - - // Add services to the container. builder.Services.AddRazorComponents() .AddInteractiveServerComponents() .AddInteractiveWebAssemblyComponents(); - -// register the cookie handler -builder.Services.AddTransient(); -builder.Services.AddTransient(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); - -var clientAppSettings = builder.Configuration.GetSection(ClientAppSettings.KEY).Get(); -builder.Services.AddSingleton(clientAppSettings!); - -builder.Services.TryAddScopedMudBlazor(builder.Configuration); - -var httpClientBuilder = builder.Services.AddHttpClient("apiservice", (sp, options) => -{ - var settings = sp.GetRequiredService(); - options.BaseAddress = new Uri(settings.ServiceBaseUrl); - -}).AddHttpMessageHandler(); - -builder.Services.AddScoped(sp => -{ - ApiClientBuilder.RegisterDefaultSerializer(); - ApiClientBuilder.RegisterDefaultSerializer(); - ApiClientBuilder.RegisterDefaultSerializer(); - ApiClientBuilder.RegisterDefaultSerializer(); - ApiClientBuilder.RegisterDefaultDeserializer(); - ApiClientBuilder.RegisterDefaultDeserializer(); - ApiClientBuilder.RegisterDefaultDeserializer(); - var settings = sp.GetRequiredService(); - var httpClientFactory = sp.GetRequiredService(); - var httpClient = httpClientFactory.CreateClient("apiservice"); - var authProvider = new AnonymousAuthenticationProvider(); - var requestAdapter = new HttpClientRequestAdapter(authProvider, httpClient: httpClient); - var apiClient = new ApiClient(requestAdapter); - if (!string.IsNullOrEmpty(settings.ServiceBaseUrl)) - { - requestAdapter.BaseUrl = settings.ServiceBaseUrl; - } - return apiClient; - -}); -builder.Services.AddHttpClient("Webpushr", client => -{ - client.BaseAddress = new Uri("https://api.webpushr.com"); -}).AddHttpMessageHandler(); -builder.Services.AddScoped(); - -builder.Services.AddScoped(); -builder.Services.AddAuthorizationCore(); -builder.Services.AddCascadingAuthenticationState(); -builder.Services.AddOidcAuthentication(options => -{ - // Configure your authentication provider options here. - // For more information, see https://aka.ms/blazor-standalone-auth - builder.Configuration.Bind("Local", options.ProviderOptions); -}); -// register the custom state provider -builder.Services.AddScoped(); - -// register the account management interface -builder.Services.AddScoped( - sp => (ISignInManagement)sp.GetRequiredService()); - - -builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); +builder.Services.AddCoreServices(builder.Configuration); +builder.Services.AddHttpClients(builder.Configuration); +builder.Services.AddAuthenticationAndLocalization(builder.Configuration); var app = builder.Build(); diff --git a/src/CleanAspire.WebApp/appsettings.Development.json b/src/CleanAspire.WebApp/appsettings.Development.json index 327db12..2b580a1 100644 --- a/src/CleanAspire.WebApp/appsettings.Development.json +++ b/src/CleanAspire.WebApp/appsettings.Development.json @@ -7,7 +7,7 @@ }, "ClientAppSettings": { "AppName": "Blazor Aspire", - "Version": "v0.0.52", + "Version": "v0.0.53", "ServiceBaseUrl": "https://localhost:7341" } } diff --git a/src/CleanAspire.WebApp/appsettings.json b/src/CleanAspire.WebApp/appsettings.json index 8552084..39a0a8d 100644 --- a/src/CleanAspire.WebApp/appsettings.json +++ b/src/CleanAspire.WebApp/appsettings.json @@ -8,7 +8,7 @@ "AllowedHosts": "*", "ClientAppSettings": { "AppName": "Blazor Aspire", - "Version": "v0.0.52", + "Version": "v0.0.53", "ServiceBaseUrl": "https://apiservice.blazorserver.com" } } diff --git a/src/CleanAspire.WebApp/wwwroot/app.css b/src/CleanAspire.WebApp/wwwroot/app.css index 771f127..102501d 100644 --- a/src/CleanAspire.WebApp/wwwroot/app.css +++ b/src/CleanAspire.WebApp/wwwroot/app.css @@ -1,20 +1,247 @@ +.mud-main-content { + height: 100%; + min-height: 100vh; + display: flex; +} + +.mud-chip { + font-size: var(--mud-typography-default-size); +} + + .mud-chip.mud-chip-size-small { + font-size: var(--mud-typography-body1-size); + } + +.mud-tabs { + background-color: var(--mud-palette-surface); +} + +.mud-input-control > .mud-input-control-input-container > .mud-input-label-inputcontrol { + font-size: var(--mud-typography-subtitle1-size); +} + +.mud-input > input.mud-input-root, div.mud-input-slot.mud-input-root { + font-size: var(--mud-typography-default-size) !important; +} + +.mud-input > textarea.mud-input-root { + font-size: var(--mud-typography-default-size) !important; +} + +.mud-simple-table table * tr > td, .mud-simple-table table * tr th { + font-size: var(--mud-typography-default-size) !important; +} + +.mud-expand-panel .mud-expand-panel-header { + font-size: var(--mud-typography-default-size) !important; +} + +.mud-button-year { + font-size: var(--mud-typography-default-size) !important; +} + +.mud-table-cell { + font-size: var(--mud-typography-default-size) !important; +} + + +.mud-typography-subtitle2 { + font-size: var(--mud-typography-subtitle2-size); + color: var(--mud-palette-text-secondary); +} + +.mud-typography-body1 { + font-size: var(--mud-typography-body1-size); +} + +.mud-typography-body2 { + font-size: var(--mud-typography-body2-size); + color: var(--mud-palette-text-secondary); +} + +.mud-button-outlined-size-small { + font-size: var(--mud-typography-body2-size); +} + +.mud-grid.readonly-grid > .mud-grid-item { + border-bottom: 1px solid var(--mud-palette-table-lines); + padding-bottom: 2px; +} + +.mud-nav-link { + white-space: normal !important; +} + +.user-button { + text-transform: none; + background: rgba(var(--mud-palette-primary-rgb), 0.1) +} + +.mud-list-item-icon { + min-width: none !important; +} + +.side-menu .mud-chip.mud-chip-size-small { + font-size: 0.625rem; + height: 1.125rem; +} + +.appbar-special-menu +.mud-list-item { + border-radius: 6px; + margin: 4px 0; +} + +.appbar-special-menu +.mud-list-subheader { + font-weight: 700; + font-size: 1rem; + color: #8898aa; +} -h1:focus { - outline: none; +.appbar-special-menu +.mud-typography-body1 { + font-weight: 600; } -.valid.modified:not([type=checkbox]) { - outline: 1px solid #26b050; +.appbar-special-menu +.mud-typography-body2 { + font-weight: 600; + color: #8898aa; } -.invalid { - outline: 1px solid #e50000; +.appbar-special-menu +.mud-list-item-disabled +.mud-typography-body2 { + font-weight: 600; + color: rgba(136, 152, 170, 0.6); } -.validation-message { - color: #e50000; +.layout-menu-shadow { + box-shadow: 0 30px 60px rgba(0,0,0,0.12) !important; } +.mud-table.mud-data-grid.mud-xs-table.mud-table-dense.mud-table-hover.mud-elevation-1 .mud-toolbar { + height: auto !important; + padding: 1rem +} + + +.mud-table.mud-data-grid.mud-xs-table.mud-table-dense.mud-table-hover.mud-elevation-1 .mud-toolbar-gutters { + height: auto !important; + padding: 1rem +} + +.mud-table.mud-data-grid.mud-xs-table.mud-table-dense.mud-table-hover.mud-elevation-1 .mud-table-toolbar { + height: auto !important; + padding: 1rem +} + +.mud-table.mud-data-grid.mud-xs-table.mud-table-dense.mud-table-hover.mud-elevation-1 .mud-table-pagination-toolbar { + height: auto !important; + padding: 0rem !important; +} + +.network-status-indicator { + width: 43px; + height: 43px; + display: flex; + justify-content: center; + align-items: center; + margin: 0 auto; /* Center horizontally if needed */ + box-sizing: border-box; +} + +.avatar-container { + position: relative; + width: 35px; /* Fixed container width, same as avatar */ + height: 35px; /* Fixed container height, same as avatar */ +} + +/* Red rotating border (common style) */ +.rotating-border { + position: absolute; + top: -4px; + left: -4px; + width: 43px; + height: 43px; + border: 3px solid transparent; /* Default transparent */ + border-radius: 50%; + animation: spin 2s linear infinite; /* Rotating animation */ + z-index: 1; + box-sizing: border-box; +} + + /* Red border in dark mode */ + .rotating-border.dark-mode { + border-top: 3px solid rgba(255, 0, 0, 0.8); /* Dark red border */ + box-shadow: 0 0 8px rgba(255, 0, 0, 0.6), 0 0 12px rgba(255, 50, 50, 0.4); /* Enhanced shadow */ + } + + /* Red border in light mode */ + .rotating-border.light-mode { + border-top: 3px solid rgba(255, 50, 50, 0.8); /* Light red border */ + box-shadow: 0 0 6px rgba(255, 50, 50, 0.5), 0 0 10px rgba(255, 100, 100, 0.3); /* Soft shadow */ + } + +/* Dynamic green border (common style) */ +.online-border { + position: absolute; + top: -4px; + left: -4px; + width: 43px; + height: 43px; + border-radius: 50%; + animation: green-pulse 2s infinite; /* Breathing animation */ + z-index: 1; + box-sizing: border-box; +} + + /* Green border in dark mode */ + .online-border.dark-mode { + border: 3px solid rgba(0, 128, 0, 1); /* Dark green border */ + box-shadow: 0 0 8px rgba(0, 128, 0, 0.6), 0 0 12px rgba(0, 255, 0, 0.4); + } + + /* Green border in light mode */ + .online-border.light-mode { + border: 3px solid rgba(0, 200, 0, 1); /* Light green border */ + box-shadow: 0 0 6px rgba(0, 200, 0, 0.5), 0 0 10px rgba(0, 255, 0, 0.3); + } +/* Breathing animation */ +@keyframes green-pulse { + 0% { + box-shadow: 0 0 8px rgba(0, 128, 0, 0.6), 0 0 12px rgba(0, 255, 0, 0.4); + transform: scale(1); + } + + 50% { + box-shadow: 0 0 10px rgba(0, 128, 0, 0.8), 0 0 14px rgba(0, 255, 0, 0.5); + transform: scale(1.03); /* Reduce scaling amplitude */ + } + + 100% { + box-shadow: 0 0 8px rgba(0, 128, 0, 0.6), 0 0 12px rgba(0, 255, 0, 0.4); + transform: scale(1); + } +} + +MudAvatar { + position: relative; + z-index: 2; /* Ensure avatar is above the border */ +} + +@keyframes spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + + .blazor-error-boundary { background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; padding: 1rem 1rem 1rem 3.7rem; @@ -24,16 +251,3 @@ h1:focus { .blazor-error-boundary::after { content: "An error has occurred." } - -.darker-border-checkbox.form-check-input { - border-color: #929292; -} - -.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder { - color: var(--bs-secondary-color); - text-align: end; -} - -.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder { - text-align: start; -} \ No newline at end of file