253 lines
13 KiB
HTML
253 lines
13 KiB
HTML
<!doctype html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>{{ article.title }} — MONT</title>
|
||
<meta name="description" content="{{ article.body[:160] | replace('\n',' ') }}" />
|
||
<meta name="robots" content="index, follow" />
|
||
<link rel="canonical" href="{{ base_url }}/news/{{ article.slug }}" />
|
||
<meta property="og:type" content="article" />
|
||
<meta property="og:url" content="{{ base_url }}/news/{{ article.slug }}" />
|
||
<meta property="og:title" content="{{ article.title }} — MONT" />
|
||
<meta property="og:description" content="{{ article.body[:200] | replace('\n',' ') }}" />
|
||
{% if article.image %}<meta property="og:image" content="{{ base_url }}/static/{{ article.image }}" />{% endif %}
|
||
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg" />
|
||
<link rel="icon" type="image/png" href="/static/favicon.png" />
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link href="https://fonts.googleapis.com/css2?family=Caveat:wght@600;700&family=Manrope:wght@400;600;700;800&display=swap" rel="stylesheet">
|
||
<style>
|
||
:root { --brand: #1f4ea3; --brand2: #3978e0; --bg: #eef4ff; --radius: 16px; }
|
||
* { box-sizing: border-box; }
|
||
body { margin: 0; font-family: Manrope, sans-serif; background: var(--bg); color: #15203b; min-height: 100vh; }
|
||
.wrap { width: min(1100px, calc(100% - 32px)); margin: 0 auto; padding: 28px 0 60px; }
|
||
.back-btn {
|
||
display: inline-flex; align-items: center; gap: 6px;
|
||
font-size: 13px; font-weight: 700; color: var(--brand);
|
||
text-decoration: none; margin-bottom: 20px;
|
||
padding: 8px 16px; border-radius: 999px;
|
||
background: #fff; border: 1px solid #c8d8f7; transition: .15s ease;
|
||
}
|
||
.back-btn:hover { background: #eef4ff; transform: translateX(-2px); }
|
||
.article-card {
|
||
background: #fff; border-radius: 20px;
|
||
border: 1px solid #dae6ff;
|
||
box-shadow: 0 12px 40px rgba(16,43,95,.1);
|
||
overflow: hidden;
|
||
}
|
||
.article-header { display: flex; gap: 20px; align-items: flex-start; padding: 28px 32px 0; }
|
||
.article-hero-img {
|
||
flex-shrink: 0;
|
||
width: 160px; height: 106px;
|
||
object-fit: cover;
|
||
border-radius: 12px;
|
||
display: block;
|
||
}
|
||
.article-header-text { flex: 1; min-width: 0; }
|
||
.article-body-wrap { padding: 20px 32px 36px; }
|
||
.article-date { font-size: 12px; color: #8aa0c0; font-weight: 600; margin-bottom: 8px; }
|
||
.article-title { font-size: 24px; font-weight: 800; color: #1a3e79; margin: 0; line-height: 1.25; }
|
||
.article-body { font-size: 15px; color: #2e3f58; line-height: 1.75; }
|
||
.article-body p { margin: 0 0 16px; }
|
||
.article-body p:last-child { margin-bottom: 0; }
|
||
.article-body a { color: var(--brand); font-weight: 600; text-decoration: none; }
|
||
.article-body a:hover { text-decoration: underline; }
|
||
.article-body strong, .article-body b { font-weight: 700; color: #1a3e79; }
|
||
.article-body em, .article-body i { font-style: italic; }
|
||
.article-body ul, .article-body ol { margin: 0 0 16px 20px; padding: 0; }
|
||
.article-body li { margin-bottom: 6px; }
|
||
.article-body h2, .article-body h3, .article-body h4 { font-weight: 800; color: #1a3e79; margin: 20px 0 10px; line-height: 1.3; }
|
||
.article-body h2 { font-size: 20px; }
|
||
.article-body h3 { font-size: 17px; }
|
||
.article-body blockquote { border-left: 3px solid var(--brand); margin: 16px 0; padding: 8px 16px; background: #f0f5ff; border-radius: 0 8px 8px 0; color: #526079; }
|
||
.article-body table { width: 100%; border-collapse: collapse; margin: 0 0 16px; font-size: 14px; }
|
||
.article-body th, .article-body td { border: 1px solid #dae6ff; padding: 8px 12px; text-align: left; }
|
||
.article-body th { background: #eef4ff; font-weight: 700; color: #1a3e79; }
|
||
.article-contact {
|
||
margin-top: 28px; padding-top: 20px;
|
||
border-top: 1px solid #e8f0ff;
|
||
font-size: 13px; color: #526079;
|
||
}
|
||
.article-contact a { color: var(--brand); font-weight: 700; text-decoration: none; }
|
||
.article-contact a:hover { text-decoration: underline; }
|
||
.credit {
|
||
text-align: center; margin-top: 24px;
|
||
}
|
||
.credit button {
|
||
font-family: 'Caveat', cursive; font-size: 18px;
|
||
color: #1c3f7c; background: none; border: none;
|
||
cursor: pointer; padding: 0;
|
||
transition: opacity .15s;
|
||
}
|
||
.credit button:hover { opacity: .7; }
|
||
.edit-btn {
|
||
display: inline-flex; align-items: center; gap: 6px;
|
||
font-size: 13px; font-weight: 700; color: #1f4ea3;
|
||
text-decoration: none; padding: 7px 16px;
|
||
border-radius: 999px; background: #eef4ff;
|
||
border: 1px solid #c8d8f7; transition: .15s;
|
||
margin-bottom: 16px; float: right;
|
||
}
|
||
.edit-btn:hover { background: #dceeff; }
|
||
@media (max-width: 640px) {
|
||
.article-header { flex-direction: column; padding: 20px 20px 0; }
|
||
.article-hero-img { width: 100%; height: 140px; }
|
||
.article-body-wrap { padding: 16px 20px 28px; }
|
||
.article-title { font-size: 20px; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="wrap">
|
||
<a href="/" class="back-btn">← На главную</a>
|
||
{% if is_news_editor %}
|
||
<a href="/news-admin" class="edit-btn">✏ Редактировать</a>
|
||
<div style="clear:both;"></div>
|
||
{% endif %}
|
||
<article class="article-card">
|
||
<div class="article-header">
|
||
{% if article.image %}
|
||
<img class="article-hero-img" src="/static/{{ article.image }}" alt="{{ article.title }}" />
|
||
{% endif %}
|
||
<div class="article-header-text">
|
||
<div class="article-date">{{ article.created_at[8:10] }}.{{ article.created_at[5:7] }}.{{ article.created_at[:4] }}</div>
|
||
<h1 class="article-title">{{ article.title }}</h1>
|
||
</div>
|
||
</div>
|
||
<div class="article-body-wrap">
|
||
<div class="article-body">
|
||
{% if '<' in article.body %}
|
||
{{ article.body | safe }}
|
||
{% else %}
|
||
{% for paragraph in article.body.split('\n\n') %}
|
||
<p>{{ paragraph }}</p>
|
||
{% endfor %}
|
||
{% endif %}
|
||
</div>
|
||
<div class="article-contact">
|
||
По вопросам сотрудничества: <a href="mailto:mshamov@mont.com">mshamov@mont.com</a>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
<div class="credit">
|
||
<button type="button" id="btn-contact-ruslan">Made by Galyaviev</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Contact modal -->
|
||
<div id="contact-modal" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:9000;align-items:center;justify-content:center;padding:1rem;">
|
||
<div style="background:#fff;border-radius:20px;width:100%;max-width:460px;max-height:90vh;overflow-y:auto;box-shadow:0 24px 64px rgba(16,43,95,.22);">
|
||
<div style="padding:1.5rem 1.75rem .75rem;display:flex;align-items:center;justify-content:space-between;">
|
||
<div style="font-size:1.15rem;font-weight:800;color:#1a3e79;">Связаться с Русланом</div>
|
||
<button onclick="window._closeContact()" style="background:none;border:none;font-size:1.4rem;color:#8aa;cursor:pointer;line-height:1;padding:0 4px;">×</button>
|
||
</div>
|
||
<div id="cm-body" style="padding:.5rem 1.75rem;display:flex;flex-direction:column;gap:.9rem;"></div>
|
||
<div id="cm-footer" style="display:flex;justify-content:flex-end;gap:.75rem;padding:.75rem 1.75rem 1.5rem;"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function() {
|
||
const overlay = document.getElementById('contact-modal');
|
||
|
||
const fieldStyle = 'width:100%;box-sizing:border-box;margin-top:.3rem;padding:.6rem .85rem;' +
|
||
'background:#f7faff;border:1px solid #c8d8f7;border-radius:9px;color:#1a3060;' +
|
||
'font-size:.92rem;outline:none;font-family:Manrope,sans-serif;';
|
||
const labelStyle = 'color:#526079;font-size:.8rem;font-weight:700;letter-spacing:.2px;';
|
||
|
||
function buildForm() {
|
||
document.getElementById('cm-body').innerHTML =
|
||
'<div><label style="' + labelStyle + '">Ваше имя *</label>' +
|
||
'<input id="cm-name" type="text" placeholder="Иван Иванов" style="' + fieldStyle + '"/></div>' +
|
||
'<div><label style="' + labelStyle + '">Email *</label>' +
|
||
'<input id="cm-email" type="email" placeholder="ivan@company.ru" style="' + fieldStyle + '"/></div>' +
|
||
'<div><label style="' + labelStyle + '">Телефон *</label>' +
|
||
'<input id="cm-phone" type="tel" placeholder="+7 (999) 000-00-00" style="' + fieldStyle + '"/></div>' +
|
||
'<div><label style="' + labelStyle + '">Сообщение *</label>' +
|
||
'<textarea id="cm-text" rows="4" placeholder="Ваш вопрос или предложение..." style="' + fieldStyle + 'resize:vertical;"></textarea></div>' +
|
||
'<div id="cm-error" style="display:none;background:#fff0f0;border:1px solid #fcc;border-radius:8px;' +
|
||
'padding:.5rem .85rem;color:#c0392b;font-size:.85rem;"></div>';
|
||
|
||
document.getElementById('cm-footer').innerHTML =
|
||
'<button onclick="window._closeContact()" style="background:#f0f5ff;border:1px solid #c8d8f7;border-radius:9px;' +
|
||
'padding:.6rem 1.25rem;color:#526079;cursor:pointer;font-family:Manrope,sans-serif;font-weight:600;">Отмена</button>' +
|
||
'<button id="cm-submit" style="background:linear-gradient(135deg,#1f4ea3,#3978e0);border:none;border-radius:9px;' +
|
||
'padding:.6rem 1.5rem;color:#fff;font-weight:700;cursor:pointer;font-family:Manrope,sans-serif;">Отправить</button>';
|
||
|
||
document.getElementById('cm-submit').addEventListener('click', submit);
|
||
}
|
||
|
||
function openModal() {
|
||
buildForm();
|
||
overlay.style.display = 'flex';
|
||
document.body.style.overflow = 'hidden';
|
||
setTimeout(() => { const n = document.getElementById('cm-name'); if (n) n.focus(); }, 80);
|
||
}
|
||
|
||
window._closeContact = function() {
|
||
overlay.style.display = 'none';
|
||
document.body.style.overflow = '';
|
||
};
|
||
|
||
async function submit() {
|
||
const name = document.getElementById('cm-name').value.trim();
|
||
const email = document.getElementById('cm-email').value.trim();
|
||
const phone = document.getElementById('cm-phone').value.trim();
|
||
const text = document.getElementById('cm-text').value.trim();
|
||
const errEl = document.getElementById('cm-error');
|
||
const btn = document.getElementById('cm-submit');
|
||
|
||
const emailRe = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||
const phoneRe = /^[\+\d][\d\s\-\(\)]{6,18}$/;
|
||
const errors = [];
|
||
[[!name, 'cm-name'], [!emailRe.test(email), 'cm-email'],
|
||
[!phoneRe.test(phone), 'cm-phone'], [!text, 'cm-text']].forEach(([bad, id]) => {
|
||
document.getElementById(id).style.borderColor = bad ? '#e74c3c' : '#c8d8f7';
|
||
if (bad) errors.push(id);
|
||
});
|
||
if (errors.length) {
|
||
errEl.textContent = 'Пожалуйста, заполните все поля корректно';
|
||
errEl.style.display = 'block';
|
||
return;
|
||
}
|
||
|
||
btn.disabled = true;
|
||
btn.textContent = 'Отправка...';
|
||
errEl.style.display = 'none';
|
||
|
||
try {
|
||
const res = await fetch('/api/contact', {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify({name, email, phone, text}),
|
||
});
|
||
if (!res.ok) {
|
||
const d = await res.json().catch(() => ({}));
|
||
throw new Error(d.detail || 'Ошибка отправки');
|
||
}
|
||
document.getElementById('cm-body').innerHTML =
|
||
'<div style="text-align:center;padding:2rem 0">' +
|
||
'<div style="width:56px;height:56px;border-radius:50%;background:linear-gradient(135deg,#1f4ea3,#3978e0);' +
|
||
'color:#fff;font-size:1.8rem;display:flex;align-items:center;justify-content:center;margin:0 auto 1rem;">✓</div>' +
|
||
'<div style="font-size:1.1rem;font-weight:800;color:#1a3e79;">Отправлено!</div>' +
|
||
'<div style="color:#526079;font-size:.9rem;margin-top:.4rem;">Постараюсь ответить в ближайшее время</div></div>';
|
||
document.getElementById('cm-footer').innerHTML =
|
||
'<button onclick="window._closeContact()" style="background:linear-gradient(135deg,#1f4ea3,#3978e0);border:none;' +
|
||
'border-radius:9px;padding:.6rem 1.5rem;color:#fff;font-weight:700;cursor:pointer;font-family:Manrope,sans-serif;">Закрыть</button>';
|
||
} catch(e) {
|
||
errEl.textContent = e.message || 'Ошибка отправки';
|
||
errEl.style.display = 'block';
|
||
btn.disabled = false;
|
||
btn.textContent = 'Отправить';
|
||
}
|
||
}
|
||
|
||
document.getElementById('btn-contact-ruslan').addEventListener('click', openModal);
|
||
overlay.addEventListener('click', e => { if (e.target === overlay) window._closeContact(); });
|
||
document.addEventListener('keydown', e => { if (e.key === 'Escape') window._closeContact(); });
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|