From 1d55ab23f0740c3f8bd3f03120e8adf9c1132592 Mon Sep 17 00:00:00 2001 From: Mia Rose Winter <44292375+miawinter98@users.noreply.github.com> Date: Tue, 18 Jun 2024 09:09:47 +0200 Subject: [PATCH] Implemented client side article editor (#6) * started implementing article API, missing lots of tests to validate feature * made tests more pretty * re-structured tests * refactored dto contracts * tested and fixed updating categories * added permission tests, fixed bug in Permissions system * added data validation tests for update article * refactored repository interface * Added ArticleView dto, fixed bug in requesting articles over repository * updated dependencies * optimized program.cs, added repo service * Removed all interactivity from ArticleEditor, merged files * added vite, tailwind working, dev server is not, js is not yet * added fontsource for font management using vite's bundling * moved vite output to wwwroot/dist reorganized stuff that will never need processing or needs to be at site root * fixed heading font weight not being 700 anymore * implemented react in ArticleEditor * added article status steps to react component noticed I need to figure out client side localization * fixed vite dev server thingies, tailwind and react refresh works now * added article form skeletton to react * more editor implementations * minor typescript fixes * implemented proper editor functions * added all missing toolbar buttons * fixed error, made open article work * improved article editor structure * implemented article editor taking id from the url * Implemented categories endpoint * implemented categories in article editor * fixed minor TS issues * implemented localization in article editor * completed localization * implemented loading selected categories * minor code improvements and maybe a regex fix * fixed bug with not getting unpublished articles * implemented form state * fixed validation issues * implemented saving (missing creation) * fixed minor bug with status display * organized models * added live markdown preview (incomplete) * fixed issues in article create api endpoint * improved article saving, implemented creating * fixed publish date not being set correctly when creating article * fixed slugs once more * added run config for production (without vite dev) * removed unused code * updated dockerfile to build Assets * fixed slug generation * updated tests to validate new slug generator * savsdSACAVSD * fixed validation issues and tests --- Wave.Tests/Data/ApplicationDbContextTest.cs | 26 +- Wave.Tests/Data/ApplicationRepositoryTest.cs | 353 ++++++++++++++++ Wave.Tests/Data/ArticleTest.cs | 14 +- Wave.Tests/TestUtilities/DbContextTest.cs | 31 ++ Wave.Tests/Wave.Tests.csproj | 1 + Wave/Assets/React/ArticleEditor.tsx | 382 ++++++++++++++++++ Wave/Assets/React/Forms.tsx | 22 + Wave/{wwwroot/app.css => Assets/css/main.css} | 87 ++-- Wave/Assets/main.tsx | 160 ++++++++ Wave/Assets/model/Models.ts | 40 ++ .../public}/android-icon-144x144.png | Bin .../public}/android-icon-192x192.png | Bin .../public}/android-icon-36x36.png | Bin .../public}/android-icon-48x48.png | Bin .../public}/android-icon-72x72.png | Bin .../public}/android-icon-96x96.png | Bin .../public}/apple-icon-114x114.png | Bin .../public}/apple-icon-120x120.png | Bin .../public}/apple-icon-144x144.png | Bin .../public}/apple-icon-152x152.png | Bin .../public}/apple-icon-180x180.png | Bin .../public}/apple-icon-57x57.png | Bin .../public}/apple-icon-60x60.png | Bin .../public}/apple-icon-72x72.png | Bin .../public}/apple-icon-76x76.png | Bin .../public}/apple-icon-precomposed.png | Bin .../{wwwroot => Assets/public}/apple-icon.png | Bin .../public}/browserconfig.xml | 0 .../public}/favicon-16x16.png | Bin .../public}/favicon-32x32.png | Bin .../public}/favicon-96x96.png | Bin Wave/{wwwroot => Assets/public}/favicon.ico | Bin .../public}/img/default_avatar.jpg | Bin Wave/{wwwroot => Assets/public}/img/logo.jxl | Bin Wave/{wwwroot => Assets/public}/img/logo.png | Bin Wave/{wwwroot => Assets/public}/img/logo.svg | 0 Wave/{wwwroot => Assets/public}/img/logo.webp | Bin Wave/{wwwroot => Assets/public}/manifest.json | 0 .../public}/ms-icon-144x144.png | Bin .../public}/ms-icon-150x150.png | Bin .../public}/ms-icon-310x310.png | Bin .../public}/ms-icon-70x70.png | Bin Wave/Assets/utilities/md_functions.ts | 63 +++ Wave/Assets/vite-env.d.ts | 5 + Wave/Components/App.razor | 90 +++-- Wave/Components/LogoPartial.razor | 8 +- Wave/Components/Pages/ArticleEditor.razor | 88 ++-- .../Pages/Partials/ArticleEditorPartial.razor | 314 -------------- Wave/Controllers/ArticleController.cs | 107 +++++ Wave/Controllers/UserController.cs | 4 +- Wave/Data/ApplicationDbContext.cs | 72 ++++ Wave/Data/ApplicationRepository.cs | 116 ++++++ Wave/Data/Article.cs | 24 +- Wave/Data/Transactional/ArticleDto.cs | 81 ++++ Wave/Data/Transactional/ArticleView.cs | 30 ++ Wave/Dockerfile | 14 + Wave/Program.cs | 27 +- Wave/Utilities/Permissions.cs | 25 +- Wave/Wave.csproj | 27 +- Wave/appsettings.Development.json | 1 + Wave/package-lock.json | Bin 205162 -> 220275 bytes Wave/package.json | 52 ++- Wave/postcss.config.js | 9 - ...{tailwind.config.js => tailwind.config.ts} | 7 +- Wave/tsconfig.json | 25 ++ Wave/tsconfig.node.json | 12 + Wave/vite.config.ts | 52 +++ Wave/wwwroot/css/main.css | 58 --- Wave/wwwroot/css/main.min.css | 3 - .../noto-sans-display-v26-latin-regular.woff2 | Bin 13048 -> 0 bytes .../fonts/nunito-sans-v15-latin-700.woff2 | Bin 13800 -> 0 bytes docker-compose.override.yml | 2 +- launchSettings.json | 61 ++- 73 files changed, 1903 insertions(+), 590 deletions(-) create mode 100644 Wave.Tests/Data/ApplicationRepositoryTest.cs create mode 100644 Wave.Tests/TestUtilities/DbContextTest.cs create mode 100644 Wave/Assets/React/ArticleEditor.tsx create mode 100644 Wave/Assets/React/Forms.tsx rename Wave/{wwwroot/app.css => Assets/css/main.css} (57%) create mode 100644 Wave/Assets/main.tsx create mode 100644 Wave/Assets/model/Models.ts rename Wave/{wwwroot => Assets/public}/android-icon-144x144.png (100%) rename Wave/{wwwroot => Assets/public}/android-icon-192x192.png (100%) rename Wave/{wwwroot => Assets/public}/android-icon-36x36.png (100%) rename Wave/{wwwroot => Assets/public}/android-icon-48x48.png (100%) rename Wave/{wwwroot => Assets/public}/android-icon-72x72.png (100%) rename Wave/{wwwroot => Assets/public}/android-icon-96x96.png (100%) rename Wave/{wwwroot => Assets/public}/apple-icon-114x114.png (100%) rename Wave/{wwwroot => Assets/public}/apple-icon-120x120.png (100%) rename Wave/{wwwroot => Assets/public}/apple-icon-144x144.png (100%) rename Wave/{wwwroot => Assets/public}/apple-icon-152x152.png (100%) rename Wave/{wwwroot => Assets/public}/apple-icon-180x180.png (100%) rename Wave/{wwwroot => Assets/public}/apple-icon-57x57.png (100%) rename Wave/{wwwroot => Assets/public}/apple-icon-60x60.png (100%) rename Wave/{wwwroot => Assets/public}/apple-icon-72x72.png (100%) rename Wave/{wwwroot => Assets/public}/apple-icon-76x76.png (100%) rename Wave/{wwwroot => Assets/public}/apple-icon-precomposed.png (100%) rename Wave/{wwwroot => Assets/public}/apple-icon.png (100%) rename Wave/{wwwroot => Assets/public}/browserconfig.xml (100%) rename Wave/{wwwroot => Assets/public}/favicon-16x16.png (100%) rename Wave/{wwwroot => Assets/public}/favicon-32x32.png (100%) rename Wave/{wwwroot => Assets/public}/favicon-96x96.png (100%) rename Wave/{wwwroot => Assets/public}/favicon.ico (100%) rename Wave/{wwwroot => Assets/public}/img/default_avatar.jpg (100%) rename Wave/{wwwroot => Assets/public}/img/logo.jxl (100%) rename Wave/{wwwroot => Assets/public}/img/logo.png (100%) rename Wave/{wwwroot => Assets/public}/img/logo.svg (100%) rename Wave/{wwwroot => Assets/public}/img/logo.webp (100%) rename Wave/{wwwroot => Assets/public}/manifest.json (100%) rename Wave/{wwwroot => Assets/public}/ms-icon-144x144.png (100%) rename Wave/{wwwroot => Assets/public}/ms-icon-150x150.png (100%) rename Wave/{wwwroot => Assets/public}/ms-icon-310x310.png (100%) rename Wave/{wwwroot => Assets/public}/ms-icon-70x70.png (100%) create mode 100644 Wave/Assets/utilities/md_functions.ts create mode 100644 Wave/Assets/vite-env.d.ts delete mode 100644 Wave/Components/Pages/Partials/ArticleEditorPartial.razor create mode 100644 Wave/Controllers/ArticleController.cs create mode 100644 Wave/Data/ApplicationRepository.cs create mode 100644 Wave/Data/Transactional/ArticleDto.cs create mode 100644 Wave/Data/Transactional/ArticleView.cs delete mode 100644 Wave/postcss.config.js rename Wave/{tailwind.config.js => tailwind.config.ts} (97%) create mode 100644 Wave/tsconfig.json create mode 100644 Wave/tsconfig.node.json create mode 100644 Wave/vite.config.ts delete mode 100644 Wave/wwwroot/css/main.css delete mode 100644 Wave/wwwroot/css/main.min.css delete mode 100644 Wave/wwwroot/fonts/noto-sans-display-v26-latin-regular.woff2 delete mode 100644 Wave/wwwroot/fonts/nunito-sans-v15-latin-700.woff2 diff --git a/Wave.Tests/Data/ApplicationDbContextTest.cs b/Wave.Tests/Data/ApplicationDbContextTest.cs index 14755be..6833941 100644 --- a/Wave.Tests/Data/ApplicationDbContextTest.cs +++ b/Wave.Tests/Data/ApplicationDbContextTest.cs @@ -1,34 +1,12 @@ using Microsoft.EntityFrameworkCore; -using Testcontainers.PostgreSql; using Wave.Data; +using Wave.Tests.TestUtilities; namespace Wave.Tests.Data; [TestFixture, FixtureLifeCycle(LifeCycle.InstancePerTestCase)] [TestOf(typeof(ApplicationDbContext))] -public class ApplicationDbContextTest { - private PostgreSqlContainer PostgresContainer { get; } = new PostgreSqlBuilder().WithImage("postgres:16.1-alpine").Build(); - - [SetUp] - public async Task SetUp() { - await PostgresContainer.StartAsync(); - } - - [TearDown] - public async Task TearDown() { - await PostgresContainer.DisposeAsync(); - } - - private ApplicationDbContext GetContext() { - return new ApplicationDbContext( - new DbContextOptionsBuilder() - .UseNpgsql(PostgresContainer.GetConnectionString()) - .EnableSensitiveDataLogging() - .EnableDetailedErrors() - .EnableThreadSafetyChecks() - .Options); - } - +public class ApplicationDbContextTest : DbContextTest { [Test] public async Task Migration() { await using var context = GetContext(); diff --git a/Wave.Tests/Data/ApplicationRepositoryTest.cs b/Wave.Tests/Data/ApplicationRepositoryTest.cs new file mode 100644 index 0000000..c83ff60 --- /dev/null +++ b/Wave.Tests/Data/ApplicationRepositoryTest.cs @@ -0,0 +1,353 @@ +using System.Security.Claims; +using System.Text; +using Microsoft.EntityFrameworkCore; +using Wave.Data; +using Wave.Data.Transactional; +using Wave.Tests.TestUtilities; + +// ReSharper disable InconsistentNaming + +namespace Wave.Tests.Data; + +public abstract class ApplicationRepositoryTests : DbContextTest { + protected ApplicationRepository Repository { get; set; } = null!; + + protected const string TestUserName = "testuser@example.com"; + protected const string AuthorUserName = "author@example.com"; + protected const string ReviewerUserName = "reviewer@example.com"; + + protected ClaimsPrincipal AnonymousPrincipal { get; set; } = null!; + protected ClaimsPrincipal UserPrincipal { get; set; } = null!; + protected ClaimsPrincipal AuthorPrincipal { get; set; } = null!; + protected ClaimsPrincipal ReviewerPrincipal { get; set; } = null!; + + protected Guid PrimaryCategoryId { get; set; } + protected Guid SecondaryCategoryId { get; set; } + + protected virtual ValueTask InitializeTestEntities(ApplicationDbContext context) { + return ValueTask.CompletedTask; + } + + protected override async ValueTask AndThenSetUp() { + Repository = new ApplicationRepository(new MockDbContextFactory(GetContext)); + + List categories = [ + new Category { + Name = "Primary Category", + Color = CategoryColors.Primary + }, + new Category { + Name = "Secondary Category", + Color = CategoryColors.Secondary + } + ]; + + await using var context = GetContext(); + var user = new ApplicationUser { + UserName = TestUserName + }; + var author = new ApplicationUser { + UserName = AuthorUserName + }; + var reviewer = new ApplicationUser { + UserName = ReviewerUserName + }; + + context.AddRange(categories); + context.Users.AddRange([user, author, reviewer]); + + await context.Database.EnsureCreatedAsync(); + await context.SaveChangesAsync(); + + AnonymousPrincipal = new ClaimsPrincipal(new ClaimsIdentity()); + UserPrincipal = new ClaimsPrincipal(new ClaimsIdentity([ + new Claim(ClaimTypes.Name, user.UserName), + new Claim(ClaimTypes.NameIdentifier, user.Id), + new Claim("Id", user.Id), + ], "Mock Authentication")); + AuthorPrincipal = new ClaimsPrincipal(new ClaimsIdentity([ + new Claim(ClaimTypes.Name, author.UserName), + new Claim(ClaimTypes.NameIdentifier, author.Id), + new Claim("Id", author.Id), + new Claim(ClaimTypes.Role, "Author"), + ], "Mock Authentication")); + ReviewerPrincipal = new ClaimsPrincipal(new ClaimsIdentity([ + new Claim(ClaimTypes.Name, reviewer.UserName), + new Claim(ClaimTypes.NameIdentifier, reviewer.Id), + new Claim("Id", reviewer.Id), + new Claim(ClaimTypes.Role, "Author"), + new Claim(ClaimTypes.Role, "Reviewer"), + ], "Mock Authentication")); + + PrimaryCategoryId = categories[0].Id; + SecondaryCategoryId = categories[1].Id; + + await InitializeTestEntities(context); + } + + private sealed class MockDbContextFactory(Func supplier) + : IDbContextFactory { + public ApplicationDbContext CreateDbContext() => supplier(); + } +} + +[TestFixture, FixtureLifeCycle(LifeCycle.InstancePerTestCase)] +[TestOf(typeof(ApplicationRepository))] +public class ApplicationRepositoryTest_GetCategories : ApplicationRepositoryTests { + + #region Success Tests + + [Test] + public async Task AnonymousDefaultOneArticleOneCategory_Success() { + await Repository.CreateArticleAsync( + new ArticleCreateDto("test", "*test*", null, null, [PrimaryCategoryId], null), AuthorPrincipal); + + var result = await Repository.GetCategories(AnonymousPrincipal); + Assert.Multiple(() => { + Assert.That(result, Is.Not.Empty); + Assert.That(result.First().Id, Is.EqualTo(PrimaryCategoryId)); + Assert.That(result, Has.Count.EqualTo(1)); + }); + } + + #endregion + + #region Permission Tests + + [Test] + public async Task AnonymousDefaultNoArticles_Success() { + var result = await Repository.GetCategories(AnonymousPrincipal); + + Assert.Multiple(() => { Assert.That(result, Is.Empty); }); + } + + [Test] + public void AnonymousNoArticlesAllCategories_ThrowsMissingPermissions() { + Assert.ThrowsAsync(async () => await Repository.GetCategories(AnonymousPrincipal, true)); + } + + [Test] + public async Task AuthorDefaultNoArticles_Success() { + var result = await Repository.GetCategories(AuthorPrincipal); + + Assert.Multiple(() => { Assert.That(result, Is.Empty); }); + } + + [Test] + public async Task AuthorDefaultNoArticlesAllCategories_Success() { + var result = await Repository.GetCategories(AuthorPrincipal, true); + + Assert.Multiple(() => { + Assert.That(result, Is.Not.Empty); + Assert.That(result, Has.Count.EqualTo(2)); + Assert.That(result.FirstOrDefault(c => c.Id == PrimaryCategoryId), Is.Not.Null); + Assert.That(result.FirstOrDefault(c => c.Id == SecondaryCategoryId), Is.Not.Null); + }); + } + + #endregion + +} + +[TestFixture, FixtureLifeCycle(LifeCycle.InstancePerTestCase)] +[TestOf(typeof(ApplicationRepository))] +public class ApplicationRepositoryTest_CreateArticle : ApplicationRepositoryTests { + private static ArticleCreateDto GetValidTestArticle(Guid[]? categories = null) { + return new ArticleCreateDto( + "Test Article", + "*Test* Body", + null, null, categories, null); + } + + #region Success Tests + + [Test] + public async Task MinimalArticle_Success() { + var article = GetValidTestArticle(); + + var view = await Repository.CreateArticleAsync(article, AuthorPrincipal); + + await using var context = GetContext(); + Assert.Multiple(() => { + Assert.That(context.Set
().IgnoreQueryFilters().ToList(), Has.Count.EqualTo(1)); + Assert.That(context.Set
().IgnoreQueryFilters().First().Id, Is.EqualTo(view.Id)); + Assert.That(view.Status, Is.EqualTo(ArticleStatus.Draft)); + Assert.That(view.BodyHtml, Is.Not.Null); + Assert.That(view.BodyPlain, Is.Not.Null); + Assert.That(view.Slug, Is.EqualTo("test-article")); + }); + } + + [Test] + public async Task WithCategories_Success() { + var article = GetValidTestArticle([PrimaryCategoryId]); + var view = await Repository.CreateArticleAsync(article, AuthorPrincipal); + + await using var context = GetContext(); + Assert.Multiple(() => { + Assert.That(view.Categories, Has.Count.EqualTo(1)); + Assert.That(context.Set
().IgnoreQueryFilters() + .Include(a => a.Categories) + .First(a => a.Id == view.Id).Categories.First().Id, Is.EqualTo(PrimaryCategoryId)); + }); + } + + #endregion + + #region Permission Tests + + [Test] + public void RegularUser_ThrowsMissingPermissions() { + var article = GetValidTestArticle(); + + Assert.ThrowsAsync( + async () => await Repository.CreateArticleAsync(article, UserPrincipal)); + } + + [Test] + public void AnonymousUser_ThrowsMissingPermissions() { + var article = GetValidTestArticle(); + + Assert.ThrowsAsync( + async () => await Repository.CreateArticleAsync(article, AnonymousPrincipal)); + } + + #endregion + + #region Data Validation Tests + + [Test] + public void MissingTitle_ThrowsMalformed() { + var article = new ArticleCreateDto(null!, "test", null, null, null, null); + + Assert.ThrowsAsync( + async () => await Repository.CreateArticleAsync(article, AuthorPrincipal)); + } + + #endregion + +} + +[TestFixture, FixtureLifeCycle(LifeCycle.InstancePerTestCase)] +[TestOf(typeof(ApplicationRepository))] +public class ApplicationRepositoryTest_UpdateArticle : ApplicationRepositoryTests { + private Guid TestArticleId { get; set; } + + private ArticleUpdateDto GetValidTestArticle() => new(TestArticleId); + + private static string StringOfLength(int length) { + var builder = new StringBuilder(); + + for (int i = 0; i < length; i++) { + builder.Append('_'); + } + + return builder.ToString(); + } + + protected override async ValueTask InitializeTestEntities(ApplicationDbContext context) { + var testArticle = new ArticleCreateDto( + "Test Article", + "Test **Article** with *formatting.", + "test-article", + DateTimeOffset.Now.AddHours(-5), + [PrimaryCategoryId], null); + + var view = await Repository.CreateArticleAsync(testArticle, AuthorPrincipal); + TestArticleId = view.Id; + } + + #region Success Tests + + [Test] + public async Task UpdateTitle_Success() { + var update = new ArticleUpdateDto(TestArticleId, "New Title"); + + await Repository.UpdateArticleAsync(update, AuthorPrincipal); + + await using var context = GetContext(); + Assert.Multiple(() => { + Assert.That(context.Set
().IgnoreQueryFilters().First(a => a.Id == TestArticleId).Title, + Is.EqualTo("New Title")); + }); + } + + [Test] + public async Task UpdateBodyUpdatesHtmlAndPlain_Success() { + var update = new ArticleUpdateDto(TestArticleId, body:"Some *new* Body"); + const string expectedHtml = "

Some new Body

"; + const string expectedPlain = "Some new Body"; + + await Repository.UpdateArticleAsync(update, AuthorPrincipal); + + await using var context = GetContext(); + Assert.Multiple(() => { + var article = context.Set
().IgnoreQueryFilters().First(a => a.Id == TestArticleId); + Assert.That(article.BodyHtml, Is.EqualTo(expectedHtml)); + Assert.That(article.BodyPlain, Is.EqualTo(expectedPlain)); + }); + } + + [Test] + public async Task UpdateCategories_Success() { + var update = new ArticleUpdateDto(TestArticleId, categories:[SecondaryCategoryId]); + await Repository.UpdateArticleAsync(update, AuthorPrincipal); + + await using var context = GetContext(); + Assert.Multiple(() => { + var article = context.Set
().IgnoreQueryFilters() + .Include(a => a.Categories).First(a => a.Id == TestArticleId); + Assert.That(article.Categories, Has.Count.EqualTo(1)); + Assert.That(article.Categories.First().Id, Is.EqualTo(SecondaryCategoryId)); + }); + } + + #endregion + + #region Permission Tests + + [Test] + public void AnonymousUser_ThrowsMissingPermissions() { + var update = GetValidTestArticle(); + + Assert.ThrowsAsync( + async () => await Repository.UpdateArticleAsync(update, AnonymousPrincipal)); + } + + [Test] + public void RegularUser_ThrowsMissingPermissions() { + var update = GetValidTestArticle(); + + Assert.ThrowsAsync( + async () => await Repository.UpdateArticleAsync(update, UserPrincipal)); + } + + [Test] + public void UnrelatedAuthor_ThrowsMissingPermissions() { + var update = GetValidTestArticle(); + + Assert.ThrowsAsync( + async () => await Repository.UpdateArticleAsync(update, ReviewerPrincipal)); + } + + #endregion + + #region Data Validation Tests + + [Test] + public void SlugLength65_ThrowsMalformed() { + var update = new ArticleUpdateDto(TestArticleId, slug:StringOfLength(65)); + Assert.ThrowsAsync( + async () => await Repository.UpdateArticleAsync(update, AuthorPrincipal)); + } + + [Test] + public void TitleLength257_ThrowsMalformed() { + var update = new ArticleUpdateDto(TestArticleId, slug:StringOfLength(257)); + Assert.ThrowsAsync( + async () => await Repository.UpdateArticleAsync(update, AuthorPrincipal)); + } + + #endregion + +} \ No newline at end of file diff --git a/Wave.Tests/Data/ArticleTest.cs b/Wave.Tests/Data/ArticleTest.cs index eddb38b..469fcb1 100644 --- a/Wave.Tests/Data/ArticleTest.cs +++ b/Wave.Tests/Data/ArticleTest.cs @@ -22,7 +22,7 @@ public class ArticleTest { public void SlugWithSpecialCharacters() { Article.Title = "Title with, special characters?"; Article.UpdateSlug(); - Assert.That(Article.Slug, Is.EqualTo("title-with%2C-special-characters%3F")); + Assert.That(Article.Slug, Is.EqualTo("title-with-special-characters")); } [Test] @@ -36,14 +36,14 @@ public class ArticleTest { public void SlugFromTitleLongerThan64CharacterWithSpecialCharacterEscapeSize3AtPosition55() { Article.Title = "Auto generating slugs was a mistake I hate this ______ €"; Article.UpdateSlug(); - Assert.That(Article.Slug, Is.EqualTo("auto-generating-slugs-was-a-mistake-i-hate-this-______-%E2%82%AC")); + Assert.That(Article.Slug, Is.EqualTo("auto-generating-slugs-was-a-mistake-i-hate-this-______-")); } [Test] public void SlugFromTitleLongerThan64CharacterWithSpecialCharacterEscapeSize2AtPosition56() { Article.Title = "Auto generating slugs was a mistake I hate this _______ üa"; Article.UpdateSlug(); - Assert.That(Article.Slug, Is.EqualTo("auto-generating-slugs-was-a-mistake-i-hate-this-_______-%C3%BCa")); + Assert.That(Article.Slug, Is.EqualTo("auto-generating-slugs-was-a-mistake-i-hate-this-_______-a")); } [Test] @@ -57,7 +57,7 @@ public class ArticleTest { public void SlugFromTitleLongerThan64CharacterWithSpecialCharacterEscapeSize2AtPosition57() { Article.Title = "Auto generating slugs was a mistake I hate this ________ üa"; Article.UpdateSlug(); - Assert.That(Article.Slug, Is.EqualTo("auto-generating-slugs-was-a-mistake-i-hate-this-________-%C3%BCa")); + Assert.That(Article.Slug, Is.EqualTo("auto-generating-slugs-was-a-mistake-i-hate-this-________-a")); } [Test] @@ -71,21 +71,21 @@ public class ArticleTest { public void SlugFromTitleLongerThan64CharacterWithSpecialCharacterAtPosition61() { Article.Title = "Article that ends with a special character and need special cäre"; Article.UpdateSlug(); - Assert.That(Article.Slug, Is.EqualTo("article-that-ends-with-a-special-character-and-need-special-c")); + Assert.That(Article.Slug, Is.EqualTo("article-that-ends-with-a-special-character-and-need-special-cre")); } [Test] public void SlugFromTitleLongerThan64CharacterWithSpecialCharacterAtPosition62() { Article.Title = "Article that ends with a special character and needs special cäre"; Article.UpdateSlug(); - Assert.That(Article.Slug, Is.EqualTo("article-that-ends-with-a-special-character-and-needs-special-c")); + Assert.That(Article.Slug, Is.EqualTo("article-that-ends-with-a-special-character-and-needs-special-cre")); } [Test] public void SlugFromTitleLongerThan64CharacterWithSpecialCharacterAtPosition63() { Article.Title = "Article that ends with a special character and needs special caäre"; Article.UpdateSlug(); - Assert.That(Article.Slug, Is.EqualTo("article-that-ends-with-a-special-character-and-needs-special-ca")); + Assert.That(Article.Slug, Is.EqualTo("article-that-ends-with-a-special-character-and-needs-special-car")); } [Test] diff --git a/Wave.Tests/TestUtilities/DbContextTest.cs b/Wave.Tests/TestUtilities/DbContextTest.cs new file mode 100644 index 0000000..8134fb7 --- /dev/null +++ b/Wave.Tests/TestUtilities/DbContextTest.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore; +using Testcontainers.PostgreSql; +using Wave.Data; + +namespace Wave.Tests.TestUtilities; + +[FixtureLifeCycle(LifeCycle.InstancePerTestCase)] +public abstract class DbContextTest { + private PostgreSqlContainer PostgresContainer { get; } = new PostgreSqlBuilder().WithImage("postgres:16.1-alpine").Build(); + + [SetUp] + public async Task SetUp() { + await PostgresContainer.StartAsync(); + await AndThenSetUp(); + } + protected virtual ValueTask AndThenSetUp() { + return ValueTask.CompletedTask; + } + + [TearDown] + public async Task TearDown() => await PostgresContainer.DisposeAsync(); + + protected ApplicationDbContext GetContext() => + new(new DbContextOptionsBuilder() + .UseNpgsql(PostgresContainer.GetConnectionString()) + .EnableSensitiveDataLogging() + .EnableDetailedErrors() + .EnableThreadSafetyChecks() + .Options); + +} \ No newline at end of file diff --git a/Wave.Tests/Wave.Tests.csproj b/Wave.Tests/Wave.Tests.csproj index a05251b..6d78126 100644 --- a/Wave.Tests/Wave.Tests.csproj +++ b/Wave.Tests/Wave.Tests.csproj @@ -35,6 +35,7 @@ + diff --git a/Wave/Assets/React/ArticleEditor.tsx b/Wave/Assets/React/ArticleEditor.tsx new file mode 100644 index 0000000..9b0a008 --- /dev/null +++ b/Wave/Assets/React/ArticleEditor.tsx @@ -0,0 +1,382 @@ +import React, { useState, useEffect, useRef } from "react"; +import { updateCharactersLeft, insertBeforeSelection, insertBeforeAndAfterSelection } from "../utilities/md_functions"; +import { LabelInput, ToolBarButton } from "./Forms"; +import { CategoryColor, Category, ArticleStatus, ArticleView, ArticleDto } from "../model/Models"; +import { useTranslation } from 'react-i18next'; +import markdownit from "markdown-it"; +import markdownitmark from "markdown-it-mark"; +import "groupby-polyfill/lib/polyfill.js"; + +const nameof = function(name: keyof T) { return name; } + +async function get(url: string): Promise { + let response = await fetch(url, { + method: "GET" + }); + if (!response.ok) + throw new Error(response.statusText); + + return response.json(); +} + +async function post(url: string, data: T) : Promise { + let response = await fetch(url, { + method: "POST", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json" + } + }); + if (!response.ok) + throw new Error(response.statusText); + + return response.json(); +} +async function put(url: string, data: T) : Promise { + let response = await fetch(url, { + method: "PUT", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json" + } + }); + if (!response.ok) + throw new Error(response.statusText); + + return response.json(); +} + +function Loading(message: string) { + return
+
+

{message}

+ +
+
+} + +export default function Editor() { + const {t} = useTranslation(); + const [notice, setNotice] = useState(""); + const [dirty, setDirty] = useState(false); + const [isPublished, setIsPublished] = useState(false); + const [article, setArticle] = useState(null); + const [categories, setCategories] = useState([]); + const [model, setModel] = useState({ + body: "", + categories: [], + id: "", + publishDate: new Date(), + slug: "", + title: "" + }); + + const md = markdownit({ + html: false, + linkify: true, + typographer: true, + }) + .use(markdownitmark) + ; + + function onChangeModel(event: React.ChangeEvent) { + const {name, value} = event.target as (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement); + if (name == nameof("publishDate")) { + setModel((m : ArticleDto) => ({...m, publishDate: new Date(value)})); + } else if (event.target instanceof HTMLSelectElement) { + const select = event.target as HTMLSelectElement; + setModel((m : ArticleDto) => ({...m, [name]: [...select.selectedOptions].map(o => o.value)})); + } else { + setModel((m : ArticleDto) => ({...m, [name]: value})); + } + setDirty(true); + } + function onSubmit(event: React.FormEvent) { + event.preventDefault(); + + if (!article || !article.id || article.id.length < 1) { + put("/api/article", model) + .then(result => { + // we just reload the editor, to make sure everything is updated properly + window.location.pathname = `/article/${result.id}/edit`; + }).catch(err => setNotice(`Error creating article: ${err}`)); + } else { + post("/api/article", model) + .then(result => { + setDirty(false) + setArticle(result) + + if (model.slug != result.slug) { + setModel(m => ({...m, slug: result.slug})); + } + }) + .catch(err => setNotice(`Error trying to save article: ${err}`)); + } + } + + const location = window.location.pathname; + useEffect(() => { + if (categories.length < 1) { + get("/api/categories?all=true").then(result => { + setCategories(result); + }).catch(error => { + setNotice(`Error loading Categories: ${error.Message}`); + console.log(`Error loading Categories: ${error.message}`); + }); + } + + const id = location.match(/article\/([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})\/edit/i); + if (!id) { + const publishDate = new Date(); + publishDate.setDate(publishDate.getDate() + 7); + const article : ArticleView = { + body: "", + id: "", + publishDate: publishDate.toString(), + slug: "", + status: 0, + title: "", + categories: [] + }; + setArticle(article); + setModel(m => ({...m, publishDate: publishDate})); + } else if (!article) { + get(`/api/article/${id[1]}`) + .then(result => { + setNotice(""); + setIsPublished(result.status >= ArticleStatus.Published && (new Date(result.publishDate) <= new Date())); + setModel(m => ({ + ...m, + id: result.id, + title: result.title, + slug: result.slug, + body: result.body, + publishDate: new Date(result.publishDate), + categories: result.categories.map(c => c.id), + })); + setArticle(result); + console.log("Article loaded"); + }) + .catch(error => { + setNotice(`Error loading Article: ${error.message}`); + console.log(`Error loading Article: ${error.message}`); + setArticle(null); + }); + } + }, ([setArticle, setNotice, console, location]) as any[]); + + const markdownArea = useRef(null); + return ( + <> + { + dirty && +
+ + + +

{t("editor.unsaved_changes_notice")}

+
+ } + { + notice.length > 0 && +
+ + + +

{notice}

+
+ } + { + article === null ? + Loading(t("loading.article")) : + <> +
+
    +
  • = ArticleStatus.Draft ? "step-primary" : ""}`}>{t("Draft")}
  • +
  • = ArticleStatus.InReview ? "step-primary" : ""}`}>{t("InReview")}
  • +
  • {t("Published")}
  • +
+ +
+
+ + ) => updateCharactersLeft(event.target as HTMLInputElement)} + placeholder={t("Title_Placeholder")} + name={nameof("title")} value={model.title} onChange={onChangeModel} /> + + + + +
+ + ) => updateCharactersLeft(event.target as HTMLInputElement)} + placeholder={t("Slug_Placeholder")} + name={nameof("slug")} value={model.slug} onChange={onChangeModel} /> + + + ("publishDate")} + defaultValue={(new Date(article.publishDate).toLocaleString("sv", {timeZoneName: "short"}).substring(0, 16))} + onChange={onChangeModel} /> + +
+
+ +
+
+
+
+ insertBeforeSelection(markdownArea.current, "# ", true)}> + {t("Tools.H1_Label")} + + insertBeforeSelection(markdownArea.current, "## ", true)}> + {t("Tools.H2_Label")} + + insertBeforeSelection(markdownArea.current, "### ", true)}> + {t("Tools.H3_Label")} + + insertBeforeSelection(markdownArea.current, "#### ", true)}> + {t("Tools.H4_Label")} + +
+
+ insertBeforeAndAfterSelection(markdownArea.current, "**")}> + B + + insertBeforeAndAfterSelection(markdownArea.current, "*")}> + I + + insertBeforeAndAfterSelection(markdownArea.current, "++")}> + U + + insertBeforeAndAfterSelection(markdownArea.current, "~~")}> + {t("Tools.StrikeThrough_Label")} + + insertBeforeAndAfterSelection(markdownArea.current, "==")}> + {t("Tools.Mark_Label")} + + insertBeforeSelection(markdownArea.current, "> ", true)}> + | {t("Tools.Cite_Label")} + +
+
+ insertBeforeSelection(markdownArea.current, "1. ", true)}> + 1. + + insertBeforeSelection(markdownArea.current, "a. ", true)}> + a. + + insertBeforeSelection(markdownArea.current, "A. ", true)}> + A. + + insertBeforeSelection(markdownArea.current, "i. ", true)}> + i. + + insertBeforeSelection(markdownArea.current, "I. ", true)}> + I. + +
+
+ insertBeforeAndAfterSelection(markdownArea.current, "`")}> + + + + + insertBeforeAndAfterSelection(markdownArea.current, "```")}> + + + + +
+
+ - - -
- - @if (Article.Id != Guid.Empty) { - - @Localizer["ViewArticle_Label"] - - } -
- - - -
- @foreach (var image in Article.Images) { -
- @image.ImageDescription -
- -
- -
- } - -
- -@code { - private const string ImageModal = "AddImage"; - - [Parameter] - public Guid? Id { get; set; } - [Parameter] - public required ApplicationUser User { get; set; } - [Parameter] - public required ClaimsPrincipal ClaimsUser { get; set; } - - [SupplyParameterFromForm] - private InputModel Model { get; set; } = new(); - - private Article Article { get; set; } = default!; - private List Categories { get; set; } = []; - private bool Saving { get; set; } - - protected override void OnInitialized() { - // ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract - Article ??= new Article {Author = User, Title = "", Body = ""}; - } - - protected override async Task OnInitializedAsync() { - await using var context = await ContextFactory.CreateDbContextAsync(); - if (Categories.Count < 1) - Categories = await context.Set().IgnoreQueryFilters().OrderBy(c => c.Color).ToListAsync(); - - Article? article = null; - if (Id is not null) { - // Ensure we are not double-tracking User on existing articles, since - // a different context loaded this user originally - context.Entry(User).State = EntityState.Unchanged; - - article = await context.Set
() - .IgnoreQueryFilters().Where(a => !a.IsDeleted) - .Include(a => a.Author) - .Include(a => a.Reviewer) - .Include(a => a.Categories) - .Include(a => a.Images) - .FirstAsync(a => a.Id == Id); - if (article is null) throw new ApplicationException("Article not found."); - } - - if (article is not null) { - if (!article.AllowedToEdit(ClaimsUser)) - throw new ApplicationException("You are not allowed to edit this article"); - - Model.Id ??= article.Id; - Model.Title ??= article.Title; - Model.Slug ??= article.Slug; - Model.Body ??= article.Body; - Model.PublishDate ??= article.PublishDate.LocalDateTime; - if (Model.Categories?.Length < 1) { - Model.Categories = article.Categories.Select(c => c.Id).ToArray(); - } - Article = article; - await InvokeAsync(StateHasChanged); - } - } - - private async Task OnValidSubmit() { - if (Article.AllowedToEdit(ClaimsUser) is false) { - Message.ShowError("Permission denied."); - return; - } - try { - Saving = true; - - // Double check user permissions - await HandleRoles(Article, User); - - if (Model.Title is not null) Article.Title = Model.Title; - if (Model.Body is not null) Article.Body = Model.Body; - if (Model.PublishDate is not null && - (Article.Status is not ArticleStatus.Published || Article.PublishDate >= DateTimeOffset.UtcNow)) - Article.PublishDate = Model.PublishDate.Value; - if (Article.Status is ArticleStatus.Published && Article.PublishDate < DateTimeOffset.Now) { - // can't change slugs when the article is public - } else { - Article.UpdateSlug(Model.Slug); - Model.Slug = Article.Slug; - } - - Article.LastModified = DateTimeOffset.UtcNow; - - await using var context = await ContextFactory.CreateDbContextAsync(); - - // Update Newsletter distribution if exists - var newsletter = await context.Set() - .IgnoreQueryFilters().IgnoreAutoIncludes() - .FirstOrDefaultAsync(n => n.Article == Article); - if (newsletter is not null) { - newsletter.DistributionDateTime = Article.PublishDate; - } - - // Avoid unnecessary updates - context.Entry(User).State = EntityState.Unchanged; - Categories.ForEach(c => context.Entry(c).State = EntityState.Unchanged); - await context.Set().IgnoreQueryFilters().IgnoreAutoIncludes() - .Where(ac => ac.Article.Id == Article.Id).LoadAsync(); - - context.Update(Article); - context.RemoveRange(Article.Headings); - Article.UpdateBody(); - - var existingImages = await context.Set
() - .IgnoreQueryFilters().Where(a => a.Id == Article.Id) - .AsNoTrackingWithIdentityResolution() - .SelectMany(a => a.Images).ToListAsync(); - foreach (var image in Article.Images) { - int index = existingImages.FindIndex(a => a.Id == image.Id); - context.Entry(image).State = index > -1 ? EntityState.Modified : EntityState.Added; - if(index > -1) existingImages.RemoveAt(index); - } - foreach (var image in existingImages) { - context.Entry(image).State = EntityState.Deleted; - } - - var relations = await context.Set() - .IgnoreQueryFilters().IgnoreAutoIncludes() - .Where(ac => ac.Article == Article && !Model.Categories.Contains(ac.Category.Id)) - .ToListAsync(); - context.RemoveRange(relations); - - foreach (var category in Model.Categories) { - if (Article.Categories.Any(c => c.Id == category) is not true) { - context.Add(new ArticleCategory { - Article = Article, - Category = Categories.First(c => c.Id == category) - }); - } - } - - await context.SaveChangesAsync(); - foreach (var image in existingImages) { - try { - Images.Delete(image.Id); - } catch (Exception ex) { - Logger.LogWarning(ex, "Failed to delete image: {image}", image.Id); - } - } - Message.ShowSuccess(Localizer["Save_Success"]); - - if (Navigation.Uri.EndsWith("/article/new")) { - Navigation.NavigateTo($"/article/{Article.Id}/edit", false, true); - } - } catch (Exception ex) { - Message.ShowError(Localizer["Save_Error"]); - Logger.LogError(ex, "Failed to save article."); - } finally { - Saving = false; - await InvokeAsync(StateHasChanged); - } - } - - [SuppressMessage("ReSharper", "ConvertIfStatementToSwitchStatement")] - private async Task HandleRoles(Article article, ApplicationUser me) { - // it's our draft - if (article.Status is ArticleStatus.Draft && article.Author.Id == me.Id) return; - - var roles = await UserManager.GetRolesAsync(me); - - // reviewers and admins can review articles - if (article.Status is ArticleStatus.InReview && roles.Any(r => r is "Admin" or "Reviewer")) { - article.Reviewer = me; - return; - } - - // published articles may only be edited my admins or moderators - if (article.Status is ArticleStatus.Published && roles.Any(r => r is "Admin" or "Moderator")) { - article.Reviewer = me; // TODO replace with editor or something? - return; - } - - throw new ApplicationException("You do not have permissions to edit this article"); - } - - private async Task ImageAdded(ArticleImage image) { - Article.Images.Add(image); - await InvokeAsync(StateHasChanged); - } - - private async Task ImageDelete(ArticleImage image) { - Article.Images.Remove(image); - await InvokeAsync(StateHasChanged); - } - - private sealed class InputModel { - public Guid? Id { get; set; } - - [Required(AllowEmptyStrings = false), MaxLength(256)] - public string? Title { get; set; } - [MaxLength(64)] - public string? Slug { get; set; } - [Required(AllowEmptyStrings = false)] - public string? Body { get; set; } - - public Guid[]? Categories { get; set; } = []; - public DateTimeOffset? PublishDate { get; set; } - } - -} \ No newline at end of file diff --git a/Wave/Controllers/ArticleController.cs b/Wave/Controllers/ArticleController.cs new file mode 100644 index 0000000..c2a0842 --- /dev/null +++ b/Wave/Controllers/ArticleController.cs @@ -0,0 +1,107 @@ +using System.Security.Claims; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Wave.Data; +using Wave.Data.Transactional; + +namespace Wave.Controllers; + +[ApiController] +[Route("/api/[controller]")] +public class ArticleController(ILogger logger, ApplicationRepository repository) : ControllerBase { + [HttpGet("/api/categories"), AllowAnonymous] + [Produces("application/json")] + public async Task>, + NoContent, + UnauthorizedHttpResult, + ProblemHttpResult>> GetCategories(bool all = false, CancellationToken cancellation = default) { + try { + var categories = await repository.GetCategories(User, all, cancellation); + + if (categories.Count < 1) return TypedResults.NoContent(); + return TypedResults.Ok>(categories); + } catch (ApplicationException) { + logger.LogTrace("Unauthenticated user tried to access all categories. Denied."); + return TypedResults.Unauthorized(); + } catch (Exception ex) { + logger.LogError(ex, "Unexpected error trying to get Categories for user {UserId}.", User.FindFirstValue("Id") ?? "unknown or anonymous"); + return TypedResults.Problem(); + } + } + + [HttpGet("{id:guid}"), AllowAnonymous] + [Produces("application/json")] + public async Task, + NotFound, + UnauthorizedHttpResult, + ProblemHttpResult>> GetArticle(Guid id, CancellationToken cancellation = default) { + try { + return TypedResults.Ok(new ArticleView(await repository.GetArticleAsync(id, User, cancellation))); + } catch (ArticleNotFoundException) { + logger.LogWarning("Failed to look up Article with Id {ArticleId}. Not Found", id); + return TypedResults.NotFound(); + } catch (ArticleMissingPermissionsException) { + logger.LogWarning( + "Failed to look up Article with Id {ArticleId}. User {UserId} Access Denied.", + id, User.FindFirstValue("Id") ?? "unknown or anonymous"); + return TypedResults.Unauthorized(); + } catch (Exception ex) { + logger.LogError(ex, "Unexpected Error."); + return TypedResults.Problem(); + } + } + + [HttpPut(Name = nameof(CreateArticle)), Authorize] + [Produces("application/json")] + public async Task, + BadRequest, + UnauthorizedHttpResult, + ProblemHttpResult>> CreateArticle(ArticleCreateDto input, CancellationToken cancellation = default) { + try { + var article = new ArticleView(await repository.CreateArticleAsync(input, User, cancellation)); + return TypedResults.CreatedAtRoute(article, nameof(CreateArticle), article.Id); + } catch (ArticleMissingPermissionsException) { + logger.LogWarning( + "Unauthorized User with ID {UserId} tried to create an Article.", + User.FindFirstValue("Id") ?? "unknown or anonymous"); + return TypedResults.Unauthorized(); + } catch (ArticleMalformedException ex) { + logger.LogWarning("User with ID {UserId} tried to create an article but submitted bad data.", + User.FindFirstValue("Id") ?? "unknown or anonymous"); + return TypedResults.BadRequest($"Submitted data is not valid: {string.Join(",", ex.Errors.Select(e => e.ErrorMessage))}."); + } catch (Exception ex) { + logger.LogError(ex, "Unexpected Error."); + return TypedResults.Problem(); + } + } + + [HttpPost, Authorize] + [Produces("application/json")] + public async Task, + NotFound, + BadRequest, + UnauthorizedHttpResult, + ProblemHttpResult>> UpdateArticle(ArticleUpdateDto input, CancellationToken cancellation = default) + { + try { + return TypedResults.Ok(new ArticleView(await repository.UpdateArticleAsync(input, User, cancellation))); + } catch (ArticleNotFoundException) { + return TypedResults.NotFound(); + } catch (ArticleMalformedException ex) { + logger.LogWarning("User with ID {UserId} tried to update article with ID {ArticleId} but submitted bad data.", + User.FindFirstValue("Id") ?? "unknown or anonymous", input.Id); + return TypedResults.BadRequest($"Submitted data is not valid: {string.Join(",", ex.Errors.Select(e => e.ErrorMessage))}."); + } catch (ArticleMissingPermissionsException) { + return TypedResults.Unauthorized(); + } catch (ArticleException ex) { + logger.LogError(ex, "Unexpected Article Error."); + return TypedResults.Problem(); + } + } + +} \ No newline at end of file diff --git a/Wave/Controllers/UserController.cs b/Wave/Controllers/UserController.cs index 025a46b..59d42a6 100644 --- a/Wave/Controllers/UserController.cs +++ b/Wave/Controllers/UserController.cs @@ -23,12 +23,12 @@ public class UserController(ImageService imageService, IDbContextFactory u.ProfilePicture).FirstOrDefaultAsync(u => u.Id == userId); if (user is null) return NotFound(); if (user.ProfilePicture is null) { - return Redirect("/img/default_avatar.jpg"); + return Redirect("/dist/img/default_avatar.jpg"); } string? path = ImageService.GetPath(user.ProfilePicture.ImageId); if (path is null) { - return Redirect("/img/default_avatar.jpg"); + return Redirect("/dist/img/default_avatar.jpg"); } if (size < 800) return File(await ImageService.GetResized(path, size), ImageService.ImageMimeType); diff --git a/Wave/Data/ApplicationDbContext.cs b/Wave/Data/ApplicationDbContext.cs index 9d5ad3d..aa5aa5c 100644 --- a/Wave/Data/ApplicationDbContext.cs +++ b/Wave/Data/ApplicationDbContext.cs @@ -1,6 +1,8 @@ +using System.Text; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Wave.Data.Transactional; namespace Wave.Data; @@ -131,4 +133,74 @@ public class ApplicationDbContext(DbContextOptions options key.Ignore(k => k.Claims); }); } + + internal async ValueTask UpdateArticle(ArticleDto dto, Article article, + CancellationToken cancellation) { + if (dto is ArticleCreateDto cDto) { + article.Title = cDto.Title; + article.Body = cDto.Body; + } else if (dto is ArticleUpdateDto uDto) { + if (!string.IsNullOrWhiteSpace(uDto.Title)) article.Title = uDto.Title; + if (!string.IsNullOrWhiteSpace(uDto.Body)) article.Body = uDto.Body; + } + article.LastModified = DateTimeOffset.UtcNow; + article.UpdateBody(); + + // We can't use CanBePublic here since when we create a new article, that isn't initialized yet + if (article.Status != ArticleStatus.Published || article.PublishDate > DateTimeOffset.UtcNow) { + // Update publish date, if it exists and article isn't public yet + if (dto.PublishDate is {} date) article.PublishDate = date; + // Can only change slugs when the article is not public + article.UpdateSlug(dto.Slug); + } + + await UpdateCategories(dto, article, cancellation); + await UpdateImages(dto, article, cancellation); + await UpdateNewsletter(article, cancellation); + } + + private async ValueTask UpdateCategories(ArticleDto dto, Article article, CancellationToken cancellation) { + if (dto.Categories is null) return; + + // Retrieve all existing links between this article and categories + var relationships = await Set() + .IgnoreQueryFilters() + .IgnoreAutoIncludes() + .Include(ac => ac.Category) + .Where(ac => ac.Article == article) + .ToListAsync(cancellation); + + // check which Category is not in the DTO and needs its relationship removed + foreach (var ac in relationships.Where(ac => !dto.Categories.Contains(ac.Category.Id))) { + article.Categories.Remove(ac.Category); + Remove(ac); + } + + // check which Category in the DTO is absent from the article's relationships, and add them + var added = dto.Categories.Where(cId => relationships.All(ac => ac.Category.Id != cId)).ToList(); + if (added.Count > 0) { + var categories = await Set() + .IgnoreAutoIncludes().IgnoreQueryFilters() + .Where(c => added.Contains(c.Id)) + .ToListAsync(cancellation); + + await AddRangeAsync(categories.Select(c => new ArticleCategory { + Article = article, Category = c + }).ToList(), cancellation); + } + } + + private async ValueTask UpdateImages(ArticleDto dto, Article article, CancellationToken cancellation) { + if (dto.Images is null) return; + + // TODO:: implement + } + + private async ValueTask UpdateNewsletter(Article article, CancellationToken cancellation) { + // Update Newsletter distribution if it exists + var newsletter = await Set() + .IgnoreQueryFilters().IgnoreAutoIncludes() + .FirstOrDefaultAsync(n => n.Article == article, cancellation); + if (newsletter is not null) newsletter.DistributionDateTime = article.PublishDate; + } } \ No newline at end of file diff --git a/Wave/Data/ApplicationRepository.cs b/Wave/Data/ApplicationRepository.cs new file mode 100644 index 0000000..9b908f0 --- /dev/null +++ b/Wave/Data/ApplicationRepository.cs @@ -0,0 +1,116 @@ +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations; +using System.Security.Claims; +using Microsoft.EntityFrameworkCore; +using Wave.Data.Transactional; +using Wave.Utilities; + +namespace Wave.Data; + +public class ArticleException : ApplicationException; +public class ArticleNotFoundException : ArticleException; +public class ArticleMissingPermissionsException : ArticleException; +public class ArticleMalformedException : ArticleException { + public IReadOnlyCollection Errors { get; init; } = []; +} + +/// +/// Adapter for ApplicationDbContext, that enforced valid data and the permission system +/// +/// +public class ApplicationRepository(IDbContextFactory contextFactory) { + private IDbContextFactory ContextFactory { get; } = contextFactory; + + public async ValueTask> GetCategories(ClaimsPrincipal user, bool includeUnusedCategories = false, CancellationToken cancellation = default) { + if (includeUnusedCategories && user.Identity?.IsAuthenticated is not true) + throw new ApplicationException("Trying to access unused articles with unauthenticated user"); + + await using var context = await ContextFactory.CreateDbContextAsync(cancellation); + var categories = await context.Set() + .IgnoreAutoIncludes() + .IgnoreQueryFilters() + .Where(c => includeUnusedCategories || c.Articles.Any()) + .OrderBy(c => c.Color) + .ToListAsync(cancellation); + + return new ReadOnlyCollection(categories); + } + + public async ValueTask
GetArticleAsync(Guid id, ClaimsPrincipal user, CancellationToken cancellation = default) { + await using var context = await ContextFactory.CreateDbContextAsync(cancellation); + var article = await context.Set
() + .IgnoreQueryFilters() + .IgnoreAutoIncludes() + .Include(a => a.Author) + .Include(a => a.Reviewer) + .Include(a => a.Categories) + .FirstOrDefaultAsync(a => a.Id == id, cancellation); + + if (article is null) + throw new ArticleNotFoundException(); + if (article.AllowedToRead(user)) + return article; + + throw new ArticleMissingPermissionsException(); + } + + public async ValueTask
CreateArticleAsync(ArticleCreateDto dto, ClaimsPrincipal user, + CancellationToken cancellation = default) { + if (!Permissions.AllowedToCreate(user)) + throw new ArticleMissingPermissionsException(); + + List results = []; + if (!Validator.TryValidateObject(dto, new ValidationContext(dto), results, true)) { + throw new ArticleMalformedException() { + Errors = results + }; + } + + await using var context = await ContextFactory.CreateDbContextAsync(cancellation); + var appUser = await context.Users.FindAsync([user.FindFirstValue("Id")], cancellation); + + var article = new Article { + Author = appUser ?? throw new ArticleException(), + Title = "", + Body = "" + }; + await context.UpdateArticle(dto, article, cancellation); + await context.Set
().AddAsync(article, cancellation); + await context.SaveChangesAsync(cancellation); + + return article; + } + + public async ValueTask
UpdateArticleAsync(ArticleUpdateDto dto, ClaimsPrincipal user, + CancellationToken cancellation = default) { + List results = []; + if (!Validator.TryValidateObject(dto, new ValidationContext(dto), results, true)) { + throw new ArticleMalformedException() { + Errors = results + }; + } + + await using var context = await ContextFactory.CreateDbContextAsync(cancellation); + var article = await context.Set
() + .IgnoreQueryFilters() + .Include(a => a.Author) + .FirstOrDefaultAsync(a => a.Id == dto.Id, cancellation); + if (article is null) + throw new ArticleNotFoundException(); + if (!article.AllowedToEdit(user)) + throw new ArticleMissingPermissionsException(); + var appUser = await context.Users.FindAsync([user.FindFirstValue("Id")], cancellation); + if (appUser is null) + throw new ArticleException(); + + if (appUser.Id != article.Author.Id) { + article.Reviewer = appUser; + } + + await context.UpdateArticle(dto, article, cancellation); + await context.SaveChangesAsync(cancellation); + + return article; + } + +} \ No newline at end of file diff --git a/Wave/Data/Article.cs b/Wave/Data/Article.cs index 8d46644..bd926d1 100644 --- a/Wave/Data/Article.cs +++ b/Wave/Data/Article.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using System.Text; using System.Text.RegularExpressions; using Wave.Utilities; @@ -60,15 +61,32 @@ public partial class Article : ISoftDelete { public void UpdateSlug(string? potentialNewSlug = null) { if (!string.IsNullOrWhiteSpace(potentialNewSlug) && Uri.IsWellFormedUriString(potentialNewSlug, UriKind.Relative)) { + if (potentialNewSlug.Length > 64) potentialNewSlug = potentialNewSlug[..64]; Slug = potentialNewSlug; return; } - if (string.IsNullOrWhiteSpace(potentialNewSlug) && !string.IsNullOrWhiteSpace(Slug)) return; + // if (string.IsNullOrWhiteSpace(potentialNewSlug) && !string.IsNullOrWhiteSpace(Slug)) return; + + string baseSlug = string.IsNullOrWhiteSpace(potentialNewSlug) ? Title.ToLower() : potentialNewSlug; + + { + baseSlug = Regex.Replace(Uri.EscapeDataString(Encoding.ASCII.GetString( + Encoding.Convert( + Encoding.UTF8, + Encoding.GetEncoding( + Encoding.ASCII.EncodingName, + new EncoderReplacementFallback(string.Empty), + new DecoderExceptionFallback()), + Encoding.UTF8.GetBytes(baseSlug)) + ).Replace("-", "+").Replace(" ", "-")), @"(%[\dA-F]{2})", string.Empty); + if (baseSlug.Length > 64) baseSlug = baseSlug[..64]; + Slug = baseSlug; + return; + } - string baseSlug = potentialNewSlug ?? Title; baseSlug = baseSlug.ToLowerInvariant()[..Math.Min(64, baseSlug.Length)]; - string slug = Uri.EscapeDataString(baseSlug).Replace("-", "+").Replace("%20", "-"); + string slug = Uri.EscapeDataString(baseSlug); // I hate my life int escapeTrimOvershoot = 0; diff --git a/Wave/Data/Transactional/ArticleDto.cs b/Wave/Data/Transactional/ArticleDto.cs new file mode 100644 index 0000000..d5ebc74 --- /dev/null +++ b/Wave/Data/Transactional/ArticleDto.cs @@ -0,0 +1,81 @@ +using System.ComponentModel.DataAnnotations; + +namespace Wave.Data.Transactional; + +public abstract class ArticleDto( + string? slug, + DateTimeOffset? publishDate, + Guid[]? categories, + Guid[]? images) +{ + [MaxLength(64)] + public string? Slug { get; init; } = slug; + + public DateTimeOffset? PublishDate { get; init; } = publishDate; + public Guid[]? Categories { get; init; } = categories; + public Guid[]? Images { get; init; } = images; + + public void Deconstruct( + out string? slug, out DateTimeOffset? publishDate, out Guid[]? categories, out Guid[]? images) { + slug = Slug; + publishDate = PublishDate; + categories = Categories; + images = Images; + } +} + +public class ArticleCreateDto( + string title, + [Required(AllowEmptyStrings = false)] string body, + string? slug, + DateTimeOffset? publishDate, + Guid[]? categories, + Guid[]? images) : ArticleDto(slug, publishDate, categories, images) +{ + [Required(AllowEmptyStrings = false)] + [MaxLength(256)] + public string Title { get; init; } = title; + + public string Body { get; init; } = body; + + public void Deconstruct( + out string title, out string body, out string? slug, out DateTimeOffset? publishDate, out Guid[]? categories, + out Guid[]? images) { + title = Title; + body = Body; + slug = Slug; + publishDate = PublishDate; + categories = Categories; + images = Images; + } +} + +public class ArticleUpdateDto( + Guid id, + string? title = null, + string? body = null, + string? slug = null, + DateTimeOffset? publishDate = null, + Guid[]? categories = null, + Guid[]? images = null) : ArticleDto(slug, publishDate, categories, images) +{ + [Required] + public Guid Id { get; init; } = id; + + [MaxLength(256)] + public string? Title { get; init; } = title; + + public string? Body { get; init; } = body; + + public void Deconstruct( + out Guid id, out string? title, out string? body, out string? slug, out DateTimeOffset? publishDate, + out Guid[]? categories, out Guid[]? images) { + id = Id; + title = Title; + body = Body; + slug = Slug; + publishDate = PublishDate; + categories = Categories; + images = Images; + } +} \ No newline at end of file diff --git a/Wave/Data/Transactional/ArticleView.cs b/Wave/Data/Transactional/ArticleView.cs new file mode 100644 index 0000000..28b75a6 --- /dev/null +++ b/Wave/Data/Transactional/ArticleView.cs @@ -0,0 +1,30 @@ +namespace Wave.Data.Transactional; + +public sealed record CategoryView(Guid id, string Name, CategoryColors Color) { + public CategoryView(Category category) : this( + category.Id, category.Name, category.Color) {} + +} + +public sealed record ArticleView( + Guid Id, + string Title, + string Slug, + string BodyHtml, + string Body, + string BodyPlain, + ArticleStatus Status, + DateTimeOffset PublishDate, + IReadOnlyList Categories) +{ + public ArticleView(Article article) : this( + article.Id, + article.Title, + article.Slug, + article.BodyHtml, + article.Body, + article.BodyPlain, + article.Status, + article.PublishDate, + article.Categories.Select(c => new CategoryView(c)).ToList()) {} +} \ No newline at end of file diff --git a/Wave/Dockerfile b/Wave/Dockerfile index 7a03e28..6510898 100644 --- a/Wave/Dockerfile +++ b/Wave/Dockerfile @@ -13,6 +13,19 @@ EXPOSE 8080 HEALTHCHECK --start-period=5s --start-interval=15s --interval=30s --timeout=30s --retries=3 \ CMD curl --fail http://localhost:8080/health || exit 1 +FROM node:20-alpine AS vite-build +WORKDIR /src +RUN mkdir -p "wwwroot" +COPY ["Wave/package.json", "Wave/package-lock.json", "./"] +RUN npm install +COPY [ \ + "Wave/tsconfig.json", \ + "Wave/tsconfig.node.json", \ + "Wave/*.config.ts", \ + "./"] +COPY ["Wave/Assets/", "./Assets/"] +RUN npx vite build + FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build ARG BUILD_CONFIGURATION=Release ARG VERSION=0.0.1 @@ -38,6 +51,7 @@ RUN dotnet publish "./Wave.csproj" \ FROM base AS final WORKDIR /app +COPY --from=vite-build /src/wwwroot ./wwwroot COPY --from=publish /app/publish . COPY LICENSE . ENTRYPOINT ["dotnet", "Wave.dll"] diff --git a/Wave/Program.cs b/Wave/Program.cs index de94552..2352d80 100644 --- a/Wave/Program.cs +++ b/Wave/Program.cs @@ -26,6 +26,7 @@ using Serilog; using Serilog.Events; using Serilog.Sinks.Grafana.Loki; +using Vite.AspNetCore; using Wave.Utilities.Metrics; #region Version Information @@ -81,6 +82,13 @@ options.OutputFormatters.Add(new SyndicationFeedFormatter()); }); builder.Services.AddOutputCache(); +builder.Services.AddViteServices(options => { + // options.Server.AutoRun = true; + options.Server.ScriptName = "dev"; + options.Server.Https = false; + options.Server.UseReactRefresh = true; + options.Base = "/dist/"; +}); #region Data Protection & Redis @@ -198,6 +206,7 @@ .AddSignInManager() .AddDefaultTokenProviders() .AddClaimsPrincipalFactory(); +builder.Services.AddScoped(); #endregion @@ -334,18 +343,22 @@ } } }); +app.UseAuthentication(); +app.UseAuthorization(); + app.UseAntiforgery(); -app.MapRazorComponents().AddInteractiveServerRenderMode(); - -// Add additional endpoints required by the Identity /Account Razor components. -app.MapAdditionalIdentityEndpoints(); - app.MapHealthChecks("/health"); - +app.MapRazorComponents().AddInteractiveServerRenderMode(); +app.MapAdditionalIdentityEndpoints(); app.MapControllers(); -app.UseOutputCache(); +if (app.Environment.IsDevelopment()) { + //app.UseWebSockets(); + app.UseViteDevelopmentServer(true); +} + +app.UseOutputCache(); app.UseRequestLocalization(); { diff --git a/Wave/Utilities/Permissions.cs b/Wave/Utilities/Permissions.cs index 6114edc..c8cad1e 100644 --- a/Wave/Utilities/Permissions.cs +++ b/Wave/Utilities/Permissions.cs @@ -15,7 +15,9 @@ public static class Permissions { if (article.Status >= ArticleStatus.Published && article.PublishDate <= DateTimeOffset.UtcNow) { return true; } - + + if (principal.Identity?.IsAuthenticated is false) return false; + // Admins always get access if (principal.IsInRole("Admin")) { return true; @@ -33,9 +35,26 @@ public static class Permissions { return false; } + + public static bool AllowedToCreate(ClaimsPrincipal principal) { + if (principal.Identity?.IsAuthenticated is false) return false; + + // Admins always get access + if (principal.IsInRole("Admin")) { + return true; + } + + // Authors can author articles (duh) + if (principal.IsInRole("Author")) { + return true; + } + + return false; + } public static bool AllowedToEdit(this Article? article, ClaimsPrincipal principal) { if (article is null || article.IsDeleted) return false; + if (principal.Identity?.IsAuthenticated is false) return false; // anon users can't edit ever if (article.Author is null) throw new ArgumentException("Checking permissions without loading related Author."); // Admins always can edit articles @@ -70,12 +89,14 @@ public static class Permissions { } public static bool AllowedToRejectReview(this Article? article, ClaimsPrincipal principal) { + if (principal.Identity?.IsAuthenticated is false) return false; // anon users can't review ever // if you can publish it, you can reject it return article?.Status is ArticleStatus.InReview && article.AllowedToPublish(principal); } public static bool AllowedToSubmitForReview(this Article? article, ClaimsPrincipal principal) { if (article is null || article.IsDeleted) return false; + if (principal.Identity?.IsAuthenticated is false) return false; // anon users can't edit ever if (article.Author is null) throw new ArgumentException("Checking permissions without loading related Author."); // Draft articles can be submitted by their authors (admins can publish them anyway, no need to submit) @@ -88,6 +109,7 @@ public static class Permissions { public static bool AllowedToPublish(this Article? article, ClaimsPrincipal principal) { if (article is null || article.IsDeleted) return false; + if (principal.Identity?.IsAuthenticated is false) return false; // anon users can't publish ever if (article.Author is null) throw new ArgumentException("Checking permissions without loading related Author."); // Admins can skip review and directly publish draft articles @@ -111,6 +133,7 @@ public static class Permissions { public static bool AllowedToDelete(this Article? article, ClaimsPrincipal principal) { if (article is null || article.IsDeleted) return false; + if (principal.Identity?.IsAuthenticated is false) return false; // anon users can't delete ever if (article.Author is null) throw new ArgumentException("Checking permissions without loading related Author."); // Admins can delete articles whenever diff --git a/Wave/Wave.csproj b/Wave/Wave.csproj index 97de6c4..79c7f58 100644 --- a/Wave/Wave.csproj +++ b/Wave/Wave.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -9,25 +9,29 @@ ..\docker-compose.dcproj + + + + - + - - - + + + - + - + - - + + @@ -42,10 +46,7 @@ - - - - + diff --git a/Wave/appsettings.Development.json b/Wave/appsettings.Development.json index 7a73a41..0c7a32a 100644 --- a/Wave/appsettings.Development.json +++ b/Wave/appsettings.Development.json @@ -1,2 +1,3 @@ { + "DetailedErrors": true } \ No newline at end of file diff --git a/Wave/package-lock.json b/Wave/package-lock.json index c348a2be91bd0334a9fc3ba4b922cd2b742f953c..9c195200f66b6b28e656b1a92e7f5c2a0ada8ad9 100644 GIT binary patch literal 220275 zcmdqKS+nBGvL^W6zv9@gx1v`H4M^geozoj35CSnt0s+@*w`m^Ggl17y_qTUQ%qy8z z?##40{jwH=@R0m-_wev=_xPXx*FXO8hcA2jAOG=>KXN(K|MH@a^H%y%Fmx?v7f2 zF@gG*rruFmOw7&u;Z7f5G5cnt#-{^N)Z0 z@9I8}R5JP@p+AklPvRhrR2}kzB>0GBKmO3{ICSN*rrH8jk>>fPz~kNgCiU&(ug+J) z=*`uMY`eMbYib-rNf`!aB!||4cJo{78+=O}T%pI{R>F}Ru)ZYHWi>fG zH~9_y_G!$^B_CSgT`s#FEVC2ciJ{OubO>`m!I?U*mvrH+QAUc3h@*{U!Dde0}{(8zz0dI6M%7euLp}t?REn zIofJL?tj?FX9gqR61ckJqk4TDrV@#(hX{i>0XJEHNrKx)Z|?9DPY;T56r%%oZkT!J z`|HO5z`?iBU5P?{2WZ8>>)Wf*S0g(-JY@@ff5V0fu=k*4B}o|n2LwgBX~#)a ze)B`miN6Jr`5kfS<1)}kP4Zh}?#~bShwUf28QDoK{jnvtVB}*FsU3=HV9Fxucc@%( zQ<0^5(JIfBcmXX5aU&U?Vh#;uo7+^nw}rM@Xj6ItL`hc-jhT}z$8^UM?xX_R*tf)Z z#O43|=Veq)&%kq>Y*%d)bRP)(XQOgbx_|u>=;VpBC)xSKNPW%r%`5%^ok*kF^qg2^ z+KH7a-_*c^;xO>zAc~I38Ie+!~XcIwwZSze1SUt ztqpYG1pE_-^jJx4SA%4`_y|K4$F79pc5(&g`(nG_)~fI51E|hpeN@vC(AJlVMK^lX zbU0XPla0y^d1`C*CKHB~92?o1YP+*(kL+0l57UhkPm*%5k79%4qjfXcA_GJY`YFzL zCR4bC?b&S6rPtC{X_?oGrG}L``OhQAfI1wQaeV(j&Z=`q0fR6B9*A6N&y8XRm1(}B z2p;={$c5eu9AV`2lmGn=h(J99TlZyu5oG%A`&5G9Kp0 zQl_olM4BSg&_cMCvWI#@)#tns$56w(m##ldd4h ziGjriGNJeay3xDupsd*OQ-M4@_V+Y@6_~$HD=z@z*e#$q_BNy*zjruUsPG3`f9R9A*JVwy$HhUg@bZP%?r$w2Yz@|Fv&lb)vtq};ADEgPfyGc| zZGRb>*Fyj}uiw6nCpN@cUTnb4Au10Cs0)|-p4l$Zd@Ir>y(L6}?ynm8sBcToP6{Er zYjEs(&y;dpwB4rA>CZ%XkPBVD(aa$W?g`M?={%i0f4+Jip8R_u`Kc!N$lhP4oRa)L((SY zgzY9N_0qNL;$gqB5RygL=!IGtKZo*XtLAS3(uj0jiEBsbm#OB>7y!@L&oGmB^x3%a-}B?d2b4<4z^W+^n#{@Ptz$t0MV>qt_w?KF^gV=G??<7mUX zc)Jq~VrJO()|#TcbccSjxjjDmFV@ZzgMXcRUX5@C=vNd}YtVLBW&=Lm_4ILTPutmO z36Ij1-cJ8sQqqFL<-do6q z8NkgnvGv||GV9Zu{@iPKgBc-a3W_d3Jb$<|(cQ>^XVOyFht@D}&QXk*72}LDm&?8x zq-&00t^S&6E*OnUJ$_o+_H(7Ix$!d>Cch6zHwb+57whG5j5D0a_irOQK}-|6&(0qa}tyklC+<%WYdA*&|TG!XmBykw*X7cbWv(iH>> ztW{sEI8XQZ{fzfFBDTLzTYqKf{eWsc!Wq)~-P?FZG&+i9I*e%5kR4&9`A91W_N`$H zG9;>WWqGwtgM^|Pf9%sUc#*Yet}}tK*3R$^bV#quVFr~6GnmVJd$7>Tz1(?jd4GQR z{r7`xZt(hL`Ah;OI z(`DkYvWexKAqn=T+^+Vkvuui|&meKQ>^uUmRPcVO72;pFC0sS+OUkM+;V=ZU#=~Rr3 zxuI{#n9I%5nXWo1h|gMFFOa94=qR?c#d`?Y23v=N_GW>2lZ0=$8-&8rJZhxzj!BnB zUu-AigvprS8$S3QX4cn}D!TXUP`nHPV7$C}TOCIvL|as$F6Z0*TE)I&A0nOf(~I3wl~k!v0}#0 zRK~+oe^2tK2HXRX6!&Y9ycz*OdG+pXEcJ0Xa+gg(w1%EHH0@P2_`LK1h+P(We?5O% zsUO6@P$|#!0g&g{Z^MWz%6`IkadpL&x?@1=o~vO4*$IfnfaP?s=Lu&quQD8}%h9GM z5yY^F`py9B?GX_3vwOza?5ql-v*~)Uk&Ph+%%H#5wAK&(i$Me%njj?eE4MVSMgTxw zy?Yxkn?eS)Ai}XpP^|SEa+)FTWrHl!Ll2inX?VnU3yV#J45%2UBiWmqQ{AY zu_Q`+r;rgdolVLp+`)|G%`%mFZe4$VNUwhI-vZ_@4Cx)vJBIWwZ{9|7U~p5zZ?7e9 zD~$O0F33Wk73IB_?9!e@LP9W*h)@dCo^Gb{hQ;Q7mzQv*5p2YLqEY^4Dj?Qwh}#}S zx76955=Hkpl0QA9_xphSb^gu)Iza!dk>K^)C{D2U3Uh}mglM>JN8v`oZi6eMiL;+) z16d?lw!bJFYj)?Y=9;taiUA|#Q#PR^Ln&cQB}kdpT9d)tMcM_(OI;aVjeCyb&z>QF zC5SK5^6v%mJ|*hEoo)GSC;;tuRRJKexy}fDnSeQ&GUar_nrLTBl+kdtSnH zwHJFo0sQ*;ZmJa?G4ZN?;fI)b8Kh$0alzd(`8RRO~B zXW<8^#yJ#>fMS%}QiMDsL_n$q z`Qc~Y{FKF=6WN-n=ep}cAg3J^u!P}lvB7O#IeJwV^0toN9|OqW)resJ0<>RCA-m_u zP0*uRikEtOx2y8jRPLtXx}3C3jU6@SxS{m58ExW&-3oWYEt~iR-Dg9o&CT~K2B(d7 z+#wp%k-uy1KqQrs=Qp9yFG=B_SI-vf3Gl_EWBC>k##6g1VkEx9!b>fi zu`7)sn#-Yzgq?AYPCEE-#I-D|pThBQ)g1di^lBRT1u}i8y}VYz`^*MPd8vf^A#UI5 zdd2hGPXOnuL0+?7?;}ysf6;4Y_0}$27fBAS%=!*uM7+!)L2>kA=0J`g<(A83r)$=6yYL zAaAfQn{08pmzN5Y$hqW|&}^Uk3_W$aTTT*aB;REY!*tAPC+{*+DXdqY=^9S^50%)Ny6*YG0-@c@L+8PvTSmpcbLaWbg#Ns@TxA z708Ic#VV)?va6cfd$@t=>qjR0@96`;E`xp4WM9jAwnH##2P{l$(3^Y6WYmq&az*Ek zN@QZ(6D^+hw;@80+990oIKDv-(#V4*Q!!|c7-FyET#0y8ft1^fu*2o%27Ngq{VIQ*^s#r-mR>Ti{tzOl$FZr6U0Yfzwg=u-SY{vr2BYSK+KBly+tJri!_jQg4|Y3l?xv0997>i# zY>j!`4Q6AXTr{-VEBGFjyuRQ${MK|51+JTh(BU6gwJFvxHas!W*>m2x%?Vjo_ez=`eX`u z$j*o9P(K~GI*9!}Y9OBdE@X1n)#WDNnKe;YjA^S^8fC)@jfiZGj8asSafjXwK#f4B zkB(h-yCc!=j9eIpv5Ig?==+_P_HntLV6KY9QDs5fUpcpJ21 zjoM+y>%P7FIhb7!bWybHPv1t2l?*Lk5F=Xfngp1hW@!hKkl{MmV7BO>;$rS>m+=(B z7Yz&qt0yg2##|5)UP90)n?JV%H<>6I9}|DwVx7nFpq@!mNH0t5;{#>-aWvaB;S@@@Lv1c{jMe`4LJ`<4po+go2@hl4!S3+I+ptB$7L5@aDbd8R zK?veV>n=K`H{W9IBJD@K-3~WfDd1^%p$lVqtEhS?t!90)RJ#@xbapWuDoDQ1lr=s_ zQOTPiMsgFB{te#A-&H@rvr6KB8*l`yWvY+_JmYHFj^(9BzyyI2JMb!6h37}`4f&K$JHSt}tqEH+>ho#XZJCSLe| zI(A`@>rvHb%GH09>U|pVGm4+Sej7?_vK-Gxja}4fi=aPUyOHmr)pStwZMwDgw4RNI zvV&){CNe5u%h3>yTl0u6PY6)v9b0Cz-DszK$wnlY91m%iX{yEWx%K?jH8EeD1y3a> zzsG`JjrJMBtFPXMkDqqOgx&DqiJ?WYm*v7fD8lxjpLio?(A%Z0$%M8y(mYvl9a3lw zsP1-|jXK2;1W39|H5uefgi%_{g*+k_o$cPD9rq?|@|`9gZ}Yq&yNVHi*VOObrTO2o zqlXfc-vi%ytk2+`zjzzE=Atb5K}k=`(1@ zkKcx@NKKbVB5FD4v=%W-TI51mVap*#G-nCZHCoFs&MhKD(yhFsn7-)8#=clkdJ;&K zRClMVhy`wk#2*-YN^7Y@+w2EK9$zM4Qbq}&H`6}E<-p#po5U(LSLQFm7 zmKo2-jTH2Fo7nDN>$RI=SO%-6KH1IolEZs27L0qn#+u7?Yzu+>t*$oPGHY6<`z;}F z6qNB?&A`3?pI{vi*|2p0?8A$*DwpP7)c@x!(mxM&!R_-mZ)+Pd#KrAq-e-dLjv5V` z;TBPQOM$nB3WtvqLn;!BSOYI*6Ss(&-M|W5MKmGlEHZh%9n3kuH_u>aPc0-2WwMP# zPW!v(uE`-F{5~tu|i2N8?UIeMar{`P-l^ra`N(WmB%%(AlME3RuEwiqsGjpW-AF zUQ?ibA~KT3gr81we&1HMF};EneLEa>!xU*vV0tOZ-P{+^wzixX`<*~O2kmFu$+vY4 zG*pMwAgcOy-?NAyyW<=31HGJ2WC0cxb+B_?(RsbMHt+J{4@_$xW)Q!^thwJ9gASK{vRo_m> ze7oa!HBdE9RUW8%WbQ{v~JoSo~pFF(3=Z(LtlmxJg2=Ed)j{_H5cV$Sz- z?Bvak6>WdhoUZbjqMKSCqO? z^F=8m6iX~Jx9Q}nhi$bc4;r#CTgg=WosE~LD(EpOqP__R|Oq8I!i)!Qs3!KIRx7Rwnfg#tC5QZFHNaIn<4yv2{y5ognevhq(0&htPm3%Sf86 zNnRLG*h}U8sZiIC|2@T@tGQ<$pXbhBi}GQZ?+`wG{5HBHcRN*uSrK)28_~m7kqB`j z9JEcZ93vvGfKJ*R&gSBpr-o)D)*UQT+qPgV`TmA7Cg5n1-g4UqTeF3|Z8Xc}bj7#P z8{hQ10Q1jZg#UJYp9IPN_N;p?N7Xp@5UxId8{%HBiAif$Zj1hEm=ar|(FC<8A;h}* zlpGClZaI;+NMk}O2|R>%kl)ozIN|B(dJb=(@lu9Gui*}H9Gk~*iA>grK#MOG_$OQI z-w1Iv4<4M~U#P&xL2ki4e)u-Bd`u~YVhakUxxQMI%y4g)u(X@L5+69gmk)BiN{1Iz@puVmO+SOzMW9t7kTi&Rv1Jc+*8^m+iyhl*&C8 zj09=NZaPsozi~7!Y&lEgmp31dfuCom3tpY{T5;fV= zV9?<=#0pNJ1!GyNKBwc>s;M%&QMPsmlWCd}QyDHir5ViA4*KJw2abo<zdEU(Z4Tn=VR>w zZ>j-4j-*~oTv4XD)EO`H4DXEk9M#Yvq7*jE2x{)R?tUs0kr3{1XOf4zX|zz(PM4Ot zjTWk5J~AIneL6^+hQh`snQu}kE`Z!&4_u|Q`abpvs$;-a`=f@tvg`i^(k}3C@9A^R zgfI%i^Uv=YXwZX(_y!I!KHton7W&VF2wvz{w)s5R$C2!7hPU>awE}WA;oUUoK~5*c zm}M+z>2k53NTcm^6Lo1yS|>e10cRWJxz?=p%6t~UCke5xq}7S;bhKqWk&^_n?WVncj06q-92DvE{}vjn9TKIU{H%VB?x$(5KFavGahcRJFfyxDK(Zoy| zEQFiVbT}N)Foua7itMqH-gPAuRAT;}26PAAJ4x$Rp2ia{XLh1joig0i1V`c?_yLwq z4{R?Atilg4`@tZUZTK`U=l+o4~6qHtNJkGirw6g{~t3RU!aC%tcq@KFd zM&n>I*?UvB<&IaPXz%uplrY#_j=|aTT9)nQi7BMMGH3LJgqUcgy>bDbsK6;jq!#fi zHba~p>$3(uchxH%)xX9n_x!Kc`S*{(s~S@R$V~l_XI6W^XGMHhH!frWK$kZMU-~sP zerrs&TE<90gxDCfz|#trQHL4~yX3s8z9|~sK$@X*wYQ@NYg_l7mNpPfM=6qSQ|fJi z*~fB~#`n>@=h8FK8*XD7ub_G5on0)>84jbGMSb&1(t)M=lsISFiIpmK!klVVU3xC; z_e%sqF9LL3m6Cdl5Oi?IK!k~R6>apw^bxFvI@fC zuyHS1rZ++NJ4^203f6%iUqq|?08Wc%$B%r_D!%r0J1F~Sx;0wocfdujrp1?Nfh;j^ zB)bxyz`5ygFds2RAPgm_Ip6eI-3)b*_0P1oPDo}EpSD^naiHY>Zig`8%4?^bqNY~i zq3mweo>JI&!^6t$nV1)}o|&D}lM}USwR_Jasv6dP-5~5tk~^W2?c5hkyK4EqX7` z`+0~LYVuYiEYSSw0ZerV@vqMfky#-WnTHPKuSIsYcFO*g8_nBgix`5lAm>~_Y8`X3 z1BGMc80N>rwKmsM5idZaR&#{nGiU>4jgTbCaE!N|@z@Z^l}7e)7T$uhUE6~N^T5D7 z5!uMBLun6qQ2}u2()_mZJrX@Iq^4i@#CyZ+l8v^s(-oz^4}m7~4N1nQNE;-m2d2)C z_bQWg*ohX72ZOR>!cC*ul7;?~0;hxjkG)J;0 zbfnWo^%%!Tfeu~_1R9>-0P+6N2LewAzVeigj!_KB_SFzaW?pBiKI-SLL_r>d*tBcM zr%*Zq`e)u)P|#t}PGkMUJ-N+QlnZS(n{W%g>=psI4A3n*u>=3xq3b&cx}&#Y`HQ`d zWd9hMuXfNb!H=WC2Bj9kAp;(C^ZabkgE#@J+>cCl)5`FJzJqnx{@7Fg`0$rf5XJVd zY!MjXT0_7$e}D__f^{MBbb9y;uA}^a!AP~5_}4$LI{2L>{rP(2D4^B7{B>wke|m`e z|M5Ov$Ky&iP{=p$weZGq~153B0fl0ajpbl~(uT2UX2>N2$6vs=PuqJTF zQ&#Z^E9KpSNF00MDg{q(rs1GDlG=@~zQPo~Bd?krA2k0>3S=CGd?@8}d6u&-EA)oe zdeM5c#q@+vwl7EJhh8K)Si*s2#FZ@EggUEu_*w1VwY@-eZmCz?`urJ~sosjUJG7b% zA$B=eHo>sm2Kqp;R^im0P&;O#=Bwdo7?>E+YYphxBA<(b=5z;|Z8=Vpc702q6N;;d zxHg!|Apgo1$RL=H{^n}#Qd;$d#X;aI@)HOCT7lo@?2%~2(BsQm@ZNCUhv3Ac4lxee z@r0qs#=;TIy~ZWMR_bg^c(3e}F)Hy~SJ@Cv2vx<-#G89l4J^nIvoUPyh_ov65-tS{ zCzEx9jnZ8&f8eA(;YxjUfL?^vIySgALAPS}BkquLOS|IH?I-U#M=QT-flBJ*# z_BKj?+#X`+hTjgw6}8xmFw-kqcthB2+l^)1_VP{9e%TuPH#xXBPTUdN-{j=}*wDY( z$$jF$;+G>5fM;0ef<%G;kpv&ARfVO}YBQv2DGw4znwNDexVGNajKD9z%vaZH*0BZP z{GD_PT$6?x$Q$^$X3~eIob4JodFwkx{LWjw{&Dq7aC%hbUw`+*ryBehUPro#`Y&1k zZP$NKzAJoqcXDCD*1&m$dZfEHSCu{81vxwV2k^(iz1>s!A6xI=PzEZ0^Zwn*Z9Ww; zJ+r{t#xd79U*LR3>_^(TPr3^46<~eJ6i6eZ)y9a0bjpv*_SQ~XvV))tVqqhmTr$-$uFK^{GyJ0O-~{J&#gPZEtv1 zN-Too&`pTiY(`KP=}U3FRs<=~k$!`KXT+#AXL_qfC?c&UIOxP!z~gxca9gXvGw<8ePoI)2KoIdcZPHObW6L;ZiUZ|C-$^*MN@jwAjPkggO{aI#Pd<%)PdzS6Y2xdVpKJP8fL0G%`^twkI)T5Q9Sx&J zY4VoQkr^t?<8f^7yaeV{5<%bz4=?uvr{%0Bt&H-^b_X}Yz23$K_HqgN#EK8%sT&K{ zP|e0!%hUW2^eOK4%m<;vGqC^vpB=9OI_drEiTP*Fj!%rY6>M!#hy1{9SI5GAeQQBI z60M~1_!8I_K3m39Pa2QD0l_^aoYYLXC-)S-A>yy75)FZJ?RY$Trc=)zXN<%rFonv zg6~W>P^!R~?$3-iV>f@>-|_2`vd{p9?7-gv3+;)Vc7 zaL~XxN8$1Q!3Oz>4@YML-07>?5=6r)i~gOnbE-6;^+$nCBi1wU{09ypKmae>(ob}v z3Oj=Y`LRxnztaep9$VSnPs4%9-X zOOYQb*nZXu{8hf}qx+@jiNQpj8ces*<>}BEL5miNfpgkXax>`4J$LjfNdH(s56|EO zC$NUNI(F&nTWhzcY`%i#IM_X04#S_c;BA+v#-Sp62Bmrfrq9adf4SDzrey=|q!KD4 z`9#?a*mS%JMb&helv_Y4#X+f}Zu;%%N}&VNFt90EF2fdOGW+#4B!0>`M+CzD5|A-;4_@bS7q5%m7R9^GL(Yvr*tU_ODLI^lva1C>_l+!@} z6>dPtv^q$!QEz1IaUSWD8ZeL%H67mD+z1%_J)*1D-;w_P+hs3t+MfU`oM@k z*gvppW}v=LQ2_G~cU7nLK`nk&cGA2qGljG0H$ifU};!gA)Z5^E*BX?xHx^MO2O z)^@+uwX$H?7_~RdfPvy=EaTu9$ni-)qM2PVJr z_b!6<71R!7k4PQffb5fMk@^xHKM(jm9D)9~zTe&L)&vNCO?f&_cccAoJw(Vx0FGK1 zj>qOyPA$~P^1*H_5WP*v&UPb`;TmS!8x?&x16e7Kpii9Ma`0*i`B)uKn?|*!RS$4s z2+*`j5OeErpd>gr{F+_hTacJ+f%(Hd?knG>?;O6bDuWJDzsmc*^^JiYP%T}p4l#VF z$(M!4N$mjLPm76r`}~H|dM91AdcJdI8`$~MeGuGuwA5>U`;lYe?hkPzI>47cj|~cr zsuS;DiqTNRSrdgq9Y>&@-V&&pI03z|IelS5p@_MhnaJ79sH7{;2VvIV7uj?UvRfU5 z+t6cY;Zu7vV;2I@e*>%~TZ8?e|Knl=p7LRJSarPODb?w4>gZc*3;@lOa-?dhauKJm z=x#;y$o}djaM`L^=q1DPeg>MWLgG4ypn1Q=?&sPrp3qJKxc9ImZPO*oMh zf+x0+w`)Mll`-tPgb>gz-HV4o*jB-6e7G@U(pvwG3I`BA0{t%QmWJR!%PP<0?5F_^ zIUK_KQJo)s%rU7{`>QkMC1c|oC`&qKZ-Cq@pvqMk9N6(nXfAHiUGR~SjK*z%KBPw5ApJ+ypf&c542x>zyrRpo_M+^MDdDjNAJ7;{jbjQJhbWgRl~%T1`V$S%h7I0s8^nue36 z%ps)Tz+e?#Y}L?f;T~+^URN*J0mV4R#_+{m!hq($?YO zps}6+AKU=J!b8&CEn|S4b8Qzyp$xmqC_dD2U98briJt1+_pa%cK|7PUtA{VMEfKEhaJ=onbyvyM8gU zHl;tr-IRK@L;2We2B6(v8vgOu?LrVp=t-I{j_`Lu;!~plRdx^c_3e7DJ_#Qna=xO9 zHhFcP<{!Wv{}j%?Tvf+q4~d@#=lkKcnjNchq}A)~Qy93WeDSTW#y?%HrJ-wArT!P{ zPp{X#FgYyvs~dTGX#hgXk*#TZ6-7Bbf)kd4F!8*C^2xGO=&YZH*s78}55ydWKCX621M;X<{m5Aw+GiR9Nj zr1xgrUpW7rO!2*G@76efb=s>bU(I&)dyskuY~C9S%-uX))4P}n>{T3Z(7l@AnmR7* zogw0SSP})sH^uo7>=t62G)3bXj}Hge(a{>Be zC&i>g$}C+NO@@nk3sy&Ki)uC*4R-0NfR)Su2M6y=d>CzrlCm81#QrNdp8FifaL6BE z6S~@%`KsET$}gTT=C9liP@PlRgn#|>?ajwH4sLreRj$(0D9(?R7@vq9G_9r&qBw6A z7f(A)kL5t433%I`c7>rHP4yjJ&~t1swHgdLQ9zTmsc25S`!FYrE|n_VrqL^lknEUK z4stTiTz8;!*;L1hj-frb58ocOd8u+caq>xK*5@b=a#JVtd!sm~+Xep6PXPYv$?nei7G(;^s-J0K;CGgCzmd(5}S63mHWZEGn}M7fk7?9>Nc9J5<=t7*p{ao zbCO}9*VDimSsTl;{1O{a?2aL6)EwsLVAq6}yfIvmLdKNg?cqun=$|gaj_byIY^frV z7ti!vt^j?gXdcv|dIh2`Rr&VInC2Kx=i9MMM)MIA@98Etv65ZE&bZL_7_Vxsm@f#I z^FjA9MJ(57sW0HAO1RiaZ0$uXhRSI%7__ED!lo%V?fP7YeiR0K!jcrMY942Bf;iMU zwD~qiYLXR0>KA|?RW$1*Kf(d%pYJGXKkhpFwynBzYFBb7g$%eZ)hA#oUrthIvF>GE zeLl{XZP2@>J)VqE9%(q{5S3v=-I#2fLbJ8GC*6GnQ7>)&i|_<6Y`3x3It3ZTUaO_l zWfFMIUQGr)PSZ#Hts4G)oxew#fWgOCz{#oZ=Ou^1E+hrT>V6f57&q1eNZ3TldJQcQ zYu8vtZ5D3L3Md+{vIP-+a0FmS0J-Sj(NV#kp7w_;6a zkM^<$Q#-<7ALcA}z$6|7ss84opw-e5EFi9{Ft2}eT7RC(Jij<&*BFCX!1q7%6Tjw_*�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 diff --git a/Wave/package.json b/Wave/package.json index 0fba23e..afd4350 100644 --- a/Wave/package.json +++ b/Wave/package.json @@ -1,18 +1,38 @@ { - "name": "wave", - "version": "0.0.1", - "scripts": { - "css:build": "postcss -o wwwroot/css/main.min.css wwwroot/css/main.css" - }, - "author": "Mia Rose Winter", - "license": "MIT", - "devDependencies": { - "@tailwindcss/typography": "^0.5.10", - "autoprefixer": "^10.4.16", - "cssnano": "^6.0.3", - "daisyui": "^4.6.0", - "postcss": "^8.4.33", - "postcss-cli": "^11.0.0", - "tailwindcss": "^3.4.1" - } + "name": "wave", + "version": "0.0.1", + "type": "module", + "scripts": { + "dev": "vite", + "check": "tsc", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "author": "Mia Rose Winter", + "license": "MIT", + "devDependencies": { + "@fontsource/noto-sans-display": "^5.0.20", + "@fontsource/nunito-sans": "^5.0.13", + "@tailwindcss/typography": "^0.5.10", + "@types/node": "^20.14.2", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react-swc": "^3.7.0", + "autoprefixer": "^10.4.16", + "cssnano": "^6.0.3", + "daisyui": "^4.6.0", + "i18next": "^23.11.5", + "markdown-it": "^14.1.0", + "markdown-it-mark": "^4.0.0", + "postcss": "^8.4.33", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-i18next": "^14.1.2", + "tailwindcss": "^3.4.1", + "typescript": "^5.4.5", + "vite": "^5.2.13" + }, + "dependencies": { + "groupby-polyfill": "^1.0.0" + } } diff --git a/Wave/postcss.config.js b/Wave/postcss.config.js deleted file mode 100644 index b6d05b3..0000000 --- a/Wave/postcss.config.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - cssnano: { - preset: "default" - } - } -} diff --git a/Wave/tailwind.config.js b/Wave/tailwind.config.ts similarity index 97% rename from Wave/tailwind.config.js rename to Wave/tailwind.config.ts index 8c204ab..c2bd463 100644 --- a/Wave/tailwind.config.js +++ b/Wave/tailwind.config.ts @@ -1,9 +1,8 @@ +const defaultTheme = require('tailwindcss/defaultTheme'); /** @type {import('tailwindcss').Config} */ -const defaultTheme = require('tailwindcss/defaultTheme') - -module.exports = { - content: ["Pages/**/*.cshtml", "Components/**/*.razor"], +export default { + content: ["Assets/**/*.{ts,tsx}", "Pages/**/*.cshtml", "Components/**/*.razor"], safelist: ["youtube"], theme: { extend: { diff --git a/Wave/tsconfig.json b/Wave/tsconfig.json new file mode 100644 index 0000000..ea94063 --- /dev/null +++ b/Wave/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": [ "ES2020", "ES2020.Promise", "DOM", "DOM.Iterable" ], + "module": "ESNext", + "skipLibCheck": true, + + "moduleResolution": "Bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "typeRoots": [ "node_modules/@types" ], + + "strict": true + }, + "include": [ + "Assets/**/*.ts", "Assets/**/*.tsx" + ], + "references": [ + { "path": "./tsconfig.node.json" } + ] +} \ No newline at end of file diff --git a/Wave/tsconfig.node.json b/Wave/tsconfig.node.json new file mode 100644 index 0000000..32a7def --- /dev/null +++ b/Wave/tsconfig.node.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": [ + "vite.config.ts" + ] +} diff --git a/Wave/vite.config.ts b/Wave/vite.config.ts new file mode 100644 index 0000000..28b70b2 --- /dev/null +++ b/Wave/vite.config.ts @@ -0,0 +1,52 @@ +import { defineConfig } from "vite"; +import tailwindcss from "tailwindcss"; +import autoprefixer from "autoprefixer"; +import cssnano from "cssnano"; +import react from "@vitejs/plugin-react-swc" + +export default defineConfig({ + appType: "custom", + base: "/dist/", + root: "Assets", + publicDir: "public", + build: { + emptyOutDir: true, + manifest: true, + outDir: "../wwwroot/dist", + assetsDir: "", + rollupOptions: { + input: [ + "Assets/css/main.css", + "Assets/main.tsx" + ], + output: { + entryFileNames: "js/[name].[hash].js", + chunkFileNames: "js/[name]-chunk.js", + assetFileNames: (info) => { + if (info.name) { + if (/\.css$/.test(info.name)) { + return "css/[name].[hash][extname]"; + } + + return "[name][extname]"; + } else { + return "[name][extname]"; + } + } + } + }, + }, + optimizeDeps: { + include: [] + }, + plugins: [react()], + css: { + postcss: { + plugins: [ + tailwindcss(), + autoprefixer(), + cssnano({preset: "default"}), + ] + } + } +}); \ No newline at end of file diff --git a/Wave/wwwroot/css/main.css b/Wave/wwwroot/css/main.css deleted file mode 100644 index 85a0d80..0000000 --- a/Wave/wwwroot/css/main.css +++ /dev/null @@ -1,58 +0,0 @@ -@font-face { - font-display: swap; - font-family: 'Nunito Sans'; - font-style: normal; - font-weight: 700; - src: url('../fonts/nunito-sans-v15-latin-700.woff2') format('woff2'); -} -@font-face { - font-display: swap; - font-family: 'Noto Sans Display'; - font-style: normal; - font-weight: 400; - src: url('../fonts/noto-sans-display-v26-latin-regular.woff2') format('woff2'); -} - -@tailwind base; -@tailwind components; -@tailwind utilities; - -@layer base { - body { - @apply font-body; - } - h1, h2, h3, h4, h5, h6 { - @apply font-heading tracking-tight; - } - hyphens-auto { - hyphenate-limit-chars: 5 3; - } -} -@layer components { - .youtube { - @apply rounded p-2 bg-base-200; - } - - input.narrow-reading-toggle { - display: none; - } - body:has(label[for=narrow-reading-toggle]) input.narrow-reading-toggle:checked + .reading-toggle-target { - @apply max-w-3xl; - } - - .fade-away { - -webkit-mask-image: linear-gradient(black, black 80%, rgba(0, 0, 0, 0.5) 85%, transparent 100%); - mask-image: linear-gradient(black, black 80%, rgba(0, 0, 0, 0.5) 85%, transparent 100%); - } - - .prose div > pre, .prose > pre { - @apply bg-inherit text-inherit rounded-none; - } - .prose pre:has(code) { - @apply border-2 border-current; - } - - .characters-left { - @apply absolute right-6 bottom-6 select-none pointer-events-none; - } -} diff --git a/Wave/wwwroot/css/main.min.css b/Wave/wwwroot/css/main.min.css deleted file mode 100644 index 6a4bc3b..0000000 --- a/Wave/wwwroot/css/main.min.css +++ /dev/null @@ -1,3 +0,0 @@ -@font-face{font-display:swap;font-family:Nunito Sans;font-style:normal;font-weight:700;src:url(../fonts/nunito-sans-v15-latin-700.woff2) format("woff2")}@font-face{font-display:swap;font-family:Noto Sans Display;font-style:normal;font-weight:400;src:url(../fonts/noto-sans-display-v26-latin-regular.woff2) format("woff2")} - -/*! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-tap-highlight-color:transparent}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-size:1em;font-variation-settings:normal}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-feature-settings:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}:root,[data-theme]{background-color:var(--fallback-b1,oklch(var(--b1)/1));color:var(--fallback-bc,oklch(var(--bc)/1))}@supports not (color:oklch(0 0 0)){:root{color-scheme:light;--fallback-p:#491eff;--fallback-pc:#d4dbff;--fallback-s:#ff41c7;--fallback-sc:#fff9fc;--fallback-a:#00cfbd;--fallback-ac:#00100d;--fallback-n:#2b3440;--fallback-nc:#d7dde4;--fallback-b1:#fff;--fallback-b2:#e5e6e6;--fallback-b3:#e5e6e6;--fallback-bc:#1f2937;--fallback-in:#00b3f0;--fallback-inc:#000;--fallback-su:#00ca92;--fallback-suc:#000;--fallback-wa:#ffc22d;--fallback-wac:#000;--fallback-er:#ff6f70;--fallback-erc:#000}@media (prefers-color-scheme:dark){:root{color-scheme:dark;--fallback-p:#7582ff;--fallback-pc:#050617;--fallback-s:#ff71cf;--fallback-sc:#190211;--fallback-a:#00c7b5;--fallback-ac:#000e0c;--fallback-n:#2a323c;--fallback-nc:#a6adbb;--fallback-b1:#1d232a;--fallback-b2:#191e24;--fallback-b3:#15191e;--fallback-bc:#a6adbb;--fallback-in:#00b3f0;--fallback-inc:#000;--fallback-su:#00ca92;--fallback-suc:#000;--fallback-wa:#ffc22d;--fallback-wac:#000;--fallback-er:#ff6f70;--fallback-erc:#000}}}html{-webkit-tap-highlight-color:transparent}:root{--wave-heading-font:Nunito Sans;--pc:0.180887 0.036283 105.052616;--ac:0.164005 0.020628 219.654428;--nc:0.136569 0.027089 105.04608;--inc:0.130481 0.033356 249.181093;--suc:0.155205 0.051559 141.441374;--wac:0.187418 0.039766 105.010469;--animation-btn:0.25s;--animation-input:.2s;--btn-focus-scale:0.95;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem;--wave-body-font:Noto Sans Display;--p:0.904433 0.181415 105.052616;--s:0.844147 0.091903 1.145315;--sc:0.159066 0 0;--a:0.820026 0.103138 219.654428;--n:0.682843 0.135444 105.04608;--b1:0.979009 0.008213 91.481779;--b2:0.829552 0.021252 91.613791;--b3:0.657213 0.03418 91.110572;--bc:0 0 0;--in:0.652403 0.166781 249.181093;--su:0.776026 0.257795 141.441374;--wa:0.937091 0.198832 105.010469;--er:0.48269 0.196179 27.62926;--erc:1 0 0;--rounded-box:0.2rem;--rounded-btn:0.2rem;--rounded-badge:0.2rem}@media (prefers-color-scheme:dark){:root{--wave-heading-font:Nunito Sans;--pc:0.188058 0.037706 104.932014;--ac:0.170394 0.0215 220.006723;--nc:0.136569 0.027089 105.04608;--inc:0.118647 0.036441 252.872278;--suc:0.110432 0.036439 141.138418;--wac:0.170992 0.036177 104.408029;--animation-btn:0.25s;--animation-input:.2s;--btn-focus-scale:0.95;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem;--wave-body-font:Noto Sans Display;--p:0.940289 0.188531 104.932014;--s:0.754158 0.080841 1.060979;--sc:0 0 0;--a:0.851972 0.107498 220.006723;--n:0.682843 0.135444 105.04608;--b1:0.223295 0.035604 1.967265;--b2:0.160428 0.018448 359.8262;--b3:0.149116 0.005595 355.678569;--bc:0.940422 0.025515 288.31809;--in:0.593236 0.182207 252.872278;--su:0.55216 0.182195 141.138418;--wa:0.854959 0.180883 104.408029;--er:0.310766 0.125346 26.370357;--erc:1 0 0;--rounded-box:0.2rem;--rounded-btn:0.2rem;--rounded-badge:0.2rem}}[data-theme=wave-light]{--wave-heading-font:Nunito Sans;--pc:0.180887 0.036283 105.052616;--ac:0.164005 0.020628 219.654428;--nc:0.136569 0.027089 105.04608;--inc:0.130481 0.033356 249.181093;--suc:0.155205 0.051559 141.441374;--wac:0.187418 0.039766 105.010469;--animation-btn:0.25s;--animation-input:.2s;--btn-focus-scale:0.95;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem;--wave-body-font:Noto Sans Display;--p:0.904433 0.181415 105.052616;--s:0.844147 0.091903 1.145315;--sc:0.159066 0 0;--a:0.820026 0.103138 219.654428;--n:0.682843 0.135444 105.04608;--b1:0.979009 0.008213 91.481779;--b2:0.829552 0.021252 91.613791;--b3:0.657213 0.03418 91.110572;--bc:0 0 0;--in:0.652403 0.166781 249.181093;--su:0.776026 0.257795 141.441374;--wa:0.937091 0.198832 105.010469;--er:0.48269 0.196179 27.62926;--erc:1 0 0;--rounded-box:0.2rem;--rounded-btn:0.2rem;--rounded-badge:0.2rem}[data-theme=wave-dark]{--wave-heading-font:Nunito Sans;--pc:0.188058 0.037706 104.932014;--ac:0.170394 0.0215 220.006723;--nc:0.136569 0.027089 105.04608;--inc:0.118647 0.036441 252.872278;--suc:0.110432 0.036439 141.138418;--wac:0.170992 0.036177 104.408029;--animation-btn:0.25s;--animation-input:.2s;--btn-focus-scale:0.95;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem;--wave-body-font:Noto Sans Display;--p:0.940289 0.188531 104.932014;--s:0.754158 0.080841 1.060979;--sc:0 0 0;--a:0.851972 0.107498 220.006723;--n:0.682843 0.135444 105.04608;--b1:0.223295 0.035604 1.967265;--b2:0.160428 0.018448 359.8262;--b3:0.149116 0.005595 355.678569;--bc:0.940422 0.025515 288.31809;--in:0.593236 0.182207 252.872278;--su:0.55216 0.182195 141.138418;--wa:0.854959 0.180883 104.408029;--er:0.310766 0.125346 26.370357;--erc:1 0 0;--rounded-box:0.2rem;--rounded-btn:0.2rem;--rounded-badge:0.2rem}[data-theme=modern-light]{--wave-heading-font:Tahoma;--animation-btn:0.25s;--animation-input:.2s;--btn-focus-scale:0.95;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem;--wave-body-font:ui-sans-serif;--p:0.379059 0.137761 265.522188;--pc:1 0 0;--s:0.985104 0 0;--sc:0.379059 0.137761 265.522188;--a:0.809069 0.095598 251.812784;--ac:0 0 0;--n:0.424445 0.180869 265.63771;--nc:1 0 0;--b1:1 0 0;--b2:0.966956 0.002874 264.541934;--b3:0.927582 0.005814 264.531291;--bc:0 0 0;--in:0.684687 0.147869 237.322518;--inc:1 0 0;--su:0.722746 0.192007 149.57933;--suc:1 0 0;--wa:0.76859 0.164659 70.08039;--wac:0 0 0;--er:0.50542 0.190493 27.518103;--erc:1 0 0;--rounded-box:0.2rem;--rounded-btn:0.2rem;--rounded-badge:0.2rem}[data-theme=modern-dark]{--wave-heading-font:Tahoma;--animation-btn:0.25s;--animation-input:.2s;--btn-focus-scale:0.95;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem;--wave-body-font:ui-sans-serif;--p:0.71374 0.143381 254.624021;--pc:0 0 0;--s:0.372927 0.03062 259.732849;--sc:0.71374 0.143381 254.624021;--a:0.809069 0.095598 251.812784;--ac:0 0 0;--n:0.54615 0.215208 262.880917;--nc:1 0 0;--b1:0.446112 0.026312 256.801751;--b2:0.278078 0.029596 256.847952;--b3:0.210084 0.031763 264.664526;--bc:1 0 0;--in:0.684687 0.147869 237.322518;--inc:1 0 0;--su:0.722746 0.192007 149.57933;--suc:1 0 0;--wa:0.76859 0.164659 70.08039;--wac:0 0 0;--er:0.50542 0.190493 27.518103;--erc:1 0 0;--rounded-box:0.2rem;--rounded-btn:0.2rem;--rounded-badge:0.2rem}body{font-family:var(--wave-body-font),ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"}h1,h2,h3,h4,h5,h6{font-family:var(--wave-heading-font),ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";letter-spacing:-.025em}hyphens-auto{hyphenate-limit-chars:5 3}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}@media (min-width:1792px){.container{max-width:1792px}}@media (min-width:2048px){.container{max-width:2048px}}@media (min-width:2304px){.container{max-width:2304px}}@media (min-width:2560px){.container{max-width:2560px}}@media (min-width:3072px){.container{max-width:3072px}}.alert{align-content:flex-start;align-items:center;border-radius:var(--rounded-box,1rem);border-width:1px;display:grid;gap:1rem;grid-auto-flow:row;justify-items:center;text-align:center;width:100%;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));padding:1rem;--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--alert-bg:var(--fallback-b2,oklch(var(--b2)/1));--alert-bg-mix:var(--fallback-b1,oklch(var(--b1)/1));background-color:var(--alert-bg)}@media (min-width:640px){.alert{grid-auto-flow:column;grid-template-columns:auto minmax(auto,1fr);justify-items:start;text-align:start}}.avatar{display:inline-flex;position:relative}.avatar>div{aspect-ratio:1/1;display:block;overflow:hidden}.avatar img{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.avatar.placeholder>div{display:flex}.avatar.placeholder>div,.badge{align-items:center;justify-content:center}.badge{border-radius:var(--rounded-badge,1.9rem);border-width:1px;display:inline-flex;font-size:.875rem;height:1.25rem;line-height:1.25rem;padding-left:.563rem;padding-right:.563rem;transition-duration:.2s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1);width:-moz-fit-content;width:fit-content;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}@media (hover:hover){.label a:hover{--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}.menu li>:not(ul):not(.menu-title):not(details).active,.menu li>:not(ul):not(.menu-title):not(details):active,.menu li>details>summary:active{--tw-bg-opacity:1;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)))}.table tr.hover:hover,.table tr.hover:nth-child(2n):hover{--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)))}.table-zebra tr.hover:hover,.table-zebra tr.hover:nth-child(2n):hover{--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}}.btn{align-items:center;animation:button-pop var(--animation-btn,.25s) ease-out;border-color:transparent;border-color:oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity));border-radius:var(--rounded-btn,.5rem);border-width:var(--border-btn,1px);cursor:pointer;display:inline-flex;flex-shrink:0;flex-wrap:wrap;font-size:.875rem;font-weight:600;gap:.5rem;height:3rem;justify-content:center;line-height:1em;min-height:3rem;padding-left:1rem;padding-right:1rem;text-align:center;text-decoration-line:none;transition-duration:.2s;transition-property:color,background-color,border-color,opacity,box-shadow,transform;transition-timing-function:cubic-bezier(0,0,.2,1);-webkit-user-select:none;-moz-user-select:none;user-select:none;--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);background-color:oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity));box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:var(--fallback-bc,oklch(var(--bc)/1));--tw-bg-opacity:1;--tw-border-opacity:1}.btn-disabled,.btn:disabled,.btn[disabled]{pointer-events:none}.btn-circle,.btn-square{height:3rem;padding:0;width:3rem}.btn-circle{border-radius:9999px}:where(.btn:is(input[type=checkbox])),:where(.btn:is(input[type=radio])){-webkit-appearance:none;-moz-appearance:none;appearance:none;width:auto}.btn:is(input[type=checkbox]):after,.btn:is(input[type=radio]):after{--tw-content:attr(aria-label);content:var(--tw-content)}.card{border-radius:var(--rounded-box,1rem);display:flex;flex-direction:column;position:relative}.card:focus{outline:2px solid transparent;outline-offset:2px}.card-body{display:flex;flex:1 1 auto;flex-direction:column;gap:.5rem;padding:var(--padding-card,2rem)}.card-body :where(p){flex-grow:1}.card-actions{align-items:flex-start;display:flex;flex-wrap:wrap;gap:.5rem}.card figure{align-items:center;display:flex;justify-content:center}.card.image-full{display:grid}.card.image-full:before{border-radius:var(--rounded-box,1rem);content:"";position:relative;z-index:10;--tw-bg-opacity:1;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));opacity:.75}.card.image-full:before,.card.image-full>*{grid-column-start:1;grid-row-start:1}.card.image-full>figure img{height:100%;-o-object-fit:cover;object-fit:cover}.card.image-full>.card-body{position:relative;z-index:20;--tw-text-opacity:1;color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)))}.checkbox{flex-shrink:0;--chkbg:var(--fallback-bc,oklch(var(--bc)/1));--chkfg:var(--fallback-b1,oklch(var(--b1)/1));-webkit-appearance:none;-moz-appearance:none;appearance:none;border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));border-radius:var(--rounded-btn,.5rem);border-width:1px;cursor:pointer;height:1.5rem;width:1.5rem;--tw-border-opacity:0.2}.drawer{display:grid;grid-auto-columns:max-content auto;position:relative;width:100%}.drawer-content{grid-column-start:2;min-width:0}.drawer-content,.drawer-side{grid-row-start:1}.drawer-side{align-items:flex-start;display:grid;grid-column-start:1;grid-template-columns:repeat(1,minmax(0,1fr));grid-template-rows:repeat(1,minmax(0,1fr));height:100vh;height:100dvh;inset-inline-start:0;justify-items:start;overflow-y:auto;overscroll-behavior:contain;pointer-events:none;position:fixed;top:0;width:100%}.drawer-side>.drawer-overlay{background-color:transparent;cursor:pointer;place-self:stretch;position:sticky;top:0;transition-duration:.2s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1)}.drawer-side>*{grid-column-start:1;grid-row-start:1}.drawer-side>:not(.drawer-overlay){transform:translateX(-100%);transition-duration:.3s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1);will-change:transform}[dir=rtl] .drawer-side>:not(.drawer-overlay){transform:translateX(100%)}.drawer-toggle{-webkit-appearance:none;-moz-appearance:none;appearance:none;height:0;opacity:0;position:fixed;width:0}.drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible}.drawer-toggle:checked~.drawer-side>:not(.drawer-overlay){transform:translateX(0)}.drawer-end{grid-auto-columns:auto max-content}.drawer-end .drawer-toggle~.drawer-content{grid-column-start:1}.drawer-end .drawer-toggle~.drawer-side{grid-column-start:2;justify-items:end}.drawer-end .drawer-toggle~.drawer-side>:not(.drawer-overlay){transform:translateX(100%)}[dir=rtl] .drawer-end .drawer-toggle~.drawer-side>:not(.drawer-overlay){transform:translateX(-100%)}.drawer-end .drawer-toggle:checked~.drawer-side>:not(.drawer-overlay){transform:translateX(0)}.dropdown{display:inline-block;position:relative}.dropdown>:not(summary):focus{outline:2px solid transparent;outline-offset:2px}.dropdown .dropdown-content{position:absolute}.dropdown:is(:not(details)) .dropdown-content{opacity:0;transform-origin:top;visibility:hidden;--tw-scale-x:.95;--tw-scale-y:.95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));transition-duration:.2s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1)}.dropdown-end .dropdown-content{inset-inline-end:0}.dropdown-left .dropdown-content{bottom:auto;inset-inline-end:100%;top:0;transform-origin:right}.dropdown-right .dropdown-content{bottom:auto;inset-inline-start:100%;top:0;transform-origin:left}.dropdown-bottom .dropdown-content{bottom:auto;top:100%;transform-origin:top}.dropdown-top .dropdown-content{bottom:100%;top:auto;transform-origin:bottom}.dropdown-end.dropdown-left .dropdown-content,.dropdown-end.dropdown-right .dropdown-content{bottom:0;top:auto}.dropdown.dropdown-open .dropdown-content,.dropdown:focus-within .dropdown-content,.dropdown:not(.dropdown-hover):focus .dropdown-content{opacity:1;visibility:visible}@media (hover:hover){.dropdown.dropdown-hover:hover .dropdown-content{opacity:1;visibility:visible}.btm-nav>.disabled:hover,.btm-nav>[disabled]:hover{pointer-events:none;--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btn:hover{--tw-border-opacity:1;border-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn:hover{background-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity,1)) 90%,#000);border-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity,1)) 90%,#000)}}@supports not (color:oklch(0 0 0)){.btn:hover{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn.glass:hover{--glass-opacity:25%;--glass-border-opacity:15%}.btn-ghost:hover{border-color:transparent}@supports (color:oklch(0 0 0)){.btn-ghost:hover{background-color:var(--fallback-bc,oklch(var(--bc)/.2))}}.btn-link:hover{background-color:transparent;border-color:transparent;text-decoration-line:underline}.btn-outline.btn-primary:hover{--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-primary:hover{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}}.btn-outline.btn-secondary:hover{--tw-text-opacity:1;color:var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-secondary:hover{background-color:color-mix(in oklab,var(--fallback-s,oklch(var(--s)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-s,oklch(var(--s)/1)) 90%,#000)}}.btn-outline.btn-accent:hover{--tw-text-opacity:1;color:var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-accent:hover{background-color:color-mix(in oklab,var(--fallback-a,oklch(var(--a)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-a,oklch(var(--a)/1)) 90%,#000)}}.btn-outline.btn-info:hover{--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-info:hover{background-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000)}}.btn-outline.btn-error:hover{--tw-text-opacity:1;color:var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-error:hover{background-color:color-mix(in oklab,var(--fallback-er,oklch(var(--er)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-er,oklch(var(--er)/1)) 90%,#000)}}.btn-disabled:hover,.btn:disabled:hover,.btn[disabled]:hover{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}@supports (color:color-mix(in oklab,black,black)){.btn:is(input[type=checkbox]:checked):hover,.btn:is(input[type=radio]:checked):hover{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}}.dropdown.dropdown-hover:hover .dropdown-content{--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:where(.menu li:not(.menu-title):not(.disabled)>:not(ul):not(details):not(.menu-title)):not(.active):hover,:where(.menu li:not(.menu-title):not(.disabled)>details>summary:not(.menu-title)):not(.active):hover{cursor:pointer;outline:2px solid transparent;outline-offset:2px}@supports (color:oklch(0 0 0)){:where(.menu li:not(.menu-title):not(.disabled)>:not(ul):not(details):not(.menu-title)):not(.active):hover,:where(.menu li:not(.menu-title):not(.disabled)>details>summary:not(.menu-title)):not(.active):hover{background-color:var(--fallback-bc,oklch(var(--bc)/.1))}}}.dropdown:is(details) summary::-webkit-details-marker{display:none}.file-input{border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));border-radius:var(--rounded-btn,.5rem);border-width:1px;flex-shrink:1;font-size:1rem;height:3rem;line-height:2;line-height:1.5rem;overflow:hidden;padding-inline-end:1rem;--tw-border-opacity:0;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.file-input::file-selector-button{align-items:center;border-style:solid;cursor:pointer;display:inline-flex;flex-shrink:0;flex-wrap:wrap;font-size:.875rem;height:100%;justify-content:center;line-height:1.25rem;line-height:1em;margin-inline-end:1rem;padding-left:1rem;padding-right:1rem;text-align:center;transition-duration:.2s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1);-webkit-user-select:none;-moz-user-select:none;user-select:none;--tw-border-opacity:1;border-color:var(--fallback-n,oklch(var(--n)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));font-weight:600;text-transform:uppercase;--tw-text-opacity:1;animation:button-pop var(--animation-btn,.25s) ease-out;border-width:var(--border-btn,1px);color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)));text-decoration-line:none}.footer{-moz-column-gap:1rem;column-gap:1rem;font-size:.875rem;grid-auto-flow:row;line-height:1.25rem;row-gap:2.5rem;width:100%}.footer,.footer>*{display:grid;place-items:start}.footer>*{gap:.5rem}@media (min-width:48rem){.footer{grid-auto-flow:column}.footer-center{grid-auto-flow:row dense}}.form-control{flex-direction:column}.form-control,.label{display:flex}.label{align-items:center;justify-content:space-between;padding:.5rem .25rem;-webkit-user-select:none;-moz-user-select:none;user-select:none}.input{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-color:transparent;border-radius:var(--rounded-btn,.5rem);border-width:1px;flex-shrink:1;font-size:1rem;height:3rem;line-height:2;line-height:1.5rem;padding-left:1rem;padding-right:1rem;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.join{align-items:stretch;border-radius:var(--rounded-btn,.5rem);display:inline-flex}.join :where(.join-item){border-end-end-radius:0;border-end-start-radius:0;border-start-end-radius:0;border-start-start-radius:0}.join .join-item:not(:first-child):not(:last-child),.join :not(:first-child):not(:last-child) .join-item{border-end-end-radius:0;border-end-start-radius:0;border-start-end-radius:0;border-start-start-radius:0}.join .join-item:first-child:not(:last-child),.join :first-child:not(:last-child) .join-item{border-end-end-radius:0;border-start-end-radius:0}.join .dropdown .join-item:first-child:not(:last-child),.join :first-child:not(:last-child) .dropdown .join-item{border-end-end-radius:inherit;border-start-end-radius:inherit}.join :where(.join-item:first-child:not(:last-child)),.join :where(:first-child:not(:last-child) .join-item){border-end-start-radius:inherit;border-start-start-radius:inherit}.join .join-item:last-child:not(:first-child),.join :last-child:not(:first-child) .join-item{border-end-start-radius:0;border-start-start-radius:0}.join :where(.join-item:last-child:not(:first-child)),.join :where(:last-child:not(:first-child) .join-item){border-end-end-radius:inherit;border-start-end-radius:inherit}@supports not selector(:has(*)){:where(.join *){border-radius:inherit}}@supports selector(:has(*)){:where(.join :has(.join-item)){border-radius:inherit}}.\!link{cursor:pointer!important;text-decoration-line:underline!important}.link{cursor:pointer;text-decoration-line:underline}.menu{display:flex;flex-direction:column;flex-wrap:wrap;font-size:.875rem;line-height:1.25rem;padding:.5rem}.menu :where(li ul){margin-inline-start:1rem;padding-inline-start:.5rem;position:relative;white-space:nowrap}.menu :where(li:not(.menu-title)>:not(ul):not(details):not(.menu-title)),.menu :where(li:not(.menu-title)>details>summary:not(.menu-title)){align-content:flex-start;align-items:center;display:grid;gap:.5rem;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;-webkit-user-select:none;-moz-user-select:none;user-select:none}.menu li.disabled{color:var(--fallback-bc,oklch(var(--bc)/.3));cursor:not-allowed;-webkit-user-select:none;-moz-user-select:none;user-select:none}.menu :where(li>.menu-dropdown:not(.menu-dropdown-show)){display:none}:where(.menu li){align-items:stretch;display:flex;flex-direction:column;flex-shrink:0;flex-wrap:wrap;position:relative}:where(.menu li) .badge{justify-self:end}.modal{background-color:transparent;color:inherit;display:grid;height:100%;inset:0;justify-items:center;margin:0;max-height:none;max-width:none;opacity:0;overflow-y:hidden;overscroll-behavior:contain;padding:0;pointer-events:none;position:fixed;transition-duration:.2s;transition-property:transform,opacity,visibility;transition-timing-function:cubic-bezier(0,0,.2,1);width:100%;z-index:999}:where(.modal){align-items:center}.modal-box{grid-column-start:1;grid-row-start:1;max-height:calc(100vh - 5em);max-width:32rem;width:91.666667%;--tw-scale-x:.9;--tw-scale-y:.9;border-bottom-left-radius:var(--rounded-box,1rem);border-bottom-right-radius:var(--rounded-box,1rem);border-top-left-radius:var(--rounded-box,1rem);border-top-right-radius:var(--rounded-box,1rem);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));box-shadow:0 25px 50px -12px rgba(0,0,0,.25);overflow-y:auto;overscroll-behavior:contain;padding:1.5rem;transition-duration:.2s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1)}.modal-open,.modal-toggle:checked+.modal,.modal:target,.modal[open]{opacity:1;pointer-events:auto;visibility:visible}.modal-action{display:flex;justify-content:flex-end;margin-top:1.5rem}:root:has(:is(.modal-open,.modal:target,.modal-toggle:checked+.modal,.modal[open])){overflow:hidden}.progress{background-color:var(--fallback-bc,oklch(var(--bc)/.2));border-radius:var(--rounded-box,1rem);height:.5rem;overflow:hidden;position:relative;width:100%}.progress,.select{-webkit-appearance:none;-moz-appearance:none;appearance:none}.select{border-color:transparent;border-radius:var(--rounded-btn,.5rem);border-width:1px;cursor:pointer;display:inline-flex;font-size:.875rem;height:3rem;line-height:1.25rem;line-height:2;min-height:3rem;padding-left:1rem;padding-right:2.5rem;-webkit-user-select:none;-moz-user-select:none;user-select:none;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));background-image:linear-gradient(45deg,transparent 50%,currentColor 0),linear-gradient(135deg,currentColor 50%,transparent 0);background-position:calc(100% - 20px) calc(1px + 50%),calc(100% - 16.1px) calc(1px + 50%);background-repeat:no-repeat;background-size:4px 4px,4px 4px}.select[multiple]{height:auto}.steps{counter-reset:step;display:inline-grid;grid-auto-columns:1fr;grid-auto-flow:column;overflow:hidden;overflow-x:auto}.steps .step{display:grid;grid-template-columns:repeat(1,minmax(0,1fr));grid-template-columns:auto;grid-template-rows:repeat(2,minmax(0,1fr));grid-template-rows:40px 1fr;min-width:4rem;place-items:center;text-align:center}.swap{cursor:pointer;display:inline-grid;place-content:center;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none}.swap>*{grid-column-start:1;grid-row-start:1;transition-duration:.3s;transition-property:transform,opacity;transition-timing-function:cubic-bezier(0,0,.2,1)}.swap input{-webkit-appearance:none;-moz-appearance:none;appearance:none}.swap .swap-indeterminate,.swap .swap-on,.swap input:indeterminate~.swap-on{opacity:0}.swap input:checked~.swap-off,.swap input:indeterminate~.swap-off,.swap-active .swap-off{opacity:0}.swap input:checked~.swap-on,.swap input:indeterminate~.swap-indeterminate,.swap-active .swap-on{opacity:1}.table{border-radius:var(--rounded-box,1rem);font-size:.875rem;line-height:1.25rem;position:relative;text-align:left;width:100%}.table :where(.table-pin-rows thead tr){position:sticky;top:0;z-index:1;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.table :where(.table-pin-rows tfoot tr){bottom:0;position:sticky;z-index:1;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.table :where(.table-pin-cols tr th){left:0;position:sticky;right:0;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.table-zebra tbody tr:nth-child(2n) :where(.table-pin-cols tr th){--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)))}.textarea{border-color:transparent;border-radius:var(--rounded-btn,.5rem);border-width:1px;flex-shrink:1;font-size:.875rem;line-height:1.25rem;line-height:2;min-height:3rem;padding:.5rem 1rem;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.toast{display:flex;flex-direction:column;gap:.5rem;min-width:-moz-fit-content;min-width:fit-content;padding:1rem;position:fixed;white-space:nowrap}.toggle{flex-shrink:0;--tglbg:var(--fallback-b1,oklch(var(--b1)/1));--handleoffset:1.5rem;--handleoffsetcalculator:calc(var(--handleoffset)*-1);--togglehandleborder:0 0;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:currentColor;border-color:currentColor;border-radius:var(--rounded-badge,1.9rem);border-width:1px;box-shadow:var(--handleoffsetcalculator) 0 0 2px var(--tglbg) inset,0 0 0 2px var(--tglbg) inset,var(--togglehandleborder);color:var(--fallback-bc,oklch(var(--bc)/.5));cursor:pointer;height:1.5rem;transition:background,box-shadow var(--animation-input,.2s) ease-out;width:3rem}.alert-info{border-color:var(--fallback-in,oklch(var(--in)/.2));--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)));--alert-bg:var(--fallback-in,oklch(var(--in)/1));--alert-bg-mix:var(--fallback-b1,oklch(var(--b1)/1))}.alert-success{border-color:var(--fallback-su,oklch(var(--su)/.2));--tw-text-opacity:1;color:var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity)));--alert-bg:var(--fallback-su,oklch(var(--su)/1));--alert-bg-mix:var(--fallback-b1,oklch(var(--b1)/1))}.alert-warning{border-color:var(--fallback-wa,oklch(var(--wa)/.2));--tw-text-opacity:1;color:var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity)));--alert-bg:var(--fallback-wa,oklch(var(--wa)/1));--alert-bg-mix:var(--fallback-b1,oklch(var(--b1)/1))}.alert-error{border-color:var(--fallback-er,oklch(var(--er)/.2));--tw-text-opacity:1;color:var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)));--alert-bg:var(--fallback-er,oklch(var(--er)/1));--alert-bg-mix:var(--fallback-b1,oklch(var(--b1)/1))}.avatar-group :where(.avatar){border-radius:9999px;border-width:4px;overflow:hidden;--tw-border-opacity:1;border-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-border-opacity)))}.badge-neutral{background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));border-color:var(--fallback-n,oklch(var(--n)/var(--tw-border-opacity)));color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)))}.badge-neutral,.badge-primary{--tw-border-opacity:1;--tw-bg-opacity:1;--tw-text-opacity:1}.badge-primary{background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.badge-secondary{background-color:var(--fallback-s,oklch(var(--s)/var(--tw-bg-opacity)));border-color:var(--fallback-s,oklch(var(--s)/var(--tw-border-opacity)));color:var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity)))}.badge-accent,.badge-secondary{--tw-border-opacity:1;--tw-bg-opacity:1;--tw-text-opacity:1}.badge-accent{background-color:var(--fallback-a,oklch(var(--a)/var(--tw-bg-opacity)));border-color:var(--fallback-a,oklch(var(--a)/var(--tw-border-opacity)));color:var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity)))}.badge-info{background-color:var(--fallback-in,oklch(var(--in)/var(--tw-bg-opacity)));color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)))}.badge-info,.badge-warning{border-color:transparent;--tw-bg-opacity:1;--tw-text-opacity:1}.badge-warning{background-color:var(--fallback-wa,oklch(var(--wa)/var(--tw-bg-opacity)));color:var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity)))}.badge-error{border-color:transparent;--tw-bg-opacity:1;background-color:var(--fallback-er,oklch(var(--er)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)))}.badge-outline{border-color:currentColor;--tw-border-opacity:0.5;background-color:transparent;color:currentColor}.badge-outline.badge-neutral{--tw-text-opacity:1;color:var(--fallback-n,oklch(var(--n)/var(--tw-text-opacity)))}.badge-outline.badge-primary{--tw-text-opacity:1;color:var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)))}.badge-outline.badge-secondary{--tw-text-opacity:1;color:var(--fallback-s,oklch(var(--s)/var(--tw-text-opacity)))}.badge-outline.badge-accent{--tw-text-opacity:1;color:var(--fallback-a,oklch(var(--a)/var(--tw-text-opacity)))}.badge-outline.badge-info{--tw-text-opacity:1;color:var(--fallback-in,oklch(var(--in)/var(--tw-text-opacity)))}.badge-outline.badge-success{--tw-text-opacity:1;color:var(--fallback-su,oklch(var(--su)/var(--tw-text-opacity)))}.badge-outline.badge-warning{--tw-text-opacity:1;color:var(--fallback-wa,oklch(var(--wa)/var(--tw-text-opacity)))}.badge-outline.badge-error{--tw-text-opacity:1;color:var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity)))}.btm-nav>.disabled,.btm-nav>[disabled]{pointer-events:none;--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btm-nav>* .label{font-size:1rem;line-height:1.5rem}.btn:active:focus,.btn:active:hover{animation:button-pop 0s ease-out;transform:scale(var(--btn-focus-scale,.97))}@supports not (color:oklch(0 0 0)){.btn{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}.btn-primary{--btn-color:var(--fallback-p)}.btn-secondary{--btn-color:var(--fallback-s)}.btn-accent{--btn-color:var(--fallback-a)}.btn-neutral{--btn-color:var(--fallback-n)}.btn-info{--btn-color:var(--fallback-in)}.btn-error{--btn-color:var(--fallback-er)}.prose :where(code):not(:where([class~=not-prose] *,pre *)){background-color:var(--fallback-b3,oklch(var(--b3)/1))}}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-primary.btn-active{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}.btn-outline.btn-secondary.btn-active{background-color:color-mix(in oklab,var(--fallback-s,oklch(var(--s)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-s,oklch(var(--s)/1)) 90%,#000)}.btn-outline.btn-accent.btn-active{background-color:color-mix(in oklab,var(--fallback-a,oklch(var(--a)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-a,oklch(var(--a)/1)) 90%,#000)}.btn-outline.btn-info.btn-active{background-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000)}.btn-outline.btn-error.btn-active{background-color:color-mix(in oklab,var(--fallback-er,oklch(var(--er)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-er,oklch(var(--er)/1)) 90%,#000)}}.btn:focus-visible{outline-offset:2px;outline-style:solid;outline-width:2px}.btn-primary{--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)));outline-color:var(--fallback-p,oklch(var(--p)/1))}@supports (color:oklch(0 0 0)){.btn-primary{--btn-color:var(--p)}.btn-secondary{--btn-color:var(--s)}.btn-accent{--btn-color:var(--a)}.btn-neutral{--btn-color:var(--n)}.btn-info{--btn-color:var(--in)}.btn-error{--btn-color:var(--er)}}.btn-secondary{color:var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity)));outline-color:var(--fallback-s,oklch(var(--s)/1))}.btn-accent,.btn-secondary{--tw-text-opacity:1}.btn-accent{color:var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity)));outline-color:var(--fallback-a,oklch(var(--a)/1))}.btn-neutral{color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)));outline-color:var(--fallback-n,oklch(var(--n)/1))}.btn-info,.btn-neutral{--tw-text-opacity:1}.btn-info{color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)));outline-color:var(--fallback-in,oklch(var(--in)/1))}.btn-error{--tw-text-opacity:1;color:var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)));outline-color:var(--fallback-er,oklch(var(--er)/1))}.btn.glass{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn.glass.btn-active{--glass-opacity:25%;--glass-border-opacity:15%}.btn-ghost{background-color:transparent;border-width:1px;color:currentColor;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-ghost,.btn-ghost.btn-active{border-color:transparent}.btn-ghost.btn-active{background-color:var(--fallback-bc,oklch(var(--bc)/.2))}.btn-link{--tw-text-opacity:1;color:var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)));--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-link,.btn-link.btn-active{background-color:transparent;border-color:transparent;text-decoration-line:underline}.btn-outline.btn-primary{--tw-text-opacity:1;color:var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)))}.btn-outline.btn-primary.btn-active{--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.btn-outline.btn-secondary{--tw-text-opacity:1;color:var(--fallback-s,oklch(var(--s)/var(--tw-text-opacity)))}.btn-outline.btn-secondary.btn-active{--tw-text-opacity:1;color:var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity)))}.btn-outline.btn-accent{--tw-text-opacity:1;color:var(--fallback-a,oklch(var(--a)/var(--tw-text-opacity)))}.btn-outline.btn-accent.btn-active{--tw-text-opacity:1;color:var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity)))}.btn-outline.btn-info{--tw-text-opacity:1;color:var(--fallback-in,oklch(var(--in)/var(--tw-text-opacity)))}.btn-outline.btn-info.btn-active{--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)))}.btn-outline.btn-error{--tw-text-opacity:1;color:var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity)))}.btn-outline.btn-error.btn-active{--tw-text-opacity:1;color:var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)))}.btn.btn-disabled,.btn:disabled,.btn[disabled]{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btn:is(input[type=checkbox]:checked),.btn:is(input[type=radio]:checked){--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.btn:is(input[type=checkbox]:checked):focus-visible,.btn:is(input[type=radio]:checked):focus-visible{outline-color:var(--fallback-p,oklch(var(--p)/1))}@keyframes button-pop{0%{transform:scale(var(--btn-focus-scale,.98))}40%{transform:scale(1.02)}to{transform:scale(1)}}.card :where(figure:first-child){border-end-end-radius:unset;border-end-start-radius:unset;border-start-end-radius:inherit;border-start-start-radius:inherit;overflow:hidden}.card :where(figure:last-child){border-end-end-radius:inherit;border-end-start-radius:inherit;border-start-end-radius:unset;border-start-start-radius:unset;overflow:hidden}.card:focus-visible{outline:2px solid currentColor;outline-offset:2px}.card.bordered{border-width:1px;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)))}.card.compact .card-body{font-size:.875rem;line-height:1.25rem;padding:1rem}.card-title{align-items:center;display:flex;font-size:1.25rem;font-weight:600;gap:.5rem;line-height:1.75rem}.card.image-full :where(figure){border-radius:inherit;overflow:hidden}.checkbox:focus{box-shadow:none}.checkbox:focus-visible{outline-color:var(--fallback-bc,oklch(var(--bc)/1));outline-offset:2px;outline-style:solid;outline-width:2px}.checkbox:checked,.checkbox[aria-checked=true],.checkbox[checked=true]{animation:checkmark var(--animation-input,.2s) ease-out;background-color:var(--chkbg);background-image:linear-gradient(-45deg,transparent 65%,var(--chkbg) 65.99%),linear-gradient(45deg,transparent 75%,var(--chkbg) 75.99%),linear-gradient(-45deg,var(--chkbg) 40%,transparent 40.99%),linear-gradient(45deg,var(--chkbg) 30%,var(--chkfg) 30.99%,var(--chkfg) 40%,transparent 40.99%),linear-gradient(-45deg,var(--chkfg) 50%,var(--chkbg) 50.99%);background-repeat:no-repeat}.checkbox:indeterminate{--tw-bg-opacity:1;animation:checkmark var(--animation-input,.2s) ease-out;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));background-image:linear-gradient(90deg,transparent 80%,var(--chkbg) 80%),linear-gradient(-90deg,transparent 80%,var(--chkbg) 80%),linear-gradient(0deg,var(--chkbg) 43%,var(--chkfg) 43%,var(--chkfg) 57%,var(--chkbg) 57%);background-repeat:no-repeat}.checkbox:disabled{border-color:transparent;cursor:not-allowed;--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));opacity:.2}@keyframes checkmark{0%{background-position-y:5px}50%{background-position-y:-2px}to{background-position-y:0}}.drawer-toggle:checked~.drawer-side>.drawer-overlay{background-color:#0006}.drawer-toggle:focus-visible~.drawer-content label.drawer-button{outline-offset:2px;outline-style:solid;outline-width:2px}.dropdown.dropdown-open .dropdown-content,.dropdown:focus .dropdown-content,.dropdown:focus-within .dropdown-content{--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.file-input-bordered{--tw-border-opacity:0.2}.file-input:focus{outline-color:var(--fallback-bc,oklch(var(--bc)/.2));outline-offset:2px;outline-style:solid;outline-width:2px}.file-input-disabled,.file-input[disabled]{cursor:not-allowed;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));--tw-text-opacity:0.2}.file-input-disabled::-moz-placeholder,.file-input[disabled]::-moz-placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.file-input-disabled::placeholder,.file-input[disabled]::placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.file-input-disabled::file-selector-button,.file-input[disabled]::file-selector-button{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.label-text{font-size:.875rem;line-height:1.25rem}.label-text,.label-text-alt{--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}.label-text-alt{font-size:.75rem;line-height:1rem}.input input:focus{outline:2px solid transparent;outline-offset:2px}.input[list]::-webkit-calendar-picker-indicator{line-height:1em}.input-bordered{border-color:var(--fallback-bc,oklch(var(--bc)/.2))}.input:focus,.input:focus-within{border-color:var(--fallback-bc,oklch(var(--bc)/.2));box-shadow:none;outline-color:var(--fallback-bc,oklch(var(--bc)/.2));outline-offset:2px;outline-style:solid;outline-width:2px}.input-disabled,.input:disabled,.input[disabled]{cursor:not-allowed;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));color:var(--fallback-bc,oklch(var(--bc)/.4))}.input-disabled::-moz-placeholder,.input:disabled::-moz-placeholder,.input[disabled]::-moz-placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.input-disabled::placeholder,.input:disabled::placeholder,.input[disabled]::placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.input::-webkit-date-and-time-value{text-align:inherit}.join>:where(:not(:first-child)){margin-bottom:0;margin-top:0;margin-inline-start:-1px}.join-item:focus{isolation:isolate}.link-primary{--tw-text-opacity:1;color:var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){@media (hover:hover){.link-primary:hover{color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 80%,#000)}}}.\!link:focus{outline:2px solid transparent!important;outline-offset:2px!important}.link:focus{outline:2px solid transparent;outline-offset:2px}.\!link:focus-visible{outline:2px solid currentColor!important;outline-offset:2px!important}.link:focus-visible{outline:2px solid currentColor;outline-offset:2px}.loading{aspect-ratio:1/1;background-color:currentColor;display:inline-block;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:100%;mask-size:100%;pointer-events:none;width:1.5rem}.loading,.loading-spinner{-webkit-mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' stroke='%23000'%3E%3Cstyle%3E@keyframes spinner_zKoa{to{transform:rotate(360deg)}}@keyframes spinner_YpZS{0%25{stroke-dasharray:0 150;stroke-dashoffset:0}47.5%25{stroke-dasharray:42 150;stroke-dashoffset:-16}95%25,to{stroke-dasharray:42 150;stroke-dashoffset:-59}}%3C/style%3E%3Cg style='transform-origin:center;animation:spinner_zKoa 2s linear infinite'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' class='spinner_V8m1' style='stroke-linecap:round;animation:spinner_YpZS 1.5s ease-out infinite'/%3E%3C/g%3E%3C/svg%3E");mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' stroke='%23000'%3E%3Cstyle%3E@keyframes spinner_zKoa{to{transform:rotate(360deg)}}@keyframes spinner_YpZS{0%25{stroke-dasharray:0 150;stroke-dashoffset:0}47.5%25{stroke-dasharray:42 150;stroke-dashoffset:-16}95%25,to{stroke-dasharray:42 150;stroke-dashoffset:-59}}%3C/style%3E%3Cg style='transform-origin:center;animation:spinner_zKoa 2s linear infinite'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' class='spinner_V8m1' style='stroke-linecap:round;animation:spinner_YpZS 1.5s ease-out infinite'/%3E%3C/g%3E%3C/svg%3E")}.loading-lg{width:2.5rem}:where(.menu li:empty){--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));height:1px;margin:.5rem 1rem;opacity:.1}.menu :where(li ul):before{bottom:.75rem;inset-inline-start:0;position:absolute;top:.75rem;width:1px;--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));content:"";opacity:.1}.menu :where(li:not(.menu-title)>:not(ul):not(details):not(.menu-title)),.menu :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--rounded-btn,.5rem);padding:.5rem 1rem;text-align:start;transition-duration:.2s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1);text-wrap:balance}:where(.menu li:not(.menu-title):not(.disabled)>:not(ul):not(details):not(.menu-title)):is(summary):not(.active):focus-visible,:where(.menu li:not(.menu-title):not(.disabled)>:not(ul):not(details):not(.menu-title)):not(summary):not(.active).focus,:where(.menu li:not(.menu-title):not(.disabled)>:not(ul):not(details):not(.menu-title)):not(summary):not(.active):focus,:where(.menu li:not(.menu-title):not(.disabled)>details>summary:not(.menu-title)):is(summary):not(.active):focus-visible,:where(.menu li:not(.menu-title):not(.disabled)>details>summary:not(.menu-title)):not(summary):not(.active).focus,:where(.menu li:not(.menu-title):not(.disabled)>details>summary:not(.menu-title)):not(summary):not(.active):focus{background-color:var(--fallback-bc,oklch(var(--bc)/.1));cursor:pointer;--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));outline:2px solid transparent;outline-offset:2px}.menu li>:not(ul):not(.menu-title):not(details).active,.menu li>:not(ul):not(.menu-title):not(details):active,.menu li>details>summary:active{--tw-bg-opacity:1;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)))}.menu :where(li>details>summary)::-webkit-details-marker{display:none}.menu :where(li>.menu-dropdown-toggle):after,.menu :where(li>details>summary):after{box-shadow:2px 2px;content:"";display:block;height:.5rem;justify-self:end;margin-top:-.5rem;pointer-events:none;transform:rotate(45deg);transform-origin:75% 75%;transition-duration:.3s;transition-property:transform,margin-top;transition-timing-function:cubic-bezier(.4,0,.2,1);width:.5rem}.menu :where(li>.menu-dropdown-toggle.menu-dropdown-show):after,.menu :where(li>details[open]>summary):after{margin-top:0;transform:rotate(225deg)}.mockup-phone .display{border-radius:40px;margin-top:-25px;overflow:hidden}.mockup-browser .mockup-browser-toolbar .input{display:block;height:1.75rem;margin-left:auto;margin-right:auto;overflow:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:24rem;--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));direction:ltr;padding-left:2rem}.mockup-browser .mockup-browser-toolbar .input:before{aspect-ratio:1/1;height:.75rem;left:.5rem;--tw-translate-y:-50%;border-color:currentColor;border-radius:9999px;border-width:2px}.mockup-browser .mockup-browser-toolbar .input:after,.mockup-browser .mockup-browser-toolbar .input:before{content:"";opacity:.6;position:absolute;top:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.mockup-browser .mockup-browser-toolbar .input:after{height:.5rem;left:1.25rem;--tw-translate-y:25%;--tw-rotate:-45deg;border-color:currentColor;border-radius:9999px;border-width:1px}.modal::backdrop,.modal:not(dialog:not(.modal-open)){animation:modal-pop .2s ease-out;background-color:#0006}.modal-open .modal-box,.modal-toggle:checked+.modal .modal-box,.modal:target .modal-box,.modal[open] .modal-box{--tw-translate-y:0px;--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.modal-action>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}@keyframes modal-pop{0%{opacity:0}}.progress::-moz-progress-bar{background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)))}.progress-primary::-moz-progress-bar,.progress::-moz-progress-bar{border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1}.progress-primary::-moz-progress-bar{background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)))}.progress:indeterminate{--progress-color:var(--fallback-bc,oklch(var(--bc)/1));animation:progress-loading 5s ease-in-out infinite;background-image:repeating-linear-gradient(90deg,var(--progress-color) -1%,var(--progress-color) 10%,transparent 10%,transparent 90%);background-position-x:15%;background-size:200%}.progress-primary:indeterminate{--progress-color:var(--fallback-p,oklch(var(--p)/1))}.progress::-webkit-progress-bar{background-color:transparent;border-radius:var(--rounded-box,1rem)}.progress::-webkit-progress-value{border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)))}.progress-primary::-webkit-progress-value{--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)))}.progress:indeterminate::-moz-progress-bar{animation:progress-loading 5s ease-in-out infinite;background-color:transparent;background-image:repeating-linear-gradient(90deg,var(--progress-color) -1%,var(--progress-color) 10%,transparent 10%,transparent 90%);background-position-x:15%;background-size:200%}@keyframes progress-loading{50%{background-position-x:-115%}}@keyframes radiomark{0%{box-shadow:0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset,0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset}50%{box-shadow:0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset,0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset}to{box-shadow:0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset,0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset}}@keyframes rating-pop{0%{transform:translateY(-.125em)}40%{transform:translateY(-.125em)}to{transform:translateY(0)}}.select-bordered,.select:focus{border-color:var(--fallback-bc,oklch(var(--bc)/.2))}.select:focus{box-shadow:none;outline-color:var(--fallback-bc,oklch(var(--bc)/.2));outline-offset:2px;outline-style:solid;outline-width:2px}.select-primary,.select-primary:focus{--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)))}.select-primary:focus{outline-color:var(--fallback-p,oklch(var(--p)/1))}.select-disabled,.select:disabled,.select[disabled]{cursor:not-allowed;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));--tw-text-opacity:0.2}.select-disabled::-moz-placeholder,.select:disabled::-moz-placeholder,.select[disabled]::-moz-placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.select-disabled::placeholder,.select:disabled::placeholder,.select[disabled]::placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.select-multiple,.select[multiple],.select[size].select:not([size="1"]){background-image:none;padding-right:1rem}[dir=rtl] .select{background-position:12px calc(1px + 50%),16px calc(1px + 50%)}.skeleton{border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;animation:skeleton 1.8s ease-in-out infinite;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));background-image:linear-gradient(105deg,transparent 0,transparent 40%,var(--fallback-b1,oklch(var(--b1)/1)) 50%,transparent 60%,transparent 100%);background-position-x:-50%;background-repeat:no-repeat;background-size:200% auto;will-change:background-position}@media (prefers-reduced-motion){.skeleton{animation-duration:15s}}@keyframes skeleton{0%{background-position:150%}to{background-position:-50%}}.steps .step:before{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));content:"";height:.5rem;margin-inline-start:-100%;top:0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));width:100%}.steps .step:after,.steps .step:before{grid-column-start:1;grid-row-start:1;--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));--tw-text-opacity:1}.steps .step:after{border-radius:9999px;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));content:counter(step);counter-increment:step;display:grid;height:2rem;place-items:center;place-self:center;position:relative;width:2rem;z-index:1}.steps .step:first-child:before{content:none}.steps .step[data-content]:after{content:attr(data-content)}.steps .step-neutral+.step-neutral:before,.steps .step-neutral:after{--tw-bg-opacity:1;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)))}.steps .step-primary+.step-primary:before,.steps .step-primary:after{--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.steps .step-secondary+.step-secondary:before,.steps .step-secondary:after{--tw-bg-opacity:1;background-color:var(--fallback-s,oklch(var(--s)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity)))}.steps .step-accent+.step-accent:before,.steps .step-accent:after{--tw-bg-opacity:1;background-color:var(--fallback-a,oklch(var(--a)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity)))}.steps .step-info+.step-info:before,.steps .step-info:after{--tw-bg-opacity:1;background-color:var(--fallback-in,oklch(var(--in)/var(--tw-bg-opacity)))}.steps .step-info:after{--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)))}.steps .step-success+.step-success:before,.steps .step-success:after{--tw-bg-opacity:1;background-color:var(--fallback-su,oklch(var(--su)/var(--tw-bg-opacity)))}.steps .step-success:after{--tw-text-opacity:1;color:var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity)))}.steps .step-warning+.step-warning:before,.steps .step-warning:after{--tw-bg-opacity:1;background-color:var(--fallback-wa,oklch(var(--wa)/var(--tw-bg-opacity)))}.steps .step-warning:after{--tw-text-opacity:1;color:var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity)))}.steps .step-error+.step-error:before,.steps .step-error:after{--tw-bg-opacity:1;background-color:var(--fallback-er,oklch(var(--er)/var(--tw-bg-opacity)))}.steps .step-error:after{--tw-text-opacity:1;color:var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)))}.swap-rotate .swap-indeterminate,.swap-rotate .swap-on,.swap-rotate input:indeterminate~.swap-on{--tw-rotate:45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.swap-active:where(.swap-rotate) .swap-off,.swap-rotate input:checked~.swap-off,.swap-rotate input:indeterminate~.swap-off{--tw-rotate:-45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.swap-active:where(.swap-rotate) .swap-on,.swap-rotate input:checked~.swap-on,.swap-rotate input:indeterminate~.swap-indeterminate{--tw-rotate:0deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.swap-flip .swap-indeterminate,.swap-flip .swap-on,.swap-flip input:indeterminate~.swap-on{backface-visibility:hidden;opacity:1;transform:rotateY(180deg)}.swap-active:where(.swap-flip) .swap-off,.swap-flip input:checked~.swap-off,.swap-flip input:indeterminate~.swap-off{backface-visibility:hidden;opacity:1;transform:rotateY(-180deg)}.swap-active:where(.swap-flip) .swap-on,.swap-flip input:checked~.swap-on,.swap-flip input:indeterminate~.swap-indeterminate{transform:rotateY(0deg)}:is([dir=rtl] .table){text-align:right}.table :where(th,td){padding:.75rem 1rem;vertical-align:middle}.table tr.active,.table tr.active:nth-child(2n),.table-zebra tbody tr:nth-child(2n){--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)))}.table-zebra tr.active,.table-zebra tr.active:nth-child(2n),.table-zebra-zebra tbody tr:nth-child(2n){--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}.table :where(thead,tbody) :where(tr:first-child:last-child),.table :where(thead,tbody) :where(tr:not(:last-child)){border-bottom-width:1px;--tw-border-opacity:1;border-bottom-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)))}.table :where(thead,tfoot){color:var(--fallback-bc,oklch(var(--bc)/.6));font-size:.75rem;font-weight:700;line-height:1rem;white-space:nowrap}.textarea-bordered,.textarea:focus{border-color:var(--fallback-bc,oklch(var(--bc)/.2))}.textarea:focus{box-shadow:none;outline-color:var(--fallback-bc,oklch(var(--bc)/.2));outline-offset:2px;outline-style:solid;outline-width:2px}.textarea-disabled,.textarea:disabled,.textarea[disabled]{cursor:not-allowed;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));--tw-text-opacity:0.2}.textarea-disabled::-moz-placeholder,.textarea:disabled::-moz-placeholder,.textarea[disabled]::-moz-placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.textarea-disabled::placeholder,.textarea:disabled::placeholder,.textarea[disabled]::placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.toast>*{animation:toast-pop .25s ease-out}@keyframes toast-pop{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:scale(1)}}[dir=rtl] .toggle{--handleoffsetcalculator:calc(var(--handleoffset)*1)}.toggle:focus-visible{outline-color:var(--fallback-bc,oklch(var(--bc)/.2));outline-offset:2px;outline-style:solid;outline-width:2px}.toggle:hover{background-color:currentColor}.toggle:checked,.toggle[aria-checked=true],.toggle[checked=true]{background-image:none;--handleoffsetcalculator:var(--handleoffset);--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}[dir=rtl] .toggle:checked,[dir=rtl] .toggle[aria-checked=true],[dir=rtl] .toggle[checked=true]{--handleoffsetcalculator:calc(var(--handleoffset)*-1)}.toggle:indeterminate{--tw-text-opacity:1;box-shadow:calc(var(--handleoffset)/2) 0 0 2px var(--tglbg) inset,calc(var(--handleoffset)/-2) 0 0 2px var(--tglbg) inset,0 0 0 2px var(--tglbg) inset;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}[dir=rtl] .toggle:indeterminate{box-shadow:calc(var(--handleoffset)/2) 0 0 2px var(--tglbg) inset,calc(var(--handleoffset)/-2) 0 0 2px var(--tglbg) inset,0 0 0 2px var(--tglbg) inset}.toggle:disabled{cursor:not-allowed;--tw-border-opacity:1;background-color:transparent;border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));opacity:.3;--togglehandleborder:0 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset,var(--handleoffsetcalculator) 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset}:root .prose{--tw-prose-body:var(--fallback-bc,oklch(var(--bc)/0.8));--tw-prose-headings:var(--fallback-bc,oklch(var(--bc)/1));--tw-prose-lead:var(--fallback-bc,oklch(var(--bc)/1));--tw-prose-links:var(--fallback-bc,oklch(var(--bc)/1));--tw-prose-bold:var(--fallback-bc,oklch(var(--bc)/1));--tw-prose-counters:var(--fallback-bc,oklch(var(--bc)/1));--tw-prose-bullets:var(--fallback-bc,oklch(var(--bc)/0.5));--tw-prose-hr:var(--fallback-bc,oklch(var(--bc)/0.2));--tw-prose-quotes:var(--fallback-bc,oklch(var(--bc)/1));--tw-prose-quote-borders:var(--fallback-bc,oklch(var(--bc)/0.2));--tw-prose-captions:var(--fallback-bc,oklch(var(--bc)/0.5));--tw-prose-code:var(--fallback-bc,oklch(var(--bc)/1));--tw-prose-pre-code:var(--fallback-nc,oklch(var(--nc)/1));--tw-prose-pre-bg:var(--fallback-n,oklch(var(--n)/1));--tw-prose-th-borders:var(--fallback-bc,oklch(var(--bc)/0.5));--tw-prose-td-borders:var(--fallback-bc,oklch(var(--bc)/0.2))}.prose :where(code):not(:where([class~=not-prose] *,pre *)){background-color:var(--fallback-bc,oklch(var(--bc)/.1));border-radius:var(--rounded-badge);font-weight:400;padding:1px 8px}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):after,.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):before{display:none}.prose pre code{border-radius:0;padding:0}.prose :where(tbody tr,thead):not(:where([class~=not-prose] *)){border-bottom-color:var(--fallback-bc,oklch(var(--bc)/.2))}.no-animation{--btn-focus-scale:1;--animation-btn:0;--animation-input:0}.badge-sm{height:1rem;line-height:1rem;padding-left:.438rem;padding-right:.438rem}.badge-sm,.btn-xs{font-size:.75rem}.btn-xs{height:1.5rem;min-height:1.5rem;padding-left:.5rem;padding-right:.5rem}.btn-sm{font-size:.875rem;height:2rem;min-height:2rem;padding-left:.75rem;padding-right:.75rem}.btn-lg{font-size:1.125rem;height:4rem;min-height:4rem;padding-left:1.5rem;padding-right:1.5rem}.btn-wide{width:16rem}.btn-square:where(.btn-xs){height:1.5rem;padding:0;width:1.5rem}.btn-square:where(.btn-sm){height:2rem;padding:0;width:2rem}.btn-square:where(.btn-md){height:3rem;padding:0;width:3rem}.btn-square:where(.btn-lg){height:4rem;padding:0;width:4rem}.btn-circle:where(.btn-xs){border-radius:9999px;height:1.5rem;padding:0;width:1.5rem}.btn-circle:where(.btn-sm){border-radius:9999px;height:2rem;padding:0;width:2rem}.btn-circle:where(.btn-md){border-radius:9999px;height:3rem;padding:0;width:3rem}.btn-circle:where(.btn-lg){border-radius:9999px;height:4rem;padding:0;width:4rem}.card-side{align-items:stretch;flex-direction:row}.card-side :where(figure:first-child){border-end-end-radius:unset;border-end-start-radius:inherit;border-start-end-radius:unset;border-start-start-radius:inherit;overflow:hidden}.card-side :where(figure:last-child){border-end-end-radius:inherit;border-end-start-radius:unset;border-start-end-radius:inherit;border-start-start-radius:unset;overflow:hidden}.card-side figure>*{max-width:unset}:where(.card-side figure>*){height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.drawer-open>.drawer-toggle{display:none}.drawer-open>.drawer-toggle~.drawer-side{display:block;overscroll-behavior:auto;pointer-events:auto;position:sticky;visibility:visible;width:auto}.drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay),[dir=rtl] .drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay){transform:translateX(0)}.drawer-open>.drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible}.join.join-vertical{flex-direction:column}.join.join-vertical .join-item:first-child:not(:last-child),.join.join-vertical :first-child:not(:last-child) .join-item{border-end-end-radius:0;border-end-start-radius:0;border-start-end-radius:inherit;border-start-start-radius:inherit}.join.join-vertical .join-item:last-child:not(:first-child),.join.join-vertical :last-child:not(:first-child) .join-item{border-end-end-radius:inherit;border-end-start-radius:inherit;border-start-end-radius:0;border-start-start-radius:0}.join.join-horizontal{flex-direction:row}.join.join-horizontal .join-item:first-child:not(:last-child),.join.join-horizontal :first-child:not(:last-child) .join-item{border-end-end-radius:0;border-end-start-radius:inherit;border-start-end-radius:0;border-start-start-radius:inherit}.join.join-horizontal .join-item:last-child:not(:first-child),.join.join-horizontal :last-child:not(:first-child) .join-item{border-end-end-radius:inherit;border-end-start-radius:0;border-start-end-radius:inherit;border-start-start-radius:0}.select-sm{font-size:.875rem;height:2rem;line-height:2rem;min-height:2rem;padding-left:.75rem;padding-right:2rem}[dir=rtl] .select-sm{padding-left:2rem;padding-right:.75rem}.steps-horizontal .step{display:grid;grid-template-columns:repeat(1,minmax(0,1fr));grid-template-rows:repeat(2,minmax(0,1fr));place-items:center;text-align:center}.steps-vertical .step{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:repeat(1,minmax(0,1fr))}:where(.toast){bottom:0;inset-inline-end:0;inset-inline-start:auto;top:auto;--tw-translate-x:0px;--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.toast:where(.toast-start){inset-inline-end:auto;inset-inline-start:0;--tw-translate-x:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.toast:where(.toast-center){inset-inline-end:50%;inset-inline-start:50%;--tw-translate-x:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir=rtl] .toast:where(.toast-center)){--tw-translate-x:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.toast:where(.toast-end){inset-inline-end:0;inset-inline-start:auto;--tw-translate-x:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.toast:where(.toast-bottom){bottom:0;top:auto;--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.toast:where(.toast-middle){bottom:auto;top:50%;--tw-translate-y:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.toast:where(.toast-top){bottom:auto;top:0;--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.avatar.online:before{background-color:var(--fallback-su,oklch(var(--su)/var(--tw-bg-opacity)))}.avatar.offline:before,.avatar.online:before{border-radius:9999px;content:"";display:block;position:absolute;z-index:10;--tw-bg-opacity:1;height:15%;outline-color:var(--fallback-b1,oklch(var(--b1)/1));outline-style:solid;outline-width:2px;right:7%;top:7%;width:15%}.avatar.offline:before{background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}.card-compact .card-body{font-size:.875rem;line-height:1.25rem;padding:1rem}.card-compact .card-title{margin-bottom:.25rem}.card-normal .card-body{font-size:1rem;line-height:1.5rem;padding:var(--padding-card,2rem)}.card-normal .card-title{margin-bottom:.75rem}.drawer-open>.drawer-toggle~.drawer-side>.drawer-overlay{background-color:transparent;cursor:default}.join.join-vertical>:where(:not(:first-child)){margin-left:0;margin-right:0;margin-top:-1px}.join.join-horizontal>:where(:not(:first-child)){margin-bottom:0;margin-top:0;margin-inline-start:-1px}.modal-top :where(.modal-box){max-width:none;width:100%;--tw-translate-y:-2.5rem;--tw-scale-x:1;--tw-scale-y:1;border-bottom-left-radius:var(--rounded-box,1rem);border-bottom-right-radius:var(--rounded-box,1rem);border-top-left-radius:0;border-top-right-radius:0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.modal-middle :where(.modal-box){max-width:32rem;width:91.666667%;--tw-translate-y:0px;--tw-scale-x:.9;--tw-scale-y:.9;border-bottom-left-radius:var(--rounded-box,1rem);border-bottom-right-radius:var(--rounded-box,1rem);border-top-left-radius:var(--rounded-box,1rem);border-top-right-radius:var(--rounded-box,1rem);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.modal-bottom :where(.modal-box){max-width:none;width:100%;--tw-translate-y:2.5rem;--tw-scale-x:1;--tw-scale-y:1;border-bottom-left-radius:0;border-bottom-right-radius:0;border-top-left-radius:var(--rounded-box,1rem);border-top-right-radius:var(--rounded-box,1rem);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.steps-horizontal .step{grid-template-columns:auto;grid-template-rows:40px 1fr;min-width:4rem}.steps-horizontal .step:before{height:.5rem;width:100%;--tw-translate-x:0px;--tw-translate-y:0px;content:"";margin-inline-start:-100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir=rtl] .steps-horizontal .step):before{--tw-translate-x:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.steps-vertical .step{gap:.5rem;grid-template-columns:40px 1fr;grid-template-rows:auto;justify-items:start;min-height:4rem}.steps-vertical .step:before{height:100%;width:.5rem;--tw-translate-x:-50%;--tw-translate-y:-50%;margin-inline-start:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir=rtl] .steps-vertical .step):before{--tw-translate-x:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em;margin-top:1.25em}.prose :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-lead);font-size:1.25em;line-height:1.6;margin-bottom:1.2em;margin-top:1.2em}.prose :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-links);font-weight:500;text-decoration:underline}.prose :where(strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(a strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(blockquote strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(thead th strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal;margin-bottom:1.25em;margin-top:1.25em;padding-left:1.625em}.prose :where(ol[type=A]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=A s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=I]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type=I s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:disc;margin-bottom:1.25em;margin-top:1.25em;padding-left:1.625em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-counters);font-weight:400}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-bullets)}.prose :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;margin-top:1.25em}.prose :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-bottom:3em;margin-top:3em}.prose :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){border-left-color:var(--tw-prose-quote-borders);border-left-width:.25rem;color:var(--tw-prose-quotes);font-style:italic;font-weight:500;margin-bottom:1.6em;margin-top:1.6em;padding-left:1em;quotes:"\201C""\201D""\2018""\2019"}.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:close-quote}.prose :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-size:2.25em;font-weight:800;line-height:1.1111111;margin-bottom:.8888889em;margin-top:0}.prose :where(h1 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:900}.prose :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-size:1.5em;font-weight:700;line-height:1.3333333;margin-bottom:1em;margin-top:2em}.prose :where(h2 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:800}.prose :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-size:1.25em;font-weight:600;line-height:1.6;margin-bottom:.6em;margin-top:1.6em}.prose :where(h3 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;line-height:1.5;margin-bottom:.5em;margin-top:1.5em}.prose :where(h4 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:2em;margin-top:2em}.prose :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){display:block;margin-bottom:2em;margin-top:2em}.prose :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){border-radius:.3125rem;box-shadow:0 0 0 1px rgb(var(--tw-prose-kbd-shadows)/10%),0 3px 0 rgb(var(--tw-prose-kbd-shadows)/10%);color:var(--tw-prose-kbd);font-family:inherit;font-size:.875em;font-weight:500;padding:.1875em .375em}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-code);font-size:.875em;font-weight:600}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:"`"}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:"`"}.prose :where(a code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h1 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.875em}.prose :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.9em}.prose :where(h4 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(blockquote code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(thead th code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){background-color:var(--tw-prose-pre-bg);border-radius:.375rem;color:var(--tw-prose-pre-code);font-size:.875em;font-weight:400;line-height:1.7142857;margin-bottom:1.7142857em;margin-top:1.7142857em;overflow-x:auto;padding:.8571429em 1.1428571em}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)){background-color:transparent;border-radius:0;border-width:0;color:inherit;font-family:inherit;font-size:inherit;font-weight:inherit;line-height:inherit;padding:0}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:none}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:none}.prose :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.875em;line-height:1.7142857;margin-bottom:2em;margin-top:2em;table-layout:auto;text-align:left;width:100%}.prose :where(thead):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-color:var(--tw-prose-th-borders);border-bottom-width:1px}.prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;padding-bottom:.5714286em;padding-left:.5714286em;padding-right:.5714286em;vertical-align:bottom}.prose :where(tbody tr):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-color:var(--tw-prose-td-borders);border-bottom-width:1px}.prose :where(tbody tr:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:baseline}.prose :where(tfoot):not(:where([class~=not-prose],[class~=not-prose] *)){border-top-color:var(--tw-prose-th-borders);border-top-width:1px}.prose :where(tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:top}.prose :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0;margin-top:0}.prose :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-captions);font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.prose{--tw-prose-body:#374151;--tw-prose-headings:#111827;--tw-prose-lead:#4b5563;--tw-prose-links:#111827;--tw-prose-bold:#111827;--tw-prose-counters:#6b7280;--tw-prose-bullets:#d1d5db;--tw-prose-hr:#e5e7eb;--tw-prose-quotes:#111827;--tw-prose-quote-borders:#e5e7eb;--tw-prose-captions:#6b7280;--tw-prose-kbd:#111827;--tw-prose-kbd-shadows:17 24 39;--tw-prose-code:#111827;--tw-prose-pre-code:#e5e7eb;--tw-prose-pre-bg:#1f2937;--tw-prose-th-borders:#d1d5db;--tw-prose-td-borders:#e5e7eb;--tw-prose-invert-body:#d1d5db;--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:#9ca3af;--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:#9ca3af;--tw-prose-invert-bullets:#4b5563;--tw-prose-invert-hr:#374151;--tw-prose-invert-quotes:#f3f4f6;--tw-prose-invert-quote-borders:#374151;--tw-prose-invert-captions:#9ca3af;--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:255 255 255;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:#d1d5db;--tw-prose-invert-pre-bg:rgba(0,0,0,.5);--tw-prose-invert-th-borders:#4b5563;--tw-prose-invert-td-borders:#374151;font-size:1rem;line-height:1.75}.prose :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0;margin-top:0}.prose :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:2em;margin-top:2em}.prose :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:.5em;margin-top:.5em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:.375em}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:.375em}.prose :where(.prose>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:.75em;margin-top:.75em}.prose :where(.prose>ul>li>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ul>li>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(.prose>ol>li>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ol>li>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:.75em;margin-top:.75em}.prose :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em;margin-top:1.25em}.prose :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;padding-left:1.625em}.prose :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:0}.prose :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-right:0}.prose :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding:.5714286em}.prose :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:0}.prose :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-right:0}.prose :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:2em;margin-top:2em}.prose :where(.prose>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(.prose>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.prose-sm{font-size:.875rem;line-height:1.7142857}.prose-sm :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.1428571em;margin-top:1.1428571em}.prose-sm :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:1.2857143em;line-height:1.5555556;margin-bottom:.8888889em;margin-top:.8888889em}.prose-sm :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.3333333em;margin-top:1.3333333em;padding-left:1.1111111em}.prose-sm :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:2.1428571em;line-height:1.2;margin-bottom:.8em;margin-top:0}.prose-sm :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:1.4285714em;line-height:1.4;margin-bottom:.8em;margin-top:1.6em}.prose-sm :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:1.2857143em;line-height:1.5555556;margin-bottom:.4444444em;margin-top:1.5555556em}.prose-sm :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){line-height:1.4285714;margin-bottom:.5714286em;margin-top:1.4285714em}.prose-sm :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.7142857em;margin-top:1.7142857em}.prose-sm :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.7142857em;margin-top:1.7142857em}.prose-sm :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0;margin-top:0}.prose-sm :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.7142857em;margin-top:1.7142857em}.prose-sm :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){border-radius:.3125rem;font-size:.8571429em;padding:.1428571em .3571429em}.prose-sm :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.8571429em}.prose-sm :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.9em}.prose-sm :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.8888889em}.prose-sm :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){border-radius:.25rem;font-size:.8571429em;line-height:1.6666667;margin-bottom:1.6666667em;margin-top:1.6666667em;padding:.6666667em 1em}.prose-sm :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.1428571em;margin-top:1.1428571em;padding-left:1.5714286em}.prose-sm :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.1428571em;margin-top:1.1428571em;padding-left:1.5714286em}.prose-sm :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:.2857143em;margin-top:.2857143em}.prose-sm :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:.4285714em}.prose-sm :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:.4285714em}.prose-sm :where(.prose-sm>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:.5714286em;margin-top:.5714286em}.prose-sm :where(.prose-sm>ul>li>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.1428571em}.prose-sm :where(.prose-sm>ul>li>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.1428571em}.prose-sm :where(.prose-sm>ol>li>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.1428571em}.prose-sm :where(.prose-sm>ol>li>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.1428571em}.prose-sm :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:.5714286em;margin-top:.5714286em}.prose-sm :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.1428571em;margin-top:1.1428571em}.prose-sm :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.1428571em}.prose-sm :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.2857143em;padding-left:1.5714286em}.prose-sm :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:2.8571429em;margin-top:2.8571429em}.prose-sm :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-sm :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-sm :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-sm :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-sm :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.8571429em;line-height:1.5}.prose-sm :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){padding-bottom:.6666667em;padding-left:1em;padding-right:1em}.prose-sm :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:0}.prose-sm :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-right:0}.prose-sm :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding:.6666667em 1em}.prose-sm :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:0}.prose-sm :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-right:0}.prose-sm :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.7142857em;margin-top:1.7142857em}.prose-sm :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0;margin-top:0}.prose-sm :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.8571429em;line-height:1.3333333;margin-top:.6666667em}.prose-sm :where(.prose-sm>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-sm :where(.prose-sm>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.prose-neutral{--tw-prose-body:#404040;--tw-prose-headings:#171717;--tw-prose-lead:#525252;--tw-prose-links:#171717;--tw-prose-bold:#171717;--tw-prose-counters:#737373;--tw-prose-bullets:#d4d4d4;--tw-prose-hr:#e5e5e5;--tw-prose-quotes:#171717;--tw-prose-quote-borders:#e5e5e5;--tw-prose-captions:#737373;--tw-prose-kbd:#171717;--tw-prose-kbd-shadows:23 23 23;--tw-prose-code:#171717;--tw-prose-pre-code:#e5e5e5;--tw-prose-pre-bg:#262626;--tw-prose-th-borders:#d4d4d4;--tw-prose-td-borders:#e5e5e5;--tw-prose-invert-body:#d4d4d4;--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:#a3a3a3;--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:#a3a3a3;--tw-prose-invert-bullets:#525252;--tw-prose-invert-hr:#404040;--tw-prose-invert-quotes:#f5f5f5;--tw-prose-invert-quote-borders:#404040;--tw-prose-invert-captions:#a3a3a3;--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:255 255 255;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:#d4d4d4;--tw-prose-invert-pre-bg:rgba(0,0,0,.5);--tw-prose-invert-th-borders:#525252;--tw-prose-invert-td-borders:#404040}.youtube{border-radius:.1rem;--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));padding:.5rem}input.narrow-reading-toggle{display:none}body:has(label[for=narrow-reading-toggle]) input.narrow-reading-toggle:checked+.reading-toggle-target{max-width:48rem}.fade-away{-webkit-mask-image:linear-gradient(#000,#000 80%,rgba(0,0,0,.5) 85%,transparent);mask-image:linear-gradient(#000,#000 80%,rgba(0,0,0,.5) 85%,transparent)}.prose div>pre,.prose>pre{background-color:inherit;border-radius:0;color:inherit}.prose pre:has(code){border-color:currentColor;border-width:2px}.characters-left{bottom:1.5rem;pointer-events:none;position:absolute;right:1.5rem;-webkit-user-select:none;-moz-user-select:none;user-select:none}.static{position:static}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-8{inset:2rem}.bottom-2{bottom:.5rem}.left-2{left:.5rem}.right-0{right:0}.right-2{right:.5rem}.top-0{top:0}.top-2{top:.5rem}.z-10{z-index:10}.z-50{z-index:50}.z-\[1\]{z-index:1}.row-span-2{grid-row:span 2/span 2}.row-span-3{grid-row:span 3/span 3}.float-start{float:inline-start}.float-left{float:left}.mx-auto{margin-left:auto;margin-right:auto}.my-3{margin-bottom:.75rem;margin-top:.75rem}.my-6{margin-bottom:1.5rem;margin-top:1.5rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-6{margin-bottom:1.5rem}.ml-2{margin-left:.5rem}.mr-2{margin-right:.5rem}.mt-3{margin-top:.75rem}.line-clamp-1{-webkit-line-clamp:1}.line-clamp-1,.line-clamp-2{display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical}.line-clamp-2{-webkit-line-clamp:2}.line-clamp-3{display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:3}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.aspect-square{aspect-ratio:1/1}.h-12{height:3rem}.h-128{height:32rem}.h-16{height:4rem}.h-24{height:6rem}.h-32{height:8rem}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-full{height:100%}.h-screen{height:100vh}.max-h-full{max-height:100%}.min-h-24{min-height:6rem}.min-h-56{min-height:14rem}.min-h-96{min-height:24rem}.min-h-\[2\.8em\]{min-height:2.8em}.w-0{width:0}.w-1\/3{width:33.333333%}.w-16{width:4rem}.w-24{width:6rem}.w-4{width:1rem}.w-40{width:10rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-52{width:13rem}.w-56{width:14rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-80{width:20rem}.w-full{width:100%}.min-w-0{min-width:0}.max-w-full{max-width:100%}.max-w-none{max-width:none}.max-w-sm{max-width:24rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.flex-grow,.grow{flex-grow:1}.grow-0{flex-grow:0}.cursor-pointer{cursor:pointer}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-content-center{place-content:center}.content-center{align-content:center}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-x-8{-moz-column-gap:2rem;column-gap:2rem}.gap-y-3{row-gap:.75rem}.gap-y-4{row-gap:1rem}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.75rem*var(--tw-space-y-reverse));margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-bottom-width:calc(1px*var(--tw-divide-y-reverse));border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hyphens-auto{-webkit-hyphens:auto;hyphens:auto}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.1rem}.rounded-box{border-radius:var(--rounded-box,1rem)}.rounded-md{border-radius:.2rem}.border-2{border-width:2px}.border-b-2{border-bottom-width:2px}.border-current{border-color:currentColor}.bg-accent{background-color:var(--fallback-a,oklch(var(--a)/var(--tw-bg-opacity)))}.bg-accent,.bg-base-100{--tw-bg-opacity:1}.bg-base-100{background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.bg-base-200{--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)))}.bg-base-300{background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}.bg-base-300,.bg-error{--tw-bg-opacity:1}.bg-error{background-color:var(--fallback-er,oklch(var(--er)/var(--tw-bg-opacity)))}.bg-info{background-color:var(--fallback-in,oklch(var(--in)/var(--tw-bg-opacity)))}.bg-info,.bg-orange-500{--tw-bg-opacity:1}.bg-orange-500{background-color:rgb(249 115 22/var(--tw-bg-opacity))}.bg-primary{--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)))}.bg-secondary{--tw-bg-opacity:1;background-color:var(--fallback-s,oklch(var(--s)/var(--tw-bg-opacity)))}.bg-warning{--tw-bg-opacity:1;background-color:var(--fallback-wa,oklch(var(--wa)/var(--tw-bg-opacity)))}.fill-current{fill:currentColor}.stroke-current{stroke:currentColor}.object-contain{-o-object-fit:contain;object-fit:contain}.object-left{-o-object-position:left;object-position:left}.p-0{padding:0}.p-2{padding:.5rem}.p-4{padding:1rem}.px-4{padding-left:1rem;padding-right:1rem}.py-6{padding-bottom:1.5rem;padding-top:1.5rem}.py-8{padding-bottom:2rem;padding-top:2rem}.text-center{text-align:center}.text-justify{text-align:justify}.text-2xl{font-size:1.777rem}.text-3xl{font-size:2.369rem}.text-sm{font-size:.75rem}.text-xl{font-size:1.333rem}.font-bold{font-weight:700}.font-normal{font-weight:400}.not-italic{font-style:normal}.text-accent-content{--tw-text-opacity:1;color:var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity)))}.text-base-content{--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}.text-error{--tw-text-opacity:1;color:var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity)))}.text-error-content{--tw-text-opacity:1;color:var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)))}.text-info{--tw-text-opacity:1;color:var(--fallback-in,oklch(var(--in)/var(--tw-text-opacity)))}.text-info-content{--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)))}.text-primary{--tw-text-opacity:1;color:var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)))}.text-primary-content{--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.text-secondary-content{--tw-text-opacity:1;color:var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity)))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity))}.text-slate-50{--tw-text-opacity:1;color:rgb(248 250 252/var(--tw-text-opacity))}.text-success{--tw-text-opacity:1;color:var(--fallback-su,oklch(var(--su)/var(--tw-text-opacity)))}.text-warning-content{--tw-text-opacity:1;color:var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity)))}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-\[4px_4px_0_0_currentColor\]{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[4px_4px_0_0_currentColor\]{--tw-shadow:4px 4px 0 0 currentColor;--tw-shadow-colored:4px 4px 0 0 var(--tw-shadow-color)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.hover\:link:hover{cursor:pointer;text-decoration-line:underline}.hover\:badge-outline:hover{border-color:currentColor;--tw-border-opacity:0.5;background-color:transparent;color:currentColor}.hover\:badge-outline:hover.badge-neutral{--tw-text-opacity:1;color:var(--fallback-n,oklch(var(--n)/var(--tw-text-opacity)))}.hover\:badge-outline:hover.badge-primary{--tw-text-opacity:1;color:var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)))}.hover\:badge-outline:hover.badge-secondary{--tw-text-opacity:1;color:var(--fallback-s,oklch(var(--s)/var(--tw-text-opacity)))}.hover\:badge-outline:hover.badge-accent{--tw-text-opacity:1;color:var(--fallback-a,oklch(var(--a)/var(--tw-text-opacity)))}.hover\:badge-outline:hover.badge-info{--tw-text-opacity:1;color:var(--fallback-in,oklch(var(--in)/var(--tw-text-opacity)))}.hover\:badge-outline:hover.badge-success{--tw-text-opacity:1;color:var(--fallback-su,oklch(var(--su)/var(--tw-text-opacity)))}.hover\:badge-outline:hover.badge-warning{--tw-text-opacity:1;color:var(--fallback-wa,oklch(var(--wa)/var(--tw-text-opacity)))}.hover\:badge-outline:hover.badge-error{--tw-text-opacity:1;color:var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity)))}.hover\:link:hover:focus{outline:2px solid transparent;outline-offset:2px}.hover\:link:hover:focus-visible{outline:2px solid currentColor;outline-offset:2px}@media not all and (min-width:1024px){.max-lg\:dropdown-bottom .dropdown-content{bottom:auto;top:100%;transform-origin:top}.max-lg\:dropdown-end .dropdown-content{inset-inline-end:0}.max-lg\:dropdown-end.dropdown-left .dropdown-content,.max-lg\:dropdown-end.dropdown-right .dropdown-content{bottom:0;top:auto}}@media (min-width:640px){.sm\:btn-wide{width:16rem}.sm\:card-side{align-items:stretch;flex-direction:row}.sm\:card-side :where(figure:first-child){border-end-end-radius:unset;border-end-start-radius:inherit;border-start-end-radius:unset;border-start-start-radius:inherit;overflow:hidden}.sm\:card-side :where(figure:last-child){border-end-end-radius:inherit;border-end-start-radius:unset;border-start-end-radius:inherit;border-start-start-radius:unset;overflow:hidden}.sm\:card-side figure>*{max-width:unset}:where(.sm\:card-side figure>*){height:100%;-o-object-fit:cover;object-fit:cover;width:100%}}@media (min-width:768px){.md\:btn-wide{width:16rem}.md\:drawer-open>.drawer-toggle{display:none}.md\:drawer-open>.drawer-toggle~.drawer-side{display:block;overscroll-behavior:auto;pointer-events:auto;position:sticky;visibility:visible;width:auto}.md\:drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay),[dir=rtl] .md\:drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay){transform:translateX(0)}.md\:drawer-open>.drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible}.md\:join-horizontal.join{flex-direction:row}.md\:join-horizontal .join :first-child:not(:last-child) .join-item,.md\:join-horizontal.join .join-item:first-child:not(:last-child){border-end-end-radius:0;border-end-start-radius:inherit;border-start-end-radius:0;border-start-start-radius:inherit}.md\:join-horizontal .join :last-child:not(:first-child) .join-item,.md\:join-horizontal.join .join-item:last-child:not(:first-child){border-end-end-radius:inherit;border-end-start-radius:0;border-start-end-radius:inherit;border-start-start-radius:0}.md\:drawer-open>.drawer-toggle~.drawer-side>.drawer-overlay{background-color:transparent;cursor:default}.md\:join-horizontal.join>:where(:not(:first-child)){margin-bottom:0;margin-top:0;margin-inline-start:-1px}}@media (min-width:1024px){.lg\:dropdown-right .dropdown-content{bottom:auto;inset-inline-start:100%;top:0;transform-origin:left}.lg\:dropdown-right.dropdown-end .dropdown-content{bottom:0;top:auto}.lg\:prose-base{font-size:1rem;line-height:1.75}.lg\:prose-base :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em;margin-top:1.25em}.lg\:prose-base :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:1.25em;line-height:1.6;margin-bottom:1.2em;margin-top:1.2em}.lg\:prose-base :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.6em;margin-top:1.6em;padding-left:1em}.lg\:prose-base :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:2.25em;line-height:1.1111111;margin-bottom:.8888889em;margin-top:0}.lg\:prose-base :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:1.5em;line-height:1.3333333;margin-bottom:1em;margin-top:2em}.lg\:prose-base :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:1.25em;line-height:1.6;margin-bottom:.6em;margin-top:1.6em}.lg\:prose-base :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){line-height:1.5;margin-bottom:.5em;margin-top:1.5em}.lg\:prose-base :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:2em;margin-top:2em}.lg\:prose-base :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:2em;margin-top:2em}.lg\:prose-base :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0;margin-top:0}.lg\:prose-base :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:2em;margin-top:2em}.lg\:prose-base :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){border-radius:.3125rem;font-size:.875em;padding:.1875em .375em}.lg\:prose-base :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.875em}.lg\:prose-base :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.875em}.lg\:prose-base :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.9em}.lg\:prose-base :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){border-radius:.375rem;font-size:.875em;line-height:1.7142857;margin-bottom:1.7142857em;margin-top:1.7142857em;padding:.8571429em 1.1428571em}.lg\:prose-base :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em;margin-top:1.25em;padding-left:1.625em}.lg\:prose-base :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em;margin-top:1.25em;padding-left:1.625em}.lg\:prose-base :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:.5em;margin-top:.5em}.lg\:prose-base :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:.375em}.lg\:prose-base :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:.375em}.lg\:prose-base :where(.lg\:prose-base>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:.75em;margin-top:.75em}.lg\:prose-base :where(.lg\:prose-base>ul>li>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.lg\:prose-base :where(.lg\:prose-base>ul>li>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.lg\:prose-base :where(.lg\:prose-base>ol>li>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.lg\:prose-base :where(.lg\:prose-base>ol>li>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.lg\:prose-base :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:.75em;margin-top:.75em}.lg\:prose-base :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em;margin-top:1.25em}.lg\:prose-base :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.lg\:prose-base :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;padding-left:1.625em}.lg\:prose-base :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:3em;margin-top:3em}.lg\:prose-base :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.lg\:prose-base :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.lg\:prose-base :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.lg\:prose-base :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.lg\:prose-base :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.875em;line-height:1.7142857}.lg\:prose-base :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){padding-bottom:.5714286em;padding-left:.5714286em;padding-right:.5714286em}.lg\:prose-base :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:0}.lg\:prose-base :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-right:0}.lg\:prose-base :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding:.5714286em}.lg\:prose-base :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:0}.lg\:prose-base :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-right:0}.lg\:prose-base :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:2em;margin-top:2em}.lg\:prose-base :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0;margin-top:0}.lg\:prose-base :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.lg\:prose-base :where(.lg\:prose-base>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.lg\:prose-base :where(.lg\:prose-base>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}}@media not all and (min-width:1024px){.max-lg\:hidden{display:none}}@media not all and (min-width:768px){.max-md\:\!hidden{display:none!important}.max-md\:hidden{display:none}}@media not all and (min-width:640px){.max-sm\:w-full{width:100%}}@media (min-width:640px){.sm\:col-span-2{grid-column:span 2/span 2}.sm\:col-span-4{grid-column:span 4/span 4}.sm\:block{display:block}.sm\:max-h-56{max-height:14rem}.sm\:w-56{width:14rem}.sm\:max-w-44{max-width:11rem}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:justify-start{justify-content:flex-start}.sm\:border-l-2{border-left-width:2px}}@media (min-width:768px){.md\:block{display:block}.md\:hidden{display:none}.md\:w-40{width:10rem}.md\:w-48{width:12rem}.md\:w-8{width:2rem}.md\:max-w-xs{max-width:20rem}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-\[fit-content\(20rem\)_1fr\]{grid-template-columns:fit-content(20rem) 1fr}.md\:flex-row{flex-direction:row}.md\:justify-start{justify-content:flex-start}.md\:px-12{padding-left:3rem;padding-right:3rem}.md\:text-left{text-align:left}.md\:text-center{text-align:center}}@media (min-width:1024px){.lg\:w-56{width:14rem}.lg\:w-64{width:16rem}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:hyphens-auto{-webkit-hyphens:auto;hyphens:auto}.lg\:text-2xl{font-size:1.777rem}.lg\:text-3xl{font-size:2.369rem}.lg\:text-4xl{font-size:3.158rem}.lg\:text-5xl{font-size:4.21rem}}@media (min-width:1280px){.xl\:order-first{order:-9999}.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xl\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xl\:grid-rows-4{grid-template-rows:repeat(4,minmax(0,1fr))}}@media (prefers-color-scheme:dark){.dark\:bg-base-200{--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)))}}.\[\&_li\>\*\]\:rounded-none li>*{border-radius:0} \ No newline at end of file diff --git a/Wave/wwwroot/fonts/noto-sans-display-v26-latin-regular.woff2 b/Wave/wwwroot/fonts/noto-sans-display-v26-latin-regular.woff2 deleted file mode 100644 index b278720e16eb04cc3b238c2a45dadcb29c447f4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13048 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
58u>#-J3v_{mZ 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 diff --git a/docker-compose.override.yml b/docker-compose.override.yml index f4cb04f..5dcec09 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -3,7 +3,7 @@ version: '3.4' services: web: environment: - - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_HTTP_PORTS=8080 + - ASPNETCORE_ENVIRONMENT=Development volumes: - ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro \ No newline at end of file diff --git a/launchSettings.json b/launchSettings.json index cc19705..8282b22 100644 --- a/launchSettings.json +++ b/launchSettings.json @@ -1,23 +1,42 @@ { - "profiles": { - "Docker Compose": { - "commandName": "DockerCompose", - "commandVersion": "1.0", - "serviceActions": { - "web": "StartDebugging", - "database": "StartWithoutDebugging", - "mailhog": "DoNotStart", - "redis": "StartWithoutDebugging" - } - }, - "SMTP Debugging": { - "commandName": "DockerCompose", - "commandVersion": "1.0", - "composeProfile": { - "includes": [ - "smtp-debug" - ] - } - } - } + "profiles": { + "Docker Compose": { + "commandName": "DockerCompose", + "commandVersion": "1.0", + "serviceActions": { + "web": "StartDebugging", + "database": "StartWithoutDebugging", + "mailhog": "DoNotStart", + "redis": "StartWithoutDebugging", + "grafana": "StartWithoutDebugging", + "loki": "StartWithoutDebugging", + "prometheus": "StartWithoutDebugging" + } + }, + "SMTP Debugging": { + "commandName": "DockerCompose", + "commandVersion": "1.0", + "composeProfile": { + "includes": [ + "smtp-debug" + ] + } + }, + "Production": { + "commandName": "DockerCompose", + "commandVersion": "1.0", + "serviceActions": { + "database": "StartWithoutDebugging", + "grafana": "DoNotStart", + "loki": "DoNotStart", + "mailhog": "DoNotStart", + "prometheus": "DoNotStart", + "redis": "StartWithoutDebugging", + "web": "StartDebugging" + }, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Production" + } + } + } } \ No newline at end of file