feat: Introduce full-screen navigation menu, refresh overall UI styling, and simplify the home page content.

This commit is contained in:
Ho Ngoc Hai
2026-01-19 10:50:58 +07:00
parent b022eb1071
commit caf1a06dc8
3 changed files with 461 additions and 619 deletions

View File

@@ -5,40 +5,60 @@
<MudDialogProvider />
<MudSnackbarProvider />
<!-- Full Screen Navigation Overlay -->
<div class="nav-overlay @(_menuOpen ? "open" : "")">
<div class="d-flex flex-column align-center">
<a href="/" class="nav-overlay-link" @onclick="CloseMenu">Home</a>
<a href="/solutions" class="nav-overlay-link" @onclick="CloseMenu">Solutions</a>
<a href="/enterprise" class="nav-overlay-link" @onclick="CloseMenu">Enterprise</a>
<a href="/company" class="nav-overlay-link" @onclick="CloseMenu">Company</a>
<div class="mt-8">
<button class="btn-enterprise-primary" @onclick="CloseMenu">Get in Touch</button>
</div>
</div>
<!-- Close Button Absolute -->
<MudIconButton Icon="@Icons.Material.Rounded.Close"
Color="Color.Inherit"
Size="Size.Large"
OnClick="@ToggleMenu"
Style="position: absolute; top: 24px; right: 24px;"
Class="z-50" />
</div>
<MudLayout>
<MudAppBar Elevation="0" Class="border-b border-solid mud-border-lines-default" Fixed="true" Color="Color.Default" Style="backdrop-filter: blur(12px);">
<MudIconButton Icon="@Icons.Material.Rounded.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@ToggleDrawer" Class="d-md-none" />
<MudText Typo="Typo.h6" Class="ml-3 font-weight-bold" Style="font-family: 'Inter', sans-serif;">GoodGo</MudText>
<MudAppBar Elevation="0" Fixed="true" Color="Color.Transparent" Style="backdrop-filter: blur(12px); border-bottom: 1px solid var(--border-subtle);">
<!-- Logo -->
<MudText Typo="Typo.h6" Class="font-weight-bold" Style="font-family: var(--font-heading); color: var(--text-primary);">
GOODGO
</MudText>
<MudSpacer />
<!-- Desktop Navigation -->
<!-- Desktop Navigation & Actions (Hidden on Mobile) -->
<div class="d-none d-md-flex align-center gap-4">
<MudStack Row="true" Spacing="4" Class="mr-4">
<MudLink Href="/" Color="Color.Inherit" Underline="Underline.None" Class="mud-nav-link px-3 py-2">Home</MudLink>
<MudLink Href="/features" Color="Color.Inherit" Underline="Underline.None" Class="mud-nav-link px-3 py-2">Features</MudLink>
<MudLink Href="/enterprise" Color="Color.Inherit" Underline="Underline.None" Class="mud-nav-link px-3 py-2">Enterprise</MudLink>
<MudLink Href="/pricing" Color="Color.Inherit" Underline="Underline.None" Class="mud-nav-link px-3 py-2">Pricing</MudLink>
</MudStack>
<!-- Action Group (Theme + Menu) -->
<MudStack Row="true" Spacing="1" AlignItems="AlignItems.Center">
<!-- Theme Toggle -->
<button class="theme-toggle mr-2" @onclick="ToggleDarkMode" aria-label="Toggle theme">
@if (_isDarkMode)
{
<MudIcon Icon="@Icons.Material.Rounded.LightMode" Size="Size.Small" />
}
else
{
<MudIcon Icon="@Icons.Material.Rounded.DarkMode" Size="Size.Small" />
}
</button>
<MudStack Row="true" Spacing="2">
<MudButton Variant="Variant.Outlined" Color="Color.Inherit" Class="rounded-lg">Sign in</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="rounded-lg">Download</MudButton>
</MudStack>
</div>
<MudIconButton Icon="@(_isDarkMode ? Icons.Material.Rounded.LightMode : Icons.Material.Rounded.DarkMode)"
Color="Color.Inherit"
Class="ml-2"
OnClick="@ToggleDarkMode" />
<!-- Hamburger Menu (Unified) -->
<MudIconButton Icon="@Icons.Material.Rounded.Menu"
Color="Color.Default"
Edge="Edge.End"
OnClick="@ToggleMenu"
Style="color: var(--text-primary);" />
</MudStack>
</MudAppBar>
<MudDrawer @bind-Open="_drawerOpen" Variant="@DrawerVariant.Temporary" Elevation="1">
<MudDrawerHeader>
<MudText Typo="Typo.h6">GoodGo</MudText>
</MudDrawerHeader>
<NavMenu />
</MudDrawer>
<MudMainContent Class="pt-16">
@Body
</MudMainContent>
@@ -47,57 +67,46 @@
@code {
[Inject] private IJSRuntime JSRuntime { get; set; } = default!;
private bool _drawerOpen = false;
private bool _menuOpen = false;
private bool _isDarkMode = false;
private MudTheme _theme = new()
{
PaletteLight = new PaletteLight()
{
Primary = "#18181b", // Zinc-900 (almost black)
AppbarBackground = "#f7f7f4",
// Mapping to Enterprise Primitives
Primary = "#18181b",
AppbarBackground = "rgba(255,255,255,0.0)", // Transparent for glass effect
AppbarText = "#18181b",
Background = "#f7f7f4",
Background = "#fafafa", // Neutral-50
Surface = "#ffffff",
DrawerBackground = "#f7f7f4",
DrawerText = "#52525b", // Zinc-600
TextPrimary = "#18181b",
TextSecondary = "#52525b",
ActionDefault = "#52525b",
Divider = "#e4e4e7", // Zinc-200
LinesDefault = "#e4e4e7"
ActionDefault = "#18181b",
LinesDefault = "#e4e4e7" // Neutral-200
},
PaletteDark = new PaletteDark()
{
Primary = "#fafafa", // Zinc-50
PrimaryContrastText = "#18181b", // Zinc-900 (Black text on White Primary)
AppbarBackground = "#09090b", // Zinc-950
Primary = "#fafafa",
PrimaryContrastText = "#18181b",
AppbarBackground = "rgba(9,9,11,0.0)", // Transparent for glass effect
AppbarText = "#fafafa",
Background = "#09090b",
Surface = "#18181b", // Zinc-900
DrawerBackground = "#09090b", // Zinc-950 (Match Body Background)
DrawerText = "#fafafa", // Zinc-50 (Ligher text for better contrast)
Background = "#09090b", // Neutral-950
Surface = "#18181b", // Neutral-900
TextPrimary = "#fafafa",
TextSecondary = "#a1a1aa",
ActionDefault = "#a1a1aa",
Divider = "#27272a", // Zinc-800
LinesDefault = "#27272a"
ActionDefault = "#fafafa",
LinesDefault = "#27272a" // Neutral-800
},
LayoutProperties = new LayoutProperties()
{
DefaultBorderRadius = "6px",
AppbarHeight = "64px"
}
};
protected override void OnInitialized()
private void ToggleMenu()
{
_theme.Typography.Default.FontFamily = new[] { "Inter", "Helvetica", "Arial", "sans-serif" };
_menuOpen = !_menuOpen;
}
private void ToggleDrawer()
private void CloseMenu()
{
_drawerOpen = !_drawerOpen;
_menuOpen = false;
}
private async Task ToggleDarkMode()

View File

@@ -1,75 +1,129 @@
@page "/"
<PageTitle>GoodGo - The AI Code Editor</PageTitle>
<PageTitle>GoodGo - Enterprise AI Solutions</PageTitle>
<MudContainer MaxWidth="MaxWidth.Large" Class="px-4 py-16">
<!-- Hero Section -->
<MudStack AlignItems="AlignItems.Center" Spacing="6" Class="py-12 text-center">
<MudText Typo="Typo.h1" Class="hero-title" Style="font-weight: 700; line-height: 1.1; letter-spacing: -0.02em;">
The AI Code Editor
</MudText>
<MudText Typo="Typo.h5" Class="hero-subtitle mb-6" Style="color: var(--text-secondary); max-width: 600px;">
Built to make you extraordinarily productive, GoodGo is the best way to code with AI.
</MudText>
<MudStack Row="true" Spacing="3" Class="justify-center">
<MudButton Variant="Variant.Filled" Color="Color.Primary" Size="Size.Large" Class="px-8 py-3 rounded-lg"
Style="font-weight: 600; font-size: 1.1rem;">
Download for Mac
</MudButton>
<MudButton Variant="Variant.Outlined" Color="Color.Inherit" Size="Size.Large" Class="px-8 py-3 rounded-lg"
Style="border-color: var(--border-default); font-weight: 500;">
Read the Manifesto
</MudButton>
</MudStack>
<MudText Typo="Typo.caption" Class="mt-4" Style="color: var(--text-tertiary);">
Free to use. No credit card required.
</MudText>
</MudStack>
<!-- Demo / Visual Section -->
<div class="mt-12 mx-auto rounded-xl overflow-hidden glass-card" style="max-width: 1000px; aspect-ratio: 16/9; display: flex; align-items: center; justify-content: center; border: 1px solid var(--border-default);">
<MudText Typo="Typo.h6" Style="color: var(--text-tertiary);">[ Interactive Demo Placeholder ]</MudText>
<!-- Hero Section -->
<section class="hero-section">
<h1 class="hero-headline">
Powering the Next Generation <br />
<span style="background: var(--brand-gradient); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;">of Digital Enterprise</span>
</h1>
<p class="hero-subtext">
Secure, scalable, and intelligent infrastructure for modern businesses.
Unlock potential with our AI-driven ecosystem.
</p>
<div class="hero-actions">
<a href="/solutions" class="btn-enterprise-primary">Explore Solutions</a>
<a href="/contact" class="btn-enterprise-secondary">Contact Sales</a>
</div>
<!-- Features Section -->
<MudGrid Class="mt-24" Spacing="4">
<MudItem xs="12" md="4">
<div class="feature-card p-6 rounded-lg" style="border: 1px solid var(--border-default);">
<MudIcon Icon="@Icons.Material.Rounded.AutoFixHigh" Size="Size.Large" Class="mb-4" />
<MudText Typo="Typo.h6" Class="mb-2 font-weight-bold">Tab to Autocomplete</MudText>
<MudText Style="color: var(--text-secondary);">GoodGo predicts your next edit, so you can just hit tab to fly through changes.</MudText>
</div>
</MudItem>
<MudItem xs="12" md="4">
<div class="feature-card p-6 rounded-lg" style="border: 1px solid var(--border-default);">
<MudIcon Icon="@Icons.Material.Rounded.ChatBubble" Size="Size.Large" Class="mb-4" />
<MudText Typo="Typo.h6" Class="mb-2 font-weight-bold">Chat with Your Codebase</MudText>
<MudText Style="color: var(--text-secondary);">No more alt-tabbing. Get answers to codebase-wide questions strictly from your editor.</MudText>
</div>
</MudItem>
<MudItem xs="12" md="4">
<div class="feature-card p-6 rounded-lg" style="border: 1px solid var(--border-default);">
<MudIcon Icon="@Icons.Material.Rounded.Security" Size="Size.Large" Class="mb-4" />
<MudText Typo="Typo.h6" Class="mb-2 font-weight-bold">Privacy First</MudText>
<MudText Style="color: var(--text-secondary);">Your code never leaves your machine unless you explicitly choose to use cloud AI models.</MudText>
</div>
</MudItem>
</MudGrid>
</MudContainer>
<div class="image-placeholder hero-image-placeholder">
<span>Hero Image Placeholder</span>
</div>
<!--
IMAGE PROMPT:
A high-tech, abstract representations of a "digital ecosystem."
Cinematic lighting, dark mode aesthetic, deep blues and blacks with neon cyan accents.
3D geometric shapes connecting in a network, symbolizing blockchain and AI integration.
Clean, minimalist, premium texture. Ultrawide aspect ratio.
-->
</section>
<!-- Trust Section -->
<section class="trust-section">
<div class="trust-label">Trusted by 500+ Innovative Companies</div>
<div class="d-flex justify-center gap-8 mt-4" style="opacity: 0.5;">
<!-- Logos would go here. Using text placeholders for now. -->
<MudText Typo="Typo.h5" Style="font-weight: 700; color: var(--text-tertiary);">ACME Corp</MudText>
<MudText Typo="Typo.h5" Style="font-weight: 700; color: var(--text-tertiary);">GlobalTech</MudText>
<MudText Typo="Typo.h5" Style="font-weight: 700; color: var(--text-tertiary);">Nebula</MudText>
<MudText Typo="Typo.h5" Style="font-weight: 700; color: var(--text-tertiary);">Vertex</MudText>
</div>
</section>
<!-- Solutions Grid -->
<section class="container">
<div class="solutions-grid">
<!-- Service 1: AI & Blockchain -->
<div class="solution-card">
<div class="image-placeholder service-icon-placeholder">
<MudIcon Icon="@Icons.Material.Filled.Security" Size="Size.Large" />
</div>
<!--
IMAGE PROMPT:
3D icon of a glowing digital shield interwoven with neural network nodes.
Isometric view. High gloss finish. Blue and silver color palette.
Symbolizing security and intelligence. White background.
-->
<h3 class="solution-title">AI & Blockchain Core</h3>
<p class="solution-desc">
Decentralized security meets machine learning. Our core infrastructure ensures immutable data integrity while automating complex decision-making processes.
</p>
<a href="/solutions/core" class="nav-overlay-link" style="font-size: 1rem;">Learn more &rarr;</a>
</div>
<!-- Service 2: Data-Driven Marketing -->
<div class="solution-card">
<div class="image-placeholder service-icon-placeholder">
<MudIcon Icon="@Icons.Material.Filled.TrendingUp" Size="Size.Large" />
</div>
<!--
IMAGE PROMPT:
3D icon of an ascending abstract data graph morphing into a target arrow.
Vibrant orange and purple gradients. Isometric view.
Symbolizing growth and precision targeting. White background.
-->
<h3 class="solution-title">Data-Driven Marketing</h3>
<p class="solution-desc">
Maximize ROI with predictive analytics. Transform raw data into actionable insights to target the right audience at the perfect moment.
</p>
<a href="/solutions/marketing" class="nav-overlay-link" style="font-size: 1rem;">Learn more &rarr;</a>
</div>
<!-- Service 3: Next-Gen Rewards -->
<div class="solution-card">
<div class="image-placeholder service-icon-placeholder">
<MudIcon Icon="@Icons.Material.Filled.Loyalty" Size="Size.Large" />
</div>
<!--
IMAGE PROMPT:
3D icon of a floating premium gift box or token coin with a digital glow.
Gold and emerald accents. Isometric view.
Symbolizing value and loyalty. White background.
-->
<h3 class="solution-title">Next-Gen Rewards</h3>
<p class="solution-desc">
Elevate customer retention with a seamless digital loyalty ecosystem. Instant redemption, gamified tiers, and personalized rewards.
</p>
<a href="/solutions/rewards" class="nav-overlay-link" style="font-size: 1rem;">Learn more &rarr;</a>
</div>
<!-- Service 4: Multi-Industry POS -->
<div class="solution-card">
<div class="image-placeholder service-icon-placeholder">
<MudIcon Icon="@Icons.Material.Filled.PointOfSale" Size="Size.Large" />
</div>
<!--
IMAGE PROMPT:
3D icon of a sleek, futuristic payment terminal or tablet interface.
Clean white and metallic grey. Isometric view.
Symbolizing commerce and connectivity. White background.
-->
<h3 class="solution-title">Multi-Industry POS</h3>
<p class="solution-desc">
Unified commerce for retail and services. Manage inventory, sales, and staff across multiple locations from a single cloud dashboard.
</p>
<a href="/solutions/pos" class="nav-overlay-link" style="font-size: 1rem;">Learn more &rarr;</a>
</div>
</div>
</section>
<!-- Simple Footer -->
<footer style="border-top: 1px solid var(--border-subtle); padding: var(--space-8) 0; text-align: center; margin-top: var(--space-16); color: var(--text-tertiary);">
<p>&copy; 2024 GoodGo Enterprise. All rights reserved.</p>
</footer>
<style>
.hero-title {
font-size: 3rem;
}
@@media (min-width: 600px) {
.hero-title {
font-size: 5rem;
}
}
.glass-card {
background: var(--bg-secondary);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
</style>

View File

@@ -1,55 +1,43 @@
/* ═══════════════════════════════════════════════════════════════════════════════
WebClientBase Design System
EN: GoodGo branding with Dark/Light mode support
VI: GoodGo branding với hỗ trợ Dark/Light mode
WebClientBase Design System - Enterprise B2B
Architecture: Primitives -> Semantics -> Components
═══════════════════════════════════════════════════════════════════════════════ */
/* ═══════════════════════════════════════════════════════════════════════════════
CSS Variables / Biến CSS
═══════════════════════════════════════════════════════════════════════════════ */
:root {
/* Light Mode Colors */
--bg-primary: #f7f7f4;
--bg-secondary: #ffffff;
--bg-tertiary: #f0f0f0;
--bg-elevated: #ffffff;
/* ═════════════════════════════════════════════════════════════════════════
1. PRIMITIVES (Raw Color Palettes)
Do NOT use these directly in components. Use Semantic Tokens instead.
═════════════════════════════════════════════════════════════════════════ */
--text-primary: #18181b;
--text-secondary: #52525b;
--text-tertiary: #a1a1aa;
/* Neutral (Zinc) */
--primitive-neutral-0: #ffffff;
--primitive-neutral-50: #fafafa;
--primitive-neutral-100: #f4f4f5;
--primitive-neutral-200: #e4e4e7;
--primitive-neutral-300: #d4d4d8;
--primitive-neutral-400: #a1a1aa;
--primitive-neutral-500: #71717a;
--primitive-neutral-600: #52525b;
--primitive-neutral-700: #3f3f46;
--primitive-neutral-800: #27272a;
--primitive-neutral-900: #18181b;
--primitive-neutral-950: #09090b;
--accent-primary: #18181b;
--accent-primary-hover: #000000;
--accent-success: #10b981;
--accent-warning: #f59e0b;
--accent-error: #ef4444;
/* Brand (Blue/Indigo based for Enterprise Trust) */
--primitive-brand-500: #18181b;
/* Using Black as luxury/premium brand */
--primitive-brand-600: #000000;
--border-default: #e4e4e7;
--border-strong: #d4d4d8;
/* Glass Effects */
--glass-bg: rgba(255, 255, 255, 0.8);
--glass-border: rgba(0, 0, 0, 0.05);
--glass-blur: 12px;
--glass-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
/* Brand */
--brand-gradient: #18181b;
/* Solid black for light mode */
/* Utility */
--primitive-white: #ffffff;
--primitive-black: #000000;
--primitive-overlay: rgba(0, 0, 0, 0.4);
/* Typography */
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
--font-mono: 'JetBrains Mono', 'SF Mono', monospace;
--font-heading: 'Inter', system-ui, sans-serif;
--font-body: 'Inter', system-ui, sans-serif;
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 1.875rem;
/* Spacing */
/* Spacing Scale */
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 0.75rem;
@@ -57,533 +45,324 @@
--space-6: 1.5rem;
--space-8: 2rem;
--space-12: 3rem;
--space-16: 4rem;
--space-24: 6rem;
/* Border Radius */
--radius-sm: 0.25rem;
--radius-md: 0.375rem;
--radius-lg: 0.5rem;
--radius-xl: 0.75rem;
--radius-full: 9999px;
/* ═════════════════════════════════════════════════════════════════════════
2. SEMANTIC TOKENS (Light Mode Default)
Use these in your CSS.
═════════════════════════════════════════════════════════════════════════ */
/* Transitions */
--transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
--transition-normal: 250ms cubic-bezier(0.4, 0, 0.2, 1);
/* Backgrounds */
--bg-page: var(--primitive-neutral-50);
/* Main page background */
--bg-surface: var(--primitive-white);
/* Cards, Panels */
--bg-surface-hover: var(--primitive-neutral-50);
--bg-overlay: rgba(255, 255, 255, 0.9);
/* Glassmorphism base */
/* Sidebar */
--sidebar-width: 260px;
/* Gradients */
--brand-gradient: linear-gradient(135deg, #18181b 0%, #52525b 100%);
/* Zinc-900 to Zinc-600 */
/* Text */
--text-primary: var(--primitive-neutral-900);
/* Headings, Body */
--text-secondary: var(--primitive-neutral-600);
/* Subtitles */
--text-tertiary: var(--primitive-neutral-400);
/* Placeholders, disabled */
--text-inverse: var(--primitive-white);
/* Text on primary buttons */
/* Borders */
--border-subtle: var(--primitive-neutral-200);
--border-strong: var(--primitive-neutral-300);
/* Actions */
--action-primary-bg: var(--primitive-neutral-900);
--action-primary-bg-hover: var(--primitive-neutral-700);
--action-primary-text: var(--primitive-white);
--action-secondary-bg: var(--primitive-white);
--action-secondary-bg-hover: var(--primitive-neutral-50);
--action-secondary-text: var(--primitive-neutral-900);
--action-secondary-border: var(--primitive-neutral-200);
/* Status */
--border-radius-base: 4px;
--border-radius-lg: 8px;
--border-radius-xl: 12px;
}
/* Dark Mode */
/* Dark Mode */
/* ═════════════════════════════════════════════════════════════════════════
3. DARK MODE RE-MAPPING
═════════════════════════════════════════════════════════════════════════ */
[data-theme="dark"],
:root[data-theme="dark"] {
--bg-primary: #09090b;
--bg-secondary: #18181b;
--bg-tertiary: #27272a;
--bg-elevated: #18181b;
/* Backgrounds */
--bg-page: var(--primitive-neutral-950);
--bg-surface: var(--primitive-neutral-900);
--bg-surface-hover: var(--primitive-neutral-800);
--bg-overlay: rgba(9, 9, 11, 0.9);
--text-primary: #fafafa;
--text-secondary: #a1a1aa;
--text-tertiary: #71717a;
/* Gradients */
--brand-gradient: linear-gradient(135deg, #ffffff 0%, #a1a1aa 100%);
/* White to Zinc-400 */
--accent-primary: #fafafa;
--accent-primary-hover: #ffffff;
/* Text */
--text-primary: var(--primitive-neutral-50);
--text-secondary: var(--primitive-neutral-400);
--text-tertiary: var(--primitive-neutral-600);
--text-inverse: var(--primitive-neutral-950);
--border-default: #27272a;
--border-strong: #3f3f46;
/* Borders */
--border-subtle: var(--primitive-neutral-800);
--border-strong: var(--primitive-neutral-700);
--glass-bg: rgba(24, 24, 27, 0.8);
--glass-border: rgba(255, 255, 255, 0.1);
--glass-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.5);
/* Actions */
--action-primary-bg: var(--primitive-neutral-50);
--action-primary-bg-hover: var(--primitive-neutral-200);
--action-primary-text: var(--primitive-neutral-950);
--brand-gradient: #fafafa;
/* Solid white for dark mode */
}
/* Fix for MudButton Filled Primary in Dark Mode (White/White -> White/Black) */
[data-theme="dark"] .mud-button-filled-primary {
color: #18181b !important;
}
/* MudBlazor Overrides for Monochrome Nav */
.mud-nav-link {
border-radius: var(--radius-md) !important;
transition: all var(--transition-fast) !important;
color: var(--text-secondary) !important;
}
.mud-nav-link:hover {
background-color: var(--bg-tertiary) !important;
color: var(--text-primary) !important;
}
.mud-nav-link.active {
background-color: var(--accent-primary) !important;
color: var(--bg-primary) !important;
/* Invert text color on active */
}
.mud-nav-link.active .mud-icon-root {
color: var(--bg-primary) !important;
}
/* ═══════════════════════════════════════════════════════════════════════════════
Base Styles
═══════════════════════════════════════════════════════════════════════════════ */
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
font-size: 16px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
--action-secondary-bg: var(--primitive-neutral-900);
--action-secondary-bg-hover: var(--primitive-neutral-800);
--action-secondary-text: var(--primitive-neutral-50);
--action-secondary-border: var(--primitive-neutral-700);
}
/* ═════════════════════════════════════════════════════════════════════════
4. GLOBAL RESET & BASE STYLES
═════════════════════════════════════════════════════════════════════════ */
html,
body {
font-family: var(--font-sans);
background: var(--bg-primary) !important;
color: var(--text-primary) !important;
margin: 0;
padding: 0;
line-height: 1.5;
transition: background-color var(--transition-normal), color var(--transition-normal);
font-family: var(--font-body);
background-color: var(--bg-page) !important;
color: var(--text-primary) !important;
transition: background-color 0.3s ease, color 0.3s ease;
line-height: 1.6;
}
/* ═══════════════════════════════════════════════════════════════════════════════
Layout
═══════════════════════════════════════════════════════════════════════════════ */
.page {
display: flex;
min-height: 100vh;
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: var(--font-heading);
color: var(--text-primary);
margin-top: 0;
}
.sidebar {
width: var(--sidebar-width);
background: var(--bg-secondary);
border-right: 1px solid var(--border-default);
/* ═════════════════════════════════════════════════════════════════════════
5. COMPONENT UTILITIES
═════════════════════════════════════════════════════════════════════════ */
/* Unified Navigation Overlay */
.nav-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: var(--bg-overlay);
backdrop-filter: blur(16px);
z-index: 2000;
display: flex;
flex-direction: column;
}
main {
flex: 1;
display: flex;
flex-direction: column;
}
.top-row {
background: var(--bg-elevated);
border-bottom: 1px solid var(--border-default);
padding: var(--space-4);
display: flex;
justify-content: flex-end;
justify-content: center;
align-items: center;
gap: var(--space-4);
opacity: 0;
pointer-events: none;
transition: opacity 0.4s ease;
}
.content {
flex: 1;
padding: var(--space-6);
overflow-y: auto;
.nav-overlay.open {
opacity: 1;
pointer-events: auto;
}
.container {
.nav-overlay-link {
font-size: var(--text-3xl);
/* Large, legible type */
font-weight: 500;
color: var(--text-primary);
text-decoration: none;
margin: var(--space-4) 0;
transition: color 0.2s ease;
}
.nav-overlay-link:hover {
color: var(--text-secondary);
}
/* Hero Section */
.hero-section {
padding: var(--space-24) var(--space-6);
text-align: center;
max-width: 1200px;
margin: 0 auto;
}
/* ═══════════════════════════════════════════════════════════════════════════════
Navigation
═══════════════════════════════════════════════════════════════════════════════ */
.nav-brand {
padding: var(--space-6) var(--space-4);
font-size: var(--text-xl);
font-weight: 700;
background: var(--brand-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.nav-menu {
padding: var(--space-4);
}
.nav-link {
display: flex;
align-items: center;
gap: var(--space-3);
padding: var(--space-3) var(--space-4);
color: var(--text-secondary);
text-decoration: none;
border-radius: var(--radius-lg);
transition: all var(--transition-fast);
}
.nav-link:hover {
background: var(--bg-tertiary);
color: var(--text-primary);
}
.nav-link.active {
background: var(--accent-primary);
color: white;
}
/* ═══════════════════════════════════════════════════════════════════════════════
Glass Card
═══════════════════════════════════════════════════════════════════════════════ */
.glass-card {
background: var(--glass-bg);
backdrop-filter: blur(var(--glass-blur));
-webkit-backdrop-filter: blur(var(--glass-blur));
border: 1px solid var(--glass-border);
border-radius: var(--radius-xl);
padding: var(--space-6);
box-shadow: var(--glass-shadow);
.hero-headline {
font-size: 3.5rem;
font-weight: 800;
line-height: 1.1;
margin-bottom: var(--space-6);
letter-spacing: -0.02em;
}
.glass-card h2 {
margin: 0 0 var(--space-4);
font-size: var(--text-xl);
font-weight: 600;
}
/* ═══════════════════════════════════════════════════════════════════════════════
Forms
═══════════════════════════════════════════════════════════════════════════════ */
.form-group {
margin-bottom: var(--space-4);
}
.form-group label {
display: block;
margin-bottom: var(--space-2);
font-size: var(--text-sm);
font-weight: 500;
.hero-subtext {
font-size: 1.25rem;
color: var(--text-secondary);
max-width: 700px;
margin: 0 auto var(--space-8);
}
.form-input {
width: 100%;
padding: var(--space-3) var(--space-4);
font-size: var(--text-base);
font-family: var(--font-sans);
background: var(--bg-primary);
border: 1px solid var(--border-default);
border-radius: var(--radius-md);
color: var(--text-primary);
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.form-input:focus {
outline: none;
border-color: var(--accent-primary);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
}
.form-input::placeholder {
color: var(--text-tertiary);
}
.form-input.invalid,
.form-input:invalid {
border-color: var(--accent-error);
}
.form-row {
display: grid;
grid-template-columns: repeat(2, 1fr);
.hero-actions {
display: flex;
gap: var(--space-4);
justify-content: center;
margin-bottom: var(--space-12);
}
.form-hint {
display: block;
margin-top: var(--space-1);
font-size: var(--text-xs);
color: var(--text-tertiary);
/* Buttons */
.btn-enterprise-primary {
background-color: var(--action-primary-bg);
color: var(--action-primary-text);
padding: var(--space-3) var(--space-8);
border-radius: var(--border-radius-base);
font-weight: 600;
text-decoration: none;
border: none;
transition: background-color 0.2s;
cursor: pointer;
}
.form-actions {
.btn-enterprise-primary:hover {
background-color: var(--action-primary-bg-hover);
}
.btn-enterprise-secondary {
background-color: var(--action-secondary-bg);
color: var(--action-secondary-text);
border: 1px solid var(--action-secondary-border);
padding: var(--space-3) var(--space-8);
border-radius: var(--border-radius-base);
font-weight: 600;
text-decoration: none;
transition: background-color 0.2s;
cursor: pointer;
}
.btn-enterprise-secondary:hover {
background-color: var(--action-secondary-bg-hover);
}
/* Image Placeholders */
.image-placeholder {
background-color: var(--bg-surface);
border: 1px dashed var(--border-strong);
border-radius: var(--border-radius-xl);
display: flex;
gap: var(--space-3);
margin-top: var(--space-6);
}
.checkbox-group {
display: flex;
align-items: center;
gap: var(--space-2);
}
.checkbox-group label {
margin: 0;
}
/* ═══════════════════════════════════════════════════════════════════════════════
Buttons
═══════════════════════════════════════════════════════════════════════════════ */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--space-2);
padding: var(--space-3) var(--space-6);
font-size: var(--text-base);
font-weight: 500;
font-family: var(--font-sans);
border: none;
border-radius: var(--radius-md);
cursor: pointer;
transition: all var(--transition-fast);
color: var(--text-tertiary);
font-size: 0.875rem;
overflow: hidden;
position: relative;
}
.btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.btn-primary {
background: var(--brand-gradient);
color: white;
}
.btn-primary:hover:not(:disabled) {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
}
.btn-secondary {
background: var(--bg-tertiary);
color: var(--text-primary);
}
.btn-secondary:hover:not(:disabled) {
background: var(--bg-secondary);
}
.btn-full {
.hero-image-placeholder {
width: 100%;
height: 500px;
/* Large banner */
margin-top: var(--space-8);
}
/* ═══════════════════════════════════════════════════════════════════════════════
Validation
═══════════════════════════════════════════════════════════════════════════════ */
.validation-summary {
background: rgba(239, 68, 68, 0.1);
border: 1px solid var(--accent-error);
border-radius: var(--radius-md);
padding: var(--space-4);
.service-icon-placeholder {
width: 64px;
height: 64px;
margin-bottom: var(--space-4);
color: var(--accent-error);
border-radius: var(--border-radius-lg);
background-color: var(--bg-surface-hover);
}
.validation-summary ul {
margin: 0;
padding-left: var(--space-4);
}
.validation-message {
display: block;
margin-top: var(--space-1);
font-size: var(--text-xs);
color: var(--accent-error);
}
/* ═══════════════════════════════════════════════════════════════════════════════
Alerts
═══════════════════════════════════════════════════════════════════════════════ */
.alert {
padding: var(--space-4);
border-radius: var(--radius-md);
margin-top: var(--space-4);
}
.alert-success {
background: rgba(34, 197, 94, 0.1);
border: 1px solid var(--accent-success);
color: var(--accent-success);
}
.alert-error {
background: rgba(239, 68, 68, 0.1);
border: 1px solid var(--accent-error);
color: var(--accent-error);
}
/* ═══════════════════════════════════════════════════════════════════════════════
Product Grid
═══════════════════════════════════════════════════════════════════════════════ */
.product-grid {
/* Solutions Grid */
.solutions-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: var(--space-4);
grid-template-columns: repeat(1, 1fr);
/* Mobile First */
gap: var(--space-8);
max-width: 1200px;
margin: var(--space-16) auto;
padding: 0 var(--space-6);
}
.product-card {
background: var(--bg-elevated);
border: 1px solid var(--border-default);
border-radius: var(--radius-lg);
padding: var(--space-4);
transition: all var(--transition-fast);
@media (min-width: 768px) {
.solutions-grid {
grid-template-columns: repeat(2, 1fr);
/* 2x2 on Tablet/Desktop */
}
}
.product-card:hover {
.solution-card {
background-color: var(--bg-surface);
border: 1px solid var(--border-subtle);
padding: var(--space-8);
border-radius: var(--border-radius-xl);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.solution-card:hover {
transform: translateY(-2px);
box-shadow: var(--glass-shadow);
border-color: var(--border-strong);
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.1);
}
.product-card h3 {
margin: 0 0 var(--space-2);
font-size: var(--text-lg);
}
.product-card .description {
color: var(--text-secondary);
font-size: var(--text-sm);
.solution-title {
font-size: 1.5rem;
font-weight: 700;
margin-bottom: var(--space-3);
}
.product-details {
display: flex;
justify-content: space-between;
align-items: center;
}
.product-details .price {
font-weight: 600;
color: var(--accent-primary);
}
.product-details .quantity {
font-size: var(--text-sm);
color: var(--text-tertiary);
}
/* ═══════════════════════════════════════════════════════════════════════════════
Auth
═══════════════════════════════════════════════════════════════════════════════ */
.auth-container {
max-width: 400px;
margin: var(--space-12) auto;
}
.auth-tabs {
display: flex;
gap: var(--space-2);
margin-bottom: var(--space-4);
}
.tab-btn {
flex: 1;
padding: var(--space-3);
font-size: var(--text-base);
font-weight: 500;
background: var(--bg-tertiary);
border: none;
border-radius: var(--radius-md);
color: var(--text-secondary);
cursor: pointer;
transition: all var(--transition-fast);
}
.tab-btn.active {
background: var(--accent-primary);
color: white;
}
.auth-card .subtitle {
.solution-desc {
color: var(--text-secondary);
margin-bottom: var(--space-6);
}
/* ═══════════════════════════════════════════════════════════════════════════════
Page Title
═══════════════════════════════════════════════════════════════════════════════ */
.page-title {
font-size: var(--text-2xl);
font-weight: 700;
margin-bottom: var(--space-6);
background: var(--brand-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
/* ═══════════════════════════════════════════════════════════════════════════════
Theme Toggle
═══════════════════════════════════════════════════════════════════════════════ */
.theme-toggle {
padding: var(--space-2) var(--space-3);
background: var(--bg-tertiary);
border: 1px solid var(--border-default);
border-radius: var(--radius-full);
color: var(--text-primary);
cursor: pointer;
transition: all var(--transition-fast);
}
.theme-toggle:hover {
background: var(--bg-secondary);
}
/* ═══════════════════════════════════════════════════════════════════════════════
Loading & States
═══════════════════════════════════════════════════════════════════════════════ */
.loading {
/* Trust Section */
.trust-section {
padding: var(--space-16) 0;
border-top: 1px solid var(--border-subtle);
text-align: center;
color: var(--text-secondary);
padding: var(--space-8);
}
.empty-state {
text-align: center;
.trust-label {
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--text-tertiary);
padding: var(--space-8);
margin-bottom: var(--space-8);
}
.spinner {
display: inline-block;
width: 1rem;
height: 1rem;
border: 2px solid currentColor;
border-right-color: transparent;
border-radius: 50%;
animation: spin 0.75s linear infinite;
/* MudBlazor Overrides for Dark Mode Button Text */
[data-theme="dark"] .mud-button-filled-primary {
color: var(--action-primary-text) !important;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
/* Hardened Overrides for Dark Mode Text Visibility */
[data-theme="dark"] .nav-overlay-link {
color: var(--primitive-neutral-50) !important;
/* Force White */
}
/* ═══════════════════════════════════════════════════════════════════════════════
Responsive
═══════════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {
.sidebar {
position: fixed;
left: -100%;
top: 0;
bottom: 0;
z-index: 100;
transition: left var(--transition-normal);
}
.sidebar.open {
left: 0;
}
.form-row {
grid-template-columns: 1fr;
}
.content {
padding: var(--space-4);
}
[data-theme="dark"] .btn-enterprise-secondary {
background-color: var(--primitive-neutral-900) !important;
color: var(--primitive-neutral-50) !important;
/* Force White */
border-color: var(--primitive-neutral-700) !important;
}