diff --git a/README.md b/README.md
index f8b15f4cb..d0131e3e9 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,20 @@
# Weather App
-Replace this readme with your own information about your project.
-
-Start by briefly describing the assignment in a sentence or two. Keep it short and to the point.
+This project is a weather application that fetches and displays real-time weather data from the OpenWeatherMap API. Users can search for the current weather in a specific city or allow the app to use their location via the Geolocation API. The app shows key information such as temperature, weather description, sunrise and sunset times, and a 5-day weather forecast.
## The problem
-Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next?
+The task was to create a responsive weather app that retrieves data from an external API and presents it in a user-friendly format. The goal was also to implement a feature that fetches the user's current location and displays the weather based on that.
+
+- Technologies: I used the following tools and technologies to build the app:
+
+HTML and CSS for structuring and styling the interface.
+JavaScript for fetching data using the fetch() API and manipulating the DOM to display the weather information.
+OpenWeatherMap API to retrieve the weather data for the specified city or current location.
+Responsive Design techniques to ensure the app works across various screen sizes.
+
+- Challenges: The main challenge was ensuring the weather data (including background images) loaded efficiently, and formatting the dates (e.g., sunrise and sunset) into a user-friendly format.
## View it live
-Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about.
+https://weather-free-api.netlify.app/
diff --git a/assets/design-2/noun_Cloud_1188486.svg b/assets/design-2/noun_Cloud_1188486.svg
deleted file mode 100644
index c2375e901..000000000
--- a/assets/design-2/noun_Cloud_1188486.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/assets/design-2/noun_Sunglasses_2055147.svg b/assets/design-2/noun_Sunglasses_2055147.svg
deleted file mode 100644
index a1fcd7e8b..000000000
--- a/assets/design-2/noun_Sunglasses_2055147.svg
+++ /dev/null
@@ -1,23 +0,0 @@
-
diff --git a/assets/design-2/noun_Umbrella_2030530.svg b/assets/design-2/noun_Umbrella_2030530.svg
deleted file mode 100644
index 8a414b15f..000000000
--- a/assets/design-2/noun_Umbrella_2030530.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-
diff --git a/images/cloudy.png b/images/cloudy.png
new file mode 100644
index 000000000..a5ac4a45d
Binary files /dev/null and b/images/cloudy.png differ
diff --git a/images/default.png b/images/default.png
new file mode 100644
index 000000000..fc76fee96
Binary files /dev/null and b/images/default.png differ
diff --git a/images/dust.png b/images/dust.png
new file mode 100644
index 000000000..ca93c3849
Binary files /dev/null and b/images/dust.png differ
diff --git a/images/mist.png b/images/mist.png
new file mode 100644
index 000000000..36d5373fb
Binary files /dev/null and b/images/mist.png differ
diff --git a/images/rain.png b/images/rain.png
new file mode 100644
index 000000000..cf926fb8b
Binary files /dev/null and b/images/rain.png differ
diff --git a/images/snowy.png b/images/snowy.png
new file mode 100644
index 000000000..459f5ccef
Binary files /dev/null and b/images/snowy.png differ
diff --git a/images/sunny.png b/images/sunny.png
new file mode 100644
index 000000000..505c01fcc
Binary files /dev/null and b/images/sunny.png differ
diff --git a/images/thunderstorm.png b/images/thunderstorm.png
new file mode 100644
index 000000000..3bc9c5106
Binary files /dev/null and b/images/thunderstorm.png differ
diff --git a/index.html b/index.html
new file mode 100644
index 000000000..d2edab7ee
--- /dev/null
+++ b/index.html
@@ -0,0 +1,86 @@
+
+
+
+
+
+ Weather App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Fetching weather data...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pull_request_template.md b/pull_request_template.md
deleted file mode 100644
index 70fa177f7..000000000
--- a/pull_request_template.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## Netlify link
-Add your Netlify link here.
-PS. Don't forget to add it in your readme as well.
diff --git a/script.js b/script.js
new file mode 100644
index 000000000..1bae0a07a
--- /dev/null
+++ b/script.js
@@ -0,0 +1,304 @@
+// Function to preload weather images into the browser's cache
+// This helps in displaying images quickly.
+const preloadImages = () => {
+ const imagePaths = [
+ "./images/thunderstorm.png",
+ "./images/rain.png",
+ "./images/snowy.png",
+ "./images/mist.png",
+ "./images/dust.png",
+ "./images/cloudy.png",
+ "./images/sunny.png",
+ "./images/default.png",
+ ];
+
+ // Loop through each image path and load it into the browser's memory
+ imagePaths.forEach((path) => {
+ const img = new Image();
+ img.src = path;
+ });
+};
+
+// Show a loading message while data is being fetched
+const showLoading = () => {
+ document.getElementById("loadingMessage").style.display = "flex"; // Show the loading message
+ document.getElementById("appContent").style.display = "none"; // Hide the main content
+};
+// Hide the loading message when data is fetched
+const hideLoading = () => {
+ document.getElementById("loadingMessage").style.display = "none"; // Hide the loading message
+ document.getElementById("appContent").style.display = "block"; // Show the main content
+};
+
+// Show a loading message specifically for location permission (geolocation)
+const showLocationLoading = () => {
+ document.getElementById("loadingMessage").style.display = "flex"; // Show loading message for location
+ document.getElementById("appContent").style.display = "none"; // Hide the main content
+};
+// Hide the loading message after location is fetched
+const hideLocationLoading = () => {
+ document.getElementById("loadingMessage").style.display = "none"; // Hide loading message
+ document.getElementById("appContent").style.display = "block"; // Show main content
+};
+
+// Call the preloadImages function to start preloading images
+preloadImages();
+
+// Select DOM elements
+const tempToday = document.getElementById("tempToday");
+const cityName = document.getElementById("cityName");
+const localTime = document.getElementById("localTime");
+const weatherDescription = document.getElementById("weatherDescription");
+const sunriseText = document.getElementById("sunriseText");
+const sunsetText = document.getElementById("sunsetText");
+const inputField = document.getElementById("inputField");
+const searchBtn = document.getElementById("searchBtn");
+const forecastContainer = document.getElementById("weatherForecast");
+const mainWrapper = document.querySelector(".mainWrapper");
+
+// Centralized error handling function to show a single error message and reload the page
+const handleError = (message) => {
+ alert(message); // Display a simple alert message
+ window.location.reload(); // Refresh the page after the alert
+};
+
+// Function to fetch current weather data from the OpenWeatherMap API
+// The 'city' parameter is the name of the city entered by the user
+const fetchWeatherData = async (city) => {
+ try {
+ const API_KEY = "0c5116ff347d8ce8d78e8d3c18029dd7"; // My OpenWeatherMap API key
+ const API_URL = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&APPID=${API_KEY}`;
+ const response = await fetch(API_URL); // API request to get the weather data
+
+ if (!response.ok) {
+ throw new Error(`City "${city}" not found.`); // If the city is not found, throw an error
+ }
+
+ const data = await response.json(); // Convert the response to JSON format
+ displayWeatherData(data); // Display the fetched weather data
+ return true; // Return true to indicate that the fetch was successful
+ } catch (error) {
+ handleError(error.message); // Call centralized error handler
+ return false; // Return false to indicate that fetch failed
+ }
+};
+
+// Function to fetch the 5-day weather forecast
+const fetchWeatherForecast = async (city) => {
+ try {
+ const API_KEY = "0c5116ff347d8ce8d78e8d3c18029dd7";
+ const API_URL = `https://api.openweathermap.org/data/2.5/forecast?q=${city}&units=metric&APPID=${API_KEY}`;
+ const response = await fetch(API_URL);
+
+ if (!response.ok) {
+ throw new Error(`Forecast not available for city "${city}".`); // If no forecast is available, throw an error
+ }
+
+ const data = await response.json();
+ displayWeatherForecast(data);
+ } catch (error) {
+ // Log the error but do not show another alert to avoid duplicate messages
+ console.error("Error fetching weather forecast:", error.message);
+ }
+};
+
+// Function to update the background image based on the weather description
+const updateBackgroundImage = (weatherDescription) => {
+ if (!mainWrapper) return;
+
+ const weather = weatherDescription.toLowerCase(); // Convert weather description to lowercase
+ // Check which weather condition matches and update the background image accordingly
+ if (weather.includes("thunderstorm")) {
+ mainWrapper.style.backgroundImage = 'url("./images/thunderstorm.png")';
+ } else if (
+ weather.includes("drizzle") ||
+ weather.includes("rain") ||
+ weather.includes("freezing rain")
+ ) {
+ mainWrapper.style.backgroundImage = 'url("./images/rain.png")';
+ } else if (weather.includes("sleet") || weather.includes("snow")) {
+ mainWrapper.style.backgroundImage = 'url("./images/snowy.png")';
+ } else if (
+ weather.includes("mist") ||
+ weather.includes("haze") ||
+ weather.includes("fog") ||
+ weather.includes("smoke")
+ ) {
+ mainWrapper.style.backgroundImage = 'url("./images/mist.png")';
+ } else if (
+ weather.includes("dust") ||
+ weather.includes("sand") ||
+ weather.includes("ash")
+ ) {
+ mainWrapper.style.backgroundImage = 'url("./images/dust.png")';
+ } else if (weather.includes("squall") || weather.includes("clouds")) {
+ mainWrapper.style.backgroundImage = 'url("./images/cloudy.png")';
+ } else if (weather.includes("tornado")) {
+ mainWrapper.style.backgroundImage = 'url("./images/thunderstorm.png")';
+ } else if (weather.includes("clear")) {
+ mainWrapper.style.backgroundImage = 'url("./images/sunny.png")';
+ } else {
+ mainWrapper.style.backgroundImage = 'url("./images/default.png")'; // Default image
+ }
+};
+
+// Function to display the fetched weather data on the webpage
+const displayWeatherData = (data) => {
+ if (tempToday) tempToday.textContent = `${Math.round(data.main.temp)}°C`; // Displays current temperature
+ if (cityName) cityName.textContent = data.name; // Display the city name
+ if (weatherDescription) {
+ // Display the weather description
+ weatherDescription.textContent = capitalizeFirstLetter(
+ data.weather[0].description
+ );
+ }
+
+ updateBackgroundImage(data.weather[0].description); // Update the background image
+ // Calculate and display local time based on the city's timezone
+ const timezoneOffset = data.timezone;
+ const utcTime = new Date().getTime() + new Date().getTimezoneOffset() * 60000;
+ const localTimeDate = new Date(utcTime + timezoneOffset * 1000);
+ if (localTime) {
+ localTime.textContent = localTimeDate.toLocaleTimeString([], {
+ hour: "2-digit",
+ minute: "2-digit",
+ });
+ hideLocationLoading(); // Hide loading message and show content
+ }
+
+ if (mainIcon) {
+ const iconCode = data.weather[0].icon;
+ mainIcon.innerHTML = ``;
+ }
+ // Display sunrise and sunset times
+ const sunriseTime = new Date((data.sys.sunrise + data.timezone) * 1000);
+ const sunsetTime = new Date((data.sys.sunset + data.timezone) * 1000);
+ if (sunriseText) {
+ sunriseText.textContent = `Sunrise: ${sunriseTime.toLocaleTimeString([], {
+ hour: "2-digit",
+ minute: "2-digit",
+ })}`;
+ }
+ if (sunsetText) {
+ sunsetText.textContent = `Sunset: ${sunsetTime.toLocaleTimeString([], {
+ hour: "2-digit",
+ minute: "2-digit",
+ })}`;
+ }
+};
+
+// Function to display the 5-day weather forecast
+const displayWeatherForecast = (data) => {
+ if (!forecastContainer) return;
+
+ forecastContainer.innerHTML = ""; // Clear the previous forecast
+
+ const forecastList = data.list.filter((forecast) =>
+ forecast.dt_txt.includes("12:00:00")
+ );
+ // Display the forecast for the next 5 days
+ forecastList.slice(0, 5).forEach((forecast) => {
+ const date = new Date(forecast.dt_txt).toLocaleDateString(undefined, {
+ weekday: "short",
+ });
+ const temp = `${Math.round(forecast.main.temp)}°C`;
+ const windSpeed = `${forecast.wind.speed.toFixed(1)} m/s`;
+ const iconCode = forecast.weather[0].icon;
+
+ const forecastRow = document.createElement("tr");
+ forecastRow.innerHTML = `
+
${date}
+
+
+
+
${temp}
+
${windSpeed}
+ `;
+ forecastContainer.appendChild(forecastRow); // Add forecast row to the table
+ });
+};
+
+// Helper function to capitalize the first letter of the weather description
+const capitalizeFirstLetter = (string) => {
+ return string.charAt(0).toUpperCase() + string.slice(1);
+};
+
+// Add event listener to the search button to fetch weather data based on the user's input
+if (searchBtn) {
+ searchBtn.addEventListener("click", async () => {
+ const city = inputField.value.trim(); // Get the city name from the input field
+ if (city) {
+ const weatherDataFetched = await fetchWeatherData(city); // Fetch the weather data for the entered city
+ if (weatherDataFetched) {
+ await fetchWeatherForecast(city); // Fetch the forecast if weather data is successfully fetched
+ }
+ inputField.value = ""; // Clear the input field after search
+ } else {
+ alert("Please enter a city name."); // Show an alert if no city is entered
+ }
+ });
+}
+
+// Function to get the user's current location and fetch weather data if location access is granted
+const getWeatherForCurrentLocation = () => {
+ if (navigator.geolocation) {
+ showLocationLoading(); // Show loading message while waiting for location permission
+ navigator.geolocation.getCurrentPosition(successCallback, errorCallback); // Get current location
+ } else {
+ handleError("Geolocation is not supported by this browser."); // Show error if geolocation is not supported
+ }
+};
+
+// Callback function for successful geolocation
+// Callback function for successful geolocation
+const successCallback = async (position) => {
+ const { latitude, longitude } = position.coords; // Extract latitude and longitude from position
+
+ try {
+ const reverseGeocodeUrl = `https://api.openweathermap.org/geo/1.0/reverse?lat=${latitude}&lon=${longitude}&limit=1&appid=0c5116ff347d8ce8d78e8d3c18029dd7`;
+ const response = await fetch(reverseGeocodeUrl); // Fetch city name based on latitude and longitude
+
+ if (!response.ok) {
+ throw new Error("Unable to fetch location data.");
+ }
+
+ const data = await response.json();
+ if (data.length > 0) {
+ const city = data[0].name; // Get the city name from the response
+ const weatherDataFetched = await fetchWeatherData(city); // Fetch weather data for the city
+ if (weatherDataFetched) {
+ await fetchWeatherForecast(city); // Fetch forecast only if weather data was fetched successfully
+ }
+ } else {
+ // Handle case where location is not found
+ throw new Error(
+ `Your current location (Lat: ${latitude}, Lon: ${longitude}) was not found. Please try again or enter a city manually.`
+ );
+ }
+ } catch (error) {
+ handleError(error.message); // Show a specific error message when location is not found
+ } finally {
+ hideLocationLoading(); // Hide loading message after location permission is handled
+ }
+};
+
+// Error callback function for geolocation errors
+const errorCallback = (error) => {
+ let errorMessage = "An unknown error occurred."; // Default error message
+ switch (error.code) {
+ case error.PERMISSION_DENIED:
+ errorMessage = "Please activate your location."; // Handle permission denied error
+ break;
+ case error.POSITION_UNAVAILABLE:
+ errorMessage = "Location information is unavailable."; // Handle unavailable location error
+ break;
+ case error.TIMEOUT:
+ errorMessage = "The request to get your location timed out."; // Handle timeout error
+ break;
+ }
+ handleError(errorMessage); // Show error message to the user
+ hideLocationLoading(); // Hide loading message after location permission is handled
+};
+
+// Call the function to get weather data for current location on page load
+getWeatherForCurrentLocation();
diff --git a/style.css b/style.css
new file mode 100644
index 000000000..e32c6f729
--- /dev/null
+++ b/style.css
@@ -0,0 +1,359 @@
+/* Preload images by using hidden divs */
+/* This ensures images are loaded in the background but not visible */
+#preload {
+ position: absolute;
+ width: 0;
+ height: 0;
+ overflow: hidden;
+ background: url("./images/thunderstorm.png"), url("./images/rain.png"),
+ url("./images/snowy.png"), url("./images/mist.png"),
+ url("./images/dust.png"), url("./images/cloudy.png"),
+ url("./images/sunny.png"), url("./images/default.png");
+}
+
+/* Styles for the loading message container */
+/* This will center the spinner and text vertically and horizontally */
+#loadingMessage {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 100vh;
+ font-size: 20px;
+ text-align: center;
+}
+
+#loadingMessage .spinner {
+ width: 40px;
+ height: 40px;
+ border: 4px solid rgba(0, 0, 0, 0.1);
+ border-top: 4px solid #333;
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
+ margin-bottom: 10px; /* Space between spinner and text */
+}
+
+/* Defines the spinning animation */
+@keyframes spin {
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+/* Hide the spinner when app content is visible */
+#appContent {
+ display: none; /* This is shown once the data is loaded */
+}
+
+/* General styling */
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: "Arial", sans-serif;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ min-height: 100vh;
+ background-color: #f0f0f0; /* Background color for the body */
+}
+
+/* Main container styling */
+.container {
+ width: 500px; /* Adjusted width to make the container wider */
+ max-width: 90%; /* Max width to ensure responsiveness */
+ overflow: hidden;
+ box-shadow: 20px 20px 30px rgba(0, 0, 0, 0.1);
+ /* background-color: rgba(255, 255, 255, 0.3); */
+ backdrop-filter: blur(5px); /* Adds a slight blur effect */
+ border-radius: 10px;
+ position: relative;
+ margin: 0 auto; /* Center the container */
+ padding: 0; /* Remove any extra padding */
+ /* Background image settings */
+ background-size: cover; /* Make sure the image covers the entire container */
+ background-position: center; /* Center the image */
+ background-repeat: no-repeat; /* Do not repeat the image */
+ background-clip: border-box; /* Ensure the background respects the border radius */
+ background-attachment: fixed; /* Optional: Makes the background fixed */
+ background-color: rgba(255, 255, 255, 1);
+}
+
+/* Container for the curved area */
+.feature-image {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100px; /* Match height to the .background-top-gradient */
+ background: no-repeat center center/cover; /* Use adjusted path and !important */
+ z-index: 0; /* Ensure it stays behind the gradient */
+ transition: background-image 0.5s ease-in-out;
+}
+
+/* Main content wrapper */
+.mainWrapper {
+ padding: 10px;
+ padding-bottom: 20px;
+ margin-bottom: 20px;
+ text-align: center;
+ position: relative;
+ z-index: 2;
+ /* border-radius: 0 0 10px 10px; */
+ /* border: 1px solid rgba(200, 200, 200, 0.5); */
+ background-repeat: no-repeat;
+ background-size: cover; /* Ensures the background image covers the entire element */
+ background-position: center;
+ transition: background-image 0.5s ease-in-out; /* Adds a smooth transition effect for background changes */
+ height: 100%;
+ width: 100%;
+}
+/* Pseudo-element for the gradient overlay */
+.mainWrapper::before {
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: linear-gradient(to top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0) 30%),
+ linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0) 30%);
+ z-index: 2; /* Higher z-index than .mainWrapper content */
+ pointer-events: none; /* Allow clicks through the pseudo-element */
+}
+
+/* Temperature styling */
+.tempNumber {
+ font-size: 64px;
+ padding-top: 100px;
+ margin: 10px;
+ color: white;
+ font-weight: bold;
+ text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.5);
+}
+
+/* City name styling */
+.cityText {
+ font-size: 28px;
+ margin: 5px 0;
+ color: white;
+ text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.5);
+}
+
+/* Local time styling */
+.local-time {
+ font-size: 18px;
+ margin: 5px 0;
+ color: white;
+ text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5); /* Add text shadow */
+}
+
+/* Weather description styling */
+.describeText {
+ font-size: 18px;
+ margin: 5px 0;
+ color: white;
+ text-transform: capitalize;
+ text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5); /* Add text shadow */
+}
+
+/* Weather icon styling */
+#mainIcon img {
+ width: 60px;
+ height: 60px;
+ margin: 10px 0;
+}
+
+/* Sunrise and sunset styling with text-shadow */
+.sun-position {
+ display: flex;
+ justify-content: space-between;
+ margin: 10px 0;
+ color: white; /* Ensure the text color remains white */
+ font-size: 17px;
+ font-weight: bold;
+ z-index: 3; /* Increase z-index to stay above any overlays */
+ position: relative; /* Ensure it takes the z-index into account */
+ text-shadow: 0 0 5px rgba(0, 0, 0, 0.5); /* Optional: Adds a shadow to make the text stand out more */
+}
+
+.sun-position div {
+ width: 50%;
+ text-align: center;
+}
+
+/* Search bar styling */
+.search {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: transparent;
+ box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.1);
+ margin-top: 10px;
+}
+
+/* Style for the input field */
+.search-bar {
+ flex: 1; /* Allow input to take available space */
+ height: 35px; /* Adjust height */
+ padding: 10px; /* Adds padding inside the input */
+ font-size: 16px; /* Increase font size */
+ border: none;
+ outline: none; /* Remove default outline on focus */
+ background-color: rgba(
+ 255,
+ 255,
+ 255,
+ 0.1
+ ); /* Slightly transparent background */
+ color: #ffffff; /* White text color */
+ /* box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); */
+
+ backdrop-filter: blur(10px); /* Apply blur effect */
+ -webkit-backdrop-filter: blur(10px); /* Safari support */
+ border-radius: 10px; /* Rounded corners */
+}
+
+/* Style for the search button */
+.search-button {
+ width: auto; /* Automatically size the button */
+ padding: 8px 15px; /* Adjust padding for the button */
+ background: transparent; /* Transparent background */
+ color: #ffffff; /* White text color */
+ filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8));
+
+ border: none;
+ border-radius: 20px; /* Rounded corners */
+ cursor: pointer; /* Pointer cursor */
+}
+.search-bar::placeholder {
+ color: white; /* Sets the placeholder text color to white */
+ opacity: 1; /* Ensures full opacity for the placeholder text */
+}
+
+/* Forecast section */
+.weather-forecast {
+ width: 100%;
+ border-collapse: collapse;
+ margin-top: 20px;
+ text-align: center; /* Center the text inside the table */
+ border: none; /* Remove the border from the table */
+}
+
+.weather-forecast td {
+ padding: 10px;
+ font-size: 18px;
+ padding-left: 0; /* Remove left padding to center the text */
+ border: none; /* Remove the border from table cells */
+}
+
+.weather-forecast .forecast-category.icon img {
+ width: 40px;
+ background-color: rgba(255, 255, 255, 1);
+}
+
+.weather-forecast tr:last-child td {
+ border-bottom: none;
+ padding-bottom: 20px;
+}
+
+/* Navbar with search and close icons */
+.nav {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ width: 95%;
+}
+
+/* Search and close button styling */
+.search-button {
+ cursor: pointer;
+}
+
+.search-icon {
+ width: 24px;
+ height: 24px;
+}
+
+/* Hidden elements */
+.hidden {
+ display: none;
+}
+
+/* Search bar toggle functionality */
+#search-box {
+ display: flex;
+ align-items: center; /* Vertically center */
+ justify-content: center; /* Horizontally center */
+ width: 100%; /* Adjust width of the container */
+ margin: 0 auto; /* Center the container horizontally */
+ padding: 10px;
+ /* background-color: transparent; */
+ border-radius: 10px;
+ box-shadow: none;
+ z-index: 3; /* Ensure it stays above other elements */
+}
+
+#search-box.active {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+/* ------------------------------------------------ */
+@media only screen and (max-width: 425px) {
+ .container {
+ width: 100vw; /* Take full viewport width */
+ height: 100vh; /* Take full viewport height */
+ max-width: 100%; /* Remove any max-width limitations */
+ margin: 0; /* Remove any margins */
+ border-radius: 0; /* Remove border radius */
+ box-shadow: none; /* Remove shadow */
+ overflow: auto; /* Allow scrolling if content overflows */
+ display: flex; /* Use flexbox for proper alignment */
+ flex-direction: column; /* Stack children vertically */
+ justify-content: center; /* Center content vertically */
+ align-items: center; /* Center content horizontally */
+ }
+
+ #search-box {
+ margin-bottom: 50px; /* Add space below the search toggler */
+ }
+
+ .mainWrapper {
+ padding: 10px;
+ height: auto; /* Let the content determine the height */
+ flex: 1; /* Let it grow to fill available space */
+ display: flex; /* Use flexbox */
+ flex-direction: column; /* Stack children vertically */
+ justify-content: center; /* Center content */
+ margin: 0;
+ }
+
+ .search {
+ margin-top: 10px;
+
+ width: 90%; /* Take most of the available width */
+ }
+
+ .tempNumber {
+ font-size: 48px; /* Adjust font size * /
+ padding-top: 20px; /* Reduce top padding */
+ }
+
+ .cityText {
+ font-size: 24px; /* Adjust font size */
+ }
+
+ .sun-position {
+ font-size: 16px; /* Adjust font size */
+ }
+}