diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..dfe0770
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..859c854
--- /dev/null
+++ b/README.md
@@ -0,0 +1,382 @@
+# Tools.io
+#### `Video Demo:` https://youtu.be/Sh-YE-4NC1Y
+#### `Creator:` Sameer Prajapati
+#### `Github:` SamXop123
+
+## Description:
+
+Welcome to **Tools.io**, your ultimate destination for innovative tools and entertaining games. This project combines functionality, creativity, and fun, offering a versatile platform for various needs.
+
+## Features
+
+### Tools
+- **Random Number Generator**: Generate secure and customizable random numbers effortlessly.
+- **Markdown Previewer**: Convert Markdown syntax into a live preview for efficient documentation.
+- **QR Code Generator**: Create QR codes for URLs, text, or contact details instantly.
+
+### Games
+- **Memory Game**: Test and enhance your memory with this engaging and interactive game.
+- Additional games to keep you entertained and relaxed.
+
+## Tech Stack
+
+This project is built using:
+- **Frontend**: HTML, CSS, JavaScript
+- **Backend**: Flask (Python)
+
+
+## File Structure
+
+```
+/tools.io
+├── static/
+│ ├── css/ # Stylesheets
+│ ├── js/ # JavaScript files
+│ └── media/ # Images used in the app
+├── templates/ # HTML templates
+├── app.py # Main Flask application
+├── requirements.txt # Python dependencies
+└── README.md # Project documentation
+```
+
+## Screenshots
+
+### Home Page
+
+
+### Tools Page
+
+
+### Games Page
+
+
+### Login Page
+
+
+
+
+
+
+## Detailed Explaination:
+
+### `app.py`
+
+The `app.py` file is the main Python script for this Flask-based web application. It serves as the backbone of the project, orchestrating the various functionalities and routes that make up the toolset. Below is an overview of its structure and purpose.
+
+#### Overview
+`app.py` leverages the Flask framework to provide a web-based interface for multiple tools and games. It integrates libraries like:
+- **Flask** for web routing and rendering templates.
+- **Werkzeug Security** for password hashing and validation.
+- **gTTS** for generating text-to-speech audio.
+- **Pillow** and **rembg** for image processing.
+- **qrcode** for QR code generation.
+- **Random** and **String** for generating random data.
+- **Requests** for fetching data from external APIs.
+
+The file includes a variety of routes corresponding to different functionalities, each explained below.
+
+#### Key Routes and Functionalities
+
+1. **Home (`/`)**
+ - Displays the main landing page (`index.html`).
+ - Acts as a navigation hub for all the tools and games.
+
+2. **Tools Page (`/tools.html`)**
+ - Provides a centralized page for accessing all the utilities offered by the application.
+
+3. **Background Removal (`/bg_remove.html`)**
+ - Accepts an image file via a POST request.
+ - Uses the `rembg` library to remove the image's background.
+ - Returns the processed image for download as a PNG file.
+
+4. **IP Finder (`/ip_finder.html`)**
+ - Displays the user’s IP address or fetches details for a custom IP using the `ipinfo.io` API.
+ - Presents the data in a user-friendly format, including city, region, and organization information.
+
+5. **Random Number Generator (`/random_number.html`)**
+ - Accepts the number of digits from the user and generates a random number of the specified length.
+ - Validates input to ensure meaningful output.
+
+6. **Image Compression (`/compress.html`)**
+ - Compresses uploaded images, reducing file size while preserving quality.
+ - Allows the user to download the compressed image.
+
+7. **Password Generator (`/password_generator.html`)**
+ - Generates a secure password based on user specifications such as length and inclusion of symbols.
+
+8. **Text-to-Speech (`/text_to_speech.html`)**
+ - Converts user-provided text into speech using the `gTTS` library.
+ - Provides a downloadable audio file in MP3 format.
+
+9. **QR Code Generator (`/qr_generator.html`)**
+ - Generates a QR code from user-provided data.
+ - Returns the QR code as an image file for download.
+
+10. **Word Counter (`/word_counter.html`)**
+ - Analyzes user-provided text.
+ - Outputs word count, character count (with and without spaces).
+
+11. **Games:**
+ - **Guessing Game (`/guess.html`)**:
+ - Implements a number guessing game with session-based state management.
+ - Provides feedback to the user (“high”, “low”, or “correct”).
+ - **Snake-Water-Gun (`/snake_water_gun.html`)**:
+ - Classic hand game with random choices for the computer.
+ - Determines the winner based on game logic.
+ - **Tic-Tac-Toe (`/tictactoe.html`)**:
+ - Renders a basic Tic-Tac-Toe game page.
+ - **Memory Match (`/match.html`)** and **Snake Game (`/snake.html`)**:
+ - Provides links to respective games hosted on separate HTML pages.
+
+12. **Authentication**
+ - **Login (`/login.html`)**:
+ - Allows users to log in using a username and password.
+ - Hashes passwords securely with `Werkzeug`.
+ - **Signup (`/signup.html`)**:
+ - Enables new user registration.
+ - Prevents duplicate usernames and securely stores hashed passwords.
+
+13. **Contact Page (`/contact.html`)**
+ - Simple form for user feedback or inquiries.
+
+#### Design Choices
+1. **Session Management**:
+ - Used for maintaining state in games like the guessing game.
+2. **API Integration**:
+ - Chose the `ipinfo.io` API for its simplicity and rich data set for IP location services.
+3. **Dynamic Features**:
+ - Incorporated tools like QR generation and background removal to demonstrate versatility.
+4. **Security**:
+ - Utilized `generate_password_hash` and `check_password_hash` to secure user credentials.
+
+#### Summary
+`app.py` is the cornerstone of the project, bringing together various libraries and frameworks to offer a diverse range of tools and entertainment options. Its modular design ensures that each functionality operates independently, yet cohesively as part of the broader application.
+
+
+
+### `layout.html`
+
+This file defines the base layout for the "tools.io" web application, built using Flask, HTML, CSS, and JavaScript. It serves as the foundational structure for all pages on the website, ensuring a consistent look and feel across the site.
+
+### Overview
+
+The `layout.html` template is used by Flask to render the overall structure of the site. It includes navigation, dynamic content blocks, and links to various CSS and JavaScript files for styling and interactivity. This layout template is inherited by other pages in the Flask project. For example, pages like `tools.html`, `games.html`, and `contact.html` extend this layout and inject their unique content into the `{% block content %}`.
+
+## Key Features
+
+- **Navigation Bar**:
+ - Includes links to the home page, tools, games, and contact pages.
+ - Displays different buttons based on the user's session (Log in, Log out, Sign up).
+
+- **Dynamic Content Blocks**:
+ - Usage of jinja syntax allows custom body content to be added to different pages for specific styling.
+
+- **Responsive Design**:
+
+- **External Stylesheets**:
+
+- **Links JavaScript Files**:
+
+
+
+
+### `index.html`
+
+This file defines the layout and content of the home page for the "tools.io" web application, built using Flask, HTML, CSS, and JavaScript. The home page serves as an introduction to the website, providing users with a welcoming experience, a brief overview of the platform, and direct links to explore its tools and games.
+
+
+### Key Features
+
+- **Main Title**:
+ - Displays the website title, "tools.io", with a brief tagline: *"Unleash Your Creativity: Explore a World of Games and Tools to Ignite Your Imagination!"*
+
+- **Call-to-Action (CTA) Buttons**:
+ - Links to "Explore Tools" and "Play Games" to direct users to the respective pages.
+
+- **About Us Section**:
+ - A brief description of Tools.io's mission and offerings: tools for productivity, creativity, and entertainment.
+
+- **User Testimonials**:
+ - Positive feedback from users, showcasing the site’s utility and user satisfaction.
+
+- **Latest Updates Section**:
+ - Features announcements about new games and tools available on the platform, including links to try them out.
+
+- **Footer**:
+ - Contains three sections: *About Us*, *Quick Links* to the main pages, and *Follow Us* with social media links.
+
+
+
+### `tools.html`
+
+This file defines the layout and content of the tools page for the "tools.io" web application, built using Flask, HTML, CSS, and JavaScript. The tools page provides a categorized display of various tools available on the platform for users to explore and use.
+
+### Key Features
+
+- **Title**:
+ - The page displays the title "Explore Our Tools!" to introduce the tools section of the website.
+
+- **Tools Cards**:
+ - Each tool is displayed in its own card with:
+ - A title (e.g., *Background Remover*, *IP Finder*, *Random Number Generator*).
+ - An associated image representing the tool.
+ - A link that navigates to the specific tool's page.
+
+ The current tools displayed are:
+ - **Background Remover**: A tool to remove backgrounds from images.
+ - **IP Finder**: A tool to find the IP address of the user or other information.
+ - **Random Number Generator**: A tool for generating random numbers.
+ - **Image Compressor**: A tool to compress images to save space.
+ - **Password Generator**: A tool to generate secure passwords.
+ - **Text-to-Speech**: A tool that converts text to speech.
+ - **Word Counter**: A tool to count the number of words in a text.
+ - **QR Generator**: A tool to generate QR codes for any text or URL.
+
+
+
+### `games.html`
+
+This file defines the layout and content of the games page for the "tools.io" web application, built using Flask, HTML, CSS, and JavaScript. The games page showcases a collection of interactive games available for users to play and enjoy.
+
+### Key Features
+
+- **Title**:
+ - The page displays the title "Explore Our Available Games!" to introduce the games section of the website.
+
+- **Games Cards**:
+ - Each game is displayed in its own card with:
+ - A title (e.g., *Number Guess*, *Snake Water Gun*, *Tic Tac Toe*).
+ - An associated image representing the game.
+ - A link that navigates to the specific game's page.
+
+ The current games displayed are:
+ - **Number Guess**: A guessing game where users try to guess a number.
+ - **Snake Water Gun**: A simple game based on the classic "rock, paper, scissors" with a twist.
+ - **Tic Tac Toe**: The classic two-player grid game.
+ - **Snake Game**: The classic snake game where players control a snake to eat food and grow longer.
+ - **Memory Match**: A memory matching game where users flip cards to find pairs.
+
+
+
+
+# Styling
+
+The overall theme of the web application is based on shades of purple, giving it a rich and dark aesthetic, with contrasting highlights to create a sleek, modern look. The primary background of the website is set to an elegant dark purple with a soft, semi-transparent texture, adding depth and vibrancy.
+
+
+#### General Body Styling
+The body background features a beautiful background image, with an overlay of dark purple shades. On specific pages like the Games and Tools pages, the background image is removed to focus more on content, while maintaining the consistent dark purple hue.
+
+#### Navbar Styling
+The navigation bar (navbar) is designed with a gradient of purples to match the overall theme, blending dark shades of purple for a refined, luxurious feel. The buttons in the navbar have a smooth transition and subtle hover effects, creating an interactive experience for the user.
+
+#### Button Styling
+Buttons across the website are clean, with a simple transparent background and white borders, making them stand out against the dark background. On hover, the buttons get a subtle glow effect and slightly enlarge, creating a sense of interactivity.
+
+#### Typography
+The font choices include both playful and professional options. For example, the "Most Heroes" and "Atma" fonts are used to give the website an adventurous and dynamic feel.
+
+#### Cards
+The card design is especially unique, incorporating a blurred background effect using an image. The hover effect reduces the blur to bring attention to the content, giving the cards a dynamic feel.
+
+#### Visual Effects and Transitions
+The website includes various smooth transitions for elements like buttons, logos, and cards. These transitions include hover effects for buttons and glow for cards.
+
+#### Consistency and Responsiveness
+Throughout the design, there is a consistent use of purple tones, smooth shadows, and soft gradients that tie all elements together visually.
+
+
+
+
+# Javascript
+
+This project also showcases various interactive features powered by JavaScript. These include a contact form submission handler, memory match game, Tic Tac Toe, Snake game, and a number guessing game. Each feature enhances the user experience by utilizing JavaScript for dynamic content and real-time updates.
+
+## Features
+
+### 1. Contact Form
+- The contact form on the `contact.html` page allows users to send messages. Upon submitting the form, a popup message appears thanking the user for their submission. After 2.5 seconds, the popup disappears, and the user is redirected to the homepage.
+Prevents the default form submission `e.preventDefault()`.
+Creates and styles a popup message.
+
+### 2. Memory Match Game
+
+ - **Card flipping**: In the code, when a user clicks a card, the `card.classList.add('flipped')` line adds the flipped class to the clicked card. This class triggers the CSS that visually flips the card to reveal the image inside. Additionally, const `img = card.querySelector('img')` targets the image inside the card, and `img.style.opacity = 1` makes the image visible when the card is flipped.
+
+ - **Card matching**: After two cards are flipped, the game checks whether the images on the two flipped cards match by comparing their `dataset.id` values: `flippedCards[0].dataset.id === flippedCards[1].dataset.id`. If the IDs match, the cards are added to the matchedCards array, which keeps track of matched cards. If the IDs do not match, the cards are flipped back by resetting their opacity to 0 and removing the flipped class after a short delay.
+
+ - **Move counter**: Each time two cards are flipped, the `moves++` statement increments the moves variable by 1. This counts the number of turns the player takes to match all the cards.
+
+ - **Shuffle**: To shuffle the cards, the `shuffle()` function is called at the beginning. It selects each card using `cards.forEach(card => {...})`, and for each card, it generates a random order by setting the `style.order` property with `const randomIndex = Math.floor(Math.random() * cards.length)`.
+
+ - **Game completion**: Once all pairs are matched, the game displays a congratulatory message. The message is set using `document.getElementById('message').textContent = Congratulations! You won in ${moves} moves`.
+
+### 3. TicTacToe Game
+
+- **Board creation**:
+The `createBoard` function dynamically creates a 3x3 grid by adding div elements for each cell and attaching click event listeners to handle player moves.
+
+- Game logic:
+The `checkWinner` function checks the `gameBoard` for any winning conditions, looking for three consecutive matching marks ("X" or "O") in rows, columns, or diagonals. If a win or tie is detected, it updates the game status and stops further moves.
+- Cell clicks:
+The `handleCellClick` function handles player moves. It updates the cell with the current player's mark ("X" or "O") and alternates the turn after each valid move. If a winner or tie is not found, the next player’s turn is displayed.
+- Game restart:
+The `restartButton` listener resets the `gameBoard`, sets the current player back to "X", and recreates the board to start a new game.
+
+### 4. Snake Game
+
+
+- **Canvas setup:**
+In the code, `const canvas = document.getElementById("gameCanvas");` accesses the HTML canvas element, and `const ctx = canvas.getContext("2d");` gets the 2D rendering context. This context is used to draw shapes (like the snake and food) on the canvas.
+
+- **Snake movement:**
+The snake's initial position is set with `let snake = [{ x: 9 * box, y: 10 * box }];`, where each grid cell is 20x20 pixels. The `document.addEventListener("keydown", (event) => {...})` function listens for arrow key presses and changes the snake's direction. For example, `if (event.key === "ArrowLeft" && direction !== "RIGHT") direction = "LEFT";` ensures the snake can only move in the opposite direction if it isn't already moving in that direction.
+
+- **Game drawing:**
+The `draw()` function clears the canvas each frame with `ctx.clearRect(0, 0, canvas.width, canvas.height);`. Then, it draws the snake and the food. The snake is drawn by looping through each segment of the snake's body and coloring the head green and the body light green. `ctx.fillStyle = "green"; ctx.fillRect(segment.x, segment.y, box, box);` handles this for each segment.
+
+- **Food placement:**
+Food is placed at a random position using:
+```javascript
+let food = {
+ x: Math.floor(Math.random() * 19 + 1) * box,
+ y: Math.floor(Math.random() * 19 + 1) * box,
+};
+```
+This ensures the food appears within the canvas bounds and on the grid.
+
+- **Snake growth:**
+When the snake eats food (when the head’s position matches the food’s position), it grows in size. The condition `if (head.x === food.x && head.y === food.y)` checks if the snake’s head touches the food. If true, the score increments, and new food is placed randomly. If the snake does not eat, `snake.pop();` removes the last segment of the snake to simulate movement.
+
+- **Collision detection:**
+The game checks for collisions with the wall or the snake's own body using the following condition:
+```javascript
+if (
+ head.x < 0 || head.y < 0 ||
+ head.x >= canvas.width || head.y >= canvas.height ||
+ snake.some((segment) => segment.x === head.x && segment.y === head.y)
+) {
+ clearInterval(game);
+ alert("Game Over! Your score: " + score);
+}
+```
+If the snake hits the wall or itself, the game ends, and the player is shown the score.
+
+- **Snake movement logic:**
+The snake moves by updating its head’s position based on the current direction:
+```javascript
+let head = { ...snake[0] };
+if (direction === "LEFT") head.x -= box;
+if (direction === "UP") head.y -= box;
+if (direction === "RIGHT") head.x += box;
+if (direction === "DOWN") head.y += box;
+```
+
+- **Game loop:**
+`const game = setInterval(draw, 100);` runs the `draw()` function every 100 milliseconds, updating the canvas and game state.
+
+---
+
+
+## Contact
+For any inquiries, feedback, or suggestions, feel free to contact us via the **Contact** section on the website or email us at `sameerprajapati066@gmail.com`.
\ No newline at end of file
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..37899fd
--- /dev/null
+++ b/app.py
@@ -0,0 +1,297 @@
+from flask import Flask, render_template, request, redirect, jsonify, session, flash, send_file, url_for
+from flask_cors import CORS
+from flask_session import Session
+from werkzeug.security import check_password_hash, generate_password_hash
+from gtts import gTTS
+from PIL import Image
+from rembg import remove
+import qrcode
+from io import BytesIO
+import requests
+import random
+import string
+import io
+
+
+app = Flask(__name__)
+app.secret_key = "supersecretkey"
+CORS(app)
+users_db = {}
+
+
+@app.route('/')
+def home():
+ return render_template('index.html')
+
+
+@app.route('/tools.html')
+def tools():
+ return render_template('tools.html')
+
+
+@app.route('/bg_remove.html', methods=['GET', 'POST'])
+def bg_remove():
+ if request.method == 'POST':
+ file = request.files['image']
+ img = Image.open(file.stream)
+
+ # Removes the background
+ output = remove(img)
+
+ # Save the image to a BytesIO object
+ img_byte_arr = io.BytesIO()
+ output.save(img_byte_arr, format="PNG")
+ img_byte_arr.seek(0)
+
+ return send_file(img_byte_arr, as_attachment=True, download_name="output.png")
+
+ return render_template('bg_remove.html')
+
+
+@app.route('/ip_finder.html', methods=['GET', 'POST'])
+def ip_finder():
+ if request.method == 'POST':
+ option = request.form.get('option')
+
+ if option == 'know_your_ip':
+ # Display the user's IP
+ user_ip = request.remote_addr
+ return render_template('ip_finder.html', ip=user_ip, location=None, show_ip=True)
+
+ elif option == 'custom_ip':
+ # Extracting location of a custom IP
+ custom_ip = request.form.get('custom_ip')
+ response = requests.get(f"https://ipinfo.io/{custom_ip}/json")
+ if response.status_code == 200:
+ data = response.json()
+ location = {
+ "IP": data.get("ip"),
+ "City": data.get("city"),
+ "Region": data.get("region"),
+ "Country": data.get("country"),
+ "Latitude and Longitude": data.get("loc"),
+ "Organization": data.get("org"),
+ }
+ else:
+ location = None # Handle any invalid IP
+ return render_template('ip_finder.html', ip=None, location=location, show_ip=False)
+
+ return render_template('ip_finder.html', ip=None, location=None, show_ip=False)
+
+
+@app.route('/random_number.html', methods=['GET', 'POST'])
+def random_number():
+ if request.method == 'POST':
+ digits = request.form.get('digits', type=int)
+ if digits and digits > 0:
+ min_num = 10**(digits - 1)
+ max_num = (10**digits) - 1
+ random_num = random.randint(min_num, max_num)
+ return render_template('random_number.html', random_num=random_num, digits=digits)
+ else:
+ error = "Please enter a valid number of digits greater than 0."
+ return render_template('random_number.html', random_num=None, error=error)
+ return render_template('random_number.html', random_num=None)
+
+
+@app.route('/compress.html', methods=['GET', 'POST'])
+def compress_image():
+ if request.method == 'POST':
+ file = request.files['image']
+ image = Image.open(file)
+ buffer = io.BytesIO()
+ image_format = "JPEG" if file.filename.endswith(".jpg") or file.filename.endswith(".jpeg") else "PNG"
+ image.save(buffer, format=image_format, quality=50) # 50% compression for JPEG, no quality param for PNG
+ buffer.seek(0)
+
+ # Saves the file temporarily for download
+ compressed_image_path = "static/compressed_image." + image_format.lower()
+ with open(compressed_image_path, "wb") as f:
+ f.write(buffer.getbuffer())
+
+ return render_template(
+ 'compress.html',
+ success=True,
+ download_url="/" + compressed_image_path
+ )
+ return render_template('compress.html', success=False)
+
+
+@app.route('/password_generator.html', methods=['GET', 'POST'])
+def password_generator():
+ if request.method == 'POST':
+ length = int(request.form['length'])
+ include_symbols = 'symbols' in request.form
+ chars = string.ascii_letters + string.digits
+ if include_symbols:
+ chars += string.punctuation
+ password = ''.join(random.choices(chars, k=length))
+ return render_template('password_generator.html', password=password)
+ return render_template('password_generator.html')
+
+
+@app.route('/text_to_speech.html', methods=['GET', 'POST'])
+def text_to_speech():
+ if request.method == 'POST':
+ text = request.form['text']
+ tts = gTTS(text)
+ file_path = "static/output.mp3"
+ tts.save(file_path)
+
+ # To Provide the file's URL to the template:
+ audio_url = url_for('static', filename='output.mp3')
+ return render_template('text_to_speech.html', audio_url=audio_url)
+
+ return render_template('text_to_speech.html')
+
+
+@app.route('/qr_generator.html', methods=['GET', 'POST'])
+def qr_generator():
+ if request.method == 'POST':
+ data = request.form['qr_text']
+ qr_img = qrcode.make(data)
+ buffer = BytesIO()
+ qr_img.save(buffer, 'PNG')
+ buffer.seek(0)
+ return send_file(buffer, mimetype='image/png')
+ return render_template('qr_generator.html')
+
+
+@app.route('/word_counter.html', methods=['GET', 'POST'])
+def word_counter():
+ word_count = None
+ char_count_with_spaces = None
+ char_count_without_spaces = None
+
+ if request.method == 'POST':
+ text = request.form.get('text', '')
+ words = text.strip().split()
+ word_count = len(words)
+ char_count_with_spaces = len(text)
+ char_count_without_spaces = len(text.replace(' ', ''))
+
+ return render_template(
+ 'word_counter.html',
+ word_count=word_count,
+ char_count_with_spaces=char_count_with_spaces,
+ char_count_without_spaces=char_count_without_spaces
+ )
+
+
+@app.route('/games.html')
+def games():
+ return render_template('games.html')
+
+
+@app.route('/guess.html', methods=['GET', 'POST'])
+def guessing_game():
+ if request.method == 'POST':
+ # Handles the guess and session logic here
+ guess = int(request.json.get('guess', 0))
+ secret_number = session.get('secret_number', None)
+
+ if not secret_number:
+ secret_number = random.randint(1, 100)
+ session['secret_number'] = secret_number
+
+ if guess < secret_number:
+ return jsonify({'result': 'low'})
+ elif guess > secret_number:
+ return jsonify({'result': 'high'})
+ else:
+ session.pop('secret_number', None) # Resets the game
+ return jsonify({'result': 'correct'})
+
+ return render_template('guess.html')
+
+
+@app.route("/snake_water_gun.html", methods=["GET", "POST"])
+def snake_water_gun():
+ if request.method == "POST":
+ user_choice = request.form["choice"].lower()
+ game = ["snake", "water", "gun"]
+ computer_choice = random.choice(game)
+
+ result = ""
+ if user_choice == computer_choice:
+ result = "Draw!"
+ elif (user_choice == "snake" and computer_choice == "water") or \
+ (user_choice == "water" and computer_choice == "gun") or \
+ (user_choice == "gun" and computer_choice == "snake"):
+ result = "You won!"
+ else:
+ result = "Computer wins!"
+
+ return render_template("snake_water_gun.html", result=result, user_choice=user_choice, computer_choice=computer_choice)
+
+ return render_template("snake_water_gun.html", result=None)
+
+@app.route('/tictactoe.html')
+def tictactoe():
+ return render_template('tictactoe.html')
+
+@app.route('/match.html')
+def memory_match():
+ return render_template('match.html')
+
+@app.route('/snake.html')
+def snake():
+ return render_template('snake.html')
+
+@app.route('/contact.html')
+def contact():
+ return render_template('contact.html')
+
+
+@app.route('/login.html', methods=['GET', 'POST'])
+def login():
+ if request.method == 'POST':
+ username = request.form['username']
+ password = request.form['password']
+
+ user = users_db.get(username)
+
+ if user and check_password_hash(user['password'], password):
+ session['username'] = username # Stores the username in session
+ flash("Logged in successfully!", "success")
+ return redirect(url_for('home')) # Redirects to the home page
+ else:
+ flash("Invalid username or password", "danger")
+ return render_template('login.html', error="Invalid username or password")
+
+ return render_template('login.html')
+
+
+@app.route('/signup.html', methods=['GET', 'POST'])
+def signup():
+ if request.method == 'POST':
+ username = request.form['username']
+ email = request.form['email']
+ password = request.form['password']
+
+ if username in users_db:
+ return render_template('signup.html', error="Username already exists")
+
+ users_db[username] = {'email': email, 'password': generate_password_hash(password)}
+
+ return render_template('signup.html', success="Account created successfully!")
+
+ return render_template('signup.html')
+
+
+@app.route('/dashboard')
+def dashboard():
+ if 'username' not in session:
+ return redirect(url_for('login'))
+ return f'Welcome, {session["username"]}!'
+
+@app.route('/logout')
+def logout():
+ session.pop('username', None) # Correctly pops the session variable
+ flash("You have been logged out.", "info")
+ return redirect(url_for('login'))
+
+
+if __name__ == '__main__':
+ # init_db()
+ app.run(debug=True)
diff --git a/intro.txt b/intro.txt
new file mode 100644
index 0000000..34a8722
--- /dev/null
+++ b/intro.txt
@@ -0,0 +1 @@
+Welcome to Tools.io, your ultimate destination for innovative tools and entertaining games. This project combines functionality, creativity, and fun, offering a versatile platform for various needs.
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..2a85521
Binary files /dev/null and b/requirements.txt differ
diff --git a/static/css/bg_remove.css b/static/css/bg_remove.css
new file mode 100644
index 0000000..3b13697
--- /dev/null
+++ b/static/css/bg_remove.css
@@ -0,0 +1,82 @@
+
+.bg-remove {
+ font-family: Arial, sans-serif;
+ color: white;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 60vh;
+ margin: 0;
+}
+
+/* Container for the form */
+.formbg-container {
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(10px);
+ padding: 30px 50px;
+ border-radius: 20px;
+ box-shadow: 0px 8px 20px rgba(0, 0, 0, 0.3);
+ text-align: center;
+ width: 350px;
+}
+
+/* File Input for Image */
+.bg-remove-file {
+ width: 100%;
+ padding: 10px;
+ border: none;
+ border-radius: 5px;
+ font-size: 16px;
+ box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2);
+ background: rgba(255, 255, 255, 0.1);
+ margin-bottom: 20px;
+}
+
+/* Remove Background Button */
+.bg-remove-btn {
+ padding: 12px 24px;
+ border: none;
+ border-radius: 5px;
+ background-color: #7f0cea;
+ color: white;
+ font-weight: bold;
+ font-size: 16px;
+ cursor: pointer;
+ transition: 0.3s ease;
+ margin-top: 10px;
+ width: 100%;
+}
+
+.bg-remove-btn:hover {
+ background-color: #5d059b;
+ box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.2);
+}
+
+.bg-remove-result {
+ margin-top: 20px;
+}
+
+/* Processed Image Display */
+.bg-remove-image {
+ max-width: 100%;
+ height: auto;
+ border-radius: 10px;
+ margin-top: 15px;
+}
+
+.bg-remove-download-btn {
+ padding: 10px 20px;
+ border: none;
+ border-radius: 5px;
+ background-color: #28a745;
+ color: white;
+ font-size: 16px;
+ font-weight: bold;
+ cursor: pointer;
+ transition: 0.3s ease;
+}
+
+.bg-remove-download-btn:hover {
+ background-color: #218838;
+ box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2);
+}
diff --git a/static/css/compress.css b/static/css/compress.css
new file mode 100644
index 0000000..d4599a7
--- /dev/null
+++ b/static/css/compress.css
@@ -0,0 +1,106 @@
+/* General Styles */
+.compressed {
+ font-family: Arial, sans-serif;
+ color: white;
+ margin: 0;
+ height: 60vh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+/* Compressor Container */
+.image-compressor {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ height: 100%;
+}
+
+/* Compression Box */
+.compression-box {
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(10px);
+ padding: 20px 40px;
+ border-radius: 15px;
+ box-shadow: 0px 8px 20px rgba(0, 0, 0, 0.3);
+ text-align: center;
+ width: 350px;
+}
+
+/* Heading Styles */
+.compression-box h1 {
+ font-size: 24px;
+ margin-bottom: 20px;
+ color: linear-gradient(to right, #2c0143 60%, #9304cc);;
+}
+
+/* File Input */
+.compression-box input[type="file"] {
+ display: block;
+ margin: 10px 0;
+ padding: 10px;
+ border: none;
+ border-radius: 5px;
+ width: 100%;
+ font-size: 14px;
+ background-color: white;
+ color: black;
+ box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2);
+}
+
+/* Button Styles */
+.compression-box button {
+ padding: 10px 20px;
+ border: none;
+ border-radius: 5px;
+ background-color: #7f0cea;
+ color: white;
+ font-weight: bold;
+ font-size: 16px;
+ cursor: pointer;
+ transition: 0.3s ease;
+ margin-top: 10px;
+}
+
+.compression-box button:hover {
+ background-color: #5d059b;
+ box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.2);
+}
+
+/* Note Below the Form */
+.compression-box .note {
+ font-size: 14px;
+ margin-top: 10px;
+ color: #ccc;
+ font-style: italic;
+}
+
+/* Success Message */
+.success-message {
+ color: #074c09;
+ font-size: 16px;
+ margin-top: 20px;
+ font-weight: bold;
+ text-align: center;
+}
+
+/* Download Button */
+.download-button {
+ display: inline-block;
+ margin-top: 15px;
+ padding: 10px 20px;
+ background-color: #3b8de3;
+ color: white;
+ font-weight: bold;
+ text-decoration: none;
+ border-radius: 5px;
+ transition: 0.3s ease;
+ text-align: center;
+}
+
+.download-button:hover {
+ background-color: #1e7fdc;
+ box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.2);
+}
\ No newline at end of file
diff --git a/static/css/contact.css b/static/css/contact.css
new file mode 100644
index 0000000..7da6fe4
--- /dev/null
+++ b/static/css/contact.css
@@ -0,0 +1,86 @@
+/* Contact page title styling */
+.contact_title {
+ font-family: Sunday Milk, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
+ text-align: center;
+ font-size: 50px;
+ color: #c7a6e2; /* Light purple for contrast */
+ text-shadow: 3px 3px 5px black;
+ margin-bottom: 10px;
+}
+
+/* Subtitle below the title */
+.contact_subtitle {
+ text-align: center;
+ font-family: Arial, sans-serif;
+ color: #e0cfe8;
+ margin-bottom: 30px;
+ font-size: 18px;
+}
+
+/* Contact form container styling */
+.contact_form_container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+ padding: 20px;
+ background-color: rgba(42, 14, 82, 0.9); /* Dark purple background with transparency */
+ border-radius: 10px;
+ width: 50%;
+ margin: 0 auto;
+ box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.3); /* Add a shadow for depth */
+}
+
+/* Fieldset and form field styling */
+fieldset {
+ border: none;
+ margin-bottom: 15px;
+ width: 100%;
+}
+
+label {
+ font-family: Arial, sans-serif;
+ font-size: 16px;
+ color: #e0cfe8; /* Light purple */
+ display: block;
+ margin-bottom: 5px;
+}
+
+input,
+textarea {
+ width: 100%;
+ padding: 10px;
+ margin-bottom: 10px;
+ font-size: 16px;
+ color: #2a0e52;
+ background-color: #c7a6e2; /* Light purple background */
+ border: 1px solid #9b79b0;
+ border-radius: 5px;
+ outline: none;
+ transition: all 0.3s ease;
+}
+
+input:focus,
+textarea:focus {
+ border-color: #d9c1f0;
+ box-shadow: 0px 0px 5px #d9c1f0;
+}
+
+/* Submit button styling */
+.submit_button {
+ padding: 10px 20px;
+ font-size: 16px;
+ font-weight: bold;
+ color: #ffffff;
+ background-color: #5e278b; /* Medium purple */
+ border: none;
+ border-radius: 5px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+}
+
+.submit_button:hover {
+ background-color: #431c6b; /* Darker purple */
+ transform: scale(1.05); /* Slightly enlarge on hover */
+ box-shadow: 0px 4px 10px rgba(94, 39, 139, 0.8);
+}
diff --git a/static/css/ip_finder.css b/static/css/ip_finder.css
new file mode 100644
index 0000000..e125981
--- /dev/null
+++ b/static/css/ip_finder.css
@@ -0,0 +1,75 @@
+/* Styles for IP Finder */
+.ip-finder {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 80vh;
+ color: white;
+ font-family: Arial, sans-serif;
+}
+
+.ip-container {
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(10px);
+ padding: 30px 50px;
+ border-radius: 15px;
+ box-shadow: 0px 8px 20px rgba(0, 0, 0, 0.3);
+ text-align: center;
+ width: 400px;
+}
+
+.ip-container h1 {
+ font-size: 24px;
+ margin-bottom: 20px;
+ background: linear-gradient(to right, #2c0143 60%, #9304cc);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.ip-container form {
+ margin-bottom: 20px;
+}
+
+.ip-container input[type="text"] {
+ width: 100%;
+ padding: 10px;
+ border-radius: 5px;
+ border: none;
+ margin: 10px 0;
+ font-size: 16px;
+ box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2);
+}
+
+.ip-container button {
+ padding: 10px 20px;
+ border: none;
+ border-radius: 5px;
+ background-color: #7f0cea;
+ color: white;
+ font-weight: bold;
+ font-size: 16px;
+ cursor: pointer;
+ transition: 0.3s ease;
+}
+
+.ip-container button:hover {
+ background-color: #5d059b;
+ box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.2);
+}
+
+.ip-display,
+.location-display {
+ margin-top: 20px;
+ text-align: left;
+ background: rgba(0, 0, 0, 0.1);
+ padding: 15px;
+ border-radius: 10px;
+}
+
+.location-display h3 {
+ font-size: 18px;
+ margin-bottom: 10px;
+ background: linear-gradient(to right, #7f0cea, #5d059b);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
diff --git a/static/css/match.css b/static/css/match.css
new file mode 100644
index 0000000..f666dd5
--- /dev/null
+++ b/static/css/match.css
@@ -0,0 +1,88 @@
+
+.memory-game {
+ display: flex;
+ flex-wrap: wrap;
+ width: 400px;
+ margin: auto;
+}
+
+.memory-card {
+ width: 80px;
+ height: 80px;
+ margin: 5px;
+ background-color: #ccc;
+ display: inline-block;
+ cursor: pointer;
+ transition: transform 0.3s;
+ position: relative;
+ overflow: hidden;
+ border: 5px solid blueviolet;
+ box-shadow: 2px 3px 5px purple;
+}
+
+.memory-card.flipped {
+ background-color: #f0f0f0;
+ transform: rotateY(180deg);
+}
+
+.memory-card img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover; /* ensures images fit the card size */
+ display: block;
+ opacity: 0; /* hides the image initially */
+ transition: opacity 0.3s;
+}
+
+.match-text p {
+ text-align: center;
+}
+.match-text h1 {
+ margin-top: 30px;
+ text-align: center;
+ font-family: Atma;
+ font-size: 30px;
+ font-weight: 800;
+ margin-bottom: 20px;
+ background: linear-gradient(to right, #2c0143 60%, #9304cc);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.mem-message {
+ font-size: 20px;
+ color: linear-gradient(to right, #2c0143 60%, #9304cc);
+ text-align: center;
+ font-weight: bold;
+ text-shadow: 2px 2px 5px white;
+}
+
+.mem-action {
+ text-align: center;
+}
+.mem-action form button {
+ padding: 10px 20px;
+ border: none;
+ border-radius: 5px;
+ background-color: blueviolet;
+ color: white;
+ font-weight: bold;
+ font-size: 16px;
+ cursor: pointer;
+ transition: 0.3s ease;
+}
+
+.mem-action form button:hover {
+ background-color: #35006d;
+ box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.2);
+}
+
+/* Add custom classes for each card to display specific images */
+.memory-card[data-id="1"] img { content: url('/static/media/image1.jpeg'); }
+.memory-card[data-id="2"] img { content: url('/static/media/image2.jpeg'); }
+.memory-card[data-id="3"] img { content: url('/static/media/image3.jpeg'); }
+.memory-card[data-id="4"] img { content: url('/static/media/image4.jpeg'); }
+.memory-card[data-id="5"] img { content: url('/static/media/image5.jpeg'); }
+.memory-card[data-id="6"] img { content: url('/static/media/image6.jpeg'); }
+.memory-card[data-id="7"] img { content: url('/static/media/image7.jpeg'); }
+.memory-card[data-id="8"] img { content: url('/static/media/image8.jpeg'); }
diff --git a/static/css/number_guess.css b/static/css/number_guess.css
new file mode 100644
index 0000000..34b554f
--- /dev/null
+++ b/static/css/number_guess.css
@@ -0,0 +1,106 @@
+
+body.guess-page {
+ background: linear-gradient(135deg, #2a0e52, #5a3fc0);
+ font-family: 'Arial', sans-serif;
+ color: #fff;
+ margin: 0;
+ padding: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+ overflow: hidden;
+}
+
+/* Title */
+.game_title {
+ padding-top: 27px;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 2.5em;
+ text-align: center;
+ margin-bottom: 1.5rem;
+ font-weight: bold;
+ color: #fff;
+}
+
+/* instructions */
+.game_instructions {
+ font-family:Georgia, 'Times New Roman', Times, serif;
+ text-align: center;
+ font-size: 1.4em;
+ margin-bottom: 3rem;
+ color: #eee;
+ text-align: center;
+}
+
+/* main container */
+.game_container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 1.5rem;
+ background-color: rgba(0, 0, 0, 0.6);
+ padding: 40px;
+ border-radius: 10px;
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4);
+ margin-left: 500px;
+ margin-right: 500px;
+}
+
+/* input field styling */
+#guessInput {
+ padding: 12px;
+ font-size: 1.2rem;
+ border: 2px solid #fff;
+ border-radius: 5px;
+ background-color: #3a1151;
+ color: #fff;
+ width: 250px;
+ max-width: 100%;
+ transition: all 0.3s ease;
+}
+
+#guessInput:focus {
+ border-color: #5a3fc0;
+ outline: none;
+ background-color: #5a3fc0;
+}
+
+/* button styling */
+#submitGuess {
+ padding: 12px 24px;
+ font-size: 1.1rem;
+ border: none;
+ border-radius: 5px;
+ background-color: #5a3fc0;
+ color: #fff;
+ cursor: pointer;
+ transition: transform 0.3s ease, background-color 0.3s ease;
+ width: 250px;
+ max-width: 100%;
+}
+
+#submitGuess:hover {
+ transform: scale(1.1);
+ background-color: #6b4fd8;
+}
+
+/* feedback message */
+#feedback {
+ font-size: 1.3em;
+ color: #ddd;
+ text-align: center;
+}
+
+/* for responsive design */
+@media (max-width: 600px) {
+ .game_container {
+ width: 80%;
+ padding: 20px;
+ }
+
+ #guessInput, #submitGuess {
+ width: 100%;
+ font-size: 1rem;
+ }
+}
diff --git a/static/css/password.css b/static/css/password.css
new file mode 100644
index 0000000..7f1c31c
--- /dev/null
+++ b/static/css/password.css
@@ -0,0 +1,68 @@
+
+.password {
+ font-family: Arial, sans-serif;
+ color: white;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 60vh;
+ margin: 0;
+}
+
+/* container for the form */
+.form-container {
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(10px);
+ padding: 20px 40px;
+ border-radius: 15px;
+ box-shadow: 0px 8px 20px rgba(0, 0, 0, 0.3);
+ text-align: center;
+ width: 300px;
+}
+
+/* form elements */
+label {
+ font-size: 16px;
+ margin-bottom: 10px;
+ display: block;
+ text-align: center;
+}
+
+input[type="number"],
+input[type="checkbox"] {
+ margin: 10px 0;
+ padding: 10px;
+ border: none;
+ border-radius: 5px;
+ width: 100%;
+ font-size: 14px;
+ box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2);
+}
+
+button {
+ padding: 10px 20px;
+ border: none;
+ border-radius: 5px;
+ background-color: #7f0cea;
+ color: white;
+ font-weight: bold;
+ font-size: 16px;
+ cursor: pointer;
+ transition: 0.3s ease;
+ margin-top: 10px;
+}
+
+button:hover {
+ background-color: #5d059b;
+ box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.2);
+}
+
+.generated-password {
+ margin-top: 15px;
+ font-size: 18px;
+ font-weight: bold;
+ background: rgba(255, 255, 255, 0.1);
+ padding: 10px;
+ border-radius: 10px;
+ box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2);
+}
diff --git a/static/css/qr_generator.css b/static/css/qr_generator.css
new file mode 100644
index 0000000..cdf12c3
--- /dev/null
+++ b/static/css/qr_generator.css
@@ -0,0 +1,33 @@
+.qr-container {
+ text-align: center;
+ margin: 50px auto;
+ padding: 30px;
+ font-family: Arial, sans-serif ;
+ color: white;
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(10px);
+ border-radius: 15px;
+ box-shadow: 0px 8px 20px rgba(0, 0, 0, 0.3);
+ width: 300px;
+}
+
+.qr-container form input {
+ width: 90%;
+ padding: 10px;
+ margin: 10px 0;
+ border-radius: 5px;
+ border: 1px solid #ccc;
+}
+
+.qr-container button {
+ padding: 10px 20px;
+ background-color: #7f0cea;
+ color: white;
+ border: none;
+ border-radius: 5px;
+ cursor: pointer;
+}
+
+.qr-container button:hover {
+ background-color: #5d059b;
+}
diff --git a/static/css/random.css b/static/css/random.css
new file mode 100644
index 0000000..662819b
--- /dev/null
+++ b/static/css/random.css
@@ -0,0 +1,81 @@
+/* Styles for Random Number Generator */
+.random-number-tool {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 60vh;
+ font-family: Arial, sans-serif;
+ color: white;
+}
+
+.random-number-container {
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(10px);
+ padding: 30px 50px;
+ border-radius: 15px;
+ box-shadow: 0px 8px 20px rgba(0, 0, 0, 0.3);
+ text-align: center;
+ width: 400px;
+}
+
+.random-number-container h1 {
+ font-size: 24px;
+ margin-bottom: 20px;
+ background: linear-gradient(to right, #2c0143 60%, #9304cc);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.random-number-container form input {
+ width: 100%;
+ padding: 10px;
+ border-radius: 5px;
+ border: none;
+ margin: 10px 0;
+ font-size: 16px;
+ box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2);
+}
+
+.random-number-container form button {
+ padding: 10px 20px;
+ border: none;
+ border-radius: 5px;
+ background-color: #7f0cea;
+ color: white;
+ font-weight: bold;
+ font-size: 16px;
+ cursor: pointer;
+ transition: 0.3s ease;
+}
+
+.random-number-container form button:hover {
+ background-color: #5d059b;
+ box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.2);
+}
+
+.result {
+ margin-top: 20px;
+ background: rgba(0, 0, 0, 0.1);
+ padding: 15px;
+ border-radius: 10px;
+}
+
+.result h2 {
+ font-size: 18px;
+ margin-bottom: 10px;
+ background: linear-gradient(to right, #7f0cea, #5d059b);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.result p {
+ font-size: 20px;
+ font-weight: bold;
+}
+
+.error {
+ margin-top: 20px;
+ color: red;
+ font-size: 16px;
+ font-weight: bold;
+}
diff --git a/static/css/session.css b/static/css/session.css
new file mode 100644
index 0000000..29a848f
--- /dev/null
+++ b/static/css/session.css
@@ -0,0 +1,44 @@
+.login-container, .register-container, .tools-container {
+ text-align: center;
+ max-width: 400px;
+ margin: 50px auto;
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(10px);
+ border-radius: 15px;
+ box-shadow: 0px 8px 20px rgba(0, 0, 0, 0.3);
+ color: white;
+}
+
+.login-container h1, .register-container h1, .tools-container h1 {
+ font-family: Atma;
+ font-size: 24px;
+ margin-bottom: 20px;
+ background: linear-gradient(to right, #9500ff, #540ba3);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.login-container form input, .register-container form input {
+ width: 90%;
+ padding: 10px;
+ margin: 10px 0;
+ border: none;
+ border-radius: 5px;
+ box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2);
+}
+
+.login-container form button, .register-container form button {
+ width: 90%;
+ padding: 10px;
+ background-color: #9500ff;
+ color: white;
+ border: none;
+ border-radius: 5px;
+ font-size: 16px;
+ cursor: pointer;
+}
+
+.login-container form button:hover, .register-container form button:hover {
+ background-color: #0056b3;
+}
diff --git a/static/css/snake.css b/static/css/snake.css
new file mode 100644
index 0000000..b490361
--- /dev/null
+++ b/static/css/snake.css
@@ -0,0 +1,53 @@
+
+.snake-page {
+ margin: 0;
+ padding: 0;
+ color: #ffffff;
+ font-family: "Arial", sans-serif;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 80vh;
+}
+
+/* Header */
+.snake-head {
+ margin-top: -10px;
+ font-size: 2rem;
+ color: #ffcc00;
+}
+
+/* Canvas styling */
+canvas {
+ border: 5px solid #ffcc00;
+ background-color: #2e2e3f;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
+ border-radius: 10px;
+ display: block;
+}
+
+/* Button styling */
+.snake-game {
+ margin-top: 20px;
+ padding: 10px 20px;
+ background-color: #ffcc00;
+ color: #1e1e2f;
+ border: none;
+ border-radius: 5px;
+ font-size: 1rem;
+ cursor: pointer;
+ transition: background-color 0.3s ease;
+}
+
+.snake-game:hover {
+ background-color: #e6b800;
+}
+
+/* Message for starting game */
+.start-message {
+ text-align: center;
+ font-size: 1.2rem;
+ color: #ffffff;
+ margin-top: 10px;
+}
diff --git a/static/css/speech.css b/static/css/speech.css
new file mode 100644
index 0000000..7f3510e
--- /dev/null
+++ b/static/css/speech.css
@@ -0,0 +1,80 @@
+
+.text-to-speech {
+ font-family: Arial, sans-serif;
+ color: white;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 90vh;
+ margin: 0;
+}
+
+/* Container for the form */
+.formtext-container {
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(10px);
+ padding: 30px 50px;
+ border-radius: 20px;
+ box-shadow: 0px 8px 20px rgba(0, 0, 0, 0.3);
+ text-align: center;
+ width: 350px;
+}
+
+/* textarea styling */
+.tts-textarea {
+ width: 100%;
+ height: 150px;
+ padding: 10px;
+ border: none;
+ border-radius: 5px;
+ font-size: 16px;
+ box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2);
+ background: rgba(255, 255, 255, 0.1);
+ margin-bottom: 20px;
+}
+
+/* Submit button styling */
+.tts-submit-btn {
+ padding: 12px 24px;
+ border: none;
+ border-radius: 5px;
+ background-color: #7f0cea;
+ color: white;
+ font-weight: bold;
+ font-size: 16px;
+ cursor: pointer;
+ transition: 0.3s ease;
+ margin-top: 10px;
+ width: 100%;
+}
+
+.tts-submit-btn:hover {
+ background-color: #5d059b;
+ box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.2);
+}
+
+/* Audio player and download button */
+.tts-audio-container {
+ margin-top: 20px;
+}
+
+.tts-audio-player {
+ margin-bottom: 15px;
+}
+
+.tts-download-btn {
+ padding: 10px 20px;
+ border: none;
+ border-radius: 5px;
+ background-color: #28a745;
+ color: white;
+ font-size: 16px;
+ font-weight: bold;
+ cursor: pointer;
+ transition: 0.3s ease;
+}
+
+.tts-download-btn:hover {
+ background-color: #218838;
+ box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2);
+}
diff --git a/static/css/styles.css b/static/css/styles.css
new file mode 100644
index 0000000..74ae0d1
--- /dev/null
+++ b/static/css/styles.css
@@ -0,0 +1,411 @@
+
+body {
+ background-image: url(/static/media/download.jpeg);
+ background-size: cover;
+ background-repeat: no-repeat;
+ background-color: #2a0e52;
+}
+
+body.main-page {
+ background-image: url(/static/media/download.jpeg);
+ background-size: contain;
+ background-repeat: no-repeat;
+ background-color: #2a0e52;
+}
+
+/* Specific styling for Games and Tools pages */
+body.games-page,
+body.tools-page {
+ background-image: none;
+ background-size: cover;
+ background-color: #2a0e52;
+}
+
+/* Navbar styling */
+nav {
+ display: flex;
+ align-items: center;
+ justify-content: space-between; /* Space out the items across the navbar */
+ padding: 10px 20px;
+ background: linear-gradient(90deg, #5b2a8f, #7d2e99);
+ background-color: #3d2a63;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.4);
+ border-radius: 10px;
+}
+
+/* Center buttons container */
+.center-buttons {
+ display: flex;
+ justify-content: center;
+ gap: 15px; /* Space between buttons */
+}
+
+/* Auth buttons container (right side) */
+.auth-buttons {
+ display: flex;
+ gap: 15px;
+}
+
+/* Styling for buttons */
+nav button {
+ padding: 10px 15px;
+ border: 2px solid rgba(255, 255, 255, 0.7);
+ border-radius: 8px;
+ color: white;
+ background: transparent;
+ font-size: 16px;
+ font-weight: bold;
+ cursor: pointer;
+ transition: 0.3s ease-in-out;
+ font-family: Most Heroes, Atma, Arial Rounded MT, Berlin Sans FB, Boogie Boys;
+}
+
+/* Hover effects for buttons */
+nav button:hover {
+ box-shadow: 0 0 15px 5px rgba(255, 255, 255, 0.7);
+ transform: scale(1.05); /* Slightly enlarge the button */
+ background-color: rgba(255, 255, 255, 0.1);
+}
+
+/* Logo styling */
+nav .logo {
+ height: 60px;
+ width: 60px;
+ border: 0;
+ border-radius: 50%;
+ transition: 0.3s ease-in-out; /* Smooth animation effect */
+}
+
+nav .logo:hover {
+ box-shadow: 0 0 15px 5px rgba(140, 0, 255, 0.7); /* Glow effect */
+ transform: scale(1.1); /* Slightly enlarges the logo */
+}
+
+
+/* Welcome message styling */
+.welcome-message {
+ font-size: 18px;
+ font-weight: bold;
+ color: #ffffff;
+ background: rgba(42, 19, 108, 0.3);
+ padding: 10px 20px;
+ border-radius: 10px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3); /* Slight shadow */
+ transition: background 0.3s ease-in-out; /* Smooth transition effect */
+ text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.5);
+ display: inline-block;
+ font-family: Most Heroes, Atma, Arial Rounded MT, Berlin Sans FB, Boogie Boys;
+ outline: 3px solid white;
+ margin: 10px;
+}
+
+.welcome-message:hover {
+ background: rgba(42, 19, 108, 0.5);
+ cursor: default;
+}
+
+
+.main-index {
+ display: flex;
+}
+
+.web-title {
+ font-size: 90px;
+ font-weight: 700;
+ font-family: Atma;
+ margin-left: 300px;
+ margin-top: 205px;
+ margin-right: auto;
+ background: linear-gradient(90deg, rgb(40,0,150), rgb(80,0,140), rgb(120,0,200)); /* Purple gradient */
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ text-shadow: -10px 10px 30px red;
+}
+.index {
+ font-size: 50px;
+ font-weight: 700;
+ font-family: Most Heroes, Atma, Arial Rounded MT, Berlin Sans FB, Boogie Boys;
+ margin-left: 50px;
+ margin-top: 150px;
+ background: linear-gradient(90deg, rgb(40,0,150), rgb(80,0,140), rgb(120,0,200)); /* Purple gradient */
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ text-shadow: -3px 7px 30px #000000;
+ border-left: 5px solid #5c1f7b;
+ border-radius: 5%;
+ padding: 35px;
+}
+
+.section-title {
+ font-family: 'Sunday Milk', sans-serif;
+ font-size: 36px;
+ color: white;
+ text-align: center;
+ margin-top: 50px;
+ text-shadow: 2px 2px 5px black;
+}
+
+.featured-section, .testimonials-section, .updates-section {
+ padding: 50px 20px;
+ background: rgba(42, 19, 108, 0.5);
+ border-radius: 15px;
+ margin: 20px auto;
+ max-width: 1200px;
+ border: 2px solid red;
+ box-shadow: 5px 5px 10px rgb(161, 79, 8);
+ font-family:'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
+ font-size: large;
+}
+
+.testimonials-section {
+ border: 2px solid red;
+ box-shadow: 5px 5px 10px rgb(161, 79, 8);
+ margin-bottom: 75px;
+}
+
+.about-section {
+ padding: 30px 20px;
+ background: rgba(42, 19, 108, 1);
+ border-radius: 15px;
+ margin: 150px auto 100px auto;
+ max-width: 500px;
+ border: 2px solid red;
+ box-shadow: 5px 5px 10px rgb(161, 79, 8);
+}
+
+.updates-section {
+ margin-bottom: 100px;
+}
+
+.about-section p {
+ color: white;
+ text-align: center;
+ font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
+}
+
+.testimonial {
+ background: rgba(255, 255, 255, 0.1);
+ padding: 20px;
+ border-radius: 8px;
+ margin: 10px 0;
+ text-align: center;
+ color: white;
+ text-shadow: 1px 1px 3px black;
+
+}
+
+.update {
+ background: rgba(0, 0, 0, 0.1);
+ padding: 20px;
+ border-radius: 8px;
+ margin: 10px 0;
+ color: white;
+ text-shadow: 1px 1px 3px black;
+}
+
+.update a {
+ color:aqua;
+}
+
+.cta-buttons {
+ display: flex;
+ justify-content: center;
+ gap: 75px;
+ margin: 40px 0;
+}
+
+.cta-button {
+ background: linear-gradient(90deg, #5b2a8f, #7d2e99);
+ color: white;
+ padding: 15px 30px;
+ border-radius: 8px;
+ text-decoration: none;
+ font-size: 18px;
+ font-weight: bold;
+ transition: background 0.3s;
+}
+
+.cta-button:hover {
+ background: linear-gradient(90deg, #7d2e99, #5b2a8f);
+}
+
+
+.tools_title {
+ font-family: Sunday milk, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
+ text-align: center;
+ padding-top: 50px;
+ font-size: 60px;
+ color: white;
+ text-shadow: 3px 3px 5px black;
+ letter-spacing: 5px
+}
+
+/* Card container */
+.cards-container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-wrap: wrap;
+ height: 60vh; /* Take up most of the vertical space */
+ margin-bottom: 100px;
+}
+
+/* Card styling */
+.card {
+ width: 200px;
+ height: 150px;
+ background-color: rgba(42, 19, 108, 0.15);
+ margin: 15px;
+ padding: 20px;
+ border-radius: 15px;
+ text-align: center;
+ box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.3);
+ border: 2px solid rgba(0, 0, 0, 0.3);
+ overflow: hidden; /* Ensure the background doesn't overflow the card */
+ position: relative;
+ transition: all 0.3s ease;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+/* Card content (blurry background effect) */
+.card::before {
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-image: url('/static/media/tools-io.webp');
+ background-size: cover;
+ background-position: center;
+ filter: blur(10px); /* Initial blur effect */
+ transition: filter 0.3s ease; /* Smooth transition for the blur effect */
+ z-index: -1; /* To place it behind the card content */
+}
+
+/* Hover effect for the card */
+.card:hover {
+ transform: translateY(-10px);
+ box-shadow: 0px 6px 15px rgba(0, 0, 0, 0.4);
+}
+
+/* Card hover background - reduce blur */
+.card:hover::before {
+ filter: blur(2px); /* Decrease blur when hovering */
+}
+
+/* Card title */
+.card h3 {
+ font-size: 25px;
+ font-weight: bold;
+ z-index: 1; /* Ensures text is above the blurred background */
+ font-family: Sunday Milk;
+ letter-spacing: 2px;
+ color: #ffffff;
+}
+
+/* Card link */
+.card a {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ display: block;
+ text-decoration: none;
+ background-color: rgba(128, 0, 128, 0.7);
+ color: white;
+ padding: 20px;
+ border-radius: 15px;
+ font-weight: bold;
+ transition: background-color 0.3s;
+ text-align: center;
+ z-index: 1; /* Ensures link is above the background */
+}
+
+/* Hover effect for links */
+.card a:hover {
+ background-color: rgba(102, 0, 102, 0.7);
+}
+
+/* Optional: Text for the card link (if you want specific text) */
+.card p {
+ z-index: 1;
+ font-size: 16px;
+ color: white;
+}
+
+.card img {
+ transition: opacity 0.2s ease; /* Smooth fade-out effect over 0.5 seconds */
+}
+
+.card:hover img {
+ opacity: 0;
+}
+
+
+
+/* Footer styling */
+footer {
+ background: linear-gradient(90deg, #5b2a8f, #7d2e99);
+ color: white;
+ padding: 30px 20px;
+ text-align: center;
+ box-shadow: 0 -4px 6px rgba(0, 0, 0, 0.3);
+ border-top: 2px solid rgba(255, 255, 255, 0.7);
+}
+
+.footer-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ max-width: 1200px;
+ margin: 0 auto;
+ padding-bottom: 20px;
+}
+
+.footer-section {
+ flex: 1;
+ padding: 10px 20px;
+ min-width: 250px;
+}
+
+.footer-section h3 {
+ font-family: 'Sunday Milk', sans-serif;
+ font-size: 24px;
+ margin-bottom: 10px;
+}
+
+.footer-section p {
+ font-size: 16px;
+ line-height: 1.6;
+}
+
+.footer-section ul {
+ list-style: none;
+ padding: 0;
+}
+
+.footer-section ul li {
+ margin: 10px 0;
+}
+
+.footer-section ul li a {
+ color: white;
+ text-decoration: none;
+ transition: color 0.3s;
+}
+
+.footer-section ul li a:hover {
+ color: #ddd;
+}
+
+.footer-bottom {
+ padding-top: 20px;
+ border-top: 1px solid rgba(255, 255, 255, 0.2);
+ font-size: 14px;
+ font-family: Atma, Arial Rounded MT, Berlin Sans FB, Boogie Boys;
+ letter-spacing: 5px;
+}
diff --git a/static/css/swg.css b/static/css/swg.css
new file mode 100644
index 0000000..21e4a44
--- /dev/null
+++ b/static/css/swg.css
@@ -0,0 +1,100 @@
+.swg {
+ font-family: 'Arial', sans-serif;
+ color: white;
+ margin: 0;
+ padding: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 70vh;
+}
+
+/* Container */
+.game-container {
+ margin-left: 10px;
+ margin-right: 10px;
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(10px);
+ padding: 40px 60px;
+ border-radius: 20px;
+ box-shadow: 0px 8px 20px rgba(0, 0, 0, 0.3);
+ text-align: center;
+ width: 450px;
+ max-width: 100%;
+}
+
+
+/* Title */
+.game-container h1 {
+ font-size: 28px;
+ margin-bottom: 20px;
+ background: linear-gradient(to right, #29026d, #b300ff);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+/* Buttons for choices */
+.choice-buttons {
+ display: flex;
+ justify-content: space-around;
+ margin-bottom: 30px;
+}
+
+.choice-buttons button {
+ padding: 15px 30px;
+ font-size: 18px;
+ background-color: #4c6ef5;
+ color: white;
+ border: none;
+ border-radius: 10px;
+ cursor: pointer;
+ transition: 0.3s ease;
+ width: 100px;
+}
+
+/* Hover effect for buttons */
+.choice-buttons button:hover {
+ background-color: #3a57f5;
+ box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2);
+}
+
+/* Result message styles */
+.result-section {
+ margin-top: 30px;
+ background: rgba(0, 0, 0, 0.1);
+ padding: 20px;
+ border-radius: 15px;
+}
+
+.result-section h2 {
+ font-size: 22px;
+ margin-bottom: 15px;
+ background: linear-gradient(to right, #3b0675, #8e0ae0);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.result-section p {
+ font-size: 20px;
+ font-weight: bold;
+}
+
+.win-message {
+ color: #28a745; /* Green for win */
+}
+
+.lose-message {
+ color: #dc3545; /* Red for lose */
+}
+
+.draw-message {
+ color: #ffc107; /* Yellow for draw */
+}
+
+/* Error message styling */
+.error-message {
+ margin-top: 20px;
+ color: red;
+ font-size: 16px;
+ font-weight: bold;
+}
diff --git a/static/css/tictactoe.css b/static/css/tictactoe.css
new file mode 100644
index 0000000..48bb8b3
--- /dev/null
+++ b/static/css/tictactoe.css
@@ -0,0 +1,87 @@
+.tictactoe {
+ font-family: Arial, sans-serif;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 80vh;
+ margin: 0;
+ color: rgb(255, 0, 0);
+}
+
+.tic-tac-toe-tool {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 80vh;
+}
+
+.tic-tac-toe-container {
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(10px);
+ padding: 30px 50px;
+ border-radius: 15px;
+ box-shadow: 0px 8px 20px rgba(0, 0, 0, 0.3);
+ text-align: center;
+ width: 400px;
+}
+
+.tic-tac-toe-container h1 {
+ font-size: 28px;
+ font-weight: 800;
+ margin-bottom: 20px;
+ background: linear-gradient(to right, #b300ff, #4a0478);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.board {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 5px;
+ margin: 20px 0;
+}
+
+.cell {
+ width: 100px;
+ height: 100px;
+ background-color: rgba(255, 255, 255, 0.2);
+ border-radius: 5px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-size: 24px;
+ font-weight: bold;
+ cursor: pointer;
+ transition: transform 0.2s ease;
+}
+
+.cell:hover {
+ transform: scale(1.05);
+ background-color: rgba(255, 255, 255, 0.3);
+}
+
+.game-status {
+ font-size: 18px;
+ margin-bottom: 20px;
+}
+
+.restart-button {
+ padding: 10px 20px;
+ border: none;
+ border-radius: 5px;
+ background-color: #7d00d0;
+ color: white;
+ font-size: 16px;
+ cursor: pointer;
+ transition: 0.3s ease;
+}
+
+.restart-button:hover {
+ background-color: #4c007f;
+ box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.2);
+}
+
+.winner-message {
+ color: green;
+ font-weight: bold;
+}
diff --git a/static/css/word.css b/static/css/word.css
new file mode 100644
index 0000000..48c966a
--- /dev/null
+++ b/static/css/word.css
@@ -0,0 +1,70 @@
+
+.word-counter {
+ font-family: Arial, sans-serif;
+ color: white;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 70vh;
+ margin: 30px;
+}
+
+/* Container */
+.form-container {
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(10px);
+ padding: 20px 80px;
+ border-radius: 15px;
+ box-shadow: 0px 8px 20px rgba(0, 0, 0, 0.3);
+ text-align: center;
+ width: 300px;
+}
+
+/* Form elements */
+label {
+ font-size: 16px;
+ margin-bottom: 10px;
+ display: block;
+ text-align: center;
+}
+
+textarea {
+ margin: 10px 0;
+ padding: 10px;
+ border: none;
+ border-radius: 5px;
+ width: 100%;
+ font-size: 14px;
+ box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2);
+ resize: none; /* Prevent resizing the textarea */
+}
+
+/* Button styling */
+button {
+ padding: 10px 20px;
+ border: none;
+ border-radius: 5px;
+ background-color: #7f0cea;
+ color: white;
+ font-weight: bold;
+ font-size: 16px;
+ cursor: pointer;
+ transition: 0.3s ease;
+ margin-top: 10px;
+}
+
+button:hover {
+ background-color: #5d059b;
+ box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.2);
+}
+
+/* results display */
+.counter-output {
+ margin-top: 15px;
+ font-size: 18px;
+ font-weight: bold;
+ background: rgba(255, 255, 255, 0.1);
+ padding: 10px;
+ border-radius: 10px;
+ box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2);
+}
diff --git a/static/js/contact.js b/static/js/contact.js
new file mode 100644
index 0000000..f7d013c
--- /dev/null
+++ b/static/js/contact.js
@@ -0,0 +1,34 @@
+document.addEventListener("DOMContentLoaded", () => {
+ // Handle form submission
+ const contactForm = document.getElementById("contactForm");
+ if (contactForm) {
+ contactForm.addEventListener("submit", function (e) {
+ e.preventDefault(); // Prevents default form submission behavior
+
+ // Create and display the popup message
+ const popup = document.createElement("div");
+ popup.innerHTML = "Thank you for contacting us! We will get back to you shortly.";
+ popup.style.position = "fixed";
+ popup.style.top = "50%";
+ popup.style.left = "50%";
+ popup.style.transform = "translate(-50%, -50%)";
+ popup.style.backgroundColor = "#ffffff";
+ popup.style.color = "red";
+ popup.style.padding = "20px";
+ popup.style.borderRadius = "8px";
+ popup.style.boxShadow = "0 4px 8px rgba(0, 0, 0, 0.2)";
+ popup.style.fontSize = "18px";
+ popup.style.textAlign = "center";
+ popup.style.zIndex = "1000";
+ popup.style.border = "2px solid white";
+
+ document.body.appendChild(popup);
+
+ // Automatically remove the popup after 3 seconds and redirect to homepage
+ setTimeout(() => {
+ popup.remove();
+ window.location.href = "/";
+ }, 2500);
+ });
+ }
+});
diff --git a/static/js/guess.js b/static/js/guess.js
new file mode 100644
index 0000000..69b35ef
--- /dev/null
+++ b/static/js/guess.js
@@ -0,0 +1,43 @@
+document.addEventListener("DOMContentLoaded", () => {
+ const submitButton = document.getElementById("submitGuess");
+ const guessInput = document.getElementById("guessInput");
+ const feedback = document.getElementById("feedback");
+
+ submitButton.addEventListener("click", () => {
+ const guess = parseInt(guessInput.value);
+
+ if (isNaN(guess) || guess < 1 || guess > 100) {
+ feedback.textContent = "Please enter a number between 1 and 100.";
+ feedback.style.color = "red";
+ return;
+ }
+
+ // Send the guess to the Flask server using a POST request
+ fetch('/guess.html', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ guess: guess }),
+ })
+ .then(response => response.json())
+ .then(data => {
+ // Display feedback based on server response
+ if (data.result === 'low') {
+ feedback.textContent = "Too low! Try again.";
+ feedback.style.color = "yellow";
+ } else if (data.result === 'high') {
+ feedback.textContent = "Too high! Try again.";
+ feedback.style.color = "orange";
+ } else if (data.result === 'correct') {
+ feedback.textContent = `Congratulations! You guessed the number!`;
+ feedback.style.color = "lime";
+ }
+ })
+ .catch(error => {
+ console.error('Error:', error);
+ feedback.textContent = "Something went wrong. Please try again.";
+ feedback.style.color = "red";
+ });
+ });
+});
diff --git a/static/js/memory-game.js b/static/js/memory-game.js
new file mode 100644
index 0000000..247241f
--- /dev/null
+++ b/static/js/memory-game.js
@@ -0,0 +1,45 @@
+
+const cards = document.querySelectorAll('.memory-card');
+let flippedCards = [];
+let matchedCards = [];
+let moves = 0;
+
+// Shuffle the cards
+const shuffle = () => {
+ cards.forEach(card => {
+ const randomIndex = Math.floor(Math.random() * cards.length);
+ card.style.order = randomIndex;
+ });
+};
+
+shuffle();
+
+// Add event listeners to each card
+cards.forEach(card => {
+ card.addEventListener('click', function() {
+ if (flippedCards.length < 2 && !card.classList.contains('flipped') && !matchedCards.includes(card)) {
+ card.classList.add('flipped');
+ const img = card.querySelector('img');
+ img.style.opacity = 1; // Show the image when flipped
+ flippedCards.push(card);
+ if (flippedCards.length === 2) {
+ moves++;
+ if (flippedCards[0].dataset.id === flippedCards[1].dataset.id) {
+ matchedCards.push(flippedCards[0], flippedCards[1]);
+ flippedCards = [];
+ if (matchedCards.length === cards.length) {
+ document.getElementById('message').textContent = `Congratulations! You won in ${moves} moves.`;
+ }
+ } else {
+ setTimeout(() => {
+ flippedCards[0].querySelector('img').style.opacity = 0;
+ flippedCards[1].querySelector('img').style.opacity = 0;
+ flippedCards[0].classList.remove('flipped');
+ flippedCards[1].classList.remove('flipped');
+ flippedCards = [];
+ }, 1000);
+ }
+ }
+ }
+ });
+});
diff --git a/static/js/snake.js b/static/js/snake.js
new file mode 100644
index 0000000..68c0c20
--- /dev/null
+++ b/static/js/snake.js
@@ -0,0 +1,78 @@
+
+const canvas = document.getElementById("gameCanvas");
+const ctx = canvas.getContext("2d");
+
+const box = 20; // Size of the grid box
+let snake = [{ x: 9 * box, y: 10 * box }];
+let food = {
+ x: Math.floor(Math.random() * 19 + 1) * box,
+ y: Math.floor(Math.random() * 19 + 1) * box,
+};
+let direction = null; // Start with no direction
+let score = 0;
+
+// Control the snake
+document.addEventListener("keydown", (event) => {
+ if (event.key === "ArrowLeft" && direction !== "RIGHT") direction = "LEFT";
+ else if (event.key === "ArrowUp" && direction !== "DOWN") direction = "UP";
+ else if (event.key === "ArrowRight" && direction !== "LEFT") direction = "RIGHT";
+ else if (event.key === "ArrowDown" && direction !== "UP") direction = "DOWN";
+});
+
+// Draw function
+function draw() {
+ // Clear the canvas
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+ // Draw the snake
+ snake.forEach((segment, index) => {
+ ctx.fillStyle = index === 0 ? "green" : "lightgreen";
+ ctx.fillRect(segment.x, segment.y, box, box);
+ ctx.strokeRect(segment.x, segment.y, box, box);
+ });
+
+ // Draw the food
+ ctx.fillStyle = "red";
+ ctx.fillRect(food.x, food.y, box, box);
+
+ // Check if direction is null (game hasn't started)
+ if (!direction) {
+ ctx.fillStyle = "black";
+ ctx.font = "20px Arial";
+ ctx.fillText("Press an arrow key to start!", 50, canvas.height / 2);
+ return; // Skip updating the snake
+ }
+
+ // Move the snake
+ let head = { ...snake[0] };
+ if (direction === "LEFT") head.x -= box;
+ if (direction === "UP") head.y -= box;
+ if (direction === "RIGHT") head.x += box;
+ if (direction === "DOWN") head.y += box;
+
+ // Check for collisions
+ if (
+ head.x < 0 || head.y < 0 ||
+ head.x >= canvas.width || head.y >= canvas.height ||
+ snake.some((segment) => segment.x === head.x && segment.y === head.y)
+ ) {
+ clearInterval(game);
+ alert("Game Over! Your score: " + score);
+ }
+
+ // Check for food
+ if (head.x === food.x && head.y === food.y) {
+ score++;
+ food = {
+ x: Math.floor(Math.random() * 19 + 1) * box,
+ y: Math.floor(Math.random() * 19 + 1) * box,
+ };
+ } else {
+ snake.pop(); // Remove the tail
+ }
+
+ snake.unshift(head); // Add new head
+}
+
+// Update the game every 100ms
+const game = setInterval(draw, 100);
diff --git a/static/js/tictactoe.js b/static/js/tictactoe.js
new file mode 100644
index 0000000..8937c97
--- /dev/null
+++ b/static/js/tictactoe.js
@@ -0,0 +1,70 @@
+const board = document.getElementById("board");
+const gameStatus = document.getElementById("game-status");
+const restartButton = document.getElementById("restart-button");
+
+let currentPlayer = "X";
+let gameBoard = ["", "", "", "", "", "", "", "", ""];
+let gameActive = true;
+
+const winningConditions = [
+ [0, 1, 2], [3, 4, 5], [6, 7, 8], // Rows
+ [0, 3, 6], [1, 4, 7], [2, 5, 8], // Columns
+ [0, 4, 8], [2, 4, 6] // Diagonals
+];
+
+// To Create the board dynamically
+function createBoard() {
+ board.innerHTML = "";
+ gameBoard.forEach((cell, index) => {
+ const cellElement = document.createElement("div");
+ cellElement.classList.add("cell");
+ cellElement.dataset.index = index;
+ cellElement.addEventListener("click", handleCellClick);
+ board.appendChild(cellElement);
+ });
+}
+
+// Check for a winner or tie
+function checkWinner() {
+ for (let condition of winningConditions) {
+ const [a, b, c] = condition;
+ if (gameBoard[a] && gameBoard[a] === gameBoard[b] && gameBoard[a] === gameBoard[c]) {
+ gameActive = false;
+ gameStatus.textContent = `Player ${gameBoard[a]} wins!`;
+ gameStatus.classList.add("winner-message");
+ return true;
+ }
+ }
+ if (!gameBoard.includes("")) {
+ gameActive = false;
+ gameStatus.textContent = "It's a tie!";
+ gameStatus.classList.remove("winner-message");
+ return true;
+ }
+ gameStatus.classList.remove("winner-message"); // Ensure no green color during regular turns
+ return false;
+}
+
+// Handle cell clicks
+function handleCellClick(event) {
+ const index = event.target.dataset.index;
+ if (gameBoard[index] || !gameActive) return;
+
+ gameBoard[index] = currentPlayer;
+ event.target.textContent = currentPlayer;
+
+ if (!checkWinner()) {
+ currentPlayer = currentPlayer === "X" ? "O" : "X";
+ gameStatus.textContent = `Player ${currentPlayer}'s turn`;
+ }
+}
+
+restartButton.addEventListener("click", () => {
+ gameBoard = ["", "", "", "", "", "", "", "", ""];
+ currentPlayer = "X";
+ gameActive = true;
+ gameStatus.textContent = "Player X's turn";
+ createBoard();
+});
+
+createBoard();
diff --git a/static/media/10 Mesmerizing Gradient Blue iPad Wallpapers for Stylish Screens.jpeg b/static/media/10 Mesmerizing Gradient Blue iPad Wallpapers for Stylish Screens.jpeg
new file mode 100644
index 0000000..ead9db0
Binary files /dev/null and b/static/media/10 Mesmerizing Gradient Blue iPad Wallpapers for Stylish Screens.jpeg differ
diff --git a/static/media/Nightskylandscape.jpeg b/static/media/Nightskylandscape.jpeg
new file mode 100644
index 0000000..97aef24
Binary files /dev/null and b/static/media/Nightskylandscape.jpeg differ
diff --git a/static/media/TicTacToe-game-logo.png b/static/media/TicTacToe-game-logo.png
new file mode 100644
index 0000000..cf9cebb
Binary files /dev/null and b/static/media/TicTacToe-game-logo.png differ
diff --git a/static/media/bgrem.webp b/static/media/bgrem.webp
new file mode 100644
index 0000000..9f67e2e
Binary files /dev/null and b/static/media/bgrem.webp differ
diff --git a/static/media/blue gradient.jpg b/static/media/blue gradient.jpg
new file mode 100644
index 0000000..48a3631
Binary files /dev/null and b/static/media/blue gradient.jpg differ
diff --git a/static/media/boy_sunset_.png b/static/media/boy_sunset_.png
new file mode 100644
index 0000000..438871d
Binary files /dev/null and b/static/media/boy_sunset_.png differ
diff --git a/static/media/compress.png b/static/media/compress.png
new file mode 100644
index 0000000..61845d1
Binary files /dev/null and b/static/media/compress.png differ
diff --git a/static/media/download.jpeg b/static/media/download.jpeg
new file mode 100644
index 0000000..0f0b065
Binary files /dev/null and b/static/media/download.jpeg differ
diff --git a/static/media/download1.jpeg b/static/media/download1.jpeg
new file mode 100644
index 0000000..9f625cc
Binary files /dev/null and b/static/media/download1.jpeg differ
diff --git a/static/media/games-page.png b/static/media/games-page.png
new file mode 100644
index 0000000..6f04bf5
Binary files /dev/null and b/static/media/games-page.png differ
diff --git a/static/media/home-page.png b/static/media/home-page.png
new file mode 100644
index 0000000..5dfe28c
Binary files /dev/null and b/static/media/home-page.png differ
diff --git a/static/media/image1.jpeg b/static/media/image1.jpeg
new file mode 100644
index 0000000..f0f7d48
Binary files /dev/null and b/static/media/image1.jpeg differ
diff --git a/static/media/image2.jpeg b/static/media/image2.jpeg
new file mode 100644
index 0000000..f9900f1
Binary files /dev/null and b/static/media/image2.jpeg differ
diff --git a/static/media/image3.jpeg b/static/media/image3.jpeg
new file mode 100644
index 0000000..1d45b5a
Binary files /dev/null and b/static/media/image3.jpeg differ
diff --git a/static/media/image4.jpeg b/static/media/image4.jpeg
new file mode 100644
index 0000000..32ad82b
Binary files /dev/null and b/static/media/image4.jpeg differ
diff --git a/static/media/image5.jpeg b/static/media/image5.jpeg
new file mode 100644
index 0000000..9842b56
Binary files /dev/null and b/static/media/image5.jpeg differ
diff --git a/static/media/image6.jpeg b/static/media/image6.jpeg
new file mode 100644
index 0000000..5faa0b1
Binary files /dev/null and b/static/media/image6.jpeg differ
diff --git a/static/media/image7.jpeg b/static/media/image7.jpeg
new file mode 100644
index 0000000..f5e9bcb
Binary files /dev/null and b/static/media/image7.jpeg differ
diff --git a/static/media/image8.jpeg b/static/media/image8.jpeg
new file mode 100644
index 0000000..375454f
Binary files /dev/null and b/static/media/image8.jpeg differ
diff --git a/static/media/ip.webp b/static/media/ip.webp
new file mode 100644
index 0000000..2b9dce4
Binary files /dev/null and b/static/media/ip.webp differ
diff --git a/static/media/login-page.png b/static/media/login-page.png
new file mode 100644
index 0000000..0e19eb4
Binary files /dev/null and b/static/media/login-page.png differ
diff --git a/static/media/mem-game.jpeg b/static/media/mem-game.jpeg
new file mode 100644
index 0000000..e554d4f
Binary files /dev/null and b/static/media/mem-game.jpeg differ
diff --git a/static/media/num_guess.png b/static/media/num_guess.png
new file mode 100644
index 0000000..1d75f0d
Binary files /dev/null and b/static/media/num_guess.png differ
diff --git a/static/media/password.png b/static/media/password.png
new file mode 100644
index 0000000..b9ca02a
Binary files /dev/null and b/static/media/password.png differ
diff --git a/static/media/qr.png b/static/media/qr.png
new file mode 100644
index 0000000..b430930
Binary files /dev/null and b/static/media/qr.png differ
diff --git a/static/media/random-transformed.png b/static/media/random-transformed.png
new file mode 100644
index 0000000..ff063d0
Binary files /dev/null and b/static/media/random-transformed.png differ
diff --git a/static/media/scroll.png b/static/media/scroll.png
new file mode 100644
index 0000000..dd93edf
Binary files /dev/null and b/static/media/scroll.png differ
diff --git a/static/media/snake.png b/static/media/snake.png
new file mode 100644
index 0000000..1f9bcd3
Binary files /dev/null and b/static/media/snake.png differ
diff --git a/static/media/swg.png b/static/media/swg.png
new file mode 100644
index 0000000..a6c83d5
Binary files /dev/null and b/static/media/swg.png differ
diff --git a/static/media/tools-io.webp b/static/media/tools-io.webp
new file mode 100644
index 0000000..aa5da2d
Binary files /dev/null and b/static/media/tools-io.webp differ
diff --git a/static/media/tools-page.png b/static/media/tools-page.png
new file mode 100644
index 0000000..668794e
Binary files /dev/null and b/static/media/tools-page.png differ
diff --git a/static/media/tts.png b/static/media/tts.png
new file mode 100644
index 0000000..b372d3d
Binary files /dev/null and b/static/media/tts.png differ
diff --git a/static/media/word-counter-thumbnail.png b/static/media/word-counter-thumbnail.png
new file mode 100644
index 0000000..4a07b0f
Binary files /dev/null and b/static/media/word-counter-thumbnail.png differ
diff --git a/templates/bg_remove.html b/templates/bg_remove.html
new file mode 100644
index 0000000..d305768
--- /dev/null
+++ b/templates/bg_remove.html
@@ -0,0 +1,25 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
+
+{% endblock %}
diff --git a/templates/compress.html b/templates/compress.html
new file mode 100644
index 0000000..92e6dd4
--- /dev/null
+++ b/templates/compress.html
@@ -0,0 +1,22 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/contact.html b/templates/contact.html
new file mode 100644
index 0000000..14d3eb2
--- /dev/null
+++ b/templates/contact.html
@@ -0,0 +1,28 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
+Feel free to reach out by filling out the form below.
+
+
+
+
+
+{% endblock %}
diff --git a/templates/games.html b/templates/games.html
new file mode 100644
index 0000000..eb565b4
--- /dev/null
+++ b/templates/games.html
@@ -0,0 +1,52 @@
+{% extends "layout.html" %}
+
+{% block body_class %}
+games-page
+{% endblock %}
+
+{% block content %}
+
+
+
+
+{% endblock %}
+
+
\ No newline at end of file
diff --git a/templates/guess.html b/templates/guess.html
new file mode 100644
index 0000000..707837e
--- /dev/null
+++ b/templates/guess.html
@@ -0,0 +1,17 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+ Guess the Number Game
+
+ I'm thinking of a number between 1 and 100. Can you guess it?
+
+
+
+{% endblock %}
diff --git a/templates/index.html b/templates/index.html
new file mode 100644
index 0000000..e83593f
--- /dev/null
+++ b/templates/index.html
@@ -0,0 +1,90 @@
+{% extends "layout.html" %}
+
+{% block body_class %}
+main-page
+{% endblock %}
+
+{% block content %}
+
+
+
tools.io
+
+ Unleash Your Creativity:
+ Explore a World of Games and Tools to Ignite Your Imagination!
+
+
+
+
+
+
+
+
+
+
+
+
About Us
+
Welcome to Tools.io, your one-stop destination for innovative tools and entertaining games designed to simplify tasks and add a touch of fun to your day! Our mission is to empower individuals and businesses with versatile, user-friendly solutions that blend functionality with creativity. From productivity boosters to creative utilities, and even engaging games to relax and recharge, Tools.io offers something for everyone. We believe in the power of simplicity, efficiency, and enjoyment, ensuring our tools and games are intuitive, effective, and delightful to use. Join us on this exciting journey as we continue to expand our collection and bring new, impactful features to your fingertips. Let’s simplify tasks, spark creativity, and have fun—together!
+
+
+
+
What Our Users Say
+
+
"Tools.io has become my go-to site for productivity tools and fun games. Highly recommended!"
+
- ABC
+
+
+
"The variety and quality of tools available here are simply amazing!"
+
- XYZ
+
+
+
+
+
Latest Updates
+
+
New Game: Memory Match
+
We just launched a new game - Memory Match! Check it out now and challenge your friends.
+
Play Memory Match
+
+
+
New Tool: Word Counter
+
We just launched a new tool - Word Counter! Check it out now and improve your productivity.
+
Try Word Counter
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/templates/ip_finder.html b/templates/ip_finder.html
new file mode 100644
index 0000000..d0f7c60
--- /dev/null
+++ b/templates/ip_finder.html
@@ -0,0 +1,37 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
+
+
IP Finder
+
+
+ Know Your IP
+
+
+
+
+
+ Find Location
+
+
+ {% if show_ip %}
+
Your IP: {{ ip }}
+ {% endif %}
+
+ {% if location %}
+
+
Location Details:
+
IP: {{ location['IP'] }}
+
City: {{ location['City'] }}
+
Region: {{ location['Region'] }}
+
Country: {{ location['Country'] }}
+
Lat & Long: {{ location['Latitude and Longitude'] }}
+
Organization: {{ location['Organization'] }}
+
+ {% endif %}
+
+
+
+{% endblock %}
diff --git a/templates/layout.html b/templates/layout.html
new file mode 100644
index 0000000..8ffc7e6
--- /dev/null
+++ b/templates/layout.html
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+ tools.io
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Home
+
+
+ Tools
+
+
+ Games
+
+
+ Contact
+
+
+
+
+ {% if session.get('username') %}
+
+ Log out
+
+ Welcome, {{ session.get('username') }}!
+ {% else %}
+
+ Log in
+
+
+ Sign up
+
+ {% endif %}
+
+
+
+ {% block content %}
+ {% endblock %}
+
+
+
+
+
+
+
+
+
+
diff --git a/templates/login.html b/templates/login.html
new file mode 100644
index 0000000..e879a92
--- /dev/null
+++ b/templates/login.html
@@ -0,0 +1,17 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+{% endblock %}
diff --git a/templates/match.html b/templates/match.html
new file mode 100644
index 0000000..36b721d
--- /dev/null
+++ b/templates/match.html
@@ -0,0 +1,68 @@
+{% extends 'layout.html' %}
+
+{% block content %}
+
+
+
Memory Match Game
+
Click on the cards to match pairs!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Restart
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/password_generator.html b/templates/password_generator.html
new file mode 100644
index 0000000..509c40c
--- /dev/null
+++ b/templates/password_generator.html
@@ -0,0 +1,24 @@
+{% extends "layout.html" %}
+{% block content %}
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/qr_generator.html b/templates/qr_generator.html
new file mode 100644
index 0000000..96aa895
--- /dev/null
+++ b/templates/qr_generator.html
@@ -0,0 +1,11 @@
+{% extends "layout.html" %}
+{% block content %}
+
+
QR Code Generator
+
+ Enter Text or URL:
+
+ Generate QR Code
+
+
+{% endblock %}
diff --git a/templates/random_number.html b/templates/random_number.html
new file mode 100644
index 0000000..f95ee22
--- /dev/null
+++ b/templates/random_number.html
@@ -0,0 +1,26 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
+
+{% endblock %}
diff --git a/templates/signup.html b/templates/signup.html
new file mode 100644
index 0000000..1cab892
--- /dev/null
+++ b/templates/signup.html
@@ -0,0 +1,36 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
+
Sign up
+
+
+ {% if success %}
+
{{ success }}
+
Redirecting to login page in 3 seconds...
+
+ {% elif error %}
+
{{ error }}
+ {% endif %}
+
+
+
+ Username:
+
+
+ Email:
+
+
+ Create a password:
+
+
+ Sign up
+
+
+
+{% endblock %}
diff --git a/templates/snake.html b/templates/snake.html
new file mode 100644
index 0000000..3c10b16
--- /dev/null
+++ b/templates/snake.html
@@ -0,0 +1,12 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
+
Snake Game
+
+
Press an arrow key to start!
+
Restart
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/snake_water_gun.html b/templates/snake_water_gun.html
new file mode 100644
index 0000000..59f20b3
--- /dev/null
+++ b/templates/snake_water_gun.html
@@ -0,0 +1,45 @@
+{% extends "layout.html" %}
+
+{% block body_class %}
+swg-page
+{% endblock %}
+
+{% block content %}
+
+
+
+
Snake Water Gun Game
+
Select your choice:
+
+
+
+ Snake
+ Water
+ Gun
+
+
+
+ {% if result %}
+
+
Result:
+ {% if result == 'Draw!' %}
+ {{ result }}
+ {% elif result == 'You won!' %}
+ {{ result }}
+ {% else %}
+ {{ result }}
+ {% endif %}
+
+
Your choice: {{ user_choice }}
+
Computer's choice: {{ computer_choice }}
+
+ {% endif %}
+
+ {% if error %}
+
+ {% endif %}
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/text_to_speech.html b/templates/text_to_speech.html
new file mode 100644
index 0000000..e5e42e6
--- /dev/null
+++ b/templates/text_to_speech.html
@@ -0,0 +1,26 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
+
Text to Speech
+
+
+ Convert to Speech
+
+
+ {% if audio_url %}
+
+
Your Speech:
+
+
+ Your browser does not support the audio element.
+
+
+ Download MP3
+
+
+ {% endif %}
+
+
+{% endblock %}
diff --git a/templates/tictactoe.html b/templates/tictactoe.html
new file mode 100644
index 0000000..4ed27ea
--- /dev/null
+++ b/templates/tictactoe.html
@@ -0,0 +1,16 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/tools.html b/templates/tools.html
new file mode 100644
index 0000000..b5b496a
--- /dev/null
+++ b/templates/tools.html
@@ -0,0 +1,71 @@
+{% extends "layout.html" %}
+
+{% block body_class %}
+tools-page
+{% endblock %}
+
+{% block content %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/word_counter.html b/templates/word_counter.html
new file mode 100644
index 0000000..c9e91aa
--- /dev/null
+++ b/templates/word_counter.html
@@ -0,0 +1,24 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
+
+{% endblock %}