Files
2026-hypn0-site/hypn0/templates/index.html
T

568 lines
41 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "_base.html" %}{% load static %}
{% block CONTENT %}
<div class="grid grid-cols-1 lg:grid-cols-[400px_1fr] gap-8 items-start"
x-data="{
/* Активная вкладка: 'style' (фигуры), 'params' (ползунки), 'color' (палитра) */
activeTab: 'style',
/* Палитра цветов (1-3 цвета: монотон, дуотон, триатон) */
colors: ['#a855ff'],
/* Параметры сетки и трансформаций */
cols: 80, /* Плотность галлюцинации (число колонок сетки, 20-200) */
radius: 8, /* Размер гипно-точки (максимальный радиус элементов, 3-20) */
blink: 6, /* Интенсивность мерцания CSS-анимации (0-10) */
rotation: 0, /* Укачивание (угол поворота элементов, от -15° до +15°) */
scale: 980, /* Масштаб 'Взз-з-з-з…' (980 = 98.0%, диапазон 800-1040) */
angle: 0, /* Перекос (наклон растровой сетки, от -44° до +45°) */
/* Служебные состояния интерфейса */
isLoading: false, /* Идет ли процесс генерации SVG (индикация, блокировка) */
hasChanges: true, /* Флаг наличия правок в форме для активности кнопки */
hasImage: false, /* Флаг загрузки пользовательского файла */
timer: null, /* Ссылка на таймер удержания анимации размышления */
copied: false, /* Флаг успешного копирования в буфер */
/* Метод запуска состояния размышления (8 секунд) */
startThinking() {
this.isLoading = true;
if (this.timer) clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.isLoading = false;
this.hasChanges = false;
}, 8000);
},
copySvg() {
const svg = document.querySelector('#preview svg');
if (!svg) return;
navigator.clipboard.writeText(svg.outerHTML).then(() => {
this.copied = true;
setTimeout(() => this.copied = false, 2000);
});
},
downloadSvg() {
const svg = document.querySelector('#preview svg');
if (!svg) return;
const blob = new Blob([svg.outerHTML], {type: 'image/svg+xml;charset=utf-8'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'hypn0-art.svg';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
}">
<!-- ЛЕВАЯ ПАНЕЛЬ: НАСТРОЙКИ -->
<aside class="space-y-6">
<form hx-post="/generate"
hx-target="#preview"
hx-trigger="submit"
hx-encoding="multipart/form-data"
@submit="startThinking()"
@change="hasChanges = true"
@input="hasChanges = true"
@htmx:before-request="startThinking()"
@htmx:after-request="isLoading = false; hasChanges = false"
class="relative bg-white dark:bg-zinc-900 p-6 rounded-2xl shadow-sm border border-stone-200 dark:border-zinc-800 overflow-hidden">
{% csrf_token %}
<!-- Фоновая спираль размышления при генерации (прижата снизу на всю левую панель) -->
<div x-show="isLoading"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
class="absolute inset-0 z-20 pointer-events-none flex items-end justify-center overflow-hidden rounded-2xl bg-white/70 dark:bg-zinc-900/75 backdrop-blur-[2px]">
<img src="{% static 'img/thinking.svg' %}" alt="thinking"
class="w-120 h-120 -mb-24 opacity-75 animate-spin [animation-duration:10s]">
</div>
<!-- Загрузка файла -->
<div class="mb-8">
<label class="block text-sm font-bold mb-2 uppercase tracking-wider text-stone-500 dark:text-zinc-400">Источник</label>
<div class="relative group">
<input type="file" name="image" accept="image/*"
@change="hasImage = $el.files.length > 0; hasChanges = true"
class="absolute inset-0 w-full h-full opacity-0 cursor-pointer z-10">
<div
class="border-2 border-dashed border-stone-300 dark:border-zinc-700 group-hover:border-emerald-500 rounded-xl p-8 flex flex-col items-center justify-center text-center transition-colors">
<span class="text-stone-400 group-hover:text-emerald-500 flex flex-col items-center gap-3">
<svg class="w-20 h-20 fill-current transition-colors opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M477 174c8.812-13.708 13.948-29.993 13.948-47.466 0-48.55-39.499-88.048-88.05-88.048-32.839 0-61.516 18.084-76.651 44.803-22.773-5.031-46.356-7.586-70.424-7.586-24.003 0-47.624 2.55-70.427 7.582-15.135-26.717-43.813-44.799-76.65-44.799-48.55 0-88.048 39.498-88.048 88.049 0 17.473 5.137 33.759 13.949 47.467C11.987 204.676 0 239.016 0 274.61c0 53.849 27.194 104.194 76.573 141.763C124.677 452.97 188.399 473.125 256 473.125s131.323-20.155 179.427-56.753C484.806 378.803 512 328.457 512 274.609c0-35.59-11.986-69.935-34.822-100.219zM403.076 70.224c31.266 0 56.703 25.436 56.703 56.701s-25.437 56.702-56.703 56.702-56.701-25.436-56.701-56.702 25.436-56.701 56.701-56.701zm-294.152 0c31.266 0 56.703 25.436 56.703 56.701s-25.437 56.702-56.703 56.702-56.701-25.436-56.701-56.702 25.435-56.701 56.701-56.701zM56.629 197.71a87.57 87.57 0 0 0 52.294 17.264c48.55 0 88.05-39.498 88.05-88.049a88.25 88.25 0 0 0-1.02-13.409c19.464-4.03 39.588-6.075 60.047-6.075 20.515 0 40.613 2.041 60.048 6.068-.672 4.376-1.021 8.857-1.021 13.417 0 48.55 39.498 88.049 88.049 88.049 19.568 0 37.66-6.424 52.294-17.263 15.157 21.633 23.712 45.416 25.08 69.911-23.821 20.076-49.402 34.122-79.949 43.943-38.207 12.281-85.474 18.252-144.5 18.252s-106.292-5.971-144.499-18.253c-30.549-9.821-56.132-23.869-79.952-43.945 1.369-24.496 9.921-48.278 25.079-69.91zm199.372 244.067c-107.337 0-197.317-56.31-219.433-131.312 19.882 13.102 41.246 23.196 65.34 30.94 41.355 13.295 91.76 19.758 154.094 19.758s112.738-6.463 154.095-19.758c24.092-7.745 45.456-17.839 65.338-30.939-22.12 75.002-112.099 131.311-219.434 131.311z"/><use href="#B"/><use href="#B" x="294.153"/><path d="M219.852 256.624c-9.79 0-17.756 8.048-17.756 17.986s7.966 17.992 17.756 17.992c9.802 0 17.767-8.055 17.767-17.992s-7.965-17.986-17.767-17.986zm72.163-.14c-9.885 0-17.902 8.115-17.902 18.126s8.017 18.126 17.902 18.126c9.872 0 17.89-8.115 17.89-18.126s-8.018-18.126-17.89-18.126z"/><defs><path id="B" d="M108.931 105.926c-11.45 0-20.738 9.401-20.738 20.998s9.288 20.998 20.738 20.998c11.436 0 20.725-9.401 20.725-20.998s-9.289-20.998-20.725-20.998z"/></defs></svg>
<span>Покорми Гипнoжабу,<br />притащи сюда img или&nbsp;кликни</span>
</span>
</div>
</div>
</div>
<!-- Табы настроек -->
<nav class="flex border-b border-stone-200 dark:border-zinc-800 mb-6 overflow-x-auto no-scrollbar">
<button type="button" @click="activeTab = 'style'"
:class="activeTab === 'style' ? 'border-emerald-500 text-emerald-600' : 'border-transparent text-stone-400'"
class="pb-2 px-4 border-b-2 font-bold text-sm uppercase transition-all whitespace-nowrap">Гюко-элемент
</button>
<button type="button" @click="activeTab = 'params'"
:class="activeTab === 'params' ? 'border-emerald-500 text-emerald-600' : 'border-transparent text-stone-400'"
class="pb-2 px-4 border-b-2 font-bold text-sm uppercase transition-all whitespace-nowrap">Параметры
</button>
<button type="button" @click="activeTab = 'color'"
:class="activeTab === 'color' ? 'border-emerald-500 text-emerald-600' : 'border-transparent text-stone-400'"
class="pb-2 px-4 border-b-2 font-bold text-sm uppercase transition-all whitespace-nowrap">Цвета
</button>
</nav>
<!-- Контент табов -->
<div class="space-y-6 min-h-[460px]">
<!-- Таб: Стиль (Фигуры) -->
<div x-show="activeTab === 'style'" class="grid grid-cols-4 gap-2">
<!-- 1. Круг -->
<label class="cursor-pointer group" title="Круг">
<input type="radio" name="shape" value="circle" class="hidden peer" checked>
<div class="aspect-square flex flex-col items-center justify-center p-2 border-2 border-stone-100 dark:border-zinc-800 rounded-xl text-stone-400 group-hover:text-emerald-500 peer-checked:text-emerald-500 peer-checked:border-emerald-500 peer-checked:bg-emerald-50/10 transition-all hover:border-stone-300 dark:hover:border-zinc-700">
<div class="w-6 h-6 rounded-full bg-current transition-colors"></div>
</div>
</label>
<!-- 2. Кольцо (Бублик) -->
<label class="cursor-pointer group" title="Кольцо">
<input type="radio" name="shape" value="ring" class="hidden peer">
<div class="aspect-square flex flex-col items-center justify-center p-2 border-2 border-stone-100 dark:border-zinc-800 rounded-xl text-stone-400 group-hover:text-emerald-500 peer-checked:text-emerald-500 peer-checked:border-emerald-500 peer-checked:bg-emerald-50/10 transition-all hover:border-stone-300 dark:hover:border-zinc-700">
<div class="w-6 h-6 rounded-full border-[6px] border-current transition-colors"></div>
</div>
</label>
<!-- 3. Треугольник -->
<label class="cursor-pointer group" title="Треугольник">
<input type="radio" name="shape" value="triangle" class="hidden peer">
<div class="aspect-square flex flex-col items-center justify-center p-2 border-2 border-stone-100 dark:border-zinc-800 rounded-xl text-stone-400 group-hover:text-emerald-500 peer-checked:text-emerald-500 peer-checked:border-emerald-500 peer-checked:bg-emerald-50/10 transition-all hover:border-stone-300 dark:hover:border-zinc-700">
<svg class="w-6 h-6 fill-current transition-colors" viewBox="0 0 24 24">
<path d="M12 4L2 20h20L12 4z"/>
</svg>
</div>
</label>
<!-- 4. Квадрат -->
<label class="cursor-pointer group" title="Квадрат">
<input type="radio" name="shape" value="square" class="hidden peer">
<div class="aspect-square flex flex-col items-center justify-center p-2 border-2 border-stone-100 dark:border-zinc-800 rounded-xl text-stone-400 group-hover:text-emerald-500 peer-checked:text-emerald-500 peer-checked:border-emerald-500 peer-checked:bg-emerald-50/10 transition-all hover:border-stone-300 dark:hover:border-zinc-700">
<div class="w-5 h-5 rounded-xs bg-current transition-colors"></div>
</div>
</label>
<!-- 5. Ромб (Бриллиант) -->
<label class="cursor-pointer group" title="Ромб">
<input type="radio" name="shape" value="diamond" class="hidden peer">
<div class="aspect-square flex flex-col items-center justify-center p-2 border-2 border-stone-100 dark:border-zinc-800 rounded-xl text-stone-400 group-hover:text-emerald-500 peer-checked:text-emerald-500 peer-checked:border-emerald-500 peer-checked:bg-emerald-50/10 transition-all hover:border-stone-300 dark:hover:border-zinc-700">
<div class="w-5 h-5 rotate-45 rounded-xs bg-current transition-colors"></div>
</div>
</label>
<!-- 6. Шестиугольник (Гексагон) -->
<label class="cursor-pointer group" title="Гексагон">
<input type="radio" name="shape" value="hexagon" class="hidden peer">
<div class="aspect-square flex flex-col items-center justify-center p-2 border-2 border-stone-100 dark:border-zinc-800 rounded-xl text-stone-400 group-hover:text-emerald-500 peer-checked:text-emerald-500 peer-checked:border-emerald-500 peer-checked:bg-emerald-50/10 transition-all hover:border-stone-300 dark:hover:border-zinc-700">
<svg class="w-6 h-6 fill-current transition-colors" viewBox="0 0 24 24">
<path d="M12 2l8.66 5v10L12 22l-8.66-5V7L12 2z"/>
</svg>
</div>
</label>
<!-- 7. Звездочка -->
<label class="cursor-pointer group" title="Звезда">
<input type="radio" name="shape" value="star" class="hidden peer">
<div class="aspect-square flex flex-col items-center justify-center p-2 border-2 border-stone-100 dark:border-zinc-800 rounded-xl text-stone-400 group-hover:text-emerald-500 peer-checked:text-emerald-500 peer-checked:border-emerald-500 peer-checked:bg-emerald-50/10 transition-all hover:border-stone-300 dark:hover:border-zinc-700">
<svg class="w-6 h-6 fill-current transition-colors" viewBox="0 0 24 24">
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
</svg>
</div>
</label>
<!-- 8. Сердечко -->
<label class="cursor-pointer group" title="Сердечко">
<input type="radio" name="shape" value="heart" class="hidden peer">
<div class="aspect-square flex flex-col items-center justify-center p-2 border-2 border-stone-100 dark:border-zinc-800 rounded-xl text-stone-400 group-hover:text-emerald-500 peer-checked:text-emerald-500 peer-checked:border-emerald-500 peer-checked:bg-emerald-50/10 transition-all hover:border-stone-300 dark:hover:border-zinc-700">
<svg class="w-6 h-6 fill-current transition-colors" viewBox="0 0 24 24">
<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
</svg>
</div>
</label>
<!-- 9. Крестик / Плюс -->
<label class="cursor-pointer group" title="Крестик">
<input type="radio" name="shape" value="cross" class="hidden peer">
<div class="aspect-square flex flex-col items-center justify-center p-2 border-2 border-stone-100 dark:border-zinc-800 rounded-xl text-stone-400 group-hover:text-emerald-500 peer-checked:text-emerald-500 peer-checked:border-emerald-500 peer-checked:bg-emerald-50/10 transition-all hover:border-stone-300 dark:hover:border-zinc-700">
<svg class="w-6 h-6 fill-current transition-colors" viewBox="0 0 24 24">
<path d="M19 10.5h-5.5V5a1.5 1.5 0 00-3 0v5.5H5a1.5 1.5 0 000 3h5.5V19a1.5 1.5 0 003 0v-5.5H19a1.5 1.5 0 000-3z"/>
</svg>
</div>
</label>
<!-- 10. Черточка / Линия -->
<label class="cursor-pointer group" title="Линия">
<input type="radio" name="shape" value="line" class="hidden peer">
<div class="aspect-square flex flex-col items-center justify-center p-2 border-2 border-stone-100 dark:border-zinc-800 rounded-xl text-stone-400 group-hover:text-emerald-500 peer-checked:text-emerald-500 peer-checked:border-emerald-500 peer-checked:bg-emerald-50/10 transition-all hover:border-stone-300 dark:hover:border-zinc-700">
<div class="w-5 h-1 rounded-full bg-current transition-colors"></div>
</div>
</label>
<!-- 11. Волна / Синусоида -->
<label class="cursor-pointer group" title="Волна">
<input type="radio" name="shape" value="wave" class="hidden peer">
<div class="aspect-square flex flex-col items-center justify-center p-2 border-2 border-stone-100 dark:border-zinc-800 rounded-xl text-stone-400 group-hover:text-emerald-500 peer-checked:text-emerald-500 peer-checked:border-emerald-500 peer-checked:bg-emerald-50/10 transition-all hover:border-stone-300 dark:hover:border-zinc-700">
<svg class="w-6 h-6 stroke-current transition-colors" fill="none" stroke-width="2.5" stroke-linecap="round" viewBox="0 0 24 24">
<path d="M2 12c2.5-4 5.5-4 8 0s5.5 4 8 0 3.5-4 4-4"/>
</svg>
</div>
</label>
<!-- 12. Двоичный блок 3x3 -->
<label class="cursor-pointer group" title="Матрица 3x3 (0/1)">
<input type="radio" name="shape" value="binary" class="hidden peer">
<div class="aspect-square flex flex-col items-center justify-center p-1 border-2 border-stone-100 dark:border-zinc-800 rounded-xl text-stone-400 group-hover:text-emerald-500 peer-checked:text-emerald-500 peer-checked:border-emerald-500 peer-checked:bg-emerald-50/10 transition-all hover:border-stone-300 dark:hover:border-zinc-700">
<div class="grid grid-cols-2 gap-0.5 font-mono text-[14px] leading-[12px] font-black transition-colors select-none">
<span>1</span><span>0</span>
<span>0</span><span>1</span>
</div>
</div>
</label>
</div>
<!-- Таб: Цвет -->
<div x-show="activeTab === 'color'" class="space-y-4">
<div class="flex items-center justify-between pb-1 border-b border-stone-100 dark:border-zinc-800">
<span class="text-xs font-bold text-stone-400 uppercase">Цветовая схема</span>
<span class="text-xs font-semibold px-2.5 py-0.5 rounded-full bg-emerald-100 text-emerald-800 dark:bg-emerald-950/60 dark:text-emerald-400"
x-text="colors.length === 1 ? 'Монотон (1 цвет)' : (colors.length === 2 ? 'Дуотон (2 цвета)' : 'Триатон (3 цвета)')"></span>
</div>
<div class="space-y-3">
<template x-for="(color, index) in colors" :key="index">
<div class="flex items-center gap-2">
<div class="flex-1">
<div class="flex justify-between mb-1">
<label class="text-xs font-bold text-stone-400 uppercase"
x-text="colors.length === 1 ? 'Основной цвет' : ('Цвет ' + (index + 1))"></label>
<span class="text-xs font-mono uppercase text-stone-500 dark:text-stone-400" x-text="colors[index]"></span>
</div>
<input type="color" name="colors" x-model="colors[index]"
class="w-full h-10 border-none rounded-lg cursor-pointer bg-stone-50 dark:bg-zinc-800">
</div>
<template x-if="colors.length > 1">
<button type="button"
@click="colors.splice(index, 1); $nextTick(() => $el.closest('form').dispatchEvent(new Event('change')))"
class="self-end mb-1 p-2 text-stone-400 hover:text-red-500 rounded-lg hover:bg-stone-100 dark:hover:bg-zinc-800 transition-colors"
title="Удалить цвет">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
</svg>
</button>
</template>
</div>
</template>
</div>
<div x-show="colors.length < 3" class="pt-2">
<button type="button"
@click="colors.push(colors.length === 1 ? '#f97316' : '#06b6d4'); $nextTick(() => $el.closest('form').dispatchEvent(new Event('change')))"
class="w-full flex items-center justify-center gap-2 py-2.5 px-3 text-xs font-bold uppercase rounded-xl border-2 border-dashed border-stone-300 dark:border-zinc-700 text-stone-500 dark:text-stone-400 hover:border-emerald-500 hover:text-emerald-500 transition-colors cursor-pointer">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
</svg>
<span x-text="colors.length === 1 ? 'Добавить второй цвет (Дуотон)' : 'Добавить третий цвет (Триатон)'"></span>
</button>
</div>
</div>
<!-- Таб: Параметры -->
<div x-show="activeTab === 'params'" class="space-y-4">
{# ПЛОТНОСТЬ СЕТКИ (ЧИСЛО КОЛОНОК) #}<div>
<div class="flex justify-between mb-1">
<label class="text-xs font-bold text-stone-400 uppercase">Плотность галлюцинации</label>
<span class="text-xs transition-colors duration-300"
:class="cols >= 140 ? 'text-red-600' : (cols > 80 ? 'text-yellow-500' : 'text-emerald-600')"
x-text="cols"></span>
</div>
<input type="range" name="cols" min="20" max="200" x-model="cols"
@input="$el.dispatchEvent(new CustomEvent('input-change'))"
:class="cols >= 140 ? 'accent-red-600' : (cols > 80 ? 'accent-yellow-500' : 'accent-emerald-500')"
class="w-full transition-all duration-300">
</div>
{# РАЗМЕР ЭЛЕМЕНТА #}<div>
<div class="flex justify-between mb-1">
<label class="text-xs font-bold text-stone-400 uppercase">Размер гипно-точки</label>
<span class="text-xs transition-colors duration-300"
:class="radius < 4 ? 'text-red-600' : (radius < 5 ? 'text-yellow-600' : (radius > 15 ? 'text-red-600' : (radius > 12 ? 'text-yellow-600' : 'text-emerald-600')))"
x-text="radius"></span>
</div>
<input type="range" name="max_radius" min="3" max="20" x-model="radius"
@input="$el.dispatchEvent(new CustomEvent('input-change'))"
:class="radius < 4 ? 'accent-red-600' : (radius < 5 ? 'accent-yellow-500' : (radius > 15 ? 'accent-red-600' : (radius > 12 ? 'accent-yellow-500' : 'accent-emerald-500')))"
class="w-full accent-emerald-500">
</div>
{# МЕРЦАНИЕ #}<div>
<div class="flex justify-between mb-1">
<label class="text-xs font-bold text-stone-400 uppercase">Мерцание</label>
<span class="text-xs transition-colors duration-300"
:class="blink < 1 ? 'text-emerald-600' : (blink < 2 ? 'text-red-600' : (blink < 4 ? 'text-yellow-600' : 'text-emerald-600'))"
x-text="blink"></span>
</div>
<input type="range" name="blink" min="0" max="10" x-model="blink"
@input="$el.dispatchEvent(new CustomEvent('input-change'))"
:class="blink < 1 ? 'accent-emerald-600' : (blink < 2 ? 'accent-red-600' : (blink < 4 ? 'accent-yellow-500' : 'accent-emerald-500'))"
class="w-full accent-emerald-500">
</div>
{# ПОВОРОТЫ #}<div>
<div class="flex justify-between mb-1">
<label class="text-xs font-bold text-stone-400 uppercase">Укачивание</label>
<span class="text-xs transition-colors duration-300"
:class="rotation < -7 ? 'text-red-600' : (rotation < -4 ? 'text-yellow-600' : (rotation > 7 ? 'text-red-600' : (rotation > 4 ? 'text-yellow-600' : 'text-emerald-600')))"
x-text="rotation + '°'"></span>
</div>
<input type="range" name="rotation" min="-15" max="15" x-model="rotation"
@input="$el.dispatchEvent(new CustomEvent('input-change'))"
:class="rotation < -7 ? 'accent-red-600' : (rotation < -4 ? 'accent-yellow-500' : (rotation > 7 ? 'accent-red-600' : (rotation > 4 ? 'accent-yellow-500' : 'accent-emerald-500')))"
class="w-full accent-emerald-500">
</div>
{# МАСШТАБ #}<div>
<div class="flex justify-between mb-1">
<label class="text-xs font-bold text-stone-400">Взз-з-з-з…</label>
<span class="text-xs transition-colors duration-300"
:class="scale < 900 ? 'text-red-600' : (scale < 950 ? 'text-yellow-600' : (scale > 1030 ? 'text-red-600' : (scale > 1010 ? 'text-yellow-600' : 'text-emerald-600')))"
x-text="(scale / 10).toFixed(1) + '%'"></span>
</div>
<input type="range" name="scale" min="800" max="1040" x-model="scale"
@input="$el.dispatchEvent(new CustomEvent('input-change'))"
:class="scale < 900 ? 'accent-red-600' : (scale < 950 ? 'accent-yellow-500' : (scale > 1030 ? 'accent-red-600' : (scale > 1010 ? 'accent-yellow-500' : 'accent-emerald-500')))"
class="w-full accent-emerald-500">
</div>
{# НАКЛОН СЕТКИ #}<div>
<div class="flex justify-between mb-1">
<label class="text-xs font-bold text-stone-400 uppercase">Перекос</label>
<span class="text-xs transition-colors duration-300 text-emerald-600" x-text="angle + '°'"></span>
</div>
<input type="range" name="angle" min="-44" max="45" step="1" x-model="angle"
class="w-full accent-emerald-500">
</div>
</div>
</div>
<!-- Индикатор размышления / статус активности -->
<div class="h-8 mt-2 flex items-center justify-center">
<div x-show="isLoading"
x-transition
class="flex items-center gap-2 px-3.5 py-1 rounded-full bg-emerald-500/10 border border-emerald-500/30 text-emerald-600 dark:text-emerald-400 text-xs font-bold font-mono tracking-wide animate-pulse">
<img src="{% static 'img/thinking.svg' %}" class="w-4 h-4 animate-spin [animation-duration:3s]">
<span>Глюкало думает...</span>
</div>
<div x-show="!isLoading && !hasChanges"
class="text-[11px] font-mono text-stone-400 dark:text-zinc-500 tracking-wider">
Параметры зафиксированы
</div>
<div x-show="!isLoading && hasChanges"
class="text-[11px] font-mono text-emerald-600 dark:text-emerald-500 font-semibold tracking-wider flex items-center gap-1.5">
<span class="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-ping"></span>
<span>Готово к запуску транса</span>
</div>
</div>
<button type="submit"
:disabled="isLoading || !hasChanges"
:class="(!hasChanges || isLoading)
? 'bg-stone-200 dark:bg-zinc-800 text-stone-400 dark:text-zinc-600 cursor-not-allowed shadow-none'
: 'bg-emerald-600 hover:bg-emerald-500 text-white shadow-lg shadow-emerald-900/20 active:scale-95 cursor-pointer'"
class="w-full mt-2 font-bold py-3.5 px-6 rounded-xl transition-all flex items-center justify-center gap-2">
<template x-if="isLoading">
<span class="flex items-center gap-2">
<img src="{% static 'img/thinking.svg' %}" class="w-5 h-5 animate-spin [animation-duration:2s]">
<span>ГЛЮКОТРОН В ТРАНСЕ...</span>
</span>
</template>
<template x-if="!isLoading">
<span>ЗАПУСТИТЬ ГЛЮКОТРОН</span>
</template>
</button>
</form>
</aside>
<!-- ПРАВАЯ ПАНЕЛЬ: ПРЕВЬЮ -->
<section class="flex flex-col gap-6">
<div id="preview"
class="w-full h-[744px] bg-stone-200 dark:bg-zinc-900 rounded-3xl flex items-center justify-center border border-stone-300 dark:border-zinc-800 overflow-hidden relative group">
<div class="text-stone-400 flex flex-col items-center gap-4 text-center px-6">
<svg xmlns="http://www.w3.org/2000/svg" class="w-16 h-16 opacity-50" fill="none" viewBox="0 0 24 24" stroke="currentColor"
:class="isLoading ? 'animate-pulse text-emerald-500 opacity-80' : 'opacity-50'">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/>
</svg>
<p class="transition-all duration-300"
:class="isLoading ? 'text-emerald-600 dark:text-emerald-400 font-mono text-xs font-bold uppercase tracking-wider animate-pulse' : 'font-medium opacity-50'"
x-text="isLoading ? 'Гипножаба переваривает пиксели…' : 'Ваше искусство появится здесь'"></p>
</div>
<!-- Заглушка для кнопок действий (появятся при генерации) -->
<div
class="absolute bottom-6 right-6 flex items-center gap-3 translate-y-20 group-hover:translate-y-0 transition-transform duration-300 pointer-events-none">
<button id="like-to-gallery" type="button" title="Нравится!"
class="pointer-events-auto flex items-center gap-2 bg-emerald-600/85 hover:bg-emerald-600 text-white text-xs font-bold uppercase tracking-wide backdrop-blur-md px-4 py-2.5 rounded-full shadow-xl transition-all hover:scale-105 active:scale-95 cursor-pointer">
<span>Кандидат в галерею транса</span>
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"/>
</svg>
</button>
<button id="dislike-from-gallery" type="button" title="Не нравится!"
class="pointer-events-auto flex items-center gap-2 bg-rose-900/90 hover:bg-rose-500 text-white text-xs font-bold uppercase tracking-wide backdrop-blur-md px-4 py-2.5 rounded-full shadow-xl transition-all hover:scale-105 active:scale-95 cursor-pointer">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636"/>
<span>Гипнoжаба такое не одобрит</span>
</svg>
</button>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<button
type="button"
@click="copySvg()"
class="bg-stone-800 text-white dark:bg-zinc-800 py-3.5 rounded-xl font-bold flex items-center justify-center gap-2 hover:bg-stone-700 transition-colors cursor-pointer active:scale-95">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/></svg>
<span x-text="copied ? 'СКОПИРОВАНО В БУФЕР!' : 'КОПИРОВАТЬ SVG'"></span>
</button>
<button
type="button"
@click="downloadSvg()"
class="bg-emerald-600 text-white py-3.5 rounded-xl font-bold flex items-center justify-center gap-2 hover:bg-emerald-500 transition-colors shadow-lg shadow-emerald-900/20 cursor-pointer active:scale-95">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M4 16v1a2 2 0 002 2h12a2 2 0 002-2v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg>
СКАЧАТЬ
</button>
</div>
</section>
</div>
<!-- СЕКЦИЯ: ТРЕХЭТАЖНАЯ ГАЛЕРЕЯ -->
<section class="mt-20 space-y-12">
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 pb-6 border-b border-stone-200 dark:border-zinc-800">
<div>
<h2 class="text-3xl font-black uppercase tracking-tighter">Галерея транса</h2>
<p class="text-sm text-stone-500 dark:text-zinc-400 mt-1">Многоуровневое хранилище зрительного подчинения</p>
</div>
<a href="#" class="text-emerald-600 dark:text-emerald-400 font-bold hover:underline self-start sm:self-auto">Смотреть весь архив →</a>
</div>
<!-- 1-й ЭТАЖ: ПЛЕСК БЕССОЗНАТЕЛЬНОГО (Свежий поток)... Сюда попадет только что созданный шедевр (нужно чтобы это было интерактивно... лаккнул и сразу через HTMX на первом уровне галереи -->
<div class="space-y-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<div class="w-5 h-5 rounded-full bg-amber-500"></div>
<div>
<h3 class="text-xl font-black uppercase tracking-tight flex items-center gap-2">
Плеск бессознательного
<span class="text-xs font-bold font-mono px-2 py-0.5 rounded-full bg-amber-100 dark:bg-amber-950/70 text-amber-700 dark:text-amber-400 border border-amber-300 dark:border-amber-800/50">FRESH STREAM</span>
</h3>
<p class="text-xs text-stone-400 dark:text-zinc-500">Свежие галлюцинации из инкубатора • Первичная оценка сообщества</p>
</div>
</div>
<span class="text-xs font-semibold text-stone-400">Свежее • до 100 лайков</span>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4">
<template x-for="i in 6">
<div class="aspect-square bg-stone-200 dark:bg-zinc-900 rounded-xl border border-stone-300 dark:border-zinc-800 overflow-hidden relative group cursor-pointer hover:border-amber-500/50 transition-all hover:scale-[1.02]">
<div class="absolute inset-0 flex items-center justify-center text-stone-400 group-hover:scale-110 transition-transform">
<svg class="w-8 h-8 opacity-20" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>
</svg>
</div>
<div class="absolute bottom-2 left-2 flex items-center gap-1 text-[11px] font-bold text-amber-600 dark:text-amber-400 bg-white/90 dark:bg-zinc-900/90 px-2 py-0.5 rounded-full opacity-0 group-hover:opacity-100 transition-opacity">
<span x-text="Math.floor(Math.random()*99) + 1"></span>
</div>
</div>
</template>
</div>
</div>
<!-- 2-й ЭТАЖ: ОДОБРЕНО МОЗГОВЫМ СЛИЗНЕМ (Кураторский отбор) -->
<div class="space-y-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<div class="w-5 h-5 rounded-full bg-cyan-500"></div>
<div>
<h3 class="text-xl font-black uppercase tracking-tight flex items-center gap-2">
Одобрено Мозговым Слизнем
<span class="text-xs font-bold font-mono px-2 py-0.5 rounded-full bg-cyan-100 dark:bg-cyan-950/70 text-cyan-700 dark:text-cyan-400 border border-cyan-300 dark:border-cyan-800/50">CURATED</span>
</h3>
<p class="text-xs text-stone-400 dark:text-zinc-500">Проверено контролем качества • Высокий психоделический резонанс</p>
</div>
</div>
<span class="text-xs font-semibold text-stone-400">100999 лайков</span>
</div>
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4">
<template x-for="i in 6">
<div class="aspect-square bg-stone-200 dark:bg-zinc-900 rounded-xl border border-stone-300 dark:border-zinc-800 overflow-hidden relative group cursor-pointer hover:border-cyan-500/50 transition-all hover:scale-[1.02]">
<div class="absolute inset-0 flex items-center justify-center text-stone-400 group-hover:scale-110 transition-transform">
<svg class="w-8 h-8 opacity-20" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>
</svg>
</div>
<div class="absolute bottom-2 left-2 flex items-center gap-1 text-[11px] font-bold text-cyan-600 dark:text-cyan-400 bg-white/90 dark:bg-zinc-900/90 px-2 py-0.5 rounded-full opacity-0 group-hover:opacity-100 transition-opacity">
<span x-text="100 + Math.floor(Math.random()*400)"></span>
</div>
</div>
</template>
</div>
</div>
<!-- 3-й ЭТАЖ: ГЛУБОКИЙ ТРАНС (Высшая лига) -->
<div class="space-y-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<div class="w-5 h-5"><img src="{% static 'img/favicon.svg' %}" alt="Favicon" class="w-full h-full object-cover"></div>
<div>
<h3 class="text-xl font-black uppercase tracking-tight flex items-center gap-2">
Глубокий транс
<span class="text-xs font-bold font-mono px-2 py-0.5 rounded-full bg-emerald-100 dark:bg-emerald-950/70 text-emerald-700 dark:text-emerald-400 border border-emerald-300 dark:border-emerald-800/50">TOP TIER</span>
</h3>
<p class="text-xs text-stone-400 dark:text-zinc-500">Золотой фонд гипноза • Абсолютное подчинение воли</p>
</div>
</div>
<span class="text-xs font-semibold text-stone-400">1000+ лайков</span>
</div>
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4">
<template x-for="i in 6">
<div class="aspect-square bg-stone-200 dark:bg-zinc-900 rounded-2xl border-2 border-emerald-500/30 dark:border-emerald-500/20 overflow-hidden relative group cursor-pointer shadow-lg shadow-emerald-950/5 hover:border-emerald-500 transition-all hover:scale-[1.02]">
<div class="absolute inset-0 flex items-center justify-center text-emerald-600/40 group-hover:scale-110 transition-transform">
<svg class="w-10 h-10 opacity-30" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>
</svg>
</div>
<div class="absolute top-2 right-2 text-[10px] font-black tracking-widest text-emerald-600 dark:text-emerald-400 bg-emerald-500/10 backdrop-blur-md px-1.5 py-0.5 rounded border border-emerald-500/20">
★ 99%
</div>
<div class="absolute bottom-2.5 left-2.5 flex items-center gap-1.5 text-xs font-bold text-white bg-emerald-600/90 backdrop-blur-md px-2.5 py-1 rounded-full shadow">
<span></span> <span x-text="500 + Math.floor(Math.random()*500)"></span>
</div>
</div>
</template>
</div>
</div>
</section>{% endblock CONTENT %}