Compare commits

..

31 Commits

Author SHA1 Message Date
bea27be461 api 2026-05-11 17:36:03 +03:00
11879ffd39 adaptive_fix_5 2026-05-11 17:35:09 +03:00
001922c5e2 api 2026-05-11 17:04:47 +03:00
beef191051 adaptive_fix_4 2026-05-11 16:48:09 +03:00
7ddee3f12d adaptive_fix_3 2026-05-11 14:33:23 +03:00
3ec7aa43e5 fix_photos 2026-05-11 14:15:34 +03:00
942a287b26 adaptive_fix_2 2026-05-11 13:07:00 +03:00
eb97ed0e4a adaptive_fix_1 2026-05-10 12:38:16 +03:00
916d020909 adaptive_3 2026-05-09 21:58:40 +03:00
dd41046e75 adaptive_2 2026-05-08 03:31:13 +03:00
6b6361b25a adaptive_1 2026-04-26 20:42:33 +03:00
0932c40127 final-fix-text 2026-04-19 21:50:16 +03:00
d58bfbb7c1 final 2026-04-19 20:25:06 +03:00
66b6878e50 cache images
All checks were successful
Build Docker / deploy (push) Successful in 40s
Build Docker / build (push) Successful in 35s
2026-03-19 03:06:41 +03:00
7bdf422c32 fix js
All checks were successful
Build Docker / deploy (push) Successful in 51s
Build Docker / build (push) Successful in 34s
2026-03-19 03:00:41 +03:00
9a259cb637 fix logout button
All checks were successful
Build Docker / deploy (push) Successful in 40s
Build Docker / build (push) Successful in 35s
2026-03-19 02:57:02 +03:00
54072eb87d logout button fix
All checks were successful
Build Docker / deploy (push) Successful in 40s
Build Docker / build (push) Successful in 35s
2026-03-19 02:53:17 +03:00
ecf374685f error handle 0.152
All checks were successful
Build Docker / deploy (push) Successful in 38s
Build Docker / build (push) Successful in 34s
2026-03-19 02:48:16 +03:00
62d58e30cd remake apis 0.151
All checks were successful
Build Docker / deploy (push) Successful in 44s
Build Docker / build (push) Successful in 34s
2026-03-19 02:41:39 +03:00
a13b88bd32 fix font types 0.150
All checks were successful
Build Docker / deploy (push) Successful in 49s
Build Docker / build (push) Successful in 36s
2026-03-19 02:25:51 +03:00
ea7bfc64f2 fix jss 0.149
All checks were successful
Build Docker / deploy (push) Successful in 55s
Build Docker / build (push) Successful in 35s
2026-03-19 02:09:25 +03:00
0e2a17a3e3 fix login.js 0.148
All checks were successful
Build Docker / deploy (push) Successful in 38s
Build Docker / build (push) Successful in 39s
2026-03-19 02:00:48 +03:00
185cefe250 fix login.js 0.147
All checks were successful
Build Docker / deploy (push) Successful in 45s
Build Docker / build (push) Successful in 44s
2026-03-19 01:58:13 +03:00
25ec2c7bcb fix jss 0.146
All checks were successful
Build Docker / deploy (push) Successful in 41s
Build Docker / build (push) Successful in 38s
2026-03-19 01:52:57 +03:00
b667cde3d7 fix caddyfile 0.145
All checks were successful
Build Docker / deploy (push) Successful in 1m40s
Build Docker / build (push) Successful in 36s
2026-03-19 01:47:41 +03:00
d30af82765 fix caddy file 0.134
All checks were successful
Build Docker / deploy (push) Successful in 48s
Build Docker / build (push) Successful in 42s
2026-03-19 01:43:57 +03:00
efd8510853 fix caddy file 0.133
All checks were successful
Build Docker / deploy (push) Successful in 38s
Build Docker / build (push) Successful in 34s
2026-03-19 01:32:00 +03:00
e558aa6bdd fix caddy 0.132
All checks were successful
Build Docker / deploy (push) Successful in 50s
Build Docker / build (push) Successful in 38s
2026-03-19 01:29:09 +03:00
bd9210a3b5 fix caddy 0.131
All checks were successful
Build Docker / deploy (push) Successful in 39s
Build Docker / build (push) Successful in 34s
2026-03-19 01:22:49 +03:00
1eba5623a3 fix caddyfile 0.130
All checks were successful
Build Docker / deploy (push) Successful in 50s
Build Docker / build (push) Successful in 32s
2026-03-19 01:16:07 +03:00
c762662231 fix caddyfile
All checks were successful
Build Docker / deploy (push) Successful in 1m6s
Build Docker / build (push) Successful in 36s
2026-03-19 01:12:24 +03:00
91 changed files with 1911 additions and 480 deletions

View File

@@ -4,23 +4,41 @@ http://ru.homyk.space {
https://ru.homyk.space {
encode gzip
# --- API ---
handle /api/* {
reverse_proxy backend:{$PORT}
}
# --- Frontend ---
root * /srv
file_server
handle_path /main/* {
@images path_regexp \.(jpg|jpeg|png|webp|gif|svg)$
header @images Cache-Control "public, max-age=604800"
forward_auth backend:{$PORT} {
uri /api/verify
copy_headers Authorization
}
root * /srv/main
file_server
}
handle_errors {
@unauth expression {http.error.status_code} == 401
redir @unauth / 302
}
handle {
root * /srv/auth
file_server {
index login.html
}
}
log {
output file /data/logs/caddy.log {
roll_size 5mb
roll_keep 5
roll_keep_for 72h
}
format json
}
format json
}
}
https://music.homyk.space {
encode gzip
@@ -35,7 +53,7 @@ https://music.homyk.space {
roll_size 5mb
roll_keep 5
roll_keep_for 72h
}
format json
}
format json
}
}

View File

@@ -1,12 +1,15 @@
VENV=source ./.venv/bin/activate;
ALEMBIC=alembic -c ./server/backend/database/alembic/alembic.ini
#VENV=source ./.venv/bin/activate;
#ALEMBIC=alembic -c ./server/backend/database/alembic/alembic.ini
VENV= .venv\Scripts\activate #Windows
ALEMBIC=alembic -c server\backend\database\alembic\alembic.ini
.PHONY: run run_debug migrate_head migrate_down migrate_history migrate_current migrate_heads migrate_stamp migrate
run:
$(VENV) python run.py --user_name admin
run_debug:
$(VENV) python run.py --mode debug --user_name admin
migrate_head:
$(VENV) $(ALEMBIC) upgrade head
$(VENV) $(ALEMBIC)
migrate_down:
$(VENV) $(ALEMBIC) downgrade -1
migrate_history:

View File

@@ -1,16 +1,21 @@
from fastapi import FastAPI, Depends, HTTPException,status
from fastapi import FastAPI, Depends, HTTPException,status, Response, Cookie
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import server.backend.schema.pydantic as pydantic
import server.backend.database.db as db
from server.backend.auth.JWT import signJWT, decodeJWT
api = FastAPI(openapi_url="/api/openapi.json",docs_url="/api/docs", redoc_url="/api/redoc")
security = HTTPBearer()
security = HTTPBearer(auto_error=False)
async def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)):
token = credentials.credentials
async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security),
token_cookie: str = Cookie(default=None)
):
token = credentials.credentials if credentials else token_cookie
if not token:
raise HTTPException(status_code=401, detail="Not authenticated")
user = decodeJWT(token)
if not user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token")
raise HTTPException(status_code=401, detail="Invalid token")
return user
async def check_roles(user=Depends(get_current_user)):
user_check = await db.list_user(user["user_id"])
@@ -58,10 +63,29 @@ async def list_users(user=Depends(check_roles)):
list_of_users = await db.list_users()
return list_of_users
@api.post("/api/auth",response_model=pydantic.Token)
async def auth(code:pydantic.UserAccess):
@api.post("/api/auth")
async def auth(code: pydantic.UserAccess, response: Response):
login = await db.login_user(code)
if login == None:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Forbidden")
if login is None:
raise HTTPException(status_code=401, detail="Forbidden")
token = signJWT(login)
response.set_cookie(
key="token",
value=token,
httponly=True,
secure=True,
samesite="strict"
)
return {"access_token": token, "token_type": "bearer"}
@api.get("/api/verify")
async def verify(token: str = Cookie(default=None)):
if not token:
raise HTTPException(status_code=401, detail="No token")
user = decodeJWT(token)
if not user:
raise HTTPException(status_code=401, detail="Invalid token")
return {"status": "ok"}
@api.post("/api/logout")
async def logout(response: Response):
response.delete_cookie(key="token")
return {"status": "ok"}

View File

@@ -0,0 +1 @@
DoubleRus encoding by Diai; unfinished

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

View File

@@ -0,0 +1,126 @@
@font-face {
font-family: "MurreyC";
src: url("fonts/MurreyC/murreyc.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "MurreyC";
src: url("fonts/MurreyC/murreyc.woff") format("woff");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "MurreyC";
src: url("fonts/MurreyC/murreyc.eot") format("eot");
font-weight: 400;
font-style: normal;
font-display: swap;
}
body, html {
font-family: "MurreyC";
margin: 0;
padding: 0;
}
.bg {
position: fixed;
inset: 0;
background: url("image/bg.webp") center center / cover no-repeat;
z-index: -1;
}
.glass-container {
position: fixed;
inset: 0;
backdrop-filter: blur(16px);
background: rgba(20,20,20,.35);
}
.login-box {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
background: url('./image/hamster.webp') no-repeat 50% 50%;
padding-top: 50px;
}
form {
display: flex;
flex-direction: column;
}
h2 {
font-weight: 900;
font-size: 50px;
text-decoration: underline;
margin: 0;
padding: 0;
}
input {
width: 320px;
height: 50px;
padding: 0 20px;
border-radius: 25px;
border: 1px solid #000;
background-color: #ffffff;
outline: none;
font-size: 30px;
}
button {
margin-top: 10px;
font-size: 30px;
background-color: #3a1f09;
padding: 10px 15px;
border-radius: 33px;
transition:
transform .1s ease,
background-color .1s ease,
color .1s ease;
color: #e5b97e;
box-shadow: 0 4px 12px rgba(58,31,9,.3);
cursor: pointer;
}
button:hover {
background-color: #f0c590;
color: #b06029;
transform: scale(1.015);
}
/* ----------------------------------ADAPTIVE------------------------------------- */
@media (max-width: 820px) {
.login-box {
background-size: 190%;
}
}
@media (max-width: 620px) {
.login-box {
background-size: 220%;
}
}
@media (max-width: 520px) {
.login-box {
background-size: 260%;
}
}
@media (max-width: 420px) {
.login-box {
background-size: 310%;
}
input {
width: 250px;
}
}
@media (max-width: 320px) {
.login-box {
background-size: 420%;
background: url('./image/hamster.png') no-repeat 55% 50%;
}
input {
width: 200px;
}
}

View File

@@ -5,17 +5,25 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
<link rel="stylesheet" href="login.css">
<link
rel="preload"
href="fonts/MurreyC/murreyc.woff2"
as="font"
type="font/woff2"
crossorigin
>
</head>
<body>
<div class="bg"></div>
<div class="glass-container">
<div class="login-box">
<h2>Login</h2>
<h2>Введите код</h2>
<form id="loginForm">
<input type="password" id="password" name="password" required placeholder="Code">
<button type="submit">Login</button>
<input type="password" id="password" name="password" required placeholder="Код">
<button type="submit">Войти</button>
</form>
</div>
</div>
<script src="login.js"></script>
<script src="login.js" defer></script>
</body>
</html>

View File

@@ -1,73 +1,64 @@
function getToken() {
return localStorage.getItem("token") || sessionStorage.getItem("token");
}
function tokenCheck(){
const token = getToken();
if (token) {
window.location.href = "http://localhost:5500/server/frontend/main/index.html";
}
}
document.getElementById('loginForm').addEventListener('submit', async function (e) {
e.preventDefault();
const password = document.getElementById('password').value;
const userData = {
password
};
try {
const response = await fetch("http://localhost:8000/api/auth", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
password: userData.password
}),
});
document.addEventListener('DOMContentLoaded', () => {
fetch('/api/verify', { credentials: 'include' })
.then(r => { if (r.ok) window.location.href = '/main/'; })
.catch(() => {});
const data = await response.json(); // читаем только один раз
if (response.ok) { // сохраняем только при успехе
// в sessionstorage до перезахода в браузер(
sessionStorage.setItem("token", data.access_token);
window.location.href = 'http://localhost:5500/server/frontend/main/index.html';
} else { //парсинг и вывод ошибок, если есть
if (Array.isArray(data.detail)) {
const messages = data.detail.map(e => {
const field = e.loc.filter(locPart => locPart !== 'body').join(' -> ');
return `${field}: ${e.msg}`;
});
showError(messages);
} else if (typeof data.detail === 'string') {
showError([data.detail]);
document.getElementById('loginForm').addEventListener('submit', async function(e) {
e.preventDefault();
const code = document.getElementById('password').value;
try {
const response = await fetch('/api/auth', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include', // ← чтобы браузер принял cookie
body: JSON.stringify({ code })
});
const data = await response.json();
if (response.ok) {
window.location.href = '/main/';
} else {
showError(['Unknown error']);
if (Array.isArray(data.detail)) {
const messages = data.detail.map(e => {
const field = e.loc.filter(p => p !== 'body').join(' -> ');
return `${field}: ${e.msg}`;
});
showError(messages);
} else if (typeof data.detail === 'string') {
showError([data.detail]);
} else {
showError(['Unknown error']);
}
}
} catch (err) {
showError(['Connection error: ' + err.message]);
}
} catch (err) {
showError(['Connection error: ' + err.message]);
}
});
});
function showError(messages){ //Добавление их на form со стилями
function showError(messages) {
let errorElem = document.getElementById('formError');
let container = document.getElementById('glass-container');
if (!errorElem){
if (!errorElem) {
errorElem = document.createElement('div');
errorElem.style.transition="3s";
errorElem.id = 'formError';
errorElem.style.color = 'red';
errorElem.style.marginTop = '20px';
errorElem.style.fontSize = '14px';
errorElem.style.fontWeight = '100';
errorElem.style.marginBottom = '20px';
errorElem.style.lineHeight="120%";
errorElem.style.height = 'auto';
const form = document.getElementById('loginForm');
form.insertAdjacentElement('afterend', errorElem);
};
errorElem.style.cssText = `
color: red;
margin-top: 20px;
margin-bottom: 20px;
font-size: 14px;
font-weight: 100;
line-height: 120%;
transition: 3s;
`;
document.getElementById('loginForm').insertAdjacentElement('afterend', errorElem);
}
errorElem.innerHTML = '';
messages.forEach(msg => {
const li = document.createElement('li');
li.style.listStyleType="none";
li.style.listStyleType = 'none';
li.textContent = msg;
errorElem.appendChild(li);
});

View File

@@ -1,69 +1,55 @@
function getToken() {
return localStorage.getItem("token") || sessionStorage.getItem("token");
}
function tokenCheck(){
const token = getToken();
if (!token) {
window.location.href = "http://localhost:5500/server/frontend/auth/login.html";
}
}
tokenCheck()
document.getElementById('logoutForm').addEventListener('submit', async function (e) {
e.preventDefault();
localStorage.removeItem("token");
sessionStorage.removeItem("token");
tokenCheck();
});
document.addEventListener("DOMContentLoaded", () => {
const form = document.querySelector(".form-info");
form.addEventListener("submit", async (e) => {
// Проверка авторизации через cookie
fetch('/api/verify', { credentials: 'include' })
.then(r => { if (!r.ok) window.location.href = '/'; })
.catch(() => { window.location.href = '/'; });
// Logout — удаляем cookie на бэкенде
document.getElementById('logoutForm').addEventListener('click', async function(e) {
e.preventDefault();
// try {
// собираем данные из формы
const name = document.getElementById('ffname').value || "";
const middlename = document.getElementById('fmname').value || "";
const surname = document.getElementById('flname').value || "";
const text_field = document.getElementById('text_field')?.value || "";
const food = document.querySelector('input[name="food"]:checked')?.value || "";
const types_of_alco = Array.from(document.querySelectorAll('input[name="drink"]:checked'))
.map(el => el.value)
.join(', ');
const guestData = {
name: name,
middlename: middlename,
surname: surname,
text_field: text_field,
activated: true,
types_of_food: food,
types_of_alco: types_of_alco
};
console.log(guestData)
// отправка на /api/update с Authorization
// const updateResponse = await fetch('/api/update', {
// method: 'POST',
// headers: {
// 'Content-Type': 'application/json',
// 'Authorization': `Bearer ${token}`
// },
// body: JSON.stringify(guestData)
// });
// if (!updateResponse.ok) {
// throw new Error('Ошибка при отправке формы');
// }
// const updateData = await updateResponse.json();
// console.log('Форма успешно отправлена:', updateData);
// } catch (err) {
// console.error(err);
// alert('Ошибка: ' + err.message);
// }
await fetch('/api/logout', {
method: 'POST',
credentials: 'include'
});
window.location.href = '/';
});
});
document.querySelector(".form-info").addEventListener("submit", async (e) => {
e.preventDefault();
const guestData = {
name: document.getElementById('ffname').value || "",
middlename: document.getElementById('fmname').value || "",
surname: document.getElementById('flname').value || "",
text_field: document.getElementById('text_field')?.value || "",
activated: true,
types_of_food: document.querySelector('input[name="food"]:checked')?.value || "",
types_of_alco: Array.from(document.querySelectorAll('input[name="drink"]:checked'))
.map(el => el.value)
.join(', ')
};
try {
const response = await fetch('/api/update', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include', // ← токен идёт через cookie
body: JSON.stringify(guestData)
});
if (!response.ok) {
const err = await response.json();
throw new Error(JSON.stringify(err.detail || 'Ошибка при отправке'));
}
const data = await response.json();
console.log('Успешно:', data);
alert('Данные сохранены!');
} catch (err) {
console.error(err);
alert('Ошибка: ' + err.message);
}
});
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" ?><svg style="enable-background:new 0 0 24 24;" version="1.1" viewBox="0 0 24 24" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><style type="text/css">
.st0{display:none;}
</style><g class="st0" id="grid"/><g id="icon"><path d="M5.528,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199L23.899,5.275c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.166-0.535-0.124-0.7,0.099 L12.91,18.226l-6.677-7.839C6.053,10.176,5.736,10.151,5.528,10.33z"/><path d="M12.028,13.945l6.519-8.67c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.167-0.535-0.12-0.7,0.099l-6.519,8.67 c-0.166,0.221-0.122,0.534,0.099,0.7c0.091,0.068,0.196,0.101,0.301,0.101C11.78,14.145,11.931,14.075,12.028,13.945z"/><path d="M0.176,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199l0.967-1.285c0.166-0.221,0.122-0.534-0.099-0.7c-0.219-0.166-0.535-0.123-0.7,0.099 l-0.592,0.786l-6.677-7.839C0.7,10.176,0.385,10.151,0.176,10.33z"/></g></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 525 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="14" fill="url(#paint0_linear_87_7225)"/>
<path d="M22.9866 10.2088C23.1112 9.40332 22.3454 8.76755 21.6292 9.082L7.36482 15.3448C6.85123 15.5703 6.8888 16.3483 7.42147 16.5179L10.3631 17.4547C10.9246 17.6335 11.5325 17.541 12.0228 17.2023L18.655 12.6203C18.855 12.4821 19.073 12.7665 18.9021 12.9426L14.1281 17.8646C13.665 18.3421 13.7569 19.1512 14.314 19.5005L19.659 22.8523C20.2585 23.2282 21.0297 22.8506 21.1418 22.1261L22.9866 10.2088Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear_87_7225" x1="16" y1="2" x2="16" y2="30" gradientUnits="userSpaceOnUse">
<stop stop-color="#37BBFE"/>
<stop offset="1" stop-color="#007DBB"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 920 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

View File

@@ -7,59 +7,68 @@
<title>Wedding invitation</title>
<link rel="stylesheet" href="reset.css">
<link rel="stylesheet" href="style.css">
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/swiper@12/swiper-bundle.min.css"
/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@12/swiper-bundle.min.css" />
<link rel="preload" href="fonts/yourfont.woff2" as="font" type="font/woff2" crossorigin>
</head>
<body>
<div class="bg"></div>
<header class="header">
<nav class="nav">
<div class="burger" id="burger">
<span></span>
<span></span>
<span></span>
</div>
<nav class="nav" id="nav">
<ul class="menu">
<!-- 1 -->
<li class="item">
<a href="#heading" class="link">
Добро пожаловать!
</a>
</li>
<!-- 2 -->
<li class="item">
<a href="#people" class="link">
Список гостей
</a>
</li>
<!-- 3 -->
<li class="item">
<a href="#timetable" class="link">
Расписание
</a>
</li>
<!-- 4 -->
<li class="item">
<a href="#transfer" class="link">
Путешествие
</a>
</li>
<!-- 5 -->
<li class="item">
<a href="#photos" class="link">
Фотографии
</a>
</li>
<!-- 6 -->
<li class="item">
<a href="#to-do-list" class="link">
Список задач
</a>
</li>
<!-- 7 -->
<li class="item">
<a href="#answer" class="link">
Прошу ответить
</a>
</li>
<div class="items_up">
<!-- 1 -->
<li class="item">
<a href="#" class="link">
Добро пожаловать!
</a>
</li>
<!-- 2 -->
<li class="item">
<a href="#people" class="link">
Список гостей
</a>
</li>
<!-- 3 -->
<li class="item">
<a href="#timetable" class="link">
Расписание
</a>
</li>
<!-- 4 -->
<li class="item">
<a href="#transfer" class="link">
Путешествие
</a>
</li>
</div>
<div class="items_down">
<!-- 5 -->
<li class="item item_none">
<a href="#photos" class="link">
Фотографии
</a>
</li>
<!-- 6 -->
<li class="item">
<a href="#to-do-list" class="link">
Список задач
</a>
</li>
<!-- 7 -->
<li class="item">
<a href="#answer" class="link">
Прошу ответить
</a>
</li>
</div>
</ul>
</nav>
</header>
@@ -74,21 +83,25 @@
</h2>
<h3 class="heading_date">22 августа 2026</h3>
<p class="heading_text">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste possimus ipsa, labore repudiandae
ratione placeat dolore vitae praesentium perspiciatis ipsam non illum reiciendis accusamus quae
quo veritatis maiores quod sequi. Ipsam at consequatur quia recusandae, rem dicta autem quaerat
placeat?
Мы — та самая история, которая началась со странного сообщения и превратилась в нечто настоящее.
В нас есть легкость и смех, который когда-то стал началом всего, любовь к простым вещам вроде
чашки чая и бесконечных разговоров обо всем на свете. Мы разные и неидеальные, но именно в этом
— наше совпадение: нам всегда интересно друг с другом, спокойно и по-настоящему. Мы умеем
смеяться до слез, поддерживать в нужный момент и находить радость в мелочах. И, пожалуй, самое
важное — мы с самого начала почувствовали, что это надолго, и с каждым днем только убеждаемся в
этом.
</p>
<button class="btn_share" button>
Подтвердить участие
<a class="btn_link" href="#answer">
Подтвердить участие
</a>
</button>
</div>
</article>
</section>
<aside>
<div class="time">
<!-- отсчет до даты -->
00:00:00
<p id="demo"></p>
</div>
</aside>
<section class="people" id="people">
@@ -97,30 +110,33 @@
</h4>
<div class="newlywed">
<div class="newlywed_item">
<img class="img_newlywed" src="images/people//IMG_20260107_140110_500.jpg" alt="groom">
<img class="img_newlywed" src="images/people/groom.webp" alt="groom" loading="lazy"
decoding="async">
<div class="newlywed_text">
<h3 class="newlywed_title">Жених</h3>
<p class="newlywed_info">Lorem ipsum dolor sit amet consectetur adipisicing elit. Qui voluptatum
odio autem, ut dolorum suscipit soluta reiciendis quam reprehenderit saepe doloribus
asperiores
architecto? Debitis magnam, exercitationem nam temporibus eos molestias?</p>
<p class="newlywed_info">
Самый лучший, милый,классный, очаровательный, крутой, забавный, любящий, удивительный,
необычный, прелестный, веселый, смешной, умный, добрый,красивый, гениальный</p>
</div>
</div>
<div class="newlywed_item">
<img class="img_newlywed" src="images/people/IMG_20260107_140120_301.jpg" alt="bride">
<img class="img_newlywed" src="images/people/bride.webp" alt="bride" loading="lazy"
decoding="async">
<div class="newlywed_text">
<h3 class="newlywed_title">Невеста</h3>
<p class="newlywed_info">Lorem ipsum dolor sit amet consectetur adipisicing elit. Qui voluptatum
odio autem, ut dolorum suscipit soluta reiciendis quam reprehenderit saepe doloribus
asperiores
architecto? Debitis magnam, exercitationem nam temporibus eos molestias?</p>
<p class="newlywed_info">Я — творческий и активный человек, люблю петь, путешествовать и
создавать что-то своими руками. Увлекаюсь готовкой, особенно десертами, которыми радую
близких. Люблю веселье, тусовки, животных и жизнь без
скуки.
</p>
</div>
</div>
</div>
<div class="guest_list">
<!-- <div class="guest_list">
<div class="guest_inner">
<!-- 1 -->
<div class="guest_item">
<!-- <div class="guest_item">
<div class="guest_index">
Стол 1
</div>
@@ -147,9 +163,9 @@
Lorem, ipsum.
</div>
</div>
</div>
<!-- 2 -->
<div class="guest_item">
</div> -->
<!-- 2 -->
<!-- <div class="guest_item">
<div class="guest_index">
Стол 1
</div>
@@ -176,9 +192,9 @@
Lorem, ipsum.
</div>
</div>
</div>
<!-- 3 -->
<div class="guest_item">
</div> -->
<!-- 3 -->
<!-- <div class="guest_item">
<div class="guest_index">
Стол 1
</div>
@@ -205,8 +221,8 @@
Lorem, ipsum.
</div>
</div>
</div>
</div>
</div> -->
</div>
</div>
</section>
<section class="timetable" id="timetable">
@@ -220,70 +236,68 @@
<!-- 1 -->
<div class="row_up_item">
<div class="time_img_box">
<img src="images/time/ring.png" alt="ring" class="time_img">
<h6 class="time_h6">10:40</h6>
<p class="time_p">Церемония</p>
<div class="time_comment">Начало нашего свадебного дня и самый важный момент для нас
<img src="images/time/guest1.webp" alt="ring" class="time_img" loading="lazy"
decoding="async">
<h6 class="time_h6">10:10</h6>
<p class="time_p">Сбор гостей</p>
<div class="time_comment">Приходите заранее, чтобы спокойно встретиться и сделать
фото
</div>
</div>
</div>
<!-- 2 -->
<div class="row_up_item">
<div class="time_img_box">
<img src="images/time/camera.png" alt="camera" class="time_img">
<img src="images/time/ring.webp" alt="ring" class="time_img" loading="lazy"
decoding="async">
<h6 class="time_h6">10:40</h6>
<p class="time_p">Церемония</p>
<div class="time_comment">Самый трогательный и важный момент дня — регистрация
нашего брака
</div>
</div>
</div>
<!-- 3 -->
<div class="row_up_item">
<div class="time_img_box">
<img src="images/time/camera.webp" alt="camera" class="time_img" loading="lazy"
decoding="async">
<h6 class="time_h6">11:30</h6>
<p class="time_p">Фотосессия</p>
<div class="time_comment">После церемонии мы ненадолго отправимся на фотосессию,
чтобы сохранить этот день в памяти</div>
</div>
</div>
<!-- 3 -->
<div class="row_up_item">
<div class="time_img_box">
<img src="images/time/wedding-dinner_11196102.png" alt="" class="time_img">
<h6 class="time_h6">14:00</h6>
<p class="time_p">Фуршет и бармен</p>
<div class="time_comment">Берем напиток, закуски и наслаждаемся началом вечера</div>
</div>
</div>
</div>
<div class="time_row_down">
<!-- 4 -->
<div class="row_up_item">
<div class="time_img_box">
<img src="images/time/free-icon-fireworks-7201451.png" alt="" class="time_img">
<h6 class="time_h6">14:30</h6>
<p class="time_p">Поздравления и подарки</p>
<div class="time_comment">Мы будем рады теплым словам и подаркам во время фуршета
</div>
<img src="images/time/wedding-dinner_11196102.webp" alt="" class="time_img"
loading="lazy" decoding="async">
<h6 class="time_h6">18:30</h6>
<p class="time_p">Сбор гостей и фуршет</p>
<div class="time_comment">Берем напиток, закуски и наслаждаемся началом вечера</div>
</div>
</div>
</div>
<div class="time_line"></div>
<div class="time_row_down">
<!-- 5 -->
<div class="row_up_item">
<div class="time_img_box">
<img src="images/time/food.png" alt="" class="time_img">
<h6 class="time_h6">17:00</h6>
<img src="images/time/food.webp" alt="" class="time_img" loading="lazy"
decoding="async">
<h6 class="time_h6">19:00</h6>
<p class="time_p">Банкет</p>
<div class="time_comment">Приглашаем вас за столы, чтобы продолжить вечер в тёплой и
уютной атмосфере. Приветственный тост</div>
уютной атмосфере
</div>
</div>
</div>
<!-- 6 -->
<div class="row_up_item">
<div class="time_img_box">
<img src="images/time/cake.png" alt="" class="time_img">
<h6 class="time_h6">19:00</h6>
<p class="time_p">Свадебный торт</p>
<div class="time_comment">Самый сладкий момент вечера. Чай или кофе находятся в
велком зоне</div>
</div>
</div>
<!-- 7 -->
<div class="row_up_item">
<div class="time_img_box">
<img src="images/time/disco-ball_18181959.png" alt="" class="time_img">
<h6 class="time_h6">19:30</h6>
<img src="images/time/disco-ball_18181959.webp" alt="" class="time_img"
loading="lazy" decoding="async">
<h6 class="time_h6">22:00</h6>
<p class="time_p">Танцы</p>
<div class="time_comment">Приглашаем вас на танцпол. Танцуйте столько, сколько
захочется</div>
@@ -293,6 +307,7 @@
</div>
</div>
</div>
</div>
</section>
<section class="transfer" id="transfer">
<h4 class="transfer_title">
@@ -301,25 +316,34 @@
<div class="transfer_inner">
<div class="transfer_map">
<div class="map">
<div style="position:relative;overflow:hidden; border-radius: 33px;">
<a href="https://www.google.com/maps/place/Glavnoye+Upravleniye+Zapisi+Aktov+Grazhdanskogo+Sostoyaniya+Tverskoy+Oblasti/@56.8571039,35.901453,17z/data=!3m1!4b1!4m6!3m5!1s0x46b687a4d4edacad:0x15df9a38c874eb5d!8m2!3d56.857101!4d35.9040279!16s%2Fg%2F11ls6j2lvj?entry=ttu&g_ep=EgoyMDI2MDMxMS4wIKXMDSoASAFQAw%3D%3D"
style="color:#eee;font-size:12px;position:absolute;top:0px;">
Главное управление записи актов гражданского состояния</a>
<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2181.349338718406!2d35.901452977352925!3d56.85710390639812!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x46b687a4d4edacad%3A0x15df9a38c874eb5d!2sGlavnoye%20Upravleniye%20Zapisi%20Aktov%20Grazhdanskogo%20Sostoyaniya%20Tverskoy%20Oblasti!5e0!3m2!1sen!2s!4v1773428540512!5m2!1sen!2s" width="760" height="500" style="border:1px;" allowfullscreen="true" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>
<div class="map_div">
<a href="https://maps.app.goo.gl/ZYTyA2qTvCpnXTdN7" target="_blank" class="map_link">
<img src="images/maps/zags.webp" alt="ЗАГС" class="map_preview" loading="lazy">
<div class="map_btn">
Открыть маршрут
</div>
</a>
</div>
<p class="map_adress">Тверь, Свободный переулок, 5</p>
<a href="https://maps.app.goo.gl/ZYTyA2qTvCpnXTdN7" class="map_adress" target="_blank">Тверь,
Свободный переулок, 5</a>
<h6 class="map_info">Начало в</h6>
<h6 class="map_time">10:30</h6>
<h6 class="map_time">10:10</h6>
</div>
<div class="map">
<div style="position:relative;overflow:hidden; border-radius: 33px;">
<a href="https://www.google.com/maps/place/Loft+1870+%7C+%D0%9F%D0%BB%D0%BE%D1%89%D0%B0%D0%B4%D0%BA%D0%B0+%D0%B4%D0%BB%D1%8F+%D0%BC%D0%B5%D1%80%D0%BE%D0%BF%D1%80%D0%B8%D1%8F%D1%82%D0%B8%D0%B9+%D0%A2%D0%B2%D0%B5%D1%80%D1%8C+%7C+%D0%BA%D0%B5%D0%B9%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B3+%D0%BD%D0%B0+%D1%81%D0%B2%D0%B0%D0%B4%D1%8C%D0%B1%D1%83,+%D0%B1%D0%B0%D0%BD%D0%BA%D0%B5%D1%82%D0%BD%D1%8B%D0%B9+%D0%B7%D0%B0%D0%BB/@56.850656,35.8603082,17.32z/data=!3m1!5s0x46b687a53bac0dcf:0x5c270d07d710d5a!4m6!3m5!1s0x46b68764eb0c1387:0x7cb135f5414bc1e0!8m2!3d56.8508612!4d35.8650531!16s%2Fg%2F11p0wc5v7q?entry=ttu&g_ep=EgoyMDI2MDMxMS4wIKXMDSoASAFQAw%3D%3D"
style="color:#eee;font-size:12px;position:absolute;top:0px;">Лофт 1870</a>
<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d1749.675516895515!2d35.86030818806184!3d56.850656040536194!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x46b68764eb0c1387%3A0x7cb135f5414bc1e0!2zTG9mdCAxODcwIHwg0J_Qu9C-0YnQsNC00LrQsCDQtNC70Y8g0LzQtdGA0L7Qv9GA0LjRj9GC0LjQuSDQotCy0LXRgNGMIHwg0LrQtdC50YLQtdGA0LjQvdCzINC90LAg0YHQstCw0LTRjNCx0YMsINCx0LDQvdC60LXRgtC90YvQuSDQt9Cw0Ls!5e0!3m2!1sen!2s!4v1773428705434!5m2!1sen!2s" width="760" height="500" style="border:1px;" allowfullscreen="true" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>
<div class="map_div">
<a href="https://maps.app.goo.gl/5WFQzNhDqmo2dBxXA" target="_blank" class="map_link">
<img src="images/maps/loft.webp" alt="ЗАГС" class="map_preview" loading="lazy">
<div class="map_btn">
Открыть маршрут
</div>
</a>
</div>
<p class="map_adress">Тверь, улица Двор Пролетарки, 16</p>
<a href="https://maps.app.goo.gl/5WFQzNhDqmo2dBxXA" class="map_adress" target="_blank">Тверь,
улица Двор Пролетарки, 16</a>
<h6 class="map_info">Начало в</h6>
<h6 class="map_time">14:00</h6>
<h6 class="map_time">18:30</h6>
</div>
</div>
</div>
@@ -329,54 +353,61 @@
Фотографии
</h4>
<!-- Slider main container -->
<div class="swiper">
<!-- Additional required wrapper -->
<div class="swiper-wrapper">
<!-- Slides -->
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/IMG_20260223_151005_128.jpg" alt="photo">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos//IMG_20260223_151049_713.jpg" alt="photo">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/IMG_20260223_151005_128.jpg" alt="photo">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/IMG_20260223_151049_713.jpg" alt="photo">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/IMG_20260223_151005_128.jpg" alt="photo">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/IMG_20260223_151049_713.jpg" alt="photo">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/IMG_20260223_151005_128.jpg" alt="photo">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/IMG_20260223_151005_128.jpg" alt="photo">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/IMG_20260223_151005_128.jpg" alt="photo">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/IMG_20260223_151005_128.jpg" alt="photo">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/IMG_20260223_151005_128.jpg" alt="photo">
</div>
</div>
<!-- If we need pagination -->
<div class="swiper-pagination"></div>
<div class="swiper">
<!-- Additional required wrapper -->
<div class="swiper-wrapper">
<!-- Slides -->
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/1.webp" alt="photo" width="500" height="500"
loading="lazy" decoding="async">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/2.webp" alt="photo" width="500" height="500"
loading="lazy" decoding="async">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/3.webp" alt="photo" width="500" height="500"
loading="lazy" decoding="async">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/4.webp" alt="photo" width="500" height="500"
loading="lazy" decoding="async">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/5.webp" alt="photo" width="500" height="500"
loading="lazy" decoding="async">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/6.webp" alt="photo" width="500" height="500"
loading="lazy" decoding="async">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/7.webp" alt="photo" width="500" height="500"
loading="lazy" decoding="async">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/8.webp" alt="photo" width="500" height="500"
loading="lazy" decoding="async">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/9.webp" alt="photo" width="500" height="500"
loading="lazy" decoding="async">
</div>
<div class="swiper-slide">
<img class="swiper_img" src="images/photos/10.webp" alt="photo" width="500" height="500"
loading="lazy" decoding="async">
</div>
</div>
<!-- If we need pagination -->
<div class="swiper-pagination"></div>
<!-- If we need navigation buttons -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<!-- If we need navigation buttons -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<!-- If we need scrollbar -->
<div class="swiper-scrollbar"></div>
</div>
<!-- If we need scrollbar -->
<div class="swiper-scrollbar"></div>
</div>
</section>
<section class="to-do-list" id="to-do-list">
<h4 class="do-list_title">
@@ -385,133 +416,279 @@
<div class="to-do-list_wrapper">
<div class="to-do-list_items">
<div class="to-do-list_item">
<img class="to-do-list_item_img" src="images/icon.png" alt="icon">
<svg style="enable-background:new 0 0 24 24;" version="1.1" viewBox="0 0 24 24"
xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css">
.st0 {
display: none;
}
</style>
<g class="st0" id="grid" />
<g id="icon">
<path
d="M5.528,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199L23.899,5.275c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.166-0.535-0.124-0.7,0.099 L12.91,18.226l-6.677-7.839C6.053,10.176,5.736,10.151,5.528,10.33z" />
<path
d="M12.028,13.945l6.519-8.67c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.167-0.535-0.12-0.7,0.099l-6.519,8.67 c-0.166,0.221-0.122,0.534,0.099,0.7c0.091,0.068,0.196,0.101,0.301,0.101C11.78,14.145,11.931,14.075,12.028,13.945z" />
<path
d="M0.176,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199l0.967-1.285c0.166-0.221,0.122-0.534-0.099-0.7c-0.219-0.166-0.535-0.123-0.7,0.099 l-0.592,0.786l-6.677-7.839C0.7,10.176,0.385,10.151,0.176,10.33z" />
</g>
</svg>
Поздравить молодых и сказать тёплые слова
</div>
<div class="to-do-list_item">
<img class="to-do-list_item_img" src="images/icon.png" alt="icon">
<svg style="enable-background:new 0 0 24 24;" version="1.1" viewBox="0 0 24 24"
xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css">
.st0 {
display: none;
}
</style>
<g class="st0" id="grid" />
<g id="icon">
<path
d="M5.528,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199L23.899,5.275c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.166-0.535-0.124-0.7,0.099 L12.91,18.226l-6.677-7.839C6.053,10.176,5.736,10.151,5.528,10.33z" />
<path
d="M12.028,13.945l6.519-8.67c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.167-0.535-0.12-0.7,0.099l-6.519,8.67 c-0.166,0.221-0.122,0.534,0.099,0.7c0.091,0.068,0.196,0.101,0.301,0.101C11.78,14.145,11.931,14.075,12.028,13.945z" />
<path
d="M0.176,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199l0.967-1.285c0.166-0.221,0.122-0.534-0.099-0.7c-0.219-0.166-0.535-0.123-0.7,0.099 l-0.592,0.786l-6.677-7.839C0.7,10.176,0.385,10.151,0.176,10.33z" />
</g>
</svg>
Вручить подарок молодожёнам
</div>
<div class="to-do-list_item">
<img class="to-do-list_item_img" src="images/icon.png" alt="icon">
<svg style="enable-background:new 0 0 24 24;" version="1.1" viewBox="0 0 24 24"
xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css">
.st0 {
display: none;
}
</style>
<g class="st0" id="grid" />
<g id="icon">
<path
d="M5.528,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199L23.899,5.275c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.166-0.535-0.124-0.7,0.099 L12.91,18.226l-6.677-7.839C6.053,10.176,5.736,10.151,5.528,10.33z" />
<path
d="M12.028,13.945l6.519-8.67c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.167-0.535-0.12-0.7,0.099l-6.519,8.67 c-0.166,0.221-0.122,0.534,0.099,0.7c0.091,0.068,0.196,0.101,0.301,0.101C11.78,14.145,11.931,14.075,12.028,13.945z" />
<path
d="M0.176,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199l0.967-1.285c0.166-0.221,0.122-0.534-0.099-0.7c-0.219-0.166-0.535-0.123-0.7,0.099 l-0.592,0.786l-6.677-7.839C0.7,10.176,0.385,10.151,0.176,10.33z" />
</g>
</svg>
Сделать фото и видео, чтобы потом было что выложить
</div>
<div class="to-do-list_item">
<img class="to-do-list_item_img" src="images/icon.png" alt="icon">
<svg style="enable-background:new 0 0 24 24;" version="1.1" viewBox="0 0 24 24"
xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css">
.st0 {
display: none;
}
</style>
<g class="st0" id="grid" />
<g id="icon">
<path
d="M5.528,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199L23.899,5.275c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.166-0.535-0.124-0.7,0.099 L12.91,18.226l-6.677-7.839C6.053,10.176,5.736,10.151,5.528,10.33z" />
<path
d="M12.028,13.945l6.519-8.67c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.167-0.535-0.12-0.7,0.099l-6.519,8.67 c-0.166,0.221-0.122,0.534,0.099,0.7c0.091,0.068,0.196,0.101,0.301,0.101C11.78,14.145,11.931,14.075,12.028,13.945z" />
<path
d="M0.176,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199l0.967-1.285c0.166-0.221,0.122-0.534-0.099-0.7c-0.219-0.166-0.535-0.123-0.7,0.099 l-0.592,0.786l-6.677-7.839C0.7,10.176,0.385,10.151,0.176,10.33z" />
</g>
</svg>
Поднять тост за любовь
</div>
<div class="to-do-list_item">
<img class="to-do-list_item_img" src="images/icon.png" alt="icon">
<svg style="enable-background:new 0 0 24 24;" version="1.1" viewBox="0 0 24 24"
xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css">
.st0 {
display: none;
}
</style>
<g class="st0" id="grid" />
<g id="icon">
<path
d="M5.528,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199L23.899,5.275c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.166-0.535-0.124-0.7,0.099 L12.91,18.226l-6.677-7.839C6.053,10.176,5.736,10.151,5.528,10.33z" />
<path
d="M12.028,13.945l6.519-8.67c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.167-0.535-0.12-0.7,0.099l-6.519,8.67 c-0.166,0.221-0.122,0.534,0.099,0.7c0.091,0.068,0.196,0.101,0.301,0.101C11.78,14.145,11.931,14.075,12.028,13.945z" />
<path
d="M0.176,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199l0.967-1.285c0.166-0.221,0.122-0.534-0.099-0.7c-0.219-0.166-0.535-0.123-0.7,0.099 l-0.592,0.786l-6.677-7.839C0.7,10.176,0.385,10.151,0.176,10.33z" />
</g>
</svg>
Добраться до свадебного торта, сфотографировать его
</div>
<div class="to-do-list_item">
<img class="to-do-list_item_img" src="images/icon.png" alt="icon">
<svg style="enable-background:new 0 0 24 24;" version="1.1" viewBox="0 0 24 24"
xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css">
.st0 {
display: none;
}
</style>
<g class="st0" id="grid" />
<g id="icon">
<path
d="M5.528,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199L23.899,5.275c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.166-0.535-0.124-0.7,0.099 L12.91,18.226l-6.677-7.839C6.053,10.176,5.736,10.151,5.528,10.33z" />
<path
d="M12.028,13.945l6.519-8.67c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.167-0.535-0.12-0.7,0.099l-6.519,8.67 c-0.166,0.221-0.122,0.534,0.099,0.7c0.091,0.068,0.196,0.101,0.301,0.101C11.78,14.145,11.931,14.075,12.028,13.945z" />
<path
d="M0.176,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199l0.967-1.285c0.166-0.221,0.122-0.534-0.099-0.7c-0.219-0.166-0.535-0.123-0.7,0.099 l-0.592,0.786l-6.677-7.839C0.7,10.176,0.385,10.151,0.176,10.33z" />
</g>
</svg>
Потанцевать хотя бы один медленный танец
</div>
<div class="to-do-list_item">
<img class="to-do-list_item_img" src="images/icon.png" alt="icon">
<svg style="enable-background:new 0 0 24 24;" version="1.1" viewBox="0 0 24 24"
xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css">
.st0 {
display: none;
}
</style>
<g class="st0" id="grid" />
<g id="icon">
<path
d="M5.528,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199L23.899,5.275c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.166-0.535-0.124-0.7,0.099 L12.91,18.226l-6.677-7.839C6.053,10.176,5.736,10.151,5.528,10.33z" />
<path
d="M12.028,13.945l6.519-8.67c0.166-0.221,0.122-0.534-0.099-0.7c-0.222-0.167-0.535-0.12-0.7,0.099l-6.519,8.67 c-0.166,0.221-0.122,0.534,0.099,0.7c0.091,0.068,0.196,0.101,0.301,0.101C11.78,14.145,11.931,14.075,12.028,13.945z" />
<path
d="M0.176,10.33c-0.21,0.18-0.235,0.495-0.057,0.705l7.082,8.314c0.096,0.111,0.234,0.176,0.381,0.176c0.005,0,0.01,0,0.016,0 c0.151-0.005,0.293-0.078,0.384-0.199l0.967-1.285c0.166-0.221,0.122-0.534-0.099-0.7c-0.219-0.166-0.535-0.123-0.7,0.099 l-0.592,0.786l-6.677-7.839C0.7,10.176,0.385,10.151,0.176,10.33z" />
</g>
</svg>
Повеселиться так, чтобы этот день запомнился
</div>
</div>
</div>
</section>
<section class="answer" id="answer">
<h4 class="answer_title">Прошу ответить</h4>
<h4 class="answer_title">Прошу ответить</h4>
<div class="answer_wrapper">
<h6 class="answer_heading">
Просим Вас заполнить форму и подтвердить своё участие
</h6>
<div class="answer_wrapper">
<h6 class="answer_heading">
Просим Вас заполнить форму и подтвердить своё участие
</h6>
<form class="form-info">
<form class="form-info">
<!-- Левая колонка -->
<div class="form_name">
<label>Имя
<input type="text" name="firstName" id="ffname" required>
</label>
<!-- Левая колонка -->
<div class="form_name">
<label class="label_style">Имя
<input type="text" name="firstName" id="ffname" required>
</label>
<label>Отчество
<input type="text" name="middleName" id="fmname" required>
</label>
<label class="label_style">Отчество
<input type="text" name="middleName" id="fmname" required>
</label>
<label>Фамилия
<input type="text" name="lastName" id="flname" required>
</label>
<label class="label_style">Фамилия
<input type="text" name="lastName" id="flname" required>
</label>
<label class="label_1">Комментарий
<textarea cols="1.5" rows="1" type="text" name="lastName" id="fename"
placeholder="Напишите здесь о ваших особых предпочтениях и аллергиях"></textarea>
</label>
</div>
<!-- Средняя колонка -->
<div class="form_menu">
<p class="block_title">Горячее блюдо</p>
<label class="option">
<input type="radio" name="food" id="rmeat" value="meat" required>
Мясо
</label>
<label class="option">
<input type="radio" name="food" id="rfish" value="fish">
Рыба
</label>
</div>
<!-- Правая колонка -->
<div class="form_drink">
<p class="block_title">Напитки</p>
<label class="option"><input type="checkbox" name="drink" value="champagne" id="cchampagne">
Шампанское</label>
<label class="option"><input type="checkbox" name="drink" value="wine" id="cwine"> Вино</label>
<label class="option"><input type="checkbox" name="drink" value="vodka" id="cvodka">
Водка</label>
<label class="option"><input type="checkbox" name="drink" value="whiskey" id="cwhiskey">
Виски</label>
<label class="option"><input type="checkbox" name="drink" value="tequila" id="ctequila">
Текила</label>
</div>
</form>
<form class="form-connect">
<button type="submit" class="answer_btn" id="bsubmit">
Подтвердить участие
</button>
<button type="logout" class="answer_btn" id="logoutForm">
Выйти
</button>
</form>
</div>
<!-- Средняя колонка -->
<div class="form_menu">
<p class="block_title">Горячее блюдо</p>
<label class="option">
<input type="radio" name="food" id="rmeat" value="meat" required>
Мясо
</label>
<label class="option">
<input type="radio" name="food" id="rfish" value="fish">
Рыба
</label>
</div>
<!-- Правая колонка -->
<div class="form_drink">
<p class="block_title">Напитки</p>
<label class="option"><input type="checkbox" name="drink" value="champagne" id="cchampagne"> Шампанское</label>
<label class="option"><input type="checkbox" name="drink" value="wine" id="cwine"> Вино</label>
<label class="option"><input type="checkbox" name="drink" value="vodka" id="cvodka"> Водка</label>
<label class="option"><input type="checkbox" name="drink" value="whiskey" id="cwhiskey"> Виски</label>
<label class="option"><input type="checkbox" name="drink" value="tequila" id="ctequila"> Текила</label>
</div>
<button type="submit" class="answer_btn" id="bsubmit">
Подтвердить участие
</button>
</form>
</div>
</section>
</main>
<footer class="footer">
<div class="footer_inner">
<div class="footer_title">
<h1 class="fotter_logo">
Алёна и Дмитрий
</h1>
<p class="footer_date">22 августа 2026</p>
<p class="footer_place">LOFT 1870</p>
<h1 class="fotter_logo">
Алёна и Дмитрий
</h1>
<p class="footer_date">22 августа 2026</p>
<p class="footer_place">LOFT 1870</p>
</div>
<div class="footer_contacts">
<p class="footer_text">"С нетерпением ждем встречи!"</p>
<div class="footer_cntcts">
<a class="footer_cnt" href="https://t.me/Alena7729" target="_blank"><?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="40px" height="40px" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="14" fill="url(#paint0_linear_87_7225)"/>
<path d="M22.9866 10.2088C23.1112 9.40332 22.3454 8.76755 21.6292 9.082L7.36482 15.3448C6.85123 15.5703 6.8888 16.3483 7.42147 16.5179L10.3631 17.4547C10.9246 17.6335 11.5325 17.541 12.0228 17.2023L18.655 12.6203C18.855 12.4821 19.073 12.7665 18.9021 12.9426L14.1281 17.8646C13.665 18.3421 13.7569 19.1512 14.314 19.5005L19.659 22.8523C20.2585 23.2282 21.0297 22.8506 21.1418 22.1261L22.9866 10.2088Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear_87_7225" x1="16" y1="2" x2="16" y2="30" gradientUnits="userSpaceOnUse">
<stop stop-color="#37BBFE"/>
<stop offset="1" stop-color="#007DBB"/>
</linearGradient>
</defs>
</svg>
Алёна</a>
<a class="footer_cnt" href="https://t.me/DisaTylov" target="_blank"><?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="40px" height="40px" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="14" fill="url(#paint0_linear_87_7225)"/>
<path d="M22.9866 10.2088C23.1112 9.40332 22.3454 8.76755 21.6292 9.082L7.36482 15.3448C6.85123 15.5703 6.8888 16.3483 7.42147 16.5179L10.3631 17.4547C10.9246 17.6335 11.5325 17.541 12.0228 17.2023L18.655 12.6203C18.855 12.4821 19.073 12.7665 18.9021 12.9426L14.1281 17.8646C13.665 18.3421 13.7569 19.1512 14.314 19.5005L19.659 22.8523C20.2585 23.2282 21.0297 22.8506 21.1418 22.1261L22.9866 10.2088Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear_87_7225" x1="16" y1="2" x2="16" y2="30" gradientUnits="userSpaceOnUse">
<stop stop-color="#37BBFE"/>
<stop offset="1" stop-color="#007DBB"/>
</linearGradient>
</defs>
</svg>
Дмитрий</a>
</div>
<a class="footer_cnt" href="https://t.me/Alena7729" target="_blank">
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="40px" height="40px" viewBox="0 0 32 32" fill="none"
xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="14" fill="url(#paint0_linear_87_7225)" />
<path
d="M22.9866 10.2088C23.1112 9.40332 22.3454 8.76755 21.6292 9.082L7.36482 15.3448C6.85123 15.5703 6.8888 16.3483 7.42147 16.5179L10.3631 17.4547C10.9246 17.6335 11.5325 17.541 12.0228 17.2023L18.655 12.6203C18.855 12.4821 19.073 12.7665 18.9021 12.9426L14.1281 17.8646C13.665 18.3421 13.7569 19.1512 14.314 19.5005L19.659 22.8523C20.2585 23.2282 21.0297 22.8506 21.1418 22.1261L22.9866 10.2088Z"
fill="white" />
<defs>
<linearGradient id="paint0_linear_87_7225" x1="16" y1="2" x2="16" y2="30"
gradientUnits="userSpaceOnUse">
<stop stop-color="#37BBFE" />
<stop offset="1" stop-color="#007DBB" />
</linearGradient>
</defs>
</svg>
Алёна
</a>
<a class="footer_cnt" href="https://t.me/DisaTylov" target="_blank">
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="40px" height="40px" viewBox="0 0 32 32" fill="none"
xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="14" fill="url(#paint0_linear_87_7225)" />
<path
d="M22.9866 10.2088C23.1112 9.40332 22.3454 8.76755 21.6292 9.082L7.36482 15.3448C6.85123 15.5703 6.8888 16.3483 7.42147 16.5179L10.3631 17.4547C10.9246 17.6335 11.5325 17.541 12.0228 17.2023L18.655 12.6203C18.855 12.4821 19.073 12.7665 18.9021 12.9426L14.1281 17.8646C13.665 18.3421 13.7569 19.1512 14.314 19.5005L19.659 22.8523C20.2585 23.2282 21.0297 22.8506 21.1418 22.1261L22.9866 10.2088Z"
fill="white" />
<defs>
<linearGradient id="paint0_linear_87_7225" x1="16" y1="2" x2="16" y2="30"
gradientUnits="userSpaceOnUse">
<stop stop-color="#37BBFE" />
<stop offset="1" stop-color="#007DBB" />
</linearGradient>
</defs>
</svg>
Дмитрий
</a>
</div>
</div>
<div class="footer_copy">
<div class="footer_hashtag">#свадьба2026</div>

View File

@@ -1,30 +1,91 @@
const swiper = new Swiper('.swiper', {
// Optional parameters
direction: 'horizontal',
loop: true,
// Navigation arrows
direction: 'horizontal',
loop: false,
// Производительность
preloadImages: false,
lazy: true,
watchSlidesProgress: true,
// Слайды
slidesPerView: 3,
spaceBetween: 15,
// Анимация
speed: 700,
// Навигация
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
// And if we need scrollbar
// Скроллбар
scrollbar: {
el: '.swiper-scrollbar',
hide: true,
},
speed: 1000,
breakpoints: {
740: {
slidesPerView: 1,
},
1200: {
slidesPerView: 2,
},
1600: {
slidesPerView: 3,
},
// Адаптив
breakpoints: {
330: {
slidesPerView: 1,
},
768: {
slidesPerView: 2,
},
1400: {
slidesPerView: 3,
},
}
});
// Set the date we're counting down to
var countDownDate = new Date("Aug 22, 2026 10:40:00").getTime();
// Update the count down every 1 second
var x = setInterval(function() {
// Get today's date and time
var now = new Date().getTime();
// Find the distance between now and the count down date
var distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Display the result in the element with id="demo"
document.getElementById("demo").innerHTML = days + "д " + hours + "ч "
+ minutes + "м " + seconds + "с ";
// If the count down is finished, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("demo").innerHTML = "EXPIRED";
}
}, 1000);
const burger = document.getElementById('burger');
const nav = document.getElementById('nav');
const links = document.querySelectorAll('.menu .link');
burger.addEventListener('click', () => {
burger.classList.toggle('active');
nav.classList.toggle('active');
});
links.forEach(link => {
link.addEventListener('click', () => {
burger.classList.remove('active');
nav.classList.remove('active');
});
});

File diff suppressed because it is too large Load Diff