modelhub/assets/css/style.css
/* Общие стили */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    line-height: 1.6;
    color: #333;
    background-color: #f8f8f8;
}

.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
}

/* Шапка */
header {
    background: #222;
    color: white;
    padding: 1rem 0;
    text-align: center;
}

header h1 {
    font-size: 2rem;
    margin-bottom: 0.5rem;
}

header p {
    font-size: 1rem;
    opacity: 0.8;
}

/* Главная секция */
.hero {
    background: linear-gradient(135deg, #1e3c72, #2a5298);
    color: white;
    padding: 4rem 0;
    text-align: center;
}

.hero h2 {
    font-size: 2.5rem;
    margin-bottom: 1rem;
}

.hero p {
    font-size: 1.2rem;
    max-width: 600px;
    margin: 0 auto 2rem;
}

.btn {
    display: inline-block;
    background: #fff;
    color: #222;
    padding: 0.75rem 1.5rem;
    text-decoration: none;
    border-radius: 5px;
    font-weight: bold;
    transition: all 0.3s ease;
}

.btn:hover {
    background: #eee;
    transform: translateY(-2px);
}

/* Карусель */
.carousel-section {
    padding: 3rem 0;
    background: white;
}

.carousel-section h3 {
    text-align: center;
    margin-bottom: 2rem;
    font-size: 2rem;
}

.carousel {
    display: flex;
    overflow-x: auto;
    scroll-behavior: smooth;
    gap: 1rem;
    padding: 1rem;
    scrollbar-width: thin;
    scrollbar-color: #ccc #f0f0f0;
}

.carousel::-webkit-scrollbar {
    height: 8px;
}

.carousel::-webkit-scrollbar-thumb {
    background: #ccc;
    border-radius: 10px;
}

.carousel::-webkit-scrollbar-track {
    background: #f0f0f0;
}

.carousel-item {
    min-width: 250px;
    position: relative;
    border-radius: 10px;
    overflow: hidden;
    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}

.carousel-item img {
    width: 100%;
    height: 200px;
    object-fit: cover;
}

.carousel-item .caption {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    background: rgba(0,0,0,0.7);
    color: white;
    padding: 0.5rem;
    text-align: center;
    font-weight: bold;
}

.carousel-btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background: rgba(255,255,255,0.8);
    border: none;
    padding: 0.5rem 1rem;
    cursor: pointer;
    font-size: 1.5rem;
    z-index: 10;
    border-radius: 50%;
    box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}

.carousel-btn.prev {
    left: 10px;
}

.carousel-btn.next {
    right: 10px;
}

/* Как это работает */
.how-it-works {
    padding: 3rem 0;
    background: #f0f0f0;
}

.how-it-works h3 {
    text-align: center;
    margin-bottom: 2rem;
    font-size: 2rem;
}

.how-it-works ol {
    list-style: decimal;
    padding-left: 2rem;
    max-width: 800px;
    margin: 0 auto;
}

.how-it-works li {
    margin-bottom: 1rem;
    font-size: 1.1rem;
}

/* Профиль модели */
.model-profile {
    padding: 3rem 0;
    background: white;
}

.profile-header {
    text-align: center;
    margin-bottom: 2rem;
}

.profile-header img {
    width: 200px;
    height: 200px;
    border-radius: 50%;
    object-fit: cover;
    border: 3px solid #ddd;
    margin-bottom: 1rem;
}

.profile-header h2 {
    font-size: 2rem;
    margin-bottom: 0.5rem;
}

.profile-info {
    max-width: 600px;
    margin: 0 auto;
    background: #f9f9f9;
    padding: 1.5rem;
    border-radius: 10px;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

.cta {
    text-align: center;
    margin-top: 2rem;
}

/* Форма контактов */
.contact-form {
    padding: 3rem 0;
    background: white;
}

.contact-form h2 {
    text-align: center;
    margin-bottom: 2rem;
    font-size: 2rem;
}

.contact-form form {
    max-width: 600px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.contact-form label {
    font-weight: bold;
    margin-top: 1rem;
}

.contact-form input,
.contact-form select,
.contact-form textarea {
    width: 100%;
    padding: 0.75rem;
    border: 1px solid #ddd;
    border-radius: 5px;
    font-size: 1rem;
}

.contact-form textarea {
    resize: vertical;
}

.info-box {
    background: #e8f4fd;
    border-left: 4px solid #2a5298;
    padding: 1rem;
    margin-top: 2rem;
    border-radius: 5px;
}

.success {
    background: #d4edda;
    color: #155724;
    padding: 0.75rem;
    border-radius: 5px;
    margin-bottom: 1rem;
}

.error {
    background: #f8d7da;
    color: #721c24;
    padding: 0.75rem;
    border-radius: 5px;
    margin-bottom: 1rem;
}

/* Таблицы */
table {
    width: 100%;
    border-collapse: collapse;
    margin: 1rem 0 2rem;
}

th, td {
    padding: 0.75rem;
    border: 1px solid #ddd;
    text-align: left;
}

th {
    background: #f0f0f0;
}

/* Подвал */
footer {
    background: #222;
    color: white;
    text-align: center;
    padding: 1.5rem 0;
    margin-top: 3rem;
}

footer a {
    color: #007bff;
    text-decoration: none;
}

footer a:hover {
    text-decoration: underline;
}

/* Адаптивность */
@media (max-width: 768px) {
    .container {
        padding: 10px;
    }

    header h1 {
        font-size: 1.5rem;
    }

    .hero h2 {
        font-size: 2rem;
    }

    .hero p {
        font-size: 1rem;
    }

    .carousel-item {
        min-width: 200px;
    }

    .carousel-item img {
        height: 150px;
    }

    .how-it-works ol {
        padding-left: 1rem;
    }

    .profile-header img {
        width: 150px;
        height: 150px;
    }

    .contact-form form {
        gap: 0.5rem;
    }
}

@media (max-width: 480px) {
    .hero h2 {
        font-size: 1.5rem;
    }

    .carousel-btn {
        display: none;
    }

    .carousel {
        flex-wrap: wrap;
        justify-content: center;
    }

    .carousel-item {
        min-width: 100%;
        max-width: 300px;
    }

    .contact-form form {
        padding: 0.5rem;
    }
}

/* Темная тема (кнопка "Ночь") */
body.dark-mode {
    background-color: #121212;
    color: #f0f0f0;
}

body.dark-mode header {
    background: #000;
}

body.dark-mode .hero {
    background: linear-gradient(135deg, #0a192f, #112b4e);
}

body.dark-mode .contact-form {
    background: #1e1e1e;
}

body.dark-mode .profile-info {
    background: #2d2d2d;
}

body.dark-mode .info-box {
    background: #1a2b3c;
}

body.dark-mode footer {
    background: #000;
}

body.dark-mode a {
    color: #6bb9ff;
}

/* Кнопка "Ночь" */
.night-mode-btn {
    position: fixed;
    bottom: 20px;
    right: 20px;
    background: #333;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 5px;
    cursor: pointer;
    z-index: 1000;
    font-size: 0.9rem;
}

.night-mode-btn:hover {
    background: #555;
}

/* Принудительное включение темы на основе устройства */
@media (prefers-color-scheme: dark) {
    body {
        background-color: #121212;
        color: #f0f0f0;
    }

    header {
        background: #000;
    }

    .hero {
        background: linear-gradient(135deg, #0a192f, #112b4e);
    }

    .contact-form {
        background: #1e1e1e;
    }

    .profile-info {
        background: #2d2d2d;
    }

    .info-box {
        background: #1a2b3c;
    }

    footer {
        background: #000;
    }

    a {
        color: #6bb9ff;
    }
}

modelhub/assets/js/main.js
document.addEventListener('DOMContentLoaded', function() {
    // Карусель
    const carousel = document.querySelector('.carousel');
    const prevBtn = document.querySelector('.carousel-btn.prev');
    const nextBtn = document.querySelector('.carousel-btn.next');

    if (carousel && prevBtn && nextBtn) {
        prevBtn.addEventListener('click', () => {
            carousel.scrollBy({ left: -300, behavior: 'smooth' });
        });

        nextBtn.addEventListener('click', () => {
            carousel.scrollBy({ left: 300, behavior: 'smooth' });
        });
    }

    // Кнопка "Ночь"
    const nightModeBtn = document.createElement('button');
    nightModeBtn.textContent = 'Ночь';
    nightModeBtn.className = 'night-mode-btn';
    document.body.appendChild(nightModeBtn);

    nightModeBtn.addEventListener('click', () => {
        document.body.classList.toggle('dark-mode');
        localStorage.setItem('darkMode', document.body.classList.contains('dark-mode'));
    });

    // Автоматическое включение темы на основе устройства
    if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
        document.body.classList.add('dark-mode');
    }

    // Загрузка сохранённого состояния
    if (localStorage.getItem('darkMode') === 'true') {
        document.body.classList.add('dark-mode');
    }
});

modelhub/assets/images/placeholder.jpg
[Бинарные данные изображения не могут быть отображены в текстовом формате. Пожалуйста, загрузите файл placeholder.jpg в папку assets/images/ самостоятельно.]

modelhub/includes/config.php
<?php
// Настройки сайта
define('SITE_NAME', 'ModelHub — Безопасная биржа моделей');
define('SITE_URL', 'https://вашсайт.рф'); // замените позже
define('CONTACT_PHONE', '+79677018686'); // ваш номер

// Настройки БД
define('DB_HOST', 'localhost');
define('DB_USER', 'your_db_user');
define('DB_PASS', 'your_db_password');
define('DB_NAME', 'modelhub');

// SEO метатеги
define('META_TITLE', 'ModelHub — Безопасная биржа моделей | Найдите модель с проверкой');
define('META_DESCRIPTION', 'Безопасная платформа для сотрудничества с моделями. Все заявки проходят строгую проверку. Человечность и безопасность — превыше всего.');
define('META_KEYWORDS', 'биржа моделей, безопасная модель, найти модель, фотосъёмка, модельный бизнес, защита моделей');

// Кодировка
header('Content-Type: text/html; charset=utf-8');
?>

modelhub/includes/db.php
<?php
require_once 'config.php';

class Database {
    private static $instance = null;
    private $pdo;

    private function __construct() {
        try {
            $this->pdo = new PDO(
                "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4",
                DB_USER,
                DB_PASS,
                [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
                ]
            );
        } catch (PDOException $e) {
            die("Ошибка подключения к БД: " . $e->getMessage());
        }
    }

    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function getConnection() {
        return $this->pdo;
    }
}
?>

modelhub/includes/functions.php
<?php
// Пустой файл для будущих вспомогательных функций
// Например, для фильтрации данных, логирования, отправки почты и т.д.

function sanitize_output($buffer) {
    $search = array(
        '/\>[^\S ]+/s',     // убираем пробелы после тегов
        '/[^\S ]+\</s',     // убираем пробелы перед тегами
        '/(\s)+/s'          // сжимаем множественные пробелы
    );
    $replace = array('>', '<', '\\1');
    return preg_replace($search, $replace, $buffer);
}

// Пример: хэширование пароля администратора
function hash_admin_password($password) {
    return password_hash($password, PASSWORD_DEFAULT);
}

// Пример: проверка, является ли строка допустимым ID участника (например, 00000001)
function is_valid_participant_id($id) {
    return preg_match('/^[0-9]{8}$/', $id);
}

?>

modelhub/sql/modelhub.sql
-- Создание базы данных
CREATE DATABASE IF NOT EXISTS modelhub CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE modelhub;

-- Таблица пользователей (администраторы, модели, клиенты)
CREATE TABLE IF NOT EXISTS users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    role ENUM('admin', 'model', 'client') DEFAULT 'client',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Таблица моделей (участников проекта)
CREATE TABLE IF NOT EXISTS models (
    id INT AUTO_INCREMENT PRIMARY KEY,
    participant_id VARCHAR(10) UNIQUE NOT NULL, -- например: 00000001
    name VARCHAR(100) NOT NULL,                -- скрыто от публики
    height INT,
    weight INT,
    eyes VARCHAR(20),
    hair VARCHAR(20),
    city VARCHAR(100),
    bio TEXT,
    status ENUM('active', 'inactive', 'pending') DEFAULT 'pending',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Таблица заявок
CREATE TABLE IF NOT EXISTS requests (
    id INT AUTO_INCREMENT PRIMARY KEY,
    client_name VARCHAR(100),
    client_email VARCHAR(255),
    project_type VARCHAR(100),
    budget DECIMAL(10,2),
    city VARCHAR(100),
    message TEXT,
    status ENUM('new', 'reviewed', 'approved', 'rejected') DEFAULT 'new',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Таблица отзывов (по мере роста)
CREATE TABLE IF NOT EXISTS reviews (
    id INT AUTO_INCREMENT PRIMARY KEY,
    model_id INT,
    client_name VARCHAR(100),
    rating TINYINT CHECK(rating BETWEEN 1 AND 5),
    comment TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (model_id) REFERENCES models(id) ON DELETE CASCADE
);

-- Добавление администратора (ваш личный аккаунт)
INSERT INTO users (username, password_hash, role) VALUES 
('admin', '$2y$10$examplehashhere', 'admin');

-- Добавление первого участника (ваша дочь — участник № 00000001)
INSERT INTO models (participant_id, name, height, weight, eyes, hair, city, bio, status) VALUES 
('00000001', 'Иванова Мария Юрьевна', 170, 55, 'карие', 'каштановые', 'Москва', 'Фактурная внешность, глубина взгляда, элегантность.', 'active');

modelhub/.htaccess
RewriteEngine On

# Убираем .php из URL
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]

# Запрет доступа к папке admin без авторизации (пока просто заглушка)
# Для полноценной защиты — используйте сессии и авторизацию
<Files "admin">
    Require all denied
</Files>
