Vibe Google Analytics
This commit is contained in:
@@ -0,0 +1 @@
|
||||
[]
|
||||
@@ -0,0 +1 @@
|
||||
3.0
|
||||
@@ -60,7 +60,7 @@ foreach (var file in mdFiles)
|
||||
ImmortalizeWhen = NullIfNa(StripWikiLinks(yaml.GetValueOrDefault("immortalizeWhen"))),
|
||||
ImageFile = imageFile,
|
||||
Artist = yaml.GetValueOrDefault("artist"),
|
||||
Rarity = yaml.GetValueOrDefault("rarity"),
|
||||
Rarity = yaml.GetValueOrDefault("rarity")
|
||||
};
|
||||
|
||||
cards.Add(card);
|
||||
@@ -117,7 +117,7 @@ for (var i = 0; i < cards.Count; i++)
|
||||
WriteStrProp(writer, "ImmortalizeFrom", c.ImmortalizeFrom, 3);
|
||||
WriteStrProp(writer, "ImmortalizeWhen", c.ImmortalizeWhen, 3);
|
||||
WriteStrProp(writer, "ImageFile", c.ImageFile, 3);
|
||||
|
||||
|
||||
WriteStrProp(writer, "Artist", c.Artist, 3);
|
||||
WriteStrProp(writer, "Rarity", c.Rarity, 3);
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Model\Model.csproj" />
|
||||
<ProjectReference Include="..\Shared\Shared.csproj" />
|
||||
<ProjectReference Include="..\Model\Model.csproj"/>
|
||||
<ProjectReference Include="..\Shared\Shared.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -21,20 +21,20 @@ main {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
||||
white-space: nowrap;
|
||||
margin-left: 1.5rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
||||
white-space: nowrap;
|
||||
margin-left: 1.5rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.top-row ::deep a:first-child {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.top-row ::deep a:first-child {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@media (max-width: 640.98px) {
|
||||
.top-row {
|
||||
@@ -90,9 +90,9 @@ main {
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#blazor-error-ui .dismiss {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
top: 0.5rem;
|
||||
}
|
||||
#blazor-error-ui .dismiss {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
top: 0.5rem;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
.top-row {
|
||||
min-height: 3.5rem;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
@@ -51,33 +51,33 @@
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-item:first-of-type {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
.nav-item:first-of-type {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.nav-item:last-of-type {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
.nav-item:last-of-type {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.nav-item ::deep .nav-link {
|
||||
color: #d7d7d7;
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
height: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 3rem;
|
||||
width: 100%;
|
||||
}
|
||||
.nav-item ::deep .nav-link {
|
||||
color: #d7d7d7;
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
height: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 3rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nav-item ::deep a.active {
|
||||
background-color: rgba(255,255,255,0.37);
|
||||
background-color: rgba(255, 255, 255, 0.37);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-item ::deep .nav-link:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,12 +31,11 @@
|
||||
opacity: 0;
|
||||
transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
|
||||
animation: components-reconnect-modal-fadeOutOpacity 0.5s both;
|
||||
&[open]
|
||||
|
||||
{
|
||||
animation: components-reconnect-modal-slideUp 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity 0.5s ease-in-out 0.3s;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
&[open] {
|
||||
animation: components-reconnect-modal-slideUp 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity 0.5s ease-in-out 0.3s;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -96,13 +95,13 @@
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
#components-reconnect-modal button:hover {
|
||||
background-color: #3b6ea2;
|
||||
}
|
||||
#components-reconnect-modal button:hover {
|
||||
background-color: #3b6ea2;
|
||||
}
|
||||
|
||||
#components-reconnect-modal button:active {
|
||||
background-color: #6b9ed2;
|
||||
}
|
||||
#components-reconnect-modal button:active {
|
||||
background-color: #6b9ed2;
|
||||
}
|
||||
|
||||
.components-rejoining-animation {
|
||||
position: relative;
|
||||
@@ -110,17 +109,17 @@
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.components-rejoining-animation div {
|
||||
position: absolute;
|
||||
border: 3px solid #0087ff;
|
||||
opacity: 1;
|
||||
border-radius: 50%;
|
||||
animation: components-rejoining-animation 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
|
||||
}
|
||||
.components-rejoining-animation div {
|
||||
position: absolute;
|
||||
border: 3px solid #0087ff;
|
||||
opacity: 1;
|
||||
border-radius: 50%;
|
||||
animation: components-rejoining-animation 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
|
||||
}
|
||||
|
||||
.components-rejoining-animation div:nth-child(2) {
|
||||
animation-delay: -0.5s;
|
||||
}
|
||||
.components-rejoining-animation div:nth-child(2) {
|
||||
animation-delay: -0.5s;
|
||||
}
|
||||
|
||||
@keyframes components-rejoining-animation {
|
||||
0% {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
|
||||
|
||||
@code {
|
||||
private int currentCount = 0;
|
||||
private int currentCount;
|
||||
|
||||
private void IncrementCount()
|
||||
{
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that
|
||||
occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||
It can result in displaying sensitive information from exceptions to end users.
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong>
|
||||
environment variable to <strong>Development</strong>
|
||||
and restarting the app.
|
||||
</p>
|
||||
|
||||
@@ -30,7 +32,9 @@
|
||||
private string? RequestId { get; set; }
|
||||
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
protected override void OnInitialized() =>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
@using Shared.Pages
|
||||
<Router AppAssembly="typeof(Program).Assembly" AdditionalAssemblies="new[] { typeof(Home).Assembly }" NotFoundPage="typeof(Pages.NotFound)">
|
||||
@using NotFound = Cloud.Components.Pages.NotFound
|
||||
<Router AppAssembly="typeof(Program).Assembly" AdditionalAssemblies="new[] { typeof(Home).Assembly }"
|
||||
NotFoundPage="typeof(NotFound)">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)"/>
|
||||
<RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)"/>
|
||||
<FocusOnNavigate RouteData="routeData" Selector="h1"/>
|
||||
</Found>
|
||||
</Router>
|
||||
@@ -11,7 +11,7 @@ var app = builder.Build();
|
||||
// Configure the HTTP request pipeline.
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
||||
app.UseExceptionHandler("/Error", true);
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5230",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:7086;http://localhost:5230",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5230",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:7086;http://localhost:5230",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ a, .btn-link {
|
||||
}
|
||||
|
||||
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
|
||||
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
|
||||
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
|
||||
}
|
||||
|
||||
.content {
|
||||
@@ -42,9 +42,9 @@ h1:focus {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.blazor-error-boundary::after {
|
||||
content: "An error has occurred."
|
||||
}
|
||||
.blazor-error-boundary::after {
|
||||
content: "An error has occurred."
|
||||
}
|
||||
|
||||
.darker-border-checkbox.form-check-input {
|
||||
border-color: #929292;
|
||||
|
||||
+4416
-3450
File diff suppressed because it is too large
Load Diff
+4417
-3450
File diff suppressed because it is too large
Load Diff
+339
-327
@@ -5,427 +5,435 @@
|
||||
*/
|
||||
:root,
|
||||
[data-bs-theme=light] {
|
||||
--bs-blue: #0d6efd;
|
||||
--bs-indigo: #6610f2;
|
||||
--bs-purple: #6f42c1;
|
||||
--bs-pink: #d63384;
|
||||
--bs-red: #dc3545;
|
||||
--bs-orange: #fd7e14;
|
||||
--bs-yellow: #ffc107;
|
||||
--bs-green: #198754;
|
||||
--bs-teal: #20c997;
|
||||
--bs-cyan: #0dcaf0;
|
||||
--bs-black: #000;
|
||||
--bs-white: #fff;
|
||||
--bs-gray: #6c757d;
|
||||
--bs-gray-dark: #343a40;
|
||||
--bs-gray-100: #f8f9fa;
|
||||
--bs-gray-200: #e9ecef;
|
||||
--bs-gray-300: #dee2e6;
|
||||
--bs-gray-400: #ced4da;
|
||||
--bs-gray-500: #adb5bd;
|
||||
--bs-gray-600: #6c757d;
|
||||
--bs-gray-700: #495057;
|
||||
--bs-gray-800: #343a40;
|
||||
--bs-gray-900: #212529;
|
||||
--bs-primary: #0d6efd;
|
||||
--bs-secondary: #6c757d;
|
||||
--bs-success: #198754;
|
||||
--bs-info: #0dcaf0;
|
||||
--bs-warning: #ffc107;
|
||||
--bs-danger: #dc3545;
|
||||
--bs-light: #f8f9fa;
|
||||
--bs-dark: #212529;
|
||||
--bs-primary-rgb: 13, 110, 253;
|
||||
--bs-secondary-rgb: 108, 117, 125;
|
||||
--bs-success-rgb: 25, 135, 84;
|
||||
--bs-info-rgb: 13, 202, 240;
|
||||
--bs-warning-rgb: 255, 193, 7;
|
||||
--bs-danger-rgb: 220, 53, 69;
|
||||
--bs-light-rgb: 248, 249, 250;
|
||||
--bs-dark-rgb: 33, 37, 41;
|
||||
--bs-primary-text-emphasis: #052c65;
|
||||
--bs-secondary-text-emphasis: #2b2f32;
|
||||
--bs-success-text-emphasis: #0a3622;
|
||||
--bs-info-text-emphasis: #055160;
|
||||
--bs-warning-text-emphasis: #664d03;
|
||||
--bs-danger-text-emphasis: #58151c;
|
||||
--bs-light-text-emphasis: #495057;
|
||||
--bs-dark-text-emphasis: #495057;
|
||||
--bs-primary-bg-subtle: #cfe2ff;
|
||||
--bs-secondary-bg-subtle: #e2e3e5;
|
||||
--bs-success-bg-subtle: #d1e7dd;
|
||||
--bs-info-bg-subtle: #cff4fc;
|
||||
--bs-warning-bg-subtle: #fff3cd;
|
||||
--bs-danger-bg-subtle: #f8d7da;
|
||||
--bs-light-bg-subtle: #fcfcfd;
|
||||
--bs-dark-bg-subtle: #ced4da;
|
||||
--bs-primary-border-subtle: #9ec5fe;
|
||||
--bs-secondary-border-subtle: #c4c8cb;
|
||||
--bs-success-border-subtle: #a3cfbb;
|
||||
--bs-info-border-subtle: #9eeaf9;
|
||||
--bs-warning-border-subtle: #ffe69c;
|
||||
--bs-danger-border-subtle: #f1aeb5;
|
||||
--bs-light-border-subtle: #e9ecef;
|
||||
--bs-dark-border-subtle: #adb5bd;
|
||||
--bs-white-rgb: 255, 255, 255;
|
||||
--bs-black-rgb: 0, 0, 0;
|
||||
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||
--bs-body-font-size: 1rem;
|
||||
--bs-body-font-weight: 400;
|
||||
--bs-body-line-height: 1.5;
|
||||
--bs-body-color: #212529;
|
||||
--bs-body-color-rgb: 33, 37, 41;
|
||||
--bs-body-bg: #fff;
|
||||
--bs-body-bg-rgb: 255, 255, 255;
|
||||
--bs-emphasis-color: #000;
|
||||
--bs-emphasis-color-rgb: 0, 0, 0;
|
||||
--bs-secondary-color: rgba(33, 37, 41, 0.75);
|
||||
--bs-secondary-color-rgb: 33, 37, 41;
|
||||
--bs-secondary-bg: #e9ecef;
|
||||
--bs-secondary-bg-rgb: 233, 236, 239;
|
||||
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
|
||||
--bs-tertiary-color-rgb: 33, 37, 41;
|
||||
--bs-tertiary-bg: #f8f9fa;
|
||||
--bs-tertiary-bg-rgb: 248, 249, 250;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #0d6efd;
|
||||
--bs-link-color-rgb: 13, 110, 253;
|
||||
--bs-link-decoration: underline;
|
||||
--bs-link-hover-color: #0a58ca;
|
||||
--bs-link-hover-color-rgb: 10, 88, 202;
|
||||
--bs-code-color: #d63384;
|
||||
--bs-highlight-color: #212529;
|
||||
--bs-highlight-bg: #fff3cd;
|
||||
--bs-border-width: 1px;
|
||||
--bs-border-style: solid;
|
||||
--bs-border-color: #dee2e6;
|
||||
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
|
||||
--bs-border-radius: 0.375rem;
|
||||
--bs-border-radius-sm: 0.25rem;
|
||||
--bs-border-radius-lg: 0.5rem;
|
||||
--bs-border-radius-xl: 1rem;
|
||||
--bs-border-radius-xxl: 2rem;
|
||||
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
|
||||
--bs-border-radius-pill: 50rem;
|
||||
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
|
||||
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
--bs-focus-ring-width: 0.25rem;
|
||||
--bs-focus-ring-opacity: 0.25;
|
||||
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
|
||||
--bs-form-valid-color: #198754;
|
||||
--bs-form-valid-border-color: #198754;
|
||||
--bs-form-invalid-color: #dc3545;
|
||||
--bs-form-invalid-border-color: #dc3545;
|
||||
--bs-blue: #0d6efd;
|
||||
--bs-indigo: #6610f2;
|
||||
--bs-purple: #6f42c1;
|
||||
--bs-pink: #d63384;
|
||||
--bs-red: #dc3545;
|
||||
--bs-orange: #fd7e14;
|
||||
--bs-yellow: #ffc107;
|
||||
--bs-green: #198754;
|
||||
--bs-teal: #20c997;
|
||||
--bs-cyan: #0dcaf0;
|
||||
--bs-black: #000;
|
||||
--bs-white: #fff;
|
||||
--bs-gray: #6c757d;
|
||||
--bs-gray-dark: #343a40;
|
||||
--bs-gray-100: #f8f9fa;
|
||||
--bs-gray-200: #e9ecef;
|
||||
--bs-gray-300: #dee2e6;
|
||||
--bs-gray-400: #ced4da;
|
||||
--bs-gray-500: #adb5bd;
|
||||
--bs-gray-600: #6c757d;
|
||||
--bs-gray-700: #495057;
|
||||
--bs-gray-800: #343a40;
|
||||
--bs-gray-900: #212529;
|
||||
--bs-primary: #0d6efd;
|
||||
--bs-secondary: #6c757d;
|
||||
--bs-success: #198754;
|
||||
--bs-info: #0dcaf0;
|
||||
--bs-warning: #ffc107;
|
||||
--bs-danger: #dc3545;
|
||||
--bs-light: #f8f9fa;
|
||||
--bs-dark: #212529;
|
||||
--bs-primary-rgb: 13, 110, 253;
|
||||
--bs-secondary-rgb: 108, 117, 125;
|
||||
--bs-success-rgb: 25, 135, 84;
|
||||
--bs-info-rgb: 13, 202, 240;
|
||||
--bs-warning-rgb: 255, 193, 7;
|
||||
--bs-danger-rgb: 220, 53, 69;
|
||||
--bs-light-rgb: 248, 249, 250;
|
||||
--bs-dark-rgb: 33, 37, 41;
|
||||
--bs-primary-text-emphasis: #052c65;
|
||||
--bs-secondary-text-emphasis: #2b2f32;
|
||||
--bs-success-text-emphasis: #0a3622;
|
||||
--bs-info-text-emphasis: #055160;
|
||||
--bs-warning-text-emphasis: #664d03;
|
||||
--bs-danger-text-emphasis: #58151c;
|
||||
--bs-light-text-emphasis: #495057;
|
||||
--bs-dark-text-emphasis: #495057;
|
||||
--bs-primary-bg-subtle: #cfe2ff;
|
||||
--bs-secondary-bg-subtle: #e2e3e5;
|
||||
--bs-success-bg-subtle: #d1e7dd;
|
||||
--bs-info-bg-subtle: #cff4fc;
|
||||
--bs-warning-bg-subtle: #fff3cd;
|
||||
--bs-danger-bg-subtle: #f8d7da;
|
||||
--bs-light-bg-subtle: #fcfcfd;
|
||||
--bs-dark-bg-subtle: #ced4da;
|
||||
--bs-primary-border-subtle: #9ec5fe;
|
||||
--bs-secondary-border-subtle: #c4c8cb;
|
||||
--bs-success-border-subtle: #a3cfbb;
|
||||
--bs-info-border-subtle: #9eeaf9;
|
||||
--bs-warning-border-subtle: #ffe69c;
|
||||
--bs-danger-border-subtle: #f1aeb5;
|
||||
--bs-light-border-subtle: #e9ecef;
|
||||
--bs-dark-border-subtle: #adb5bd;
|
||||
--bs-white-rgb: 255, 255, 255;
|
||||
--bs-black-rgb: 0, 0, 0;
|
||||
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||
--bs-body-font-size: 1rem;
|
||||
--bs-body-font-weight: 400;
|
||||
--bs-body-line-height: 1.5;
|
||||
--bs-body-color: #212529;
|
||||
--bs-body-color-rgb: 33, 37, 41;
|
||||
--bs-body-bg: #fff;
|
||||
--bs-body-bg-rgb: 255, 255, 255;
|
||||
--bs-emphasis-color: #000;
|
||||
--bs-emphasis-color-rgb: 0, 0, 0;
|
||||
--bs-secondary-color: rgba(33, 37, 41, 0.75);
|
||||
--bs-secondary-color-rgb: 33, 37, 41;
|
||||
--bs-secondary-bg: #e9ecef;
|
||||
--bs-secondary-bg-rgb: 233, 236, 239;
|
||||
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
|
||||
--bs-tertiary-color-rgb: 33, 37, 41;
|
||||
--bs-tertiary-bg: #f8f9fa;
|
||||
--bs-tertiary-bg-rgb: 248, 249, 250;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #0d6efd;
|
||||
--bs-link-color-rgb: 13, 110, 253;
|
||||
--bs-link-decoration: underline;
|
||||
--bs-link-hover-color: #0a58ca;
|
||||
--bs-link-hover-color-rgb: 10, 88, 202;
|
||||
--bs-code-color: #d63384;
|
||||
--bs-highlight-color: #212529;
|
||||
--bs-highlight-bg: #fff3cd;
|
||||
--bs-border-width: 1px;
|
||||
--bs-border-style: solid;
|
||||
--bs-border-color: #dee2e6;
|
||||
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
|
||||
--bs-border-radius: 0.375rem;
|
||||
--bs-border-radius-sm: 0.25rem;
|
||||
--bs-border-radius-lg: 0.5rem;
|
||||
--bs-border-radius-xl: 1rem;
|
||||
--bs-border-radius-xxl: 2rem;
|
||||
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
|
||||
--bs-border-radius-pill: 50rem;
|
||||
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
|
||||
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
--bs-focus-ring-width: 0.25rem;
|
||||
--bs-focus-ring-opacity: 0.25;
|
||||
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
|
||||
--bs-form-valid-color: #198754;
|
||||
--bs-form-valid-border-color: #198754;
|
||||
--bs-form-invalid-color: #dc3545;
|
||||
--bs-form-invalid-border-color: #dc3545;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] {
|
||||
color-scheme: dark;
|
||||
--bs-body-color: #dee2e6;
|
||||
--bs-body-color-rgb: 222, 226, 230;
|
||||
--bs-body-bg: #212529;
|
||||
--bs-body-bg-rgb: 33, 37, 41;
|
||||
--bs-emphasis-color: #fff;
|
||||
--bs-emphasis-color-rgb: 255, 255, 255;
|
||||
--bs-secondary-color: rgba(222, 226, 230, 0.75);
|
||||
--bs-secondary-color-rgb: 222, 226, 230;
|
||||
--bs-secondary-bg: #343a40;
|
||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||
--bs-tertiary-bg: #2b3035;
|
||||
--bs-tertiary-bg-rgb: 43, 48, 53;
|
||||
--bs-primary-text-emphasis: #6ea8fe;
|
||||
--bs-secondary-text-emphasis: #a7acb1;
|
||||
--bs-success-text-emphasis: #75b798;
|
||||
--bs-info-text-emphasis: #6edff6;
|
||||
--bs-warning-text-emphasis: #ffda6a;
|
||||
--bs-danger-text-emphasis: #ea868f;
|
||||
--bs-light-text-emphasis: #f8f9fa;
|
||||
--bs-dark-text-emphasis: #dee2e6;
|
||||
--bs-primary-bg-subtle: #031633;
|
||||
--bs-secondary-bg-subtle: #161719;
|
||||
--bs-success-bg-subtle: #051b11;
|
||||
--bs-info-bg-subtle: #032830;
|
||||
--bs-warning-bg-subtle: #332701;
|
||||
--bs-danger-bg-subtle: #2c0b0e;
|
||||
--bs-light-bg-subtle: #343a40;
|
||||
--bs-dark-bg-subtle: #1a1d20;
|
||||
--bs-primary-border-subtle: #084298;
|
||||
--bs-secondary-border-subtle: #41464b;
|
||||
--bs-success-border-subtle: #0f5132;
|
||||
--bs-info-border-subtle: #087990;
|
||||
--bs-warning-border-subtle: #997404;
|
||||
--bs-danger-border-subtle: #842029;
|
||||
--bs-light-border-subtle: #495057;
|
||||
--bs-dark-border-subtle: #343a40;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #6ea8fe;
|
||||
--bs-link-hover-color: #8bb9fe;
|
||||
--bs-link-color-rgb: 110, 168, 254;
|
||||
--bs-link-hover-color-rgb: 139, 185, 254;
|
||||
--bs-code-color: #e685b5;
|
||||
--bs-highlight-color: #dee2e6;
|
||||
--bs-highlight-bg: #664d03;
|
||||
--bs-border-color: #495057;
|
||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||
--bs-form-valid-color: #75b798;
|
||||
--bs-form-valid-border-color: #75b798;
|
||||
--bs-form-invalid-color: #ea868f;
|
||||
--bs-form-invalid-border-color: #ea868f;
|
||||
color-scheme: dark;
|
||||
--bs-body-color: #dee2e6;
|
||||
--bs-body-color-rgb: 222, 226, 230;
|
||||
--bs-body-bg: #212529;
|
||||
--bs-body-bg-rgb: 33, 37, 41;
|
||||
--bs-emphasis-color: #fff;
|
||||
--bs-emphasis-color-rgb: 255, 255, 255;
|
||||
--bs-secondary-color: rgba(222, 226, 230, 0.75);
|
||||
--bs-secondary-color-rgb: 222, 226, 230;
|
||||
--bs-secondary-bg: #343a40;
|
||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||
--bs-tertiary-bg: #2b3035;
|
||||
--bs-tertiary-bg-rgb: 43, 48, 53;
|
||||
--bs-primary-text-emphasis: #6ea8fe;
|
||||
--bs-secondary-text-emphasis: #a7acb1;
|
||||
--bs-success-text-emphasis: #75b798;
|
||||
--bs-info-text-emphasis: #6edff6;
|
||||
--bs-warning-text-emphasis: #ffda6a;
|
||||
--bs-danger-text-emphasis: #ea868f;
|
||||
--bs-light-text-emphasis: #f8f9fa;
|
||||
--bs-dark-text-emphasis: #dee2e6;
|
||||
--bs-primary-bg-subtle: #031633;
|
||||
--bs-secondary-bg-subtle: #161719;
|
||||
--bs-success-bg-subtle: #051b11;
|
||||
--bs-info-bg-subtle: #032830;
|
||||
--bs-warning-bg-subtle: #332701;
|
||||
--bs-danger-bg-subtle: #2c0b0e;
|
||||
--bs-light-bg-subtle: #343a40;
|
||||
--bs-dark-bg-subtle: #1a1d20;
|
||||
--bs-primary-border-subtle: #084298;
|
||||
--bs-secondary-border-subtle: #41464b;
|
||||
--bs-success-border-subtle: #0f5132;
|
||||
--bs-info-border-subtle: #087990;
|
||||
--bs-warning-border-subtle: #997404;
|
||||
--bs-danger-border-subtle: #842029;
|
||||
--bs-light-border-subtle: #495057;
|
||||
--bs-dark-border-subtle: #343a40;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #6ea8fe;
|
||||
--bs-link-hover-color: #8bb9fe;
|
||||
--bs-link-color-rgb: 110, 168, 254;
|
||||
--bs-link-hover-color-rgb: 139, 185, 254;
|
||||
--bs-code-color: #e685b5;
|
||||
--bs-highlight-color: #dee2e6;
|
||||
--bs-highlight-bg: #664d03;
|
||||
--bs-border-color: #495057;
|
||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||
--bs-form-valid-color: #75b798;
|
||||
--bs-form-valid-border-color: #75b798;
|
||||
--bs-form-invalid-color: #ea868f;
|
||||
--bs-form-invalid-border-color: #ea868f;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--bs-body-font-family);
|
||||
font-size: var(--bs-body-font-size);
|
||||
font-weight: var(--bs-body-font-weight);
|
||||
line-height: var(--bs-body-line-height);
|
||||
color: var(--bs-body-color);
|
||||
text-align: var(--bs-body-text-align);
|
||||
background-color: var(--bs-body-bg);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
margin: 0;
|
||||
font-family: var(--bs-body-font-family);
|
||||
font-size: var(--bs-body-font-size);
|
||||
font-weight: var(--bs-body-font-weight);
|
||||
line-height: var(--bs-body-line-height);
|
||||
color: var(--bs-body-color);
|
||||
text-align: var(--bs-body-text-align);
|
||||
background-color: var(--bs-body-bg);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
border: 0;
|
||||
border-top: var(--bs-border-width) solid;
|
||||
opacity: 0.25;
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
border: 0;
|
||||
border-top: var(--bs-border-width) solid;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
h6, h5, h4, h3, h2, h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
color: var(--bs-heading-color);
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
color: var(--bs-heading-color);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-left: 2rem;
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-left: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.875em;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.1875em;
|
||||
color: var(--bs-highlight-color);
|
||||
background-color: var(--bs-highlight-bg);
|
||||
padding: 0.1875em;
|
||||
color: var(--bs-highlight-color);
|
||||
background-color: var(--bs-highlight-bg);
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
|
||||
text-decoration: underline;
|
||||
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
|
||||
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
|
||||
}
|
||||
|
||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: var(--bs-font-monospace);
|
||||
font-size: 1em;
|
||||
font-family: var(--bs-font-monospace);
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-code-color);
|
||||
word-wrap: break-word;
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-code-color);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
a > code {
|
||||
color: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 0.1875rem 0.375rem;
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-body-bg);
|
||||
background-color: var(--bs-body-color);
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.1875rem 0.375rem;
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-body-bg);
|
||||
background-color: var(--bs-body-color);
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
kbd kbd {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: var(--bs-secondary-color);
|
||||
text-align: left;
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: var(--bs-secondary-color);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
thead,
|
||||
@@ -434,21 +442,21 @@ tfoot,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
@@ -456,76 +464,80 @@ button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
select:disabled {
|
||||
opacity: 1;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
|
||||
display: none !important;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
button,
|
||||
[type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
button:not(:disabled),
|
||||
[type=button]:not(:disabled),
|
||||
[type=reset]:not(:disabled),
|
||||
[type=submit]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
float: left;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
line-height: inherit;
|
||||
float: left;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
legend + * {
|
||||
clear: left;
|
||||
clear: left;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper,
|
||||
@@ -535,16 +547,16 @@ legend + * {
|
||||
::-webkit-datetime-edit-day-field,
|
||||
::-webkit-datetime-edit-month-field,
|
||||
::-webkit-datetime-edit-year-field {
|
||||
padding: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-inner-spin-button {
|
||||
height: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type=search] {
|
||||
-webkit-appearance: textfield;
|
||||
outline-offset: -2px;
|
||||
-webkit-appearance: textfield;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
/* rtl:raw:
|
||||
@@ -556,42 +568,42 @@ legend + * {
|
||||
}
|
||||
*/
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
::file-selector-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
||||
+342
-328
@@ -5,427 +5,435 @@
|
||||
*/
|
||||
:root,
|
||||
[data-bs-theme=light] {
|
||||
--bs-blue: #0d6efd;
|
||||
--bs-indigo: #6610f2;
|
||||
--bs-purple: #6f42c1;
|
||||
--bs-pink: #d63384;
|
||||
--bs-red: #dc3545;
|
||||
--bs-orange: #fd7e14;
|
||||
--bs-yellow: #ffc107;
|
||||
--bs-green: #198754;
|
||||
--bs-teal: #20c997;
|
||||
--bs-cyan: #0dcaf0;
|
||||
--bs-black: #000;
|
||||
--bs-white: #fff;
|
||||
--bs-gray: #6c757d;
|
||||
--bs-gray-dark: #343a40;
|
||||
--bs-gray-100: #f8f9fa;
|
||||
--bs-gray-200: #e9ecef;
|
||||
--bs-gray-300: #dee2e6;
|
||||
--bs-gray-400: #ced4da;
|
||||
--bs-gray-500: #adb5bd;
|
||||
--bs-gray-600: #6c757d;
|
||||
--bs-gray-700: #495057;
|
||||
--bs-gray-800: #343a40;
|
||||
--bs-gray-900: #212529;
|
||||
--bs-primary: #0d6efd;
|
||||
--bs-secondary: #6c757d;
|
||||
--bs-success: #198754;
|
||||
--bs-info: #0dcaf0;
|
||||
--bs-warning: #ffc107;
|
||||
--bs-danger: #dc3545;
|
||||
--bs-light: #f8f9fa;
|
||||
--bs-dark: #212529;
|
||||
--bs-primary-rgb: 13, 110, 253;
|
||||
--bs-secondary-rgb: 108, 117, 125;
|
||||
--bs-success-rgb: 25, 135, 84;
|
||||
--bs-info-rgb: 13, 202, 240;
|
||||
--bs-warning-rgb: 255, 193, 7;
|
||||
--bs-danger-rgb: 220, 53, 69;
|
||||
--bs-light-rgb: 248, 249, 250;
|
||||
--bs-dark-rgb: 33, 37, 41;
|
||||
--bs-primary-text-emphasis: #052c65;
|
||||
--bs-secondary-text-emphasis: #2b2f32;
|
||||
--bs-success-text-emphasis: #0a3622;
|
||||
--bs-info-text-emphasis: #055160;
|
||||
--bs-warning-text-emphasis: #664d03;
|
||||
--bs-danger-text-emphasis: #58151c;
|
||||
--bs-light-text-emphasis: #495057;
|
||||
--bs-dark-text-emphasis: #495057;
|
||||
--bs-primary-bg-subtle: #cfe2ff;
|
||||
--bs-secondary-bg-subtle: #e2e3e5;
|
||||
--bs-success-bg-subtle: #d1e7dd;
|
||||
--bs-info-bg-subtle: #cff4fc;
|
||||
--bs-warning-bg-subtle: #fff3cd;
|
||||
--bs-danger-bg-subtle: #f8d7da;
|
||||
--bs-light-bg-subtle: #fcfcfd;
|
||||
--bs-dark-bg-subtle: #ced4da;
|
||||
--bs-primary-border-subtle: #9ec5fe;
|
||||
--bs-secondary-border-subtle: #c4c8cb;
|
||||
--bs-success-border-subtle: #a3cfbb;
|
||||
--bs-info-border-subtle: #9eeaf9;
|
||||
--bs-warning-border-subtle: #ffe69c;
|
||||
--bs-danger-border-subtle: #f1aeb5;
|
||||
--bs-light-border-subtle: #e9ecef;
|
||||
--bs-dark-border-subtle: #adb5bd;
|
||||
--bs-white-rgb: 255, 255, 255;
|
||||
--bs-black-rgb: 0, 0, 0;
|
||||
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||
--bs-body-font-size: 1rem;
|
||||
--bs-body-font-weight: 400;
|
||||
--bs-body-line-height: 1.5;
|
||||
--bs-body-color: #212529;
|
||||
--bs-body-color-rgb: 33, 37, 41;
|
||||
--bs-body-bg: #fff;
|
||||
--bs-body-bg-rgb: 255, 255, 255;
|
||||
--bs-emphasis-color: #000;
|
||||
--bs-emphasis-color-rgb: 0, 0, 0;
|
||||
--bs-secondary-color: rgba(33, 37, 41, 0.75);
|
||||
--bs-secondary-color-rgb: 33, 37, 41;
|
||||
--bs-secondary-bg: #e9ecef;
|
||||
--bs-secondary-bg-rgb: 233, 236, 239;
|
||||
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
|
||||
--bs-tertiary-color-rgb: 33, 37, 41;
|
||||
--bs-tertiary-bg: #f8f9fa;
|
||||
--bs-tertiary-bg-rgb: 248, 249, 250;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #0d6efd;
|
||||
--bs-link-color-rgb: 13, 110, 253;
|
||||
--bs-link-decoration: underline;
|
||||
--bs-link-hover-color: #0a58ca;
|
||||
--bs-link-hover-color-rgb: 10, 88, 202;
|
||||
--bs-code-color: #d63384;
|
||||
--bs-highlight-color: #212529;
|
||||
--bs-highlight-bg: #fff3cd;
|
||||
--bs-border-width: 1px;
|
||||
--bs-border-style: solid;
|
||||
--bs-border-color: #dee2e6;
|
||||
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
|
||||
--bs-border-radius: 0.375rem;
|
||||
--bs-border-radius-sm: 0.25rem;
|
||||
--bs-border-radius-lg: 0.5rem;
|
||||
--bs-border-radius-xl: 1rem;
|
||||
--bs-border-radius-xxl: 2rem;
|
||||
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
|
||||
--bs-border-radius-pill: 50rem;
|
||||
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
|
||||
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
--bs-focus-ring-width: 0.25rem;
|
||||
--bs-focus-ring-opacity: 0.25;
|
||||
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
|
||||
--bs-form-valid-color: #198754;
|
||||
--bs-form-valid-border-color: #198754;
|
||||
--bs-form-invalid-color: #dc3545;
|
||||
--bs-form-invalid-border-color: #dc3545;
|
||||
--bs-blue: #0d6efd;
|
||||
--bs-indigo: #6610f2;
|
||||
--bs-purple: #6f42c1;
|
||||
--bs-pink: #d63384;
|
||||
--bs-red: #dc3545;
|
||||
--bs-orange: #fd7e14;
|
||||
--bs-yellow: #ffc107;
|
||||
--bs-green: #198754;
|
||||
--bs-teal: #20c997;
|
||||
--bs-cyan: #0dcaf0;
|
||||
--bs-black: #000;
|
||||
--bs-white: #fff;
|
||||
--bs-gray: #6c757d;
|
||||
--bs-gray-dark: #343a40;
|
||||
--bs-gray-100: #f8f9fa;
|
||||
--bs-gray-200: #e9ecef;
|
||||
--bs-gray-300: #dee2e6;
|
||||
--bs-gray-400: #ced4da;
|
||||
--bs-gray-500: #adb5bd;
|
||||
--bs-gray-600: #6c757d;
|
||||
--bs-gray-700: #495057;
|
||||
--bs-gray-800: #343a40;
|
||||
--bs-gray-900: #212529;
|
||||
--bs-primary: #0d6efd;
|
||||
--bs-secondary: #6c757d;
|
||||
--bs-success: #198754;
|
||||
--bs-info: #0dcaf0;
|
||||
--bs-warning: #ffc107;
|
||||
--bs-danger: #dc3545;
|
||||
--bs-light: #f8f9fa;
|
||||
--bs-dark: #212529;
|
||||
--bs-primary-rgb: 13, 110, 253;
|
||||
--bs-secondary-rgb: 108, 117, 125;
|
||||
--bs-success-rgb: 25, 135, 84;
|
||||
--bs-info-rgb: 13, 202, 240;
|
||||
--bs-warning-rgb: 255, 193, 7;
|
||||
--bs-danger-rgb: 220, 53, 69;
|
||||
--bs-light-rgb: 248, 249, 250;
|
||||
--bs-dark-rgb: 33, 37, 41;
|
||||
--bs-primary-text-emphasis: #052c65;
|
||||
--bs-secondary-text-emphasis: #2b2f32;
|
||||
--bs-success-text-emphasis: #0a3622;
|
||||
--bs-info-text-emphasis: #055160;
|
||||
--bs-warning-text-emphasis: #664d03;
|
||||
--bs-danger-text-emphasis: #58151c;
|
||||
--bs-light-text-emphasis: #495057;
|
||||
--bs-dark-text-emphasis: #495057;
|
||||
--bs-primary-bg-subtle: #cfe2ff;
|
||||
--bs-secondary-bg-subtle: #e2e3e5;
|
||||
--bs-success-bg-subtle: #d1e7dd;
|
||||
--bs-info-bg-subtle: #cff4fc;
|
||||
--bs-warning-bg-subtle: #fff3cd;
|
||||
--bs-danger-bg-subtle: #f8d7da;
|
||||
--bs-light-bg-subtle: #fcfcfd;
|
||||
--bs-dark-bg-subtle: #ced4da;
|
||||
--bs-primary-border-subtle: #9ec5fe;
|
||||
--bs-secondary-border-subtle: #c4c8cb;
|
||||
--bs-success-border-subtle: #a3cfbb;
|
||||
--bs-info-border-subtle: #9eeaf9;
|
||||
--bs-warning-border-subtle: #ffe69c;
|
||||
--bs-danger-border-subtle: #f1aeb5;
|
||||
--bs-light-border-subtle: #e9ecef;
|
||||
--bs-dark-border-subtle: #adb5bd;
|
||||
--bs-white-rgb: 255, 255, 255;
|
||||
--bs-black-rgb: 0, 0, 0;
|
||||
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||
--bs-body-font-size: 1rem;
|
||||
--bs-body-font-weight: 400;
|
||||
--bs-body-line-height: 1.5;
|
||||
--bs-body-color: #212529;
|
||||
--bs-body-color-rgb: 33, 37, 41;
|
||||
--bs-body-bg: #fff;
|
||||
--bs-body-bg-rgb: 255, 255, 255;
|
||||
--bs-emphasis-color: #000;
|
||||
--bs-emphasis-color-rgb: 0, 0, 0;
|
||||
--bs-secondary-color: rgba(33, 37, 41, 0.75);
|
||||
--bs-secondary-color-rgb: 33, 37, 41;
|
||||
--bs-secondary-bg: #e9ecef;
|
||||
--bs-secondary-bg-rgb: 233, 236, 239;
|
||||
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
|
||||
--bs-tertiary-color-rgb: 33, 37, 41;
|
||||
--bs-tertiary-bg: #f8f9fa;
|
||||
--bs-tertiary-bg-rgb: 248, 249, 250;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #0d6efd;
|
||||
--bs-link-color-rgb: 13, 110, 253;
|
||||
--bs-link-decoration: underline;
|
||||
--bs-link-hover-color: #0a58ca;
|
||||
--bs-link-hover-color-rgb: 10, 88, 202;
|
||||
--bs-code-color: #d63384;
|
||||
--bs-highlight-color: #212529;
|
||||
--bs-highlight-bg: #fff3cd;
|
||||
--bs-border-width: 1px;
|
||||
--bs-border-style: solid;
|
||||
--bs-border-color: #dee2e6;
|
||||
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
|
||||
--bs-border-radius: 0.375rem;
|
||||
--bs-border-radius-sm: 0.25rem;
|
||||
--bs-border-radius-lg: 0.5rem;
|
||||
--bs-border-radius-xl: 1rem;
|
||||
--bs-border-radius-xxl: 2rem;
|
||||
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
|
||||
--bs-border-radius-pill: 50rem;
|
||||
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
|
||||
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
--bs-focus-ring-width: 0.25rem;
|
||||
--bs-focus-ring-opacity: 0.25;
|
||||
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
|
||||
--bs-form-valid-color: #198754;
|
||||
--bs-form-valid-border-color: #198754;
|
||||
--bs-form-invalid-color: #dc3545;
|
||||
--bs-form-invalid-border-color: #dc3545;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] {
|
||||
color-scheme: dark;
|
||||
--bs-body-color: #dee2e6;
|
||||
--bs-body-color-rgb: 222, 226, 230;
|
||||
--bs-body-bg: #212529;
|
||||
--bs-body-bg-rgb: 33, 37, 41;
|
||||
--bs-emphasis-color: #fff;
|
||||
--bs-emphasis-color-rgb: 255, 255, 255;
|
||||
--bs-secondary-color: rgba(222, 226, 230, 0.75);
|
||||
--bs-secondary-color-rgb: 222, 226, 230;
|
||||
--bs-secondary-bg: #343a40;
|
||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||
--bs-tertiary-bg: #2b3035;
|
||||
--bs-tertiary-bg-rgb: 43, 48, 53;
|
||||
--bs-primary-text-emphasis: #6ea8fe;
|
||||
--bs-secondary-text-emphasis: #a7acb1;
|
||||
--bs-success-text-emphasis: #75b798;
|
||||
--bs-info-text-emphasis: #6edff6;
|
||||
--bs-warning-text-emphasis: #ffda6a;
|
||||
--bs-danger-text-emphasis: #ea868f;
|
||||
--bs-light-text-emphasis: #f8f9fa;
|
||||
--bs-dark-text-emphasis: #dee2e6;
|
||||
--bs-primary-bg-subtle: #031633;
|
||||
--bs-secondary-bg-subtle: #161719;
|
||||
--bs-success-bg-subtle: #051b11;
|
||||
--bs-info-bg-subtle: #032830;
|
||||
--bs-warning-bg-subtle: #332701;
|
||||
--bs-danger-bg-subtle: #2c0b0e;
|
||||
--bs-light-bg-subtle: #343a40;
|
||||
--bs-dark-bg-subtle: #1a1d20;
|
||||
--bs-primary-border-subtle: #084298;
|
||||
--bs-secondary-border-subtle: #41464b;
|
||||
--bs-success-border-subtle: #0f5132;
|
||||
--bs-info-border-subtle: #087990;
|
||||
--bs-warning-border-subtle: #997404;
|
||||
--bs-danger-border-subtle: #842029;
|
||||
--bs-light-border-subtle: #495057;
|
||||
--bs-dark-border-subtle: #343a40;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #6ea8fe;
|
||||
--bs-link-hover-color: #8bb9fe;
|
||||
--bs-link-color-rgb: 110, 168, 254;
|
||||
--bs-link-hover-color-rgb: 139, 185, 254;
|
||||
--bs-code-color: #e685b5;
|
||||
--bs-highlight-color: #dee2e6;
|
||||
--bs-highlight-bg: #664d03;
|
||||
--bs-border-color: #495057;
|
||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||
--bs-form-valid-color: #75b798;
|
||||
--bs-form-valid-border-color: #75b798;
|
||||
--bs-form-invalid-color: #ea868f;
|
||||
--bs-form-invalid-border-color: #ea868f;
|
||||
color-scheme: dark;
|
||||
--bs-body-color: #dee2e6;
|
||||
--bs-body-color-rgb: 222, 226, 230;
|
||||
--bs-body-bg: #212529;
|
||||
--bs-body-bg-rgb: 33, 37, 41;
|
||||
--bs-emphasis-color: #fff;
|
||||
--bs-emphasis-color-rgb: 255, 255, 255;
|
||||
--bs-secondary-color: rgba(222, 226, 230, 0.75);
|
||||
--bs-secondary-color-rgb: 222, 226, 230;
|
||||
--bs-secondary-bg: #343a40;
|
||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||
--bs-tertiary-bg: #2b3035;
|
||||
--bs-tertiary-bg-rgb: 43, 48, 53;
|
||||
--bs-primary-text-emphasis: #6ea8fe;
|
||||
--bs-secondary-text-emphasis: #a7acb1;
|
||||
--bs-success-text-emphasis: #75b798;
|
||||
--bs-info-text-emphasis: #6edff6;
|
||||
--bs-warning-text-emphasis: #ffda6a;
|
||||
--bs-danger-text-emphasis: #ea868f;
|
||||
--bs-light-text-emphasis: #f8f9fa;
|
||||
--bs-dark-text-emphasis: #dee2e6;
|
||||
--bs-primary-bg-subtle: #031633;
|
||||
--bs-secondary-bg-subtle: #161719;
|
||||
--bs-success-bg-subtle: #051b11;
|
||||
--bs-info-bg-subtle: #032830;
|
||||
--bs-warning-bg-subtle: #332701;
|
||||
--bs-danger-bg-subtle: #2c0b0e;
|
||||
--bs-light-bg-subtle: #343a40;
|
||||
--bs-dark-bg-subtle: #1a1d20;
|
||||
--bs-primary-border-subtle: #084298;
|
||||
--bs-secondary-border-subtle: #41464b;
|
||||
--bs-success-border-subtle: #0f5132;
|
||||
--bs-info-border-subtle: #087990;
|
||||
--bs-warning-border-subtle: #997404;
|
||||
--bs-danger-border-subtle: #842029;
|
||||
--bs-light-border-subtle: #495057;
|
||||
--bs-dark-border-subtle: #343a40;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #6ea8fe;
|
||||
--bs-link-hover-color: #8bb9fe;
|
||||
--bs-link-color-rgb: 110, 168, 254;
|
||||
--bs-link-hover-color-rgb: 139, 185, 254;
|
||||
--bs-code-color: #e685b5;
|
||||
--bs-highlight-color: #dee2e6;
|
||||
--bs-highlight-bg: #664d03;
|
||||
--bs-border-color: #495057;
|
||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||
--bs-form-valid-color: #75b798;
|
||||
--bs-form-valid-border-color: #75b798;
|
||||
--bs-form-invalid-color: #ea868f;
|
||||
--bs-form-invalid-border-color: #ea868f;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--bs-body-font-family);
|
||||
font-size: var(--bs-body-font-size);
|
||||
font-weight: var(--bs-body-font-weight);
|
||||
line-height: var(--bs-body-line-height);
|
||||
color: var(--bs-body-color);
|
||||
text-align: var(--bs-body-text-align);
|
||||
background-color: var(--bs-body-bg);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
margin: 0;
|
||||
font-family: var(--bs-body-font-family);
|
||||
font-size: var(--bs-body-font-size);
|
||||
font-weight: var(--bs-body-font-weight);
|
||||
line-height: var(--bs-body-line-height);
|
||||
color: var(--bs-body-color);
|
||||
text-align: var(--bs-body-text-align);
|
||||
background-color: var(--bs-body-bg);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
border: 0;
|
||||
border-top: var(--bs-border-width) solid;
|
||||
opacity: 0.25;
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
border: 0;
|
||||
border-top: var(--bs-border-width) solid;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
h6, h5, h4, h3, h2, h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
color: var(--bs-heading-color);
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
color: var(--bs-heading-color);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-right: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-right: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.875em;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.1875em;
|
||||
color: var(--bs-highlight-color);
|
||||
background-color: var(--bs-highlight-bg);
|
||||
padding: 0.1875em;
|
||||
color: var(--bs-highlight-color);
|
||||
background-color: var(--bs-highlight-bg);
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
|
||||
text-decoration: underline;
|
||||
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
|
||||
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
|
||||
}
|
||||
|
||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: var(--bs-font-monospace);
|
||||
font-size: 1em;
|
||||
font-family: var(--bs-font-monospace);
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-code-color);
|
||||
word-wrap: break-word;
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-code-color);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
a > code {
|
||||
color: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 0.1875rem 0.375rem;
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-body-bg);
|
||||
background-color: var(--bs-body-color);
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.1875rem 0.375rem;
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-body-bg);
|
||||
background-color: var(--bs-body-color);
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
kbd kbd {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: var(--bs-secondary-color);
|
||||
text-align: right;
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: var(--bs-secondary-color);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
thead,
|
||||
@@ -434,21 +442,21 @@ tfoot,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
@@ -456,76 +464,80 @@ button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
select:disabled {
|
||||
opacity: 1;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
|
||||
display: none !important;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
button,
|
||||
[type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
button:not(:disabled),
|
||||
[type=button]:not(:disabled),
|
||||
[type=reset]:not(:disabled),
|
||||
[type=submit]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
float: right;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
line-height: inherit;
|
||||
float: right;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
legend + * {
|
||||
clear: right;
|
||||
clear: right;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper,
|
||||
@@ -535,60 +547,62 @@ legend + * {
|
||||
::-webkit-datetime-edit-day-field,
|
||||
::-webkit-datetime-edit-month-field,
|
||||
::-webkit-datetime-edit-year-field {
|
||||
padding: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-inner-spin-button {
|
||||
height: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type=search] {
|
||||
-webkit-appearance: textfield;
|
||||
outline-offset: -2px;
|
||||
-webkit-appearance: textfield;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
[type="tel"],
|
||||
[type="url"],
|
||||
[type="email"],
|
||||
[type="number"] {
|
||||
direction: ltr;
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
::file-selector-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */
|
||||
+4740
-3832
File diff suppressed because it is too large
Load Diff
+4740
-3830
File diff suppressed because it is too large
Load Diff
+10002
-8338
File diff suppressed because it is too large
Load Diff
+10012
-8337
File diff suppressed because it is too large
Load Diff
+6340
-6144
File diff suppressed because it is too large
Load Diff
+3421
-3232
File diff suppressed because it is too large
Load Diff
+4602
-4412
File diff suppressed because it is too large
Load Diff
@@ -21,10 +21,10 @@ public class CardData
|
||||
public string? ImmortalizeFrom { get; init; }
|
||||
public string? ImmortalizeWhen { get; init; }
|
||||
public string? ImageFile { get; init; }
|
||||
|
||||
|
||||
public string? Artist { get; init; }
|
||||
public string? Rarity { get; init; }
|
||||
|
||||
|
||||
public bool IsAgent => Category == "Agent";
|
||||
public bool IsSpell => Category == "Spell";
|
||||
public bool IsToken => Category == "Token";
|
||||
|
||||
@@ -7,7 +7,7 @@ public class DeckData
|
||||
public List<string> Keycards { get; init; } = [];
|
||||
public List<string> Divers { get; init; } = [];
|
||||
public string? Description { get; init; }
|
||||
|
||||
|
||||
public string? DeckCode { get; init; }
|
||||
public string? DeckType { get; init; }
|
||||
|
||||
|
||||
@@ -5,5 +5,5 @@ public class DocData
|
||||
public string Title { get; init; } = "";
|
||||
public string Category { get; init; } = "";
|
||||
public string Content { get; init; } = "";
|
||||
public System.Collections.Generic.Dictionary<string, string> Frontmatter { get; init; } = [];
|
||||
}
|
||||
public Dictionary<string, string> Frontmatter { get; init; } = [];
|
||||
}
|
||||
@@ -20,8 +20,8 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<Routes />
|
||||
<script src="_framework/blazor.web.js"></script>
|
||||
<Routes/>
|
||||
<script src="_framework/blazor.web.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Router AppAssembly="@typeof(Program).Assembly" AdditionalAssemblies="new[] { typeof(Shared.Pages.Home).Assembly }">
|
||||
<Router AppAssembly="@typeof(Program).Assembly" AdditionalAssemblies="new[] { typeof(Home).Assembly }">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
|
||||
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Server;
|
||||
using Server.Components;
|
||||
using Shared.Pages;
|
||||
using Shared.Services;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@@ -7,7 +10,7 @@ builder.Services.AddControllers();
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddRazorComponents().AddInteractiveServerComponents();
|
||||
builder.Services.AddTelerikBlazor();
|
||||
builder.Services.AddSingleton<Shared.Services.CardRenderingService>();
|
||||
builder.Services.AddSingleton<CardRenderingService>();
|
||||
|
||||
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
|
||||
builder.Services.AddDbContext<AppDbContext>(options =>
|
||||
@@ -32,17 +35,14 @@ using (var scope = app.Services.CreateScope())
|
||||
}
|
||||
}
|
||||
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseExceptionHandler("/Error");
|
||||
}
|
||||
if (!app.Environment.IsDevelopment()) app.UseExceptionHandler("/Error");
|
||||
|
||||
app.UseStaticFiles();
|
||||
app.UseAntiforgery();
|
||||
|
||||
app.MapControllers();
|
||||
app.MapRazorComponents<Server.Components.App>()
|
||||
app.MapRazorComponents<App>()
|
||||
.AddInteractiveServerRenderMode()
|
||||
.AddAdditionalAssemblies(typeof(Shared.Pages.Home).Assembly);
|
||||
.AddAdditionalAssemblies(typeof(Home).Assembly);
|
||||
|
||||
app.Run();
|
||||
app.Run();
|
||||
@@ -257,9 +257,6 @@ a, .btn-link {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.inline-card-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@namespace Shared.Components
|
||||
@using Chrono.Model
|
||||
|
||||
@if (Card != null)
|
||||
{
|
||||
@@ -11,7 +10,7 @@
|
||||
{
|
||||
<div class="detail-image">
|
||||
<img src="@Card.ImagePath" alt="@Card.Name"
|
||||
onerror="this.style.display='none';this.parentElement.style.display='none'" />
|
||||
onerror="this.style.display='none';this.parentElement.style.display='none'"/>
|
||||
</div>
|
||||
}
|
||||
<div class="detail-info">
|
||||
@@ -61,7 +60,7 @@
|
||||
<span class="field-value">@Card.Set</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@if (Card.Artist != null)
|
||||
{
|
||||
<div class="detail-field">
|
||||
@@ -69,7 +68,7 @@
|
||||
<span class="field-value">@Card.Artist</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@if (Card.Rarity != null)
|
||||
{
|
||||
<div class="detail-field">
|
||||
@@ -105,7 +104,8 @@
|
||||
var target = LookupCard(targetName);
|
||||
if (target != null)
|
||||
{
|
||||
<button class="inline-card-btn" @onclick="() => SelectCard(target)">@targetName</button>
|
||||
<button class="inline-card-btn"
|
||||
@onclick="() => SelectCard(target)">@targetName</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -125,7 +125,8 @@
|
||||
var fromCard = LookupCard(Card.ImmortalizeFrom);
|
||||
if (fromCard != null)
|
||||
{
|
||||
<button class="inline-card-btn" @onclick="() => SelectCard(fromCard)">@Card.ImmortalizeFrom</button>
|
||||
<button class="inline-card-btn"
|
||||
@onclick="() => SelectCard(fromCard)">@Card.ImmortalizeFrom</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -148,9 +149,15 @@
|
||||
|
||||
private bool HasImage => Card?.ImageFile is { Length: > 0 } && Card.ImageFile != "placeholder.png";
|
||||
|
||||
private async Task Close() => await OnClose.InvokeAsync();
|
||||
private async Task Close()
|
||||
{
|
||||
await OnClose.InvokeAsync();
|
||||
}
|
||||
|
||||
private async Task SelectCard(CardData card) => await OnSelectCard.InvokeAsync(card);
|
||||
private async Task SelectCard(CardData card)
|
||||
{
|
||||
await OnSelectCard.InvokeAsync(card);
|
||||
}
|
||||
|
||||
private RenderFragment RenderCardDescription(string description)
|
||||
{
|
||||
@@ -163,4 +170,5 @@
|
||||
return CardDatabase.Cards.FirstOrDefault(c =>
|
||||
string.Equals(c.Name, cardName, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,8 +10,12 @@
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.card-detail {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@namespace Shared.Components
|
||||
@using Chrono.Model
|
||||
|
||||
<div class="deck-card-row">
|
||||
@foreach (var group in Cards.GroupBy(x => x))
|
||||
@@ -29,10 +28,13 @@
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter, EditorRequired] public List<string> Cards { get; set; } = [];
|
||||
[Parameter][EditorRequired] public List<string> Cards { get; set; } = [];
|
||||
[Parameter] public EventCallback<CardData?> OnSelectCard { get; set; }
|
||||
|
||||
private async Task SelectCard(CardData? card) => await OnSelectCard.InvokeAsync(card);
|
||||
private async Task SelectCard(CardData? card)
|
||||
{
|
||||
await OnSelectCard.InvokeAsync(card);
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, CardData> CardLookup = CardDatabase.Cards
|
||||
.Where(c => !string.IsNullOrWhiteSpace(c.Name))
|
||||
@@ -43,4 +45,5 @@
|
||||
{
|
||||
return CardLookup.GetValueOrDefault(cardName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="mana-curve">
|
||||
@foreach (var entry in Distribution)
|
||||
{
|
||||
var height = MaxCount > 0 ? (entry.Count * 100 / MaxCount) : 0;
|
||||
var height = MaxCount > 0 ? entry.Count * 100 / MaxCount : 0;
|
||||
<div class="mana-bar-container">
|
||||
<div class="mana-bar-label">@entry.Count</div>
|
||||
<div class="mana-bar" style="height: @($"{Math.Max(height, 5)}%")"></div>
|
||||
@@ -13,7 +13,7 @@
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter, EditorRequired] public List<(int Cost, int Count)> Distribution { get; set; } = [];
|
||||
[Parameter][EditorRequired] public List<(int Cost, int Count)> Distribution { get; set; } = [];
|
||||
[Parameter] public int MaxCostLabel { get; set; } = 10;
|
||||
|
||||
private int MaxCount => Distribution.Count > 0 ? Distribution.Max(x => x.Count) : 0;
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
@implements IDisposable
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject AnalyticsService AnalyticsService
|
||||
|
||||
@code {
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
NavigationManager.LocationChanged += OnLocationChanged;
|
||||
}
|
||||
|
||||
private async void OnLocationChanged(object? sender, LocationChangedEventArgs e)
|
||||
{
|
||||
await TrackPageView(e.Location);
|
||||
}
|
||||
|
||||
private async Task TrackPageView(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
var relativePath = NavigationManager.ToBaseRelativePath(url);
|
||||
if (!relativePath.StartsWith("/"))
|
||||
{
|
||||
relativePath = "/" + relativePath;
|
||||
}
|
||||
|
||||
await AnalyticsService.TrackPageView(relativePath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore errors during tracking
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
NavigationManager.LocationChanged -= OnLocationChanged;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -154,7 +154,7 @@ public static class DocDatabase
|
||||
{
|
||||
Title = "Lifeblood",
|
||||
Category = "Faction",
|
||||
Content = "Concepts:\r\n- Wide Boards\r\n- Overpower",
|
||||
Content = "Concepts:\r\n\r\n- Wide Boards\r\n- Overpower",
|
||||
Frontmatter = new()
|
||||
{
|
||||
{ "category", "Faction" },
|
||||
@@ -164,7 +164,7 @@ public static class DocDatabase
|
||||
{
|
||||
Title = "Phasetide",
|
||||
Category = "Faction",
|
||||
Content = "Concepts:\r\n- Healing\r\n-",
|
||||
Content = "Concepts:\r\n\r\n- Healing\r\n-",
|
||||
Frontmatter = new()
|
||||
{
|
||||
{ "category", "Faction" },
|
||||
@@ -174,7 +174,7 @@ public static class DocDatabase
|
||||
{
|
||||
Title = "Silence",
|
||||
Category = "Faction",
|
||||
Content = "Concepts:\r\n- Activatable Agents\r\n-",
|
||||
Content = "Concepts:\r\n\r\n- Activatable Agents\r\n-",
|
||||
Frontmatter = new()
|
||||
{
|
||||
{ "category", "Faction" },
|
||||
@@ -184,7 +184,7 @@ public static class DocDatabase
|
||||
{
|
||||
Title = "Singularity",
|
||||
Category = "Faction",
|
||||
Content = "Concepts:\r\n- Discard",
|
||||
Content = "Concepts:\r\n\r\n- Discard",
|
||||
Frontmatter = new()
|
||||
{
|
||||
{ "category", "Faction" },
|
||||
@@ -194,7 +194,7 @@ public static class DocDatabase
|
||||
{
|
||||
Title = "Splintergleam",
|
||||
Category = "Faction",
|
||||
Content = "# Self Damage\r\n\r\nCan hurt it's own units for power. Has [[Bleed]] to make reoccurring damage on units very easy.\r\n\r\n# Core Damage \r\n\r\nCan hurt both cores easily. Has [[Breakdown]] to take advantage of having an injured core for more damage.",
|
||||
Content = "# Self Damage\r\n\r\nCan hurt it's own units for power. Has [[Bleed]] to make reoccurring damage on units very easy.\r\n\r\n# Core Damage\r\n\r\nCan hurt both cores easily. Has [[Breakdown]] to take advantage of having an injured core for more damage.",
|
||||
Frontmatter = new()
|
||||
{
|
||||
{ "category", "Faction" },
|
||||
@@ -204,7 +204,7 @@ public static class DocDatabase
|
||||
{
|
||||
Title = "Sungrace",
|
||||
Category = "Faction",
|
||||
Content = "# Energy Reserves\r\n\r\nCare about always having banked energy. Spells can refund themselves when using [[Energy Reserves]], or get stronger is you [[Overflow]] your energy reserve.\r\n\r\nConcepts:\r\n- Ramp\r\n- Using and Replenishing Reserved Energy\r\n-",
|
||||
Content = "# Energy Reserves\r\n\r\nCare about always having banked energy. Spells can refund themselves when using [[Energy Reserves]], or get stronger is\r\nyou [[Overflow]] your energy reserve.\r\n\r\nConcepts:\r\n\r\n- Ramp\r\n- Using and Replenishing Reserved Energy\r\n-",
|
||||
Frontmatter = new()
|
||||
{
|
||||
{ "category", "Faction" },
|
||||
@@ -479,7 +479,7 @@ public static class DocDatabase
|
||||
{
|
||||
Title = "Onboarding Track",
|
||||
Category = "Pass",
|
||||
Content = "| Tier | Reward |\r\n| ---- | -------------------------------- |\r\n| 1 | Sprouts Record |\r\n| 2 | 120 Core Charges |\r\n| 3 | Burn Precon |\r\n| 4 | 120 Core Charges, 25 Flux |\r\n| 5 | Profile Pictures |\r\n| 6 | Emotes |\r\n| 7 | 120 Core Charges |\r\n| 8 | Profile Pictures |\r\n| 9 | 60 Core Charges, 50 Flux |\r\n| 10 | 240 Core Charges, 1 Draft Ticket |\r\n\r\n| Core Charges | Flux |\r\n| ------------ | ---- |\r\n| 660 | 75 |",
|
||||
Content = "| Tier | Reward |\r\n|------|----------------------------------|\r\n| 1 | Sprouts Record |\r\n| 2 | 120 Core Charges |\r\n| 3 | Burn Precon |\r\n| 4 | 120 Core Charges, 25 Flux |\r\n| 5 | Profile Pictures |\r\n| 6 | Emotes |\r\n| 7 | 120 Core Charges |\r\n| 8 | Profile Pictures |\r\n| 9 | 60 Core Charges, 50 Flux |\r\n| 10 | 240 Core Charges, 1 Draft Ticket |\r\n\r\n| Core Charges | Flux |\r\n|--------------|------|\r\n| 660 | 75 |",
|
||||
Frontmatter = new()
|
||||
{
|
||||
{ "expPer", "30" },
|
||||
@@ -491,7 +491,7 @@ public static class DocDatabase
|
||||
{
|
||||
Title = "Daily Wins",
|
||||
Category = "Quest",
|
||||
Content = "1: 30cc 30xp \n2: 20cc 25xp \n3: 20cc 20xp \n4: 10cc 20xp \n5: 10cc 15xp \n6-12 are all simply 5xp. \n\nSo the daily total win reward for 12 wins is 90cc/145xp.",
|
||||
Content = "1: 30cc 30xp\n2: 20cc 25xp\n3: 20cc 20xp\n4: 10cc 20xp\n5: 10cc 15xp\n6-12 are all simply 5xp.\n\nSo the daily total win reward for 12 wins is 90cc/145xp.",
|
||||
Frontmatter = new()
|
||||
{
|
||||
{ "category", "Quest" },
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
</div>
|
||||
|
||||
<main>
|
||||
<NavigationTracker/>
|
||||
<article class="content px-4">
|
||||
<TelerikRootComponent>
|
||||
@Body
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
<PageTitle>Chrono CCG - Agents</PageTitle>
|
||||
|
||||
<HeadContent>
|
||||
<meta name="description" content="View and compare all Chrono CCG agents. Analyze stats, factions, and efficiency to build the perfect deck." />
|
||||
<meta name="description"
|
||||
content="View and compare all Chrono CCG agents. Analyze stats, factions, and efficiency to build the perfect deck."/>
|
||||
</HeadContent>
|
||||
|
||||
<div class="agents-page">
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
<PageTitle>Chrono CCG - @(deck?.Name ?? "Deck Details")</PageTitle>
|
||||
|
||||
<HeadContent>
|
||||
<meta name="description" content="@(deck != null ? $"View details for the {deck.Name} deck. {deck.Cards.Count} cards, {deck.Factions.Count} factions." : "Deck details and card list.")" />
|
||||
<meta name="description"
|
||||
content="@(deck != null ? $"View details for the {deck.Name} deck. {deck.Cards.Count} cards, {deck.Factions.Count} factions." : "Deck details and card list.")"/>
|
||||
</HeadContent>
|
||||
|
||||
<div class="deck-detail-page">
|
||||
@@ -23,7 +24,8 @@
|
||||
<article class="deck-article">
|
||||
<header class="deck-header">
|
||||
<h1>@deck.Name</h1>
|
||||
<b>Deck Code:</b> <pre>@deck.DeckCode</pre>
|
||||
<b>Deck Code:</b>
|
||||
<pre>@deck.DeckCode</pre>
|
||||
@if (deck.Factions.Count > 0)
|
||||
{
|
||||
<div class="deck-factions">
|
||||
@@ -44,14 +46,14 @@
|
||||
}
|
||||
</div>
|
||||
|
||||
<ManaCurve Distribution="GetManaDistribution()" MaxCostLabel="10" />
|
||||
<ManaCurve Distribution="GetManaDistribution()" MaxCostLabel="10"/>
|
||||
</header>
|
||||
|
||||
@if (deck.Keycards.Count > 0)
|
||||
{
|
||||
<section class="deck-section">
|
||||
<h2><i class="bi bi-star-fill" style="color: var(--gold);"></i> Keycards</h2>
|
||||
<CardGrid Cards="deck.Keycards" OnSelectCard="SelectCard" />
|
||||
<CardGrid Cards="deck.Keycards" OnSelectCard="SelectCard"/>
|
||||
</section>
|
||||
}
|
||||
|
||||
@@ -59,13 +61,13 @@
|
||||
{
|
||||
<section class="deck-section">
|
||||
<h2><i class="bi bi-shuffle"></i> Divers</h2>
|
||||
<CardGrid Cards="deck.Divers" OnSelectCard="SelectCard" />
|
||||
<CardGrid Cards="deck.Divers" OnSelectCard="SelectCard"/>
|
||||
</section>
|
||||
}
|
||||
|
||||
<section class="deck-section">
|
||||
<h2><i class="bi bi-collection-fill"></i> Cards</h2>
|
||||
<CardGrid Cards="deck.Cards" OnSelectCard="SelectCard" />
|
||||
<CardGrid Cards="deck.Cards" OnSelectCard="SelectCard"/>
|
||||
</section>
|
||||
|
||||
@if (deck.Description != null)
|
||||
@@ -81,10 +83,10 @@
|
||||
}
|
||||
</div>
|
||||
|
||||
<CardDetailModal Card="selectedCard"
|
||||
OnClose="CloseDetail"
|
||||
OnSelectCard="SelectCard"
|
||||
DescriptionRenderer="@(desc => CardRenderer.RenderDescription(desc, SelectCard))" />
|
||||
<CardDetailModal Card="selectedCard"
|
||||
OnClose="CloseDetail"
|
||||
OnSelectCard="SelectCard"
|
||||
DescriptionRenderer="@(desc => CardRenderer.RenderDescription(desc, SelectCard))"/>
|
||||
|
||||
@code {
|
||||
[Parameter] public string Name { get; set; } = "";
|
||||
@@ -124,7 +126,7 @@
|
||||
{
|
||||
if (deck == null) return [];
|
||||
var counts = new Dictionary<int, int>();
|
||||
for (int i = 0; i <= 10; i++) counts[i] = 0;
|
||||
for (var i = 0; i <= 10; i++) counts[i] = 0;
|
||||
|
||||
foreach (var cardName in deck.Cards)
|
||||
{
|
||||
@@ -139,4 +141,5 @@
|
||||
|
||||
return counts.OrderBy(x => x.Key).Select(x => (x.Key, x.Value)).ToList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
<PageTitle>Chrono CCG - Decks</PageTitle>
|
||||
|
||||
<HeadContent>
|
||||
<meta name="description" content="Explore community and official Chrono CCG decks. Find the best strategies and card combinations." />
|
||||
<meta name="description"
|
||||
content="Explore community and official Chrono CCG decks. Find the best strategies and card combinations."/>
|
||||
</HeadContent>
|
||||
|
||||
<div class="decks-page">
|
||||
@@ -13,7 +14,8 @@
|
||||
<div class="decks-header-row">
|
||||
<p class="text-secondary">@decks.Count deck@(decks.Count != 1 ? "s" : "")</p>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="showPrecons" @bind="showPrecons" @bind:after="RefreshDecks">
|
||||
<input class="form-check-input" type="checkbox" id="showPrecons" @bind="showPrecons"
|
||||
@bind:after="RefreshDecks">
|
||||
<label class="form-check-label" for="showPrecons">Show Precons</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -34,11 +36,11 @@
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
<div class="deck-card-factions">
|
||||
<span class="faction-badge">@deck.DeckType</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="deck-card-meta">
|
||||
<span>@deck.Cards.Distinct().Count() unique, @deck.Cards.Count total</span>
|
||||
@if (deck.Keycards.Count > 0)
|
||||
@@ -70,7 +72,7 @@
|
||||
|
||||
@code {
|
||||
private List<DeckData> decks = [];
|
||||
private bool showPrecons = false;
|
||||
private bool showPrecons;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
@@ -81,10 +83,10 @@
|
||||
{
|
||||
decks = DeckDatabase.Decks
|
||||
.Where(d => d.IsVisible)
|
||||
.Where(d =>
|
||||
showPrecons
|
||||
? d.DeckType is "precon" or "store" :
|
||||
d.DeckType is "custom")
|
||||
.Where(d =>
|
||||
showPrecons
|
||||
? d.DeckType is "precon" or "store"
|
||||
: d.DeckType is "custom")
|
||||
.ToList();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,17 +13,19 @@
|
||||
<aside class="docs-sidebar">
|
||||
<div class="search-box">
|
||||
<i class="bi bi-search"></i>
|
||||
<input type="text" placeholder="Search docs..." @bind="searchQuery" @bind:event="oninput" />
|
||||
<input type="text" placeholder="Search docs..." @bind="searchQuery" @bind:event="oninput"/>
|
||||
</div>
|
||||
|
||||
<div class="category-list">
|
||||
<div class="category-item @(selectedCategory == null ? "active" : "")" @onclick="() => SelectCategory(null)">
|
||||
<div class="category-item @(selectedCategory == null ? "active" : "")"
|
||||
@onclick="() => SelectCategory(null)">
|
||||
All Pages
|
||||
</div>
|
||||
@foreach (var category in categories)
|
||||
{
|
||||
var cat = category;
|
||||
<div class="category-item @(selectedCategory == cat ? "active" : "")" @onclick="() => SelectCategory(cat)">
|
||||
<div class="category-item @(selectedCategory == cat ? "active" : "")"
|
||||
@onclick="() => SelectCategory(cat)">
|
||||
@cat
|
||||
</div>
|
||||
}
|
||||
@@ -134,20 +136,24 @@
|
||||
return doc.Frontmatter.TryGetValue(key, out var val) && !string.IsNullOrWhiteSpace(val) ? val : null;
|
||||
}
|
||||
|
||||
private static string GetLabel(string key) => key switch
|
||||
private static string GetLabel(string key)
|
||||
{
|
||||
"category" => "Category",
|
||||
"description" => "Description",
|
||||
"essencePrice" => "Essence Price",
|
||||
"crytalPrice" => "Crystal Price",
|
||||
"coreChargesPrice" => "Core Charges Price",
|
||||
"pricePerPack" => "Price per Pack",
|
||||
"codeCharges" => "Code Charges",
|
||||
"coreCharges" => "Core Charges",
|
||||
"currency" => "Currency",
|
||||
"faction" => "Faction",
|
||||
"exp" => "EXP Reward",
|
||||
"see" => "See Also",
|
||||
_ => string.Concat(key.Select((c, i) => i > 0 && char.IsUpper(c) ? " " + c : c.ToString())),
|
||||
};
|
||||
return key switch
|
||||
{
|
||||
"category" => "Category",
|
||||
"description" => "Description",
|
||||
"essencePrice" => "Essence Price",
|
||||
"crytalPrice" => "Crystal Price",
|
||||
"coreChargesPrice" => "Core Charges Price",
|
||||
"pricePerPack" => "Price per Pack",
|
||||
"codeCharges" => "Code Charges",
|
||||
"coreCharges" => "Core Charges",
|
||||
"currency" => "Currency",
|
||||
"faction" => "Faction",
|
||||
"exp" => "EXP Reward",
|
||||
"see" => "See Also",
|
||||
_ => string.Concat(key.Select((c, i) => i > 0 && char.IsUpper(c) ? " " + c : c.ToString()))
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Shared.Services;
|
||||
|
||||
public class AnalyticsService
|
||||
{
|
||||
private readonly IJSRuntime _jsRuntime;
|
||||
|
||||
public AnalyticsService(IJSRuntime jsRuntime)
|
||||
{
|
||||
_jsRuntime = jsRuntime;
|
||||
}
|
||||
|
||||
public async ValueTask TrackPageView(string path)
|
||||
{
|
||||
await _jsRuntime.InvokeVoidAsync("trackPageView", path);
|
||||
}
|
||||
|
||||
public async ValueTask TrackEvent(string eventName, object? eventData = null)
|
||||
{
|
||||
if (eventData != null)
|
||||
await _jsRuntime.InvokeVoidAsync("gtag", "event", eventName, eventData);
|
||||
else
|
||||
await _jsRuntime.InvokeVoidAsync("gtag", "event", eventName);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Text.RegularExpressions;
|
||||
using Chrono.Model;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Shared.Services;
|
||||
|
||||
public class CardRenderingService
|
||||
{
|
||||
private readonly List<string> _cardNames;
|
||||
private readonly Dictionary<string, CardData> _cardLookup;
|
||||
private readonly List<string> _cardNames;
|
||||
private readonly Regex _nameRegex;
|
||||
|
||||
public CardRenderingService()
|
||||
@@ -33,7 +33,7 @@ public class CardRenderingService
|
||||
{
|
||||
return builder =>
|
||||
{
|
||||
int sequence = 0;
|
||||
var sequence = 0;
|
||||
var paragraphs = description.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
foreach (var paragraph in paragraphs)
|
||||
@@ -41,31 +41,27 @@ public class CardRenderingService
|
||||
builder.OpenElement(sequence++, "p");
|
||||
|
||||
var matches = _nameRegex.Matches(paragraph);
|
||||
int lastIndex = 0;
|
||||
var lastIndex = 0;
|
||||
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
if (match.Index > lastIndex)
|
||||
{
|
||||
builder.AddContent(sequence++, paragraph.Substring(lastIndex, match.Index - lastIndex));
|
||||
}
|
||||
|
||||
var cardName = match.Value;
|
||||
var card = LookupCard(cardName);
|
||||
|
||||
builder.OpenElement(sequence++, "button");
|
||||
builder.AddAttribute(sequence++, "class", "inline-card-btn");
|
||||
builder.AddAttribute(sequence++, "onclick", EventCallback.Factory.Create(this, () => onCardClick(card)));
|
||||
builder.AddAttribute(sequence++, "onclick",
|
||||
EventCallback.Factory.Create(this, () => onCardClick(card)));
|
||||
builder.AddContent(sequence++, cardName);
|
||||
builder.CloseElement();
|
||||
|
||||
lastIndex = match.Index + match.Length;
|
||||
}
|
||||
|
||||
if (lastIndex < paragraph.Length)
|
||||
{
|
||||
builder.AddContent(sequence++, paragraph.Substring(lastIndex));
|
||||
}
|
||||
if (lastIndex < paragraph.Length) builder.AddContent(sequence++, paragraph.Substring(lastIndex));
|
||||
|
||||
builder.CloseElement();
|
||||
}
|
||||
@@ -76,4 +72,4 @@ public class CardRenderingService
|
||||
{
|
||||
return _cardLookup.GetValueOrDefault(cardName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Playwright;
|
||||
using Microsoft.Playwright.NUnit;
|
||||
using Microsoft.Playwright.NUnit;
|
||||
using Tests.PageObjects;
|
||||
|
||||
namespace Tests;
|
||||
@@ -8,10 +7,6 @@ namespace Tests;
|
||||
[TestFixture]
|
||||
public class FeatureTests : PageTest
|
||||
{
|
||||
private DecksPage _decksPage;
|
||||
private DeckDetailPage _deckDetailPage;
|
||||
private AgentsPage _agentsPage;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
@@ -20,17 +15,21 @@ public class FeatureTests : PageTest
|
||||
_agentsPage = new AgentsPage(Page);
|
||||
}
|
||||
|
||||
private DecksPage _decksPage;
|
||||
private DeckDetailPage _deckDetailPage;
|
||||
private AgentsPage _agentsPage;
|
||||
|
||||
[Test]
|
||||
public async Task DeckManaCurve_ShouldBeVisibleOnDetail()
|
||||
{
|
||||
await _decksPage.GotoAsync();
|
||||
|
||||
|
||||
// Assuming there is at least one deck. If not, this might need a more robust approach.
|
||||
var deckCards = _decksPage.GetDeckCards();
|
||||
await Expect(deckCards.First).ToBeVisibleAsync();
|
||||
|
||||
|
||||
await deckCards.First.ClickAsync();
|
||||
|
||||
|
||||
await Expect(_deckDetailPage.ManaCurve).ToBeVisibleAsync();
|
||||
var barCount = await _deckDetailPage.GetManaBarCountAsync();
|
||||
Assert.That(barCount, Is.GreaterThan(0));
|
||||
@@ -43,4 +42,4 @@ public class FeatureTests : PageTest
|
||||
await _agentsPage.WaitForGridAsync();
|
||||
await Expect(_agentsPage.Grid).ToBeVisibleAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,15 +4,20 @@ namespace Tests.PageObjects;
|
||||
|
||||
public class AgentsPage : BasePage
|
||||
{
|
||||
public AgentsPage(IPage page) : base(page) { }
|
||||
|
||||
public async Task GotoAsync() => await NavigateToAsync("/agents");
|
||||
public AgentsPage(IPage page) : base(page)
|
||||
{
|
||||
}
|
||||
|
||||
public ILocator Grid => Page.Locator(".agents-grid");
|
||||
|
||||
|
||||
public async Task GotoAsync()
|
||||
{
|
||||
await NavigateToAsync("/agents");
|
||||
}
|
||||
|
||||
public async Task WaitForGridAsync()
|
||||
{
|
||||
await Page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
await Grid.WaitForAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,8 @@ namespace Tests.PageObjects;
|
||||
|
||||
public abstract class BasePage
|
||||
{
|
||||
protected readonly IPage Page;
|
||||
protected readonly string BaseUrl = "http://localhost:5256";
|
||||
protected readonly IPage Page;
|
||||
|
||||
protected BasePage(IPage page)
|
||||
{
|
||||
@@ -17,5 +17,8 @@ public abstract class BasePage
|
||||
await Page.GotoAsync($"{BaseUrl}{path}");
|
||||
}
|
||||
|
||||
public ILocator GetHeading() => Page.Locator("h1");
|
||||
}
|
||||
public ILocator GetHeading()
|
||||
{
|
||||
return Page.Locator("h1");
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,17 @@ namespace Tests.PageObjects;
|
||||
|
||||
public class DeckDetailPage : BasePage
|
||||
{
|
||||
public DeckDetailPage(IPage page) : base(page) { }
|
||||
public DeckDetailPage(IPage page) : base(page)
|
||||
{
|
||||
}
|
||||
|
||||
public ILocator ManaCurve => Page.Locator(".mana-curve");
|
||||
public ILocator ManaBars => Page.Locator(".mana-bar");
|
||||
public ILocator ManaBarLabels => Page.Locator(".mana-bar-label");
|
||||
public ILocator ManaCosts => Page.Locator(".mana-cost");
|
||||
|
||||
public async Task<int> GetManaBarCountAsync() => await ManaBars.CountAsync();
|
||||
}
|
||||
public async Task<int> GetManaBarCountAsync()
|
||||
{
|
||||
return await ManaBars.CountAsync();
|
||||
}
|
||||
}
|
||||
@@ -4,14 +4,23 @@ namespace Tests.PageObjects;
|
||||
|
||||
public class DecksPage : BasePage
|
||||
{
|
||||
public DecksPage(IPage page) : base(page) { }
|
||||
public DecksPage(IPage page) : base(page)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task GotoAsync() => await NavigateToAsync("/decks");
|
||||
public async Task GotoAsync()
|
||||
{
|
||||
await NavigateToAsync("/decks");
|
||||
}
|
||||
|
||||
public ILocator GetDeckCards()
|
||||
{
|
||||
return Page.Locator(".deck-card");
|
||||
}
|
||||
|
||||
public ILocator GetDeckCards() => Page.Locator(".deck-card");
|
||||
|
||||
public async Task ClickDeckByNameAsync(string name)
|
||||
{
|
||||
await Page.Locator(".deck-card-title").GetByText(name, new() { Exact = true }).ClickAsync();
|
||||
await Page.Locator(".deck-card-title").GetByText(name, new LocatorGetByTextOptions { Exact = true })
|
||||
.ClickAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Playwright;
|
||||
using Microsoft.Playwright.NUnit;
|
||||
|
||||
@@ -13,8 +14,8 @@ public class PlaywrightTests : PageTest
|
||||
public async Task HomePage_ShouldLoad()
|
||||
{
|
||||
await Page.GotoAsync(BaseUrl);
|
||||
await Expect(Page).ToHaveTitleAsync(new System.Text.RegularExpressions.Regex("Chrono CCG"));
|
||||
|
||||
await Expect(Page).ToHaveTitleAsync(new Regex("Chrono CCG"));
|
||||
|
||||
// Check for some content that should be on the home page
|
||||
var heading = Page.Locator("h1");
|
||||
await Expect(heading).ToBeVisibleAsync();
|
||||
|
||||
@@ -7,14 +7,13 @@ namespace Tests;
|
||||
[TestFixture]
|
||||
public class TelerikLicenseTests : PageTest
|
||||
{
|
||||
|
||||
private const string BaseUrl = "http://localhost:5256";
|
||||
|
||||
[Test]
|
||||
public async Task TelerikLicenseBannerIsNotVisible()
|
||||
{
|
||||
await Page.GotoAsync(BaseUrl + "/agents");
|
||||
|
||||
|
||||
await Page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
var grid = Page.Locator(".agents-grid");
|
||||
await Expect(grid).ToBeVisibleAsync();
|
||||
|
||||
+16
-21
@@ -1,30 +1,24 @@
|
||||
using System.Diagnostics;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Tests;
|
||||
|
||||
[SetUpFixture]
|
||||
public class TestSetup
|
||||
{
|
||||
private Process? _serverProcess;
|
||||
private const string ServerUrl = "http://localhost:5256";
|
||||
private Process? _serverProcess;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public async Task BeforeAllTests()
|
||||
{
|
||||
Console.WriteLine("[DEBUG_LOG] Starting Server...");
|
||||
|
||||
|
||||
// Find solution root
|
||||
var currentDir = AppContext.BaseDirectory;
|
||||
while (currentDir != null && !File.Exists(Path.Combine(currentDir, "Chrono.sln")))
|
||||
{
|
||||
currentDir = Path.GetDirectoryName(currentDir);
|
||||
}
|
||||
|
||||
if (currentDir == null)
|
||||
{
|
||||
throw new Exception("Could not find Chrono.sln to determine project path.");
|
||||
}
|
||||
if (currentDir == null) throw new Exception("Could not find Chrono.sln to determine project path.");
|
||||
|
||||
var projectPath = Path.Combine(currentDir, "Server", "Server.csproj");
|
||||
|
||||
@@ -40,25 +34,27 @@ public class TestSetup
|
||||
};
|
||||
|
||||
_serverProcess = Process.Start(startInfo);
|
||||
|
||||
_serverProcess.OutputDataReceived += (s, e) => { if (e.Data != null) Console.WriteLine($"[SERVER OUT] {e.Data}"); };
|
||||
_serverProcess.ErrorDataReceived += (s, e) => { if (e.Data != null) Console.WriteLine($"[SERVER ERR] {e.Data}"); };
|
||||
|
||||
_serverProcess.OutputDataReceived += (s, e) =>
|
||||
{
|
||||
if (e.Data != null) Console.WriteLine($"[SERVER OUT] {e.Data}");
|
||||
};
|
||||
_serverProcess.ErrorDataReceived += (s, e) =>
|
||||
{
|
||||
if (e.Data != null) Console.WriteLine($"[SERVER ERR] {e.Data}");
|
||||
};
|
||||
_serverProcess.BeginOutputReadLine();
|
||||
_serverProcess.BeginErrorReadLine();
|
||||
|
||||
if (_serverProcess == null)
|
||||
{
|
||||
throw new Exception("Failed to start server process.");
|
||||
}
|
||||
if (_serverProcess == null) throw new Exception("Failed to start server process.");
|
||||
|
||||
// Wait for the server to be ready
|
||||
using var client = new HttpClient();
|
||||
var sw = Stopwatch.StartNew();
|
||||
var timeout = TimeSpan.FromSeconds(30);
|
||||
bool isReady = false;
|
||||
var isReady = false;
|
||||
|
||||
while (sw.Elapsed < timeout)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await client.GetAsync(ServerUrl);
|
||||
@@ -73,14 +69,13 @@ public class TestSetup
|
||||
// Wait and retry
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isReady)
|
||||
{
|
||||
_serverProcess.Kill(true);
|
||||
throw new Exception($"Server did not start within {timeout.TotalSeconds} seconds.");
|
||||
}
|
||||
|
||||
|
||||
Console.WriteLine("[DEBUG_LOG] Server is ready.");
|
||||
}
|
||||
|
||||
@@ -94,4 +89,4 @@ public class TestSetup
|
||||
_serverProcess.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
<Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="new[] { typeof(Home).Assembly }" NotFoundPage="typeof(NotFound)">
|
||||
<Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="new[] { typeof(Home).Assembly }"
|
||||
NotFoundPage="typeof(NotFound)">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
|
||||
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@using System.Text.RegularExpressions
|
||||
@namespace Chrono.Components
|
||||
|
||||
@if (Card != null)
|
||||
@@ -10,7 +11,7 @@
|
||||
{
|
||||
<div class="detail-image">
|
||||
<img src="@Card.ImagePath" alt="@Card.Name"
|
||||
onerror="this.style.display='none';this.parentElement.style.display='none'" />
|
||||
onerror="this.style.display='none';this.parentElement.style.display='none'"/>
|
||||
</div>
|
||||
}
|
||||
<div class="detail-info">
|
||||
@@ -88,7 +89,8 @@
|
||||
var target = LookupCard(targetName);
|
||||
if (target != null)
|
||||
{
|
||||
<button class="inline-card-btn" @onclick="() => Navigate(target)">@targetName</button>
|
||||
<button class="inline-card-btn"
|
||||
@onclick="() => Navigate(target)">@targetName</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -108,7 +110,8 @@
|
||||
var fromCard = LookupCard(Card.ImmortalizeFrom);
|
||||
if (fromCard != null)
|
||||
{
|
||||
<button class="inline-card-btn" @onclick="() => Navigate(fromCard)">@Card.ImmortalizeFrom</button>
|
||||
<button class="inline-card-btn"
|
||||
@onclick="() => Navigate(fromCard)">@Card.ImmortalizeFrom</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -181,7 +184,9 @@
|
||||
{
|
||||
await Http.PostAsJsonAsync("api/notes", new CardNote { CardName = Card.Name, Note = currentNote });
|
||||
}
|
||||
catch { }
|
||||
catch
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
isSaving = false;
|
||||
@@ -209,64 +214,68 @@
|
||||
string.Equals(c.Name, cardName, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private RenderFragment RenderDescription(string description) => builder =>
|
||||
private RenderFragment RenderDescription(string description)
|
||||
{
|
||||
var cardNames = CardDatabase.Cards
|
||||
.Select(c => c.Name)
|
||||
.Where(n => !string.IsNullOrWhiteSpace(n))
|
||||
.OrderByDescending(n => n.Length)
|
||||
.ToList();
|
||||
|
||||
int seq = 0;
|
||||
var remaining = description;
|
||||
|
||||
while (!string.IsNullOrEmpty(remaining))
|
||||
return builder =>
|
||||
{
|
||||
int bestIdx = -1;
|
||||
string? bestName = null;
|
||||
var cardNames = CardDatabase.Cards
|
||||
.Select(c => c.Name)
|
||||
.Where(n => !string.IsNullOrWhiteSpace(n))
|
||||
.OrderByDescending(n => n.Length)
|
||||
.ToList();
|
||||
|
||||
foreach (var name in cardNames)
|
||||
var seq = 0;
|
||||
var remaining = description;
|
||||
|
||||
while (!string.IsNullOrEmpty(remaining))
|
||||
{
|
||||
var pattern = $@"\b{System.Text.RegularExpressions.Regex.Escape(name)}\b";
|
||||
var match = System.Text.RegularExpressions.Regex.Match(remaining, pattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
|
||||
var bestIdx = -1;
|
||||
string? bestName = null;
|
||||
|
||||
if (match.Success)
|
||||
foreach (var name in cardNames)
|
||||
{
|
||||
if (bestIdx == -1 || match.Index < bestIdx)
|
||||
var pattern = $@"\b{Regex.Escape(name)}\b";
|
||||
var match = Regex.Match(remaining, pattern, RegexOptions.IgnoreCase);
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
bestIdx = match.Index;
|
||||
bestName = match.Value;
|
||||
if (bestIdx == -1 || match.Index < bestIdx)
|
||||
{
|
||||
bestIdx = match.Index;
|
||||
bestName = match.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestIdx != -1 && bestName != null)
|
||||
{
|
||||
if (bestIdx > 0)
|
||||
builder.AddContent(seq++, remaining[..bestIdx]);
|
||||
|
||||
var card = LookupCard(bestName);
|
||||
if (card != null)
|
||||
if (bestIdx != -1 && bestName != null)
|
||||
{
|
||||
builder.OpenElement(seq++, "button");
|
||||
builder.AddAttribute(seq++, "class", "inline-card-btn");
|
||||
builder.AddAttribute(seq++, "onclick",
|
||||
EventCallback.Factory.Create(this, () => Navigate(card)));
|
||||
builder.AddContent(seq++, bestName);
|
||||
builder.CloseElement();
|
||||
if (bestIdx > 0)
|
||||
builder.AddContent(seq++, remaining[..bestIdx]);
|
||||
|
||||
var card = LookupCard(bestName);
|
||||
if (card != null)
|
||||
{
|
||||
builder.OpenElement(seq++, "button");
|
||||
builder.AddAttribute(seq++, "class", "inline-card-btn");
|
||||
builder.AddAttribute(seq++, "onclick",
|
||||
EventCallback.Factory.Create(this, () => Navigate(card)));
|
||||
builder.AddContent(seq++, bestName);
|
||||
builder.CloseElement();
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddContent(seq++, bestName);
|
||||
}
|
||||
|
||||
remaining = remaining[(bestIdx + bestName.Length)..];
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddContent(seq++, bestName);
|
||||
builder.AddContent(seq++, remaining);
|
||||
remaining = "";
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
remaining = remaining[(bestIdx + bestName.Length)..];
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddContent(seq++, remaining);
|
||||
remaining = "";
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,8 +8,12 @@
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.card-detail {
|
||||
@@ -231,7 +235,8 @@
|
||||
text-decoration-color: #7b73ff;
|
||||
}
|
||||
|
||||
@@media (max-width: 768px) {
|
||||
@
|
||||
@media (max-width: 768px) {
|
||||
.detail-layout {
|
||||
flex-direction: column;
|
||||
padding: 1rem;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
@page "/cards"
|
||||
@inject HttpClient Http
|
||||
@inject AnalyticsService AnalyticsService
|
||||
|
||||
<PageTitle>Chrono CCG - Card Gallery</PageTitle>
|
||||
|
||||
<HeadContent>
|
||||
<meta name="description" content="Browse and filter all Chrono CCG cards. Explore agents, spells, and more." />
|
||||
<meta name="description" content="Browse and filter all Chrono CCG cards. Explore agents, spells, and more."/>
|
||||
</HeadContent>
|
||||
|
||||
<div class="gallery-container">
|
||||
@@ -17,18 +18,19 @@
|
||||
<button class="tab @(categoryFilter == "" ? "active" : "")" @onclick='@(() => SetCategory(""))'>
|
||||
<i class="bi bi-grid-3x3-gap-fill"></i> All
|
||||
</button>
|
||||
|
||||
|
||||
<button class="tab agent @(categoryFilter == "Agent" ? "active" : "")" @onclick='@(() => SetCategory("Agent"))'>
|
||||
<i class="bi bi-person-fill"></i> Agents
|
||||
</button>
|
||||
<button class="tab agent @(categoryFilter == "Immortalized" ? "active" : "")" @onclick='@(() => SetCategory("Immortalized"))'>
|
||||
<button class="tab agent @(categoryFilter == "Immortalized" ? "active" : "")"
|
||||
@onclick='@(() => SetCategory("Immortalized"))'>
|
||||
<i class="bi bi-person-fill"></i> Immortalized
|
||||
</button>
|
||||
<!-- //Todo make agent being linked to immortal for side by side sorting
|
||||
<button class="tab agent @(agentLink ? "active" : "")" @onclick='@(() => ToggleAgentLink())'>
|
||||
<i class="bi bi-person-fill"></i> Link
|
||||
</button>
|
||||
-->
|
||||
<!-- //Todo make agent being linked to immortal for side by side sorting
|
||||
<button class="tab agent @(agentLink ? "active" : "")" @onclick='@(() => ToggleAgentLink())'>
|
||||
<i class="bi bi-person-fill"></i> Link
|
||||
</button>
|
||||
-->
|
||||
<button class="tab spell @(categoryFilter == "Spell" ? "active" : "")" @onclick='@(() => SetCategory("Spell"))'>
|
||||
<i class="bi bi-wand"></i> Spells
|
||||
</button>
|
||||
@@ -118,7 +120,7 @@
|
||||
{
|
||||
<div class="card-grid @(showDetailedView ? "detailed-view" : "")">
|
||||
@{ var idx = 0; }
|
||||
@foreach (var card in filteredCards.Where(a=>a.Category is "Agent" or "Spell" or "Immortalized"))
|
||||
@foreach (var card in filteredCards.Where(a => a.Category is "Agent" or "Spell" or "Immortalized"))
|
||||
{
|
||||
<div class="card-cell @(selectedCard == card ? "selected" : "")"
|
||||
style="--i: @idx"
|
||||
@@ -149,7 +151,7 @@
|
||||
</div>
|
||||
<div class="card-description-preview">@card.Description</div>
|
||||
<div class="card-category-badge @card.Category?.ToLowerInvariant()">@card.Category</div>
|
||||
|
||||
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -171,7 +173,7 @@
|
||||
|
||||
@if (selectedCard != null)
|
||||
{
|
||||
<CardDialog Card="selectedCard" OnClose="CloseDetail" OnNavigate="SelectCard" />
|
||||
<CardDialog Card="selectedCard" OnClose="CloseDetail" OnNavigate="SelectCard"/>
|
||||
}
|
||||
|
||||
@code {
|
||||
@@ -220,12 +222,12 @@
|
||||
_ => sortDescending ? filtered.OrderByDescending(c => c.Name) : filtered.OrderBy(c => c.Name)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private void SetImmortal(string imm)
|
||||
{
|
||||
immortalFilter = immortalFilter == imm ? "" : imm;
|
||||
}
|
||||
|
||||
|
||||
private void ClearImmortalFilter()
|
||||
{
|
||||
immortalFilter = "";
|
||||
@@ -234,11 +236,13 @@
|
||||
private void SetCategory(string cat)
|
||||
{
|
||||
categoryFilter = categoryFilter == cat ? "" : cat;
|
||||
_ = AnalyticsService.TrackEvent("filter_category", new { category = categoryFilter });
|
||||
}
|
||||
|
||||
private void ClearCategoryFilter()
|
||||
{
|
||||
categoryFilter = "";
|
||||
_ = AnalyticsService.TrackEvent("filter_category", new { category = "All" });
|
||||
}
|
||||
|
||||
private void ClearFactionFilter()
|
||||
@@ -250,7 +254,7 @@
|
||||
{
|
||||
agentLink = !agentLink;
|
||||
}
|
||||
|
||||
|
||||
private void ClearCostFilter()
|
||||
{
|
||||
costFilter = "";
|
||||
@@ -264,6 +268,7 @@
|
||||
private void SelectCard(CardData card)
|
||||
{
|
||||
selectedCard = card;
|
||||
_ = AnalyticsService.TrackEvent("select_item", new { item_name = card.Name, item_category = card.Category });
|
||||
}
|
||||
|
||||
private void CloseDetail()
|
||||
@@ -278,4 +283,5 @@
|
||||
factionFilter = "";
|
||||
costFilter = "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||
using Shared.Services;
|
||||
using Web;
|
||||
|
||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||
@@ -8,6 +9,7 @@ builder.RootComponents.Add<HeadOutlet>("head::after");
|
||||
|
||||
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
|
||||
builder.Services.AddTelerikBlazor();
|
||||
builder.Services.AddSingleton<Shared.Services.CardRenderingService>();
|
||||
builder.Services.AddSingleton<CardRenderingService>();
|
||||
builder.Services.AddScoped<AnalyticsService>();
|
||||
|
||||
await builder.Build().RunAsync();
|
||||
@@ -10,7 +10,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ServiceWorker Include="wwwroot\service-worker.js" PublishedContent="wwwroot\service-worker.published.js" />
|
||||
<ServiceWorker Include="wwwroot\service-worker.js" PublishedContent="wwwroot\service-worker.published.js"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -21,6 +21,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Model\Model.csproj"/>
|
||||
<ProjectReference Include="..\Shared\Shared.csproj" />
|
||||
<ProjectReference Include="..\Shared\Shared.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
@using Microsoft.JSInterop
|
||||
@using Shared.Layout
|
||||
@using Shared.Pages
|
||||
@using Shared.Services
|
||||
@using Shared.Components
|
||||
@using Chrono.Components
|
||||
@using Telerik.Blazor
|
||||
@using Telerik.Blazor.Components
|
||||
|
||||
@@ -257,9 +257,6 @@ a, .btn-link {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.inline-card-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
|
||||
@@ -6,26 +6,29 @@
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<title>Chrono CCG - Card Gallery</title>
|
||||
<base href="/"/>
|
||||
<meta name="description" content="Explore the full collection of Chrono CCG cards. Filter by cost, faction, and type."/>
|
||||
<meta name="keywords" content="Chrono CCG, Reference, Card Gallery, DB"/>
|
||||
|
||||
<meta content="Explore the full collection of Chrono CCG cards. Filter by cost, faction, and type."
|
||||
name="description"/>
|
||||
<meta content="Chrono CCG, Reference, Card Gallery, DB" name="keywords"/>
|
||||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website"/>
|
||||
<meta property="og:url" content="https://chronoccg.com/"/>
|
||||
<meta property="og:title" content="Chrono CCG - Card Gallery"/>
|
||||
<meta property="og:description" content="Explore the full collection of Chrono CCG cards. Filter by cost, faction, and type."/>
|
||||
<meta property="og:image" content="https://chronoccg.com/favicon.png"/>
|
||||
<meta content="website" property="og:type"/>
|
||||
<meta content="https://chronoccg.com/" property="og:url"/>
|
||||
<meta content="Chrono CCG - Card Gallery" property="og:title"/>
|
||||
<meta content="Explore the full collection of Chrono CCG cards. Filter by cost, faction, and type."
|
||||
property="og:description"/>
|
||||
<meta content="https://chronoccg.com/favicon.png" property="og:image"/>
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta property="twitter:card" content="summary_large_image"/>
|
||||
<meta property="twitter:url" content="https://chronoccg.com/"/>
|
||||
<meta property="twitter:title" content="Chrono CCG - Card Gallery"/>
|
||||
<meta property="twitter:description" content="Explore the full collection of Chrono CCG cards. Filter by cost, faction, and type."/>
|
||||
<meta property="twitter:image" content="https://chronoccg.com/favicon.png"/>
|
||||
<meta content="summary_large_image" property="twitter:card"/>
|
||||
<meta content="https://chronoccg.com/" property="twitter:url"/>
|
||||
<meta content="Chrono CCG - Card Gallery" property="twitter:title"/>
|
||||
<meta content="Explore the full collection of Chrono CCG cards. Filter by cost, faction, and type."
|
||||
property="twitter:description"/>
|
||||
<meta content="https://chronoccg.com/favicon.png" property="twitter:image"/>
|
||||
|
||||
<link href="manifest.json" rel="manifest" />
|
||||
<link rel="apple-touch-icon" sizes="512x512" href="icon-512.png" />
|
||||
<link rel="apple-touch-icon" sizes="192x192" href="icon-192.png" />
|
||||
<link href="manifest.json" rel="manifest"/>
|
||||
<link href="icon-512.png" rel="apple-touch-icon" sizes="512x512"/>
|
||||
<link href="icon-192.png" rel="apple-touch-icon" sizes="192x192"/>
|
||||
<link href="https://fonts.googleapis.com" rel="preconnect"/>
|
||||
<link crossorigin href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"/>
|
||||
@@ -37,6 +40,26 @@
|
||||
<script defer src="/_content/Telerik.UI.for.Blazor/js/telerik-blazor.js"></script>
|
||||
<link href="/favicon.png" rel="icon" type="image/png"/>
|
||||
<script type="importmap"></script>
|
||||
<!-- Google tag (gtag.js) -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-HVMP2QEJLR"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-HVMP2QEJLR');
|
||||
|
||||
window.trackPageView = (path) => {
|
||||
gtag('event', 'page_view', {
|
||||
page_path: path,
|
||||
page_location: window.location.origin + path
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// In development, always fetch from the network and do not cache.
|
||||
// This is appropriate during development as the service worker will wake up and fetch resources from the network.
|
||||
self.addEventListener('fetch', () => { });
|
||||
self.addEventListener('fetch', () => {
|
||||
});
|
||||
|
||||
@@ -8,8 +8,8 @@ self.addEventListener('fetch', event => event.respondWith(onFetch(event)));
|
||||
|
||||
const cacheNamePrefix = 'offline-cache-';
|
||||
const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`;
|
||||
const offlineAssetsInclude = [ /\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/, /\.blat$/, /\.dat$/ ];
|
||||
const offlineAssetsExclude = [ /^service-worker\.js$/ ];
|
||||
const offlineAssetsInclude = [/\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/, /\.blat$/, /\.dat$/];
|
||||
const offlineAssetsExclude = [/^service-worker\.js$/];
|
||||
|
||||
async function onInstall(event) {
|
||||
console.info('Service worker installing');
|
||||
@@ -18,7 +18,7 @@ async function onInstall(event) {
|
||||
const assetsRequests = self.assetsManifest.assets
|
||||
.filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url)))
|
||||
.filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url)))
|
||||
.map(asset => new Request(asset.url, { integrity: asset.hash, cache: 'no-cache' }));
|
||||
.map(asset => new Request(asset.url, {integrity: asset.hash, cache: 'no-cache'}));
|
||||
await caches.open(cacheName).then(cache => cache.addAll(assetsRequests));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
{
|
||||
"navigationFallback": {
|
||||
"rewrite": "/index.html",
|
||||
"exclude": ["/css/*", "/lib/*", "/_framework/*", "/_content/*", "/sample-data/*"]
|
||||
"exclude": [
|
||||
"/css/*",
|
||||
"/lib/*",
|
||||
"/_framework/*",
|
||||
"/_content/*",
|
||||
"/sample-data/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"id": "frontmatter-folder-organizer",
|
||||
"name": "Frontmatter Folder Organizer",
|
||||
"version": "1.0.0",
|
||||
"minAppVersion": "1.0.0",
|
||||
"description": "Organize markdown files into folders based on frontmatter hierarchy.",
|
||||
"author": "Obsidian",
|
||||
"authorUrl": "https://obsidian.md",
|
||||
"isDesktopOnly": false
|
||||
"id": "frontmatter-folder-organizer",
|
||||
"name": "Frontmatter Folder Organizer",
|
||||
"version": "1.0.0",
|
||||
"minAppVersion": "1.0.0",
|
||||
"description": "Organize markdown files into folders based on frontmatter hierarchy.",
|
||||
"author": "Obsidian",
|
||||
"authorUrl": "https://obsidian.md",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ archetypes:
|
||||
imageLink: "[[Aardvark Precinct Captain.png]]"
|
||||
ranking: A
|
||||
---
|
||||
I feel like it easy to always make this card sprout 5, so +5/+5 worth of stats for two man. Plus at that point, it will Immortalize as a +3/+3 and activate [[Deadly Fauna]].
|
||||
|
||||
I feel like it easy to always make this card sprout 5, so +5/+5 worth of stats for two man. Plus at that point, it will
|
||||
Immortalize as a +3/+3 and activate [[Deadly Fauna]].
|
||||
|
||||
![[Aardvark Precinct Captain.png]]
|
||||
|
||||
@@ -17,6 +17,7 @@ archetypes:
|
||||
- "[[Rewound]]"
|
||||
imageLink: "[[Divergence Assassin.png]]"
|
||||
---
|
||||
|
||||
![[Divergence Assassin.png]]
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ archetypes:
|
||||
imageLink: "[[Scuttling Spares.png]]"
|
||||
rank: S
|
||||
---
|
||||
|
||||
I haven't played this card, but it sounds like it obviously enables discard.
|
||||
|
||||
![[Scuttling Spares.png]]
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
category: Debuff
|
||||
description: Set this Agent's strength to 0 until Round End.
|
||||
---
|
||||
|
||||
Reduce attack to zero.
|
||||
@@ -74,20 +74,30 @@ factions:
|
||||
deckCode: AUHUE2LHEBCW4ZLSM54SAQ3POB4QWY3PNZZXI4TVMN2GKZBTAADACASPCICESCQCAUFDCAYGAMCAGAQDDYBQCAYBAOTQCAYQAMDQG
|
||||
deckType: custom
|
||||
---
|
||||
The idea of this deck is to go heavy on stat-efficient cards. Like 2 for a 2/3 [[Kinetic Absorber]], 5/6 [[Lumbering Starseeker]], and 8 for a 9/14 [[Lightsteel Colossus]].
|
||||
|
||||
You got [[Devourer Spawn]] to help push for lethal. It's going to have a bunch of keywords on it, given how popular timelines are in the meta.
|
||||
The idea of this deck is to go heavy on stat-efficient cards. Like 2 for a 2/3 [[Kinetic Absorber]],
|
||||
5/6 [[Lumbering Starseeker]], and 8 for a 9/14 [[Lightsteel Colossus]].
|
||||
|
||||
You need to Overflow your mana once in a while, or some of your [[Supernova]] removal will be useless. Be pass heavy. And if you do end up overflowing many times [[Supernova]] can refill for mana bar, and it's worth adding some [[Snap Back]]s to the deck to use that spell multiple times.
|
||||
You got [[Devourer Spawn]] to help push for lethal. It's going to have a bunch of keywords on it, given how popular
|
||||
timelines are in the meta.
|
||||
|
||||
You need to Overflow your mana once in a while, or some of your [[Supernova]] removal will be useless. Be pass heavy.
|
||||
And if you do end up overflowing many times [[Supernova]] can refill for mana bar, and it's worth adding
|
||||
some [[Snap Back]]s to the deck to use that spell multiple times.
|
||||
|
||||
Attack aggressively with [[Brilliant Martyr]]. You really want [[Star Siphon]] to ramp.
|
||||
|
||||
As divers, [[Peaceful Synthesizer]] is a 1 drop that will quickly turn into a 3/3. Can't get more stat efficient than that. [[Nonlethal Special Forces]] is to enable [[Phasetide]] for AOE [[Mute]] cards given we don't care about stat buffs. Also as it stands, it always seems to punch a above it's weight on the board given the [[Disarm]] effect.
|
||||
As divers, [[Peaceful Synthesizer]] is a 1 drop that will quickly turn into a 3/3. Can't get more stat efficient than
|
||||
that. [[Nonlethal Special Forces]] is to enable [[Phasetide]] for AOE [[Mute]] cards given we don't care about stat
|
||||
buffs. Also as it stands, it always seems to punch a above it's weight on the board given the [[Disarm]] effect.
|
||||
|
||||
So ya, [[Curb the Anomalies]] can weaken the enemy board, by shutting off all there better stats, activates, and synergies. Hopefully destroy the entire enemy board in combat.
|
||||
So ya, [[Curb the Anomalies]] can weaken the enemy board, by shutting off all there better stats, activates, and
|
||||
synergies. Hopefully destroy the entire enemy board in combat.
|
||||
|
||||
And I suppose [[Bearer of the Broth]]. Since the deck has so much raw stats, you will probably find somewhere to heal. Like healing [[Kinetic Absorber]] so it can keep killing after it Immortalizes.
|
||||
And I suppose [[Bearer of the Broth]]. Since the deck has so much raw stats, you will probably find somewhere to heal.
|
||||
Like healing [[Kinetic Absorber]] so it can keep killing after it Immortalizes.
|
||||
|
||||
Also in practice [[Bearer of the Broth]] has proven to be an insane and reliable draw engine for this deck.
|
||||
Also in practice [[Bearer of the Broth]] has proven to be an insane and reliable draw engine for this deck.
|
||||
|
||||
[[Gunnery Captain]] helps clear up the board. Tokens are just 1 to 2 cost units that grew to absurd sizes. And [[Army of the Sun]] helps in the mirror match, given how common this deck is due to the precon.
|
||||
[[Gunnery Captain]] helps clear up the board. Tokens are just 1 to 2 cost units that grew to absurd sizes.
|
||||
And [[Army of the Sun]] helps in the mirror match, given how common this deck is due to the precon.
|
||||
@@ -62,11 +62,13 @@ factions:
|
||||
deckCode: AUMU65TFOJTGY33XNFXGOICTMVRXK4TJOR4SAQ3POB4QWY3PNZZXI4TVMN2GKZBRACQAAANZAEBZEAI6AQFTSAYCAMOQGBADAEBQCAZ2AMCAGGQDAQBQCAY
|
||||
deckType: custom
|
||||
---
|
||||
|
||||
Built deck as a joke, but it kind of feels nuts in limited testing.
|
||||
|
||||
Mulligan everything for [[Radiant Channeling]] and [[Supernova]]. You are hoping that limited removal keeps you alive.
|
||||
|
||||
If they heavy buff something out from your removal range, you might still have enough reserve to [[Throw into the Sun]] that big target.
|
||||
If they heavy buff something out from your removal range, you might still have enough reserve to [[Throw into the Sun]]
|
||||
that big target.
|
||||
|
||||
If you survive, start scaling your board with [[Awakened Security System]] or [[Limit Breaker]].
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
category: Faction
|
||||
---
|
||||
|
||||
Concepts:
|
||||
|
||||
- Wide Boards
|
||||
- Overpower
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
category: Faction
|
||||
---
|
||||
|
||||
Concepts:
|
||||
|
||||
- Healing
|
||||
-
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
category: Faction
|
||||
---
|
||||
|
||||
Concepts:
|
||||
|
||||
- Activatable Agents
|
||||
-
|
||||
@@ -1,5 +1,7 @@
|
||||
---
|
||||
category: Faction
|
||||
---
|
||||
|
||||
Concepts:
|
||||
|
||||
- Discard
|
||||
@@ -6,6 +6,6 @@ category: Faction
|
||||
|
||||
Can hurt it's own units for power. Has [[Bleed]] to make reoccurring damage on units very easy.
|
||||
|
||||
# Core Damage
|
||||
# Core Damage
|
||||
|
||||
Can hurt both cores easily. Has [[Breakdown]] to take advantage of having an injured core for more damage.
|
||||
@@ -1,11 +1,14 @@
|
||||
---
|
||||
category: Faction
|
||||
---
|
||||
|
||||
# Energy Reserves
|
||||
|
||||
Care about always having banked energy. Spells can refund themselves when using [[Energy Reserves]], or get stronger is you [[Overflow]] your energy reserve.
|
||||
Care about always having banked energy. Spells can refund themselves when using [[Energy Reserves]], or get stronger is
|
||||
you [[Overflow]] your energy reserve.
|
||||
|
||||
Concepts:
|
||||
|
||||
- Ramp
|
||||
- Using and Replenishing Reserved Energy
|
||||
-
|
||||
@@ -17,4 +17,5 @@ archetypes:
|
||||
- "[[Keyword/Sprout]]"
|
||||
imageLink: "[[Horticulturist Oswald.png]]"
|
||||
---
|
||||
|
||||
![[Horticulturist Oswald.png]]
|
||||
@@ -17,4 +17,5 @@ archetypes:
|
||||
- "[[Rewound]]"
|
||||
imageLink: "[[Violet Inquisitioner]]"
|
||||
---
|
||||
|
||||
![[Violent Inquisitioner.png]]
|
||||
@@ -17,4 +17,5 @@ archetypes:
|
||||
- N/A
|
||||
imageLink: "[[Scoot Sparkles.png]]"
|
||||
---
|
||||
|
||||
![[Scoot Sparkles.png]]
|
||||
@@ -17,4 +17,5 @@ archetypes:
|
||||
- N/A
|
||||
imageLink: "[[The Ripper.png]]"
|
||||
---
|
||||
|
||||
![[The Ripper.png]]
|
||||
|
||||
@@ -5,7 +5,7 @@ category: Pass
|
||||
---
|
||||
|
||||
| Tier | Reward |
|
||||
| ---- | -------------------------------- |
|
||||
|------|----------------------------------|
|
||||
| 1 | Sprouts Record |
|
||||
| 2 | 120 Core Charges |
|
||||
| 3 | Burn Precon |
|
||||
@@ -18,5 +18,5 @@ category: Pass
|
||||
| 10 | 240 Core Charges, 1 Draft Ticket |
|
||||
|
||||
| Core Charges | Flux |
|
||||
| ------------ | ---- |
|
||||
|--------------|------|
|
||||
| 660 | 75 |
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
---
|
||||
category: Quest
|
||||
---
|
||||
1: 30cc 30xp
|
||||
2: 20cc 25xp
|
||||
3: 20cc 20xp
|
||||
4: 10cc 20xp
|
||||
5: 10cc 15xp
|
||||
6-12 are all simply 5xp.
|
||||
|
||||
1: 30cc 30xp
|
||||
2: 20cc 25xp
|
||||
3: 20cc 20xp
|
||||
4: 10cc 20xp
|
||||
5: 10cc 15xp
|
||||
6-12 are all simply 5xp.
|
||||
|
||||
So the daily total win reward for 12 wins is 90cc/145xp.
|
||||
Reference in New Issue
Block a user