Files
PassKeeper/app/static/css/app.css
T
2026-04-18 21:50:11 -04:00

1763 lines
36 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ── Reset & base ──────────────────────────────────────────────────── */
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--color-bg: #f4f5f7;
--color-surface: #ffffff;
--color-primary: #d0021b;
--color-primary-dark: #a80016;
--color-text: #1a1a2e;
--color-text-muted: #6b7280;
--color-border: #e2e4e9;
--color-sidebar-bg: #1e2235;
--color-sidebar-text: #c8ccd8;
--color-sidebar-hover: #2d3250;
--color-sidebar-active: #d0021b;
--radius: 8px;
--shadow: 0 1px 4px rgba(0, 0, 0, 0.08), 0 2px 12px rgba(0, 0, 0, 0.05);
--transition: 150ms ease;
}
html,
body {
height: 100%;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 14px;
color: var(--color-text);
background: var(--color-bg);
}
a {
color: var(--color-primary);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
button {
cursor: pointer;
font: inherit;
border: none;
background: none;
}
input,
select,
textarea {
font: inherit;
}
ul {
list-style: none;
}
/* ── Utilities ───────────────────────────────────────────────────── */
.hidden {
display: none !important;
}
/* ── Auth pages ──────────────────────────────────────────────────── */
.auth-page {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: var(--color-bg);
}
.auth-container {
width: 100%;
max-width: 420px;
padding: 16px;
}
.auth-card {
background: var(--color-surface);
border-radius: var(--radius);
box-shadow: var(--shadow);
padding: 40px 36px;
}
@media (max-width: 480px) {
.auth-container {
padding: 12px;
}
.auth-card {
padding: 28px 20px;
border-radius: 12px;
}
.auth-title {
font-size: 20px;
}
}
.auth-logo {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 28px;
}
.auth-logo .logo-icon {
font-size: 28px;
}
.auth-logo .logo-text {
font-size: 20px;
font-weight: 700;
color: var(--color-text);
}
.auth-title {
font-size: 22px;
font-weight: 600;
margin-bottom: 24px;
}
.auth-footer {
margin-top: 20px;
text-align: center;
color: var(--color-text-muted);
}
/* ── Form elements ──────────────────────────────────────────────── */
.form-group {
margin-bottom: 16px;
}
.form-group label {
display: block;
margin-bottom: 6px;
font-weight: 500;
color: var(--color-text);
}
.form-group label .hint {
font-weight: 400;
color: var(--color-text-muted);
font-size: 12px;
}
.form-group input,
.form-group select,
.form-group textarea {
width: 100%;
padding: 9px 12px;
border: 1px solid var(--color-border);
border-radius: var(--radius);
background: var(--color-surface);
color: var(--color-text);
transition: border-color var(--transition);
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
outline: none;
border-color: var(--color-primary);
box-shadow: 0 0 0 3px rgba(208, 2, 27, 0.12);
}
/* Prevent iOS viewport auto-zoom on input focus (requires font-size >= 16px) */
@media (max-width: 768px) {
.form-group input,
.form-group select,
.form-group textarea {
font-size: 16px;
}
}
.input-with-toggle {
position: relative;
}
.input-with-toggle input {
padding-right: 40px;
}
.btn-show-pass {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
cursor: pointer;
font-size: 16px;
opacity: 0.6;
transition: opacity var(--transition);
}
.btn-show-pass:hover {
opacity: 1;
}
.form-error {
color: #c00;
background: #fff0f0;
border: 1px solid #fcc;
border-radius: var(--radius);
padding: 8px 12px;
margin-bottom: 12px;
font-size: 13px;
}
/* Buttons */
.btn-primary {
display: inline-flex;
align-items: center;
justify-content: center;
background: var(--color-primary);
color: #fff;
padding: 10px 20px;
border-radius: var(--radius);
font-weight: 600;
transition: background var(--transition);
}
.btn-primary:hover {
background: var(--color-primary-dark);
}
.btn-primary:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.btn-full {
width: 100%;
}
.btn-secondary {
display: inline-flex;
align-items: center;
justify-content: center;
background: var(--color-border);
color: var(--color-text);
padding: 10px 20px;
border-radius: var(--radius);
font-weight: 500;
transition: background var(--transition);
}
.btn-secondary:hover {
background: #d1d5dc;
}
.btn-text {
background: none;
border: none;
color: inherit;
padding: 0;
}
/* Notices */
.notice-success {
background: #e8f5e9;
border: 1px solid #a5d6a7;
color: #2e7d32;
border-radius: var(--radius);
padding: 10px 14px;
margin-bottom: 16px;
font-size: 13px;
}
.notice-info {
background: #e3f2fd;
border: 1px solid #90caf9;
color: #1565c0;
border-radius: var(--radius);
padding: 10px 14px;
margin-bottom: 16px;
font-size: 13px;
}
/* ── Password Generator modal ────────────────────────────────────────── */
.gen-opt {
display: flex;
align-items: center;
gap: 6px;
cursor: pointer;
font-size: 13px;
}
.gen-opt input[type="checkbox"] {
width: 15px;
height: 15px;
accent-color: var(--color-primary);
cursor: pointer;
}
#gen-output {
letter-spacing: 0.5px;
font-family: "Courier New", monospace;
}
/* Launch (open URL) button — distinct colour so it reads as navigation */
.btn-icon[data-action="launch"] {
color: #1a73e8;
}
.btn-icon[data-action="launch"]:hover {
background: #e8f0fe;
color: #1558b0;
}
/* Password strength */
.password-strength {
margin-top: 6px;
font-size: 12px;
font-weight: 500;
}
.strength-1 {
color: #c62828;
}
.strength-2 {
color: #e65100;
}
.strength-3 {
color: #f57f17;
}
.strength-4 {
color: #2e7d32;
}
.strength-5 {
color: #1b5e20;
}
/* ── App layout (vault) ──────────────────────────────────────────── */
.vault-page {
height: 100vh;
height: -webkit-fill-available;
height: calc(var(--vh, 1vh) * 100);
overflow: hidden;
}
.app-layout {
display: flex;
height: 100%;
}
/* ── Sidebar ─────────────────────────────────────────────────────── */
.sidebar {
width: 240px;
flex-shrink: 0;
background: var(--color-sidebar-bg);
color: var(--color-sidebar-text);
display: flex;
flex-direction: column;
overflow: hidden;
transition: width 0.22s ease;
}
.sidebar.collapsed {
width: 72px;
}
/* Sidebar must not clip its children when collapsed — tooltips need to escape */
.sidebar.collapsed .sidebar-nav,
.sidebar.collapsed .sidebar-footer {
overflow: visible;
}
.sidebar-header {
display: flex;
align-items: center;
gap: 8px;
padding: 14px 12px;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
flex-shrink: 0;
min-height: 56px;
overflow: hidden;
}
/* When collapsed: centre the toggle button, hide everything else */
.sidebar.collapsed .sidebar-header {
justify-content: center;
padding: 14px 0;
overflow: visible;
}
.sidebar-header .logo-icon {
font-size: 22px;
flex-shrink: 0;
transition: opacity 0.15s ease;
}
.sidebar-header .logo-text {
font-size: 16px;
font-weight: 700;
color: #fff;
flex: 1;
white-space: nowrap;
overflow: hidden;
transition: opacity 0.15s ease;
}
.sidebar.collapsed .sidebar-header .logo-icon,
.sidebar.collapsed .sidebar-header .logo-text {
opacity: 0;
width: 0;
pointer-events: none;
}
/* Toggle button — always visible, always clickable */
.btn-sidebar-toggle {
background: none;
border: none;
color: rgba(255, 255, 255, 0.5);
font-size: 14px;
cursor: pointer;
padding: 6px 8px;
border-radius: 4px;
line-height: 1;
flex-shrink: 0;
transition:
color var(--transition),
transform 0.22s ease;
margin-left: auto;
z-index: 10;
}
.btn-sidebar-toggle:hover {
color: #fff;
background: rgba(255, 255, 255, 0.12);
}
.sidebar.collapsed .btn-sidebar-toggle {
transform: rotate(180deg);
margin-left: 0;
}
.sidebar-nav {
flex: 1;
padding: 8px 0;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.sidebar-section-header {
padding: 12px 16px 4px;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.08em;
color: rgba(255, 255, 255, 0.35);
white-space: nowrap;
overflow: hidden;
transition: opacity 0.15s ease;
}
.sidebar.collapsed .sidebar-section-header {
opacity: 0;
pointer-events: none;
height: 0;
padding: 0;
}
.sidebar-item {
display: flex;
align-items: center;
gap: 10px;
padding: 9px 16px;
border-radius: 0;
color: var(--color-sidebar-text);
cursor: pointer;
transition: background var(--transition);
font-size: 14px;
width: 100%;
text-align: left;
position: relative;
white-space: nowrap;
overflow: hidden;
}
.sidebar-item:hover {
background: var(--color-sidebar-hover);
}
.sidebar-item.active {
background: var(--color-sidebar-active);
color: #fff;
}
.sidebar-icon {
font-size: 20px;
flex-shrink: 0;
width: 22px;
text-align: center;
}
/* Labels — fade out when collapsed; use max-width so icon stays visible */
.sidebar-label {
transition:
opacity 0.15s ease,
max-width 0.22s ease;
max-width: 200px;
overflow: hidden;
}
.sidebar.collapsed .sidebar-label {
opacity: 0;
max-width: 0;
}
.sidebar.collapsed .sidebar-item {
justify-content: center;
padding: 10px 0;
overflow: visible;
}
/* Tooltip — appears to the right of the 72px rail */
.sidebar.collapsed .sidebar-item::after {
content: attr(data-tooltip);
position: fixed;
left: 80px;
background: #111827;
color: #fff;
font-size: 12px;
padding: 5px 10px;
border-radius: 5px;
white-space: nowrap;
pointer-events: none;
opacity: 0;
transition: opacity 0.12s ease;
z-index: 1000;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}
.sidebar.collapsed .sidebar-item:hover::after {
opacity: 1;
}
.sidebar-footer {
padding: 12px 0;
border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.folder-item {
justify-content: space-between;
}
.folder-label {
display: flex;
align-items: center;
gap: 10px;
flex: 1;
cursor: pointer;
}
.btn-delete-folder {
background: none;
border: none;
cursor: pointer;
font-size: 13px;
opacity: 0;
color: rgba(255, 255, 255, 0.6);
transition:
opacity var(--transition),
color var(--transition);
padding: 2px 4px;
border-radius: 4px;
flex-shrink: 0;
}
.folder-item:hover .btn-delete-folder {
opacity: 1;
}
.btn-delete-folder:hover {
color: #ff6b6b;
}
.btn-new-folder {
float: right;
margin-right: 4px;
background: none;
border: none;
color: rgba(255, 255, 255, 0.5);
font-size: 16px;
line-height: 1;
cursor: pointer;
padding: 0 4px;
transition: color var(--transition);
}
.btn-new-folder:hover {
color: #fff;
}
.new-folder-row {
padding: 4px 10px 4px 16px;
}
.new-folder-row form {
display: flex;
align-items: center;
gap: 4px;
}
.new-folder-row input {
flex: 1;
padding: 5px 8px;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.2);
background: rgba(255, 255, 255, 0.1);
color: #fff;
font-size: 13px;
}
.new-folder-row input::placeholder {
color: rgba(255, 255, 255, 0.4);
}
.new-folder-row input:focus {
outline: none;
border-color: rgba(255, 255, 255, 0.5);
}
.new-folder-row .btn-icon {
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
}
.new-folder-row .btn-icon:hover {
color: #fff;
background: rgba(255, 255, 255, 0.1);
}
/* ── Vault main ──────────────────────────────────────────────────── */
.vault-main {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
background: var(--color-bg);
}
#view-vault,
#view-security {
display: flex;
flex-direction: column;
flex: 1;
overflow: hidden;
min-height: 0;
position: relative;
}
#view-vault.hidden,
#view-security.hidden {
display: none;
}
.vault-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 24px;
background: var(--color-surface);
border-bottom: 1px solid var(--color-border);
gap: 16px;
}
/* Inner wrapper constrains content width on very large screens */
.vault-header-inner {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
max-width: 900px;
margin: 0 auto;
gap: 16px;
}
.vault-title {
font-size: 18px;
font-weight: 600;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.vault-toolbar {
display: flex;
align-items: center;
gap: 12px;
flex: 1;
justify-content: flex-end;
}
.search-wrapper {
display: flex;
align-items: center;
background: var(--color-bg);
border: 1px solid var(--color-border);
border-radius: 20px;
padding: 6px 14px;
gap: 8px;
flex: 1;
max-width: 360px;
}
.search-icon {
color: var(--color-text-muted);
}
#search-input {
border: none;
background: none;
outline: none;
flex: 1;
font-size: 14px;
}
.btn-fab {
width: 40px;
height: 40px;
border-radius: 50%;
background: var(--color-primary);
color: #fff;
font-size: 24px;
font-weight: 300;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 8px rgba(208, 2, 27, 0.35);
transition:
background var(--transition),
box-shadow var(--transition);
flex-shrink: 0;
}
.btn-fab:hover {
background: var(--color-primary-dark);
box-shadow: 0 4px 14px rgba(208, 2, 27, 0.45);
}
/* ── Vault list ──────────────────────────────────────────────────── */
/* Outer scroll container */
.vault-list {
flex: 1;
overflow-y: auto;
padding: 12px 24px 24px;
-webkit-overflow-scrolling: touch;
}
/* Content max-width — keeps items readable on very wide screens */
.vault-list-inner {
max-width: 900px;
margin: 0 auto;
}
.vault-group-header {
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--color-text-muted);
padding: 16px 0 6px;
border-bottom: 1px solid var(--color-border);
margin-bottom: 4px;
}
.vault-empty {
text-align: center;
color: var(--color-text-muted);
padding: 60px 0;
font-size: 15px;
}
.vault-item {
display: flex;
align-items: center;
gap: 12px;
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius);
padding: 12px 14px;
margin-bottom: 6px;
cursor: pointer;
transition:
box-shadow var(--transition),
border-color var(--transition);
}
.vault-item:hover {
box-shadow: var(--shadow);
border-color: #c9ccd4;
}
.item-icon {
font-size: 22px;
flex-shrink: 0;
}
.item-info {
flex: 1;
min-width: 0;
}
.item-name {
display: block;
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.item-sub {
display: block;
font-size: 12px;
color: var(--color-text-muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* Actions always visible — no hover-only opacity trick on desktop */
.item-actions {
display: flex;
gap: 4px;
}
.vault-item:hover .item-actions {
opacity: 1;
}
.btn-icon {
width: 36px;
height: 36px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
font-size: 15px;
color: var(--color-text-muted);
transition:
background var(--transition),
color var(--transition);
/* Expand touch target without changing visual size */
touch-action: manipulation;
}
.btn-icon:hover {
background: var(--color-bg);
color: var(--color-text);
}
@media (max-width: 768px) {
.btn-icon {
min-width: 44px;
min-height: 44px;
}
}
/* ── Spinner ─────────────────────────────────────────────────────── */
.spinner-overlay {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.7);
z-index: 10;
}
.spinner-overlay.hidden {
display: none;
}
.spinner {
width: 36px;
height: 36px;
border: 3px solid var(--color-border);
border-top-color: var(--color-primary);
border-radius: 50%;
animation: spin 0.7s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
/* ── Modal ───────────────────────────────────────────────────────── */
.modal-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.45);
display: none;
align-items: center;
justify-content: center;
z-index: 100;
padding: 16px;
}
.modal-overlay.open {
display: flex;
}
.modal {
background: var(--color-surface);
border-radius: var(--radius);
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.2);
width: 100%;
max-width: 480px;
max-height: 90vh;
max-height: calc(var(--vh, 1vh) * 90);
overflow-y: auto;
-webkit-overflow-scrolling: touch;
padding: 28px;
}
.modal-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
}
.modal-header h3 {
font-size: 18px;
font-weight: 600;
}
.btn-close {
font-size: 18px;
color: var(--color-text-muted);
padding: 4px;
border-radius: 4px;
}
.btn-close:hover {
background: var(--color-bg);
color: var(--color-text);
}
.modal-actions {
display: flex;
gap: 10px;
justify-content: flex-end;
margin-top: 20px;
}
.required {
color: var(--color-primary);
}
/* ── Toast ───────────────────────────────────────────────────────── */
.toast {
position: fixed;
bottom: 24px;
left: 50%;
transform: translateX(-50%) translateY(20px);
background: #1a1a2e;
color: #fff;
padding: 10px 20px;
border-radius: 20px;
font-size: 14px;
font-weight: 500;
opacity: 0;
transition:
opacity 0.25s,
transform 0.25s;
pointer-events: none;
z-index: 200;
white-space: nowrap;
}
.toast.show {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
.toast.toast-error {
background: #c00;
}
/* ── Unlock overlay ──────────────────────────────────────────────── */
.modal-unlock {
max-width: 380px;
}
.unlock-logo {
margin-bottom: 16px;
}
.unlock-title {
margin-bottom: 4px;
}
.unlock-subtitle {
color: var(--color-text-muted);
font-size: 13px;
margin-bottom: 20px;
}
.btn-link {
padding: 10px 20px;
border-radius: var(--radius);
text-decoration: none;
}
/* ── Auth step hint ─────────────────────────────────────────────── */
.auth-step-hint {
color: var(--color-text-muted);
font-size: 13px;
margin-bottom: 16px;
}
#mfa-code {
font-size: 22px;
letter-spacing: 0.2em;
text-align: center;
}
/* ── Panel body (sharing / emergency) ───────────────────────────── */
.panel-body {
flex: 1;
overflow-y: auto;
padding: 20px 24px;
-webkit-overflow-scrolling: touch;
}
/* ── Tabs ────────────────────────────────────────────────────────── */
.panel-tabs {
display: flex;
gap: 4px;
margin-bottom: 16px;
border-bottom: 2px solid var(--color-border);
padding-bottom: 0;
}
.tab-btn {
padding: 8px 16px;
border-radius: 6px 6px 0 0;
font-size: 13px;
font-weight: 500;
color: var(--color-text-muted);
border-bottom: 2px solid transparent;
margin-bottom: -2px;
transition:
color var(--transition),
border-color var(--transition);
}
.tab-btn:hover {
color: var(--color-text);
}
.tab-btn.active {
color: var(--color-primary);
border-bottom-color: var(--color-primary);
}
/* ── Share / Emergency lists ────────────────────────────────────── */
.share-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.share-item {
display: flex;
align-items: center;
gap: 12px;
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius);
padding: 12px 14px;
}
.share-icon {
font-size: 22px;
flex-shrink: 0;
}
.share-info {
flex: 1;
min-width: 0;
}
.share-name {
display: block;
font-weight: 500;
}
.share-meta {
display: block;
font-size: 12px;
color: var(--color-text-muted);
margin-top: 2px;
}
.share-actions {
display: flex;
gap: 6px;
align-items: center;
flex-shrink: 0;
}
/* ── Badges ──────────────────────────────────────────────────────── */
.badge {
display: inline-block;
padding: 3px 8px;
border-radius: 12px;
font-size: 12px;
font-weight: 500;
}
.badge-warn {
background: #fff8e1;
color: #e65100;
border: 1px solid #ffb74d;
}
.badge-info {
background: #e3f2fd;
color: #1565c0;
border: 1px solid #90caf9;
}
/* ── Settings modal ──────────────────────────────────────────────── */
.modal-settings {
max-width: 520px;
}
.settings-section {
padding: 16px 0;
border-bottom: 1px solid var(--color-border);
}
.settings-section:last-child {
border-bottom: none;
}
.settings-section-title {
font-size: 15px;
font-weight: 600;
margin-bottom: 8px;
}
.settings-desc {
font-size: 13px;
color: var(--color-text-muted);
margin-bottom: 10px;
line-height: 1.5;
}
.mfa-qr {
display: block;
margin: 12px auto;
max-width: 180px;
border: 1px solid var(--color-border);
border-radius: 4px;
}
.mfa-secret-text {
font-family: monospace;
font-size: 12px;
}
.mfa-secret-text code {
background: var(--color-bg);
padding: 2px 6px;
border-radius: 4px;
user-select: all;
}
/* ── Sort control ────────────────────────────────────────────────── */
.sort-wrapper select {
padding: 6px 10px;
border: 1px solid var(--color-border);
border-radius: 20px;
background: var(--color-bg);
color: var(--color-text);
font-size: 13px;
cursor: pointer;
outline: none;
}
.sort-wrapper select:focus {
border-color: var(--color-primary);
}
/* ── Modal item (wider for address/card forms) ───────────────────── */
.modal-item {
max-width: 540px;
}
/* ── Multi-column form rows ──────────────────────────────────────── */
.form-row {
display: flex;
gap: 12px;
}
.form-row .form-group {
flex: 1;
}
/* ── Btn small ───────────────────────────────────────────────────── */
.btn-sm {
padding: 5px 12px;
font-size: 12px;
border-radius: 6px;
}
/* ── Security dashboard ──────────────────────────────────────────── */
.security-dashboard {
flex: 1;
overflow-y: auto;
padding: 24px;
display: flex;
flex-direction: column;
gap: 24px;
-webkit-overflow-scrolling: touch;
}
.sec-notice {
text-align: center;
color: var(--color-text-muted);
padding: 40px 0;
font-size: 15px;
}
.security-summary {
display: flex;
gap: 20px;
align-items: center;
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius);
padding: 24px;
flex-wrap: wrap;
}
.sec-score-card {
text-align: center;
flex-shrink: 0;
}
.sec-score {
font-size: 56px;
font-weight: 700;
line-height: 1;
}
.sec-score.score-good {
color: #2e7d32;
}
.sec-score.score-fair {
color: #e65100;
}
.sec-score.score-poor {
color: #c62828;
}
.sec-score-label {
font-size: 16px;
font-weight: 600;
margin-top: 4px;
}
.sec-score-desc {
font-size: 12px;
color: var(--color-text-muted);
margin-top: 2px;
}
.sec-stats {
display: flex;
gap: 16px;
flex-wrap: wrap;
}
.sec-stat {
text-align: center;
background: var(--color-bg);
border: 1px solid var(--color-border);
border-radius: var(--radius);
padding: 12px 20px;
min-width: 80px;
}
.sec-stat-warn {
border-color: #ffb74d;
background: #fff8e1;
}
.sec-stat-info {
border-color: #90caf9;
background: #e3f2fd;
}
.sec-stat-ok {
border-color: #a5d6a7;
background: #e8f5e9;
}
.sec-stat-num {
display: block;
font-size: 28px;
font-weight: 700;
}
.sec-stat-label {
display: block;
font-size: 12px;
color: var(--color-text-muted);
margin-top: 2px;
}
.sec-section {
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius);
overflow: hidden;
}
.sec-section-header {
display: flex;
align-items: flex-start;
gap: 12px;
padding: 16px 20px;
border-bottom: 1px solid var(--color-border);
background: var(--color-bg);
}
.sec-section-icon {
font-size: 20px;
flex-shrink: 0;
}
.sec-section-title {
font-weight: 600;
font-size: 15px;
}
.sec-section-desc {
font-size: 12px;
color: var(--color-text-muted);
margin-top: 2px;
}
.sec-item-list {
padding: 0;
}
.sec-item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 20px;
border-bottom: 1px solid var(--color-border);
}
.sec-item:last-child {
border-bottom: none;
}
.sec-item-name {
font-weight: 500;
flex: 1;
}
.sec-item-sub {
font-size: 12px;
color: var(--color-text-muted);
flex: 1;
}
/* ── Item Detail Modal ───────────────────────────────────────────── */
.modal-detail {
max-height: 80vh;
display: flex;
flex-direction: column;
}
.detail-body {
flex: 1;
overflow-y: auto;
padding: 4px 0;
}
.detail-field {
display: flex;
align-items: flex-start;
gap: 12px;
padding: 10px 0;
border-bottom: 1px solid var(--color-border);
}
.detail-field:last-child {
border-bottom: none;
}
.detail-label {
font-size: 12px;
color: var(--color-text-muted);
width: 140px;
flex-shrink: 0;
padding-top: 4px;
}
.detail-val-row {
display: flex;
align-items: center;
gap: 6px;
flex: 1;
flex-wrap: wrap;
}
.detail-val {
font-size: 14px;
word-break: break-all;
}
.detail-sensitive {
display: inline-flex;
align-items: center;
font-family: monospace;
font-size: 14px;
}
.detail-masked {
letter-spacing: 2px;
}
.detail-actual {
word-break: break-all;
}
.btn-reveal,
.btn-copy-field {
background: none;
border: none;
cursor: pointer;
padding: 2px 4px;
font-size: 14px;
color: var(--color-text-muted);
flex-shrink: 0;
}
.btn-reveal:hover,
.btn-copy-field:hover {
color: var(--color-primary);
}
/* ── Emergency Vault Panel ───────────────────────────────────────── */
.em-vault-panel {
padding: 8px 0;
}
.em-vault-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 4px 0 16px;
border-bottom: 2px solid var(--color-border);
margin-bottom: 8px;
}
.em-vault-header h4 {
margin: 0;
font-size: 15px;
font-weight: 600;
}
.em-vault-list {
list-style: none;
padding: 0;
margin: 0;
}
.em-vault-item {
border-bottom: 1px solid var(--color-border);
}
.em-vault-item:last-child {
border-bottom: none;
}
.em-vault-item-header {
display: flex;
align-items: center;
gap: 10px;
width: 100%;
background: none;
border: none;
padding: 12px 4px;
cursor: pointer;
text-align: left;
}
.em-vault-item-header:hover {
background: var(--color-sidebar-hover);
border-radius: var(--radius);
}
.em-vault-icon {
font-size: 18px;
flex-shrink: 0;
}
.em-vault-name {
font-weight: 500;
flex: 1;
}
.em-vault-type {
font-size: 12px;
color: var(--color-text-muted);
}
.em-vault-chevron {
font-size: 12px;
color: var(--color-text-muted);
flex-shrink: 0;
}
.em-vault-item-body {
padding: 0 8px 12px 36px;
}
.em-detail-body .detail-field {
padding: 8px 0;
}
/* ── Responsive ──────────────────────────────────────────────────── */
/* Mobile top bar — hidden on tablet+ */
.mobile-topbar {
display: none;
align-items: center;
gap: 12px;
padding: 0 16px;
height: 54px;
background: var(--color-sidebar-bg);
color: #fff;
flex-shrink: 0;
position: sticky;
top: 0;
z-index: 50;
}
.btn-mobile-menu {
font-size: 22px;
color: rgba(255, 255, 255, 0.8);
background: none;
border: none;
padding: 4px 6px;
cursor: pointer;
flex-shrink: 0;
}
.btn-mobile-menu:hover {
color: #fff;
}
.mobile-logo {
flex: 1;
font-size: 16px;
font-weight: 700;
color: #fff;
}
.btn-fab-mobile {
width: 36px;
height: 36px;
font-size: 20px;
flex-shrink: 0;
}
/* Sidebar backdrop */
.sidebar-backdrop {
display: none;
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 89;
}
.sidebar-backdrop.open {
display: block;
}
/* ── Phone + iPad portrait (≤ 768px) ───────────────────────────── */
@media (max-width: 768px) {
.app-layout {
flex-direction: column;
height: calc(var(--vh, 1vh) * 100);
min-height: calc(var(--vh, 1vh) * 100);
overflow: hidden;
}
.mobile-topbar {
display: flex;
}
/* Sidebar: completely out of layout flow — fixed overlay only */
.sidebar {
display: none !important;
position: fixed !important;
top: 0;
left: 0;
bottom: 0;
width: 280px !important;
height: 100% !important; /* Chrome needs explicit height on position:fixed */
z-index: 90;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
transition: none;
}
.sidebar.mobile-open {
display: flex !important;
flex-direction: column;
}
/* Cancel all collapsed-state overrides inside mobile sidebar */
.sidebar.collapsed {
display: none !important;
}
.sidebar.collapsed.mobile-open {
display: flex !important;
}
/* Mobile sidebar: always show full expanded state */
.sidebar .sidebar-label {
opacity: 1 !important;
max-width: none !important;
overflow: visible !important;
}
.sidebar .sidebar-section-header {
opacity: 1 !important;
height: auto !important;
padding: 12px 16px 4px !important;
pointer-events: auto !important;
}
.sidebar .sidebar-item {
justify-content: flex-start !important;
padding: 9px 16px !important;
overflow: hidden !important;
}
.sidebar .sidebar-item::after {
display: none !important;
}
.sidebar .sidebar-header {
justify-content: flex-start !important;
padding: 14px 12px !important;
overflow: hidden !important;
}
.sidebar .sidebar-header .logo-icon,
.sidebar .sidebar-header .logo-text {
opacity: 1 !important;
width: auto !important;
pointer-events: auto !important;
}
.btn-sidebar-toggle {
display: none !important;
}
.vault-main {
flex: 1;
overflow: hidden;
min-height: 0;
}
.vault-header {
padding: 12px 16px;
gap: 8px;
}
.vault-title {
font-size: 16px;
}
.vault-list {
padding: 8px 12px 80px;
}
.panel-body {
padding: 16px;
}
.security-dashboard {
padding: 12px;
gap: 16px;
}
.vault-toolbar {
gap: 8px;
}
.search-wrapper {
max-width: none;
}
.sort-wrapper {
display: none;
}
.vault-header .btn-fab {
display: none;
}
.form-row {
flex-direction: column;
gap: 0;
}
.modal-actions {
flex-wrap: wrap;
}
.modal-overlay {
padding: 0;
align-items: flex-end;
}
.modal {
max-width: 100% !important;
max-height: calc(var(--vh, 1vh) * 92);
border-radius: 16px 16px 0 0;
padding: 20px 16px;
}
.security-summary {
padding: 16px;
gap: 12px;
flex-wrap: wrap;
}
.sec-score {
font-size: 40px;
}
.sec-stats {
gap: 8px;
flex-wrap: wrap;
}
.sec-stat {
padding: 8px 12px;
min-width: 68px;
}
.sec-stat-num {
font-size: 22px;
}
.detail-field {
flex-direction: column;
gap: 4px;
}
.detail-label {
width: auto;
}
}
/* ── iPad landscape / small laptop (769px 1024px) ─────────────── */
@media (min-width: 769px) and (max-width: 1024px) {
.sidebar:not(.collapsed) {
width: 200px;
}
.vault-header {
padding: 14px 18px;
}
.vault-list {
padding: 10px 18px 18px;
}
.panel-body {
padding: 16px 18px;
}
.security-dashboard {
padding: 16px;
gap: 16px;
}
.search-wrapper {
max-width: 280px;
}
.security-summary {
flex-wrap: wrap;
gap: 12px;
}
.sec-stats {
flex-wrap: wrap;
gap: 10px;
}
.modal {
max-width: 460px;
}
}
/* ── Laptop (1025px 1440px) ───────────────────────────────────── */
@media (min-width: 1025px) and (max-width: 1440px) {
.vault-header {
padding: 16px 24px;
}
.vault-list {
padding: 12px 24px 24px;
}
.security-dashboard {
padding: 20px 24px;
}
}
/* ── Large PC (> 1440px) ────────────────────────────────────────── */
@media (min-width: 1441px) {
.sidebar:not(.collapsed) {
width: 260px;
}
.vault-header {
padding: 18px 40px;
}
.vault-list {
padding: 16px 40px 40px;
}
.vault-list-inner {
max-width: 1100px;
}
.vault-header-inner {
max-width: 1100px;
}
.panel-body {
padding: 24px 40px;
}
.security-dashboard {
padding: 24px 40px;
gap: 28px;
}
.search-wrapper {
max-width: 480px;
}
.modal {
max-width: 520px;
}
.modal-settings {
max-width: 580px;
}
}
/* ── Auth pages — phone ──────────────────────────────────────────── */
@media (max-width: 480px) {
.auth-container {
padding: 12px;
}
.auth-card {
padding: 28px 20px;
border-radius: 12px;
}
.auth-title {
font-size: 20px;
}
}
/* ── Settings — new sections (Phase 6) ──────────────────────────── */
.settings-section-danger {
border-top: 2px solid var(--color-danger, #e53e3e);
margin-top: 8px;
padding-top: 16px;
}
.settings-section-danger .settings-section-title {
color: var(--color-danger, #e53e3e);
}
.btn-danger {
background: var(--color-danger, #e53e3e);
color: #fff;
border: none;
border-radius: var(--radius);
padding: 8px 18px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: opacity 0.15s;
}
.btn-danger:hover {
opacity: 0.85;
}
.btn-danger:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.recovery-code-box {
display: flex;
align-items: center;
gap: 8px;
background: var(--color-bg-secondary, #f7f7f7);
border: 1px solid var(--color-border);
border-radius: var(--radius);
padding: 12px 14px;
margin: 8px 0;
}
.recovery-code-box code {
font-family: monospace;
font-size: 15px;
letter-spacing: 0.08em;
word-break: break-all;
flex: 1;
}
.warning-text {
color: var(--color-danger, #e53e3e);
font-size: 13px;
font-weight: 500;
}