From e218a6453fffeeb8ef8791b65d139238dec6142d Mon Sep 17 00:00:00 2001
From: Reza Mehdikhanlou <rezamehdikhanlou@gmail.com>
Date: Sun, 11 May 2025 18:34:37 +0330
Subject: [PATCH 1/4] Adding Day #80

---
 Day #80 - Google Recaptcha/README.md        |  23 +++
 Day #80 - Google Recaptcha/index.html       |  39 ++++
 Day #80 - Google Recaptcha/screenshot-1.png | Bin 0 -> 301205 bytes
 Day #80 - Google Recaptcha/screenshot-2.png | Bin 0 -> 46535 bytes
 Day #80 - Google Recaptcha/script.js        | 153 +++++++++++++++
 Day #80 - Google Recaptcha/style.css        | 207 ++++++++++++++++++++
 README.md                                   |   3 +-
 7 files changed, 424 insertions(+), 1 deletion(-)
 create mode 100644 Day #80 - Google Recaptcha/README.md
 create mode 100644 Day #80 - Google Recaptcha/index.html
 create mode 100644 Day #80 - Google Recaptcha/screenshot-1.png
 create mode 100644 Day #80 - Google Recaptcha/screenshot-2.png
 create mode 100644 Day #80 - Google Recaptcha/script.js
 create mode 100644 Day #80 - Google Recaptcha/style.css

diff --git a/Day #80 - Google Recaptcha/README.md b/Day #80 - Google Recaptcha/README.md
new file mode 100644
index 0000000..914569d
--- /dev/null
+++ b/Day #80 - Google Recaptcha/README.md	
@@ -0,0 +1,23 @@
+# Day #80
+
+### Google reCAPTCHA
+🛡️ Want to Protect Your Forms from Spam and Bots using Google reCAPTCHA? In this tutorial, we’ll integrate Google reCAPTCHA v2 & v3 step-by-step with HTML, JavaScript, and a touch of modern styling! 💻🤖
+
+🔥 What You’ll Learn:
+✅ Integrating Google reCAPTCHA – Add powerful spam protection to your forms with just HTML, CSS & JS. 🔐
+✅ reCAPTCHA v2 vs v3 – Understand the differences and choose what’s best for your site. 🧠
+✅ Seamless User Experience – Keep your UI clean while securing your forms. ✨
+✅ Bonus Tips – reCAPTCHA best practices and error handling techniques. 💡
+
+## Warning
+You need to get your own api key (in video we showed how!) and replace it in index.html file on line 29 :
+
+```html
+<div class="g-recaptcha" data-sitekey="<YOUR_API_KEY>"></div>
+```
+
+# Screenshot
+Here we have project screenshot :
+
+![screenshot-1](screenshot-1.png)
+![screenshot-2](screenshot-2.png)
\ No newline at end of file
diff --git a/Day #80 - Google Recaptcha/index.html b/Day #80 - Google Recaptcha/index.html
new file mode 100644
index 0000000..6c339f1
--- /dev/null
+++ b/Day #80 - Google Recaptcha/index.html	
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <link rel="stylesheet" href="style.css">
+    <script src="https://www.google.com/recaptcha/api.js"></script>
+    <title>Day #80 - Google Recaptcha API</title>
+</head>
+
+<body>
+
+    <div class="container">
+        <h1>Contact Form</h1>
+        <form id="contactForm">
+            <div class="form-group">
+                <label for="name">Name:</label>
+                <input type="text" name="name" id="name" required>
+            </div>
+            <div class="form-group">
+                <label for="email">Email:</label>
+                <input type="email" name="email" id="email" required>
+            </div>
+            <div class="form-group">
+                <label for="message">Message:</label>
+                <textarea name="message" id="message" required></textarea>
+            </div>
+            <div class="g-recaptcha" data-sitekey="<YOUR_API_KEY>"></div>
+            <button type="submit" class="submit-btn">Submit</button>
+        </form>
+        <div id="messageContainer"></div>
+    </div>
+
+
+    <script src="script.js"></script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/Day #80 - Google Recaptcha/screenshot-1.png b/Day #80 - Google Recaptcha/screenshot-1.png
new file mode 100644
index 0000000000000000000000000000000000000000..0df07439e538c52fc6bb49c03b559c180a6beee8
GIT binary patch
diff --git a/Day #80 - Google Recaptcha/screenshot-2.png b/Day #80 - Google Recaptcha/screenshot-2.png
new file mode 100644
index 0000000000000000000000000000000000000000..d31789f6e3f0589b7548f3d9af0ff57f4761cd58
GIT binary patch
diff --git a/Day #80 - Google Recaptcha/script.js b/Day #80 - Google Recaptcha/script.js
new file mode 100644
index 0000000..d164a93
--- /dev/null
+++ b/Day #80 - Google Recaptcha/script.js	
@@ -0,0 +1,153 @@
+// Configuration
+const CONFIG = { displayTime: 500000, loadingTime: 1500, maxRetries: 3 };
+const state = { retryCount: 0 };
+
+// Form submission handler
+document.getElementById('contactForm').addEventListener('submit', async function (e) {
+    e.preventDefault();
+    try {
+        const formData = validateFormData({
+            name: document.getElementById('name').value.trim(),
+            email: document.getElementById('email').value.trim(),
+            message: document.getElementById('message').value.trim()
+        });
+        const recaptchaResponse = await getRecaptchaResponse();
+        await processFormSubmission(formData, recaptchaResponse);
+    } catch (error) {
+        handleError(error);
+    }
+});
+
+// Core functions
+function validateFormData(data) {
+    const errors = [];
+    if (!data.name) errors.push('Name is required!');
+    if (!data.email) errors.push('Email is required!');
+    if (!data.message) errors.push('Message is required!');
+    if (data.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email)) errors.push('Invalid email!');
+    if (errors.length) throw new Error(errors.join(', '));
+    return data;
+}
+
+async function getRecaptchaResponse() {
+    const response = grecaptcha.getResponse();
+    if (!response) throw new Error('Please complete the reCAPTCHA verification');
+    return response;
+}
+
+async function processFormSubmission(formData, recaptchaResponse) {
+    showMessage('Verifying reCAPTCHA and submitting form...', 'info');
+    try {
+        await new Promise(resolve => setTimeout(resolve, CONFIG.loadingTime));
+        const info = await extractRecaptchaInfo(recaptchaResponse);
+        displaySuccessMessage(info);
+        resetForm();
+    } catch (error) {
+        throw new Error(`Form submission failed: ${error.message}`);
+    }
+}
+
+async function extractRecaptchaInfo(response) {
+    const timestamp = new Date();
+    return {
+        timestamp: timestamp.toLocaleTimeString(),
+        date: timestamp.toLocaleDateString(),
+        browserInfo: getBrowserInfo(),
+        deviceInfo: getDeviceInfo()
+    };
+}
+
+// Helper functions
+function getBrowserInfo() {
+    const ua = navigator.userAgent;
+    const browser = {
+        chrome: /Chrome\/([0-9.]+)/,
+        firefox: /Firefox\/([0-9.]+)/,
+        safari: /Version\/([0-9.]+).*Safari/,
+        edge: /Edg\/([0-9.]+)/,
+        ie: /MSIE ([0-9.]+)/
+    };
+
+    for (const [name, regex] of Object.entries(browser)) {
+        const match = ua.match(regex);
+        if (match) return { name: name.charAt(0).toUpperCase() + name.slice(1), version: match[1] };
+    }
+    return { name: 'Unknown', version: 'Unknown' };
+}
+
+function getDeviceInfo() {
+    return {
+        screenSize: `${window.innerWidth}x${window.innerHeight}`,
+        platform: navigator.platform,
+        language: navigator.language
+    };
+}
+
+function displaySuccessMessage(info) {
+    const successMessage = `
+        <div class="recaptcha-details">
+            <h3>reCAPTCHA Verification Details</h3>
+            <div class="info-grid">
+                <div class="info-card">
+                    <div class="info-icon">🌐</div>
+                    <div class="info-content">
+                        <h4>Browser Information</h4>
+                        <p>${info.browserInfo.name} ${info.browserInfo.version}</p>
+                        <p>Platform: ${info.deviceInfo.platform}</p>
+                        <p>Language: ${info.deviceInfo.language}</p>
+                    </div>
+                </div>
+                <div class="info-card">
+                    <div class="info-icon">📱</div>
+                    <div class="info-content">
+                        <h4>Device Details</h4>
+                        <p>Screen: ${info.deviceInfo.screenSize}</p>
+                        <p>Time: ${info.timestamp}</p>
+                        <p>Date: ${info.date}</p>
+                    </div>
+                </div>
+            </div>
+        </div>
+    `;
+    showMessage(successMessage, 'success');
+}
+
+function resetForm() {
+    document.getElementById('contactForm').reset();
+    grecaptcha.reset();
+    state.retryCount = 0;
+}
+
+function handleError(error) {
+    console.error('Error:', error);
+    if (state.retryCount < CONFIG.maxRetries) {
+        state.retryCount++;
+        showMessage(`Error: ${error.message}. Retrying... (${state.retryCount}/${CONFIG.maxRetries})`, 'error');
+        setTimeout(() => grecaptcha.reset(), 1000);
+    } else {
+        showMessage(`Error: ${error.message}. Please try again later.`, 'error');
+        state.retryCount = 0;
+    }
+}
+
+function showMessage(message, type) {
+    const messageContainer = document.getElementById('messageContainer');
+    messageContainer.innerHTML = message;
+    messageContainer.className = type + ' visible';
+
+    if (type === 'info') {
+        messageContainer.classList.add('loading');
+    }
+
+    if (type !== 'info') {
+        setTimeout(() => {
+            messageContainer.innerHTML = '';
+            messageContainer.className = '';
+        }, CONFIG.displayTime);
+    }
+}
+
+// reCAPTCHA expiration handler
+window.onload = function () {
+    window.recaptchaExpired = () => showMessage('reCAPTCHA has expired. Please verify again!', 'error');
+};
\ No newline at end of file
diff --git a/Day #80 - Google Recaptcha/style.css b/Day #80 - Google Recaptcha/style.css
new file mode 100644
index 0000000..40cd940
--- /dev/null
+++ b/Day #80 - Google Recaptcha/style.css	
@@ -0,0 +1,207 @@
+*{
+    margin: 0;
+    padding: 0;
+    box-sizing: border-box;
+}
+
+body{
+    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+    line-height: 1.4;
+    background: linear-gradient(135deg, #f5f7fa 0%, #e4e9f2 100%);
+    color: #333;
+    min-height: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 2rem 1rem;
+}
+
+.container{
+    width: 100%;
+    max-width: 600px;
+    background-color: #fff;
+    padding: 2rem;
+    border-radius: 8px;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05), 0 1px 3px rgba(0, 0, 0, 0.1);
+    margin: 2rem auto;
+    backdrop-filter: blur(10px);
+    background-color: rgba(255, 255, 255, 0.95);
+}
+
+h1{
+    font-size: 1.5rem;
+    margin-bottom: 1rem;
+    color: #2c3e50;
+    text-align: center;
+}
+
+h2{
+    font-size: 1.2rem;
+    margin-bottom: 0.8rem;
+    color: #34495e;
+}
+
+.form-group{
+    margin-bottom: 1rem;
+}
+
+label{
+    display: block;
+    margin-bottom: 0.3rem;
+    font-weight: 500;
+    color: #2c3e50;
+}
+
+input[type="text"],
+input[type="email"],
+textarea{
+    width: 100%;
+    padding: 0.5rem;
+    border: 1px solid #ddd;
+    border-radius: 4px;
+    font-size: 0.9rem;
+    transition: border-color 0.3s ease;
+}
+
+input[type="text"]:focus,
+input[type="email"]:focus,
+textarea:focus{
+    border-color: #3498db;
+    outline: none;
+}
+
+textarea{
+    min-height: 100px;
+    resize: vertical;
+}
+
+button{
+    background-color: #3498db;
+    margin-top: 12px;
+    color: #fff;
+    padding: 0.5rem 1rem;
+    border: none;
+    border-radius: 4px;
+    font-size: 0.9rem;
+    cursor: pointer;
+    width: 100%;
+    transition: background-color 0.3s ease;
+}
+
+button:hover{
+    background-color: #2980b9;
+}
+
+.g-recaptcha{
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+#messageContainer{
+    display: none;
+    margin-top: 1rem;
+    padding: 0.8rem;
+    border-radius: 4px;
+    font-size: 0.9rem;
+}
+
+#messageContainer.visible{
+    display: block;
+}
+
+.info-grid{
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+    gap: 1rem;
+    margin-top: 1rem;
+}
+
+.info-card{
+    background-color: #fff;
+    border-radius: 6px;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+    transition: transform 0.2s ease;
+    padding: 0.8rem;
+}
+
+.info-card:hover{
+    transform: translateY(-2px);
+}
+
+.info-icon{
+    font-size: 1.2rem;
+    margin-bottom: 0.5rem;
+}
+
+.info-content h4{
+    font-size: 0.9rem;
+    margin-bottom: 0.3rem;
+    color: #2c3e50;
+}
+
+.info-content p{
+    font-size: 0.8rem;
+    color: #666;
+    margin-bottom: 0.2rem;
+}
+
+.success{
+    background-color: #d4edda;
+    color: #155724;
+    border: 1px solid #c3e6cb;
+}
+
+.error{
+    background-color: #f8d7da;
+    color: #721c24;
+    border: 1px solid #f5c6cb;
+}
+
+.info{
+    background-color: #d1ecf1;
+    color: #0c5460;
+    border: 1px solid #bee5eb;
+}
+
+.loading{
+    position: relative;
+}
+
+.loading::after{
+    content: '';
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    width: 1rem;
+    height: 1rem;
+    margin: -0.5rem 0 0 -0.5rem;
+    border: 2px solid #3498db;
+    border-top-color: transparent;
+    border-radius: 50%;
+    animation: spin 1s linear infinite;
+}
+
+@keyframes spin {
+    to { transform: rotate(360deg); }
+}
+
+@media screen and (max-width: 600px) {
+    
+    .container{
+        padding: 1rem;
+    }
+
+    .info-grid{
+        grid-template-columns: 1fr;
+    }
+
+    h1{
+        font-size: 1.3rem;
+    }
+
+    h2{
+        font-size: 1.1rem;
+    }
+
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index f06d7a9..4aaf67f 100644
--- a/README.md
+++ b/README.md
@@ -89,7 +89,8 @@ Here we have list of projects:
 77. AI Image Detector
 78. Google Gemini Clone
 79. Simple Python Compiler
+80. Google reCAPTCHA
 
-## Where is rest 21 Projects
+## Where is rest 20 Projects
 
 You can vote for upcoming projects on our <a href="https://youtube.com/@AsmrProg" target="_blank">Channel</a> **community** page :wink:
\ No newline at end of file

From db5614f9cdecdfbebf7d1f9859ae18cc8085a131 Mon Sep 17 00:00:00 2001
From: Reza Mehdikhanlou <rezamehdikhanlou@gmail.com>
Date: Wed, 13 Aug 2025 17:01:46 +0330
Subject: [PATCH 2/4] Adding Day #81

---
 Day #81 - Contact Form With EmailJS/Logo.png  | Bin 0 -> 98884 bytes
 Day #81 - Contact Form With EmailJS/README.md |  32 ++
 .../index.html                                | 127 +++++++
 .../screenshot.png                            | Bin 0 -> 155524 bytes
 Day #81 - Contact Form With EmailJS/script.js |  40 +++
 Day #81 - Contact Form With EmailJS/style.css | 323 ++++++++++++++++++
 README.md                                     |   3 +-
 7 files changed, 524 insertions(+), 1 deletion(-)
 create mode 100644 Day #81 - Contact Form With EmailJS/Logo.png
 create mode 100644 Day #81 - Contact Form With EmailJS/README.md
 create mode 100644 Day #81 - Contact Form With EmailJS/index.html
 create mode 100644 Day #81 - Contact Form With EmailJS/screenshot.png
 create mode 100644 Day #81 - Contact Form With EmailJS/script.js
 create mode 100644 Day #81 - Contact Form With EmailJS/style.css

diff --git a/Day #81 - Contact Form With EmailJS/Logo.png b/Day #81 - Contact Form With EmailJS/Logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..166580d17cdd1dd278bef771635d5c804fd4a73d
GIT binary patch
diff --git a/Day #81 - Contact Form With EmailJS/README.md b/Day #81 - Contact Form With EmailJS/README.md
new file mode 100644
index 0000000..c4f711a
--- /dev/null
+++ b/Day #81 - Contact Form With EmailJS/README.md	
@@ -0,0 +1,32 @@
+# Day #81
+
+### Contact Form With EmailJS
+🛡️ Want to Build a Contact Form with Backend Using EmailJS API? In this tutorial, we’ll create a fully functional contact form using HTML, CSS & JavaScript — no backend server required! 💬📧
+
+🔥 What You’ll Learn:
+
+* EmailJS API Integration – Send emails directly from your frontend using EmailJS, no server needed! ⚙️ 
+* Fully Functional Contact Form – Capture name, email, subject, and message in real time. 📩 
+* Responsive UI Design – Design a clean, modern, and mobile-friendly contact form using HTML & CSS. 💡 
+* Bonus Tips – Input validation, success/failure alerts, and production-ready code. 💪 
+
+💡 Whether you're a beginner looking to build your first web project or a developer exploring serverless tools, this is the perfect hands-on tutorial!
+
+## Warning
+You need to get your own EmailJS Keys (in video we showed how!) and replace them in script.js file on line 4 :
+
+```javascript
+// Replace this with your EmailJS public key
+emailjs.init("EMAILJS_PUBLIC_KEY");
+```
+and line 27:
+```javascript
+// Send email using EmailJS
+// Replace Service_ID and Template_ID with your EmailJS service and template IDs
+emailjs.send('EMAILJS_SERVICE_ID', 'EMAILJS_TEMPLATE_ID', formData).then(function (response) {
+```
+
+# Screenshot
+Here we have project screenshot :
+
+![screenshot](screenshot.png)
\ No newline at end of file
diff --git a/Day #81 - Contact Form With EmailJS/index.html b/Day #81 - Contact Form With EmailJS/index.html
new file mode 100644
index 0000000..d1acf1b
--- /dev/null
+++ b/Day #81 - Contact Form With EmailJS/index.html	
@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <link rel="stylesheet" href="style.css">
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css">
+    <script src="https://cdn.jsdelivr.net/npm/@emailjs/browser@4/dist/email.min.js"></script>
+    <title>Day #81 - Contact Form With Backend | AsmrProg</title>
+</head>
+
+<body>
+
+    <nav class="navbar">
+        <div class="nav-logo">
+            <img src="Logo.png" alt="Logo" class="logo">
+        </div>
+        <div class="nav-links">
+            <a href="#">Features</a>
+            <a href="#">How it works</a>
+            <a href="#">Pricing</a>
+            <a href="#">Documentation</a>
+        </div>
+        <div class="nav-buttons">
+            <a href="#" class="login-btn">Log In</a>
+            <a href="#" class="try-btn">Try for free</a>
+        </div>
+    </nav>
+
+    <main class="main-content">
+        <div class="left-section">
+            <h1>Get in touch</h1>
+            <p class="subtitle">We are here for you! How can we help?</p>
+
+            <div class="form-container">
+                <h2>Drop us a line</h2>
+                <form autocomplete="off" id="contactForm">
+                    <div class="form-row">
+                        <div class="form-group">
+                            <label for="name">Your name</label>
+                            <input type="text" name="name" id="name" required placeholder="Please enter your name"
+                                autocomplete="off">
+                        </div>
+
+                        <div class="form-group">
+                            <label for="subject">Subject</label>
+                            <select name="subject" id="subject" required autocomplete="off">
+                                <option value="" disabled selected>Just saying hi</option>
+                                <option value="general">General Inquiry</option>
+                                <option value="support">Support</option>
+                                <option value="feedback">Feedback</option>
+                            </select>
+                        </div>
+                    </div>
+
+                    <div class="form-group">
+                        <label for="email">Email</label>
+                        <input type="email" name="email" id="email" required placeholder="Please enter your email"
+                            autocomplete="off">
+                    </div>
+
+                    <div class="form-group">
+                        <label for="message">Message</label>
+                        <textarea name="message" id="message" required placeholder="Enter your message here"
+                            autocomplete="off"></textarea>
+                    </div>
+                    <button type="submit">Send Message</button>
+
+                </form>
+            </div>
+        </div>
+
+        <div class="right-section">
+            <h2>Or check out these resources</h2>
+
+            <div class="resource-card">
+                <div class="resource-icon slack-icon">
+                    <i class="fab fa-slack fa-2x" style="color:#611f69;"></i>
+                </div>
+                <div class="resource-content">
+                    <h3>Join our community on Slack</h3>
+                    <p>Popular UI components like tooltips, modals, cards, surveys are there to help you.</p>
+                </div>
+            </div>
+
+            <div class="resource-card">
+                <div class="resource-icon docs-icon">
+                    <i class="fas fa-book fa-2x" style="color:#4263EB;"></i>
+                </div>
+                <div class="resource-content">
+                    <h3>Read our documentation</h3>
+                    <p>Popular UI components like tooltips, modals, cards, surveys are there to help you.</p>
+                </div>
+            </div>
+
+            <div class="resource-card">
+                <div class="resource-icon support-icon">
+                    <i class="fas fa-headset fa-2x" style="color:#10B981;"></i>
+                </div>
+                <div class="resource-content">
+                    <h3>Contact Support</h3>
+                    <p>Need help? Our support team is here to assist you 24/7 with any issues or questions.</p>
+                </div>
+            </div>
+
+            <div class="resource-card">
+                <div class="resource-icon video-icon">
+                    <i class="fas fa-circle-play fa-2x" style="color:#f59e42;"></i>
+                </div>
+                <div class="resource-content">
+                    <h3>Watch Video Tutorials</h3>
+                    <p>Learn how to get the most out of our platform with step-by-step video guides.</p>
+                </div>
+            </div>
+        </div>
+    </main>
+
+    <div id="success-message" class="hidden">
+        Message sent successfully!
+    </div>
+
+    <script src="script.js"></script>
+
+</body>
+
+</html>
\ No newline at end of file
diff --git a/Day #81 - Contact Form With EmailJS/screenshot.png b/Day #81 - Contact Form With EmailJS/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..7feff8c636a4fbe2a3ca12210e927181324d6d31
GIT binary patch
diff --git a/Day #81 - Contact Form With EmailJS/script.js b/Day #81 - Contact Form With EmailJS/script.js
new file mode 100644
index 0000000..ac8525f
--- /dev/null
+++ b/Day #81 - Contact Form With EmailJS/script.js	
@@ -0,0 +1,40 @@
+// Initialize EmailJS with your public key
+(function () {
+    // Replace this with your EmailJS public key
+    emailjs.init("EMAILJS_PUBLIC_KEY");
+})();
+
+// Get form and success message elements
+const contactForm = document.getElementById('contactForm');
+const successMessage = document.getElementById('success-message');
+
+// Add form submit event listener
+contactForm.addEventListener('submit', function (event) {
+    event.preventDefault();
+
+    // Get form data
+    const formData = {
+        to_name: "Admin",
+        from_name: document.getElementById('name').value,
+        from_email: document.getElementById('email').value,
+        subject: document.getElementById('subject').value,
+        message: document.getElementById('message').value,
+        reply_to: document.getElementById('email').value // This allows you to reply directly to the sender
+    };
+
+    // Send email using EmailJS
+    // Replace Service_ID and Template_ID with your EmailJS service and template IDs
+    emailjs.send('EMAILJS_SERVICE_ID', 'EMAILJS_TEMPLATE_ID', formData).then(function (response) {
+        // Show success message
+        successMessage.classList.remove('hidden');
+        // Clear form
+        contactForm.reset();
+
+        // Hide success message after 5 seconds
+        setTimeout(() => {
+            successMessage.classList.add('hidden');
+        }, 5000);
+    }).catch(function (error) {
+        alert('Failed to send message. Please try again.');
+    });
+});
\ No newline at end of file
diff --git a/Day #81 - Contact Form With EmailJS/style.css b/Day #81 - Contact Form With EmailJS/style.css
new file mode 100644
index 0000000..a150a3e
--- /dev/null
+++ b/Day #81 - Contact Form With EmailJS/style.css	
@@ -0,0 +1,323 @@
+@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');
+
+:root{
+    --primary-color: #4263EB;
+    --text-primary: #1b1b1b;
+    --text-secondary: #6b7280;
+    --background-light: #f8f9ff;
+    --border-color: #e5e7eb;
+    --base-font-size: 15px;
+}
+
+*{
+    margin: 0;
+    padding: 0;
+    outline: none;
+    box-sizing: border-box;
+}
+
+body{
+    font-family: 'Inter', sans-serif;
+    color: var(--text-primary);
+    line-height: 1.5;
+    background-color: #fff;
+    min-height: 100vh;
+    font-size: var(--base-font-size);
+}
+
+.navbar{
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0.5rem 2rem;
+    background: #fff;
+    border-bottom: 1px solid var(--border-color);
+}
+
+.nav-logo{
+    display: flex;
+    align-items: center;
+}
+
+.logo{
+    height: 32px;
+    width: 32px;
+    object-fit: cover;
+}
+
+.nav-links{
+    display: flex;
+    gap: 2rem;
+}
+
+.nav-links a{
+    text-decoration: none;
+    color: var(--text-secondary);
+    font-weight: 500;
+    transition: color 0.2s ease;
+}
+
+.nav-links a:hover{
+    color: var(--text-primary);
+}
+
+.nav-buttons{
+    display: flex;
+    align-items: center;
+    gap: 1rem;
+}
+
+.login-btn{
+    color: var(--text-secondary);
+    text-decoration: none;
+    font-weight: 500;
+}
+
+.try-btn{
+    background-color: var(--primary-color);
+    color: #fff;
+    padding: 0.4rem 1rem;
+    border-radius: 6px;
+    text-decoration: none;
+    font-weight: 500;
+    transition: opacity 0.2s ease;
+}
+
+.try-btn:hover{
+    opacity: 0.9;
+}
+
+.main-content{
+    display: grid;
+    grid-template-columns: 1fr 1fr;
+    gap: 4rem;
+    max-width: 1200px;
+    margin: 0 auto;
+    padding: 2rem;
+}
+
+.left-section{
+    max-width: 560px;
+}
+
+h1{
+    font-size: 2rem;
+    font-weight: 700;
+    margin-bottom: 1rem;
+    color: var(--text-primary);
+}
+
+.subtitle{
+    color: var(--text-secondary);
+    font-size: 1rem;
+    margin-bottom: 3rem;
+}
+
+.form-container h2,
+.right-section h2 {
+    font-size: 1.1rem;
+    font-weight: 600;
+    margin-bottom: 1rem;
+}
+
+.form-row{
+    display: flex;
+    gap: 1rem;
+}
+
+.form-row .form-group{
+    flex: 1 1 0;
+    min-width: 0;
+}
+
+.form-group{
+    margin-bottom: 1.5rem;
+}
+
+label{
+    display: block;
+    margin-bottom: 0.5rem;
+    color: var(--text-primary);
+    font-size: 0.85rem;
+    font-weight: 500;
+}
+
+input,
+textarea,
+select{
+    width: 100%;
+    padding: 0.75rem 1rem;
+    border: 1px solid var(--border-color);
+    border-radius: 8px;
+    font-size: 0.97rem;
+    color: var(--text-primary);
+    background-color: #fff;
+    transition: all 0.2s ease;
+}
+
+select{
+    appearance: none;
+    background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1L6 6L11 1' stroke='%236B7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
+    background-repeat: no-repeat;
+    background-position: right 1rem center;
+    padding-right: 2.5rem;
+    cursor: pointer;
+}
+
+textarea{
+    height: 120px;
+    resize: vertical;
+}
+
+button{
+    width: 100%;
+    padding: 0.875rem 1.5rem;
+    background-color: var(--primary-color);
+    color: #fff;
+    border: none;
+    border-radius: 8px;
+    font-size: 0.97rem;
+    font-weight: 500;
+    cursor: pointer;
+    transition: opacity 0.2s ease;
+}
+
+button:hover{
+    opacity: 0.9;
+}
+
+.right-section{
+    background-color: var(--background-light);
+    padding: 1rem 2rem;
+    border-radius: 16px;
+}
+
+.resource-card{
+    display: flex;
+    gap: 1rem;
+    padding: 1.5rem;
+    background: #fff;
+    border-radius: 12px;
+    margin-bottom: 1rem;
+    transition: transform 0.2s ease;
+    cursor: pointer;
+}
+
+.resource-card:hover{
+    transform: translateY(-2px);
+}
+
+.resource-icon{
+    flex-shrink: 0;
+    width: 48px;
+    height: 48px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background: var(--background-light);
+    border-radius: 12px;
+}
+
+.resource-content h3{
+    font-size: 0.95rem;
+    font-weight: 600;
+    margin-bottom: 0.5rem;
+}
+
+.resource-content p{
+    color: var(--text-secondary);
+    font-size: 0.82rem;
+    line-height: 1.5;
+}
+
+#success-message{
+    position: fixed;
+    bottom: 2rem;
+    left: 50%;
+    transform: translateX(-50%);
+    background-color: #10b981;
+    color: #fff;
+    padding: 1rem 2rem;
+    border-radius: 8px;
+    font-weight: 500;
+    opacity: 0;
+    transition: opacity 0.3s ease;
+}
+
+#success-message:not(.hidden){
+    opacity: 1;
+}
+
+@media screen and (max-width: 1024px) {
+    
+    .main-content{
+        grid-template-columns: 1fr;
+        gap: 2rem;
+    }
+
+    .left-section{
+        max-width: 100%;
+    }
+
+}
+
+@media screen and (max-width: 768px) {
+    
+    .nav-links{
+        display: none;
+    }
+
+    .main-content{
+        padding: 2rem 1rem;
+    }
+
+    h1{
+        font-size: 1.3rem;
+    }
+
+    .form-container h2,
+    .right-section h2{
+        font-size: 1rem;
+    }
+
+    .subtitle{
+        font-size: 0.95rem;
+    }
+
+    input,
+    textarea,
+    select,
+    button{
+        font-size: 0.93rem;
+    }
+
+    .resource-content h3{
+        font-size: 0.9rem;
+    }
+
+    .resource-content p{
+        font-size: 0.78rem;
+    }
+
+}
+
+@media screen and (max-width: 600px) {
+    
+    .form-row{
+        flex-direction: column;
+        gap: 0;
+    }
+
+}
+
+@media screen and (max-width: 480px) {
+    
+    .nav-buttons{
+        gap: 0.5rem;
+    }
+
+    .try-btn{
+        padding: 0.5rem 0.75rem;
+    }
+
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 4aaf67f..9d42f4c 100644
--- a/README.md
+++ b/README.md
@@ -90,7 +90,8 @@ Here we have list of projects:
 78. Google Gemini Clone
 79. Simple Python Compiler
 80. Google reCAPTCHA
+81. Contact Form With EmailJS
 
-## Where is rest 20 Projects
+## Where is rest 19 Projects
 
 You can vote for upcoming projects on our <a href="https://youtube.com/@AsmrProg" target="_blank">Channel</a> **community** page :wink:
\ No newline at end of file

From bfff8c0a013864cc1a78a1d2e84d9592f623d69b Mon Sep 17 00:00:00 2001
From: Reza Mehdikhanlou <rezamehdikhanlou@gmail.com>
Date: Wed, 13 Aug 2025 17:16:53 +0330
Subject: [PATCH 3/4] Adding Day #82 - Fixing Orders

---
 Day #81 - Virus Total API/README.md           |  26 +
 Day #81 - Virus Total API/index.html          |  44 ++
 Day #81 - Virus Total API/screenshot.png      | Bin 0 -> 70932 bytes
 Day #81 - Virus Total API/script.js           | 266 ++++++++++
 Day #81 - Virus Total API/style.css           | 493 ++++++++++++++++++
 .../Logo.png                                  | Bin
 .../README.md                                 |   2 +-
 .../index.html                                |   0
 .../screenshot.png                            | Bin
 .../script.js                                 |   0
 .../style.css                                 |   0
 README.md                                     |   3 +-
 12 files changed, 832 insertions(+), 2 deletions(-)
 create mode 100644 Day #81 - Virus Total API/README.md
 create mode 100644 Day #81 - Virus Total API/index.html
 create mode 100644 Day #81 - Virus Total API/screenshot.png
 create mode 100644 Day #81 - Virus Total API/script.js
 create mode 100644 Day #81 - Virus Total API/style.css
 rename {Day #81 - Contact Form With EmailJS => Day #82 - Contact Form With EmailJS}/Logo.png (100%)
 rename {Day #81 - Contact Form With EmailJS => Day #82 - Contact Form With EmailJS}/README.md (99%)
 rename {Day #81 - Contact Form With EmailJS => Day #82 - Contact Form With EmailJS}/index.html (100%)
 rename {Day #81 - Contact Form With EmailJS => Day #82 - Contact Form With EmailJS}/screenshot.png (100%)
 rename {Day #81 - Contact Form With EmailJS => Day #82 - Contact Form With EmailJS}/script.js (100%)
 rename {Day #81 - Contact Form With EmailJS => Day #82 - Contact Form With EmailJS}/style.css (100%)

diff --git a/Day #81 - Virus Total API/README.md b/Day #81 - Virus Total API/README.md
new file mode 100644
index 0000000..af24e3d
--- /dev/null
+++ b/Day #81 - Virus Total API/README.md	
@@ -0,0 +1,26 @@
+# Day #81
+
+### Virus Total API
+🛡️ Want to Scan Files & URLs for Malware Using VirusTotal API? In this tutorial, we’ll build a powerful web tool using HTML, CSS & JavaScript to interact with the VirusTotal API and check for threats in real-time! 💻🦠
+
+🔥 What You’ll Learn:
+
+* VirusTotal API Integration – Learn how to send files and links to VirusTotal and analyze responses using JavaScript. 🔐 
+* File & URL Scanning – Check suspicious uploads and URLs with a few lines of code. 🕵️‍♂️ 
+* Clean UI Design – Build a simple, user-friendly interface using modern HTML & CSS. ✨ 
+* Bonus Tips – API rate limits, error handling, and security best practices. 💡 
+
+💡 Whether you're a developer, ethical hacker, or just curious about malware detection, this hands-on project is the perfect starting point!
+
+## Warning
+You need to get your own EmailJS Keys (in video we showed how!) and replace them in script.js file on line 2 :
+
+```javascript
+// API key from VirusTotal API
+const API_KEY = "YOUR_API_KEY";
+```
+
+# Screenshot
+Here we have project screenshot :
+
+![screenshot](screenshot.png)
\ No newline at end of file
diff --git a/Day #81 - Virus Total API/index.html b/Day #81 - Virus Total API/index.html
new file mode 100644
index 0000000..f51630f
--- /dev/null
+++ b/Day #81 - Virus Total API/index.html	
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <link rel="stylesheet" href="style.css">
+    <title>Day #81 - Virus Total API | AsmrProg</title>
+</head>
+
+<body>
+
+    <div class="container">
+        <h1>VirusTotal Scanner</h1>
+
+        <section>
+            <h2>Scan a URL</h2>
+            <input type="text" id="urlInput" placeholder="Enter URL (e.g., https://example.com)">
+            <button onclick="scanURL()">Scan URL</button>
+        </section>
+
+        <section>
+            <h2>Scan a File</h2>
+            <input type="file" id="fileInput">
+            <button onclick="scanFile()">Scan File</button>
+        </section>
+
+        <div id="result"></div>
+
+        <div id="fullReportModal" class="modal">
+            <div class="modal-content">
+                <span class="close" onclick="closeModal()">&times;</span>
+                <h2>Full Report</h2>
+                <div id="fullReportContent"></div>
+            </div>
+        </div>
+
+    </div>
+
+
+    <script src="script.js"></script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/Day #81 - Virus Total API/screenshot.png b/Day #81 - Virus Total API/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..11943b4edcd8100a56e83e62fa7e78fec6365483
GIT binary patch
diff --git a/Day #81 - Virus Total API/script.js b/Day #81 - Virus Total API/script.js
new file mode 100644
index 0000000..d0358c4
--- /dev/null
+++ b/Day #81 - Virus Total API/script.js	
@@ -0,0 +1,266 @@
+// API key from VirusTotal API
+const API_KEY = "a3c07744cb4f644ec060470d4c4bae32808ef3595204229445f15f2b2d32d0fa";
+
+// Utility function to get DOM elements by ID
+const getElement = id => document.getElementById(id);
+
+// Updates the result display section with given content
+const updateResult = (content, display = true) => {
+    const result = getElement('result');
+    result.style.display = display ? 'block' : 'none';
+    result.innerHTML = content;
+};
+
+// Shows a loading spinner and message
+const showLoading = message => updateResult(`
+        <div class="loading">
+            <p>${message}</p>
+            <div class="spinner"></div>
+        </div>
+`);
+
+// Displays an error message
+const showError = message => updateResult(`<p class="error">${message}</p>`);
+
+// Generic function to make authenticated API requests ro VirusTotal
+async function makeRequest(url, options = {}) {
+    const response = await fetch(url, {
+        ...options,
+        headers: {
+            "x-apikey": API_KEY,
+            ...options.headers
+        }
+    });
+
+    // Handle failed requests gracefully
+    if (!response.ok) {
+        const error = await response.json().catch(() => ({ error: { message: response.statusText } }));
+        throw new Error(error.error?.message || 'Request failed!');
+    }
+
+    return response.json(); // Parse response JSON
+}
+
+// Handles the process of scanning a URL using VirusTotal
+async function scanURL() {
+    const url = getElement('urlInput').value.trim();
+    if (!url) return showError("Please enter a URL!");
+
+    try {
+        new URL(url); // Validate URL format
+    } catch {
+        return showError("Please enter a valid URL (e.g., https://example.com)");
+    }
+
+    try {
+        showLoading("Submitting URL for scanning...");
+
+        const encodedUrl = encodeURIComponent(url);
+
+        // Submit URL to VirusTotal
+        const submitResult = await makeRequest("https://www.virustotal.com/api/v3/urls", {
+            method: "POST",
+            headers: {
+                "accept": "application/json",
+                "content-type": "application/x-www-form-urlencoded"
+            },
+            body: `url=${encodedUrl}`
+        });
+
+        if (!submitResult.data?.id) {
+            throw new Error("Failed to get analysis ID");
+        }
+
+        // Delay before polling for results
+        await new Promise(resolve => setTimeout(resolve, 3000));
+
+        showLoading("Getting scan results...");
+        await pollAnalysisResults(submitResult.data.id);
+    } catch (error) {
+        showError(`Error: ${error.message}`);
+    }
+}
+
+// Handles the process of scanning a file using VirusTotal
+async function scanFile() {
+    const file = getElement('fileInput').files[0];
+    if (!file) return showError("Please select a file!");
+    if (file.size > 32 * 1024 * 1024) return showError("File size exceeds 32MB limit.");
+
+    try {
+        showLoading("Uploading file...");
+
+        const formData = new FormData();
+        formData.append("file", file);
+
+        // Upload file to VirusTotal
+        const uploadResult = await makeRequest("https://www.virustotal.com/api/v3/files", {
+            method: "POST",
+            body: formData
+        });
+
+        if (!uploadResult.data?.id) {
+            throw new Error("Failed to get file ID!");
+        }
+
+        // Delay before polling for analysis results
+        await new Promise(resolve => setTimeout(resolve, 3000));
+
+        showLoading("Getting scan results...");
+        const analysisResult = await makeRequest(`https://www.virustotal.com/api/v3/analyses/${uploadResult.data.id}`);
+
+        if (!analysisResult.data?.id) {
+            throw new Error("Failed to get analysis results!");
+        }
+
+        await pollAnalysisResults(analysisResult.data.id, file.name);
+    } catch (error) {
+        showError(`Error: ${error.message}`);
+    }
+}
+
+// Polls VirusTotal for analysis results, retrying until complete or timeout
+async function pollAnalysisResults(analysisId, fileName = '') {
+    const maxAttempts = 20;
+    let attempts = 0;
+    let interval = 2000;
+
+    while (attempts < maxAttempts) {
+        try {
+            showLoading(`Analyzing${fileName ? ` ${fileName}` : ''}... (${((maxAttempts - attempts) * interval / 1000).toFixed(0)}s remaining)`);
+
+            const report = await makeRequest(`https://www.virustotal.com/api/v3/analyses/${analysisId}`);
+            const status = report.data?.attributes?.status;
+
+            if (!status) throw new Error("Invalid analysis response!");
+
+            if (status === "completed") {
+                showFormattedResult(report);
+                break;
+            }
+
+            if (status === "failed") {
+                throw new Error("Analysis failed!");
+            }
+
+            if (++attempts >= maxAttempts) {
+                throw new Error("Analysis timeout - please try again!");
+            }
+
+            // Increase interval between retries
+            interval = Math.min(interval * 1.5, 8000);
+            await new Promise(resolve => setTimeout(resolve, interval));
+        } catch (error) {
+            showError(`Error: ${error.message}`);
+            break;
+        }
+    }
+}
+
+// Formats and displays analysis results in the UI
+function showFormattedResult(data) {
+    if (!data?.data?.attributes?.stats) return showError("Invalid response format!");
+
+    const stats = data.data.attributes.stats;
+    const total = Object.values(stats).reduce((sum, val) => sum + val, 0);
+    if (!total) return showError("No analysis results available!");
+
+    const getPercent = val => ((val / total) * 100).toFixed(1);
+
+    const categories = {
+        malicious: { color: 'malicious', label: 'Malicious' },
+        suspicious: { color: 'suspicious', label: 'Suspicious' },
+        harmless: { color: 'safe', label: 'Clean' },
+        undetected: { color: 'undetected', label: 'Undetected' }
+    };
+
+    const percents = Object.keys(categories).reduce((acc, key) => {
+        acc[key] = getPercent(stats[key]);
+        return acc;
+    }, {});
+
+    // Determine overall vardict
+    const verdict = stats.malicious > 0 ? "Malicious" : stats.suspicious > 0 ? "Suspicious" : "Safe";
+    const verdictClass = stats.malicious > 0 ? "malicious" : stats.suspicious > 0 ? "suspicious" : "safe";
+
+    // Render result summary UI
+    updateResult(`
+        <h3>Scan Report</h3>
+        <div class="scan-stats">
+            <p><strong>Verdict:</strong> <span class="${verdictClass}">${verdict}</span></p>
+            <div class="progress-section">
+                <div class="progress-label">
+                    <span>Detection Results</span>
+                    <span class="progress-percent">${percents.malicious}% Detection Rate</span>
+                </div>
+                <div class="progress-stacked">
+                    ${Object.entries(categories).map(([key, { color }]) => `
+                        <div class="progress-bar ${color}" style="width: ${percents[key]}%" title="${categories[key].label}: ${stats[key]} (${percents[key]}%)">
+                            <span class="progress-label-overlay">${stats[key]}</span>
+                        </div>
+                    `).join('')}
+                </div>
+                <div class="progress-legend">
+                    ${Object.entries(categories).map(([key, { color, label }]) => `
+                        <div class="legend-item">
+                            <span class="legend-color ${color}"></span>
+                            <span>${label} (${percents[key]}%)</span>
+                        </div>
+                    `).join('')}
+                </div>
+            </div>
+            <div class="detection-details">
+                ${Object.entries(categories).map(([key, { color, label }]) => `
+                    <div class="detail-item ${color}">
+                        <span class="detail-label">${label}</span>
+                        <span class="detail-value">${stats[key]}</span>
+                        <span class="detail-percent">${percents[key]}%<span>
+                    </div>
+                `).join('')}
+            </div>
+        </div>
+        <button onclick="showFullReport(this.getAttribute('data-report'))" data-report='${JSON.stringify(data)}'>View Full Report</button>
+    `);
+
+    // Trigger animation
+    setTimeout(() => getElement('result').querySelector('.progress-stacked').classList.add('animate'), 1000);
+}
+
+// Displays a detailed report modal with engine-by-engine detection results
+function showFullReport(reportData) {
+    const data = typeof reportData === 'string' ? JSON.parse(reportData) : reportData;
+    const modal = getElement("fullReportModal");
+    const results = data.data?.attributes?.results;
+
+    getElement("fullReportContent").innerHTML = `
+        <h3>Full Report Details</h3>
+        ${results ? `
+            <table>
+                <tr><th>Engine</th><th>Result</th></tr>
+                ${Object.entries(results).map(([engine, { category }]) => `
+                    <tr>
+                        <td>${engine}</td>
+                        <td class="${category === "malicious" ? "malicious" : category === "suspicious" ? "suspicious" : "safe"}">${category}</td>
+                    </tr>
+                `).join('')}
+            </table>
+        ` : '<p>No detailed results available!</p>'}
+    `;
+
+    modal.style.display = "block";
+    modal.offsetHeight;
+    modal.classList.add("show");
+}
+
+// Closes the full report modal
+const closeModal = () => {
+    const modal = getElement("fullReportModal");
+    modal.classList.remove("show");
+    setTimeout(() => modal.style.display = "none", 300);
+}
+
+// Close modal on outside click
+window.addEventListener('load', () => {
+    const modal = getElement("fullReportModal");
+    window.addEventListener('click', e => e.target === modal && closeModal());
+});
\ No newline at end of file
diff --git a/Day #81 - Virus Total API/style.css b/Day #81 - Virus Total API/style.css
new file mode 100644
index 0000000..ea6bf7d
--- /dev/null
+++ b/Day #81 - Virus Total API/style.css	
@@ -0,0 +1,493 @@
+@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');
+
+:root{
+    --primary-color: #6366f1;
+    --primary-hover: #4f46e5;
+    --background: #f8fafc;
+    --surface: #ffffff;
+    --text: #1e293b;
+    --text-secondary: #64748b;
+    --danger: #ef4444;
+    --warning: #f59e0b;
+    --success: #10b981;
+    --border-radius: 12px;
+}
+
+body{
+    font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+    background-color: var(--background);
+    color: var(--text);
+    line-height: 1.6;
+    padding: 2rem;
+    margin: 0;
+    min-height: 100vh;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    box-sizing: border-box;
+}
+
+.container{
+    background: var(--surface);
+    padding: 1.5rem;
+    border-radius: var(--border-radius);
+    box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
+    width: 100%;
+    max-width: 525px;
+    margin: 0 auto;
+}
+
+h1{
+    color: var(--text);
+    font-size: 1.75rem;
+    font-weight: 700;
+    margin-bottom: 1.5rem;
+    letter-spacing: -0.025em;
+}
+
+section{
+    margin: 1.5rem 0;
+    text-align: left;
+}
+
+input[type="text"], input[type="file"]{
+    width: 100%;
+    padding: 0.6rem 0.875rem;
+    border: 1px solid #e2e8f0;
+    border-radius: var(--border-radius);
+    background-color: var(--surface);
+    color: var(--text);
+    font-size: 0.9375rem;
+    transition: all 0.2s ease;
+    box-sizing: border-box;
+    margin-bottom: 0.75rem;
+}
+
+input[type="text"]:focus{
+    outline: none;
+    border-color: var(--primary-color);
+    box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
+}
+
+button{
+    width: 100%;
+    padding: 0.6rem 1.25rem;
+    background-color: var(--primary-color);
+    color: #fff;
+    border: none;
+    border-radius: var(--border-radius);
+    font-size: 0.9375rem;
+    font-weight: 500;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+button:hover{
+    background-color: var(--primary-hover);
+    transform: translateY(-1px);
+}
+
+.loading{
+    padding: 2rem;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    text-align: center;
+}
+
+.spinner{
+    display: inline-block;
+    width: 40px;
+    height: 40px;
+    border: 3px solid var(--background);
+    border-radius: 50%;
+    border-top-color: var(--primary-color);
+    animation: spin 1s ease-in-out infinite;
+    margin: 1rem auto 0;
+}
+
+@keyframes spin {
+    to { transform: rotate(360deg); }
+}
+
+#result{
+    margin-top: 2rem;
+    padding: 1.5rem;
+    background: var(--surface);
+    border-radius: var(--border-radius);
+    border: 1px solid #e2e8f0;
+    display: none;
+}
+
+#result h3{
+    margin-top: 0;
+    margin-bottom: 1rem;
+    color: var(--text);
+}
+
+#result button{
+    margin-top: 1rem;
+}
+
+#result .error{
+    color: var(--danger);
+    background-color: #fee2e2;
+    padding: 1rem;
+    border-radius: var(--border-radius);
+    margin: 0;
+}
+
+.safe{
+    color: var(--success);
+    font-weight: 600;
+}
+
+.malicious{
+    color: var(--danger);
+    font-weight: 600;
+}
+
+.suspicious{
+    color: var(--warning);
+    font-weight: 600;
+}
+
+.modal{
+    display: none;
+    position: fixed;
+    z-index: 1000;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0);
+    backdrop-filter: blur(0);
+    opacity: 0;
+    transition: background-color 0.3s ease, backdrop-filter 0.3s ease, opacity 0.3s ease;
+}
+
+.modal.show{
+    background-color: rgba(0, 0, 0, 0.5);
+    backdrop-filter: blur(4px);
+    opacity: 1;
+}
+
+.modal-content{
+    background-color: var(--surface);
+    padding: 1.5rem;
+    margin: 5% auto;
+    width: 80%;
+    max-width: 800px;
+    max-height: 80vh;
+    border-radius: var(--border-radius);
+    box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
+    overflow-y: auto;
+    transform: translateY(20px);
+    opacity: 0;
+    transition: transform 0.3s ease, opacity 0.3s ease;
+}
+
+.modal.show .modal-content{
+    transform: translateY(0);
+    opacity: 1;
+}
+
+.close{
+    position: absolute;
+    right: 1.5rem;
+    top: 1rem;
+    font-size: 1.5rem;
+    font-weight: 600;
+    color: var(--text-secondary);
+    cursor: pointer;
+    transition: color 0.2s ease;
+    width: auto;
+    background: none;
+    padding: 0;
+}
+
+.close:hover{
+    color: var(--danger);
+    background: none;
+    transform: none;
+}
+
+#fullReportModal .modal-content{
+    position: relative;
+    padding-top: 3rem;
+}
+
+#fullReportContent{
+    margin-top: 1rem;
+}
+
+#fullReportContent table{
+    margin-top: 1.5rem;
+    width: 100%;
+    border-radius: var(--border-radius);
+    overflow: hidden;
+}
+
+#fullReportContent th{
+    background-color: var(--primary-color);
+    color: #fff;
+    font-weight: 600;
+    padding: 1rem;
+}
+
+#fullReportContent td{
+    padding: 0.75rem 1rem;
+    border: 1px solid #e2e8f0;
+}
+
+#fullReportContent tr:hover{
+    background-color: #f8fafc;
+}
+
+.scan-stats{
+    background: #fff;
+    border: 1px solid #e2e8f0;
+    border-radius: var(--border-radius);
+    padding: 1.5rem;
+    margin: 1rem 0;
+}
+
+.scan-stats ul{
+    list-style: none;
+    padding: 0;
+    margin: 0.5rem 0 0 0;
+}
+
+.scan-stats li{
+    padding: 0.5rem 0;
+    display: flex;
+    align-items: center;
+}
+
+.scan-stats li::before{
+    content: '';
+    display: inline-block;
+    width: 8px;
+    height: 8px;
+    border-radius: 50%;
+    margin-right: 8px;
+}
+
+.scan-stats li span.malicious::before{
+    background-color: var(--danger);
+}
+
+.scan-stats li span.suspicious::before{
+    background-color: var(--warning);
+}
+
+.scan-stats li span.safe::before{
+    background-color: var(--success);
+}
+
+.progress-section{
+    margin: 2rem 0;
+}
+
+.progress-label{
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 0.5rem;
+    font-weight: 500;
+}
+
+.progress-percent{
+    color: var(--text-secondary);
+    font-size: 0.875rem;
+}
+
+.progress-stacked{
+    height: 24px;
+    border-radius: var(--border-radius);
+    background-color: #f1f5f9;
+    overflow: hidden;
+    display: flex;
+    box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.05);
+    border: 1px solid #e2e8f0;
+}
+
+.progress-stacked:not(.animate) .progress-bar{
+    width: 0 !important;
+}
+
+.progress-bar{
+    height: 20px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: #fff;
+    font-size: 0.7rem;
+    font-weight: 600;
+    transition: all 1s ease-in-out;
+    position: relative;
+    min-width: 2rem;
+}
+
+.progress-bar.malicious{
+    background: #dc2626;
+    background-image: linear-gradient(110deg, #ef4444 0%, #dc2626 50%, #b91c1c 100%);
+    box-shadow: 0 1px 3px #dc2626;
+}
+
+.progress-bar.suspicious{
+    background: #f97316;
+    background-image: linear-gradient(110deg, #fb923c 0%, #f97316 50%, #ea580c 100%);
+    box-shadow: 0 1px 3px #f97316;
+}
+
+.progress-bar.safe{
+    background: #22c55e;
+    background-image: linear-gradient(110deg, #4ade80 0%, #22c55e 50%, #16a34a 100%);
+    box-shadow: 0 1px 3px #22c55e;
+}
+
+.progress-bar.undetected{
+    background: #64748b;
+    background-image: linear-gradient(110deg, #94a3b8 0%, #64748b 50%, #475569 100%);
+    box-shadow: 0 1px 3px #64748b;
+}
+
+.progress-label-overlay{
+    position: absolute;
+    left: 50%;
+    transform: translateX(-50%);
+    white-space: nowrap;
+    z-index: 1;
+    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
+    font-weight: 700;
+}
+
+.progress-bar[style*="width: 1."]{
+    min-width: 2rem;
+}
+
+.progress-legend{
+    display: flex;
+    gap: 1rem;
+    margin-top: 0.5rem;
+    flex-wrap: wrap;
+}
+
+.legend-item{
+    display: flex;
+    align-items: center;
+    font-size: 0.75rem;
+    color: var(--text-secondary);
+}
+
+.legend-color{
+    width: 12px;
+    height: 12px;
+    border-radius: 2px;
+    margin-right: 0.5rem;
+}
+
+.legend-color.malicious{
+    background: #dc2626;
+}
+
+.legend-color.suspicious{
+    background: #f97316;
+}
+
+.legend-color.safe{
+    background: #22c55e;
+}
+
+.legend-color.undetected{
+    background: #64748b;
+}
+
+.detection-details{
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+    gap: 0.75rem;
+    margin-top: 1.5rem;
+}
+
+.detail-item{
+    background: #fff;
+    padding: 0.875rem;
+    border-radius: var(--border-radius);
+    border: 1px solid #e2e8f0;
+    display: flex;
+    flex-direction: column;
+    gap: 0.5rem;
+    position: relative;
+    overflow: hidden;
+    cursor: pointer;
+}
+
+.detail-item::before{
+    content: '';
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 4px;
+    height: 100%;
+    background: linear-gradient(to bottom, transparent, currentColor, transparent);
+    opacity: 0.8;
+}
+
+.detail-item.malicious::before{
+    background: #dc2626;
+}
+
+.detail-item.suspicious::before{
+    background: #f97316;
+}
+
+.detail-item.safe::before{
+    background: #22c55e;
+}
+
+.detail-item:not(.malicious):not(.suspicious):not(.safe)::before{
+    background: #64748b;
+}
+
+.detail-label{
+    color: var(--text-secondary);
+    font-size: 0.875rem;
+}
+
+.detail-value{
+    font-size: 1.25rem;
+    font-weight: 700;
+    color: var(--text);
+    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.detail-percent{
+    font-size: 0.875rem;
+    color: var(--text-secondary);
+}
+
+.detail-item:hover{
+    transform: translateY(-1px);
+    box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
+    transition: all 0.2s ease;
+}
+
+@media screen and (max-width: 768px) {
+    
+    body{
+        padding: 1rem;
+    }
+
+    .container{
+        padding: 1.5rem;
+    }
+
+    .modal-content{
+        width: 95%;
+        margin: 2% auto;
+    }
+
+}
\ No newline at end of file
diff --git a/Day #81 - Contact Form With EmailJS/Logo.png b/Day #82 - Contact Form With EmailJS/Logo.png
similarity index 100%
rename from Day #81 - Contact Form With EmailJS/Logo.png
rename to Day #82 - Contact Form With EmailJS/Logo.png
diff --git a/Day #81 - Contact Form With EmailJS/README.md b/Day #82 - Contact Form With EmailJS/README.md
similarity index 99%
rename from Day #81 - Contact Form With EmailJS/README.md
rename to Day #82 - Contact Form With EmailJS/README.md
index c4f711a..3cd9853 100644
--- a/Day #81 - Contact Form With EmailJS/README.md	
+++ b/Day #82 - Contact Form With EmailJS/README.md	
@@ -1,4 +1,4 @@
-# Day #81
+# Day #82
 
 ### Contact Form With EmailJS
 🛡️ Want to Build a Contact Form with Backend Using EmailJS API? In this tutorial, we’ll create a fully functional contact form using HTML, CSS & JavaScript — no backend server required! 💬📧
diff --git a/Day #81 - Contact Form With EmailJS/index.html b/Day #82 - Contact Form With EmailJS/index.html
similarity index 100%
rename from Day #81 - Contact Form With EmailJS/index.html
rename to Day #82 - Contact Form With EmailJS/index.html
diff --git a/Day #81 - Contact Form With EmailJS/screenshot.png b/Day #82 - Contact Form With EmailJS/screenshot.png
similarity index 100%
rename from Day #81 - Contact Form With EmailJS/screenshot.png
rename to Day #82 - Contact Form With EmailJS/screenshot.png
diff --git a/Day #81 - Contact Form With EmailJS/script.js b/Day #82 - Contact Form With EmailJS/script.js
similarity index 100%
rename from Day #81 - Contact Form With EmailJS/script.js
rename to Day #82 - Contact Form With EmailJS/script.js
diff --git a/Day #81 - Contact Form With EmailJS/style.css b/Day #82 - Contact Form With EmailJS/style.css
similarity index 100%
rename from Day #81 - Contact Form With EmailJS/style.css
rename to Day #82 - Contact Form With EmailJS/style.css
diff --git a/README.md b/README.md
index 9d42f4c..c1f0cf1 100644
--- a/README.md
+++ b/README.md
@@ -90,7 +90,8 @@ Here we have list of projects:
 78. Google Gemini Clone
 79. Simple Python Compiler
 80. Google reCAPTCHA
-81. Contact Form With EmailJS
+81. Virus Total API
+82. Contact Form With EmailJS
 
 ## Where is rest 19 Projects
 

From 951d19518b7cbfdb91ca4c1dbb6bfca1fc0859b9 Mon Sep 17 00:00:00 2001
From: Reza Mehdikhanlou <rezamehdikhanlou@gmail.com>
Date: Wed, 13 Aug 2025 17:23:53 +0330
Subject: [PATCH 4/4] Fixing Day #81 Code

---
 Day #81 - Virus Total API/script.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Day #81 - Virus Total API/script.js b/Day #81 - Virus Total API/script.js
index d0358c4..f86588d 100644
--- a/Day #81 - Virus Total API/script.js	
+++ b/Day #81 - Virus Total API/script.js	
@@ -1,5 +1,5 @@
 // API key from VirusTotal API
-const API_KEY = "a3c07744cb4f644ec060470d4c4bae32808ef3595204229445f15f2b2d32d0fa";
+const API_KEY = "YOUR_API_KEY";
 
 // Utility function to get DOM elements by ID
 const getElement = id => document.getElementById(id);
