From a77d00c3b9c3265fb3f89e4e765a207616bfdf15 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 17 May 2025 15:40:39 +0800 Subject: [PATCH] :lipstick: Restyled web pages :bricks: Add tailwindcss --- DysonNetwork.Sphere/.gitignore | 6 +- .../Account/MagicSpellService.cs | 5 +- DysonNetwork.Sphere/AppDatabase.cs | 3 + DysonNetwork.Sphere/Dockerfile | 14 + .../DysonNetwork.Sphere.csproj | 21 +- .../Pages/Checkpoint/CheckpointPage.cshtml | 224 ++-- DysonNetwork.Sphere/Pages/Index.cshtml | 24 + DysonNetwork.Sphere/Pages/Index.cshtml.cs | 11 + .../Pages/Shared/_Layout.cshtml | 36 + .../Pages/Spell/MagicSpellPage.cshtml | 146 ++- .../Pages/Spell/MagicSpellPage.cshtml.cs | 35 +- DysonNetwork.Sphere/Pages/_ViewImports.cshtml | 3 + DysonNetwork.Sphere/Pages/_ViewStart.cshtml | 3 + DysonNetwork.Sphere/appsettings.json | 4 + DysonNetwork.Sphere/package.json | 12 + DysonNetwork.Sphere/postcss.config.js | 5 + DysonNetwork.Sphere/tailwind.config.js | 11 + DysonNetwork.Sphere/wwwroot/css/site.css | 32 + DysonNetwork.Sphere/wwwroot/css/styles.css | 980 ++++++++++++++++++ 19 files changed, 1344 insertions(+), 231 deletions(-) create mode 100644 DysonNetwork.Sphere/Pages/Index.cshtml create mode 100644 DysonNetwork.Sphere/Pages/Index.cshtml.cs create mode 100644 DysonNetwork.Sphere/Pages/Shared/_Layout.cshtml create mode 100644 DysonNetwork.Sphere/Pages/_ViewImports.cshtml create mode 100644 DysonNetwork.Sphere/Pages/_ViewStart.cshtml create mode 100644 DysonNetwork.Sphere/package.json create mode 100644 DysonNetwork.Sphere/postcss.config.js create mode 100644 DysonNetwork.Sphere/tailwind.config.js create mode 100644 DysonNetwork.Sphere/wwwroot/css/site.css create mode 100644 DysonNetwork.Sphere/wwwroot/css/styles.css diff --git a/DysonNetwork.Sphere/.gitignore b/DysonNetwork.Sphere/.gitignore index fd7ee1f..1916c79 100644 --- a/DysonNetwork.Sphere/.gitignore +++ b/DysonNetwork.Sphere/.gitignore @@ -1,2 +1,6 @@ Keys -Uploads \ No newline at end of file +Uploads + +node_modules +bun.lock +package-lock.json \ No newline at end of file diff --git a/DysonNetwork.Sphere/Account/MagicSpellService.cs b/DysonNetwork.Sphere/Account/MagicSpellService.cs index 6d6cffe..8c0536a 100644 --- a/DysonNetwork.Sphere/Account/MagicSpellService.cs +++ b/DysonNetwork.Sphere/Account/MagicSpellService.cs @@ -44,7 +44,7 @@ public class MagicSpellService(AppDatabase db, EmailService email, ILogger - c.Account.Id == spell.AccountId && c.Content == spell.Meta["contact_method"] as string + c.Account.Id == spell.AccountId && c.Content == contactMethod ); if (contact is not null) { diff --git a/DysonNetwork.Sphere/AppDatabase.cs b/DysonNetwork.Sphere/AppDatabase.cs index 6348e0c..df81d9a 100644 --- a/DysonNetwork.Sphere/AppDatabase.cs +++ b/DysonNetwork.Sphere/AppDatabase.cs @@ -83,6 +83,9 @@ public class AppDatabase( dataSourceBuilder.EnableDynamicJson(); dataSourceBuilder.UseNetTopologySuite(); dataSourceBuilder.UseNodaTime(); + + if (configuration.GetValue("Debug")) + optionsBuilder.EnableSensitiveDataLogging(); optionsBuilder.UseNpgsql( dataSourceBuilder.Build(), diff --git a/DysonNetwork.Sphere/Dockerfile b/DysonNetwork.Sphere/Dockerfile index e6a5c35..e7e1047 100644 --- a/DysonNetwork.Sphere/Dockerfile +++ b/DysonNetwork.Sphere/Dockerfile @@ -5,12 +5,26 @@ EXPOSE 8080 EXPOSE 8081 FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +# Install Node.js +RUN apt-get update && apt-get install -y curl +RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ + && apt-get install -y nodejs \ + && npm install -g npm@latest + ARG BUILD_CONFIGURATION=Release WORKDIR /src COPY ["DysonNetwork.Sphere/DysonNetwork.Sphere.csproj", "DysonNetwork.Sphere/"] RUN dotnet restore "DysonNetwork.Sphere/DysonNetwork.Sphere.csproj" COPY . . WORKDIR "/src/DysonNetwork.Sphere" + +# Install npm packages and build Tailwind CSS +COPY ["DysonNetwork.Sphere/package*.json", "./"] +RUN npm install +COPY ["DysonNetwork.Sphere/postcss.config.js", "./"] +COPY ["DysonNetwork.Sphere/wwwroot/css/site.css", "./wwwroot/css/"] +RUN npx @tailwindcss/cli -i ./wwwroot/css/site.css -o ./wwwroot/css/styles.css + RUN dotnet build "DysonNetwork.Sphere.csproj" -c $BUILD_CONFIGURATION -o /app/build FROM build AS publish diff --git a/DysonNetwork.Sphere/DysonNetwork.Sphere.csproj b/DysonNetwork.Sphere/DysonNetwork.Sphere.csproj index d7df8f6..e31f505 100644 --- a/DysonNetwork.Sphere/DysonNetwork.Sphere.csproj +++ b/DysonNetwork.Sphere/DysonNetwork.Sphere.csproj @@ -1,12 +1,27 @@ - + + net9.0 enable enable Linux - cfdec342-d2f2-4a86-800b-93f0a0e4abde - + cfdec342-d2f2-4a86-800b-93f0a0e4abde + + + + + node_modules/.install-stamp + + + + + + + + + + diff --git a/DysonNetwork.Sphere/Pages/Checkpoint/CheckpointPage.cshtml b/DysonNetwork.Sphere/Pages/Checkpoint/CheckpointPage.cshtml index e6984d4..bedf0ac 100644 --- a/DysonNetwork.Sphere/Pages/Checkpoint/CheckpointPage.cshtml +++ b/DysonNetwork.Sphere/Pages/Checkpoint/CheckpointPage.cshtml @@ -2,157 +2,109 @@ @model DysonNetwork.Sphere.Pages.Checkpoint.CheckpointPage @{ - Layout = null; - + ViewData["Title"] = "Security Checkpoint"; var cfg = ViewData.Model.Configuration; var provider = cfg.GetSection("Captcha")["Provider"]?.ToLower(); var apiKey = cfg.GetSection("Captcha")["ApiKey"]; } - - - - - - Solar Network Captcha - - +@section Scripts { @switch (provider) { case "recaptcha": break; case "cloudflare": - + break; case "hcaptcha": break; } - - -
-
-

reCaptcha

- @switch (provider) - { - case "cloudflare": -
- break; - case "recaptcha": -
- break; - case "hcaptcha": -
- break; - default: -

Captcha provider not configured correctly.

- break; - } -
- -
- - - \ No newline at end of file + + function onSuccess(token) { + window.parent.postMessage("captcha_tk=" + token, "*"); + const redirectUri = getQueryParam("redirect_uri"); + if (redirectUri) { + window.location.href = `${redirectUri}?captcha_tk=${encodeURIComponent(token)}`; + } + } + +} + +
+
+
+

Security Check

+

Please complete the contest below to confirm you're not a robot

+ +
+ @switch (provider) + { + case "cloudflare": +
+
+ break; + case "recaptcha": +
+
+ break; + case "hcaptcha": +
+
+ break; + default: +
+

+ Captcha provider not configured correctly. +

+
+ break; + } +
+
+ +
+
Solar Network Anti-Robot
+
+ Powered by + @switch (provider) + { + case "cloudflare": + + Cloudflare Turnstile + + break; + case "recaptcha": + + Google reCaptcha + + break; + default: + Nothing + break; + } +
+ Hosted by + + DysonNetwork.Sphere + +
+
+
+
\ No newline at end of file diff --git a/DysonNetwork.Sphere/Pages/Index.cshtml b/DysonNetwork.Sphere/Pages/Index.cshtml new file mode 100644 index 0000000..99dad6b --- /dev/null +++ b/DysonNetwork.Sphere/Pages/Index.cshtml @@ -0,0 +1,24 @@ +@page +@model IndexModel +@{ + ViewData["Title"] = "The Solar Network"; +} + +
+
+

+ Solar Network +

+

+ This Solar Network instance is up and running. +

+ +
+
diff --git a/DysonNetwork.Sphere/Pages/Index.cshtml.cs b/DysonNetwork.Sphere/Pages/Index.cshtml.cs new file mode 100644 index 0000000..59832d8 --- /dev/null +++ b/DysonNetwork.Sphere/Pages/Index.cshtml.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace DysonNetwork.Sphere.Pages; + +public class IndexModel : PageModel +{ + public void OnGet() + { + // Add any page initialization logic here + } +} \ No newline at end of file diff --git a/DysonNetwork.Sphere/Pages/Shared/_Layout.cshtml b/DysonNetwork.Sphere/Pages/Shared/_Layout.cshtml new file mode 100644 index 0000000..ca87193 --- /dev/null +++ b/DysonNetwork.Sphere/Pages/Shared/_Layout.cshtml @@ -0,0 +1,36 @@ + + + + + + @ViewData["Title"] + + + +
+ +
+ +@* The header 64px + The footer 56px = 118px *@ +
+ @RenderBody() +
+ +
+
+

+ © @DateTime.Now.Year Solsynth LLC. All + rights reserved. +

+
+
+ +@await RenderSectionAsync("Scripts", required: false) + + \ No newline at end of file diff --git a/DysonNetwork.Sphere/Pages/Spell/MagicSpellPage.cshtml b/DysonNetwork.Sphere/Pages/Spell/MagicSpellPage.cshtml index d6eb888..d2fe5d6 100644 --- a/DysonNetwork.Sphere/Pages/Spell/MagicSpellPage.cshtml +++ b/DysonNetwork.Sphere/Pages/Spell/MagicSpellPage.cshtml @@ -1,92 +1,76 @@ @page "/spells/{spellWord}" -@using DysonNetwork.Sphere.Account @model DysonNetwork.Sphere.Pages.Spell.MagicSpellPage @{ - Layout = null; - - var spell = ViewData["Spell"] as MagicSpell; + ViewData["Title"] = "Magic Spell"; } - - - - - - Solar Network Magic Spell - - - - -
-
-

Magic Spell

- @if (spell == null) - { -
-

The spell was expired or not exists.

+
+
Solar Network
+
+ + Solsynth LLC + + © @DateTime.Now.Year +
+ Powered by + + DysonNetwork.Sphere +
- } - else - { -
-

The spell was applied successfully!

-
- } +
- -
- - \ No newline at end of file +
\ No newline at end of file diff --git a/DysonNetwork.Sphere/Pages/Spell/MagicSpellPage.cshtml.cs b/DysonNetwork.Sphere/Pages/Spell/MagicSpellPage.cshtml.cs index a11ebdd..5f798de 100644 --- a/DysonNetwork.Sphere/Pages/Spell/MagicSpellPage.cshtml.cs +++ b/DysonNetwork.Sphere/Pages/Spell/MagicSpellPage.cshtml.cs @@ -8,23 +8,42 @@ namespace DysonNetwork.Sphere.Pages.Spell; public class MagicSpellPage(AppDatabase db, MagicSpellService spells) : PageModel { + [BindProperty] + public MagicSpell? CurrentSpell { get; set; } + + public bool IsSuccess { get; set; } + public async Task OnGetAsync(string spellWord) { spellWord = Uri.UnescapeDataString(spellWord); var now = SystemClock.Instance.GetCurrentInstant(); - var spell = await db.MagicSpells + CurrentSpell = await db.MagicSpells .Where(e => e.Spell == spellWord) .Where(e => e.ExpiresAt == null || now < e.ExpiresAt) .Where(e => e.AffectedAt == null || now >= e.AffectedAt) + .Include(e => e.Account) .FirstOrDefaultAsync(); - - ViewData["Spell"] = spell; - - if (spell is not null) - { - await spells.ApplyMagicSpell(spell); - } return Page(); } + + public async Task OnPostAsync() + { + if (CurrentSpell?.Id == null) + return Page(); + + var now = SystemClock.Instance.GetCurrentInstant(); + var spell = await db.MagicSpells + .Where(e => e.Id == CurrentSpell.Id) + .Where(e => e.ExpiresAt == null || now < e.ExpiresAt) + .Where(e => e.AffectedAt == null || now >= e.AffectedAt) + .FirstOrDefaultAsync(); + + if (spell == null) + return Page(); + + await spells.ApplyMagicSpell(spell); + IsSuccess = true; + return Page(); + } } \ No newline at end of file diff --git a/DysonNetwork.Sphere/Pages/_ViewImports.cshtml b/DysonNetwork.Sphere/Pages/_ViewImports.cshtml new file mode 100644 index 0000000..313f074 --- /dev/null +++ b/DysonNetwork.Sphere/Pages/_ViewImports.cshtml @@ -0,0 +1,3 @@ +@using DysonNetwork.Sphere +@namespace DysonNetwork.Sphere.Pages +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers \ No newline at end of file diff --git a/DysonNetwork.Sphere/Pages/_ViewStart.cshtml b/DysonNetwork.Sphere/Pages/_ViewStart.cshtml new file mode 100644 index 0000000..40c70bc --- /dev/null +++ b/DysonNetwork.Sphere/Pages/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "_Layout"; +} \ No newline at end of file diff --git a/DysonNetwork.Sphere/appsettings.json b/DysonNetwork.Sphere/appsettings.json index bd00a63..2e2fe4d 100644 --- a/DysonNetwork.Sphere/appsettings.json +++ b/DysonNetwork.Sphere/appsettings.json @@ -1,4 +1,5 @@ { + "Debug": true, "Logging": { "LogLevel": { "Default": "Information", @@ -69,5 +70,8 @@ "FromAddress": "no-reply@mail.solsynth.dev", "FromName": "Alphabot", "SubjectPrefix": "Solar Network" + }, + "GeoIp": { + "DatabasePath": "./Keys/GeoLite2-City.mmdb" } } diff --git a/DysonNetwork.Sphere/package.json b/DysonNetwork.Sphere/package.json new file mode 100644 index 0000000..b93b1a4 --- /dev/null +++ b/DysonNetwork.Sphere/package.json @@ -0,0 +1,12 @@ +{ + "name": "@dyson/sphere", + "version": "1.0.0", + "description": "DysonNetwork Sphere Web Application", + "scripts": { + "css:build": "npx @tailwindcss/cli -i ./wwwroot/css/site.css -o ./wwwroot/css/styles.css" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4.1.7", + "@tailwindcss/cli": "^4.1.7" + } +} \ No newline at end of file diff --git a/DysonNetwork.Sphere/postcss.config.js b/DysonNetwork.Sphere/postcss.config.js new file mode 100644 index 0000000..84455e7 --- /dev/null +++ b/DysonNetwork.Sphere/postcss.config.js @@ -0,0 +1,5 @@ +export default { + plugins: { + "@tailwindcss/postcss": {}, + }, +} \ No newline at end of file diff --git a/DysonNetwork.Sphere/tailwind.config.js b/DysonNetwork.Sphere/tailwind.config.js new file mode 100644 index 0000000..288ba7b --- /dev/null +++ b/DysonNetwork.Sphere/tailwind.config.js @@ -0,0 +1,11 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + "./Pages/**/*.cshtml", + "./Views/**/*.cshtml" + ], + theme: { + extend: {}, + }, + plugins: [], +} \ No newline at end of file diff --git a/DysonNetwork.Sphere/wwwroot/css/site.css b/DysonNetwork.Sphere/wwwroot/css/site.css new file mode 100644 index 0000000..5fc9ea2 --- /dev/null +++ b/DysonNetwork.Sphere/wwwroot/css/site.css @@ -0,0 +1,32 @@ +@import "tailwindcss"; + +@layer theme, base, components, utilities; +@import "tailwindcss/theme.css" layer(theme); +@import "tailwindcss/preflight.css" layer(base); +@import "tailwindcss/utilities.css" layer(utilities); + +@layer base { + html, body { + padding: 0; + margin: 0; + box-sizing: border-box; + } + + /* For Firefox. */ + * { + scrollbar-width: none; + } + + /* For WebKit (Chrome & Safari). */ + ::-webkit-scrollbar { + display: none; + } +} + +.btn-primary { + @apply px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors dark:bg-blue-600 dark:hover:bg-blue-700; +} + +.container-default { + @apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8; +} \ No newline at end of file diff --git a/DysonNetwork.Sphere/wwwroot/css/styles.css b/DysonNetwork.Sphere/wwwroot/css/styles.css new file mode 100644 index 0000000..3f05f0a --- /dev/null +++ b/DysonNetwork.Sphere/wwwroot/css/styles.css @@ -0,0 +1,980 @@ +/*! tailwindcss v4.1.7 | MIT License | https://tailwindcss.com */ +@layer properties; +@layer theme, base, components, utilities; +@layer theme { + :root, :host { + --font-sans: ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', + 'Noto Color Emoji'; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', + monospace; + --color-yellow-100: oklch(97.3% 0.071 103.193); + --color-yellow-200: oklch(94.5% 0.129 101.54); + --color-yellow-500: oklch(79.5% 0.184 86.047); + --color-yellow-600: oklch(68.1% 0.162 75.834); + --color-yellow-800: oklch(47.6% 0.114 61.907); + --color-yellow-900: oklch(42.1% 0.095 57.708); + --color-green-100: oklch(96.2% 0.044 156.743); + --color-green-200: oklch(92.5% 0.084 155.995); + --color-green-500: oklch(72.3% 0.219 149.579); + --color-green-600: oklch(62.7% 0.194 149.214); + --color-green-800: oklch(44.8% 0.119 151.328); + --color-green-900: oklch(39.3% 0.095 152.535); + --color-blue-100: oklch(93.2% 0.032 255.585); + --color-blue-200: oklch(88.2% 0.059 254.128); + --color-blue-400: oklch(70.7% 0.165 254.624); + --color-blue-500: oklch(62.3% 0.214 259.815); + --color-blue-600: oklch(54.6% 0.245 262.881); + --color-blue-700: oklch(48.8% 0.243 264.376); + --color-blue-800: oklch(42.4% 0.199 265.638); + --color-blue-900: oklch(37.9% 0.146 265.522); + --color-gray-100: oklch(96.7% 0.003 264.542); + --color-gray-300: oklch(87.2% 0.01 258.338); + --color-gray-400: oklch(70.7% 0.022 261.325); + --color-gray-500: oklch(55.1% 0.027 264.364); + --color-gray-600: oklch(44.6% 0.03 256.802); + --color-gray-700: oklch(37.3% 0.034 259.733); + --color-gray-800: oklch(27.8% 0.033 256.848); + --color-gray-900: oklch(21% 0.034 264.665); + --color-white: #fff; + --spacing: 0.25rem; + --container-lg: 32rem; + --container-2xl: 42rem; + --container-7xl: 80rem; + --text-sm: 0.875rem; + --text-sm--line-height: calc(1.25 / 0.875); + --text-lg: 1.125rem; + --text-lg--line-height: calc(1.75 / 1.125); + --text-xl: 1.25rem; + --text-xl--line-height: calc(1.75 / 1.25); + --text-2xl: 1.5rem; + --text-2xl--line-height: calc(2 / 1.5); + --text-3xl: 1.875rem; + --text-3xl--line-height: calc(2.25 / 1.875); + --text-4xl: 2.25rem; + --text-4xl--line-height: calc(2.5 / 2.25); + --text-6xl: 3.75rem; + --text-6xl--line-height: 1; + --font-weight-medium: 500; + --font-weight-semibold: 600; + --font-weight-bold: 700; + --tracking-tight: -0.025em; + --radius-lg: 0.5rem; + --radius-xl: 0.75rem; + --default-transition-duration: 150ms; + --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + --default-font-family: var(--font-sans); + --default-mono-font-family: var(--font-mono); + } +} +@layer base { + *, ::after, ::before, ::backdrop, ::file-selector-button { + box-sizing: border-box; + margin: 0; + padding: 0; + border: 0 solid; + } + html, :host { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + tab-size: 4; + font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"); + font-feature-settings: var(--default-font-feature-settings, normal); + font-variation-settings: var(--default-font-variation-settings, normal); + -webkit-tap-highlight-color: transparent; + } + hr { + height: 0; + color: inherit; + border-top-width: 1px; + } + 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; + -webkit-text-decoration: inherit; + text-decoration: inherit; + } + b, strong { + font-weight: bolder; + } + code, kbd, samp, pre { + font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace); + font-feature-settings: var(--default-mono-font-feature-settings, normal); + font-variation-settings: var(--default-mono-font-variation-settings, normal); + font-size: 1em; + } + small { + font-size: 80%; + } + sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; + } + sub { + bottom: -0.25em; + } + sup { + top: -0.5em; + } + table { + text-indent: 0; + border-color: inherit; + border-collapse: collapse; + } + :-moz-focusring { + outline: auto; + } + progress { + vertical-align: baseline; + } + summary { + display: list-item; + } + ol, ul, menu { + list-style: none; + } + img, svg, video, canvas, audio, iframe, embed, object { + display: block; + vertical-align: middle; + } + img, video { + max-width: 100%; + height: auto; + } + button, input, select, optgroup, textarea, ::file-selector-button { + font: inherit; + font-feature-settings: inherit; + font-variation-settings: inherit; + letter-spacing: inherit; + color: inherit; + border-radius: 0; + background-color: transparent; + opacity: 1; + } + :where(select:is([multiple], [size])) optgroup { + font-weight: bolder; + } + :where(select:is([multiple], [size])) optgroup option { + padding-inline-start: 20px; + } + ::file-selector-button { + margin-inline-end: 4px; + } + ::placeholder { + opacity: 1; + } + @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) { + ::placeholder { + color: currentcolor; + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, currentcolor 50%, transparent); + } + } + } + textarea { + resize: vertical; + } + ::-webkit-search-decoration { + -webkit-appearance: none; + } + ::-webkit-date-and-time-value { + min-height: 1lh; + text-align: inherit; + } + ::-webkit-datetime-edit { + display: inline-flex; + } + ::-webkit-datetime-edit-fields-wrapper { + padding: 0; + } + ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field { + padding-block: 0; + } + :-moz-ui-invalid { + box-shadow: none; + } + button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button { + appearance: button; + } + ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { + height: auto; + } + [hidden]:where(:not([hidden="until-found"])) { + display: none !important; + } +} +@layer utilities { + .invisible { + visibility: hidden; + } + .fixed { + position: fixed; + } + .static { + position: static; + } + .top-0 { + top: calc(var(--spacing) * 0); + } + .right-0 { + right: calc(var(--spacing) * 0); + } + .bottom-0 { + bottom: calc(var(--spacing) * 0); + } + .left-0 { + left: calc(var(--spacing) * 0); + } + .z-50 { + z-index: 50; + } + .mx-auto { + margin-inline: auto; + } + .mt-4 { + margin-top: calc(var(--spacing) * 4); + } + .mt-6 { + margin-top: calc(var(--spacing) * 6); + } + .mt-8 { + margin-top: calc(var(--spacing) * 8); + } + .mt-10 { + margin-top: calc(var(--spacing) * 10); + } + .mt-\[64px\] { + margin-top: 64px; + } + .mb-1 { + margin-bottom: calc(var(--spacing) * 1); + } + .mb-2 { + margin-bottom: calc(var(--spacing) * 2); + } + .mb-4 { + margin-bottom: calc(var(--spacing) * 4); + } + .mb-6 { + margin-bottom: calc(var(--spacing) * 6); + } + .mb-8 { + margin-bottom: calc(var(--spacing) * 8); + } + .block { + display: block; + } + .flex { + display: flex; + } + .hidden { + display: none; + } + .table { + display: table; + } + .h-16 { + height: calc(var(--spacing) * 16); + } + .h-\[calc\(100dvh-118px\)\] { + height: calc(100dvh - 118px); + } + .h-full { + height: 100%; + } + .w-full { + width: 100%; + } + .max-w-2xl { + max-width: var(--container-2xl); + } + .max-w-lg { + max-width: var(--container-lg); + } + .transform { + transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,); + } + .flex-col { + flex-direction: column; + } + .items-center { + align-items: center; + } + .justify-between { + justify-content: space-between; + } + .justify-center { + justify-content: center; + } + .gap-x-6 { + column-gap: calc(var(--spacing) * 6); + } + .rounded-lg { + border-radius: var(--radius-lg); + } + .bg-blue-500 { + background-color: var(--color-blue-500); + } + .bg-green-100 { + background-color: var(--color-green-100); + } + .bg-white { + background-color: var(--color-white); + } + .bg-yellow-100 { + background-color: var(--color-yellow-100); + } + .p-4 { + padding: calc(var(--spacing) * 4); + } + .p-6 { + padding: calc(var(--spacing) * 6); + } + .px-4 { + padding-inline: calc(var(--spacing) * 4); + } + .px-6 { + padding-inline: calc(var(--spacing) * 6); + } + .py-3 { + padding-block: calc(var(--spacing) * 3); + } + .py-12 { + padding-block: calc(var(--spacing) * 12); + } + .text-center { + text-align: center; + } + .text-2xl { + font-size: var(--text-2xl); + line-height: var(--tw-leading, var(--text-2xl--line-height)); + } + .text-3xl { + font-size: var(--text-3xl); + line-height: var(--tw-leading, var(--text-3xl--line-height)); + } + .text-4xl { + font-size: var(--text-4xl); + line-height: var(--tw-leading, var(--text-4xl--line-height)); + } + .text-lg { + font-size: var(--text-lg); + line-height: var(--tw-leading, var(--text-lg--line-height)); + } + .text-sm { + font-size: var(--text-sm); + line-height: var(--tw-leading, var(--text-sm--line-height)); + } + .text-xl { + font-size: var(--text-xl); + line-height: var(--tw-leading, var(--text-xl--line-height)); + } + .leading-6 { + --tw-leading: calc(var(--spacing) * 6); + line-height: calc(var(--spacing) * 6); + } + .leading-8 { + --tw-leading: calc(var(--spacing) * 8); + line-height: calc(var(--spacing) * 8); + } + .font-bold { + --tw-font-weight: var(--font-weight-bold); + font-weight: var(--font-weight-bold); + } + .font-medium { + --tw-font-weight: var(--font-weight-medium); + font-weight: var(--font-weight-medium); + } + .font-semibold { + --tw-font-weight: var(--font-weight-semibold); + font-weight: var(--font-weight-semibold); + } + .tracking-tight { + --tw-tracking: var(--tracking-tight); + letter-spacing: var(--tracking-tight); + } + .text-gray-500 { + color: var(--color-gray-500); + } + .text-gray-600 { + color: var(--color-gray-600); + } + .text-gray-700 { + color: var(--color-gray-700); + } + .text-gray-900 { + color: var(--color-gray-900); + } + .text-green-800 { + color: var(--color-green-800); + } + .text-white { + color: var(--color-white); + } + .text-yellow-800 { + color: var(--color-yellow-800); + } + .opacity-80 { + opacity: 80%; + } + .shadow-\[0_-1px_3px_0_rgba\(0\,0\,0\,0\.1\)\] { + --tw-shadow: 0 -1px 3px 0 var(--tw-shadow-color, rgba(0,0,0,0.1)); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + .shadow-lg { + --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + .shadow-sm { + --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + .blur { + --tw-blur: blur(8px); + filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); + } + .filter { + filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); + } + .transition-colors { + transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + } + .hover\:scale-105 { + &:hover { + @media (hover: hover) { + --tw-scale-x: 105%; + --tw-scale-y: 105%; + --tw-scale-z: 105%; + scale: var(--tw-scale-x) var(--tw-scale-y); + } + } + } + .hover\:bg-blue-600 { + &:hover { + @media (hover: hover) { + background-color: var(--color-blue-600); + } + } + } + .hover\:text-blue-600 { + &:hover { + @media (hover: hover) { + color: var(--color-blue-600); + } + } + } + .hover\:text-gray-700 { + &:hover { + @media (hover: hover) { + color: var(--color-gray-700); + } + } + } + .focus\:ring-2 { + &:focus { + --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + } + .focus\:ring-blue-400 { + &:focus { + --tw-ring-color: var(--color-blue-400); + } + } + .focus\:outline-none { + &:focus { + --tw-outline-style: none; + outline-style: none; + } + } + .sm\:text-6xl { + @media (width >= 40rem) { + font-size: var(--text-6xl); + line-height: var(--tw-leading, var(--text-6xl--line-height)); + } + } + .dark\:bg-gray-800 { + @media (prefers-color-scheme: dark) { + background-color: var(--color-gray-800); + } + } + .dark\:bg-gray-900 { + @media (prefers-color-scheme: dark) { + background-color: var(--color-gray-900); + } + } + .dark\:bg-green-900 { + @media (prefers-color-scheme: dark) { + background-color: var(--color-green-900); + } + } + .dark\:bg-yellow-900 { + @media (prefers-color-scheme: dark) { + background-color: var(--color-yellow-900); + } + } + .dark\:text-gray-100 { + @media (prefers-color-scheme: dark) { + color: var(--color-gray-100); + } + } + .dark\:text-gray-300 { + @media (prefers-color-scheme: dark) { + color: var(--color-gray-300); + } + } + .dark\:text-gray-400 { + @media (prefers-color-scheme: dark) { + color: var(--color-gray-400); + } + } + .dark\:text-green-200 { + @media (prefers-color-scheme: dark) { + color: var(--color-green-200); + } + } + .dark\:text-white { + @media (prefers-color-scheme: dark) { + color: var(--color-white); + } + } + .dark\:text-yellow-200 { + @media (prefers-color-scheme: dark) { + color: var(--color-yellow-200); + } + } + .dark\:hover\:text-blue-400 { + @media (prefers-color-scheme: dark) { + &:hover { + @media (hover: hover) { + color: var(--color-blue-400); + } + } + } + } + .dark\:hover\:text-gray-300 { + @media (prefers-color-scheme: dark) { + &:hover { + @media (hover: hover) { + color: var(--color-gray-300); + } + } + } + } +} +@layer theme, base, components, utilities; +@layer theme; +@layer base { + *, ::after, ::before, ::backdrop, ::file-selector-button { + box-sizing: border-box; + margin: 0; + padding: 0; + border: 0 solid; + } + html, :host { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + tab-size: 4; + font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'); + font-feature-settings: var(--default-font-feature-settings, normal); + font-variation-settings: var(--default-font-variation-settings, normal); + -webkit-tap-highlight-color: transparent; + } + hr { + height: 0; + color: inherit; + border-top-width: 1px; + } + 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; + -webkit-text-decoration: inherit; + text-decoration: inherit; + } + b, strong { + font-weight: bolder; + } + code, kbd, samp, pre { + font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace); + font-feature-settings: var(--default-mono-font-feature-settings, normal); + font-variation-settings: var(--default-mono-font-variation-settings, normal); + font-size: 1em; + } + small { + font-size: 80%; + } + sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; + } + sub { + bottom: -0.25em; + } + sup { + top: -0.5em; + } + table { + text-indent: 0; + border-color: inherit; + border-collapse: collapse; + } + :-moz-focusring { + outline: auto; + } + progress { + vertical-align: baseline; + } + summary { + display: list-item; + } + ol, ul, menu { + list-style: none; + } + img, svg, video, canvas, audio, iframe, embed, object { + display: block; + vertical-align: middle; + } + img, video { + max-width: 100%; + height: auto; + } + button, input, select, optgroup, textarea, ::file-selector-button { + font: inherit; + font-feature-settings: inherit; + font-variation-settings: inherit; + letter-spacing: inherit; + color: inherit; + border-radius: 0; + background-color: transparent; + opacity: 1; + } + :where(select:is([multiple], [size])) optgroup { + font-weight: bolder; + } + :where(select:is([multiple], [size])) optgroup option { + padding-inline-start: 20px; + } + ::file-selector-button { + margin-inline-end: 4px; + } + ::placeholder { + opacity: 1; + } + @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) { + ::placeholder { + color: currentcolor; + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, currentcolor 50%, transparent); + } + } + } + textarea { + resize: vertical; + } + ::-webkit-search-decoration { + -webkit-appearance: none; + } + ::-webkit-date-and-time-value { + min-height: 1lh; + text-align: inherit; + } + ::-webkit-datetime-edit { + display: inline-flex; + } + ::-webkit-datetime-edit-fields-wrapper { + padding: 0; + } + ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field { + padding-block: 0; + } + :-moz-ui-invalid { + box-shadow: none; + } + button, input:where([type='button'], [type='reset'], [type='submit']), ::file-selector-button { + appearance: button; + } + ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { + height: auto; + } + [hidden]:where(:not([hidden='until-found'])) { + display: none !important; + } +} +@layer utilities; +@layer base { + html, body { + padding: 0; + margin: 0; + box-sizing: border-box; + } + * { + scrollbar-width: none; + } + ::-webkit-scrollbar { + display: none; + } +} +.btn-primary { + border-radius: var(--radius-lg); + background-color: var(--color-blue-500); + padding-inline: calc(var(--spacing) * 4); + padding-block: calc(var(--spacing) * 2); + color: var(--color-white); + transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + &:hover { + @media (hover: hover) { + background-color: var(--color-blue-600); + } + } + @media (prefers-color-scheme: dark) { + background-color: var(--color-blue-600); + } + @media (prefers-color-scheme: dark) { + &:hover { + @media (hover: hover) { + background-color: var(--color-blue-700); + } + } + } +} +.container-default { + margin-inline: auto; + max-width: var(--container-7xl); + padding-inline: calc(var(--spacing) * 4); + @media (width >= 40rem) { + padding-inline: calc(var(--spacing) * 6); + } + @media (width >= 64rem) { + padding-inline: calc(var(--spacing) * 8); + } +} +@property --tw-rotate-x { + syntax: "*"; + inherits: false; +} +@property --tw-rotate-y { + syntax: "*"; + inherits: false; +} +@property --tw-rotate-z { + syntax: "*"; + inherits: false; +} +@property --tw-skew-x { + syntax: "*"; + inherits: false; +} +@property --tw-skew-y { + syntax: "*"; + inherits: false; +} +@property --tw-leading { + syntax: "*"; + inherits: false; +} +@property --tw-font-weight { + syntax: "*"; + inherits: false; +} +@property --tw-tracking { + syntax: "*"; + inherits: false; +} +@property --tw-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@property --tw-shadow-color { + syntax: "*"; + inherits: false; +} +@property --tw-shadow-alpha { + syntax: ""; + inherits: false; + initial-value: 100%; +} +@property --tw-inset-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@property --tw-inset-shadow-color { + syntax: "*"; + inherits: false; +} +@property --tw-inset-shadow-alpha { + syntax: ""; + inherits: false; + initial-value: 100%; +} +@property --tw-ring-color { + syntax: "*"; + inherits: false; +} +@property --tw-ring-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@property --tw-inset-ring-color { + syntax: "*"; + inherits: false; +} +@property --tw-inset-ring-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@property --tw-ring-inset { + syntax: "*"; + inherits: false; +} +@property --tw-ring-offset-width { + syntax: ""; + inherits: false; + initial-value: 0px; +} +@property --tw-ring-offset-color { + syntax: "*"; + inherits: false; + initial-value: #fff; +} +@property --tw-ring-offset-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@property --tw-blur { + syntax: "*"; + inherits: false; +} +@property --tw-brightness { + syntax: "*"; + inherits: false; +} +@property --tw-contrast { + syntax: "*"; + inherits: false; +} +@property --tw-grayscale { + syntax: "*"; + inherits: false; +} +@property --tw-hue-rotate { + syntax: "*"; + inherits: false; +} +@property --tw-invert { + syntax: "*"; + inherits: false; +} +@property --tw-opacity { + syntax: "*"; + inherits: false; +} +@property --tw-saturate { + syntax: "*"; + inherits: false; +} +@property --tw-sepia { + syntax: "*"; + inherits: false; +} +@property --tw-drop-shadow { + syntax: "*"; + inherits: false; +} +@property --tw-drop-shadow-color { + syntax: "*"; + inherits: false; +} +@property --tw-drop-shadow-alpha { + syntax: ""; + inherits: false; + initial-value: 100%; +} +@property --tw-drop-shadow-size { + syntax: "*"; + inherits: false; +} +@property --tw-scale-x { + syntax: "*"; + inherits: false; + initial-value: 1; +} +@property --tw-scale-y { + syntax: "*"; + inherits: false; + initial-value: 1; +} +@property --tw-scale-z { + syntax: "*"; + inherits: false; + initial-value: 1; +} +@layer properties { + @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) { + *, ::before, ::after, ::backdrop { + --tw-rotate-x: initial; + --tw-rotate-y: initial; + --tw-rotate-z: initial; + --tw-skew-x: initial; + --tw-skew-y: initial; + --tw-leading: initial; + --tw-font-weight: initial; + --tw-tracking: initial; + --tw-shadow: 0 0 #0000; + --tw-shadow-color: initial; + --tw-shadow-alpha: 100%; + --tw-inset-shadow: 0 0 #0000; + --tw-inset-shadow-color: initial; + --tw-inset-shadow-alpha: 100%; + --tw-ring-color: initial; + --tw-ring-shadow: 0 0 #0000; + --tw-inset-ring-color: initial; + --tw-inset-ring-shadow: 0 0 #0000; + --tw-ring-inset: initial; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-offset-shadow: 0 0 #0000; + --tw-blur: initial; + --tw-brightness: initial; + --tw-contrast: initial; + --tw-grayscale: initial; + --tw-hue-rotate: initial; + --tw-invert: initial; + --tw-opacity: initial; + --tw-saturate: initial; + --tw-sepia: initial; + --tw-drop-shadow: initial; + --tw-drop-shadow-color: initial; + --tw-drop-shadow-alpha: 100%; + --tw-drop-shadow-size: initial; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-scale-z: 1; + } + } +}