Upload files to "/"
This commit is contained in:
commit
76eb07896c
41
README.md
Normal file
41
README.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# AOU GPA Calculator
|
||||||
|
|
||||||
|
Visit the site here: [AOU GPA Calculator](https://aougpa.netlify.app/)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The AOU GPA Calculator is a web-based tool designed to assist students at the Arab Open University (AOU) in calculating their Grade Point Average (GPA) based on the university's grading system. This calculator provides a user-friendly interface for students to input their grades and study hours, offering a quick and accurate assessment of their academic performance.
|
||||||
|
|
||||||
|
|
||||||
|
![لقطة شاشة 2024-10-24 040541](https://github.com/user-attachments/assets/1a5d73ac-6167-4503-a07f-ed8d0f0286f9)
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Dynamic Subject Input**:
|
||||||
|
Easily add subjects with individual grade and study hour inputs. Remove specific subjects to tailor your GPA calculation.
|
||||||
|
|
||||||
|
- **Intuitive User Interface**:
|
||||||
|
Clear and straightforward design for efficient use. Responsive layout for a seamless experience on various devices.
|
||||||
|
|
||||||
|
- **AOU Grading System**:
|
||||||
|
Follows the AOU grading system, providing accurate GPA calculations. Corresponding grades include A, B+, B, C+, C, D, and F.
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
1. **Add Subjects**: Click the "Add Subject" button to input your grades and study hours for each subject.
|
||||||
|
|
||||||
|
2. **Calculate GPA**: Use the "Calculate GPA" button to obtain your GPA based on the entered subjects.
|
||||||
|
|
||||||
|
3. **Remove Subjects**: Click the "Remove All" button to clear all subjects and start fresh.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions are welcome! If you have ideas for improvements, bug fixes, or additional features, feel free to open an issue or submit a pull request.
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
This GPA Calculator was created by **Mohammed Nuseirat**. Connect with me on [LinkedIn](https://www.linkedin.com/in/mohammednuseirat/) and [X](https://x.com/MohaNuseirat).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||||
|
|
35
Update2.0.md
Normal file
35
Update2.0.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
## Update 2.0 - AOU GPA Calculator
|
||||||
|
|
||||||
|
### Overview
|
||||||
|
In this update, I have introduced several new features and enhancements to improve the user experience of the AOU GPA Calculator.
|
||||||
|
The primary goal of this release is to provide users with a more intuitive interface and streamline the process of calculating GPA.
|
||||||
|
|
||||||
|
|
||||||
|
## New
|
||||||
|
![لقطة شاشة 2024-10-24 040541](https://github.com/user-attachments/assets/1a5d73ac-6167-4503-a07f-ed8d0f0286f9)
|
||||||
|
|
||||||
|
## Old
|
||||||
|
![لقطة شاشة 2024-10-23 215500](https://github.com/user-attachments/assets/3a695d15-9d73-4d18-b15b-aae9b42d4891)
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
- **Dynamic Subject Input**: Users can now add multiple subjects dynamically, allowing for a more personalized and flexible GPA calculation experience. Each subject can be easily added and removed as needed.
|
||||||
|
|
||||||
|
- **Enhanced Button Functionality**:
|
||||||
|
- **Calculate GPA**: A dedicated button for calculating GPA has been implemented, making it easier for users to perform calculations with a single click.
|
||||||
|
- **Remove All Subjects**: Users can now clear all subject inputs with a single button click, providing a quick way to reset the form.
|
||||||
|
|
||||||
|
- **Improved User Interface**:
|
||||||
|
- The overall design has been refined with better spacing, layout adjustments, and a more modern aesthetic.
|
||||||
|
- The input fields have been styled for improved accessibility and usability, including focused states for better user feedback.
|
||||||
|
|
||||||
|
- **Responsive Design**: The application has been optimized for mobile devices, ensuring a seamless experience across various screen sizes.
|
||||||
|
|
||||||
|
### Visual Updates
|
||||||
|
- The logo and overall color scheme have been updated to enhance visual appeal and align with modern design trends.
|
||||||
|
- Buttons have been styled with hover effects to provide interactive feedback.
|
||||||
|
|
||||||
|
### Author
|
||||||
|
This update was developed by **Mohammed Nuseirat**.
|
||||||
|
|
||||||
|
### Future Plans
|
||||||
|
I am committed to continuously improving the AOU GPA Calculator. In future updates, I plan to explore additional features such as GPA history tracking, a dark mode option, and more detailed grading scales.
|
121
index.html
Normal file
121
index.html
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
<!-- Created by Mohammed Nuseirat -->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- Setting language to English -->
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<!-- Character encoding for Unicode support -->
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<!-- Responsive viewport settings for mobile devices -->
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<!-- Page title showing app name and institution -->
|
||||||
|
<title>GPA Calculator | AOU</title>
|
||||||
|
<!-- Link to custom CSS stylesheet -->
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
<!-- Font Awesome icons library -->
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Main container wrapper -->
|
||||||
|
<main class="container">
|
||||||
|
<!-- Logo section with glass effect -->
|
||||||
|
<div class="logo-container glass-effect">
|
||||||
|
<!-- University logo image -->
|
||||||
|
<img src="https://www.arabou.edu.sa/assets/common/images/logo-footer-ar.png" alt="AOU Logo" class="logo">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main calculator container with glass effect -->
|
||||||
|
<div class="calculator-container glass-effect">
|
||||||
|
<!-- Arabic title for GPA calculator -->
|
||||||
|
<h1>حساب المعدل التراكمي للجامعة العربية المفتوحة</h1>
|
||||||
|
|
||||||
|
<!-- Previous GPA input section -->
|
||||||
|
<div class="previous-gpa-section">
|
||||||
|
<div class="input-group">
|
||||||
|
<!-- Previous GPA input field -->
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<label for="prev-gpa"></label>
|
||||||
|
<input type="number"
|
||||||
|
id="prev-gpa"
|
||||||
|
step="0.01"
|
||||||
|
min="0"
|
||||||
|
max="4"
|
||||||
|
placeholder="Enter previous GPA / المعدل السابق">
|
||||||
|
</div>
|
||||||
|
<!-- Previous hours input field -->
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<label for="prev-hours"></label>
|
||||||
|
<input type="number"
|
||||||
|
id="prev-hours"
|
||||||
|
min="0"
|
||||||
|
placeholder="Enter previous hours / الساعات السابقة">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Container for dynamically added subjects -->
|
||||||
|
<div id="subjects-container" class="subjects-container">
|
||||||
|
<!-- Subjects will be added here dynamically via JavaScript -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Action buttons group -->
|
||||||
|
<div class="button-group">
|
||||||
|
<!-- Add subject button -->
|
||||||
|
<button class="btn btn-primary" onclick="addSubject()">
|
||||||
|
<i class="fas fa-plus"></i>
|
||||||
|
Add Subject
|
||||||
|
</button>
|
||||||
|
<!-- Calculate GPA button -->
|
||||||
|
<button class="btn btn-success" onclick="calculateGPA()">
|
||||||
|
<i class="fas fa-calculator"></i>
|
||||||
|
Calculate
|
||||||
|
</button>
|
||||||
|
<!-- Clear all inputs button -->
|
||||||
|
<button class="btn btn-danger" onclick="clearAll()">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
Clear All
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Results container (hidden by default) -->
|
||||||
|
<div id="result" class="result glass-effect hidden">
|
||||||
|
<!-- Results will be displayed here via JavaScript -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer section -->
|
||||||
|
<footer class="footer glass-effect">
|
||||||
|
<div class="footer-content">
|
||||||
|
<!-- Developer credit -->
|
||||||
|
<p class="footer-text">Developed by Mohammed Nuseirat
|
||||||
|
<br>• v2.0</p>
|
||||||
|
<!-- Social media links -->
|
||||||
|
<div class="social-links">
|
||||||
|
<!-- GitHub profile link -->
|
||||||
|
<a href="https://github.com/nuseirat" target="_blank" class="social-link">
|
||||||
|
<i class="fab fa-github fa-2x"></i>
|
||||||
|
</a>
|
||||||
|
<!-- LinkedIn profile link -->
|
||||||
|
<a href="https://linkedin.com/in/mohammednuseirat" target="_blank" class="social-link">
|
||||||
|
<i class="fab fa-linkedin fa-2x"></i>
|
||||||
|
</a>
|
||||||
|
<!-- Twitter/X profile link -->
|
||||||
|
<a href="https://x.com/mohanuseirat" target="_blank" class="social-link">
|
||||||
|
<i class="fa-brands fa-x-twitter fa-2x"></i>
|
||||||
|
<!-- Website link -->
|
||||||
|
<a href="https://nuseirat.github.io/" target="_blank" class="social-link">
|
||||||
|
<i class="fas fa-globe fa-2x"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- JavaScript libraries and scripts -->
|
||||||
|
<!-- GSAP animation library -->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
|
||||||
|
<!-- Custom JavaScript file -->
|
||||||
|
<script src="script.js"></script>
|
||||||
|
<!-- Font Awesome kit -->
|
||||||
|
<script src="https://kit.fontawesome.com/86e812f22e.js" crossorigin="anonymous"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
262
script.js
Normal file
262
script.js
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
// Created by Mohammed Nuseirat
|
||||||
|
|
||||||
|
// script.js
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
// Array to store all subject input elements
|
||||||
|
const subjects = [];
|
||||||
|
|
||||||
|
// Add Subject Button Handler
|
||||||
|
window.addSubject = function() {
|
||||||
|
// Create container for new subject inputs
|
||||||
|
const subjectInput = document.createElement("div");
|
||||||
|
subjectInput.className = "subject";
|
||||||
|
|
||||||
|
// Create grade input field
|
||||||
|
const gradeInput = document.createElement("input");
|
||||||
|
gradeInput.type = "text";
|
||||||
|
gradeInput.placeholder = "Enter grade (A, B+, B, C+, C, D, F)";
|
||||||
|
gradeInput.className = "grade-input";
|
||||||
|
|
||||||
|
// Create credit hours input field
|
||||||
|
const hoursInput = document.createElement("input");
|
||||||
|
hoursInput.type = "number";
|
||||||
|
hoursInput.placeholder = "Enter hours";
|
||||||
|
hoursInput.className = "hours-input";
|
||||||
|
hoursInput.min = "1";
|
||||||
|
|
||||||
|
// Create remove button with icon
|
||||||
|
const removeButton = document.createElement("button");
|
||||||
|
removeButton.innerHTML = '<i class="fas fa-times"></i>';
|
||||||
|
removeButton.className = "remove-button";
|
||||||
|
|
||||||
|
// Add animation and removal functionality to remove button
|
||||||
|
removeButton.addEventListener("click", function () {
|
||||||
|
gsap.to(subjectInput, {
|
||||||
|
duration: 0.3,
|
||||||
|
opacity: 0,
|
||||||
|
y: -20,
|
||||||
|
ease: 'power2.in',
|
||||||
|
onComplete: () => {
|
||||||
|
subjectInput.remove();
|
||||||
|
updateSubjectsArray();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assemble the subject input container
|
||||||
|
subjectInput.appendChild(gradeInput);
|
||||||
|
subjectInput.appendChild(hoursInput);
|
||||||
|
subjectInput.appendChild(removeButton);
|
||||||
|
|
||||||
|
// Add to DOM and subjects array
|
||||||
|
document.getElementById("subjects-container").appendChild(subjectInput);
|
||||||
|
subjects.push(subjectInput);
|
||||||
|
|
||||||
|
// Animate new subject entry
|
||||||
|
gsap.from(subjectInput, {
|
||||||
|
duration: 0.5,
|
||||||
|
opacity: 0,
|
||||||
|
y: 20,
|
||||||
|
ease: 'power2.out'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Validate grade input
|
||||||
|
gradeInput.addEventListener('input', function() {
|
||||||
|
this.value = this.value.toUpperCase();
|
||||||
|
const validGrades = ['A', 'B+', 'B', 'C+', 'C', 'D', 'F'];
|
||||||
|
if (!validGrades.includes(this.value) && this.value !== '') {
|
||||||
|
this.classList.add('invalid');
|
||||||
|
} else {
|
||||||
|
this.classList.remove('invalid');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Validate hours input
|
||||||
|
hoursInput.addEventListener('input', function() {
|
||||||
|
if (this.value < 1) {
|
||||||
|
this.classList.add('invalid');
|
||||||
|
} else {
|
||||||
|
this.classList.remove('invalid');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clear All Button Handler
|
||||||
|
window.clearAll = function() {
|
||||||
|
const subjectInputs = document.querySelectorAll(".subject");
|
||||||
|
|
||||||
|
// Animate removal of all subjects
|
||||||
|
gsap.to(subjectInputs, {
|
||||||
|
duration: 0.3,
|
||||||
|
opacity: 0,
|
||||||
|
y: -20,
|
||||||
|
stagger: 0.1,
|
||||||
|
ease: 'power2.in',
|
||||||
|
onComplete: () => {
|
||||||
|
// Clear all inputs and results
|
||||||
|
document.getElementById("subjects-container").innerHTML = '';
|
||||||
|
subjects.length = 0;
|
||||||
|
document.getElementById("prev-gpa").value = "";
|
||||||
|
document.getElementById("prev-hours").value = "";
|
||||||
|
document.getElementById("result").innerHTML = "";
|
||||||
|
document.getElementById("result").classList.add("hidden");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Animate calculator container
|
||||||
|
gsap.to('.calculator-container', {
|
||||||
|
duration: 0.2,
|
||||||
|
scale: 0.98,
|
||||||
|
ease: 'power2.in',
|
||||||
|
yoyo: true,
|
||||||
|
repeat: 1
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calculate GPA Button Handler
|
||||||
|
window.calculateGPA = function() {
|
||||||
|
// Validate all inputs before calculation
|
||||||
|
const invalidInputs = document.querySelectorAll('.invalid');
|
||||||
|
if (invalidInputs.length > 0) {
|
||||||
|
showResult("Please correct invalid inputs before calculating", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate totals
|
||||||
|
const totalGradePoints = calculateTotalGradePoints();
|
||||||
|
const totalHours = calculateTotalHours();
|
||||||
|
|
||||||
|
// Get previous GPA data
|
||||||
|
const prevGPA = parseFloat(document.getElementById("prev-gpa").value) || 0;
|
||||||
|
const prevHours = parseFloat(document.getElementById("prev-hours").value) || 0;
|
||||||
|
|
||||||
|
// Validate previous GPA
|
||||||
|
if (prevGPA > 4) {
|
||||||
|
showResult("Previous GPA cannot be greater than 4.0", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate cumulative statistics
|
||||||
|
const cumulativeGradePoints = totalGradePoints + (prevGPA * prevHours);
|
||||||
|
const cumulativeTotalHours = totalHours + prevHours;
|
||||||
|
|
||||||
|
// Validate hours
|
||||||
|
if (totalHours === 0 && prevHours === 0) {
|
||||||
|
showResult("Please enter valid grades and hours", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate GPAs
|
||||||
|
const currentGPA = totalHours === 0 ? 0 : totalGradePoints / totalHours;
|
||||||
|
const cumulativeGPA = cumulativeTotalHours === 0 ? 0 : cumulativeGradePoints / cumulativeTotalHours;
|
||||||
|
|
||||||
|
// Format and display results
|
||||||
|
const resultHTML = `
|
||||||
|
<div class="result-content">
|
||||||
|
<div class="result-item">
|
||||||
|
<span class="result-label">Semester Hours:</span>
|
||||||
|
<span class="result-value">${totalHours}</span>
|
||||||
|
</div>
|
||||||
|
<div class="result-item">
|
||||||
|
<span class="result-label">Total Hours:</span>
|
||||||
|
<span class="result-value">${cumulativeTotalHours}</span>
|
||||||
|
</div>
|
||||||
|
<div class="result-item">
|
||||||
|
<span class="result-label">Semester GPA:</span>
|
||||||
|
<span class="result-value">${currentGPA.toFixed(2)}</span>
|
||||||
|
</div>
|
||||||
|
<div class="result-item">
|
||||||
|
<span class="result-label">Cumulative GPA:</span>
|
||||||
|
<span class="result-value">${cumulativeGPA.toFixed(2)}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
showResult(resultHTML);
|
||||||
|
|
||||||
|
// Animate result items
|
||||||
|
gsap.from('.result-item', {
|
||||||
|
duration: 0.5,
|
||||||
|
opacity: 0,
|
||||||
|
y: 20,
|
||||||
|
stagger: 0.1,
|
||||||
|
ease: 'power2.out'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to calculate total grade points
|
||||||
|
function calculateTotalGradePoints() {
|
||||||
|
let totalGradePoints = 0;
|
||||||
|
|
||||||
|
subjects.forEach(subject => {
|
||||||
|
const grade = subject.querySelector(".grade-input").value;
|
||||||
|
const hours = parseFloat(subject.querySelector(".hours-input").value) || 0;
|
||||||
|
|
||||||
|
const gradePoint = getGradePoint(grade);
|
||||||
|
totalGradePoints += (gradePoint * hours);
|
||||||
|
});
|
||||||
|
|
||||||
|
return totalGradePoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to calculate total hours
|
||||||
|
function calculateTotalHours() {
|
||||||
|
let totalHours = 0;
|
||||||
|
|
||||||
|
subjects.forEach(subject => {
|
||||||
|
const hours = parseFloat(subject.querySelector(".hours-input").value) || 0;
|
||||||
|
totalHours += hours;
|
||||||
|
});
|
||||||
|
|
||||||
|
return totalHours;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert letter grades to grade points
|
||||||
|
function getGradePoint(grade) {
|
||||||
|
const gradePoints = {
|
||||||
|
'A': 4,
|
||||||
|
'B+': 3.5,
|
||||||
|
'B': 3,
|
||||||
|
'C+': 2.5,
|
||||||
|
'C': 2,
|
||||||
|
'D': 1.5,
|
||||||
|
'F': 0
|
||||||
|
};
|
||||||
|
return gradePoints[grade.toUpperCase()] || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display result with animation
|
||||||
|
function showResult(message, type = "success") {
|
||||||
|
const resultDiv = document.getElementById("result");
|
||||||
|
resultDiv.innerHTML = message;
|
||||||
|
resultDiv.classList.remove("hidden");
|
||||||
|
resultDiv.style.opacity = "0";
|
||||||
|
|
||||||
|
// Animate result appearance
|
||||||
|
gsap.to(resultDiv, {
|
||||||
|
duration: 0.5,
|
||||||
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
ease: 'power2.out'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Scroll result into view
|
||||||
|
resultDiv.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update subjects array after removal
|
||||||
|
function updateSubjectsArray() {
|
||||||
|
subjects.length = 0;
|
||||||
|
document.querySelectorAll(".subject").forEach(subject => subjects.push(subject));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate previous GPA input
|
||||||
|
const prevGPAInput = document.getElementById("prev-gpa");
|
||||||
|
prevGPAInput.addEventListener('input', function() {
|
||||||
|
if (this.value > 4) {
|
||||||
|
this.classList.add('invalid');
|
||||||
|
} else {
|
||||||
|
this.classList.remove('invalid');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
361
style.css
Normal file
361
style.css
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
/* Created by Mohammed Nuseirat*/
|
||||||
|
|
||||||
|
/* Define CSS custom properties (variables) for consistent theming across the application */
|
||||||
|
:root {
|
||||||
|
--primary-bg: linear-gradient(135deg, #020617, #1e293b); /* Dark gradient background */
|
||||||
|
--glass-bg: rgba(30, 41, 59, 0.7); /* Semi-transparent background for glass effect */
|
||||||
|
--text-color: #e2e8f0; /* Light text color for dark theme */
|
||||||
|
--input-bg: rgba(30, 41, 59, 0.8); /* Slightly darker background for input fields */
|
||||||
|
--btn-primary: #1e3a8a; /* Deep blue for primary buttons */
|
||||||
|
--btn-success: #059669; /* Green for success buttons */
|
||||||
|
--btn-danger: #991b1b; /* Red for danger/delete buttons */
|
||||||
|
--shadow: 0 8px 32px rgba(0, 0, 0, 0.3); /* Subtle shadow for depth */
|
||||||
|
--border: rgba(255, 255, 255, 0.1); /* Light border for glass effect */
|
||||||
|
--invalid-color: #ef4444; /* Red for validation errors */
|
||||||
|
--success-color: #10b981; /* Green for success states */
|
||||||
|
--warning-color: #f59e0b; /* Orange for warnings */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset default browser styles */
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Base body styles with flexbox centering */
|
||||||
|
body {
|
||||||
|
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--primary-bg);
|
||||||
|
color: var(--text-color);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reusable glass morphism effect */
|
||||||
|
.glass-effect {
|
||||||
|
background: var(--glass-bg);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 1.5rem;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main container layout */
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 900px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logo section styling */
|
||||||
|
.logo-container {
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logo image styling with smooth transition */
|
||||||
|
.logo {
|
||||||
|
height: 100px;
|
||||||
|
width: auto;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculator section container */
|
||||||
|
.calculator-container {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main heading styles */
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grid layout for input fields */
|
||||||
|
.input-group {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 1.5rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Individual input field container */
|
||||||
|
.input-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Input field styling */
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 1rem;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
background: var(--input-bg);
|
||||||
|
color: var(--text-color);
|
||||||
|
font-size: 1rem;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Input focus state */
|
||||||
|
input:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: var(--btn-primary);
|
||||||
|
box-shadow: 0 0 0 2px rgba(30, 58, 138, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Input label styling */
|
||||||
|
.input-label {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: var(--text-color);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Container for subject entries */
|
||||||
|
.subjects-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Individual subject entry styling */
|
||||||
|
.subject {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1.5fr 1fr auto;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
padding: 1rem;
|
||||||
|
background: var(--glass-bg);
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
animation: slideIn 0.3s ease forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button group layout */
|
||||||
|
.button-group {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Base button styles */
|
||||||
|
.btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 1rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Icon sizing within buttons */
|
||||||
|
.btn i {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button variants */
|
||||||
|
.btn-primary { background: var(--btn-primary); }
|
||||||
|
.btn-success { background: var(--btn-success); }
|
||||||
|
.btn-danger { background: var(--btn-danger); }
|
||||||
|
|
||||||
|
/* Button hover effects */
|
||||||
|
.btn:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button active state */
|
||||||
|
.btn:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove button styling */
|
||||||
|
.remove-button {
|
||||||
|
background: var(--btn-danger);
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove button hover effect */
|
||||||
|
.remove-button:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Results section container */
|
||||||
|
.result {
|
||||||
|
padding: 2rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Results content layout */
|
||||||
|
.result-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Individual result item styling */
|
||||||
|
.result-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 1rem;
|
||||||
|
background: rgba(30, 41, 59, 0.5);
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Result label styling */
|
||||||
|
.result-label {
|
||||||
|
font-weight: 500;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Result value styling */
|
||||||
|
.result-value {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Footer section styling */
|
||||||
|
.footer-content {
|
||||||
|
text-align: center;
|
||||||
|
padding: 2rem;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Social links container */
|
||||||
|
.social-links {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Individual social link styling */
|
||||||
|
.social-link {
|
||||||
|
color: var(--text-color);
|
||||||
|
opacity: 0.8;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Social link hover effect */
|
||||||
|
.social-link:hover {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-3px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invalid input state */
|
||||||
|
.invalid {
|
||||||
|
border-color: var(--invalid-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide elements */
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animation keyframes */
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive design for mobile devices */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
body {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group,
|
||||||
|
.button-group {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subject {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-item {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading state styles */
|
||||||
|
.loading {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading overlay animation */
|
||||||
|
.loading::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(30, 41, 59, 0.7);
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
animation: pulse 1.5s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading pulse animation */
|
||||||
|
@keyframes pulse {
|
||||||
|
0% { opacity: 0.7; }
|
||||||
|
50% { opacity: 0.4; }
|
||||||
|
100% { opacity: 0.7; }
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user