feat: complete Phase 1 foundation hardening + three-mode UI design doc
Phase 1a — Gradient Removal: - Replaced all gradient-button/gradient-card with glass-button/path-option-card - Removed banned gradient CSS classes Phase 1b — Security Hardening: - SecretsManager: AES-256-GCM encryption (core/security) - electrs_status: credentials from env vars instead of hardcoded - port_manager: RwLock proper error handling (no unwrap) - Pinned all 11 :latest manifest images to specific versions - parmanode converter: pinned inferred image versions Phase 1c — Code Quality: - Split rpc.rs (1795 lines) into 6 handler modules (auth, node, container, package, peers) - Removed sideload code (UI, store, RPC client, 3 doc files) - Fixed body background flash on logout/refresh - Replaced 30 TypeScript `any` types with proper types - Deleted HelloWorld.vue, removed TODO comments - Added set -euo pipefail to all shell scripts - Made deploy script verbose with timestamps and elapsed time Also adds: - CLAUDE.md project guide - docs/three-mode-ui-design.md — design spec for Easy/Pro/Chat UI modes - OnlineStatusPill component Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -66,28 +66,56 @@
|
||||
overflow-x: hidden;
|
||||
overflow-y: visible;
|
||||
}
|
||||
|
||||
|
||||
.glass-button {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 48px;
|
||||
min-height: 48px;
|
||||
padding-block: 0 !important;
|
||||
line-height: 48px;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
backdrop-filter: blur(18px);
|
||||
-webkit-backdrop-filter: blur(18px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.18);
|
||||
padding-inline: 1.25rem;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
backdrop-filter: blur(24px);
|
||||
-webkit-backdrop-filter: blur(24px);
|
||||
box-shadow:
|
||||
0 8px 24px rgba(0, 0, 0, 0.45),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.22);
|
||||
border-radius: 0.75rem;
|
||||
border: none;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.glass-button::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
padding: 2px;
|
||||
background: linear-gradient(135deg, rgba(0, 0, 0, 0.8), transparent);
|
||||
-webkit-mask:
|
||||
linear-gradient(#fff 0 0) content-box,
|
||||
linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.glass-button:hover {
|
||||
transform: translateY(-2px);
|
||||
background: rgba(0, 0, 0, 0.35);
|
||||
box-shadow:
|
||||
0 12px 32px rgba(0, 0, 0, 0.6),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
.glass-button:hover::before {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.3), transparent);
|
||||
}
|
||||
|
||||
.glass-button-sm {
|
||||
min-height: 0 !important;
|
||||
height: auto !important;
|
||||
line-height: inherit;
|
||||
padding-block: 0.375rem !important;
|
||||
padding-block: 0.375rem;
|
||||
padding-inline: 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
/* Toast - glassmorphic, top-right */
|
||||
@@ -111,39 +139,10 @@
|
||||
transform: translateX(1rem);
|
||||
}
|
||||
|
||||
/* Gradient containers - transparent to black */
|
||||
.gradient-card {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(0, 0, 0, 0.8) 100%);
|
||||
backdrop-filter: blur(18px);
|
||||
-webkit-backdrop-filter: blur(18px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
|
||||
border-radius: 1rem;
|
||||
}
|
||||
|
||||
.gradient-card-dark {
|
||||
background: linear-gradient(180deg, rgba(0, 0, 0, 0.4) 0%, rgba(0, 0, 0, 0.9) 100%);
|
||||
backdrop-filter: blur(18px);
|
||||
-webkit-backdrop-filter: blur(18px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
|
||||
border-radius: 1rem;
|
||||
}
|
||||
|
||||
.gradient-button {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(0, 0, 0, 0.8) 100%);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.gradient-button:hover {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(0, 0, 0, 0.9) 100%);
|
||||
border-color: rgba(255, 255, 255, 0.3);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
/* BANNED: gradient-card, gradient-card-dark, gradient-button
|
||||
Use .glass-card or .path-option-card for containers.
|
||||
Use .glass-button for all buttons.
|
||||
These gradient styles break the clean glass aesthetic. */
|
||||
|
||||
/* Gradient border for logo badge */
|
||||
.logo-gradient-border {
|
||||
@@ -198,7 +197,7 @@
|
||||
-webkit-backdrop-filter: blur(40px);
|
||||
border-radius: 24px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
box-shadow:
|
||||
box-shadow:
|
||||
0 20px 60px rgba(0, 0, 0, 0.3),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
display: flex;
|
||||
@@ -236,8 +235,8 @@
|
||||
border-radius: inherit;
|
||||
padding: 2px;
|
||||
background: linear-gradient(135deg, rgba(0, 0, 0, 0.8), transparent);
|
||||
-webkit-mask:
|
||||
linear-gradient(#fff 0 0) content-box,
|
||||
-webkit-mask:
|
||||
linear-gradient(#fff 0 0) content-box,
|
||||
linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
@@ -248,7 +247,7 @@
|
||||
.path-option-card svg {
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
transition: all 0.3s ease;
|
||||
filter:
|
||||
filter:
|
||||
drop-shadow(0 1px 1px rgba(255, 255, 255, 0.3))
|
||||
drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))
|
||||
drop-shadow(0 -1px 2px rgba(0, 0, 0, 0.6));
|
||||
@@ -269,7 +268,7 @@
|
||||
|
||||
.path-option-card:hover svg {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
filter:
|
||||
filter:
|
||||
drop-shadow(0 1px 2px rgba(255, 255, 255, 0.5))
|
||||
drop-shadow(0 3px 6px rgba(0, 0, 0, 0.9))
|
||||
drop-shadow(0 -1px 3px rgba(0, 0, 0, 0.7));
|
||||
@@ -291,7 +290,7 @@
|
||||
|
||||
.path-option-card--selected svg {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
filter:
|
||||
filter:
|
||||
drop-shadow(0 1px 2px rgba(255, 255, 255, 0.6))
|
||||
drop-shadow(0 3px 8px rgba(0, 0, 0, 1))
|
||||
drop-shadow(0 0 12px rgba(255, 255, 255, 0.3));
|
||||
@@ -299,7 +298,7 @@
|
||||
|
||||
.path-option-card--selected h3 {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Action Buttons */
|
||||
.path-action-button {
|
||||
@@ -415,7 +414,7 @@ body {
|
||||
font-family: 'Avenir Next', system-ui, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
background: #000 url('/assets/img/bg.jpg') center top / auto 100vh no-repeat fixed;
|
||||
background: #000;
|
||||
color: white;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user