Vibe documents

This commit is contained in:
6d486f49
2026-06-23 13:30:43 -04:00
parent 6eaf7b0980
commit 89bd1ca1f9
92 changed files with 69503 additions and 67 deletions
+83
View File
@@ -197,6 +197,78 @@ deckWriter.WriteLine(" ];");
deckWriter.WriteLine("}"); deckWriter.WriteLine("}");
Console.WriteLine($"Generated {decks.Count} decks in {deckGeneratedFile}"); Console.WriteLine($"Generated {decks.Count} decks in {deckGeneratedFile}");
// ── Docs ──
var excludedCategories = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"Agent", "Immortalized", "Spell", "Token", "Decks", "Deck"
};
var docs = new List<DocData>();
foreach (var file in mdFiles)
{
var content = Encoding.UTF8.GetString(File.ReadAllBytes(file));
Dictionary<string, string> yaml = [];
var body = content;
if (content.StartsWith("---"))
{
var endIndex = content.IndexOf("---", 3, StringComparison.Ordinal);
if (endIndex >= 0)
{
var frontmatter = content[3..endIndex].Trim().Replace("\r\n", "\n").Replace("\r", "\n");
yaml = ParseYaml(frontmatter);
body = content[(endIndex + 3)..].Trim();
}
}
var category = yaml.GetValueOrDefault("category") ?? Path.GetFileName(Path.GetDirectoryName(file)) ?? "";
if (excludedCategories.Contains(category)) continue;
// Also exclude files that look like base templates
var fileName = Path.GetFileName(file);
if (fileName.StartsWith("_")) continue;
docs.Add(new DocData
{
Title = Path.GetFileNameWithoutExtension(file),
Category = category,
Content = body,
Frontmatter = yaml
});
}
var docGeneratedFile = Path.Combine(repoRoot, "Chrono", "Shared", "Generated", "Docs.g.cs");
Directory.CreateDirectory(Path.GetDirectoryName(docGeneratedFile)!);
using var docWriter = new StreamWriter(docGeneratedFile, false, Encoding.UTF8);
docWriter.WriteLine("// <auto-generated/>");
docWriter.WriteLine("#nullable enable");
docWriter.WriteLine();
docWriter.WriteLine("namespace Chrono.Model;");
docWriter.WriteLine();
docWriter.WriteLine("public static class DocDatabase");
docWriter.WriteLine("{");
docWriter.WriteLine(" public static readonly System.Collections.Generic.List<DocData> Docs =");
docWriter.WriteLine(" [");
for (var i = 0; i < docs.Count; i++)
{
var d = docs[i];
docWriter.WriteLine(" new()");
docWriter.WriteLine(" {");
WriteProp(docWriter, "Title", d.Title, 3);
WriteProp(docWriter, "Category", d.Category, 3);
WriteStrProp(docWriter, "Content", d.Content, 3);
WriteDictProp(docWriter, "Frontmatter", d.Frontmatter, 3);
var comma = i < docs.Count - 1 ? "," : "";
docWriter.WriteLine($" }}{comma}");
}
docWriter.WriteLine(" ];");
docWriter.WriteLine("}");
Console.WriteLine($"Generated {docs.Count} docs in {docGeneratedFile}");
return 0; return 0;
// --- Helpers --- // --- Helpers ---
@@ -419,6 +491,17 @@ static void WriteListProp(StreamWriter w, string name, List<string>? values, int
w.WriteLine($"{pad}],"); w.WriteLine($"{pad}],");
} }
static void WriteDictProp(StreamWriter w, string name, Dictionary<string, string>? values, int indent)
{
if (values == null || values.Count == 0) return;
var pad = new string(' ', indent * 4);
w.WriteLine($"{pad}{name} = new()");
w.WriteLine($"{pad}{{");
foreach (var (k, v) in values)
w.WriteLine($"{pad} {{ {ToLiteral(k)}, {ToLiteral(v)} }},");
w.WriteLine($"{pad}}},");
}
static string ToLiteral(string? s) static string ToLiteral(string? s)
{ {
if (s == null) return "null"; if (s == null) return "null";
+9
View File
@@ -0,0 +1,9 @@
namespace Chrono.Model;
public class DocData
{
public string Title { get; init; } = "";
public string Category { get; init; } = "";
public string Content { get; init; } = "";
public System.Collections.Generic.Dictionary<string, string> Frontmatter { get; init; } = [];
}
+27
View File
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>Chrono CCG</title>
<base href="/"/>
<link href="https://fonts.googleapis.com" rel="preconnect"/>
<link crossorigin href="https://fonts.gstatic.com" rel="preconnect"/>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"/>
<link href="/lib/bootstrap-icons/bootstrap-icons.min.css" rel="stylesheet"/>
<link href="/lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="/_content/Telerik.UI.for.Blazor/css/kendo-theme-bootstrap/all.css" rel="stylesheet"/>
<link href="/css/app.css" rel="stylesheet"/>
<link href="/_content/Shared/Shared.styles.css" rel="stylesheet"/>
<script defer src="/_content/Telerik.UI.for.Blazor/js/telerik-blazor.js"></script>
<link href="/favicon.png" rel="icon" type="image/png"/>
<HeadOutlet/>
</head>
<body>
<Routes/>
<script src="_framework/blazor.web.js"></script>
</body>
</html>
+6
View File
@@ -0,0 +1,6 @@
<Router AppAssembly="@typeof(Program).Assembly" AdditionalAssemblies="new[] { typeof(Shared.Pages.Home).Assembly }" NotFoundPage="typeof(NotFound)">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
</Found>
</Router>
+13
View File
@@ -0,0 +1,13 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Chrono.Model
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using Shared.Layout
@using Shared.Pages
@using Telerik.Blazor
@using Telerik.Blazor.Components
@using Telerik.DataSource
+8 -13
View File
@@ -2,11 +2,10 @@ using Microsoft.EntityFrameworkCore;
using Server; using Server;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseStaticWebAssets();
// Add services to the container. builder.Services.AddControllers();
builder.Services.AddControllersWithViews(); builder.Services.AddEndpointsApiExplorer();
builder.Services.AddRazorPages(); builder.Services.AddRazorComponents().AddInteractiveServerComponents();
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<AppDbContext>(options => builder.Services.AddDbContext<AppDbContext>(options =>
@@ -31,19 +30,15 @@ using (var scope = app.Services.CreateScope())
} }
} }
// Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment())
if (app.Environment.IsDevelopment()) {
app.UseWebAssemblyDebugging();
else
app.UseExceptionHandler("/Error"); app.UseExceptionHandler("/Error");
}
app.UseBlazorFrameworkFiles();
app.UseStaticFiles(); app.UseStaticFiles();
app.UseAntiforgery();
app.UseRouting();
app.MapRazorPages();
app.MapControllers(); app.MapControllers();
app.MapFallbackToFile("index.html"); app.MapRazorComponents<Server.Components.App>().AddInteractiveServerRenderMode();
app.Run(); app.Run();
+1 -2
View File
@@ -1,12 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\Shared.csproj"/>
<ProjectReference Include="..\Model\Model.csproj"/> <ProjectReference Include="..\Model\Model.csproj"/>
<ProjectReference Include="..\Web\Web.csproj"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.9"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.9"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.9">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
+283
View File
@@ -0,0 +1,283 @@
:root {
--bg-primary: #0b0b1a;
--bg-surface: #141428;
--bg-elevated: #1c1c3a;
--bg-hover: #252548;
--text-primary: #e8e8f0;
--text-secondary: #9898b8;
--text-muted: #686888;
--accent: #6c63ff;
--accent-rgb: 108, 99, 255;
--accent-glow: rgba(108, 99, 255, 0.3);
--gold: #ffd700;
--gold-glow: rgba(255, 215, 0, 0.4);
--border: #2a2a4a;
--radius: 10px;
--radius-sm: 6px;
--shadow: 0 4px 24px rgba(0, 0, 0, 0.3);
--transition: 0.2s ease;
}
* {
scrollbar-width: thin;
scrollbar-color: #2a2a4a transparent;
}
::-webkit-scrollbar {
width: 5px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: #2a2a4a;
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: #3a3a5a;
}
html, body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
min-height: 100vh;
}
h1, h2, h3, h4, h5, h6 {
font-weight: 700;
letter-spacing: -0.02em;
}
h1 {
font-size: 2rem;
background: linear-gradient(135deg, #e8e8f0 0%, #6c63ff 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
a, .btn-link {
color: var(--accent);
}
.btn-primary {
background: var(--accent);
border-color: var(--accent);
}
.btn-primary:hover {
background: #7b73ff;
border-color: #7b73ff;
}
.btn-outline-secondary {
color: var(--text-secondary);
border-color: var(--border);
}
.btn-outline-secondary:hover {
background: var(--bg-hover);
border-color: var(--accent);
color: var(--text-primary);
}
.form-control, .form-select {
background: var(--bg-surface);
border-color: var(--border);
color: var(--text-primary);
border-radius: var(--radius-sm);
font-size: 0.9rem;
}
.form-control:focus, .form-select:focus {
background: var(--bg-elevated);
border-color: var(--accent);
color: var(--text-primary);
box-shadow: 0 0 0 0.2rem var(--accent-glow);
}
.form-control::placeholder {
color: var(--text-muted);
}
.content {
padding-top: 1.5rem;
}
.sidebar {
background-image: linear-gradient(180deg, #0d0d2b 0%, #1a0a2e 70%) !important;
}
.alert-info {
background: var(--bg-surface);
border-color: var(--border);
color: var(--text-secondary);
}
/* ── Loading Screen ── */
.loading-screen {
position: fixed;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: radial-gradient(ellipse at center, #141428 0%, #0b0b1a 100%);
gap: 0.75rem;
z-index: 9999;
}
.loading-content {
position: relative;
width: 5rem;
height: 5rem;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 0.5rem;
}
.loading-ring {
width: 100%;
height: 100%;
transform: rotate(-90deg);
position: absolute;
}
.ring-track {
fill: none;
stroke: var(--border);
stroke-width: 5;
}
.ring-fill {
fill: none;
stroke: var(--accent);
stroke-width: 5;
stroke-linecap: round;
stroke-dasharray: 263.9;
stroke-dashoffset: calc(263.9 - (263.9 * var(--blazor-load-percentage, 0%)) / 100);
transition: stroke-dashoffset 0.2s ease;
filter: drop-shadow(0 0 6px var(--accent-glow));
}
.loading-icon {
font-size: 1.5rem;
color: var(--accent);
animation: loading-pulse 1.5s ease-in-out infinite;
z-index: 1;
}
@keyframes loading-pulse {
0%, 100% {
transform: scale(1);
opacity: 0.7;
}
50% {
transform: scale(1.15);
opacity: 1;
}
}
.loading-title {
font-size: 1.4rem;
font-weight: 700;
margin: 0;
letter-spacing: -0.02em;
background: linear-gradient(135deg, #e8e8f0 0%, #6c63ff 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.loading-subtitle {
font-size: 0.8rem;
color: var(--text-muted);
margin: 0;
letter-spacing: 0.15em;
text-transform: uppercase;
}
.loading-bar {
width: 12rem;
margin-top: 0.5rem;
}
.loading-bar-track {
width: 100%;
height: 3px;
background: var(--border);
border-radius: 2px;
overflow: hidden;
}
.loading-bar-fill {
height: 100%;
width: calc(var(--blazor-load-percentage, 0%));
background: linear-gradient(90deg, var(--accent), #8b83ff);
border-radius: 2px;
transition: width 0.2s ease;
}
.loading-status {
font-size: 0.8rem;
color: var(--text-muted);
margin: 0;
}
.loading-status::after {
content: var(--blazor-load-percentage-text, "Loading...");
}
.card-detail .detail-field.note {
margin-top: 1.5rem;
padding-top: 1.5rem;
border-top: 1px solid var(--border);
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.note-input {
min-height: 100px;
resize: vertical;
background: var(--bg-primary);
border: 1px solid var(--border);
}
.saving-indicator {
font-size: 0.75rem;
color: var(--text-muted);
font-style: italic;
align-self: flex-end;
}
.inline-card-btn {
background: none;
border: none;
padding: 0 2px;
color: var(--accent);
font-weight: 500;
text-decoration: none;
border-bottom: 1px dashed var(--accent);
cursor: pointer;
transition: all var(--transition);
display: inline;
font-size: inherit;
font-family: inherit;
border-radius: 2px;
}
.inline-card-btn:hover {
color: var(--accent-light, #60a5fa);
border-bottom-style: solid;
background-color: rgba(var(--accent-rgb, 59, 130, 246), 0.1);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

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
@@ -0,0 +1,609 @@
/*!
* 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
@@ -0,0 +1,608 @@
/*!
* 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
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
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
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
+174 -9
View File
@@ -7,6 +7,38 @@ public static class CardDatabase
{ {
public static readonly System.Collections.Generic.List<CardData> Cards = public static readonly System.Collections.Generic.List<CardData> Cards =
[ [
new()
{
Name = "Core Charges",
Category = "Currency",
Description = "Earnable currency, can be used to buy packs.",
Archetypes = [
],
},
new()
{
Name = "Crystals",
Category = "Currency",
Description = "Premium currency, can be used to buy packs and cosmetics.",
Archetypes = [
],
},
new()
{
Name = "Draft Ticket",
Category = "Currency",
Description = "Spend to participate in a draft.",
Archetypes = [
],
},
new()
{
Name = "Flux",
Category = "Currency",
Description = "Can be used to craft cards via wildcards.",
Archetypes = [
],
},
new() new()
{ {
Name = "Bleed", Name = "Bleed",
@@ -298,6 +330,69 @@ public static class CardDatabase
], ],
}, },
new() new()
{
Name = "Daily Wins",
Category = "Quest",
Archetypes = [
],
},
new()
{
Name = "Deal 200 Damage",
Category = "Quest",
Description = "",
Archetypes = [
],
},
new()
{
Name = "Deal 30 Damage with Overpower Agents",
Category = "Quest",
Description = "",
Archetypes = [
],
},
new()
{
Name = "Deal 50 Damage with Specific Faction",
Category = "Quest",
Description = "",
Archetypes = [
],
},
new()
{
Name = "Deplete 10 Agents",
Category = "Quest",
Description = "",
Archetypes = [
],
},
new()
{
Name = "Erase 7 Cards",
Category = "Quest",
Description = "",
Archetypes = [
],
},
new()
{
Name = "Overflow 10 Times",
Category = "Quest",
Description = "",
Archetypes = [
],
},
new()
{
Name = "Weekly Wins",
Category = "Quest",
Description = "",
Archetypes = [
],
},
new()
{ {
Name = "Agents", Name = "Agents",
Category = "Redirect", Category = "Redirect",
@@ -335,6 +430,22 @@ public static class CardDatabase
], ],
}, },
new() new()
{
Name = "Fast",
Category = "Rule",
Description = "This spell can be reacted to.",
Archetypes = [
],
},
new()
{
Name = "Immediate",
Category = "Rule",
Description = "This spell cannot be reacted to.",
Archetypes = [
],
},
new()
{ {
Name = "Round End", Name = "Round End",
Category = "Rule", Category = "Rule",
@@ -343,6 +454,14 @@ public static class CardDatabase
], ],
}, },
new() new()
{
Name = "Slow",
Category = "Rule",
Description = "This spell cannot be used as a reaction to something on the Chain.",
Archetypes = [
],
},
new()
{ {
Name = "Core Set", Name = "Core Set",
Category = "Set", Category = "Set",
@@ -351,25 +470,71 @@ public static class CardDatabase
}, },
new() new()
{ {
Name = "Fast", Name = "Card Backs",
Category = "Speed", Category = "Store",
Description = "This spell can be reacted to.",
Archetypes = [ Archetypes = [
], ],
}, },
new() new()
{ {
Name = "Immediate", Name = "Common",
Category = "Speed", Category = "Store",
Description = "This spell cannot be reacted to.",
Archetypes = [ Archetypes = [
], ],
}, },
new() new()
{ {
Name = "Slow", Name = "Core Set Packs x1",
Category = "Speed", Category = "Store",
Description = "This spell cannot be used as a reaction to something on the Chain.", Archetypes = [
],
},
new()
{
Name = "Core Set Packs x10",
Category = "Store",
Archetypes = [
],
},
new()
{
Name = "Core Set Packs x5",
Category = "Store",
Archetypes = [
],
},
new()
{
Name = "Core Set Packs x50",
Category = "Store",
Archetypes = [
],
},
new()
{
Name = "Divergent",
Category = "Store",
Archetypes = [
],
},
new()
{
Name = "Lost",
Category = "Store",
Archetypes = [
],
},
new()
{
Name = "Rare",
Category = "Store",
Archetypes = [
],
},
new()
{
Name = "Text Emote",
Category = "Store",
Archetypes = [ Archetypes = [
], ],
}, },
+862
View File
@@ -0,0 +1,862 @@
// <auto-generated/>
#nullable enable
namespace Chrono.Model;
public static class DocDatabase
{
public static readonly System.Collections.Generic.List<DocData> Docs =
[
new()
{
Title = "Core Charges",
Category = "Currency",
Content = "",
Frontmatter = new()
{
{ "category", "Currency" },
{ "description", "Earnable currency, can be used to buy packs." },
},
},
new()
{
Title = "Crystals",
Category = "Currency",
Content = "",
Frontmatter = new()
{
{ "category", "Currency" },
{ "description", "Premium currency, can be used to buy packs and cosmetics." },
},
},
new()
{
Title = "Draft Ticket",
Category = "Currency",
Content = "",
Frontmatter = new()
{
{ "category", "Currency" },
{ "description", "Spend to participate in a draft." },
},
},
new()
{
Title = "Flux",
Category = "Currency",
Content = "",
Frontmatter = new()
{
{ "category", "Currency" },
{ "description", "Can be used to craft cards via wildcards." },
},
},
new()
{
Title = "Bleed",
Category = "Debuff",
Content = "",
Frontmatter = new()
{
{ "category", "Debuff" },
{ "description", "This Agent takes X damage at Round End." },
},
},
new()
{
Title = "Decay",
Category = "Debuff",
Content = "",
Frontmatter = new()
{
{ "category", "Debuff" },
{ "description", "Grant this Agent -1/-1." },
},
},
new()
{
Title = "Delay",
Category = "Debuff",
Content = "",
Frontmatter = new()
{
{ "category", "Debuff" },
{ "description", "This Agent always Strikes after its opponent in combat. Replaces Blitz." },
},
},
new()
{
Title = "Disarm",
Category = "Debuff",
Content = "Reduce attack to zero.",
Frontmatter = new()
{
{ "category", "Debuff" },
{ "description", "Set this Agent's strength to 0 until Round End." },
},
},
new()
{
Title = "Erase",
Category = "Debuff",
Content = "",
Frontmatter = new()
{
{ "category", "Debuff" },
{ "description", "Remove this card from the game." },
},
},
new()
{
Title = "Exposed",
Category = "Debuff",
Content = "",
Frontmatter = new()
{
{ "category", "Debuff" },
{ "description", "This Agent may be chosen as a blocker by enemy Agents when confirming their attack." },
},
},
new()
{
Title = "Mute",
Category = "Debuff",
Content = "",
Frontmatter = new()
{
{ "category", "Debuff" },
{ "description", "Remove all text as well as any Strength/Durability changes from this Agent. Muted Agents have no name." },
},
},
new()
{
Title = "Temporary",
Category = "Debuff",
Content = "",
Frontmatter = new()
{
{ "category", "Debuff" },
{ "description", "This Agent is destroyed at Round End or when it Strikes." },
},
},
new()
{
Title = "Transient",
Category = "Debuff",
Content = "",
Frontmatter = new()
{
{ "category", "Debuff" },
{ "description", "This card in hand is Discarded at Round End." },
},
},
new()
{
Title = "Lifeblood",
Category = "Faction",
Content = "Concepts:\n- Wide Boards\n- Overpower",
Frontmatter = new()
{
{ "category", "Faction" },
},
},
new()
{
Title = "Phasetide",
Category = "Faction",
Content = "Concepts:\n- Healing\n-",
Frontmatter = new()
{
{ "category", "Faction" },
},
},
new()
{
Title = "Silence",
Category = "Faction",
Content = "Concepts:\n- Activatable Agents\n-",
Frontmatter = new()
{
{ "category", "Faction" },
},
},
new()
{
Title = "Singularity",
Category = "Faction",
Content = "Concepts:\n- Discard",
Frontmatter = new()
{
{ "category", "Faction" },
},
},
new()
{
Title = "Splintergleam",
Category = "Faction",
Content = "Concepts:\n- Self Damage\n- Bleed\n-",
Frontmatter = new()
{
{ "category", "Faction" },
},
},
new()
{
Title = "Sungrace",
Category = "Faction",
Content = "Concepts:\n- Ramp\n- Using and Replenishing Reserved Energy\n-",
Frontmatter = new()
{
{ "category", "Faction" },
},
},
new()
{
Title = "Blitz",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "When attack, this Agent strikes before its blocker. Replaces [[Delay]]." },
},
},
new()
{
Title = "Breakdown",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "When your Core has X or less Durability remaining this effect triggers." },
},
},
new()
{
Title = "Cleave",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "When Striking a blocker, this Agent also Strikes Agents to the left and right of its blocker at the same time." },
},
},
new()
{
Title = "Confront",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "This Agent may choose an enemy Agent to block it when confirming their attack." },
},
},
new()
{
Title = "Draw",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "Place the card from the top of your deck into your hand." },
},
},
new()
{
Title = "Evasive",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "This Agent may only be blocker by other Evasive Agents." },
},
},
new()
{
Title = "Fervor",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "When this Agent survives damage, grant it +1/+1." },
},
},
new()
{
Title = "Flourish",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "Grant this Agent +1/+1." },
},
},
new()
{
Title = "Heal",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "Increase the Durability of the Agent or Core being healed by this amount. Agents being healed cannot exceed their maximum Durability. Cores have no maximum Durability and can be healed any amount." },
},
},
new()
{
Title = "Overpower",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "Excess damage beyond the Durability of this Agent's blocker is dealt directly to the enemy core." },
},
},
new()
{
Title = "Phase",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "A [[Phased]] [[Agent]] is treated as removed from play for the round, though it still occupies its board-space. At the start of the next round this unit Phases in and is in the exact same state as it Phased out. Phasing back in does not trigger Enter effects." },
},
},
new()
{
Title = "Phased",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "Triggered when this [[Agent]] has been affected by [[Phase]]." },
},
},
new()
{
Title = "Refresh",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "Remove the Depleted status." },
},
},
new()
{
Title = "Rejuvenate",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "At Round Start heal this Agent to full Durability." },
},
},
new()
{
Title = "Revive",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "Return from the Graveyard to play." },
},
},
new()
{
Title = "Rewind",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "Return this [[Agent]] to its owner's hand." },
},
},
new()
{
Title = "Rewound",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "Triggered when this [[Agent]] has been affected by [[Rewind]]." },
},
},
new()
{
Title = "Shift",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "Timeline is changed to the indicated Timeline." },
},
},
new()
{
Title = "Siphon",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "When an Agent strikes or an Action, Effect, or Timeline with the Siphon icon deals damage, heal your Core that amount." },
},
},
new()
{
Title = "Sprout",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "Create X 1/1 Seedling Tokens. If your board is full, grant your weakest Seedling +1|+1 instead." },
},
},
new()
{
Title = "Surge",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "Gain an attack token if you dont already have one." },
},
},
new()
{
Title = "Transient",
Category = "Keyword",
Content = "",
Frontmatter = new()
{
{ "category", "Keyword" },
{ "description", "This card in hand is [[Discarded]] at [[Round End]]." },
},
},
new()
{
Title = "Daily Wins",
Category = "Quest",
Content = "",
Frontmatter = new()
{
{ "category", "Quest" },
},
},
new()
{
Title = "Deal 200 Damage",
Category = "Quest",
Content = "",
Frontmatter = new()
{
{ "category", "Quest" },
{ "description", "" },
},
},
new()
{
Title = "Deal 30 Damage with Overpower Agents",
Category = "Quest",
Content = "",
Frontmatter = new()
{
{ "category", "Quest" },
{ "description", "" },
},
},
new()
{
Title = "Deal 50 Damage with Specific Faction",
Category = "Quest",
Content = "",
Frontmatter = new()
{
{ "category", "Quest" },
{ "description", "" },
},
},
new()
{
Title = "Deplete 10 Agents",
Category = "Quest",
Content = "",
Frontmatter = new()
{
{ "category", "Quest" },
{ "description", "" },
},
},
new()
{
Title = "Erase 7 Cards",
Category = "Quest",
Content = "",
Frontmatter = new()
{
{ "category", "Quest" },
{ "description", "" },
},
},
new()
{
Title = "Overflow 10 Times",
Category = "Quest",
Content = "",
Frontmatter = new()
{
{ "category", "Quest" },
{ "description", "" },
{ "codeCharges", "" },
{ "exp", "" },
},
},
new()
{
Title = "Weekly Wins",
Category = "Quest",
Content = "",
Frontmatter = new()
{
{ "category", "Quest" },
{ "description", "" },
},
},
new()
{
Title = "Agents",
Category = "Redirect",
Content = "",
Frontmatter = new()
{
{ "category", "Redirect" },
{ "see", "\"[[Agent]]\"" },
},
},
new()
{
Title = "Cores",
Category = "Redirect",
Content = "",
Frontmatter = new()
{
{ "category", "Redirect" },
{ "see", "\"[[Core]]\"" },
},
},
new()
{
Title = "Chain",
Category = "Rule",
Content = "",
Frontmatter = new()
{
{ "category", "Rule" },
{ "description", "Effects are stacked until they are able to be resolved. This enables [[Immediate]] and [[Fast]] reactions to be added onto the stack for reactive gameplay." },
},
},
new()
{
Title = "Core",
Category = "Rule",
Content = "",
Frontmatter = new()
{
{ "category", "Rule" },
},
},
new()
{
Title = "Discarded",
Category = "Rule",
Content = "",
Frontmatter = new()
{
{ "category", "Rule" },
{ "description", "Remove this card from your hand." },
},
},
new()
{
Title = "Fast",
Category = "Rule",
Content = "",
Frontmatter = new()
{
{ "category", "Rule" },
{ "description", "This spell can be reacted to." },
},
},
new()
{
Title = "Immediate",
Category = "Rule",
Content = "",
Frontmatter = new()
{
{ "category", "Rule" },
{ "description", "This spell cannot be reacted to." },
},
},
new()
{
Title = "Round End",
Category = "Rule",
Content = "",
Frontmatter = new()
{
{ "category", "Rule" },
{ "description", "The end state of the round. Triggered when both players end there turns without action." },
},
},
new()
{
Title = "Slow",
Category = "Rule",
Content = "",
Frontmatter = new()
{
{ "category", "Rule" },
{ "description", "This spell cannot be used as a reaction to something on the [[Chain]]." },
},
},
new()
{
Title = "Core Set",
Category = "Set",
Content = "",
Frontmatter = new()
{
{ "category", "Set" },
},
},
new()
{
Title = "Card Backs",
Category = "Store",
Content = "",
Frontmatter = new()
{
{ "category", "Store" },
{ "essencePrice", "" },
{ "crytalPrice", "\"1450\"" },
},
},
new()
{
Title = "Common",
Category = "Store",
Content = "",
Frontmatter = new()
{
{ "category", "Store" },
{ "essencePrice", "25" },
},
},
new()
{
Title = "Core Set Packs x1",
Category = "Store",
Content = "",
Frontmatter = new()
{
{ "category", "Store" },
{ "crytalPrice", "\"450\"" },
{ "coreChargesPrice", "\"120\"" },
{ "essencePrice", "" },
{ "pricePerPack", "\"450\"" },
},
},
new()
{
Title = "Core Set Packs x10",
Category = "Store",
Content = "",
Frontmatter = new()
{
{ "category", "Store" },
{ "crytalPrice", "\"3900\"" },
{ "coreChargesPrice", "\"1200\"" },
{ "essencePrice", "" },
{ "pricePerPack", "\"390\"" },
},
},
new()
{
Title = "Core Set Packs x5",
Category = "Store",
Content = "",
Frontmatter = new()
{
{ "category", "Store" },
{ "crytalPrice", "\"2100\"" },
{ "coreChargesPrice", "\"600\"" },
{ "essencePrice", "" },
{ "pricePerPack", "\"420\"" },
},
},
new()
{
Title = "Core Set Packs x50",
Category = "Store",
Content = "",
Frontmatter = new()
{
{ "category", "Store" },
{ "essencePrice", "" },
{ "crytalPrice", "\"18000\"" },
{ "coreChargesPrice", "\"6000\"" },
{ "pricePerPack", "\"360\"" },
},
},
new()
{
Title = "Divergent",
Category = "Store",
Content = "",
Frontmatter = new()
{
{ "category", "Store" },
{ "essencePrice", "200" },
},
},
new()
{
Title = "Lost",
Category = "Store",
Content = "",
Frontmatter = new()
{
{ "category", "Store" },
{ "currency", "essence" },
{ "essencePrice", "400" },
},
},
new()
{
Title = "Rare",
Category = "Store",
Content = "",
Frontmatter = new()
{
{ "category", "Store" },
{ "essencePrice", "75" },
},
},
new()
{
Title = "Text Emote",
Category = "Store",
Content = "",
Frontmatter = new()
{
{ "category", "Store" },
{ "essencePrice", "" },
{ "crytalPrice", "\"450\"" },
},
},
new()
{
Title = "Deadly Fauna",
Category = "Timeline",
Content = "",
Frontmatter = new()
{
{ "category", "Timeline" },
{ "description", "All Agents have [[Overpower]]." },
{ "faction", "\"[[Lifeblood]]\"" },
},
},
new()
{
Title = "The One True Timeline",
Category = "Timeline",
Content = "",
Frontmatter = new()
{
{ "category", "Timeline" },
{ "description", "\"Round Start: Heal all [[Agents]] and [[Cores]] 1.\"" },
{ "faction", "\"[[Phasetide]]\"" },
},
},
new()
{
Title = "Voiceless Sky",
Category = "Timeline",
Content = "",
Frontmatter = new()
{
{ "category", "Timeline" },
{ "description", "If a player has exactly one Agent, it has +3/+3." },
{ "faction", "\"[[Silence]]\"" },
},
},
new()
{
Title = "Erudite Beacon",
Category = "Timeline",
Content = "",
Frontmatter = new()
{
{ "category", "Timeline" },
{ "description", "\"When you Shift here, draw 1. Round Start: Players draw 1.\"" },
{ "faction", "\"[[Singularity]]\"" },
},
},
new()
{
Title = "Torment",
Category = "Timeline",
Content = "",
Frontmatter = new()
{
{ "category", "Timeline" },
{ "description", "All Agents and Cores have Bleed 1." },
{ "faction", "\"[[Splintergleam]]\"" },
},
},
new()
{
Title = "Volcanic Rivers",
Category = "Timeline",
Content = "",
Frontmatter = new()
{
{ "category", "Timeline" },
{ "description", "When you Shift here, deal 1 to both Cores." },
{ "faction", "\"[[Splintergleam]]\"" },
},
},
new()
{
Title = "Star Siphon",
Category = "Timeline",
Content = "",
Frontmatter = new()
{
{ "category", "Timeline" },
{ "description", "\" Round End: Refill all Energy Reserves.\"" },
{ "faction", "\"[[Sungrace]]\"" },
},
}
];
}
+5
View File
@@ -33,6 +33,11 @@
<i class="bi bi-journal-text nav-icon"></i> Decks <i class="bi bi-journal-text nav-icon"></i> Decks
</NavLink> </NavLink>
</div> </div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="docs">
<i class="bi bi-book-fill nav-icon"></i> Docs
</NavLink>
</div>
</nav> </nav>
</div> </div>
+237
View File
@@ -0,0 +1,237 @@
@namespace Shared.Pages
@page "/docs"
<PageTitle>Docs</PageTitle>
<div class="docs-page">
<div class="docs-header">
<h1>Documentation</h1>
<p class="text-muted">Rules, keywords, factions, and more.</p>
</div>
<div class="docs-container">
<aside class="docs-sidebar">
<div class="search-box">
<i class="bi bi-search"></i>
<input type="text" placeholder="Search docs..." @bind="searchQuery" @bind:event="oninput" />
</div>
<div class="category-list">
<div class="category-item @(selectedCategory == null ? "active" : "")" @onclick="() => SelectCategory(null)">
All Pages
</div>
@foreach (var category in categories)
{
var cat = category;
<div class="category-item @(selectedCategory == cat ? "active" : "")" @onclick="() => SelectCategory(cat)">
@cat
</div>
}
</div>
</aside>
<main class="docs-content">
@if (selectedDoc == null)
{
<div class="doc-list">
@foreach (var doc in filteredDocs)
{
<div class="doc-card" @onclick="() => SelectDoc(doc)">
<div class="doc-card-category">@doc.Category</div>
<h3 class="doc-card-title">@doc.Title</h3>
@{
var desc = GetDescription(doc);
}
@if (desc != null)
{
<p class="doc-card-desc">@desc</p>
}
</div>
}
@if (!filteredDocs.Any())
{
<div class="empty-state">
<i class="bi bi-search"></i>
<p>No documentation found matching your search.</p>
</div>
}
</div>
}
else
{
<article class="doc-article">
<button class="btn-back" @onclick="() => SelectDoc(null)">
<i class="bi bi-arrow-left"></i> Back to list
</button>
<header class="doc-header">
<div class="doc-meta">@selectedDoc.Category</div>
<h1>@selectedDoc.Title</h1>
@{
var desc = GetDescription(selectedDoc);
}
@if (desc != null)
{
<p class="doc-description">@desc</p>
}
</header>
@if (!string.IsNullOrWhiteSpace(selectedDoc.Content))
{
<div class="doc-body">
@((MarkupString)FormatContent(selectedDoc.Content))
</div>
}
@if (HasExtraFrontmatter(selectedDoc))
{
<div class="doc-extra">
<h3>Details</h3>
<div class="doc-frontmatter">
@foreach (var kvp in selectedDoc.Frontmatter.Where(kvp => kvp.Key != "category" && kvp.Key != "description"))
{
<div class="fm-item">
<span class="fm-key">@kvp.Key</span>
<span class="fm-value">@kvp.Value</span>
</div>
}
</div>
</div>
}
</article>
}
</main>
</div>
</div>
@code {
private string searchQuery = "";
private string? selectedCategory;
private DocData? selectedDoc;
private List<string> categories = [];
private List<DocData> allDocs = [];
protected override void OnInitialized()
{
allDocs = DocDatabase.Docs.OrderBy(d => d.Category).ThenBy(d => d.Title).ToList();
categories = allDocs.Select(d => d.Category).Distinct().OrderBy(c => c).ToList();
}
private IEnumerable<DocData> filteredDocs => allDocs
.Where(d => (selectedCategory == null || d.Category == selectedCategory) &&
(string.IsNullOrWhiteSpace(searchQuery) ||
d.Title.Contains(searchQuery, StringComparison.OrdinalIgnoreCase) ||
(GetDescription(d)?.Contains(searchQuery, StringComparison.OrdinalIgnoreCase) ?? false) ||
d.Content.Contains(searchQuery, StringComparison.OrdinalIgnoreCase)));
private void SelectCategory(string? category)
{
selectedCategory = category;
selectedDoc = null;
}
private void SelectDoc(DocData? doc)
{
selectedDoc = doc;
}
private static string? GetDescription(DocData doc)
{
return doc.Frontmatter.TryGetValue("description", out var desc) && !string.IsNullOrWhiteSpace(desc) ? desc : null;
}
private static bool HasExtraFrontmatter(DocData doc)
{
var count = doc.Frontmatter.Count;
if (count == 0) return false;
if (count == 1 && doc.Frontmatter.ContainsKey("category")) return false;
if (count == 2 && doc.Frontmatter.ContainsKey("category") && doc.Frontmatter.ContainsKey("description")) return false;
return doc.Frontmatter.Any(kvp => kvp.Key != "category" && kvp.Key != "description");
}
private string FormatContent(string content)
{
if (string.IsNullOrWhiteSpace(content)) return "";
var lines = content.Replace("\r\n", "\n").Split('\n');
var html = new System.Text.StringBuilder();
var inList = false;
foreach (var rawLine in lines)
{
var line = rawLine.TrimEnd();
if (string.IsNullOrWhiteSpace(line))
{
if (inList) { html.AppendLine("</ul>"); inList = false; }
continue;
}
if (line.StartsWith("- "))
{
var item = line[2..].Trim();
if (item.Length > 0)
{
if (!inList) { html.AppendLine("<ul class=\"doc-list-items\">"); inList = true; }
html.Append("<li>");
html.Append(EncodeInline(item));
html.AppendLine("</li>");
}
continue;
}
if (inList) { html.AppendLine("</ul>"); inList = false; }
if (line.EndsWith(":") || line.Contains(":\n"))
{
var trimmed = line.TrimEnd(':');
if (trimmed.Length > 0)
{
html.Append("<p class=\"doc-label\">");
html.Append(System.Web.HttpUtility.HtmlEncode(trimmed));
html.AppendLine("</p>");
}
}
else
{
html.Append("<p>");
html.Append(EncodeInline(line));
html.AppendLine("</p>");
}
}
if (inList) html.AppendLine("</ul>");
return html.ToString();
}
private string EncodeInline(string text)
{
var result = new System.Text.StringBuilder();
var remaining = text;
while (remaining.Length > 0)
{
var boldIdx = remaining.IndexOf("**", StringComparison.Ordinal);
if (boldIdx >= 0)
{
var endBold = remaining.IndexOf("**", boldIdx + 2, StringComparison.Ordinal);
if (endBold >= 0)
{
result.Append(System.Web.HttpUtility.HtmlEncode(remaining[..boldIdx]));
result.Append("<strong>");
result.Append(System.Web.HttpUtility.HtmlEncode(remaining[(boldIdx + 2)..endBold]));
result.Append("</strong>");
remaining = remaining[(endBold + 2)..];
continue;
}
}
result.Append(System.Web.HttpUtility.HtmlEncode(remaining));
break;
}
return result.ToString();
}
}
+325
View File
@@ -0,0 +1,325 @@
.docs-page {
padding: 1rem 2rem 3rem;
max-width: 1200px;
margin: 0 auto;
}
.docs-header {
margin-bottom: 2rem;
}
.docs-header h1 {
margin-bottom: 0.25rem;
}
.docs-header p {
font-size: 0.9rem;
margin: 0;
}
.docs-container {
display: grid;
grid-template-columns: 220px 1fr;
gap: 2.5rem;
}
.docs-sidebar {
position: sticky;
top: 2rem;
align-self: start;
}
.search-box {
position: relative;
margin-bottom: 1.5rem;
}
.search-box i {
position: absolute;
left: 0.75rem;
top: 50%;
transform: translateY(-50%);
color: var(--text-muted);
font-size: 0.85rem;
}
.search-box input {
width: 100%;
padding: 0.55rem 0.75rem 0.55rem 2.25rem;
background: var(--bg-surface);
border: 1px solid var(--border);
border-radius: var(--radius);
color: var(--text-primary);
font-size: 0.88rem;
font-family: inherit;
}
.search-box input:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 2px var(--accent-glow);
}
.category-list {
display: flex;
flex-direction: column;
gap: 0.15rem;
}
.category-item {
padding: 0.45rem 0.75rem;
border-radius: var(--radius-sm);
cursor: pointer;
font-size: 0.88rem;
color: var(--text-secondary);
transition: all var(--transition);
}
.category-item:hover {
background: var(--bg-hover);
color: var(--text-primary);
}
.category-item.active {
background: rgba(108, 99, 255, 0.12);
color: var(--accent);
font-weight: 600;
}
.doc-list {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.doc-card {
background: var(--bg-surface);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 1.1rem 1.4rem;
cursor: pointer;
transition: all var(--transition);
}
.doc-card:hover {
border-color: var(--accent);
box-shadow: 0 0 15px var(--accent-glow);
transform: translateY(-1px);
}
.doc-card-category {
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--accent);
font-weight: 600;
margin-bottom: 0.3rem;
}
.doc-card-title {
margin: 0 0 0.35rem;
font-size: 1.15rem;
font-weight: 600;
}
.doc-card-desc {
font-size: 0.88rem;
color: var(--text-secondary);
line-height: 1.5;
margin: 0;
}
.doc-article {
background: var(--bg-surface);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 2rem 2.5rem;
}
.btn-back {
background: none;
border: none;
color: var(--text-muted);
font-size: 0.88rem;
padding: 0;
margin-bottom: 1.5rem;
cursor: pointer;
display: flex;
align-items: center;
gap: 0.4rem;
font-family: inherit;
transition: color var(--transition);
}
.btn-back:hover {
color: var(--text-primary);
}
.doc-header {
margin-bottom: 1.5rem;
padding-bottom: 1.5rem;
border-bottom: 1px solid var(--border);
}
.doc-meta {
font-size: 0.8rem;
color: var(--accent);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 0.4rem;
}
.doc-header h1 {
margin: 0 0 0.75rem;
font-size: 1.8rem;
font-weight: 700;
}
.doc-description {
font-size: 1.05rem;
line-height: 1.6;
color: var(--text-secondary);
margin: 0;
}
.doc-body {
line-height: 1.7;
font-size: 1rem;
color: var(--text-primary);
margin-bottom: 1.5rem;
}
.doc-body p {
margin: 0 0 0.6rem;
}
.doc-body p:last-child {
margin-bottom: 0;
}
.doc-label {
font-weight: 600;
color: var(--text-primary);
margin-bottom: 0.4rem;
}
.doc-list-items {
margin: 0 0 0.8rem;
padding-left: 1.5rem;
list-style: none;
}
.doc-list-items li {
position: relative;
padding: 0.2rem 0;
color: var(--text-secondary);
font-size: 0.95rem;
}
.doc-list-items li::before {
content: "▸";
position: absolute;
left: -1.2rem;
color: var(--accent);
font-size: 0.75rem;
}
.doc-extra {
margin-top: 2rem;
padding-top: 1.5rem;
border-top: 1px solid var(--border);
}
.doc-extra h3 {
font-size: 0.9rem;
font-weight: 600;
margin: 0 0 0.75rem;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.doc-frontmatter {
display: grid;
grid-template-columns: auto 1fr;
gap: 0.4rem 1rem;
padding: 0.75rem 1rem;
background: var(--bg-elevated);
border-radius: var(--radius);
border: 1px solid var(--border);
}
.fm-item {
display: contents;
}
.fm-key {
color: var(--text-muted);
font-weight: 500;
font-size: 0.85rem;
white-space: nowrap;
}
.fm-value {
color: var(--text-secondary);
font-size: 0.85rem;
}
.doc-link-btn {
background: none;
border: none;
padding: 0;
font-family: inherit;
font-size: inherit;
font-weight: 600;
color: var(--accent);
cursor: pointer;
text-decoration: underline;
text-underline-offset: 2px;
text-decoration-color: rgba(108, 99, 255, 0.3);
transition: color var(--transition), text-decoration-color var(--transition);
}
.doc-link-btn:hover {
color: #7b73ff;
text-decoration-color: #7b73ff;
}
.empty-state {
text-align: center;
padding: 4rem 1rem;
color: var(--text-muted);
}
.empty-state i {
font-size: 3rem;
display: block;
margin-bottom: 1rem;
}
@media (max-width: 900px) {
.docs-container {
grid-template-columns: 1fr;
}
.docs-sidebar {
position: static;
}
.category-list {
flex-direction: row;
overflow-x: auto;
gap: 0.4rem;
padding-bottom: 0.5rem;
}
.category-item {
white-space: nowrap;
flex-shrink: 0;
}
.doc-article {
padding: 1.25rem;
}
}
+1
View File
@@ -2,6 +2,7 @@
@using System.Net.Http.Json @using System.Net.Http.Json
@using Chrono.Model @using Chrono.Model
@using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components
@using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.AspNetCore.Components.Web.Virtualization
+2 -1
View File
@@ -1,3 +1,4 @@
{ {
"alwaysUpdateLinks": true "alwaysUpdateLinks": true,
"promptDelete": false
} }
+4 -1
View File
@@ -12,6 +12,9 @@
"archetypes": "multitext", "archetypes": "multitext",
"keycards": "multitext", "keycards": "multitext",
"isVisible": "checkbox", "isVisible": "checkbox",
"factions": "multitext" "factions": "multitext",
"essencePrice": "number",
"codeCharges": "number",
"exp": "number"
} }
} }
+37 -37
View File
@@ -4,21 +4,21 @@
"type": "split", "type": "split",
"children": [ "children": [
{ {
"id": "02cc741a0e7b6b27", "id": "bfe949e4d41446ac",
"type": "tabs", "type": "tabs",
"children": [ "children": [
{ {
"id": "9aaa8a83f2165190", "id": "852a1aaf6b54ec43",
"type": "leaf", "type": "leaf",
"state": { "state": {
"type": "markdown", "type": "markdown",
"state": { "state": {
"file": "Immortalized/[[Phasetide]]/Alina, the Overflowing Cup.md", "file": "Rule/Slow.md",
"mode": "source", "mode": "source",
"source": false "source": false
}, },
"icon": "lucide-file", "icon": "lucide-file",
"title": "Alina, the Overflowing Cup" "title": "Slow"
} }
} }
] ]
@@ -183,45 +183,45 @@
"bases:Create new base": false "bases:Create new base": false
} }
}, },
"active": "9aaa8a83f2165190", "active": "852a1aaf6b54ec43",
"lastOpenFiles": [ "lastOpenFiles": [
"Rule/Immediate.md",
"Rule/Fast.md",
"_Store.base",
"Untitled.md",
"_Timeline.base",
"Store/Core Set Packs x1.md",
"Store/Core Set Packs x5.md",
"Store/Core Set Packs x10.md",
"Store/Core Set Packs x50.md",
"Store/Card Backs.md",
"Store/Text Emote.md",
"Store/Common.md",
"Store/Rare.md",
"Store/Divergent.md",
"_Quests.base",
"Quest",
"Quest/Overflow 10 Times.md",
"exp.md",
"Quest/Deal 30 Damage with Overpower Agents.md",
"Quest/Deal 50 Damage with Specific Faction.md",
"Quest/Erase 7 Cards.md",
"Quest/Deplete 10 Agents.md",
"Quest/Deal 200 Damage.md",
"Quest/Weekly Wins.md",
"Quest/Daily Wins.md",
"Currency/Draft Ticket.md",
"Store/Lost.md",
"Currency/Flux.md",
"Store",
"Currency",
"Currency/Core Charges.md",
"Currency/Crystals.md",
"_Factions.base", "_Factions.base",
"Redirect/Cores.md",
"Redirect/Agents.md",
"Rule/Round End.md",
"Rule/Discarded.md",
"Rule/Core.md",
"Rule/Chain.md",
"Decks/Rewind Me.canvas", "Decks/Rewind Me.canvas",
"Faction/Singularity.md",
"Faction/Splintergleam.md",
"Faction/Silence.md",
"Faction/Phasetide.md",
"Faction/Lifeblood.md",
"Faction/Sungrace.md",
"_Debuff.base", "_Debuff.base",
"Keyword/Sprout.md",
"Keyword/Sprout.md",
"Keyword/Siphon.md",
"Debuff/Transient.md",
"Debuff/Temporary.md",
"Debuff/Exposed.md",
"Debuff/Erase.md",
"Debuff/Delay.md",
"Debuff/Decay.md",
"Debuff/Bleed.md",
"_Keyword.base", "_Keyword.base",
"Debuff/Mute.md",
"Debuff/Disarm.md",
"Agent/[[Lifeblood]]/1", "Agent/[[Lifeblood]]/1",
"Agent/[[Lifeblood]]/8",
"Agent/[[Lifeblood]]/4",
"Agent/[[Lifeblood]]/3",
"Agent/[[Lifeblood]]/5",
"Agent/[[Lifeblood]]/6",
"Agent/[[Lifeblood]]/2",
"Agent/[[Phasetide]]/5",
"Keyword/Surge.md",
"images/Wolf.png", "images/Wolf.png",
"images/Seedling.png", "images/Seedling.png",
"images/Pocket Scout.png", "images/Pocket Scout.png",
+4
View File
@@ -0,0 +1,4 @@
---
category: Currency
description: Earnable currency, can be used to buy packs.
---
+4
View File
@@ -0,0 +1,4 @@
---
category: Currency
description: Premium currency, can be used to buy packs and cosmetics.
---
+4
View File
@@ -0,0 +1,4 @@
---
category: Currency
description: Spend to participate in a draft.
---
+4
View File
@@ -0,0 +1,4 @@
---
category: Currency
description: Can be used to craft cards via wildcards.
---
+3
View File
@@ -0,0 +1,3 @@
---
category: Quest
---
+4
View File
@@ -0,0 +1,4 @@
---
category: Quest
description:
---
@@ -0,0 +1,4 @@
---
category: Quest
description:
---
@@ -0,0 +1,4 @@
---
category: Quest
description:
---
+4
View File
@@ -0,0 +1,4 @@
---
category: Quest
description:
---
+4
View File
@@ -0,0 +1,4 @@
---
category: Quest
description:
---
+6
View File
@@ -0,0 +1,6 @@
---
category: Quest
description:
codeCharges:
exp:
---
+4
View File
@@ -0,0 +1,4 @@
---
category: Quest
description:
---
@@ -1,4 +1,4 @@
--- ---
category: Speed category: Rule
description: This spell can be reacted to. description: This spell can be reacted to.
--- ---
@@ -1,4 +1,4 @@
--- ---
category: Speed category: Rule
description: This spell cannot be reacted to. description: This spell cannot be reacted to.
--- ---
@@ -1,4 +1,4 @@
--- ---
category: Speed category: Rule
description: This spell cannot be used as a reaction to something on the [[Chain]]. description: This spell cannot be used as a reaction to something on the [[Chain]].
--- ---
+5
View File
@@ -0,0 +1,5 @@
---
category: Store
essencePrice:
crytalPrice: "1450"
---
+4
View File
@@ -0,0 +1,4 @@
---
category: Store
essencePrice: 25
---
+7
View File
@@ -0,0 +1,7 @@
---
category: Store
crytalPrice: "450"
coreChargesPrice: "120"
essencePrice:
pricePerPack: "450"
---
+7
View File
@@ -0,0 +1,7 @@
---
category: Store
crytalPrice: "3900"
coreChargesPrice: "1200"
essencePrice:
pricePerPack: "390"
---
+7
View File
@@ -0,0 +1,7 @@
---
category: Store
crytalPrice: "2100"
coreChargesPrice: "600"
essencePrice:
pricePerPack: "420"
---
+7
View File
@@ -0,0 +1,7 @@
---
category: Store
essencePrice:
crytalPrice: "18000"
coreChargesPrice: "6000"
pricePerPack: "360"
---
+4
View File
@@ -0,0 +1,4 @@
---
category: Store
essencePrice: 200
---
+5
View File
@@ -0,0 +1,5 @@
---
category: Store
currency: essence
essencePrice: 400
---
+4
View File
@@ -0,0 +1,4 @@
---
category: Store
essencePrice: 75
---
+5
View File
@@ -0,0 +1,5 @@
---
category: Store
essencePrice:
crytalPrice: "450"
---
+16
View File
@@ -0,0 +1,16 @@
views:
- type: table
name: Table
filters:
and:
- category == "Quest"
order:
- file.name
- description
- codeCharges
- exp
sort:
- property: codeCharges
direction: ASC
columnSize:
file.name: 287
+18
View File
@@ -0,0 +1,18 @@
properties:
note.essencePrice:
displayName: fluxPrice
note.pricePerPack:
displayName: crystalPricePerPack
views:
- type: table
name: Table
filters:
and:
- category == "Store"
order:
- file.name
- crytalPrice
- coreChargesPrice
- essencePrice
- pricePerPack
sort: []