first init

This commit is contained in:
Arsen Mirzaev Tatyano-Muradovich 2022-11-28 22:07:45 +10:00
parent e696e1e574
commit a069a720f8
74 changed files with 7264 additions and 7 deletions

9
.gitignore vendored
View File

@ -1,8 +1,3 @@
# ---> Composer !.gitignore
composer.phar composer.phar
/vendor/ vendor
# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
# composer.lock

57
composer.json Normal file
View File

@ -0,0 +1,57 @@
{
"name": "mirzaev/site-wanda",
"description": "Site about my friend Wanda Switch",
"readme": "README.md",
"keywords": [
"site",
"funny",
"love",
"friendship"
],
"type": "site",
"homepage": "https://git.mirzaev.sexy/mirzaev/site-wanda",
"license": "WTFPL",
"authors": [
{
"name": "Arsen Mirzaev Tatyano-Muradovich",
"email": "arsen@mirzaev.sexy",
"homepage": "https://mirzaev.sexy",
"role": "Programmer"
}
],
"support": {
"email": "arsen@mirzaev.sexy",
"wiki": "https://git.mirzaev.sexy/mirzaev/site-wanda/wiki",
"issues": "https://git.mirzaev.sexy/mirzaev/site-wanda/issues"
},
"funding": [
{
"type": "funding",
"url": "https://fund.mirzaev.sexy"
}
],
"require": {
"php": "~8.1",
"ext-sodium": "~8.1",
"mirzaev/minimal": "^2.0.x-dev",
"mirzaev/accounts": "~1.2.x-dev",
"mirzaev/arangodb": "^1.0.0",
"mirzaev/vk": "^5.0",
"triagens/arangodb": "~3.9.x-dev",
"twig/twig": "^3.4",
"guzzlehttp/guzzle": "^7.5"
},
"require-dev": {
"phpunit/phpunit": "~9.5"
},
"autoload": {
"psr-4": {
"mirzaev\\site\\wanda\\": "mirzaev/site/wanda/system"
}
},
"autoload-dev": {
"psr-4": {
"mirzaev\\site\\wanda\\tests\\": "mirzaev/site/wanda/tests"
}
}
}

3051
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace mirzaev\site\wanda\controllers;
// Файлы проекта
use mirzaev\site\wanda\views\manager;
use mirzaev\site\wanda\models\core as models;
// Библиотека для ArangoDB
use ArangoDBClient\Document as _document;
// Фреймворк PHP
use mirzaev\minimal\controller;
// Фреймворк ВКонтакте
use mirzaev\vk\core as vk;
use mirzaev\vk\robots\user as robot;
/**
* Ядро контроллеров
*
* @package mirzaev\site\wanda\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class core extends controller
{
/**
* Переменные окружения
*/
protected robot $vk;
/**
* Переменные окружения
*/
protected array $variables = [];
/**
* Конструктор
*
* @return void
*/
public function __construct()
{
parent::__construct();
// Инициализация ядра моделей (соединение с базой данных...)
new models();
// Инициализация журнала ошибок
$this->variables['errors'] = [
];
// Инициализация препроцессора представления
$this->view = new manager;
}
}

View File

@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace mirzaev\site\wanda\controllers;
// Файлы проекта
use mirzaev\site\wanda\controllers\core;
/**
* Контроллер ошибок
*
* @package mirzaev\site\wanda\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class error_controller extends core
{
/**
* Страница с ошибкой
*
* @param array $parameters
*/
public function index(array $parameters = []): ?string
{
// Запись текста ошибки в переменную окружения
$this->variables['text'] = $parameters['text'] ?? null;
if (isset($parameters['code'])) {
// Получен код ошибки
// Запись кода ошибки в переменную окружения
$this->variables['code'] = $parameters['code'];
// Запись кода ответа
http_response_code($parameters['code']);
// Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
}
// Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . ($parameters['code'] ?? 'index') . '.html', $this->variables);
}
}

View File

@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace mirzaev\site\wanda\controllers;
// Файлы проекта
use mirzaev\site\wanda\controllers\core;
/**
* Контроллер основной страницы
*
* @package mirzaev\site\wanda\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class index_controller extends core
{
/**
* Главная страница
*
* @param array $parameters Параметры запроса
*/
public function index(array $parameters = []): ?string
{
// Инициализация загружаемых категорий
$this->variables['include'] = [
'head' => ['self'],
'body' => ['self']
];
// Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'index.html', $this->variables);
}
}

View File

@ -0,0 +1,143 @@
<?php
declare(strict_types=1);
namespace mirzaev\site\wanda\models;
use mirzaev\minimal\model;
use mirzaev\arangodb\connection;
use exception;
/**
* Ядро моделей
*
* @package mirzaev\site\wanda\models
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class core extends model
{
/**
* Коллекция в которой хранятся аккаунты
*/
public const SETTINGS = '../settings/arangodb.php';
/**
* Соединение с базой данных
*/
protected static connection $db;
public function __construct(connection $db = null)
{
if (isset($db)) {
// Получена инстанция соединения с базой данных
// Запись и инициализация соединения с базой данных
$this->__set('db', $db);
} else {
// Не получена инстанция соединения с базой данных
// Инициализация соединения с базой данных по умолчанию
$this->__get('db');
}
}
/**
* Записать свойство
*
* @param string $name Название
* @param mixed $value Значение
*/
public function __set(string $name, mixed $value = null): void
{
match ($name) {
'db' => (function () use ($value) {
if ($this->__isset('db')) {
// Свойство уже было инициализировано
// Выброс исключения (неудача)
throw new exception('Запрещено реинициализировать соединение с базой данных ($this->db)', 500);
} else {
// Свойство ещё не было инициализировано
if ($value instanceof connection) {
// Передано подходящее значение
// Запись свойства (успех)
self::$db = $value;
} else {
// Передано неподходящее значение
// Выброс исключения (неудача)
throw new exception('Соединение с базой данных ($this->db) должен быть инстанцией mirzaev\arangodb\connection', 500);
}
}
})(),
default => parent::__set($name, $value)
};
}
/**
* Прочитать свойство
*
* @param string $name Название
*
* @return mixed Содержимое
*/
public function __get(string $name): mixed
{
return match ($name) {
'db' => (function () {
if (!$this->__isset('db')) {
// Свойство не инициализировано
// Инициализация значения по умолчанию исходя из настроек
$this->__set('db', new connection(require static::SETTINGS));
}
return self::$db;
})(),
default => parent::__get($name)
};
}
/**
* Проверить свойство на инициализированность
*
* @param string $name Название
*/
public function __isset(string $name): bool
{
return match ($name) {
default => parent::__isset($name)
};
}
/**
* Удалить свойство
*
* @param string $name Название
*/
public function __unset(string $name): void
{
match ($name) {
default => parent::__isset($name)
};
}
/**
* Статический вызов
*
* @param string $name Название
* @param array $arguments Параметры
*/
public static function __callStatic(string $name, array $arguments): mixed
{
match ($name) {
'db' => (new static)->__get('db'),
default => throw new exception("Не найдено свойство или функция: $name", 500)
};
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>

View File

@ -0,0 +1,135 @@
@import url('/fonts/comissioner.ttf');
* {
text-decoration: none;
outline : none;
border : none;
color : var(--text);
font-family : 'Commissioner', sans-serif;
transition : 0.1s ease-out;
}
.unselectable {
-webkit-touch-callout: none;
-webkit-user-select : none;
-khtml-user-select : none;
-moz-user-select : none;
-ms-user-select : none;
user-select : none;
}
a {
color: var(--link);
}
a:hover {
color: var(--link-hover);
}
a:active {
color: var(--link-active);
}
body {
height : 100vh;
margin : 0;
overflow : hidden;
display : flex;
background: #fff;
}
aside {
z-index : 500;
grid-column: 1/ 4;
grid-row : 2;
overflow : hidden;
}
header {
z-index : 5000;
position : absolute;
display : flex;
flex-direction: column;
box-shadow : 2px 0 5px rgba(0, 0, 0, 0.3);
}
header>menu {
margin : unset;
padding : 20px;
display : flex;
flex-direction : column;
flex-grow : 1;
background-color: var(--background-light-1);
}
header>#account>button#login {
z-index: 1500;
}
header>menu a {
margin-bottom: 8px;
display : flex;
align-items : center;
}
header>menu a:last-child {
margin-bottom: unset;
}
header>menu a svg {
margin-right: 8px;
height : 1.2rem;
position : relative;
}
header>menu a:hover svg {
margin-left : -5px;
margin-right: 13px;
}
header>menu a svg path {
fill: var(--text);
}
header>section {
background-color: var(--background-light-1);
}
header :is(button, a[type="button"]) {
width : 100%;
height : 40px;
display : flex;
justify-content : center;
align-items : center;
cursor : pointer;
background-color: var(--red);
transition : unset;
}
header button {
font-weight : bold;
text-transform: uppercase;
}
header :is(button, a[type="button"]):hover {
background-color: var(--red-light);
}
header :is(button, a[type="button"]):active {
background-color: var(--red-dark);
}
header>nav {
margin-top : auto;
display : flex;
flex-direction: column;
}
main {
z-index: 1000;
}
footer {
z-index : 3000;
position: absolute;
}

View File

@ -0,0 +1,765 @@
#valentine {
width : 100vw;
height : 100vh;
display : flex;
justify-content: center;
align-items : center;
perspective : 1300px;
pointer-events: none;
}
div {
position : absolute;
transform-style: preserve-3d;
}
#chocolate_rains {
transform: rotateX(-15deg);
}
.heart .ring {
width : 300px;
height : 300px;
border-radius: 100%;
opacity : 0;
border : 1px solid red;
}
.heart .left {
left : -20px;
width : 20px;
height : 20px;
background : #c80000;
border-radius : 100%;
transform-origin: 100% 0;
}
.heart .left::before {
content : "";
position : absolute;
top : 10px;
width : 20px;
height : 25px;
background : #c80000;
border-radius: 0 0 0 100%;
}
.heart .right {
width : 20px;
height : 20px;
background : #c80000;
border-radius : 100%;
transform-origin: 0 0;
}
.heart .right::before {
content : "";
position : absolute;
top : 10px;
width : 20px;
height : 25px;
background : #c80000;
border-radius: 0 0 100% 0;
}
.heart .movable {
opacity: 0;
}
.heart .reverse {
transform: translateY(70px) rotateZ(180deg);
opacity : 0.1;
}
.heart .reverse .left,
.heart .reverse .right {
opacity: 0.5;
}
.heart:nth-child(1) {
transform: translateX(455px) translateZ(-691px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(1) .movable {
-webkit-animation: drop 5000ms -2569ms linear infinite;
animation : drop 5000ms -2569ms linear infinite;
}
.heart:nth-child(1) .ring {
-webkit-animation: wave 5000ms 1331ms ease-out infinite;
animation : wave 5000ms 1331ms ease-out infinite;
}
.heart:nth-child(1) .inner {
-webkit-animation: rotation 2734ms linear infinite;
animation : rotation 2734ms linear infinite;
}
.heart:nth-child(2) {
transform: translateX(396px) translateZ(697px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(2) .movable {
-webkit-animation: drop 5000ms -742ms linear infinite;
animation : drop 5000ms -742ms linear infinite;
}
.heart:nth-child(2) .ring {
-webkit-animation: wave 5000ms 3158ms ease-out infinite;
animation : wave 5000ms 3158ms ease-out infinite;
}
.heart:nth-child(2) .inner {
-webkit-animation: rotation 2211ms linear infinite;
animation : rotation 2211ms linear infinite;
}
.heart:nth-child(3) {
transform: translateX(266px) translateZ(-436px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(3) .movable {
-webkit-animation: drop 5000ms 537ms linear infinite;
animation : drop 5000ms 537ms linear infinite;
}
.heart:nth-child(3) .ring {
-webkit-animation: wave 5000ms 4437ms ease-out infinite;
animation : wave 5000ms 4437ms ease-out infinite;
}
.heart:nth-child(3) .inner {
-webkit-animation: rotation 3474ms linear infinite;
animation : rotation 3474ms linear infinite;
}
.heart:nth-child(4) {
transform: translateX(-329px) translateZ(-563px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(4) .movable {
-webkit-animation: drop 5000ms -1846ms linear infinite;
animation : drop 5000ms -1846ms linear infinite;
}
.heart:nth-child(4) .ring {
-webkit-animation: wave 5000ms 2054ms ease-out infinite;
animation : wave 5000ms 2054ms ease-out infinite;
}
.heart:nth-child(4) .inner {
-webkit-animation: rotation 3278ms linear infinite;
animation : rotation 3278ms linear infinite;
}
.heart:nth-child(5) {
transform: translateX(-414px) translateZ(215px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(5) .movable {
-webkit-animation: drop 5000ms 1318ms linear infinite;
animation : drop 5000ms 1318ms linear infinite;
}
.heart:nth-child(5) .ring {
-webkit-animation: wave 5000ms 5218ms ease-out infinite;
animation : wave 5000ms 5218ms ease-out infinite;
}
.heart:nth-child(5) .inner {
-webkit-animation: rotation 2130ms linear infinite;
animation : rotation 2130ms linear infinite;
}
.heart:nth-child(6) {
transform: translateX(-445px) translateZ(-614px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(6) .movable {
-webkit-animation: drop 5000ms 962ms linear infinite;
animation : drop 5000ms 962ms linear infinite;
}
.heart:nth-child(6) .ring {
-webkit-animation: wave 5000ms 4862ms ease-out infinite;
animation : wave 5000ms 4862ms ease-out infinite;
}
.heart:nth-child(6) .inner {
-webkit-animation: rotation 3069ms linear infinite;
animation : rotation 3069ms linear infinite;
}
.heart:nth-child(7) {
transform: translateX(499px) translateZ(39px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(7) .movable {
-webkit-animation: drop 5000ms -2544ms linear infinite;
animation : drop 5000ms -2544ms linear infinite;
}
.heart:nth-child(7) .ring {
-webkit-animation: wave 5000ms 1356ms ease-out infinite;
animation : wave 5000ms 1356ms ease-out infinite;
}
.heart:nth-child(7) .inner {
-webkit-animation: rotation 4560ms linear infinite;
animation : rotation 4560ms linear infinite;
}
.heart:nth-child(8) {
transform: translateX(154px) translateZ(-228px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(8) .movable {
-webkit-animation: drop 5000ms 1853ms linear infinite;
animation : drop 5000ms 1853ms linear infinite;
}
.heart:nth-child(8) .ring {
-webkit-animation: wave 5000ms 5753ms ease-out infinite;
animation : wave 5000ms 5753ms ease-out infinite;
}
.heart:nth-child(8) .inner {
-webkit-animation: rotation 4949ms linear infinite;
animation : rotation 4949ms linear infinite;
}
.heart:nth-child(9) {
transform: translateX(-288px) translateZ(-300px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(9) .movable {
-webkit-animation: drop 5000ms 883ms linear infinite;
animation : drop 5000ms 883ms linear infinite;
}
.heart:nth-child(9) .ring {
-webkit-animation: wave 5000ms 4783ms ease-out infinite;
animation : wave 5000ms 4783ms ease-out infinite;
}
.heart:nth-child(9) .inner {
-webkit-animation: rotation 3148ms linear infinite;
animation : rotation 3148ms linear infinite;
}
.heart:nth-child(10) {
transform: translateX(274px) translateZ(549px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(10) .movable {
-webkit-animation: drop 5000ms -1415ms linear infinite;
animation : drop 5000ms -1415ms linear infinite;
}
.heart:nth-child(10) .ring {
-webkit-animation: wave 5000ms 2485ms ease-out infinite;
animation : wave 5000ms 2485ms ease-out infinite;
}
.heart:nth-child(10) .inner {
-webkit-animation: rotation 3861ms linear infinite;
animation : rotation 3861ms linear infinite;
}
.heart:nth-child(11) {
transform: translateX(142px) translateZ(79px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(11) .movable {
-webkit-animation: drop 5000ms 157ms linear infinite;
animation : drop 5000ms 157ms linear infinite;
}
.heart:nth-child(11) .ring {
-webkit-animation: wave 5000ms 4057ms ease-out infinite;
animation : wave 5000ms 4057ms ease-out infinite;
}
.heart:nth-child(11) .inner {
-webkit-animation: rotation 2800ms linear infinite;
animation : rotation 2800ms linear infinite;
}
.heart:nth-child(12) {
transform: translateX(-360px) translateZ(-721px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(12) .movable {
-webkit-animation: drop 5000ms -1407ms linear infinite;
animation : drop 5000ms -1407ms linear infinite;
}
.heart:nth-child(12) .ring {
-webkit-animation: wave 5000ms 2493ms ease-out infinite;
animation : wave 5000ms 2493ms ease-out infinite;
}
.heart:nth-child(12) .inner {
-webkit-animation: rotation 3174ms linear infinite;
animation : rotation 3174ms linear infinite;
}
.heart:nth-child(13) {
transform: translateX(27px) translateZ(792px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(13) .movable {
-webkit-animation: drop 5000ms -1176ms linear infinite;
animation : drop 5000ms -1176ms linear infinite;
}
.heart:nth-child(13) .ring {
-webkit-animation: wave 5000ms 2724ms ease-out infinite;
animation : wave 5000ms 2724ms ease-out infinite;
}
.heart:nth-child(13) .inner {
-webkit-animation: rotation 4215ms linear infinite;
animation : rotation 4215ms linear infinite;
}
.heart:nth-child(14) {
transform: translateX(278px) translateZ(-694px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(14) .movable {
-webkit-animation: drop 5000ms 1363ms linear infinite;
animation : drop 5000ms 1363ms linear infinite;
}
.heart:nth-child(14) .ring {
-webkit-animation: wave 5000ms 5263ms ease-out infinite;
animation : wave 5000ms 5263ms ease-out infinite;
}
.heart:nth-child(14) .inner {
-webkit-animation: rotation 2320ms linear infinite;
animation : rotation 2320ms linear infinite;
}
.heart:nth-child(15) {
transform: translateX(481px) translateZ(366px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(15) .movable {
-webkit-animation: drop 5000ms -1590ms linear infinite;
animation : drop 5000ms -1590ms linear infinite;
}
.heart:nth-child(15) .ring {
-webkit-animation: wave 5000ms 2310ms ease-out infinite;
animation : wave 5000ms 2310ms ease-out infinite;
}
.heart:nth-child(15) .inner {
-webkit-animation: rotation 2371ms linear infinite;
animation : rotation 2371ms linear infinite;
}
.heart:nth-child(16) {
transform: translateX(-379px) translateZ(-124px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(16) .movable {
-webkit-animation: drop 5000ms -625ms linear infinite;
animation : drop 5000ms -625ms linear infinite;
}
.heart:nth-child(16) .ring {
-webkit-animation: wave 5000ms 3275ms ease-out infinite;
animation : wave 5000ms 3275ms ease-out infinite;
}
.heart:nth-child(16) .inner {
-webkit-animation: rotation 2053ms linear infinite;
animation : rotation 2053ms linear infinite;
}
.heart:nth-child(17) {
transform: translateX(255px) translateZ(-374px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(17) .movable {
-webkit-animation: drop 5000ms -90ms linear infinite;
animation : drop 5000ms -90ms linear infinite;
}
.heart:nth-child(17) .ring {
-webkit-animation: wave 5000ms 3810ms ease-out infinite;
animation : wave 5000ms 3810ms ease-out infinite;
}
.heart:nth-child(17) .inner {
-webkit-animation: rotation 2180ms linear infinite;
animation : rotation 2180ms linear infinite;
}
.heart:nth-child(18) {
transform: translateX(-339px) translateZ(419px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(18) .movable {
-webkit-animation: drop 5000ms 645ms linear infinite;
animation : drop 5000ms 645ms linear infinite;
}
.heart:nth-child(18) .ring {
-webkit-animation: wave 5000ms 4545ms ease-out infinite;
animation : wave 5000ms 4545ms ease-out infinite;
}
.heart:nth-child(18) .inner {
-webkit-animation: rotation 2716ms linear infinite;
animation : rotation 2716ms linear infinite;
}
.heart:nth-child(19) {
transform: translateX(-102px) translateZ(355px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(19) .movable {
-webkit-animation: drop 5000ms -2424ms linear infinite;
animation : drop 5000ms -2424ms linear infinite;
}
.heart:nth-child(19) .ring {
-webkit-animation: wave 5000ms 1476ms ease-out infinite;
animation : wave 5000ms 1476ms ease-out infinite;
}
.heart:nth-child(19) .inner {
-webkit-animation: rotation 3368ms linear infinite;
animation : rotation 3368ms linear infinite;
}
.heart:nth-child(20) {
transform: translateX(-134px) translateZ(714px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(20) .movable {
-webkit-animation: drop 5000ms 1537ms linear infinite;
animation : drop 5000ms 1537ms linear infinite;
}
.heart:nth-child(20) .ring {
-webkit-animation: wave 5000ms 5437ms ease-out infinite;
animation : wave 5000ms 5437ms ease-out infinite;
}
.heart:nth-child(20) .inner {
-webkit-animation: rotation 2578ms linear infinite;
animation : rotation 2578ms linear infinite;
}
.heart:nth-child(21) {
transform: translateX(-320px) translateZ(728px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(21) .movable {
-webkit-animation: drop 5000ms -606ms linear infinite;
animation : drop 5000ms -606ms linear infinite;
}
.heart:nth-child(21) .ring {
-webkit-animation: wave 5000ms 3294ms ease-out infinite;
animation : wave 5000ms 3294ms ease-out infinite;
}
.heart:nth-child(21) .inner {
-webkit-animation: rotation 2357ms linear infinite;
animation : rotation 2357ms linear infinite;
}
.heart:nth-child(22) {
transform: translateX(261px) translateZ(285px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(22) .movable {
-webkit-animation: drop 5000ms 680ms linear infinite;
animation : drop 5000ms 680ms linear infinite;
}
.heart:nth-child(22) .ring {
-webkit-animation: wave 5000ms 4580ms ease-out infinite;
animation : wave 5000ms 4580ms ease-out infinite;
}
.heart:nth-child(22) .inner {
-webkit-animation: rotation 2295ms linear infinite;
animation : rotation 2295ms linear infinite;
}
.heart:nth-child(23) {
transform: translateX(-371px) translateZ(-297px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(23) .movable {
-webkit-animation: drop 5000ms -1132ms linear infinite;
animation : drop 5000ms -1132ms linear infinite;
}
.heart:nth-child(23) .ring {
-webkit-animation: wave 5000ms 2768ms ease-out infinite;
animation : wave 5000ms 2768ms ease-out infinite;
}
.heart:nth-child(23) .inner {
-webkit-animation: rotation 2082ms linear infinite;
animation : rotation 2082ms linear infinite;
}
.heart:nth-child(24) {
transform: translateX(-169px) translateZ(663px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(24) .movable {
-webkit-animation: drop 5000ms 493ms linear infinite;
animation : drop 5000ms 493ms linear infinite;
}
.heart:nth-child(24) .ring {
-webkit-animation: wave 5000ms 4393ms ease-out infinite;
animation : wave 5000ms 4393ms ease-out infinite;
}
.heart:nth-child(24) .inner {
-webkit-animation: rotation 4600ms linear infinite;
animation : rotation 4600ms linear infinite;
}
.heart:nth-child(25) {
transform: translateX(83px) translateZ(-755px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(25) .movable {
-webkit-animation: drop 5000ms 317ms linear infinite;
animation : drop 5000ms 317ms linear infinite;
}
.heart:nth-child(25) .ring {
-webkit-animation: wave 5000ms 4217ms ease-out infinite;
animation : wave 5000ms 4217ms ease-out infinite;
}
.heart:nth-child(25) .inner {
-webkit-animation: rotation 2607ms linear infinite;
animation : rotation 2607ms linear infinite;
}
.heart:nth-child(26) {
transform: translateX(-119px) translateZ(501px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(26) .movable {
-webkit-animation: drop 5000ms 1178ms linear infinite;
animation : drop 5000ms 1178ms linear infinite;
}
.heart:nth-child(26) .ring {
-webkit-animation: wave 5000ms 5078ms ease-out infinite;
animation : wave 5000ms 5078ms ease-out infinite;
}
.heart:nth-child(26) .inner {
-webkit-animation: rotation 2796ms linear infinite;
animation : rotation 2796ms linear infinite;
}
.heart:nth-child(27) {
transform: translateX(4px) translateZ(-268px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(27) .movable {
-webkit-animation: drop 5000ms -1114ms linear infinite;
animation : drop 5000ms -1114ms linear infinite;
}
.heart:nth-child(27) .ring {
-webkit-animation: wave 5000ms 2786ms ease-out infinite;
animation : wave 5000ms 2786ms ease-out infinite;
}
.heart:nth-child(27) .inner {
-webkit-animation: rotation 3196ms linear infinite;
animation : rotation 3196ms linear infinite;
}
.heart:nth-child(28) {
transform: translateX(48px) translateZ(-611px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(28) .movable {
-webkit-animation: drop 5000ms -2925ms linear infinite;
animation : drop 5000ms -2925ms linear infinite;
}
.heart:nth-child(28) .ring {
-webkit-animation: wave 5000ms 975ms ease-out infinite;
animation : wave 5000ms 975ms ease-out infinite;
}
.heart:nth-child(28) .inner {
-webkit-animation: rotation 2491ms linear infinite;
animation : rotation 2491ms linear infinite;
}
.heart:nth-child(29) {
transform: translateX(-463px) translateZ(373px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(29) .movable {
-webkit-animation: drop 5000ms 305ms linear infinite;
animation : drop 5000ms 305ms linear infinite;
}
.heart:nth-child(29) .ring {
-webkit-animation: wave 5000ms 4205ms ease-out infinite;
animation : wave 5000ms 4205ms ease-out infinite;
}
.heart:nth-child(29) .inner {
-webkit-animation: rotation 2700ms linear infinite;
animation : rotation 2700ms linear infinite;
}
.heart:nth-child(30) {
transform: translateX(-404px) translateZ(568px) scale3d(0.5, 0.5, 0.5);
}
.heart:nth-child(30) .movable {
-webkit-animation: drop 5000ms -1461ms linear infinite;
animation : drop 5000ms -1461ms linear infinite;
}
.heart:nth-child(30) .ring {
-webkit-animation: wave 5000ms 2439ms ease-out infinite;
animation : wave 5000ms 2439ms ease-out infinite;
}
.heart:nth-child(30) .inner {
-webkit-animation: rotation 3300ms linear infinite;
animation : rotation 3300ms linear infinite;
}
@-webkit-keyframes blur {
0% {
filter: blur(20px) grayscale(150%);
}
100% {
filter: blur(10px) grayscale(50%);
}
}
@keyframes blur {
0% {
filter: blur(20px) grayscale(150%);
}
100% {
filter: blur(10px) grayscale(50%);
}
}
@-webkit-keyframes rotation {
0% {
transform: rotateY(0deg);
}
100% {
transform: rotateY(360deg);
}
}
@keyframes rotation {
0% {
transform: rotateY(0deg);
}
100% {
transform: rotateY(360deg);
}
}
@-webkit-keyframes drop {
0% {
transform: translateY(-1000px);
opacity : 0;
}
80% {
transform: translateY(0);
opacity : 3;
}
100% {
transform: translateY(-40px);
opacity : 0;
}
}
@keyframes drop {
0% {
transform: translateY(-1000px);
opacity : 0;
}
80% {
transform: translateY(0);
opacity : 3;
}
100% {
transform: translateY(-40px);
opacity : 0;
}
}
@-webkit-keyframes wave {
0% {
transform: translate(-50%, -50%) rotateX(90deg) scale(0) translateZ(-37px);
opacity : 2;
}
100% {
transform: translate(-50%, -50%) rotateX(90deg) scale(2) translateZ(-37px);
opacity : 0;
}
}
@keyframes wave {
0% {
transform: translate(-50%, -50%) rotateX(90deg) scale(0) translateZ(-37px);
opacity : 2;
}
100% {
transform: translate(-50%, -50%) rotateX(90deg) scale(2) translateZ(-37px);
opacity : 0;
}
}
@-webkit-keyframes wing {
0% {
transform: rotateY(70deg);
}
100% {
transform: rotateY(0deg);
}
}
@keyframes wing {
0% {
transform: rotateY(70deg);
}
100% {
transform: rotateY(0deg);
}
}

View File

@ -0,0 +1,42 @@
@import url('/fonts/veganstyle.ttf');
a#wanda {
margin : auto;
font-size : 5em;
font-family: 'Vegan Style Personal Use', 'Commissioner', sans-serif;
transition : 0.1s ease-in;
color : #b35050;
}
a#wanda:hover {
padding-bottom: 30px;
color : #c56565;
}
a#wanda:active {
color: #913f3f;
}
a#wanda::before {
z-index : -1000;
transform : rotateX(-66deg);
content : 'Wanda Switch';
position : absolute;
margin : auto;
padding-left: 0.2em;
padding-top : 0.45em;
transition : 0.1s ease-in;
color : #00000030;
}
a#wanda:hover::before {
padding-left : 0.3em;
padding-top : 0.45em;
padding-bottom: 30px;
}
@media (max-width: 600px) {
a#wanda {
font-size: 2em;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 977 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

View File

@ -0,0 +1 @@
<svg height="32" width="32" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path fill="none" d="M0 0h32v32H0z"/><path d="M30 17.349V12h-2v-2h2V2H2v8h2v2H2v8h2v2H2v8h15.349A8.97 8.97 0 0 0 23 32a9.002 9.002 0 0 0 9-9 8.968 8.968 0 0 0-2-5.651zM14.059 22H6v-2h8.522a8.932 8.932 0 0 0-.463 2zM26 12H6v-2h20v2zM4 6h4v2H4V6zm0 10h4v2H4v-2zm4 12H4v-2h4v2zm15 1.883A6.898 6.898 0 0 1 16.115 23 6.898 6.898 0 0 1 23 16.115 6.898 6.898 0 0 1 29.883 23 6.898 6.898 0 0 1 23 29.883z"/><path d="m19 25 2 2 2-2 2 2 2-2-2-2 2-2-2-2-2 2-2-2-2 2 2 2z"/></svg>

After

Width:  |  Height:  |  Size: 552 B

View File

@ -0,0 +1 @@
<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M0 6c0-1.1.9-2 2-2h16a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V6zm2 0v2h2V6H2zm1 3v2h2V9H3zm-1 3v2h2v-2H2zm3 0v2h10v-2H5zm11 0v2h2v-2h-2zM6 9v2h2V9H6zm3 0v2h2V9H9zm3 0v2h2V9h-2zm3 0v2h2V9h-2zM5 6v2h2V6H5zm3 0v2h2V6H8zm3 0v2h2V6h-2zm3 0v2h4V6h-4z"/></svg>

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -0,0 +1 @@
<svg viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg"><path fill="none" d="M0 0h256v256H0z"/><path d="M224 177.3V78.7a8.1 8.1 0 0 0-4.1-7l-88-49.5a7.8 7.8 0 0 0-7.8 0l-88 49.5a8.1 8.1 0 0 0-4.1 7v98.6a8.1 8.1 0 0 0 4.1 7l88 49.5a7.8 7.8 0 0 0 7.8 0l88-49.5a8.1 8.1 0 0 0 4.1-7Z" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" d="m222.9 74.6-94 53.4-95.8-53.4M128.9 128l-.9 106.8"/></svg>

After

Width:  |  Height:  |  Size: 537 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m11.136 12.117-.596 2.415c.736.185 3.004.921 3.34-.441.35-1.421-2.009-1.789-2.744-1.974Zm.813-3.297-.54 2.191c.612.154 2.5.784 2.806-.455.318-1.293-1.654-1.581-2.266-1.736ZM12 2a10 10 0 1 0 10 10A10 10 0 0 0 12 2Zm4.358 8.575a1.743 1.743 0 0 1-1.385 1.611 1.933 1.933 0 0 1 .997 2.661c-.586 1.692-1.977 1.835-3.827 1.481l-.449 1.82-1.085-.274.443-1.795c-.28-.07-.568-.145-.864-.227l-.445 1.804-1.084-.273.45-1.824c-.254-.065-.511-.135-.774-.201l-1.412-.356.539-1.256s.8.215.788.199a.394.394 0 0 0 .498-.26l1.217-4.939a.583.583 0 0 0-.505-.638c.016-.011-.789-.198-.789-.198l.29-1.172 1.495.378-.001.006c.225.056.457.11.693.164l.444-1.802 1.085.274-.436 1.766c.291.068.584.135.87.207l.432-1.755 1.085.274-.445 1.802c1.37.477 2.372 1.193 2.175 2.523Z"/></svg>

After

Width:  |  Height:  |  Size: 825 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace mirzaev\site\wanda;
use mirzaev\minimal\core;
use mirzaev\minimal\router;
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
define('VIEWS', realpath('..' . DIRECTORY_SEPARATOR . 'views'));
define('STORAGE', realpath('..' . DIRECTORY_SEPARATOR . 'storage'));
define('INDEX', __DIR__);
// Автозагрузка
require __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
// Инициализация маршрутазитора
$router = new router;
// Запись маршрутов
$router->write('/', 'index', 'index');
$router->write('/system/hotline', 'hotline', 'index');
$router->write('/system/graph', 'graph', 'index');
$router->write('/account/initialization', 'account', 'initialization', 'PUT');
$router->write('/account/vk/connect', 'account', 'connect');
$router->write('/account/panel', 'account', 'panel');
// Инициализация ядра
$core = new core(namespace: __NAMESPACE__, router: $router);
// Обработка запроса
echo $core->start();

View File

@ -0,0 +1,26 @@
"use strict";
class account {
static async initialization() {
// Запрос
return fetch('https://auth.mirzaev.sexy/account/initialization', {
method: 'GET'
});
}
static authentication() {
// Инициализация аккаунта
alert(1);
this.initialization()
.then(
(response) => {
alert(2);
}
);
return true;
}
static deauthentication() {
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,668 @@
'use strict';
/**
* Бегущая строка
*
* @description
* Простой, но мощный класс для создания бегущих строк. Поддерживает
* перемещение мышью и прокрутку колесом, полностью настраивается очень гибок
* для настроек в CSS и подразумевается, что отлично индексируется поисковыми роботами.
* Имеет свой препроцессор, благодаря которому можно создавать бегущие строки
* без программирования - с помощью HTML-аттрибутов, а так же возможность
* изменять параметры (data-hotline-* аттрибуты) на лету. Есть возможность вызывать
* события при выбранных действиях для того, чтобы пользователь имел возможность
* дорабатывать функционал без изучения и изменения моего кода
*
* @example
* сonst hotline = new hotline();
* hotline.step = '-5';
* hotline.start();
*
* @todo
* 1. Бесконечный режим - элементы не удаляются если видны на экране (будут дубликаты)
*
* @copyright WTFPL
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class hotline {
// Идентификатор
#id = 0;
// Оболочка (instanceof HTMLElement)
#shell = document.getElementById("hotline");
// Инстанция горячей строки
#instance = null;
// Перемещение
#transfer = true;
// Движение
#move = true;
// Наблюдатель
#observer = null;
// Наблюдатель
#block = new Set(["events"]);
// Настраиваемые параметры
transfer = null;
move = null;
delay = 10;
step = 1;
hover = true;
movable = true;
sticky = false;
wheel = false;
delta = null;
vertical = false;
observe = false;
events = new Map([
["start", false],
["stop", false],
["move", false],
["move.block", false],
["move.unblock", false],
["offset", false],
["transfer.start", true],
["transfer.end", true],
["onmousemove", false]
]);
constructor(id, shell) {
// Запись идентификатора
if (typeof id === "string" || typeof id === "number") this.#id = id;
// Запись оболочки
if (shell instanceof HTMLElement) this.#shell = shell;
}
start() {
if (this.#instance === null) {
// Нет запущенной инстанции бегущей строки
// Инициализация ссылки на ядро
const _this = this;
// Запуск движения
this.#instance = setInterval(function () {
if (_this.#shell.childElementCount > 1) {
// Найдено содержимое бегущей строки (2 и более)
// Инициализация буфера для временных данных
let buffer;
// Инициализация данных первого элемента в строке
const first = {
element: (buffer = _this.#shell.firstElementChild),
coords: buffer.getBoundingClientRect()
};
if (_this.vertical) {
// Вертикальная бегущая строка
// Инициализация сдвига у первого элемента (движение)
first.offset = isNaN(
(buffer = parseFloat(first.element.style.marginTop))
)
? 0
: buffer;
// Инициализация отступа до второго элемента у первого элемента (разделение)
first.separator = isNaN(
(buffer = parseFloat(
getComputedStyle(first.element).marginBottom
))
)
? 0
: buffer;
// Инициализация крайнего с конца ребра первого элемента в строке
first.end = first.coords.y + first.coords.height + first.separator;
} else {
// Горизонтальная бегущая строка
// Инициализация отступа у первого элемента (движение)
first.offset = isNaN(
(buffer = parseFloat(first.element.style.marginLeft))
)
? 0
: buffer;
// Инициализация отступа до второго элемента у первого элемента (разделение)
first.separator = isNaN(
(buffer = parseFloat(getComputedStyle(first.element).marginRight))
)
? 0
: buffer;
// Инициализация крайнего с конца ребра первого элемента в строке
first.end = first.coords.x + first.coords.width + first.separator;
}
if (
(_this.vertical &&
Math.round(first.end) < _this.#shell.offsetTop) ||
(!_this.vertical && Math.round(first.end) < _this.#shell.offsetLeft)
) {
// Элемент (вместе с отступом до второго элемента) вышел из области видимости (строки)
if (
(_this.transfer === null && _this.#transfer) ||
_this.transfer === true
) {
// Перенос разрешен
if (_this.vertical) {
// Вертикальная бегущая строка
// Удаление отступов (движения)
first.element.style.marginTop = null;
} else {
// Горизонтальная бегущая строка
// Удаление отступов (движения)
first.element.style.marginLeft = null;
}
// Копирование первого элемента в конец строки
_this.#shell.appendChild(first.element);
if (_this.events.get("transfer.end")) {
// Запрошен вызов события: "перемещение в конец"
// Вызов события: "перемещение в конец"
document.dispatchEvent(
new CustomEvent(`hotline.${_this.#id}.transfer.end`, {
detail: {
element: first.element,
offset: -(
(_this.vertical
? first.coords.height
: first.coords.width) + first.separator
)
}
})
);
}
}
} else if (
(_this.vertical &&
Math.round(first.coords.y) > _this.#shell.offsetTop) ||
(!_this.vertical &&
Math.round(first.coords.x) > _this.#shell.offsetLeft)
) {
// Передняя (движущая) граница первого элемента вышла из области видимости
if (
(_this.transfer === null && _this.#transfer) ||
_this.transfer === true
) {
// Перенос разрешен
// Инициализация отступа у последнего элемента (разделение)
const separator =
(buffer = isNaN(
(buffer = parseFloat(
getComputedStyle(_this.#shell.lastElementChild)[
_this.vertical ? "marginBottom" : "marginRight"
]
))
)
? 0
: buffer) === 0
? first.separator
: buffer;
// Инициализация координат первого элемента в строке
const coords = _this.#shell.lastElementChild.getBoundingClientRect();
if (_this.vertical) {
// Вертикальная бегущая строка
// Удаление отступов (движения)
_this.#shell.lastElementChild.style.marginTop =
-coords.height - separator + "px";
} else {
// Горизонтальная бегущая строка
// Удаление отступов (движения)
_this.#shell.lastElementChild.style.marginLeft =
-coords.width - separator + "px";
}
// Копирование последнего элемента в начало строки
_this.#shell.insertBefore(
_this.#shell.lastElementChild,
first.element
);
// Удаление отступов у второго элемента в строке (движения)
_this.#shell.children[1].style[
_this.vertical ? "marginTop" : "marginLeft"
] = null;
if (_this.events.get("transfer.start")) {
// Запрошен вызов события: "перемещение в начало"
// Вызов события: "перемещение в начало"
document.dispatchEvent(
new CustomEvent(`hotline.${_this.#id}.transfer.start`, {
detail: {
element: _this.#shell.lastElementChild,
offset:
(_this.vertical ? coords.height : coords.width) +
separator
}
})
);
}
}
} else {
// Элемент в области видимости
if ((_this.move === null && _this.#move) || _this.move === true) {
// Движение разрешено
// Запись новых координат сдвига
const offset = first.offset + _this.step;
// Запись сдвига (движение)
_this.offset(offset);
if (_this.events.get("move")) {
// Запрошен вызов события: "движение"
// Вызов события: "движение"
document.dispatchEvent(
new CustomEvent(`hotline.${_this.#id}.move`, {
detail: {
from: first.offset,
to: offset
}
})
);
}
}
}
}
}, _this.delay);
if (this.hover) {
// Запрошена возможность останавливать бегущую строку
// Инициализация сдвига
let offset = 0;
// Инициализация слушателя события при перемещении элемента в бегущей строке
const listener = function (e) {
// Увеличение сдвига
offset += e.detail.offset ?? 0;
};
// Инициализация обработчика наведения курсора (остановка движения)
this.#shell.onmouseover = function (e) {
// Курсор наведён на бегущую строку
// Блокировка движения
_this.#move = false;
if (_this.events.get("move.block")) {
// Запрошен вызов события: "блокировка движения"
// Вызов события: "блокировка движения"
document.dispatchEvent(
new CustomEvent(`hotline.${_this.#id}.move.block`)
);
}
if (_this.movable) {
// Запрошена возможность двигать бегущую строку
_this.#shell.onmousedown = function (onmousedown) {
// Курсор активирован
// Инициализация слушателей события перемещения элемента в бегущей строке
document.addEventListener(
`hotline.${_this.#id}.transfer.start`,
listener
);
document.addEventListener(
`hotline.${_this.#id}.transfer.end`,
listener
);
// Инициализация буфера для временных данных
let buffer;
// Инициализация данных первого элемента в строке
const first = {
offset: isNaN(
(buffer = parseFloat(
_this.vertical
? _this.#shell.firstElementChild.style.marginTop
: _this.#shell.firstElementChild.style.marginLeft
))
)
? 0
: buffer
};
document.onmousemove = function (onmousemove) {
// Курсор движется
if (_this.vertical) {
// Вертикальная бегущая строка
// Инициализация буфера местоположения
const from = _this.#shell.firstElementChild.style.marginTop;
const to = onmousemove.pageY - (onmousedown.pageY + offset - first.offset);
// Движение
_this.#shell.firstElementChild.style.marginTop = to +
"px";
if (_this.events.get("onmousemove")) {
// Запрошен вызов события: "перемещение мышью"
// Вызов события: "перемещение мышью"
document.dispatchEvent(
new CustomEvent(`hotline.${_this.#id}.onmousemove`, {
detail: { from, to }
})
);
}
} else {
// Горизонтальная бегущая строка
// Инициализация буфера местоположения
const from = _this.#shell.firstElementChild.style.marginLeft;
const to = onmousemove.pageX - (onmousedown.pageX + offset - first.offset);
// Движение
_this.#shell.firstElementChild.style.marginLeft = to + "px";
if (_this.events.get("onmousemove")) {
// Запрошен вызов события: "перемещение мышью"
// Вызов события: "перемещение мышью"
document.dispatchEvent(
new CustomEvent(`hotline.${_this.#id}.onmousemove`, {
detail: { from, to }
})
);
}
}
// Запись курсора
_this.#shell.style.cursor = "grabbing";
};
};
// Перещапись событий браузера (чтобы не дёргалось)
_this.#shell.ondragstart = null;
_this.#shell.onmouseup = function () {
// Курсор деактивирован
// Остановка обработки движения
document.onmousemove = null;
// Сброс сдвига
offset = 0;
document.removeEventListener(
`hotline.${_this.#id}.transfer.start`,
listener
);
document.removeEventListener(
`hotline.${_this.#id}.transfer.end`,
listener
);
// Восстановление курсора
_this.#shell.style.cursor = null;
};
}
};
// Инициализация обработчика отведения курсора (остановка движения)
this.#shell.onmouseleave = function (onmouseleave) {
// Курсор отведён от бегущей строки
if (!_this.sticky) {
// Отключено прилипание
// Остановка обработки движения
document.onmousemove = null;
document.removeEventListener(
`hotline.${_this.#id}.transfer.start`,
listener
);
document.removeEventListener(
`hotline.${_this.#id}.transfer.end`,
listener
);
// Восстановление курсора
_this.#shell.style.cursor = null;
}
// Сброс сдвига
offset = 0;
// Разблокировка движения
_this.#move = true;
if (_this.events.get("move.unblock")) {
// Запрошен вызов события: "разблокировка движения"
// Вызов события: "разблокировка движения"
document.dispatchEvent(
new CustomEvent(`hotline.${_this.#id}.move.unblock`)
);
}
};
}
if (this.wheel) {
// Запрошена возможность прокручивать колесом мыши
// Инициализация обработчика наведения курсора (остановка движения)
this.#shell.onwheel = function (e) {
// Курсор наведён на бегущую
// Инициализация буфера для временных данных
let buffer;
// Перемещение
_this.offset(
(isNaN(
(buffer = parseFloat(
_this.#shell.firstElementChild.style[
_this.vertical ? "marginTop" : "marginLeft"
]
))
)
? 0
: buffer) +
(_this.delta === null
? e.wheelDelta
: e.wheelDelta > 0
? _this.delta
: -_this.delta)
);
};
}
}
if (this.observe) {
// Запрошено наблюдение за изменениями аттрибутов элемента бегущей строки
if (this.#observer === null) {
// Отсутствует наблюдатель
// Инициализация ссылки на ядро
const _this = this;
// Инициализация наблюдателя
this.#observer = new MutationObserver(function (mutations) {
for (const mutation of mutations) {
if (mutation.type === "attributes") {
// Запись параметра в инстанцию бегущей строки
_this.write(mutation.attributeName);
}
}
// Перезапуск бегущей строки
_this.restart();
});
// Активация наблюдения
this.#observer.observe(this.#shell, {
attributes: true
});
}
} else if (this.#observer instanceof MutationObserver) {
// Запрошено отключение наблюдения
// Деактивация наблюдения
this.#observer.disconnect();
// Удаление наблюдателя
this.#observer = null;
}
if (this.events.get("start")) {
// Запрошен вызов события: "запуск"
// Вызов события: "запуск"
document.dispatchEvent(new CustomEvent(`hotline.${this.#id}.start`));
}
}
stop() {
// Остановка бегущей строки
clearInterval(this.#instance);
// Удаление инстанции интервала
this.#instance = null;
if (this.events.get("stop")) {
// Запрошен вызов события: "остановка"
// Вызов события: "остановка"
document.dispatchEvent(new CustomEvent(`hotline.${this.#id}.stop`));
}
}
restart() {
// Остановка бегущей строки
this.stop();
// Запуск бегущей строки
this.start();
}
write(attribute) {
// Инициализация названия параметра
const parameter = (/^data-hotline-(\w+)$/.exec(attribute) ?? [, null])[1];
if (typeof parameter === "string") {
// Параметр найден
// Проверка на разрешение изменения
if (this.#block.has(parameter)) return;
// Инициализация значения параметра
const value = this.#shell.getAttribute(attribute);
// Инициализация буфера для временных данных
let buffer;
// Запись параметра
this[parameter] = isNaN((buffer = parseFloat(value)))
? value === "true"
? true
: value === "false"
? false
: value
: buffer;
}
}
offset(value) {
// Запись отступа
this.#shell.firstElementChild.style[
this.vertical ? "marginTop" : "marginLeft"
] = value + "px";
if (this.events.get("offset")) {
// Запрошен вызов события: "сдвиг"
// Вызов события: "сдвиг"
document.dispatchEvent(
new CustomEvent(`hotline.${this.#id}.offset`, {
detail: {
to: value
}
})
);
}
}
static preprocessing(event = false) {
// Инициализация счётчиков инстанций горячей строки
const success = new Set();
let error = 0;
for (const element of document.querySelectorAll('*[data-hotline="true"]')) {
// Перебор бегущих строк
if (typeof element.id === "string") {
// Найден идентификатор
// Инициализация инстанции бегущей строки
const hotline = new this(element.id, element);
for (const attribute of element.getAttributeNames()) {
// Перебор аттрибутов
// Запись параметра в инстанцию бегущей строки
hotline.write(attribute);
}
// Запуск бегущей строки
hotline.start();
// Запись инстанции бегущей строки в элемент
element.hotline = hotline;
// Запись в счётчик успешных инициализаций
success.add(hotline);
} else ++error;
}
if (event) {
// Запрошен вызов события: "предварительная подготовка"
// Вызов события: "предварительная подготовка"
document.dispatchEvent(
new CustomEvent(`hotline.preprocessed`, {
detail: {
success,
error
}
})
);
}
}
}
document.dispatchEvent(
new CustomEvent("hotline.loaded", {
detail: { hotline }
})
);

View File

@ -0,0 +1,2 @@
/*! js-cookie v3.0.1 | MIT */
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self,function(){var n=e.Cookies,o=e.Cookies=t();o.noConflict=function(){return e.Cookies=n,o}}())}(this,(function(){"use strict";function e(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)e[o]=n[o]}return e}return function t(n,o){function r(t,r,i){if("undefined"!=typeof document){"number"==typeof(i=e({},o,i)).expires&&(i.expires=new Date(Date.now()+864e5*i.expires)),i.expires&&(i.expires=i.expires.toUTCString()),t=encodeURIComponent(t).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape);var c="";for(var u in i)i[u]&&(c+="; "+u,!0!==i[u]&&(c+="="+i[u].split(";")[0]));return document.cookie=t+"="+n.write(r,t)+c}}return Object.create({set:r,get:function(e){if("undefined"!=typeof document&&(!arguments.length||e)){for(var t=document.cookie?document.cookie.split("; "):[],o={},r=0;r<t.length;r++){var i=t[r].split("="),c=i.slice(1).join("=");try{var u=decodeURIComponent(i[0]);if(o[u]=n.read(c,u),e===u)break}catch(e){}}return e?o[e]:o}},remove:function(t,n){r(t,"",e({},n,{expires:-1}))},withAttributes:function(n){return t(this.converter,e({},this.attributes,n))},withConverter:function(n){return t(e({},this.converter,n),this.attributes)}},{attributes:{value:Object.freeze(o)},converter:{value:Object.freeze(n)}})}({read:function(e){return'"'===e[0]&&(e=e.slice(1,-1)),e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)},write:function(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}},{path:"/"})}));

View File

@ -0,0 +1,127 @@
"use strict";
class troller {
static what = {
enable() {
document.body.onmouseleave = function () {
// if (Math.random() > 0.90) {
// 10%
troller.what.start();
// }
};
document.body.onmouseenter = function () {
troller.what.end();
};
},
disable() {
document.body.onmouseleave = document.body.onmouseenter = undefined;
},
start() {
// Отображение изображения
document.getElementById('what_image').classList.add('active');
// Инициализация элемента со звуком
const what_sound = document.getElementById('what_sound');
// Воспроизведение звука
what_sound.currentTime = 0;
what_sound.play();
},
end() {
// Сокрытие изображения
document.getElementById('what_image').classList.remove('active');
// Остановка звука
document.getElementById('what_sound').pause();
},
single(event = 'onmouseleave') {
if (typeof event === 'string') {
// Получены обязательные входные параметры
// Отображение изображения
document.getElementById('what_image').classList.add('active');
// Инициализация элемента со звуком
const what_sound = document.getElementById('what_sound');
// Воспроизведение звука
what_sound.currentTime = 0;
what_sound.play();
document.body[event] = function () {
troller.what.end();
document.body[event] = undefined;
};
}
}
}
static vk() {
setInterval(function () {
const sound = document.getElementById('sound_vk');
if (Math.random() > 0.95) {
// 5%
// Воспроизведение звука
sound.currentTime = 0;
sound.play();
}
}, 85000);
}
static whatsapp() {
setInterval(function () {
const sound = document.getElementById('sound_whatsup');
if (Math.random() > 0.97) {
// 3%
// Воспроизведение звука
sound.currentTime = 0;
sound.play();
}
}, 125000);
}
static iphone() {
setInterval(function () {
const sound = document.getElementById('sound_iphone');
if (Math.random() > 0.98) {
// 2%
// Воспроизведение звука
sound.currentTime = 0;
sound.play();
}
}, 265000);
}
}
if (Math.random() > 0.90) {
// 10%
troller.what.enable();
}
if (Math.random() > 0.90) {
// 10%
troller.vk();
}
if (Math.random() > 0.90) {
// 10%
troller.whatsapp();
}
if (Math.random() > 0.90) {
// 10%
troller.iphone();
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,41 @@
{
"name": "App",
"icons": [
{
"src": "\/android-icon-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "0.75"
},
{
"src": "\/android-icon-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1.0"
},
{
"src": "\/android-icon-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "\/android-icon-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
},
{
"src": "\/android-icon-144x144.png",
"sizes": "144x144",
"type": "image\/png",
"density": "3.0"
},
{
"src": "\/android-icon-192x192.png",
"sizes": "192x192",
"type": "image\/png",
"density": "4.0"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1 @@
arangodb.php

View File

@ -0,0 +1,8 @@
<?php
return [
'endpoint' => 'unix:///var/run/arangodb3/arango.sock',
'database' => '',
'name' => '',
'password' => ''
];

View File

@ -0,0 +1,33 @@
<!doctype html>
<html lang="ru">
<head>
{% use 'head.html' with title as head_title, meta as head_meta, css as head_css %}
{% block title %}
{{ block('head_title') }}
{% endblock %}
{% block meta %}
{{ block('head_meta') }}
{% endblock %}
{% block css %}
{{ block('head_css') }}
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
{% block js %}
{% include 'js.html' %}
{% endblock %}
{% block js_init %}
{% endblock %}
</body>
</html>

View File

@ -0,0 +1,39 @@
{% block title %}
<title>{% if head.title != empty %}{{head.title}}{% else %}Сайт про Ванду{% endif %}</title>
{% endblock %}
{% block meta %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
<meta property="og:locale" content="ru_RU"/>
<meta property="og:type" content="article"/>
<meta property="og:title" content="Сайт про мою жену Ванда Свитч"/>
<meta property="og:description" content="Всем привет я создал сайт про мою будущую жену Ванда Свитч"/>
<meta property="og:image" content="https://wanda.mirzaev.sexy/images/wanda.jpg"/>
<meta property="og:url" content="https://wanda.mirzaev.sexy"/>
<meta property="og:site_name" content="Сайт про мою жену Ванда Свитч"/>
{% for meta in head.metas %}
<meta {% for name, value in meta.attributes %}{{name}}="{{value}}" {% endfor %}>
{% endfor %}
{% endblock %}
{% block css %}
<link type="text/css" rel="stylesheet" href="/css/main.css" />
{% endblock %}

View File

@ -0,0 +1,23 @@
{% extends "core.html" %}
{% use "core.html" with css as core_css, body as core_body, js as core_js, js_init as core_js_init %}
{% use "valentine.html" with css as valentine_css, body as valentine_body %}
{% block css %}
{{ block('core_css') }}
{{ block('valentine_css') }}
<link type="text/css" rel="stylesheet" href="/css/wanda.css" />
{% endblock %}
{% block body %}
<main>
</main>
<a id="wanda" href="https://vk.com/id682269419" class="unselectable">Wanda Switch</a>
{{ block('valentine_body') }}
{% endblock %}
{% block js %}
{% endblock %}
{% block js_init %}
{% endblock %}

View File

@ -0,0 +1,3 @@
{% block js %}
<script type="text/javascript" src="/js/js.cookie.min.js" defer></script>
{% endblock %}

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace mirzaev\site\wanda\views;
use mirzaev\minimal\controller;
use Twig\Loader\FilesystemLoader;
use Twig\Environment as view;
/**
* Менеджер представлений
*
* @package mirzaev\site\wanda\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class manager extends controller
{
public function render(string $file, array $vars = []): ?string
{
// Генерация представления
return (new view(new FilesystemLoader(VIEWS)))->render($file, $vars);
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,520 @@
{% block css %}
<link type="text/css" rel="stylesheet" href="/css/valentine.css" />
{% endblock %}
{% block body %}
<div id="valentine">
<div id="chocolate_rains">
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
<div class="heart">
<div class="ring"></div>
<div class="inner">
<div class="regular">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="reverse">
<div class="movable">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}