uthvah_vaultguard/styles.css

952 lines
24 KiB
CSS
Raw Permalink Normal View History

/*
* vaultguard: Stylesheet
* Refactored with bug fixes and improved layout
*/
/* ============================================================================
MAIN LOCKSCREEN & CORE STYLES
============================================================================ */
.vaultguard-screen {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 10000;
color: white;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background-color: #181818;
display: flex;
flex-direction: column;
overflow: hidden;
/* Shared glass surface tokens
All panels, navbar, and input decorations derive from these.
Changing one variable updates every surface for instant cohesion. */
--vg-glass-bg: rgba(255, 255, 255, 0.10);
--vg-glass-blur: blur(30px) saturate(190%);
--vg-glass-border: rgba(255, 255, 255, 0.18);
--vg-glass-highlight: rgba(255, 255, 255, 0.18);
--vg-glass-shadow: 0 20px 56px rgba(0, 0, 0, 0.50);
--vg-glass-radius: 28px;
}
.vaultguard-screen-loading {
/* No animations while loading */
animation: none !important;
}
.vaultguard-screen-loading * {
animation: none !important;
opacity: 1 !important;
}
.vaultguard-screen.is-leaving {
animation: unlockOut 0.4s cubic-bezier(0.4, 0, 1, 1) forwards;
}
@keyframes unlockOut {
0% { opacity: 1; transform: scale(1); filter: blur(0px); }
100% { opacity: 0; transform: scale(1.07); filter: blur(6px); }
}
/* ============================================================================
NAVBAR shown for hidden and obsidian frame styles.
Glass treatment is driven by the same surface tokens as the password bar,
so both elements always look visually unified across all atmospheres.
native frame: omitted entirely (OS chrome handles it).
============================================================================ */
.vaultguard-navbar {
flex-shrink: 0;
height: 33px;
width: 100%;
-webkit-app-region: drag;
background: var(--vg-glass-bg);
backdrop-filter: var(--vg-glass-blur);
-webkit-backdrop-filter: var(--vg-glass-blur);
border-bottom: 1px solid var(--vg-glass-border);
/* Top highlight + bottom fade — visually reads as thick glass */
box-shadow:
inset 0 1px 0 var(--vg-glass-highlight),
inset 0 -1px 0 rgba(0, 0, 0, 0.12);
position: relative;
z-index: 1;
display: flex;
align-items: center;
}
/* ============================================================================
WINDOW CONTROLS rendered inside .vaultguard-navbar on Windows/Linux
where Electron's own controls are web content covered by the lockscreen.
macOS: traffic lights are native OS overlays always visible, never needed here.
============================================================================ */
.vg-window-controls {
position: absolute;
top: 0;
right: 0;
height: 100%;
display: flex;
align-items: stretch;
-webkit-app-region: no-drag;
}
.vg-wc-btn {
width: 46px;
border: none;
background: transparent;
color: rgba(255, 255, 255, 0.60);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: background-color 0.1s ease, color 0.1s ease;
padding: 0;
-webkit-app-region: no-drag;
}
.vg-wc-btn svg {
width: 10px;
height: 10px;
pointer-events: none;
}
.vg-wc-btn:hover {
background: rgba(255, 255, 255, 0.08);
color: white;
}
.vg-wc-close:hover {
background: #c42b1c;
color: #fff;
}
/* ============================================================================
MAIN CONTENT AREA
============================================================================ */
.vaultguard-main-content {
flex-grow: 1;
position: relative;
display: flex;
align-items: center;
justify-content: center;
animation: fadeInContent 0.45s 0.08s ease-in-out forwards;
opacity: 0;
user-select: none;
-webkit-user-select: none;
}
@keyframes fadeInContent {
to { opacity: 1; }
}
/* ============================================================================
BACKGROUND MEDIA (video, image, or color)
============================================================================ */
.vaultguard-background-media {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
/* Prevent interaction */
pointer-events: none;
user-select: none;
}
/* ============================================================================
OVERLAY (blur and darkening effect)
============================================================================ */
.vaultguard-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, var(--vg-overlay-opacity, 0.30));
backdrop-filter: none;
-webkit-backdrop-filter: none;
pointer-events: none;
user-select: none;
}
/* ============================================================================
CONTENT CONTAINER (username + password input)
============================================================================ */
.vaultguard-content {
position: relative;
z-index: 10;
animation: slideUpIn 0.5s 0.12s cubic-bezier(0.25, 1, 0.5, 1) forwards,
fadeInContent 0.5s 0.12s ease-in-out forwards;
transform: translateY(12px);
opacity: 0;
pointer-events: auto;
isolation: isolate;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
--vaultguard-base-font: 1rem;
font-family: var(--vaultguard-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif);
user-select: none;
-webkit-user-select: none;
}
/* ============================================================================
TILE GRID master-stack tiling layout (Hyprland dwindle style)
First widget = master pane (left, full height)
Remaining widgets = stack pane (right, split equally)
To add a widget: push to WIDGET_REGISTRY in index.js
============================================================================ */
.vg-tile-grid {
display: grid;
grid-template-columns: 3fr 2fr;
gap: 20px;
width: min(900px, 88vw);
height: min(480px, 70vh);
}
.vg-tile-single {
grid-template-columns: 1fr;
width: min(460px, 88vw);
}
.vg-tile-master {
height: 100%;
}
.vg-tile-stack {
display: flex;
flex-direction: column;
gap: 20px;
height: 100%;
}
.vg-tile-item {
flex: 1;
min-height: 0;
}
@keyframes slideUpIn {
to {
transform: translateY(0);
}
}
/* ============================================================================
WIDGET PANELS shared glass surface
============================================================================ */
.vg-time-widget,
.vg-login-card {
background: var(--vg-glass-bg);
backdrop-filter: var(--vg-glass-blur);
-webkit-backdrop-filter: var(--vg-glass-blur);
border: 1px solid var(--vg-glass-border);
border-radius: var(--vg-glass-radius);
box-shadow:
var(--vg-glass-shadow),
inset 0 1px 0 var(--vg-glass-highlight);
height: 100%;
box-sizing: border-box;
}
.vg-time-widget {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: calc(10px * var(--vaultguard-ui-scale, 1));
padding: calc(28px * var(--vaultguard-ui-scale, 1)) calc(40px * var(--vaultguard-ui-scale, 1));
}
.vg-login-card {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: calc(20px * var(--vaultguard-ui-scale, 1));
padding: calc(32px * var(--vaultguard-ui-scale, 1)) calc(36px * var(--vaultguard-ui-scale, 1)) calc(28px * var(--vaultguard-ui-scale, 1));
}
/* ============================================================================
USERNAME DISPLAY
============================================================================ */
.vaultguard-username {
font-size: calc(34px * var(--vaultguard-ui-scale, 1));
text-shadow: 0px 1px 8px rgba(0, 0, 0, 0.5);
font-family: var(--vaultguard-font-family, inherit);
font-weight: var(--vaultguard-font-weight, 500);
font-style: var(--vaultguard-font-style, normal);
user-select: none;
-webkit-user-select: none;
}
.vaultguard-clock {
font-size: calc(72px * var(--vaultguard-ui-scale, 1));
font-weight: 300;
letter-spacing: -0.03em;
color: rgba(255,255,255,0.92);
text-shadow: 0 2px 20px rgba(0,0,0,0.3);
font-variant-numeric: tabular-nums;
line-height: 1;
margin-bottom: 4px;
font-family: var(--vaultguard-font-family, inherit);
}
.vaultguard-date {
font-size: calc(12px * var(--vaultguard-ui-scale, 1));
font-weight: 500;
color: rgba(255,255,255,0.78);
letter-spacing: 0.08em;
text-transform: uppercase;
font-family: var(--vaultguard-font-family, inherit);
text-shadow: 0 1px 6px rgba(0,0,0,0.45);
}
/* ============================================================================
ANALOGUE CLOCK
============================================================================ */
.vg-analogue-clock {
/* Fills the widget's flex space while staying square */
flex: 1 1 0;
min-height: 0;
width: 100%;
max-width: min(100%, 220px);
aspect-ratio: 1 / 1;
display: block;
overflow: visible;
}
/* ============================================================================
PASSWORD INPUT WRAPPER & INPUT
============================================================================ */
.vaultguard-password-wrapper {
position: relative;
width: var(--vaultguard-input-width, 340px);
/* Constrained to card width in the tiling layout */
max-width: 100%;
transition: width 0.3s ease;
z-index: 10;
}
.vaultguard-password-wrapper.is-error {
animation: shake 0.4s linear;
}
/* Input bar — "carved into" the glass card */
.vaultguard-screen .vaultguard-input {
width: 100%;
background: rgba(0, 0, 0, 0.22) !important;
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
border: 1px solid rgba(255, 255, 255, 0.14);
/* Top shadow reads as a carved recess; bottom edge gives subtle lift */
box-shadow:
inset 0 2px 8px rgba(0, 0, 0, 0.30),
inset 0 1px 2px rgba(0, 0, 0, 0.20),
0 1px 0 rgba(255, 255, 255, 0.06);
border-radius: calc(var(--vaultguard-input-radius, 100) * 1px);
color: rgba(255, 255, 255, 0.95);
padding: calc(15px * var(--vaultguard-ui-scale, 1)) calc(28px * var(--vaultguard-ui-scale, 1));
font-size: calc(14px * var(--vaultguard-ui-scale, 1));
letter-spacing: 0.22em;
text-align: center;
box-sizing: border-box;
outline: none;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
user-select: text;
-webkit-user-select: text;
text-shadow: 0 1px 4px rgba(0,0,0,0.5);
caret-color: rgba(255, 255, 255, 0.80);
}
.vaultguard-screen .vaultguard-input::placeholder {
color: rgba(255, 255, 255, 0.7) !important;
letter-spacing: 0.06em;
text-shadow: none;
}
.vaultguard-screen .vaultguard-input:focus {
border-color: rgba(255, 255, 255, 0.32);
box-shadow:
inset 0 2px 8px rgba(0, 0, 0, 0.30),
inset 0 1px 2px rgba(0, 0, 0, 0.20),
0 0 0 3px rgba(255, 255, 255, 0.10),
0 1px 0 rgba(255, 255, 255, 0.06);
}
.vaultguard-input.is-error {
border-color: rgba(255, 90, 90, 0.65) !important;
box-shadow:
inset 0 2px 8px rgba(0, 0, 0, 0.30),
0 0 0 3px rgba(255, 80, 80, 0.16) !important;
}
.vaultguard-input.is-success {
border-color: rgba(80, 220, 120, 0.65) !important;
box-shadow:
inset 0 2px 8px rgba(0, 0, 0, 0.30),
0 0 0 3px rgba(80, 220, 130, 0.16) !important;
}
@keyframes shake {
10%, 90% { transform: translateX(calc(var(--vaultguard-shake-intensity, 6px) * -1)); }
30%, 70% { transform: translateX(var(--vaultguard-shake-intensity, 6px)); }
50% { transform: translateX(calc(var(--vaultguard-shake-intensity, 6px) * -1)); }
}
/* ============================================================================
PROGRESS MODAL (for encryption/decryption)
============================================================================ */
/* Progress modal */
.vaultguard-progress-modal .modal-content {
padding: 32px 36px 28px;
text-align: center;
}
.vaultguard-progress-modal h2 {
font-size: 15px;
font-weight: 500;
color: var(--text-muted);
letter-spacing: 0.03em;
text-transform: uppercase;
margin-bottom: 20px;
}
.vaultguard-progress-modal .progress-status {
font-size: 22px;
font-weight: 600;
color: var(--text-normal);
margin: 0 0 6px;
}
.vaultguard-progress-modal .progress-details {
font-size: 12px;
min-height: 1.4em;
color: var(--text-faint);
letter-spacing: 0.01em;
}
/* Add background modal */
.vaultguard-add-bg-modal .modal-content {
padding: 28px 32px 24px;
}
.vaultguard-add-bg-modal h2 {
font-size: 18px;
font-weight: 600;
margin-bottom: 6px;
}
.vaultguard-add-bg-modal .vaultguard-modal-desc {
font-size: 13px;
color: var(--text-muted);
margin-bottom: 20px;
line-height: 1.5;
}
.vaultguard-modal-divider {
display: flex;
align-items: center;
gap: 10px;
margin: 20px 0 4px;
color: var(--text-faint);
font-size: 11px;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.vaultguard-modal-divider::before,
.vaultguard-modal-divider::after {
content: '';
flex: 1;
height: 1px;
background: var(--background-modifier-border);
}
/* ============================================================================
SETTINGS PANEL - SECTION HEADINGS
============================================================================ */
.vaultguard-settings h3 {
font-size: var(--font-ui-small);
font-weight: 600;
letter-spacing: 0.05em;
text-transform: uppercase;
color: var(--text-muted);
margin: 28px 0 10px;
}
.vaultguard-settings h2 + h3 {
margin-top: 16px;
}
/* ============================================================================
SETTINGS PANEL - TOGGLE LABELS (Bold / Italic)
============================================================================ */
.vaultguard-toggle-label {
font-size: var(--font-ui-small);
color: var(--text-normal);
margin-right: 6px;
}
.vaultguard-toggle-label--gap {
margin-left: 16px;
}
/* ============================================================================
SETTINGS PANEL - CHANGE PASSWORD CARD
============================================================================ */
.vaultguard-cp-card {
border: 1px solid var(--background-modifier-border);
border-radius: 8px;
padding: 16px;
margin-bottom: 4px;
}
.vaultguard-cp-title {
font-size: var(--font-ui-medium);
font-weight: 600;
margin-bottom: 4px;
}
.vaultguard-cp-desc {
font-size: var(--font-ui-small);
color: var(--text-muted);
margin-bottom: 14px;
}
.vaultguard-cp-form {
display: flex;
flex-direction: column;
gap: 8px;
}
.vaultguard-cp-input {
width: 100%;
box-sizing: border-box;
}
.vaultguard-cp-btn {
align-self: flex-end;
}
.vaultguard-cp-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* ============================================================================
SETTINGS PANEL - PASSWORD STRENGTH INDICATOR
============================================================================ */
.password-strength-container {
margin: 4px 0;
width: 100%;
}
.password-strength-bar-wrapper {
width: 100%;
height: 6px;
background-color: var(--background-modifier-border);
border-radius: 3px;
overflow: hidden;
margin-bottom: 4px;
}
.password-strength-bar {
height: 100%;
width: 0%;
border-radius: 3px;
transition: width 0.35s ease, background-color 0.35s ease;
}
.password-strength-bar.strength-0,
.password-strength-bar.strength-1 {
width: 25%;
background-color: var(--color-red, #e74c3c);
}
.password-strength-bar.strength-2 {
width: 50%;
background-color: var(--color-orange, #f39c12);
}
.password-strength-bar.strength-3 {
width: 75%;
background-color: var(--color-green, #27ae60);
}
.password-strength-bar.strength-4 {
width: 100%;
background-color: var(--color-green, #2ecc71);
}
.password-strength-text {
font-size: var(--font-ui-smaller);
color: var(--text-muted);
text-align: right;
min-height: 1.4em;
}
/* ============================================================================
SETTINGS PANEL - DANGER ZONE (Note Encryption)
============================================================================ */
.vaultguard-danger-zone {
border: 1px solid color-mix(in srgb, var(--color-red, #e03131) 40%, transparent);
border-radius: 8px;
padding: 16px;
background-color: color-mix(in srgb, var(--color-red, #e03131) 6%, transparent);
}
.vaultguard-danger-zone p {
margin: 0 0 14px;
font-size: var(--font-ui-small);
line-height: 1.55;
color: var(--text-normal);
}
.vaultguard-danger-zone button {
background-color: var(--color-red, #e03131);
color: #fff;
border: none;
border-radius: 5px;
padding: 6px 14px;
font-size: var(--font-ui-small);
cursor: pointer;
transition: opacity 0.15s ease;
}
.vaultguard-danger-zone button:hover {
opacity: 0.82;
}
/* ============================================================================
SETTINGS PANEL - BACKGROUND THUMBNAIL GRID
============================================================================ */
.vaultguard-thumbnail-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
gap: 15px;
margin-top: 10px;
overflow: visible;
padding: 4px;
}
.vaultguard-thumbnail-item {
position: relative;
aspect-ratio: 16 / 9;
border-radius: 8px;
border: 3px solid transparent;
cursor: pointer;
transition: all 0.2s ease-in-out;
background-color: var(--background-secondary);
}
.vaultguard-thumbnail-item-inner {
width: 100%;
height: 100%;
border-radius: 8px;
overflow: hidden;
position: relative;
}
.vaultguard-thumbnail-item:hover {
transform: scale(1.03);
box-shadow: 0 0 15px rgba(var(--accent-h), var(--accent-s), var(--accent-l), 0.3);
}
.vaultguard-thumbnail-item.is-active {
border-color: var(--interactive-accent);
box-shadow: 0 0 15px rgba(var(--accent-h), var(--accent-s), var(--accent-l), 0.5);
transform: scale(1.05);
}
.vaultguard-thumbnail-item .thumbnail-image {
width: 100%;
height: 100%;
object-fit: cover;
background-color: var(--background-secondary);
}
.vaultguard-thumbnail-item .thumbnail-icon {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: var(--text-muted);
background-color: var(--background-secondary-alt);
}
.vaultguard-thumbnail-item .thumbnail-video-overlay {
position: absolute;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.38);
pointer-events: none;
}
.vaultguard-thumbnail-item .thumbnail-icon svg {
width: 40px;
height: 40px;
}
.vaultguard-thumbnail-item.add-new-btn {
border-style: dashed;
border-color: var(--text-faint);
color: var(--text-muted);
}
.vaultguard-thumbnail-item.add-new-btn:hover {
border-color: var(--interactive-accent-hover);
color: var(--interactive-accent-hover);
}
.vaultguard-thumbnail-item .delete-btn {
position: absolute;
top: 6px;
right: 6px;
width: 26px;
height: 26px;
background-color: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(3px);
-webkit-backdrop-filter: blur(3px);
border-radius: 50%;
border: none;
color: rgba(255, 255, 255, 0.8);
cursor: pointer;
display: none;
align-items: center;
justify-content: center;
opacity: 0;
transition: all 0.2s ease;
}
.vaultguard-thumbnail-item:hover .delete-btn {
display: flex;
opacity: 1;
}
.vaultguard-thumbnail-item .delete-btn:hover {
background-color: #e74c3c;
color: white;
transform: scale(1.1);
}
/* ============================================================================
RESPONSIVE ADJUSTMENTS
============================================================================ */
/* Small window: stack tiles vertically so neither panel is crushed */
@media (max-width: 640px) {
.vg-tile-grid {
grid-template-columns: 1fr;
width: min(440px, 88vw);
height: auto;
}
.vg-tile-master,
.vg-tile-stack {
height: auto;
}
.vg-tile-item {
flex: none;
}
.vg-time-widget,
.vg-login-card {
height: auto;
}
.vg-time-widget {
min-height: 200px;
}
.vg-login-card {
min-height: 140px;
}
}
@media (max-width: 768px) {
.vaultguard-username {
font-size: calc(26px * var(--vaultguard-ui-scale, 1));
}
.vaultguard-thumbnail-grid {
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
gap: 10px;
}
}
/* ============================================================================
ACCESSIBILITY IMPROVEMENTS
============================================================================ */
.vaultguard-input:focus-visible {
outline: 2px solid var(--interactive-accent);
outline-offset: 2px;
}
/* High contrast mode support */
@media (prefers-contrast: high) {
.vaultguard-overlay {
background-color: rgba(0, 0, 0, 0.7);
}
.vaultguard-input {
border-width: 3px;
}
}
/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
.vaultguard-screen,
.vaultguard-main-content,
.vaultguard-content,
.vaultguard-input,
.vaultguard-thumbnail-item,
.vg-time-widget,
.vg-login-card {
animation: none !important;
transition: none !important;
opacity: 1 !important;
transform: none !important;
}
.vaultguard-screen.is-leaving {
opacity: 0 !important;
}
}
/* ============================================================================
TAMPER WARNING / DANGER ZONE
============================================================================ */
/* ============================================================================
WARNING ICON (used in tamper panel)
============================================================================ */
.vaultguard-warning-icon {
/* Explicit dimensions prevent the SVG from expanding before CSS loads */
width: 18px;
height: 18px;
flex-shrink: 0;
display: block;
color: #e67e22;
}
/* ============================================================================
TAMPER SCREEN minimal view shown when vault integrity cannot be confirmed
(no user visual preferences are applied here)
============================================================================ */
.vaultguard-tamper-screen {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
background: #0f0f0f;
animation: fadeInContent 0.4s ease forwards;
}
.vaultguard-tamper-panel {
width: 100%;
max-width: 380px;
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(230, 126, 34, 0.35);
border-radius: 12px;
padding: 28px 28px 24px;
display: flex;
flex-direction: column;
gap: 16px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
}
.vaultguard-tamper-panel-header {
display: flex;
align-items: center;
gap: 10px;
color: #e67e22;
}
.vaultguard-tamper-panel-title {
font-size: 14px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
color: #e67e22;
}
.vaultguard-tamper-panel-message {
font-size: 13px;
line-height: 1.6;
color: rgba(255, 255, 255, 0.6);
margin: 0;
}
/* Password input inside the tamper panel inherits the glass style
but needs a fixed width since --vaultguard-input-width isn't set here */
.vaultguard-tamper-panel .vaultguard-password-wrapper {
width: 100%;
max-width: 100%;
}
/* Legacy banner — kept for any callers that may still reference it */
.vaultguard-tamper-warning {
display: flex;
align-items: center;
gap: 8px;
background: rgba(231, 76, 60, 0.15);
border: 1px solid rgba(231, 76, 60, 0.4);
border-radius: 8px;
color: rgba(255,255,255,0.9);
font-size: 13px;
padding: 10px 16px;
margin-bottom: 20px;
text-align: center;
letter-spacing: 0.02em;
}
.vaultguard-danger-zone {
padding: 16px;
border: 1px solid var(--text-error);
border-radius: 8px;
margin-top: 8px;
}
.vaultguard-danger-zone p {
color: var(--text-muted);
font-size: 13px;
margin-bottom: 12px;
}
.vaultguard-danger-zone button {
background: var(--text-error);
color: white;
border: none;
border-radius: 6px;
padding: 8px 16px;
cursor: pointer;
font-size: 13px;
}