diff --git a/css/style.css b/css/style.css index f15b100..d2fee8e 100644 --- a/css/style.css +++ b/css/style.css @@ -1,343 +1,1225 @@ -:root { - --bg: #0e1015; --bg2: #191d27; --text: #e2e6ea; --text2: #7f8a98; - --accent: #6b7280; --accent-rgb: 107,114,128; - --danger: #ef4444; --success: #22c55e; --warning: #f59e0b; - --border: rgba(255,255,255,0.12); --card: #212734; - --input: #11141a; --vault-bg: rgba(255,255,255,0.06); -} -.light { - --bg: #eef0f4; --bg2: #e2e5eb; --text: #161b24; --text2: #5f6a7a; - --accent: #6b7280; --accent-rgb: 107,114,128; - --card: #ffffff; --input: #ffffff; - --border: rgba(0,0,0,0.16); --vault-bg: rgba(255,255,255,0.7); -} +/* ============================================================ + Vault — UI V2 (Linear/Notion design system) + Dark default, cyan/violet accent, glassmorphism subtil. + ============================================================ */ -* { margin:0; padding:0; box-sizing:border-box; } +/* ---- 1. RESET & TOKENS ----------------------------------- */ + +*,*::before,*::after { box-sizing: border-box; } +html, body { margin: 0; padding: 0; height: 100%; } body { - background: linear-gradient(145deg, var(--bg) 0%, var(--bg2) 100%); - font-family: 'Segoe UI', system-ui, sans-serif; - min-height: 100vh; display: flex; justify-content: center; - align-items: flex-start; padding: 1.2rem; color: var(--text); - transition: background 0.3s, color 0.3s; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + font-size: 14px; + line-height: 1.5; + color: var(--text); + background: var(--bg); + -webkit-font-smoothing: antialiased; + overflow: hidden; } -.toast-container { position:fixed; top:1rem; right:1rem; z-index:9999; display:flex; flex-direction:column; gap:0.5rem; } -.toast { padding:0.7rem 1.2rem; border-radius:0.8rem; font-size:0.85rem; animation:slideIn 0.3s ease; color:#fff; } -.toast.error { background:var(--danger); } -.toast.success { background:var(--success); } -.toast { display:flex; align-items:center; gap:0.6rem; max-width:400px; } -.toast-action { background:rgba(0,0,0,0.3); border:1px solid rgba(255,255,255,0.4); color:#fff; font-weight:700; font-size:0.8rem; padding:0.25rem 0.7rem; border-radius:1rem; cursor:pointer; white-space:nowrap; flex-shrink:0; transition:0.15s; } -.toast-action:hover { background:rgba(0,0,0,0.5); } -@keyframes slideIn { from { transform:translateX(100%); opacity:0; } to { transform:translateX(0); opacity:1; } } - -.vault { - width:96%; max-width:1700px; background:var(--vault-bg); - backdrop-filter:blur(20px); border:1px solid var(--border); - border-radius:2rem; padding:1.8rem; margin:0.5rem auto; - box-shadow:0 30px 50px rgba(0,0,0,0.4); - user-select:none; -webkit-user-drag:none; +button { font-family: inherit; cursor: pointer; } +input, select, textarea { font-family: inherit; font-size: inherit; } +kbd { + font-family: 'JetBrains Mono', 'SF Mono', Consolas, monospace; + font-size: 11px; + padding: 2px 6px; + border: 1px solid var(--border); + border-radius: 4px; + background: var(--bg-elev); + color: var(--text-dim); } -h1 { font-size:2rem; margin-bottom:0.6rem; display:flex; align-items:center; gap:0.6rem; flex-wrap:wrap; } -h1 span { background:var(--accent); padding:0.2rem 0.7rem; border-radius:3rem; font-size:0.8rem; color:#fff; } -/* Auth */ -.auth-section { background:rgba(0,0,0,0.25); border-radius:1.5rem; padding:1.3rem; margin-bottom:1rem; border:1px solid var(--border); } -.auth-tabs { display:flex; gap:1rem; margin-bottom:0.8rem; } -.auth-tab { background:none; border:none; color:var(--text2); padding:0.4rem 0.8rem; cursor:pointer; border-bottom:2px solid transparent; font-size:0.9rem; } -.auth-tab.active { color:var(--accent); border-bottom-color:var(--accent); } - -input, select, textarea { - flex:1; min-width:130px; background:var(--input); border:1px solid #2d3748; - padding:0.65rem 1rem; border-radius:2rem; color:var(--text); font-size:0.85rem; - outline:none; font-family:inherit; +:root, [data-theme="dark"] { + /* Slightly lighter surfaces + warmer tones, brighter text-dim/faint + and more visible borders. Less "black hole" feel. */ + --bg: #15151c; + --bg-elev: #1d1d26; + --bg-elev-2: #292932; + --bg-glass: rgba(29,29,38,0.78); + --border: #353541; + --border-soft: #25252e; + --text: #f1f1f5; + --text-dim: #b8b8c4; + --text-faint: #82828f; + --accent: #06b6d4; + --accent-hover: #22d3ee; + --accent-soft: rgba(6,182,212,0.12); + --accent-2: #a78bfa; + --danger: #f43f5e; + --danger-soft: rgba(244,63,94,0.12); + --success: #10b981; + --warning: #f59e0b; + --shadow: 0 8px 24px rgba(0,0,0,0.4); + --shadow-lg: 0 24px 48px rgba(0,0,0,0.55); + --blur: saturate(140%) blur(20px); + --radius: 12px; + --radius-sm: 8px; + --radius-lg: 16px; + --t-fast: 120ms cubic-bezier(0.16,1,0.3,1); + --t-base: 200ms cubic-bezier(0.16,1,0.3,1); } -input:focus, select:focus { border-color:var(--accent); } + +[data-theme="light"] { + --bg: #f7f7f5; + --bg-elev: #ffffff; + --bg-elev-2: #efefec; + --bg-glass: rgba(255,255,255,0.92); + --border: #dcdcd7; + --border-soft: #ebebe6; + --text: #1a1a1f; + --text-dim: #57575e; + --text-faint: #8e8e96; + --accent: #0891b2; /* cyan-600 — darker for better contrast on white */ + --accent-hover: #0e7490; + --accent-soft: rgba(8,145,178,0.10); + --accent-2: #7c3aed; + --shadow: 0 4px 16px rgba(0,0,0,0.06); + --shadow-lg: 0 16px 36px rgba(0,0,0,0.08); + --blur: saturate(160%) blur(16px); +} +[data-theme="light"] .auth-screen { + background: + radial-gradient(ellipse at top, rgba(8,145,178,0.08), transparent 50%), + radial-gradient(ellipse at bottom right, rgba(124,58,237,0.06), transparent 50%), + var(--bg); +} + +svg { width: 16px; height: 16px; flex-shrink: 0; } + +/* ---- 2. UTILITIES ---------------------------------------- */ + +.is-hidden { display: none !important; } +.hint { color: var(--text-faint); font-weight: 400; font-size: 12px; margin-left: 4px; } + +/* ---- 3. BUTTONS ------------------------------------------ */ .btn { - background:linear-gradient(135deg, #6b7280, #4b5563); border:none; color:#fff; - font-weight:600; padding:0.65rem 1.3rem; border-radius:2rem; cursor:pointer; - font-size:0.85rem; transition:0.2s; white-space:nowrap; + display: inline-flex; align-items: center; justify-content: center; + gap: 6px; + padding: 8px 14px; + border: 1px solid transparent; + border-radius: var(--radius-sm); + font-size: 13px; font-weight: 500; line-height: 1; + transition: all var(--t-fast); + white-space: nowrap; } -.btn:hover { filter:brightness(1.15); transform:scale(1.02); } -.btn:disabled { opacity:0.5; cursor:not-allowed; transform:none; } -.btn-outline { background:transparent; border:1px solid #475569; color:var(--text2); } -.btn-sm { padding:0.35rem 0.9rem; font-size:0.75rem; } -.btn-xs { padding:0.2rem 0.5rem; font-size:0.7rem; } -.btn-danger { background:var(--danger); } - -.input-group { display:flex; gap:0.5rem; margin:0.7rem 0; flex-wrap:wrap; align-items:center; } - -/* Toolbar */ -.toolbar { display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:0.5rem; margin-bottom:0.7rem; } -.view-dropdown { position:relative; } -.view-dropdown-menu { position:absolute; top:100%; right:0; margin-top:4px; min-width:155px; background:var(--bg2); border:1px solid var(--border); border-radius:0.6rem; padding:0.3rem; box-shadow:0 8px 24px rgba(0,0,0,0.3); z-index:100; display:flex; flex-direction:column; gap:2px; } -.view-opt { background:none; border:none; color:var(--text); padding:0.45rem 0.8rem; border-radius:0.4rem; cursor:pointer; font-size:0.8rem; text-align:left; transition:0.12s; white-space:nowrap; } -.view-opt:hover { background:var(--accent); color:#fff; } -.view-opt.active { background:var(--accent); color:#fff; font-weight:600; } - -.toggles-row { display:flex; gap:1.2rem; align-items:center; flex-wrap:wrap; } -.toggle-item { display:flex; align-items:center; gap:0.4rem; font-size:0.75rem; color:var(--text2); } -.toggle-switch { position:relative; width:36px; height:20px; background:#334155; border-radius:10px; cursor:pointer; transition:0.2s; } -.toggle-switch.active { background:var(--accent); } -.toggle-switch::after { content:''; position:absolute; top:2px; left:2px; width:16px; height:16px; background:#fff; border-radius:50%; transition:0.2s; } -.toggle-switch.active::after { left:18px; } - -.status-badge { background:var(--bg2); padding:0.25rem 0.8rem; border-radius:2rem; font-size:0.75rem; white-space:nowrap; } -.hidden { display:none !important; } - -/* Strength */ -.strength-bar { height:4px; border-radius:2px; transition:0.3s; margin-top:0.2rem; } -.s0 { background:var(--danger); width:20%; } -.s1 { background:var(--warning); width:40%; } -.s2 { background:#eab308; width:60%; } -.s3 { background:#84cc16; width:80%; } -.s4 { background:var(--success); width:100%; } - -/* ========== SEARCH BOX WITH CLEAR BUTTON (FIXED) ========== */ -.search-box { - position: relative; - width: 240px; /* fixed width – adjust if needed */ - flex-shrink: 0; +.btn-primary { background: var(--accent); color: white; } +.btn-primary:hover { background: var(--accent-hover); } +.btn.is-danger { background: var(--danger); color: white; } +.btn.is-danger:hover { background: #e11d48; } +.btn-ghost { + background: transparent; + color: var(--text-dim); + border-color: var(--border); } -.search-box input { +.btn-ghost:hover { background: var(--bg-elev-2); color: var(--text); } +.btn-block { width: 100%; } +.btn-sm { padding: 6px 10px; font-size: 12px; } +.btn:disabled { opacity: 0.5; cursor: not-allowed; } + +.icon-btn { + display: inline-flex; align-items: center; justify-content: center; + width: 32px; height: 32px; + background: transparent; + border: 1px solid transparent; + border-radius: var(--radius-sm); + color: var(--text-dim); + transition: all var(--t-fast); +} +.icon-btn:hover { background: var(--bg-elev-2); color: var(--text); } +.icon-btn-sm { width: 24px; height: 24px; } +.icon-btn-sm svg { width: 14px; height: 14px; } + +/* ---- 4. FORM CONTROLS ------------------------------------ */ + +.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; } +.field > span { + font-size: 12px; font-weight: 500; color: var(--text-dim); + display: flex; align-items: center; +} +.field input[type="text"], +.field input[type="password"], +.field input[type="search"], +.field input[type="email"], +.field select { width: 100%; - box-sizing: border-box; - padding-right: 30px; /* space for the ✕ button */ -} -.clear-search-btn { - position: absolute; - right: 6px; - top: 50%; - transform: translateY(-50%); - background: none; - border: none; - color: var(--text2); - cursor: pointer; - font-size: 0.9rem; - line-height: 1; - padding: 6px; - display: none; -} - -/* Folders */ -.folders-bar { display:flex; gap:0.4rem; margin-bottom:0.8rem; flex-wrap:wrap; align-items:center; padding:0.4rem 0.6rem; background:rgba(0,0,0,0.2); border-radius:1rem; } -.folder-chip { background:var(--bg2); border:1px solid var(--border); color:var(--text2); padding:0.3rem 0.8rem; border-radius:2rem; cursor:pointer; font-size:0.78rem; transition:0.2s; white-space:nowrap; } -.folder-chip:hover { background:var(--chip-color, var(--accent)); color:#fff; border-color:var(--chip-color, var(--accent)); } -.folder-chip.active { background:var(--chip-color, var(--accent)); color:#fff; border-color:var(--chip-color, var(--accent)); } -.folder-chip.drag-over { border-color:var(--accent)!important; box-shadow:0 0 12px rgba(var(--accent-rgb),0.5); transform:scale(1.05); } -.pw-display.pw-hover { cursor:pointer; } -.folder-count { background:rgba(0,0,0,0.3); padding:0.1rem 0.4rem; border-radius:1rem; margin-left:0.3rem; font-size:0.7rem; } -.folder-delete-btn { background:transparent; border:none; color:var(--danger); cursor:pointer; font-size:0.7rem; margin-left:0.2rem; opacity:0.7; } -.folder-delete-btn:hover { opacity:1; } -.folder-add-btn { background:transparent; border:1px dashed #475569; color:var(--text2); padding:0.3rem 0.6rem; border-radius:2rem; cursor:pointer; font-size:0.75rem; transition:0.2s; } -.folder-add-btn:hover { border-color:var(--accent); color:var(--accent); } - -.light .entry-card, .light .entry-row, .light .entry-compact { box-shadow:0 1px 4px rgba(0,0,0,0.08); } -#addFolderSelect { min-width:110px; max-width:150px; background:var(--input); border:1px solid #2d3748; color:var(--text); padding:0.5rem 0.8rem; border-radius:2rem; font-size:0.8rem; cursor:pointer; } - -/* Entries */ -#entriesContainer { user-select:none; -webkit-user-drag:none; } -#entriesContainer.grid-view { display:grid; grid-template-columns: repeat(auto-fill, minmax(180px,1fr)); gap:0.6rem; } -#entriesContainer.list-view { display:flex; flex-direction:column; gap:0.4rem; } -#entriesContainer.compact-view { display:flex; flex-direction:column; gap:0.2rem; } -#entriesContainer.table-view { overflow-x:auto; } -#entriesContainer.table-view table { width:100%; border-collapse:collapse; } -#entriesContainer.table-view th { text-align:left; padding:0.4rem 0.6rem; color:var(--text2); font-size:0.75rem; border-bottom:1px solid var(--border); } -#entriesContainer.table-view td { padding:0.4rem 0.6rem; font-size:0.8rem; border-bottom:1px solid rgba(255,255,255,0.03); } - -.entry-card, .entry-row, .entry-compact, .table-row-drag { cursor:pointer; user-select:none; } -.entry-card.drag-over, .entry-row.drag-over, .entry-compact.drag-over, .table-row-drag.drag-over { border-color:var(--accent)!important; box-shadow:0 0 15px rgba(var(--accent-rgb),0.3); } -.entry-card.selected { border-color:var(--accent)!important; box-shadow:0 0 0 2px var(--accent),0 0 18px rgba(var(--accent-rgb),0.35); background:rgba(var(--accent-rgb),0.18); } -.entry-row.selected, .entry-compact.selected { border-color:var(--accent)!important; box-shadow:0 0 0 2px var(--accent),0 0 18px rgba(var(--accent-rgb),0.35); background:rgba(var(--accent-rgb),0.14); border-left:3px solid var(--accent); } -.table-row-drag.selected td { background:rgba(var(--accent-rgb),0.14)!important; box-shadow:inset 0 0 0 1px var(--accent); border-bottom:1px solid var(--accent); } -.entry-card { background:var(--card); border:1px solid var(--border); border-radius:0.8rem; padding:0.9rem 2.8rem 0.9rem 0.9rem; transition:0.2s; position:relative; word-break:break-word; box-shadow:0 2px 6px rgba(0,0,0,0.2); } -.entry-card:hover { border-color:rgba(255,255,255,0.15); transform:translateY(-2px); box-shadow:0 4px 12px rgba(0,0,0,0.3); } -.card-site { font-weight:700; font-size:0.9rem; color:var(--text); margin-bottom:0.2rem; } -.card-user { color:var(--text2); font-size:0.75rem; margin-bottom:0.3rem; } -.card-folder { font-size:0.65rem; color:var(--accent); margin-bottom:0.3rem; background:rgba(var(--accent-rgb),0.15); display:inline-block; padding:0.1rem 0.5rem; border-radius:1rem; } -.card-password { background:var(--bg2); padding:0.3rem 0.5rem; border-radius:0.6rem; display:flex; align-items:center; justify-content:space-between; font-family:monospace; font-size:0.75rem; gap:0.2rem; } -#entriesContainer.card-view .entry-card { padding:1.2rem 3rem 1.2rem 1.2rem; } -#entriesContainer.card-view .card-site { font-size:1.05rem; } -#entriesContainer.card-view .card-password { font-size:0.9rem; } -#entriesContainer.card-view .entry-card:hover { transform:translateY(-3px); } -.entry-row { background:var(--card); border:1px solid var(--border); border-radius:0.8rem; padding:0.7rem 2.8rem 0.7rem 0.9rem; display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:0.4rem; position:relative; box-shadow:0 2px 6px rgba(0,0,0,0.15); } -.entry-compact { display:flex; align-items:center; gap:0.5rem; padding:0.35rem 2.8rem 0.35rem 0.7rem; background:var(--card); border-radius:0.5rem; border:1px solid var(--border); font-size:0.8rem; position:relative; box-shadow:0 1px 4px rgba(0,0,0,0.12); } -.action-btns { position:absolute; top:4px; right:6px; display:flex; gap:4px; z-index:1; } -.delete-btn { width:20px; height:20px; background:transparent; color:var(--danger); border:none; cursor:pointer; font-size:0.9rem; font-weight:700; display:flex; align-items:center; justify-content:center; } -.delete-btn:hover { color:#fff; transform:scale(1.2); } -.light .delete-btn:hover { color:#000!important; } -.edit-btn { width:20px; height:20px; background:transparent; color:var(--accent); border:none; cursor:pointer; font-size:0.75rem; display:flex; align-items:center; justify-content:center; } -.edit-btn:hover { color:#fff; transform:scale(1.2); } -.light .edit-btn:hover { color:#000!important; } -.star-btn { width:20px; height:20px; background:transparent; border:none; cursor:pointer; font-size:0.85rem; display:flex; align-items:center; justify-content:center; color:var(--text2); } -.star-btn:hover { transform:scale(1.3); } -.entry-card.favorite { border-color:rgba(255,200,0,0.3); background:rgba(255,200,0,0.05); } -.entry-row.favorite { border-color:rgba(255,200,0,0.3); background:rgba(255,200,0,0.05); } -.entry-compact.favorite { border-color:rgba(255,200,0,0.3); background:rgba(255,200,0,0.05); } -.table-row-drag.favorite td { background:rgba(255,200,0,0.05); } - -/* Grouped view */ -#entriesContainer.grouped-view { display:flex; flex-direction:column; gap:0.15rem; } -.grouped-header { position:sticky; top:0; z-index:2; background:var(--bg); padding:0.55rem 0.8rem; border-radius:0.5rem; font-weight:600; font-size:0.9rem; color:var(--accent); display:flex; align-items:center; gap:0.5rem; border-bottom:2px solid var(--accent); margin-top:0.4rem; } -.grouped-header:first-child { margin-top:0; } -#entriesContainer.grouped-view .entry-row { border-left:3px solid transparent; transition:0.15s; padding-left:1rem; } -#entriesContainer.grouped-view .entry-row:hover { border-left-color:var(--accent); } - -/* Detail view */ -#entriesContainer.detail-view { display:flex; flex-direction:column; gap:1rem; } -.detail-nav { display:flex; align-items:center; justify-content:center; gap:1rem; padding:0.5rem 0; position:sticky; top:0; z-index:2; background:var(--bg); } -.detail-nav button { background:var(--bg2); border:1px solid var(--border); color:var(--text); padding:0.4rem 1rem; border-radius:0.5rem; cursor:pointer; transition:0.15s; font-size:0.85rem; } -.detail-nav button:hover { border-color:var(--accent); color:var(--accent); } -.detail-nav button:disabled { opacity:0.4; cursor:default; } -.detail-nav .detail-counter { font-size:0.8rem; color:var(--text2); min-width:80px; text-align:center; } -.detail-card { background:var(--bg2); border:1px solid var(--border); border-radius:1rem; padding:1.5rem; display:flex; flex-direction:column; gap:0.9rem; max-width:520px; margin:0 auto; width:100%; } -.detail-field { display:flex; flex-direction:column; gap:0.15rem; } -.detail-label { font-size:0.7rem; color:var(--text2); text-transform:uppercase; letter-spacing:0.5px; } -.detail-value { font-size:1.2rem; word-break:break-all; } -.detail-value.pw-display { font-family:monospace; letter-spacing:2px; font-size:1.3rem; cursor:default; } -.detail-folder { display:flex; gap:0.5rem; align-items:center; } -.detail-actions { display:flex; gap:0.5rem; margin-top:0.3rem; } -.detail-actions button { flex:1; padding:0.5rem; border-radius:0.5rem; border:1px solid var(--border); background:var(--bg); cursor:pointer; transition:0.15s; font-size:0.85rem; } -.detail-actions button:hover { border-color:var(--accent); background:var(--bg2); } - - -.entry-info { display:flex; gap:0.5rem; align-items:center; flex-wrap:wrap; flex:1; } -.entry-site { font-weight:700; color:var(--text); } -.entry-user { color:var(--text2); } -.entry-folder { font-size:0.7rem; color:var(--accent); background:rgba(var(--accent-rgb),0.15); padding:0.1rem 0.5rem; border-radius:1rem; } -.password-field { display:flex; align-items:center; gap:0.3rem; background:var(--bg2); padding:0.2rem 0.5rem; border-radius:2rem; } -.password-text { font-family:monospace; color:var(--text2); font-size:0.8rem; } -.icon-btn { background:none; border:1px solid #475569; color:var(--text2); border-radius:2rem; padding:0.2rem 0.5rem; font-size:0.65rem; cursor:pointer; } -.icon-btn:hover { background:rgba(var(--accent-rgb),0.2); } - -/* Settings Dropdown */ -.settings-dropdown { position:relative; display:inline-block; } -.settings-menu { position:absolute; top:100%; right:0; background:var(--bg2); border:1px solid var(--border); border-radius:0.8rem; padding:0.5rem; min-width:200px; z-index:1000; box-shadow:0 10px 25px rgba(0,0,0,0.4); } -.settings-item { display:flex; justify-content:space-between; align-items:center; padding:0.4rem 0.6rem; border-radius:0.5rem; font-size:0.8rem; color:var(--text2); cursor:pointer; } -.settings-item:hover { background:rgba(255,255,255,0.05); } -.settings-item select { background:var(--input); border:1px solid #334155; color:var(--text); padding:0.2rem 0.5rem; border-radius:1rem; font-size:0.75rem; } - -/* Trash */ -.trash-badge { background:var(--danger); color:#fff; padding:0.15rem 0.5rem; border-radius:1rem; font-size:0.65rem; margin-left:0.3rem; } -.trash-info { font-size:0.7rem; color:var(--text2); margin-top:0.2rem; } -.restore-btn { background:none; color:#fff; border:none; padding:0.2rem 0.6rem; border-radius:1.5rem; cursor:pointer; font-size:0.7rem; } -.restore-btn:hover { filter:brightness(1.2); } -.empty-trash-btn { background:var(--danger); color:#fff; border:none; padding:0.3rem 0.8rem; border-radius:1.5rem; cursor:pointer; font-size:0.75rem; } -.empty-trash-btn:hover { filter:brightness(1.2); } - -/* Edit Modal */ -.edit-modal { position:fixed; top:0; left:0; right:0; bottom:0; background:rgba(0,0,0,0.7); display:none; justify-content:center; align-items:center; z-index:1001; } -.edit-modal.show { display:flex; } -.edit-box { background:var(--bg2); border-radius:1.5rem; padding:1.5rem; min-width:380px; max-width:90%; } -.edit-box h3 { margin-bottom:1rem; color:var(--text); } -.edit-box label { color:var(--text2); font-size:0.8rem; display:block; margin-bottom:0.2rem; } -.edit-box input, .edit-box select { width:100%; margin-bottom:0.5rem; } - -/* Custom modals */ -.custom-modal-overlay { position:fixed; top:0; left:0; right:0; bottom:0; background:rgba(0,0,0,0.6); display:flex; justify-content:center; align-items:center; z-index:10001; display:none; } -.custom-modal-overlay.show { display:flex; } -.custom-modal { background:var(--bg2); border:1px solid var(--border); border-radius:1.2rem; padding:1.5rem; min-width:300px; max-width:90%; } -.custom-modal h3 { margin-bottom:1rem; color:var(--text); } -.custom-modal input { width:100%; margin-bottom:1rem; } -.custom-modal .modal-actions { display:flex; gap:0.5rem; justify-content:flex-end; } - -/* Confirm popup near element */ -.custom-confirm { position:fixed; background:var(--bg2); border:1px solid var(--accent); border-radius:0.8rem; padding:0.7rem 1rem; z-index:9999; box-shadow:0 10px 30px rgba(0,0,0,0.5); display:none; font-size:0.8rem; color:var(--text); white-space:nowrap; } -.custom-confirm.show { display:block; } -.custom-confirm .confirm-text { margin-bottom:0.5rem; } -.custom-confirm .confirm-btns { display:flex; gap:0.4rem; } -.custom-confirm .confirm-yes { background:var(--danger); color:#fff; border:none; padding:0.3rem 0.8rem; border-radius:1.5rem; cursor:pointer; font-size:0.75rem; } -.custom-confirm .confirm-no { background:#334155; color:#fff; border:none; padding:0.3rem 0.8rem; border-radius:1.5rem; cursor:pointer; font-size:0.75rem; } - -/* Zigzag toast */ -.toast-zigzag { position:fixed; z-index:9998; padding:0.4rem 0.7rem; border-radius:0.5rem; font-size:0.72rem; font-weight:600; pointer-events:none; animation:zigzagUp 1.2s ease-out forwards; white-space:nowrap; } -.toast-zigzag.success { background:rgba(34,197,94,0.95); color:#fff; } -.toast-zigzag.error { background:rgba(239,68,68,0.95); color:#fff; } -@keyframes zigzagUp { 0%{opacity:1;transform:translate(0,0) scale(1)} 20%{opacity:0.9;transform:translate(-10px,-14px) scale(0.9)} 40%{opacity:0.65;transform:translate(12px,-28px) scale(0.75)} 70%{opacity:0.3;transform:translate(-8px,-42px) scale(0.6)} 100%{opacity:0;transform:translate(0,-60px) scale(0.4)} } - -.idle-warning { position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); background:rgba(0,0,0,0.95); color:#fff; padding:2rem; border-radius:2rem; z-index:10000; text-align:center; display:none; } -.idle-warning.show { display:block; } - -@media(max-width:700px) { - .vault { padding:1rem; border-radius:1.5rem; width:98%; } - .entry-row { flex-direction:column; } - #entriesContainer.grid-view { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); } - .toolbar { flex-direction:column; } - .folders-bar { flex-direction:column; align-items:stretch; } -} - -/* Floating action button */ -.fab { - position: fixed; bottom: 2rem; right: 2rem; - width: 56px; height: 56px; border-radius: 50%; - background: var(--accent); color: #fff; border: none; - font-size: 1.8rem; cursor: pointer; box-shadow: 0 8px 20px rgba(0,0,0,0.4); - display: flex; align-items: center; justify-content: center; - transition: 0.2s; z-index: 100; -} -.fab:hover { transform: scale(1.1); filter: brightness(1.1); } -.fab-trash { left: 2rem; right: auto; font-size:1.4rem; background:transparent; box-shadow:none; } -.fab-trash.active { box-shadow:0 0 18px rgba(var(--accent-rgb),0.5); } - -/* Generic modal overlay (if you don’t already have it) */ -.modal-overlay { - position: fixed; top: 0; left: 0; right: 0; bottom: 0; - background: rgba(0,0,0,0.7); display: none; - justify-content: center; align-items: center; z-index: 1001; -} -.modal-overlay.show { display: flex; } - -/* Modal box (used by both edit and add modals) */ -.modal-box { - background: var(--bg2); border-radius: 1.5rem; padding: 1.5rem; - min-width: 380px; max-width: 90%; -} -.modal-box h3 { margin-bottom: 1rem; color: var(--text); } -.modal-box label { color: var(--text2); font-size: 0.8rem; display: block; margin-bottom: 0.2rem; } -.modal-box input, .modal-box select { width: 100%; margin-bottom: 0.5rem; } -/* Batch select */ -.select-checkbox { - position: absolute; - top: 6px; - left: 6px; - z-index: 2; - accent-color: var(--accent); -} -.batch-actions { - position: fixed; - bottom: 20px; - left: 50%; - transform: translateX(-50%); - background: var(--bg2); - border: 1px solid var(--accent); - border-radius: 2rem; - padding: 0.5rem 1.5rem; - display: flex; - gap: 0.8rem; - align-items: center; - z-index: 1000; - box-shadow: 0 10px 25px rgba(0,0,0,0.5); - font-size: 0.85rem; + padding: 10px 12px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius-sm); color: var(--text); + transition: all var(--t-fast); } -.batch-actions button { - font-size: 0.78rem; - padding: 0.35rem 0.8rem; +.field input:focus, .field select:focus { + outline: none; + border-color: var(--accent); + background: var(--bg); + box-shadow: 0 0 0 3px var(--accent-soft); } -.selected-count { - font-weight: 600; + +.input-with-action { position: relative; display: flex; align-items: center; gap: 4px; } +.input-with-action input { padding-right: 80px; } +.input-with-action .icon-btn { + position: absolute; + top: 50%; transform: translateY(-50%); +} +.input-with-action .icon-btn:nth-of-type(1) { right: 38px; } +.input-with-action .icon-btn:nth-of-type(2) { right: 4px; } + +.strength-bar { + height: 4px; + background: var(--border); + border-radius: 2px; + position: relative; + overflow: hidden; + margin-top: 4px; +} +.strength-bar::after { + content: ''; + position: absolute; inset: 0; + width: var(--strength, 0%); + background: linear-gradient(90deg, var(--danger), var(--warning) 50%, var(--success)); + transition: width var(--t-base); +} + +input[type="range"] { + -webkit-appearance: none; appearance: none; + width: 100%; height: 4px; + background: var(--border); + border-radius: 2px; +} +input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; appearance: none; + width: 16px; height: 16px; + background: var(--accent); + border-radius: 50%; + cursor: pointer; +} + +.check { + display: inline-flex; align-items: center; gap: 6px; + padding: 6px 10px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + font-size: 12px; + cursor: pointer; + user-select: none; + transition: all var(--t-fast); +} +.check:has(input:checked) { + background: var(--accent-soft); + border-color: var(--accent); color: var(--accent); } -#rectSelect { - position:fixed; pointer-events:none; z-index:999; - border:1px solid var(--accent); - background:rgba(var(--accent-rgb),0.1); - display:none; +.check input { display: none; } + +/* ---- 5. AUTH SCREEN -------------------------------------- */ + +.auth-screen { + position: fixed; inset: 0; + display: grid; place-items: center; + padding: 24px; + background: + radial-gradient(ellipse at top, var(--accent-soft), transparent 50%), + radial-gradient(ellipse at bottom right, rgba(167,139,250,0.08), transparent 50%), + var(--bg); } -#trashBtn.drag-over { - border-color:var(--danger)!important; - box-shadow:0 0 15px rgba(239,68,68,0.4); - background:rgba(239,68,68,0.15); +.auth-card { + width: 100%; max-width: 400px; + padding: 32px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-lg); +} +.auth-brand { text-align: center; margin-bottom: 24px; } +.auth-brand-icon { + width: 40px; height: 40px; + padding: 10px; + background: var(--accent-soft); + color: var(--accent); + border-radius: var(--radius); + margin-bottom: 12px; +} +.auth-brand h1 { font-size: 20px; font-weight: 600; margin: 0 0 4px; } +.auth-brand p { color: var(--text-dim); font-size: 13px; margin: 0; } +.auth-tabs { + display: flex; + padding: 4px; + background: var(--bg); + border-radius: var(--radius-sm); + margin-bottom: 20px; +} +.auth-tab { + flex: 1; + padding: 8px 12px; + background: transparent; + border: none; + border-radius: 6px; + color: var(--text-dim); + font-size: 13px; font-weight: 500; + transition: all var(--t-fast); +} +.auth-tab.is-active { + background: var(--bg-elev); + color: var(--text); + box-shadow: 0 1px 3px rgba(0,0,0,0.1); +} +.auth-form { display: flex; flex-direction: column; } +.auth-form .btn-block { margin-top: 8px; } + +.auth-hint { + padding: 10px 12px; + margin-bottom: 14px; + background: var(--accent-soft); + border: 1px solid var(--accent); + border-radius: var(--radius-sm); + color: var(--accent); + font-size: 12px; + text-align: center; +} +.auth-hint:empty { display: none; } + +/* Tag chip input */ +.chip-input { + display: flex; flex-wrap: wrap; align-items: center; gap: 4px; + padding: 6px 8px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + min-height: 38px; + transition: all var(--t-fast); +} +.chip-input:focus-within { + border-color: var(--accent); + box-shadow: 0 0 0 3px var(--accent-soft); + background: var(--bg); +} +.chip-input input { + flex: 1; + min-width: 80px; + background: transparent; + border: none; + outline: none; + color: var(--text); + font-size: 13px; + padding: 2px 4px; +} +.chip { + display: inline-flex; align-items: center; gap: 4px; + padding: 2px 4px 2px 8px; + background: var(--accent-soft); + color: var(--accent); + border-radius: 10px; + font-size: 11px; + font-weight: 500; +} +.chip button { + display: inline-flex; align-items: center; justify-content: center; + width: 16px; height: 16px; + background: transparent; + border: none; + border-radius: 50%; + color: inherit; + cursor: pointer; + opacity: 0.6; +} +.chip button:hover { opacity: 1; background: rgba(0,0,0,0.1); } +.chip button svg { width: 10px; height: 10px; } + +/* Tag suggestions dropdown */ +.chip-suggestions { + position: absolute; + z-index: 50; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + box-shadow: var(--shadow); + padding: 4px; + max-height: 200px; + overflow-y: auto; + min-width: 160px; +} +.chip-suggestion { + padding: 6px 10px; + border-radius: 6px; + font-size: 12px; + cursor: pointer; +} +.chip-suggestion:hover, .chip-suggestion.is-active { background: var(--bg-elev-2); color: var(--text); } +.chip-suggestion-empty { padding: 6px 10px; color: var(--text-faint); font-size: 12px; } + +/* Settings rows */ +.setting-row { + display: flex; align-items: center; justify-content: space-between; + gap: 12px; + padding: 10px 12px; + background: var(--bg); + border: 1px solid var(--border-soft); + border-radius: var(--radius-sm); + margin-bottom: 6px; + font-size: 13px; +} +.setting-row > span { display: flex; flex-direction: column; gap: 2px; } +.setting-hint { + color: var(--text-faint); + font-size: 11px; + font-weight: normal; + line-height: 1.35; + max-width: 320px; +} +.setting-row select { + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: 6px; + color: var(--text); + padding: 4px 8px; + font-size: 12px; +} +.setting-row select:focus { + outline: none; + border-color: var(--accent); +} + +/* iOS-style toggle switch */ +.toggle { + position: relative; + display: inline-block; + width: 36px; height: 20px; + flex-shrink: 0; +} +.toggle input { opacity: 0; width: 0; height: 0; } +.toggle-slider { + position: absolute; inset: 0; + background: var(--bg-elev-2); + border: 1px solid var(--border); + border-radius: 12px; + cursor: pointer; + transition: all var(--t-fast); +} +.toggle-slider::before { + content: ''; + position: absolute; + left: 2px; top: 1px; + width: 14px; height: 14px; + background: var(--text-dim); + border-radius: 50%; + transition: all var(--t-fast); +} +.toggle input:checked + .toggle-slider { + background: var(--accent); + border-color: var(--accent); +} +.toggle input:checked + .toggle-slider::before { + background: white; + transform: translateX(16px); +} + +/* ---- 6. APP SHELL ---------------------------------------- */ + +.app-shell { + display: grid; + grid-template-columns: 240px 1fr; + height: 100vh; + background: var(--bg); +} + +/* ---- 7. SIDEBAR ------------------------------------------ */ + +.sidebar { + display: flex; flex-direction: column; + padding: 16px 12px; + background: var(--bg-elev); + border-right: 1px solid var(--border); + overflow-y: auto; +} +.sidebar-brand { + display: flex; align-items: center; gap: 10px; + padding: 6px 8px 18px; + font-size: 15px; font-weight: 600; +} +.sidebar-brand svg { color: var(--accent); width: 18px; height: 18px; } + +.sidebar-nav { display: flex; flex-direction: column; gap: 2px; } +.nav-item { + display: flex; align-items: center; gap: 10px; + padding: 7px 10px; + background: transparent; + border: none; + border-radius: 6px; + color: var(--text-dim); + font-size: 13px; font-weight: 500; + text-align: left; + width: 100%; + transition: all var(--t-fast); +} +.nav-item:hover { background: var(--bg-elev-2); color: var(--text); } +.nav-item.is-active { + background: var(--accent-soft); + color: var(--accent); +} +.nav-item.is-active svg { color: var(--accent); } +.nav-item svg { color: var(--text-faint); } +.nav-item > span:first-of-type { flex: 1; } +.nav-count { + font-size: 11px; + color: var(--text-faint); + background: var(--bg-elev-2); + padding: 1px 6px; + border-radius: 8px; + min-width: 18px; + text-align: center; +} +.nav-item.is-active .nav-count { background: var(--accent); color: white; } + +.sidebar-section { margin-top: 18px; } +.sidebar-section-header { + display: flex; align-items: center; justify-content: space-between; + padding: 4px 10px 6px; + font-size: 11px; font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + color: var(--text-faint); +} +.sidebar-bottom { + margin-top: auto; + padding-top: 12px; + border-top: 1px solid var(--border-soft); + display: flex; flex-direction: column; gap: 2px; +} + +.folder-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; } +.nav-item.drag-over { + background: var(--accent-soft); + box-shadow: inset 0 0 0 2px var(--accent); +} + +/* ---- 8. MAIN --------------------------------------------- */ + +.main { display: flex; flex-direction: column; overflow: hidden; } +.topbar { + display: flex; align-items: center; gap: 12px; + padding: 12px 24px; + border-bottom: 1px solid var(--border); + background: var(--bg-glass); + backdrop-filter: var(--blur); + -webkit-backdrop-filter: var(--blur); +} +.search { flex: 1; max-width: 480px; position: relative; display: flex; align-items: center; } +.search svg { + position: absolute; left: 10px; + color: var(--text-faint); + pointer-events: none; +} +.search input { + width: 100%; + padding: 8px 60px 8px 34px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + color: var(--text); + transition: all var(--t-fast); +} +.search input:focus { + outline: none; + border-color: var(--accent); + box-shadow: 0 0 0 3px var(--accent-soft); +} +.search kbd { position: absolute; right: 8px; } +.topbar-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; } + +/* View toggle (Cards / List) */ +.view-toggle { + display: inline-flex; + padding: 2px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius-sm); +} +.view-btn { + width: 28px; height: 28px; + display: grid; place-items: center; + background: transparent; + border: none; + border-radius: 6px; + color: var(--text-dim); + transition: all var(--t-fast); +} +.view-btn:hover { color: var(--text); } +.view-btn.is-active { + background: var(--accent-soft); + color: var(--accent); +} + +[data-theme="dark"] .theme-icon-light { display: none; } +[data-theme="light"] .theme-icon-dark { display: none; } + +.user-menu { position: relative; } +.user-chip { + display: inline-flex; align-items: center; gap: 6px; + padding: 6px 12px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: 16px; + color: var(--text); + font-size: 12px; + transition: all var(--t-fast); +} +.user-chip:hover { background: var(--bg-elev-2); } +.user-dropdown { + position: absolute; top: calc(100% + 6px); right: 0; + min-width: 180px; + padding: 4px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + box-shadow: var(--shadow); + z-index: 50; +} +.dropdown-item { + display: flex; align-items: center; gap: 8px; + width: 100%; + padding: 8px 10px; + background: transparent; + border: none; + border-radius: 6px; + color: var(--text); + font-size: 13px; + text-align: left; +} +.dropdown-item:hover { background: var(--bg-elev-2); } +.dropdown-item svg { color: var(--text-dim); } + +.content { flex: 1; padding: 24px 32px; overflow-y: auto; } +.content-header { display: flex; align-items: baseline; gap: 12px; margin-bottom: 20px; } +.content-header h2 { font-size: 22px; font-weight: 600; margin: 0; } +.content-meta { color: var(--text-faint); font-size: 12px; } + +/* ---- 9. ENTRY GRID --------------------------------------- */ + +.entry-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 12px; + position: relative; + user-select: none; /* avoid native text-selection during marquee */ +} + +/* Marquee rectangle for rubber-band selection */ +.marquee { + position: fixed; + z-index: 5; + background: var(--accent-soft); + border: 1px solid var(--accent); + border-radius: 2px; + pointer-events: none; +} + +.entry-card { + position: relative; + padding: 14px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius); + transition: all var(--t-fast); + cursor: pointer; +} +.entry-card:hover { + transform: translateY(-1px); + border-color: var(--accent); + box-shadow: var(--shadow); +} +.entry-card.is-selected { + border-color: var(--accent); + background: var(--accent-soft); +} +.entry-card.is-checked { + border-color: var(--accent); + background: var(--accent-soft); + box-shadow: inset 0 0 0 2px var(--accent); +} + +/* === List view layout === */ +/* Cards are flattened into a single horizontal row using flexbox + `order`. + `.entry-head` and `.entry-pw-row` get display:contents so their children + participate directly in the card flex container — no wrapping, ever. */ +.entry-grid.is-list { + grid-template-columns: 1fr; + gap: 4px; +} +.entry-grid.is-list .entry-card { + display: flex; + align-items: center; + gap: 12px; + padding: 8px 12px; +} +.entry-grid.is-list .entry-card:hover { transform: none; } + +.entry-grid.is-list .entry-head { display: contents; } +.entry-grid.is-list .entry-pw-row { display: contents; } + +.entry-grid.is-list .entry-avatar { + order: 1; + width: 28px; height: 28px; + font-size: 12px; + margin: 0; +} +.entry-grid.is-list .entry-title { + order: 2; + flex: 1; + min-width: 0; + display: flex; flex-direction: column; +} +.entry-grid.is-list .entry-title b { font-size: 13px; } +.entry-grid.is-list .entry-title small { font-size: 11px; } + +.entry-grid.is-list .entry-pw { + order: 3; + font-size: 11px; + width: 110px; + flex-shrink: 0; + padding: 4px 8px; + background: var(--bg); + border-radius: 6px; + border: 1px solid var(--border-soft); +} +.entry-grid.is-list .entry-pw-row .icon-btn { + order: 4; + flex-shrink: 0; +} + +.entry-grid.is-list .entry-meta { + order: 5; + margin: 0; + flex-shrink: 0; + max-width: 220px; + overflow: hidden; + flex-wrap: nowrap; +} +.entry-grid.is-list .entry-meta .entry-chip { + flex-shrink: 0; + font-size: 10px; +} + +/* Right-side action buttons: favorite + delete (normal view), + restore + purge (trash view), or kebab (compact mode). Same order slot. */ +.entry-grid.is-list .entry-fav, +.entry-grid.is-list .entry-del, +.entry-grid.is-list .entry-kebab-wrap, +.entry-grid.is-list .entry-head .icon-btn { + order: 6; + flex-shrink: 0; +} +.entry-avatar.is-checkable { + position: relative; + cursor: pointer; +} +.entry-avatar.is-checkable:hover::after { + content: ''; + position: absolute; inset: 0; + border-radius: var(--radius-sm); + background: var(--accent-soft); + border: 2px solid var(--accent); +} +.entry-card.is-checked .entry-avatar { + background: var(--accent); + color: white; +} + +/* Batch action bar (appears when selection is non-empty) */ +.batch-bar { + position: sticky; + top: -1px; + z-index: 10; + display: flex; align-items: center; gap: 8px; + padding: 10px 14px; + margin-bottom: 16px; + background: var(--bg-elev); + border: 1px solid var(--accent); + border-radius: var(--radius); + box-shadow: var(--shadow); + animation: toastIn var(--t-base); +} +.batch-bar-count { + font-weight: 600; + color: var(--accent); + margin-right: 8px; +} +.batch-bar select { + background: var(--bg); + border: 1px solid var(--border); + border-radius: 6px; + color: var(--text); + padding: 4px 8px; + font-size: 12px; +} +.batch-bar .grow { flex: 1; } + +.entry-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; } +.entry-avatar { + width: 32px; height: 32px; + display: grid; place-items: center; + background: var(--bg-elev-2); + border-radius: var(--radius-sm); + font-weight: 600; font-size: 14px; + color: var(--text); + flex-shrink: 0; +} +.entry-title { flex: 1; min-width: 0; display: flex; flex-direction: column; } +.entry-title b { + font-size: 14px; font-weight: 600; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; +} +.entry-title small { + color: var(--text-dim); + font-size: 12px; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; +} +.entry-fav, .entry-del { + color: var(--text-faint); + background: transparent; border: none; + padding: 4px; + transition: all var(--t-fast); + cursor: pointer; +} +.entry-fav.is-on { color: var(--warning); } +.entry-fav:hover { color: var(--warning); transform: scale(1.1); } + +/* Delete button — always visible, brightens on hover */ +.entry-del { + color: var(--text-dim); + opacity: 0.8; +} +.entry-del:hover { + opacity: 1; + color: var(--danger); + background: var(--danger-soft); + border-radius: 6px; + transform: scale(1.1); +} + +/* Username row with inline copy button (visible on card hover) */ +.entry-user-row { + display: flex; + align-items: center; + gap: 4px; +} +.entry-user-row > span { + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; +} +.entry-copy-user { + background: transparent; border: none; + padding: 2px; + color: var(--text-faint); + opacity: 0; + cursor: pointer; + transition: all var(--t-fast); + border-radius: 4px; +} +.entry-copy-user svg { width: 11px; height: 11px; } +.entry-card:hover .entry-copy-user { opacity: 0.7; } +.entry-copy-user:hover { + opacity: 1 !important; + color: var(--accent); + background: var(--accent-soft); +} + +/* Kebab (⋯) menu */ +.entry-kebab-wrap { + position: relative; +} +.entry-kebab { + background: transparent; border: none; + padding: 4px; + color: var(--text-dim); + border-radius: 6px; + cursor: pointer; + transition: all var(--t-fast); +} +.entry-kebab:hover { color: var(--text); background: var(--bg-elev-2); } + +.entry-kebab-menu { + position: absolute; + top: calc(100% + 4px); + right: 0; + min-width: 180px; + padding: 4px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + box-shadow: var(--shadow); + z-index: 60; + display: none; + animation: modalIn var(--t-fast); +} +.entry-kebab-menu.is-open { display: block; } + +.kebab-item { + display: flex; align-items: center; gap: 10px; + width: 100%; + padding: 8px 10px; + background: transparent; + border: none; + border-radius: 6px; + color: var(--text); + font-size: 13px; + text-align: left; + cursor: pointer; + transition: all var(--t-fast); +} +.kebab-item:hover { background: var(--bg-elev-2); } +.kebab-item svg { color: var(--text-dim); } +.kebab-item.is-danger { color: var(--danger); } +.kebab-item.is-danger:hover { background: var(--danger-soft); } +.kebab-item.is-danger svg { color: var(--danger); } + +.entry-pw-row { + display: flex; align-items: center; gap: 6px; + padding: 6px 8px; + background: var(--bg); + border: 1px solid var(--border-soft); + border-radius: 6px; + margin-bottom: 8px; +} +.entry-pw { + flex: 1; + font-family: 'JetBrains Mono', 'SF Mono', Consolas, monospace; + font-size: 12px; + color: var(--text-dim); + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + user-select: none; +} +.entry-pw.is-revealed { color: var(--text); } +.entry-pw.is-error { color: var(--danger); } + +.entry-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; } +.entry-chip { + display: inline-flex; align-items: center; gap: 4px; + padding: 2px 8px; + background: var(--bg-elev-2); + border-radius: 10px; + font-size: 11px; + color: var(--text-dim); +} +.entry-chip svg { width: 11px; height: 11px; } +.entry-chip.is-folder { color: var(--accent); background: var(--accent-soft); } +.entry-chip.is-pwned { + color: #fff; + background: #dc2626; /* solid red — high-attention signal */ + font-weight: 600; +} +.entry-chip.is-pwned svg { stroke: #fff; } + +/* ---- 10. SLIDE-OVER -------------------------------------- */ + +.slideover { + position: fixed; top: 0; right: 0; bottom: 0; + width: 420px; + background: var(--bg-elev); + border-left: 1px solid var(--border); + box-shadow: var(--shadow-lg); + transform: translateX(100%); + transition: transform var(--t-base); + display: flex; flex-direction: column; + z-index: 30; +} +.slideover.is-open { transform: translateX(0); } +.slideover-header { + display: flex; align-items: center; justify-content: space-between; + padding: 16px 20px; + border-bottom: 1px solid var(--border); +} +.slideover-header h3 { + font-size: 15px; font-weight: 600; + margin: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; +} +.slideover-body { padding: 20px; overflow-y: auto; flex: 1; } +.slideover-field { margin-bottom: 16px; } +.slideover-field-label { font-size: 11px; font-weight: 500; color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 6px; } +.slideover-field-value { + display: flex; align-items: center; gap: 6px; + padding: 10px 12px; + background: var(--bg); + border: 1px solid var(--border-soft); + border-radius: var(--radius-sm); + font-size: 13px; + word-break: break-all; +} +.so-input { + width: 100%; + padding: 10px 12px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + color: var(--text); + font-size: 13px; + transition: all var(--t-fast); +} +.so-input:focus { + outline: none; + border-color: var(--accent); + background: var(--bg); + box-shadow: 0 0 0 3px var(--accent-soft); +} +.so-pw-row { + display: flex; align-items: center; gap: 4px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + padding: 2px 4px 2px 10px; +} +.so-pw-row:focus-within { + border-color: var(--accent); + box-shadow: 0 0 0 3px var(--accent-soft); +} +.so-pw-row .so-input { + background: transparent; + border: none; + padding: 8px 4px; +} +.so-pw-row .so-input:focus { box-shadow: none; } +.slideover-actions { display: flex; gap: 8px; margin-top: 24px; } + +/* ---- 11. MODALS ------------------------------------------ */ + +.modal { + position: fixed; inset: 0; + z-index: 100; + display: grid; place-items: center; + padding: 24px; +} +.modal-backdrop { + position: absolute; inset: 0; + background: rgba(0,0,0,0.5); + backdrop-filter: blur(4px); +} +.modal-panel { + position: relative; + width: 100%; max-width: 480px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-lg); + overflow: hidden; + animation: modalIn var(--t-base); +} +.modal-panel-sm { max-width: 360px; } +@keyframes modalIn { + from { opacity: 0; transform: scale(0.96) translateY(8px); } + to { opacity: 1; transform: scale(1) translateY(0); } +} +.modal-header { + display: flex; align-items: center; justify-content: space-between; + padding: 16px 20px; + border-bottom: 1px solid var(--border); +} +.modal-header h3 { font-size: 15px; font-weight: 600; margin: 0; } +.modal-body { padding: 20px; } +.modal-footer { + display: flex; gap: 8px; justify-content: flex-end; + padding: 14px 20px; + background: var(--bg); + border-top: 1px solid var(--border); +} + +.gen-preview { + padding: 12px; + background: var(--bg); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + font-family: 'JetBrains Mono', monospace; + font-size: 13px; + word-break: break-all; + margin-bottom: 16px; + min-height: 42px; + display: flex; align-items: center; +} +.gen-options { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; } + +/* ---- 12. COMMAND PALETTE -------------------------------- */ + +.cmd-palette { + position: fixed; inset: 0; + z-index: 200; + display: grid; place-items: start center; + padding-top: 15vh; +} +.cmd-panel { + position: relative; + width: 100%; max-width: 560px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-lg); + overflow: hidden; + animation: modalIn var(--t-base); +} +.cmd-input { + display: flex; align-items: center; gap: 10px; + padding: 14px 16px; + border-bottom: 1px solid var(--border); +} +.cmd-input svg { color: var(--text-faint); } +.cmd-input input { + flex: 1; + background: transparent; border: none; outline: none; + color: var(--text); + font-size: 15px; +} +.cmd-results { max-height: 360px; overflow-y: auto; padding: 8px; } +.cmd-item { + display: flex; align-items: center; gap: 10px; + padding: 10px 12px; + border-radius: 6px; + cursor: pointer; + color: var(--text); + font-size: 13px; +} +.cmd-item:hover, .cmd-item.is-active { background: var(--bg-elev-2); } + +/* ---- 13. EMPTY STATE ------------------------------------ */ + +.empty-state { + display: flex; flex-direction: column; align-items: center; gap: 8px; + padding: 80px 20px; + color: var(--text-dim); + animation: fadeIn var(--t-base); +} +.empty-illustration { + width: 140px; height: 140px; + margin-bottom: 12px; +} +.empty-icon { + width: 48px; height: 48px; + padding: 12px; + background: var(--bg-elev); + border-radius: var(--radius); + color: var(--text-faint); +} +.empty-state h3 { margin: 8px 0 0; font-size: 18px; color: var(--text); font-weight: 600; } +.empty-state p { margin: 0; font-size: 13px; max-width: 320px; text-align: center; } + +@keyframes fadeIn { + from { opacity: 0; transform: translateY(8px); } + to { opacity: 1; transform: translateY(0); } +} + +/* ---- Skeleton loaders ----------------------------------- */ +.skeleton-card { + padding: 14px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: var(--radius); + overflow: hidden; + position: relative; +} +.skeleton-card::after { + content: ''; + position: absolute; inset: 0; + background: linear-gradient(90deg, transparent, var(--bg-elev-2), transparent); + animation: shimmer 1.4s infinite; +} +.skeleton-line { + height: 12px; + background: var(--bg-elev-2); + border-radius: 4px; + margin-bottom: 10px; +} +.skeleton-line.w-40 { width: 40%; } +.skeleton-line.w-60 { width: 60%; } +.skeleton-line.w-80 { width: 80%; } +.skeleton-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; } +.skeleton-circle { + width: 32px; height: 32px; + background: var(--bg-elev-2); + border-radius: var(--radius-sm); + flex-shrink: 0; +} + +@keyframes shimmer { + from { transform: translateX(-100%); } + to { transform: translateX(100%); } +} + +/* ---- Idle warning ---------------------------------------- */ +.idle-warning { + position: fixed; + top: 50%; left: 50%; + transform: translate(-50%, -50%); + z-index: 400; + width: 320px; + padding: 24px; + background: var(--bg-elev); + border: 1px solid var(--warning); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-lg); + text-align: center; + animation: modalIn var(--t-base); +} +.idle-warning .idle-icon { + width: 36px; height: 36px; + padding: 8px; + background: rgba(245,158,11,0.12); + color: var(--warning); + border-radius: 50%; + margin: 0 auto 8px; + display: block; +} +.idle-warning h3 { font-size: 16px; font-weight: 600; margin: 0 0 4px; } +.idle-warning p { color: var(--text-dim); font-size: 13px; margin: 0 0 16px; } +.idle-warning b { color: var(--warning); font-size: 20px; } + +/* ---- 14. TOASTS ----------------------------------------- */ + +.toast-container { + position: fixed; bottom: 20px; right: 20px; + z-index: 300; + display: flex; flex-direction: column-reverse; gap: 8px; + pointer-events: none; +} +.toast { + pointer-events: auto; + display: flex; align-items: center; gap: 8px; + padding: 10px 14px; + background: var(--bg-elev); + border: 1px solid var(--border); + border-left: 3px solid var(--accent); + border-radius: var(--radius-sm); + box-shadow: var(--shadow); + font-size: 13px; + min-width: 240px; + animation: toastIn var(--t-base); +} +.toast.is-success { border-left-color: var(--success); } +.toast.is-error { border-left-color: var(--danger); } +.toast.is-warning { border-left-color: var(--warning); } +@keyframes toastIn { + from { opacity: 0; transform: translateX(20px); } + to { opacity: 1; transform: translateX(0); } +} + +/* ---- 15. SCROLLBARS ------------------------------------- */ + +::-webkit-scrollbar { width: 8px; height: 8px; } +::-webkit-scrollbar-track { background: transparent; } +::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; } +::-webkit-scrollbar-thumb:hover { background: var(--text-faint); } + +/* ---- 16. RESPONSIVE ------------------------------------- */ + +@media (max-width: 900px) { + .app-shell { grid-template-columns: 60px 1fr; } + .sidebar { padding: 12px 6px; } + .sidebar-brand span, + .nav-item > span:first-of-type, + .nav-count, + .sidebar-section-header { display: none; } + .nav-item { justify-content: center; padding: 8px; } + .topbar { padding: 12px 16px; } + .content { padding: 16px; } + .slideover { width: 100%; } } -/* Batch confirm modal backdrop */ -.batch-confirm-overlay { background:rgba(0,0,0,0.3); } \ No newline at end of file diff --git a/delphi-backend/Source/PM.HTTPServer.pas b/delphi-backend/Source/PM.HTTPServer.pas index 1ac68d6..4b2949a 100644 --- a/delphi-backend/Source/PM.HTTPServer.pas +++ b/delphi-backend/Source/PM.HTTPServer.pas @@ -138,9 +138,22 @@ var begin AResponse.CustomHeaders.Values['Strict-Transport-Security'] := 'max-age=31536000; includeSubDomains'; + // Content-Security-Policy — tightened May 2026: + // - script-src: removed 'unsafe-inline'. No + + + +