Files
PassKeeper/app/templates/vault/index.html
T
2026-04-26 15:29:28 -04:00

1055 lines
35 KiB
HTML
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.
{% extends "base.html" %} {% block title %}My Vault — PassKeeper{% endblock %}
{% block body_class %}vault-page{% endblock %} {% block body %}
<div class="app-layout">
<!-- ── Mobile top bar (phones only) ────────────────────────────── -->
<div class="mobile-topbar" id="mobile-topbar">
<button class="btn-mobile-menu" id="btn-mobile-menu" aria-label="Open menu">
</button>
<span class="mobile-logo">🔒 PassKeeper</span>
<button
class="btn-fab btn-fab-mobile"
id="btn-add-item-mobile"
title="Add item"
>
+
</button>
</div>
<!-- ── Sidebar backdrop (mobile) ───────────────────────────────── -->
<div class="sidebar-backdrop" id="sidebar-backdrop"></div>
<!-- ── Sidebar ─────────────────────────────────────────────────── -->
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
<span class="logo-icon">🔒</span>
<span class="logo-text">PassKeeper</span>
<button
class="btn-sidebar-toggle"
id="btn-sidebar-toggle"
aria-label="Collapse sidebar"
title="Collapse sidebar"
>
&#x276E;
</button>
</div>
<nav class="sidebar-nav">
<ul>
<li
class="sidebar-item active"
id="sidebar-all"
data-view="vault"
data-tooltip="All Items"
>
<span class="sidebar-icon">🏠</span>
<span class="sidebar-label">All Items</span>
</li>
<li class="sidebar-section-header">Item Types</li>
<li
class="sidebar-item"
data-type-filter="password"
data-tooltip="Passwords"
>
<span class="sidebar-icon">🔑</span>
<span class="sidebar-label">Passwords</span>
</li>
<li
class="sidebar-item"
data-type-filter="note"
data-tooltip="Secure Notes"
>
<span class="sidebar-icon">📝</span>
<span class="sidebar-label">Secure Notes</span>
</li>
<li
class="sidebar-item"
data-type-filter="card"
data-tooltip="Payment Cards"
>
<span class="sidebar-icon">💳</span>
<span class="sidebar-label">Payment Cards</span>
</li>
<li
class="sidebar-item"
data-type-filter="bank"
data-tooltip="Bank Accounts"
>
<span class="sidebar-icon">🏦</span>
<span class="sidebar-label">Bank Accounts</span>
</li>
<li
class="sidebar-item"
data-type-filter="address"
data-tooltip="Addresses"
>
<span class="sidebar-icon">🏠</span>
<span class="sidebar-label">Addresses</span>
</li>
<li
class="sidebar-item"
data-type-filter="ssn"
data-tooltip="Identities"
>
<span class="sidebar-icon">🪪</span>
<span class="sidebar-label">Identities</span>
</li>
<li class="sidebar-section-header">Tools</li>
<li
class="sidebar-item"
id="sidebar-security"
data-view="security"
data-tooltip="Security"
>
<span class="sidebar-icon">🛡️</span>
<span class="sidebar-label">Security</span>
</li>
<li
class="sidebar-item"
id="sidebar-sharing"
data-view="sharing"
data-tooltip="Sharing"
>
<span class="sidebar-icon">🔗</span>
<span class="sidebar-label">Sharing</span>
</li>
<li
class="sidebar-item"
id="sidebar-emergency"
data-view="emergency"
data-tooltip="Emergency Access"
>
<span class="sidebar-icon">🚨</span>
<span class="sidebar-label">Emergency Access</span>
</li>
<li
class="sidebar-item"
id="sidebar-import-export"
data-view="import-export"
data-tooltip="Import / Export"
>
<span class="sidebar-icon">📤</span>
<span class="sidebar-label">Import / Export</span>
</li>
<li
class="sidebar-item"
id="sidebar-generator"
data-tooltip="Password Generator"
>
<span class="sidebar-icon"></span>
<span class="sidebar-label">Password Generator</span>
</li>
<li class="sidebar-section-header">Tags</li>
<ul id="sidebar-tags" class="sidebar-tag-list"></ul>
<li class="sidebar-section-header">
Folders
<button class="btn-new-folder" id="btn-new-folder" title="New folder">
+
</button>
</li>
<li id="new-folder-row" class="new-folder-row hidden">
<form id="new-folder-form">
<input
type="text"
id="new-folder-input"
placeholder="Folder name"
maxlength="128"
/>
<button type="submit" class="btn-icon" title="Save"></button>
<button
type="button"
class="btn-icon"
id="btn-cancel-folder"
title="Cancel"
>
</button>
</form>
</li>
<ul id="sidebar-folders"></ul>
</ul>
</nav>
<div class="sidebar-footer">
<button
class="sidebar-item btn-text"
id="btn-settings"
data-tooltip="Settings"
>
<span class="sidebar-icon">⚙️</span>
<span class="sidebar-label">Settings</span>
</button>
<button
class="sidebar-item btn-text"
id="btn-logout"
data-tooltip="Sign out"
>
<span class="sidebar-icon">🚪</span>
<span class="sidebar-label">Sign out</span>
</button>
</div>
</aside>
<!-- ── Main ───────────────────────────────────────────────────── -->
<main class="vault-main">
<!-- Vault view -->
<div id="view-vault">
<header class="vault-header">
<div class="vault-header-inner">
<h2 class="vault-title" id="vault-title">All Items</h2>
<div class="vault-toolbar">
<div class="search-wrapper">
<span class="search-icon">🔍</span>
<input
type="search"
id="search-input"
placeholder="Search vault…"
autocomplete="off"
/>
</div>
<div class="sort-wrapper">
<select id="sort-select" title="Sort by">
<option value="name-asc">Name AZ</option>
<option value="name-desc">Name ZA</option>
<option value="date-desc">Newest first</option>
<option value="date-asc">Oldest first</option>
<option value="folder">By folder</option>
</select>
</div>
<button class="btn-fab" id="btn-add-item" title="Add item">
+
</button>
</div>
</div>
</header>
<div id="vault-spinner" class="spinner-overlay hidden">
<div class="spinner"></div>
</div>
<div class="vault-list">
<div class="vault-list-inner">
<ul id="vault-list"></ul>
</div>
</div>
</div>
<!-- Security dashboard view -->
<div id="view-security" class="hidden">
<header class="vault-header">
<h2 class="vault-title">Security Dashboard</h2>
</header>
<div class="security-dashboard">
<div class="security-summary" id="security-summary"></div>
<div class="security-sections" id="security-sections"></div>
</div>
</div>
<!-- Sharing view -->
<div id="view-sharing" class="hidden">
<header class="vault-header">
<h2 class="vault-title">Sharing</h2>
<div class="vault-toolbar">
<button class="btn-primary btn-sm" id="btn-share-item">
+ Share an item
</button>
</div>
</header>
<div class="panel-body">
<div id="sharing-keys-notice" class="notice-info hidden">
You need to set up sharing keys before you can share items.
<button class="btn-primary btn-sm" id="btn-setup-keys-from-sharing">
Set up keys
</button>
</div>
<div class="panel-tabs">
<button class="tab-btn active" data-tab="shared-out">
Shared by me
</button>
<button class="tab-btn" data-tab="shared-in">Shared with me</button>
</div>
<div id="tab-shared-out" class="tab-pane">
<ul id="shared-out-list" class="share-list"></ul>
</div>
<div id="tab-shared-in" class="tab-pane hidden">
<ul id="shared-in-list" class="share-list"></ul>
</div>
</div>
</div>
<!-- Import / Export view -->
<div id="view-import-export" class="hidden">
<header class="vault-header">
<h2 class="vault-title">Import / Export</h2>
</header>
<div class="panel-body">
<!-- Export -->
<section class="import-export-section">
<h3 class="import-export-heading">Export Vault</h3>
<p class="import-export-desc">
Download an encrypted backup of your entire vault. The file contains
AES-256-GCM ciphertext — your master password is required to read
it. Keep it safe.
</p>
<div class="import-export-row">
<button class="btn-primary" id="btn-export-json">
Download encrypted JSON
</button>
<button class="btn-secondary" id="btn-export-csv">
Download CSV (plaintext — handle with care)
</button>
</div>
</section>
<!-- Import -->
<section class="import-export-section">
<h3 class="import-export-heading">Import</h3>
<p class="import-export-desc">
Import from a PassKeeper encrypted JSON export, or from a CSV file
exported by Chrome, Bitwarden, or 1Password. Duplicates are not
checked — review your vault after importing.
</p>
<div class="import-export-row">
<label
class="btn-secondary import-file-label"
for="import-file-input"
>
Choose file&hellip;
</label>
<input
type="file"
id="import-file-input"
accept=".json,.csv"
class="hidden"
/>
<span id="import-file-name" class="import-file-name"
>No file chosen</span
>
</div>
<div id="import-preview" class="import-preview hidden"></div>
<div class="import-export-row">
<button class="btn-primary" id="btn-import-confirm" disabled>
Import items
</button>
</div>
<div id="import-result" class="import-result hidden"></div>
</section>
</div>
</div>
<!-- Emergency Access view -->
<div id="view-emergency" class="hidden">
<header class="vault-header">
<h2 class="vault-title">Emergency Access</h2>
<div class="vault-toolbar">
<button class="btn-primary btn-sm" id="btn-add-emergency">
+ Add trusted contact
</button>
</div>
</header>
<div class="panel-body">
<div class="panel-tabs">
<button class="tab-btn active" data-tab="em-grants">
My trusted contacts
</button>
<button class="tab-btn" data-tab="em-access">
I'm a trusted contact
</button>
</div>
<div id="tab-em-grants" class="tab-pane">
<ul id="em-grants-list" class="share-list"></ul>
</div>
<div id="tab-em-access" class="tab-pane hidden">
<ul id="em-access-list" class="share-list"></ul>
<div id="em-vault-panel" class="em-vault-panel hidden">
<div class="em-vault-header">
<h4>Emergency Vault — Decrypted Items</h4>
<button class="btn-secondary btn-sm" id="btn-em-vault-back">
← Back
</button>
</div>
<ul id="em-vault-list" class="em-vault-list"></ul>
</div>
</div>
</div>
</div>
</main>
</div>
<!-- ── Unlock overlay ──────────────────────────────────────────────── -->
<div
id="unlock-overlay"
class="modal-overlay"
role="dialog"
aria-modal="true"
aria-labelledby="unlock-title"
>
<div class="modal modal-unlock">
<div class="auth-logo unlock-logo">
<span class="logo-icon">🔒</span><span class="logo-text">PassKeeper</span>
</div>
<h3 id="unlock-title" class="unlock-title">Unlock your vault</h3>
<p class="unlock-subtitle">Re-enter your master password to continue.</p>
<p id="unlock-error" class="form-error hidden">
Incorrect master password.
</p>
<form id="unlock-form" novalidate>
<div class="form-group">
<label for="unlock-password">Master password</label>
<input
type="password"
id="unlock-password"
autocomplete="current-password"
placeholder="Enter master password"
/>
</div>
<div class="modal-actions">
<a href="/login" class="btn-secondary btn-link">Sign out</a>
<button type="submit" class="btn-primary">Unlock</button>
</div>
</form>
</div>
</div>
<!-- ── Add / Edit Item Modal ─────────────────────────────────────────── -->
<div
id="item-modal"
class="modal-overlay"
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
>
<div class="modal modal-item">
<div class="modal-header">
<h3 id="modal-title">Add Item</h3>
<button
class="btn-icon btn-close"
id="btn-close-modal"
aria-label="Close"
>
</button>
</div>
<form id="item-form" novalidate>
<div class="form-group" id="type-selector-group">
<label for="field-type">Item Type</label>
<select id="field-type" name="item_type">
<option value="password">🔑 Password</option>
<option value="note">📝 Secure Note</option>
<option value="card">💳 Payment Card</option>
<option value="bank">🏦 Bank Account</option>
<option value="address">🏠 Address</option>
<option value="ssn">🪪 Identity (SSN)</option>
</select>
</div>
<div class="form-group">
<label for="field-name">Name <span class="required">*</span></label>
<input
type="text"
id="field-name"
name="name"
required
placeholder="e.g. Gmail"
/>
</div>
<div class="type-fields" data-for-types="password">
<div class="form-group">
<label for="field-url">Website URL</label
><input type="url" id="field-url" placeholder="https://example.com" />
</div>
<div class="form-group">
<label for="field-username">Username / Email</label
><input
type="text"
id="field-username"
autocomplete="off"
placeholder="username or email"
/>
</div>
<div class="form-group">
<label for="field-password">Password</label>
<div class="input-with-toggle">
<input
type="password"
id="field-password"
autocomplete="new-password"
placeholder="Enter password"
/>
<button
type="button"
class="btn-show-pass"
id="btn-toggle-pass"
aria-label="Toggle"
>
👁
</button>
</div>
</div>
<div class="form-group">
<label for="field-totp-uri"
>Authenticator Key (TOTP)
<span class="field-label-optional">optional</span></label
>
<input
type="text"
id="field-totp-uri"
autocomplete="off"
placeholder="otpauth://totp/… or plain base32 secret"
/>
<p class="field-hint">
Paste the otpauth URI from a QR code scanner, or the plain base32
secret key. PassKeeper will generate your 2FA codes.
</p>
</div>
</div>
<div class="type-fields hidden" data-for-types="note">
<div class="form-group">
<label for="field-note-body">Note</label
><textarea
id="field-note-body"
rows="6"
placeholder="Enter your secure note…"
></textarea>
</div>
</div>
<div class="type-fields hidden" data-for-types="card">
<div class="form-group">
<label for="field-cardholder">Cardholder Name</label
><input
type="text"
id="field-cardholder"
placeholder="Name on card"
/>
</div>
<div class="form-group">
<label for="field-card-number">Card Number</label
><input
type="text"
id="field-card-number"
autocomplete="off"
placeholder="•••• •••• •••• ••••"
maxlength="19"
/>
</div>
<div class="form-row">
<div class="form-group">
<label for="field-expiry-month">Expiry Month</label>
<select id="field-expiry-month">
<option value="">MM</option>
<option value="01">01</option>
<option value="02">02</option>
<option value="03">03</option>
<option value="04">04</option>
<option value="05">05</option>
<option value="06">06</option>
<option value="07">07</option>
<option value="08">08</option>
<option value="09">09</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
</select>
</div>
<div class="form-group">
<label for="field-expiry-year">Year</label
><input
type="text"
id="field-expiry-year"
placeholder="YYYY"
maxlength="4"
/>
</div>
<div class="form-group">
<label for="field-cvv">CVV</label
><input
type="text"
id="field-cvv"
autocomplete="off"
placeholder="•••"
maxlength="4"
/>
</div>
</div>
</div>
<div class="type-fields hidden" data-for-types="bank">
<div class="form-group">
<label for="field-bank-name">Bank Name</label
><input type="text" id="field-bank-name" placeholder="e.g. Chase" />
</div>
<div class="form-group">
<label for="field-account-type">Account Type</label>
<select id="field-account-type">
<option value="">— Select —</option>
<option value="checking">Checking</option>
<option value="savings">Savings</option>
<option value="money_market">Money Market</option>
<option value="other">Other</option>
</select>
</div>
<div class="form-group">
<label for="field-routing">Routing Number</label
><input
type="text"
id="field-routing"
autocomplete="off"
placeholder="9-digit routing number"
maxlength="9"
/>
</div>
<div class="form-group">
<label for="field-account-number">Account Number</label
><input
type="text"
id="field-account-number"
autocomplete="off"
placeholder="Account number"
/>
</div>
</div>
<div class="type-fields hidden" data-for-types="address">
<div class="form-row">
<div class="form-group">
<label for="field-first-name">First Name</label
><input
type="text"
id="field-first-name"
placeholder="First name"
/>
</div>
<div class="form-group">
<label for="field-last-name">Last Name</label
><input type="text" id="field-last-name" placeholder="Last name" />
</div>
</div>
<div class="form-group">
<label for="field-company">Company</label
><input
type="text"
id="field-company"
placeholder="Company (optional)"
/>
</div>
<div class="form-group">
<label for="field-address-line">Street Address</label
><input
type="text"
id="field-address-line"
placeholder="123 Main St"
/>
</div>
<div class="form-row">
<div class="form-group">
<label for="field-city">City</label
><input type="text" id="field-city" placeholder="City" />
</div>
<div class="form-group">
<label for="field-state">State</label
><input type="text" id="field-state" placeholder="State" />
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="field-zip">ZIP</label
><input type="text" id="field-zip" placeholder="ZIP" />
</div>
<div class="form-group">
<label for="field-country">Country</label
><input type="text" id="field-country" placeholder="Country" />
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="field-phone">Phone</label
><input type="tel" id="field-phone" placeholder="+1 555-000-0000" />
</div>
<div class="form-group">
<label for="field-email">Email</label
><input
type="email"
id="field-email"
placeholder="email@example.com"
/>
</div>
</div>
</div>
<div class="type-fields hidden" data-for-types="ssn">
<div class="form-group">
<label for="field-ssn-number">Social Security Number</label>
<div class="input-with-toggle">
<input
type="password"
id="field-ssn-number"
autocomplete="off"
placeholder="•••-••-••••"
maxlength="11"
/>
<button
type="button"
class="btn-show-pass"
id="btn-toggle-ssn"
aria-label="Toggle"
>
👁
</button>
</div>
</div>
</div>
<div class="form-group">
<label for="field-folder">Folder</label>
<select id="field-folder">
<option value="">— No folder —</option>
</select>
</div>
<div
class="type-fields"
data-for-types="password note card bank address ssn"
>
<div class="form-group">
<label for="field-tags">Tags</label>
<input
type="text"
id="field-tags"
placeholder="e.g. work, finance, personal (comma-separated)"
autocomplete="off"
/>
<div id="field-tags-preview" class="tag-preview"></div>
</div>
</div>
<div class="type-fields" data-for-types="password card bank address ssn">
<div class="form-group">
<label for="field-notes">Notes</label
><textarea
id="field-notes"
rows="3"
placeholder="Optional notes…"
></textarea>
</div>
</div>
<div class="modal-actions">
<button type="button" class="btn-secondary" id="btn-cancel-modal">
Cancel
</button>
<button type="submit" class="btn-primary">Save</button>
</div>
</form>
</div>
</div>
<!-- ── Account Settings Modal ────────────────────────────────────────── -->
<div id="settings-modal" class="modal-overlay" role="dialog" aria-modal="true">
<div class="modal modal-settings">
<div class="modal-header">
<h3>Account Settings</h3>
<button
class="btn-icon btn-close"
id="btn-close-settings"
aria-label="Close"
>
</button>
</div>
<!-- MFA Section -->
<div class="settings-section">
<h4 class="settings-section-title">🔐 Two-Factor Authentication</h4>
<div id="mfa-status-area">
<p id="mfa-status-text" class="settings-desc"></p>
<div id="mfa-setup-area" class="hidden">
<img id="mfa-qr-img" src="" alt="QR Code" class="mfa-qr" />
<p class="settings-desc">
Scan with Google Authenticator or Authy, then enter the 6-digit code
below.
</p>
<p class="settings-desc mfa-secret-text">
Manual key: <code id="mfa-secret-display"></code>
</p>
<div class="form-group">
<label for="mfa-verify-code">Verification code</label>
<input
type="text"
id="mfa-verify-code"
inputmode="numeric"
maxlength="6"
placeholder="000000"
/>
</div>
<button class="btn-primary" id="btn-mfa-confirm">Enable MFA</button>
<button class="btn-secondary" id="btn-mfa-cancel-setup">
Cancel
</button>
</div>
<div id="mfa-disable-area" class="hidden">
<div class="form-group">
<label for="mfa-disable-code"
>Enter your current code to disable MFA</label
>
<input
type="text"
id="mfa-disable-code"
inputmode="numeric"
maxlength="6"
placeholder="000000"
/>
</div>
<button class="btn-primary" id="btn-mfa-disable-confirm">
Disable MFA
</button>
<button class="btn-secondary" id="btn-mfa-disable-cancel">
Cancel
</button>
</div>
<div id="mfa-actions"></div>
</div>
</div>
<!-- Sharing Keys Section -->
<div class="settings-section">
<h4 class="settings-section-title">
🔗 Sharing &amp; Emergency Access Keys
</h4>
<p id="sharing-keys-status" class="settings-desc"></p>
<div id="sharing-keys-actions"></div>
</div>
<!-- Change Password Section -->
<div class="settings-section">
<h4 class="settings-section-title">🔑 Change Master Password</h4>
<p class="settings-desc">
Your vault will be automatically re-encrypted with the new password.
</p>
<div id="change-password-area">
<div class="form-group">
<label for="cp-current">Current master password</label>
<input
type="password"
id="cp-current"
autocomplete="current-password"
placeholder="Current password"
/>
</div>
<div class="form-group">
<label for="cp-new">New master password</label>
<input
type="password"
id="cp-new"
autocomplete="new-password"
placeholder="Minimum 12 characters"
/>
</div>
<div class="form-group">
<label for="cp-confirm">Confirm new password</label>
<input
type="password"
id="cp-confirm"
autocomplete="new-password"
placeholder="Repeat new password"
/>
</div>
<p id="cp-error" class="form-error hidden"></p>
<button class="btn-primary" id="btn-change-password">
Change Password
</button>
</div>
</div>
<!-- Recovery Code Section -->
<div class="settings-section">
<h4 class="settings-section-title">🆘 Account Recovery</h4>
<p class="settings-desc">
A recovery code lets you regain access if you forget your master
password. Store it somewhere safe — it is shown only once and never
stored on our servers.
</p>
<p id="recovery-status-text" class="settings-desc"></p>
<div id="recovery-code-display" class="hidden">
<div class="recovery-code-box">
<code id="recovery-code-value"></code>
<button
class="btn-icon"
id="btn-copy-recovery-code"
title="Copy to clipboard"
>
📋
</button>
</div>
<p class="settings-desc warning-text">
⚠️ Copy this code now. It will not be shown again.
</p>
<button class="btn-secondary" id="btn-recovery-done">
I've saved my recovery code
</button>
</div>
<div id="recovery-actions"></div>
</div>
<!-- Danger Zone -->
<div class="settings-section">
<h4 class="settings-section-title">⏱️ Auto-Lock</h4>
<p class="settings-desc">
Automatically lock the vault after a period of inactivity.
</p>
<div class="form-group">
<label for="web-idle-select">Lock after</label>
<select id="web-idle-select" class="form-control">
<option value="0">Never</option>
<option value="5">5 minutes</option>
<option value="10">10 minutes</option>
<option value="15" selected>15 minutes</option>
<option value="30">30 minutes</option>
<option value="60">1 hour</option>
</select>
</div>
</div>
<div class="settings-section settings-section-danger">
<h4 class="settings-section-title">⚠️ Danger Zone</h4>
<p class="settings-desc">
Permanently delete your account and all vault data. This cannot be
undone.
</p>
<div id="delete-account-area">
<div id="delete-confirm-area" class="hidden">
<div class="form-group">
<label for="delete-password"
>Enter your master password to confirm</label
>
<input
type="password"
id="delete-password"
autocomplete="current-password"
placeholder="Master password"
/>
</div>
<p id="delete-error" class="form-error hidden"></p>
<div class="modal-actions">
<button class="btn-secondary" id="btn-delete-cancel">Cancel</button>
<button class="btn-danger" id="btn-delete-confirm">
Permanently Delete Account
</button>
</div>
</div>
<button class="btn-danger" id="btn-delete-account">
Delete My Account
</button>
</div>
</div>
</div>
</div>
<!-- ── Share Item Modal ───────────────────────────────────────────────── -->
<div id="share-modal" class="modal-overlay" role="dialog" aria-modal="true">
<div class="modal">
<div class="modal-header">
<h3>Share an Item</h3>
<button
class="btn-icon btn-close"
id="btn-close-share-modal"
aria-label="Close"
>
</button>
</div>
<form id="share-form" novalidate>
<p id="share-error" class="form-error hidden"></p>
<div class="form-group">
<label for="share-item-select">Item to share</label>
<select id="share-item-select"></select>
</div>
<div class="form-group">
<label for="share-recipient-email">Recipient's email</label>
<input
type="email"
id="share-recipient-email"
placeholder="recipient@example.com"
/>
</div>
<div class="modal-actions">
<button type="button" class="btn-secondary" id="btn-cancel-share">
Cancel
</button>
<button type="submit" class="btn-primary">Share</button>
</div>
</form>
</div>
</div>
<!-- ── Emergency Access Setup Modal ──────────────────────────────────── -->
<div id="emergency-modal" class="modal-overlay" role="dialog" aria-modal="true">
<div class="modal">
<div class="modal-header">
<h3>Add Emergency Contact</h3>
<button
class="btn-icon btn-close"
id="btn-close-emergency-modal"
aria-label="Close"
>
</button>
</div>
<form id="emergency-form" novalidate>
<p id="emergency-error" class="form-error hidden"></p>
<p class="settings-desc">
Your trusted contact will be able to request access to your vault after
a waiting period if you are unable to access your account.
</p>
<div class="form-group">
<label for="emergency-email">Trusted contact's email</label>
<input
type="email"
id="emergency-email"
placeholder="contact@example.com"
/>
</div>
<div class="form-group">
<label for="emergency-wait-days">Wait period (days)</label>
<select id="emergency-wait-days">
<option value="1">1 day</option>
<option value="3">3 days</option>
<option value="7" selected>7 days</option>
<option value="14">14 days</option>
<option value="30">30 days</option>
</select>
</div>
<div class="modal-actions">
<button type="button" class="btn-secondary" id="btn-cancel-emergency">
Cancel
</button>
<button type="submit" class="btn-primary">Send Invitation</button>
</div>
</form>
</div>
</div>
<!-- ── Item Detail Modal (read-only: shared items) ────────────────────── -->
<div
id="detail-modal"
class="modal-overlay"
role="dialog"
aria-modal="true"
aria-labelledby="detail-modal-title"
>
<div class="modal modal-detail">
<div class="modal-header">
<h3 id="detail-modal-title">Item Details</h3>
<button
class="btn-icon btn-close"
id="btn-close-detail-modal"
aria-label="Close"
>
</button>
</div>
<div id="detail-modal-body" class="detail-body"></div>
<div class="modal-actions">
<button type="button" class="btn-secondary" id="btn-detail-done">
Close
</button>
</div>
</div>
</div>
{% endblock %} {% block scripts %}
<script src="{{ url_for('static', filename='js/crypto.js') }}"></script>
<script src="{{ url_for('static', filename='js/auth.js') }}"></script>
<script src="{{ url_for('static', filename='js/sharing.js') }}"></script>
<script src="{{ url_for('static', filename='js/vault.js') }}"></script>
{% endblock %}