{
  "manifest_version": 3,
  "name": "Sync Waves",
  "version": "1.1",
  "description": "Sync audio and video from YouTube or local files.",
  "permissions": [
    "tabs"
  ],
  "action": {
    "default_title": "Sync Waves",
    "default_icon": {
      "16": "icons/icon16.png",
      "48": "icons/icon48.png",
      "128": "icons/icon128.png"
    }
  },
  "background": {
    "service_worker": "background.js"
  },
  "icons": {
    "16": "icons/icon16.png",
    "48": "icons/icon48.png",
    "128": "icons/icon128.png"
  }
}

// background.js

chrome.action.onClicked.addListener((tab) => {
  // Get the extension's URL for newtab.html
  const newTabURL = chrome.runtime.getURL("newtab.html");

  // Create a new tab with newtab.html
  chrome.tabs.create({ url: newTabURL });
});

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Sync Waves</title>
  <link rel="stylesheet" href="newtab.css">
</head>
<body>
  <div class="container">
    <h1>Sync Waves</h1>
    
    <div class="section" id="audio-section">
      <h2>Audio</h2>
      <input type="url" id="audio-youtube-url" placeholder="YouTube URL">
      <input type="file" id="audio-file-input" accept="audio/*">
      <input type="number" id="audio-start-time" placeholder="Start Time (seconds)" min="0">
      <button class="load-button" id="audio-load-button">Load Audio</button>
    </div>
    
    <div class="section" id="video-section">
      <h2>Video</h2>
      <input type="url" id="video-youtube-url" placeholder="YouTube URL">
      <input type="file" id="video-file-input" accept="video/*">
      <input type="number" id="video-start-time" placeholder="Start Time (seconds)" min="0">
      <button class="load-button" id="video-load-button">Load Video</button>
    </div>
    
    <div class="controls">
      <button id="play-button">Play</button>
      <button id="pause-button">Pause</button>
      <button id="resume-button">Resume</button>
    </div>
    
    <!-- Hidden media elements -->
    <div class="media-container">
      <audio id="audio-element"></audio>
      <video id="video-element" controls></video>
    </div>
  </div>
  
  <script src="newtab.js"></script>
</body>
</html>

/* newtab.css */

body, html {
  height: 100%;
  margin: 0;
  font-family: Arial, sans-serif;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  background: radial-gradient(circle, white, black);
  animation: gradientCycle 8s linear forwards;
}

.container {
  text-align: center;
  background: rgba(255, 255, 255, 0.8);
  padding: 20px;
  border-radius: 10px;
  max-width: 90%;
  box-sizing: border-box;
}

h1 {
  margin-bottom: 20px;
}

.section {
  margin-bottom: 20px;
}

.section h2 {
  margin-bottom: 10px;
}

input[type="url"],
input[type="file"],
input[type="number"] {
  display: block;
  width: 80%;
  margin: 10px auto;
  padding: 8px;
  box-sizing: border-box;
}

.load-button {
  padding: 10px 20px;
  margin-top: 10px;
  cursor: pointer;
}

.controls {
  margin-top: 20px;
}

.controls button {
  padding: 10px 20px;
  margin: 0 10px;
  cursor: pointer;
}

.media-container {
  display: none;
}

@keyframes gradientCycle {
  0% { background: radial-gradient(circle, white, red); }
  14% { background: radial-gradient(circle, white, orange); }
  28% { background: radial-gradient(circle, white, yellow); }
  42% { background: radial-gradient(circle, white, green); }
  56% { background: radial-gradient(circle, white, blue); }
  70% { background: radial-gradient(circle, white, indigo); }
  84% { background: radial-gradient(circle, white, violet); }
  100% { background: radial-gradient(circle, white, black); }
}

@media (max-width: 600px) {
  .container {
    width: 95%;
  }

  input[type="url"],
  input[type="file"],
  input[type="number"] {
    width: 100%;
  }

  .controls button {
    width: 80px;
    margin: 5px;
  }
}

// newtab.js

document.addEventListener('DOMContentLoaded', () => {
  // Audio Elements
  const audioYouTubeURLInput = document.getElementById('audio-youtube-url');
  const audioFileInput = document.getElementById('audio-file-input');
  const audioStartTimeInput = document.getElementById('audio-start-time');
  const audioLoadButton = document.getElementById('audio-load-button');
  const audioElement = document.getElementById('audio-element');
  
  // Video Elements
  const videoYouTubeURLInput = document.getElementById('video-youtube-url');
  const videoFileInput = document.getElementById('video-file-input');
  const videoStartTimeInput = document.getElementById('video-start-time');
  const videoLoadButton = document.getElementById('video-load-button');
  const videoElement = document.getElementById('video-element');
  
  // Control Buttons
  const playButton = document.getElementById('play-button');
  const pauseButton = document.getElementById('pause-button');
  const resumeButton = document.getElementById('resume-button');
  
  // Helper function to load media from YouTube URL
  const loadYouTubeMedia = (url, mediaType) => {
    const videoId = extractYouTubeID(url);
    if (videoId) {
      if (mediaType === 'audio') {
        // For audio, use YouTube embed and mute the video
        videoElement.src = `https://www.youtube.com/embed/${videoId}?enablejsapi=1&autoplay=1&mute=1`;
        videoElement.style.display = 'none';
      } else if (mediaType === 'video') {
        videoElement.src = `https://www.youtube.com/embed/${videoId}?enablejsapi=1&autoplay=1`;
        videoElement.style.display = 'block';
      }
    } else {
      alert('Invalid YouTube URL');
    }
  };
  
  // Helper function to extract YouTube Video ID
  const extractYouTubeID = (url) => {
    const regex = /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|embed)\/|.*[?&]v=)|youtu\.be\/)([^"&?/\s]{11})/;
    const match = url.match(regex);
    return match ? match[1] : null;
  };
  
  // Load Audio Handler
  audioLoadButton.addEventListener('click', () => {
    const url = audioYouTubeURLInput.value.trim();
    const file = audioFileInput.files[0];
    const startTime = parseInt(audioStartTimeInput.value, 10) || 0;
    
    if (url) {
      loadYouTubeMedia(url, 'audio');
      // Play for 1/8th second then pause and seek
      videoElement.onloadedmetadata = () => {
        videoElement.play();
        setTimeout(() => {
          videoElement.pause();
          // Seek to start time
          videoElement.currentTime = startTime;
        }, 125); // 1/8th of a second = 125ms
      };
    } else if (file) {
      const fileURL = URL.createObjectURL(file);
      audioElement.src = fileURL;
      audioElement.play();
      setTimeout(() => {
        audioElement.pause();
        audioElement.currentTime = startTime;
      }, 125);
    } else {
      alert('Please provide a YouTube URL or select an audio file.');
    }
  });
  
  // Load Video Handler
  videoLoadButton.addEventListener('click', () => {
    const url = videoYouTubeURLInput.value.trim();
    const file = videoFileInput.files[0];
    const startTime = parseInt(videoStartTimeInput.value, 10) || 0;
    
    if (url) {
      loadYouTubeMedia(url, 'video');
      // Play for 1/8th second then pause and seek
      videoElement.onloadedmetadata = () => {
        videoElement.play();
        setTimeout(() => {
          videoElement.pause();
          // Seek to start time
          videoElement.currentTime = startTime;
        }, 125); // 1/8th of a second = 125ms
      };
    } else if (file) {
      const fileURL = URL.createObjectURL(file);
      videoElement.src = fileURL;
      videoElement.style.display = 'block';
      videoElement.play();
      setTimeout(() => {
        videoElement.pause();
        videoElement.currentTime = startTime;
      }, 125);
    } else {
      alert('Please provide a YouTube URL or select a video file.');
    }
  });
  
  // Play Button Handler
  playButton.addEventListener('click', () => {
    if (audioElement.src) {
      audioElement.play();
    }
    if (videoElement.src) {
      videoElement.play();
    }
  });
  
  // Pause Button Handler
  pauseButton.addEventListener('click', () => {
    if (audioElement.src) {
      audioElement.pause();
    }
    if (videoElement.src) {
      videoElement.pause();
    }
  });
  
  // Resume Button Handler
  resumeButton.addEventListener('click', () => {
    if (audioElement.src) {
      audioElement.play();
    }
    if (videoElement.src) {
      videoElement.play();
    }
  });
  
  // Prevent default behavior for drag-and-drop if needed
  window.addEventListener('dragover', (e) => e.preventDefault());
  window.addEventListener('drop', (e) => e.preventDefault());
});

i only want the completed updated files.  when using a youtube url, make the videos appear bellow the load button in both the audio and video section. make the background gradient outside colors blend over time instead of simply changing.