diff --git a/run-stage.sh b/run-stage.sh
index f923401..5da5195 100755
--- a/run-stage.sh
+++ b/run-stage.sh
@@ -4,11 +4,23 @@
# -------------------------------------------------------------
set -e
+NEXUS_ONLY=false
+for arg in "$@"; do
+ case $arg in
+ --nexus-only|-n)
+ NEXUS_ONLY=true
+ ;;
+ esac
+done
+
ENV_FILE=".env.stage"
TEMPLATE_FILE=".env.stage.template"
COMPOSE_FILE="docker-compose.stage.yml"
echo "🏁 Starting staging environment orchestration..."
+if [ "$NEXUS_ONLY" = true ]; then
+ echo "ℹ️ Mode: --nexus-only (only the web/nexus application container will be modified)"
+fi
# 1. Create .env.stage if it doesn't exist
if [ ! -f "$ENV_FILE" ]; then
@@ -58,13 +70,24 @@ POSTGRES_PORT=${POSTGRES_PORT:-5438}
WEB_PORT=${WEB_PORT:-5080}
# 3. Stop any conflicting Docker Compose environments
-echo "🧹 Stopping existing containers..."
-docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" down --remove-orphans || true
-docker compose down --remove-orphans 2>/dev/null || true
+if [ "$NEXUS_ONLY" = true ]; then
+ echo "🧹 Stopping and removing only the web (nexus) container..."
+ docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" stop web || true
+ docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" rm -f web || true
+else
+ echo "🧹 Stopping existing containers..."
+ docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" down --remove-orphans || true
+ docker compose down --remove-orphans 2>/dev/null || true
+fi
# 4. Build and start containers
-echo "🚀 Building and starting staging containers..."
-docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --build
+if [ "$NEXUS_ONLY" = true ]; then
+ echo "🚀 Building and restarting only the web (nexus) container..."
+ docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --build web
+else
+ echo "🚀 Building and starting staging containers..."
+ docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --build
+fi
# 5. Wait for Database to be healthy
echo "⏳ Waiting for database (nexus-db-stage) to become healthy..."
diff --git a/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor b/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor
index 4633326..39e2c83 100644
--- a/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor
+++ b/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor
@@ -6,15 +6,18 @@
@@ -22,8 +25,10 @@
@@ -57,7 +62,6 @@
private async Task FetchContent()
{
- // Tutaj trafia Twoja logika wyciągania zawartości z edytora Milkdown
await Task.CompletedTask;
}
}
diff --git a/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor.css b/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor.css
index 3e2c092..4b60b84 100644
--- a/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor.css
+++ b/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor.css
@@ -1,150 +1,179 @@
/* ==========================================================================
- NEXUSREADER CREATOR EDIT MODE - PREMIUM SAAS CORE STYLES
+ NEXUSREADER CREATOR EDIT MODE - HIGH-FIDELITY SAAS PREMIUM DESIGN OVERRIDE
========================================================================== */
-/* 1. MASTER WRAPPER (Zgładzenie globalnego scrolla przeglądarki) */
+/* 1. ARCHITECTURAL BOUNDARY CONTROL */
.creator-edit-fullscreen-wrapper {
width: 100% !important;
max-width: 100% !important;
- height: calc(100vh - 4rem) !important; /* Sztywne cięcie pod wysokość topbaru platformy */
+ height: calc(100vh - 4rem) !important;
margin: 0 !important;
padding: 0 !important;
display: flex !important;
- overflow: hidden !important; /* Całkowity zakaz scrollowania okna głównego */
- background-color: var(--bg-base);
+ overflow: hidden !important;
+ background-color: #121214;
box-sizing: border-box;
}
-/* 2. MATTE CHAPTERS SIDEBAR (Luksusowy panel boczny) */
+/* Dynamic theme bridge mapping for Warm Paper mode */
+.theme-light .creator-edit-fullscreen-wrapper {
+ background-color: #f4f1ea;
+}
+
+/* 2. UNIFIED SIDEBAR DESIGN (Eliminating layout color fragmentation) */
.chapters-sidebar {
- width: 290px !important;
+ width: 300px !important;
flex-shrink: 0;
- background-color: #141417 !important; /* Matowy głęboki antracyt z readera */
- border-right: 1px solid rgba(255, 255, 255, 0.05) !important;
+ background-color: #16161a !important;
+ border-right: 1px solid rgba(255, 255, 255, 0.04) !important;
display: flex;
flex-direction: column;
- padding: 2rem 1.25rem !important;
+ padding: 2.5rem 1.5rem !important;
box-sizing: border-box;
}
.theme-light .chapters-sidebar {
- background-color: #ede9df !important; /* Dopasowanie do motywu Warm Paper */
- border-right: 1px solid var(--border) !important;
+ background-color: #eae6db !important; /* Rich warm tone that remains fully cohesive with warm paper base */
+ border-right: 1px solid #dcd7cc !important;
}
-.chapters-sidebar h2 {
- font-size: 0.85rem;
+.sidebar-meta-header h2 {
+ font-size: 0.8rem;
font-weight: 700;
text-transform: uppercase;
- letter-spacing: 1.5px;
- color: var(--text-muted);
- margin: 0 0 1.5rem 0;
- padding-left: 0.5rem;
+ letter-spacing: 2px;
+ color: #a1a1aa;
+ margin: 0 0 1.75rem 0;
+}
+
+.theme-light .sidebar-meta-header h2 {
+ color: #78716c;
}
.chapters-list-wrapper {
display: flex;
flex-direction: column;
- gap: 4px;
+ gap: 6px;
}
-/* Elementy listy rozdziałów */
+/* Premium Navigation Links */
.chapter-item {
+ position: relative;
display: flex;
align-items: center;
gap: 12px;
- padding: 12px 14px !important;
- border-radius: 8px;
- color: var(--text-muted);
+ padding: 12px 16px !important;
+ border-radius: 10px;
+ color: #a1a1aa;
font-size: 0.95rem;
cursor: pointer;
- transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
- border-left: 3px solid transparent !important;
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+}
+
+.theme-light .chapter-item {
+ color: #78716c;
}
.chapter-item i.chapter-icon {
- font-size: 0.9rem;
- color: var(--text-muted);
+ font-size: 0.95rem;
+ color: #71717a;
+ transition: color 0.25s ease;
}
-/* Aktywny stan unifikacji wizualnej */
+/* Active Indicator Node Alignment */
.chapter-item.active {
- background-color: rgba(0, 255, 153, 0.04) !important;
- color: var(--accent) !important;
+ background-color: rgba(0, 255, 153, 0.05) !important;
+ color: #00ff99 !important;
font-weight: 600;
- border-left: 3px solid var(--accent) !important;
-}
-
-.chapter-item.active i.chapter-icon {
- color: var(--accent) !important;
}
.theme-light .chapter-item.active {
background-color: rgba(16, 185, 129, 0.06) !important;
+ color: #10b981 !important;
+}
+
+.chapter-item.active i.chapter-icon {
+ color: inherit !important;
}
.chapter-item:hover:not(.active) {
background-color: rgba(255, 255, 255, 0.02);
- color: var(--text-main);
+ color: #ffffff;
}
-/* 3. WORKSPACE CORE (Główna oś edytora) */
+.theme-light .chapter-item:hover:not(.active) {
+ background-color: rgba(0, 0, 0, 0.02);
+ color: #2d2a26;
+}
+
+/* 3. WORKSPACE METRICS (Zen presentation spacing) */
.editor-workspace-area {
flex-grow: 1;
display: flex;
flex-direction: column;
height: 100%;
- padding: 2.5rem 3.5rem 2rem 3.5rem !important; /* Odpowiedni, dostojny margines Zen Mode */
+ padding: 3rem 4rem 2.5rem 4rem !important; /* Generous padding context for premium scale */
box-sizing: border-box;
overflow: hidden;
}
-/* Nagłówek i ID bez ryzyka kolizji */
.editor-header-row {
display: flex;
justify-content: space-between;
align-items: center;
- margin-bottom: 1.5rem;
+ margin-bottom: 2rem;
flex-shrink: 0;
width: 100%;
}
.editor-workspace-area h1.chapter-title {
- font-size: 2.2rem;
+ font-size: 2.4rem;
font-weight: 700;
- color: var(--text-main);
+ color: #ffffff;
margin: 0;
- letter-spacing: -0.5px;
+ letter-spacing: -0.75px;
+}
+
+.theme-light .editor-workspace-area h1.chapter-title {
+ color: #2d2a26;
}
.chapter-id-badge {
font-family: 'Azeret Mono', monospace;
- font-size: 0.75rem;
- color: var(--text-muted);
- background: rgba(255, 255, 255, 0.03);
- padding: 5px 12px;
- border-radius: 6px;
- border: 1px solid rgba(255, 255, 255, 0.08);
- white-space: nowrap;
+ font-size: 0.72rem;
+ color: #71717a;
+ background: #1a1a1e;
+ padding: 6px 14px;
+ border-radius: 8px;
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ letter-spacing: 0.2px;
}
.theme-light .chapter-id-badge {
- background: rgba(0, 0, 0, 0.02);
- border: 1px solid var(--border);
+ background: #ffffff;
+ color: #78716c;
+ border: 1px solid #dcd7cc;
}
-/* 4. PREMIUM CANVAS CARD (Rozciąganie Flex na 100% wysokości) */
+/* 4. ELEVATED EDITOR CANVAS CARD (Introducing layered shadow mechanics) */
.editor-canvas-card {
- background-color: var(--bg-surface) !important;
- border: 1px solid var(--border) !important;
- border-radius: 16px;
- padding: 2.5rem !important;
+ background-color: #1a1a1e !important;
+ border: 1px solid rgba(255, 255, 255, 0.04) !important;
+ border-radius: 20px;
+ padding: 3rem !important;
display: flex;
flex-direction: column;
- flex-grow: 1; /* Wymusza rozciągnięcie do samego paska stopki */
+ flex-grow: 1;
overflow: hidden;
box-sizing: border-box;
- box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
+ /* Soft diffuse structural shadows mimicking actual surface elevation */
+ box-shadow: 0 20px 50px rgba(0, 0, 0, 0.4), 0 4px 12px rgba(0, 0, 0, 0.2);
+}
+
+.theme-light .editor-canvas-card {
+ background-color: #ffffff !important;
+ border: 1px solid #dcd7cc !important;
+ box-shadow: 0 20px 50px rgba(45, 42, 38, 0.04), 0 4px 12px rgba(45, 42, 38, 0.02);
}
.milkdown-premium-container {
@@ -155,8 +184,7 @@
width: 100%;
}
-/* --- DEEP SELECTORS DLA PROSEMIRROR (MILKDOWN RENDER) --- */
-
+/* DEEP MOUNTING COMPONENT INTEROP */
::deep .milkdown {
background: transparent !important;
box-shadow: none !important;
@@ -169,51 +197,32 @@
}
::deep .ProseMirror {
- color: var(--text-main) !important;
+ color: #e4e1d9 !important;
background-color: transparent !important;
- font-family: inherit !important;
- font-size: 1.1rem !important;
- line-height: 1.75 !important;
+ font-size: 1.15rem !important;
+ line-height: 1.8 !important;
flex-grow: 1;
- overflow-y: auto !important; /* Scroll pojawia się TYLKO na tekście rozdziału */
- padding-right: 15px !important;
+ overflow-y: auto !important;
+ padding-right: 24px !important;
outline: none !important;
box-sizing: border-box;
width: 100%;
}
-/* Kontekst zaznaczenia zunifikowany z readerem */
+.theme-light ::deep .ProseMirror {
+ color: #2d2a26 !important;
+}
+
+/* Precise matching text selection token */
::deep .ProseMirror ::selection {
- background-color: rgba(0, 255, 153, 0.25) !important;
- color: inherit !important;
+ background-color: rgba(0, 255, 153, 0.2) !important;
}
.theme-light ::deep .ProseMirror ::selection {
- background-color: rgba(16, 185, 129, 0.2) !important;
+ background-color: rgba(16, 185, 129, 0.18) !important;
}
-/* Popover / dymek formatowania zintegrowany z czytnikiem */
-::deep .milkdown .popover,
-::deep .milkdown-popover,
-::deep .prosemirror-bubble-menu {
- background-color: #1e1e22 !important;
- border: 1px solid rgba(255, 255, 255, 0.08) !important;
- border-radius: 12px !important;
- padding: 6px 10px !important;
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5) !important;
- display: flex !important;
- align-items: center !important;
- gap: 12px !important;
-}
-
-.theme-light ::deep .milkdown .popover,
-.theme-light ::deep .prosemirror-bubble-menu {
- background-color: #ffffff !important;
- border: 1px solid var(--border) !important;
- box-shadow: 0 10px 30px rgba(45, 42, 38, 0.06) !important;
-}
-
-/* Customowy, dyskretny scrollbar dla tekstu książki */
+/* Core webkit custom scrollbar mapping */
::deep .ProseMirror::-webkit-scrollbar {
width: 6px;
}
@@ -221,71 +230,96 @@
background: transparent;
}
::deep .ProseMirror::-webkit-scrollbar-thumb {
- background: var(--border);
- border-radius: 3px;
+ background: rgba(255, 255, 255, 0.08);
+ border-radius: 4px;
}
-/* 5. FIXED FOOTER BAR (Zintegrowany dół pancernej karty) */
+.theme-light ::deep .ProseMirror::-webkit-scrollbar-thumb {
+ background: #dcd7cc;
+}
+
+/* 5. SEAMLESS INTEGRATED ACTIONS FOOTER BAR */
.editor-footer-bar {
display: flex;
justify-content: space-between;
align-items: center;
- margin-top: 1.5rem;
- padding-top: 1.25rem;
- border-top: 1px solid var(--border);
- flex-shrink: 0; /* Gwarancja, że pasek nigdy nie ucieknie poza kartę */
+ margin-top: 2rem;
+ padding-top: 1.5rem;
+ border-top: 1px solid rgba(255, 255, 255, 0.04);
+ flex-shrink: 0;
width: 100%;
}
-/* Status zapisu w chmurze z pulsującą diodą akcentową */
+.theme-light .editor-footer-bar {
+ border-top: 1px solid #dcd7cc;
+}
+
+/* Telemetry cloud synchronization line */
.cloud-status-container {
display: flex;
align-items: center;
- gap: 10px;
+ gap: 12px;
}
.cloud-status-pulse {
- width: 8px;
- height: 8px;
- background-color: var(--accent);
+ width: 7px;
+ height: 7px;
+ background-color: #00ff99;
border-radius: 50%;
display: inline-block;
- box-shadow: 0 0 10px var(--accent);
- position: relative;
+ box-shadow: 0 0 10px rgba(0, 255, 153, 0.8);
+}
+
+.theme-light .cloud-status-pulse {
+ background-color: #10b981;
+ box-shadow: 0 0 10px rgba(16, 185, 129, 0.6);
}
.cloud-status-text {
font-family: 'Azeret Mono', monospace;
- font-size: 0.85rem;
- color: var(--text-muted);
+ font-size: 0.82rem;
+ color: #71717a;
+ letter-spacing: 0.1px;
}
-/* Przycisk akcji premium */
+/* Premium Tactile Operational Button Trigger */
.btn-nexus-premium {
- background-color: var(--accent) !important;
+ background-color: #00ff99 !important;
color: #121214 !important;
font-weight: 700;
- font-size: 0.95rem;
- padding: 10px 22px;
+ font-size: 0.9rem;
+ letter-spacing: -0.1px;
+ padding: 11px 24px;
border: none !important;
- border-radius: 8px;
+ border-radius: 10px;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 10px;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
- box-shadow: 0 4px 14px var(--accent-glow);
+ box-shadow: 0 4px 20px rgba(0, 255, 153, 0.15);
}
.theme-light .btn-nexus-premium {
+ background-color: #10b981 !important;
color: #ffffff !important;
+ box-shadow: 0 4px 20px rgba(16, 185, 129, 0.15);
+}
+
+.btn-nexus-premium i {
+ font-size: 0.85rem;
+ transition: transform 0.2s ease;
}
.btn-nexus-premium:hover {
transform: translateY(-1px);
- box-shadow: 0 6px 20px var(--accent-glow);
+ box-shadow: 0 8px 24px rgba(0, 255, 153, 0.3);
}
-.btn-nexus-premium:active {
- transform: translateY(0);
+.theme-light .btn-nexus-premium:hover {
+ box-shadow: 0 8px 24px rgba(16, 185, 129, 0.3);
+}
+
+.btn-nexus-premium:hover i {
+ transform: translateX(3px);
}