@if (GraphService.IsLoading || GraphService.CurrentGraphData == null)
{
-
-
-
-
+
+
+
Mapowanie relacji rozdziału...
-
Mapowanie relacji rozdziału...
-
}
else
{
-
-
-
-
-
+
+
+
+
+
}
@@ -49,7 +49,7 @@
private async Task HandleGraphUpdate()
{
if (_module == null) return;
-
+
if (GraphService.CurrentGraphData == null)
{
await _module.InvokeVoidAsync("clear");
@@ -58,7 +58,7 @@
{
await _module.InvokeVoidAsync("updateData", GraphService.CurrentGraphData);
}
-
+
await InvokeAsync(StateHasChanged);
}
@@ -78,7 +78,7 @@
if (firstRender)
{
await InitializeGraphAsync();
-
+
if (GraphService.CurrentGraphData != null)
{
await HandleGraphUpdate();
@@ -101,7 +101,7 @@
public async Task OnNodeClicked(string nodeId)
{
await InteractionService.NotifyNodeSelected(nodeId);
-
+
if (OnNodeSelected.HasDelegate)
{
await OnNodeSelected.InvokeAsync(nodeId);
@@ -128,7 +128,7 @@
GraphService.OnGraphUpdated -= HandleGraphUpdate;
GraphService.OnActiveNodeChanged -= HandleActiveNodeChange;
GraphService.OnLoadingChanged -= HandleLoadingChange;
-
+
try
{
if (_module is not null)
@@ -138,7 +138,7 @@
}
}
catch { }
-
+
_dotNetHelper?.Dispose();
}
}
diff --git a/src/NexusReader.UI.Shared/Components/Organisms/KnowledgeGraph.razor.css b/src/NexusReader.UI.Shared/Components/Organisms/KnowledgeGraph.razor.css
index 761e103..0fb0d26 100644
--- a/src/NexusReader.UI.Shared/Components/Organisms/KnowledgeGraph.razor.css
+++ b/src/NexusReader.UI.Shared/Components/Organisms/KnowledgeGraph.razor.css
@@ -10,7 +10,7 @@
position: relative;
}
-.knowledge-graph-container.loading > ::deep svg {
+.knowledge-graph-container.loading> ::deep svg {
display: none !important;
}
@@ -93,9 +93,20 @@
}
@keyframes robot-pulse {
- 0% { transform: scale(1); filter: drop-shadow(0 0 10px var(--nexus-neon)); }
- 50% { transform: scale(1.1); filter: drop-shadow(0 0 25px var(--nexus-neon)); }
- 100% { transform: scale(1); filter: drop-shadow(0 0 10px var(--nexus-neon)); }
+ 0% {
+ transform: scale(1);
+ filter: drop-shadow(0 0 10px var(--nexus-neon));
+ }
+
+ 50% {
+ transform: scale(1.1);
+ filter: drop-shadow(0 0 25px var(--nexus-neon));
+ }
+
+ 100% {
+ transform: scale(1);
+ filter: drop-shadow(0 0 10px var(--nexus-neon));
+ }
}
.scan-line {
@@ -111,9 +122,17 @@
}
@keyframes scan {
- 0% { top: 0; }
- 50% { top: 100%; }
- 100% { top: 0; }
+ 0% {
+ top: 0;
+ }
+
+ 50% {
+ top: 100%;
+ }
+
+ 100% {
+ top: 0;
+ }
}
::deep .nexus-node-active {
@@ -124,11 +143,24 @@
}
::deep @keyframes neon-flash {
- 0% { filter: brightness(1) drop-shadow(0 0 0px var(--nexus-neon)); }
- 50% { filter: brightness(3) drop-shadow(0 0 30px var(--nexus-neon)); }
- 100% { filter: brightness(1) drop-shadow(0 0 0px var(--nexus-neon)); }
+ 0% {
+ filter: brightness(1) drop-shadow(0 0 0px var(--nexus-neon));
+ }
+
+ 50% {
+ filter: brightness(3) drop-shadow(0 0 30px var(--nexus-neon));
+ }
+
+ 100% {
+ filter: brightness(1) drop-shadow(0 0 0px var(--nexus-neon));
+ }
}
::deep .neon-flash-node {
animation: neon-flash 0.8s ease-out;
}
+
+.knowledge-graph-container ::deep svg {
+ background: radial-gradient(circle, #1a1a1a 0%, #121212 100%);
+ transition: background 0.3s ease;
+}
\ No newline at end of file
diff --git a/src/NexusReader.UI.Shared/Components/Organisms/ReaderCanvas.razor.css b/src/NexusReader.UI.Shared/Components/Organisms/ReaderCanvas.razor.css
index d9b1641..6b00afe 100644
--- a/src/NexusReader.UI.Shared/Components/Organisms/ReaderCanvas.razor.css
+++ b/src/NexusReader.UI.Shared/Components/Organisms/ReaderCanvas.razor.css
@@ -6,7 +6,7 @@
padding: 2rem 0;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
-
+
/* Dedicated Scrollbar Styling */
scrollbar-width: thin;
scrollbar-color: rgba(0, 255, 153, 0.2) transparent;
@@ -35,7 +35,8 @@
}
.reader-canvas.theme-light {
- background-color: #F9F9F9; /* Paper-white requirement */
+ background-color: #f4f1ea;
+ /* Warm light beige/gray background */
}
.reader-flow-container {
@@ -46,7 +47,8 @@
flex-direction: column;
gap: 1.5rem;
position: relative;
- padding: 3rem 4rem 15rem 4rem; /* Large padding-bottom for reachability, plus comfortable side margins */
+ padding: 3rem 4rem 15rem 4rem;
+ /* Large padding-bottom for reachability, plus comfortable side margins */
border-radius: 12px;
box-sizing: border-box;
transition: background-color 0.3s, box-shadow 0.3s, border-color 0.3s;
@@ -61,7 +63,7 @@
.theme-light .reader-flow-container {
background-color: #ffffff;
border: 1px solid rgba(0, 0, 0, 0.04);
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
+ box-shadow: 0 4px 20px rgba(139, 130, 115, 0.12);
}
.block-wrapper {
@@ -79,11 +81,13 @@
font-size: 1.15rem;
font-weight: 400;
text-align: left !important;
- color: #e4e4e7; /* Off-white with light gray tint */
+ color: #e4e4e7;
+ /* Off-white with light gray tint */
}
.theme-light ::deep .nexus-ebook {
- color: #1a1a1a;
+ color: #292524;
+ /* Warm charcoal for legibility */
}
/* Callout Box styling for legacy blockquote segments */
@@ -99,22 +103,25 @@
}
.theme-light ::deep .nexus-ebook blockquote {
- background-color: rgba(0, 0, 0, 0.02);
- color: #333333;
+ background-color: rgba(245, 158, 11, 0.04);
+ border-left: 4px solid #f59e0b;
+ color: #44403c;
}
/* Technical Code Block Container */
::deep .nexus-ebook pre {
- background-color: #2d2d2d; /* Dark theme for code for better contrast */
+ background-color: #2d2d2d;
+ /* Dark theme for code for better contrast */
color: #e0e0e0;
padding: 1.25rem;
border-radius: 8px;
margin: 2rem 0;
overflow-x: auto;
- box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
- border-left: 4px solid var(--nexus-neon); /* Nexus neon accent */
-
+ box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1);
+ border-left: 4px solid var(--nexus-neon);
+ /* Nexus neon accent */
+
/* Dedicated Scrollbar for Code */
scrollbar-width: thin;
scrollbar-color: rgba(0, 255, 153, 0.3) transparent;
@@ -141,7 +148,8 @@
/* Inline Code Highlight */
::deep .nexus-ebook p code {
background-color: rgba(0, 0, 0, 0.05);
- color: #d63384; /* Classic differentiator for inline code */
+ color: #d63384;
+ /* Classic differentiator for inline code */
padding: 0.2rem 0.4rem;
border-radius: 4px;
font-size: 0.9em;
@@ -193,9 +201,20 @@
}
@keyframes pulse-small {
- 0% { transform: scale(1); opacity: 1; }
- 50% { transform: scale(1.1); opacity: 0.8; }
- 100% { transform: scale(1); opacity: 1; }
+ 0% {
+ transform: scale(1);
+ opacity: 1;
+ }
+
+ 50% {
+ transform: scale(1.1);
+ opacity: 0.8;
+ }
+
+ 100% {
+ transform: scale(1);
+ opacity: 1;
+ }
}
/* Chapter Loading Overlay and Spinners */
@@ -286,29 +305,48 @@
}
@keyframes spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(360deg); }
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
}
@keyframes scaleIn {
- from { transform: scale(0.9) translateY(10px); opacity: 0; }
- to { transform: scale(1) translateY(0); opacity: 1; }
+ from {
+ transform: scale(0.9) translateY(10px);
+ opacity: 0;
+ }
+
+ to {
+ transform: scale(1) translateY(0);
+ opacity: 1;
+ }
}
@keyframes fadeIn {
- from { opacity: 0; }
- to { opacity: 1; }
+ from {
+ opacity: 0;
+ }
+
+ to {
+ opacity: 1;
+ }
}
/* MOBILE READER UI OVERRIDES */
@media (max-width: 768px) {
.reader-canvas {
padding-top: 54px !important;
- padding-bottom: 80px !important; /* Ensure content is clear of bottom toolbar */
+ padding-bottom: 80px !important;
+ /* Ensure content is clear of bottom toolbar */
}
.reader-flow-container {
- padding-bottom: 4rem; /* Safe breathing room */
+ padding-bottom: 4rem;
+ /* Safe breathing room */
}
}
@@ -378,7 +416,20 @@
}
.theme-light .nexus-mobile-chapter-title {
- color: #1a1a1a;
+ color: #292524;
+}
+
+.theme-light .nexus-mobile-escape-btn {
+ color: #78716c;
+}
+
+.theme-light .nexus-mobile-escape-btn:hover {
+ color: #10b981;
+ background-color: rgba(16, 185, 129, 0.05);
+}
+
+.theme-light .nexus-mobile-escape-btn:active {
+ background-color: rgba(16, 185, 129, 0.08);
}
.nexus-chapter-nav-btn {
@@ -412,4 +463,4 @@
.theme-light .nexus-chapter-nav-btn:hover:not(:disabled) {
background: rgba(0, 0, 0, 0.06);
-}
+}
\ No newline at end of file
diff --git a/src/NexusReader.UI.Shared/Components/Organisms/ReaderFooter.razor.css b/src/NexusReader.UI.Shared/Components/Organisms/ReaderFooter.razor.css
index f8da658..0770298 100644
--- a/src/NexusReader.UI.Shared/Components/Organisms/ReaderFooter.razor.css
+++ b/src/NexusReader.UI.Shared/Components/Organisms/ReaderFooter.razor.css
@@ -18,11 +18,10 @@
transition: background 0.3s, border-color 0.3s, box-shadow 0.3s;
}
-/* Light mode override for .reader-footer */
:global(.theme-light) .reader-footer {
- background: rgba(255, 255, 255, 0.7);
- border: 1px solid rgba(0, 0, 0, 0.06);
- box-shadow: 0 10px 25px rgba(0, 0, 0, 0.05);
+ background: rgba(254, 254, 254, 0.75);
+ border: 1px solid rgba(0, 0, 0, 0.08);
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.04), 0 1px 3px rgba(0, 0, 0, 0.02);
}
.footer-content {
@@ -72,14 +71,14 @@
:global(.theme-light) .nav-btn {
background: rgba(0, 0, 0, 0.02);
border-color: rgba(0, 0, 0, 0.08);
- color: #71717a; /* Zinc-500 for light mode */
+ color: #78716c; /* Warm stone-500 */
}
:global(.theme-light) .nav-btn:hover:not(:disabled),
:global(.theme-light) .nav-btn:focus:not(:disabled) {
- background: rgba(0, 0, 0, 0.05);
- border-color: var(--nexus-neon, #00bb77);
- color: var(--nexus-neon, #00bb77);
+ background: rgba(16, 185, 129, 0.05);
+ border-color: #10b981;
+ color: #10b981;
outline: none;
}
@@ -94,7 +93,7 @@
}
:global(.theme-light) .chapter-info {
- color: #18181b; /* Zinc-900 for high light contrast */
+ color: #292524; /* Warm charcoal for legibility */
}
.chapter-title {
@@ -113,7 +112,7 @@
}
:global(.theme-light) .chapter-count {
- color: #71717a; /* Zinc-500 secondary info for light mode */
+ color: #78716c; /* Warm stone-500 secondary info */
}
.progress-container {
@@ -137,6 +136,10 @@
transition: width 0.3s ease;
}
+:global(.theme-light) .progress-bar {
+ background: #10b981;
+}
+
.meta-info {
display: flex;
align-items: center;
@@ -148,7 +151,7 @@
}
:global(.theme-light) .meta-info {
- color: #71717a;
+ color: #78716c;
}
.battery {
diff --git a/src/NexusReader.UI.Shared/Layout/ReaderLayout.razor.css b/src/NexusReader.UI.Shared/Layout/ReaderLayout.razor.css
index 64779c3..2f2ff1c 100644
--- a/src/NexusReader.UI.Shared/Layout/ReaderLayout.razor.css
+++ b/src/NexusReader.UI.Shared/Layout/ReaderLayout.razor.css
@@ -30,7 +30,8 @@ main {
.intelligence-sidebar {
display: grid;
grid-template-columns: 50px 1fr;
- width: 100%; /* controlled by grid */
+ width: 100%;
+ /* controlled by grid */
height: 100%;
background: var(--nexus-card);
box-shadow: -10px 0 30px rgba(0, 0, 0, 0.3);
@@ -49,7 +50,8 @@ main {
border-left: 1px solid rgba(255, 255, 255, 0.05);
}
-.resizer:hover, .app-container.is-resizing .resizer {
+.resizer:hover,
+.app-container.is-resizing .resizer {
background: var(--nexus-neon);
width: 6px;
box-shadow: 0 0 10px var(--nexus-neon);
@@ -151,9 +153,20 @@ main {
}
@keyframes quiz-pulse {
- 0% { filter: drop-shadow(0 0 2px var(--nexus-neon)); transform: scale(1); }
- 50% { filter: drop-shadow(0 0 10px var(--nexus-neon)); transform: scale(1.1); }
- 100% { filter: drop-shadow(0 0 2px var(--nexus-neon)); transform: scale(1); }
+ 0% {
+ filter: drop-shadow(0 0 2px var(--nexus-neon));
+ transform: scale(1);
+ }
+
+ 50% {
+ filter: drop-shadow(0 0 10px var(--nexus-neon));
+ transform: scale(1.1);
+ }
+
+ 100% {
+ filter: drop-shadow(0 0 2px var(--nexus-neon));
+ transform: scale(1);
+ }
}
/* Contextual Intelligence Panel Layout */
@@ -228,9 +241,20 @@ main {
}
@keyframes glow-pulse {
- 0% { transform: scale(0.9); opacity: 0.5; }
- 50% { transform: scale(1.1); opacity: 1; }
- 100% { transform: scale(0.9); opacity: 0.5; }
+ 0% {
+ transform: scale(0.9);
+ opacity: 0.5;
+ }
+
+ 50% {
+ transform: scale(1.1);
+ opacity: 1;
+ }
+
+ 100% {
+ transform: scale(0.9);
+ opacity: 0.5;
+ }
}
.placeholder-text {
@@ -247,8 +271,15 @@ main {
}
@keyframes fade-in {
- from { opacity: 0; transform: translateY(5px); }
- to { opacity: 1; transform: translateY(0); }
+ from {
+ opacity: 0;
+ transform: translateY(5px);
+ }
+
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
}
.node-header-section {
@@ -434,9 +465,20 @@ main {
}
@keyframes quiz-pulse-glow {
- 0% { border-color: rgba(0, 240, 255, 0.3); box-shadow: 0 0 5px rgba(0, 240, 255, 0.1); }
- 50% { border-color: var(--nexus-neon, #00f0ff); box-shadow: 0 0 25px rgba(0, 240, 255, 0.3); }
- 100% { border-color: rgba(0, 240, 255, 0.3); box-shadow: 0 0 5px rgba(0, 240, 255, 0.1); }
+ 0% {
+ border-color: rgba(0, 240, 255, 0.3);
+ box-shadow: 0 0 5px rgba(0, 240, 255, 0.1);
+ }
+
+ 50% {
+ border-color: var(--nexus-neon, #00f0ff);
+ box-shadow: 0 0 25px rgba(0, 240, 255, 0.3);
+ }
+
+ 100% {
+ border-color: rgba(0, 240, 255, 0.3);
+ box-shadow: 0 0 5px rgba(0, 240, 255, 0.1);
+ }
}
/* Quiz Navigation Header */
@@ -481,7 +523,8 @@ main {
.platform-mobile .reader-pane {
width: 100vw !important;
- height: 100vh !important; /* full viewport height */
+ height: 100vh !important;
+ /* full viewport height */
position: absolute;
top: 0;
left: 0;
@@ -508,9 +551,11 @@ main {
}
.platform-mobile .nexus-mobile-reader-tabs {
- display: none; /* Keep hidden by default */
+ display: none;
+ /* Keep hidden by default */
width: 100vw;
- height: 100vh; /* full viewport height */
+ height: 100vh;
+ /* full viewport height */
position: absolute;
top: 0;
left: 0;
@@ -521,7 +566,8 @@ main {
.app-container.platform-mobile.active-mobile-tab-graph .nexus-mobile-reader-tabs,
.app-container.platform-mobile.active-mobile-tab-concepts .nexus-mobile-reader-tabs {
- display: block; /* Show only when graph or concepts tabs are active */
+ display: block;
+ /* Show only when graph or concepts tabs are active */
}
.nexus-mobile-tab-content {
@@ -544,6 +590,7 @@ main {
opacity: 0;
transform: translateY(10px);
}
+
to {
opacity: 1;
transform: translateY(0);
@@ -623,9 +670,18 @@ main {
}
@keyframes quiz-pulse-btn-anim {
- 0% { color: rgba(255, 255, 255, 0.5); }
- 50% { color: #f43f5e; text-shadow: 0 0 8px rgba(244, 63, 94, 0.6); }
- 100% { color: rgba(255, 255, 255, 0.5); }
+ 0% {
+ color: rgba(255, 255, 255, 0.5);
+ }
+
+ 50% {
+ color: #f43f5e;
+ text-shadow: 0 0 8px rgba(244, 63, 94, 0.6);
+ }
+
+ 100% {
+ color: rgba(255, 255, 255, 0.5);
+ }
}
.mobile-insight-body {
@@ -653,22 +709,42 @@ main {
/* Theme-specific Overrides for Light Mode */
.app-container.theme-light .intelligence-sidebar {
- background: #ffffff;
+ background: #f4f1ea;
border-left: 1px solid rgba(0, 0, 0, 0.08);
+ box-shadow: -10px 0 30px rgba(139, 130, 115, 0.05);
+}
+
+.app-container.theme-light .resizer {
+ background: rgba(0, 0, 0, 0.02);
+ border-left: 1px solid rgba(0, 0, 0, 0.08);
+}
+
+.app-container.theme-light .resizer:hover,
+.app-container.theme-light.is-resizing .resizer {
+ background: #10b981;
+ box-shadow: 0 0 10px rgba(16, 185, 129, 0.3);
}
.app-container.theme-light .intelligence-header {
background: rgba(0, 0, 0, 0.02);
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
- color: #121212;
+ color: #292524;
}
.app-container.theme-light .close-btn {
- color: #666;
+ color: #878378;
+}
+
+.app-container.theme-light .close-btn:hover {
+ color: #292524;
+}
+
+.app-container.theme-light .visual-workspace {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}
.app-container.theme-light .contextual-intelligence-panel {
- background: rgba(0, 0, 0, 0.02);
+ background: #f4f1ea;
border-top: 1px solid rgba(0, 0, 0, 0.05);
}
@@ -678,31 +754,142 @@ main {
}
.app-container.theme-light .panel-title {
- color: rgba(0, 0, 0, 0.6);
+ color: #78716c;
}
.app-container.theme-light .no-node-selected {
- color: rgba(0, 0, 0, 0.5);
+ color: #878378;
+}
+
+.app-container.theme-light .placeholder-glow {
+ background: radial-gradient(circle, rgba(16, 185, 129, 0.15) 0%, transparent 70%);
+}
+
+.app-container.theme-light .node-header-section {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.08);
+}
+
+.app-container.theme-light .node-label {
+ color: #292524;
}
.app-container.theme-light .node-details .section-title {
- color: #121212;
+ color: #78716c;
+}
+
+.app-container.theme-light .neon-sub-header {
+ border-left: 2px solid #10b981;
+ text-shadow: none;
}
.app-container.theme-light .node-description {
- color: #333333;
+ color: #292524;
}
.app-container.theme-light .node-summary {
- color: #333333;
+ color: #44403c;
+ background: rgba(0, 0, 0, 0.02);
+ border-left: 2px solid rgba(0, 0, 0, 0.1);
}
.app-container.theme-light .key-term-item {
- color: #333333;
+ color: #292524;
+}
+
+.app-container.theme-light .term-bullet {
+ color: #10b981;
+ filter: none;
+}
+
+.app-container.theme-light .sidebar-footer {
+ background: #f4f1ea;
+ border-top: 1px solid rgba(0, 0, 0, 0.08);
+}
+
+.app-container.theme-light .open-quiz-btn {
+ background: rgba(16, 185, 129, 0.03);
+ border: 1px solid rgba(16, 185, 129, 0.3);
+ color: #10b981;
+ box-shadow: 0 4px 15px rgba(16, 185, 129, 0.05);
+}
+
+.app-container.theme-light .open-quiz-btn:hover {
+ background: rgba(16, 185, 129, 0.08);
+ border-color: #10b981;
+ color: #10b981;
+ box-shadow: 0 0 20px rgba(16, 185, 129, 0.15);
+}
+
+.app-container.theme-light .quiz-pulse-btn {
+ animation: quiz-pulse-btn-light 2s infinite ease-in-out;
+}
+
+@keyframes quiz-pulse-btn-light {
+ 0% {
+ border-color: rgba(16, 185, 129, 0.3);
+ box-shadow: 0 0 5px rgba(16, 185, 129, 0.05);
+ }
+
+ 50% {
+ border-color: #10b981;
+ box-shadow: 0 0 20px rgba(16, 185, 129, 0.2);
+ }
+
+ 100% {
+ border-color: rgba(16, 185, 129, 0.3);
+ box-shadow: 0 0 5px rgba(16, 185, 129, 0.05);
+ }
+}
+
+.app-container.theme-light .quiz-nav {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.08);
+ background: rgba(0, 0, 0, 0.01);
+}
+
+.app-container.theme-light .back-to-graph-btn {
+ color: #78716c;
+}
+
+.app-container.theme-light .back-to-graph-btn:hover {
+ color: #10b981;
+ background: rgba(0, 0, 0, 0.03);
}
.app-container.theme-light .mobile-insight-body {
- background: #f9f9f9;
+ background: #f4f1ea;
+}
+
+.app-container.theme-light .mobile-insight-header {
+ background: #f4f1ea;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.08);
+}
+
+.app-container.theme-light .mobile-insight-nav {
+ background: rgba(0, 0, 0, 0.02);
+ border: 1px solid rgba(0, 0, 0, 0.05);
+}
+
+.app-container.theme-light .mobile-insight-nav-btn {
+ color: #78716c;
+}
+
+.app-container.theme-light .mobile-insight-nav-btn.active {
+ background: rgba(16, 185, 129, 0.1);
+ color: #10b981;
+ box-shadow: 0 0 10px rgba(16, 185, 129, 0.1);
+}
+
+.app-container.theme-light .skeleton-line {
+ background: linear-gradient(90deg, rgba(0, 0, 0, 0.03) 25%, rgba(0, 0, 0, 0.08) 50%, rgba(0, 0, 0, 0.03) 75%);
+}
+
+.app-container.theme-light .clear-summary-btn {
+ color: rgba(0, 0, 0, 0.4);
+}
+
+.app-container.theme-light .clear-summary-btn:hover {
+ color: #ef4444;
+ background: rgba(239, 68, 68, 0.08);
}
/* Skeleton Loader for Selection Summary */
@@ -727,15 +914,27 @@ main {
margin-bottom: 0.5rem;
}
-.skeleton-line.w-90 { width: 90%; }
-.skeleton-line.w-80 { width: 80%; }
-.skeleton-line.w-70 { width: 70%; }
-.skeleton-line.w-60 { width: 60%; }
+.skeleton-line.w-90 {
+ width: 90%;
+}
+
+.skeleton-line.w-80 {
+ width: 80%;
+}
+
+.skeleton-line.w-70 {
+ width: 70%;
+}
+
+.skeleton-line.w-60 {
+ width: 60%;
+}
@keyframes skeleton-shimmer {
0% {
background-position: 200% 0;
}
+
100% {
background-position: -200% 0;
}
@@ -767,4 +966,4 @@ main {
.clear-summary-btn:hover {
color: #ef4444;
background: rgba(239, 68, 68, 0.1);
-}
+}
\ No newline at end of file
diff --git a/src/NexusReader.UI.Shared/wwwroot/app.css b/src/NexusReader.UI.Shared/wwwroot/app.css
index b4b05e2..b3095e3 100644
--- a/src/NexusReader.UI.Shared/wwwroot/app.css
+++ b/src/NexusReader.UI.Shared/wwwroot/app.css
@@ -19,31 +19,32 @@
color: inherit;
}
-
- /* Global Semantic Theme Mapping */
- --nexus-primary: var(--nexus-neon);
- --nexus-primary-glow: var(--nexus-neon-glow);
- --nexus-primary-hover: #00e688;
-
- /* Standard Layout Tokens */
- --radius-sm: 8px;
- --radius-md: 12px;
- --radius-lg: 16px;
- --radius-xl: 20px;
-
- /* Safe Area Insets with fallbacks */
- --safe-area-inset-top: env(safe-area-inset-top, 0px);
- --safe-area-inset-bottom: env(safe-area-inset-bottom, 0px);
- --safe-area-inset-left: env(safe-area-inset-left, 0px);
- --safe-area-inset-right: env(safe-area-inset-right, 0px);
- /* Transitions */
- --nexus-transition: 0.4s cubic-bezier(0.4, 0, 0.2, 1);
+/* Global Semantic Theme Mapping */
+--nexus-primary: var(--nexus-neon);
+--nexus-primary-glow: var(--nexus-neon-glow);
+--nexus-primary-hover: #00e688;
+
+/* Standard Layout Tokens */
+--radius-sm: 8px;
+--radius-md: 12px;
+--radius-lg: 16px;
+--radius-xl: 20px;
+
+/* Safe Area Insets with fallbacks */
+--safe-area-inset-top: env(safe-area-inset-top, 0px);
+--safe-area-inset-bottom: env(safe-area-inset-bottom, 0px);
+--safe-area-inset-left: env(safe-area-inset-left, 0px);
+--safe-area-inset-right: env(safe-area-inset-right, 0px);
+
+/* Transitions */
+--nexus-transition: 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Global Glassmorphism with Fallback */
.glass-panel {
- background: rgba(20, 20, 20, 0.85); /* Darker fallback for readability */
+ background: rgba(20, 20, 20, 0.85);
+ /* Darker fallback for readability */
border: 1px solid rgba(255, 255, 255, 0.05);
border-radius: var(--radius-xl);
padding: 1.5rem;
@@ -71,33 +72,167 @@
border: none;
text-decoration: none;
}
+
.btn-nexus-primary {
background: var(--nexus-neon);
color: #000000;
}
+
.btn-nexus-secondary {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
color: #ffffff;
}
+
.btn-nexus:hover {
transform: translateY(-2px);
filter: brightness(1.1);
}
+
.btn-nexus-primary:hover {
box-shadow: 0 4px 15px var(--nexus-primary-glow);
}
+
.btn-nexus-secondary:hover {
box-shadow: 0 4px 15px rgba(255, 255, 255, 0.05);
}
.theme-light {
- --nexus-bg: var(--nexus-paper);
+ --nexus-bg: #f4f1ea;
--nexus-card: #ffffff;
- --nexus-text: #121212;
+ --nexus-text: #2d2a26;
+ --nexus-selection: rgba(16, 185, 129, 0.18);
}
+/* Scoped Component overrides for Light Mode (Bypassing Blazor CSS isolation) */
+.theme-light .intelligence-toolbar {
+ background: #f5f5f4 !important;
+ border-right: 1px solid rgba(0, 0, 0, 0.08) !important;
+ box-shadow: inset -2px 0 10px rgba(0, 0, 0, 0.02) !important;
+}
+
+.theme-light .intelligence-toolbar .toolbar-item {
+ color: #78716c !important;
+}
+
+.theme-light .intelligence-toolbar .toolbar-item:hover {
+ color: #10b981 !important;
+ background: rgba(16, 185, 129, 0.05) !important;
+ box-shadow: 0 0 10px rgba(16, 185, 129, 0.1) !important;
+ filter: none !important;
+}
+
+.theme-light .intelligence-toolbar .toolbar-item.active {
+ color: #10b981 !important;
+ background: rgba(16, 185, 129, 0.08) !important;
+ box-shadow: 0 0 15px rgba(16, 185, 129, 0.15) !important;
+ filter: none !important;
+}
+
+.theme-light .intelligence-toolbar .toolbar-item.active::after {
+ background: #10b981 !important;
+ box-shadow: none !important;
+}
+
+.theme-light .intelligence-toolbar .toolbar-item.focus-active {
+ color: #10b981 !important;
+ filter: none !important;
+}
+
+.theme-light .intelligence-toolbar .toolbar-item.logout-item {
+ border-top: 1px solid rgba(0, 0, 0, 0.08) !important;
+ color: #a8a29e !important;
+}
+
+.theme-light .intelligence-toolbar .toolbar-item.logout-item:hover {
+ color: #ef4444 !important;
+ filter: none !important;
+}
+
+.theme-light .knowledge-graph-container svg {
+ background: radial-gradient(circle, #ffffff 0%, #e8e4da 100%) !important;
+}
+
+.theme-light .graph-controls {
+ background: rgba(254, 254, 253, 0.4) !important;
+ border: 1px solid rgba(0, 0, 0, 0.08) !important;
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.04) !important;
+}
+
+.theme-light .zoom-btn {
+ background: rgba(0, 0, 0, 0.02) !important;
+ border: 1px solid rgba(0, 0, 0, 0.06) !important;
+ color: #78716c !important;
+}
+
+.theme-light .zoom-btn:hover {
+ background: rgba(16, 185, 129, 0.05) !important;
+ color: #10b981 !important;
+ border-color: #10b981 !important;
+}
+
+.theme-light .loading-state {
+ color: #292524 !important;
+ background: rgba(254, 254, 254, 0.85) !important;
+ border: 1px solid rgba(0, 0, 0, 0.05) !important;
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.05) !important;
+}
+
+.theme-light .neon-pulse {
+ color: #10b981 !important;
+ filter: none !important;
+ animation: robot-pulse-light 2s infinite ease-in-out !important;
+}
+
+.theme-light .scan-line {
+ background: #10b981 !important;
+ box-shadow: 0 0 10px rgba(16, 185, 129, 0.5) !important;
+}
+
+.theme-light .nexus-node-active {
+ stroke: #10b981 !important;
+ filter: drop-shadow(0 0 8px rgba(16, 185, 129, 0.2)) !important;
+}
+
+@keyframes robot-pulse-light {
+ 0% { transform: scale(1); }
+ 50% { transform: scale(1.05); }
+ 100% { transform: scale(1); }
+}
+
+.theme-light ::-webkit-scrollbar-thumb {
+ background: rgba(0, 0, 0, 0.1);
+}
+
+.theme-light ::-webkit-scrollbar-thumb:hover {
+ background: rgba(0, 0, 0, 0.2);
+}
+
+.theme-light .glass-panel {
+ background: rgba(255, 255, 255, 0.85);
+ border: 1px solid rgba(0, 0, 0, 0.05);
+}
+
+@supports (backdrop-filter: blur(10px)) {
+ .theme-light .glass-panel {
+ background: rgba(255, 255, 255, 0.7);
+ backdrop-filter: blur(10px);
+ }
+}
+
+.theme-light .btn-nexus-secondary {
+ background: rgba(0, 0, 0, 0.04);
+ border: 1px solid rgba(0, 0, 0, 0.08);
+ color: #292524;
+}
+
+.theme-light .btn-nexus-secondary:hover {
+ background: rgba(0, 0, 0, 0.08);
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
+}
+
+
* {
box-sizing: border-box;
@@ -111,13 +246,13 @@ body {
font-family: var(--nexus-font-sans);
margin: 0;
padding: 0;
-
+
/* Handle Notches */
padding-top: var(--safe-area-inset-top);
padding-bottom: var(--safe-area-inset-bottom);
padding-left: var(--safe-area-inset-left);
padding-right: var(--safe-area-inset-right);
-
+
min-height: 100vh;
overflow-x: hidden;
}
@@ -174,7 +309,8 @@ h1:focus {
}
/* Preloader Styles */
-#app-preloader, .app-preloader {
+#app-preloader,
+.app-preloader {
position: fixed;
top: 0;
left: 0;
@@ -216,12 +352,25 @@ h1:focus {
}
@keyframes spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(360deg); }
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
}
@keyframes pulse {
- 0%, 100% { opacity: 1; transform: scale(1); }
- 50% { opacity: 0.5; transform: scale(0.95); }
-}
-
\ No newline at end of file
+
+ 0%,
+ 100% {
+ opacity: 1;
+ transform: scale(1);
+ }
+
+ 50% {
+ opacity: 0.5;
+ transform: scale(0.95);
+ }
+}
\ No newline at end of file
diff --git a/src/NexusReader.UI.Shared/wwwroot/js/knowledgeGraph.js b/src/NexusReader.UI.Shared/wwwroot/js/knowledgeGraph.js
index d5f671f..a5c78de 100644
--- a/src/NexusReader.UI.Shared/wwwroot/js/knowledgeGraph.js
+++ b/src/NexusReader.UI.Shared/wwwroot/js/knowledgeGraph.js
@@ -131,16 +131,16 @@ const getNodeGlyph = d => {
function updateNodeAppearances() {
if (!node) return;
-
- node.each(function(d) {
+
+ node.each(function (d) {
const g = d3.select(this);
const rect = g.select(".node-pill");
const text = g.select("text");
-
+
const isCurrent = getNodeGroup(d) === 'current';
const isSelected = activeNodeId && d.id === activeNodeId;
const showFull = !isMobileMode || isSelected || isCurrent;
-
+
if (showFull) {
rect.transition().duration(250)
.attr("x", -getPillWidth(d) / 2)
@@ -148,7 +148,7 @@ function updateNodeAppearances() {
.attr("height", 30)
.attr("rx", 15)
.attr("y", -15);
-
+
text.text(getDisplayLabel(d))
.attr("font-size", isCurrent || isSelected ? "0.85rem" : "0.8rem")
.attr("font-weight", isCurrent || isSelected ? "600" : "normal");
@@ -159,7 +159,7 @@ function updateNodeAppearances() {
.attr("height", 30)
.attr("rx", 15)
.attr("y", -15);
-
+
text.text(getNodeGlyph(d))
.attr("font-size", "0.9rem")
.attr("font-weight", "bold");
@@ -170,7 +170,7 @@ function updateNodeAppearances() {
export function setMobileMode(isMobile) {
isMobileMode = isMobile;
if (!simulation) return;
-
+
if (isMobile) {
simulation.force("charge", d3.forceManyBody().strength(-60));
simulation.force("link").distance(180);
@@ -187,7 +187,7 @@ export function setMobileMode(isMobile) {
simulation.force("link").distance(120);
simulation.force("collide", d3.forceCollide().radius(d => (getPillWidth(d) / 2) + 20));
}
-
+
updateNodeAppearances();
simulation.alpha(0.3).restart();
}
@@ -212,7 +212,7 @@ export function mount(containerId, data, dotNetHelper) {
// Radial gradients for Nebula effects
const defs = svgElement.append("defs");
-
+
// Fallback radial gradient for legacy nebulaGlow
const radialGradient = defs.append("radialGradient")
.attr("id", "nebulaGlow")
@@ -275,7 +275,7 @@ export function mount(containerId, data, dotNetHelper) {
zoomBehavior = d3.zoom()
.scaleExtent([0.3, 4])
.on("zoom", (e) => rootGroup.attr("transform", e.transform));
-
+
svgElement.call(zoomBehavior).on("wheel.zoom", null);
// Use ResizeObserver for more reliable container size tracking
@@ -324,7 +324,7 @@ export function mount(containerId, data, dotNetHelper) {
return `translate(${d.x},${d.y})`;
});
}
-
+
if (badge && badge.style("display") !== "none") {
const activeData = badge.datum();
if (activeData) {
@@ -424,9 +424,9 @@ export function updateData(data) {
g.append("title")
.text(d => d.description ? `${d.label}\n\n${d.description}` : d.label);
-
+
g.transition().duration(500).style("opacity", 1);
-
+
return g;
},
update => update.classed("neon-flash-node", false),
@@ -466,7 +466,7 @@ function drag(simulation) {
export function setActiveNode(nodeId) {
if (!svgElement || !node) return;
-
+
activeNodeId = nodeId;
// Safety check: ensure we only target the first occurrence if IDs are duplicated
const targetNode = node.filter(d => d.id === nodeId);
@@ -479,7 +479,7 @@ export function setActiveNode(nodeId) {
const firstMatch = targetNode.filter((d, i) => i === 0);
const d = firstMatch.datum();
if (!d || d.x === undefined || d.y === undefined || isNaN(d.x) || !isFinite(d.x) || isNaN(d.y) || !isFinite(d.y)) return;
-
+
// Reset all active classes
rootGroup.selectAll(".node-pill").classed("nexus-node-active", false);
firstMatch.select(".node-pill").classed("nexus-node-active", true);
@@ -502,7 +502,7 @@ export function setActiveNode(nodeId) {
return 20;
}));
}
-
+
updateNodeAppearances();
// Smooth transition to the first matching node
@@ -514,10 +514,10 @@ export function setActiveNode(nodeId) {
export function dimNodes(activeNodeId) {
if (!node) return;
-
+
node.transition().duration(500)
.style("opacity", d => (activeNodeId === null || d.id === activeNodeId) ? 1 : 0.4);
-
+
if (link) {
link.transition().duration(500)
.style("opacity", d => {
@@ -558,7 +558,7 @@ export function handleResize(containerId) {
svgElement.attr("viewBox", [0, 0, width, height]);
simulation.force("center", d3.forceCenter(width / 2, height / 2));
-
+
const prevMobileMode = isMobileMode;
isMobileMode = window.innerWidth < 768;
if (isMobileMode !== prevMobileMode) {