Files
Viz/public/index.html
T

884 lines
43 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.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Viz 2.0 — Audio Visualizer Studio für DaVinci Resolve</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@700&family=Inter:wght@300;400;500;600;700;800&family=Montserrat:wght@400;600;800&family=Orbitron:wght@600;800;900&family=Outfit:wght@400;600;700;800&family=Syncopate:wght@700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="app-layout">
<!-- Header -->
<header class="app-header">
<div class="brand">
<div class="brand-logo">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
<polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
<polyline points="2 17 12 22 22 17"></polyline>
<polyline points="2 12 12 17 22 12"></polyline>
</svg>
</div>
<div class="brand-text">
<h1>VIZ<span>Studio 2.0</span></h1>
<span class="badge">DaVinci Alpha Edition</span>
</div>
</div>
<div class="header-actions">
<!-- Quick Presets -->
<div class="quick-preset-picker">
<label for="quickPresetSelect">⚡ Preset:</label>
<select id="quickPresetSelect">
<option value="trap_nation">🟣 Trap Nation (Kreis & Radial)</option>
<option value="cyber_hexagon">⬡ Cyber Hexagon (Neon Core)</option>
<option value="synthwave_horizon">🌅 Synthwave Horizon (Linear & 3D Grid)</option>
<option value="laser_oscilloscope">〰️ Laser Oscilloscope (No-Cover Wave)</option>
<option value="diamond_bass">💎 Diamond Bass Drop (Polygon Core)</option>
<option value="cosmic_wormhole">🌀 Cosmic Wormhole (3D Tunnel)</option>
<option value="studio_rack_eq">📊 Studio Graphic EQ (Block Bars)</option>
<option value="minimal_ice_wave">❄️ Minimal Ice Wave (Clean Spline)</option>
</select>
</div>
<button id="headerExportBtn" class="btn btn-primary btn-glow">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
Exportieren
</button>
</div>
</header>
<!-- Main Workspace -->
<main class="workspace">
<!-- Left: Stage & Player -->
<section class="stage-section">
<!-- Aspect & Tools Bar -->
<div class="stage-toolbar">
<div class="aspect-switchers">
<button class="aspect-btn active" data-aspect="16:9" title="16:9 YouTube Standard (1920x1080 / 4K)">
<span class="icon">📺</span> 16:9
</button>
<button class="aspect-btn" data-aspect="9:16" title="9:16 Shorts, TikTok & Reels (1080x1920)">
<span class="icon">📱</span> 9:16
</button>
<button class="aspect-btn" data-aspect="1:1" title="1:1 Quadratisch (Instagram 1080x1080)">
<span class="icon">🔲</span> 1:1
</button>
</div>
<div class="stage-toggles">
<label class="toggle-chip" title="Zeigt TikTok & Shorts UI-Überlagerung für exaktes Platzieren">
<input type="checkbox" id="toggleSafeZone">
<span>Safe-Zone</span>
</label>
<label class="toggle-chip" title="Transparenz-Gitter im Hintergrund ein-/ausblenden">
<input type="checkbox" id="toggleAlphaGrid" checked>
<span>Alpha-Gitter</span>
</label>
</div>
</div>
<!-- Canvas Viewport -->
<div class="canvas-viewport" id="canvasViewport">
<div class="canvas-wrapper aspect-16-9" id="canvasWrapper">
<canvas id="vizCanvas" width="1920" height="1080"></canvas>
<!-- Safe Zone Overlay (Visual helper for Shorts UI) -->
<div class="safe-zone-overlay hidden" id="safeZoneOverlay">
<div class="safe-zone-box">
<div class="safe-zone-title">Shorts / TikTok Safe Area</div>
<div class="mock-right-buttons">
<div class="mock-btn">❤️</div>
<div class="mock-btn">💬</div>
<div class="mock-btn">↗️</div>
<div class="mock-disc">💿</div>
</div>
<div class="mock-bottom-bar">
<div class="mock-channel">@DeinChannel</div>
<div class="mock-song">🎵 Song Title • Original Audio</div>
</div>
</div>
</div>
</div>
</div>
<!-- Audio Player Controls -->
<div class="player-bar">
<div class="player-main-controls">
<button id="btnPlayPause" class="player-btn-play" title="Play / Pause (Leertaste)">
<svg id="iconPlay" viewBox="0 0 24 24" width="22" height="22" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>
<svg id="iconPause" class="hidden" viewBox="0 0 24 24" width="22" height="22" fill="currentColor"><rect x="6" y="4" width="4" height="16"></rect><rect x="14" y="4" width="4" height="16"></rect></svg>
</button>
<button id="btnRewind" class="player-btn-sub" title="-5 Sekunden">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><polyline points="11 17 6 12 11 7"></polyline><polyline points="18 17 13 12 18 7"></polyline></svg>
</button>
<button id="btnForward" class="player-btn-sub" title="+5 Sekunden">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><polyline points="13 17 18 12 13 7"></polyline><polyline points="6 17 11 12 6 7"></polyline></svg>
</button>
<div class="time-display">
<span id="currentTime">00:00</span> / <span id="durationTime">00:00</span>
</div>
</div>
<!-- Waveform / Timeline Scrubber -->
<div class="timeline-container">
<input type="range" id="seekScrubber" min="0" max="100" value="0" step="0.1" class="timeline-slider">
<div class="timeline-progress-bar" id="timelineProgressBar"></div>
</div>
<div class="player-extra-controls">
<button id="btnLoop" class="player-btn-sub active" title="Audio-Schleife an/aus">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><polyline points="17 1 21 5 17 9"></polyline><path d="M3 11V9a4 4 0 0 1 4-4h14"></path><polyline points="7 23 3 19 7 15"></polyline><path d="M21 13v2a4 4 0 0 1-4 4H3"></path></svg>
</button>
<div class="volume-control">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon><path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path></svg>
<input type="range" id="volumeSlider" min="0" max="1" step="0.05" value="0.9" class="volume-slider">
</div>
</div>
</div>
</section>
<!-- Right: Inspector & Parameter Controls -->
<aside class="controls-sidebar">
<!-- Navigation Tabs -->
<nav class="sidebar-tabs">
<button class="tab-btn active" data-tab="tab-media">📁 Media</button>
<button class="tab-btn" data-tab="tab-shape">📐 Form</button>
<button class="tab-btn" data-tab="tab-spectrum">📊 Spektrum</button>
<button class="tab-btn" data-tab="tab-fx">✨ FX & 3D</button>
<button class="tab-btn" data-tab="tab-colors">🎨 Farben & Glow</button>
<button class="tab-btn" data-tab="tab-text">📝 Text</button>
<button class="tab-btn" data-tab="tab-export">🚀 Export</button>
</nav>
<div class="sidebar-content">
<!-- TAB 1: MEDIA -->
<div class="tab-panel active" id="tab-media">
<div class="panel-section">
<h3 class="section-title">1. Audio-Datei (Song)</h3>
<div class="dropzone" id="audioDropzone">
<input type="file" id="audioFileInput" accept="audio/*,.wav,.mp3,.flac,.m4a,.ogg" class="file-input-hidden">
<div class="dropzone-content">
<svg viewBox="0 0 24 24" width="32" height="32" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18V5l12-2v13"></path><circle cx="6" cy="18" r="3"></circle><circle cx="18" cy="16" r="3"></circle></svg>
<p class="dropzone-text"><strong>WAV / MP3 / FLAC</strong> hierher ziehen</p>
<span class="dropzone-sub">oder klicken zum Auswählen (bis 200 MB)</span>
<div class="file-badge hidden" id="audioFileBadge">Kein Song geladen</div>
</div>
</div>
</div>
<div class="panel-section">
<div class="section-header-with-toggle">
<h3 class="section-title">2. Cover-Art / Logo</h3>
<label class="switch-toggle" title="Cover-Artwork komplett deaktivieren (für reine Wellenformen/No-Cover Visuals)">
<input type="checkbox" id="showCover" checked>
<span class="switch-slider"></span>
</label>
</div>
<div id="coverUploadContainer">
<div class="dropzone" id="imageDropzone">
<input type="file" id="imageFileInput" accept="image/*,.png,.jpg,.jpeg,.webp" class="file-input-hidden">
<div class="dropzone-content">
<svg viewBox="0 0 24 24" width="32" height="32" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg>
<p class="dropzone-text"><strong>Cover-Bild / Logo</strong> hierher ziehen</p>
<span class="dropzone-sub">PNG / JPG (wird zentriert maskiert)</span>
<div class="file-badge hidden" id="imageFileBadge">Standard-Cover</div>
</div>
</div>
</div>
</div>
<div class="panel-section">
<h3 class="section-title">3. Track-Metadaten</h3>
<div class="form-group">
<label for="trackTitle">Song-Titel</label>
<input type="text" id="trackTitle" placeholder="z. B. Du bist mein Käse" value="Dein Songtitel">
</div>
<div class="form-group">
<label for="trackArtist">Interpret / Artist</label>
<input type="text" id="trackArtist" placeholder="z. B. Jannik" value="Artist Name">
</div>
</div>
</div>
<!-- TAB 2: FORM & TOPOLOGIE -->
<div class="tab-panel" id="tab-shape">
<div class="panel-section">
<h3 class="section-title">Visualizer Form & Topologie</h3>
<div class="shape-grid-picker">
<label class="shape-card">
<input type="radio" name="shapeType" value="circle" checked>
<div class="shape-card-inner">
<span class="shape-icon">⭕</span>
<span class="shape-label">Kreis</span>
</div>
</label>
<label class="shape-card">
<input type="radio" name="shapeType" value="linear">
<div class="shape-card-inner">
<span class="shape-icon">➖</span>
<span class="shape-label">Linear</span>
</div>
</label>
<label class="shape-card">
<input type="radio" name="shapeType" value="hexagon">
<div class="shape-card-inner">
<span class="shape-icon">⬡</span>
<span class="shape-label">Hexagon</span>
</div>
</label>
<label class="shape-card">
<input type="radio" name="shapeType" value="diamond">
<div class="shape-card-inner">
<span class="shape-icon">💎</span>
<span class="shape-label">Diamond</span>
</div>
</label>
<label class="shape-card">
<input type="radio" name="shapeType" value="triangle">
<div class="shape-card-inner">
<span class="shape-icon">🔺</span>
<span class="shape-label">Dreieck</span>
</div>
</label>
<label class="shape-card">
<input type="radio" name="shapeType" value="octagon">
<div class="shape-card-inner">
<span class="shape-icon">🛑</span>
<span class="shape-label">Achteck</span>
</div>
</label>
<label class="shape-card">
<input type="radio" name="shapeType" value="oscilloscope">
<div class="shape-card-inner">
<span class="shape-icon">〰️</span>
<span class="shape-label">Oszilloskop</span>
</div>
</label>
<label class="shape-card">
<input type="radio" name="shapeType" value="tunnel">
<div class="shape-card-inner">
<span class="shape-icon">🌀</span>
<span class="shape-label">3D Tunnel</span>
</div>
</label>
</div>
</div>
<div class="panel-section">
<h3 class="section-title">Größe & Bass-Pulse</h3>
<div class="control-row">
<label for="circleRadius">Größe / Radius</label>
<div class="range-group">
<input type="range" id="circleRadius" min="40" max="350" value="150" step="1">
<span class="range-value" id="valCircleRadius">150px</span>
</div>
</div>
<div class="control-row">
<label for="pulseIntensity">Bass-Pulse Stärke</label>
<div class="range-group">
<input type="range" id="pulseIntensity" min="0" max="1" value="0.45" step="0.01">
<span class="range-value" id="valPulseIntensity">45%</span>
</div>
</div>
<div class="control-row">
<label for="pulseDecay">Pulse Glättung (Decay)</label>
<div class="range-group">
<input type="range" id="pulseDecay" min="0.1" max="0.95" value="0.8" step="0.01">
<span class="range-value" id="valPulseDecay">80%</span>
</div>
</div>
</div>
<div class="panel-section">
<div class="section-header-with-toggle">
<h3 class="section-title">Rand & Rahmen</h3>
<label class="switch-toggle">
<input type="checkbox" id="showBorder" checked>
<span class="switch-slider"></span>
</label>
</div>
<div id="borderOptionsContainer">
<div class="control-row">
<label for="borderWidth">Rand-Dicke</label>
<div class="range-group">
<input type="range" id="borderWidth" min="1" max="30" value="6" step="1">
<span class="range-value" id="valBorderWidth">6px</span>
</div>
</div>
<div class="control-row">
<label for="borderColor">Rand-Farbe</label>
<input type="color" id="borderColor" value="#ffffff" class="color-picker-input">
</div>
</div>
</div>
<div class="panel-section">
<div class="section-header-with-toggle">
<h3 class="section-title">Fortschritts-Ring (0-360°)</h3>
<label class="switch-toggle">
<input type="checkbox" id="showProgressRing" checked>
<span class="switch-slider"></span>
</label>
</div>
<div id="progressRingOptionsContainer">
<div class="control-row">
<label for="progressRingColor">Ring-Farbe</label>
<input type="color" id="progressRingColor" value="#00f0ff" class="color-picker-input">
</div>
<div class="control-row">
<label for="progressRingWidth">Ring-Dicke</label>
<div class="range-group">
<input type="range" id="progressRingWidth" min="2" max="20" value="6" step="1">
<span class="range-value" id="valProgressRingWidth">6px</span>
</div>
</div>
</div>
</div>
<div class="panel-section">
<h3 class="section-title">Rotation & Drehung</h3>
<div class="control-row">
<label for="rotationSpeed">Vinyl-Drehung (Speed)</label>
<div class="range-group">
<input type="range" id="rotationSpeed" min="0" max="20" value="3" step="0.5">
<span class="range-value" id="valRotationSpeed">3 RPM</span>
</div>
</div>
<div class="toggle-row">
<label for="beatSpinImpulse">Beat-Drehimpuls bei Drops</label>
<input type="checkbox" id="beatSpinImpulse" checked>
</div>
</div>
</div>
<!-- TAB 3: SPECTRUM -->
<div class="tab-panel" id="tab-spectrum">
<div class="panel-section">
<div class="section-header-with-toggle">
<h3 class="section-title">Audio-Spektrum</h3>
<label class="switch-toggle" title="Spektrum ein-/ausschalten">
<input type="checkbox" id="showSpectrum" checked>
<span class="switch-slider"></span>
</label>
</div>
<div class="radio-pill-group">
<label class="radio-pill">
<input type="radio" name="spectrumMode" value="radial_bars" checked>
<span>📊 Balken</span>
</label>
<label class="radio-pill">
<input type="radio" name="spectrumMode" value="smooth_wave">
<span>〰️ Welle</span>
</label>
<label class="radio-pill">
<input type="radio" name="spectrumMode" value="floating_dots">
<span>✨ Punkte</span>
</label>
<label class="radio-pill">
<input type="radio" name="spectrumMode" value="dual_ring">
<span>⭕ Dual Ring</span>
</label>
<label class="radio-pill">
<input type="radio" name="spectrumMode" value="block_matrix">
<span>🧱 Block EQ</span>
</label>
</div>
</div>
<!-- Linear-spezifische Ausrichtung (sichtbar wenn Linear gewählt) -->
<div class="panel-section" id="linearAlignmentSection">
<h3 class="section-title">Lineare Horizont-Ausrichtung</h3>
<select id="linearAlignment" class="select-input">
<option value="center_mirrored">Symmetrischer Horizont (Oben & Unten)</option>
<option value="bottom_up">Boden-Equalizer (Von Unten Aufsteigend)</option>
<option value="top_down">Decken-Equalizer (Von Oben Herabfallend)</option>
<option value="floating_wave">Frei schwebende Center-Welle</option>
</select>
</div>
<div class="panel-section">
<h3 class="section-title">Geometrie & Dichte</h3>
<div class="control-row">
<label for="barCount">Anzahl Balken / Punkte</label>
<div class="range-group">
<input type="range" id="barCount" min="24" max="256" value="96" step="8">
<span class="range-value" id="valBarCount">96</span>
</div>
</div>
<div class="control-row">
<label for="spectrumMaxHeight">Maximale Höhe</label>
<div class="range-group">
<input type="range" id="spectrumMaxHeight" min="20" max="400" value="130" step="5">
<span class="range-value" id="valSpectrumMaxHeight">130px</span>
</div>
</div>
<div class="control-row">
<label for="barWidth">Balkenbreite</label>
<div class="range-group">
<input type="range" id="barWidth" min="1" max="25" value="4" step="0.5">
<span class="range-value" id="valBarWidth">4px</span>
</div>
</div>
<div class="control-row">
<label for="barSpacing">Abstand vom Zentrum</label>
<div class="range-group">
<input type="range" id="barSpacing" min="0" max="100" value="12" step="1">
<span class="range-value" id="valBarSpacing">12px</span>
</div>
</div>
<div class="control-row">
<label for="barCornerRadius">Ecken-Abrundung</label>
<div class="range-group">
<input type="range" id="barCornerRadius" min="0" max="10" value="2" step="0.5">
<span class="range-value" id="valBarCornerRadius">2px</span>
</div>
</div>
</div>
<div class="panel-section">
<h3 class="section-title">Frequenz-Analyse</h3>
<div class="control-row">
<label for="freqSensitivity">Empfindlichkeit</label>
<div class="range-group">
<input type="range" id="freqSensitivity" min="0.5" max="3.5" value="1.3" step="0.1">
<span class="range-value" id="valFreqSensitivity">1.3x</span>
</div>
</div>
<div class="control-row">
<label for="freqFocus">Frequenz-Fokus</label>
<select id="freqFocus" class="select-input">
<option value="balanced">Ausgewogen (Sub bis Höhen)</option>
<option value="bass_heavy">Basslastig (EDM / Trap)</option>
<option value="vocal_mid">Mitten & Gesang (Pop / Rock)</option>
</select>
</div>
<div class="toggle-row">
<label for="mirrorSpectrum">Spektrum spiegeln (Symmetrisch)</label>
<input type="checkbox" id="mirrorSpectrum" checked>
</div>
</div>
</div>
<!-- TAB 4: FX & 3D -->
<div class="tab-panel" id="tab-fx">
<div class="panel-section">
<div class="section-header-with-toggle">
<h3 class="section-title">Partikel-System</h3>
<label class="switch-toggle">
<input type="checkbox" id="enableParticles" checked>
<span class="switch-slider"></span>
</label>
</div>
<div id="particleOptionsContainer">
<div class="control-row">
<label for="particleType">Partikel-Typ</label>
<select id="particleType" class="select-input">
<option value="starfield">3D Warp Starfield (Kameraflug)</option>
<option value="dust">Schwebender Staub (Floating Dust)</option>
<option value="sparks">Audio-Funken (Reactive Sparks)</option>
</select>
</div>
<div class="control-row">
<label for="particleCount">Partikel-Anzahl</label>
<div class="range-group">
<input type="range" id="particleCount" min="20" max="300" value="100" step="10">
<span class="range-value" id="valParticleCount">100</span>
</div>
</div>
<div class="control-row">
<label for="particleSpeed">Geschwindigkeit</label>
<div class="range-group">
<input type="range" id="particleSpeed" min="0.2" max="4.0" value="1.0" step="0.1">
<span class="range-value" id="valParticleSpeed">1.0x</span>
</div>
</div>
<div class="control-row">
<label for="particleWarp">Warp-Explosion bei Drops</label>
<div class="range-group">
<input type="range" id="particleWarp" min="0" max="6.0" value="2.5" step="0.2">
<span class="range-value" id="valParticleWarp">2.5x</span>
</div>
</div>
</div>
</div>
<div class="panel-section">
<div class="section-header-with-toggle">
<h3 class="section-title">3D Synthwave Grid Floor</h3>
<label class="switch-toggle" title="Retro-Perspektiven-Gitterboden aktivieren">
<input type="checkbox" id="enableGrid">
<span class="switch-slider"></span>
</label>
</div>
<div id="gridOptionsContainer">
<div class="control-row">
<label for="colorGrid">Grid-Farbe</label>
<input type="color" id="colorGrid" value="#ff007f" class="color-picker-input">
</div>
<div class="control-row">
<label for="gridPerspective">Gitter-Perspektive (Horizont)</label>
<div class="range-group">
<input type="range" id="gridPerspective" min="0.3" max="0.9" value="0.65" step="0.05">
<span class="range-value" id="valGridPerspective">65%</span>
</div>
</div>
<div class="control-row">
<label for="gridAudioReactive">Audio-Reaktivität</label>
<div class="range-group">
<input type="range" id="gridAudioReactive" min="0" max="1.0" value="0.5" step="0.05">
<span class="range-value" id="valGridAudioReactive">50%</span>
</div>
</div>
</div>
</div>
<div class="panel-section">
<h3 class="section-title">Kamera & Beat-Effekte</h3>
<div class="toggle-row">
<label for="enableShake">Bass-Shake (Kamera-Erschütterung)</label>
<input type="checkbox" id="enableShake" checked>
</div>
<div class="control-row">
<label for="camShakeIntensity">Shake-Intensität</label>
<div class="range-group">
<input type="range" id="camShakeIntensity" min="0" max="1.0" value="0.35" step="0.05">
<span class="range-value" id="valCamShakeIntensity">35%</span>
</div>
</div>
<div class="toggle-row">
<label for="enableGlitch">RGB-Split / Glitch bei Drops</label>
<input type="checkbox" id="enableGlitch" checked>
</div>
<div class="control-row">
<label for="rgbSplitIntensity">Glitch-Stärke</label>
<div class="range-group">
<input type="range" id="rgbSplitIntensity" min="0" max="1.0" value="0.25" step="0.05">
<span class="range-value" id="valRgbSplitIntensity">25%</span>
</div>
</div>
<div class="toggle-row">
<label for="beatFlash">Beat-Flash (Strobe-Effekt bei Kicks)</label>
<input type="checkbox" id="beatFlash">
</div>
<div class="toggle-row">
<label for="enableBassZoom">Kamera Bass-Zoom (Pulsierender Viewport)</label>
<input type="checkbox" id="enableBassZoom" checked>
</div>
</div>
</div>
<!-- TAB 5: COLORS & NEON GLOW -->
<div class="tab-panel" id="tab-colors">
<div class="panel-section">
<h3 class="section-title">Kuratierte Farbpaletten</h3>
<div class="palette-quick-grid">
<button class="palette-chip" data-p1="#00f0ff" data-p2="#ff007f" data-p3="#7000ff" title="Cyberpunk Neon">
<span class="palette-preview" style="background: linear-gradient(135deg, #00f0ff, #ff007f, #7000ff);"></span>
<span>Cyberpunk</span>
</button>
<button class="palette-chip" data-p1="#ff7700" data-p2="#ff0055" data-p3="#7900ff" title="Synthwave Sunset">
<span class="palette-preview" style="background: linear-gradient(135deg, #ff7700, #ff0055, #7900ff);"></span>
<span>Synthwave</span>
</button>
<button class="palette-chip" data-p1="#00ff88" data-p2="#00e5ff" data-p3="#0055ff" title="Toxic Emerald">
<span class="palette-preview" style="background: linear-gradient(135deg, #00ff88, #00e5ff, #0055ff);"></span>
<span>Emerald</span>
</button>
<button class="palette-chip" data-p1="#00e1ff" data-p2="#ffffff" data-p3="#0051ff" title="Ice Blade">
<span class="palette-preview" style="background: linear-gradient(135deg, #00e1ff, #ffffff, #0051ff);"></span>
<span>Ice Blade</span>
</button>
<button class="palette-chip" data-p1="#ffcc00" data-p2="#ff3300" data-p3="#880000" title="Fire Amber">
<span class="palette-preview" style="background: linear-gradient(135deg, #ffcc00, #ff3300, #880000);"></span>
<span>Fire Amber</span>
</button>
<button class="palette-chip" data-p1="#bf00ff" data-p2="#e066ff" data-p3="#3b0066" title="Royal Violet">
<span class="palette-preview" style="background: linear-gradient(135deg, #bf00ff, #e066ff, #3b0066);"></span>
<span>Royal Violet</span>
</button>
<button class="palette-chip" data-p1="#ffffff" data-p2="#aaaaaa" data-p3="#555555" title="Monochrome Clean">
<span class="palette-preview" style="background: linear-gradient(135deg, #ffffff, #aaaaaa, #555555);"></span>
<span>Monochrome</span>
</button>
</div>
</div>
<div class="panel-section">
<h3 class="section-title">Farbverlaufs-Editor</h3>
<div class="control-row">
<label for="colorMode">Farb-Modus</label>
<select id="colorMode" class="select-input">
<option value="gradient_2">2-Farben Verlauf</option>
<option value="gradient_3">3-Farben Verlauf</option>
<option value="rainbow">Regenbogen / Chroma Beat-Loop</option>
<option value="solid">Einfarbig (Solid)</option>
</select>
</div>
<div class="color-picker-row">
<div class="color-picker-item">
<label for="colorGrad1">Farbe 1</label>
<input type="color" id="colorGrad1" value="#00f0ff" class="color-picker-input">
</div>
<div class="color-picker-item" id="colorGrad2Item">
<label for="colorGrad2">Farbe 2</label>
<input type="color" id="colorGrad2" value="#ff007f" class="color-picker-input">
</div>
<div class="color-picker-item" id="colorGrad3Item">
<label for="colorGrad3">Farbe 3</label>
<input type="color" id="colorGrad3" value="#7000ff" class="color-picker-input">
</div>
<div class="color-picker-item">
<label for="colorParticle">Partikel</label>
<input type="color" id="colorParticle" value="#ffffff" class="color-picker-input">
</div>
</div>
<div class="control-row">
<label for="gradientStyle">Verlauf-Geometrie</label>
<select id="gradientStyle" class="select-input">
<option value="angular">360° Winkelverlauf (Radial Conic)</option>
<option value="radial">Zentrum zu Rand (Linear Radial)</option>
<option value="linear_h">Horizontal (Links nach Rechts)</option>
<option value="linear_v">Vertikal (Oben nach Unten)</option>
</select>
</div>
</div>
<div class="panel-section">
<div class="section-header-with-toggle">
<h3 class="section-title">Neon Bloom & Glow Engine</h3>
<label class="switch-toggle" title="Neon-Glow aktivieren">
<input type="checkbox" id="enableGlow" checked>
<span class="switch-slider"></span>
</label>
</div>
<div id="glowOptionsContainer">
<div class="control-row">
<label for="glowIntensity">Glow-Leuchtkraft</label>
<div class="range-group">
<input type="range" id="glowIntensity" min="0" max="1.0" value="0.75" step="0.05">
<span class="range-value" id="valGlowIntensity">75%</span>
</div>
</div>
<div class="control-row">
<label for="glowBlur">Glow-Radius (Bloom Spread)</label>
<div class="range-group">
<input type="range" id="glowBlur" min="0" max="60" value="25" step="2">
<span class="range-value" id="valGlowBlur">25px</span>
</div>
</div>
<div class="toggle-row">
<label for="laserCore">Doppelter Laser-Kern (Laser Core Line)</label>
<input type="checkbox" id="laserCore" checked>
</div>
</div>
</div>
<div class="panel-section">
<h3 class="section-title">Hintergrund-Modus</h3>
<select id="backgroundMode" class="select-input">
<option value="transparent">100% Transparent (Alpha-Kanal für DaVinci Resolve)</option>
<option value="blurred_cover">Unscharfes Cover-Artwork im Hintergrund</option>
<option value="dark_vignette">Dunkle Obsidian-Vignette</option>
<option value="solid_black">Reines Schwarz (#000000)</option>
</select>
</div>
</div>
<!-- TAB 6: TYPOGRAPHY -->
<div class="tab-panel" id="tab-text">
<div class="panel-section">
<div class="section-header-with-toggle">
<h3 class="section-title">Song-Info Overlay</h3>
<label class="switch-toggle" title="Text-Overlay aktivieren">
<input type="checkbox" id="showTextOverlay" checked>
<span class="switch-slider"></span>
</label>
</div>
<div id="textOptionsContainer">
<div class="control-row">
<label for="fontFamily">Schriftart</label>
<select id="fontFamily" class="select-input">
<option value="'Outfit', sans-serif">Outfit (Modern Clean)</option>
<option value="'Orbitron', sans-serif">Orbitron (Cyber / EDM)</option>
<option value="'Syncopate', sans-serif">Syncopate (Futuristic Wide)</option>
<option value="'Montserrat', sans-serif">Montserrat (Bold Studio)</option>
<option value="'Inter', sans-serif">Inter (Minimalist)</option>
<option value="'Cinzel', serif">Cinzel (Cinematic Serif)</option>
</select>
</div>
<div class="control-row">
<label for="textPosition">Position</label>
<select id="textPosition" class="select-input">
<option value="below_circle">Direkt unter der Form</option>
<option value="bottom_center">Unten Zentriert</option>
<option value="top_center">Oben Zentriert</option>
</select>
</div>
<div class="control-row">
<label for="titleFontSize">Titel Schriftgröße</label>
<div class="range-group">
<input type="range" id="titleFontSize" min="16" max="72" value="38" step="2">
<span class="range-value" id="valTitleFontSize">38px</span>
</div>
</div>
<div class="control-row">
<label for="artistFontSize">Artist Schriftgröße</label>
<div class="range-group">
<input type="range" id="artistFontSize" min="12" max="48" value="22" step="2">
<span class="range-value" id="valArtistFontSize">22px</span>
</div>
</div>
<div class="toggle-row">
<label for="textPulseWithBeat">Text pulsiert im Beat</label>
<input type="checkbox" id="textPulseWithBeat" checked>
</div>
<div class="toggle-row">
<label for="showTimecode">Live-Timecode einblenden</label>
<input type="checkbox" id="showTimecode" checked>
</div>
<div class="toggle-row">
<label for="showProgressBar">Linearer Fortschrittsbalken</label>
<input type="checkbox" id="showProgressBar">
</div>
</div>
</div>
</div>
<!-- TAB 7: EXPORT -->
<div class="tab-panel" id="tab-export">
<div class="panel-section">
<h3 class="section-title">DaVinci Resolve Export-Einstellungen</h3>
<div class="form-group">
<label for="exportFormat">Video-Format & Transparenz</label>
<select id="exportFormat" class="select-input">
<option value="prores">🎬 QuickTime ProRes 4444 (.mov) — Echter Alpha-Kanal für DaVinci (Beste Qualität)</option>
<option value="webm">🌐 WebM VP9 (.webm) — Echter Alpha-Kanal (Kompakte Datei)</option>
<option value="mp4">📹 MP4 Video (.mp4) — H.264 (Mit gewähltem Hintergrund)</option>
</select>
</div>
<div class="form-row-2">
<div class="form-group">
<label for="exportResolution">Auflösung</label>
<select id="exportResolution" class="select-input">
<option value="1080p">1080p Full HD</option>
<option value="4k">4K Ultra HD (2160p)</option>
<option value="720p">720p HD (Schneller Test)</option>
</select>
</div>
<div class="form-group">
<label for="exportFps">Bildrate (FPS)</label>
<select id="exportFps" class="select-input">
<option value="60">60 FPS (Super Flüssig)</option>
<option value="30">30 FPS (Standard)</option>
</select>
</div>
</div>
<div class="export-banner">
<div class="export-banner-icon">💡</div>
<div class="export-banner-text">
<strong>Workflow in DaVinci Resolve:</strong><br>
Ziehe die exportierte <code>.mov</code> Datei einfach auf eine Videospur (V2) über dein Hintergrund-Footage (V1). Alle Elemente sind transparent freigestellt!
</div>
</div>
<!-- Export Button -->
<button id="btnStartExport" class="btn btn-primary btn-large btn-glow">
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
Video jetzt rendern & downloaden
</button>
<!-- Progress Modal / Bar -->
<div class="export-progress-card hidden" id="exportProgressCard">
<div class="progress-header">
<span id="exportStatusText">Rendert Video...</span>
<span id="exportPercent">0%</span>
</div>
<div class="progress-bar-track">
<div class="progress-bar-fill" id="exportProgressBarFill"></div>
</div>
<div class="progress-meta">
<span id="exportFpsLive">FPS: --</span>
<span id="exportEta">Verbleibend: --</span>
</div>
<button id="btnCancelExport" class="btn btn-secondary btn-sm">Abbrechen</button>
</div>
</div>
<!-- Preset Manager Section -->
<div class="panel-section">
<h3 class="section-title">Presets verwalten</h3>
<div class="preset-manager-controls">
<button id="btnSavePreset" class="btn btn-secondary btn-sm">💾 Aktuelles Preset speichern</button>
<button id="btnExportPresetJson" class="btn btn-secondary btn-sm">📤 Export JSON</button>
<label class="btn btn-secondary btn-sm">
📥 Import JSON
<input type="file" id="importPresetInput" accept=".json" class="file-input-hidden">
</label>
</div>
</div>
</div>
</div>
</aside>
</main>
</div>
<script src="presets.js"></script>
<script src="app.js"></script>
</body>
</html>