626 lines
16 KiB
HTML
626 lines
16 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Subtitle Preset Grid Redesign Demo</title>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Lobster&display=swap" rel="stylesheet">
|
|
<style>
|
|
/* Catppuccin Mocha - Matching the actual project colors */
|
|
:root {
|
|
/* Backgrounds */
|
|
--bg-canvas: #11111b;
|
|
--bg-default: #1e1e2e;
|
|
--bg-surface: #313244;
|
|
--bg-hover: #45475a;
|
|
--bg-default-invert: #eff1f5;
|
|
|
|
/* Text */
|
|
--text-primary: #cdd6f4;
|
|
--text-secondary: #bac2de;
|
|
--text-tertiary: #9399b2;
|
|
|
|
/* Borders */
|
|
--border-default: #45475a;
|
|
--border-subtle: #313244;
|
|
|
|
/* Purples (accent) */
|
|
--purple-400: #cba6f7;
|
|
--purple-500: #d9bcfa;
|
|
--purple-600: #e4cffc;
|
|
--purple-700: #eddfff;
|
|
--purple-300: #6a5a93;
|
|
--purple-200: #4b4168;
|
|
--purple-100: #362f4c;
|
|
--purple-50: #2b253b;
|
|
|
|
/* Shadows */
|
|
--shadow-sm: 0 1px 2px rgba(17, 17, 27, 0.5);
|
|
--shadow-md: 0 4px 6px -1px rgba(17, 17, 27, 0.58), 0 24px 48px -12px rgba(17, 17, 27, 0.52);
|
|
--shadow-lg: 0 10px 15px -3px rgba(17, 17, 27, 0.6), 0 40px 80px -20px rgba(17, 17, 27, 0.7);
|
|
|
|
/* Accent glow */
|
|
--accent-shadow: rgba(203, 166, 247, 0.22);
|
|
--accent-shadow-hover: rgba(203, 166, 247, 0.3);
|
|
|
|
/* Preview background */
|
|
--preview-bg: #0c0a1a;
|
|
}
|
|
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Inter', sans-serif;
|
|
background: var(--bg-canvas);
|
|
color: var(--text-primary);
|
|
padding: 40px 20px;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
body::before {
|
|
content: "";
|
|
position: fixed;
|
|
inset: 0;
|
|
background: radial-gradient(circle at 50% 0%, rgba(203, 166, 247, 0.08) 0%, transparent 55%);
|
|
pointer-events: none;
|
|
z-index: -1;
|
|
}
|
|
|
|
.container {
|
|
max-width: 1400px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
h1 {
|
|
font-size: 24px;
|
|
font-weight: 600;
|
|
margin-bottom: 32px;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
/* Controls */
|
|
.controls {
|
|
display: flex;
|
|
gap: 16px;
|
|
margin-bottom: 32px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.control-group {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
.control-group label {
|
|
font-size: 11px;
|
|
color: var(--text-tertiary);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.8px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.aspect-buttons {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
|
|
.aspect-btn {
|
|
padding: 8px 14px;
|
|
background: var(--bg-surface);
|
|
border: 1px solid var(--border-default);
|
|
color: var(--text-secondary);
|
|
border-radius: 8px;
|
|
cursor: pointer;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
transition: all 0.15s ease;
|
|
}
|
|
|
|
.aspect-btn:hover {
|
|
background: var(--bg-hover);
|
|
border-color: var(--purple-400);
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.aspect-btn.active {
|
|
background: var(--purple-100);
|
|
border-color: var(--purple-400);
|
|
color: var(--purple-400);
|
|
}
|
|
|
|
/* Grid */
|
|
.preset-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
gap: 20px;
|
|
margin-bottom: 48px;
|
|
}
|
|
|
|
/* Preset Card */
|
|
.preset-card {
|
|
position: relative;
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
background: var(--bg-default);
|
|
border: 1px solid var(--border-subtle);
|
|
cursor: pointer;
|
|
transition: all 0.2s cubic-bezier(0.2, 0.8, 0.2, 1);
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.preset-card:hover {
|
|
border-color: var(--purple-400);
|
|
transform: translateY(-2px);
|
|
box-shadow: var(--shadow-md);
|
|
}
|
|
|
|
.preset-card.selected {
|
|
border-color: var(--purple-400);
|
|
box-shadow:
|
|
0 0 0 1px var(--purple-400),
|
|
0 0 20px rgba(203, 166, 247, 0.25),
|
|
var(--shadow-lg);
|
|
}
|
|
|
|
.preset-card.selected::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: -1px;
|
|
border-radius: 12px;
|
|
padding: 1px;
|
|
background: linear-gradient(135deg, var(--purple-400), var(--purple-600));
|
|
-webkit-mask:
|
|
linear-gradient(#fff 0 0) content-box,
|
|
linear-gradient(#fff 0 0);
|
|
-webkit-mask-composite: xor;
|
|
mask-composite: exclude;
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* Preview Area */
|
|
.preview-area {
|
|
position: relative;
|
|
aspect-ratio: 16 / 9;
|
|
background: var(--preview-bg);
|
|
overflow: hidden;
|
|
transition: aspect-ratio 0.3s ease;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.preview-area.vertical {
|
|
aspect-ratio: 9 / 16;
|
|
}
|
|
|
|
.preview-area.square {
|
|
aspect-ratio: 1 / 1;
|
|
}
|
|
|
|
.preview-area.instagram {
|
|
aspect-ratio: 4 / 5;
|
|
}
|
|
|
|
.preview-text {
|
|
text-align: center;
|
|
padding: 16px;
|
|
font-size: 28px;
|
|
line-height: 1.4;
|
|
z-index: 1;
|
|
}
|
|
|
|
.preview-text .highlight {
|
|
font-weight: 700;
|
|
}
|
|
|
|
/* Card Footer */
|
|
.card-footer {
|
|
padding: 14px 16px;
|
|
background: linear-gradient(to top, var(--bg-surface), var(--bg-default));
|
|
border-top: 1px solid var(--border-subtle);
|
|
}
|
|
|
|
.preset-name {
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: var(--text-primary);
|
|
margin-bottom: 6px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.system-badge {
|
|
font-size: 10px;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
padding: 2px 8px;
|
|
background: var(--purple-100);
|
|
color: var(--purple-400);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.style-chars {
|
|
font-size: 12px;
|
|
color: var(--text-tertiary);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.color-dot {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
display: inline-block;
|
|
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
/* Create New Card */
|
|
.create-card {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 12px;
|
|
aspect-ratio: 16 / 9;
|
|
background: transparent;
|
|
border: 2px dashed var(--border-default);
|
|
border-radius: 12px;
|
|
cursor: pointer;
|
|
transition: all 0.2s ease;
|
|
color: var(--text-tertiary);
|
|
min-height: 100%;
|
|
}
|
|
|
|
.create-card:hover {
|
|
border-color: var(--purple-400);
|
|
background: rgba(203, 166, 247, 0.05);
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.create-card svg {
|
|
width: 32px;
|
|
height: 32px;
|
|
opacity: 0.6;
|
|
}
|
|
|
|
/* Skeleton Loading - Improved */
|
|
.skeleton-card {
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
background: var(--bg-default);
|
|
border: 1px solid var(--border-subtle);
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.skeleton-preview {
|
|
aspect-ratio: 16 / 9;
|
|
background: var(--bg-surface);
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.skeleton-preview::after {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
background: linear-gradient(
|
|
90deg,
|
|
transparent 0%,
|
|
rgba(203, 166, 247, 0.08) 50%,
|
|
transparent 100%
|
|
);
|
|
animation: shimmer 1.5s infinite;
|
|
}
|
|
|
|
@keyframes shimmer {
|
|
0% { transform: translateX(-100%); }
|
|
100% { transform: translateX(100%); }
|
|
}
|
|
|
|
.skeleton-footer {
|
|
padding: 14px 16px;
|
|
background: linear-gradient(to top, var(--bg-surface), var(--bg-default));
|
|
border-top: 1px solid var(--border-subtle);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
}
|
|
|
|
.skeleton-line {
|
|
height: 14px;
|
|
background: var(--bg-hover);
|
|
border-radius: 4px;
|
|
width: 60%;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.skeleton-line.short {
|
|
width: 40%;
|
|
height: 10px;
|
|
}
|
|
|
|
.skeleton-line::after {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
background: linear-gradient(
|
|
90deg,
|
|
transparent 0%,
|
|
rgba(203, 166, 247, 0.06) 50%,
|
|
transparent 100%
|
|
);
|
|
animation: shimmer 1.5s infinite;
|
|
}
|
|
|
|
/* Section Label */
|
|
.section-label {
|
|
font-size: 11px;
|
|
color: var(--text-tertiary);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.8px;
|
|
margin-bottom: 12px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* Selected indicator */
|
|
.selected-indicator {
|
|
position: absolute;
|
|
top: 8px;
|
|
right: 8px;
|
|
width: 20px;
|
|
height: 20px;
|
|
background: var(--purple-400);
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: 0 2px 8px rgba(203, 166, 247, 0.4);
|
|
}
|
|
|
|
.selected-indicator svg {
|
|
width: 12px;
|
|
height: 12px;
|
|
color: var(--bg-canvas);
|
|
}
|
|
|
|
/* Responsive */
|
|
@media (max-width: 768px) {
|
|
.preset-grid {
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 12px;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1>Выбор пресета субтитров</h1>
|
|
|
|
<!-- Controls -->
|
|
<div class="controls">
|
|
<div class="control-group">
|
|
<label>Аспектное соотношение видео</label>
|
|
<div class="aspect-buttons">
|
|
<button class="aspect-btn active" data-ratio="16:9">16:9 (Широкое)</button>
|
|
<button class="aspect-btn" data-ratio="9:16">9:16 (Вертикальное)</button>
|
|
<button class="aspect-btn" data-ratio="1:1">1:1 (Квадрат)</button>
|
|
<button class="aspect-btn" data-ratio="4:5">4:5 (Instagram)</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Section: Ready Presets -->
|
|
<div class="section-label">Пример: готовые пресеты</div>
|
|
<div class="preset-grid" id="presetGrid">
|
|
<!-- Card 1: Классические -->
|
|
<div class="preset-card selected" data-preset="classic">
|
|
<div class="preview-area">
|
|
<div class="preview-text" style="font-family: 'Lobster', cursive; color: #ffffff;">
|
|
Пример <span class="highlight" style="color: #FFD700;">субтитров</span>
|
|
</div>
|
|
<div class="selected-indicator">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
|
|
<polyline points="20 6 9 17 4 12"></polyline>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
<div class="card-footer">
|
|
<div class="preset-name">
|
|
Классические
|
|
<span class="system-badge">Системный</span>
|
|
</div>
|
|
<div class="style-chars">
|
|
Lobster
|
|
<span style="color: var(--border-default);">·</span>
|
|
<span class="color-dot" style="background: #FFD700;"></span>
|
|
<span style="color: #FFD700;">Золотой</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Card 2: Неон -->
|
|
<div class="preset-card" data-preset="neon">
|
|
<div class="preview-area">
|
|
<div class="preview-text" style="font-family: 'Inter', sans-serif; font-weight: 700; color: #ffffff; text-shadow: 0 0 10px #00ffff, 0 0 20px #00ffff;">
|
|
Пример <span class="highlight" style="color: #00ffff;">субтитров</span>
|
|
</div>
|
|
</div>
|
|
<div class="card-footer">
|
|
<div class="preset-name">
|
|
Неон
|
|
<span class="system-badge">Системный</span>
|
|
</div>
|
|
<div class="style-chars">
|
|
Inter Bold
|
|
<span style="color: var(--border-default);">·</span>
|
|
<span class="color-dot" style="background: #00ffff; box-shadow: 0 0 6px #00ffff;"></span>
|
|
<span style="color: #00ffff;">Неоновый</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Card 3: Минимализм -->
|
|
<div class="preset-card" data-preset="minimal">
|
|
<div class="preview-area">
|
|
<div class="preview-text" style="font-family: 'Inter', sans-serif; font-weight: 400; color: #e0e0e0; font-size: 24px;">
|
|
Пример <span class="highlight" style="color: #ffffff; font-weight: 500;">субтитров</span>
|
|
</div>
|
|
</div>
|
|
<div class="card-footer">
|
|
<div class="preset-name">
|
|
Минимализм
|
|
<span class="system-badge">Системный</span>
|
|
</div>
|
|
<div class="style-chars">
|
|
Inter Regular
|
|
<span style="color: var(--border-default);">·</span>
|
|
<span class="color-dot" style="background: #ffffff;"></span>
|
|
<span style="color: #ffffff;">Белый</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Card 4: Жирный -->
|
|
<div class="preset-card" data-preset="bold">
|
|
<div class="preview-area">
|
|
<div class="preview-text" style="font-family: 'Inter', sans-serif; font-weight: 900; color: #ffffff; -webkit-text-stroke: 2px #000000; font-size: 32px;">
|
|
Пример <span class="highlight" style="color: #ff006e;">субтитров</span>
|
|
</div>
|
|
</div>
|
|
<div class="card-footer">
|
|
<div class="preset-name">
|
|
Жирный
|
|
<span class="system-badge">Системный</span>
|
|
</div>
|
|
<div class="style-chars">
|
|
Inter Black
|
|
<span style="color: var(--border-default);">·</span>
|
|
<span class="color-dot" style="background: #ff006e;"></span>
|
|
<span style="color: #ff006e;">Розовый</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Create New Card -->
|
|
<div class="create-card">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<line x1="12" y1="5" x2="12" y2="19"></line>
|
|
<line x1="5" y1="12" x2="19" y2="12"></line>
|
|
</svg>
|
|
<span style="font-size: 14px; font-weight: 500;">Создать пресет</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Section: Loading State -->
|
|
<div class="section-label">Пример: состояние загрузки</div>
|
|
<div class="preset-grid">
|
|
<div class="skeleton-card">
|
|
<div class="skeleton-preview"></div>
|
|
<div class="skeleton-footer">
|
|
<div class="skeleton-line"></div>
|
|
<div class="skeleton-line short"></div>
|
|
</div>
|
|
</div>
|
|
<div class="skeleton-card">
|
|
<div class="skeleton-preview"></div>
|
|
<div class="skeleton-footer">
|
|
<div class="skeleton-line"></div>
|
|
<div class="skeleton-line short"></div>
|
|
</div>
|
|
</div>
|
|
<div class="skeleton-card">
|
|
<div class="skeleton-preview"></div>
|
|
<div class="skeleton-footer">
|
|
<div class="skeleton-line"></div>
|
|
<div class="skeleton-line short"></div>
|
|
</div>
|
|
</div>
|
|
<div class="skeleton-card">
|
|
<div class="skeleton-preview"></div>
|
|
<div class="skeleton-footer">
|
|
<div class="skeleton-line"></div>
|
|
<div class="skeleton-line short"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Aspect ratio switching
|
|
const aspectButtons = document.querySelectorAll('.aspect-btn');
|
|
const previewAreas = document.querySelectorAll('.preview-area');
|
|
const skeletonPreviews = document.querySelectorAll('.skeleton-preview');
|
|
const createCard = document.querySelector('.create-card');
|
|
|
|
aspectButtons.forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
// Update active button
|
|
aspectButtons.forEach(b => b.classList.remove('active'));
|
|
btn.classList.add('active');
|
|
|
|
const ratio = btn.dataset.ratio;
|
|
|
|
// Update preview areas
|
|
previewAreas.forEach(preview => {
|
|
preview.classList.remove('vertical', 'square', 'instagram');
|
|
if (ratio === '9:16') preview.classList.add('vertical');
|
|
if (ratio === '1:1') preview.classList.add('square');
|
|
if (ratio === '4:5') preview.classList.add('instagram');
|
|
});
|
|
|
|
// Update skeleton previews
|
|
skeletonPreviews.forEach(preview => {
|
|
if (ratio === '9:16') preview.style.aspectRatio = '9 / 16';
|
|
else if (ratio === '1:1') preview.style.aspectRatio = '1 / 1';
|
|
else if (ratio === '4:5') preview.style.aspectRatio = '4 / 5';
|
|
else preview.style.aspectRatio = '16 / 9';
|
|
});
|
|
|
|
// Update create card
|
|
if (ratio === '9:16') createCard.style.aspectRatio = '9 / 16';
|
|
else if (ratio === '1:1') createCard.style.aspectRatio = '1 / 1';
|
|
else if (ratio === '4:5') createCard.style.aspectRatio = '4 / 5';
|
|
else createCard.style.aspectRatio = '16 / 9';
|
|
});
|
|
});
|
|
|
|
// Card selection
|
|
const presetCards = document.querySelectorAll('.preset-card');
|
|
presetCards.forEach(card => {
|
|
card.addEventListener('click', () => {
|
|
presetCards.forEach(c => {
|
|
c.classList.remove('selected');
|
|
const indicator = c.querySelector('.selected-indicator');
|
|
if (indicator) indicator.remove();
|
|
});
|
|
card.classList.add('selected');
|
|
|
|
// Add checkmark indicator
|
|
const preview = card.querySelector('.preview-area');
|
|
if (!preview.querySelector('.selected-indicator')) {
|
|
const indicator = document.createElement('div');
|
|
indicator.className = 'selected-indicator';
|
|
indicator.innerHTML = `
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
|
|
<polyline points="20 6 9 17 4 12"></polyline>
|
|
</svg>
|
|
`;
|
|
preview.appendChild(indicator);
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|