Добавлена модалка «О проекте», версия 0.1.2; Jenkins берёт VERSION из коммита.

This commit is contained in:
Sergey Antropoff
2026-07-27 23:11:27 +03:00
parent f431fc3c1c
commit 9be207154e
13 changed files with 177 additions and 218 deletions
+58 -106
View File
@@ -201,6 +201,10 @@ html[data-theme="dark"] .icon-btn:hover {
box-shadow: none;
}
.icon { width: 18px; height: 18px; }
.icon-btn i {
font-size: 1.05rem;
line-height: 1;
}
.hidden { display: none !important; }
.shell {
@@ -784,126 +788,24 @@ html[data-theme="light"] .form-alert-attempts {
text-align: center;
color: var(--muted);
font-size: 0.85rem;
padding: 0.5rem 1.25rem 2.25rem;
padding: 0.75rem 1.25rem 2rem;
max-width: 760px;
margin: 0 auto;
}
.footer-pillars {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 0.55rem 0.7rem;
}
.footer-pillars li {
display: inline-flex;
align-items: center;
gap: 0.55rem;
padding: 0.55rem 0.85rem;
border: 1px solid rgba(110, 168, 255, 0.22);
border-radius: 12px;
background: linear-gradient(160deg, rgba(110, 168, 255, 0.1), rgba(13, 20, 32, 0.35));
color: var(--text);
text-align: left;
backdrop-filter: blur(8px);
max-width: 240px;
}
html[data-theme="light"] .footer-pillars li {
background: linear-gradient(160deg, rgba(47, 111, 237, 0.1), rgba(255, 255, 255, 0.85));
border-color: rgba(47, 111, 237, 0.2);
}
.footer-pillars i {
color: var(--accent-2);
font-size: 0.95rem;
width: 1.1rem;
text-align: center;
flex-shrink: 0;
}
.footer-pillars span {
display: flex;
flex-direction: column;
gap: 0.1rem;
min-width: 0;
}
.footer-pillars strong {
font-size: 0.8rem;
font-weight: 650;
letter-spacing: 0.01em;
line-height: 1.2;
}
.footer-pillars small {
font-size: 0.7rem;
color: var(--muted);
font-weight: 500;
line-height: 1.25;
}
@media (max-width: 720px) {
.site-footer {
max-width: 100%;
padding: 0.35rem 0.6rem 1.5rem;
}
.footer-pillars {
flex-wrap: nowrap;
gap: 0.3rem;
width: 100%;
}
.footer-pillars li {
flex: 1 1 0;
max-width: none;
min-width: 0;
flex-direction: column;
align-items: center;
justify-content: flex-start;
gap: 0.2rem;
padding: 0.4rem 0.3rem;
border-radius: 9px;
text-align: center;
}
.footer-pillars i {
font-size: 0.72rem;
width: auto;
}
.footer-pillars span {
align-items: center;
gap: 0.05rem;
}
.footer-pillars strong {
font-size: 0.62rem;
line-height: 1.15;
}
.footer-pillars small {
font-size: 0.55rem;
line-height: 1.2;
padding: 0.5rem 0.85rem 1.5rem;
}
.footer-copy {
margin-top: 0.65rem;
font-size: 0.72rem;
}
}
.footer-copy {
margin: 0.85rem 0 0;
margin: 0;
font-size: 0.8rem;
color: var(--muted);
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
flex-wrap: wrap;
}
.footer-copy-left {
min-width: 0;
}
.footer-copy-version {
margin-left: auto;
font-family: var(--font-mono);
font-size: 0.72rem;
font-weight: 500;
letter-spacing: 0.02em;
color: var(--muted);
opacity: 0.9;
white-space: nowrap;
text-align: center;
}
.footer-copy a {
color: var(--accent-2);
@@ -914,6 +816,56 @@ html[data-theme="light"] .footer-pillars li {
text-decoration: underline;
}
.about-modal-panel {
width: min(520px, 100%);
}
.about-modal-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 0.85rem;
margin-bottom: 0.15rem;
}
.about-modal-head .modal-title {
margin: 0;
flex: 1;
min-width: 0;
}
.about-version {
flex-shrink: 0;
margin-top: 0.15rem;
padding: 0.28rem 0.65rem;
border-radius: 999px;
border: 1px solid rgba(110, 168, 255, 0.28);
background: linear-gradient(160deg, rgba(110, 168, 255, 0.16), rgba(61, 214, 198, 0.08));
color: var(--accent-2);
font-family: var(--font-mono);
font-size: 0.72rem;
font-weight: 600;
letter-spacing: 0.03em;
line-height: 1;
white-space: nowrap;
}
html[data-theme="light"] .about-version {
border-color: rgba(47, 111, 237, 0.25);
background: linear-gradient(160deg, rgba(47, 111, 237, 0.12), rgba(14, 160, 140, 0.08));
color: var(--accent);
}
.about-modal-body {
display: grid;
gap: 0.75rem;
margin: 0.85rem 0 1.1rem;
}
.about-modal-body p {
margin: 0;
color: var(--muted);
font-size: 0.92rem;
line-height: 1.5;
}
.about-modal-panel .modal-actions {
justify-content: flex-end;
}
.sr-only {
position: absolute;
width: 1px; height: 1px;
+36
View File
@@ -0,0 +1,36 @@
(() => {
const modal = document.getElementById("about-modal");
const toggle = document.getElementById("about-toggle");
if (!modal || !toggle) return;
function syncToggleLabels() {
const label = window.WrappedI18n?.t("about.open") || "About Wrapped";
toggle.setAttribute("title", label);
toggle.setAttribute("aria-label", label);
}
function openModal() {
modal.classList.remove("hidden");
document.body.classList.add("modal-open");
modal.querySelector("[data-about-close].btn")?.focus?.();
}
function closeModal() {
modal.classList.add("hidden");
document.body.classList.remove("modal-open");
toggle.focus?.();
}
toggle.addEventListener("click", openModal);
modal.addEventListener("click", (e) => {
if (e.target.closest("[data-about-close]")) closeModal();
});
document.addEventListener("keydown", (e) => {
if (e.key === "Escape" && !modal.classList.contains("hidden")) closeModal();
});
if (window.WrappedI18n?.onChange) {
window.WrappedI18n.onChange(syncToggleLabels);
}
syncToggleLabels();
})();
+14 -12
View File
@@ -10,13 +10,14 @@
"footer.cap.media.hint": "Screenshots, archives, docs",
"footer.cap.browser": "Encrypted in-browser",
"footer.cap.browser.hint": "Only ciphertext reaches the server",
"footer.pillar.zk": "Zero-knowledge",
"footer.pillar.once": "One-time",
"footer.pillar.encrypted": "Encrypted",
"footer.pillar.zk.hint": "Server never sees content",
"footer.pillar.once.hint": "Gone after unwrap",
"footer.pillar.encrypted.hint": "Key lives only in your link",
"footer.copy.author": "Sergey Antropov",
"about.open": "About Wrapped",
"about.title": "About Wrapped",
"about.p1": "Wrapped is a one-time secure drop for text, images and files.",
"about.p2": "Send a note or code snippet, and attachments too: documents, archives, screenshots (drag-and-drop, file picker, or paste from the clipboard). Both text and files are encrypted in the browser before upload — only ciphertext reaches the server.",
"about.p3": "The server never sees plaintext: encrypted data stays on the server until the recipient opens the link with the key and decrypts the package.",
"about.p4": "After a successful unwrap the server copy is destroyed. The encryption key lives in the URL fragment (#…) and is not sent to the server with the page request. Optionally, a wrap can also be protected with a password.",
"about.close": "Got it",
"brand.tagline": "Wrap. Send. Vanish.",
"create.eyebrow": "Secure drop",
"create.title": "Wrap. Send. Vanish.",
@@ -227,13 +228,14 @@
"footer.cap.media.hint": "Скриншоты, архивы, документы",
"footer.cap.browser": "Шифрование в браузере",
"footer.cap.browser.hint": "На сервер уходит только ciphertext",
"footer.pillar.zk": "Zero-knowledge",
"footer.pillar.once": "Одноразово",
"footer.pillar.encrypted": "Зашифровано",
"footer.pillar.zk.hint": "Сервер не видит содержимое",
"footer.pillar.once.hint": "После открытия — удаление",
"footer.pillar.encrypted.hint": "Ключ только в вашей ссылке",
"footer.copy.author": "Сергей Антропов",
"about.open": "О проекте Wrapped",
"about.title": "О проекте Wrapped",
"about.p1": "Wrapped — сервис одноразовой безопасной передачи текста, изображений и файлов.",
"about.p2": "Можно отправить заметку или код, а также вложения: документы, архивы, скриншоты (drag-and-drop, выбор с диска или вставка из буфера). И текст, и файлы шифруются в браузере до загрузки — на сервер уходит только ciphertext.",
"about.p3": "Сервер никогда не видит plaintext: зашифрованные данные лежат на сервере до тех пор, пока получатель не откроет ссылку с ключом и не расшифрует пакет.",
"about.p4": "После успешной расшифровки копия на сервере уничтожается. Ключ шифрования живёт во фрагменте URL (#…) и не уходит на сервер вместе с запросом страницы. При желании wrap можно дополнительно защитить паролем.",
"about.close": "Понятно",
"brand.tagline": "Упакуй. Отправь. Исчезни.",
"create.eyebrow": "Безопасная передача",
"create.title": "Упакуй. Отправь. Исчезни.",