Cleanup
This commit is contained in:
@@ -1,16 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net10.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
|
|
||||||
<StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
|
|
||||||
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.8"/>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
|
||||||
|
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
|
||||||
|
|
||||||
await builder.Build().RunAsync();
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
@using System.Net.Http
|
|
||||||
@using System.Net.Http.Json
|
|
||||||
@using Microsoft.AspNetCore.Components.Forms
|
|
||||||
@using Microsoft.AspNetCore.Components.Routing
|
|
||||||
@using Microsoft.AspNetCore.Components.Web
|
|
||||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
|
||||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
|
||||||
@using Microsoft.JSInterop
|
|
||||||
@using AOW4.Client
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft.AspNetCore": "Warning"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft.AspNetCore": "Warning"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net10.0</TargetFramework>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="MudBlazor" Version="9.5.0" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.8"/>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
@using AOW4.Portals
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
||||||
<base href="/"/>
|
|
||||||
<ResourcePreloader/>
|
|
||||||
<link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]"/>
|
|
||||||
<link rel="stylesheet" href="@Assets["app.css"]"/>
|
|
||||||
<link rel="stylesheet" href="@Assets["AOW4.styles.css"]"/>
|
|
||||||
<ImportMap/>
|
|
||||||
<link rel="icon" type="image/png" href="favicon.png"/>
|
|
||||||
<HeadOutlet/>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<Routes/>
|
|
||||||
<script src="@Assets["_framework/blazor.web.js"]"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
|
|
||||||
<ToastPortal/>
|
|
||||||
<ConfirmationDialogPortal/>
|
|
||||||
<TechStackPortal/>
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
a {
|
|
||||||
color: white;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
color: white;
|
|
||||||
text-decoration: underline;
|
|
||||||
text-decoration-color: #8fc5ff;
|
|
||||||
text-decoration-thickness: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--severity-warning-color: #2a2000;
|
|
||||||
--severity-warning-border-color: #755c13;
|
|
||||||
--severity-error-color: #290102;
|
|
||||||
--severity-error-border-color: #4C2C33;
|
|
||||||
--severity-information-color: #030129;
|
|
||||||
--severity-information-border-color: #2c3a4c;
|
|
||||||
--severity-success-color: #042901;
|
|
||||||
--severity-success-border-color: #2E4C2C;
|
|
||||||
|
|
||||||
--accent: #432462;
|
|
||||||
--primary: #4308a3;
|
|
||||||
--primary-border: #2c0b62;
|
|
||||||
--primary-hover: #5e00f7;
|
|
||||||
--primary-border-hover: #a168ff;
|
|
||||||
--background: #161618;
|
|
||||||
--secondary: #23133e;
|
|
||||||
--secondary-hover: #2a0070;
|
|
||||||
--secondary-border-hover: #a168ff;
|
|
||||||
--paper: #252526;
|
|
||||||
--paper-border: #151516;
|
|
||||||
|
|
||||||
--paper-hover: #52366f;
|
|
||||||
--paper-border-hover: #653497;
|
|
||||||
|
|
||||||
--info: #451376;
|
|
||||||
--info-border: #210b36;
|
|
||||||
|
|
||||||
--dialog-border-color: black;
|
|
||||||
--dialog-border-width: 2px;
|
|
||||||
--dialog-radius: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
@using AOW4.Components.Inputs
|
|
||||||
@implements IDisposable;
|
|
||||||
@inject IMyDialogService MyDialogService
|
|
||||||
@inject IJSRuntime JsRuntime
|
|
||||||
|
|
||||||
|
|
||||||
@inject NavigationManager NavigationManager
|
|
||||||
|
|
||||||
@if (MyDialogService.IsVisible)
|
|
||||||
{
|
|
||||||
<div class="confirmDialogBackground" onclick="@CloseDialog">
|
|
||||||
<div class="confirmDialogContainer"
|
|
||||||
@onclick:preventDefault="true"
|
|
||||||
@onclick:stopPropagation="true">
|
|
||||||
|
|
||||||
<div class="confirmDialogHeader">
|
|
||||||
@MyDialogService.GetDialogContents().Title
|
|
||||||
</div>
|
|
||||||
<div class="confirmDialogBody">
|
|
||||||
@MyDialogService.GetDialogContents().Message
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="confirmDialogFooter">
|
|
||||||
<ButtonComponent MyButtonType="MyButtonType.Secondary"
|
|
||||||
OnClick="MyDialogService.GetDialogContents().OnCancel">
|
|
||||||
Cancel
|
|
||||||
</ButtonComponent>
|
|
||||||
<ButtonComponent MyButtonType="MyButtonType.Primary"
|
|
||||||
OnClick="MyDialogService.GetDialogContents().OnConfirm">
|
|
||||||
@MyDialogService.GetDialogContents().ConfirmButtonLabel
|
|
||||||
</ButtonComponent>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.pageContents * {
|
|
||||||
filter: blur(2px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.confirmDialogBackground {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.confirmDialogContainer {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
margin-top: 64px;
|
|
||||||
width: 800px;
|
|
||||||
height: 600px;
|
|
||||||
|
|
||||||
/**
|
|
||||||
background-color: var(--background);
|
|
||||||
border-width: var(--dialog-border-width);
|
|
||||||
border-style: solid;
|
|
||||||
border-color: var(--dialog-border-color);
|
|
||||||
border-radius: var(--dialog-radius);
|
|
||||||
*/
|
|
||||||
padding: 8px;
|
|
||||||
|
|
||||||
|
|
||||||
box-shadow: 1px 2px 2px black;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.confirmDialogHeader {
|
|
||||||
font-size: 1.4em;
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.confirmDialogBody {
|
|
||||||
padding: 12px;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.confirmDialogFooter {
|
|
||||||
display: flex;
|
|
||||||
gap: 12px;
|
|
||||||
justify-content: flex-end;
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
|
|
||||||
MyDialogService.Subscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
MyDialogService.Unsubscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void CloseDialog()
|
|
||||||
{
|
|
||||||
MyDialogService.Hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
@using AOW4.Components.Inputs
|
|
||||||
@implements IDisposable;
|
|
||||||
@inject IMyDialogService MyDialogService
|
|
||||||
|
|
||||||
@if (MyDialogService.IsVisible && MyDialogService.GetDialogContents().TechStack != null)
|
|
||||||
{
|
|
||||||
var techStack = MyDialogService.GetDialogContents().TechStack;
|
|
||||||
|
|
||||||
<div class="techStackDialogBackground" onclick="@CloseDialog">
|
|
||||||
<div class="techStackDialogContainer"
|
|
||||||
@onclick:preventDefault="true"
|
|
||||||
@onclick:stopPropagation="true">
|
|
||||||
|
|
||||||
<div class="techStackDialogHeader">
|
|
||||||
@techStack.Name
|
|
||||||
</div>
|
|
||||||
<div class="techStackDialogBody">
|
|
||||||
<div class="description">
|
|
||||||
@techStack.Description
|
|
||||||
</div>
|
|
||||||
<hr/>
|
|
||||||
<div class="extendedNotes">
|
|
||||||
@((MarkupString)(techStack.ExtendedNotes?.Replace("\n", "<br />") ?? ""))
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="techStackDialogFooter">
|
|
||||||
<ButtonComponent MyButtonType="MyButtonType.Primary"
|
|
||||||
OnClick="CloseDialog">
|
|
||||||
Close
|
|
||||||
</ButtonComponent>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.pageContents * {
|
|
||||||
filter: blur(2px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.techStackDialogBackground {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
display: flex;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.techStackDialogContainer {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
margin-top: 64px;
|
|
||||||
width: 800px;
|
|
||||||
max-height: 80vh;
|
|
||||||
background-color: var(--paper);
|
|
||||||
border-width: var(--dialog-border-width);
|
|
||||||
border-style: solid;
|
|
||||||
border-color: var(--dialog-border-color);
|
|
||||||
border-radius: var(--dialog-radius);
|
|
||||||
padding: 16px;
|
|
||||||
box-shadow: 1px 2px 2px black;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
color: white;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.techStackDialogHeader {
|
|
||||||
font-size: 1.8em;
|
|
||||||
font-weight: bold;
|
|
||||||
padding-bottom: 12px;
|
|
||||||
border-bottom: 1px solid var(--paper-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.techStackDialogBody {
|
|
||||||
padding: 16px 0;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
font-style: italic;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.extendedNotes {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.techStackDialogFooter {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
padding-top: 12px;
|
|
||||||
border-top: 1px solid var(--paper-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
MyDialogService.Subscribe(StateHasChanged);
|
|
||||||
|
|
||||||
Console.WriteLine("TechStackDialogComponent initialized");
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
MyDialogService.Unsubscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CloseDialog()
|
|
||||||
{
|
|
||||||
Console.WriteLine( "Closing dialog");
|
|
||||||
MyDialogService.Hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
@inject IToastService ToastService
|
|
||||||
|
|
||||||
@using AOW4.Data
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
@* ReSharper disable once CSharpWarnings::CS8974 *@
|
|
||||||
@if (Toast == null)
|
|
||||||
{
|
|
||||||
<div>Add toast object...</div>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<div onclick="@Dismiss" style="opacity: @Opacity()" class="toastContainer @Toast.SeverityType.ToLower()">
|
|
||||||
<div class="toastTitle">
|
|
||||||
@Toast.Title
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
@Toast.Message
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.toastContainer {
|
|
||||||
border: 4px solid;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 16px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-items: stretch;
|
|
||||||
width: 250px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
.@SeverityType.Warning.ToLower() {
|
|
||||||
background-color: var(--severity-warning-color);
|
|
||||||
border-color: var(--severity-warning-border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.@SeverityType.Error.ToLower() {
|
|
||||||
background-color: var(--severity-error-color);
|
|
||||||
border-color: var(--severity-error-border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.@SeverityType.Information.ToLower() {
|
|
||||||
background-color: var(--severity-information-color);
|
|
||||||
border-color: var(--severity-information-border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.@SeverityType.Success.ToLower() {
|
|
||||||
background-color: var(--severity-success-color);
|
|
||||||
border-color: var(--severity-success-border-color);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
.toastTitle {
|
|
||||||
font-weight: 800;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public ToastModel? Toast { get; set; }
|
|
||||||
|
|
||||||
private readonly float removalTime = 1300;
|
|
||||||
private readonly float fadeoutTime = 1200;
|
|
||||||
|
|
||||||
private float Opacity()
|
|
||||||
{
|
|
||||||
if (Toast!.Age < fadeoutTime)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1.0f - (Toast.Age - fadeoutTime) / (removalTime - fadeoutTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
ToastService.Subscribe(OnUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Dismiss()
|
|
||||||
{
|
|
||||||
ToastService.RemoveToast(Toast!);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
ToastService.Unsubscribe(OnUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnUpdate()
|
|
||||||
{
|
|
||||||
if (Toast!.Age > removalTime)
|
|
||||||
{
|
|
||||||
ToastService.RemoveToast(Toast);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
<button class="buttonContainer @MyButtonType.ToString().ToLower()" @onclick="ButtonClicked">@ChildContent</button>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.buttonContainer {
|
|
||||||
padding: 16px;
|
|
||||||
border: 1px solid;
|
|
||||||
border-radius: 8px;
|
|
||||||
font-weight: 800;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.@(MyButtonType.Primary.ToString().ToLower()) {
|
|
||||||
border-color: var(--primary);
|
|
||||||
background-color: var(--primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.@MyButtonType.Secondary.ToString().ToLower() {
|
|
||||||
border-color: var(--secondary);
|
|
||||||
background-color: var(--secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.@MyButtonType.Primary.ToString().ToLower():hover {
|
|
||||||
background-color: var(--primary-hover);
|
|
||||||
border-color: var(--primary-border-hover);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.@MyButtonType.Secondary.ToString().ToLower():hover {
|
|
||||||
background-color: var(--secondary-hover);
|
|
||||||
border-color: var(--secondary-border-hover);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public RenderFragment ChildContent { get; set; } = default!;
|
|
||||||
|
|
||||||
[Parameter] public EventCallback<EventArgs> OnClick { get; set; }
|
|
||||||
|
|
||||||
[Parameter] public MyButtonType MyButtonType { get; set; }
|
|
||||||
|
|
||||||
private void ButtonClicked(EventArgs eventArgs)
|
|
||||||
{
|
|
||||||
OnClick.InvokeAsync(eventArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace AOW4.Components.Inputs;
|
|
||||||
|
|
||||||
public enum MyButtonType
|
|
||||||
{
|
|
||||||
Primary, // Positive Actions
|
|
||||||
Secondary // Destruction Action
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
@using MudBlazor
|
|
||||||
@inherits LayoutComponentBase
|
|
||||||
|
|
||||||
<MudPopoverProvider/>
|
|
||||||
<MudDialogProvider/>
|
|
||||||
<MudSnackbarProvider/>
|
|
||||||
|
|
||||||
<div class="page">
|
|
||||||
<main>
|
|
||||||
<div class="top-row px-4">
|
|
||||||
<a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article class="content px-4">
|
|
||||||
@Body
|
|
||||||
</article>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="blazor-error-ui" data-nosnippet>
|
|
||||||
An unhandled error has occurred.
|
|
||||||
<a href="." class="reload">Reload</a>
|
|
||||||
<span class="dismiss">🗙</span>
|
|
||||||
</div>
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
.page {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-row {
|
|
||||||
background-color: #f7f7f7;
|
|
||||||
border-bottom: 1px solid #d6d5d5;
|
|
||||||
justify-content: flex-end;
|
|
||||||
height: 3.5rem;
|
|
||||||
display: flex;
|
|
||||||
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:hover, .top-row ::deep .btn-link:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-row ::deep a:first-child {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 640.98px) {
|
|
||||||
.top-row {
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 641px) {
|
|
||||||
.page {
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
width: 250px;
|
|
||||||
height: 100vh;
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-row {
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-row.auth ::deep a:first-child {
|
|
||||||
flex: 1;
|
|
||||||
text-align: right;
|
|
||||||
width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-row, article {
|
|
||||||
padding-left: 2rem !important;
|
|
||||||
padding-right: 1.5rem !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#blazor-error-ui {
|
|
||||||
color-scheme: light only;
|
|
||||||
background: lightyellow;
|
|
||||||
bottom: 0;
|
|
||||||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: none;
|
|
||||||
left: 0;
|
|
||||||
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
|
|
||||||
position: fixed;
|
|
||||||
width: 100%;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
#blazor-error-ui .dismiss {
|
|
||||||
cursor: pointer;
|
|
||||||
position: absolute;
|
|
||||||
right: 0.75rem;
|
|
||||||
top: 0.5rem;
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
@page "/building-calculator"
|
|
||||||
@using System.Text.Json
|
|
||||||
@using AOW4.Data
|
|
||||||
|
|
||||||
<div class="calculator-page">
|
|
||||||
<h1>Building Plan Calculator</h1>
|
|
||||||
<p>Simulates resource income each turn and tracks build completion times for ordered buildings.</p>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<h2>Build Order</h2>
|
|
||||||
<table class="calculator-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Turn Requested</th>
|
|
||||||
<th>Building</th>
|
|
||||||
<th>Finish Turn</th>
|
|
||||||
<th>Industry Remaining</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach (var entry in Result.BuildOrder)
|
|
||||||
{
|
|
||||||
<tr>
|
|
||||||
<td>@entry.RequestedTurn</td>
|
|
||||||
<td>@entry.Name</td>
|
|
||||||
<td>@(entry.BuiltFinishTurn == 0 ? "Starting" : entry.BuiltFinishTurn.ToString())</td>
|
|
||||||
<td>@entry.IndustryCostRemaining</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<h2>Gold Over Time</h2>
|
|
||||||
<table class="calculator-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Turn</th>
|
|
||||||
<th>Stored Gold</th>
|
|
||||||
<th>Income</th>
|
|
||||||
<th>Upkeep</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach (var snapshot in Result.ResourceHistory)
|
|
||||||
{
|
|
||||||
<tr>
|
|
||||||
<td>@snapshot.Turn</td>
|
|
||||||
<td>@snapshot.Stored.Gold</td>
|
|
||||||
<td>@snapshot.TotalIncome.Gold</td>
|
|
||||||
<td>@snapshot.TotalUpkeep.Gold</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<h2>Result JSON</h2>
|
|
||||||
<pre class="json-output">@Json</pre>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private BuildPlanResult Result = new();
|
|
||||||
private string Json = string.Empty;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
Result = BuildingPlanCalculator.CreateSampleBuildPlan();
|
|
||||||
Json = JsonSerializer.Serialize(Result, new JsonSerializerOptions
|
|
||||||
{
|
|
||||||
WriteIndented = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.calculator-page {
|
|
||||||
padding: 2rem;
|
|
||||||
max-width: 1100px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.calculator-table {
|
|
||||||
width: 100%;
|
|
||||||
border-collapse: collapse;
|
|
||||||
margin-bottom: 1.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.calculator-table th,
|
|
||||||
.calculator-table td {
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border: 1px solid #d3d3d3;
|
|
||||||
text-align: left;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.calculator-table th {
|
|
||||||
background-color: #f3f6fb;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.json-output {
|
|
||||||
display: block;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
background: #1f2937;
|
|
||||||
color: #f8fafc;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
overflow-x: auto;
|
|
||||||
font-family: Consolas, "Courier New", monospace;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
@page "/Error"
|
|
||||||
@using System.Diagnostics
|
|
||||||
|
|
||||||
<PageTitle>Error</PageTitle>
|
|
||||||
|
|
||||||
<h1 class="text-danger">Error.</h1>
|
|
||||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
|
||||||
|
|
||||||
@if (ShowRequestId)
|
|
||||||
{
|
|
||||||
<p>
|
|
||||||
<strong>Request ID:</strong> <code>@RequestId</code>
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
|
|
||||||
<h3>Development Mode</h3>
|
|
||||||
<p>
|
|
||||||
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>
|
|
||||||
and restarting the app.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
@code{
|
|
||||||
[CascadingParameter] private HttpContext? HttpContext { get; set; }
|
|
||||||
|
|
||||||
private string? RequestId { get; set; }
|
|
||||||
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,185 +0,0 @@
|
|||||||
@page "/"
|
|
||||||
@using AOW4.Data
|
|
||||||
|
|
||||||
<div class="home-container">
|
|
||||||
<h1>Welcome to AOW4</h1>
|
|
||||||
<p class="subtitle">Explore our tools and resources</p>
|
|
||||||
|
|
||||||
<div class="sections-grid">
|
|
||||||
@foreach (var section in sections)
|
|
||||||
{
|
|
||||||
<div class="section-card">
|
|
||||||
<div class="section-header">
|
|
||||||
<h2>@section.Name</h2>
|
|
||||||
@if (!string.IsNullOrEmpty(section.Description))
|
|
||||||
{
|
|
||||||
<p class="section-description">@section.Description</p>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section-links">
|
|
||||||
@if (section.Links.Any())
|
|
||||||
{
|
|
||||||
<ul>
|
|
||||||
@foreach (var link in section.Links)
|
|
||||||
{
|
|
||||||
<li>
|
|
||||||
<a href="@link.Url">
|
|
||||||
<span class="link-title">@link.Title</span>
|
|
||||||
@if (!string.IsNullOrEmpty(link.Description))
|
|
||||||
{
|
|
||||||
<span class="link-description">@link.Description</span>
|
|
||||||
}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<p class="no-links">Coming soon...</p>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private List<Section> sections = new();
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
sections = SectionsData.GetAllSections();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.home-container {
|
|
||||||
padding: 2rem;
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 2.5rem;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.subtitle {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
color: #666;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sections-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
|
||||||
gap: 2rem;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-card {
|
|
||||||
border: 2px solid #e0e0e0;
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
background-color: #ffffff;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
transition: box-shadow 0.3s ease, transform 0.3s ease;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-card:hover {
|
|
||||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
|
||||||
transform: translateY(-2px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-header {
|
|
||||||
padding: 1.5rem;
|
|
||||||
border-bottom: 2px solid #e0e0e0;
|
|
||||||
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-header h2 {
|
|
||||||
margin: 0 0 0.5rem 0;
|
|
||||||
font-size: 1.8rem;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-description {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-links {
|
|
||||||
padding: 1.5rem;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-links ul {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-links li {
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-links li:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-links a {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
border-left: 4px solid #4a90e2;
|
|
||||||
text-decoration: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-links a:hover {
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
border-left-color: #2563eb;
|
|
||||||
padding-left: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-title {
|
|
||||||
font-weight: 600;
|
|
||||||
color: #2c3e50;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-description {
|
|
||||||
font-size: 0.85rem;
|
|
||||||
color: #7f8c8d;
|
|
||||||
margin-top: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-links {
|
|
||||||
text-align: center;
|
|
||||||
color: #bdc3c7;
|
|
||||||
font-style: italic;
|
|
||||||
padding: 2rem 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media (max-width: 768px) {
|
|
||||||
.sections-grid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
@page "/references/magic-materials"
|
|
||||||
@using AOW4.Data
|
|
||||||
|
|
||||||
<div class="page-container">
|
|
||||||
<h1>Magic Materials Reference</h1>
|
|
||||||
<p class="subtitle">A reference view of the `MagicMaterial` data loaded from `MagicMaterialsData.RawData`.</p>
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-striped table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Category</th>
|
|
||||||
<th>Annex Resources</th>
|
|
||||||
<th>Global Bonus</th>
|
|
||||||
<th>Infusion 1</th>
|
|
||||||
<th>Infusion 2</th>
|
|
||||||
<th>Infusion 3</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach (var material in MagicMaterialsData.RawData)
|
|
||||||
{
|
|
||||||
<tr>
|
|
||||||
<td>@material.Name</td>
|
|
||||||
<td>@material.Category</td>
|
|
||||||
<td>@FormatAnnexResources(material)</td>
|
|
||||||
<td>@material.GlobalBonus</td>
|
|
||||||
<td>
|
|
||||||
<div class="preformatted">@material.InfusionEffects1</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div class="preformatted">@material.InfusionEffects2</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div class="preformatted">@material.InfusionEffects3</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
private static string FormatAnnexResources(MagicMaterial material)
|
|
||||||
{
|
|
||||||
var parts = new List<string>();
|
|
||||||
|
|
||||||
void Add(string label, int? value)
|
|
||||||
{
|
|
||||||
if (value.HasValue)
|
|
||||||
{
|
|
||||||
parts.Add(value.Value < 0 ? $"{value.Value}% {label}" : $"+{value.Value} {label}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Add("Production", material.IncreaseProduction);
|
|
||||||
Add("Gold", material.IncreaseGold);
|
|
||||||
Add("Mana", material.IncreaseMana);
|
|
||||||
Add("Draft", material.IncreaseDraft);
|
|
||||||
Add("Knowledge", material.IncreaseKnowledge);
|
|
||||||
Add("Food", material.IncreaseFood);
|
|
||||||
Add("Stability", material.IncreaseStability);
|
|
||||||
Add("Imperium", material.IncreaseImperium);
|
|
||||||
Add("Allegiance from Whispering Stones", material.IncreaseAllegianceFromWhisperingStones);
|
|
||||||
Add("Relations with Free Cities and Rulers", material.IncreaseRelationWithFreeCitiesAndRulers);
|
|
||||||
Add("Combat Casting Points", material.IncreaseCombatCastingPoints);
|
|
||||||
Add("World Map Casting Points", material.IncreaseWorldCastingPoints);
|
|
||||||
Add("HP Regeneration", material.IncreaseHpRegen);
|
|
||||||
Add("Hit Points", material.IncreaseHitPoints);
|
|
||||||
Add("Experience Percent", material.IncreaseExperiencePercent);
|
|
||||||
Add("Allegiance from Umbral Dwellings", material.IncreaseAllegianceFromUmbralDwellings);
|
|
||||||
Add("Draft Cost Reduction", material.DecreaseDraftCostPercent);
|
|
||||||
Add("Recruitment Cost Reduction", material.DecreaseRecruitmentCostPercent);
|
|
||||||
Add("Knowledge Research Cost Reduction", material.DecreaseKnowledgeResearchCostPercent);
|
|
||||||
Add("Turn Reduction to Found/Absorb/Migrate", material.DecreaseTurnsTakenToFoundAbsorbMigrateCities);
|
|
||||||
|
|
||||||
return parts.Count > 0 ? string.Join("; ", parts) : "—";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.page-container {
|
|
||||||
padding: 2rem;
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.subtitle {
|
|
||||||
color: #666;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-responsive {
|
|
||||||
overflow-x: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preformatted {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
font-family: var(--bs-font-sans-serif);
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
@page "/not-found"
|
|
||||||
@layout MainLayout
|
|
||||||
|
|
||||||
<h3>Not Found</h3>
|
|
||||||
<p>Sorry, the content you are looking for does not exist.</p>
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
@page "/references/province-improvements"
|
|
||||||
@using AOW4.Data
|
|
||||||
|
|
||||||
<div class="page-container">
|
|
||||||
<h1>Province Improvements Reference</h1>
|
|
||||||
<p class="subtitle">A reference view of the `ProvinceImprovement` data loaded from
|
|
||||||
`ProvinceImprovementsData.RawData`.</p>
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-striped table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Category</th>
|
|
||||||
<th>Source</th>
|
|
||||||
<th>Cost (Prod/Gold)</th>
|
|
||||||
<th>Effects</th>
|
|
||||||
<th>Requirements</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach (var improvement in ProvinceImprovementsData.RawData)
|
|
||||||
{
|
|
||||||
<tr>
|
|
||||||
<td>@improvement.Name</td>
|
|
||||||
<td>@improvement.Category</td>
|
|
||||||
<td>@improvement.Source</td>
|
|
||||||
<td>@improvement.CostProduction / @improvement.CostGold</td>
|
|
||||||
<td>
|
|
||||||
<div class="preformatted">@improvement.Effects</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div class="preformatted">@improvement.Requirements</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.page-container {
|
|
||||||
padding: 2rem;
|
|
||||||
max-width: 1400px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.subtitle {
|
|
||||||
color: #666;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-responsive {
|
|
||||||
overflow-x: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preformatted {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
font-family: var(--bs-font-sans-serif);
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table th {
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
@page "/tech-stack"
|
|
||||||
@using AOW4.Services
|
|
||||||
@using MudBlazor
|
|
||||||
@rendermode InteractiveWebAssembly
|
|
||||||
@inject IMyDialogService DialogService
|
|
||||||
|
|
||||||
<div class="techStackPage">
|
|
||||||
<h1>Tech Stack</h1>
|
|
||||||
|
|
||||||
<div class="techStackGrid">
|
|
||||||
@foreach (var tech in Data.TechStackData.RawData)
|
|
||||||
{
|
|
||||||
<div class="techStackItem @(tech.InUse ? "" : "notInUse")" @onclick="() => OpenDialog(tech)">
|
|
||||||
<div class="techStackName">@tech.Name</div>
|
|
||||||
<div class="techStackDescription">@tech.Description</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.techStackPage {
|
|
||||||
padding: 20px;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.techStackGrid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
|
||||||
gap: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.techStackItem {
|
|
||||||
background-color: var(--paper);
|
|
||||||
border: 1px solid var(--paper-border);
|
|
||||||
border-radius: var(--dialog-radius);
|
|
||||||
padding: 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: transform 0.2s, background-color 0.2s, box-shadow 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.techStackItem:hover {
|
|
||||||
background-color: var(--paper-hover);
|
|
||||||
border-color: var(--paper-border-hover);
|
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.techStackItem.notInUse {
|
|
||||||
opacity: 0.5;
|
|
||||||
filter: grayscale(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.techStackName {
|
|
||||||
font-size: 1.5em;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.techStackDescription {
|
|
||||||
font-size: 1em;
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private void OpenDialog(AOW4.Data.TechStack tech)
|
|
||||||
{
|
|
||||||
Console.WriteLine(tech.Name);
|
|
||||||
|
|
||||||
DialogService.Show(new DialogContents
|
|
||||||
{
|
|
||||||
Title = tech.Name,
|
|
||||||
TechStack = tech
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
@using AOW4.Components.Pages
|
|
||||||
<Router AppAssembly="typeof(Program).Assembly" AdditionalAssemblies="new[] { typeof(Client._Imports).Assembly }"
|
|
||||||
NotFoundPage="typeof(NotFound)">
|
|
||||||
<Found Context="routeData">
|
|
||||||
<RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)"/>
|
|
||||||
<FocusOnNavigate RouteData="routeData" Selector="h1"/>
|
|
||||||
</Found>
|
|
||||||
</Router>
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
@using System.Net.Http
|
|
||||||
@using System.Net.Http.Json
|
|
||||||
@using Microsoft.AspNetCore.Components.Forms
|
|
||||||
@using Microsoft.AspNetCore.Components.Routing
|
|
||||||
@using Microsoft.AspNetCore.Components.Web
|
|
||||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
|
||||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
|
||||||
@using Microsoft.JSInterop
|
|
||||||
@using AOW4
|
|
||||||
@using AOW4.Client
|
|
||||||
@using AOW4.Components
|
|
||||||
@using AOW4.Components.Layout
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@using System.Globalization
|
|
||||||
@using System.Reflection
|
|
||||||
@using System.Timers
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
namespace AOW4.Data;
|
|
||||||
|
|
||||||
public enum MagicMaterialCategory
|
|
||||||
{
|
|
||||||
Ore,
|
|
||||||
SunlessOre,
|
|
||||||
Liquid,
|
|
||||||
Plant,
|
|
||||||
VoidStone
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MagicMaterial
|
|
||||||
{
|
|
||||||
public MagicMaterialCategory Category { get; set; }
|
|
||||||
public string Name { get; set; } = string.Empty;
|
|
||||||
public string? Description { get; set; }
|
|
||||||
public string? GlobalBonus { get; set; }
|
|
||||||
public string? InfusionEffects1 { get; set; }
|
|
||||||
public string? InfusionEffects2 { get; set; }
|
|
||||||
public string? InfusionEffects3 { get; set; }
|
|
||||||
public int? IncreaseProduction { get; set; }
|
|
||||||
public int? IncreaseGold { get; set; }
|
|
||||||
public int? IncreaseMana { get; set; }
|
|
||||||
public int? IncreaseDraft { get; set; }
|
|
||||||
public int? IncreaseKnowledge { get; set; }
|
|
||||||
public int? IncreaseFood { get; set; }
|
|
||||||
public int? IncreaseStability { get; set; }
|
|
||||||
public int? IncreaseImperium { get; set; }
|
|
||||||
public int? IncreaseAllegianceFromWhisperingStones { get; set; }
|
|
||||||
public int? IncreaseRelationWithFreeCitiesAndRulers { get; set; }
|
|
||||||
public int? IncreaseCombatCastingPoints { get; set; }
|
|
||||||
public int? IncreaseWorldCastingPoints { get; set; }
|
|
||||||
public int? IncreaseHpRegen { get; set; }
|
|
||||||
public int? IncreaseHitPoints { get; set; }
|
|
||||||
public int? IncreaseExperiencePercent { get; set; }
|
|
||||||
public int? IncreaseAllegianceFromUmbralDwellings { get; set; }
|
|
||||||
public int? DecreaseDraftCostPercent { get; set; }
|
|
||||||
public int? DecreaseRecruitmentCostPercent { get; set; }
|
|
||||||
public int? DecreaseKnowledgeResearchCostPercent { get; set; }
|
|
||||||
public int? DecreaseTurnsTakenToFoundAbsorbMigrateCities { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,329 +0,0 @@
|
|||||||
namespace AOW4.Data;
|
|
||||||
|
|
||||||
public static class MagicMaterialsData
|
|
||||||
{
|
|
||||||
public static readonly IReadOnlyList<MagicMaterial> RawData = new List<MagicMaterial>
|
|
||||||
{
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Category = MagicMaterialCategory.Ore,
|
|
||||||
Name = "Arcanum Ore",
|
|
||||||
Description =
|
|
||||||
"Desolate, Cave Underground and Desolate Underground only. Collection effect: Rings of Binding.",
|
|
||||||
IncreaseProduction = 10,
|
|
||||||
IncreaseMana = 10,
|
|
||||||
GlobalBonus = "-25% Hurry Recruitment Cost",
|
|
||||||
InfusionEffects1 = """
|
|
||||||
Inflict Sundered Defense
|
|
||||||
Power Cleave
|
|
||||||
Support - Bolstered Defense
|
|
||||||
Reinforced
|
|
||||||
+2 Defense
|
|
||||||
Bolstering Defense
|
|
||||||
Juggernaut
|
|
||||||
Demolisher
|
|
||||||
""",
|
|
||||||
InfusionEffects2 = """
|
|
||||||
Construct Slayer
|
|
||||||
Dragon Slayer
|
|
||||||
Inflict Immobilized
|
|
||||||
Push Back
|
|
||||||
Displace and Replace
|
|
||||||
+3 Defense
|
|
||||||
Siege Master
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Category = MagicMaterialCategory.Ore,
|
|
||||||
Name = "Focus Crystals",
|
|
||||||
Description =
|
|
||||||
"Desolate, Cave Underground and Desolate Underground only. Collection effect: Rings of Binding.",
|
|
||||||
IncreaseGold = 10,
|
|
||||||
IncreaseKnowledge = 10,
|
|
||||||
GlobalBonus = "+10% Unit Experience Gain",
|
|
||||||
InfusionEffects1 = """
|
|
||||||
Retaliator +50%
|
|
||||||
+1 Range
|
|
||||||
Inflict Marked
|
|
||||||
Damage Reflection 30%
|
|
||||||
+20% Accuracy
|
|
||||||
Lightning Strike
|
|
||||||
""",
|
|
||||||
InfusionEffects2 = """
|
|
||||||
Retaliator +100%
|
|
||||||
Elemental Slayer
|
|
||||||
Inflict Stunned
|
|
||||||
Hyper-Awareness
|
|
||||||
+30% Accuracy
|
|
||||||
Inversion
|
|
||||||
""",
|
|
||||||
InfusionEffects3 = """
|
|
||||||
Area Damage - Line
|
|
||||||
Damage Reflection 40%
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Category = MagicMaterialCategory.Ore,
|
|
||||||
Name = "Fireforge Stone",
|
|
||||||
Description =
|
|
||||||
"Desolate, Cave Underground and Desolate Underground only. Collection effect: Rings of Binding.",
|
|
||||||
IncreaseProduction = 20,
|
|
||||||
DecreaseDraftCostPercent = 20,
|
|
||||||
GlobalBonus = "-20% Unit Draft Cost",
|
|
||||||
InfusionEffects1 = """
|
|
||||||
Fire Damage
|
|
||||||
+20% Critical Damage
|
|
||||||
Inflict Burning
|
|
||||||
Support - Strengthened
|
|
||||||
Lesser Fire Shield
|
|
||||||
+2 Fire Resistance
|
|
||||||
Berserker's Rage
|
|
||||||
""",
|
|
||||||
InfusionEffects2 = """
|
|
||||||
Arcfire Damage
|
|
||||||
+40% Critical Damage
|
|
||||||
Plant Slayer
|
|
||||||
Greater Fire Shield
|
|
||||||
+4 Fire Resistance
|
|
||||||
Ignore 4 Status Resistance
|
|
||||||
""",
|
|
||||||
InfusionEffects3 = """
|
|
||||||
Area Damage - Blast
|
|
||||||
Inflict Insanity
|
|
||||||
Consume Chaos
|
|
||||||
+6 Fire Resistance
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Category = MagicMaterialCategory.SunlessOre,
|
|
||||||
Name = "Blood Glass",
|
|
||||||
Description = "Sunless Terrain only. Counts as Ore.",
|
|
||||||
IncreaseDraft = 20,
|
|
||||||
IncreaseHpRegen = 5,
|
|
||||||
GlobalBonus = "+5 HP regeneration (on the world map)",
|
|
||||||
InfusionEffects1 = """
|
|
||||||
Greater Inflict Bleed
|
|
||||||
Lifedrinker
|
|
||||||
Blood Sigil
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Category = MagicMaterialCategory.Liquid,
|
|
||||||
Name = "Archon Blood",
|
|
||||||
Description = "Arctic, Highlands and Arctic Underground only. Collection effect: Cosmoflux Elixir.",
|
|
||||||
IncreaseMana = 20,
|
|
||||||
IncreaseCombatCastingPoints = 15,
|
|
||||||
GlobalBonus = "+15 Combat Casting Points",
|
|
||||||
InfusionEffects1 = """
|
|
||||||
Frost Damage
|
|
||||||
Infecting
|
|
||||||
Assassinate
|
|
||||||
Life Steal
|
|
||||||
Lesser Frost Shield
|
|
||||||
+10 Hit Points
|
|
||||||
+2 Frost Resistance
|
|
||||||
Vicious Killer
|
|
||||||
Flanker
|
|
||||||
Raise Undead
|
|
||||||
""",
|
|
||||||
InfusionEffects2 = """
|
|
||||||
Death Damage
|
|
||||||
Inflict Diseased
|
|
||||||
+15 Hit Points
|
|
||||||
+4 Frost Resistance
|
|
||||||
Bolstering Regeneration
|
|
||||||
Undying
|
|
||||||
""",
|
|
||||||
InfusionEffects3 = """
|
|
||||||
Inflict Decaying
|
|
||||||
Gravecall
|
|
||||||
Greater Frost Shield
|
|
||||||
+6 Frost Resistance
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Category = MagicMaterialCategory.Liquid,
|
|
||||||
Name = "Astral Dew",
|
|
||||||
Description = "Arctic, Highlands and Arctic Underground only. Collection effect: Cosmoflux Elixir.",
|
|
||||||
IncreaseMana = 10,
|
|
||||||
IncreaseKnowledge = 10,
|
|
||||||
IncreaseWorldCastingPoints = 15,
|
|
||||||
GlobalBonus = "+15 World Map Casting Points",
|
|
||||||
InfusionEffects1 = """
|
|
||||||
Lightning Damage
|
|
||||||
Inflict Status Vulnerability
|
|
||||||
Inflict Sundered Resistance
|
|
||||||
Support - Bolstered Resistance
|
|
||||||
Lesser Lightning Shield
|
|
||||||
Warded
|
|
||||||
+2 Lightning Resistance
|
|
||||||
Slip Away
|
|
||||||
Casting Points +20
|
|
||||||
""",
|
|
||||||
InfusionEffects2 = """
|
|
||||||
Magic Origin Slayer
|
|
||||||
Inflict Frozen
|
|
||||||
Greater Lightning Shield
|
|
||||||
+4 Lightning Resistance
|
|
||||||
""",
|
|
||||||
InfusionEffects3 = """
|
|
||||||
Static Shield
|
|
||||||
+6 Lightning Resistance
|
|
||||||
Pass Through
|
|
||||||
Astral Membrane
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Category = MagicMaterialCategory.Liquid,
|
|
||||||
Name = "Tranquility Pool",
|
|
||||||
Description = "Arctic, Highlands and Arctic Underground only. Collection effect: Cosmoflux Elixir.",
|
|
||||||
IncreaseKnowledge = 20,
|
|
||||||
DecreaseKnowledgeResearchCostPercent = 10,
|
|
||||||
GlobalBonus = "-10% Knowledge research cost for spells",
|
|
||||||
InfusionEffects1 = """
|
|
||||||
Inflict Slowed
|
|
||||||
Inflict Weakened
|
|
||||||
Inflict Wet
|
|
||||||
Support - Status Protection
|
|
||||||
Lesser Spirit Shield
|
|
||||||
+2 Resistance
|
|
||||||
+2 Status Resistance
|
|
||||||
Attunement: Star Blades
|
|
||||||
Bolstering Resistance
|
|
||||||
Slippery
|
|
||||||
Hindering Blizzard
|
|
||||||
""",
|
|
||||||
InfusionEffects2 = """
|
|
||||||
Celestial Slayer
|
|
||||||
Undead Slayer
|
|
||||||
+3 Resistance
|
|
||||||
+3 Status Resistance
|
|
||||||
Attunement: Fortune
|
|
||||||
""",
|
|
||||||
InfusionEffects3 = """
|
|
||||||
Area Damage - Cascade
|
|
||||||
Status Effect Immunity
|
|
||||||
Resurrection
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Category = MagicMaterialCategory.Plant,
|
|
||||||
Name = "Haste Berries",
|
|
||||||
Description = "Desert, Temperate and Tropical only. Collection effect: Imperial Essence.",
|
|
||||||
IncreaseDraft = 20,
|
|
||||||
DecreaseTurnsTakenToFoundAbsorbMigrateCities = 2,
|
|
||||||
GlobalBonus = "-2 turns to found, absorb or migrate cities",
|
|
||||||
InfusionEffects1 = """
|
|
||||||
Frenzy
|
|
||||||
Inflict Distracted
|
|
||||||
Swift
|
|
||||||
Wind Barrier
|
|
||||||
Conjure Animal
|
|
||||||
""",
|
|
||||||
InfusionEffects2 = """
|
|
||||||
Extra Retaliation
|
|
||||||
Giant Slayer
|
|
||||||
Inflict Blinded
|
|
||||||
Whirlwind
|
|
||||||
Defensive Masters
|
|
||||||
Very Fast Movement
|
|
||||||
Killing Momentum
|
|
||||||
Animate Flora
|
|
||||||
""",
|
|
||||||
InfusionEffects3 = """
|
|
||||||
Area Damage - Chain
|
|
||||||
Polymorph
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Category = MagicMaterialCategory.Plant,
|
|
||||||
Name = "Silvertongue Fruit",
|
|
||||||
Description = "Desert, Temperate and Tropical only. Collection effect: Imperial Essence.",
|
|
||||||
IncreaseFood = 10,
|
|
||||||
IncreaseDraft = 10,
|
|
||||||
IncreaseAllegianceFromWhisperingStones = 1,
|
|
||||||
GlobalBonus = "+1 Allegiance from Whispering Stones",
|
|
||||||
InfusionEffects1 = """
|
|
||||||
Blight Damage
|
|
||||||
Inflict Condemned
|
|
||||||
Inflict Poisoned
|
|
||||||
Support - Regeneration
|
|
||||||
Lesser Blight Shield
|
|
||||||
+2 Blight Resistance
|
|
||||||
Inspiring Killer
|
|
||||||
Universal Camouflage
|
|
||||||
Army Trainer
|
|
||||||
Summon Spider
|
|
||||||
""",
|
|
||||||
InfusionEffects2 = """
|
|
||||||
Hero Slayer
|
|
||||||
Inflict Despairing
|
|
||||||
Inflict Taunted
|
|
||||||
Greater Blight Shield
|
|
||||||
+4 Blight Resistance
|
|
||||||
Army Maintenance
|
|
||||||
""",
|
|
||||||
InfusionEffects3 = """
|
|
||||||
+6 Blight Resistance
|
|
||||||
Domination
|
|
||||||
Summon Spider Monarch
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Category = MagicMaterialCategory.Plant,
|
|
||||||
Name = "Rainbow Clover",
|
|
||||||
Description = "Desert, Temperate and Tropical only. Collection effect: Imperial Essence.",
|
|
||||||
IncreaseFood = 10,
|
|
||||||
IncreaseStability = 10,
|
|
||||||
IncreaseRelationWithFreeCitiesAndRulers = 100,
|
|
||||||
GlobalBonus = "+100 Relations with Free Cities and Rulers",
|
|
||||||
InfusionEffects1 = """
|
|
||||||
Spirit Damage
|
|
||||||
+2 Spirit Resistance
|
|
||||||
Zeal
|
|
||||||
Army Recuperation
|
|
||||||
""",
|
|
||||||
InfusionEffects2 = """
|
|
||||||
Radiant Damage
|
|
||||||
+20% Critical Hit chance
|
|
||||||
Fiend Slayer
|
|
||||||
+4 Spirit Resistance
|
|
||||||
""",
|
|
||||||
InfusionEffects3 = """
|
|
||||||
+30% Critical Hit chance
|
|
||||||
+6 Spirit Resistance
|
|
||||||
Mass Heal
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Category = MagicMaterialCategory.VoidStone,
|
|
||||||
Name = "Void Stones",
|
|
||||||
Description = "Umbral Abyss only. Collection effect: Void Ink.",
|
|
||||||
IncreaseMana = 30,
|
|
||||||
IncreaseAllegianceFromUmbralDwellings = 2,
|
|
||||||
GlobalBonus = "+2 Allegiance per turn with discovered Umbral Dwellings",
|
|
||||||
InfusionEffects1 = """
|
|
||||||
Boon Stealing
|
|
||||||
Cleansing Fire
|
|
||||||
Army: Umbral Malady Immunity
|
|
||||||
""",
|
|
||||||
InfusionEffects2 = """
|
|
||||||
Splitterling Infection
|
|
||||||
Summon Umbral Demon
|
|
||||||
""",
|
|
||||||
InfusionEffects3 = """
|
|
||||||
True Damage
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
namespace AOW4.Data;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a Province Improvement - a buildable enhancement that can be constructed in a province.
|
|
||||||
/// Each Province Improvement decreases stability by -5.
|
|
||||||
/// </summary>
|
|
||||||
public class ProvinceImprovement
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The name of the province improvement.
|
|
||||||
/// </summary>
|
|
||||||
public required string Name { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The base category/type (Conduit, Farm, Forester, Mine, Quarry, Research Post, Teleporter, Monument, etc.).
|
|
||||||
/// </summary>
|
|
||||||
public required string Category { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A description of the effects this improvement provides (resource bonuses, adjacency bonuses, special mechanics,
|
|
||||||
/// etc.).
|
|
||||||
/// </summary>
|
|
||||||
public required string Effects { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Any requirements to build this improvement (terrain, resource nodes, Town Hall tier, etc.).
|
|
||||||
/// </summary>
|
|
||||||
public required string Requirements { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The source/culture/tome that grants this improvement (General, Barbarian, Feudal, High, Mystic, etc.).
|
|
||||||
/// </summary>
|
|
||||||
public required string Source { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The production cost to build this improvement.
|
|
||||||
/// </summary>
|
|
||||||
public int CostProduction { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The gold cost to build this improvement.
|
|
||||||
/// </summary>
|
|
||||||
public int CostGold { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,342 +0,0 @@
|
|||||||
namespace AOW4.Data;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Static raw data provider for Province Improvements.
|
|
||||||
/// </summary>
|
|
||||||
public static class ProvinceImprovementsData
|
|
||||||
{
|
|
||||||
public static List<ProvinceImprovement> RawData => new()
|
|
||||||
{
|
|
||||||
// Basic Province Improvements
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Conduit",
|
|
||||||
Category = "Conduit",
|
|
||||||
Effects = "+5 Mana",
|
|
||||||
Requirements = "Mana node, pearl reef, or magic material",
|
|
||||||
Source = "Base",
|
|
||||||
CostProduction = 0,
|
|
||||||
CostGold = 0
|
|
||||||
},
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Farm",
|
|
||||||
Category = "Farm",
|
|
||||||
Effects = "+5 Food",
|
|
||||||
Requirements = "Grassland or coast terrain, fungus fields (underground)",
|
|
||||||
Source = "Base",
|
|
||||||
CostProduction = 0,
|
|
||||||
CostGold = 0
|
|
||||||
},
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Forester",
|
|
||||||
Category = "Forester",
|
|
||||||
Effects = "+2 Food\n+3 Production",
|
|
||||||
Requirements = "Forest or mangrove forest terrain, mushroom forest (underground)",
|
|
||||||
Source = "Base",
|
|
||||||
CostProduction = 0,
|
|
||||||
CostGold = 0
|
|
||||||
},
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Hut",
|
|
||||||
Category = "Hut",
|
|
||||||
Effects = "+2 Food",
|
|
||||||
Requirements = "Ashlands, sand or snow terrain",
|
|
||||||
Source = "Base",
|
|
||||||
CostProduction = 0,
|
|
||||||
CostGold = 0
|
|
||||||
},
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Mine",
|
|
||||||
Category = "Mine",
|
|
||||||
Effects = "+5 Gold",
|
|
||||||
Requirements = "Gold vein, iron deposit, or pearl reef resource node",
|
|
||||||
Source = "Base",
|
|
||||||
CostProduction = 0,
|
|
||||||
CostGold = 0
|
|
||||||
},
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Quarry",
|
|
||||||
Category = "Quarry",
|
|
||||||
Effects = "+5 Production",
|
|
||||||
Requirements = "Cliff, rocky, or sunken ruins terrain; or iron deposit resource node",
|
|
||||||
Source = "Base",
|
|
||||||
CostProduction = 0,
|
|
||||||
CostGold = 0
|
|
||||||
},
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Research Post",
|
|
||||||
Category = "Research Post",
|
|
||||||
Effects = "+5 Knowledge",
|
|
||||||
Requirements = "Mana node, magic material or sunken ruins terrain",
|
|
||||||
Source = "Base",
|
|
||||||
CostProduction = 0,
|
|
||||||
CostGold = 0
|
|
||||||
},
|
|
||||||
|
|
||||||
// General Province Improvements
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Spell Jammer",
|
|
||||||
Category = "Conduit",
|
|
||||||
Effects = """
|
|
||||||
Enemies cannot target World Map Spells in this Domain.
|
|
||||||
Enemy Spells cost +100% Combat Casting Points in Combat in Domain.
|
|
||||||
-10 Mana.
|
|
||||||
""",
|
|
||||||
Requirements = "Must be built on an acquired province.\nRequires Town Hall III",
|
|
||||||
Source = "General",
|
|
||||||
CostProduction = 250,
|
|
||||||
CostGold = 100
|
|
||||||
},
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Teleporter",
|
|
||||||
Category = "Teleporter",
|
|
||||||
Effects = """
|
|
||||||
A Province Improvement which enables an Army to teleport from one teleporter to another.
|
|
||||||
-10 Mana.
|
|
||||||
""",
|
|
||||||
Requirements = "Must be built on an acquired province",
|
|
||||||
Source = "General",
|
|
||||||
CostProduction = 250,
|
|
||||||
CostGold = 100
|
|
||||||
},
|
|
||||||
|
|
||||||
// Cultural Province Improvements - Barbarian
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Forest of Stakes",
|
|
||||||
Category = "Forester",
|
|
||||||
Effects = """
|
|
||||||
+7 Food income.
|
|
||||||
+7 Production income.
|
|
||||||
+7 Draft per adjacent Forester.
|
|
||||||
Enemy Units in this Domain get Demoralized.
|
|
||||||
""",
|
|
||||||
Requirements = "Must be built on an acquired province.\nRequires Town Hall II: Communal Tent",
|
|
||||||
Source = "Barbarian",
|
|
||||||
CostProduction = 130,
|
|
||||||
CostGold = 60
|
|
||||||
},
|
|
||||||
|
|
||||||
// Cultural Province Improvements - Dark Cult of Death
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Masoleum",
|
|
||||||
Category = "Research Post",
|
|
||||||
Effects = """
|
|
||||||
+10 Knowledge income.
|
|
||||||
+3 Knowledge Production per adjacent Conduit.
|
|
||||||
""",
|
|
||||||
Requirements = "Must be built on an acquired province.\nRequires Town Hall II: Dread Spire",
|
|
||||||
Source = "Dark - Cult of Death",
|
|
||||||
CostProduction = 130,
|
|
||||||
CostGold = 60
|
|
||||||
},
|
|
||||||
|
|
||||||
// Cultural Province Improvements - Dark Cult of Tyranny
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Dark Forge",
|
|
||||||
Category = "Mine",
|
|
||||||
Effects = """
|
|
||||||
+10 Gold income.
|
|
||||||
+5 Production per adjacent Quarry, Mine, or Forester.
|
|
||||||
""",
|
|
||||||
Requirements = "Must be built on an acquired province.\nRequires Town Hall II: Dread Spire",
|
|
||||||
Source = "Dark - Cult of Tyranny",
|
|
||||||
CostProduction = 130,
|
|
||||||
CostGold = 60
|
|
||||||
},
|
|
||||||
|
|
||||||
// Cultural Province Improvements - Feudal
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Farmstead",
|
|
||||||
Category = "Farm",
|
|
||||||
Effects = """
|
|
||||||
+15 Food income.
|
|
||||||
+5 Food per adjacent Farm.
|
|
||||||
""",
|
|
||||||
Requirements = "Must be built on an acquired province.\nRequires Town Hall II: Castle",
|
|
||||||
Source = "Feudal",
|
|
||||||
CostProduction = 130,
|
|
||||||
CostGold = 60
|
|
||||||
},
|
|
||||||
|
|
||||||
// Cultural Province Improvements - High
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Sunshrine",
|
|
||||||
Category = "Research Post",
|
|
||||||
Effects = """
|
|
||||||
+10 Knowledge income.
|
|
||||||
+3 Knowledge per adjacent Research Post.
|
|
||||||
Friendly Units in this Domain are Encouraged.
|
|
||||||
""",
|
|
||||||
Requirements = "Must be built on an acquired province.\nRequires Town Hall II: Atrium of Light",
|
|
||||||
Source = "High",
|
|
||||||
CostProduction = 130,
|
|
||||||
CostGold = 60
|
|
||||||
},
|
|
||||||
|
|
||||||
// Cultural Province Improvements - Industrious
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Builder's Quarters",
|
|
||||||
Category = "Quarry",
|
|
||||||
Effects = """
|
|
||||||
+15 Production income.
|
|
||||||
+5 Production per adjacent Quarry.
|
|
||||||
""",
|
|
||||||
Requirements = "Must be built on an acquired province.\nRequires Town Hall II: Bulwark",
|
|
||||||
Source = "Industrious",
|
|
||||||
CostProduction = 130,
|
|
||||||
CostGold = 60
|
|
||||||
},
|
|
||||||
|
|
||||||
// Cultural Province Improvements - Mystic School of Attunement
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Mystic Abbey",
|
|
||||||
Category = "Conduit",
|
|
||||||
Effects = """
|
|
||||||
+10 Mana income.
|
|
||||||
+3 Knowledge per adjacent Conduit or Research Post.
|
|
||||||
""",
|
|
||||||
Requirements = "Must be built on an acquired province.\nRequires Town Hall II: Mage's Plaza",
|
|
||||||
Source = "Mystic - School of Attunement",
|
|
||||||
CostProduction = 130,
|
|
||||||
CostGold = 60
|
|
||||||
},
|
|
||||||
|
|
||||||
// Cultural Province Improvements - Mystic School of Summoning
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Astral Manalith",
|
|
||||||
Category = "Conduit",
|
|
||||||
Effects = """
|
|
||||||
+10 Mana income.
|
|
||||||
+5 Mana per adjacent Conduit or Research Post.
|
|
||||||
""",
|
|
||||||
Requirements =
|
|
||||||
"Must be built on an acquired Province.\nRequires City Tier 2.\nRequires Town Hall II: Mage's Plaza",
|
|
||||||
Source = "Mystic - School of Summoning",
|
|
||||||
CostProduction = 130,
|
|
||||||
CostGold = 60
|
|
||||||
},
|
|
||||||
|
|
||||||
// Cultural Province Improvements - Nomad Conquerors
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Warcamp",
|
|
||||||
Category = "Forester",
|
|
||||||
Effects = """
|
|
||||||
+15 Draft.
|
|
||||||
Pillaging adjacent provinces takes -1 Turn.
|
|
||||||
Friendly units in this and adjacent provinces gain +15 Hit Point regeneration per World Map Turn.
|
|
||||||
""",
|
|
||||||
Requirements = "Must be built on an annexed Province.\nRequires Town Hall II: Council Deck",
|
|
||||||
Source = "Nomad - Conquerors",
|
|
||||||
CostProduction = 130,
|
|
||||||
CostGold = 60
|
|
||||||
},
|
|
||||||
|
|
||||||
// Cultural Province Improvements - Nomad Scavengers
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Scavenging Camp",
|
|
||||||
Category = "Mine",
|
|
||||||
Effects = """
|
|
||||||
+10 Gold.
|
|
||||||
+10 Gold for this and each adjacent province containing a Resource Node.
|
|
||||||
""",
|
|
||||||
Requirements = "Must be built on an annexed Province.\nRequires Town Hall II: Council Deck",
|
|
||||||
Source = "Nomad - Scavengers",
|
|
||||||
CostProduction = 130,
|
|
||||||
CostGold = 60
|
|
||||||
},
|
|
||||||
|
|
||||||
// Primal Megalith improvements
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Ash Megalith",
|
|
||||||
Category = "Conduit",
|
|
||||||
Effects = "+6 Gold per adjacent Ashland Province",
|
|
||||||
Requirements = "Must be built on an acquired province.\nRequires Town Hall II: Clan Lodge",
|
|
||||||
Source = "Primal - Ash Sabertooth",
|
|
||||||
CostProduction = 250,
|
|
||||||
CostGold = 100
|
|
||||||
},
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Dune Megalith",
|
|
||||||
Category = "Conduit",
|
|
||||||
Effects = "+4 Gold per adjacent Sand Province",
|
|
||||||
Requirements = "Must be built on an acquired province.\nRequires Town Hall II: Clan Lodge",
|
|
||||||
Source = "Primal - Dune Serpent",
|
|
||||||
CostProduction = 250,
|
|
||||||
CostGold = 100
|
|
||||||
},
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "Glacial Megalith",
|
|
||||||
Category = "Conduit",
|
|
||||||
Effects = "+6 Production per adjacent Snow Province",
|
|
||||||
Requirements = "Must be built on an acquired province.\nRequires Town Hall II: Clan Lodge",
|
|
||||||
Source = "Primal - Glacial Mammoth",
|
|
||||||
CostProduction = 250,
|
|
||||||
CostGold = 100
|
|
||||||
},
|
|
||||||
|
|
||||||
// Oathsworn Schools
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "School of Contemplation",
|
|
||||||
Category = "Conduit",
|
|
||||||
Effects = """
|
|
||||||
+7 Mana.
|
|
||||||
+7 Knowledge.
|
|
||||||
+3 Knowledge per adjacent Conduit or Research Post.
|
|
||||||
""",
|
|
||||||
Requirements = "Must be built on an acquired Province.\nRequires Town Hall II: Oath Square",
|
|
||||||
Source = "Oathsworn - Oath of Harmony",
|
|
||||||
CostProduction = 250,
|
|
||||||
CostGold = 100
|
|
||||||
},
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "School of Discipline",
|
|
||||||
Category = "Conduit",
|
|
||||||
Effects = """
|
|
||||||
+7 Mana.
|
|
||||||
+7 Draft.
|
|
||||||
+5 Draft per adjacent Quarry.
|
|
||||||
""",
|
|
||||||
Requirements = "Must be built on an acquired Province.\nRequires Town Hall II: Oath Square",
|
|
||||||
Source = "Oathsworn - Oath of Righteousness",
|
|
||||||
CostProduction = 250,
|
|
||||||
CostGold = 100
|
|
||||||
},
|
|
||||||
new ProvinceImprovement
|
|
||||||
{
|
|
||||||
Name = "School of Mastery",
|
|
||||||
Category = "Conduit",
|
|
||||||
Effects = """
|
|
||||||
+7 Mana.
|
|
||||||
+7 Draft.
|
|
||||||
Units produced in this city start with +1 Starting Rank.
|
|
||||||
""",
|
|
||||||
Requirements = "Must be built on an acquired Province.\nRequires Town Hall II: Oath Square",
|
|
||||||
Source = "Oathsworn - Oath of Strife",
|
|
||||||
CostProduction = 250,
|
|
||||||
CostGold = 100
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
namespace AOW4.Data;
|
|
||||||
|
|
||||||
public class ResourceNode
|
|
||||||
{
|
|
||||||
public string Name { get; set; } = string.Empty;
|
|
||||||
public string? Description { get; set; }
|
|
||||||
public int? IncreaseFood { get; set; }
|
|
||||||
public int? IncreaseProduction { get; set; }
|
|
||||||
public int? IncreaseGold { get; set; }
|
|
||||||
public int? IncreaseMana { get; set; }
|
|
||||||
public int? IncreaseKnowledge { get; set; }
|
|
||||||
public bool ForceEnableFarm { get; set; }
|
|
||||||
public bool ForceEnableMine { get; set; }
|
|
||||||
public bool ForceEnableQuarry { get; set; }
|
|
||||||
public bool ForceEnableConduit { get; set; }
|
|
||||||
public bool ForceEnableResearchPost { get; set; }
|
|
||||||
public bool ForceEnableForester { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
namespace AOW4.Data;
|
|
||||||
|
|
||||||
public static class ResourceNodesData
|
|
||||||
{
|
|
||||||
public static readonly IReadOnlyList<ResourceNode> RawData = new List<ResourceNode>
|
|
||||||
{
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Name = "Pastures",
|
|
||||||
Description = "Roaming herds on lush fields.",
|
|
||||||
IncreaseFood = 10,
|
|
||||||
ForceEnableFarm = true
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Name = "Oasis",
|
|
||||||
Description = "A lush oasis full of nutritious food.",
|
|
||||||
IncreaseFood = 10
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Name = "Iron Deposit",
|
|
||||||
Description = "A rich vein full of ore.",
|
|
||||||
IncreaseProduction = 10,
|
|
||||||
ForceEnableMine = true,
|
|
||||||
ForceEnableQuarry = true
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Name = "Gold Vein",
|
|
||||||
Description = "A large vein of valuable gold.",
|
|
||||||
IncreaseGold = 10,
|
|
||||||
ForceEnableMine = true
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Name = "Mana Node",
|
|
||||||
Description = "Magical currents converge at this location.",
|
|
||||||
IncreaseMana = 10,
|
|
||||||
ForceEnableConduit = true,
|
|
||||||
ForceEnableResearchPost = true
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Name = "Fishing Ground",
|
|
||||||
Description = "A plentiful source of fish.",
|
|
||||||
IncreaseFood = 15
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Name = "Pearl Reef",
|
|
||||||
Description = "A bloom of valuable pearls.",
|
|
||||||
IncreaseGold = 7,
|
|
||||||
IncreaseMana = 7,
|
|
||||||
ForceEnableMine = true,
|
|
||||||
ForceEnableConduit = true
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Name = "Chitinous Growths",
|
|
||||||
Description = "These grotesque growths deposit valuable liquid and ore at unnatural speed.",
|
|
||||||
IncreaseGold = 30
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Name = "Monoliths",
|
|
||||||
Description = "There is writing in an unknown language on these obsidian giants.",
|
|
||||||
IncreaseKnowledge = 30
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Name = "Blossom Orchard",
|
|
||||||
Description = "Eternally blooming trees offering bounty of fruit and wood.",
|
|
||||||
IncreaseFood = 5,
|
|
||||||
IncreaseProduction = 5,
|
|
||||||
ForceEnableForester = true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
namespace AOW4.Data;
|
|
||||||
|
|
||||||
public class SearchPointModel
|
|
||||||
{
|
|
||||||
public string Title { get; set; } = "";
|
|
||||||
public string Summary { get; set; } = "";
|
|
||||||
|
|
||||||
public string Tags { get; set; } = "";
|
|
||||||
public string PointType { get; set; } = "";
|
|
||||||
public string Href { get; set; } = "";
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
namespace AOW4.Data;
|
|
||||||
|
|
||||||
public class SectionLink
|
|
||||||
{
|
|
||||||
public string Title { get; set; } = string.Empty;
|
|
||||||
public string Url { get; set; } = string.Empty;
|
|
||||||
public string? Description { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Section
|
|
||||||
{
|
|
||||||
public string Name { get; set; } = string.Empty;
|
|
||||||
public string? Description { get; set; }
|
|
||||||
public List<SectionLink> Links { get; set; } = new();
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
namespace AOW4.Data;
|
|
||||||
|
|
||||||
public static class SectionsData
|
|
||||||
{
|
|
||||||
public static List<Section> GetAllSections()
|
|
||||||
{
|
|
||||||
return
|
|
||||||
[
|
|
||||||
new Section
|
|
||||||
{
|
|
||||||
Name = "About",
|
|
||||||
Description = "Meta information on this website",
|
|
||||||
Links =
|
|
||||||
[
|
|
||||||
new SectionLink
|
|
||||||
{
|
|
||||||
Title = "Tech Stack",
|
|
||||||
Url = "/tech-stack",
|
|
||||||
Description = "Information about the technology stack that will be used in this project."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
new Section
|
|
||||||
{
|
|
||||||
Name = "Calculators",
|
|
||||||
Description = "Useful calculator tools for various computations",
|
|
||||||
Links =
|
|
||||||
[
|
|
||||||
new SectionLink
|
|
||||||
{
|
|
||||||
Title = "Building Plan Calculator",
|
|
||||||
Url = "/building-calculator",
|
|
||||||
Description = "Simulate build order timing and gold income over turns."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
new Section
|
|
||||||
{
|
|
||||||
Name = "References",
|
|
||||||
Description = "Reference materials and documentation",
|
|
||||||
Links =
|
|
||||||
[
|
|
||||||
new SectionLink
|
|
||||||
{
|
|
||||||
Title = "Magic Materials Reference",
|
|
||||||
Url = "/references/magic-materials",
|
|
||||||
Description = "View the magic material dataset and bonuses in a reference table."
|
|
||||||
},
|
|
||||||
|
|
||||||
new SectionLink
|
|
||||||
{
|
|
||||||
Title = "Province Improvements Reference",
|
|
||||||
Url = "/references/province-improvements",
|
|
||||||
Description =
|
|
||||||
"View the province improvements dataset including costs, effects, and requirements."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
new Section
|
|
||||||
{
|
|
||||||
Name = "Learning",
|
|
||||||
Description = "Educational resources and learning materials",
|
|
||||||
Links = []
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
namespace AOW4.Data;
|
|
||||||
|
|
||||||
public class SeverityType
|
|
||||||
{
|
|
||||||
public static string Warning = "Warning";
|
|
||||||
public static string Information = "Information";
|
|
||||||
public static string Error = "Error";
|
|
||||||
public static string Success = "Success";
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace AOW4.Data;
|
|
||||||
|
|
||||||
public class TechStack
|
|
||||||
{
|
|
||||||
public string Name { get; set; } = string.Empty;
|
|
||||||
public string? Description { get; set; }
|
|
||||||
public string? ExtendedNotes { get; set; }
|
|
||||||
|
|
||||||
public bool InUse { get; set; } = false;
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
namespace AOW4.Data;
|
|
||||||
|
|
||||||
public static class TechStackData
|
|
||||||
{
|
|
||||||
public static List<TechStack> RawData =
|
|
||||||
[
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Name = "Blazor WebAssembly",
|
|
||||||
Description = "Framework for web applications for easy distribution and no hosting costs with third parties",
|
|
||||||
InUse = true,
|
|
||||||
ExtendedNotes = """
|
|
||||||
Simple and easy to distribute. I like C#, and it's C# web development, what's not to like.
|
|
||||||
Obviously con is if I want the user to save state between usages, I am relying on something unreliable like local storage which can be cleared by the user or obviously not transferred between different browsers.
|
|
||||||
So needs to be used in reference and informational only content. I suppose I could rely on the user to handle copying and pasting the data, but a tad cumbersome and unrealistic to expect that.
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Name = "Blazor Server",
|
|
||||||
Description = "Framework for web applications that allows for database interactions",
|
|
||||||
InUse = false,
|
|
||||||
ExtendedNotes = """
|
|
||||||
Easy to distribute. I'll need to have to deal with authentication and all those security concerns.
|
|
||||||
Needs a database to store data. Local hosting Postgresql is the plan.
|
|
||||||
Unideal support implications. Need to make deleting all user data very easy for legal compliance.
|
|
||||||
Less reliability. Server can go down, and I can have a long outage. Fallback to Blazor WebAssembly version hosted by a third party.
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
new() {
|
|
||||||
Name = "MAUI",
|
|
||||||
Description = "Framework for mobile and desktop applications",
|
|
||||||
InUse = false,
|
|
||||||
ExtendedNotes = """
|
|
||||||
So I get around the whole unreliableness of web storage by saving files locally.
|
|
||||||
I can easily distribute via an exe file or apk. Obviously con of that is the user needs to install a exe file or apk, so there is going be a clear 'this could be a virus' type of warning popup to discourage the user.
|
|
||||||
Potentially can distribute via Google Play or Windows Store and be subject to the whims and veto power of a third party.
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Name = "PostgreSQL",
|
|
||||||
Description = "Relational database management system",
|
|
||||||
InUse = false,
|
|
||||||
ExtendedNotes = """
|
|
||||||
I am picking PostgreSQL because it appears free and simple. I have pgAdmin installed and it running.
|
|
||||||
Need to just actually implement using it in the far future.
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
namespace AOW4.Data;
|
|
||||||
|
|
||||||
public class ToastModel
|
|
||||||
{
|
|
||||||
public string Title { get; set; } = "addTitle";
|
|
||||||
public string Message { get; set; } = "addMessage";
|
|
||||||
public string SeverityType { get; set; } = "addType";
|
|
||||||
public float Age { get; set; } = 0;
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
|
|
||||||
using AOW4.Data;
|
|
||||||
using AOW4.Services;
|
|
||||||
|
|
||||||
namespace AOW4;
|
|
||||||
|
|
||||||
public interface IToastService
|
|
||||||
{
|
|
||||||
public void Subscribe(Action action);
|
|
||||||
public void Unsubscribe(Action action);
|
|
||||||
void AddToast(ToastModel toast);
|
|
||||||
void RemoveToast(ToastModel toast);
|
|
||||||
bool HasToasts();
|
|
||||||
List<ToastModel> GetToasts();
|
|
||||||
void AgeToasts();
|
|
||||||
void ClearAllToasts();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public interface ISearchService
|
|
||||||
{
|
|
||||||
public List<SearchPointModel> SearchPoints { get; set; }
|
|
||||||
|
|
||||||
public Dictionary<string, List<SearchPointModel>> Searches { get; set; }
|
|
||||||
|
|
||||||
public bool IsVisible { get; set; }
|
|
||||||
|
|
||||||
public void Subscribe(Action action);
|
|
||||||
public void Unsubscribe(Action action);
|
|
||||||
|
|
||||||
public void Search(string entityId);
|
|
||||||
|
|
||||||
public Task Load();
|
|
||||||
|
|
||||||
public bool IsLoaded();
|
|
||||||
void Show();
|
|
||||||
void Hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IMyDialogService
|
|
||||||
{
|
|
||||||
public bool IsVisible { get; set; }
|
|
||||||
public void Subscribe(Action action);
|
|
||||||
public void Unsubscribe(Action action);
|
|
||||||
public void Show(DialogContents dialogContents);
|
|
||||||
public DialogContents GetDialogContents();
|
|
||||||
public void Hide();
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
@using AOW4.Components.Dialog
|
|
||||||
@implements IDisposable;
|
|
||||||
|
|
||||||
@inject IMyDialogService MyDialogService
|
|
||||||
|
|
||||||
<ConfirmationDialogComponent></ConfirmationDialogComponent>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
MyDialogService.Subscribe(OnUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
MyDialogService.Unsubscribe(OnUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnUpdate()
|
|
||||||
{
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
@using AOW4.Components.Dialog
|
|
||||||
@implements IDisposable;
|
|
||||||
|
|
||||||
@inject IMyDialogService MyDialogService
|
|
||||||
|
|
||||||
<TechStackDialogComponent></TechStackDialogComponent>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
MyDialogService.Subscribe(OnUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
MyDialogService.Unsubscribe(OnUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnUpdate()
|
|
||||||
{
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
@using System.Timers
|
|
||||||
@using AOW4.Components.Feedback
|
|
||||||
@using AOW4.Data
|
|
||||||
@implements IDisposable;
|
|
||||||
|
|
||||||
@inject IToastService ToastService
|
|
||||||
|
|
||||||
@if (ToastService.HasToasts())
|
|
||||||
{
|
|
||||||
<div class="toastsContainer">
|
|
||||||
@foreach (var toast in Toasts)
|
|
||||||
{
|
|
||||||
<ToastComponent Toast="toast"/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.toastsContainer {
|
|
||||||
position: fixed;
|
|
||||||
top: 64px;
|
|
||||||
right: 64px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 5px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private List<ToastModel> Toasts => ToastService.GetToasts();
|
|
||||||
|
|
||||||
private Timer _ageTimer = null!;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
ToastService.Subscribe(OnUpdate);
|
|
||||||
|
|
||||||
_ageTimer = new Timer(10);
|
|
||||||
_ageTimer.Elapsed += OnAge!;
|
|
||||||
_ageTimer.Enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
ToastService.Unsubscribe(OnUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OnAge(object? sender, ElapsedEventArgs elapsedEventArgs)
|
|
||||||
{
|
|
||||||
ToastService.AgeToasts();
|
|
||||||
_ageTimer.Enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OnUpdate()
|
|
||||||
{
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
using AOW4;
|
|
||||||
using AOW4.Components;
|
|
||||||
using AOW4.Services;
|
|
||||||
using MudBlazor.Services;
|
|
||||||
using _Imports = AOW4.Client._Imports;
|
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
|
||||||
|
|
||||||
// Add services to the container.
|
|
||||||
builder.Services.AddRazorComponents()
|
|
||||||
.AddInteractiveWebAssemblyComponents();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<IToastService, ToastService>();
|
|
||||||
builder.Services.AddScoped<IMyDialogService, MyDialogService>();
|
|
||||||
|
|
||||||
builder.Services.AddMudServices();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var app = builder.Build();
|
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
|
||||||
if (app.Environment.IsDevelopment())
|
|
||||||
{
|
|
||||||
app.UseWebAssemblyDebugging();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
|
|
||||||
app.UseHttpsRedirection();
|
|
||||||
|
|
||||||
app.UseAntiforgery();
|
|
||||||
|
|
||||||
app.MapStaticAssets();
|
|
||||||
app.MapRazorComponents<App>()
|
|
||||||
.AddInteractiveWebAssemblyRenderMode()
|
|
||||||
.AddAdditionalAssemblies(typeof(_Imports).Assembly);
|
|
||||||
|
|
||||||
app.Run();
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
|
||||||
"profiles": {
|
|
||||||
"http": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"dotnetRunMessages": true,
|
|
||||||
"launchBrowser": true,
|
|
||||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
|
||||||
"applicationUrl": "http://localhost:5212",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"https": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"dotnetRunMessages": true,
|
|
||||||
"launchBrowser": true,
|
|
||||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
|
||||||
"applicationUrl": "https://localhost:7027;http://localhost:5212",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
|
|
||||||
namespace AOW4.Services;
|
|
||||||
|
|
||||||
public class DialogContents
|
|
||||||
{
|
|
||||||
public string Title { get; set; }
|
|
||||||
public string Message { get; set; }
|
|
||||||
public string ConfirmButtonLabel { get; set; }
|
|
||||||
public EventCallback<EventArgs> OnConfirm { get; set; }
|
|
||||||
public EventCallback<EventArgs> OnCancel { get; set; }
|
|
||||||
public AOW4.Data.TechStack? TechStack { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MyDialogService : IMyDialogService
|
|
||||||
{
|
|
||||||
private DialogContents _dialogContents = new();
|
|
||||||
|
|
||||||
public bool IsVisible { get; set; }
|
|
||||||
|
|
||||||
public void Subscribe(Action action)
|
|
||||||
{
|
|
||||||
OnChange += action;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Unsubscribe(Action action)
|
|
||||||
{
|
|
||||||
OnChange += action;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Show(DialogContents dialogContents)
|
|
||||||
{
|
|
||||||
_dialogContents = dialogContents;
|
|
||||||
IsVisible = true;
|
|
||||||
|
|
||||||
NotifyDataChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public DialogContents GetDialogContents()
|
|
||||||
{
|
|
||||||
return _dialogContents;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Hide()
|
|
||||||
{
|
|
||||||
IsVisible = false;
|
|
||||||
|
|
||||||
NotifyDataChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private event Action OnChange = null!;
|
|
||||||
|
|
||||||
private void NotifyDataChanged()
|
|
||||||
{
|
|
||||||
OnChange();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
using AOW4.Data;
|
|
||||||
|
|
||||||
namespace AOW4.Services;
|
|
||||||
|
|
||||||
public class SearchService : ISearchService
|
|
||||||
{
|
|
||||||
private bool _isLoaded;
|
|
||||||
|
|
||||||
public List<SearchPointModel> SearchPoints { get; set; } = new();
|
|
||||||
|
|
||||||
public Dictionary<string, List<SearchPointModel>> Searches { get; set; } = new();
|
|
||||||
|
|
||||||
public bool IsVisible { get; set; }
|
|
||||||
|
|
||||||
public void Subscribe(Action action)
|
|
||||||
{
|
|
||||||
OnChange += action;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Unsubscribe(Action action)
|
|
||||||
{
|
|
||||||
OnChange += action;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Search(string entityId)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Load()
|
|
||||||
{
|
|
||||||
Searches.Add("MagicMaterial", []);
|
|
||||||
|
|
||||||
foreach (var entity in MagicMaterialsData.RawData)
|
|
||||||
{
|
|
||||||
var title = entity.Name;
|
|
||||||
var description = entity.Description ?? "";
|
|
||||||
|
|
||||||
var summary =
|
|
||||||
|
|
||||||
description.Length > 35
|
|
||||||
? description[..30].Trim() + "..."
|
|
||||||
: description.Length > 0
|
|
||||||
? description
|
|
||||||
: "";
|
|
||||||
|
|
||||||
SearchPoints.Add(new SearchPointModel
|
|
||||||
{
|
|
||||||
Title = title,
|
|
||||||
Tags = "Magic Material",
|
|
||||||
PointType = "Entity",
|
|
||||||
Summary = summary,
|
|
||||||
Href = ""// Add a link to the entity page
|
|
||||||
});
|
|
||||||
|
|
||||||
Searches["MagicMaterial"].Add(SearchPoints.Last());
|
|
||||||
}
|
|
||||||
|
|
||||||
_isLoaded = true;
|
|
||||||
|
|
||||||
NotifyDataChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsLoaded()
|
|
||||||
{
|
|
||||||
return _isLoaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Show()
|
|
||||||
{
|
|
||||||
IsVisible = true;
|
|
||||||
|
|
||||||
NotifyDataChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Hide()
|
|
||||||
{
|
|
||||||
IsVisible = false;
|
|
||||||
|
|
||||||
NotifyDataChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private event Action OnChange = null!;
|
|
||||||
|
|
||||||
private void NotifyDataChanged()
|
|
||||||
{
|
|
||||||
OnChange();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
using AOW4.Data;
|
|
||||||
|
|
||||||
namespace AOW4.Services;
|
|
||||||
|
|
||||||
public class ToastService : IToastService
|
|
||||||
{
|
|
||||||
private readonly List<ToastModel> _toasts = [];
|
|
||||||
|
|
||||||
public void Subscribe(Action action)
|
|
||||||
{
|
|
||||||
OnChange += action;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Unsubscribe(Action action)
|
|
||||||
{
|
|
||||||
OnChange += action;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddToast(ToastModel toast)
|
|
||||||
{
|
|
||||||
_toasts.Insert(0, toast);
|
|
||||||
|
|
||||||
NotifyDataChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveToast(ToastModel toast)
|
|
||||||
{
|
|
||||||
_toasts.Remove(toast);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasToasts()
|
|
||||||
{
|
|
||||||
return _toasts.Count > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ToastModel> GetToasts()
|
|
||||||
{
|
|
||||||
return _toasts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AgeToasts()
|
|
||||||
{
|
|
||||||
foreach (var toast in _toasts) toast.Age++;
|
|
||||||
|
|
||||||
NotifyDataChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearAllToasts()
|
|
||||||
{
|
|
||||||
_toasts.Clear();
|
|
||||||
NotifyDataChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private event Action OnChange = null!;
|
|
||||||
|
|
||||||
private void NotifyDataChanged()
|
|
||||||
{
|
|
||||||
OnChange();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,355 +0,0 @@
|
|||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace AOW4.Data;
|
|
||||||
|
|
||||||
public sealed class ResourceAmounts
|
|
||||||
{
|
|
||||||
public int Draft { get; set; }
|
|
||||||
public int Food { get; set; }
|
|
||||||
public int Knowledge { get; set; }
|
|
||||||
public int Industry { get; set; }
|
|
||||||
public int Magic { get; set; }
|
|
||||||
public int Gold { get; set; }
|
|
||||||
public int Imperial { get; set; }
|
|
||||||
public int Stability { get; set; }
|
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public bool IsZero => Draft == 0 && Food == 0 && Knowledge == 0 && Industry == 0 && Magic == 0 && Gold == 0 &&
|
|
||||||
Imperial == 0 && Stability == 0;
|
|
||||||
|
|
||||||
public void Add(ResourceAmounts other)
|
|
||||||
{
|
|
||||||
Draft += other.Draft;
|
|
||||||
Food += other.Food;
|
|
||||||
Knowledge += other.Knowledge;
|
|
||||||
Industry += other.Industry;
|
|
||||||
Magic += other.Magic;
|
|
||||||
Gold += other.Gold;
|
|
||||||
Imperial += other.Imperial;
|
|
||||||
Stability += other.Stability;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Subtract(ResourceAmounts other)
|
|
||||||
{
|
|
||||||
Draft -= other.Draft;
|
|
||||||
Food -= other.Food;
|
|
||||||
Knowledge -= other.Knowledge;
|
|
||||||
Industry -= other.Industry;
|
|
||||||
Magic -= other.Magic;
|
|
||||||
Gold -= other.Gold;
|
|
||||||
Imperial -= other.Imperial;
|
|
||||||
Stability -= other.Stability;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ResourceAmounts operator +(ResourceAmounts a, ResourceAmounts b)
|
|
||||||
{
|
|
||||||
return new ResourceAmounts
|
|
||||||
{
|
|
||||||
Draft = a.Draft + b.Draft,
|
|
||||||
Food = a.Food + b.Food,
|
|
||||||
Knowledge = a.Knowledge + b.Knowledge,
|
|
||||||
Industry = a.Industry + b.Industry,
|
|
||||||
Magic = a.Magic + b.Magic,
|
|
||||||
Gold = a.Gold + b.Gold,
|
|
||||||
Imperial = a.Imperial + b.Imperial,
|
|
||||||
Stability = a.Stability + b.Stability
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ResourceAmounts operator -(ResourceAmounts a, ResourceAmounts b)
|
|
||||||
{
|
|
||||||
return new ResourceAmounts
|
|
||||||
{
|
|
||||||
Draft = a.Draft - b.Draft,
|
|
||||||
Food = a.Food - b.Food,
|
|
||||||
Knowledge = a.Knowledge - b.Knowledge,
|
|
||||||
Industry = a.Industry - b.Industry,
|
|
||||||
Magic = a.Magic - b.Magic,
|
|
||||||
Gold = a.Gold - b.Gold,
|
|
||||||
Imperial = a.Imperial - b.Imperial,
|
|
||||||
Stability = a.Stability - b.Stability
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class BuildingDefinition
|
|
||||||
{
|
|
||||||
public string Id { get; set; } = string.Empty;
|
|
||||||
public string Name { get; set; } = string.Empty;
|
|
||||||
public string? Description { get; set; }
|
|
||||||
public string? Image { get; set; }
|
|
||||||
public string SourceId { get; set; } = "General";
|
|
||||||
public List<string> RequirementIds { get; set; } = new();
|
|
||||||
public ResourceAmounts Income { get; set; } = new();
|
|
||||||
public ResourceAmounts Upkeep { get; set; } = new();
|
|
||||||
public ResourceAmounts Cost { get; set; } = new();
|
|
||||||
public int BoostPopulation { get; set; }
|
|
||||||
public int BoostForester { get; set; }
|
|
||||||
public int BoostFarm { get; set; }
|
|
||||||
public int BoostQuarry { get; set; }
|
|
||||||
public int BoostGoldMine { get; set; }
|
|
||||||
public int BoostConduit { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class BuildOrderEntry
|
|
||||||
{
|
|
||||||
public Guid Id { get; set; } = Guid.NewGuid();
|
|
||||||
public string ItemId { get; set; } = string.Empty;
|
|
||||||
public string Name { get; set; } = string.Empty;
|
|
||||||
public int RequestedTurn { get; set; }
|
|
||||||
public int BuildStartTurn { get; set; }
|
|
||||||
public int BuiltFinishTurn { get; set; }
|
|
||||||
public int IndustryCostRemaining { get; set; }
|
|
||||||
public BuildingDefinition Definition { get; set; } = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class ResourceSnapshot
|
|
||||||
{
|
|
||||||
public int Turn { get; set; }
|
|
||||||
public ResourceAmounts Stored { get; set; } = new();
|
|
||||||
public ResourceAmounts TotalIncome { get; set; } = new();
|
|
||||||
public ResourceAmounts TotalUpkeep { get; set; } = new();
|
|
||||||
public string? Notes { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class BuildPlanResult
|
|
||||||
{
|
|
||||||
public List<BuildOrderEntry> BuildOrder { get; set; } = new();
|
|
||||||
public List<ResourceSnapshot> ResourceHistory { get; set; } = new();
|
|
||||||
public ResourceAmounts StartingPool { get; set; } = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class BuildOrderRequest
|
|
||||||
{
|
|
||||||
public string ItemId { get; init; } = string.Empty;
|
|
||||||
public BuildingDefinition Definition { get; init; } = new();
|
|
||||||
public int RequestedTurn { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class BuildingPlanCalculator
|
|
||||||
{
|
|
||||||
public static BuildPlanResult CalculateBuildPlan(
|
|
||||||
int totalTurns,
|
|
||||||
IEnumerable<BuildOrderRequest> buildRequests,
|
|
||||||
IEnumerable<BuildingDefinition>? startingBuildings = null,
|
|
||||||
ResourceAmounts? startingResources = null)
|
|
||||||
{
|
|
||||||
var activeBuildings = new List<BuildOrderEntry>();
|
|
||||||
var result = new BuildPlanResult
|
|
||||||
{
|
|
||||||
StartingPool = startingResources ?? new ResourceAmounts()
|
|
||||||
};
|
|
||||||
|
|
||||||
var stored = new ResourceAmounts();
|
|
||||||
if (startingResources is not null)
|
|
||||||
stored = new ResourceAmounts
|
|
||||||
{
|
|
||||||
Draft = startingResources.Draft,
|
|
||||||
Food = startingResources.Food,
|
|
||||||
Knowledge = startingResources.Knowledge,
|
|
||||||
Industry = startingResources.Industry,
|
|
||||||
Magic = startingResources.Magic,
|
|
||||||
Gold = startingResources.Gold,
|
|
||||||
Imperial = startingResources.Imperial,
|
|
||||||
Stability = startingResources.Stability
|
|
||||||
};
|
|
||||||
|
|
||||||
if (startingBuildings is not null)
|
|
||||||
foreach (var startingBuilding in startingBuildings)
|
|
||||||
{
|
|
||||||
var entry = new BuildOrderEntry
|
|
||||||
{
|
|
||||||
ItemId = startingBuilding.Id,
|
|
||||||
Name = startingBuilding.Name,
|
|
||||||
RequestedTurn = 1,
|
|
||||||
BuildStartTurn = 1,
|
|
||||||
BuiltFinishTurn = 0,
|
|
||||||
IndustryCostRemaining = 0,
|
|
||||||
Definition = startingBuilding
|
|
||||||
};
|
|
||||||
activeBuildings.Add(entry);
|
|
||||||
result.BuildOrder.Add(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
var requestsByTurn = buildRequests
|
|
||||||
.OrderBy(r => r.RequestedTurn)
|
|
||||||
.GroupBy(r => r.RequestedTurn)
|
|
||||||
.ToDictionary(g => g.Key, g => g.ToList());
|
|
||||||
|
|
||||||
var projects = new List<BuildOrderEntry>();
|
|
||||||
|
|
||||||
for (var turn = 1; turn <= totalTurns; turn++)
|
|
||||||
{
|
|
||||||
var incomeThisTurn = new ResourceAmounts();
|
|
||||||
var upkeepThisTurn = new ResourceAmounts();
|
|
||||||
|
|
||||||
foreach (var building in activeBuildings)
|
|
||||||
if (building.BuiltFinishTurn == 0 || turn > building.BuiltFinishTurn)
|
|
||||||
{
|
|
||||||
incomeThisTurn.Add(building.Definition.Income);
|
|
||||||
upkeepThisTurn.Add(building.Definition.Upkeep);
|
|
||||||
}
|
|
||||||
|
|
||||||
stored.Add(incomeThisTurn);
|
|
||||||
stored.Subtract(upkeepThisTurn);
|
|
||||||
|
|
||||||
if (requestsByTurn.TryGetValue(turn, out var requests))
|
|
||||||
foreach (var request in requests)
|
|
||||||
{
|
|
||||||
var nextProject = new BuildOrderEntry
|
|
||||||
{
|
|
||||||
ItemId = request.ItemId,
|
|
||||||
Name = request.Definition.Name,
|
|
||||||
RequestedTurn = turn,
|
|
||||||
BuildStartTurn = turn,
|
|
||||||
BuiltFinishTurn = 0,
|
|
||||||
IndustryCostRemaining = request.Definition.Cost.Industry,
|
|
||||||
Definition = request.Definition
|
|
||||||
};
|
|
||||||
|
|
||||||
stored.Subtract(new ResourceAmounts
|
|
||||||
{
|
|
||||||
Draft = request.Definition.Cost.Draft,
|
|
||||||
Food = request.Definition.Cost.Food,
|
|
||||||
Knowledge = request.Definition.Cost.Knowledge,
|
|
||||||
Magic = request.Definition.Cost.Magic,
|
|
||||||
Gold = request.Definition.Cost.Gold,
|
|
||||||
Imperial = request.Definition.Cost.Imperial,
|
|
||||||
Stability = 0
|
|
||||||
});
|
|
||||||
|
|
||||||
projects.Add(nextProject);
|
|
||||||
result.BuildOrder.Add(nextProject);
|
|
||||||
}
|
|
||||||
|
|
||||||
var availableIndustry = incomeThisTurn.Industry;
|
|
||||||
foreach (var project in projects.Where(p => p.BuiltFinishTurn == 0).OrderBy(p => p.RequestedTurn))
|
|
||||||
{
|
|
||||||
if (availableIndustry <= 0 || project.IndustryCostRemaining <= 0) continue;
|
|
||||||
|
|
||||||
var applied = Math.Min(availableIndustry, project.IndustryCostRemaining);
|
|
||||||
project.IndustryCostRemaining -= applied;
|
|
||||||
availableIndustry -= applied;
|
|
||||||
|
|
||||||
if (project.IndustryCostRemaining <= 0)
|
|
||||||
{
|
|
||||||
project.BuiltFinishTurn = turn;
|
|
||||||
activeBuildings.Add(project);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.ResourceHistory.Add(new ResourceSnapshot
|
|
||||||
{
|
|
||||||
Turn = turn,
|
|
||||||
Stored = new ResourceAmounts
|
|
||||||
{
|
|
||||||
Draft = stored.Draft,
|
|
||||||
Food = stored.Food,
|
|
||||||
Knowledge = stored.Knowledge,
|
|
||||||
Industry = stored.Industry,
|
|
||||||
Magic = stored.Magic,
|
|
||||||
Gold = stored.Gold,
|
|
||||||
Imperial = stored.Imperial,
|
|
||||||
Stability = stored.Stability
|
|
||||||
},
|
|
||||||
TotalIncome = incomeThisTurn,
|
|
||||||
TotalUpkeep = upkeepThisTurn,
|
|
||||||
Notes = null
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IReadOnlyList<BuildingDefinition> GetDefaultStartingBuildings()
|
|
||||||
{
|
|
||||||
return new List<BuildingDefinition>
|
|
||||||
{
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Id = "town-hall-1",
|
|
||||||
Name = "Town Hall I",
|
|
||||||
Description = "Starting civic center that produces basic resources and morale.",
|
|
||||||
SourceId = "General",
|
|
||||||
Income = new ResourceAmounts
|
|
||||||
{
|
|
||||||
Draft = 20,
|
|
||||||
Food = 30,
|
|
||||||
Industry = 20,
|
|
||||||
Gold = 0,
|
|
||||||
Stability = 10
|
|
||||||
},
|
|
||||||
Upkeep = new ResourceAmounts(),
|
|
||||||
Cost = new ResourceAmounts()
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Id = "throne",
|
|
||||||
Name = "Throne",
|
|
||||||
Description = "Royal treasury building that provides steady gold income.",
|
|
||||||
SourceId = "General",
|
|
||||||
Income = new ResourceAmounts
|
|
||||||
{
|
|
||||||
Gold = 120
|
|
||||||
},
|
|
||||||
Upkeep = new ResourceAmounts(),
|
|
||||||
Cost = new ResourceAmounts()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BuildPlanResult CreateSampleBuildPlan(int totalTurns = 60)
|
|
||||||
{
|
|
||||||
var sampleRequests = new List<BuildOrderRequest>
|
|
||||||
{
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
ItemId = "farm-1",
|
|
||||||
Definition = new BuildingDefinition
|
|
||||||
{
|
|
||||||
Id = "farm-1",
|
|
||||||
Name = "Farm",
|
|
||||||
Description = "Provides food income and supports future growth.",
|
|
||||||
SourceId = "General",
|
|
||||||
Income = new ResourceAmounts { Food = 15 },
|
|
||||||
Upkeep = new ResourceAmounts { Gold = 2 },
|
|
||||||
Cost = new ResourceAmounts { Gold = 80, Industry = 40 }
|
|
||||||
},
|
|
||||||
RequestedTurn = 2
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
ItemId = "workshop-1",
|
|
||||||
Definition = new BuildingDefinition
|
|
||||||
{
|
|
||||||
Id = "workshop-1",
|
|
||||||
Name = "Workshop",
|
|
||||||
Description = "Improves production and generates industry.",
|
|
||||||
SourceId = "General",
|
|
||||||
Income = new ResourceAmounts { Industry = 20 },
|
|
||||||
Upkeep = new ResourceAmounts { Gold = 4 },
|
|
||||||
Cost = new ResourceAmounts { Gold = 110, Industry = 80 }
|
|
||||||
},
|
|
||||||
RequestedTurn = 5
|
|
||||||
},
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
ItemId = "market-1",
|
|
||||||
Definition = new BuildingDefinition
|
|
||||||
{
|
|
||||||
Id = "market-1",
|
|
||||||
Name = "Market",
|
|
||||||
Description = "Provides ongoing gold income and supports trade.",
|
|
||||||
SourceId = "General",
|
|
||||||
Income = new ResourceAmounts { Gold = 40 },
|
|
||||||
Upkeep = new ResourceAmounts { Gold = 6 },
|
|
||||||
Cost = new ResourceAmounts { Gold = 180, Industry = 100 }
|
|
||||||
},
|
|
||||||
RequestedTurn = 12
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return CalculateBuildPlan(totalTurns, sampleRequests, GetDefaultStartingBuildings(),
|
|
||||||
new ResourceAmounts { Gold = 0 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft.AspNetCore": "Warning"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft.AspNetCore": "Warning"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"AllowedHosts": "*"
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
html, body {
|
|
||||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
a, .btn-link {
|
|
||||||
color: #006bb7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
color: #fff;
|
|
||||||
background-color: #1b6ec2;
|
|
||||||
border-color: #1861ac;
|
|
||||||
}
|
|
||||||
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
padding-top: 1.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.valid.modified:not([type=checkbox]) {
|
|
||||||
outline: 1px solid #26b050;
|
|
||||||
}
|
|
||||||
|
|
||||||
.invalid {
|
|
||||||
outline: 1px solid #e50000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.validation-message {
|
|
||||||
color: #e50000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.blazor-error-boundary {
|
|
||||||
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
|
|
||||||
padding: 1rem 1rem 1rem 3.7rem;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.blazor-error-boundary::after {
|
|
||||||
content: "An error has occurred."
|
|
||||||
}
|
|
||||||
|
|
||||||
.darker-border-checkbox.form-check-input {
|
|
||||||
border-color: #929292;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
|
|
||||||
color: var(--bs-secondary-color);
|
|
||||||
text-align: end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
|
|
||||||
text-align: start;
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
-5051
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,609 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Bootstrap Reboot v5.3.3 (https://getbootstrap.com/)
|
|
||||||
* Copyright 2011-2024 The Bootstrap Authors
|
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
||||||
*/
|
|
||||||
: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;
|
|
||||||
}
|
|
||||||
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
|
||||||
: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);
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: calc(1.375rem + 1.5vw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h1 {
|
|
||||||
font-size: 2.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: calc(1.325rem + 0.9vw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h2 {
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: calc(1.3rem + 0.6vw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h3 {
|
|
||||||
font-size: 1.75rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
font-size: calc(1.275rem + 0.3vw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h4 {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h5 {
|
|
||||||
font-size: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
h6 {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
address {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
font-style: normal;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol,
|
|
||||||
ul {
|
|
||||||
padding-left: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol,
|
|
||||||
ul,
|
|
||||||
dl {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol ol,
|
|
||||||
ul ul,
|
|
||||||
ol ul,
|
|
||||||
ul ol {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dt {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
dd {
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
|
||||||
margin: 0 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
b,
|
|
||||||
strong {
|
|
||||||
font-weight: bolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
small {
|
|
||||||
font-size: 0.875em;
|
|
||||||
}
|
|
||||||
|
|
||||||
mark {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub {
|
|
||||||
bottom: -0.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
sup {
|
|
||||||
top: -0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre,
|
|
||||||
code,
|
|
||||||
kbd,
|
|
||||||
samp {
|
|
||||||
font-family: var(--bs-font-monospace);
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
display: block;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
overflow: auto;
|
|
||||||
font-size: 0.875em;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre code {
|
|
||||||
font-size: inherit;
|
|
||||||
color: inherit;
|
|
||||||
word-break: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-size: 0.875em;
|
|
||||||
color: var(--bs-code-color);
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
a > code {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
kbd kbd {
|
|
||||||
padding: 0;
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
|
||||||
margin: 0 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
img,
|
|
||||||
svg {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
caption-side: bottom;
|
|
||||||
border-collapse: collapse;
|
|
||||||
}
|
|
||||||
|
|
||||||
caption {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
thead,
|
|
||||||
tbody,
|
|
||||||
tfoot,
|
|
||||||
tr,
|
|
||||||
td,
|
|
||||||
th {
|
|
||||||
border-color: inherit;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:focus:not(:focus-visible) {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input,
|
|
||||||
button,
|
|
||||||
select,
|
|
||||||
optgroup,
|
|
||||||
textarea {
|
|
||||||
margin: 0;
|
|
||||||
font-family: inherit;
|
|
||||||
font-size: inherit;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
|
||||||
select {
|
|
||||||
text-transform: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
[role=button] {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
word-wrap: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
select:disabled {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
|
||||||
[type=button],
|
|
||||||
[type=reset],
|
|
||||||
[type=submit] {
|
|
||||||
-webkit-appearance: button;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:not(:disabled),
|
|
||||||
[type=button]:not(:disabled),
|
|
||||||
[type=reset]:not(:disabled),
|
|
||||||
[type=submit]:not(:disabled) {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-moz-focus-inner {
|
|
||||||
padding: 0;
|
|
||||||
border-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
resize: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
legend {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
legend + * {
|
|
||||||
clear: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-datetime-edit-fields-wrapper,
|
|
||||||
::-webkit-datetime-edit-text,
|
|
||||||
::-webkit-datetime-edit-minute,
|
|
||||||
::-webkit-datetime-edit-hour-field,
|
|
||||||
::-webkit-datetime-edit-day-field,
|
|
||||||
::-webkit-datetime-edit-month-field,
|
|
||||||
::-webkit-datetime-edit-year-field {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-inner-spin-button {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
[type=search] {
|
|
||||||
-webkit-appearance: textfield;
|
|
||||||
outline-offset: -2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* rtl:raw:
|
|
||||||
[type="tel"],
|
|
||||||
[type="url"],
|
|
||||||
[type="email"],
|
|
||||||
[type="number"] {
|
|
||||||
direction: ltr;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
::-webkit-search-decoration {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-color-swatch-wrapper {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-file-upload-button {
|
|
||||||
font: inherit;
|
|
||||||
-webkit-appearance: button;
|
|
||||||
}
|
|
||||||
|
|
||||||
::file-selector-button {
|
|
||||||
font: inherit;
|
|
||||||
-webkit-appearance: button;
|
|
||||||
}
|
|
||||||
|
|
||||||
output {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
iframe {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
summary {
|
|
||||||
display: list-item;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
progress {
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
|
|
||||||
[hidden] {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,608 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Bootstrap Reboot v5.3.3 (https://getbootstrap.com/)
|
|
||||||
* Copyright 2011-2024 The Bootstrap Authors
|
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
||||||
*/
|
|
||||||
: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;
|
|
||||||
}
|
|
||||||
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
|
||||||
: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);
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: calc(1.375rem + 1.5vw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h1 {
|
|
||||||
font-size: 2.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: calc(1.325rem + 0.9vw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h2 {
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: calc(1.3rem + 0.6vw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h3 {
|
|
||||||
font-size: 1.75rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
font-size: calc(1.275rem + 0.3vw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h4 {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h5 {
|
|
||||||
font-size: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
h6 {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
address {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
font-style: normal;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol,
|
|
||||||
ul {
|
|
||||||
padding-right: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol,
|
|
||||||
ul,
|
|
||||||
dl {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol ol,
|
|
||||||
ul ul,
|
|
||||||
ol ul,
|
|
||||||
ul ol {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dt {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
dd {
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
|
||||||
margin: 0 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
b,
|
|
||||||
strong {
|
|
||||||
font-weight: bolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
small {
|
|
||||||
font-size: 0.875em;
|
|
||||||
}
|
|
||||||
|
|
||||||
mark {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub {
|
|
||||||
bottom: -0.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
sup {
|
|
||||||
top: -0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre,
|
|
||||||
code,
|
|
||||||
kbd,
|
|
||||||
samp {
|
|
||||||
font-family: var(--bs-font-monospace);
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
display: block;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
overflow: auto;
|
|
||||||
font-size: 0.875em;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre code {
|
|
||||||
font-size: inherit;
|
|
||||||
color: inherit;
|
|
||||||
word-break: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-size: 0.875em;
|
|
||||||
color: var(--bs-code-color);
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
a > code {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
kbd kbd {
|
|
||||||
padding: 0;
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
|
||||||
margin: 0 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
img,
|
|
||||||
svg {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
caption-side: bottom;
|
|
||||||
border-collapse: collapse;
|
|
||||||
}
|
|
||||||
|
|
||||||
caption {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
thead,
|
|
||||||
tbody,
|
|
||||||
tfoot,
|
|
||||||
tr,
|
|
||||||
td,
|
|
||||||
th {
|
|
||||||
border-color: inherit;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:focus:not(:focus-visible) {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input,
|
|
||||||
button,
|
|
||||||
select,
|
|
||||||
optgroup,
|
|
||||||
textarea {
|
|
||||||
margin: 0;
|
|
||||||
font-family: inherit;
|
|
||||||
font-size: inherit;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
|
||||||
select {
|
|
||||||
text-transform: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
[role=button] {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
word-wrap: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
select:disabled {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
|
||||||
[type=button],
|
|
||||||
[type=reset],
|
|
||||||
[type=submit] {
|
|
||||||
-webkit-appearance: button;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:not(:disabled),
|
|
||||||
[type=button]:not(:disabled),
|
|
||||||
[type=reset]:not(:disabled),
|
|
||||||
[type=submit]:not(:disabled) {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-moz-focus-inner {
|
|
||||||
padding: 0;
|
|
||||||
border-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
resize: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
legend {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
legend + * {
|
|
||||||
clear: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-datetime-edit-fields-wrapper,
|
|
||||||
::-webkit-datetime-edit-text,
|
|
||||||
::-webkit-datetime-edit-minute,
|
|
||||||
::-webkit-datetime-edit-hour-field,
|
|
||||||
::-webkit-datetime-edit-day-field,
|
|
||||||
::-webkit-datetime-edit-month-field,
|
|
||||||
::-webkit-datetime-edit-year-field {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-inner-spin-button {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
[type=search] {
|
|
||||||
-webkit-appearance: textfield;
|
|
||||||
outline-offset: -2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
[type="tel"],
|
|
||||||
[type="url"],
|
|
||||||
[type="email"],
|
|
||||||
[type="number"] {
|
|
||||||
direction: ltr;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-search-decoration {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-color-swatch-wrapper {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-file-upload-button {
|
|
||||||
font: inherit;
|
|
||||||
-webkit-appearance: button;
|
|
||||||
}
|
|
||||||
|
|
||||||
::file-selector-button {
|
|
||||||
font: inherit;
|
|
||||||
-webkit-appearance: button;
|
|
||||||
}
|
|
||||||
|
|
||||||
output {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
iframe {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
summary {
|
|
||||||
display: list-item;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
progress {
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
|
|
||||||
[hidden] {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-13721
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-13705
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-6510
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-4636
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-4684
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user