feat: optional 4-digit PIN asked in every new tab (not on reload), on-screen keypad for phones; set, change or remove it in the account; five misses sign out

This commit is contained in:
redtea committed 2026-10-14 21:12:09 +03:00
1 parent 29353e5e6a
commit 119b524825
14 files changed
+316 -1

No files matched your search

+41
View File
@@ -107,6 +107,39 @@ pre { padding: 12px; overflow-x: auto; font-size: 13px; white-space: pre-wrap; w
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.spacer { flex: 1; }
#terminal { width: 100%; height: calc(100vh - 150px); }
/* The PIN lock of a new tab: the page stays hidden until it is unlocked. */
html.pin-wait body > :not(.pinlock) { visibility: hidden; }
.pinlock { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center; padding: 16px;
background: rgba(10, 13, 17, .92); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
opacity: 0; transition: opacity .3s ease; }
.pinlock.on { opacity: 1; }
.pinlock.done { opacity: 0; pointer-events: none; }
.pin-card { width: 100%; max-width: 300px; display: flex; flex-direction: column; align-items: center; text-align: center;
transform: translateY(8px) scale(.98); transition: transform .3s ease; }
.pinlock.on .pin-card { transform: none; }
.pinlock.done .pin-card { transform: scale(1.03); }
.pin-ico { width: 54px; height: 54px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
background: #12202f; border: 1px solid var(--border); color: var(--accent); }
.pin-title { margin: 14px 0 18px; font-size: 18px; font-weight: 600; }
.pin-dots { display: flex; gap: 16px; }
.pin-dots i { width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--muted); transition: background .15s, border-color .15s, transform .15s; }
.pin-dots i.on { background: var(--accent); border-color: var(--accent); transform: scale(1.1); }
.pin-card.bad .pin-dots i.on { background: var(--danger); border-color: var(--danger); }
.pin-card.bad .pin-dots { animation: pin-shake .38s ease; }
@keyframes pin-shake { 20% { transform: translateX(-9px); } 40% { transform: translateX(8px); } 60% { transform: translateX(-5px); } 80% { transform: translateX(3px); } }
.pin-msg { min-height: 20px; margin: 14px 0 6px; font-size: 13px; color: var(--danger); }
.pin-pad { display: grid; grid-template-columns: repeat(3, 72px); gap: 14px; justify-content: center; }
.pin-pad button { width: 72px; height: 72px; border-radius: 50%; padding: 0; display: inline-flex; align-items: center; justify-content: center;
background: #151a21; border: 1px solid var(--border); color: var(--text); font-size: 26px; font-weight: 400;
-webkit-tap-highlight-color: transparent; touch-action: manipulation; transition: background .12s, transform .08s; }
.pin-pad button:hover { background: #1b222c; }
.pin-pad button:active { background: #12202f; transform: scale(.94); }
.pin-pad button[data-k="back"] { background: transparent; border-color: transparent; color: var(--muted); }
.pin-out { margin-top: 18px; }
.pin-out button { background: transparent; color: var(--muted); padding: 6px 12px; font-size: 14px; }
.pin-out button:hover { background: transparent; color: var(--text); }
@media (max-height: 560px) { .pin-pad { grid-template-columns: repeat(3, 58px); gap: 10px; } .pin-pad button { width: 58px; height: 58px; font-size: 22px; } }
/* Dialogs shared by the pages. */
dialog { background: var(--panel); color: var(--text); border: 1px solid var(--border);
border-radius: 12px; padding: 0; max-width: 900px; width: 92vw; }
@@ -150,6 +183,14 @@ input.sw:disabled { opacity: .45; cursor: not-allowed; }
.acct-chpw summary { cursor: pointer; font-size: 14px; color: var(--text); }
.acct-pwform { display: grid; gap: 8px; margin-top: 10px; }
.acct-pwform button { justify-self: end; }
.acct-pin { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
.acct-pin summary { cursor: pointer; font-size: 14px; color: var(--text); }
.acct-pin small { color: var(--muted); font-size: 12px; }
.acct-pinform { display: grid; gap: 8px; margin-top: 10px; }
.acct-pinform input:not(:placeholder-shown) { letter-spacing: .4em; font-family: ui-monospace, Menlo, monospace; }
.acct-pinform .row { justify-content: flex-end; }
.acct-pinmsg { margin: 8px 0 0; font-size: 13px; color: var(--ok, #3fb950); min-height: 0; }
.acct-pinmsg.bad { color: var(--danger); }
.acct-out { margin-top: 10px; padding-top: 14px; border-top: 1px solid var(--border); display: flex; justify-content: flex-end; }
/* Sign-in page. */
.or { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 13px; margin: 18px 0 4px; }