diff --git a/extension/manifest.json b/extension/manifest.json index 7eb1630..f9b8da8 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -30,5 +30,10 @@ "content_security_policy": { "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'" }, + "commands": { + "open-vault": { + "description": "Open relicario vault" + } + }, "web_accessible_resources": [] } diff --git a/extension/src/service-worker/index.ts b/extension/src/service-worker/index.ts index 84bb225..e3dec89 100644 --- a/extension/src/service-worker/index.ts +++ b/extension/src/service-worker/index.ts @@ -64,6 +64,12 @@ chrome.storage.local.get('session_timeout').then((r) => { } }).catch(() => {}); +chrome.commands.onCommand.addListener((command) => { + if (command === 'open-vault') { + chrome.tabs.create({ url: chrome.runtime.getURL('vault.html') }); + } +}); + chrome.runtime.onMessage.addListener( (request: Request, sender: chrome.runtime.MessageSender, sendResponse: (r: Response) => void) => { (async () => { diff --git a/extension/src/vault/vault.css b/extension/src/vault/vault.css new file mode 100644 index 0000000..6184035 --- /dev/null +++ b/extension/src/vault/vault.css @@ -0,0 +1,1308 @@ +/* relicario vault — terminal dark theme (tab layout) */ + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + background: #0d1117; + color: #c9d1d9; + font-family: 'JetBrains Mono', 'Cascadia Code', 'Fira Code', 'SF Mono', Menlo, monospace; + font-size: 13px; + line-height: 1.5; + margin: 0; + height: 100vh; + overflow: hidden; +} + +/* Scrollbar */ +::-webkit-scrollbar { + width: 4px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: #30363d; + border-radius: 2px; +} + +/* Typography */ +.brand { + font-size: 16px; + font-weight: 700; + color: #d2ab43; + letter-spacing: 1px; +} + +.brand-logo { + display: block; + width: 48px; + height: 48px; + margin: 0 auto 8px; +} + +.label { + font-size: 11px; + font-weight: 500; + color: #8b949e; + text-transform: lowercase; + letter-spacing: 0.02em; + margin-bottom: 4px; +} + +.label .req { + color: #aa812a; + margin-left: 2px; + font-weight: 600; +} + +.secondary { + color: #8b949e; +} + +.muted { + color: #484f58; + font-size: 11px; +} + +.error { + color: #ab2b20; + font-size: 12px; + margin-top: 8px; +} + +/* Buttons */ +.btn { + display: inline-block; + padding: 6px 14px; + font-family: inherit; + font-size: 12px; + border: 1px solid #30363d; + border-radius: 4px; + background: #21262d; + color: #c9d1d9; + cursor: pointer; + transition: background 0.15s; +} + +.btn:hover { + background: #30363d; +} + +.btn:focus { + outline: 1px solid #d2ab43; + outline-offset: 1px; +} + +.btn-primary { + background: #7c5719; + border-color: #7c5719; + color: #fff; +} + +.btn-primary:hover { + background: #aa812a; +} + +.btn-danger { + background: #791111; + border-color: #791111; + color: #fff; +} + +.btn-danger:hover { + background: #ab2b20; +} + +/* Inputs */ +input, textarea, select { + width: 100%; + padding: 8px 10px; + font-family: inherit; + font-size: 13px; + background: #161b22; + border: 1px solid #30363d; + border-radius: 4px; + color: #c9d1d9; + outline: none; + transition: border-color 0.15s; +} + +input:focus, textarea:focus, select:focus { + border-color: #d2ab43; +} + +input::placeholder, textarea::placeholder { + color: #484f58; +} + +textarea { + resize: vertical; + min-height: 60px; +} + +/* Layout */ +.pad { + padding: 16px; +} + +/* Group tabs */ +.group-tabs { + display: flex; + gap: 2px; + padding: 6px 12px; + background: #0d1117; + border-bottom: 1px solid #21262d; + overflow-x: auto; +} + +.group-tab { + padding: 4px 10px; + font-size: 11px; + border: none; + border-radius: 3px; + background: transparent; + color: #8b949e; + cursor: pointer; + white-space: nowrap; + font-family: inherit; +} + +.group-tab:hover { + color: #c9d1d9; + background: #161b22; +} + +.group-tab.active { + color: #d2ab43; + background: #161b22; +} + +/* Detail view */ +.detail-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 12px; + border-bottom: 1px solid #21262d; +} + +.detail-title { + font-size: 15px; + font-weight: 600; + color: #c9d1d9; +} + +.field { + padding: 10px 12px; + border-bottom: 1px solid #21262d; +} + +.field-value { + font-size: 13px; + color: #c9d1d9; + word-break: break-all; + user-select: all; +} + +/* TOTP */ +.totp-code { + font-size: 22px; + font-weight: 700; + color: #3fb950; + letter-spacing: 4px; +} + +.totp-bar { + height: 3px; + background: #21262d; + border-radius: 2px; + margin-top: 6px; + overflow: hidden; +} + +.totp-bar-fill { + height: 100%; + background: #3fb950; + border-radius: 2px; + transition: width 1s linear; +} + +/* Wizard */ +.wizard-step { + padding: 16px; +} + +.wizard-step h3 { + font-size: 14px; + font-weight: 600; + margin-bottom: 12px; + color: #c9d1d9; +} + +.progress-bar { + display: flex; + gap: 4px; + padding: 12px 16px 0; +} + +.progress-bar .step { + flex: 1; + height: 3px; + background: #21262d; + border-radius: 2px; +} + +.progress-bar .step.done { + background: #d2ab43; +} + +.progress-bar .step.current { + background: #aa812a; +} + +/* Spinner */ +.spinner { + display: inline-block; + width: 16px; + height: 16px; + border: 2px solid #30363d; + border-top-color: #d2ab43; + border-radius: 50%; + animation: spin 0.6s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +/* Confirm overlay */ +.confirm-overlay { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.7); + display: flex; + align-items: center; + justify-content: center; + z-index: 100; +} + +.confirm-box { + background: #161b22; + border: 1px solid #30363d; + border-radius: 6px; + padding: 20px; + max-width: 280px; + text-align: center; +} + +.confirm-box p { + margin-bottom: 16px; + font-size: 13px; +} + +.confirm-box .btn + .btn { + margin-left: 8px; +} + +/* Empty state */ +.empty { + text-align: center; + padding: 40px 16px; + color: #484f58; + font-size: 13px; +} + +/* Form layout */ +.form-group { + margin-bottom: 12px; +} + +.form-group .label { + display: block; + margin-bottom: 4px; +} + +.form-actions { + display: flex; + gap: 8px; + margin-top: 16px; +} + +.inline-row { + display: flex; + gap: 8px; + align-items: center; +} + +.inline-row input { + flex: 1; +} + +/* Toggle (for host type) */ +.toggle-group { + display: flex; + gap: 0; + border: 1px solid #30363d; + border-radius: 4px; + overflow: hidden; +} + +.toggle-group button { + flex: 1; + padding: 6px 12px; + font-family: inherit; + font-size: 12px; + border: none; + background: #21262d; + color: #8b949e; + cursor: pointer; +} + +.toggle-group button.active { + background: #7c5719; + color: #fff; +} + +/* File upload area */ +.file-drop { + border: 2px dashed #30363d; + border-radius: 6px; + padding: 24px; + text-align: center; + cursor: pointer; + transition: border-color 0.15s; +} + +.file-drop:hover { + border-color: #d2ab43; +} + +.file-drop.has-file { + border-color: #3fb950; + border-style: solid; +} + +/* --- field-row + signature-block helpers --- */ + +.field-row { + display: grid; + grid-template-columns: 90px 1fr auto; + gap: 8px 10px; + align-items: baseline; + padding: 4px 0; + font-size: 12px; +} + +.field-row__label { color: #8b949e; } +.field-row__value { color: #c9d1d9; word-break: break-word; } +.field-row__value.monospace { font-family: "SF Mono", "JetBrains Mono", monospace; } +.field-row__value pre { + margin: 0; + white-space: pre-wrap; + word-break: break-word; + font-family: "SF Mono", "JetBrains Mono", monospace; +} +.field-row__actions { + display: flex; + gap: 6px; + font-size: 11px; + color: #8b949e; +} +.field-row__actions button { + background: transparent; + border: 0; + color: inherit; + cursor: pointer; + padding: 0; + font: inherit; +} +.field-row__actions button:hover { color: #c9d1d9; } + +.sig-block { + background: #161b22; + border: 1px solid #30363d; + border-left: 3px solid #7c5719; + border-radius: 5px; + padding: 14px; + margin-bottom: 10px; +} +.sig-block--gold { border-left-color: #7c5719; } +.sig-block--green { border-left-color: #3fb950; } +.sig-block--amber { border-left-color: #d29922; } +.sig-block--red { border-left-color: #ab2b20; } + +/* --- custom-section rendering --- */ +.section-header { + margin-top: 14px; + margin-bottom: 4px; + padding-top: 10px; + border-top: 1px solid #21262d; + color: #8b949e; + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.08em; +} +.section-separator { + margin: 10px 0 4px; + border: 0; + border-top: 1px solid #21262d; +} + +/* --- custom-section editor --- */ +.disclosure { + border-top: 1px solid #21262d; + margin-top: 14px; + padding-top: 10px; +} +.disclosure__toggle { + background: transparent; border: 0; color: #d2ab43; + cursor: pointer; font-size: 12px; padding: 0; + font-family: inherit; +} +.disclosure[data-expanded="false"] .disclosure__body { display: none; } + +.section-editor__head { + display: flex; align-items: baseline; gap: 8px; + margin-top: 10px; margin-bottom: 4px; + font-size: 11px; +} +.section-editor__head .name { color: #c9d1d9; font-weight: 600; } +.section-editor__head .name.anon { color: #8b949e; font-style: italic; font-weight: normal; } +.section-editor__head .actions { color: #8b949e; font-size: 10px; margin-left: auto; } +.section-editor__head .actions button { + background: transparent; border: 0; color: inherit; + cursor: pointer; padding: 0; margin-left: 8px; + font: inherit; +} +.section-editor__head .actions button:hover { color: #c9d1d9; } + +.section-editor__field { + display: grid; grid-template-columns: 120px 1fr auto; + gap: 4px; margin-bottom: 4px; font-size: 11px; +} +.section-editor__field input { + background: #0d1117; border: 1px solid #30363d; color: #c9d1d9; + padding: 3px 6px; border-radius: 3px; font: inherit; font-size: 11px; +} +.section-editor__field .delete-field { + background: transparent; border: 0; color: #ab2b20; + cursor: pointer; font-size: 14px; padding: 0 4px; +} +.section-editor__preserved { + font-size: 10px; color: #6e7681; font-style: italic; + padding: 4px 0 4px 6px; +} + +.section-editor__add { + display: flex; gap: 6px; margin-top: 6px; +} +.section-editor__add button { + background: transparent; border: 1px solid #30363d; color: #8b949e; + padding: 2px 10px; border-radius: 3px; cursor: pointer; + font-size: 10px; font-family: inherit; +} +.section-editor__add button:hover { color: #c9d1d9; border-color: #484f58; } + +.disclosure__body .add-section { + margin-top: 12px; background: transparent; + border: 1px dashed #30363d; color: #8b949e; + padding: 6px 10px; border-radius: 4px; cursor: pointer; + width: 100%; font-size: 11px; font-family: inherit; +} +.disclosure__body .add-section:hover { border-color: #484f58; color: #c9d1d9; } + +/* --- generator panel --- */ + +.gen-trigger { + background: #7c5719; + color: #fff3cf; + border: none; + border-radius: 4px; + padding: 0 12px; + font-size: 16px; + cursor: pointer; + line-height: 1; + min-width: 38px; + display: inline-flex; + align-items: center; + justify-content: center; +} +.gen-trigger:hover { background: #aa812a; } +.gen-trigger[aria-expanded="true"] { background: #aa812a; } + +.gen-panel { + background: #161b22; + border: 1px solid #aa812a; + border-radius: 6px; + padding: 11px; + margin: 6px 0; + font-size: 11px; + color: #c9d1d9; +} +.gen-panel .panel-toggle { + display: flex; + gap: 4px; + background: #21262d; + border-radius: 4px; + padding: 2px; + margin-bottom: 8px; +} +.gen-panel .panel-toggle button { + flex: 1; + background: transparent; + border: 0; + color: #8b949e; + padding: 5px; + font-size: 11px; + cursor: pointer; + border-radius: 3px; + font-weight: 600; +} +.gen-panel .panel-toggle button.active { + background: #aa812a; + color: #fff3cf; +} +.gen-panel .knob { + display: flex; + align-items: center; + gap: 8px; + margin: 6px 0; +} +.gen-panel .knob__label { + color: #8b949e; + width: 56px; + flex-shrink: 0; + font-size: 10px; +} +.gen-panel .knob__slider { flex: 1; } +.gen-panel .knob__value { + font-family: ui-monospace, monospace; + min-width: 24px; + text-align: right; + color: #c9d1d9; +} +.gen-panel .classes { + display: flex; + gap: 8px; + font-size: 10px; + margin: 6px 0; + flex-wrap: wrap; + color: #8b949e; +} +.gen-panel .classes label { + display: flex; + align-items: center; + gap: 3px; + user-select: none; + cursor: pointer; +} +.gen-panel .preview { + background: #0d1117; + border: 1px solid #30363d; + border-radius: 4px; + padding: 8px 10px; + margin-top: 8px; + display: flex; + align-items: center; + gap: 8px; +} +.gen-panel .preview__value { + flex: 1; + color: #f1cf6e; + font-family: ui-monospace, monospace; + font-size: 12px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.gen-panel .preview__regen { + background: transparent; + border: 0; + color: #8b949e; + cursor: pointer; + padding: 0 4px; + font-size: 14px; +} +.gen-panel .more { + color: #8b949e; + font-size: 10px; + margin-top: 6px; + cursor: pointer; + user-select: none; + padding: 2px 0; +} +.gen-panel .more summary { + list-style: none; + outline: none; +} +.gen-panel .more summary::-webkit-details-marker { display: none; } +.gen-panel .more:hover { color: #d2ab43; } +.gen-panel .more__advanced { margin-top: 6px; } +.gen-panel .actions { + display: flex; + gap: 6px; + margin-top: 10px; + align-items: center; +} +.gen-panel .actions .save-link { + flex: 1; + background: transparent; + border: 0; + color: #8b949e; + cursor: pointer; + font-size: 10px; + text-align: left; + padding: 4px 0; + text-decoration: underline; + text-decoration-color: #30363d; + text-underline-offset: 2px; +} +.gen-panel .actions .save-link:hover { + color: #d2ab43; + text-decoration-color: #d2ab43; +} +.gen-panel .actions .save-link__toast { + color: #3fb950; + margin-left: 6px; + font-size: 10px; +} + +.gen-preview-line { + margin: 0 0 6px; font-size: 11px; color: #c9d1d9; + font-family: "SF Mono", "JetBrains Mono", monospace; +} + +/* --- settings-vault screen --- */ +.settings-header { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; } +.settings-section { + margin-top: 14px; padding-top: 10px; + border-top: 1px solid #21262d; +} +.settings-section__title { + color: #8b949e; font-size: 10px; + text-transform: uppercase; letter-spacing: 0.08em; + margin-bottom: 6px; +} +.settings-row { + display: grid; grid-template-columns: 110px 1fr; + gap: 6px 10px; align-items: center; + margin: 4px 0; font-size: 12px; +} +.settings-row__label { color: #8b949e; } +.settings-row select { + background: #0d1117; border: 1px solid #30363d; color: #c9d1d9; + padding: 3px 8px; border-radius: 3px; font: inherit; font-size: 11px; +} +.ack-row { + display: grid; grid-template-columns: 1fr auto auto; + gap: 8px; align-items: center; + padding: 4px 0; font-size: 11px; + border-bottom: 1px solid #161b22; +} +.ack-row__host { color: #c9d1d9; font-family: monospace; } +.ack-row__meta { color: #6e7681; font-size: 10px; } +.ack-row__revoke { + background: transparent; border: 0; color: #ab2b20; + cursor: pointer; font-size: 10px; +} +.settings-footer { + display: flex; justify-content: flex-end; gap: 6px; + margin-top: 20px; padding-top: 12px; border-top: 1px solid #21262d; +} + +/* --- attachments disclosure --- */ + +.attachments-disclosure { + margin: 8px 0; + border: 1px solid #30363d; + border-radius: 4px; + padding: 6px 8px; + font-size: 11px; + color: #8b949e; +} +.attachments-disclosure[open] { + border-color: #aa812a; +} +.attachments-disclosure summary { + cursor: pointer; + list-style: none; + outline: none; + user-select: none; + padding: 2px 0; +} +.attachments-disclosure summary::-webkit-details-marker { display: none; } +.attachments-disclosure summary:hover { color: #c9d1d9; } +.attachments-disclosure__body { + margin-top: 6px; +} +.attachment-row { + display: flex; + align-items: center; + gap: 6px; + padding: 4px 0; + font-size: 10px; + border-bottom: 1px solid #21262d; +} +.attachment-row:last-of-type { + border-bottom: 0; +} +.attachment-row__icon, +.attachment-row__thumb { + width: 16px; + height: 16px; + background: #21262d; + border-radius: 2px; + display: flex; + align-items: center; + justify-content: center; + font-size: 10px; + flex-shrink: 0; + overflow: hidden; +} +.attachment-row__thumb img { + width: 100%; + height: 100%; + object-fit: cover; +} +.attachment-row__name { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: #c9d1d9; +} +.attachment-row__meta { + color: #6e7681; + font-size: 9px; + font-family: ui-monospace, monospace; + flex-shrink: 0; +} +.attachment-row__remove, +.attachment-row__download { + color: #d2ab43; + cursor: pointer; + padding: 0 6px; + flex-shrink: 0; +} +.attachment-row__remove { color: #ab2b20; } +.attachment-add-btn { + background: transparent; + border: 1px dashed #30363d; + color: #8b949e; + padding: 5px 8px; + font-size: 10px; + cursor: pointer; + border-radius: 3px; + width: 100%; + margin-top: 6px; + text-align: center; +} +.attachment-add-btn:hover { + border-color: #aa812a; + color: #c9d1d9; +} + +/* --- Document type signature block + primary picker --- */ + +.document-signature-block { + border-left: 3px solid #aa812a; + background: #161b22; + padding: 10px; + margin: 8px 0; + border-radius: 0 4px 4px 0; + display: flex; + align-items: center; + gap: 10px; +} +.document-signature-block__thumb { + width: 48px; + height: 60px; + border-radius: 2px; + background: linear-gradient(135deg, #b88a30, #7c5719); + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + flex-shrink: 0; + overflow: hidden; + color: #fff3cf; +} +.document-signature-block__thumb img { + width: 100%; height: 100%; object-fit: contain; +} +.document-signature-block__info { flex: 1; min-width: 0; } +.document-signature-block__name { + font-size: 11px; + color: #f1cf6e; + font-weight: 600; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.document-signature-block__meta { + font-size: 9px; + color: #8b949e; + font-family: ui-monospace, monospace; + margin-top: 2px; +} +.document-signature-block__actions { + font-size: 9px; + margin-top: 4px; +} +.document-signature-block__preview { + margin-top: 8px; + background: #0d1117; + border: 1px solid #30363d; + border-radius: 3px; + padding: 6px; + text-align: center; +} +.document-signature-block__preview img { + max-width: 100%; + max-height: 200px; + border-radius: 2px; +} + +/* Document primary picker (form mode) */ +.document-primary-row { + background: #161b22; + border: 1px solid #30363d; + border-radius: 4px; + padding: 6px 8px; + display: flex; + align-items: center; + gap: 6px; + font-size: 11px; + cursor: pointer; +} +.document-primary-row--empty { + border-style: dashed; + border-color: #aa812a; + color: #8b949e; + justify-content: center; + padding: 10px 8px; +} +.document-primary-row__thumb { + width: 18px; height: 18px; + border-radius: 2px; + background: linear-gradient(135deg, #b88a30, #7c5719); + display: flex; align-items: center; justify-content: center; + font-size: 10px; flex-shrink: 0; +} +.document-primary-row__name { + flex: 1; + color: #c9d1d9; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.document-primary-row__meta { + color: #6e7681; + font-size: 9px; + font-family: ui-monospace, monospace; +} +.document-primary-row__action { + color: #d2ab43; + font-size: 10px; + padding: 0 6px; + cursor: pointer; +} + +/* --- Trash view --- */ + +.trash-header { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 8px; +} + +.trash-row { + display: flex; + align-items: center; + gap: 8px; + padding: 8px; + border-radius: 4px; + background: #161b22; + margin-bottom: 6px; +} + +.trash-row__icon { + font-size: 16px; + flex-shrink: 0; +} + +.trash-row__info { + flex: 1; + min-width: 0; +} + +.trash-row__title { + display: block; + font-size: 13px; + color: #c9d1d9; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.trash-row__meta { + font-size: 11px; + color: #8b949e; +} + +.trash-row__restore { + font-size: 11px; + padding: 4px 8px; + background: #238636; + color: #fff; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.trash-row__restore:hover { + background: #2ea043; +} + +.trash-row__restore:disabled { + opacity: 0.5; + cursor: default; +} + +/* --- Devices view --- */ + +.devices-header { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 12px; +} + +.device-banner { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + padding: 10px; + background: #3d1f00; + border: 1px solid #9e6a03; + border-radius: 4px; + margin-bottom: 12px; + font-size: 12px; + color: #f0c674; +} + +.device-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px; + border-radius: 4px; + background: #161b22; + margin-bottom: 6px; +} + +.device-row__info { + flex: 1; + min-width: 0; +} + +.device-row__name { + display: block; + font-size: 13px; + color: #c9d1d9; +} + +.device-row__you { + font-size: 11px; + color: #58a6ff; +} + +.device-row__meta { + font-size: 11px; + color: #8b949e; +} + +.device-row__revoke { + font-size: 11px; + padding: 4px 8px; + background: #da3633; + color: #fff; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.device-row__revoke:hover { + background: #f85149; +} + +.device-row__revoke:disabled { + opacity: 0.5; + cursor: default; +} + +/* --- Field history view --- */ + +.history-header { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 8px; +} + +.history-item-title { + font-size: 14px; + font-weight: 600; + color: #c9d1d9; + margin-bottom: 12px; +} + +.history-field-label { + font-size: 11px; + color: #8b949e; + text-transform: uppercase; + margin: 12px 0 6px; +} + +.history-entry { + display: flex; + align-items: center; + gap: 8px; + padding: 10px; + border-radius: 4px; + background: #161b22; + margin-bottom: 6px; + cursor: pointer; +} + +.history-entry:hover { + background: #1c2128; +} + +.history-entry__value { + flex: 1; + font-family: monospace; + font-size: 13px; +} + +.history-entry__value.masked { + color: #8b949e; +} + +.history-entry__value.revealed { + color: #c9d1d9; +} + +.history-entry__meta { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 2px; + font-size: 11px; + color: #8b949e; +} + +.history-entry__current { + color: #58a6ff; + font-weight: 500; +} + +.history-entry__copy { + background: none; + border: none; + cursor: pointer; + font-size: 14px; + padding: 4px; +} + +.history-entry__copy:hover { + opacity: 0.8; +} + +/* --- Type selection --- */ + +.type-select-list { + display: flex; + flex-direction: column; + gap: 4px; +} + +.type-select-row { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 12px; + background: #161b22; + border: 1px solid transparent; + border-radius: 6px; + color: #c9d1d9; + font-size: 13px; + cursor: pointer; + text-align: left; +} + +.type-select-row:hover { + background: #21262d; + border-color: #30363d; +} + +.type-select-icon { + font-size: 16px; + width: 20px; + text-align: center; +} + +/* ===================================================== + Vault-specific layout styles (tab UI) + ===================================================== */ + +#vault-app { + display: flex; + height: 100vh; +} + +.vault-sidebar { + width: 260px; + min-width: 260px; + border-right: 1px solid #21262d; + display: flex; + flex-direction: column; + height: 100vh; + overflow: hidden; +} + +.vault-sidebar__header { + padding: 12px 16px; + border-bottom: 1px solid #21262d; + display: flex; + align-items: center; + gap: 8px; +} + +.vault-sidebar__search { + padding: 8px 12px; + border-bottom: 1px solid #21262d; +} + +.vault-sidebar__search input { + width: 100%; + background: #161b22; + border: 1px solid #30363d; + border-radius: 4px; + color: #c9d1d9; + padding: 6px 10px; + font-size: 12px; + font-family: inherit; +} + +.vault-sidebar__list { + flex: 1; + overflow-y: auto; +} + +.vault-sidebar__nav { + border-top: 1px solid #21262d; + padding: 8px 0; +} + +.vault-sidebar__nav-item { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 16px; + color: #8b949e; + font-size: 12px; + cursor: pointer; + border: none; + background: none; + width: 100%; + text-align: left; + font-family: inherit; +} + +.vault-sidebar__nav-item:hover { + color: #c9d1d9; + background: #161b22; +} + +.vault-pane { + flex: 1; + overflow-y: auto; + padding: 24px 32px; +} + +.vault-pane--empty { + display: flex; + align-items: center; + justify-content: center; + color: #484f58; + font-size: 14px; +} + +.vault-entry { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 16px; + cursor: pointer; + border-left: 2px solid transparent; + font-size: 12px; +} + +.vault-entry:hover { background: #161b22; } + +.vault-entry.selected { + background: #161b22; + border-left-color: #d2ab43; +} + +.vault-entry__title { + color: #c9d1d9; + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.vault-entry__meta { + color: #484f58; + font-size: 11px; +} + +.vault-group-header { + padding: 12px 16px 4px; + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.05em; + color: #484f58; +} + +/* --- Lock screen (vault tab) --- */ + +.vault-lock-screen { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; + gap: 16px; +} + +.vault-lock-screen__form { + display: flex; + flex-direction: column; + gap: 12px; + width: 320px; +} + +.vault-lock-screen__form input { + text-align: center; +} diff --git a/extension/src/vault/vault.html b/extension/src/vault/vault.html new file mode 100644 index 0000000..5459fac --- /dev/null +++ b/extension/src/vault/vault.html @@ -0,0 +1,12 @@ + + +
+ +${escapeHtml(item.notes)}+ Full form will be wired in Task 4 (shared state host). +
++ Full edit form will be wired in Task 4 (shared state host). +
+loading devices...
+ `; + + document.getElementById('pane-devices-back')?.addEventListener('click', () => { + setHash('list'); + renderPane(); + }); + + // Fetch and render devices + sendMessage({ type: 'list_devices' }).then((resp) => { + if (!resp.ok) return; + const data = resp.data as { devices: Array<{ name: string; public_key: string; added_at: number }> }; + const devicesContainer = pane.querySelector('.muted'); + if (!devicesContainer) return; + + if (data.devices.length === 0) { + devicesContainer.outerHTML = '+ Full settings view will be wired in Task 4 (shared state host). +
+ `; + + if (state.vaultSettings) { + const vs = state.vaultSettings; + const trashRetention = vs.trash_retention.kind === 'forever' + ? 'forever' + : `${(vs.trash_retention as { kind: 'days'; value: number }).value} days`; + const historyRetention = vs.field_history_retention.kind === 'forever' + ? 'forever' + : vs.field_history_retention.kind === 'last_n' + ? `last ${(vs.field_history_retention as { kind: 'last_n'; value: number }).value}` + : `${(vs.field_history_retention as { kind: 'days'; value: number }).value} days`; + + pane.innerHTML += ` +