be4d43105e
Node.js/Express backend + vanilla JS frontend. Features: real-time collaborative whiteboard (SSE), multi-page support, LaTeX formulas, shapes/connectors, coordinate systems, number lines, compass, zoom/pan, Catmull-Rom pencil smoothing, ruler/protractor with rotation & resize controls, minimap navigation overlay, auto-measurements, multi-page thumbnails sidebar, PNG export, page templates. Student/teacher workflows: classes, assignments, library, dashboard. Mobile responsive. SQLite (better-sqlite3). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
100 lines
4.9 KiB
HTML
100 lines
4.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="UTF-8"/>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
<title>404 — Страница не найдена</title>
|
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml"/>
|
|
<link href="https://fonts.googleapis.com/css2?family=Unbounded:wght@400;700;800&family=Manrope:wght@400;500;600;700&display=swap" rel="stylesheet"/>
|
|
<link rel="stylesheet" href="/css/ls.css"/>
|
|
<style>
|
|
html, body { height: 100%; display: flex; align-items: center; justify-content: center; }
|
|
.err-wrap {
|
|
text-align: center; padding: 40px 24px; max-width: 480px;
|
|
}
|
|
.err-code {
|
|
font-family: 'Unbounded', sans-serif; font-size: 6rem; font-weight: 900;
|
|
background: linear-gradient(135deg, #9B5DE5, #06D6E0);
|
|
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
|
|
background-clip: text; line-height: 1; margin-bottom: 8px;
|
|
}
|
|
.err-title {
|
|
font-family: 'Unbounded', sans-serif; font-size: 1.2rem; font-weight: 800;
|
|
color: var(--text); margin-bottom: 12px;
|
|
}
|
|
.err-desc { font-size: 0.92rem; color: var(--text-3); line-height: 1.6; margin-bottom: 32px; }
|
|
.err-illustration {
|
|
width: 120px; height: 120px; border-radius: 50%; margin: 0 auto 28px;
|
|
background: linear-gradient(135deg, rgba(155,93,229,.15), rgba(6,214,224,.1));
|
|
border: 2px solid rgba(155,93,229,.2);
|
|
display: flex; align-items: center; justify-content: center;
|
|
}
|
|
.err-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
|
|
.err-btn-primary {
|
|
padding: 11px 28px; border: none; border-radius: 99px;
|
|
background: linear-gradient(135deg, #9B5DE5, #06D6E0);
|
|
color: #fff; font-family: 'Manrope', sans-serif; font-size: 0.88rem; font-weight: 700;
|
|
text-decoration: none; display: inline-flex; align-items: center; gap: 7px;
|
|
transition: all .2s;
|
|
}
|
|
.err-btn-primary:hover { opacity: .88; transform: translateY(-1px); }
|
|
.err-btn-secondary {
|
|
padding: 10px 22px; border: 1.5px solid var(--border-h); border-radius: 99px;
|
|
background: transparent; color: var(--text-2); font-family: 'Manrope', sans-serif;
|
|
font-size: 0.88rem; font-weight: 600; text-decoration: none;
|
|
display: inline-flex; align-items: center; gap: 7px; transition: all .2s;
|
|
}
|
|
.err-btn-secondary:hover { border-color: var(--violet); color: var(--violet); }
|
|
.err-search {
|
|
display: flex; gap: 8px; margin-bottom: 20px;
|
|
}
|
|
.err-search input {
|
|
flex: 1; padding: 10px 14px; border: 1.5px solid var(--border-h); border-radius: 12px;
|
|
font-family: 'Manrope', sans-serif; font-size: 0.88rem; color: var(--text);
|
|
background: var(--surface); outline: none; transition: border-color .2s;
|
|
}
|
|
.err-search input:focus { border-color: var(--violet); }
|
|
.err-search button {
|
|
padding: 10px 18px; border: none; border-radius: 12px;
|
|
background: rgba(155,93,229,.12); color: var(--violet);
|
|
font-family: 'Manrope', sans-serif; font-size: 0.88rem; font-weight: 700; cursor: pointer;
|
|
transition: background .2s;
|
|
}
|
|
.err-search button:hover { background: rgba(155,93,229,.22); }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="err-wrap">
|
|
<div class="err-illustration">
|
|
<svg width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="#9B5DE5" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
|
<circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/>
|
|
<path d="M11 8v4M11 16h.01"/>
|
|
</svg>
|
|
</div>
|
|
<div class="err-code">404</div>
|
|
<div class="err-title">Страница не найдена</div>
|
|
<div class="err-desc">Такой страницы не существует или она была перемещена. Попробуй поискать или вернись на главную.</div>
|
|
<div class="err-search">
|
|
<input type="text" id="search-inp" placeholder="Поиск по системе..." onkeydown="if(event.key==='Enter')doSearch()"/>
|
|
<button onclick="doSearch()">Найти</button>
|
|
</div>
|
|
<div class="err-actions">
|
|
<a class="err-btn-primary" href="/dashboard">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
|
|
На главную
|
|
</a>
|
|
<button class="err-btn-secondary" onclick="history.back()">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m12 19-7-7 7-7"/><path d="M19 12H5"/></svg>
|
|
Назад
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
function doSearch() {
|
|
const q = document.getElementById('search-inp').value.trim();
|
|
if (q) window.location.href = '/library?q=' + encodeURIComponent(q);
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|