Vibe galaxy map
This commit is contained in:
@@ -2,21 +2,32 @@
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
background-color: #080c14;
|
||||
background-image:
|
||||
radial-gradient(circle at 15% 20%, rgba(56, 189, 248, 0.04) 0%, transparent 40%),
|
||||
radial-gradient(circle at 85% 80%, rgba(16, 185, 129, 0.03) 0%, transparent 40%);
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background-image: linear-gradient(180deg, #0d1117 0%, #161b22 70%);
|
||||
background-color: #0b0f19;
|
||||
background-image: linear-gradient(180deg, #0d131f 0%, #080c14 100%);
|
||||
border-right: 1px solid rgba(56, 189, 248, 0.12);
|
||||
box-shadow: 2px 0 16px rgba(0, 0, 0, 0.35);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #d6d5d5;
|
||||
background-color: rgba(13, 19, 31, 0.8);
|
||||
backdrop-filter: blur(8px);
|
||||
border-bottom: 1px solid rgba(56, 189, 248, 0.15);
|
||||
justify-content: flex-end;
|
||||
height: 3.5rem;
|
||||
height: 3.75rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
@@ -25,10 +36,12 @@ main {
|
||||
white-space: nowrap;
|
||||
margin-left: 1.5rem;
|
||||
text-decoration: none;
|
||||
color: #38bdf8;
|
||||
}
|
||||
|
||||
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
|
||||
text-decoration: underline;
|
||||
color: #7dd3fc;
|
||||
}
|
||||
|
||||
.top-row ::deep a:first-child {
|
||||
@@ -56,6 +69,7 @@ main {
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
@@ -70,8 +84,10 @@ main {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.top-row, article {
|
||||
article {
|
||||
padding-left: 2rem !important;
|
||||
padding-right: 1.5rem !important;
|
||||
padding-right: 2rem !important;
|
||||
padding-top: 1.5rem !important;
|
||||
padding-bottom: 2.5rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<div class="top-row ps-3 navbar navbar-dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="">ZeroSpace</a>
|
||||
<a class="navbar-brand d-flex align-items-center" href="">
|
||||
<span class="brand-glow me-2">✦</span>
|
||||
<span class="brand-text">ZeroSpace</span>
|
||||
</a>
|
||||
<button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
@@ -11,22 +14,33 @@
|
||||
<nav class="nav flex-column">
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
|
||||
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
|
||||
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span>
|
||||
<span>Home</span>
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="units">
|
||||
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Units
|
||||
<NavLink class="nav-link" href="galaxy">
|
||||
<span class="bi bi-galaxy-nav-menu" aria-hidden="true"></span>
|
||||
<span>Galaxy Map</span>
|
||||
<span class="badge badge-nav-live ms-auto">MAP</span>
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="StarSystem">
|
||||
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Star Systems
|
||||
<span class="bi bi-star-systems-nav-menu" aria-hidden="true"></span>
|
||||
<span>Star Systems</span>
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="SystemMastery">
|
||||
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Masteries
|
||||
<span class="bi bi-masteries-nav-menu" aria-hidden="true"></span>
|
||||
<span>Masteries</span>
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="units">
|
||||
<span class="bi bi-units-nav-menu" aria-hidden="true"></span>
|
||||
<span>Units</span>
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -1,14 +1,44 @@
|
||||
.navbar-toggler {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
background-color: rgba(56, 189, 248, 0.1);
|
||||
border: 1px solid rgba(56, 189, 248, 0.25);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
min-height: 3.5rem;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
min-height: 3.75rem;
|
||||
background: linear-gradient(180deg, rgba(13, 19, 31, 0.95) 0%, rgba(9, 13, 22, 0.95) 100%);
|
||||
border-bottom: 1px solid rgba(56, 189, 248, 0.15);
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-size: 1.1rem;
|
||||
font-size: 1.15rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: #f0f6fc;
|
||||
}
|
||||
|
||||
.brand-glow {
|
||||
color: #38bdf8;
|
||||
text-shadow: 0 0 10px rgba(56, 189, 248, 0.8);
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.brand-text {
|
||||
background: linear-gradient(135deg, #ffffff 30%, #38bdf8 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.badge-nav-live {
|
||||
font-size: 0.65rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.05em;
|
||||
padding: 0.2rem 0.45rem;
|
||||
border-radius: 4px;
|
||||
background: rgba(56, 189, 248, 0.2);
|
||||
color: #38bdf8;
|
||||
border: 1px solid rgba(56, 189, 248, 0.4);
|
||||
box-shadow: 0 0 6px rgba(56, 189, 248, 0.3);
|
||||
}
|
||||
|
||||
.bi {
|
||||
@@ -18,24 +48,34 @@
|
||||
height: 1.25rem;
|
||||
margin-right: 0.75rem;
|
||||
top: -1px;
|
||||
background-size: cover;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.bi-house-door-fill-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%2394a3b8' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-plus-square-fill-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
|
||||
.bi-galaxy-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%2338bdf8' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='2.5' fill='%2338bdf8'/%3E%3Ccircle cx='2.5' cy='4' r='1.5' fill='%2338bdf8'/%3E%3Ccircle cx='13.5' cy='5' r='1.5' fill='%2338bdf8'/%3E%3Ccircle cx='4' cy='13' r='1.5' fill='%2338bdf8'/%3E%3Ccircle cx='12' cy='12' r='1.5' fill='%2338bdf8'/%3E%3Cpath stroke='%2338bdf8' stroke-width='1.2' stroke-linecap='round' d='M2.5 4L8 8m0 0l5.5-3M8 8l-4 5m4-5l4 4' opacity='.65'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-list-nested-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
|
||||
.bi-star-systems-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23f59e0b' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3.5' fill='%23f59e0b'/%3E%3Cpath stroke='%23f59e0b' stroke-width='1.2' stroke-linecap='round' d='M8 1v2.5M8 12.5V15M1 8h2.5M12.5 8H15M3 3l1.8 1.8M11.2 11.2l1.8 1.8M3 13l1.8-1.8M11.2 4.8l1.8-1.8' opacity='.75'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-masteries-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23a78bfa' viewBox='0 0 16 16'%3E%3Cpath d='M8 0.5l2.2 4.6 5 .7-3.6 3.6.9 5-4.5-2.4-4.5 2.4.9-5-3.6-3.6 5-.7L8 0.5z' fill='%23a78bfa'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-units-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%2310b981' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='6' stroke='%2310b981' stroke-width='1.3' fill='none'/%3E%3Ccircle cx='8' cy='8' r='2' fill='%2310b981'/%3E%3Cpath stroke='%2310b981' stroke-width='1.3' d='M8 0v4M8 12v4M0 8h4M12 8h4'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
font-size: 0.9rem;
|
||||
padding-bottom: 0.5rem;
|
||||
font-size: 0.92rem;
|
||||
padding-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
.nav-item:first-of-type {
|
||||
@@ -47,22 +87,30 @@
|
||||
}
|
||||
|
||||
.nav-item ::deep a {
|
||||
color: #d7d7d7;
|
||||
border-radius: 4px;
|
||||
height: 3rem;
|
||||
color: #94a3b8;
|
||||
border-radius: 8px;
|
||||
height: 2.75rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 3rem;
|
||||
line-height: 2.75rem;
|
||||
padding: 0 0.85rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.nav-item ::deep a.active {
|
||||
background-color: rgba(88, 166, 255, 0.2);
|
||||
color: #58a6ff;
|
||||
background: linear-gradient(90deg, rgba(56, 189, 248, 0.15) 0%, rgba(56, 189, 248, 0.05) 100%);
|
||||
color: #38bdf8;
|
||||
border-color: rgba(56, 189, 248, 0.35);
|
||||
box-shadow: inset 0 0 12px rgba(56, 189, 248, 0.12), 0 0 8px rgba(56, 189, 248, 0.1);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.nav-item ::deep a:hover {
|
||||
background-color: rgba(88, 166, 255, 0.1);
|
||||
color: #58a6ff;
|
||||
.nav-item ::deep a:hover:not(.active) {
|
||||
background-color: rgba(56, 189, 248, 0.08);
|
||||
color: #e2e8f0;
|
||||
border-color: rgba(56, 189, 248, 0.15);
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
@@ -77,7 +125,7 @@
|
||||
|
||||
.nav-scrollable {
|
||||
/* Allow sidebar to scroll for tall menus */
|
||||
height: calc(100vh - 3.5rem);
|
||||
height: calc(100vh - 3.75rem);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,390 @@
|
||||
@page "/galaxy"
|
||||
@using System.Globalization
|
||||
@inject NavigationManager Navigation
|
||||
|
||||
<PageTitle>Galaxy Map</PageTitle>
|
||||
|
||||
<div class="galaxy-page">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-between mb-3 gap-3">
|
||||
<div>
|
||||
<h1 class="h2 mb-1 text-light fw-bold">Galaxy Map</h1>
|
||||
<p class="text-secondary mb-0 small">Interactive tactical star chart displaying all planetary systems and
|
||||
hyperlane routes.</p>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<div class="map-legend d-flex align-items-center gap-3 px-3 py-2 rounded">
|
||||
<div class="legend-item d-flex align-items-center gap-1">
|
||||
<span class="legend-dot dot-homeworld"></span>
|
||||
<span class="legend-text">Homeworld</span>
|
||||
</div>
|
||||
<div class="legend-item d-flex align-items-center gap-1">
|
||||
<span class="legend-dot dot-core"></span>
|
||||
<span class="legend-text">Core</span>
|
||||
</div>
|
||||
<div class="legend-item d-flex align-items-center gap-1">
|
||||
<span class="legend-dot dot-side"></span>
|
||||
<span class="legend-text">Side</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="map-stats text-secondary small px-3 py-2 rounded">
|
||||
<span><strong>@_systems.Count</strong> Systems</span>
|
||||
<span class="mx-1">•</span>
|
||||
<span><strong>@_connections.Count</strong> Hyperlanes</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="galaxy-map-container" @onmouseleave="OnContainerMouseLeave">
|
||||
<svg viewBox="0 0 1000 1000" class="galaxy-svg" preserveAspectRatio="xMidYMid meet"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<!-- Background Grid Pattern -->
|
||||
<pattern id="space-grid" width="50" height="50" patternUnits="userSpaceOnUse">
|
||||
<path d="M 50 0 L 0 0 0 50" fill="none" stroke="rgba(56, 189, 248, 0.04)" stroke-width="1"/>
|
||||
</pattern>
|
||||
|
||||
<!-- Center Core Glow -->
|
||||
<radialGradient id="galaxy-core-glow" cx="50%" cy="50%" r="50%">
|
||||
<stop offset="0%" stop-color="rgba(56, 189, 248, 0.08)"/>
|
||||
<stop offset="60%" stop-color="rgba(16, 185, 129, 0.03)"/>
|
||||
<stop offset="100%" stop-color="rgba(13, 17, 23, 0)"/>
|
||||
</radialGradient>
|
||||
|
||||
<!-- Glow filters -->
|
||||
<filter id="glow-homeworld" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur in="SourceGraphic" stdDeviation="3" result="blur"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="blur"/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
<filter id="glow-core" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur in="SourceGraphic" stdDeviation="3" result="blur"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="blur"/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
<filter id="glow-side" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur in="SourceGraphic" stdDeviation="2.5" result="blur"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="blur"/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<!-- Map Background & Grid -->
|
||||
<rect width="1000" height="1000" class="map-bg"/>
|
||||
<rect width="1000" height="1000" fill="url(#space-grid)"/>
|
||||
<rect width="1000" height="1000" fill="url(#galaxy-core-glow)"/>
|
||||
|
||||
<!-- Connection Lines (Hyperlanes) -->
|
||||
<g class="hyperlanes">
|
||||
@foreach (var edge in _connections)
|
||||
{
|
||||
var isHighlighted = _hoveredSystem is not null &&
|
||||
(string.Equals(edge.From.Id, _hoveredSystem.Id, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(edge.To.Id, _hoveredSystem.Id, StringComparison.OrdinalIgnoreCase));
|
||||
var isDimmed = _hoveredSystem is not null && !isHighlighted;
|
||||
var lineClass = isHighlighted ? "hyperlane-line hyperlane-highlighted" :
|
||||
isDimmed ? "hyperlane-line hyperlane-dimmed" : "hyperlane-line";
|
||||
<line x1="@SvgNumber(edge.From.X)"
|
||||
y1="@SvgNumber(edge.From.Y)"
|
||||
x2="@SvgNumber(edge.To.X)"
|
||||
y2="@SvgNumber(edge.To.Y)"
|
||||
class="@lineClass"/>
|
||||
}
|
||||
</g>
|
||||
|
||||
<!-- Planetary Nodes -->
|
||||
<g class="planetary-nodes">
|
||||
@foreach (var system in _systems)
|
||||
{
|
||||
var kindClass = GetKindCssClass(system.Kind);
|
||||
var radius = GetNodeRadius(system.Kind);
|
||||
var isHovered = _hoveredSystem is not null && string.Equals(system.Id, _hoveredSystem.Id, StringComparison.OrdinalIgnoreCase);
|
||||
var isNeighbor = _hoveredConnectedIds.Contains(system.Id);
|
||||
var isDimmed = _hoveredSystem is not null && !isHovered && !isNeighbor;
|
||||
var stateClass = isHovered ? "is-hovered" :
|
||||
isNeighbor ? "is-neighbor" :
|
||||
isDimmed ? "is-dimmed" : "";
|
||||
|
||||
<g class="node-group @kindClass @stateClass"
|
||||
transform="translate(@SvgNumber(system.X), @SvgNumber(system.Y))"
|
||||
@onclick="() => OnNodeClick(system.Id)"
|
||||
@onmouseenter="() => OnNodeMouseEnter(system)"
|
||||
@onmouseleave="() => OnNodeMouseLeave(system)"
|
||||
@onfocus="() => OnNodeFocus(system)"
|
||||
@onblur="OnNodeBlur"
|
||||
@onkeydown="e => OnNodeKeyDown(e, system.Id)"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
aria-label="@system.Name (@system.Kind)">
|
||||
|
||||
<!-- Outer aura/glow circle -->
|
||||
<circle r="@SvgNumber(radius + 4)" class="node-aura"/>
|
||||
|
||||
<!-- Main Node Circle -->
|
||||
<circle r="@SvgNumber(radius)" class="node-circle"/>
|
||||
|
||||
<!-- Center core dot for homeworlds and core systems -->
|
||||
@if (system.Kind != StarSystemKind.Side)
|
||||
{
|
||||
<circle r="@SvgNumber(radius * 0.4)" class="node-core-dot"/>
|
||||
}
|
||||
|
||||
<!-- System Name Label -->
|
||||
<text y="@SvgNumber(radius + 10)" class="node-label" text-anchor="middle">@system.Name</text>
|
||||
</g>
|
||||
}
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
<!-- Floating Glassmorphism Hover Card -->
|
||||
@if (_hoveredSystem is not null)
|
||||
{
|
||||
var kindClass = GetKindCssClass(_hoveredSystem.Kind);
|
||||
var higherYields = GetHigherYields(_hoveredSystem);
|
||||
<div class="planet-hover-card @kindClass"
|
||||
style="@GetTooltipStyle(_hoveredSystem)"
|
||||
role="tooltip"
|
||||
aria-live="polite">
|
||||
<div class="card-header-row d-flex align-items-center justify-content-between mb-2">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<span class="system-kind-indicator"></span>
|
||||
<span class="system-title fw-bold text-light">@_hoveredSystem.Name</span>
|
||||
</div>
|
||||
<span class="badge kind-badge">@_hoveredSystem.Kind</span>
|
||||
</div>
|
||||
|
||||
<div class="card-details-grid">
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">Occupation Buff</span>
|
||||
<span class="detail-value @(_hoveredSystem.OccupationBuff != null ? "text-buff" : "text-secondary")">
|
||||
@(_hoveredSystem.OccupationBuff ?? "—")
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">System Mastery</span>
|
||||
<span class="detail-value @(_hoveredSystem.SystemMastery != null ? "text-mastery" : "text-secondary")">
|
||||
@(_hoveredSystem.SystemMastery ?? "—")
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">Yield Bonuses</span>
|
||||
<div class="yield-badges d-flex flex-wrap gap-1 mt-1">
|
||||
@if (higherYields.Count == 0)
|
||||
{
|
||||
<span class="yield-badge yield-standard">Standard</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var y in higherYields)
|
||||
{
|
||||
<span class="yield-badge yield-@y.ToLowerInvariant()">+@y</span>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<span class="detail-label">Connected Systems</span>
|
||||
<span class="badge bg-dark text-secondary border border-secondary border-opacity-25">@_hoveredSystem.ConnectedSystems.Count</span>
|
||||
</div>
|
||||
<div class="connected-systems-list text-secondary small mt-1">
|
||||
@string.Join(" • ", _hoveredSystem.ConnectedSystems)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer-hint mt-2 pt-2 border-top border-secondary border-opacity-25 text-center">
|
||||
<span class="hint-text small">Click system to view full details →</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
|
||||
public sealed record ConnectionEdge(StarSystemData From, StarSystemData To);
|
||||
|
||||
private IReadOnlyList<StarSystemData> _systems = [];
|
||||
private IReadOnlyList<ConnectionEdge> _connections = [];
|
||||
private StarSystemData? _hoveredSystem;
|
||||
private readonly HashSet<string> _hoveredConnectedIds = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_systems = StarSystems.All;
|
||||
_connections = BuildUniqueConnections(_systems);
|
||||
}
|
||||
|
||||
private static IReadOnlyList<ConnectionEdge> BuildUniqueConnections(IReadOnlyList<StarSystemData> allSystems)
|
||||
{
|
||||
var edges = new List<ConnectionEdge>();
|
||||
var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var system in allSystems)
|
||||
{
|
||||
foreach (var targetName in system.ConnectedSystems)
|
||||
{
|
||||
if (!StarSystems.ByName.TryGetValue(targetName, out var target))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var edgeKey = string.Compare(system.Id, target.Id, StringComparison.OrdinalIgnoreCase) < 0
|
||||
? $"{system.Id}::{target.Id}"
|
||||
: $"{target.Id}::{system.Id}";
|
||||
|
||||
if (seen.Add(edgeKey))
|
||||
{
|
||||
edges.Add(new ConnectionEdge(system, target));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return edges;
|
||||
}
|
||||
|
||||
private void SetHoveredSystem(StarSystemData? system)
|
||||
{
|
||||
_hoveredSystem = system;
|
||||
_hoveredConnectedIds.Clear();
|
||||
if (system is not null)
|
||||
{
|
||||
foreach (var connName in system.ConnectedSystems)
|
||||
{
|
||||
if (StarSystems.ByName.TryGetValue(connName, out var target))
|
||||
{
|
||||
_hoveredConnectedIds.Add(target.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnNodeMouseEnter(StarSystemData system)
|
||||
{
|
||||
SetHoveredSystem(system);
|
||||
}
|
||||
|
||||
private void OnNodeMouseLeave(StarSystemData system)
|
||||
{
|
||||
if (_hoveredSystem?.Id == system.Id)
|
||||
{
|
||||
SetHoveredSystem(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnNodeFocus(StarSystemData system)
|
||||
{
|
||||
SetHoveredSystem(system);
|
||||
}
|
||||
|
||||
private void OnNodeBlur()
|
||||
{
|
||||
SetHoveredSystem(null);
|
||||
}
|
||||
|
||||
private void OnContainerMouseLeave()
|
||||
{
|
||||
SetHoveredSystem(null);
|
||||
}
|
||||
|
||||
private void OnNodeKeyDown(KeyboardEventArgs e, string systemId)
|
||||
{
|
||||
if (e.Key is "Enter" or " ")
|
||||
{
|
||||
OnNodeClick(systemId);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnNodeClick(string systemId)
|
||||
{
|
||||
Navigation.NavigateTo($"/StarSystem/{systemId}");
|
||||
}
|
||||
|
||||
private static IReadOnlyList<string> GetHigherYields(StarSystemData system)
|
||||
{
|
||||
var yields = new List<string>(4);
|
||||
if (system.HigherInfluenceYield) yields.Add("Influence");
|
||||
if (system.HigherCreditYield) yields.Add("Credits");
|
||||
if (system.HigherEnergyYield) yields.Add("Energy");
|
||||
if (system.HigherChanceForItems) yields.Add("Items");
|
||||
return yields;
|
||||
}
|
||||
|
||||
private static string GetTooltipStyle(StarSystemData system)
|
||||
{
|
||||
var posX = system.X / 10.0;
|
||||
var posY = system.Y / 10.0;
|
||||
|
||||
string transform;
|
||||
|
||||
if (posX > 65.0)
|
||||
{
|
||||
if (posY < 20.0)
|
||||
{
|
||||
transform = "translate(calc(-100% - 16px), 0%)";
|
||||
}
|
||||
else if (posY > 80.0)
|
||||
{
|
||||
transform = "translate(calc(-100% - 16px), -100%)";
|
||||
}
|
||||
else
|
||||
{
|
||||
transform = "translate(calc(-100% - 16px), -50%)";
|
||||
}
|
||||
}
|
||||
else if (posX < 35.0)
|
||||
{
|
||||
if (posY < 20.0)
|
||||
{
|
||||
transform = "translate(16px, 0%)";
|
||||
}
|
||||
else if (posY > 80.0)
|
||||
{
|
||||
transform = "translate(16px, -100%)";
|
||||
}
|
||||
else
|
||||
{
|
||||
transform = "translate(16px, -50%)";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (posY > 50.0)
|
||||
{
|
||||
transform = "translate(-50%, calc(-100% - 16px))";
|
||||
}
|
||||
else
|
||||
{
|
||||
transform = "translate(-50%, 16px)";
|
||||
}
|
||||
}
|
||||
|
||||
return $"left: {SvgNumber(posX)}%; top: {SvgNumber(posY)}%; transform: {transform};";
|
||||
}
|
||||
|
||||
private static string GetKindCssClass(StarSystemKind kind) => kind switch
|
||||
{
|
||||
StarSystemKind.Homeworld => "kind-homeworld",
|
||||
StarSystemKind.Core => "kind-core",
|
||||
_ => "kind-side"
|
||||
};
|
||||
|
||||
private static double GetNodeRadius(StarSystemKind kind) => kind switch
|
||||
{
|
||||
StarSystemKind.Homeworld => 7.0,
|
||||
StarSystemKind.Core => 6.0,
|
||||
_ => 4.5
|
||||
};
|
||||
|
||||
private static string SvgNumber(double value) => value.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,390 @@
|
||||
.galaxy-page {
|
||||
width: 100%;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.map-legend,
|
||||
.map-stats {
|
||||
background: rgba(22, 27, 34, 0.85);
|
||||
border: 1px solid rgba(56, 189, 248, 0.15);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.legend-dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.dot-homeworld {
|
||||
background-color: #10b981;
|
||||
box-shadow: 0 0 8px rgba(16, 185, 129, 0.7);
|
||||
}
|
||||
|
||||
.dot-core {
|
||||
background-color: #f59e0b;
|
||||
box-shadow: 0 0 8px rgba(245, 158, 11, 0.7);
|
||||
}
|
||||
|
||||
.dot-side {
|
||||
background-color: #38bdf8;
|
||||
box-shadow: 0 0 8px rgba(56, 189, 248, 0.7);
|
||||
}
|
||||
|
||||
.legend-text {
|
||||
font-size: 0.85rem;
|
||||
color: #c9d1d9;
|
||||
}
|
||||
|
||||
.galaxy-map-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 1100px;
|
||||
margin: 0 auto;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
background: #080b10;
|
||||
border: 1px solid rgba(56, 189, 248, 0.2);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6), 0 0 20px rgba(56, 189, 248, 0.05);
|
||||
}
|
||||
|
||||
.galaxy-svg {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
aspect-ratio: 1 / 1;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.map-bg {
|
||||
fill: #080b10;
|
||||
}
|
||||
|
||||
/* Hyperlanes (Connection Lines) */
|
||||
.hyperlane-line {
|
||||
stroke: #3a4d6b;
|
||||
stroke-width: 1.5;
|
||||
stroke-opacity: 0.65;
|
||||
stroke-linecap: round;
|
||||
transition: stroke 0.2s ease, stroke-opacity 0.2s ease, stroke-width 0.2s ease, filter 0.2s ease;
|
||||
}
|
||||
|
||||
.hyperlane-line.hyperlane-highlighted {
|
||||
stroke: #38bdf8;
|
||||
stroke-width: 2.75;
|
||||
stroke-opacity: 1;
|
||||
filter: drop-shadow(0 0 5px rgba(56, 189, 248, 0.85));
|
||||
}
|
||||
|
||||
.hyperlane-line.hyperlane-dimmed {
|
||||
stroke-opacity: 0.15;
|
||||
}
|
||||
|
||||
/* Node Groups */
|
||||
.node-group {
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
transition: opacity 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.node-circle {
|
||||
stroke-width: 1.5;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.node-aura {
|
||||
opacity: 0.35;
|
||||
transform-origin: 0 0;
|
||||
transition: opacity 0.2s ease, r 0.2s ease;
|
||||
}
|
||||
|
||||
.node-core-dot {
|
||||
fill: #ffffff;
|
||||
opacity: 0.9;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.node-label {
|
||||
fill: #8b949e;
|
||||
font-size: 8.5px;
|
||||
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
||||
font-weight: 500;
|
||||
pointer-events: none;
|
||||
letter-spacing: 0.2px;
|
||||
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9), 0 0 2px rgba(0, 0, 0, 0.9);
|
||||
transition: fill 0.2s ease, font-weight 0.2s ease, font-size 0.2s ease;
|
||||
}
|
||||
|
||||
/* Kinds */
|
||||
.kind-homeworld .node-circle {
|
||||
fill: #10b981;
|
||||
stroke: #34d399;
|
||||
}
|
||||
|
||||
.kind-homeworld .node-aura {
|
||||
fill: #10b981;
|
||||
filter: url(#glow-homeworld);
|
||||
}
|
||||
|
||||
.kind-core .node-circle {
|
||||
fill: #f59e0b;
|
||||
stroke: #fbbf24;
|
||||
}
|
||||
|
||||
.kind-core .node-aura {
|
||||
fill: #f59e0b;
|
||||
filter: url(#glow-core);
|
||||
}
|
||||
|
||||
.kind-side .node-circle {
|
||||
fill: #38bdf8;
|
||||
stroke: #7dd3fc;
|
||||
}
|
||||
|
||||
.kind-side .node-aura {
|
||||
fill: #38bdf8;
|
||||
filter: url(#glow-side);
|
||||
}
|
||||
|
||||
/* Node State Styles */
|
||||
.node-group.is-hovered .node-circle,
|
||||
.node-group:focus-visible .node-circle {
|
||||
stroke: #ffffff;
|
||||
stroke-width: 2.75;
|
||||
filter: brightness(1.35) drop-shadow(0 0 6px rgba(255, 255, 255, 0.7));
|
||||
}
|
||||
|
||||
.node-group.is-hovered .node-aura,
|
||||
.node-group:focus-visible .node-aura {
|
||||
opacity: 0.95;
|
||||
animation: pulseAura 1.4s infinite alternate ease-in-out;
|
||||
}
|
||||
|
||||
.node-group.is-hovered .node-label,
|
||||
.node-group:focus-visible .node-label {
|
||||
fill: #ffffff;
|
||||
font-weight: 700;
|
||||
font-size: 9.5px;
|
||||
text-shadow: 0 0 6px rgba(56, 189, 248, 0.9), 0 2px 4px rgba(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
.node-group.is-neighbor .node-aura {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.node-group.is-neighbor .node-label {
|
||||
fill: #f0f6fc;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.node-group.is-neighbor .node-circle {
|
||||
stroke-width: 2;
|
||||
filter: brightness(1.15);
|
||||
}
|
||||
|
||||
.node-group.is-dimmed {
|
||||
opacity: 0.35;
|
||||
}
|
||||
|
||||
/* Pulse Aura Animation */
|
||||
@keyframes pulseAura {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 0.75;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1.35);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Floating Glassmorphism Hover Card */
|
||||
.planet-hover-card {
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
min-width: 260px;
|
||||
max-width: 310px;
|
||||
padding: 14px 16px;
|
||||
background: rgba(13, 17, 23, 0.94);
|
||||
backdrop-filter: blur(16px);
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 16px 36px rgba(0, 0, 0, 0.8), 0 0 24px rgba(56, 189, 248, 0.12);
|
||||
border: 1px solid rgba(56, 189, 248, 0.35);
|
||||
pointer-events: none;
|
||||
animation: popupFadeIn 0.15s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
transition: transform 0.12s ease-out, left 0.12s ease-out, top 0.12s ease-out;
|
||||
}
|
||||
|
||||
@keyframes popupFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
scale: 0.96;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
scale: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.system-kind-indicator {
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.system-title {
|
||||
font-size: 1.05rem;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.kind-badge {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
padding: 3px 8px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
/* Kind Variant Themes for Hover Card */
|
||||
.planet-hover-card.kind-homeworld {
|
||||
border-color: rgba(16, 185, 129, 0.45);
|
||||
box-shadow: 0 16px 36px rgba(0, 0, 0, 0.8), 0 0 24px rgba(16, 185, 129, 0.18);
|
||||
}
|
||||
.planet-hover-card.kind-homeworld .kind-badge {
|
||||
background: rgba(16, 185, 129, 0.2);
|
||||
color: #34d399;
|
||||
border: 1px solid rgba(16, 185, 129, 0.4);
|
||||
}
|
||||
.planet-hover-card.kind-homeworld .system-kind-indicator {
|
||||
background-color: #10b981;
|
||||
box-shadow: 0 0 8px rgba(16, 185, 129, 0.8);
|
||||
}
|
||||
|
||||
.planet-hover-card.kind-core {
|
||||
border-color: rgba(245, 158, 11, 0.45);
|
||||
box-shadow: 0 16px 36px rgba(0, 0, 0, 0.8), 0 0 24px rgba(245, 158, 11, 0.18);
|
||||
}
|
||||
.planet-hover-card.kind-core .kind-badge {
|
||||
background: rgba(245, 158, 11, 0.2);
|
||||
color: #fbbf24;
|
||||
border: 1px solid rgba(245, 158, 11, 0.4);
|
||||
}
|
||||
.planet-hover-card.kind-core .system-kind-indicator {
|
||||
background-color: #f59e0b;
|
||||
box-shadow: 0 0 8px rgba(245, 158, 11, 0.8);
|
||||
}
|
||||
|
||||
.planet-hover-card.kind-side {
|
||||
border-color: rgba(56, 189, 248, 0.45);
|
||||
box-shadow: 0 16px 36px rgba(0, 0, 0, 0.8), 0 0 24px rgba(56, 189, 248, 0.18);
|
||||
}
|
||||
.planet-hover-card.kind-side .kind-badge {
|
||||
background: rgba(56, 189, 248, 0.2);
|
||||
color: #7dd3fc;
|
||||
border: 1px solid rgba(56, 189, 248, 0.4);
|
||||
}
|
||||
.planet-hover-card.kind-side .system-kind-indicator {
|
||||
background-color: #38bdf8;
|
||||
box-shadow: 0 0 8px rgba(56, 189, 248, 0.8);
|
||||
}
|
||||
|
||||
/* Card Details Grid */
|
||||
.card-details-grid {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.detail-row {
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.6px;
|
||||
color: #8b949e;
|
||||
margin-bottom: 2px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
font-size: 0.85rem;
|
||||
display: block;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.text-buff {
|
||||
color: #34d399;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.text-mastery {
|
||||
color: #60a5fa;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Yield Badges */
|
||||
.yield-badges {
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.yield-badge {
|
||||
font-size: 0.72rem;
|
||||
font-weight: 600;
|
||||
padding: 2px 7px;
|
||||
border-radius: 4px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.yield-influence {
|
||||
background: rgba(168, 85, 247, 0.18);
|
||||
color: #c084fc;
|
||||
border: 1px solid rgba(168, 85, 247, 0.4);
|
||||
}
|
||||
|
||||
.yield-credits {
|
||||
background: rgba(234, 179, 8, 0.18);
|
||||
color: #facc15;
|
||||
border: 1px solid rgba(234, 179, 8, 0.4);
|
||||
}
|
||||
|
||||
.yield-energy {
|
||||
background: rgba(6, 182, 212, 0.18);
|
||||
color: #22d3ee;
|
||||
border: 1px solid rgba(6, 182, 212, 0.4);
|
||||
}
|
||||
|
||||
.yield-items {
|
||||
background: rgba(16, 185, 129, 0.18);
|
||||
color: #34d399;
|
||||
border: 1px solid rgba(16, 185, 129, 0.4);
|
||||
}
|
||||
|
||||
.yield-standard {
|
||||
background: rgba(100, 116, 139, 0.15);
|
||||
color: #94a3b8;
|
||||
border: 1px solid rgba(100, 116, 139, 0.3);
|
||||
}
|
||||
|
||||
.connected-systems-list {
|
||||
line-height: 1.4;
|
||||
font-size: 0.76rem;
|
||||
color: #8b949e;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.card-footer-hint {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.hint-text {
|
||||
color: #38bdf8;
|
||||
font-weight: 500;
|
||||
font-size: 0.72rem;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
@@ -1,7 +1,305 @@
|
||||
@page "/"
|
||||
@page "/"
|
||||
@using ZeroSpace.Model
|
||||
|
||||
<PageTitle>Home</PageTitle>
|
||||
<PageTitle>ZeroSpace Database & Command Hub</PageTitle>
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
<div class="home-container">
|
||||
<!-- Hero Banner -->
|
||||
<div class="zs-hero p-4 p-md-5 mb-4 position-relative overflow-hidden">
|
||||
<div class="hero-glow-orb"></div>
|
||||
<div class="position-relative" style="z-index: 1;">
|
||||
<div class="d-flex align-items-center gap-2 mb-2">
|
||||
<span class="badge badge-pill-scifi badge-side">
|
||||
<span class="hero-status-pulse"></span> SYSTEM ONLINE
|
||||
</span>
|
||||
<span class="text-dim fs-7">ZEROSPACE INTEL ARCHIVE v1.0</span>
|
||||
</div>
|
||||
<h1 class="display-6 fw-bold mb-3 hero-title">ZeroSpace Database & Command Hub</h1>
|
||||
<p class="lead text-muted mb-4 hero-subtitle">
|
||||
Comprehensive tactical star map diagnostics, planetary sector dossiers, doctrine masteries, and unit combat intelligence.
|
||||
</p>
|
||||
<div class="d-flex flex-wrap gap-3">
|
||||
<a href="/galaxy" class="btn btn-scifi-primary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 16 16">
|
||||
<circle cx="8" cy="8" r="2.5"/>
|
||||
<circle cx="2.5" cy="4" r="1.5"/>
|
||||
<circle cx="13.5" cy="5" r="1.5"/>
|
||||
<circle cx="4" cy="13" r="1.5"/>
|
||||
<circle cx="12" cy="12" r="1.5"/>
|
||||
<path stroke="currentColor" stroke-width="1.2" stroke-linecap="round" d="M2.5 4L8 8m0 0l5.5-3M8 8l-4 5m4-5l4 4" opacity=".65"/>
|
||||
</svg>
|
||||
<span>Launch Galaxy Map</span>
|
||||
</a>
|
||||
<a href="/StarSystem" class="btn btn-scifi-outline">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 16 16">
|
||||
<circle cx="8" cy="8" r="3.5"/>
|
||||
<path stroke="currentColor" stroke-width="1.2" stroke-linecap="round" d="M8 1v2.5M8 12.5V15M1 8h2.5M12.5 8H15M3 3l1.8 1.8M11.2 11.2l1.8 1.8M3 13l1.8-1.8M11.2 4.8l1.8-1.8" opacity=".75"/>
|
||||
</svg>
|
||||
<span>Browse Systems</span>
|
||||
</a>
|
||||
<a href="/units" class="btn btn-scifi-outline">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 16 16">
|
||||
<circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.3" fill="none"/>
|
||||
<circle cx="8" cy="8" r="2"/>
|
||||
<path stroke="currentColor" stroke-width="1.3" d="M8 0v4M8 12v4M0 8h4M12 8h4"/>
|
||||
</svg>
|
||||
<span>Unit Intel</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Welcome to your new app.
|
||||
<!-- Quick Stats Bar -->
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-6 col-lg-3">
|
||||
<div class="zs-glass-card p-3 d-flex align-items-center gap-3 stat-card">
|
||||
<div class="stat-icon-wrapper icon-cyan">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M8 0a8 8 0 1 0 8 8A8.01 8.01 0 0 0 8 0zm0 14.5a6.5 6.5 0 1 1 6.5-6.5 6.51 6.51 0 0 1-6.5 6.5z"/>
|
||||
<circle cx="8" cy="8" r="3.5"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<div class="fs-4 fw-bold text-white lh-1">@totalSystemsCount</div>
|
||||
<div class="text-dim fs-7 text-uppercase fw-semibold">Star Systems</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-lg-3">
|
||||
<div class="zs-glass-card p-3 d-flex align-items-center gap-3 stat-card">
|
||||
<div class="stat-icon-wrapper icon-emerald">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path stroke="currentColor" stroke-width="1.5" stroke-linecap="round" d="M2 14L8 2l6 12M4 10h8"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<div class="fs-4 fw-bold text-white lh-1">@totalHyperlanesCount+</div>
|
||||
<div class="text-dim fs-7 text-uppercase fw-semibold">Hyperlanes</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-lg-3">
|
||||
<div class="zs-glass-card p-3 d-flex align-items-center gap-3 stat-card">
|
||||
<div class="stat-icon-wrapper icon-purple">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M8 0.5l2.2 4.6 5 .7-3.6 3.6.9 5-4.5-2.4-4.5 2.4.9-5-3.6-3.6 5-.7L8 0.5z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<div class="fs-4 fw-bold text-white lh-1">@totalMasteriesCount</div>
|
||||
<div class="text-dim fs-7 text-uppercase fw-semibold">Masteries</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-lg-3">
|
||||
<div class="zs-glass-card p-3 d-flex align-items-center gap-3 stat-card">
|
||||
<div class="stat-icon-wrapper icon-amber">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" viewBox="0 0 16 16">
|
||||
<circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.3" fill="none"/>
|
||||
<circle cx="8" cy="8" r="2"/>
|
||||
<path stroke="currentColor" stroke-width="1.3" d="M8 0v4M8 12v4M0 8h4M12 8h4"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<div class="fs-4 fw-bold text-white lh-1">@totalUnitsCount</div>
|
||||
<div class="text-dim fs-7 text-uppercase fw-semibold">Combat Units</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature Hub Cards (2x2 Grid) -->
|
||||
<div class="section-header d-flex align-items-center mb-3">
|
||||
<h2 class="h4 mb-0 text-white">Database Modules</h2>
|
||||
<div class="ms-3 flex-grow-1 border-bottom opacity-25"></div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4 mb-4">
|
||||
<!-- Card 1: Galaxy Map -->
|
||||
<div class="col-md-6">
|
||||
<div class="zs-glass-card p-4 h-100 d-flex flex-column feature-card">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<div class="feature-icon-badge icon-cyan">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="currentColor" viewBox="0 0 16 16">
|
||||
<circle cx="8" cy="8" r="2.5"/>
|
||||
<circle cx="2.5" cy="4" r="1.5"/>
|
||||
<circle cx="13.5" cy="5" r="1.5"/>
|
||||
<circle cx="4" cy="13" r="1.5"/>
|
||||
<circle cx="12" cy="12" r="1.5"/>
|
||||
<path stroke="currentColor" stroke-width="1.2" stroke-linecap="round" d="M2.5 4L8 8m0 0l5.5-3M8 8l-4 5m4-5l4 4" opacity=".65"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="badge badge-pill-scifi badge-side">INTERACTIVE SVG</span>
|
||||
</div>
|
||||
<h3 class="h5 fw-bold text-white mb-2">Interactive Galaxy Map</h3>
|
||||
<p class="text-muted fs-6 mb-4 flex-grow-1">
|
||||
Visual SVG star chart rendering all 78 star systems and hyperlane connection networks. Features instant hover intel cards, planetary buff diagnostics, and direct dossier navigation.
|
||||
</p>
|
||||
<div class="feature-meta mb-3 p-2 rounded">
|
||||
<span class="badge badge-homeworld me-1">@homeworldsCount Homeworlds</span>
|
||||
<span class="badge badge-core me-1">@coreCount Core</span>
|
||||
<span class="badge badge-side">@sideCount Side</span>
|
||||
</div>
|
||||
<a href="/galaxy" class="btn btn-scifi-primary w-100 justify-content-center">
|
||||
Launch Galaxy Map
|
||||
<span class="arrow-icon">→</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Card 2: Star Systems Directory -->
|
||||
<div class="col-md-6">
|
||||
<div class="zs-glass-card p-4 h-100 d-flex flex-column feature-card">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<div class="feature-icon-badge icon-amber">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="currentColor" viewBox="0 0 16 16">
|
||||
<circle cx="8" cy="8" r="3.5"/>
|
||||
<path stroke="currentColor" stroke-width="1.2" stroke-linecap="round" d="M8 1v2.5M8 12.5V15M1 8h2.5M12.5 8H15M3 3l1.8 1.8M11.2 11.2l1.8 1.8M3 13l1.8-1.8M11.2 4.8l1.8-1.8" opacity=".75"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="badge badge-pill-scifi badge-core">78 DOSSIERS</span>
|
||||
</div>
|
||||
<h3 class="h5 fw-bold text-white mb-2">Star Systems Directory</h3>
|
||||
<p class="text-muted fs-6 mb-4 flex-grow-1">
|
||||
Complete catalog of planetary systems. Review sector classifications, starting hexite buffs, system masteries, item drop chances, and resource yield bonuses.
|
||||
</p>
|
||||
<div class="feature-meta mb-3 p-2 rounded">
|
||||
<span class="badge badge-pill-scifi badge-side me-1">@buffsCount Occupation Buffs</span>
|
||||
<span class="badge badge-pill-scifi badge-mastery">@higherYieldCount Yield Modifiers</span>
|
||||
</div>
|
||||
<a href="/StarSystem" class="btn btn-scifi-outline w-100 justify-content-center">
|
||||
Browse Star Systems
|
||||
<span class="arrow-icon">→</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Card 3: System Masteries -->
|
||||
<div class="col-md-6">
|
||||
<div class="zs-glass-card p-4 h-100 d-flex flex-column feature-card">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<div class="feature-icon-badge icon-purple">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M8 0.5l2.2 4.6 5 .7-3.6 3.6.9 5-4.5-2.4-4.5 2.4.9-5-3.6-3.6 5-.7L8 0.5z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="badge badge-pill-scifi badge-mastery">@totalMasteriesCount DOCTRINES</span>
|
||||
</div>
|
||||
<h3 class="h5 fw-bold text-white mb-2">System Masteries</h3>
|
||||
<p class="text-muted fs-6 mb-4 flex-grow-1">
|
||||
Strategic progression doctrines offering tiered battle bonuses, economic multipliers, and global faction enhancements with system availability matrices.
|
||||
</p>
|
||||
<div class="feature-meta mb-3 p-2 rounded text-dim fs-7">
|
||||
<span>Includes 3-Tier Multiplier Progression per Doctrine</span>
|
||||
</div>
|
||||
<a href="/SystemMastery" class="btn btn-scifi-outline w-100 justify-content-center">
|
||||
Explore Masteries
|
||||
<span class="arrow-icon">→</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Card 4: Combat Units -->
|
||||
<div class="col-md-6">
|
||||
<div class="zs-glass-card p-4 h-100 d-flex flex-column feature-card">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<div class="feature-icon-badge icon-emerald">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="currentColor" viewBox="0 0 16 16">
|
||||
<circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.3" fill="none"/>
|
||||
<circle cx="8" cy="8" r="2"/>
|
||||
<path stroke="currentColor" stroke-width="1.3" d="M8 0v4M8 12v4M0 8h4M12 8h4"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="badge badge-pill-scifi badge-homeworld">@totalUnitsCount COMBAT UNITS</span>
|
||||
</div>
|
||||
<h3 class="h5 fw-bold text-white mb-2">Unit Roster & Intel</h3>
|
||||
<p class="text-muted fs-6 mb-4 flex-grow-1">
|
||||
Tactical combat unit encyclopedia with detailed Hexite/Flux cost breakdowns, health, DPS-per-cost efficiency metrics, armor classes, and faction hotkeys.
|
||||
</p>
|
||||
<div class="feature-meta mb-3 p-2 rounded text-dim fs-7">
|
||||
<span>Interactive Sortable & Filterable Data Grid</span>
|
||||
</div>
|
||||
<a href="/units" class="btn btn-scifi-outline w-100 justify-content-center">
|
||||
View Unit Intel
|
||||
<span class="arrow-icon">→</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Galaxy Classification Breakdown -->
|
||||
<div class="zs-glass-card p-4 mb-4">
|
||||
<h3 class="h5 fw-bold text-white mb-3 d-flex align-items-center gap-2">
|
||||
<span class="text-cyan">◈</span>
|
||||
<span>Galaxy System Classification</span>
|
||||
</h3>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<div class="classification-box p-3 rounded border-homeworld">
|
||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||
<span class="badge badge-homeworld">Homeworlds</span>
|
||||
<span class="fw-bold text-emerald">@homeworldsCount systems</span>
|
||||
</div>
|
||||
<small class="text-muted">Primary faction command centers with critical strategic value.</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="classification-box p-3 rounded border-core">
|
||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||
<span class="badge badge-core">Core Systems</span>
|
||||
<span class="fw-bold text-amber">@coreCount systems</span>
|
||||
</div>
|
||||
<small class="text-muted">High-density central systems connecting major hyperlane corridors.</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="classification-box p-3 rounded border-side">
|
||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||
<span class="badge badge-side">Side Sectors</span>
|
||||
<span class="fw-bold text-cyan">@sideCount systems</span>
|
||||
</div>
|
||||
<small class="text-muted">Outer rim border systems offering specialized tactical yields.</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private int totalSystemsCount;
|
||||
private int homeworldsCount;
|
||||
private int coreCount;
|
||||
private int sideCount;
|
||||
private int totalHyperlanesCount;
|
||||
private int totalMasteriesCount;
|
||||
private int totalUnitsCount;
|
||||
private int buffsCount;
|
||||
private int higherYieldCount;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
totalSystemsCount = StarSystems.All.Count;
|
||||
homeworldsCount = StarSystems.All.Count(s => s.Kind == StarSystemKind.Homeworld);
|
||||
coreCount = StarSystems.All.Count(s => s.Kind == StarSystemKind.Core);
|
||||
sideCount = StarSystems.All.Count(s => s.Kind == StarSystemKind.Side);
|
||||
|
||||
// Calculate unique hyperlanes
|
||||
var edges = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var s in StarSystems.All)
|
||||
{
|
||||
foreach (var connected in s.ConnectedSystems)
|
||||
{
|
||||
var edgeKey = string.Compare(s.Id, connected, StringComparison.OrdinalIgnoreCase) < 0
|
||||
? $"{s.Id}--{connected}"
|
||||
: $"{connected}--{s.Id}";
|
||||
edges.Add(edgeKey);
|
||||
}
|
||||
}
|
||||
totalHyperlanesCount = edges.Count;
|
||||
|
||||
totalMasteriesCount = SystemMasteries.All.Count;
|
||||
totalUnitsCount = ZeroSpace.Model.Units.All.Count;
|
||||
buffsCount = StarSystems.All.Count(s => !string.IsNullOrWhiteSpace(s.OccupationBuff));
|
||||
higherYieldCount = StarSystems.All.Count(s => s.HigherCreditYield || s.HigherInfluenceYield || s.HigherEnergyYield || s.HigherChanceForItems);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
.home-container {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.hero-glow-orb {
|
||||
position: absolute;
|
||||
width: 350px;
|
||||
height: 350px;
|
||||
top: -100px;
|
||||
right: -50px;
|
||||
background: radial-gradient(circle, rgba(56, 189, 248, 0.18) 0%, rgba(16, 185, 129, 0.05) 50%, transparent 70%);
|
||||
border-radius: 50%;
|
||||
filter: blur(40px);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
background: linear-gradient(135deg, #ffffff 40%, #7dd3fc 80%, #38bdf8 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
max-width: 750px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.hero-status-pulse {
|
||||
display: inline-block;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
background-color: #38bdf8;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 6px #38bdf8;
|
||||
animation: statusPulse 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes statusPulse {
|
||||
0% {
|
||||
transform: scale(0.9);
|
||||
box-shadow: 0 0 0 0 rgba(56, 189, 248, 0.7);
|
||||
}
|
||||
70% {
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 0 0 6px rgba(56, 189, 248, 0);
|
||||
}
|
||||
100% {
|
||||
transform: scale(0.9);
|
||||
box-shadow: 0 0 0 0 rgba(56, 189, 248, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.stat-card:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.stat-icon-wrapper {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.icon-cyan {
|
||||
background: rgba(56, 189, 248, 0.15);
|
||||
color: #38bdf8;
|
||||
border: 1px solid rgba(56, 189, 248, 0.3);
|
||||
box-shadow: 0 0 10px rgba(56, 189, 248, 0.2);
|
||||
}
|
||||
|
||||
.icon-emerald {
|
||||
background: rgba(16, 185, 129, 0.15);
|
||||
color: #10b981;
|
||||
border: 1px solid rgba(16, 185, 129, 0.3);
|
||||
box-shadow: 0 0 10px rgba(16, 185, 129, 0.2);
|
||||
}
|
||||
|
||||
.icon-amber {
|
||||
background: rgba(245, 158, 11, 0.15);
|
||||
color: #f59e0b;
|
||||
border: 1px solid rgba(245, 158, 11, 0.3);
|
||||
box-shadow: 0 0 10px rgba(245, 158, 11, 0.2);
|
||||
}
|
||||
|
||||
.icon-purple {
|
||||
background: rgba(167, 139, 250, 0.15);
|
||||
color: #a78bfa;
|
||||
border: 1px solid rgba(167, 139, 250, 0.3);
|
||||
box-shadow: 0 0 10px rgba(167, 139, 250, 0.2);
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
position: relative;
|
||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.7), 0 0 20px rgba(56, 189, 248, 0.15);
|
||||
border-color: rgba(56, 189, 248, 0.4);
|
||||
}
|
||||
|
||||
.feature-icon-badge {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.feature-meta {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
font-size: 1.1rem;
|
||||
line-height: 1;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.feature-card:hover .arrow-icon {
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.classification-box {
|
||||
background: rgba(0, 0, 0, 0.35);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.classification-box:hover {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.border-homeworld {
|
||||
border-left: 3px solid #10b981;
|
||||
}
|
||||
|
||||
.border-core {
|
||||
border-left: 3px solid #f59e0b;
|
||||
}
|
||||
|
||||
.border-side {
|
||||
border-left: 3px solid #38bdf8;
|
||||
}
|
||||
|
||||
.text-cyan {
|
||||
color: #38bdf8;
|
||||
}
|
||||
|
||||
.text-emerald {
|
||||
color: #10b981;
|
||||
}
|
||||
|
||||
.text-amber {
|
||||
color: #f59e0b;
|
||||
}
|
||||
|
||||
.text-purple {
|
||||
color: #a78bfa;
|
||||
}
|
||||
|
||||
.text-dim {
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.fs-7 {
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
@@ -12,8 +12,11 @@ else
|
||||
{
|
||||
<div class="section-header d-flex align-items-center mb-4">
|
||||
<h1 class="mb-0">@system.Name</h1>
|
||||
<span class="badge bg-primary ms-3">@system.Kind</span>
|
||||
<span class="badge @KindBadgeClass(system.Kind) ms-3">@system.Kind</span>
|
||||
<div class="ms-3 flex-grow-1 border-bottom opacity-25"></div>
|
||||
<a href="/galaxy" class="btn btn-sm btn-scifi-outline ms-2 d-none d-md-inline-flex">
|
||||
<span>View on Map</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<dl class="row">
|
||||
@@ -83,6 +86,14 @@ else
|
||||
system = StarSystems.All.FirstOrDefault(s => s.Id.Equals(Id, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private static string KindBadgeClass(StarSystemKind kind) => kind switch
|
||||
{
|
||||
StarSystemKind.Homeworld => "badge-homeworld",
|
||||
StarSystemKind.Core => "badge-core",
|
||||
StarSystemKind.Side => "badge-side",
|
||||
_ => "badge-side"
|
||||
};
|
||||
|
||||
private static string YieldText(StarSystemData s)
|
||||
{
|
||||
var yields = new List<string>();
|
||||
|
||||
@@ -5,18 +5,45 @@
|
||||
<div class="section-header d-flex align-items-center mb-4">
|
||||
<h1 class="mb-0">Star Systems</h1>
|
||||
<div class="ms-3 flex-grow-1 border-bottom opacity-25"></div>
|
||||
<a href="/galaxy" class="btn btn-sm btn-scifi-primary ms-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="me-1" viewBox="0 0 16 16">
|
||||
<circle cx="8" cy="8" r="2.5"/>
|
||||
<circle cx="2.5" cy="4" r="1.5"/>
|
||||
<circle cx="13.5" cy="5" r="1.5"/>
|
||||
<path stroke="currentColor" stroke-width="1.2" stroke-linecap="round" d="M2.5 4L8 8m0 0l5.5-3" opacity=".65"/>
|
||||
</svg>
|
||||
<span>Galaxy Map</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@foreach (var kind in Enum.GetValues<StarSystemKind>())
|
||||
{
|
||||
var systems = StarSystems.All.Where(s => s.Kind == kind).OrderBy(s => s.Name).ToList();
|
||||
<h2>@kind <span class="text-muted fs-5">(@systems.Count)</span></h2>
|
||||
<ul class="list-unstyled row mb-4">
|
||||
@foreach (var system in systems)
|
||||
{
|
||||
<li class="col-md-4 col-lg-3 mb-1">
|
||||
<a href="/StarSystem/@system.Id">@system.Name</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
var badgeClass = kind switch {
|
||||
StarSystemKind.Homeworld => "badge-homeworld",
|
||||
StarSystemKind.Core => "badge-core",
|
||||
StarSystemKind.Side => "badge-side",
|
||||
_ => "badge-side"
|
||||
};
|
||||
|
||||
<div class="mb-4">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<h2 class="h4 mb-0 text-white">@kind Systems</h2>
|
||||
<span class="badge @badgeClass">@systems.Count</span>
|
||||
</div>
|
||||
<ul class="list-unstyled row g-2">
|
||||
@foreach (var system in systems)
|
||||
{
|
||||
<li class="col-md-4 col-lg-3">
|
||||
<a class="d-block p-2 rounded zs-glass-card text-decoration-none" href="/StarSystem/@system.Id">
|
||||
<span class="fw-semibold text-white">@system.Name</span>
|
||||
@if (!string.IsNullOrWhiteSpace(system.OccupationBuff))
|
||||
{
|
||||
<div class="small text-dim text-truncate" title="@system.OccupationBuff">@system.OccupationBuff</div>
|
||||
}
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -4,15 +4,19 @@
|
||||
|
||||
<div class="section-header d-flex align-items-center mb-4">
|
||||
<h1 class="mb-0">System Masteries</h1>
|
||||
<span class="badge badge-mastery ms-3">@SystemMasteries.All.Count Doctrines</span>
|
||||
<div class="ms-3 flex-grow-1 border-bottom opacity-25"></div>
|
||||
</div>
|
||||
|
||||
<div class="list-group">
|
||||
<div class="list-group gap-2">
|
||||
@foreach (var mastery in SystemMasteries.All.OrderBy(m => m.Name))
|
||||
{
|
||||
<a class="list-group-item list-group-item-action" href="/SystemMastery/@mastery.Id">
|
||||
<div class="fw-bold">@mastery.Name</div>
|
||||
<small class="text-muted">@mastery.Levels[0] · available on @mastery.AvailableSystems.Count systems</small>
|
||||
<a class="list-group-item list-group-item-action rounded border p-3 zs-glass-card text-decoration-none" href="/SystemMastery/@mastery.Id">
|
||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||
<span class="fw-bold text-white fs-5">@mastery.Name</span>
|
||||
<span class="badge badge-pill-scifi badge-side">@mastery.AvailableSystems.Count systems</span>
|
||||
</div>
|
||||
<div class="text-muted small">@mastery.Levels[0]</div>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,25 @@
|
||||
:root {
|
||||
--zs-bg-base: #080c14;
|
||||
--zs-bg-surface: #0f172a;
|
||||
--zs-bg-card: rgba(15, 23, 42, 0.75);
|
||||
--zs-bg-card-hover: rgba(30, 41, 59, 0.85);
|
||||
--zs-border-subtle: rgba(56, 189, 248, 0.15);
|
||||
--zs-border-glow: rgba(56, 189, 248, 0.45);
|
||||
--zs-cyan: #38bdf8;
|
||||
--zs-emerald: #10b981;
|
||||
--zs-amber: #f59e0b;
|
||||
--zs-purple: #a78bfa;
|
||||
--zs-rose: #f43f5e;
|
||||
--zs-text-main: #f0f6fc;
|
||||
--zs-text-muted: #94a3b8;
|
||||
--zs-text-dim: #64748b;
|
||||
}
|
||||
|
||||
html, body {
|
||||
font-family: 'Segoe UI', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
background-color: #0d1117;
|
||||
color: #c9d1d9;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
||||
background-color: var(--zs-bg-base);
|
||||
color: var(--zs-text-main);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1:focus {
|
||||
@@ -9,25 +27,210 @@ h1:focus {
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: #e6edf3;
|
||||
color: #ffffff;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
a, .btn-link {
|
||||
color: #58a6ff;
|
||||
color: var(--zs-cyan);
|
||||
text-decoration: none;
|
||||
transition: color 0.15s ease, text-shadow 0.15s ease;
|
||||
}
|
||||
|
||||
a:hover, .btn-link:hover {
|
||||
color: #7dd3fc;
|
||||
text-shadow: 0 0 8px rgba(56, 189, 248, 0.5);
|
||||
}
|
||||
|
||||
p {
|
||||
color: #8b949e;
|
||||
color: var(--zs-text-muted);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Custom Scrollbars */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: #080c14;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #1e293b;
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(56, 189, 248, 0.2);
|
||||
}
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #334155;
|
||||
border-color: rgba(56, 189, 248, 0.4);
|
||||
}
|
||||
|
||||
/* Sci-Fi Glass Panels & Cards */
|
||||
.zs-glass-card {
|
||||
background: var(--zs-bg-card);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid var(--zs-border-subtle);
|
||||
border-radius: 12px;
|
||||
transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
border-color 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.zs-glass-card:hover {
|
||||
border-color: var(--zs-border-glow);
|
||||
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.8), 0 0 20px rgba(56, 189, 248, 0.15);
|
||||
}
|
||||
|
||||
.zs-hero {
|
||||
background: radial-gradient(ellipse at top right, rgba(56, 189, 248, 0.12) 0%, transparent 60%),
|
||||
radial-gradient(ellipse at bottom left, rgba(16, 185, 129, 0.08) 0%, transparent 60%),
|
||||
rgba(15, 23, 42, 0.85);
|
||||
backdrop-filter: blur(16px);
|
||||
border: 1px solid rgba(56, 189, 248, 0.25);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
/* Sci-Fi Badges */
|
||||
.badge-homeworld {
|
||||
background: rgba(16, 185, 129, 0.18);
|
||||
color: #34d399;
|
||||
border: 1px solid rgba(16, 185, 129, 0.45);
|
||||
box-shadow: 0 0 8px rgba(16, 185, 129, 0.25);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.badge-core {
|
||||
background: rgba(245, 158, 11, 0.18);
|
||||
color: #fbbf24;
|
||||
border: 1px solid rgba(245, 158, 11, 0.45);
|
||||
box-shadow: 0 0 8px rgba(245, 158, 11, 0.25);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.badge-side {
|
||||
background: rgba(56, 189, 248, 0.18);
|
||||
color: #7dd3fc;
|
||||
border: 1px solid rgba(56, 189, 248, 0.45);
|
||||
box-shadow: 0 0 8px rgba(56, 189, 248, 0.25);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.badge-mastery {
|
||||
background: rgba(167, 139, 250, 0.18);
|
||||
color: #c4b5fd;
|
||||
border: 1px solid rgba(167, 139, 250, 0.45);
|
||||
box-shadow: 0 0 8px rgba(167, 139, 250, 0.25);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.badge-pill-scifi {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
padding: 0.25rem 0.65rem;
|
||||
border-radius: 9999px;
|
||||
font-size: 0.75rem;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
|
||||
/* Sci-Fi Buttons */
|
||||
.btn-scifi-primary {
|
||||
background: linear-gradient(135deg, #0284c7 0%, #0369a1 100%);
|
||||
color: #ffffff;
|
||||
border: 1px solid #38bdf8;
|
||||
box-shadow: 0 0 16px rgba(56, 189, 248, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.2);
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.04em;
|
||||
padding: 0.6rem 1.4rem;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-scifi-primary:hover {
|
||||
background: linear-gradient(135deg, #0369a1 0%, #075985 100%);
|
||||
color: #ffffff;
|
||||
box-shadow: 0 0 24px rgba(56, 189, 248, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.3);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn-scifi-outline {
|
||||
background: rgba(15, 23, 42, 0.6);
|
||||
color: var(--zs-cyan);
|
||||
border: 1px solid rgba(56, 189, 248, 0.4);
|
||||
box-shadow: 0 0 8px rgba(56, 189, 248, 0.15);
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.04em;
|
||||
padding: 0.6rem 1.4rem;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-scifi-outline:hover {
|
||||
background: rgba(56, 189, 248, 0.15);
|
||||
color: #ffffff;
|
||||
border-color: #38bdf8;
|
||||
box-shadow: 0 0 16px rgba(56, 189, 248, 0.35);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* List group dark theme styling */
|
||||
.list-group-item {
|
||||
background-color: rgba(15, 23, 42, 0.7);
|
||||
border-color: rgba(56, 189, 248, 0.12);
|
||||
color: var(--zs-text-main);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.list-group-item-action:hover, .list-group-item-action:focus {
|
||||
background-color: rgba(30, 41, 59, 0.8);
|
||||
border-color: rgba(56, 189, 248, 0.3);
|
||||
color: #38bdf8;
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
/* Tables in dark theme */
|
||||
.table {
|
||||
--bs-table-bg: transparent;
|
||||
--bs-table-color: var(--zs-text-main);
|
||||
--bs-table-border-color: rgba(56, 189, 248, 0.15);
|
||||
}
|
||||
|
||||
.table th {
|
||||
color: var(--zs-cyan);
|
||||
font-weight: 600;
|
||||
border-bottom: 2px solid rgba(56, 189, 248, 0.3);
|
||||
}
|
||||
|
||||
/* Section Header Cyber Line */
|
||||
.section-header h1 {
|
||||
font-size: 1.75rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.section-header .border-bottom {
|
||||
border-color: rgba(56, 189, 248, 0.2) !important;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
background-color: #0284c7;
|
||||
border-color: #0369a1;
|
||||
}
|
||||
|
||||
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
|
||||
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
|
||||
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #0284c7;
|
||||
}
|
||||
|
||||
.content {
|
||||
@@ -43,14 +246,16 @@ p {
|
||||
}
|
||||
|
||||
.validation-message {
|
||||
color: red;
|
||||
color: #f43f5e;
|
||||
}
|
||||
|
||||
#blazor-error-ui {
|
||||
color-scheme: light only;
|
||||
background: lightyellow;
|
||||
color-scheme: dark only;
|
||||
background: #1e1b4b;
|
||||
color: #f87171;
|
||||
border-top: 1px solid rgba(244, 63, 94, 0.4);
|
||||
bottom: 0;
|
||||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.5);
|
||||
box-sizing: border-box;
|
||||
display: none;
|
||||
left: 0;
|
||||
@@ -65,10 +270,11 @@ p {
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
top: 0.5rem;
|
||||
color: #f87171;
|
||||
}
|
||||
|
||||
.blazor-error-boundary {
|
||||
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
|
||||
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #881337;
|
||||
padding: 1rem 1rem 1rem 3.7rem;
|
||||
color: white;
|
||||
}
|
||||
@@ -88,16 +294,17 @@ p {
|
||||
|
||||
.loading-progress circle {
|
||||
fill: none;
|
||||
stroke: #e0e0e0;
|
||||
stroke: #1e293b;
|
||||
stroke-width: 0.6rem;
|
||||
transform-origin: 50% 50%;
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
.loading-progress circle:last-child {
|
||||
stroke: #1b6ec2;
|
||||
stroke: #38bdf8;
|
||||
stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
|
||||
transition: stroke-dasharray 0.05s ease-in-out;
|
||||
filter: drop-shadow(0 0 6px #38bdf8);
|
||||
}
|
||||
|
||||
.loading-progress-text {
|
||||
@@ -105,6 +312,8 @@ p {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
|
||||
color: #38bdf8;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.loading-progress-text:after {
|
||||
@@ -112,7 +321,11 @@ p {
|
||||
}
|
||||
|
||||
code {
|
||||
color: #c02d76;
|
||||
color: #f43f5e;
|
||||
background: rgba(244, 63, 94, 0.1);
|
||||
padding: 0.15rem 0.35rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
|
||||
|
||||
Reference in New Issue
Block a user