diff --git a/MidrandBookshop/Components/Layout/MainLayout.razor b/MidrandBookshop/Components/Layout/MainLayout.razor index d19704e..77abab6 100644 --- a/MidrandBookshop/Components/Layout/MainLayout.razor +++ b/MidrandBookshop/Components/Layout/MainLayout.razor @@ -1,299 +1,53 @@ -@using Blazored.Toast -@inherits LayoutComponentBase -@inject NavigationManager Navigation +@inherits LayoutComponentBase -
-
-
-
-
- YOUR CART (@ShoppingCart.Items.Count()) -
- -
+
-
- @if (!ShoppingCart.Items.Any()) - { -
- - +
+
+
+
+ +
+ +
+ +
+ midrandbooks.co.za + +
- } - else - { -
- @foreach (var item in ShoppingCart.Items) - { -
-
- @if (!string.IsNullOrWhiteSpace(item.Product!.ImageUrl)) - { - @item.Product.Name - } - else - { - @:[COVER] - } -
-
-
@item.Product!.Name
-

by @($"{item.Author!.Name} {item.Author.LastName}")

-
-
- - @ShoppingCart.Items.FirstOrDefault(i => i.Price!.Id == item.Price!.Id)!.Quantity - -
- R @(item.Price!.Amount * item.Quantity) -
-
- -
- } -
- } -
+ - @if (ShoppingCart.Items.Any()) - { - - } -
- -
-
- - - - - - - - - - - - - - - - - - - - - - -
- - + - - - - - -
-
- -
- -
-
- - @Body - +
+ @Body
-
-
- - \ No newline at end of file + \ No newline at end of file diff --git a/MidrandBookshop/Components/Layout/MainLayout.razor.cs b/MidrandBookshop/Components/Layout/MainLayout.razor.cs index a338bbd..046b8a2 100644 --- a/MidrandBookshop/Components/Layout/MainLayout.razor.cs +++ b/MidrandBookshop/Components/Layout/MainLayout.razor.cs @@ -6,6 +6,7 @@ namespace MidrandBookshop.Components.Layout; public partial class MainLayout(CartService cartService) : IDisposable { [Inject] public IToastService ToastService { get; set; } = default!; + [Inject] private NavigationManager Navigation { get; set; } = default!; private Cart ShoppingCart => cartService.ShoppingCart; @@ -16,13 +17,13 @@ public partial class MainLayout(CartService cartService) : IDisposable protected override async Task OnInitializedAsync() { - Navigation.LocationChanged += OnLocationChanged; - cartService.OnCartChanged += CartService_OnCartChanged; + //Navigation.LocationChanged += OnLocationChanged; + //cartService.OnCartChanged += CartService_OnCartChanged; - if (cartService.ShoppingCart.Items.Count == 0) - await cartService.LoadCartFromStorageAsync(); + //if (cartService.ShoppingCart.Items.Count == 0) + // await cartService.LoadCartFromStorageAsync(); - SyncSearchQueryFromUrl(); + //SyncSearchQueryFromUrl(); } private async void CartService_OnCartChanged() => await InvokeAsync(StateHasChanged); diff --git a/MidrandBookshop/Components/Layout/MainLayout.razor.css b/MidrandBookshop/Components/Layout/MainLayout.razor.css index d76d83c..9f53a35 100644 --- a/MidrandBookshop/Components/Layout/MainLayout.razor.css +++ b/MidrandBookshop/Components/Layout/MainLayout.razor.css @@ -1,225 +1,199 @@ -.sticky-top { - position: -webkit-sticky !important; - position: sticky !important; - top: 0 !important; - z-index: 1000 !important; -} +/* MainLayout.razor.css */ -.cart-overlay { - position: fixed; - top: 0; - left: 0; +.water-background { + height: 100vh; width: 100vw; - height: 100vh; - background-color: rgba(0, 0, 0, 0.25); - backdrop-filter: blur(4px); - -webkit-backdrop-filter: blur(4px); - z-index: 1040; - opacity: 0; - pointer-events: none; - transition: opacity 0.35s cubic-bezier(0.16, 1, 0.3, 1); -} - - .cart-overlay.is-visible { - opacity: 1; - pointer-events: auto; - } - -.cart-drawer { - position: fixed; - top: 0; - right: -420px; - width: 100%; - max-width: 400px; - height: 100vh; - z-index: 1050; - pointer-events: none; - transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1); -} - - .cart-drawer.is-open { - transform: translateX(-420px); - pointer-events: auto; - } - -.cart-badge { - position: absolute; - top: 2px; - right: 2px; - background-color: #1A1A1A; - color: #FFF; - font-size: 0.62rem; - font-weight: 700; - border-radius: 50%; - width: 15px; - height: 15px; - display: flex; - align-items: center; - justify-content: center; - pointer-events: none; -} - -.xx-small { - font-size: 0.68rem; -} - -.border-bottom-dashed { - border-bottom: 1px dashed rgba(0, 0, 0, 0.12); -} - -.quantity-picker { - padding: 2px 4px; -} - - .quantity-picker button { - font-size: 0.85rem; - font-weight: 600; - line-height: 1; - } - - .quantity-picker button:hover { - background-color: rgba(0,0,0,0.05); - border-radius: 50%; - } - -.custom-site-footer { - width: 100%; + overflow: hidden; position: relative; - z-index: 10; - background-color: #1A1A1A !important; - border-top: 1px solid rgba(255, 255, 255, 0.1) !important; - padding: 3rem 0 2rem 0; + background-color: #1e2d4a; /* Base slate */ } -.footer-content-section { - border-bottom: 1px solid rgba(255, 255, 255, 0.08) !important; -} - -.footer-brand-title { - font-family: 'Inter', sans-serif; - font-size: 0.75rem; - font-weight: 700; - letter-spacing: 1px; - color: #FFFFFF !important; -} - -.footer-desc { - font-size: 0.8rem; - line-height: 1.6; - max-width: 360px; - color: #A0AEC0 !important; -} - -.footer-contact-link { - text-decoration: none; - font-size: 0.8rem; - color: #A0AEC0 !important; - display: inline-flex; - align-items: center; - gap: 8px; - transition: color 0.2s ease; -} - - .footer-contact-link:hover { - color: #FFFFFF !important; - } - -.footer-section-heading { - font-size: 0.65rem; - font-weight: 700; - letter-spacing: 1.2px; - color: #FFFFFF !important; -} - -.footer-nav-link { - text-decoration: none; - font-size: 0.8rem; - color: #A0AEC0 !important; - transition: color 0.2s ease; -} - - .footer-nav-link:hover { - color: #FFFFFF !important; - } - -.footer-meta-item { - font-size: 0.8rem; - font-weight: 500; - color: #FFFFFF !important; -} - -.footer-copyright-section { - color: #718096 !important; -} - -.footer-copyright { - font-size: 0.72rem; - font-weight: 500; - letter-spacing: 0.2px; -} - -.btn-back-to-top { +/* Base class for all floating organic shapes */ +.blotch { position: absolute; - bottom: 2rem; - right: 2rem; - width: 42px !important; - min-width: 42px !important; - max-width: 42px !important; - height: 42px !important; - border-radius: 50% !important; - background-color: #1A1A1A; - color: #FFFFFF; + border-radius: 50%; + filter: blur(80px); + z-index: 0; +} + +/* 1. Main Light Blotch - Now anchored Top-Left */ +.blotch-light-main { + width: 60vw; + height: 60vh; + background: #8892b0; + top: -10%; + left: -10%; + /* Sped up by ~0.9% from 25s to 24.7s */ + animation: driftLight 24.7s infinite ease-in-out alternate; +} + +/* 2. Main Dark Blotch - Now anchored Bottom-Right */ +.blotch-dark-main { + width: 70vw; + height: 70vh; + background: #0a192f; + bottom: -10%; + right: -10%; + /* Sped up by ~0.9% from 20s to 19.8s */ + animation: driftDark 19.8s infinite ease-in-out alternate; +} + +/* 3. New Accent Blotch - Mid-size, mid-navy */ +.blotch-accent-1 { + width: 40vw; + height: 40vh; + background: #172a45; + top: 30%; + right: 20%; + animation: driftAccentOne 22s infinite ease-in-out alternate; +} + +/* 4. New Accent Blotch - Smaller, lighter shade for depth */ +.blotch-accent-2 { + width: 30vw; + height: 35vh; + background: #2c3e50; + bottom: 20%; + left: 20%; + animation: driftAccentTwo 28s infinite ease-in-out alternate; +} + +/* Denser Pixel Packing (SVG Noise) */ +.noise-overlay { + position: absolute; + inset: 0; + z-index: 1; /* Sits above the blotches, below the glass */ + opacity: 0.06; /* Keep this low; just enough to texture the gradient */ + /* An inline SVG generating fractal noise */ + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); + pointer-events: none; /* Ensures clicks pass through to the UI */ +} + +/* The Glass Layer */ +.glass-panel { + position: absolute; + inset: 0; + background: rgba(255, 255, 255, 0.03); + box-shadow: inset 0 0 80px rgba(255, 255, 255, 0.05); + backdrop-filter: blur(30px); + -webkit-backdrop-filter: blur(30px); + z-index: 2; + display: flex; + flex-direction: column; +} + +.content-area { + z-index: 3; + flex-grow: 1; + height: 100%; + width: 100%; + overflow-y: hidden; + padding: 2rem; +} + +/* --- Animations --- */ +@keyframes driftLight { + 0% { + transform: translate(0, 0) scale(1); + } + + 100% { + transform: translate(10%, 15%) scale(1.15); + } + /* Pushes down and right */ +} + +@keyframes driftDark { + 0% { + transform: translate(0, 0) scale(1); + } + + 100% { + transform: translate(-15%, -10%) scale(1.1); + } + /* Pushes up and left */ +} + +@keyframes driftAccentOne { + 0% { + transform: translate(0, 0) scale(0.9); + } + + 100% { + transform: translate(-20%, 20%) scale(1.2); + } +} + +@keyframes driftAccentTwo { + 0% { + transform: translate(0, 0) scale(1); + } + + 100% { + transform: translate(25%, -15%) scale(0.85); + } +} + +/* --- Floating Top Bar --- */ +.top-bar { + display: flex; + align-items: center; + height: 60px; + padding: 0 2rem; + /* The Floating Magic */ + margin: 1rem 1rem 0 1rem; /* 1.5rem top gap, 2rem left/right gap, 0 bottom gap */ + border-radius: 10px; /* Smooth, rounded corners for the island effect */ + /* The Glass Effect */ + background: rgba(255, 255, 255, 0.04); + box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.2); + /* A subtle frosted edge all the way around to define the shape */ + border: 1px solid rgba(255, 255, 255, 0.08); + z-index: 10; +} + +.brand-text { + color: #f8f9fa; + font-size: 1.25rem; + font-weight: 600; + letter-spacing: 0.5px; + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); +} + +/* --- Top Navigation Icons --- */ +.top-nav-icons { + display: flex; + align-items: center; + gap: 1.5rem; /* Even spacing between icons */ + margin-left: auto; /* Pushes the nav block to the right */ +} + +/* The transparent button wrappers */ +.icon-btn { + background: transparent; border: none; + padding: 0.5rem; + cursor: pointer; + /* Set the icon color to a slightly muted off-white */ + color: rgba(255, 255, 255, 0.6); display: flex; align-items: center; justify-content: center; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); - z-index: 1010; - cursor: pointer; - transition: transform 0.2s ease, background-color 0.2s ease; + border-radius: 8px; /* For a subtle hover background if needed later */ + /* Smooth out the hover animations */ + transition: color 0.2s ease, transform 0.2s ease; } - .btn-back-to-top:hover { - background-color: #333333; + /* Hover interactions */ + .icon-btn:hover { + /* Brightens to pure white and floats up slightly when moused over */ + color: #ffffff; transform: translateY(-2px); } - .btn-back-to-top:active { - transform: translateY(0); - } - -.scroll-container { - scroll-behavior: smooth; -} - -.no-caret::after { - display: none !important; -} - -.brand-dropdown-pane { - border-radius: 0px !important; - border: 1px solid rgba(0, 0, 0, 0.15) !important; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05) !important; - min-width: 190px; - z-index: 1050; -} - - .brand-dropdown-pane .dropdown-item { - font-size: 0.72rem; - letter-spacing: 0.02em; - transition: background-color 0.15s ease, color 0.15s ease; - } - - .brand-dropdown-pane .dropdown-item:hover { - background-color: #1A1A1A !important; - color: #FFFFFF !important; - } - - .brand-dropdown-pane .dropdown-item.text-danger:hover { - background-color: #DC3545 !important; - color: #FFFFFF !important; - } - -.dropdown-header-identity { - user-select: none; -} \ No newline at end of file + /* Ensure the SVG scales neatly */ + .icon-btn svg { + width: 22px; + height: 22px; + /* This ensures the stroke/fill matches the .icon-btn color */ + stroke: currentColor; + } \ No newline at end of file diff --git a/MidrandBookshop/Components/Layout/ReconnectModal.razor b/MidrandBookshop/Components/Layout/ReconnectModal.razor index 5913b7e..5f172b6 100644 --- a/MidrandBookshop/Components/Layout/ReconnectModal.razor +++ b/MidrandBookshop/Components/Layout/ReconnectModal.razor @@ -3,56 +3,54 @@
-
-
+
-
- - Catalog Circuit Sync -
+ + + + + + + -
- - Connection interrupted. Re-indexing active reading stack... - +
+ + Losing signal... + - - Sync delayed. Re-aligning database archives in 0s... - + + reconnecting in 0s... + - - Archival path blocked. Automated sync offline. - + + Playback disconnected. + - - Reading layout paused by host environment node. - - - - State alignment broken. - -
- -
- - -
+ + Reading layout paused. + + + State alignment broken. +
+ +
+ + +
+
\ No newline at end of file diff --git a/MidrandBookshop/Components/Layout/ReconnectModal.razor.css b/MidrandBookshop/Components/Layout/ReconnectModal.razor.css index 53204b6..ae5e0b6 100644 --- a/MidrandBookshop/Components/Layout/ReconnectModal.razor.css +++ b/MidrandBookshop/Components/Layout/ReconnectModal.razor.css @@ -1,5 +1,5 @@ /* ========================================================================== - Midrand Books — Glassine Architectural Veil & Ribbon Strip + Midrand Books — Disconnect Overlay (Media Player Aesthetic) ========================================================================== */ /* --- Native Dialog Element Layout Overrides --- */ @@ -17,165 +17,151 @@ background: transparent; z-index: 99999; overflow: hidden; + /* Center the content */ + display: flex; + align-items: center; + justify-content: center; + /* Blazor handles visibility, but we handle the fade */ + opacity: 0; + pointer-events: none; + transition: opacity 0.3s ease-in-out; } - /* Remove default browser modal backdrop blockout to allow custom layering below */ #components-reconnect-modal::backdrop { background: transparent; } -/* --- Glassine Page Jacket Layer --- - Frosted translucent shield that preserves context visibility while blocking mouse actions -*/ + /* Show the modal smoothly when Blazor attaches state classes */ + #components-reconnect-modal.components-reconnect-show, + #components-reconnect-modal.components-reconnect-failed, + #components-reconnect-modal.components-reconnect-rejected { + opacity: 1; + pointer-events: all; + } + + #components-reconnect-modal.components-reconnect-hide { + display: none !important; + } + +/* --- Dark Frosted Jacket Layer --- */ .glassine-page-jacket { position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(251, 251, 250, 0.4); /* Premium warm paper tint */ - backdrop-filter: blur(5px); /* Elegant frosted glass sweep */ + inset: 0; + background-color: rgba(10, 25, 47, 0.4); /* Deep navy tint */ + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); cursor: wait; - animation: glassFadeIn 0.35s ease-out forwards; + z-index: 1; } -@keyframes glassFadeIn { - from { - opacity: 0; - backdrop-filter: blur(0px); - } - - to { - opacity: 1; - backdrop-filter: blur(5px); - } -} - -/* --- The Sliding Ribbon Banner --- */ -.literary-sync-strip { - position: absolute; - top: 0; - left: 0; - width: 100%; - background-color: #FFFFFF; - border-bottom: 1px solid rgba(0, 0, 0, 0.08); - box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05), 0 1px 3px rgba(0, 0, 0, 0.02); - padding: 1.1rem 2rem; - box-sizing: border-box; +/* --- Centered Content Wrapper --- */ +.reconnect-content { + position: relative; z-index: 2; - /* Animation kinematics: smooth physical drop slide */ - transform: translateY(-100%); - animation: stripSlideDown 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards; -} - -@keyframes stripSlideDown { - to { - transform: translateY(0); - } -} - -/* --- Ribbon Layout Matrix Grid --- */ -.strip-container { - max-width: 1200px; - margin: 0 auto; - display: grid; - grid-template-columns: auto 1fr auto; - align-items: center; - gap: 2.5rem; -} - -/* Left Node Ticker Elements & Animated Vector */ -.sync-status-indicator { display: flex; + flex-direction: column; align-items: center; - gap: 0.85rem; - border-right: 1px solid rgba(0, 0, 0, 0.08); - padding-right: 2rem; + gap: 1.5rem; + color: #f8f9fa; + text-align: center; } -.small-tracking { - font-family: var(--bs-font-monospace); - font-size: 0.7rem; - letter-spacing: 0.12em; - color: #111111; - font-weight: 600; +/* --- SVG Waveform Animation --- */ +.waveform-svg { + shape-rendering: geometricPrecision; + color: #f8f9fa; } -/* Animated Book Helix SVG */ -.literary-helix-loader { - width: 18px; - height: 18px; - color: #111111; +.bar { + transform-origin: center; + animation: wavePulse 1.2s ease-in-out infinite alternate; } -.flipping-leaf-vector { - transform-origin: 12px 12px; - animation: svgLeafFlip 1.6s infinite cubic-bezier(0.4, 0, 0.2, 1); +.bar-1 { + animation-delay: 0.0s; } -@keyframes svgLeafFlip { +.bar-2 { + animation-delay: 0.3s; +} + +.bar-3 { + animation-delay: 0.6s; +} + +.bar-4 { + animation-delay: 0.2s; +} + +.bar-5 { + animation-delay: 0.5s; +} + +@keyframes wavePulse { 0% { - transform: scaleX(1); - opacity: 1; - } - - 50% { - transform: scaleX(0); - opacity: 0.3; + transform: scaleY(0.3); + opacity: 0.5; } 100% { - transform: scaleX(-1); - opacity: 0; + transform: scaleY(1); + opacity: 1; } } -/* Center Node Text Content */ -.sync-message-body { - font-family: Georgia, 'Times New Roman', serif; - font-size: 0.95rem; - color: #333333; - font-style: italic; +/* Stop the waveform if the connection completely fails */ +#components-reconnect-modal.components-reconnect-failed .bar, +#components-reconnect-modal.components-reconnect-rejected .bar, +#components-reconnect-modal.components-reconnect-paused .bar { + animation: none; + transform: scaleY(0.1); + opacity: 0.3; +} + +/* --- Typography --- */ +.small-tracking { + font-size: 0.85rem; + letter-spacing: 0.15em; + font-weight: 500; + color: rgba(255, 255, 255, 0.7); } .text-crimson { - color: #A34843; - font-style: normal; - font-weight: 500; + color: #ff6b6b; /* Softened red for dark mode */ + font-weight: 600; } -/* Right Node Fine-Press Button Trigger */ -.btn-strip-action { - background: #111111; - color: #FFFFFF; - border: 1px solid #111111; - padding: 0.45rem 1.25rem; +/* --- Glass Buttons --- */ +.sync-action-node { + margin-top: 1rem; + display: flex; + gap: 1rem; +} + +.btn-glass-action { + background: rgba(255, 255, 255, 0.05); + color: #f8f9fa; + border: 1px solid rgba(255, 255, 255, 0.1); + padding: 0.6rem 1.5rem; font-family: var(--bs-font-monospace); - font-size: 0.7rem; - letter-spacing: 0.08em; + font-size: 0.75rem; + letter-spacing: 0.1em; text-transform: uppercase; - border-radius: 4px; - transition: all 0.2s ease; + border-radius: 8px; cursor: pointer; display: inline-flex; align-items: center; gap: 0.5rem; + transition: all 0.2s ease; } - .btn-strip-action:hover { - background: transparent; - color: #111111; + .btn-glass-action:hover { + background: rgba(255, 255, 255, 0.1); + border-color: rgba(255, 255, 255, 0.3); + transform: translateY(-2px); } - .btn-strip-action svg { - transition: transform 0.2s ease; - } - - .btn-strip-action:hover svg { - transform: rotate(45deg); - } - -/* --- Display Mechanics Matrix Controllers --- */ +/* --- Display Mechanics Matrix Controllers (Preserved) --- */ .components-reconnect-first-attempt-visible, .components-reconnect-repeated-attempt-visible, .components-reconnect-failed-visible, @@ -192,27 +178,8 @@ display: inline-block !important; } -#components-reconnect-modal.components-reconnect-failed .btn-strip-action, -#components-reconnect-modal.components-reconnect-paused .btn-strip-action, -#components-reconnect-modal.components-reconnect-resume-failed .btn-strip-action { +#components-reconnect-modal.components-reconnect-failed .btn-glass-action, +#components-reconnect-modal.components-reconnect-paused .btn-glass-action, +#components-reconnect-modal.components-reconnect-resume-failed .btn-glass-action { display: inline-flex !important; } - -/* Tablet Parameters Response Collapse Matrix */ -@media (max-width: 768px) { - .strip-container { - grid-template-columns: 1fr; - gap: 0.65rem; - text-align: center; - } - - .sync-status-indicator { - border-right: none; - padding-right: 0; - justify-content: center; - } - - .sync-action-node { - margin-top: 0.25rem; - } -} diff --git a/MidrandBookshop/Components/Pages/Home.razor b/MidrandBookshop/Components/Pages/Home.razor index f57bb0e..a336378 100644 --- a/MidrandBookshop/Components/Pages/Home.razor +++ b/MidrandBookshop/Components/Pages/Home.razor @@ -1,203 +1,1685 @@ @page "/" -@rendermode InteractiveServer -
+
-
-

- Discover thoughtfully curated
books for every reader. -

-

- Explorations into books, reading culture, and the art of thoughtful curation from Midrand to the world. -

-
+
-
+ image/svg+xml - @if (AuthorId.HasValue && !string.IsNullOrEmpty(ActiveAuthorFilterName)) - { -
-
- Author Collection - Archived items from @ActiveAuthorFilterName -
- -
- } + READ -
-
-
- @if (!AuthorId.HasValue) - { - @foreach (var category in MainCategories) - { - var catName = category; - - } - - @if (DynamicExtendedCategories.Count > 0) - { - - } - } - else - { - - } -
-
- -
-
- - -
- - -
-
-
- @if (ShowExpandedCategories && DynamicExtendedCategories.Count > 0 && !AuthorId.HasValue) - { -
-

Curated Subgenre Tag Index

-
- @foreach (var subCategory in DynamicExtendedCategories) - { - var subName = subCategory; - - } -
-
- } - - @if (ShowFilterMenu) - { -
-
-
- - -
-
- -
- - - - -
-
-
-
- - -
-
-
-
- - -
-
- } - - @if (!PaginatedBooks.Any()) - { -
- -

No archived books match your active criteria.

- Try adjusting your category definitions or search phrase query. -
- } - else if (CurrentViewMode == ViewMode.Grid) - { -
- @foreach (var book in PaginatedBooks) - { - - } -
- } - else if (CurrentViewMode == ViewMode.List) - { -
- @foreach (var book in PaginatedBooks) - { -
-
- @book.Name - by @(ProductAuthorCache.TryGetValue(book.Id, out var authorName) ? authorName : "Unknown Author") - @ProductPrimaryCategoryCache[book.Id].ToUpper() -
-
- @if (book.Enabled) - { - NEW - } - R @ProductPriceCache[book.Id].ToString("N0") - -
-
- } -
- } - - @if (HasMoreItems) - { -
- -
- } -
- - - - \ No newline at end of file +
\ No newline at end of file diff --git a/MidrandBookshop/Components/Pages/Home.razor.cs b/MidrandBookshop/Components/Pages/Home.razor.cs index 52b6459..9277fb0 100644 --- a/MidrandBookshop/Components/Pages/Home.razor.cs +++ b/MidrandBookshop/Components/Pages/Home.razor.cs @@ -101,20 +101,23 @@ public partial class Home : ComponentBase protected override async Task OnInitializedAsync() { - if (CartService.ShoppingCart.Items.Count == 0) - await CartService.LoadCartFromStorageAsync(); + //if (CartService.ShoppingCart.Items.Count == 0) + // await CartService.LoadCartFromStorageAsync(); } protected override async Task OnAfterRenderAsync(bool firstRender) { - if (firstRender == false && HydrationService.CartHydrated == false) - { - if(!CartService.ShoppingCart.CustomerId.HasValue) - await HydrationService.EnsureCustomerExistsAsync(CancellationToken); - } + //if (firstRender == false && HydrationService.CartHydrated == false) + //{ + // if(!CartService.ShoppingCart.CustomerId.HasValue) + // await HydrationService.EnsureCustomerExistsAsync(CancellationToken); + //} } - protected override async Task OnParametersSetAsync() => await LoadCatalogDataAsync(); + protected override async Task OnParametersSetAsync() + { + //await LoadCatalogDataAsync(); + } private async Task LoadCatalogDataAsync() { diff --git a/MidrandBookshop/Components/Pages/Home.razor.css b/MidrandBookshop/Components/Pages/Home.razor.css index 071284e..90713d8 100644 --- a/MidrandBookshop/Components/Pages/Home.razor.css +++ b/MidrandBookshop/Components/Pages/Home.razor.css @@ -1,177 +1,77 @@ -/* Expanding Search Input Controls */ -.search-input-container { - max-width: 0; - opacity: 0; - overflow: hidden; - transition: max-width 0.35s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.25s ease; +/* --- Centering Container --- */ +.home-portal-container { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; } - .search-input-container.is-active { - max-width: 280px; - opacity: 1; +/* --- Invisible Wrapper --- */ +.artistic-portal { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; + /* Make the whole block interactive */ + cursor: pointer; + transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1); +} + + .artistic-portal:hover { + transform: translateY(-5px) scale(1.02); } -.custom-search-field { - font-size: 0.8rem; - height: 32px; - box-shadow: none !important; +/* --- The Illustration --- */ +.portal-illustration { + width: 100%; + max-width: 450px; /* Scales nicely on larger screens */ + height: auto; + /* Adds a beautiful glass-like shadow behind the vector lines */ + filter: drop-shadow(0 15px 25px rgba(0, 0, 0, 0.3)); + transition: filter 0.4s ease; } -/* Structural Layout Typography */ -.branding-logo { - font-size: 1.1rem; - letter-spacing: -0.5px; +.artistic-portal:hover .portal-illustration { + filter: drop-shadow(0 25px 35px rgba(0, 0, 0, 0.4)) drop-shadow(0 0 15px rgba(255, 255, 255, 0.1)); } -.text-hero-wrapper { - margin-top: 5rem; - margin-bottom: 3.5rem; +/* --- Ambient Animations inside the SVG --- */ +.float-slow { + animation: floatVertical 6s ease-in-out infinite; + transform-origin: center; } -.master-headline { - letter-spacing: -1.5px; - font-weight: 400; - line-height: 1.15; +.float-medium { + animation: floatVertical 4s ease-in-out infinite reverse; + transform-origin: center; } -.sub-headline { - max-width: 520px; - font-size: 0.95rem; +@keyframes floatVertical { + 0%, 100% { + transform: translateY(0); + } + + 50% { + transform: translateY(-12px); + } +} + +/* --- The Text --- */ +.read-text { + color: #f8f9fa; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + font-size: 2rem; font-weight: 300; - line-height: 1.6; + letter-spacing: 0.35em; + margin-left: 0.35em; /* Compensates for the extra tracking on the right side */ + /* Soft glow */ + text-shadow: 0 4px 15px rgba(248, 249, 250, 0.2); + transition: all 0.4s ease; } -/* Filtering Dropdown Drawer Settings */ -.filter-dropdown-panel { - border-radius: 12px; +.artistic-portal:hover .read-text { + color: #ffffff; + letter-spacing: 0.4em; + text-shadow: 0 4px 20px rgba(248, 249, 250, 0.5); } - -.panel-section-heading { - letter-spacing: 0.5px; - font-size: 0.7rem; -} - -.reset-link-btn { - font-size: 0.7rem; -} - -/* Custom Minimal Separator Rule Layout */ -.custom-milled-line { - height: 35px; - margin-top: 5px; - margin-bottom: 25px; - z-index: 0; - pointer-events: none; -} - -.center-bloom-shadow { - bottom: 15px; - width: 55%; - height: 50px; - background: radial-gradient(ellipse at bottom, rgba(20, 20, 20, 0.07) 0%, rgba(40, 40, 40, 0.02) 60%, rgba(255, 255, 255, 0) 100%); - filter: blur(10px); -} - -.core-horizontal-rule { - bottom: 15px; - height: 1px; - background: linear-gradient(90deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.15) 50%, rgba(0,0,0,0) 100%); -} - -/* View Engine Layout Presentation Variants: Grid Cards */ -.book-grid-card { - background-color: #F1F1F1; - border-radius: 12px; - min-height: 380px; -} - -.badge-new-arrival { - background-color: #E63946; - font-size: 0.75rem; -} - -.book-spine-fallback { - width: 130px; - height: 185px; - font-size: 0.65rem; - letter-spacing: 1px; - border-radius: 2px; -} - -.product-card-title { - font-size: 0.95rem; - font-weight: 500; -} - -/* View Engine Layout Presentation Variants: List Rows */ -.list-row-item { - border-bottom: 1px solid rgba(0,0,0,0.06); - transition: background-color 0.2s ease; -} - - .list-row-item:hover { - background-color: rgba(0,0,0,0.01); - } - -.structural-list-left { - flex: 2; -} - -.list-item-title { - font-size: 0.95rem; - min-width: 260px; -} - -.list-item-author { - min-width: 160px; -} - -.list-item-tag { - font-size: 0.65rem; -} - -.list-new-badge { - font-size: 0.65rem; -} - -.list-item-price { - font-size: 0.9rem; - min-width: 80px; - text-align: right; -} - -/* Enable native smooth scrolling page-wide */ -html { - scroll-behavior: smooth; -} - -/* Back to Top Icon Layout Presentation */ -.back-to-top-btn { - position: fixed !important; - bottom: 32px; - right: 32px; - width: 42px; - height: 42px; - border-radius: 50% !important; - text-decoration: none !important; - /* Dual-tone contrast visibility profile */ - background-color: #ffffff !important; - color: #1a1a1a !important; - border: 2px solid #1a1a1a !important; - box-shadow: 0 0 0 2px #ffffff, 0 4px 12px rgba(0, 0, 0, 0.15) !important; - z-index: 2147483647 !important; - transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); -} - - .back-to-top-btn:hover { - transform: translateY(-4px); - background-color: #1a1a1a !important; - color: #ffffff !important; - border-color: #ffffff !important; - box-shadow: 0 0 0 2px #1a1a1a, 0 6px 16px rgba(0, 0, 0, 0.25) !important; - } - -/* Direct the smooth scroll action straight to the layout viewport boundary */ -#top-target { - scroll-margin-top: 100vh; -} \ No newline at end of file diff --git a/MidrandBookshop/MidrandBookshop.csproj b/MidrandBookshop/MidrandBookshop.csproj index 5232087..dc06372 100644 --- a/MidrandBookshop/MidrandBookshop.csproj +++ b/MidrandBookshop/MidrandBookshop.csproj @@ -18,6 +18,7 @@ + @@ -25,6 +26,7 @@ + diff --git a/MidrandBookshop/wwwroot/app.css b/MidrandBookshop/wwwroot/app.css index 5433325..31007fe 100644 --- a/MidrandBookshop/wwwroot/app.css +++ b/MidrandBookshop/wwwroot/app.css @@ -1,224 +1,14 @@ -@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Inter:wght@300;400;500;600&display=swap'); - -:root { - /* Fonts */ - --font-heading: 'Instrument Serif', serif; - --font-ui: 'Inter', sans-serif; - /* Color Palette */ - --mb-bg: #F9F9F9; - --mb-card-bg: #FFFFFF; - --mb-text-dark: #1A1A1A; - --mb-text-muted: #666666; - --mb-accent-red: #E63946; - --mb-radius: 12px; - /* High-Visibility Machined White Metal Core Surface Definition */ - /* Sharp linear reflection channels paired with micro-milled density grids */ - --brushed-metal-bg: linear-gradient(90deg, rgba(255, 255, 255, 1) 0%, rgba(240, 241, 245, 0.95) 25%, rgba(255, 255, 255, 1) 50%, rgba(238, 240, 244, 0.95) 75%, rgba(255, 255, 255, 1) 100% ), repeating-linear-gradient( 0deg, rgba(0, 0, 0, 0.012) 0px, rgba(0, 0, 0, 0.012) 1px, transparent 1px, transparent 2px ), repeating-linear-gradient( 90deg, rgba(255, 255, 255, 0.9) 0px, rgba(255, 255, 255, 0.9) 1px, transparent 1px, transparent 3px ), #EDEFF4; /* Definitive satin platinum breakout base fallback */ +html, body { + margin: 0; + padding: 0; + height: 100vh; + width: 100vw; + overflow: hidden; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background-color: #ffffff; } -/* Global Reset & Core Variables Mapping */ body { - background-color: var(--mb-bg); - color: var(--mb-text-dark); - font-family: var(--font-ui); -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } - -h1, h2, h3, .display-font { - font-family: var(--font-heading); - font-weight: 400; -} - -/* Custom Navigation Pill Styling */ -.nav-pill-wrapper { - background-color: #FFFFFF; - border: 1px solid rgba(0, 0, 0, 0.06); - padding: 6px; - border-radius: 50px; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.02); -} - -.nav-pill-link { - font-size: 0.9rem; - font-weight: 500; - color: var(--mb-text-muted); - padding: 8px 20px; - border-radius: 50px; - transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); - display: inline-flex; - align-items: center; - gap: 8px; - text-decoration: none; -} - - .nav-pill-link i { - width: 16px; - height: 16px; - stroke-width: 1.5; - } - - /* Navigation Pill States */ - .nav-pill-link:hover { - color: var(--mb-text-dark); - background-color: #F1F1F1; - } - - .nav-pill-link.active { - color: #FFFFFF !important; - background-color: var(--mb-text-dark); - } - - .nav-pill-link.active svg { - stroke: #FFFFFF; - } - -/* Utilities & Component Support Layouts */ -.cart-badge { - position: absolute; - top: -5px; - right: -5px; - background-color: var(--mb-text-dark); - color: #FFFFFF; - font-size: 0.7rem; - font-weight: 600; - width: 18px; - height: 18px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - border: 2px solid var(--mb-bg); -} - -.transition-smooth { - transition: color 0.2s ease; -} - - .transition-smooth:hover { - color: var(--mb-text-dark) !important; - } - -.py-1-5 { - padding-top: 0.35rem !important; - padding-bottom: 0.35rem !important; -} - -/* Global Focus Ring Corrections */ -h1:focus, h2:focus, h3:focus, h4:focus, p:focus, div:focus, span:focus { - outline: none !important; - box-shadow: none !important; -} - -[tabindex="-1"]:focus { - outline: none !important; -} - -/* ========================================================================== - Global Toast Notification Framework Extensions - ========================================================================== */ - -.blazored-toast-container { - position: fixed; - /* 🛠️ Shift anchors from top-right to bottom-left */ - bottom: 24px; - left: 24px; - top: auto; - right: auto; - z-index: 2000 !important; - display: flex; - flex-direction: column-reverse; /* 💡 Newest toasts will now stack cleanly on top of old ones */ - gap: 12px; - max-width: 400px; - width: 100%; - pointer-events: none; -} - -.blazored-toast { - display: flex; - align-items: center; - padding: 16px 20px; - border-radius: var(--mb-radius); - background-color: var(--mb-card-bg); - color: var(--mb-text-dark); - box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.04); - border: 1px solid rgba(0, 0, 0, 0.05); - font-family: var(--font-ui); - font-size: 0.9rem; - font-weight: 500; - animation: toastFadeIn 0.35s cubic-bezier(0.175, 0.885, 0.32, 1.125) forwards; -} - -/* Success Toast Core Variants */ -.blazored-toast-success { - border-left: 4px solid var(--mb-text-dark); -} - -/* Error Toast Core Variants */ -.blazored-toast-error { - border-left: 4px solid var(--mb-accent-red); - color: var(--mb-accent-red); -} - -.blazored-toast-icon { - display: inline-flex; - align-items: center; - justify-content: center; - margin-right: 12px; - flex-shrink: 0; -} - -/* Entry Transition Keyframes */ -@keyframes toastFadeIn { - from { - opacity: 0; - transform: translateY(-12px) scale(0.96); - } - - to { - opacity: 1; - transform: translateY(0) scale(1); - } -} - -.book-shadow { - filter: drop-shadow(5px 10px 15px rgba(0, 0, 0, 0.15)) drop-shadow(1px 2px 4px rgba(0, 0, 0, 0.1)); -} - -.sm-icon { - width: 14px; - height: 14px; - vertical-align: middle; -} - -/* 🛠️ Micro-interactions for the header icon placement */ -.btn-cart-icon:hover { - transform: scale(1.08); - background-color: var(--mb-text-dark) !important; -} - - .btn-cart-icon:hover svg { - stroke: #FFFFFF !important; - } - -@keyframes toastFadeIn { - from { - opacity: 0; - transform: translateX(-24px) scale(0.95); /* Slide rightward into view */ - } - - to { - opacity: 1; - transform: translateX(0) scale(1); - } -} - -.blazored-toast button.blazored-toast-close, -.blazored-toast-close-icon { - display: none !important; - visibility: hidden !important; - opacity: 0 !important; - width: 0 !important; - height: 0 !important; - padding: 0 !important; - margin: 0 !important; -} \ No newline at end of file