diff --git a/Projects/Job Application Tracker Pro/README.md b/Projects/Job Application Tracker Pro/README.md
new file mode 100644
index 00000000..bfd7e840
--- /dev/null
+++ b/Projects/Job Application Tracker Pro/README.md
@@ -0,0 +1,29 @@
+# Job Application Tracker Pro
+
+A premium, interactive developer career search center featuring horizontal Kanban pipeline lanes, salary projections, sub-task milestone checklists, and interview notes logs.
+
+## Core Features
+
+- **Kanban Board Pipeline Lanes**: Organize job applications across 5 columns:
+ * Wishlist -> Applied -> Interviewing -> Offer -> Rejected.
+ * Shift card status columns interactively to recalculate recruitment analytics.
+- **Career Search Analytics Pro**: Custom dashboards summarizing metrics:
+ * Conversion rates (Applied to Interviewing, and Offered rates).
+ * Salary distributions (median, average, and max expected base salary figures).
+ * Offers Value: Total value of active offers.
+- **Relational Inspector Panel**: Click a card to expand the inspector drawer to:
+ * Edit Company, Job Title, Salary, applied date, location status (Remote/Hybrid/Onsite), and Listing URL.
+ * Add custom sub-task checklists (e.g. Practicing DSA, System Design prep, Send follow-up).
+ * Write interviewer names, notes, and logs.
+- **Filtering & Searches**: Fast text query searches indexing companies and roles.
+- **Local Storage State Persistence**: Keeps job profiles and checklists synced locally.
+
+## Startup instructions
+
+Open `index.html` in any web browser.
+
+## Tech stack
+
+- HTML5
+- CSS3 (Vanilla variable parameters, flexbox columns, grid alignments, transition frames)
+- Vanilla JavaScript (Kanban pipeline shifting controllers, statistics calculators, local storage sync logs)
diff --git a/Projects/Job Application Tracker Pro/index.html b/Projects/Job Application Tracker Pro/index.html
new file mode 100644
index 00000000..0158906d
--- /dev/null
+++ b/Projects/Job Application Tracker Pro/index.html
@@ -0,0 +1,273 @@
+
+
+
+
+
+ Job Application Tracker Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Recruitment Board
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Application Inspector
+
Select any job card from the Kanban columns to view task checklists, modify salaries, or log interview questions.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Milestones Sub-Tasks
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Projects/Job Application Tracker Pro/project.json b/Projects/Job Application Tracker Pro/project.json
new file mode 100644
index 00000000..2518dc17
--- /dev/null
+++ b/Projects/Job Application Tracker Pro/project.json
@@ -0,0 +1,17 @@
+{
+ "title": "Job Application Tracker Pro",
+ "description": "A premium client-side career search dashboard featuring horizontal Kanban pipeline lanes, salary projections, and sub-task milestone checklists.",
+ "author": {
+ "name": "Sujal",
+ "github": "Sujal"
+ },
+ "tags": [
+ "productivity",
+ "recruitment",
+ "kanban",
+ "vanilla-js",
+ "localstorage"
+ ],
+ "entry": "index.html",
+ "thumbnail": "thumbnail.svg"
+}
diff --git a/Projects/Job Application Tracker Pro/script.js b/Projects/Job Application Tracker Pro/script.js
new file mode 100644
index 00000000..2e60c361
--- /dev/null
+++ b/Projects/Job Application Tracker Pro/script.js
@@ -0,0 +1,603 @@
+// Job Application Tracker Pro - Interaction Logic
+
+// Default seed job profiles to start the user with a beautiful, populated dashboard
+const SEED_JOBS = [
+ {
+ id: "seed-google",
+ company: "Google",
+ role: "Frontend Engineer - Cloud UX",
+ status: "Offer",
+ dateApplied: "2026-05-15",
+ salary: 145000,
+ location: "Hybrid",
+ url: "https://careers.google.com",
+ notes: "Loved the team! Met with Sarah (EM) and Dave (Tech Lead). Base salary offered is $145,000/yr + 15% bonus. Negotiated sign-on bonus.",
+ tasks: [
+ { id: "g-task-1", text: "Phone recruiter screening", completed: true },
+ { id: "g-task-2", text: "Technical coding interview (Algorithms & DOM)", completed: true },
+ { id: "g-task-3", text: "Onsite panel review & System design", completed: true },
+ { id: "g-task-4", text: "Review written compensation package offer", completed: true }
+ ]
+ },
+ {
+ id: "seed-stripe",
+ company: "Stripe",
+ role: "Senior JavaScript Architect",
+ status: "Interviewing",
+ dateApplied: "2026-06-01",
+ salary: 185000,
+ location: "Remote",
+ url: "https://stripe.com/jobs",
+ notes: "Recruiter screen went great. Next step is system design session scheduled for June 18th. Focus on idempotency, rate limiting, and API design patterns.",
+ tasks: [
+ { id: "s-task-1", text: "Submit resume & application", completed: true },
+ { id: "s-task-2", text: "Portfolio design review", completed: true },
+ { id: "s-task-3", text: "Prepare system design architecture session", completed: false },
+ { id: "s-task-4", text: "Manager alignment interview", completed: false }
+ ]
+ },
+ {
+ id: "seed-netflix",
+ company: "Netflix",
+ role: "UI Engineer - Core Experience",
+ status: "Applied",
+ dateApplied: "2026-06-10",
+ salary: 190000,
+ location: "Onsite",
+ url: "https://jobs.netflix.com",
+ notes: "Applied on the careers portal. Sent follow-up connection message to hiring manager on LinkedIn. Let's see if they respond within a week.",
+ tasks: [
+ { id: "n-task-1", text: "Submit application form", completed: true },
+ { id: "n-task-2", text: "Follow up via LinkedIn recruiter", completed: false }
+ ]
+ },
+ {
+ id: "seed-vercel",
+ company: "Vercel",
+ role: "Developer Relations Engineer",
+ status: "Wishlist",
+ dateApplied: "2026-06-12",
+ salary: 130000,
+ location: "Remote",
+ url: "https://vercel.com/careers",
+ notes: "Wishlist job. Highly interested in their DevRel open headcount. Will request Jake for a warm referral once my new portfolio is clean.",
+ tasks: [
+ { id: "v-task-1", text: "Polish portfolio site & blog posts", completed: false },
+ { id: "v-task-2", text: "Get referral from Jake", completed: false }
+ ]
+ }
+];
+
+// Kanban lane pipeline sequence
+const LANES = ["Wishlist", "Applied", "Interviewing", "Offer", "Rejected"];
+
+// App State
+let jobs = [];
+let activeJobId = null;
+
+// DOM Elements references
+const txtSearch = document.getElementById("txt-search");
+const selLocationFilter = document.getElementById("sel-location-filter");
+
+const lblHeaderApplied = document.getElementById("lbl-header-applied");
+const lblHeaderInterviews = document.getElementById("lbl-header-interviews");
+const lblHeaderOffers = document.getElementById("lbl-header-offers");
+
+const lblOffersValue = document.getElementById("lbl-offers-value");
+const lblAvgSalary = document.getElementById("lbl-avg-salary");
+const lblInterviewRate = document.getElementById("lbl-interview-rate");
+
+const btnResetWorkspace = document.getElementById("btn-reset-workspace");
+const btnAddJob = document.getElementById("btn-add-job");
+
+const colWishlist = document.getElementById("col-wishlist");
+const colApplied = document.getElementById("col-applied");
+const colInterviewing = document.getElementById("col-interviewing");
+const colOffer = document.getElementById("col-offer");
+const colRejected = document.getElementById("col-rejected");
+
+const inspectorEmpty = document.getElementById("inspector-empty");
+const inspectorActive = document.getElementById("inspector-active");
+
+// Form controls references
+const jobCompany = document.getElementById("job-company");
+const jobRole = document.getElementById("job-role");
+const jobDate = document.getElementById("job-date");
+const selStatus = document.getElementById("sel-status");
+const jobSalary = document.getElementById("job-salary");
+const selLocation = document.getElementById("sel-location");
+const jobUrl = document.getElementById("job-url");
+const jobNotes = document.getElementById("job-notes");
+
+const tasksChecklist = document.getElementById("tasks-checklist");
+const txtNewTask = document.getElementById("txt-new-task");
+const btnAddTask = document.getElementById("btn-add-task");
+
+const btnSaveJob = document.getElementById("btn-save-job");
+const btnDeleteJob = document.getElementById("btn-delete-job");
+
+// INITIALIZATION
+window.addEventListener("DOMContentLoaded", () => {
+ loadData();
+ setupEventListeners();
+ calculateAnalytics();
+ renderKanban();
+});
+
+// Load from localStorage or seeds
+function loadData() {
+ const storedJobs = localStorage.getItem("jobtrack_pro_jobs");
+ if (storedJobs) {
+ try {
+ jobs = JSON.parse(storedJobs);
+ } catch (e) {
+ console.error("Error parsing jobs from local storage, resetting to defaults", e);
+ jobs = [...SEED_JOBS];
+ }
+ } else {
+ jobs = [...SEED_JOBS];
+ saveToStorage(false); // don't trigger immediate render during init
+ }
+}
+
+// Save back to storage and recompute
+function saveToStorage(shouldRender = true) {
+ localStorage.setItem("jobtrack_pro_jobs", JSON.stringify(jobs));
+ if (shouldRender) {
+ calculateAnalytics();
+ renderKanban();
+ if (activeJobId) {
+ // Keep inspector updated
+ const activeJob = jobs.find(j => j.id === activeJobId);
+ if (activeJob) {
+ renderTasksChecklist(activeJob);
+ }
+ }
+ }
+}
+
+// Global Event Listeners
+function setupEventListeners() {
+ // Search & Filter
+ txtSearch.addEventListener("input", renderKanban);
+ selLocationFilter.addEventListener("change", renderKanban);
+
+ // Buttons
+ btnAddJob.addEventListener("click", addNewJobSpec);
+ btnResetWorkspace.addEventListener("click", resetWorkspace);
+
+ // Inspector Actions
+ btnSaveJob.addEventListener("click", saveActiveJobChanges);
+ btnDeleteJob.addEventListener("click", deleteActiveJob);
+ btnAddTask.addEventListener("click", handleAddTaskSubmit);
+ txtNewTask.addEventListener("keypress", (e) => {
+ if (e.key === "Enter") {
+ handleAddTaskSubmit();
+ }
+ });
+
+ // Track status changing from the dropdown to automatically update visual lanes in real time
+ selStatus.addEventListener("change", () => {
+ if (activeJobId) {
+ const job = jobs.find(j => j.id === activeJobId);
+ if (job) {
+ job.status = selStatus.value;
+ saveToStorage();
+ }
+ }
+ });
+}
+
+// CALCULATE ANALYTICS
+function calculateAnalytics() {
+ // Header Counter Indicators
+ const appliedCount = jobs.filter(j => j.status === "Applied").length;
+ const interviewingCount = jobs.filter(j => j.status === "Interviewing").length;
+ const offerCount = jobs.filter(j => j.status === "Offer").length;
+
+ lblHeaderApplied.textContent = appliedCount;
+ lblHeaderInterviews.textContent = interviewingCount;
+ lblHeaderOffers.textContent = offerCount;
+
+ // Active Offers Value Sum
+ const offerVal = jobs
+ .filter(j => j.status === "Offer")
+ .reduce((sum, j) => sum + (Number(j.salary) || 0), 0);
+ lblOffersValue.textContent = formatSalary(offerVal);
+
+ // Average Salary of all jobs that have a salary > 0
+ const jobsWithSalary = jobs.filter(j => Number(j.salary) > 0);
+ const avgSalary = jobsWithSalary.length > 0
+ ? Math.round(jobsWithSalary.reduce((sum, j) => sum + Number(j.salary), 0) / jobsWithSalary.length)
+ : 0;
+ lblAvgSalary.textContent = formatSalary(avgSalary);
+
+ // Interview Conversion Rate
+ // Rate = (Interviewing + Offer) / (All applied jobs i.e. not in Wishlist) * 100
+ const totalAppliedFunnel = jobs.filter(j => j.status !== "Wishlist").length;
+ const reachedInterview = jobs.filter(j => j.status === "Interviewing" || j.status === "Offer").length;
+ const conversionRate = totalAppliedFunnel > 0
+ ? Math.round((reachedInterview / totalAppliedFunnel) * 100)
+ : 0;
+ lblInterviewRate.textContent = `${conversionRate}%`;
+
+ // Update counts in lane headers
+ document.getElementById("count-wishlist").textContent = jobs.filter(j => j.status === "Wishlist").length;
+ document.getElementById("count-applied").textContent = appliedCount;
+ document.getElementById("count-interviewing").textContent = interviewingCount;
+ document.getElementById("count-offer").textContent = offerCount;
+ document.getElementById("count-rejected").textContent = jobs.filter(j => j.status === "Rejected").length;
+}
+
+// Format number to local currency format e.g. $145,000/yr
+function formatSalary(amount) {
+ if (!amount || amount <= 0) return "$0/yr";
+ return new Intl.NumberFormat("en-US", {
+ style: "currency",
+ currency: "USD",
+ maximumFractionDigits: 0
+ }).format(amount) + "/yr";
+}
+
+// RENDER KANBAN PIPELINE BOARD
+function renderKanban() {
+ const searchQuery = txtSearch.value.trim().toLowerCase();
+ const locationFilter = selLocationFilter.value;
+
+ // Clear lane wrapper structures
+ colWishlist.innerHTML = "";
+ colApplied.innerHTML = "";
+ colInterviewing.innerHTML = "";
+ colOffer.innerHTML = "";
+ colRejected.innerHTML = "";
+
+ const filteredJobs = jobs.filter(job => {
+ // 1. Search Query Match
+ const matchesSearch =
+ job.company.toLowerCase().includes(searchQuery) ||
+ job.role.toLowerCase().includes(searchQuery) ||
+ job.notes.toLowerCase().includes(searchQuery);
+
+ // 2. Location Filter Match
+ const matchesLocation = locationFilter === "All" || job.location === locationFilter;
+
+ return matchesSearch && matchesLocation;
+ });
+
+ filteredJobs.forEach(job => {
+ const card = createJobCard(job);
+
+ // Dispatch to matching lane wrapper
+ switch (job.status) {
+ case "Wishlist":
+ colWishlist.appendChild(card);
+ break;
+ case "Applied":
+ colApplied.appendChild(card);
+ break;
+ case "Interviewing":
+ colInterviewing.appendChild(card);
+ break;
+ case "Offer":
+ colOffer.appendChild(card);
+ break;
+ case "Rejected":
+ colRejected.appendChild(card);
+ break;
+ }
+ });
+
+ // Display helpful message if a lane is empty and no jobs exist
+ const wrappers = [
+ { col: colWishlist, text: "No wishlist specs" },
+ { col: colApplied, text: "No applications submitted" },
+ { col: colInterviewing, text: "No active interviews" },
+ { col: colOffer, text: "No offers received yet" },
+ { col: colRejected, text: "No profiles logged here" }
+ ];
+
+ wrappers.forEach(w => {
+ if (w.col.children.length === 0) {
+ const emptyDiv = document.createElement("div");
+ emptyDiv.className = "empty-lane-placeholder";
+ emptyDiv.style.textAlign = "center";
+ emptyDiv.style.padding = "1.5rem 0.5rem";
+ emptyDiv.style.color = "var(--text-muted)";
+ emptyDiv.style.fontSize = "0.75rem";
+ emptyDiv.style.border = "1px dashed rgba(255, 255, 255, 0.02)";
+ emptyDiv.style.borderRadius = "var(--border-radius-sm)";
+ emptyDiv.textContent = w.text;
+ w.col.appendChild(emptyDiv);
+ }
+ });
+}
+
+// CREATE CARD COMPONENT
+function createJobCard(job) {
+ const card = document.createElement("div");
+ card.className = "job-card";
+ if (job.id === activeJobId) {
+ card.classList.add("active-card");
+ }
+
+ // Calculate Subtask Checklist percentage
+ const totalTasks = job.tasks ? job.tasks.length : 0;
+ const completedTasks = job.tasks ? job.tasks.filter(t => t.completed).length : 0;
+ const pct = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0;
+
+ card.innerHTML = `
+ ${escapeHtml(job.company)}
+ ${escapeHtml(job.role)}
+
+ ${job.salary ? formatSalaryShort(job.salary) : "$--"}
+ ${job.location}
+
+
+
+
+ Milestones
+ ${completedTasks}/${totalTasks} (${pct}%)
+
+
+
+
+
+
+ Move
+
+
+ `;
+
+ // Handle Card Click to inspect details
+ card.addEventListener("click", () => {
+ selectJob(job.id);
+ });
+
+ // Shift logic left/right
+ const btnLeft = card.querySelector(".btn-shift-left");
+ const btnRight = card.querySelector(".btn-shift-right");
+
+ const currentIndex = LANES.indexOf(job.status);
+
+ if (currentIndex === 0) {
+ btnLeft.classList.add("disabled");
+ }
+ if (currentIndex === LANES.length - 1) {
+ btnRight.classList.add("disabled");
+ }
+
+ btnLeft.addEventListener("click", (e) => {
+ e.stopPropagation(); // Prevent inspecting card on shift click
+ shiftJobLane(job.id, -1);
+ });
+
+ btnRight.addEventListener("click", (e) => {
+ e.stopPropagation(); // Prevent inspecting card on shift click
+ shiftJobLane(job.id, 1);
+ });
+
+ return card;
+}
+
+// Format salary to simple K notation e.g. $145K
+function formatSalaryShort(salary) {
+ const num = Number(salary);
+ if (!num || num <= 0) return "$0";
+ return num >= 1000 ? `$${Math.round(num / 1000)}k` : `$${num}`;
+}
+
+// SHIFT CARD STATUS LANE
+function shiftJobLane(jobId, direction) {
+ const job = jobs.find(j => j.id === jobId);
+ if (!job) return;
+
+ const currentIndex = LANES.indexOf(job.status);
+ const newIndex = currentIndex + direction;
+
+ if (newIndex >= 0 && newIndex < LANES.length) {
+ job.status = LANES[newIndex];
+ saveToStorage();
+
+ // Update active inspector dropdown status sync if inspecting this job
+ if (activeJobId === jobId) {
+ selStatus.value = job.status;
+ }
+ }
+}
+
+// SELECT A JOB TO SHOW IN THE INSPECTOR
+function selectJob(jobId) {
+ activeJobId = jobId;
+ const job = jobs.find(j => j.id === jobId);
+ if (!job) {
+ deselectJob();
+ return;
+ }
+
+ // Visual classes highlight updates
+ document.querySelectorAll(".job-card").forEach(c => c.classList.remove("active-card"));
+
+ // Fill form controls with details
+ jobCompany.value = job.company;
+ jobRole.value = job.role;
+ jobDate.value = job.dateApplied || "";
+ selStatus.value = job.status;
+ jobSalary.value = job.salary || "";
+ selLocation.value = job.location || "Remote";
+ jobUrl.value = job.url || "";
+ jobNotes.value = job.notes || "";
+
+ // Render subtasks checklist
+ renderTasksChecklist(job);
+
+ // Toggle visible containers
+ inspectorEmpty.classList.add("hidden");
+ inspectorActive.classList.remove("hidden");
+
+ // Rerender cards to update active styling outline
+ renderKanban();
+}
+
+// DESELECT INSPECTED CARD
+function deselectJob() {
+ activeJobId = null;
+ inspectorActive.classList.add("hidden");
+ inspectorEmpty.classList.remove("hidden");
+ renderKanban();
+}
+
+// SAVE CHANGES IN ACTIVE INSPECTOR PANEL
+function saveActiveJobChanges() {
+ if (!activeJobId) return;
+
+ const job = jobs.find(j => j.id === activeJobId);
+ if (!job) return;
+
+ // Validate basic inputs
+ if (!jobCompany.value.trim() || !jobRole.value.trim()) {
+ alert("Please fill in both the Company and Role Title fields.");
+ return;
+ }
+
+ job.company = jobCompany.value.trim();
+ job.role = jobRole.value.trim();
+ job.dateApplied = jobDate.value;
+ job.status = selStatus.value;
+ job.salary = jobSalary.value ? Number(jobSalary.value) : null;
+ job.location = selLocation.value;
+ job.url = jobUrl.value.trim();
+ job.notes = jobNotes.value.trim();
+
+ saveToStorage();
+}
+
+// DELETE ACTIVE JOB PROFILE
+function deleteActiveJob() {
+ if (!activeJobId) return;
+
+ const job = jobs.find(j => j.id === activeJobId);
+ if (!job) return;
+
+ if (confirm(`Are you sure you want to delete the job profile for ${job.company} - ${job.role}?`)) {
+ jobs = jobs.filter(j => j.id !== activeJobId);
+ saveToStorage();
+ deselectJob();
+ }
+}
+
+// ADD NEW BLANK JOB PROFILE
+function addNewJobSpec() {
+ const newJob = {
+ id: "job-" + Date.now().toString(),
+ company: "New Company Spec",
+ role: "Software Engineer",
+ status: "Wishlist",
+ dateApplied: new Date().toISOString().split("T")[0],
+ salary: 100000,
+ location: "Remote",
+ url: "",
+ notes: "",
+ tasks: [
+ { id: "task-" + Date.now() + "-1", text: "Polish portfolio and profile spec", completed: false },
+ { id: "task-" + Date.now() + "-2", text: "Customize resume for role description", completed: false },
+ { id: "task-" + Date.now() + "-3", text: "Locate referral opportunities", completed: false }
+ ]
+ };
+
+ jobs.unshift(newJob);
+ saveToStorage();
+ selectJob(newJob.id);
+}
+
+// RENDER CHECKLIST TASKS
+function renderTasksChecklist(job) {
+ tasksChecklist.innerHTML = "";
+
+ if (!job.tasks || job.tasks.length === 0) {
+ tasksChecklist.innerHTML = `No milestones created yet.`;
+ return;
+ }
+
+ job.tasks.forEach(task => {
+ const li = document.createElement("li");
+ li.className = `task-item ${task.completed ? "completed" : ""}`;
+
+ li.innerHTML = `
+
+
+ ${escapeHtml(task.text)}
+
+
+ `;
+
+ // Toggle complete
+ li.querySelector("input").addEventListener("change", () => {
+ task.completed = !task.completed;
+ saveToStorage();
+ });
+
+ li.querySelector(".task-left").addEventListener("click", (e) => {
+ // Toggle completed when clicking details span
+ if (e.target.tagName !== "INPUT") {
+ task.completed = !task.completed;
+ saveToStorage();
+ }
+ });
+
+ // Delete task milestone
+ li.querySelector(".btn-delete-task").addEventListener("click", (e) => {
+ e.stopPropagation();
+ job.tasks = job.tasks.filter(t => t.id !== task.id);
+ saveToStorage();
+ });
+
+ tasksChecklist.appendChild(li);
+ });
+}
+
+// ADD NEW CUSTOM TASK
+function handleAddTaskSubmit() {
+ if (!activeJobId) return;
+
+ const job = jobs.find(j => j.id === activeJobId);
+ if (!job) return;
+
+ const taskText = txtNewTask.value.trim();
+ if (!taskText) return;
+
+ if (!job.tasks) {
+ job.tasks = [];
+ }
+
+ const newTask = {
+ id: "task-" + Date.now() + "-" + Math.random().toString(36).substr(2, 4),
+ text: taskText,
+ completed: false
+ };
+
+ job.tasks.push(newTask);
+ txtNewTask.value = "";
+ saveToStorage();
+}
+
+// RESET WORKSPACE MEMORY
+function resetWorkspace() {
+ if (confirm("Are you absolutely sure you want to reset all jobs data? This will restore the default sandbox specs.")) {
+ jobs = [...SEED_JOBS];
+ saveToStorage();
+ deselectJob();
+ }
+}
+
+// ESCAPE HTML TO PREVENT XSS IN USER GENERATED STRINGS
+function escapeHtml(str) {
+ if (!str) return "";
+ return str
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'");
+}
diff --git a/Projects/Job Application Tracker Pro/style.css b/Projects/Job Application Tracker Pro/style.css
new file mode 100644
index 00000000..161a69c6
--- /dev/null
+++ b/Projects/Job Application Tracker Pro/style.css
@@ -0,0 +1,892 @@
+/* Job Application Tracker Pro - Styling */
+
+:root {
+ --bg-main: #090d16;
+ --bg-card: #111827;
+ --bg-card-hover: #1f2937;
+ --border-color: #374151;
+ --text-main: #f3f4f6;
+ --text-muted: #9ca3af;
+ --text-highlight: #ffffff;
+
+ /* Status Color Palette */
+ --color-wishlist: #6366f1;
+ --color-wishlist-glow: rgba(99, 102, 241, 0.15);
+
+ --color-applied: #0ea5e9;
+ --color-applied-glow: rgba(14, 165, 233, 0.15);
+
+ --color-interviewing: #f59e0b;
+ --color-interviewing-glow: rgba(245, 158, 11, 0.15);
+
+ --color-offer: #10b981;
+ --color-offer-glow: rgba(16, 185, 129, 0.15);
+
+ --color-rejected: #ef4444;
+ --color-rejected-glow: rgba(239, 68, 68, 0.15);
+
+ --font-headers: 'Outfit', sans-serif;
+ --font-body: 'Inter', sans-serif;
+
+ --transition-speed: 0.25s;
+ --border-radius-sm: 8px;
+ --border-radius-md: 12px;
+ --border-radius-lg: 16px;
+ --glow-shadow: 0 0 20px rgba(14, 165, 233, 0.2);
+}
+
+/* GENERAL STYLES */
+* {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+body {
+ background-color: var(--bg-main);
+ color: var(--text-main);
+ font-family: var(--font-body);
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ position: relative;
+ overflow-x: hidden;
+ line-height: 1.5;
+}
+
+/* GLOW BACKGROUND */
+.glow-bg {
+ position: absolute;
+ top: -150px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 800px;
+ height: 400px;
+ background: radial-gradient(circle, rgba(99, 102, 241, 0.12) 0%, rgba(14, 165, 233, 0.05) 50%, rgba(9, 13, 22, 0) 100%);
+ filter: blur(80px);
+ z-index: -1;
+ pointer-events: none;
+}
+
+/* SCROLLBARS */
+::-webkit-scrollbar {
+ width: 6px;
+ height: 6px;
+}
+
+::-webkit-scrollbar-track {
+ background: rgba(0, 0, 0, 0.1);
+ border-radius: 4px;
+}
+
+::-webkit-scrollbar-thumb {
+ background: var(--border-color);
+ border-radius: 4px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: var(--text-muted);
+}
+
+/* HEADER styling */
+.app-header {
+ background: rgba(17, 24, 39, 0.7);
+ backdrop-filter: blur(12px);
+ border-bottom: 1px solid var(--border-color);
+ padding: 1rem 2rem;
+ position: sticky;
+ top: 0;
+ z-index: 100;
+}
+
+.header-container {
+ max-width: 1600px;
+ margin: 0 auto;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 1rem;
+}
+
+.logo {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+}
+
+.logo h1 {
+ font-family: var(--font-headers);
+ font-size: 1.75rem;
+ font-weight: 800;
+ letter-spacing: -0.5px;
+ background: linear-gradient(135deg, #ffffff 30%, var(--color-applied) 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.logo h1 span {
+ font-weight: 400;
+ color: var(--text-muted);
+ -webkit-text-fill-color: var(--text-muted);
+}
+
+.glow-icon {
+ font-size: 1.5rem;
+ color: var(--color-applied);
+ text-shadow: 0 0 10px rgba(14, 165, 233, 0.5);
+ animation: pulse 3s infinite alternate;
+}
+
+.logo .badge {
+ font-size: 0.75rem;
+ font-weight: 600;
+ padding: 0.25rem 0.6rem;
+ background: rgba(31, 41, 55, 0.6);
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius-sm);
+ color: var(--text-muted);
+ text-transform: uppercase;
+ letter-spacing: 1px;
+}
+
+.header-stats {
+ display: flex;
+ gap: 1rem;
+}
+
+.stat-badge {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.4rem 0.8rem;
+ background: rgba(17, 24, 39, 0.9);
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius-sm);
+ font-size: 0.85rem;
+ color: var(--text-muted);
+ font-weight: 500;
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
+ transition: border-color var(--transition-speed);
+}
+
+.stat-badge:hover {
+ border-color: rgba(255, 255, 255, 0.15);
+}
+
+.stat-badge strong {
+ color: var(--text-highlight);
+ font-size: 1rem;
+}
+
+.text-azure { color: var(--color-applied); }
+.text-amber { color: var(--color-interviewing); }
+.text-emerald { color: var(--color-offer); }
+
+/* MAIN CONTAINER LAYOUT */
+.main-container {
+ display: grid;
+ grid-template-columns: 280px 1fr 340px;
+ gap: 1.5rem;
+ max-width: 1600px;
+ width: 100%;
+ margin: 0 auto;
+ padding: 1.5rem 2rem;
+ flex: 1;
+}
+
+/* SECTION CARDS STYLING */
+.section-card {
+ background: var(--bg-card);
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius-md);
+ padding: 1.25rem;
+ margin-bottom: 1.25rem;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ transition: transform var(--transition-speed), border-color var(--transition-speed);
+}
+
+.section-card:hover {
+ border-color: rgba(255, 255, 255, 0.08);
+}
+
+.card-header-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 1rem;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
+ padding-bottom: 0.5rem;
+}
+
+.card-header-row h3 {
+ font-family: var(--font-headers);
+ font-size: 1.1rem;
+ font-weight: 600;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ color: var(--text-highlight);
+}
+
+/* FORM CONTROLS */
+.form-group {
+ margin-bottom: 1rem;
+}
+
+.form-group label {
+ display: block;
+ font-size: 0.8rem;
+ font-weight: 500;
+ text-transform: uppercase;
+ color: var(--text-muted);
+ margin-bottom: 0.4rem;
+ letter-spacing: 0.5px;
+}
+
+input[type="text"],
+input[type="number"],
+input[type="date"],
+select,
+textarea {
+ width: 100%;
+ padding: 0.65rem 0.9rem;
+ background-color: rgba(9, 13, 22, 0.6);
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius-sm);
+ color: var(--text-main);
+ font-family: var(--font-body);
+ font-size: 0.9rem;
+ transition: border-color var(--transition-speed), box-shadow var(--transition-speed);
+}
+
+input[type="text"]:focus,
+input[type="number"]:focus,
+input[type="date"]:focus,
+select:focus,
+textarea:focus {
+ outline: none;
+ border-color: var(--color-applied);
+ box-shadow: 0 0 0 2px rgba(14, 165, 233, 0.2);
+}
+
+textarea {
+ min-height: 100px;
+ resize: vertical;
+}
+
+.form-row {
+ display: flex;
+ gap: 1rem;
+}
+
+.flex-1 {
+ flex: 1;
+}
+
+/* BUTTONS */
+.btn {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.5rem;
+ padding: 0.65rem 1.25rem;
+ border-radius: var(--border-radius-sm);
+ font-family: var(--font-body);
+ font-weight: 600;
+ font-size: 0.9rem;
+ cursor: pointer;
+ transition: all var(--transition-speed);
+ border: 1px solid transparent;
+}
+
+.btn-sm {
+ padding: 0.45rem 0.9rem;
+ font-size: 0.8rem;
+}
+
+.btn-primary {
+ background: linear-gradient(135deg, var(--color-applied) 0%, #0284c7 100%);
+ color: white;
+ box-shadow: var(--glow-shadow);
+}
+
+.btn-primary:hover {
+ transform: translateY(-1px);
+ filter: brightness(1.1);
+ box-shadow: 0 0 25px rgba(14, 165, 233, 0.35);
+}
+
+.btn-secondary {
+ background: rgba(31, 41, 55, 0.8);
+ border-color: var(--border-color);
+ color: var(--text-main);
+}
+
+.btn-secondary:hover {
+ background: rgba(55, 65, 81, 0.8);
+ border-color: var(--text-muted);
+}
+
+.btn-danger {
+ background: linear-gradient(135deg, var(--color-rejected) 0%, #dc2626 100%);
+ color: white;
+}
+
+.btn-danger:hover {
+ transform: translateY(-1px);
+ filter: brightness(1.1);
+ box-shadow: 0 0 15px rgba(239, 68, 68, 0.3);
+}
+
+/* LEFT SIDEBAR (SEARCH, FILTERS, ANALYTICS) */
+.sidebar-column {
+ display: flex;
+ flex-direction: column;
+}
+
+.search-input-wrapper {
+ position: relative;
+}
+
+.search-input-wrapper i {
+ position: absolute;
+ left: 0.9rem;
+ top: 50%;
+ transform: translateY(-50%);
+ color: var(--text-muted);
+}
+
+.search-input-wrapper input {
+ padding-left: 2.2rem;
+}
+
+.highlights-grid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 0.75rem;
+}
+
+.highlight-item {
+ background: rgba(9, 13, 22, 0.5);
+ border: 1px solid rgba(255, 255, 255, 0.03);
+ padding: 0.75rem;
+ border-radius: var(--border-radius-sm);
+ display: flex;
+ flex-direction: column;
+ gap: 0.25rem;
+}
+
+.col-span-2 {
+ grid-column: span 2;
+}
+
+.h-lbl {
+ font-size: 0.75rem;
+ color: var(--text-muted);
+ font-weight: 500;
+ text-transform: uppercase;
+}
+
+.h-val {
+ font-family: var(--font-headers);
+ font-size: 1.25rem;
+ font-weight: 700;
+}
+
+.text-cyan {
+ color: #22d3ee;
+}
+
+.footer-btn {
+ background: transparent;
+ border: 1px dashed var(--border-color);
+ color: var(--text-muted);
+ padding: 0.75rem;
+ border-radius: var(--border-radius-sm);
+ cursor: pointer;
+ transition: all var(--transition-speed);
+ font-family: var(--font-body);
+ font-size: 0.85rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.5rem;
+ width: 100%;
+}
+
+.footer-btn:hover {
+ border-color: var(--color-rejected);
+ color: var(--color-rejected);
+ background: rgba(239, 68, 68, 0.05);
+}
+
+/* CENTER KANBAN COLUMN */
+.kanban-column {
+ display: flex;
+ flex-direction: column;
+}
+
+.kanban-actions-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 1rem;
+}
+
+.kanban-actions-row h2 {
+ font-family: var(--font-headers);
+ font-size: 1.35rem;
+ font-weight: 700;
+ color: var(--text-highlight);
+}
+
+.kanban-board-grid {
+ display: grid;
+ grid-template-columns: repeat(5, 1fr);
+ gap: 0.75rem;
+ flex: 1;
+ min-height: calc(100vh - 220px);
+ align-items: stretch;
+}
+
+.kanban-lane-col {
+ background: rgba(17, 24, 39, 0.4);
+ border: 1px solid rgba(255, 255, 255, 0.03);
+ border-radius: var(--border-radius-md);
+ display: flex;
+ flex-direction: column;
+ padding: 0.5rem;
+ transition: border-color var(--transition-speed), background var(--transition-speed);
+}
+
+.kanban-lane-col:hover {
+ border-color: rgba(255, 255, 255, 0.05);
+ background: rgba(17, 24, 39, 0.5);
+}
+
+.lane-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0.6rem 0.75rem;
+ border-radius: var(--border-radius-sm);
+ margin-bottom: 0.75rem;
+ font-family: var(--font-headers);
+ font-weight: 700;
+ font-size: 0.9rem;
+}
+
+.lane-count {
+ font-size: 0.75rem;
+ font-weight: 600;
+ background: rgba(0, 0, 0, 0.3);
+ padding: 0.1rem 0.5rem;
+ border-radius: 20px;
+ color: var(--text-highlight);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+.wishlist-header {
+ background: var(--color-wishlist-glow);
+ color: #a5b4fc;
+ border-left: 4px solid var(--color-wishlist);
+}
+.applied-header {
+ background: var(--color-applied-glow);
+ color: #7dd3fc;
+ border-left: 4px solid var(--color-applied);
+}
+.interviewing-header {
+ background: var(--color-interviewing-glow);
+ color: #fde047;
+ border-left: 4px solid var(--color-interviewing);
+}
+.offer-header {
+ background: var(--color-offer-glow);
+ color: #6ee7b7;
+ border-left: 4px solid var(--color-offer);
+}
+.rejected-header {
+ background: var(--color-rejected-glow);
+ color: #fca5a5;
+ border-left: 4px solid var(--color-rejected);
+}
+
+.lane-cards-wrapper {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 0.6rem;
+ min-height: 200px;
+ overflow-y: auto;
+ padding-bottom: 1rem;
+}
+
+/* JOB CARDS IN KANBAN */
+.job-card {
+ background: var(--bg-card);
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius-sm);
+ padding: 0.75rem;
+ cursor: pointer;
+ transition: all var(--transition-speed);
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ gap: 0.4rem;
+ user-select: none;
+}
+
+.job-card:hover {
+ transform: translateY(-2px);
+ border-color: var(--text-muted);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
+}
+
+.job-card.active-card {
+ border-color: var(--color-applied);
+ background: rgba(31, 41, 55, 0.5);
+ box-shadow: 0 0 10px rgba(14, 165, 233, 0.15);
+}
+
+.job-card .card-company {
+ font-size: 0.75rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ color: var(--text-muted);
+ letter-spacing: 0.5px;
+}
+
+.job-card .card-role {
+ font-family: var(--font-headers);
+ font-size: 0.9rem;
+ font-weight: 600;
+ color: var(--text-highlight);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.job-card .card-meta {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ font-size: 0.75rem;
+ margin-top: 0.25rem;
+}
+
+.job-card .card-salary {
+ font-weight: 600;
+ color: #e5e7eb;
+}
+
+.job-card .card-loc-badge {
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ padding: 0.1rem 0.4rem;
+ border-radius: 4px;
+ font-size: 0.7rem;
+ color: var(--text-muted);
+}
+
+/* Card Progress bar */
+.card-progress-wrapper {
+ margin-top: 0.35rem;
+}
+.card-progress-text {
+ font-size: 0.7rem;
+ color: var(--text-muted);
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 0.15rem;
+}
+.card-progress-bar {
+ height: 3px;
+ background: rgba(255, 255, 255, 0.08);
+ border-radius: 2px;
+ overflow: hidden;
+}
+.card-progress-fill {
+ height: 100%;
+ width: 0%;
+ background: var(--color-applied);
+ border-radius: 2px;
+ transition: width var(--transition-speed);
+}
+
+/* Card Quick Movement Controls */
+.card-quick-actions {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-top: 0.5rem;
+ padding-top: 0.5rem;
+ border-top: 1px solid rgba(255, 255, 255, 0.03);
+}
+
+.card-quick-btn {
+ background: transparent;
+ border: none;
+ color: var(--text-muted);
+ cursor: pointer;
+ font-size: 0.8rem;
+ padding: 0.2rem 0.4rem;
+ border-radius: 4px;
+ transition: all var(--transition-speed);
+}
+
+.card-quick-btn:hover {
+ color: var(--text-highlight);
+ background: rgba(255, 255, 255, 0.08);
+}
+
+.card-quick-btn.disabled {
+ opacity: 0.2;
+ cursor: not-allowed;
+ pointer-events: none;
+}
+
+/* RIGHT INSPECTOR COLUMN */
+.inspector-column {
+ display: flex;
+ flex-direction: column;
+}
+
+.inspector-welcome-card {
+ background: var(--bg-card);
+ border: 1px dashed var(--border-color);
+ border-radius: var(--border-radius-md);
+ padding: 2.5rem 1.5rem;
+ text-align: center;
+ color: var(--text-muted);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 1rem;
+ min-height: 400px;
+}
+
+.pulse-icon {
+ font-size: 2.5rem;
+ color: rgba(255, 255, 255, 0.15);
+ animation: float 4s infinite ease-in-out;
+}
+
+.inspector-welcome-card h4 {
+ font-family: var(--font-headers);
+ color: var(--text-highlight);
+ font-size: 1.15rem;
+ font-weight: 600;
+}
+
+.inspector-welcome-card p {
+ font-size: 0.85rem;
+ line-height: 1.4;
+}
+
+.inspector-workspace {
+ animation: fadeIn var(--transition-speed) ease;
+}
+
+.hidden {
+ display: none !important;
+}
+
+/* Tasks Checklist inside Inspector */
+.tasks-checklist-section {
+ margin: 1.25rem 0;
+ padding: 1rem;
+ background: rgba(9, 13, 22, 0.4);
+ border: 1px solid rgba(255, 255, 255, 0.03);
+ border-radius: var(--border-radius-sm);
+}
+
+.tasks-checklist-section h5 {
+ font-family: var(--font-headers);
+ font-size: 0.85rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ color: var(--text-muted);
+ margin-bottom: 0.75rem;
+ letter-spacing: 0.5px;
+}
+
+.tasks-ul {
+ list-style: none;
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ margin-bottom: 0.75rem;
+ max-height: 160px;
+ overflow-y: auto;
+}
+
+.task-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 0.5rem;
+ padding: 0.4rem 0.5rem;
+ border-radius: 4px;
+ background: rgba(17, 24, 39, 0.6);
+ border: 1px solid rgba(255, 255, 255, 0.02);
+ transition: all var(--transition-speed);
+}
+
+.task-item:hover {
+ background: rgba(17, 24, 39, 0.9);
+}
+
+.task-left {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ flex: 1;
+ cursor: pointer;
+}
+
+.task-left input[type="checkbox"] {
+ accent-color: var(--color-applied);
+ cursor: pointer;
+ width: 15px;
+ height: 15px;
+}
+
+.task-text {
+ font-size: 0.85rem;
+ transition: color var(--transition-speed);
+ word-break: break-word;
+}
+
+.task-item.completed .task-text {
+ text-decoration: line-through;
+ color: var(--text-muted);
+}
+
+.btn-delete-task {
+ background: transparent;
+ border: none;
+ color: var(--text-muted);
+ cursor: pointer;
+ font-size: 0.8rem;
+ padding: 0.2rem;
+ transition: color var(--transition-speed);
+}
+
+.btn-delete-task:hover {
+ color: var(--color-rejected);
+}
+
+.add-task-row {
+ display: flex;
+ gap: 0.5rem;
+}
+
+.add-task-row input {
+ padding: 0.45rem 0.75rem;
+ font-size: 0.8rem;
+}
+
+.add-task-row button {
+ padding: 0.45rem;
+ width: 35px;
+ height: 35px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+/* Inspector Action buttons wrapper */
+.inspector-actions {
+ display: flex;
+ justify-content: space-between;
+ gap: 1rem;
+ margin-top: 1.5rem;
+ padding-top: 1rem;
+ border-top: 1px solid rgba(255, 255, 255, 0.05);
+}
+
+.inspector-actions .btn {
+ flex: 1;
+}
+
+/* FOOTER */
+.app-footer {
+ border-top: 1px solid var(--border-color);
+ padding: 1.5rem 2rem;
+ text-align: center;
+ background-color: rgba(9, 13, 22, 0.8);
+ font-size: 0.85rem;
+ color: var(--text-muted);
+ margin-top: auto;
+}
+
+.footer-container a {
+ color: var(--color-applied);
+ text-decoration: none;
+ transition: color var(--transition-speed);
+}
+
+.footer-container a:hover {
+ color: #38bdf8;
+ text-decoration: underline;
+}
+
+/* ANIMATIONS */
+@keyframes pulse {
+ 0% { text-shadow: 0 0 8px rgba(14, 165, 233, 0.3); }
+ 100% { text-shadow: 0 0 16px rgba(14, 165, 233, 0.7); }
+}
+
+@keyframes float {
+ 0% { transform: translateY(0px); }
+ 50% { transform: translateY(-8px); }
+ 100% { transform: translateY(0px); }
+}
+
+@keyframes fadeIn {
+ from { opacity: 0; transform: translateY(5px); }
+ to { opacity: 1; transform: translateY(0); }
+}
+
+/* RESPONSIVE LAYOUT BREAKPOINTS */
+@media (max-width: 1200px) {
+ .main-container {
+ grid-template-columns: 260px 1fr;
+ }
+ .inspector-column {
+ grid-column: span 2;
+ }
+ .inspector-welcome-card {
+ min-height: 200px;
+ padding: 1.5rem;
+ }
+}
+
+@media (max-width: 900px) {
+ .main-container {
+ grid-template-columns: 1fr;
+ padding: 1rem;
+ }
+ .sidebar-column, .kanban-column, .inspector-column {
+ grid-column: span 1;
+ }
+ .kanban-board-grid {
+ grid-template-columns: 1fr;
+ gap: 1rem;
+ min-height: auto;
+ }
+ .kanban-lane-col {
+ min-height: 180px;
+ }
+ .header-container {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+ .header-stats {
+ width: 100%;
+ justify-content: space-between;
+ }
+}
diff --git a/Projects/Job Application Tracker Pro/thumbnail.svg b/Projects/Job Application Tracker Pro/thumbnail.svg
new file mode 100644
index 00000000..48d88abb
--- /dev/null
+++ b/Projects/Job Application Tracker Pro/thumbnail.svg
@@ -0,0 +1,162 @@
+