diff --git a/submissions/Visual Timer/.gitignore b/submissions/Visual Timer/.gitignore
new file mode 100644
index 00000000..7e7a7ee7
--- /dev/null
+++ b/submissions/Visual Timer/.gitignore
@@ -0,0 +1,5 @@
+node_modules/
+.pnp
+.pnp.*
+.yarn/*
+!.yarn/patches
\ No newline at end of file
diff --git a/submissions/Visual Timer/README.md b/submissions/Visual Timer/README.md
new file mode 100644
index 00000000..984973b1
--- /dev/null
+++ b/submissions/Visual Timer/README.md
@@ -0,0 +1,314 @@
+# Visual Timer Chrome/Firefox Extension
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+A Chrome extension that provides a visual time-tracking overlay that changes color over time, helping you stay aware of time passing while working on tasks.
+
+## Screenshots
+
+
+
+
+ Default Pixel UI
+
+
+
+
+ Settings: Time
+
+
+
+
+ Settings: Display
+
+
+
+
+ Settings: Colors
+
+
+
+
+ Classic UI
+
+
+## Features
+
+- Visual color-changing overlay that transitions through different colors (Blue → Green → Purple → Red)
+- Adjustable overlay opacity (1-100%)
+- Customizable time settings (up to 24 hours)
+- Show/hide time display
+- Pause and reset functionality
+- Works on all websites
+- Special compatibility with YouTube
+- Settings sync across Chrome instances
+- Automatic pause during system idle
+- Choice between Classic and Minecraft-styled Pixel UI
+
+## Version History
+
+### 1.5.0 (Current)
+- Major UI improvements with pixel-perfect design
+- Added alternative Minecraft-styled Pixel UI
+- Fixed live timer update issue - timer now updates in real-time without requiring extension click
+- Fixed timer display visibility - timer now properly disappears when extension is disabled
+- Enhanced code structure and organization
+- Improved extension reliability and performance
+- Better handling of disabled state
+- Added UI switcher to toggle between Classic and Pixel interfaces
+- Improved performance with CSS-based textures
+- Enhanced cross-browser compatibility
+- Style enhancements to both interfaces
+
+### v1.4.4
+- Implemented gradual opacity increase as timer progresses
+- Added gentler visual start with initially reduced opacity
+- Fixed permissions policy violations with safer event listeners
+- Enhanced cleanup handling for better browser compatibility
+- Added fallback event listeners for cross-browser support
+
+### v1.4.3
+- Fixed multiple script injection issues
+- Prevented tab reloading on message failures
+- Added protection against duplicate elements
+- Improved script messaging and error handling
+- Added script presence detection
+- Enhanced compatibility with different websites
+- Reduced unnecessary tab updates
+
+### v1.4.2
+- Fixed overlay persistence after disabling extension
+- Fixed glitchy behavior after system idle/sleep
+- Improved state management across tabs
+- Added periodic state verification
+- Enhanced visibility state handling
+- Improved tab reload behavior
+- Added force disable functionality
+- Optimized transitions and animations
+
+### v1.4.1
+- Fixed overlay flickering issue on page load/refresh
+- Improved transition animations
+- Enhanced initialization timing
+- Optimized performance with will-change CSS property
+
+### v1.4.0
+- Added color stage customization
+- Added visual timeline for color transitions
+- Added color reset functionality
+- Updated interface with color picker controls
+- Improved color transition visualization
+
+### v1.3.1
+- Fixed message handling for better stability
+- Improved error handling across browsers
+- Enhanced settings synchronization
+- Updated documentation
+
+### v1.3
+- Added adjustable opacity control
+- Added opacity sync across browser instances
+- Added tooltip for opacity percentage
+- Improved settings persistence
+
+### v1.0
+- Initial release
+- Basic timer functionality
+- Color transitions
+- YouTube compatibility
+
+## Installation
+
+### Watch Installation & Usage Guide
+[](https://youtu.be/ik6qIkiS-jo "Watch the Installation & Usage Guide")
+
👆 Click the image above to watch the installation and usage guide on YouTube
+
+### Chrome
+1. Clone this repository or download the source code
+2. Open Chrome and navigate to `chrome://extensions/`
+3. Enable "Developer mode" in the top right corner
+4. Click "Load unpacked" in the top left
+5. Select the folder containing the extension files
+
+### Firefox
+1. Clone this repository or download the source code
+2. Rename `manifest-ff.json` to `manifest.json` (make sure to backup the original Chrome manifest if needed)
+3. ### Firefox
+1. Clone this repository or download the source code
+2. Rename `manifest-ff.json` to `manifest.json` (make sure to backup the original Chrome manifest if needed)
+3. Open Firefox and navigate to `about:debugging`
+4. Click on "This Firefox" in the left sidebar
+5. Click "Load Temporary Add-on"
+6. Navigate to your extension folder and select the `manifest.json` file
+
+Note: Firefox extensions loaded this way are temporary and will be removed when Firefox is closed. For permanent installation, the extension needs to be signed by Mozilla.
+
+## Usage
+
+1. Click the extension icon to open the settings popup
+2. Toggle between Classic and Pixel UI styles using the UI switch button
+3. Set your desired time duration (default is 2 hours)
+4. Adjust overlay opacity as needed
+5. Customize colors if desired
+6. Enable/Disable the timer as needed
+7. Use Pause/Resume to control timing
+
+### Settings
+
+#### Timer Controls
+- **Enable Visual Timer**: Toggle the overlay on/off for all websites
+- **Show Time Display**: Toggle the visibility of the time counter
+- **Time Until Red**: Set the total duration before the overlay turns red
+ - Hours: 0-24
+ - Minutes: 0-59
+- **Overlay Opacity**: Adjust the transparency of the color overlay (1-100%)
+ - Lower values make the overlay more transparent
+ - Higher values make the overlay more visible
+ - Default: 70%
+- **Color Transitions**: Customize the color stages of the timer
+ - Choose colors for Start, 33%, 66%, and End stages
+ - Reset to default colors (Blue → Green → Purple → Red)
+ - Changes apply immediately to all tabs
+
+#### Control Buttons
+- **Reset Timer**: Restart the timer from 0 and reset the color to blue
+- **Pause/Resume**: Temporarily stop/start the timer
+
+### Color Stages
+
+The overlay transitions through four distinct colors:
+1. Blue (Start)
+2. Green (33% of set time)
+3. Purple (66% of set time)
+4. Red (100% of set time)
+
+### YouTube Compatibility
+
+When using YouTube, the extension automatically adjusts its overlay to:
+- Keep video controls accessible
+- Maintain video player visibility
+- Use a screen blend mode for better color visibility
+
+## Tips
+
+- Use the time display toggle to reduce distractions while keeping the color indicator
+- Reset the timer when starting a new task
+- Pause the timer during breaks
+- The extension automatically pauses when your system is idle
+- The settings are synchronized across your Chrome profile
+- The overlay works independently on each tab
+- Use the opacity slider to find the perfect balance between visibility and non-intrusiveness
+- Your opacity settings will sync across all your Chrome instances
+- Find your ideal opacity setting based on your screen brightness and website colors
+- On dark websites, you might want to use lower opacity values
+- On light websites, higher opacity values might work better
+- Save different opacity settings for different times of day
+
+## Technical Details
+
+- Built with vanilla JavaScript
+- Uses Chrome Extension Manifest V3
+- Utilizes Chrome's storage, alarms, idle, and tabs APIs
+- Lightweight with minimal performance impact
+
+## Permissions
+
+The extension requires the following permissions:
+- `storage`: Save your settings and timer state
+- `alarms`: Update the timer every second
+- `idle`: Detect system idle state
+- `tabs`: Apply the overlay to web pages
+
+## Troubleshooting
+
+### Common Issues
+
+1. **Timer Not Appearing or Extension not working**
+ - Try toggling the "Enable Visual Timer" switch off and on again
+ - Refresh the webpage you're trying to use the timer on
+ - Make sure you've granted all necessary permissions
+
+2. **Time Display Not Showing**
+ - Toggle the "Show Time Display" switch off and then on
+ - Check if "Enable Visual Timer" is turned on, as the time display requires the timer to be enabled
+
+3. **Settings Not Syncing**
+ - Make sure you're signed into your browser
+ - Try closing and reopening your browser
+ - Check if you have sync enabled in your browser settings
+
+If these steps don't resolve your issue, please don't hesitate to:
+1. [Create a new issue](https://github.com/yourusername/visual-timer/issues/new) with details about:
+ - Your browser and version
+ - Steps to reproduce the problem
+ - What you expected to happen
+ - What actually happened
+2. Include any error messages from the browser's developer console (F12)
+
+## Contributing
+
+Feel free to submit issues, fork the repository, and create pull requests for any improvements.
+
+## Browser Support
+
+### Chrome
+- Supports Manifest V3
+- Full feature support
+- Persistent settings across sessions
+- Syncs across devices when signed in
+
+### Firefox
+- Uses Manifest V2
+- All core features supported
+- Temporary installation for development
+- Requires Mozilla signing for permanent installation
+
+## Development
+
+### Building from Source
+1. Clone the repository
+2. No build step required - plain JavaScript
+3. Load unpacked in Chrome or temporary add-on in Firefox
+4. Make changes and reload extension as needed
+
+### Contributing
+We welcome contributions! Please:
+1. Fork the repository
+2. Create a feature branch
+3. Make your changes
+4. Test in both Chrome and Firefox
+5. Submit a pull request
+
+### Testing
+- Test on both light and dark websites
+- Verify YouTube compatibility
+- Check all opacity levels
+- Confirm sync functionality
+- Validate timer accuracy
+
+## Support
+
+If you find this extension helpful, you can:
+- Star the repository
+- Report bugs
+- Suggest features
+- Share with others
+- Contribute improvements
+
+## License
+
+This project is licensed under the MIT License - see the LICENSE file for details.
\ No newline at end of file
diff --git a/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182049.png b/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182049.png
new file mode 100644
index 00000000..04fe7ce1
Binary files /dev/null and b/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182049.png differ
diff --git a/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182112.png b/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182112.png
new file mode 100644
index 00000000..adef320a
Binary files /dev/null and b/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182112.png differ
diff --git a/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182132.png b/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182132.png
new file mode 100644
index 00000000..22536095
Binary files /dev/null and b/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182132.png differ
diff --git a/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182147.png b/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182147.png
new file mode 100644
index 00000000..15277e59
Binary files /dev/null and b/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182147.png differ
diff --git a/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182218.png b/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182218.png
new file mode 100644
index 00000000..a1af25d3
Binary files /dev/null and b/submissions/Visual Timer/assets/Screenshots/Screenshot 2025-03-17 182218.png differ
diff --git a/submissions/Visual Timer/visual-timer/icon128.png b/submissions/Visual Timer/assets/icons/icon128.png
similarity index 100%
rename from submissions/Visual Timer/visual-timer/icon128.png
rename to submissions/Visual Timer/assets/icons/icon128.png
diff --git a/submissions/Visual Timer/visual-timer/overlay.css b/submissions/Visual Timer/css/overlay.css
similarity index 96%
rename from submissions/Visual Timer/visual-timer/overlay.css
rename to submissions/Visual Timer/css/overlay.css
index 3b278f9a..d11329fb 100644
--- a/submissions/Visual Timer/visual-timer/overlay.css
+++ b/submissions/Visual Timer/css/overlay.css
@@ -1,31 +1,31 @@
-#visual-timer-overlay {
- position: fixed;
- top: 0;
- left: 0;
- width: 100vw;
- height: 100vh;
- pointer-events: none;
- z-index: 2147483647;
- mix-blend-mode: screen;
- background-color: hsl(240, 100%, 50%);
- transition: background-color 0.5s linear, opacity 0.3s ease-in-out, visibility 0.3s ease-in-out !important;
- opacity: 0; /* Start fully transparent */
- will-change: opacity, background-color; /* Optimize for animations */
-}
-
-#visual-timer-display {
- position: fixed;
- top: 20px;
- right: 20px;
- color: white;
- font-family: Arial, sans-serif;
- font-size: 16px;
- text-shadow: 1px 1px 3px rgba(0,0,0,0.7);
- z-index: 2147483647;
- background: rgba(0,0,0,0.5);
- padding: 5px 10px;
- border-radius: 4px;
- transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out;
- opacity: 0; /* Start fully transparent */
- will-change: opacity; /* Optimize for animations */
-}
+#visual-timer-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100vw;
+ height: 100vh;
+ pointer-events: none;
+ z-index: 2147483647;
+ mix-blend-mode: screen;
+ background-color: hsl(240, 100%, 50%);
+ transition: background-color 0.5s linear, opacity 0.3s ease-in-out, visibility 0.3s ease-in-out !important;
+ opacity: 0; /* Start fully transparent */
+ will-change: opacity, background-color; /* Optimize for animations */
+}
+
+#visual-timer-display {
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ color: white;
+ font-family: Arial, sans-serif;
+ font-size: 16px;
+ text-shadow: 1px 1px 3px rgba(0,0,0,0.7);
+ z-index: 2147483647;
+ background: rgba(0,0,0,0.5);
+ padding: 5px 10px;
+ border-radius: 4px;
+ transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out;
+ opacity: 0; /* Start fully transparent */
+ will-change: opacity; /* Optimize for animations */
+}
\ No newline at end of file
diff --git a/submissions/Visual Timer/css/pixel-popup.css b/submissions/Visual Timer/css/pixel-popup.css
new file mode 100644
index 00000000..0081b3be
--- /dev/null
+++ b/submissions/Visual Timer/css/pixel-popup.css
@@ -0,0 +1,572 @@
+/* Base styles */
+* {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+body {
+ width: 340px;
+ height: 500px;
+ overflow: hidden;
+ font-family: 'Minecraft', sans-serif;
+ background: #333333;
+ color: white;
+}
+
+/* UI Container */
+.pixel-ui {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+}
+
+/* CSS-based texture patterns */
+.main-interface, .settings-panel {
+ /* Dirt texture - brown with noise pattern */
+ background-color: #866043;
+ background-image:
+ linear-gradient(45deg, #705236 25%, transparent 25%),
+ linear-gradient(-45deg, #705236 25%, transparent 25%),
+ linear-gradient(45deg, transparent 75%, #705236 75%),
+ linear-gradient(-45deg, transparent 75%, #705236 75%);
+ background-size: 8px 8px;
+ background-position: 0 0, 0 4px, 4px -4px, -4px 0px;
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ transition: transform 0.3s ease-in-out;
+}
+
+.main-interface {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ transform: translateX(0);
+}
+
+.settings-panel {
+ display: flex;
+ flex-direction: column;
+ left: 100%;
+ transform: translateX(0);
+}
+
+/* When settings are active */
+.main-interface.show-settings {
+ transform: translateX(-100%);
+}
+
+.settings-panel.show {
+ transform: translateX(-100%);
+}
+
+/* Header styles - uses plank texture */
+.header {
+ width: 100%;
+ height: 64px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: #9e7c5a;
+ background-image:
+ linear-gradient(90deg, #876a4c 2px, transparent 2px),
+ linear-gradient(0deg, #876a4c 2px, transparent 2px);
+ background-size: 16px 16px;
+ border-bottom: 2px solid black;
+ position: relative;
+}
+
+.title {
+ font-size: 22px;
+ text-align: center;
+ text-shadow: 2px 2px 0 rgba(0, 0, 0, 1);
+}
+
+.ui-switcher-btn, .settings-btn, .back-btn {
+ width: 40px;
+ height: 40px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: 2px solid black;
+ border-radius: 4px;
+ /* Stone texture - gray with noise */
+ background-color: #888888;
+ background-image:
+ linear-gradient(45deg, #7a7a7a 25%, transparent 25%),
+ linear-gradient(-45deg, #7a7a7a 25%, transparent 25%),
+ linear-gradient(45deg, transparent 75%, #7a7a7a 75%),
+ linear-gradient(-45deg, transparent 75%, #7a7a7a 75%);
+ background-size: 6px 6px;
+ cursor: pointer;
+ position: absolute;
+}
+
+.ui-switcher-btn {
+ left: 8px;
+}
+
+.settings-btn {
+ right: 8px;
+}
+
+.back-btn {
+ left: 8px;
+}
+
+.ui-switcher-btn:hover, .settings-btn:hover, .back-btn:hover {
+ filter: brightness(1.1);
+}
+
+.ui-switcher-icon {
+ width: 24px;
+ height: 24px;
+ /* Checkerboard pattern for UI switcher icon */
+ background-color: #8BC34A;
+ background-image:
+ linear-gradient(45deg, #5b9630 25%, transparent 25%),
+ linear-gradient(-45deg, #5b9630 25%, transparent 25%);
+ background-size: 8px 8px;
+ border: 2px solid #000;
+}
+
+.settings-btn svg, .back-btn svg {
+ stroke: white;
+ filter: drop-shadow(2px 2px 0 rgba(0, 0, 0, 1));
+}
+
+/* Timer Display - uses dark obsidian texture */
+.timer-display {
+ width: 280px;
+ height: 100px;
+ margin-top: 32px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: #15151b;
+ background-image:
+ radial-gradient(#252531 15%, transparent 16%),
+ radial-gradient(#252531 15%, transparent 16%);
+ background-size: 8px 8px;
+ background-position: 0 0, 4px 4px;
+ border: 2px solid black;
+}
+
+.timer-text {
+ font-size: 36px;
+ text-shadow: 2px 2px 0 rgba(0, 0, 0, 1);
+}
+
+/* Progress Bar - uses bedrock texture */
+.progress-container {
+ width: 280px;
+ height: 30px;
+ margin-top: 16px;
+ background-color: #535353;
+ background-image:
+ linear-gradient(45deg, #414141 25%, transparent 25%),
+ linear-gradient(-45deg, #414141 25%, transparent 25%),
+ linear-gradient(45deg, transparent 75%, #414141 75%),
+ linear-gradient(-45deg, transparent 75%, #414141 75%);
+ background-size: 8px 8px;
+ background-position: 0 0, 0 4px, 4px -4px, -4px 0px;
+ border: 2px solid black;
+ position: relative;
+}
+
+.progress-bar {
+ height: 100%;
+ width: 100%;
+ /* Water texture - blue with waves */
+ background-color: #3498db;
+ background-image:
+ linear-gradient(90deg, #2980b9 2px, transparent 2px),
+ linear-gradient(0deg, #2980b9 2px, transparent 2px);
+ background-size: 10px 10px;
+ position: absolute;
+ top: 0;
+ left: 0;
+ transition: width 0.3s linear;
+}
+
+/* Timer Toggle */
+.timer-toggle {
+ margin-top: 24px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.toggle-label {
+ font-size: 18px;
+ margin-right: 8px;
+ text-shadow: 2px 2px 0 rgba(0, 0, 0, 1);
+}
+
+.toggle-btn {
+ width: 48px;
+ height: 48px;
+ border: 2px solid black;
+ border-radius: 4px;
+ cursor: pointer;
+ background-position: center;
+ background-repeat: no-repeat;
+}
+
+.toggle-on {
+ /* Lever ON texture - on state with lit redstone */
+ background-color: #9e9e9e;
+ position: relative;
+}
+
+.toggle-on::after {
+ content: "";
+ position: absolute;
+ top: 10px;
+ left: 20px;
+ width: 8px;
+ height: 25px;
+ background-color: #8BC34A;
+ transform: rotate(-30deg);
+}
+
+.toggle-off {
+ /* Lever OFF texture */
+ background-color: #7a7a7a;
+ position: relative;
+}
+
+.toggle-off::after {
+ content: "";
+ position: absolute;
+ top: 10px;
+ left: 20px;
+ width: 8px;
+ height: 25px;
+ background-color: #555555;
+ transform: rotate(30deg);
+}
+
+/* Action Buttons */
+.action-buttons {
+ display: flex;
+ gap: 16px;
+ margin-top: 24px;
+}
+
+.action-btn {
+ width: 130px;
+ height: 40px;
+ font-family: 'Minecraft', sans-serif;
+ font-size: 16px;
+ color: white;
+ border: 2px solid black;
+ border-radius: 4px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ text-shadow: 2px 2px 0 rgba(0, 0, 0, 1);
+}
+
+.pause-btn {
+ /* Stone button texture */
+ background-color: #888888;
+ background-image:
+ linear-gradient(45deg, #7a7a7a 25%, transparent 25%),
+ linear-gradient(-45deg, #7a7a7a 25%, transparent 25%),
+ linear-gradient(45deg, transparent 75%, #7a7a7a 75%),
+ linear-gradient(-45deg, transparent 75%, #7a7a7a 75%);
+ background-size: 6px 6px;
+}
+
+.resume-btn {
+ /* Grass texture for Resume button */
+ background-color: #5d9c3d;
+ background-image:
+ radial-gradient(#4a8a2a 15%, transparent 16%),
+ radial-gradient(#4a8a2a 15%, transparent 16%);
+ background-size: 6px 6px;
+ background-position: 0 0, 3px 3px;
+}
+
+.reset-btn {
+ /* Redstone texture for Reset button */
+ background-color: #c01818;
+ background-image:
+ radial-gradient(#8e1010 15%, transparent 16%),
+ radial-gradient(#8e1010 15%, transparent 16%);
+ background-size: 6px 6px;
+ background-position: 0 0, 3px 3px;
+}
+
+.action-btn:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+.action-btn svg {
+ stroke: white;
+}
+
+/* Settings Panel Styles */
+/* Tabs */
+.tabs {
+ display: flex;
+ width: 100%;
+ border-bottom: 2px solid black;
+}
+
+.tab {
+ flex: 1;
+ height: 48px;
+ font-family: 'Minecraft', sans-serif;
+ font-size: 16px;
+ color: white;
+ border: none;
+ border-right: 2px solid black;
+ cursor: pointer;
+ /* Stone texture */
+ background-color: #888888;
+ background-image:
+ linear-gradient(45deg, #7a7a7a 25%, transparent 25%),
+ linear-gradient(-45deg, #7a7a7a 25%, transparent 25%),
+ linear-gradient(45deg, transparent 75%, #7a7a7a 75%),
+ linear-gradient(-45deg, transparent 75%, #7a7a7a 75%);
+ background-size: 6px 6px;
+ text-shadow: 2px 2px 0 rgba(0, 0, 0, 1);
+}
+
+.tab:last-child {
+ border-right: none;
+}
+
+.tab.active {
+ /* Plank texture for active tabs */
+ background-color: #9e7c5a;
+ background-image:
+ linear-gradient(90deg, #876a4c 2px, transparent 2px),
+ linear-gradient(0deg, #876a4c 2px, transparent 2px);
+ background-size: 16px 16px;
+}
+
+/* Tab Content */
+.tab-content {
+ flex: 1;
+ padding: 16px;
+ overflow-y: auto;
+}
+
+.tab-pane {
+ display: none;
+}
+
+.tab-pane.active {
+ display: block;
+}
+
+.section-title {
+ font-size: 20px;
+ margin-bottom: 24px;
+ text-align: center;
+ color: #FBA945;
+ text-shadow: 2px 2px 0 rgba(0, 0, 0, 1);
+}
+
+/* Time Settings */
+.time-inputs {
+ display: flex;
+ gap: 16px;
+ width: 100%;
+}
+
+.time-input-group {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.time-input-group input {
+ width: 100%;
+ height: 48px;
+ font-family: 'Minecraft', sans-serif;
+ font-size: 20px;
+ color: white;
+ text-align: center;
+ border: 2px solid black;
+ /* Obsidian texture */
+ background-color: #15151b;
+ background-image:
+ radial-gradient(#252531 15%, transparent 16%),
+ radial-gradient(#252531 15%, transparent 16%);
+ background-size: 8px 8px;
+ background-position: 0 0, 4px 4px;
+}
+
+.time-label {
+ margin-top: 8px;
+ font-size: 14px;
+ text-shadow: 2px 2px 0 rgba(0, 0, 0, 1);
+}
+
+/* Hide number input arrows */
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+
+input[type="number"] {
+ appearance: textfield;
+ -moz-appearance: textfield;
+}
+
+/* Save Button */
+.save-btn {
+ width: 200px;
+ height: 40px;
+ margin: 32px auto 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-family: 'Minecraft', sans-serif;
+ font-size: 16px;
+ color: white;
+ border: 2px solid black;
+ border-radius: 4px;
+ cursor: pointer;
+ /* Plank texture */
+ background-color: #9e7c5a;
+ background-image:
+ linear-gradient(90deg, #876a4c 2px, transparent 2px),
+ linear-gradient(0deg, #876a4c 2px, transparent 2px);
+ background-size: 16px 16px;
+ text-shadow: 2px 2px 0 rgba(0, 0, 0, 1);
+}
+
+.save-btn:hover {
+ filter: brightness(1.1);
+}
+
+/* Colors Tab */
+.color-pickers {
+ display: flex;
+ justify-content: space-between;
+ width: 100%;
+ margin-bottom: 8px;
+}
+
+.color-picker {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 4px;
+}
+
+.color-picker input[type="color"] {
+ width: 48px;
+ height: 48px;
+ border: 2px solid black;
+ background: transparent;
+ cursor: pointer;
+}
+
+.color-label {
+ font-size: 12px;
+ text-shadow: 2px 2px 0 rgba(0, 0, 0, 1);
+}
+
+.color-preview {
+ width: 100%;
+ height: 32px;
+ margin-top: 16px;
+ display: flex;
+ border: 2px solid black;
+ overflow: hidden;
+}
+
+.color-segment {
+ flex: 1;
+ height: 100%;
+}
+
+/* Display Tab */
+.display-setting {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 32px;
+ width: 100%;
+}
+
+.setting-label {
+ font-size: 18px;
+ text-shadow: 2px 2px 0 rgba(0, 0, 0, 1);
+}
+
+.opacity-setting {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 8px;
+}
+
+.slider-container {
+ position: relative;
+ width: 100%;
+ height: 32px;
+ /* Bedrock texture */
+ background-color: #535353;
+ background-image:
+ linear-gradient(45deg, #414141 25%, transparent 25%),
+ linear-gradient(-45deg, #414141 25%, transparent 25%),
+ linear-gradient(45deg, transparent 75%, #414141 75%),
+ linear-gradient(-45deg, transparent 75%, #414141 75%);
+ background-size: 8px 8px;
+ background-position: 0 0, 0 4px, 4px -4px, -4px 0px;
+ border: 2px solid black;
+}
+
+.slider {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+ cursor: pointer;
+ z-index: 10;
+}
+
+.slider-fill {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ /* Water texture */
+ background-color: #3498db;
+ background-image:
+ linear-gradient(90deg, #2980b9 2px, transparent 2px),
+ linear-gradient(0deg, #2980b9 2px, transparent 2px);
+ background-size: 10px 10px;
+ pointer-events: none;
+}
+
+.slider-knob {
+ position: absolute;
+ top: 0;
+ width: 16px;
+ height: 100%;
+ /* Diamond texture - blue with shine */
+ background-color: #38c6f4;
+ background-image:
+ linear-gradient(45deg, #29a7d1 25%, transparent 25%),
+ linear-gradient(-45deg, #29a7d1 25%, transparent 25%);
+ background-size: 6px 6px;
+ pointer-events: none;
+}
\ No newline at end of file
diff --git a/submissions/Visual Timer/html/pixel-popup.html b/submissions/Visual Timer/html/pixel-popup.html
new file mode 100644
index 00000000..8ef22278
--- /dev/null
+++ b/submissions/Visual Timer/html/pixel-popup.html
@@ -0,0 +1,140 @@
+
+
+
+
+
+ Visual Timer - Pixel UI
+
+
+
+
+
+
+
+
+
+
VISUAL TIMER
+
+
+
+
+
+ 00:00
+
+
+
+
+
+
+
+
+
+ TIMER:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
SETTINGS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Time Settings
+
+
+
+ HOURS
+
+
+
+ MINUTES
+
+
+
+
+
+
+
+
Color Settings
+
+
+
+ START
+
+
+
+ 33%
+
+
+
+ 66%
+
+
+
+ END
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Display Settings
+
+ SHOW TIME:
+
+
+
+ OPACITY: 70%
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/submissions/Visual Timer/visual-timer/popup.html b/submissions/Visual Timer/html/popup.html
similarity index 89%
rename from submissions/Visual Timer/visual-timer/popup.html
rename to submissions/Visual Timer/html/popup.html
index f50eaa13..6f443b59 100644
--- a/submissions/Visual Timer/visual-timer/popup.html
+++ b/submissions/Visual Timer/html/popup.html
@@ -1,289 +1,321 @@
-
-
-
-
-
-
-
-
-A Chrome extension that provides a visual time-tracking overlay that changes color over time, helping you stay aware of time passing while working on tasks.
-
-## Screenshots
-
-
-
- Interface of extension
-
-
-
-
- Transitioning through green
-
-
-
-
- more view of it
-
-
-
-
- overlay on youtube video
-
-
-## Features
-
-- Visual color-changing overlay that transitions through different colors (Blue → Green → Purple → Red)
-- Adjustable overlay opacity (1-100%)
-- Customizable time settings (up to 24 hours)
-- Show/hide time display
-- Pause and reset functionality
-- Works on all websites
-- Special compatibility with YouTube
-- Settings sync across Chrome instances
-- Automatic pause during system idle
-
-## Version History
-
-### v1.4.4 (Current)
-- Implemented gradual opacity increase as timer progresses
-- Added gentler visual start with initially reduced opacity
-- Fixed permissions policy violations with safer event listeners
-- Enhanced cleanup handling for better browser compatibility
-- Added fallback event listeners for cross-browser support
-
-### v1.4.3
-- Fixed multiple script injection issues
-- Prevented tab reloading on message failures
-- Added protection against duplicate elements
-- Improved script messaging and error handling
-- Added script presence detection
-- Enhanced compatibility with different websites
-- Reduced unnecessary tab updates
-
-### v1.4.2
-- Fixed overlay persistence after disabling extension
-- Fixed glitchy behavior after system idle/sleep
-- Improved state management across tabs
-- Added periodic state verification
-- Enhanced visibility state handling
-- Improved tab reload behavior
-- Added force disable functionality
-- Optimized transitions and animations
-
-### v1.4.1
-- Fixed overlay flickering issue on page load/refresh
-- Improved transition animations
-- Enhanced initialization timing
-- Optimized performance with will-change CSS property
-
-### v1.4.0
-- Added color stage customization
-- Added visual timeline for color transitions
-- Added color reset functionality
-- Updated interface with color picker controls
-- Improved color transition visualization
-
-### v1.3.1
-- Fixed message handling for better stability
-- Improved error handling across browsers
-- Enhanced settings synchronization
-- Updated documentation
-
-### v1.3
-- Added adjustable opacity control
-- Added opacity sync across browser instances
-- Added tooltip for opacity percentage
-- Improved settings persistence
-
-### v1.0
-- Initial release
-- Basic timer functionality
-- Color transitions
-- YouTube compatibility
-
-## Installation
-
-### Watch Installation & Usage Guide
-[](https://youtu.be/ik6qIkiS-jo "Watch the Installation & Usage Guide")
-
👆 Click the image above to watch the installation and usage guide on YouTube
-
-### Chrome
-1. Clone this repository or download the source code
-2. Open Chrome and navigate to `chrome://extensions/`
-3. Enable "Developer mode" in the top right corner
-4. Click "Load unpacked" in the top left
-5. Select the folder containing the extension files
-
-### Firefox
-1. Clone this repository or download the source code
-2. Rename `manifest-ff.json` to `manifest.json` (make sure to backup the original Chrome manifest if needed)
-3. Open Firefox and
diff --git a/submissions/Visual Timer/visual-timer/content-script.js b/submissions/Visual Timer/visual-timer/content-script.js
deleted file mode 100644
index c802dab4..00000000
--- a/submissions/Visual Timer/visual-timer/content-script.js
+++ /dev/null
@@ -1,315 +0,0 @@
-// Prevent multiple injections
-if (window.hasOwnProperty('__visualTimerInjected')) {
- console.debug("[CONTENT] Script already injected, skipping initialization");
-} else {
- window.__visualTimerInjected = true;
-
- console.log("[CONTENT] Script injected into:", window.location.href);
-
- let overlay = null;
- let timeDisplay = null;
- let totalSeconds = 0;
- let isInitialized = false;
- let isEnabled = false;
- let targetOpacity = 0.7; // Default target opacity
- let targetSeconds = 7200; // Default to 2 hours
-
- // Function to safely create and append elements
- function createElements() {
- if (!document.body) {
- console.debug("[CONTENT] Document body not ready, will retry");
- return false;
- }
-
- try {
- // Only create elements if they don't exist and previous ones aren't in the DOM
- const existingOverlay = document.getElementById('visual-timer-overlay');
- const existingDisplay = document.getElementById('visual-timer-display');
-
- if (existingOverlay) {
- overlay = existingOverlay;
- } else if (!overlay) {
- overlay = document.createElement('div');
- overlay.id = 'visual-timer-overlay';
- overlay.style.display = 'none';
- overlay.style.opacity = '0';
- document.body.appendChild(overlay);
- }
-
- if (existingDisplay) {
- timeDisplay = existingDisplay;
- } else if (!timeDisplay) {
- timeDisplay = document.createElement('div');
- timeDisplay.id = 'visual-timer-display';
- timeDisplay.style.display = 'none';
- timeDisplay.style.opacity = '0';
- document.body.appendChild(timeDisplay);
- }
-
- return true;
- } catch (error) {
- console.debug("[CONTENT] Error creating elements:", error);
- return false;
- }
- }
-
- // Attempt to create elements at different stages
- function initializeElements() {
- if (!createElements()) {
- // If creation fails, try again when DOM is ready
- if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', () => {
- if (!createElements()) {
- // If it still fails, try one last time after a short delay
- setTimeout(createElements, 500);
- }
- });
- } else {
- // If DOM is already ready, try again after a short delay
- setTimeout(createElements, 500);
- }
- }
- }
-
- // Initialize elements as soon as possible
- initializeElements();
-
- // Check enabled state and set up initial state once elements are created
- function initializeState() {
- if (!overlay || !timeDisplay) return;
-
- chrome.storage.sync.get(['enabled', 'showTime'], (result) => {
- isEnabled = result.enabled !== false;
- const showTime = result.showTime !== false;
-
- if (!isEnabled) {
- ensureDisabled();
- } else {
- updateOverlayVisibility(true);
- updateTimeDisplayVisibility(showTime);
- }
- });
- }
-
- // Handle settings changes and updates
- chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
- if (message.type === 'ping') {
- sendResponse({ success: true });
- return false;
- }
-
- // Ensure elements exist before handling messages
- if (!overlay || !timeDisplay) {
- if (createElements()) {
- initializeState();
- }
- }
-
- try {
- switch (message.type) {
- case 'forceDisable':
- ensureDisabled();
- break;
- case 'updateVisibility':
- if (!isEnabled) {
- ensureDisabled();
- } else {
- updateTimeDisplayVisibility(message.showTime);
- }
- break;
- case 'update':
- isEnabled = message.enabled;
- if (message.targetSeconds) {
- targetSeconds = message.targetSeconds;
- }
- if (!isEnabled) {
- ensureDisabled();
- } else {
- updateDisplay(message.color, message.seconds, message.enabled, message.opacity);
- }
- break;
- }
- sendResponse({ success: true });
- } catch (error) {
- console.error("[CONTENT] Error handling message:", error);
- sendResponse({ success: false, error: error.message });
- }
- return false;
- });
-
- function ensureDisabled() {
- if (overlay) {
- overlay.style.visibility = 'hidden';
- overlay.style.opacity = '0';
- requestAnimationFrame(() => {
- overlay.style.display = 'none';
- });
- }
- if (timeDisplay) {
- timeDisplay.style.visibility = 'hidden';
- timeDisplay.style.opacity = '0';
- requestAnimationFrame(() => {
- timeDisplay.style.display = 'none';
- });
- }
- }
-
- function updateTimeDisplayVisibility(show) {
- if (!timeDisplay || !isEnabled) return;
-
- if (!show) {
- timeDisplay.style.visibility = 'hidden';
- timeDisplay.style.opacity = '0';
- requestAnimationFrame(() => {
- timeDisplay.style.display = 'none';
- });
- } else {
- timeDisplay.style.display = 'block';
- requestAnimationFrame(() => {
- timeDisplay.style.visibility = 'visible';
- timeDisplay.style.opacity = '1';
- });
- }
- }
-
- function updateOverlayVisibility(show) {
- if (!overlay) return;
-
- if (!show) {
- overlay.style.visibility = 'hidden';
- overlay.style.opacity = '0';
- requestAnimationFrame(() => {
- overlay.style.display = 'none';
- });
- } else {
- overlay.style.display = 'block';
- requestAnimationFrame(() => {
- overlay.style.visibility = 'visible';
- });
- }
- }
-
- function updateDisplay(color, seconds, enabled, overlayOpacity) {
- if (!overlay || !timeDisplay) return;
-
- if (!enabled) {
- ensureDisabled();
- return;
- }
-
- updateOverlayVisibility(enabled);
-
- chrome.storage.sync.get(['showTime'], (result) => {
- updateTimeDisplayVisibility(result.showTime && enabled);
- if (overlay) {
- overlay.style.backgroundColor = color;
-
- // Calculate a reduced opacity for early stages
- const progress = seconds / targetSeconds;
- const startOpacity = 0.05; // Start with just 5% of the target opacity
- const currentOpacity = startOpacity + (progress * (overlayOpacity / 100 - startOpacity));
-
- // Clamp the opacity between the start value and the target
- const finalOpacity = Math.min(overlayOpacity / 100, Math.max(startOpacity, currentOpacity));
-
- // Store target opacity for future calculations
- targetOpacity = overlayOpacity / 100;
-
- overlay.style.opacity = finalOpacity;
- }
- });
-
- if (seconds !== undefined && timeDisplay) {
- totalSeconds = seconds;
- const minutes = Math.floor(totalSeconds / 60);
- const remainingSeconds = totalSeconds % 60;
- timeDisplay.textContent = `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
- }
- }
-
- // Re-verify elements and state periodically
- setInterval(() => {
- if (document.visibilityState === 'visible') {
- if (!overlay || !timeDisplay) {
- if (createElements()) {
- initializeState();
- }
- } else {
- chrome.storage.sync.get(['enabled'], (result) => {
- const shouldBeEnabled = result.enabled !== false;
- if (shouldBeEnabled !== isEnabled) {
- isEnabled = shouldBeEnabled;
- if (!isEnabled) {
- ensureDisabled();
- }
- }
- });
- }
- }
- }, 5000);
-
- // Handle visibility changes
- document.addEventListener('visibilitychange', () => {
- if (document.visibilityState === 'visible') {
- if (!overlay || !timeDisplay) {
- if (createElements()) {
- initializeState();
- }
- }
- chrome.storage.sync.get(['enabled'], (result) => {
- isEnabled = result.enabled !== false;
- if (!isEnabled) {
- ensureDisabled();
- }
- });
- }
- });
-
- // YouTube compatibility fix - only if we're on YouTube
- if (window.location.hostname.includes('youtube.com')) {
- const addYouTubeStyle = () => {
- try {
- if (document.head) {
- const style = document.createElement('style');
- style.textContent = `
- #player-container {
- z-index: 2147483646 !important;
- }
- #visual-timer-overlay {
- mix-blend-mode: screen !important;
- }
- `;
- document.head.appendChild(style);
- } else {
- setTimeout(addYouTubeStyle, 100);
- }
- } catch (error) {
- console.debug("[CONTENT] Error adding YouTube style:", error);
- }
- };
- addYouTubeStyle();
- }
-
- // Use safer cleanup method (pagehide instead of unload)
- try {
- window.addEventListener('pagehide', cleanupElements);
- // Fallback cleanup with beforeunload (more widely supported)
- window.addEventListener('beforeunload', cleanupElements);
- } catch (error) {
- console.debug("[CONTENT] Error adding cleanup listeners:", error);
- }
-
- function cleanupElements() {
- try {
- if (overlay && overlay.parentNode) {
- overlay.parentNode.removeChild(overlay);
- }
- if (timeDisplay && timeDisplay.parentNode) {
- timeDisplay.parentNode.removeChild(timeDisplay);
- }
- } catch (error) {
- console.debug("[CONTENT] Error during cleanup:", error);
- }
- }
-}
-
diff --git a/submissions/Visual Timer/visual-timer/recording/Screenshot 2025-02-24 102937.png b/submissions/Visual Timer/visual-timer/recording/Screenshot 2025-02-24 102937.png
deleted file mode 100644
index 3c4f4290..00000000
Binary files a/submissions/Visual Timer/visual-timer/recording/Screenshot 2025-02-24 102937.png and /dev/null differ
diff --git a/submissions/Visual Timer/visual-timer/recording/Screenshot 2025-02-24 103013.png b/submissions/Visual Timer/visual-timer/recording/Screenshot 2025-02-24 103013.png
deleted file mode 100644
index 8b7b0818..00000000
Binary files a/submissions/Visual Timer/visual-timer/recording/Screenshot 2025-02-24 103013.png and /dev/null differ
diff --git a/submissions/Visual Timer/visual-timer/recording/Screenshot 2025-02-24 103033.png b/submissions/Visual Timer/visual-timer/recording/Screenshot 2025-02-24 103033.png
deleted file mode 100644
index 24e94a3f..00000000
Binary files a/submissions/Visual Timer/visual-timer/recording/Screenshot 2025-02-24 103033.png and /dev/null differ
diff --git a/submissions/Visual Timer/visual-timer/recording/Screenshot 2025-02-24 103209.png b/submissions/Visual Timer/visual-timer/recording/Screenshot 2025-02-24 103209.png
deleted file mode 100644
index 2623c2af..00000000
Binary files a/submissions/Visual Timer/visual-timer/recording/Screenshot 2025-02-24 103209.png and /dev/null differ