Multi Tool Hub

Image Converter

Convert between JPG, PNG, and WEBP formats using canvas.

Age Calculator

Input date of birth → output age in years, months, and days.

Password Generator

Generate secure password with length, symbols, numbers options.

QR Code Generator

Enter text or URL → generate downloadable QR image.

Word Counter

Live count of words, characters, spaces, and reading time.

BMI Calculator

Input weight and height → show BMI category and value.

:root { --bg-color: #1E1E2F; --text-color: #EAEAEA; --header-bg: #2B2D42; --accent-color: #FFD700; --tool-card-bg: #3A3D5B; --button-hover-color: #E6C200; --soft-shadow: rgba(255, 215, 0, 0.2); } body { font-family: Arial, sans-serif; background-color: var(--bg-color); color: var(--text-color); margin: 0; padding: 0; line-height: 1.6; } .main-header { background-color: var(--header-bg); padding: 20px 0; text-align: center; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); margin-bottom: 30px; } .main-header h1 { margin: 0; color: var(--text-color); font-size: 2.5em; } .tool-grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px; padding: 20px; max-width: 1200px; margin: 0 auto; } .tool-card { background-color: var(--tool-card-bg); padding: 25px; border-radius: 10px; text-align: center; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); transition: all 0.3s ease; display: flex; flex-direction: column; justify-content: space-between; } .tool-card:hover { background-color: var(--accent-color); color: var(--bg-color); transform: translateY(-5px); box-shadow: 0 10px 20px var(--soft-shadow); } .tool-card h2 { color: var(--text-color); /* Initial color */ margin-top: 0; font-size: 1.8em; transition: color 0.3s ease; } .tool-card:hover h2 { color: var(--bg-color); /* Color on hover */ } .tool-card p { font-size: 0.95em; margin-bottom: 20px; transition: color 0.3s ease; } .tool-card:hover p { color: var(--bg-color); /* Color on hover */ } .open-tool-btn { background-color: var(--accent-color); color: var(--bg-color); border: none; padding: 12px 25px; border-radius: 5px; font-size: 1em; font-weight: bold; cursor: pointer; transition: background-color 0.3s ease, box-shadow 0.3s ease; align-self: center; /* Center button in flex container */ } .open-tool-btn:hover { background-color: var(--button-hover-color); box-shadow: 0 4px 10px var(--soft-shadow); } /* Modal Styles */ .tool-modal { display: none; /* Hidden by default */ position: fixed; /* Stay in place */ z-index: 1000; /* Sit on top */ left: 0; top: 0; width: 100%; /* Full width */ height: 100%; /* Full height */ overflow: auto; /* Enable scroll if needed */ background-color: rgba(0, 0, 0, 0.7); /* Black w/ opacity */ justify-content: center; align-items: center; } .tool-modal.active { display: flex; /* Show the modal */ } .modal-content { background-color: var(--tool-card-bg); margin: auto; padding: 30px; border-radius: 10px; width: 80%; max-width: 600px; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.5); position: relative; color: var(--text-color); } .modal-content h2 { color: var(--accent-color); margin-top: 0; margin-bottom: 20px; text-align: center; } .close-btn { color: var(--text-color); position: absolute; top: 15px; right: 25px; font-size: 30px; font-weight: bold; cursor: pointer; transition: color 0.3s ease; } .close-btn:hover, .close-btn:focus { color: var(--accent-color); text-decoration: none; } /* Form elements within modal */ .modal-content input[type="file"], .modal-content select, .modal-content button { display: block; width: calc(100% - 20px); padding: 10px; margin-bottom: 15px; border-radius: 5px; border: 1px solid var(--header-bg); background-color: var(--bg-color); color: var(--text-color); font-size: 1em; } .modal-content input[type="file"]::file-selector-button { background-color: var(--accent-color); color: var(--bg-color); border: none; padding: 8px 15px; border-radius: 3px; cursor: pointer; transition: background-color 0.3s ease; } .modal-content input[type="file"]::file-selector-button:hover { background-color: var(--button-hover-color); } .modal-content button#convert-image-btn, .modal-content a#download-image-btn { width: auto; /* Allow button/link to size to content */ padding: 12px 25px; background-color: var(--accent-color); color: var(--bg-color); border: none; font-weight: bold; cursor: pointer; transition: background-color 0.3s ease, box-shadow 0.3s ease; text-decoration: none; /* For the download link */ text-align: center; display: inline-block; /* For download link to behave like a button */ } .modal-content button#convert-image-btn:hover, .modal-content a#download-image-btn:hover { background-color: var(--button-hover-color); box-shadow: 0 4px 10px var(--soft-shadow); } #image-preview { max-width: 100%; max-height: 200px; overflow: hidden; margin-bottom: 15px; display: flex; justify-content: center; align-items: center; border: 1px dashed var(--header-bg); min-height: 100px; } #image-preview img { max-width: 100%; max-height: 100%; object-fit: contain; } /* Responsive Design */ @media (max-width: 992px) { /* Tablet */ .tool-grid-container { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 768px) { /* Mobile */ .main-header h1 { font-size: 2em; } .tool-grid-container { grid-template-columns: 1fr; } .tool-card { padding: 20px; } .tool-card h2 { font-size: 1.5em; } .open-tool-btn { padding: 10px 20px; font-size: 0.9em; } .modal-content { width: 90%; padding: 20px; } } document.addEventListener('DOMContentLoaded', () => { // --- General Modal Handling --- const toolCards = document.querySelectorAll('.tool-card'); const modals = document.querySelectorAll('.tool-modal'); const closeButtons = document.querySelectorAll('.tool-modal .close-btn'); toolCards.forEach(card => { card.querySelector('.open-tool-btn').addEventListener('click', () => { const toolType = card.dataset.tool; const modal = document.getElementById(`${toolType}-modal`); if (modal) { modal.classList.add('active'); } }); }); closeButtons.forEach(btn => { btn.addEventListener('click', () => { btn.closest('.tool-modal').classList.remove('active'); }); }); // Close modal if clicking outside of the modal content modals.forEach(modal => { modal.addEventListener('click', (event) => { if (event.target === modal) { modal.classList.remove('active'); } }); }); // --- Image Converter Tool Logic --- const imageUpload = document.getElementById('image-upload'); const conversionFormat = document.getElementById('conversion-format'); const convertImageBtn = document.getElementById('convert-image-btn'); const imagePreview = document.getElementById('image-preview'); const downloadImageBtn = document.getElementById('download-image-btn'); const imageCanvas = document.getElementById('image-canvas'); const ctx = imageCanvas.getContext('2d'); let uploadedImage = null; imageUpload.addEventListener('change', (event) => { const file = event.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = (e) => { const img = new Image(); img.onload = () => { uploadedImage = img; // Display preview imagePreview.innerHTML = ''; imagePreview.appendChild(img); // Reset download button downloadImageBtn.style.display = 'none'; downloadImageBtn.removeAttribute('href'); downloadImageBtn.removeAttribute('download'); }; img.src = e.target.result; }; reader.readAsDataURL(file); } }); convertImageBtn.addEventListener('click', () => { if (!uploadedImage) { alert('Please upload an image first.'); return; } const format = conversionFormat.value; let mimeType; let fileExtension; switch (format) { case 'jpeg': mimeType = 'image/jpeg'; fileExtension = 'jpg'; break; case 'png': mimeType = 'image/png'; fileExtension = 'png'; break; case 'webp': mimeType = 'image/webp'; fileExtension = 'webp'; break; default: alert('Invalid format selected.'); return; } imageCanvas.width = uploadedImage.width; imageCanvas.height = uploadedImage.height; ctx.clearRect(0, 0, imageCanvas.width, imageCanvas.height); ctx.drawImage(uploadedImage, 0, 0); try { const dataURL = imageCanvas.toDataURL(mimeType, 0.9); // 0.9 quality for JPG/WEBP downloadImageBtn.href = dataURL; downloadImageBtn.download = `converted-image.${fileExtension}`; downloadImageBtn.textContent = `Download as ${format.toUpperCase()}`; downloadImageBtn.style.display = 'block'; alert(`Image successfully converted to ${format.toUpperCase()}!`); } catch (error) { alert(`Error converting image: ${error.message}. Please try a different format or image.`); console.error("Image conversion error:", error); downloadImageBtn.style.display = 'none'; } }); });