UX overhaul: glassmorphism nav/footer, forms redesign, mobile fixes

Navigation:
- Nav bar pill shape (border-radius: 100px), dark glass style
- Icons added to all nav items (FA4 outline variants, fixed-width alignment)
- Footer hidden on all devices (nav panel covers mobile)
- Footer nav icons + text added before removal

Forms (ask.md, plan.md):
- Full glassmorphism redesign: rounded card, blur backdrop
- Input borders visible (#b8c4ce), focus ring, proper placeholder colors
- Select: self-contained CSS, no backdrop-filter conflict, arrow fixed
- Submit button: gradient with shadow
- File upload button: .file-btn class, fa-arrow-down icon
- form-note styled as info callout with left border + ⓘ icon
- Footnotes sup.fn: circular badge, baseline positioning (no line-height jump)
- Footnote ¹ on both consent checkboxes, accordion = full legal text
- Dark mode: opaque dark card (rgba 22,26,34,0.88), proper contrast
- Dark mode success/error messages adapted
- Double checkmark bug fixed (removed ::after overlay)
- Italic removed from privacy-details text

Layout:
- #main rounded corners (20px all sides) + margin for visibility
- Post card images rounded (border-radius: 10px)
- Page titles: uppercase removed, font-weight 900, left-aligned
- "Подробнее" button hidden on post cards
- iOS background-attachment: fixed bug fixed (scroll on mobile)
- Pagination mobile: counter restored, buttons above footer

Content:
- Page titles uncommented in front matter (gallery, map, ask, plan)
- Duplicate rawhtml title blocks removed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Kirik
2026-03-24 00:44:57 +01:00
parent e5fc0fa4e4
commit 3de138ff41
15 changed files with 964 additions and 541 deletions
+26 -41
View File
@@ -1,16 +1,12 @@
+++ +++
# title = 'Спросить' title = 'Хочу поехать'
slug = 'ask' slug = 'ask'
disableComments = true disableComments = true
+++ +++
{{< rawhtml >}} {{< rawhtml >}}
<h3 align="center">Задать вопрос</h3> <p class="page-lead">Есть вопрос или хотите предложить маршрут — напишите нам. <a href="/plan/">Смотреть календарь поездок →</a></p>
{{< /rawhtml >}} {{< /rawhtml >}}
Если у Вас есть вопрос или Вы хотите предложить свою локацию / тур для поездки, напишите в форме ниже. Мы вам с радостью ответим!
**Календарь поездок** можно посмотреть [здесь](/plan/)
{{< rawhtml >}} {{< rawhtml >}}
<div class="contact-form-container"> <div class="contact-form-container">
<!-- Сообщения об успехе/ошибке --> <!-- Сообщения об успехе/ошибке -->
@@ -57,12 +53,8 @@ disableComments = true
// Загружаем скрипт шифрования // Загружаем скрипт шифрования
const script = document.createElement('script'); const script = document.createElement('script');
script.src = '/js/encryption.js'; script.src = '/js/encryption.js';
script.onload = function() { script.onload = function() {};
console.log('✅ Скрипт шифрования загружен для формы ask'); script.onerror = function() {};
};
script.onerror = function() {
console.error('❌ Ошибка загрузки скрипта шифрования');
};
document.head.appendChild(script); document.head.appendChild(script);
}); });
@@ -83,12 +75,9 @@ disableComments = true
body: formData body: formData
}) })
.then(response => { .then(response => {
console.log('HTTP статус:', response.status);
console.log('Content-Type:', response.headers.get('content-type'));
return response.text(); return response.text();
}) })
.then(text => { .then(text => {
console.log('Ответ сервера:', text);
try { try {
const data = JSON.parse(text); const data = JSON.parse(text);
return data; return data;
@@ -147,19 +136,19 @@ disableComments = true
</div> </div>
<div class="form-note"> <div class="form-note">
<p>* Укажите email или Telegram ник (одно из двух обязательно)</p> <p>Укажите email или Telegram ник (одно из двух обязательно)</p>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="subject">Тема *</label> <label for="subject">Тема *</label>
<select id="subject" name="subject" required> <select id="subject" name="subject" required>
<option value="">Выберите тему...</option> <option value="" disabled selected></option>
<option value="работа сайта">Работа сайта</option> <option value="работа сайта">Работа сайта</option>
<option value="запланированные мероприятия">Запланированные мероприятия</option> <option value="запланированные мероприятия">Запланированные мероприятия</option>
<option value="пройденные маршруты">Пройденные маршруты</option> <option value="пройденные маршруты">Пройденные маршруты</option>
<option value="условия участия">Условия участия</option> <option value="условия участия">Условия участия</option>
<option value="условия сотрудничества">Условия сотрудничества</option> <option value="условия сотрудничества">Условия сотрудничества</option>
<option value="хочу предложить поездку">Хочу предложить поездку</option> <option value="хочу предложить поездку">Предложить поездку</option>
<option value="контакты для связи">Контакты для связи</option> <option value="контакты для связи">Контакты для связи</option>
</select> </select>
</div> </div>
@@ -175,7 +164,7 @@ disableComments = true
<input type="checkbox" id="privacy_consent" name="privacy_consent" required> <input type="checkbox" id="privacy_consent" name="privacy_consent" required>
<span class="checkmark"></span> <span class="checkmark"></span>
<span class="privacy-text"> <span class="privacy-text">
Я согласен на обработку персональных данных в соответствии с ФЗ №152 <sup>1</sup> Я согласен на обработку персональных данных в соответствии с ФЗ №152 <sup class="fn">1</sup>
<div class="privacy-details"> <div class="privacy-details">
<p>Данные будут обрабатываться для ответа на ваш вопрос.</p> <p>Данные будут обрабатываться для ответа на ваш вопрос.</p>
<p>Согласие действует 1 месяц. Отзыв согласия: <a href="mailto:sleep-trip@ya.ru">sleep-trip@ya.ru</a></p> <p>Согласие действует 1 месяц. Отзыв согласия: <a href="mailto:sleep-trip@ya.ru">sleep-trip@ya.ru</a></p>
@@ -191,26 +180,22 @@ disableComments = true
</div> </div>
{{< /rawhtml >}} {{< /rawhtml >}}
--- {{< rawhtml >}}
<details class="legal-details">
### Пояснения к форме: <summary><sup class="fn">1</sup> Постановка «галочки» в чекбоксе является подтверждением вашего согласия — читать полный текст (ФЗ №152)</summary>
<div class="legal-text">
<sup>1</sup> **Согласие на обработку персональных данных:** <p>Заполнение «чек-бокса» (проставление «галочки»/«веб-метки» на сайте sleeptrip.ru в графе «Я согласен на обработку персональных данных») и нажатие соответствующей кнопки и (или) направление персональных данных (фамилия, имя, телефон, имя (ник) в Телеграм) в ответном письме на адрес: sleep-trip@ya.ru является подтверждением Вашего согласия на обработку персональных данных либо с целью получения разрешения на полёты беспилотного воздушного судна (БВС), либо с целью ответа на вопрос, заданный на сайте sleeptrip.ru.</p>
<p>Предоставленные персональные данные будут обрабатываться в соответствии с положениями Федерального закона Российской Федерации №152-ФЗ от 27.07.2006 «О персональных данных».</p>
Заполнение «чек-бокса» (проставление «галочки»/ «веб-метки» на сайте sleeptrip.ru в графе «Я согласен на обработку персональных данных») и нажатие соответствующей кнопки и (или) направление персональных данных (фамилия, имя, телефон, имя (ник) в Телеграм) в ответном письме на адрес: sleep-trip@ya.ru является подтверждением Вашего согласия на обработку персональных данных либо с целью получения разрешения на полёты беспилотного воздушного судна (БВС), либо с целью ответа на вопрос, заданный на сайте sleeptrip.ru. <p>Заявление об уточнении персональных данных, отзыве настоящего согласия может быть направлено по электронной почте по адресу: <a href="mailto:sleep-trip@ya.ru">sleep-trip@ya.ru</a>.</p>
<p>Я выражаю свое согласие на обработку, включая: сбор, запись, систематизацию, накопление, хранение, уточнение (обновление, изменение), извлечение, использование, передачу (предоставление, доступ), блокирование, обезличивание, удаление, уничтожение, своих персональных данных (в случае предоставления мной) Оператору (владельцу сайта sleeptrip.ru) для целей:</p>
Предоставленные персональные данные будут обрабатываться в соответствии с положениями Федерального закона Российской Федерации №152-ФЗ от 27.07.2006 «О персональных данных». <ul>
<li>обеспечения получения разрешения на полёты БВС и направления мне информационных сообщений о статусе получения такого разрешения;</li>
Заявление об уточнении персональных данных, отзыве настоящего согласия может быть направлено по электронной почте по адресу: sleep-trip@ya.ru. <li>ответа на вопрос, заданный на сайте sleeptrip.ru.</li>
</ul>
Я выражаю свое согласие на обработку, включая: сбор, запись, систематизацию, накопление, хранение, уточнение (обновление, изменение), извлечение, использование, передачу (предоставление, доступ), блокирование, обезличивание, удаление, уничтожение, своих персональных данных (в случае предоставления мной) Оператору (владельцу сайта sleeptrip.ru) для целей: <p>Я согласен и разрешаю Оператору обрабатывать мои персональные данные с использованием средств автоматизации или без использования таких средств (смешанная обработка).</p>
<p>Я согласен с тем, что мои персональные данные будут переданы третьим лицам – Единой системе организации воздушного движения, сервису «Небосвод» (skyarc.ru) или сервису СППИ (sppi.ivprf.ru), а также сотрудникам полиции (в случае взаимодействия с ними на местности) для реализации целей обработки персональных данных — получения разрешения на полёты БВС. Без передачи данных указанным организациям реализация целей обработки персональных данных будет невозможна.</p>
- обеспечения получения разрешения на полёты БВС и направления мне информационных сообщений о статусе получения такого разрешения; <p>Настоящее Согласие действует до момента достижения целей обработки или отзыва согласия на обработку, но не более 1 (одного) месяца с момента предоставления Согласия.</p>
- ответа на вопрос, заданный на сайте sleeptrip.ru. </div>
</details>
Я согласен и разрешаю Оператору обрабатывать мои персональные данные с использованием средств автоматизации или без использования таких средств (смешанная обработка). {{< /rawhtml >}}
Я согласен с тем, что мои персональные данные будут переданы третьим лицам – Единой системе организации воздушного движения, сервису "Небосвод" (skyarc.ru) или сервису СППИ (https://sppi.ivprf.ru), а также сотрудникам полиции (в случае взаимодействия с ними на местности) для реализации целей обработки персональных данных - получения разрешения на полёты БВС. Без передачи данных указанным организациям (сервисам) реализация целей обработки персональных данных будет невозможна.
Настоящее Согласие действует до момента достижения целей обработки или отзыва согласия на обработку, но не более 1 (одного) месяца с момента предоставления Согласия.
+34 -56
View File
@@ -1,11 +1,9 @@
+++ +++
title = 'Предстоящие поездки'
slug = 'plan' slug = 'plan'
# description = 'Выберите поездку из календаря'
disableComments = true disableComments = true
+++ +++
{{< rawhtml >}} {{< rawhtml >}}
<h3 align="center">Предстоящие поездки</h3>
<!-- Календарь поездок из upcoming-trips.json --> <!-- Календарь поездок из upcoming-trips.json -->
<div id="trips-grid" class="trips-calendar"> <div id="trips-grid" class="trips-calendar">
<!-- Карточки поездок будут загружены динамически --> <!-- Карточки поездок будут загружены динамически -->
@@ -76,29 +74,20 @@ disableComments = true
// Загружаем скрипт шифрования // Загружаем скрипт шифрования
const encryptionScript = document.createElement('script'); const encryptionScript = document.createElement('script');
encryptionScript.src = '/js/encryption.js'; encryptionScript.src = '/js/encryption.js';
encryptionScript.onload = function() { encryptionScript.onload = function() {};
console.log('✅ Скрипт шифрования загружен для формы plan'); encryptionScript.onerror = function() {};
};
encryptionScript.onerror = function() {
console.error('❌ Ошибка загрузки скрипта шифрования');
};
document.head.appendChild(encryptionScript); document.head.appendChild(encryptionScript);
// Загружаем скрипт динамического заполнения поездок // Загружаем скрипт динамического заполнения поездок
const tripScript = document.createElement('script'); const tripScript = document.createElement('script');
tripScript.src = '/js/trip-form-loader.js'; tripScript.src = '/js/trip-form-loader.js';
tripScript.onload = function() { tripScript.onload = function() {
console.log('✅ Скрипт загрузчика поездок загружен');
// Принудительно инициализируем после загрузки скрипта
if (typeof TripFormLoader !== 'undefined') { if (typeof TripFormLoader !== 'undefined') {
window.tripFormLoader = new TripFormLoader(); window.tripFormLoader = new TripFormLoader();
window.tripFormLoader.populateTripsDropdown(); window.tripFormLoader.populateTripsDropdown();
console.log('🔄 Принудительная инициализация загрузчика поездок');
} }
}; };
tripScript.onerror = function() { tripScript.onerror = function() {};
console.error('❌ Ошибка загрузки скрипта поездок');
};
document.head.appendChild(tripScript); document.head.appendChild(tripScript);
}); });
@@ -119,12 +108,9 @@ disableComments = true
body: formData body: formData
}) })
.then(response => { .then(response => {
console.log('HTTP статус:', response.status); return response.text();
console.log('Content-Type:', response.headers.get('content-type'));
return response.text(); // Сначала получаем как текст
}) })
.then(text => { .then(text => {
console.log('Ответ сервера:', text);
try { try {
const data = JSON.parse(text); const data = JSON.parse(text);
return data; return data;
@@ -188,19 +174,19 @@ disableComments = true
</div> </div>
<div class="form-note"> <div class="form-note">
<p>* Укажите email или Telegram ник (одно из двух обязательно)</p> <p>Укажите email или Telegram ник (одно из двух обязательно)</p>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="bvs_number"><strong>Учётный номер для БВС от 0,15 кг или серийный номер для БВС до 0,15 кг *</strong></label> <label for="bvs_number">Учётный номер БВС *</label>
<textarea id="bvs_number" name="bvs_number" placeholder="Укажите учётный номер для БВС от 0,15 кг или серийный номер для БВС до 0,15 кг" required></textarea> <textarea id="bvs_number" name="bvs_number" placeholder="БВС от 0,15 кг — учётный номер, например: 123456789AB&#10;БВС до 0,15 кг серийный номер с фюзеляжа" required></textarea>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="bvs_file">Загрузите уведомление в .pdf о постановке на учёт БВС от 0,15 кг, заявки без указанного уведомления не будут рассмотрены. Для БВС до 0,15 кг будут отдельно запрошены фотографии с серийным номером на фюзеляже БВС</label> <label for="bvs_file">Уведомление о постановке на учёт (.pdf)<br><small style="font-weight:400; color:#888;">Для БВС от 0,15 кг обязательно. Для БВС до 0,15 кг — фото с серийным номером запросим отдельно</small></label>
<div style="margin-top: 10px;"> <div style="margin-top: 10px;">
<label for="bvs_file" style="display: inline-block; padding: 10px 20px; background-color: #007bff; color: white; border-radius: 4px; cursor: pointer; font-weight: bold;">Выбрать файл</label> <label for="bvs_file" class="file-btn"><i class="icon fa-arrow-down"></i>&nbsp;&nbsp;Выбрать файл</label>
<span id="file-name" style="margin-left: 10px; color: #666;"></span> <span id="file-name" class="file-name-display"></span>
</div> </div>
<input type="file" id="bvs_file" name="bvs_file" accept=".pdf" style="display: none;"> <input type="file" id="bvs_file" name="bvs_file" accept=".pdf" style="display: none;">
</div> </div>
@@ -215,7 +201,7 @@ disableComments = true
<div class="form-group"> <div class="form-group">
<label for="trip_period">Выберите мероприятие</label> <label for="trip_period">Выберите мероприятие</label>
<select id="trip_period" name="trip_period"> <select id="trip_period" name="trip_period">
<option value=""></option> <option value="" disabled selected></option>
<!-- Опции будут загружены динамически из upcoming-trips.json --> <!-- Опции будут загружены динамически из upcoming-trips.json -->
</select> </select>
</div> </div>
@@ -227,7 +213,7 @@ disableComments = true
<input type="checkbox" id="privacy_consent" name="privacy_consent" required> <input type="checkbox" id="privacy_consent" name="privacy_consent" required>
<span class="checkmark"></span> <span class="checkmark"></span>
<span class="privacy-text"> <span class="privacy-text">
Я выражаю своё согласие на обработку персональных данных Я выражаю своё согласие на обработку персональных данных <sup class="fn">1</sup>
<div class="privacy-details"> <div class="privacy-details">
<p>Персональные данные обрабатываются исключительно для получения разрешения на полёты БВС. Согласие действует 1 месяц. Отзыв согласия – заявление на sleep-trip@ya.ru</p> <p>Персональные данные обрабатываются исключительно для получения разрешения на полёты БВС. Согласие действует 1 месяц. Отзыв согласия – заявление на sleep-trip@ya.ru</p>
</div> </div>
@@ -240,7 +226,7 @@ disableComments = true
<input type="checkbox" id="age_consent" name="age_consent" required> <input type="checkbox" id="age_consent" name="age_consent" required>
<span class="checkmark"></span> <span class="checkmark"></span>
<span class="privacy-text"> <span class="privacy-text">
Мне есть 18 лет <sup>2</sup> Мне есть 18 лет <sup class="fn">2</sup>
</span> </span>
</label> </label>
</div> </div>
@@ -252,31 +238,23 @@ disableComments = true
</div> </div>
{{< /rawhtml >}} {{< /rawhtml >}}
--- {{< rawhtml >}}
<details class="legal-details">
### Пояснения к форме: <summary><sup class="fn">1</sup> Постановка «галочки» в чекбоксе является подтверждением вашего согласия — читать полный текст (ФЗ №152)</summary>
<div class="legal-text">
<sup>1</sup> **Согласие на обработку персональных данных:** <p>Заполнение «чек-бокса» (проставление «галочки»/«веб-метки» на сайте sleeptrip.ru в графе «Я согласен на обработку персональных данных») и нажатие соответствующей кнопки и (или) направление персональных данных (фамилия, имя, телефон, имя (ник) в Телеграм) в ответном письме на адрес: sleep-trip@ya.ru является подтверждением Вашего согласия на обработку персональных данных либо с целью получения разрешения на полёты беспилотного воздушного судна (БВС), либо с целью ответа на вопрос, заданный на сайте sleeptrip.ru.</p>
<p>Предоставленные персональные данные будут обрабатываться в соответствии с положениями Федерального закона Российской Федерации №152-ФЗ от 27.07.2006 «О персональных данных».</p>
Заполнение «чек-бокса» (проставление «галочки»/ «веб-метки» на сайте sleeptrip.ru в графе «Я согласен на обработку персональных данных») и нажатие соответствующей кнопки и (или) направление персональных данных (фамилия, имя, телефон, имя (ник) в Телеграм) в ответном письме на адрес: sleep-trip@ya.ru является подтверждением Вашего согласия на обработку персональных данных либо с целью получения разрешения на полёты беспилотного воздушного судна (БВС), либо с целью ответа на вопрос, заданный на сайте sleeptrip.ru. <p>Заявление об уточнении персональных данных, отзыве настоящего согласия может быть направлено по электронной почте по адресу: <a href="mailto:sleep-trip@ya.ru">sleep-trip@ya.ru</a>.</p>
<p><strong>СОГЛАСИЕ НА ОБРАБОТКУ ПЕРСОНАЛЬНЫХ ДАННЫХ</strong></p>
Предоставленные персональные данные будут обрабатываться в соответствии с положениями Федерального закона Российской Федерации №152-ФЗ от 27.07.2006 «О персональных данных». <p>Я выражаю свое согласие на обработку, включая: сбор, запись, систематизацию, накопление, хранение, уточнение (обновление, изменение), извлечение, использование, передачу (предоставление, доступ), блокирование, обезличивание, удаление, уничтожение, своих персональных данных (в случае предоставления мной) Оператору (владельцу сайта sleeptrip.ru) для целей:</p>
<ul>
Заявление об уточнении персональных данных, отзыве настоящего согласия может быть направлено по электронной почте по адресу: sleep-trip@ya.ru. <li>обеспечения получения разрешения на полёты БВС и направления мне информационных сообщений о статусе получения такого разрешения;</li>
<li>ответа на вопрос, заданный на сайте sleeptrip.ru.</li>
<div style="text-align: center; font-weight: bold; margin: 20px 0;">СОГЛАСИЕ НА ОБРАБОТКУ ПЕРСОНАЛЬНЫХ ДАННЫХ</div> </ul>
<p>Я согласен и разрешаю Оператору обрабатывать мои персональные данные с использованием средств автоматизации или без использования таких средств (смешанная обработка).</p>
Я выражаю свое согласие на обработку, включая: сбор, запись, систематизацию, накопление, хранение, уточнение (обновление, изменение), извлечение, использование, передачу (предоставление, доступ), блокирование, обезличивание, удаление, уничтожение, своих персональных данных (в случае предоставления мной) Оператору (владельцу сайта sleeptrip.ru) для целей: <p>Я согласен с тем, что мои персональные данные будут переданы третьим лицам – Единой системе организации воздушного движения, сервису «Небосвод» (skyarc.ru) или сервису СППИ (sppi.ivprf.ru), а также сотрудникам полиции (в случае взаимодействия с ними на местности) для реализации целей обработки персональных данных — получения разрешения на полёты БВС. Без передачи данных указанным организациям реализация целей обработки персональных данных будет невозможна.</p>
<p>Настоящее Согласие действует до момента достижения целей обработки или отзыва согласия на обработку, но не более 1 (одного) месяца с момента предоставления Согласия.</p>
- обеспечения получения разрешения на полёты БВС и направления мне информационных сообщений о статусе получения такого разрешения; </div>
- ответа на вопрос, заданный на сайте sleeptrip.ru. </details>
<p class="legal-note"><sup class="fn">2</sup> Отметка подтверждает, что участнику поездки исполнилось 18 лет.</p>
Я согласен и разрешаю Оператору обрабатывать мои персональные данные с использованием средств автоматизации или без использования таких средств (смешанная обработка). {{< /rawhtml >}}
Я согласен с тем, что мои персональные данные будут переданы третьим лицам – Единой системе организации воздушного движения, сервису "Небосвод" (skyarc.ru) или сервису СППИ (https://sppi.ivprf.ru), а также сотрудникам полиции (в случае взаимодействия с ними на местности) для реализации целей обработки персональных данных - получения разрешения на полёты БВС. Без передачи данных указанным организациям (сервисам) реализация целей обработки персональных данных будет невозможна.
Настоящее Согласие действует до момента достижения целей обработки или отзыва согласия на обработку, но не более 1 (одного) месяца с момента предоставления Согласия.
<sup>2</sup> **Подтверждение совершеннолетия:** Поставление отметки в данном поле подтверждает, что вам исполнилось 18 лет.
---
+5 -1
View File
@@ -1,13 +1,17 @@
items: items:
- title: 'Хочу поехать' - title: 'Хочу поехать'
url: '/plan' url: '/plan'
icon: 'fa-calendar-o'
- title: 'Маршруты' - title: 'Маршруты'
url: '/map' url: '/map'
icon: 'fa-map-o'
- title: 'Спросить' - title: 'Спросить'
url: '/ask' url: '/ask'
icon: 'fa-envelope-o'
- title: 'Галерея' - title: 'Галерея'
url: '/gallery' url: '/gallery'
icon: 'fa-picture-o'
+5 -1
View File
@@ -1,13 +1,17 @@
items: items:
- title: 'Хочу поехать' - title: 'Хочу поехать'
url: '/plan' url: '/plan'
icon: 'fa-calendar-o'
- title: 'Маршруты' - title: 'Маршруты'
url: '/map' url: '/map'
icon: 'fa-map-o'
- title: 'Спросить' - title: 'Спросить'
url: '/ask' url: '/ask'
icon: 'fa-envelope-o'
- title: 'Галерея' - title: 'Галерея'
url: '/gallery' url: '/gallery'
icon: 'fa-picture-o'
+40
View File
@@ -0,0 +1,40 @@
<!-- Nav -->
{{ $data := index .Site.Data .Site.Language.Lang }}
{{ $currentPage := .Page }}
<nav id="nav">
<ul class="links">
<li class="{{ if eq ($currentPage.RelPermalink) (`/`) }}active{{end}}">
<a href='{{ "/" | relLangURL }}' class="nav-link">
<i class="icon fa-home nav-icon"></i>
<span>Главная</span>
</a>
</li>
{{- with $data.nav.items -}}
{{- range $i, $e := . -}}
<li class="{{ if eq ($currentPage.RelPermalink) (print .url `/`) }}active{{end}}">
<a href='{{ .url | relLangURL }}' class="nav-link">
{{- with .icon -}}<i class="icon {{ . }} nav-icon"></i>{{- end -}}
<span>{{- .title -}}</span>
</a>
</li>
{{- end -}}
{{- end -}}
{{ with $data.contactinfo }}
{{ end }}
{{ if .IsTranslated }}
{{ range .AllTranslations }}
<li {{if eq ($.Site.Language) (.Language)}}class="active"{{end}}><a href='{{ .Permalink }}'>{{ .Language.LanguageName }}</a></li>
{{ end }}
{{ end }}
</ul>
{{ with $data.social }}
<ul class="icons">
{{ with .telegram }}
<li><a href="{{ . }}" class="icon fa-telegram"><span class="label">Telegram</span></a></li>
{{ end }}
{{ with .youtube }}
<li><a href="{{ . }}" class="icon fa-youtube"><span class="label">Youtube</span></a></li>
{{ end }}
</ul>
{{ end }}
</nav>
+3 -2
View File
@@ -7,8 +7,9 @@
linear-gradient(0deg, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1)), linear-gradient(0deg, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1)),
url('../../images/mobile4.webp') !important; url('../../images/mobile4.webp') !important;
background-size: cover; background-size: cover;
background-position: center; background-position: center top;
background-attachment: fixed; /* iOS Safari не поддерживает background-attachment: fixed нормально */
background-attachment: scroll;
} }
} }
+87 -74
View File
@@ -1,74 +1,87 @@
/* Горизонтальное меню в футере */ /* Меняем светлый фон футера (#f5f5f5) на тёмный под стиль сайта */
.footer-nav-links { #footer {
list-style: none; background: rgba(0, 0, 0, 0.3) !important;
padding: 0; backdrop-filter: blur(10px) !important;
margin: 0; -webkit-backdrop-filter: blur(10px) !important;
display: flex; border-top: 1px solid rgba(255, 255, 255, 0.08) !important;
flex-direction: row; border-radius: 20px 20px 0 0 !important;
justify-content: center; }
flex-wrap: wrap;
gap: 2rem; /* Скрываем футер везде — навигация есть в #nav и мобильной панели */
} #footer {
display: none !important;
.footer-nav-link { }
display: flex;
flex-direction: column; /* Текст и заголовки в футере на тёмном фоне */
align-items: center; #footer h3,
padding: 0.75rem 1rem; #footer p,
color: #ffffff; #footer a:not(.footer-nav-link) {
text-decoration: none; color: rgba(255, 255, 255, 0.5) !important;
font-size: 0.85rem; border-bottom-color: transparent !important;
font-weight: 400; }
transition: all 0.3s ease;
border-radius: 6px; #footer a:not(.footer-nav-link):hover {
background: rgba(255, 255, 255, 0.05); color: rgba(255, 255, 255, 0.85) !important;
min-width: 80px; }
}
/* Footer nav — icon left + text, единый стиль с #nav */
.footer-nav-link:hover {
color: #18bfef; #footer .footer-nav-links {
background: rgba(24, 191, 239, 0.1); list-style: none;
transform: translateY(-3px); padding: 0;
text-decoration: none; margin: 0;
} display: flex;
flex-direction: row;
.footer-nav-link .icon { justify-content: center;
font-size: 1.2rem; flex-wrap: wrap;
margin-bottom: 0.4rem; gap: 0;
opacity: 0.9; }
}
#footer .footer-nav-link {
.footer-nav-link:hover .icon { display: flex;
opacity: 1; flex-direction: row;
} align-items: center;
gap: 0.4rem;
.footer-nav-link span { padding: 0 1.3rem;
color: #ffffff; height: 3.5rem;
font-weight: 500; color: rgba(255, 255, 255, 0.75);
} text-decoration: none;
border-bottom: none;
/* Адаптивность для мобильных */ font-family: 'Source Sans Pro', Helvetica, sans-serif;
@media (max-width: 768px) { font-size: 0.78rem;
.footer-nav-links { font-weight: 900;
gap: 1rem; letter-spacing: 0.07em;
} text-transform: uppercase;
transition: color 0.2s ease, background 0.2s ease;
.footer-nav-link { }
padding: 0.6rem 0.8rem;
font-size: 0.8rem; #footer .footer-nav-link:hover {
min-width: 70px; color: #ffffff;
} background: rgba(255, 255, 255, 0.1);
border-bottom: none;
.footer-nav-link .icon { text-decoration: none;
font-size: 1rem; }
margin-bottom: 0.3rem;
} #footer .footer-nav-link .icon {
} font-size: 0.9rem;
color: inherit;
/* Стиль для заголовка секции */ opacity: 0.7;
#footer h3 { display: inline-block;
font-size: 1.1rem; line-height: 1;
margin-bottom: 1rem; flex-shrink: 0;
color: #ffffff; }
font-weight: 600;
} #footer .footer-nav-link:hover .icon {
opacity: 1;
}
#footer .footer-nav-link span {
color: inherit;
}
/* Мобильные: скрываем footer nav — есть боковое меню */
@media (max-width: 736px) {
#footer .footer-nav-links {
display: none !important;
}
}
+471 -147
View File
@@ -1,83 +1,112 @@
/* Стили для форм обратной связи */ /* Стили для форм обратной связи — glassmorphism 2025 */
.travel-form-container, .contact-form-container { .travel-form-container, .contact-form-container {
max-width: 600px; max-width: 580px;
margin: 2rem auto; margin: 0 auto 2rem;
background: rgba(255, 255, 255, 0.98); padding: 2.25rem 2.5rem;
padding: 2.5rem; background: rgba(255, 255, 255, 0.72);
backdrop-filter: blur(24px);
-webkit-backdrop-filter: blur(24px);
border-radius: 16px; border-radius: 16px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08); border: 1px solid rgba(255, 255, 255, 0.6);
backdrop-filter: blur(20px); box-shadow: 0 4px 24px rgba(0, 0, 0, 0.07), 0 1px 4px rgba(0, 0, 0, 0.04);
border: 1px solid rgba(255, 255, 255, 0.2);
} }
.travel-form, .contact-form { .travel-form, .contact-form {
width: 100%; width: 100%;
} }
/* Снимаем uppercase темы внутри форм */
.travel-form-container *,
.contact-form-container * {
text-transform: none;
letter-spacing: normal;
}
/* Разделитель секций — только капитализация первой буквы */
.travel-form-container .form-section-title,
.contact-form-container .form-section-title {
font-size: 0.72rem;
font-weight: 600;
color: #9aa3ad;
letter-spacing: 0.05em;
text-transform: uppercase; /* намеренно — tiny label */
}
.form-group { .form-group {
margin-bottom: 1.8rem; margin-bottom: 1.8rem;
} }
.form-group label { .form-group label {
display: block; display: block;
margin-bottom: 0.75rem; margin-bottom: 0.6rem;
font-weight: 500; font-weight: 600;
color: #2c3e50; color: #1e2d3d;
font-size: 0.95rem; font-size: 0.88rem;
line-height: 1.4; line-height: 1.45;
letter-spacing: 0.01em;
} }
.form-group input, .form-group input,
.form-group select,
.form-group textarea { .form-group textarea {
width: 100%; width: 100%;
padding: 1rem; padding: 0.85rem 1rem;
border: 1px solid #e1e5e9; border: 1.5px solid #b8c4ce;
border-radius: 12px; border-radius: 10px;
font-size: 0.95rem; font-size: 0.95rem;
background: #fafbfc; background: rgba(255, 255, 255, 0.92);
transition: all 0.3s ease; backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
box-sizing: border-box; box-sizing: border-box;
font-family: inherit; font-family: inherit;
color: #2c3e50; color: #1a252f;
} }
/* Select — полностью самодостаточное правило, без backdrop-filter */
.form-group select { .form-group select {
width: 100%; width: 100%;
padding: 1.5rem 3.5rem 2.5rem 1rem; padding: 0.95rem 2.5rem 1rem 1rem;
border: 1px solid #e1e5e9; border: 1.5px solid #b8c4ce;
border-radius: 12px; border-radius: 10px;
font-size: 0.9rem; font-size: 0.95rem;
background: white; background-color: rgba(255, 255, 255, 0.92);
color: #333; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
background-position: right 0.9rem center;
background-repeat: no-repeat;
background-size: 1.25rem 1.25rem;
color: #1a252f;
font-family: inherit; font-family: inherit;
appearance: none; appearance: none;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e"); -webkit-appearance: none;
background-position: right 0.75rem center; line-height: 1.7;
background-repeat: no-repeat; box-sizing: border-box;
background-size: 1.2em 1.2em; transition: border-color 0.2s, box-shadow 0.2s;
min-height: 5.5rem; cursor: pointer;
line-height: 1.3; min-height: 3rem;
transition: all 0.3s ease;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }
.form-group select option { .form-group select option {
background: white; background: #ffffff;
color: #333; color: #1a252f;
padding: 0.5rem;
} }
.form-group input:focus, .form-group input:focus,
.form-group select:focus,
.form-group textarea:focus { .form-group textarea:focus {
outline: none; outline: none;
border-color: #3498db; border-color: #4a8fc8;
background: white; background: #ffffff;
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1); box-shadow: 0 0 0 3px rgba(74, 143, 200, 0.18);
transform: translateY(-1px); }
.form-group select:focus {
outline: none;
border-color: #4a8fc8;
background-color: #ffffff;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%234a8fc8' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
background-position: right 0.9rem center;
background-repeat: no-repeat;
background-size: 1.25rem 1.25rem;
box-shadow: 0 0 0 3px rgba(74, 143, 200, 0.18);
} }
.form-group textarea { .form-group textarea {
@@ -86,15 +115,15 @@
} }
.submit-btn { .submit-btn {
background: transparent; background: linear-gradient(135deg, #4a8fc8 0%, #3476b5 100%);
color: #2c3e50; color: #ffffff;
padding: 1.2rem 2.5rem; padding: 0.9rem 2rem;
border: 2px solid #2c3e50; border: none;
border-radius: 12px; border-radius: 10px;
cursor: pointer; cursor: pointer;
font-size: 1rem; font-size: 0.95rem;
font-weight: 500; font-weight: 600;
transition: all 0.3s ease; transition: opacity 0.2s, transform 0.15s, box-shadow 0.2s;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -103,19 +132,20 @@
font-family: inherit; font-family: inherit;
letter-spacing: 0.3px; letter-spacing: 0.3px;
width: 100%; width: 100%;
margin-top: 1rem; margin-top: 0.5rem;
box-shadow: 0 2px 10px rgba(52, 118, 181, 0.3);
} }
.submit-btn:hover { .submit-btn:hover {
background: #2c3e50; opacity: 0.92;
color: white; transform: translateY(-1px);
transform: translateY(-2px); box-shadow: 0 5px 18px rgba(52, 118, 181, 0.4);
box-shadow: 0 8px 25px rgba(44, 62, 80, 0.2);
} }
.submit-btn:active { .submit-btn:active {
transform: translateY(0); transform: translateY(0);
box-shadow: 0 4px 15px rgba(44, 62, 80, 0.1); opacity: 1;
box-shadow: 0 2px 6px rgba(52, 118, 181, 0.25);
} }
.submit-btn i { .submit-btn i {
@@ -145,26 +175,51 @@
/* Мобильная адаптация */ /* Мобильная адаптация */
@media (max-width: 768px) { @media (max-width: 768px) {
.travel-form-container, .contact-form-container { .travel-form-container, .contact-form-container {
margin: 1rem; margin: 0;
padding: 1.5rem; padding: 1.5rem;
border-radius: 12px;
} }
.form-group {
margin-bottom: 1.1rem;
}
.form-group label {
margin-bottom: 0.4rem;
font-size: 0.88rem;
}
.form-group input, .form-group input,
.form-group select, .form-group select,
.form-group textarea { .form-group textarea {
padding: 0.65rem 0.8rem;
font-size: 16px; /* Предотвращает зум на iOS */ font-size: 16px; /* Предотвращает зум на iOS */
border-radius: 8px;
} }
.form-group select { .form-group select {
padding: 1.2rem 3rem 2rem 0.8rem; padding: 0.65rem 2.2rem 0.65rem 0.8rem;
min-height: 4.5rem; font-size: 16px;
font-size: 15px;
line-height: 1.2;
} }
.form-group textarea {
min-height: 80px;
}
.checkbox-group {
padding: 1rem;
margin: 1.2rem 0;
}
.submit-btn { .submit-btn {
width: 100%; width: 100%;
justify-content: center; justify-content: center;
padding: 0.9rem 1.5rem;
}
.form-subtitle {
margin-bottom: 1.2rem;
font-size: 0.88rem;
} }
} }
@@ -234,60 +289,109 @@
} }
.form-group label:has(input[type="checkbox"]:checked) { .form-group label:has(input[type="checkbox"]:checked) {
background-color: rgba(39, 174, 96, 0.1); background-color: rgba(39, 174, 96, 0.07);
border-color: rgba(39, 174, 96, 0.3); color: inherit;
color: #27ae60;
} }
.form-group label:has(input[type="checkbox"]:checked)::after, /* Подсказка — инфо-блок между полями */
.checkbox-label:has(input[type="checkbox"]:checked)::after { .form-note {
content: "✓"; margin: -0.6rem 0 1.4rem;
position: absolute; padding: 0.55rem 0.85rem;
left: 1rem; background: rgba(91, 155, 213, 0.07);
top: 50%; border-left: 2.5px solid rgba(91, 155, 213, 0.45);
transform: translateY(-50%); border-radius: 0 6px 6px 0;
color: #27ae60; font-size: 0.8rem;
font-size: 1.4em; color: #6b7f94;
font-weight: bold; line-height: 1.45;
animation: checkmark-appear 0.3s ease;
} }
@keyframes checkmark-appear { .form-note p {
0% { margin: 0;
opacity: 0;
transform: translateY(-50%) scale(0.5);
}
100% {
opacity: 1;
transform: translateY(-50%) scale(1);
}
} }
/* Специфичные стили для checkbox-label */ .form-note p::before {
.checkbox-label:has(input[type="checkbox"]):hover { content: "ⓘ ";
background-color: rgba(52, 152, 219, 0.05); font-style: normal;
color: #5b9bd5;
font-size: 0.9em;
} }
.checkbox-label:has(input[type="checkbox"]:checked) { /* Заголовок формы */
background-color: rgba(39, 174, 96, 0.1) !important; .form-title {
border-color: rgba(39, 174, 96, 0.3) !important; font-size: 1.4rem;
color: #27ae60 !important; font-weight: 700;
color: #1a252f;
margin-bottom: 0.4rem;
text-align: center;
}
.form-subtitle {
font-size: 0.92rem;
color: #7f8c8d;
text-align: center;
margin-bottom: 2rem;
line-height: 1.5;
}
/* Подводка под заголовком страницы */
.page-lead {
font-size: 1rem;
color: #555c63;
font-family: 'Source Sans Pro', Helvetica, sans-serif;
line-height: 1.65;
margin-bottom: 2rem;
text-align: left;
}
.page-lead a {
color: #5b9bd5;
text-decoration: none;
border-bottom: none;
}
.page-lead a:hover {
color: #4585c2;
}
/* Разделитель секций */
.form-section-title {
font-size: 0.78rem;
font-weight: 600;
color: #95a5a6;
text-transform: uppercase;
letter-spacing: 0.08em;
margin: 2rem 0 1rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid #f0f0f0;
} }
/* Плейсхолдеры */ /* Плейсхолдеры */
.form-group input::placeholder, .form-group input::placeholder,
.form-group textarea::placeholder { .form-group textarea::placeholder {
color: #95a5a6; color: #8896a0;
opacity: 1; opacity: 1;
} }
/* Select в состоянии placeholder (required:invalid или has disabled:checked) */
.form-group select:required:invalid,
.form-group select:has(option[value=""]:checked) {
color: #8896a0;
}
@media (prefers-color-scheme: dark) {
.form-group select:required:invalid,
.form-group select:has(option[value=""]:checked) {
color: rgba(255, 255, 255, 0.32);
}
}
/* Стили для согласия на обработку персональных данных */ /* Стили для согласия на обработку персональных данных */
.checkbox-group { .checkbox-group {
background: rgba(52, 152, 219, 0.05); background: rgba(74, 143, 200, 0.07);
border: 1px solid rgba(52, 152, 219, 0.2); border: 1.5px solid rgba(74, 143, 200, 0.3);
border-radius: 12px; border-radius: 12px;
padding: 1.5rem; padding: 1.25rem 1.5rem;
margin: 2rem 0; margin: 1.5rem 0;
} }
.checkbox-container { .checkbox-container {
@@ -321,9 +425,9 @@
border: none; border: none;
border-radius: 0; border-radius: 0;
font-size: 0.8rem; font-size: 0.8rem;
line-height: 1.3; line-height: 1.4;
color: #888; color: #888;
font-style: italic; font-style: normal;
} }
.privacy-details p { .privacy-details p {
@@ -473,74 +577,294 @@
font-style: italic; font-style: italic;
} }
/* Интеграция с темой сайта */ /* Нумерованные сноски — маленькие круглые бейджи */
sup.fn {
display: inline-block;
min-width: 1.4em;
height: 1.4em;
line-height: 1.4em;
text-align: center;
background: rgba(91, 155, 213, 0.18);
color: #5b9bd5 !important;
border-radius: 50%;
font-size: 0.58em;
font-weight: 700;
vertical-align: baseline;
position: relative;
top: -0.5em;
margin-left: 0.25em;
text-decoration: none !important;
font-style: normal;
}
/* Сворачиваемый юридический текст — без рамки */
.legal-details {
margin-top: 1.5rem;
}
.legal-details summary {
padding: 0.4rem 0;
font-size: 0.8rem;
color: #5b9bd5;
cursor: pointer;
list-style: none;
user-select: none;
display: inline-flex;
align-items: baseline;
gap: 0.35rem;
text-decoration: underline;
text-decoration-color: rgba(91, 155, 213, 0.4);
text-underline-offset: 3px;
transition: color 0.2s, text-decoration-color 0.2s;
line-height: 1.5;
}
.legal-details summary sup.fn {
flex-shrink: 0;
text-decoration: none;
}
.legal-details summary::-webkit-details-marker {
display: none;
}
.legal-details summary::after {
content: "↓";
font-size: 0.85em;
transition: transform 0.2s ease;
display: inline-block;
text-decoration: none;
}
.legal-details[open] summary::after {
transform: rotate(180deg);
}
.legal-details summary:hover {
color: #4585c2;
text-decoration-color: rgba(69, 133, 194, 0.6);
}
.legal-text {
padding: 0.75rem 0 0;
font-size: 0.79rem;
color: #8a9199;
line-height: 1.65;
}
.legal-text p {
margin: 0 0 0.7rem;
}
.legal-text p:last-child {
margin-bottom: 0;
}
.legal-text a {
color: #3498db;
text-decoration: none;
}
.legal-text a:hover {
text-decoration: underline;
}
.legal-note {
font-size: 0.78rem;
color: #aaa;
margin-top: 0.75rem;
line-height: 1.5;
}
/* Кнопка загрузки файла — единый стиль с формой */
.file-btn {
display: inline-flex;
align-items: center;
gap: 0.4rem;
padding: 0.7rem 1.4rem;
background: rgba(91, 155, 213, 0.1);
color: #5b9bd5;
border: 1.5px solid rgba(91, 155, 213, 0.35);
border-radius: 8px;
font-size: 0.88rem;
font-weight: 500;
cursor: pointer;
transition: background 0.2s, border-color 0.2s;
font-family: inherit;
}
.file-btn:hover {
background: rgba(91, 155, 213, 0.18);
border-color: #5b9bd5;
}
.file-name-display {
margin-left: 0.75rem;
font-size: 0.82rem;
color: #7f8c8d;
}
@media (prefers-color-scheme: dark) {
.file-btn {
color: #7ab3e0;
border-color: rgba(91, 155, 213, 0.3);
background: rgba(91, 155, 213, 0.08);
}
.file-name-display {
color: #888;
}
}
/* Тёмная тема — тёмная карточка с достаточным контрастом */
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
.travel-form-container, .contact-form-container { .travel-form-container, .contact-form-container {
background: rgba(30, 30, 30, 0.95); background: rgba(22, 26, 34, 0.88);
backdrop-filter: blur(28px);
-webkit-backdrop-filter: blur(28px);
border-color: rgba(255, 255, 255, 0.1);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45), 0 1px 6px rgba(0, 0, 0, 0.3);
} }
.form-group label { .form-group label {
color: #e0e0e0; color: #dde3ea;
} }
.form-group input, .form-group input,
.form-group select, .form-group select,
.form-group textarea { .form-group textarea {
background: rgba(50, 50, 50, 0.8); background: rgba(255, 255, 255, 0.07);
border-color: #555; border-color: rgba(255, 255, 255, 0.16);
color: #e0e0e0; color: #e8edf4;
} }
.form-group select {
background-color: rgba(255, 255, 255, 0.07);
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%23aab2bb' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
background-position: right 0.9rem center;
background-repeat: no-repeat;
background-size: 1.25rem 1.25rem;
border-color: rgba(255, 255, 255, 0.16);
color: #e8edf4;
}
.form-group select option {
background: #1e2533;
color: #e8edf4;
}
.form-group select:focus {
background-color: rgba(255, 255, 255, 0.11);
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236aaee0' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
background-position: right 0.9rem center;
background-repeat: no-repeat;
background-size: 1.25rem 1.25rem;
}
.form-group input::placeholder,
.form-group textarea::placeholder {
color: rgba(255, 255, 255, 0.32);
}
.form-group input:focus, .form-group input:focus,
.form-group select:focus, .form-group select:focus,
.form-group textarea:focus { .form-group textarea:focus {
border-color: #4a9eff; border-color: #6aaee0;
background: rgba(255, 255, 255, 0.11);
box-shadow: 0 0 0 3px rgba(106, 174, 224, 0.2);
} }
.submit-btn {
background: linear-gradient(135deg, #3d82be 0%, #2d6aa8 100%);
box-shadow: 0 2px 10px rgba(45, 106, 168, 0.4);
}
.submit-btn:hover {
opacity: 0.9;
box-shadow: 0 5px 18px rgba(45, 106, 168, 0.5);
}
.form-note {
background: rgba(91, 155, 213, 0.1);
border-left-color: rgba(91, 155, 213, 0.5);
color: #8ca8c4;
}
.form-note p::before {
color: #7ab3e0;
}
.form-subtitle {
color: #99a6b0;
}
.checkbox-group { .checkbox-group {
background: rgba(52, 152, 219, 0.1); background: rgba(91, 155, 213, 0.1);
border-color: rgba(52, 152, 219, 0.3); border-color: rgba(91, 155, 213, 0.3);
} }
.privacy-text { .privacy-text {
color: #e0e0e0; color: #c8d4de;
} }
.privacy-details { .privacy-details {
background: rgba(40, 40, 40, 0.8); color: #8a9baa;
border-color: rgba(52, 152, 219, 0.3);
color: #ccc;
} }
.privacy-details strong { .privacy-details a {
color: #e0e0e0; color: #7ab3e0;
} }
.file-input-wrapper { .legal-details summary {
background: rgba(50, 50, 50, 0.8); color: #7ab3e0;
border-color: #555; text-decoration-color: rgba(122, 179, 224, 0.4);
color: #aaa;
} }
.file-input-wrapper:hover { .legal-text {
border-color: #4a9eff; color: #8fa4b8;
background: rgba(50, 50, 50, 0.9);
} }
.file-input-wrapper:focus-within { .legal-text a {
border-color: #4a9eff; color: #7ab3e0;
background: rgba(50, 50, 50, 0.9);
} }
.file-input-text { .legal-note {
color: #aaa; color: #6a7884;
} }
.file-input-text.file-selected { /* Success/error в тёмной теме */
color: #5dade2; .form-success {
background: rgba(39, 174, 96, 0.15);
color: #6ecf9a;
border-color: rgba(39, 174, 96, 0.3);
} }
.file-info small { .form-error {
color: #aaa; background: rgba(231, 76, 60, 0.15);
color: #f08080;
border-color: rgba(231, 76, 60, 0.3);
}
.form-group label:has(input[type="checkbox"]:checked) {
background-color: rgba(39, 174, 96, 0.1);
}
sup.fn {
background: rgba(122, 179, 224, 0.2);
color: #7ab3e0 !important;
}
.file-btn {
background: rgba(91, 155, 213, 0.15);
color: #7ab3e0;
border-color: rgba(91, 155, 213, 0.35);
}
.file-btn:hover {
background: rgba(91, 155, 213, 0.25);
border-color: #7ab3e0;
}
.file-name-display {
color: #7a8896;
} }
} }
+17 -13
View File
@@ -1,25 +1,29 @@
/* Улучшенная мобильная кнопка меню */ /* Кнопка открытия меню */
#navPanelToggle { #navPanelToggle {
background: rgba(255, 255, 255, 0.15) !important; background: rgba(18, 22, 28, 0.75) !important;
backdrop-filter: blur(10px) !important; backdrop-filter: blur(12px) !important;
border: 1px solid rgba(255, 255, 255, 0.3) !important; -webkit-backdrop-filter: blur(12px) !important;
color: white !important; border: 1px solid rgba(255, 255, 255, 0.15) !important;
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.8) !important; border-radius: 6px !important;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2) !important; color: rgba(255, 255, 255, 0.9) !important;
border-radius: 8px !important; text-shadow: none !important;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.4) !important;
font-family: 'Source Sans Pro', Helvetica, sans-serif !important;
font-weight: 900 !important;
letter-spacing: 0.075em !important;
text-transform: uppercase !important;
} }
#navPanelToggle:hover { #navPanelToggle:hover {
background: rgba(255, 255, 255, 0.25) !important; background: rgba(18, 22, 28, 0.92) !important;
transform: translateY(-1px) !important; color: #ffffff !important;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3) !important; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5) !important;
} }
/* Улучшение для очень маленьких экранов */
@media (max-width: 480px) { @media (max-width: 480px) {
#navPanelToggle { #navPanelToggle {
font-size: 0.75rem !important; font-size: 0.75rem !important;
padding: 0.3rem 0.8rem !important; padding: 0.3rem 0.8rem !important;
backdrop-filter: blur(8px) !important;
} }
} }
+70 -23
View File
@@ -1,42 +1,89 @@
/* Улучшение фона для десктопного меню навигации */ /* Desktop nav bar */
#nav { #nav {
background: rgba(0, 0, 0, 0.4) !important; background: rgba(0, 0, 0, 0.35) !important;
backdrop-filter: blur(8px) !important; backdrop-filter: blur(10px) !important;
border-radius: 10px !important; -webkit-backdrop-filter: blur(10px) !important;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3) !important; border-radius: 100px !important;
border: 1px solid rgba(255, 255, 255, 0.1) !important; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25) !important;
border: 1px solid rgba(255, 255, 255, 0.08) !important;
} }
#nav ul.links li a { /* Ссылки с иконкой — flex row */
color: rgba(255, 255, 255, 0.9) !important; #nav ul.links li a.nav-link {
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5) !important; display: flex !important;
transition: all 0.3s ease !important; align-items: center !important;
gap: 0.5rem !important;
color: rgba(255, 255, 255, 0.82) !important;
text-shadow: none !important;
padding: 0 1.4rem !important;
transition: color 0.2s ease, background 0.2s ease !important;
text-transform: uppercase !important;
font-size: 0.78rem !important;
letter-spacing: 0.07em !important;
font-weight: 900 !important;
} }
#nav ul.links li a:hover { #nav ul.links li a.nav-link:hover {
background-color: rgba(255, 255, 255, 0.2) !important; background-color: rgba(255, 255, 255, 0.12) !important;
color: white !important; color: #ffffff !important;
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.7) !important; text-shadow: none !important;
} }
/* Иконки в nav — фиксированная ширина чтобы все выровнялись */
#nav ul.links li a .nav-icon {
font-size: 0.85rem !important;
opacity: 0.75;
flex-shrink: 0;
line-height: 1 !important;
width: 1em !important;
text-align: center !important;
display: inline-block !important;
}
#nav ul.links li a:hover .nav-icon {
opacity: 1;
}
/* Активный пункт */
#nav ul.links li.active { #nav ul.links li.active {
background-color: rgba(255, 255, 255, 0.2) !important; background-color: rgba(255, 255, 255, 0.15) !important;
border-radius: 5px !important;
} }
#nav ul.links li.active a { #nav ul.links li.active a {
color: white !important; color: #ffffff !important;
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.7) !important; }
#nav ul.links li.active a .nav-icon {
opacity: 1;
} }
/* Иконки соцсетей */ /* Иконки соцсетей */
#nav ul.icons li a { #nav ul.icons li a {
color: rgba(255, 255, 255, 0.8) !important; color: rgba(255, 255, 255, 0.75) !important;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5) !important; text-shadow: none !important;
transition: color 0.2s ease !important;
} }
#nav ul.icons li a:hover { #nav ul.icons li a:hover {
color: white !important; color: #ffffff !important;
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.7) !important; }
transform: scale(1.1) !important;
/* Мобильная панель — иконки + текст в строку */
#navPanel .links li a.nav-link {
display: flex !important;
align-items: center !important;
gap: 0.6rem !important;
padding: 0.85rem 0 !important;
}
#navPanel .links li a .nav-icon {
font-size: 1rem !important;
opacity: 0.7;
flex-shrink: 0;
width: 1.2rem;
text-align: center;
}
#navPanel .links li a:hover .nav-icon {
opacity: 1;
} }
+52 -2
View File
@@ -10,14 +10,64 @@
} }
} }
/* Уменьшение размера заголовков на страницах */ /* Заголовок страницы — убираем UPPERCASE, нормальный регистр */
.post header.major h1 { .post header.major h1 {
font-size: 2.5rem !important; font-size: 2.5rem !important;
line-height: 1.2 !important; line-height: 1.2 !important;
text-transform: none !important;
letter-spacing: 0.01em !important;
font-weight: 900 !important;
color: #1a252f !important;
margin-bottom: 1rem !important;
}
/* Описание под заголовком — читаемое, не тонкое */
.post header.major p {
font-size: 1rem !important;
font-weight: 400 !important;
line-height: 1.65 !important;
color: #555c63 !important;
font-family: 'Source Sans Pro', Helvetica, sans-serif !important;
text-align: left !important;
}
/* Выравнивание заголовка влево */
.post header.major {
text-align: left !important;
} }
@media (max-width: 736px) { @media (max-width: 736px) {
.post header.major h1 { .post header.major h1 {
font-size: 2rem !important; font-size: 1.9rem !important;
}
}
/* Скруглённые углы — изображения в карточках постов */
a.image.main img,
a.image.fit img {
border-radius: 10px;
overflow: hidden;
}
a.image.main,
a.image.fit {
border-radius: 10px;
overflow: hidden;
display: block;
}
/* Скруглённые углы — белая подложка #main */
#main {
border-radius: 20px;
overflow: hidden;
margin-top: 1rem;
margin-bottom: 1.5rem;
}
@media (max-width: 736px) {
#main {
border-radius: 14px;
margin-top: 0.75rem;
margin-bottom: 1rem;
} }
} }
+81 -71
View File
@@ -1,71 +1,81 @@
/* Фиксируем пагинацию */ /* Пагинация — новые классы, нет конфликтов с темой */
.pagination ul {
display: flex !important; .pager {
align-items: center !important; display: flex;
justify-content: center !important; justify-content: center;
list-style: none !important; padding: 1.5rem 0 3.5rem;
margin: 0 !important; }
padding: 0 !important;
gap: 1rem !important; .pager-inner {
} display: flex;
align-items: center;
/* Убираем рамки со всех кнопок пагинации */ gap: 0.5rem;
.pagination a, }
.pagination .previous,
.pagination .next, /* Кнопки Новее / Старше */
.pagination .first, .pager-btn {
.pagination .last { display: inline-flex;
border: none !important; align-items: center;
border-radius: 0 !important; gap: 0.4rem;
box-shadow: none !important; padding: 0.5rem 1.1rem;
outline: none !important; font-size: 0.82rem;
} font-weight: 500;
color: #555c63;
/* Информация о страницах для десктопа */ background: transparent;
.pagination .page-info { border: 1px solid #d0d4d8;
display: inline-flex !important; border-radius: 20px;
align-items: center !important; text-decoration: none;
justify-content: center !important; transition: color 0.18s, border-color 0.18s, background 0.18s;
padding: 0.4rem 0.8rem !important; cursor: pointer;
font-size: 0.8rem !important; white-space: nowrap;
color: #333 !important; letter-spacing: 0.01em;
background: none !important; }
border: none !important;
border-radius: 0 !important; .pager-btn:hover {
text-align: center !important; color: #5b9bd5;
font-weight: 300 !important; border-color: #5b9bd5;
white-space: nowrap !important; background: rgba(24, 191, 239, 0.06);
min-width: 60px !important; text-decoration: none;
box-sizing: border-box !important; }
flex-shrink: 0 !important;
box-shadow: none !important; .pager-btn svg {
outline: none !important; flex-shrink: 0;
} }
.pagination .page-info .current-page { /* Заблокированная кнопка */
color: #333 !important; .pager-disabled {
font-weight: 400 !important; color: #c0c5ca;
font-size: 1em !important; border-color: #e8eaec;
} cursor: default;
pointer-events: none;
.pagination .page-info .separator { }
margin: 0 0.3rem !important;
color: #666 !important; /* Счётчик страниц */
font-size: 0.9em !important; .pager-info {
font-weight: 300 !important; font-size: 0.78rem;
} color: #aaa;
padding: 0 0.5rem;
.pagination .page-info .total-pages { white-space: nowrap;
color: #333 !important; font-variant-numeric: tabular-nums;
font-weight: 300 !important; min-width: 3.5rem;
} text-align: center;
}
/* Скрываем информацию о страницах на мобильных */
@media (max-width: 768px) { /* Мобильные: уменьшить счётчик, добавить пространство */
.pagination .page-info, @media (max-width: 736px) {
.pagination .page-info.desktop-only, .pager-info {
.pagination-info, font-size: 0.72rem;
.pagination-status { min-width: 2.5rem;
display: none !important; color: #bbb;
} }
}
/* Больше белого пространства под кнопками — чёткое разделение с футером */
#main > nav.pager {
padding-bottom: 3rem !important;
}
.pager-btn {
padding: 0.6rem 1.4rem;
font-size: 0.85rem;
}
}
+68 -1
View File
@@ -42,7 +42,7 @@
} }
#main article a:hover { #main article a:hover {
color: #18bfef; color: #5b9bd5;
} }
/* Списки в статьях */ /* Списки в статьях */
@@ -118,6 +118,73 @@
color: #1a252f; color: #1a252f;
} }
/* Карточки постов */
#main > .posts > article {
padding: 2rem !important;
text-align: left !important;
transition: box-shadow 0.2s ease;
}
#main > .posts > article:hover {
box-shadow: inset 0 0 0 1px rgba(24, 191, 239, 0.3);
}
/* Фиксированная высота хедера — фото на одном уровне в ряду */
#main > .posts > article header {
min-height: 5.5rem;
}
/* Заголовок карточки */
#main > .posts > article header h2 {
font-size: 1.3rem;
line-height: 1.35;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
margin-bottom: 0;
text-align: left;
}
#main > .posts > article header h2 a {
text-decoration: none;
}
/* Убираем огромный отступ у фото (тема: 4rem 0) */
#main > .posts > article .image.main {
margin: 1rem 0 !important;
}
/* Описание — обрезаем до 2 строк */
#main > .posts > article > p {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-align: left;
font-size: 0.88rem;
color: #666;
margin-bottom: 1rem;
line-height: 1.5;
}
/* Скрываем кнопку «Подробнее» — карточка и так кликабельна по заголовку */
#main > .posts > article .actions {
display: none !important;
}
@media screen and (max-width: 980px) {
#main > .posts > article {
padding: 1.5rem !important;
}
}
@media screen and (max-width: 736px) {
#main > .posts > article {
text-align: left !important;
}
}
/* Адаптивность для мобильных */ /* Адаптивность для мобильных */
@media (max-width: 768px) { @media (max-width: 768px) {
#main article h1 { #main article h1 {
-104
View File
@@ -1,104 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Тест шифрования файлов</title>
<link rel="stylesheet" href="/css/forms.css">
</head>
<body>
<div class="travel-form-container">
<h2>Тест системы шифрования файлов</h2>
<form class="contact-form" action="#" method="POST" onsubmit="return false;">
<div class="form-group">
<label for="name">Имя</label>
<input type="text" id="name" name="name" value="Тестовый пользователь">
</div>
<div class="form-group">
<label for="test_file">Тестовый файл для шифрования</label>
<div class="file-input-wrapper" onclick="document.getElementById('test_file').click()">
<input type="file" id="test_file" name="test_file" accept=".pdf,.jpg,.png,.txt" class="file-input-hidden">
<span class="file-input-text" id="test_file_text">Выберите файл для тестирования</span>
</div>
</div>
<div class="form-group">
<button type="submit" class="submit-btn">
Тестировать отправку
</button>
</div>
</form>
<div id="debug-info" style="margin-top: 2rem; padding: 1rem; background: #f8f9fa; border-radius: 8px;">
<h3>Отладочная информация:</h3>
<pre id="debug-content">Выберите файл для просмотра информации о шифровании</pre>
</div>
</div>
<script src="/js/encryption.js"></script>
<script>
// Дополнительная отладочная информация
document.addEventListener('DOMContentLoaded', function() {
const form = document.querySelector('.contact-form');
const debugContent = document.getElementById('debug-content');
// Перехватываем событие отправки формы для демонстрации
form.addEventListener('submit', function(event) {
event.preventDefault();
const formData = new FormData(form);
const encryptedField = form.querySelector('input[name="test_file_encrypted"]');
const metadataField = form.querySelector('input[name="test_file_metadata"]');
let debugInfo = 'Форма готова к отправке:\n\n';
for (let [key, value] of formData.entries()) {
if (key !== 'test_file') { // Не показываем оригинальный файл
debugInfo += `${key}: ${typeof value === 'string' ? value.substring(0, 100) + (value.length > 100 ? '...' : '') : '[File]'}\n`;
}
}
if (encryptedField) {
debugInfo += `\nЗашифрованные данные: ${encryptedField.value.length} символов (Base64)\n`;
}
if (metadataField) {
try {
const metadata = JSON.parse(metadataField.value);
debugInfo += '\nМетаданные файла:\n';
debugInfo += `- Имя: ${metadata.fileName}\n`;
debugInfo += `- Тип: ${metadata.fileType}\n`;
debugInfo += `- Размер: ${metadata.fileSize} байт\n`;
debugInfo += `- Зашифровано: ${metadata.encryptedAt}\n`;
} catch (e) {
debugInfo += '\nОшибка чтения метаданных\n';
}
}
debugContent.textContent = debugInfo;
alert('Тест завершен! Смотрите отладочную информацию ниже.');
});
// Отслеживаем изменения в шифровании
const fileInput = document.getElementById('test_file');
if (fileInput) {
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type === 'childList') {
const encryptedField = form.querySelector('input[name="test_file_encrypted"]');
if (encryptedField && encryptedField.value) {
debugContent.textContent = 'Файл зашифрован и готов к отправке!\nНажмите "Тестировать отправку" для просмотра деталей.';
}
}
});
});
observer.observe(form, { childList: true, subtree: true });
}
});
</script>
</body>
</html>
@@ -11,7 +11,7 @@
</div> </div>
<div class="field"> <div class="field">
<label for="email">{{ i18n "CONTACT_FORM_FIELD_EMAIL" . }}</label> <label for="email">{{ i18n "CONTACT_FORM_FIELD_EMAIL" . }}</label>
<input type="text" name="email" id="email" /> <input type="email" name="email" id="email" />
</div> </div>
<div class="field"> <div class="field">
<label for="message">{{ i18n "CONTACT_FORM_FIELD_MESSAGE" . }}</label> <label for="message">{{ i18n "CONTACT_FORM_FIELD_MESSAGE" . }}</label>
@@ -52,25 +52,25 @@
{{ end }} {{ end }}
{{ with .plan}} {{ with .plan}}
<li><a href="{{ . }}" class="footer-nav-link"> <li><a href="{{ . }}" class="footer-nav-link">
<i class="icon fa-calendar"></i> <i class="icon fa-calendar-o"></i>
<span>Хочу поехать</span> <span>Хочу поехать</span>
</a></li> </a></li>
{{ end }} {{ end }}
{{ with .map}} {{ with .map}}
<li><a href="{{ . }}" class="footer-nav-link"> <li><a href="{{ . }}" class="footer-nav-link">
<i class="icon fa-map"></i> <i class="icon fa-map-o"></i>
<span>Маршруты</span> <span>Маршруты</span>
</a></li> </a></li>
{{ end }} {{ end }}
{{ with .ask}} {{ with .ask}}
<li><a href="{{ . }}" class="footer-nav-link"> <li><a href="{{ . }}" class="footer-nav-link">
<i class="icon fa-question"></i> <i class="icon fa-question-circle-o"></i>
<span>Спросить</span> <span>Спросить</span>
</a></li> </a></li>
{{ end }} {{ end }}
{{ with .gallery}} {{ with .gallery}}
<li><a href="{{ . }}" class="footer-nav-link"> <li><a href="{{ . }}" class="footer-nav-link">
<i class="icon fa-image"></i> <i class="icon fa-picture-o"></i>
<span>Галерея</span> <span>Галерея</span>
</a></li> </a></li>
{{ end }} {{ end }}