How to create AI tool website on Blogger?

How to create an AI tool website on Blogger?

How to create AI tool website on Blogger?


Friends, in today's article I will tell you how to create a tool generator website with the help of AI on the Blogger platform. Although I have already written an article on this topic, but it was PHP HTML script. 

There are many people who cannot afford to buy a hosting server, so I am writing this article for them, in which they can create their own tool website with the help of the free platform i.e. Blogger. 

To create this website, they will need some knowledge of using AI prompt, HTML code and basic AI. I will explain that too in detail in this article.

How to create an AI tool website on Blogger? 

As I told you above, you can create your tool converter website on the Blogger platform. You do not need to pay any money for this. You can do this process completely free through AI.

So first you have to create a blog or blog post on Blogger. You can use any template. Do whatever basic customization is required on Blogger and copy the AI ​​prompt I am giving below.

Propmt:

🛠️ Project Brief: Build a Modern Multi-Tool Website – “Multi Tool Hub”


✅ Objective:

Create a fully functional, mobile-friendly, and visually premium multi-tool web application named “Multi Tool Hub” using only HTML, CSS, and Vanilla JavaScript — no backend, no external libraries (use browser-native APIs only).


🎨 Design Specifications:

Color Theme:

  • Background: #1E1E2F (dark navy)

  • Header: #2B2D42 (deep blue)

  • Tool Cards: #3A3D5B (dark grayish-blue)

  • Text: #EAEAEA (light gray)

  • Accent Color (buttons, highlights): #FFD700 (gold)

  • Button Hover: #E6C200

  • Box Shadow on Hover: rgba(255, 215, 0, 0.2)

Aesthetic Guidelines:

  • Modern, minimal, premium look

  • Use soft box shadows, rounded corners, and smooth transitions

  • Responsive design for desktop, tablet, and mobile

  • CSS variables for all theme colors

  • Optional: fade-in animations using CSS or IntersectionObserver


🧱 Layout Requirements:

Header Section:

  • Centered title: “Multi Tool Hub”

Main Content:

  • Responsive grid layout of tool cards:

    • Desktop: 3-column layout

    • Tablet: 2-column layout

    • Mobile: 1-column layout

Each Tool Card Includes:

  • Title (h2)

  • Short description (p)

  • Action button that:

    • Opens a modal or replaces main content with the tool interface


🛠️ List of 20 Functional Frontend Tools:

  1. Image Converter – JPG/PNG/WEBP conversion via Canvas API

  2. Image Compressor – Reduce file size with Canvas & quality control

  3. Image Cropper – Upload, crop with preview & export

  4. Video Converter – Convert MP4/WebM using MediaRecorder or canvas

  5. Audio Converter – Convert MP3/WAV using Web Audio API

  6. Audio Trimmer – Upload and trim audio by start/end time

  7. Age Calculator – DOB input → shows age in years, months, days

  8. EMI Calculator – Calculate EMI, interest, and total amount

  9. SIP Calculator – Future value based on monthly investment

  10. QR Code Generator – Text/URL to QR image via canvas

  11. Password Generator – Customizable strong password generator

  12. Word Counter – Real-time word, character, space, reading time

  13. Base64 Encoder/Decoder – Convert to/from Base64

  14. Color Picker – Pick color and display HEX, RGB, HSL

  15. Text to Speech – Convert text to voice using SpeechSynthesis

  16. Speech to Text – Use microphone to convert speech to text

  17. JSON Formatter – Format and validate JSON with error display

  18. Unit Converter – Length, weight, temp, etc. conversions

  19. BMI Calculator – Input height/weight, calculate BMI

  20. Timer / Stopwatch – Start, pause, reset timer or stopwatch


⚙️ JavaScript Functionality:

  • Modular design — Each tool encapsulated in its own function/module

  • Native APIs only (e.g. Canvas, Web Audio, Web Speech, MediaRecorder)

  • Real-time input handling, form validation, file processing

  • Dynamic content updates, modal toggling

  • Show loaders/messages for processing or success feedback


📁 File Structure:

  • index.html – Page structure, header, tool cards, modal/section containers

  • style.css – Theming, responsive layout, transitions, animations

  • script.js – All tool logic, event handlers, UI controls, modal logic


✅ Final Requirements:

  • All 20 tools must be fully working using frontend JavaScript

  • UI should be responsive and elegant across all devices

  • Clean, well-organized, and maintainable code

  • No external libraries — only native APIs allowed

  • Fully interactive interface with dynamic modals or content areas


Let me know if you'd like this to be generated as code now in one HTML file, all html css and java script add into one file


Html Code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Multi Tool Hub</title>
    <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🛠️</text></svg>">
    
    <style>
        /* --- CSS Variables for Theming --- */
        :root {
            --bg-color: #1E1E2F;
            --text-color: #EAEAEA;
            --header-bg: #2B2D42;
            --accent-color: #FFD700;
            --card-bg: #3A3D5B;
            --btn-hover-color: #E6C200;
            --shadow-color: rgba(255, 215, 0, 0.2);
            --border-radius: 8px;
            --transition-speed: 0.3s;
        }

        /* --- General & Reset Styles --- */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        html {
            scroll-behavior: smooth;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            background-color: var(--bg-color);
            color: var(--text-color);
            line-height: 1.6;
        }

        /* --- Header --- */
        header {
            background-color: var(--header-bg);
            padding: 1.5rem 1rem;
            text-align: center;
            border-bottom: 2px solid var(--accent-color);
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
        }

        header h1 {
            font-size: 2.5rem;
            font-weight: 700;
            color: var(--text-color);
            text-shadow: 1px 1px 3px var(--shadow-color);
        }

        /* --- Main Content & Tool Grid --- */
        main {
            padding: 2rem 1.5rem;
        }

        .tool-grid {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 1.5rem;
            max-width: 1200px;
            margin: 0 auto;
        }

        /* --- Tool Card --- */
        .tool-card {
            background-color: var(--card-bg);
            padding: 1.5rem;
            border-radius: var(--border-radius);
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            transition: transform var(--transition-speed) ease, 
                        background-color var(--transition-speed) ease,
                        color var(--transition-speed) ease,
                        box-shadow var(--transition-speed) ease;
            cursor: pointer;
            border: 1px solid transparent;
            opacity: 0;
            transform: translateY(20px);
            animation: fadeIn 0.5s ease-out forwards;
        }
        
        @keyframes fadeIn {
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        .tool-card:hover {
            transform: translateY(-10px);
            background-color: var(--accent-color);
            color: var(--bg-color);
            box-shadow: 0 10px 20px var(--shadow-color);
        }

        .tool-card:hover h2,
        .tool-card:hover p,
        .tool-card:hover button {
            color: var(--bg-color);
        }

        .tool-card:hover button {
            background-color: var(--bg-color);
            color: var(--accent-color);
            border-color: var(--accent-color);
        }


        .tool-card h2 {
            font-size: 1.4rem;
            color: var(--accent-color);
            margin-bottom: 0.5rem;
            transition: color var(--transition-speed) ease;
        }

        .tool-card p {
            font-size: 0.95rem;
            flex-grow: 1;
            margin-bottom: 1.5rem;
            opacity: 0.9;
            transition: color var(--transition-speed) ease;
        }

        /* --- General UI Elements (Buttons, Inputs) --- */
        button, .btn {
            display: inline-block;
            background-color: var(--accent-color);
            color: var(--bg-color);
            border: 1px solid var(--accent-color);
            padding: 0.75rem 1.5rem;
            border-radius: 5px;
            font-weight: bold;
            text-transform: uppercase;
            font-size: 0.9rem;
            cursor: pointer;
            transition: background-color var(--transition-speed) ease, color var(--transition-speed) ease;
            text-align: center;
            align-self: flex-start;
        }

        button:hover, .btn:hover {
            background-color: var(--btn-hover-color);
            border-color: var(--btn-hover-color);
        }

        button:disabled {
            background-color: #555;
            cursor: not-allowed;
            color: #999;
            border-color: #555;
        }

        input, select, textarea {
            width: 100%;
            padding: 0.75rem;
            border-radius: 5px;
            border: 1px solid #555;
            background-color: #2B2D42;
            color: var(--text-color);
            font-size: 1rem;
            margin-bottom: 1rem;
        }

        input[type="color"] {
            padding: 0;
            height: 50px;
            cursor: pointer;
            border: none;
            background: none;
        }
        
        input[type="checkbox"] {
            width: auto;
            margin-right: 0.5rem;
        }

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

        .tool-output, .result-box {
            background-color: var(--bg-color);
            padding: 1rem;
            margin-top: 1rem;
            border-radius: 5px;
            border: 1px solid var(--card-bg);
            word-wrap: break-word;
            font-family: 'Courier New', Courier, monospace;
            color: var(--text-color);
        }

        .result-box strong {
            color: var(--accent-color);
        }

        /* --- Modal Styles --- */
        .modal-container {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.7);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 1000;
            opacity: 0;
            visibility: hidden;
            transition: opacity var(--transition-speed) ease, visibility var(--transition-speed) ease;
        }

        .modal-container:not(.hidden) {
            opacity: 1;
            visibility: visible;
        }

        .modal-content {
            background-color: var(--header-bg);
            padding: 2.5rem;
            border-radius: var(--border-radius);
            width: 90%;
            max-width: 600px;
            max-height: 90vh;
            overflow-y: auto;
            position: relative;
            box-shadow: 0 5px 25px rgba(0, 0, 0, 0.5);
            transform: scale(0.95);
            transition: transform var(--transition-speed) ease;
        }
        
        .modal-content::-webkit-scrollbar { width: 8px; }
        .modal-content::-webkit-scrollbar-track { background: var(--bg-color); }
        .modal-content::-webkit-scrollbar-thumb { background-color: var(--accent-color); border-radius: 10px; border: 2px solid var(--bg-color); }

        .modal-container:not(.hidden) .modal-content {
            transform: scale(1);
        }

        .modal-close-btn {
            position: absolute;
            top: 1rem;
            right: 1.5rem;
            background: none;
            border: none;
            color: var(--text-color);
            font-size: 2rem;
            line-height: 1;
            cursor: pointer;
            padding: 0;
        }

        #modal-title {
            margin-bottom: 1.5rem;
            color: var(--accent-color);
        }

        #modal-body .form-group { margin-bottom: 1.5rem; }
        #modal-body canvas { max-width: 100%; height: auto; background-color: #111; border: 1px dashed #555; margin-top: 1rem; border-radius: var(--border-radius); }
        
        /* --- STYLES FOR AD SPACES --- */
        .ad-container {
            margin: 2rem auto;
            display: flex;
            justify-content: center;
            align-items: center;
            background-color: #2b2d42;
            border: 1px dashed var(--card-bg);
            border-radius: var(--border-radius);
            overflow: hidden;
        }
        .ad-leaderboard {
            min-height: 90px;
            max-width: 728px;
        }
        .ad-modal-banner {
            min-height: 250px;
            max-width: 300px;
            margin-top: 2rem;
        }
        .ad-container-placeholder-text {
            color: #888;
            font-size: 0.9rem;
        }

        /* --- Responsive Design --- */
        @media (max-width: 992px) { /* Tablet */
            .tool-grid { grid-template-columns: repeat(2, 1fr); }
            header h1 { font-size: 2rem; }
        }

        @media (max-width: 768px) { /* Mobile */
            .tool-grid { grid-template-columns: 1fr; }
            main { padding: 1.5rem 1rem; }
            .modal-content { width: 95%; padding: 2rem 1.5rem; }
            #modal-title { font-size: 1.5rem; }
            button, .btn { padding: 0.8rem 1.2rem; width: 100%; }
            .tool-card button { width: auto; }
            .ad-leaderboard { max-width: 100%; }
        }

    </style>
</head>
<body>

    <header>
        <h1>Multi Tool Hub</h1>
    </header>

    <main>

        <!-- ====================================================== -->
        <!-- AD SLOT 1: TOP BANNER (728x90) -->
        <!-- ====================================================== -->
        <div class="ad-container ad-leaderboard">
            <!-- PASTE YOUR ADSTERRA 728x90 BANNER CODE HERE -->
            <span class="ad-container-placeholder-text">Adsterra 728x90 Ad Space</span>
        </div>
        <!-- ====================================================== -->

        <div id="tool-grid" class="tool-grid">
            <!-- Tool cards will be dynamically inserted here by JavaScript -->
        </div>

        <!-- ====================================================== -->
        <!-- AD SLOT 2: BOTTOM BANNER (728x90) -->
        <!-- ====================================================== -->
        <div class="ad-container ad-leaderboard">
            <!-- PASTE YOUR ADSTERRA 728x90 BANNER CODE HERE -->
            <span class="ad-container-placeholder-text">Adsterra 728x90 Ad Space</span>
        </div>
        <!-- ====================================================== -->

    </main>

    <!-- Reusable Modal for Tools -->
    <div id="modal-container" class="modal-container hidden">
        <div class="modal-content">
            <button class="modal-close-btn" id="modal-close-btn">×</button>
            <h2 id="modal-title">Tool Title</h2>
            <div id="modal-body">
                <!-- Tool-specific UI will be injected here -->
            </div>
        </div>
    </div>

    <script>
    'use strict';

    document.addEventListener('DOMContentLoaded', () => {
        
        const tools = [
            { id: 'imageConverter', title: 'Image Converter', description: 'Convert images between JPG, PNG, and WEBP formats.' },
            { id: 'imageCompressor', title: 'Image Compressor', description: 'Reduce image file size with adjustable quality settings.' },
            { id: 'imageCropper', title: 'Image Cropper', description: 'Upload, crop, and export a specific area of an image.' },
            { id: 'videoConverter', title: 'Video Converter', description: 'Convert short videos between MP4 and WebM. (Browser-based, best for small files)' },
            { id: 'audioConverter', title: 'Audio to WAV Converter', description: 'Convert various audio formats (like MP3) into WAV format.' },
            { id: 'audioTrimmer', title: 'Audio Trimmer', description: 'Trim an audio file by setting start and end times.' },
            { id: 'ageCalculator', title: 'Age Calculator', description: 'Calculate age in years, months, and days from a date of birth.' },
            { id: 'emiCalculator', title: 'EMI Calculator', description: 'Calculate Equated Monthly Installment for loans.' },
            { id: 'sipCalculator', title: 'SIP Calculator', description: 'Calculate the future value of your monthly investments.' },
            { id: 'qrCodeGenerator', title: 'QR Code Generator', description: 'Generate a downloadable QR code from text or a URL.' },
            { id: 'passwordGenerator', title: 'Password Generator', description: 'Create strong, random passwords with custom rules.' },
            { id: 'wordCounter', title: 'Word Counter', description: 'Count words, characters, and estimate reading time in real-time.' },
            { id: 'base64', title: 'Base64 Encoder/Decoder', description: 'Encode text to Base64 or decode from Base64 to text.' },
            { id: 'colorPicker', title: 'Color Picker', description: 'Pick a color and get its HEX, RGB, and HSL values.' },
            { id: 'textToSpeech', title: 'Text to Speech', description: 'Convert written text into spoken audio using your browser\'s voice.' },
            { id: 'speechToText', title: 'Speech to Text', description: 'Use your microphone to convert spoken words into text.' },
            { id: 'jsonFormatter', title: 'JSON Formatter', description: 'Format and validate JSON data with syntax highlighting.' },
            { id: 'unitConverter', title: 'Unit Converter', description: 'Convert between various units of measurement (length, weight, temp).' },
            { id: 'bmiCalculator', title: 'BMI Calculator', description: 'Calculate your Body Mass Index and see your category.' },
            { id: 'timerStopwatch', title: 'Timer / Stopwatch', description: 'A simple timer and stopwatch with lap functionality.' },
        ];

        const toolGrid = document.getElementById('tool-grid');
        const modalContainer = document.getElementById('modal-container');
        const modalTitle = document.getElementById('modal-title');
        const modalBody = document.getElementById('modal-body');
        const modalCloseBtn = document.getElementById('modal-close-btn');

        function renderToolCards() {
            toolGrid.innerHTML = '';
            tools.forEach((tool, index) => {
                const card = document.createElement('div');
                card.className = 'tool-card';
                card.dataset.toolId = tool.id;
                card.style.animationDelay = `${index * 50}ms`;
                card.innerHTML = `<h2>${tool.title}</h2><p>${tool.description}</p><button class="btn-open-tool">Open Tool</button>`;
                toolGrid.appendChild(card);
            });
        }

        function openModal(title, toolId) {
            modalTitle.textContent = title;
            modalBody.innerHTML = getToolHTML(toolId);
            modalContainer.classList.remove('hidden');
            document.body.style.overflow = 'hidden';
            initializeTool(toolId);
        }

        function closeModal() {
            if(window.speechSynthesis && window.speechSynthesis.speaking) window.speechSynthesis.cancel();
            if(window.sttRecognition && window.sttRecognition.abort) window.sttRecognition.abort();
            
            modalContainer.classList.add('hidden');
            document.body.style.overflow = 'auto';
            modalBody.innerHTML = '';
        }

        toolGrid.addEventListener('click', (e) => {
            const card = e.target.closest('.tool-card');
            if (card) {
                const tool = tools.find(t => t.id === card.dataset.toolId);
                if (tool) openModal(tool.title, tool.id);
            }
        });

        modalCloseBtn.addEventListener('click', closeModal);
        modalContainer.addEventListener('click', (e) => { if (e.target === modalContainer) closeModal(); });
        document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && !modalContainer.classList.contains('hidden')) closeModal(); });

        
        function getToolHTML(toolId) {
            let toolHtml = '';
            
            // This is the HTML for the ad that will be placed inside the modal
            const adModalHtml = `
                <!-- ====================================================== -->
                <!-- AD SLOT 3: MODAL BANNER (300x250) -->
                <!-- ====================================================== -->
                <div class="ad-container ad-modal-banner">
                    <!-- PASTE YOUR ADSTERRA 300x250 BANNER CODE HERE -->
                    <span class="ad-container-placeholder-text">Adsterra 300x250 Ad Space</span>
                </div>
                <!-- ====================================================== -->
            `;

            switch (toolId) {
                case 'imageConverter':
                    toolHtml = `
                        <div class="form-group"><label for="image-input">Upload Image:</label><input type="file" id="image-input" accept="image/*"></div>
                        <div class="form-group"><label for="format-select">Convert to:</label><select id="format-select"><option value="jpeg">JPEG</option><option value="png">PNG</option><option value="webp">WEBP</option></select></div>
                        <button id="convert-btn">Convert & Download</button><div id="image-preview" class="tool-output"></div>`;
                    break;
                case 'imageCompressor':
                    toolHtml = `
                        <div class="form-group"><label for="compress-input">Upload Image:</label><input type="file" id="compress-input" accept="image/jpeg,image/png"></div>
                        <div class="form-group"><label for="quality-slider">Quality (0.1 to 1.0):</label><input type="range" id="quality-slider" min="0.1" max="1" step="0.1" value="0.7"><span id="quality-value">0.7</span></div>
                        <button id="compress-btn">Compress & Download</button><div id="compress-output" class="tool-output"></div>`;
                    break;
                case 'imageCropper':
                    toolHtml = `
                        <div class="form-group"><label for="crop-input">Upload Image:</label><input type="file" id="crop-input" accept="image/*"></div>
                        <p>Click and drag on the image to select a crop area.</p><canvas id="crop-canvas" style="cursor: crosshair;"></canvas>
                        <button id="crop-btn" disabled>Crop & Download</button><div id="crop-output" class="tool-output"></div>`;
                    break;
                case 'videoConverter':
                    toolHtml = `
                        <p>This tool converts video in the browser. It works best for small files and may be slow.</p>
                        <div class="form-group"><label for="video-input">Upload Video (MP4 or WebM):</label><input type="file" id="video-input" accept="video/mp4,video/webm"></div>
                        <div class="form-group"><label for="video-format-select">Convert to:</label><select id="video-format-select"><option value="video/webm">WebM</option><option value="video/mp4">MP4 (Experimental)</option></select></div>
                        <button id="video-convert-btn">Convert & Download</button><div id="video-output" class="tool-output"></div>`;
                    break;
                case 'audioConverter':
                    toolHtml = `
                        <p>This tool converts any browser-supported audio format into a high-quality WAV file.</p>
                        <div class="form-group"><label for="audio-input">Upload Audio File:</label><input type="file" id="audio-input" accept="audio/*"></div>
                        <button id="audio-convert-btn">Convert to WAV & Download</button><div id="audio-output" class="tool-output"></div>`;
                    break;
                case 'audioTrimmer':
                    toolHtml = `
                        <div class="form-group"><label for="trim-input">Upload Audio File:</label><input type="file" id="trim-input" accept="audio/*"></div>
                        <div class="form-group"><label>Start Time (seconds):</label><input type="number" id="start-time" value="0" min="0" step="0.1"></div>
                        <div class="form-group"><label>End Time (seconds):</label><input type="number" id="end-time" value="10" min="0" step="0.1"></div>
                        <button id="trim-btn">Trim & Download</button><div id="trim-output" class="tool-output"></div>`;
                    break;
                case 'ageCalculator':
                    toolHtml = `
                        <div class="form-group"><label for="dob-input">Enter your Date of Birth:</label><input type="date" id="dob-input"></div>
                        <button id="calculate-age-btn">Calculate Age</button><div id="age-result" class="result-box"></div>`;
                    break;
                case 'emiCalculator':
                    toolHtml = `
                        <div class="form-group"><label for="loan-amount">Loan Amount ($):</label><input type="number" id="loan-amount" placeholder="e.g., 100000"></div>
                        <div class="form-group"><label for="interest-rate">Annual Interest Rate (%):</label><input type="number" id="interest-rate" placeholder="e.g., 7.5"></div>
                        <div class="form-group"><label for="loan-tenure">Loan Tenure (Years):</label><input type="number" id="loan-tenure" placeholder="e.g., 10"></div>
                        <button id="calculate-emi-btn">Calculate EMI</button><div id="emi-result" class="result-box"></div>`;
                    break;
                case 'sipCalculator':
                    toolHtml = `
                        <div class="form-group"><label for="monthly-investment">Monthly Investment ($):</label><input type="number" id="monthly-investment" placeholder="e.g., 500"></div>
                        <div class="form-group"><label for="sip-rate">Expected Annual Return Rate (%):</label><input type="number" id="sip-rate" placeholder="e.g., 12"></div>
                        <div class="form-group"><label for="sip-duration">Investment Duration (Years):</label><input type="number" id="sip-duration" placeholder="e.g., 15"></div>
                        <button id="calculate-sip-btn">Calculate Future Value</button><div id="sip-result" class="result-box"></div>`;
                    break;
                case 'qrCodeGenerator':
                    toolHtml = `
                        <div class="form-group"><label for="qr-text">Text or URL to encode:</label><textarea id="qr-text" rows="4" placeholder="Enter text or URL here..."></textarea></div>
                        <button id="generate-qr-btn">Generate QR Code</button>
                        <div id="qr-code-container" class="tool-output" style="text-align:center; background:white; padding:10px; display:none; border-radius: 8px; margin-top:1rem;"></div>
                        <a id="download-qr-link" class="btn" style="display:none; margin-top:1rem;">Download QR</a>`;
                    break;
                case 'passwordGenerator':
                    toolHtml = `
                        <div class="form-group"><label for="pass-length">Password Length:</label><input type="number" id="pass-length" value="16" min="8" max="128"></div>
                        <div class="form-group" style="display: flex; align-items: center;"><input type="checkbox" id="include-uppercase" checked> <label for="include-uppercase" style="margin-bottom:0;">Include Uppercase</label></div>
                        <div class="form-group" style="display: flex; align-items: center;"><input type="checkbox" id="include-numbers" checked> <label for="include-numbers" style="margin-bottom:0;">Include Numbers</label></div>
                        <div class="form-group" style="display: flex; align-items: center;"><input type="checkbox" id="include-symbols" checked> <label for="include-symbols" style="margin-bottom:0;">Include Symbols</label></div>
                        <button id="generate-pass-btn">Generate Password</button><div id="password-result" class="tool-output" style="user-select:all; cursor:copy;">Click to copy</div>`;
                    break;
                case 'wordCounter':
                    toolHtml = `
                        <div class="form-group"><label for="text-area">Paste your text below:</label><textarea id="text-area" rows="8" placeholder="Start typing or paste text here..."></textarea></div>
                        <div id="word-count-result" class="result-box"><strong>Words:</strong> 0 | <strong>Characters:</strong> 0 | <strong>Reading Time:</strong> 0 min</div>`;
                    break;
                case 'base64':
                    toolHtml = `
                        <div class="form-group"><label for="base64-input">Input Text:</label><textarea id="base64-input" rows="5"></textarea></div>
                        <button id="base64-encode-btn">Encode to Base64</button><button id="base64-decode-btn" style="margin-top:0.5rem;">Decode from Base64</button>
                        <div class="form-group" style="margin-top:1rem;"><label for="base64-output">Output:</label><textarea id="base64-output" rows="5" readonly></textarea></div>`;
                    break;
                case 'colorPicker':
                    toolHtml = `
                        <div class="form-group" style="text-align:center;"><label for="color-input">Pick a Color:</label><input type="color" id="color-input" value="#FFD700"></div>
                        <div id="color-values" class="result-box"><p><strong>HEX:</strong> <span id="hex-value"></span></p><p><strong>RGB:</strong> <span id="rgb-value"></span></p><p><strong>HSL:</strong> <span id="hsl-value"></span></p></div>`;
                    break;
                case 'textToSpeech':
                    toolHtml = `
                        <div class="form-group"><label for="tts-text">Text to Speak:</label><textarea id="tts-text" rows="5" placeholder="Enter text here..."></textarea></div>
                        <div class="form-group"><label for="tts-voice">Voice:</label><select id="tts-voice"></select></div>
                        <button id="speak-btn">Speak</button>`;
                    break;
                case 'speechToText':
                    toolHtml = `
                        <p>Click the button and start speaking. Your browser will ask for microphone permission.</p>
                        <button id="stt-btn">Start Listening</button><div id="stt-result" class="tool-output" style="min-height: 100px;"></div>`;
                    break;
                case 'jsonFormatter':
                    toolHtml = `
                        <div class="form-group"><label for="json-input">Paste your JSON here:</label><textarea id="json-input" rows="10" placeholder='{"key": "value", "number": 123}'></textarea></div>
                        <button id="format-json-btn">Format / Validate</button><pre id="json-output" class="tool-output" style="white-space: pre-wrap;"></pre>`;
                    break;
                case 'unitConverter':
                    toolHtml = `
                        <div class="form-group"><label for="unit-category">Category:</label><select id="unit-category"><option value="length">Length</option><option value="weight">Weight</option><option value="temperature">Temperature</option></select></div>
                        <div class="form-group"><input type="number" id="unit-input" placeholder="Enter value"><select id="unit-from"></select></div>
                        <div class="form-group"><input type="number" id="unit-output" readonly><select id="unit-to"></select></div>`;
                    break;
                case 'bmiCalculator':
                    toolHtml = `
                        <div class="form-group"><label for="weight">Weight (kg):</label><input type="number" id="weight" placeholder="e.g., 70"></div>
                        <div class="form-group"><label for="height">Height (cm):</label><input type="number" id="height" placeholder="e.g., 175"></div>
                        <button id="calculate-bmi-btn">Calculate BMI</button><div id="bmi-result" class="result-box"></div>`;
                    break;
                case 'timerStopwatch':
                    toolHtml = `
                        <div style="text-align:center; font-size: 3rem; font-family: 'Courier New', monospace;" id="display">00:00.00</div>
                        <div style="text-align:center; margin-top:1rem;"><button id="start-stop-btn">Start</button><button id="reset-lap-btn" style="margin-top:0.5rem;">Reset</button></div>
                        <div id="laps" class="tool-output" style="margin-top: 1rem; max-height: 150px; overflow-y: auto;"></div>`;
                    break;
                default:
                    toolHtml = `<p>Tool not found.</p>`;
            }
            // Add the ad HTML to the end of every tool's HTML
            return toolHtml + adModalHtml;
        }

        // The rest of the JavaScript logic (initializeTool and all tool functions) remains the same.
        // It's long, so I am omitting it here for brevity, but you should copy it from the previous complete answer.
        // ALL THE TOOL LOGIC FUNCTIONS (like initImageConverter, initBmiCalculator, etc.) GO HERE...
        // ...
        // ... Paste the functions from the original script here ...
        // ...
        function initializeTool(toolId){switch(toolId){case'imageConverter':setupFileConverter('image-input','format-select','convert-btn','image-preview');break;case'imageCompressor':initImageCompressor();break;case'imageCropper':initImageCropper();break;case'videoConverter':initVideoConverter();break;case'audioConverter':initAudioConverter();break;case'audioTrimmer':initAudioTrimmer();break;case'ageCalculator':initAgeCalculator();break;case'emiCalculator':initEmiCalculator();break;case'sipCalculator':initSipCalculator();break;case'qrCodeGenerator':initQrCodeGenerator();break;case'passwordGenerator':initPasswordGenerator();break;case'wordCounter':initWordCounter();break;case'base64':initBase64();break;case'colorPicker':initColorPicker();break;case'textToSpeech':initTextToSpeech();break;case'speechToText':initSpeechToText();break;case'jsonFormatter':initJsonFormatter();break;case'unitConverter':initUnitConverter();break;case'bmiCalculator':initBmiCalculator();break;case'timerStopwatch':initTimerStopwatch();break;}}
        function setupFileConverter(a,b,c,d){const e=document.getElementById(a),f=document.getElementById(b),g=document.getElementById(c),h=document.getElementById(d);g.addEventListener('click',()=>{if(0===e.files.length)return void(h.innerHTML='<p style="color: #ff6b6b;">Please upload a file first.</p>');const a=e.files[0],b=new FileReader;h.textContent='Processing...',b.onload=a=>{const b=new Image;b.onload=()=>{const c=document.createElement('canvas');c.width=b.width,c.height=b.height;const e=c.getContext('2d');e.drawImage(b,0,0);const i=f.value,j=`image/${i}`,k=c.toDataURL(j);h.innerHTML=`<strong>Preview:</strong><br><img src="${k}" style="max-width:100%; height:auto; margin-top: 1rem; border-radius: 5px;">`;const l=document.createElement('a');l.href=k,l.download=`converted.${i}`,l.textContent=`Download as ${i.toUpperCase()}`,l.className='btn',l.style.display='block',l.style.marginTop='1rem',h.appendChild(l)},b.onerror=()=>{h.innerHTML='<p style="color: #ff6b6b;">Could not load the uploaded file as an image.</p>'},b.src=a.target.result},b.readAsDataURL(a)})}
        function initImageCompressor(){const a=document.getElementById('compress-input'),b=document.getElementById('quality-slider'),c=document.getElementById('quality-value'),d=document.getElementById('compress-btn'),e=document.getElementById('compress-output');b.addEventListener('input',()=>{c.textContent=b.value}),d.addEventListener('click',()=>{if(0===a.files.length)return void(e.innerHTML='<p style="color: #ff6b6b;">Please upload an image.</p>');const c=a.files[0],d=parseFloat(b.value),f=new FileReader;e.textContent='Compressing...',f.onload=b=>{const f=new Image;f.onload=()=>{const g=document.createElement('canvas');g.width=f.width,g.height=f.height;const h=g.getContext('2d');h.drawImage(f,0,0);const i='image/jpeg',j=g.toDataURL(i,d),k=(c.size/1024).toFixed(2),l=(atob(j.split(',')[1]).length/1024).toFixed(2);e.innerHTML=`\n                        <p>Original Size: <strong>${k} KB</strong></p>\n                        <p>Compressed Size: <strong>${l} KB</strong></p>\n                        <img src="${j}" style="max-width:100%; height:auto; margin-top:1rem; border-radius: 5px;">\n                    `;const m=document.createElement('a');m.href=j,m.download=`compressed_${c.name}.jpg`,m.textContent='Download Compressed Image',m.className='btn',m.style.display='block',m.style.marginTop='1rem',e.appendChild(m)},f.onerror=()=>{e.innerHTML='<p style="color: #ff6b6b;">Could not load the uploaded file as an image.</p>'},f.src=b.target.result},f.readAsDataURL(c)})}
        function initImageCropper(){const a=document.getElementById('crop-input'),b=document.getElementById('crop-canvas'),c=b.getContext('2d'),d=document.getElementById('crop-btn'),e=document.getElementById('crop-output');let f,g={},h=!1;a.addEventListener('change',a=>{const i=a.target.files[0];if(!i)return;e.textContent='Loading image...';const j=new FileReader;j.onload=a=>{f=new Image,f.onload=()=>{const a=f.width/f.height,g=500;b.width=Math.min(f.width,g),b.height=b.width/a,c.drawImage(f,0,0,b.width,b.height),d.disabled=!0,e.textContent=''},f.onerror=()=>{e.innerHTML='<p style="color: #ff6b6b;">Could not load the file as an image.</p>'},f.src=a.target.result},j.readAsDataURL(i)});const i=function(a,b){const c=a.getBoundingClientRect();return{x:b.clientX-c.left,y:b.clientY-c.top}};b.addEventListener('mousedown',a=>{if(!f)return;const b=i(b,a);g.startX=b.x,g.startY=b.y,h=!0}),b.addEventListener('mousemove',a=>{if(!h||!f)return;const d=i(b,a);c.clearRect(0,0,b.width,b.height),c.drawImage(f,0,0,b.width,b.height),g.w=d.x-g.startX,g.h=d.y-g.startY,c.strokeStyle='#FFD700',c.lineWidth=2,c.strokeRect(g.startX,g.startY,g.w,g.h)}),b.addEventListener('mouseup',()=>{h=!1,d.disabled=!1}),b.addEventListener('mouseout',()=>{h=!1}),d.addEventListener('click',()=>{if(!g.w||!g.h)return void(e.innerHTML='<p style="color: #ff6b6b;">Please make a selection first.</p>');const a=f.width/b.width,h=f.height/b.height,i=document.createElement('canvas'),j=g.startX*a,k=g.startY*h,l=g.w*a,m=g.h*h;i.width=Math.abs(l),i.height=Math.abs(m);const n=i.getContext('2d');n.drawImage(f,Math.min(j,j+l),Math.min(k,k+m),Math.abs(l),Math.abs(m),0,0,i.width,i.height);const o=i.toDataURL('image/png');e.innerHTML=`<img src="${o}" style="max-width:100%; border-radius: 5px;">`;const p=document.createElement('a');p.href=o,p.download='cropped-image.png',p.className='btn',p.style.display='block',p.style.marginTop='1rem',p.textContent='Download Cropped Image',e.appendChild(p)})}
        function initVideoConverter(){const a=document.getElementById('video-input'),b=document.getElementById('video-format-select'),c=document.getElementById('video-convert-btn'),d=document.getElementById('video-output');c.addEventListener('click',()=>{if(!window.MediaRecorder)return void(d.innerHTML='<p style="color: #ff6b6b;">Video conversion is not supported by your browser (MediaRecorder API is missing).</p>');if(0===a.files.length)return void(d.innerHTML='<p style="color: #ff6b6b;">Please upload a video file.</p>');const e=a.files[0],f=b.value;if(!MediaRecorder.isTypeSupported(f))return void(d.innerHTML=`<p style="color: #ff6b6b;">Your browser does not support encoding to ${f}. Try another format.</p>`);d.textContent='Processing... This can take a while and may use significant resources.',c.disabled=!0;const g=URL.createObjectURL(e),h=document.createElement('video');h.src=g,h.muted=!0;const i=[];h.addEventListener('loadedmetadata',()=>{const a=h.captureStream?h.captureStream():h.mozCaptureStream();if(!a)return c.disabled=!1,void(d.innerHTML='<p style="color: #ff6b6b;">Could not capture video stream. This feature may not work on your browser.</p>');const b=new MediaRecorder(a,{mimeType:f});b.ondataavailable=a=>{a.data.size>0&&i.push(a.data)},b.onstop=()=>{const a=new Blob(i,{type:f}),b=URL.createObjectURL(a),e=f.split('/')[1].split(';')[0];d.innerHTML=`\n                            <p>Conversion complete!</p>\n                            <video controls src="${b}" style="max-width:100%; margin-top:1rem; border-radius: 5px;"></video>\n                            <a href="${b}" download="converted.${e}" class="btn" style="display:block; margin-top:1rem;">Download Video</a>\n                        `,c.disabled=!1,URL.revokeObjectURL(g)},h.play(),b.start()},{once:!0}),h.addEventListener('ended',()=>{h.pause(),h.src="",h.currentTime>0&&h.stream?.active&&h.stream.getTracks().forEach(a=>a.stop())},{once:!0})})}
        const audioContext=new(window.AudioContext||window.webkitAudioContext);function bufferToWav(a){const b=a.numberOfChannels,c=a.length*b*2+44,d=new ArrayBuffer(c),e=new DataView(d),f=[];let g,h,i=0,j=0;const k=a=>{e.setUint16(j,a,!0),j+=2},l=a=>{e.setUint32(j,a,!0),j+=4};l(1179011410),l(c-8),l(1163280727),l(544501094),l(16),k(1),k(b),l(a.sampleRate),l(a.sampleRate*2*b),k(b*2),k(16),l(1635017060),l(c-j-4);for(g=0;g<a.numberOfChannels;g++)f.push(a.getChannelData(g));for(;j<c;)for(g=0;g<b;g++)h=Math.max(-1,Math.min(1,f[g][i])),h=h<0?32768*h:32767*h,e.setInt16(j,h,!0),j+=2,i++;return new Blob([e],{type:'audio/wav'})}
        function initAudioConverter(){const a=document.getElementById('audio-input'),b=document.getElementById('audio-convert-btn'),c=document.getElementById('audio-output');b.addEventListener('click',()=>{if(0===a.files.length)return void(c.innerHTML='<p style="color: #ff6b6b;">Please upload an audio file.</p>');const d=a.files[0],e=new FileReader;c.textContent='Processing...',b.disabled=!0,e.onload=async a=>{try{const d=await audioContext.decodeAudioData(a.target.result),e=bufferToWav(d),f=URL.createObjectURL(e);c.innerHTML=`\n                        <p>Conversion to WAV successful!</p>\n                        <audio controls src="${f}" style="width:100%; margin-top:1rem;"></audio>\n                        <a href="${f}" download="converted.wav" class="btn" style="display:block; margin-top:1rem;">Download WAV</a>\n                    `}catch(a){c.innerHTML=`<p style="color: #ff6b6b;">Error processing audio: ${a.message}</p>`}finally{b.disabled=!1}},e.readAsArrayBuffer(d)})}
        function initAudioTrimmer(){const a=document.getElementById('trim-input'),b=document.getElementById('start-time'),c=document.getElementById('end-time'),d=document.getElementById('trim-btn'),e=document.getElementById('trim-output');let f;a.addEventListener('change',a=>{const g=a.target.files[0];if(!g)return;const h=new FileReader;e.textContent='Loading audio file...',h.onload=async a=>{try{f=await audioContext.decodeAudioData(a.target.result),c.value=f.duration.toFixed(2),e.textContent=`File loaded. Duration: ${f.duration.toFixed(2)}s. Ready to trim.`}catch(a){e.innerHTML=`<p style="color: #ff6b6b;">Error: ${a.message}</p>`}},h.readAsArrayBuffer(g)}),d.addEventListener('click',()=>{if(!f)return void(e.innerHTML='<p style="color: #ff6b6b;">Please upload an audio file first.</p>');const a=parseFloat(b.value),g=parseFloat(c.value);if(isNaN(a)||isNaN(g)||a>=g||a<0||g>f.duration)return void(e.innerHTML='<p style="color: #ff6b6b;">Invalid start/end times.</p>');e.textContent='Trimming...',d.disabled=!0;try{const b=Math.floor((g-a)*f.sampleRate),c=Math.floor(a*f.sampleRate),h=audioContext.createBuffer(f.numberOfChannels,b,f.sampleRate);for(let a=0;a<f.numberOfChannels;a++)f.copyFromChannel(h.getChannelData(a),a,c);const i=bufferToWav(h),j=URL.createObjectURL(i);e.innerHTML=`\n                    <p>Trimming successful!</p>\n                    <audio controls src="${j}" style="width:100%; margin-top:1rem;"></audio>\n                    <a href="${j}" download="trimmed.wav" class="btn" style="display:block; margin-top:1rem;">Download Trimmed Audio</a>\n                `}catch(a){e.innerHTML=`<p style="color: #ff6b6b;">Error trimming: ${a.message}</p>`}finally{d.disabled=!1}})}
        function initAgeCalculator(){const a=document.getElementById('dob-input'),b=document.getElementById('calculate-age-btn'),c=document.getElementById('age-result');b.addEventListener('click',()=>{const b=a.value;if(!b)return void(c.innerHTML='<p style="color: #ff6b6b;">Please enter a valid date.</p>');const d=new Date(b),e=new Date;if(d>e)return void(c.innerHTML='<p style="color: #ff6b6b;">Date of birth cannot be in the future.</p>');let f=e.getFullYear()-d.getFullYear(),g=e.getMonth()-d.getMonth(),h=e.getDate()-d.getDate();h<0&&(g--,h+=new Date(e.getFullYear(),e.getMonth(),0).getDate()),g<0&&(f--,g+=12),c.innerHTML=`Your age is: <strong>${f}</strong> years, <strong>${g}</strong> months, and <strong>${h}</strong> days.`})}
        function initEmiCalculator(){const a=document.getElementById('loan-amount'),b=document.getElementById('interest-rate'),c=document.getElementById('loan-tenure'),d=document.getElementById('calculate-emi-btn'),e=document.getElementById('emi-result');d.addEventListener('click',()=>{const d=parseFloat(a.value),f=parseFloat(b.value),g=parseFloat(c.value);if(isNaN(d)||isNaN(f)||isNaN(g)||d<=0||f<=0||g<=0)return void(e.innerHTML='<p style="color: #ff6b6b;">Please enter valid positive numbers for all fields.</p>');const h=f/12/100,i=12*g,j=d*h*Math.pow(1+h,i)/(Math.pow(1+h,i)-1),k=j*i,l=k-d;e.innerHTML=`\n                    <p>Monthly EMI: <strong>$${j.toFixed(2)}</strong></p>\n                    <p>Total Interest Payable: <strong>$${l.toFixed(2)}</strong></p>\n                    <p>Total Payment: <strong>$${k.toFixed(2)}</strong></p>\n                `})}
        function initSipCalculator(){const a=document.getElementById('monthly-investment'),b=document.getElementById('sip-rate'),c=document.getElementById('sip-duration'),d=document.getElementById('calculate-sip-btn'),e=document.getElementById('sip-result');d.addEventListener('click',()=>{const d=parseFloat(a.value),f=parseFloat(b.value),g=parseFloat(c.value);if(isNaN(d)||isNaN(f)||isNaN(g)||d<=0||f<=0||g<=0)return void(e.innerHTML='<p style="color: #ff6b6b;">Please enter valid positive numbers for all fields.</p>');const h=f/100/12,i=12*g,j=d*((Math.pow(1+h,i)-1)/h)*(1+h),k=d*i,l=j-k;e.innerHTML=`\n                    <p>Total Invested Amount: <strong>$${k.toFixed(2)}</strong></p>\n                    <p>Estimated Returns: <strong>$${l.toFixed(2)}</strong></p>\n                    <p>Future Value: <strong>$${j.toFixed(2)}</strong></p>\n                `})}
        function initQrCodeGenerator(){const a=document.getElementById('qr-text'),b=document.getElementById('generate-qr-btn'),c=document.getElementById('qr-code-container'),d=document.getElementById('download-qr-link');var e;(function(){function a(a,b){var c=document.createElement("canvas");return c.width=a,c.height=b,c.getContext("2d")}function f(a,b,c){for(var d=0;d<b;d++)if(function(a,b){var c=Math.floor(a/8),d=1<<(7-a%8);return(b[c]&d)!=0}(a+d,c))throw new Error("Bit "+(a+d)+" is already set");for(var d=0;d<b;d++){var e=Math.floor((a+d)/8),g=1<<(7-a+d%8);c[e]|=g}}function p(a){var b=j(a,i());b=m(b),b=k(b),b=l(b),b=n(b);var c=w(a,i()),d=x(c);return b=o(b,d),b}function q(b,c,d){var e=document.createElement("canvas");e.width=c,e.height=d;var f=e.getContext("2d"),g=f.createImageData(c,d),h=b;for(var i=0;i<d;i++)for(var j=0;j<c;j++){var k=4*(i*c+j),l=h[i][j];l?(g.data[k]=0,g.data[k+1]=0,g.data[k+2]=0,g.data[k+3]=255):(g.data[k]=255,g.data[k+1]=255,g.data[k+2]=255,g.data[k+3]=255)}f.putImageData(g,0,0);var m=document.createElement("a");m.href=e.toDataURL("image/png");var n=document.createElement("img");return n.src=m.href,n}function v(a,b,c){var d=c.bit,e=c.bytes,g=[];f(b,c.length,g);for(var h=0;h<a.length;h++){var i=a[h].data;for(var j=0;j<d;j++){var k=Math.floor((i&1<<(d-1-j))>>d-1-j);f(k,1,g)}i=a[h].mode,f(i,4,g);var l=a[h].chars;f(l,e,g)}var m=new Array(g.length/8);for(h=0;h<m.length;h++)for(var j=0;j<8;j++)m[h]=m[h]<<1,m[h]|=g[h*8+j];return m}function y(a,b){var c=p(a);return q(c.map,b,b)}var D=[new C(0,1,19,7),new C(0,1,16,10),new C(0,1,13,13),new C(0,1,9,17),new C(1,1,34,10),new C(1,1,28,16),new C(1,1,22,22),new C(1,1,16,28),new C(2,1,55,15),new C(2,1,44,26),new C(2,2,17,18),new C(2,2,13,22),new C(3,1,80,20),new C(3,2,32,18),new C(3,2,24,26),new C(3,4,9,16),new C(4,2,50,26),new C(4,4,18,16),new C(4,2,22,28),new C(4,4,16,24),new C(5,2,64,18),new C(5,4,24,22),new C(5,4,18,26),new C(5,4,14,28),new C(6,2,78,20),new C(6,4,28,24),new C(6,6,16,28),new C(6,4,22,18),new C(7,4,48,26),new C(7,4,20,18),new C(7,4,18,32),new C(7,4,26,24),new C(8,4,58,28),new C(8,4,24,22),new C(8,8,16,20),new C(8,4,22,26),new C(9,5,64,24),new C(9,5,26,26),new C(9,5,20,30),new C(9,5,24,28),new C(10,5,74,28),new C(10,5,26,28),new C(10,7,24,28),new C(10,7,28,26)],E=[[26,D[0],D[1],D[2],D[3]],[44,D[4],D[5],D[6],D[7]],[70,D[8],D[9],D[10],D[11]],[100,D[12],D[13],D[14],D[15]],[134,D[16],D[17],D[18],D[19]],[172,D[20],D[21],D[22],D[23]],[196,D[24],D[25],D[26],D[27]],[242,D[28],D[29],D[30],D[31]],[292,D[32],D[33],D[34],D[35]],[346,D[36],D[37],D[38],D[39]],[404,D[40],D[41],D[42],D[43]]],F=[function(a,b){return(a+b)%2==0},function(a,b){return a%2==0},function(a,b){return b%3==0},function(a,b){return(a+b)%3==0},function(a,b){return(Math.floor(a/2)+Math.floor(b/3))%2==0},function(a,b){return a*b%2+a*b%3==0},function(a,b){return(a*b%2+a*b%3)%2==0},function(a,b){return(a*b%3+(a+b)%2)%2==0}],G=[new B(1,9,function(a){var b=[];for(var c=0;c<10;c++)b[c]=a>>c&1;return b.reverse()},null),new B(2,255,function(a){var b=[];for(var c=0;c<8;c++)b[c]=a>>c&1;return b.reverse()},null)],H=[new A(0,10,9),new A(0,12,11),new A(0,14,13),new A(1,9,8),new A(1,11,10),new A(1,13,12),new A(2,9,7),new A(2,11,9),new A(2,13,11),new A(3,8,7),new A(3,10,9),new A(3,12,10)],I=[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146]],J=[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,_TEXT="text",_CANVAS="canvas",QRCode={draw:function(a,b,c){var d=document.getElementById(b),e=d.getContext("2d"),f=y(a,c);d.parentNode.replaceChild(f,d)}}]];e=e})();b.addEventListener('click',()=>{const b=a.value.trim();if(!b)return c.innerHTML='<p style="color: #ff6b6b;">Please enter text or a URL.</p>',c.style.display='block',void(d.style.display='none');c.style.display='block',c.innerHTML='';try{const a=document.createElement('canvas');QRCode.draw(b,a,256),c.appendChild(a),d.href=a.toDataURL('image/png'),d.download='qrcode.png',d.style.display='inline-block'}catch(a){c.innerHTML=`<p style="color: #ff6b6b;">Error generating QR Code: ${a.message}</p>`,d.style.display='none'}})}
        function initPasswordGenerator(){const a=document.getElementById('pass-length'),b=document.getElementById('include-numbers'),c=document.getElementById('include-symbols'),d=document.getElementById('include-uppercase'),e=document.getElementById('generate-pass-btn'),f=document.getElementById('password-result'),g={lower:'abcdefghijklmnopqrstuvwxyz',upper:'ABCDEFGHIJKLMNOPQRSTUVWXYZ',numbers:'0123456789',symbols:'!@#$%^&*()_+-=[]{}|;:,.<>?'},h=()=>{const e=parseInt(a.value);let h=g.lower,i='';const j=[];d.checked&&(h+=g.upper,j.push(g.upper[Math.floor(Math.random()*g.upper.length)])),b.checked&&(h+=g.numbers,j.push(g.numbers[Math.floor(Math.random()*g.numbers.length)])),c.checked&&(h+=g.symbols,j.push(g.symbols[Math.floor(Math.random()*g.symbols.length)])),j.push(g.lower[Math.floor(Math.random()*g.lower.length)]);for(let a=j.length;a<e;a++)i+=h.charAt(Math.floor(Math.random()*h.length));const k=(i+j.join('')).split('').sort(()=>.5-Math.random()).join('');f.textContent=k};e.addEventListener('click',h),f.addEventListener('click',()=>{if(f.textContent.includes("Click to copy"))return;navigator.clipboard.writeText(f.textContent).then(()=>{const a=f.textContent;f.textContent='Copied!',setTimeout(()=>{f.textContent=a},1500)})}),h()}
        function initWordCounter(){const a=document.getElementById('text-area'),b=document.getElementById('word-count-result');a.addEventListener('input',()=>{const c=a.value,d=c.trim().split(/\s+/).filter(a=>a.length>0),e=""===c.trim()?0:d.length,f=c.length,g=Math.ceil(e/200);b.innerHTML=`\n                    <strong>Words:</strong> ${e} | \n                    <strong>Characters:</strong> ${f} | \n                    <strong>Reading Time:</strong> ~${g} min\n                `})}
        function initBase64(){const a=document.getElementById('base64-input'),b=document.getElementById('base64-output'),c=document.getElementById('base64-encode-btn'),d=document.getElementById('base64-decode-btn');c.addEventListener('click',()=>{try{b.value=btoa(unescape(encodeURIComponent(a.value)))}catch(a){b.value='Error: Invalid characters for encoding.'}}),d.addEventListener('click',()=>{try{b.value=decodeURIComponent(escape(atob(a.value)))}catch(a){b.value='Error: Invalid Base64 string.'}})}
        function initColorPicker(){const a=document.getElementById('color-input'),b=document.getElementById('hex-value'),c=document.getElementById('rgb-value'),d=document.getElementById('hsl-value');function e(e){b.textContent=e.toUpperCase();const f=parseInt(e.slice(1,3),16),g=parseInt(e.slice(3,5),16),h=parseInt(e.slice(5,7),16);c.textContent=`rgb(${f}, ${g}, ${h})`;const i=f/255,j=g/255,k=h/255,l=Math.max(i,j,k),m=Math.min(i,j,k);let n,o,p=(l+m)/2;if(l===m)n=o=0;else{const a=l-m;switch(o=p>.5?a/(2-l-m):a/(l+m),l){case i:n=(j-k)/a+(j<k?6:0);break;case j:n=(k-i)/a+2;break;case k:n=(i-j)/a+4}n/=6}d.textContent=`hsl(${Math.round(360*n)}, ${Math.round(100*o)}%, ${Math.round(100*p)}%)`}a.addEventListener('input',()=>e(a.value)),e(a.value)}
        function initTextToSpeech(){const a=document.getElementById('tts-text'),b=document.getElementById('tts-voice'),c=document.getElementById('speak-btn');let d=[];function e(){if("undefined"==typeof speechSynthesis)return c.disabled=!0,b.disabled=!0,void(a.placeholder="Text-to-Speech is not supported in your browser.");d=speechSynthesis.getVoices();const e=b.value;b.innerHTML='',d.forEach(a=>{const c=document.createElement('option');c.textContent=`${a.name} (${a.lang})`,c.value=a.name,b.appendChild(c)}),b.value=e}e(),void 0!==speechSynthesis.onvoiceschanged&&(speechSynthesis.onvoiceschanged=e),c.addEventListener('click',()=>{if(speechSynthesis.speaking)speechSynthesis.cancel();if(""!==a.value){const e=new SpeechSynthesisUtterance(a.value),f=b.value;e.voice=d.find(a=>a.name===f),e.onend=()=>{c.textContent="Speak"},speechSynthesis.speak(e),c.textContent="Stop"}})}
        function initSpeechToText(){const a=document.getElementById('stt-btn'),b=document.getElementById('stt-result'),c=window.SpeechRecognition||window.webkitSpeechRecognition;if(!c)return a.disabled=!0,void(b.innerHTML='<p style="color: #ff6b6b;">Speech Recognition API is not supported in your browser.</p>');const d=new c;window.sttRecognition=d,d.continuous=!0,d.interimResults=!0,a.addEventListener('click',()=>{"Start Listening"===a.textContent?d.start():d.stop()}),d.onstart=()=>{a.textContent='Stop Listening'},d.onend=()=>{a.textContent='Start Listening'},d.onerror=a=>{b.innerHTML=`<p style="color: #ff6b6b;">Error: ${a.error}</p>`};let e='';d.onresult=a=>{let c='';for(let b=a.resultIndex;b<a.results.length;++b)a.results[b].isFinal?e+=a.results[b][0].transcript:c+=a.results[b][0].transcript;b.innerHTML=`${e}<span style="color:#999">${c}</span>`}}
        function initJsonFormatter(){const a=document.getElementById('json-input'),b=document.getElementById('format-json-btn'),c=document.getElementById('json-output');b.addEventListener('click',()=>{try{const b=JSON.parse(a.value),d=JSON.stringify(b,null,4);c.textContent=d,c.style.color='var(--text-color)'}catch(a){c.textContent=`Invalid JSON: ${a.message}`,c.style.color='#ff6b6b'}})}
        function initUnitConverter(){const a=document.getElementById('unit-category'),b=document.getElementById('unit-from'),c=document.getElementById('unit-to'),d=document.getElementById('unit-input'),e=document.getElementById('unit-output'),f={length:{Meter:1,Kilometer:1e3,Centimeter:.01,Mile:1609.34,Foot:.3048,Inch:.0254},weight:{Gram:1,Kilogram:1e3,Pound:453.592,Ounce:28.3495},temperature:{Celsius:a=>a,Fahrenheit:a=>9*a/5+32,Kelvin:a=>a+273.15}},g={Celsius:a=>a,Fahrenheit:a=>(a-32)*5/9,Kelvin:a=>a-273.15};function h(){const d=a.value;b.innerHTML='',c.innerHTML='';for(const a in f[d])b.add(new Option(a,a)),c.add(new Option(a,a));"temperature"===d&&(c.value='Fahrenheit'),i()}function i(){const a=parseFloat(d.value);if(isNaN(a))return void(e.value='');const h=categorySelect.value,j=b.value,k=c.value;let l;l="temperature"===h?f.temperature[k](g[j](a)):a*f[h][j]/f[h][k],e.value=l%1!=0?l.toFixed(4):l}[a,b,c].forEach(a=>a.addEventListener('change',i)),d.addEventListener('input',i),h()}
        function initBmiCalculator(){const a=document.getElementById('weight'),b=document.getElementById('height'),c=document.getElementById('calculate-bmi-btn'),d=document.getElementById('bmi-result');c.addEventListener('click',()=>{const c=parseFloat(a.value),e=parseFloat(b.value)/100;if(isNaN(c)||isNaN(e)||c<=0||e<=0)return void(d.innerHTML='<p style="color: #ff6b6b;">Please enter valid weight and height.</p>');const f=c/(e*e);let g;g=f<18.5?"Underweight":f<24.9?"Normal weight":f<29.9?"Overweight":"Obesity",d.innerHTML=`Your BMI is <strong>${f.toFixed(2)}</strong>. Category: <strong>${g}</strong>.`})}
        function initTimerStopwatch(){const a=document.getElementById('display'),b=document.getElementById('start-stop-btn'),c=document.getElementById('reset-lap-btn'),d=document.getElementById('laps');let e=0,f=0,g;const h=a=>{const b=String(a%1e3).padStart(3,'0').slice(0,2),c=String(Math.floor(a/1e3)%60).padStart(2,'0'),d=String(Math.floor(a/1e3/60)%60).padStart(2,'0');return`${d}:${c}.${b}`},i=()=>{a.textContent=h(Date.now()-e+f)};let j=!1;b.addEventListener('click',()=>{j?((f+=Date.now()-e),clearInterval(g),b.textContent='Start',c.textContent='Reset',j=!1):(e=Date.now(),g=setInterval(i,10),b.textContent='Stop',c.textContent='Lap',j=!0)}),c.addEventListener('click',()=>{if(j){const b=document.createElement('p');b.textContent=`Lap ${d.children.length+1}: ${a.textContent}`,d.prepend(b)}else clearInterval(g),f=0,a.textContent='00:00.00',d.innerHTML=''}),modalContainer.addEventListener('transitionend',()=>{modalContainer.classList.contains('hidden')&&clearInterval(g)},!1)}


        // --- INITIALIZE APP ---
        renderToolCards();
    });
    </script>
    
    <!-- ====================================================== -->
    <!-- AD SLOT 4: POP-UNDER / DIRECT LINK SCRIPT -->
    <!-- ====================================================== -->
    <!-- PASTE YOUR ADSTERRA POP-UNDER OR DIRECT LINK SCRIPT HERE -->
    <!-- ====================================================== -->

</body>
</html>

Post a Comment

0 Comments