From fd1dbf66f2ad613366b325a817c285c74f32aad0 Mon Sep 17 00:00:00 2001 From: Nguyen Ngo Date: Sun, 19 Apr 2026 09:56:39 -0400 Subject: [PATCH] 04/19 Continue fixing the UI issues with Chrome 2 --- app/static/css/app.css | 1660 +++++++++++++++++++++++++++++++--------- 1 file changed, 1286 insertions(+), 374 deletions(-) diff --git a/app/static/css/app.css b/app/static/css/app.css index b8b6046..4fa1786 100644 --- a/app/static/css/app.css +++ b/app/static/css/app.css @@ -20,14 +20,14 @@ --color-sidebar-hover: #2d3250; --color-sidebar-active: #d0021b; --radius: 8px; - --shadow: 0 1px 4px rgba(0, 0, 0, .08), 0 2px 12px rgba(0, 0, 0, .05); + --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-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-size: 14px; color: var(--color-text); background: var(--color-bg); @@ -165,7 +165,7 @@ ul { .form-group textarea:focus { outline: none; border-color: var(--color-primary); - box-shadow: 0 0 0 3px rgba(208, 2, 27, .12); + box-shadow: 0 0 0 3px rgba(208, 2, 27, 0.12); } /* Prevent iOS viewport auto-zoom on input focus (requires font-size >= 16px) */ @@ -195,7 +195,7 @@ ul { border: none; cursor: pointer; font-size: 16px; - opacity: .6; + opacity: 0.6; transition: opacity var(--transition); } @@ -231,7 +231,7 @@ ul { } .btn-primary:disabled { - opacity: .6; + opacity: 0.6; cursor: not-allowed; } @@ -300,8 +300,8 @@ ul { } #gen-output { - letter-spacing: .5px; - font-family: 'Courier New', monospace; + letter-spacing: 0.5px; + font-family: "Courier New", monospace; } /* Launch (open URL) button — distinct colour so it reads as navigation */ @@ -355,17 +355,34 @@ ul { } /* ── Sidebar ─────────────────────────────────────────────────────── */ - -/* ── Base sidebar styles (shared by mobile and desktop) ─────────── */ .sidebar { + width: 240px; + flex-shrink: 0; background: var(--color-sidebar-bg); color: var(--color-sidebar-text); display: flex; flex-direction: column; - /* Default = desktop. html.is-mobile overrides display:none below. */ - width: 240px; - flex-shrink: 0; overflow: hidden; + /* No transition here — added back in the >768px media query so it + never interferes with display:none on mobile in Chrome */ +} + +.sidebar.collapsed { + width: 72px; +} + +/* Sidebar width transition only on non-mobile — prevents Chrome from + deferring display:none while a transition is active */ +@media (min-width: 769px) { + .sidebar { + transition: width 0.22s ease; + } +} + +/* Sidebar must not clip its children when collapsed — tooltips need to escape */ +.sidebar.collapsed .sidebar-nav, +.sidebar.collapsed .sidebar-footer { + overflow: visible; } .sidebar-header { @@ -373,14 +390,23 @@ ul { align-items: center; gap: 8px; padding: 14px 12px; - border-bottom: 1px solid rgba(255, 255, 255, .08); + 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 { @@ -390,6 +416,42 @@ ul { 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 { @@ -403,10 +465,18 @@ ul { padding: 12px 16px 4px; font-size: 11px; text-transform: uppercase; - letter-spacing: .08em; - color: rgba(255, 255, 255, .35); + 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 { @@ -414,6 +484,7 @@ ul { align-items: center; gap: 10px; padding: 9px 16px; + border-radius: 0; color: var(--color-sidebar-text); cursor: pointer; transition: background var(--transition); @@ -441,110 +512,28 @@ ul { text-align: center; } +/* Labels — fade out when collapsed; use max-width so icon stays visible */ .sidebar-label { - white-space: nowrap; - overflow: hidden; -} - -.sidebar-footer { - padding: 12px 0; - border-top: 1px solid rgba(255, 255, 255, .08); -} - -/* ── DESKTOP sidebar (html.is-desktop) ───────────────────────────── */ -html.is-desktop .sidebar { - width: 240px; - flex-shrink: 0; - overflow: hidden; - /* Transition only on desktop so display:none on mobile is instant */ - transition: width .22s ease; -} - -/* Set by layout-init.js before paint so collapsed sidebar renders at right width immediately */ -html.is-desktop.sidebar-will-collapse .sidebar, -html.is-desktop .sidebar.collapsed { - width: 72px; -} - -html.is-desktop .sidebar.collapsed .sidebar-nav, -html.is-desktop .sidebar.collapsed .sidebar-footer { - overflow: visible; -} - -html.is-desktop .sidebar.collapsed .sidebar-header { - justify-content: center; - padding: 14px 0; - overflow: visible; -} - -html.is-desktop .sidebar-header .logo-icon { - transition: opacity .15s ease; -} - -html.is-desktop .sidebar-header .logo-text { - flex: 1; - transition: opacity .15s ease; -} - -html.is-desktop .sidebar.collapsed .sidebar-header .logo-icon, -html.is-desktop .sidebar.collapsed .sidebar-header .logo-text { - opacity: 0; - width: 0; - pointer-events: none; -} - -html.is-desktop .btn-sidebar-toggle { - background: none; - border: none; - color: rgba(255, 255, 255, .5); - font-size: 14px; - cursor: pointer; - padding: 6px 8px; - border-radius: 4px; - line-height: 1; - flex-shrink: 0; - transition: color var(--transition), transform .22s ease; - margin-left: auto; -} - -html.is-desktop .btn-sidebar-toggle:hover { - color: #fff; - background: rgba(255, 255, 255, .12); -} - -html.is-desktop .sidebar.collapsed .btn-sidebar-toggle { - transform: rotate(180deg); - margin-left: 0; -} - -html.is-desktop .sidebar-section-header { - transition: opacity .15s ease; -} - -html.is-desktop .sidebar.collapsed .sidebar-section-header { - opacity: 0; - pointer-events: none; - height: 0; - padding: 0; -} - -html.is-desktop .sidebar-label { - transition: opacity .15s ease, max-width .22s ease; + transition: + opacity 0.15s ease, + max-width 0.22s ease; max-width: 200px; + overflow: hidden; } -html.is-desktop .sidebar.collapsed .sidebar-label { +.sidebar.collapsed .sidebar-label { opacity: 0; max-width: 0; } -html.is-desktop .sidebar.collapsed .sidebar-item { +.sidebar.collapsed .sidebar-item { justify-content: center; padding: 10px 0; overflow: visible; } -html.is-desktop .sidebar.collapsed .sidebar-item::after { +/* Tooltip — appears to the right of the 72px rail */ +.sidebar.collapsed .sidebar-item::after { content: attr(data-tooltip); position: fixed; left: 80px; @@ -556,74 +545,1016 @@ html.is-desktop .sidebar.collapsed .sidebar-item::after { white-space: nowrap; pointer-events: none; opacity: 0; - transition: opacity .12s ease; + transition: opacity 0.12s ease; z-index: 1000; - box-shadow: 0 2px 8px rgba(0, 0, 0, .4); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4); } -html.is-desktop .sidebar.collapsed .sidebar-item:hover::after { +.sidebar.collapsed .sidebar-item:hover::after { opacity: 1; } -/* ── MOBILE sidebar (html.is-mobile) ─────────────────────────────── */ -html.is-mobile .sidebar { - /* Hidden by default — no layout space, no transitions to fight */ - display: none; - position: fixed; - top: 0; - left: 0; - width: 280px; - height: 100%; - z-index: 90; - overflow-y: auto; - -webkit-overflow-scrolling: touch; - /* No width/opacity transitions on mobile */ +.sidebar-footer { + padding: 12px 0; + border-top: 1px solid rgba(255, 255, 255, 0.08); } -html.is-mobile .sidebar.mobile-open { +.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; } -/* Mobile sidebar always shows full labels regardless of collapsed state */ -html.is-mobile .sidebar .sidebar-label { - opacity: 1; - max-width: none; +.detail-body { + flex: 1; + overflow-y: auto; + padding: 4px 0; } -html.is-mobile .sidebar .sidebar-section-header { - opacity: 1; - height: auto; - padding: 12px 16px 4px; - pointer-events: auto; +.detail-field { + display: flex; + align-items: flex-start; + gap: 12px; + padding: 10px 0; + border-bottom: 1px solid var(--color-border); } -html.is-mobile .sidebar .sidebar-item { - justify-content: flex-start; - padding: 9px 16px; +.detail-field:last-child { + border-bottom: none; } -html.is-mobile .sidebar .sidebar-header { - justify-content: flex-start; - padding: 14px 12px; +.detail-label { + font-size: 12px; + color: var(--color-text-muted); + width: 140px; + flex-shrink: 0; + padding-top: 4px; } -html.is-mobile .sidebar .sidebar-header .logo-icon, -html.is-mobile .sidebar .sidebar-header .logo-text { - opacity: 1; - width: auto; - pointer-events: auto; +.detail-val-row { + display: flex; + align-items: center; + gap: 6px; + flex: 1; + flex-wrap: wrap; } -html.is-mobile .sidebar .sidebar-item::after { - display: none; +.detail-val { + font-size: 14px; + word-break: break-all; } -html.is-mobile .btn-sidebar-toggle { - display: none; +.detail-sensitive { + display: inline-flex; + align-items: center; + font-family: monospace; + font-size: 14px; } -/* ── Mobile top bar — only on html.is-mobile ─────────────────────── */ +.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; @@ -638,13 +1569,9 @@ html.is-mobile .btn-sidebar-toggle { z-index: 50; } -html.is-mobile .mobile-topbar { - display: flex; -} - .btn-mobile-menu { font-size: 22px; - color: rgba(255, 255, 255, .8); + color: rgba(255, 255, 255, 0.8); background: none; border: none; padding: 4px 6px; @@ -675,7 +1602,7 @@ html.is-mobile .mobile-topbar { display: none; position: fixed; inset: 0; - background: rgba(0, 0, 0, .5); + background: rgba(0, 0, 0, 0.5); z-index: 89; } @@ -683,116 +1610,192 @@ html.is-mobile .mobile-topbar { display: block; } -/* ── App layout ──────────────────────────────────────────────────── */ -html.is-desktop .app-layout { - display: flex; - height: 100vh; - height: calc(var(--vh, 1vh) * 100); +/* ── Phone + iPad portrait (≤ 768px) ───────────────────────────── */ +@media (max-width: 768px) { + .app-layout { + flex-direction: column; + height: 100vh; + 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; + } } -html.is-mobile .app-layout { - display: flex; - flex-direction: column; - height: 100vh; - height: -webkit-fill-available; - height: calc(var(--vh, 1vh) * 100); - overflow: hidden; -} - -/* ── Folder items ────────────────────────────────────────────────── */ -.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, .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, .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, .2); - background: rgba(255, 255, 255, .1); - color: #fff; - font-size: 13px; -} - -.new-folder-row input::placeholder { - color: rgba(255, 255, 255, .4); -} - -.new-folder-row input:focus { - outline: none; - border-color: rgba(255, 255, 255, .5); -} - -.new-folder-row .btn-icon { - color: rgba(255, 255, 255, .7); - font-size: 14px; -} - -.new-folder-row .btn-icon:hover { - color: #fff; - background: rgba(255, 255, 255, .1); -} - -/* ── Breakpoint-driven padding adjustments ───────────────────────── */ -/* Tablet (769–1024px) */ +/* ── iPad landscape / small laptop (769px – 1024px) ─────────────── */ @media (min-width: 769px) and (max-width: 1024px) { - html.is-desktop .sidebar:not(.collapsed) { + .sidebar:not(.collapsed) { width: 200px; } @@ -832,9 +1835,24 @@ html.is-mobile .app-layout { } } -/* Large PC (> 1440px) */ +/* ── 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) { - html.is-desktop .sidebar:not(.collapsed) { + .sidebar:not(.collapsed) { width: 260px; } @@ -876,106 +1894,7 @@ html.is-mobile .app-layout { } } -/* Mobile padding and layout overrides */ -html.is-mobile .vault-main { - flex: 1; - overflow: hidden; - min-height: 0; -} - -html.is-mobile .vault-header { - padding: 12px 16px; - gap: 8px; -} - -html.is-mobile .vault-title { - font-size: 16px; -} - -html.is-mobile .vault-list { - padding: 8px 12px 80px; -} - -html.is-mobile .panel-body { - padding: 16px; -} - -html.is-mobile .security-dashboard { - padding: 12px; - gap: 16px; -} - -html.is-mobile .vault-toolbar { - gap: 8px; -} - -html.is-mobile .search-wrapper { - max-width: none; -} - -html.is-mobile .sort-wrapper { - display: none; -} - -html.is-mobile .vault-header .btn-fab { - display: none; -} - -html.is-mobile .form-row { - flex-direction: column; - gap: 0; -} - -html.is-mobile .modal-actions { - flex-wrap: wrap; -} - -html.is-mobile .modal-overlay { - padding: 0; - align-items: flex-end; -} - -html.is-mobile .modal { - max-width: 100%; - max-height: calc(var(--vh, 1vh) * 92); - border-radius: 16px 16px 0 0; - padding: 20px 16px; -} - -html.is-mobile .security-summary { - padding: 16px; - gap: 12px; - flex-wrap: wrap; -} - -html.is-mobile .sec-score { - font-size: 40px; -} - -html.is-mobile .sec-stats { - gap: 8px; - flex-wrap: wrap; -} - -html.is-mobile .sec-stat { - padding: 8px 12px; - min-width: 68px; -} - -html.is-mobile .sec-stat-num { - font-size: 22px; -} - -html.is-mobile .detail-field { - flex-direction: column; - gap: 4px; -} - -html.is-mobile .detail-label { - width: auto; -} - -/* Auth page — phone */ +/* ── Auth pages — phone ──────────────────────────────────────────── */ @media (max-width: 480px) { .auth-container { padding: 12px; @@ -991,13 +1910,6 @@ html.is-mobile .detail-label { } } -/* iOS input font-size — prevent auto-zoom on focus */ -html.is-mobile .form-group input, -html.is-mobile .form-group select, -html.is-mobile .form-group textarea { - font-size: 16px; -} - /* ── Settings — new sections (Phase 6) ──────────────────────────── */ .settings-section-danger { border-top: 2px solid var(--color-danger, #e53e3e); @@ -1018,15 +1930,15 @@ html.is-mobile .form-group textarea { font-size: 14px; font-weight: 500; cursor: pointer; - transition: opacity .15s; + transition: opacity 0.15s; } .btn-danger:hover { - opacity: .85; + opacity: 0.85; } .btn-danger:disabled { - opacity: .5; + opacity: 0.5; cursor: not-allowed; } @@ -1044,7 +1956,7 @@ html.is-mobile .form-group textarea { .recovery-code-box code { font-family: monospace; font-size: 15px; - letter-spacing: .08em; + letter-spacing: 0.08em; word-break: break-all; flex: 1; }