explain me what this app doing? <html><head><base href="."><title>Lyrical Storybook Creator</title>
<style>
/* Logo Styling */
.header {
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
}

.logo {
  margin-bottom: 1rem;
  animation: fadeIn 1s ease-in-out;
}

.logo svg {
  filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));
  transition: transform 0.3s ease;
}

.logo svg:hover {
  transform: scale(1.05);
}

@keyframes glow {
  0%, 100% { filter: drop-shadow(0 0 5px var(--primary-light)); }
  50% { filter: drop-shadow(0 0 15px var(--primary)); }
}

@keyframes fadeIn {
  from { opacity: 0; transform: scale(0.8); }
  to { opacity: 1; transform: scale(1); }
}

/* Responsive Adjustments for Logo */
@media (max-width: 1200px) {
  .logo svg {
    width: 70px;
    height: 70px;
  }
}

@media (max-width: 768px) {
  .logo svg {
    width: 60px;
    height: 60px;
  }
}

@media (max-width: 480px) {
  .logo svg {
    width: 50px;
    height: 50px;
  }
}
@import url('https://fonts.googleapis.com/css2?family=Crimson+Text:wght@400;700&family=Playfair+Display:wght@400;700&family=Lora:ital@0;1&family=Dancing+Script&family=Roboto:wght@400;700&family=Comic+Neue&family=Montserrat:wght@400;700&family=Old+Standard+TT:wght@400;700&family=Cinzel:wght@400;700&family=Alex+Brush&family=Orbitron:wght@400;700&family=Baskerville&display=swap');
@import url('https://fonts.googleapis.com/css2?family=UnifrakturMaguntia&family=MedievalSharp&family=Pacifico&family=Luminari&family=Audiowide&family=Inter&family=Cormorant+Garamond&display=swap');

/* Update color variables for better contrast and accessibility */
:root {
  /* Primary palette with guaranteed contrast ratios */
  --primary: #9f7aea;
  --primary-light: #d6bcfa; 
  --primary-dark: #6b46c1;
  
  /* Secondary palette */
  --secondary: #4fd1c5;
  --secondary-light: #9decf9;
  --secondary-dark: #319795;
  
  /* Background colors */
  --bg-primary: #1a202c;
  --bg-secondary: #2d3748;
  --bg-surface: rgba(255, 255, 255, 0.08);
  
  /* Text colors with high contrast */
  --text-primary: #ffffff;
  --text-secondary: #e2e8f0;
  --text-muted: #a0aec0;
  
  /* Accent colors */
  --accent: #f6ad55;
  --accent-light: #fbd38d;
  --accent-dark: #dd6b20;
  
  /* Interactive element colors */
  --hover: rgba(255, 255, 255, 0.12);
  --active: rgba(255, 255, 255, 0.16);
  --focus: rgba(159, 122, 234, 0.6);
  
  /* Gradient variations */
  --gradient-start: var(--primary);
  --gradient-end: var(--secondary);
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: 'Lora', serif;
  color: var(--text-primary);
  background: linear-gradient(135deg, var(--bg-primary) 0%, var(--bg-secondary) 100%);
  line-height: 1.8;
}

body::before {
  content: '';
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  opacity: 0.1;
  background-image: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M50 25L25 50L50 75L75 50L50 25Z' fill='%239f7aea' opacity='0.3'/%3E%3Cpath d='M75 25L50 0L25 25L50 50L75 25Z' fill='%234fd1c5' opacity='0.3'/%3E%3Cpath d='M25 75L50 100L75 75L50 50L25 75Z' fill='%234fd1c5' opacity='0.3'/%3E%3C/svg%3E");
  background-repeat: repeat;
}

.app {
  position: relative;
  z-index: 1;
  max-width: 1400px;
  padding: 3rem; 
}

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

.header h1 {
  font-family: 'Playfair Display', serif;
  font-size: 4rem; 
  color: var(--text-primary);
  text-shadow: 0 2px 4px rgba(0,0,0,0.3);
  background: linear-gradient(45deg, var(--gradient-start), var(--gradient-end));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  margin-bottom: 2rem;
  letter-spacing: -0.5px;
}

.header p {
  font-family: 'Dancing Script', cursive;
  font-size: 1.5rem;
  color: var(--text-secondary);
  opacity: 0.9;
}

.error-message {
  display: none;
  background: #e53e3e;
  color: var(--text-primary);
  border: 1px solid #c53030;
  padding: 1rem;
  border-radius: 0.5rem;
  margin-bottom: 1rem;
}

.project-creation {
  background: var(--bg-surface);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 1.5rem;
  padding: 3rem;
  margin-bottom: 4rem;
  box-shadow: 0 4px 20px rgba(0,0,0,0.2);
}

.input-group {
  margin-bottom: 2rem; 
}

.input-group label {
  display: block;
  margin-bottom: 0.5rem;
  font-weight: 500;
}

textarea, input, select {
  background: var(--bg-surface);
  border: 2px solid rgba(255,255,255,0.2);
  border-radius: 1rem;
  padding: 1.5rem; 
  font-family: 'Lora', serif;
  font-size: 1rem;
  color: var(--text-primary);
  transition: all 0.3s ease;
}

textarea::placeholder,
input::placeholder {
  color: var(--text-muted);
}

textarea#lyrics {
  min-height: 300px;
  width: 100%;
  line-height: 1.8;
}

select {
  width: 100%;
  padding: 0.75rem;
  cursor: pointer;
  color: var(--text-primary);
}

select option {
  background: var(--bg-secondary);
  color: var(--text-primary);
  padding: 1rem;
}

select:hover {
  background: #3a3f50;
}

select:focus {
  outline: none;
  border-color: var(--focus);
  background: #3a3f50;
}

textarea:focus, input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--focus);
}

.style-controls {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem; 
  padding: 2rem;
  margin: 2rem 0;
  background: var(--bg-surface);
  border-radius: 0.5rem;
}

.storybook-container {
  background: var(--bg-surface);
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: 1.5rem;
  padding: 4rem; 
  margin-top: 3rem;
  box-shadow: 0 8px 32px rgba(0,0,0,0.2);
  position: relative;
  overflow: hidden;
}

.storybook-page {
  display: grid; 
  grid-template-columns: 1fr;
  gap: 2rem;
  max-width: 1000px;
  margin: 0 auto;
}

.page-illustration {
  min-height: 400px;
  border-radius: 1rem;
  overflow: hidden;
}

.page-illustration img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.3s ease;
}

.page-illustration img:hover {
  transform: scale(1.02);
}

.page-text {
  font-family: 'Lora', serif;
  font-size: 1.1rem;
  line-height: 1.8;
  color: var(--text-primary);
  padding: 2rem;
  background: var(--bg-surface);
}

.page-controls {
  display: flex; 
  justify-content: center;
  align-items: center;
  gap: 2rem;
  margin-top: 3rem;
}

.page-btn {
  background: linear-gradient(45deg, var(--primary-dark), var(--primary));
  color: var(--text-primary);
  border: none;
  padding: 0.75rem 1.5rem;
  border-radius: 0.75rem;
  font-family: 'Lora', serif;
  font-weight: 600;
  box-shadow: 0 4px 12px rgba(0,0,0,0.1);
  transition: all 0.3s ease;
}

.page-btn:hover {
  transform: translateY(-3px); 
}

@keyframes pageFlip {
  from { transform: rotateY(0deg); }
  to { transform: rotateY(360deg); }
}

.page-transition {
  animation: pageFlip 0.6s ease;
}

/* Add loading animation */
@keyframes shimmer {
  0% { background-position: -1000px 0; }
  100% { background-position: 1000px 0; }
}

.loading {
  background: linear-gradient(90deg, 
    var(--bg-surface) 0%, 
    var(--bg-surface-hover) 50%, 
    var(--bg-surface) 100%);
  background-size: 1000px 100%;
  animation: shimmer 2s infinite linear;
}

/* Smooth transitions */
.fade-enter {
  opacity: 0;
  transform: translateY(20px);
}

.fade-enter-active {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 0.3s ease, transform 0.3s ease;
}

/* Responsive adjustments */
@media (max-width: 1200px) {
  .app {
    padding: 2rem;
  }
  
  .style-controls {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 768px) {
  .header h1 {
    font-size: 3rem;
  }

  .style-controls {
    grid-template-columns: 1fr;
  }

  .controls {
    flex-direction: column;
  }

  .btn {
    width: 100%;
  }
}

@media (max-width: 480px) {
  .app {
    padding: 1rem;
  }
  
  .header h1 {
    font-size: 2.5rem;
  }
  
  .project-creation {
    padding: 1.5rem;
  }
}

.controls {
  display: flex;
  gap: 1rem;
  margin-top: 2rem;
  justify-content: center;
}

/* Improved button styling */
.btn {
  padding: 1.2rem 2.4rem;
  font-size: 1.1rem;
}

.btn:hover {
  transform: translateY(-3px);
  box-shadow: 0 6px 15px rgba(0,0,0,0.2);
}

.btn-primary {
  background: linear-gradient(45deg, var(--primary-dark), var(--primary));
  color: var(--text-primary);
}

.btn-secondary {
  background: var(--bg-surface);
  border: 2px solid var(--secondary);
  color: var(--text-primary);
}

.btn-secondary {
  margin-left: 1rem;
}

#resetBtn {
  background: var(--bg-surface);
  border: 2px solid var(--accent);
  color: var(--accent);
}

#resetBtn:hover {
  background: var(--accent-light);
  border-color: var(--gradient-end);
  color: var(--gradient-end);
}

.btn:hover {
  transform: translateY(-2px);
  opacity: 0.9;
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn.generating {
  position: relative;
}

.btn.generating:after {
  content: '';
  position: absolute;
  width: 1rem;
  height: 1rem;
  border: 2px solid #fff;
  border-radius: 50%;
  border-left-color: transparent;
  margin-left: 0.5rem;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}
</style>
<meta http-equiv="Cross-Origin-Opener-Policy" content="same-origin">
<meta http-equiv="Cross-Origin-Embedder-Policy" content="require-corp">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
<script>
class PollinationsAPI {
  static retryDelay = 300;
  static maxRetries = 3;
  static requestQueue = [];
  static isProcessingQueue = false;
  static rateLimitDelay = 1000; // 1 second between requests

  static async fetchWithRetry(url, options = {}, retries = this.maxRetries) {
    try {
      const response = await fetch(url, options);
      
      if (response.status === 429) {
        throw new Error('RATE_LIMIT');
      }
      
      if (!response.ok) {
        throw new Error('FETCH_ERROR');
      }
      
      return response;
    } catch (error) {
      if (retries === 0) throw error;
      
      if (error.message === 'RATE_LIMIT') {
        await new Promise(res => setTimeout(res, this.rateLimitDelay));
      } else {
        await new Promise(res => setTimeout(res, this.retryDelay * (this.maxRetries - retries + 1)));
      }
      
      return this.fetchWithRetry(url, options, retries - 1);
    }
  }

  static async queueRequest(requestFn) {
    return new Promise((resolve, reject) => {
      this.requestQueue.push({
        requestFn,
        resolve,
        reject
      });
      
      if (!this.isProcessingQueue) {
        this.processQueue();
      }
    });
  }

  static async processQueue() {
    if (this.requestQueue.length === 0) {
      this.isProcessingQueue = false;
      return;
    }

    this.isProcessingQueue = true;
    const {requestFn, resolve, reject} = this.requestQueue.shift();

    try {
      const result = await requestFn();
      resolve(result);
    } catch (error) {
      reject(error);
    }

    await new Promise(res => setTimeout(res, this.rateLimitDelay));
    this.processQueue();
  }

  static async generateText(prompt) {
    return this.queueRequest(async () => {
      try {
        const url = `https://text.pollinations.ai/${encodeURIComponent(prompt)}`;
        const response = await this.fetchWithRetry(url);
        return response.text();
      } catch (error) {
        if (error.message === 'RATE_LIMIT') {
          throw new Error('Rate limit exceeded. Please try again in a moment.');
        }
        throw new Error('Failed to generate text. Please try again.');
      }
    });
  }

  static async generateImage(prompt, settings = {}) {
    return this.queueRequest(async () => {
      const baseUrl = 'https://image.pollinations.ai/prompt/';
      const params = new URLSearchParams({
        width: settings.width || 1280,
        height: settings.height || 720,
        seed: settings.seed || Math.floor(Math.random() * 1000000),
        nologo: 'true',
        private: 'true'
      });
      
      const encodedPrompt = encodeURIComponent(prompt);
      const url = `${baseUrl}${encodedPrompt}?${params}`;
      
      try {
        const response = await this.fetchWithRetry(url);
        return response.url;
      } catch (error) {
        if (error.message === 'RATE_LIMIT') {
          throw new Error('Rate limit exceeded. Please try again in a moment.');
        }
        throw new Error('Failed to generate image. Please try again.');
      }
    });
  }
}

class MusicVideoCreator {
  constructor() {
    this.scenes = [];
    this.currentPage = 0;
    this.pages = [];
    this.isGenerating = false;
    this.audioFile = null;
    this.defaultSettings = {
      lyrics: '',
      theme: '',
      styleFilter: 'watercolor',
      bookLayout: 'single',
      textStyle: 'storybook'
    };

    this.selectedStyle = null;
    this.showError = this.showError.bind(this);
    this.init();
  }

  init() {
    this.applyStylesBtn = document.getElementById('applyStylesBtn');
    this.generateBtn = document.getElementById('generateBtn');
    this.exportBtn = document.getElementById('exportBtn');
    this.resetBtn = document.getElementById('resetBtn');
    this.previewArea = document.getElementById('previewArea');
    
    this.bindEvents();
  }

  bindEvents() {
    this.applyStylesBtn.addEventListener('click', () => this.applyStyles());
    this.generateBtn.addEventListener('click', () => this.generatePages());
    this.exportBtn.addEventListener('click', () => this.exportStorybook());
    this.resetBtn.addEventListener('click', () => this.resetApp());
  }

  showError(message) {
    const errorMessage = document.getElementById('errorMessage');
    errorMessage.textContent = message;
    errorMessage.style.display = 'block';
    setTimeout(() => {
      errorMessage.style.display = 'none';
    }, 5000);
  }

  showSuccess(message) {
    const errorMessage = document.getElementById('errorMessage');
    errorMessage.textContent = message;
    errorMessage.style.display = 'block';
    errorMessage.style.background = '#48bb78';
    setTimeout(() => {
      errorMessage.style.display = 'none';
    }, 3000);
  }

  async generatePages() {
    if (this.isGenerating) return;
    
    const lyrics = document.getElementById('lyrics').value;
    const theme = document.getElementById('theme').value;
    
    if (!lyrics || !theme) {
      this.showError('Please enter both lyrics and theme');
      return;
    }

    if (!this.selectedStyle) {
      this.showError('Please apply your style settings first');
      return;
    }

    this.isGenerating = true;
    this.generateBtn.classList.add('generating');
    this.generateBtn.textContent = 'Generating...';

    try {
      const segments = lyrics.split('\n\n').filter(seg => seg.trim());
      this.pages = [];
      
      for (let i = 0; i < segments.length; i++) {
        const scenePrompt = await PollinationsAPI.generateText(
          `Create a vivid, detailed description for a storybook illustration. 
           Context: These song lyrics: "${segments[i]}"
           Theme: ${theme}
           Style: ${this.selectedStyle.style}
           Consider:
           - The emotional tone and mood
           - Key symbols and metaphors
           - Color palette and lighting
           - Character expressions and poses
           - Environmental details and setting
           - Composition and focal points
           Describe the scene in rich, artistic detail.`
        );

        const imagePrompt = `${this.selectedStyle.style} illustration style, 
          masterpiece, professional storybook art, 
          highly detailed, dramatic lighting, vibrant colors, 
          ${theme}, ${scenePrompt}, 
          trending on artstation, award winning book illustration, 
          artistic masterpiece in ${this.selectedStyle.style} style`;

        const imageUrl = await PollinationsAPI.generateImage(
          imagePrompt, 
          {
            width: 1280,
            height: 720,
            seed: Math.floor(Math.random() * 1000000)
          }
        );

        const page = {
          lyrics: segments[i],
          description: scenePrompt,
          imageUrl: imageUrl,
        };
        
        this.pages.push(page);
        this.showPage(i);
      }

    } catch (error) {
      console.error('Error generating pages:', error);
      this.showError('Error generating pages: ' + error.message);
    } finally {
      this.isGenerating = false;
      this.generateBtn.classList.remove('generating');
      this.generateBtn.textContent = 'Generate Storybook';
    }
  }

  async applyStyles() {
    const style = document.getElementById('styleFilter').value;
    const layout = document.getElementById('bookLayout').value;
    const textStyle = document.getElementById('textStyle').value;

    // Store the selected styles for later use during generation
    this.selectedStyle = {
      style,
      layout,
      textStyle
    };

    // Update preview area to reflect style choices
    this.previewArea.innerHTML = `
      <div class="storybook-page" style="opacity: 0.7">
        <div class="page-illustration">
          <div style="width: 100%; height: 300px; background: var(--bg-surface); border-radius: 1rem; display: flex; align-items: center; justify-content: center;">
            <p style="color: var(--text-secondary);">Styles Applied: ${style} style with ${layout} layout</p>
          </div>
        </div>
        <div class="page-text" style="font-family: ${this.getTextStyleFont(textStyle)}">
          <p>Your selected styles have been applied. Click "Generate Storybook" to create your storybook with these styles!</p>
        </div>
      </div>
    `;

    // Enable the generate button
    this.generateBtn.disabled = false;
    
    // Show success message
    this.showSuccess('Styles applied! You can now generate your storybook.');
  }

  getTextStyleFont(style) {
    switch(style) {
      case 'storybook': 
        return '"Crimson Text", "Playfair Display", serif';
      case 'elegant': 
        return '"Playfair Display", "Cormorant Garamond", serif';
      case 'modern': 
        return '"Roboto", "Inter", sans-serif';
      case 'handwritten': 
        return '"Dancing Script", "Pacifico", cursive';
      case 'gothic': 
        return '"UnifrakturMaguntia", "MedievalSharp", fantasy';
      case 'whimsical': 
        return '"Comic Neue", "Comic Sans MS", cursive';
      case 'minimalist': 
        return '"Montserrat", "Helvetica Neue", sans-serif';
      case 'vintage': 
        return '"Old Standard TT", "Courier New", serif';
      case 'fantasy': 
        return '"Cinzel", "Luminari", fantasy';
      case 'calligraphy': 
        return '"Alex Brush", "Vivaldi", cursive';
      case 'futuristic': 
        return '"Orbitron", "Audiowide", sans-serif';
      case 'classic': 
        return '"Baskerville", "Garamond", serif';
      default: 
        return '"Lora", serif';
    }
  }

  async exportStorybook() {
    try {
      const { jsPDF } = window.jspdf;
      const doc = new jsPDF();
      
      this.exportBtn.disabled = true;
      this.exportBtn.textContent = 'Exporting...';

      for (let i = 0; i < this.pages.length; i++) {
        const page = this.pages[i];
        if (i > 0) doc.addPage();

        try {
          const img = new Image();
          await new Promise((resolve, reject) => {
            img.crossOrigin = 'Anonymous';
            img.onload = resolve;
            img.onerror = reject;
            img.src = page.imageUrl;
          });

          const canvas = document.createElement('canvas');
          canvas.width = img.width;
          canvas.height = img.height;
          const ctx = canvas.getContext('2d');
          ctx.drawImage(img, 0, 0);
          const imgData = canvas.toDataURL('image/jpeg', 0.95);

          const pdfWidth = doc.internal.pageSize.getWidth();
          const pdfHeight = (img.height * pdfWidth) / img.width;
          doc.addImage(imgData, 'JPEG', 0, 0, pdfWidth, pdfHeight);

          const textY = pdfHeight + 10;
          const lines = doc.splitTextToSize(page.lyrics, pdfWidth - 20);
          doc.text(lines, 10, textY);

        } catch (err) {
          console.error('Error processing page:', err);
          this.showError(`Error processing page ${i + 1}`);
        }
      }
      
      doc.save('lyrical_storybook.pdf');
    } catch (error) {
      console.error('Error exporting storybook:', error);
      this.showError('Failed to export storybook: ' + error.message);
    } finally {
      this.exportBtn.disabled = false;
      this.exportBtn.textContent = 'Export Storybook';
    }
  }

  resetApp() {
    document.getElementById('lyrics').value = this.defaultSettings.lyrics;
    document.getElementById('theme').value = this.defaultSettings.theme;
    document.getElementById('styleFilter').value = this.defaultSettings.styleFilter;
    document.getElementById('bookLayout').value = this.defaultSettings.bookLayout;
    document.getElementById('textStyle').value = this.defaultSettings.textStyle;

    this.previewArea.innerHTML = '<p>Preview will appear here</p>';
    
    this.pages = [];
    this.currentPage = 0;
    this.isGenerating = false;
    this.selectedStyle = null;

    document.getElementById('errorMessage').style.display = 'none';
    
    this.generateBtn.classList.remove('generating');
    this.generateBtn.textContent = 'Generate Storybook';
    this.exportBtn.disabled = false;
    this.exportBtn.textContent = 'Export Storybook';
  }

  showPage(index) {
    if (index >= 0 && index < this.pages.length) {
      this.currentPage = index;
      const page = this.pages[index];

      const textStyleFont = this.getTextStyleFont(this.selectedStyle.textStyle);
      const layoutClass = `layout-${this.selectedStyle.layout}`;

      this.previewArea.innerHTML = `
        <div class="storybook-page page-transition ${layoutClass}">
          <div class="page-illustration">
            <img src="${page.imageUrl}" alt="Generated story illustration" width="1280" height="720">
          </div>
          <div class="page-text" style="font-family: ${textStyleFont};">
            <p>${page.lyrics}</p>
          </div>
        </div>
        <div class="page-controls">
          <button class="page-btn" onclick="musicVideoCreator.previousPage()" ${index === 0 ? 'disabled' : ''}>Previous</button>
          <span>Page ${index + 1} of ${this.pages.length}</span>
          <button class="page-btn" onclick="musicVideoCreator.nextPage()" ${index === this.pages.length - 1 ? 'disabled' : ''}>Next</button>
        </div>
      `;
    }
  }

  nextPage() {
    if (this.currentPage < this.pages.length - 1) {
      this.currentPage++;
      this.showPage(this.currentPage);
    }
  }

  previousPage() {
    if (this.currentPage > 0) {
      this.currentPage--;
      this.showPage(this.currentPage);
    }
  }

  checkContrast(foreground, background) {
    const hexToRgb = hex => {
      const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
      return result ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16)
      } : null;
    };

    const luminance = color => {
      const rgb = hexToRgb(color);
      const [r, g, b] = [rgb.r, rgb.g, rgb.b].map(c => {
        c = c / 255;
        return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
      });
      return 0.2126 * r + 0.7152 * g + 0.0722 * b;
    };

    const l1 = luminance(foreground);
    const l2 = luminance(background);
    const ratio = (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
    
    return ratio >= 4.5; 
  }

  adjustStyleForContrast() {
    const textElements = document.querySelectorAll('.page-text');
    textElements.forEach(el => {
      const bgColor = window.getComputedStyle(el.parentElement).backgroundColor;
      el.style.color = this.checkContrast('#ffffff', bgColor) ? '#ffffff' : '#000000';
    });
  }
}

document.addEventListener('DOMContentLoaded', () => {
  window.musicVideoCreator = new MusicVideoCreator();
});
</script>

<meta name="referrer" content="no-referrer">
</head><body>
<div class="app">
  <header class="header">
    <!-- Logo SVG -->
    <div class="logo">
      <svg width="80" height="80" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" aria-labelledby="logoTitle" role="img">
        <title id="logoTitle">Lyrical Storybook Creator Logo</title>
        <circle cx="50" cy="50" r="48" fill="var(--bg-surface)" stroke="var(--primary)" stroke-width="2">
</circle>
        <path d="M25 35 Q50 30 75 35 L75 65 Q50 60 25 65 Z" fill="none" stroke="var(--primary)" stroke-width="3"></path>
        <path d="M50 30 L50 60" fill="none" stroke="var(--primary)" stroke-width="2"></path>
        <path d="M35 45 Q38 42 38 48 L38 55 Q35 58 32 55 Q32 52 35 52 Z" fill="var(--accent)"></path>
        <path d="M65 42 Q68 39 68 45 L68 52 Q65 55 62 52 Q62 49 65 49 Z" fill="var(--accent)"></path>
        <path d="M20 70 Q35 65 50 70 Q65 75 80 70" fill="none" stroke="var(--secondary)" stroke-width="2" opacity="0.8"></path>
        <path d="M30 25 L32 30 L27 28 L33 28 L28 30 Z" fill="var(--accent-light)"></path>
        <path d="M70 25 L72 30 L67 28 L73 28 L68 30 Z" fill="var(--accent-light)"></path>
      </svg>
    </div>
    <h1>Lyrical Storybook Creator</h1>
    <p style="font-family: 'Playfair Display', serif; font-size: 1.8rem; margin-top: 0.5rem;">Transform your lyrics into an illustrated storybook journey</p>
  </header>

  <div class="error-message" id="errorMessage"></div>

  <section class="project-creation">
    <div class="input-group">
      <label for="lyrics" style="font-size: 1.5rem; text-align: center; display: block; margin: 0 auto;">Song Lyrics</label>
      <textarea id="lyrics" rows="12" placeholder="Paste your lyrics here..."></textarea>
    </div>

    <div class="input-group">
      <label for="theme">Theme &amp; Mood</label>
      <input type="text" id="theme" placeholder="e.g., Magical forest adventure, Cosmic journey through space, Urban night romance">
    </div>

    <div class="style-controls">
      <div class="input-group">
        <label for="styleFilter">Art Style</label>
        <select id="styleFilter">
          <option value="watercolor">Watercolor</option>
          <option value="digital">Digital Art</option>
          <option value="sketch">Pencil Sketch</option>
          <option value="abstract">Abstract</option>
          <option value="oil-painting">Oil Painting</option>
          <option value="anime">Anime Style</option>
          <option value="pixar">Pixar Style</option>
          <option value="pop-art">Pop Art</option>
          <option value="steampunk">Steampunk</option>
          <option value="cyberpunk">Cyberpunk</option>
          <option value="art-nouveau">Art Nouveau</option>
          <option value="impressionist">Impressionist</option>
          <option value="surreal">Surrealist</option>
          <option value="gothic">Gothic</option>
          <option value="retro">Retro/Vintage</option>
          <option value="minimalist">Minimalist</option>
          <option value="studio-ghibli">Studio Ghibli</option>
          <option value="vector">Vector Art</option>
          <option value="geometric">Geometric</option>
          <option value="collage">Mixed Media Collage</option>
        </select>
      </div>

      <div class="input-group">
        <label for="bookLayout">Page Layout</label>
        <select id="bookLayout">
          <option value="single">Single Page</option>
          <option value="spread">Double Spread</option>
          <option value="scroll">Scrolling Story</option>
          <option value="grid">Grid Layout</option>
        </select>
      </div>
      
      <div class="input-group">
        <label for="textStyle">Text Style</label>
        <select id="textStyle">
          <option value="storybook">Storybook</option>
          <option value="elegant">Elegant</option>
          <option value="modern">Modern</option>
          <option value="handwritten">Handwritten</option>
          <option value="gothic">Gothic</option>
          <option value="whimsical">Whimsical</option>
          <option value="minimalist">Minimalist</option>
          <option value="vintage">Vintage</option>
          <option value="fantasy">Fantasy</option>
          <option value="calligraphy">Calligraphy</option>
          <option value="futuristic">Futuristic</option>
          <option value="classic">Classic</option>
        </select>
      </div>
    </div>

    <div class="controls">
      <button class="btn btn-primary" id="applyStylesBtn">Apply Styles</button>
      <button class="btn btn-primary" id="generateBtn">Generate Storybook</button>
      <button class="btn btn-secondary" id="exportBtn">Export Storybook</button>
      <button class="btn btn-secondary" id="resetBtn">Reset</button>
    </div>
  </section>

  <div class="storybook-container">
    <div class="preview-content" id="previewArea" style="color: #ffffff;">
    <p>Preview will appear here</p>
  </div>
  </div>
</div>

</body></html>