Reorganzing projects
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
@using Web.Pages
|
||||
<Router AppAssembly="@typeof(App).Assembly" NotFoundPage="typeof(NotFound)">
|
||||
<Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="new[] { typeof(Home).Assembly }" NotFoundPage="typeof(NotFound)">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
|
||||
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,102 +0,0 @@
|
||||
// <auto-generated/>
|
||||
#nullable enable
|
||||
|
||||
namespace Chrono.Model;
|
||||
|
||||
public static class DeckDatabase
|
||||
{
|
||||
public static readonly System.Collections.Generic.List<DeckData> Decks =
|
||||
[
|
||||
new()
|
||||
{
|
||||
Name = "Big Energy",
|
||||
Cards = [
|
||||
"Brilliant Martyr",
|
||||
"Brilliant Martyr",
|
||||
"Brilliant Martyr",
|
||||
"Kinetic Absorber",
|
||||
"Kinetic Absorber",
|
||||
"Kinetic Absorber",
|
||||
"Hidden Locus",
|
||||
"Hidden Locus",
|
||||
"Hidden Locus",
|
||||
"Suncursed Conduit",
|
||||
"Suncursed Conduit",
|
||||
"Suncursed Conduit",
|
||||
"Paradox Capacitor",
|
||||
"Paradox Capacitor",
|
||||
"Lumbering Starseeker",
|
||||
"Lumbering Starseeker",
|
||||
"Novathermal Mining",
|
||||
"Novathermal Mining",
|
||||
"Novathermal Mining",
|
||||
"Radiant Channeling",
|
||||
"Radiant Channeling",
|
||||
"Radiant Channeling",
|
||||
"Supernova",
|
||||
"Supernova",
|
||||
"Supernova",
|
||||
"Gunnery Captain",
|
||||
"Lightsteel Colossus",
|
||||
"Lightsteel Colossus",
|
||||
"Devourer Spawn",
|
||||
"Devourer Spawn",
|
||||
"Army of the Sun",
|
||||
"Curb the Anomalies",
|
||||
"Curb the Anomalies",
|
||||
"Curb the Anomalies",
|
||||
"Bearer of the Broth",
|
||||
"Bearer of the Broth",
|
||||
"Bearer of the Broth",
|
||||
"Blessed Soup",
|
||||
"Blessed Soup",
|
||||
"Blessed Soup",
|
||||
],
|
||||
Keycards = [
|
||||
"Kinetic Absorber",
|
||||
"Lumbering Starseeker",
|
||||
"Lightsteel Colossus",
|
||||
"Curb the Anomalies",
|
||||
],
|
||||
Divers = [
|
||||
"Peaceful Synthesizer",
|
||||
"Nonlethal Special Forces",
|
||||
],
|
||||
Description = "The idea of this deck is to go heavy on stat-efficient cards. Like 2 for a 2/3 Kinetic Absorber, 5/6 Lumbering Starseeker, and 8 for a 9/14 Lightsteel Colossus.\nYou got Devourer Spawn to help push for lethal. It's going to have a bunch of keywords on it, given how popular timelines are in the meta.\nYou need to Overflow your mana once in a while, or some of your Supernova removal will be useless. Be pass heavy.\nYou're going to win on very low health if you win. Such is life.\nNo strong card draw, so Army of the Sun is your hope if things go long. At the worst, it's a spell that summons a big unit right away if it goes off.\nAttack aggressively with Brilliant Martyr. You really want Star Siphon to ramp.\nAs divers, Peaceful Synthesizer is a 1 drop that will quickly turn into a 3/3. Can't get more stat efficient than that. Nonlethal Special Forces is to enable Phasetide for AOE Mute cards given we don't care about stat buffs. Also as it stands, it always seems to punch a above it's weight on the board given the Disarm effect.\nSo ya, Curb the Anomalies can weaken the enemy board, by shutting off all there better stats, activates, and synergies. Hopefully destroy the entire enemy board in combat.\nAnd I suppose Bearer of the Broth. Since the deck has so much raw stats, you will probably find somewhere to heal. Like healing Kinetic Absorber so it can keep killing after it Immortalizes.",
|
||||
Factions = [
|
||||
"Sungrace",
|
||||
"Phasetide",
|
||||
],
|
||||
IsVisible = true,
|
||||
DeckCode = "AUHUE2LHEBCW4ZLSM54SAQ3POB4QWY3PNZZXI4TVMN2GKZBTAADACASPCICESCQCAUFDCAYGAMCAGAQDDYBQCAYBAOTQCAYQAMDQG",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "Rewind Me",
|
||||
Cards = [
|
||||
"Curious Acolyte",
|
||||
"Chronicle of the One",
|
||||
"Prayer of Rescue",
|
||||
"Backhand",
|
||||
"Snap Back",
|
||||
"Sunbringer Artillerist",
|
||||
"Sunshock",
|
||||
"Temple Analyst",
|
||||
"Holy Cleaner",
|
||||
"Balance Blade",
|
||||
"Rescind Authorization",
|
||||
"Out of Line",
|
||||
"Divergence Assassin",
|
||||
"Chronal Quarantine",
|
||||
"Holder of the Instruments",
|
||||
],
|
||||
Keycards = [
|
||||
],
|
||||
Divers = [
|
||||
],
|
||||
Factions = [
|
||||
],
|
||||
IsVisible = false,
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
@inherits LayoutComponentBase
|
||||
<div class="page">
|
||||
<div class="sidebar">
|
||||
<NavMenu/>
|
||||
</div>
|
||||
|
||||
<main>
|
||||
<article class="content px-4">
|
||||
<TelerikRootComponent>
|
||||
@Body
|
||||
</TelerikRootComponent>
|
||||
</article>
|
||||
</main>
|
||||
</div>
|
||||
@@ -1,77 +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;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
<div class="top-row ps-3 navbar navbar-dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="">
|
||||
<i class="bi bi-hourglass-split me-2 text-warning"></i> Chrono CCG
|
||||
</a>
|
||||
<button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="@NavMenuCssClass nav-scrollable" @onclick="ToggleNavMenu">
|
||||
<nav class="nav flex-column">
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
|
||||
<i class="bi bi-house-door-fill nav-icon"></i> Home
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="cards">
|
||||
<i class="bi bi-collection-fill nav-icon"></i> Cards
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="agents">
|
||||
<i class="bi bi-people-fill nav-icon"></i> Agents
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="decks">
|
||||
<i class="bi bi-journal-text nav-icon"></i> Decks
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private bool collapseNavMenu = true;
|
||||
|
||||
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
|
||||
|
||||
private void ToggleNavMenu()
|
||||
{
|
||||
collapseNavMenu = !collapseNavMenu;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
.navbar-toggler {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
min-height: 3.5rem;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.nav-icon {
|
||||
margin-right: 0.75rem;
|
||||
font-size: 1.05rem;
|
||||
width: 1.25rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
font-size: 0.9rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-item:first-of-type {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.nav-item:last-of-type {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.nav-item ::deep a {
|
||||
color: #d7d7d7;
|
||||
border-radius: 4px;
|
||||
height: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 3rem;
|
||||
}
|
||||
|
||||
.nav-item ::deep a.active {
|
||||
background-color: rgba(255, 255, 255, 0.37);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-item ::deep a:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: white;
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.navbar-toggler {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.collapse {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.nav-scrollable {
|
||||
height: calc(100vh - 3.5rem);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
@page "/agents"
|
||||
|
||||
<PageTitle>Agents</PageTitle>
|
||||
|
||||
<div class="agents-page">
|
||||
<TelerikGrid Data="@agents"
|
||||
Sortable="true"
|
||||
FilterMode="GridFilterMode.FilterRow"
|
||||
Pageable="true"
|
||||
PageSize="250"
|
||||
Resizable="true"
|
||||
Height="850px"
|
||||
Groupable="true"
|
||||
class="agents-grid">
|
||||
<GridColumns>
|
||||
<GridColumn Field="@nameof(CardData.IsImmortalized)" Title="Im." Width="120px">
|
||||
<Template>
|
||||
@if (((CardData)context).IsImmortalized)
|
||||
{
|
||||
<i class="bi bi-star-fill" style="color: #ffd700;" title="Immortalized"></i>
|
||||
}
|
||||
</Template>
|
||||
</GridColumn>
|
||||
<GridColumn Field="@nameof(CardData.Name)" Title="Card" Width="220px">
|
||||
<Template>
|
||||
<div class="agent-name-cell">
|
||||
<img src="@(((CardData)context).ImagePath)" alt="@(((CardData)context).Name)"
|
||||
class="agent-thumb"/>
|
||||
<span>@(((CardData)context).Name)</span>
|
||||
</div>
|
||||
</Template>
|
||||
</GridColumn>
|
||||
<GridColumn Field="@nameof(CardData.Cost)" Title="Cost" Width="120px"/>
|
||||
<GridColumn Field="@nameof(CardData.StatEfficiency)" Title="SE" Width="120px">
|
||||
<Template>
|
||||
@(((CardData)context).StatEfficiency)
|
||||
</Template>
|
||||
</GridColumn>
|
||||
<GridColumn Field="@nameof(CardData.Faction)" Title="Faction" Width="140px"/>
|
||||
<GridColumn Field="@nameof(CardData.Attack)" Title="ATK" Width="120px"/>
|
||||
<GridColumn Field="@nameof(CardData.Health)" Title="HP" Width="120px"/>
|
||||
<GridColumn Field="@nameof(CardData.Description)" Title="Description" Width="400px"/>
|
||||
|
||||
</GridColumns>
|
||||
</TelerikGrid>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private List<CardData> agents = [];
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
agents = CardDatabase.Cards
|
||||
.Where(c => c.Category == "Agent")
|
||||
.OrderBy(c => c.Cost)
|
||||
.ThenBy(c => c.Name)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
.agents-page {
|
||||
--kendo-color-app-surface: oklch(5.3% 0.013 270deg);
|
||||
--kendo-color-subtle: oklch(64% 0.018 270deg);
|
||||
--kendo-color-surface: oklch(10% 0.015 270deg);
|
||||
--kendo-color-border: oklch(25% 0.025 270deg / 0.7);
|
||||
--kendo-color-border-alt: oklch(30% 0.03 270deg / 0.5);
|
||||
--kendo-color-base: oklch(16% 0.02 270deg);
|
||||
--kendo-color-primary: oklch(55% 0.23 275deg);
|
||||
--kendo-color-secondary: oklch(35% 0 0deg);
|
||||
--kendo-color-tertiary: oklch(55% 0.15 240deg);
|
||||
--kendo-color-info: oklch(65% 0.15 250deg);
|
||||
--kendo-color-success: oklch(60% 0.15 140deg);
|
||||
--kendo-color-warning: oklch(75% 0.14 85deg);
|
||||
--kendo-color-error: oklch(55% 0.20 30deg);
|
||||
--kendo-color-inverse: oklch(85% 0.01 270deg);
|
||||
--kendo-color-series: oklch(55% 0.23 275deg);
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.agents-page ::deep .k-grid,
|
||||
.agents-page ::deep .k-grid-container,
|
||||
.agents-page ::deep .k-grid-content,
|
||||
.agents-page ::deep .k-grid-header-wrap {
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.agents-page ::deep .k-grid-header,
|
||||
.agents-page ::deep .k-grid-footer,
|
||||
.agents-page ::deep .k-pager-wrap {
|
||||
background: var(--bg-elevated);
|
||||
}
|
||||
|
||||
.agents-page ::deep .k-grid-header .k-header,
|
||||
.agents-page ::deep .k-grid-header .k-column-title,
|
||||
.agents-page ::deep .k-grid-header .k-link,
|
||||
.agents-page ::deep .k-grid-header .k-grid-filter {
|
||||
color: #e8e8f0;
|
||||
}
|
||||
|
||||
.agents-page ::deep .k-grid-header .k-link:hover,
|
||||
.agents-page ::deep .k-grid-header .k-grid-filter:hover {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.agents-page ::deep .k-grid td,
|
||||
.agents-page ::deep .k-grid-header th.k-header {
|
||||
border-color: oklch(25% 0.025 270deg / 0.7);
|
||||
}
|
||||
|
||||
.agents-page ::deep .k-grid tr.k-alt {
|
||||
background: oklch(12% 0.015 270deg);
|
||||
}
|
||||
|
||||
.agents-page ::deep .k-grid tr:hover {
|
||||
background: oklch(20% 0.025 270deg);
|
||||
}
|
||||
|
||||
.agents-page ::deep .k-grid-filter,
|
||||
.agents-page ::deep .k-grid-filter:hover {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.agents-page ::deep .k-input,
|
||||
.agents-page ::deep .k-picker {
|
||||
color: var(--text-primary);
|
||||
background: var(--bg-surface);
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
.agents-page ::deep .k-button-solid-base {
|
||||
color: var(--text-secondary);
|
||||
background: var(--bg-elevated);
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
.agents-page ::deep .k-button-solid-base:hover {
|
||||
background: var(--bg-hover);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.agents-page ::deep .k-pager-wrap {
|
||||
color: #e8e8f0;
|
||||
}
|
||||
|
||||
.agents-page ::deep .k-pager-nav,
|
||||
.agents-page ::deep .k-pager-numbers,
|
||||
.agents-page ::deep .k-pager-numbers .k-link,
|
||||
.agents-page ::deep .k-pager-input,
|
||||
.agents-page ::deep .k-pager-info {
|
||||
color: #e8e8f0;
|
||||
}
|
||||
|
||||
.agents-page ::deep .k-pager-nav:hover,
|
||||
.agents-page ::deep .k-pager-numbers .k-link:hover {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.agents-header {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.agents-header h1 {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.agents-header p {
|
||||
font-size: 0.9rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.agent-name-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
}
|
||||
|
||||
.agent-thumb {
|
||||
width: 36px;
|
||||
height: 50px;
|
||||
object-fit: cover;
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -1,217 +0,0 @@
|
||||
@page "/decks/{Name}"
|
||||
|
||||
<PageTitle>@deck?.Name</PageTitle>
|
||||
|
||||
<div class="deck-detail-page">
|
||||
<a class="back-link" href="/decks"><i class="bi bi-arrow-left"></i> Back to Decks</a>
|
||||
|
||||
@if (deck == null)
|
||||
{
|
||||
<div class="empty-state">
|
||||
<i class="bi bi-exclamation-circle"></i>
|
||||
<p>Deck not found.</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<article class="deck-article">
|
||||
<header class="deck-header">
|
||||
<h1>@deck.Name</h1>
|
||||
<b>Deck Code:</b> <pre>@deck.DeckCode</pre>
|
||||
@if (deck.Factions.Count > 0)
|
||||
{
|
||||
<div class="deck-factions">
|
||||
@foreach (var f in deck.Factions)
|
||||
{
|
||||
<span class="faction-badge">@f</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<div class="deck-card-count">
|
||||
<span>@deck.Cards.Count cards</span>
|
||||
<span class="ms-3 badge @(deck.IsValid ? "bg-success" : "bg-danger")">
|
||||
@(deck.IsValid ? "Valid" : "Invalid")
|
||||
</span>
|
||||
@if (!deck.IsValid)
|
||||
{
|
||||
<small class="text-danger ms-2 d-block d-md-inline">@deck.ValidationMessage</small>
|
||||
}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@if (deck.Keycards.Count > 0)
|
||||
{
|
||||
<section class="deck-section">
|
||||
<h2><i class="bi bi-star-fill" style="color: var(--gold);"></i> Keycards</h2>
|
||||
<div class="deck-card-row">
|
||||
@foreach (var cardName in deck.Keycards)
|
||||
{
|
||||
var card = LookupCard(cardName);
|
||||
<button class="mini-card-btn" @onclick="() => SelectCard(card)">
|
||||
<div class="mini-card">
|
||||
<div class="mini-card-img">
|
||||
<img src="@(card?.ImagePath ?? "cards/placeholder.png")" alt="@cardName"
|
||||
loading="lazy"/>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
|
||||
@if (deck.Divers.Count > 0)
|
||||
{
|
||||
<section class="deck-section">
|
||||
<h2><i class="bi bi-shuffle"></i> Divers</h2>
|
||||
<div class="deck-card-row">
|
||||
@foreach (var cardName in deck.Divers)
|
||||
{
|
||||
var card = LookupCard(cardName);
|
||||
<button class="mini-card-btn" @onclick="() => SelectCard(card)">
|
||||
<div class="mini-card">
|
||||
<div class="mini-card-img">
|
||||
<img src="@(card?.ImagePath ?? "cards/placeholder.png")" alt="@cardName"
|
||||
loading="lazy"/>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
|
||||
<section class="deck-section">
|
||||
<h2><i class="bi bi-collection-fill"></i> Cards</h2>
|
||||
<div class="deck-card-row">
|
||||
@foreach (var group in deck.Cards.GroupBy(x => x))
|
||||
{
|
||||
var cardName = group.Key;
|
||||
var count = group.Count();
|
||||
var card = LookupCard(cardName);
|
||||
<button class="mini-card-btn @(count > 1 ? "is-stacked" : "")"
|
||||
@onclick="() => SelectCard(card)">
|
||||
<div class="mini-card-stack">
|
||||
@for (var i = 0; i < (count > 1 ? Math.Min(count, 3) : 1); i++)
|
||||
{
|
||||
<div class="mini-card" style="--stack-index: @i">
|
||||
<div class="mini-card-img">
|
||||
<img src="@(card?.ImagePath ?? "cards/placeholder.png")" alt="@cardName"
|
||||
loading="lazy"/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@if (deck.Description != null)
|
||||
{
|
||||
<section class="deck-section description">
|
||||
<h2><i class="bi bi-chat-quote-fill"></i> Description</h2>
|
||||
<div class="deck-description">
|
||||
@RenderDescription(deck.Description)
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
</article>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (selectedCard != null)
|
||||
{
|
||||
<CardDialog Card="selectedCard" OnClose="CloseDetail" OnNavigate="SelectCard" />
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter] public string Name { get; set; } = "";
|
||||
|
||||
private DeckData? deck;
|
||||
private CardData? selectedCard;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
var decoded = Uri.UnescapeDataString(Name);
|
||||
deck = DeckDatabase.Decks.FirstOrDefault(d => d.IsVisible && d.Name == decoded);
|
||||
}
|
||||
|
||||
private CardData? LookupCard(string cardName)
|
||||
{
|
||||
return CardDatabase.Cards.FirstOrDefault(c =>
|
||||
string.Equals(c.Name, cardName, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private void SelectCard(CardData? card)
|
||||
{
|
||||
selectedCard = card;
|
||||
}
|
||||
|
||||
private void CloseDetail()
|
||||
{
|
||||
selectedCard = null;
|
||||
}
|
||||
|
||||
private RenderFragment RenderDescription(string description)
|
||||
{
|
||||
return builder =>
|
||||
{
|
||||
var cardNames = CardDatabase.Cards
|
||||
.Select(c => c.Name)
|
||||
.Where(n => !string.IsNullOrWhiteSpace(n))
|
||||
.OrderByDescending(n => n.Length)
|
||||
.ToList();
|
||||
|
||||
int sequence = 0;
|
||||
var paragraphs = description.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
foreach (var paragraph in paragraphs)
|
||||
{
|
||||
builder.OpenElement(sequence++, "p");
|
||||
|
||||
var currentText = paragraph;
|
||||
while (!string.IsNullOrEmpty(currentText))
|
||||
{
|
||||
int bestMatchIndex = -1;
|
||||
string? bestMatchName = null;
|
||||
|
||||
foreach (var name in cardNames)
|
||||
{
|
||||
int index = currentText.IndexOf(name, StringComparison.OrdinalIgnoreCase);
|
||||
if (index != -1 && (bestMatchIndex == -1 || index < bestMatchIndex))
|
||||
{
|
||||
bestMatchIndex = index;
|
||||
bestMatchName = name;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestMatchIndex != -1 && bestMatchName != null)
|
||||
{
|
||||
if (bestMatchIndex > 0)
|
||||
{
|
||||
builder.AddContent(sequence++, currentText.Substring(0, bestMatchIndex));
|
||||
}
|
||||
|
||||
var card = LookupCard(bestMatchName);
|
||||
builder.OpenElement(sequence++, "button");
|
||||
builder.AddAttribute(sequence++, "class", "inline-card-btn");
|
||||
builder.AddAttribute(sequence++, "onclick", EventCallback.Factory.Create(this, () => SelectCard(card)));
|
||||
builder.AddContent(sequence++, bestMatchName);
|
||||
builder.CloseElement();
|
||||
|
||||
currentText = currentText.Substring(bestMatchIndex + bestMatchName.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddContent(sequence++, currentText);
|
||||
currentText = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
builder.CloseElement();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
.deck-detail-page {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem 3rem;
|
||||
}
|
||||
|
||||
.back-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
font-size: 0.85rem;
|
||||
margin-bottom: 1.5rem;
|
||||
transition: color var(--transition);
|
||||
}
|
||||
|
||||
.back-link:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.deck-article {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.deck-header {
|
||||
margin-bottom: 2rem;
|
||||
padding-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.deck-header h1 {
|
||||
margin: 0 0 0.5rem;
|
||||
}
|
||||
|
||||
.deck-factions {
|
||||
display: flex;
|
||||
gap: 0.4rem;
|
||||
margin-bottom: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.faction-badge {
|
||||
display: inline-block;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
padding: 0.2rem 0.7rem;
|
||||
border-radius: 999px;
|
||||
background: var(--bg-elevated);
|
||||
color: var(--accent);
|
||||
border: 1px solid var(--border);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.deck-card-count {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-muted);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.deck-section {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.deck-section:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.deck-section h2 {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 600;
|
||||
margin: 0 0 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.deck-card-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.mini-card-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mini-card {
|
||||
width: 100px;
|
||||
background: var(--bg-elevated);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
overflow: hidden;
|
||||
transition: border-color var(--transition), transform var(--transition);
|
||||
position: relative;
|
||||
aspect-ratio: 2.5 / 3.5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.mini-card:hover {
|
||||
border-color: var(--accent);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.mini-card-img {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
background: var(--bg-primary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.mini-card-img img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.mini-card-name {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 500;
|
||||
padding: 0.25rem 0.3rem;
|
||||
text-align: center;
|
||||
color: var(--text-secondary);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
background: var(--bg-elevated);
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.mini-card-stack {
|
||||
position: relative;
|
||||
width: 110px; /* Base width + some offset space */
|
||||
height: 140px; /* Adjusted for aspect ratio */
|
||||
}
|
||||
|
||||
.mini-card-stack .mini-card {
|
||||
position: absolute;
|
||||
top: calc(var(--stack-index) * 4px);
|
||||
left: calc(var(--stack-index) * 4px);
|
||||
z-index: calc(10 - var(--stack-index));
|
||||
}
|
||||
|
||||
.mini-card-count {
|
||||
position: absolute;
|
||||
top: 0.25rem;
|
||||
right: 0.25rem;
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
font-size: 0.65rem;
|
||||
font-weight: 800;
|
||||
padding: 0.1rem 0.3rem;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.mini-card-btn.is-stacked:hover .mini-card {
|
||||
transform: translate(calc(var(--stack-index) * 2px), calc(var(--stack-index) * -2px));
|
||||
}
|
||||
|
||||
.deck-description {
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.7;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
|
||||
.deck-description p {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
.deck-description p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 4rem 1rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.empty-state i {
|
||||
font-size: 3rem;
|
||||
display: block;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
@page "/decks"
|
||||
|
||||
<PageTitle>Decks</PageTitle>
|
||||
|
||||
<div class="decks-page">
|
||||
<div class="decks-header">
|
||||
<h1>Decks</h1>
|
||||
<p class="text-secondary">@decks.Count deck@(decks.Count != 1 ? "s" : "")</p>
|
||||
<p class="text-primary">Please note these are my crafted decks. They are probably not optimal or good. See <a href="https://runeterra.ar/chrono/home">Runeterra.ar</a> and check out the decks from recognizable names there. This is not an ad, just common sense.</p>
|
||||
</div>
|
||||
|
||||
<div class="deck-list">
|
||||
@foreach (var deck in decks)
|
||||
{
|
||||
<a class="deck-card" href="/decks/@Uri.EscapeDataString(deck.Name)">
|
||||
<div class="deck-card-body">
|
||||
<h2 class="deck-card-title">@deck.Name</h2>
|
||||
@if (deck.Factions.Count > 0)
|
||||
{
|
||||
<div class="deck-card-factions">
|
||||
@foreach (var f in deck.Factions)
|
||||
{
|
||||
<span class="faction-badge">@f</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<div class="deck-card-meta">
|
||||
<span>@deck.Cards.Distinct().Count() unique, @deck.Cards.Count total</span>
|
||||
@if (deck.Keycards.Count > 0)
|
||||
{
|
||||
<span>@deck.Keycards.Count keycard@(deck.Keycards.Count != 1 ? "s" : "")</span>
|
||||
}
|
||||
@if (deck.Divers.Count > 0)
|
||||
{
|
||||
<span>@deck.Divers.Count diver@(deck.Divers.Count != 1 ? "s" : "")</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@if (deck.Description != null)
|
||||
{
|
||||
<div class="deck-card-excerpt">@Truncate(deck.Description, 120)</div>
|
||||
}
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (decks.Count == 0)
|
||||
{
|
||||
<div class="empty-state">
|
||||
<i class="bi bi-journal-text"></i>
|
||||
<p>No decks available yet.</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private List<DeckData> decks = [];
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
decks = DeckDatabase.Decks.Where(d => d.IsVisible).ToList();
|
||||
}
|
||||
|
||||
private static string Truncate(string text, int maxLength)
|
||||
{
|
||||
if (text.Length <= maxLength) return text;
|
||||
var lastSpace = text.LastIndexOf(' ', maxLength);
|
||||
return text[..(lastSpace > 0 ? lastSpace : maxLength)] + "...";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
.decks-page {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem 2rem;
|
||||
}
|
||||
|
||||
.decks-header {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.decks-header h1 {
|
||||
margin: 0 0 0.25rem;
|
||||
}
|
||||
|
||||
.deck-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.deck-card {
|
||||
display: block;
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
padding: 1.25rem 1.5rem;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
transition: border-color var(--transition), box-shadow var(--transition);
|
||||
}
|
||||
|
||||
.deck-card:hover {
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 20px var(--accent-glow);
|
||||
}
|
||||
|
||||
.deck-card-title {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 600;
|
||||
margin: 0 0 0.5rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.deck-card-factions {
|
||||
display: flex;
|
||||
gap: 0.4rem;
|
||||
margin-bottom: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.faction-badge {
|
||||
display: inline-block;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
padding: 0.15rem 0.6rem;
|
||||
border-radius: 999px;
|
||||
background: var(--bg-elevated);
|
||||
color: var(--accent);
|
||||
border: 1px solid var(--border);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.deck-card-meta {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.deck-card-meta span + span::before {
|
||||
content: "·";
|
||||
margin-right: 0.75rem;
|
||||
}
|
||||
|
||||
.deck-card-excerpt {
|
||||
margin-top: 0.6rem;
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 4rem 1rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.empty-state i {
|
||||
font-size: 3rem;
|
||||
display: block;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
@page "/"
|
||||
|
||||
<PageTitle>Slop Game Reference - Chrono CCG</PageTitle>
|
||||
|
||||
<div class="home-hero">
|
||||
<div class="hero-glow"></div>
|
||||
<div class="hero-content">
|
||||
<h1 class="hero-title">Slop Game Reference - Chrono CCG</h1>
|
||||
<p class="hero-subtitle">
|
||||
AI generated website for reference notes on playing Chrono CCG.
|
||||
</p>
|
||||
<div class="hero-actions">
|
||||
<a class="cta-button primary" href="/cards">
|
||||
<i class="bi bi-collection-fill"></i> Browse Cards
|
||||
</a>
|
||||
<a class="cta-button secondary" href="/agents">
|
||||
<i class="bi bi-people-fill"></i> Agents Data Table
|
||||
</a>
|
||||
<a class="cta-button secondary" href="/decks">
|
||||
<i class="bi bi-journal-text"></i> View Decks
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,294 +0,0 @@
|
||||
/* ── Hero ── */
|
||||
.home-hero {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
padding: 4rem 1rem 3rem;
|
||||
margin-bottom: 2.5rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-glow {
|
||||
position: absolute;
|
||||
top: -30%;
|
||||
left: 50%;
|
||||
width: 60rem;
|
||||
height: 30rem;
|
||||
transform: translateX(-50%);
|
||||
background: radial-gradient(ellipse at center, rgba(108, 99, 255, 0.15) 0%, transparent 70%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
max-width: 42rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.hero-badge {
|
||||
display: inline-block;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.2em;
|
||||
text-transform: uppercase;
|
||||
color: var(--gold);
|
||||
border: 1px solid rgba(255, 215, 0, 0.3);
|
||||
background: rgba(255, 215, 0, 0.06);
|
||||
padding: 0.3rem 0.9rem;
|
||||
border-radius: 999px;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 3.5rem;
|
||||
font-weight: 800;
|
||||
margin: 0 0 1rem;
|
||||
line-height: 1.1;
|
||||
background: linear-gradient(135deg, #e8e8f0 0%, #6c63ff 50%, #ffd700 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.65;
|
||||
color: var(--text-secondary);
|
||||
margin: 0 0 2rem;
|
||||
max-width: 34rem;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.hero-actions {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.cta-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.45rem;
|
||||
padding: 0.7rem 1.5rem;
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
transition: all var(--transition);
|
||||
}
|
||||
|
||||
.cta-button.primary {
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
box-shadow: 0 0 20px var(--accent-glow);
|
||||
}
|
||||
|
||||
.cta-button.primary:hover {
|
||||
background: #7b73ff;
|
||||
box-shadow: 0 0 30px var(--accent-glow);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.cta-button.secondary {
|
||||
background: var(--bg-elevated);
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.cta-button.secondary:hover {
|
||||
background: var(--bg-hover);
|
||||
border-color: var(--accent);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* ── Stats ── */
|
||||
.home-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
gap: 0.75rem;
|
||||
max-width: 56rem;
|
||||
margin: 0 auto 3rem;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
padding: 1rem;
|
||||
transition: all var(--transition);
|
||||
}
|
||||
|
||||
.stat-card:hover {
|
||||
background: var(--bg-elevated);
|
||||
border-color: var(--accent);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
border-radius: var(--radius-sm);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.stat-icon.agents {
|
||||
background: rgba(108, 99, 255, 0.15);
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.stat-icon.spells {
|
||||
background: rgba(255, 215, 0, 0.12);
|
||||
color: var(--gold);
|
||||
}
|
||||
|
||||
.stat-icon.tokens {
|
||||
background: rgba(0, 200, 150, 0.15);
|
||||
color: #00c896;
|
||||
}
|
||||
|
||||
.stat-icon.decks {
|
||||
background: rgba(255, 120, 80, 0.15);
|
||||
color: #ff7850;
|
||||
}
|
||||
|
||||
.stat-icon.factions {
|
||||
background: rgba(100, 200, 255, 0.15);
|
||||
color: #64c8ff;
|
||||
}
|
||||
|
||||
.stat-icon.total {
|
||||
background: rgba(200, 150, 255, 0.15);
|
||||
color: #c896ff;
|
||||
}
|
||||
|
||||
.stat-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.72rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* ── Section Cards ── */
|
||||
.home-sections {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 1.25rem;
|
||||
max-width: 56rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.section-card {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
padding: 2rem 1.5rem;
|
||||
transition: all var(--transition);
|
||||
}
|
||||
|
||||
.section-card:hover {
|
||||
background: var(--bg-elevated);
|
||||
border-color: var(--accent);
|
||||
transform: translateY(-3px);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.section-icon {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
border-radius: var(--radius);
|
||||
background: rgba(108, 99, 255, 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.3rem;
|
||||
color: var(--accent);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.section-card h2 {
|
||||
font-size: 1.15rem;
|
||||
margin: 0 0 0.5rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.section-card p {
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.55;
|
||||
color: var(--text-secondary);
|
||||
margin: 0 0 1.25rem;
|
||||
}
|
||||
|
||||
.section-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
transition: gap var(--transition);
|
||||
}
|
||||
|
||||
.section-link:hover {
|
||||
gap: 0.6rem;
|
||||
color: #7b73ff;
|
||||
}
|
||||
|
||||
/* ── Responsive ── */
|
||||
@
|
||||
@media (max-width: 900px) {
|
||||
.home-stats {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
.home-sections {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@
|
||||
@media (max-width: 600px) {
|
||||
.hero-title {
|
||||
font-size: 2.2rem;
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.hero-actions {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.cta-button {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.home-stats {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
@@ -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
-17
@@ -16,22 +16,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Model\Model.csproj"/>
|
||||
<ProjectReference Include="..\Shared\Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Label="Generated files">
|
||||
<Compile Remove="Generated\**\*.cs"/>
|
||||
<Compile Include="Generated\**\*.cs"/>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="RunBuild" BeforeTargets="CoreCompile">
|
||||
<PropertyGroup>
|
||||
<_BuildProject>$(MSBuildThisFileDirectory)..\Build\Build.csproj</_BuildProject>
|
||||
</PropertyGroup>
|
||||
<Message Text="=== Running Build project (card metadata generation) ===" Importance="high"/>
|
||||
<Exec Command="dotnet run --project "$(_BuildProject)""/>
|
||||
<ItemGroup>
|
||||
<Compile Remove="Generated\**\*.cs"/>
|
||||
<Compile Include="Generated\**\*.cs"/>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.AspNetCore.Components.WebAssembly.Http
|
||||
@using Microsoft.JSInterop
|
||||
@using Web
|
||||
@using Web.Layout
|
||||
@using Shared.Layout
|
||||
@using Shared.Pages
|
||||
@using Chrono.Components
|
||||
@using Telerik.Blazor
|
||||
@using Telerik.Blazor.Components
|
||||
|
||||
Reference in New Issue
Block a user