From 6f43bf261e203054c1b562ddc6acb074e18ae382 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 15:40:06 +0000 Subject: [PATCH 1/2] Initial plan From ff813e0085d58418e9c41e5323aa840d1d031a78 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 15:49:18 +0000 Subject: [PATCH 2/2] Separate index.html into HTML, CSS, and JavaScript files Co-authored-by: CodingMango <170359605+CodingMango@users.noreply.github.com> --- index.html | 1446 ++++++++++++++++------------------------------------ script.js | 500 ++++++++++++++++++ style.css | 57 +++ 3 files changed, 1005 insertions(+), 998 deletions(-) create mode 100644 script.js create mode 100644 style.css diff --git a/index.html b/index.html index 6bd7a36..7def02b 100644 --- a/index.html +++ b/index.html @@ -1,998 +1,448 @@ - - - - - - Abdul Jabbar Khan | Academic Portfolio - - - - - - - - - - - - -
- - -
-

- Abdul Jabbar Khan -

-

- Undergraduate Researcher & Engineer
- B.Tech Electronics & Communication Engineering -

-

- RGUKT Nuzvid (Expected 2028). Passionate about hardware-software interfacing, mathematical modelling, and low-level system design. Looking for opportunities to contribute to rigorous academic research and advanced engineering projects. -

- - -
- +91-7981994719 -
-
-
- -
-
-
-

Core Competencies & Coursework

-
-

A foundational overview of my academic subjects and technical proficiencies, establishing the baseline of my engineering toolkit.

-
- -
-
-

- Key Academic Subjects -

-
- Engineering Mathematics - Engineering Physics - Data Structures (C) - OOP (C++) - Electronic Devices & Circuits - Signals and Systems -
-
- -
-

- Technical Arsenal -

-
- C - C++ - Python - VPython - Vivado - Git/GitHub - Hardware Interfacing -
-
-
-
-
- -
-
-

Academic Trajectory

-
-

- This section details my formal educational background. The accompanying visualization demonstrates a consistent record of high academic achievement from secondary education through my current undergraduate studies. -

-
- -
-
- -
-
- -
-
-
-

B.Tech ECE

- Exp. 2028 -
-

RGUKT - Nuzvid

-
-

CGPA: 8.71 / 10.0 (3 semesters)

-
-
-
- -
-
- -
-
-
-

Pre-University (MPC)

- 2022 - 2024 -
-

RGUKT - Nuzvid

-
-

CGPA: 9.79 / 10.0

-
-
-
- -
-
- -
-
-
-

SSC

- 2021 - 2022 -
-

MPL HS BOYS - Paradesampeta

-
-

Percentage: 96.5%

-
-
-
- -
- -
-

Performance Consistency

-
- -
-
-
-
- -
-
-
-

Independent Projects & Research

-
-

- This section outlines practical applications of my theoretical knowledge. It highlights my ability to bridge hardware and software, manage low-level memory, and utilize object-oriented programming for complex mathematical and physical simulations. -

-
- -
- -
-
-
- -
-

3D Animation for Physics

-

Learn-VPython

-
    -
  • Engineered interactive Jupyter Notebooks using VPython to mathematically model and visualize 3D physical simulations.
  • -
  • Demonstrated deep proficiency in vector calculus, classical kinematics modelling, and OOP for scientific visualization.
  • -
-
-
-
- Python - VPython -
- - Repo - -
-
- -
-
-
- -
-

Cryptographic Morse Decoder

-

Hardware-Interfaced

-
    -
  • Designed hardware to intercept, decode, and translate hardware-generated (pushbutton) Morse code signals in real-time.
  • -
  • Demonstrated advanced capabilities in low-level memory management via C++.
  • -
-
-
-
- C++ - Hardware -
- - Repo - -
-
- -
-
-
- -
-

Morse Encoder

-

Hardware-Interfaced

-
    -
  • Complementary system to the decoder, designed to encode textual input into physical, hardware-transmitted Morse signals.
  • -
  • Further solidified understanding of C++ interfacing with physical electronic components.
  • -
-
-
-
- C++ - Hardware -
- - Repo - -
-
- -
-
-
- -
-
-

Scholastic Achievements

-
-

- Recognition of academic excellence through national-level scholarships and rigorous certification programs from premier institutions. -

-
- -
-
-
-
- -
-
-

NPTEL Silver Medalist (2025)

-

IISc Bangalore

-

Achieved a 79% in the "Mathematical Foundations for Machine Learning" certification. Demonstrated strong foundational knowledge in Linear Algebra, Probability, and Multivariable Calculus.

-
-
-
- -
-
-
- -
-
-

Reliance Foundation Undergraduate Scholar

-

2024

-

Awarded this highly competitive national merit-cum-means scholarship for exceptional academic performance and aptitude.

-
-
-
-
-
- -
-
-

Sports & Athletics

-

- Demonstrating discipline, teamwork, and resilience through competitive sports at the SGFI Yoga State Level Competition. -

-
-
-
- SGFI STATE TEAM -
-

SGFI STATE TEAM

-

Our SGFI Team for state-level Yoga competition.

-
-
- -
- NATIONAL SELECTED TEAM TEAM -
-

FINAL SELETED MEMBERS

-

Final selected members for National competition, SGFI Yoga.

-
-
- -
- -
- Swipe to explore -
-
- -
-
-
-

Positions of Responsibility

-
-

- Showcasing leadership and a commitment to community welfare. -

-
- -
-
-
-

State-Level Team Manager | SGFI Yoga

- 2024 -
-
    -
  • Managed state-level logistical operations, travel coordination, and tournament compliance for junior athletes.
  • -
  • Mentored team members on performance execution and resilience, coordinating directly with coaching staff to maintain a disciplined, supportive environment.
  • -
-
- -
-
-

Student Representative | Helping Hands NGO

- 2024 - Present -
-
    -
  • Spearheaded a campus-wide micro-donation initiative, delivering weekly motivational addresses to student cohorts to secure funding for economically disadvantaged peers.
  • -
  • Co-organised comprehensive health and welfare initiatives, successfully executing campus blood donation and specialised eye-care camps.
  • -
-
- -
-
-

Volunteer | National Service Scheme (NSS)

- 2023 - 2025 -
-
    -
  • Completed a rigorous two-year Government of India community service mandate.
  • -
  • Spearheaded large-scale environmental campus cleaning drives and executed the equitable distribution of essential educational supplies to student cohorts.
  • -
-
-
-
-
- -
-
- -

- "What I cannot create, I do not understand." -

-

- — Richard Feynman -

-

- Theoretical Physicist -

-
-
- - - - - - - - - - + + + + + + Abdul Jabbar Khan | Academic Portfolio + + + + + + + + + + +
+ + +
+

+ Abdul Jabbar Khan +

+

+ Undergraduate Researcher & Engineer
+ B.Tech Electronics & Communication Engineering +

+

+ RGUKT Nuzvid (Expected 2028). Passionate about hardware-software interfacing, mathematical modelling, and low-level system design. Looking for opportunities to contribute to rigorous academic research and advanced engineering projects. +

+ + +
+ +91-7981994719 +
+
+
+ +
+
+
+

Core Competencies & Coursework

+
+

A foundational overview of my academic subjects and technical proficiencies, establishing the baseline of my engineering toolkit.

+
+ +
+
+

+ Key Academic Subjects +

+
+ Engineering Mathematics + Engineering Physics + Data Structures (C) + OOP (C++) + Electronic Devices & Circuits + Signals and Systems +
+
+ +
+

+ Technical Arsenal +

+
+ C + C++ + Python + VPython + Vivado + Git/GitHub + Hardware Interfacing +
+
+
+
+
+ +
+
+

Academic Trajectory

+
+

+ This section details my formal educational background. The accompanying visualization demonstrates a consistent record of high academic achievement from secondary education through my current undergraduate studies. +

+
+ +
+
+ +
+
+ +
+
+
+

B.Tech ECE

+ Exp. 2028 +
+

RGUKT - Nuzvid

+
+

CGPA: 8.71 / 10.0 (3 semesters)

+
+
+
+ +
+
+ +
+
+
+

Pre-University (MPC)

+ 2022 - 2024 +
+

RGUKT - Nuzvid

+
+

CGPA: 9.79 / 10.0

+
+
+
+ +
+
+ +
+
+
+

SSC

+ 2021 - 2022 +
+

MPL HS BOYS - Paradesampeta

+
+

Percentage: 96.5%

+
+
+
+ +
+ +
+

Performance Consistency

+
+ +
+
+
+
+ +
+
+
+

Independent Projects & Research

+
+

+ This section outlines practical applications of my theoretical knowledge. It highlights my ability to bridge hardware and software, manage low-level memory, and utilize object-oriented programming for complex mathematical and physical simulations. +

+
+ +
+ +
+
+
+ +
+

3D Animation for Physics

+

Learn-VPython

+
    +
  • Engineered interactive Jupyter Notebooks using VPython to mathematically model and visualize 3D physical simulations.
  • +
  • Demonstrated deep proficiency in vector calculus, classical kinematics modelling, and OOP for scientific visualization.
  • +
+
+
+
+ Python + VPython +
+ + Repo + +
+
+ +
+
+
+ +
+

Cryptographic Morse Decoder

+

Hardware-Interfaced

+
    +
  • Designed hardware to intercept, decode, and translate hardware-generated (pushbutton) Morse code signals in real-time.
  • +
  • Demonstrated advanced capabilities in low-level memory management via C++.
  • +
+
+
+
+ C++ + Hardware +
+ + Repo + +
+
+ +
+
+
+ +
+

Morse Encoder

+

Hardware-Interfaced

+
    +
  • Complementary system to the decoder, designed to encode textual input into physical, hardware-transmitted Morse signals.
  • +
  • Further solidified understanding of C++ interfacing with physical electronic components.
  • +
+
+
+
+ C++ + Hardware +
+ + Repo + +
+
+ +
+
+
+ +
+
+

Scholastic Achievements

+
+

+ Recognition of academic excellence through national-level scholarships and rigorous certification programs from premier institutions. +

+
+ +
+
+
+
+ +
+
+

NPTEL Silver Medalist (2025)

+

IISc Bangalore

+

Achieved a 79% in the "Mathematical Foundations for Machine Learning" certification. Demonstrated strong foundational knowledge in Linear Algebra, Probability, and Multivariable Calculus.

+
+
+
+ +
+
+
+ +
+
+

Reliance Foundation Undergraduate Scholar

+

2024

+

Awarded this highly competitive national merit-cum-means scholarship for exceptional academic performance and aptitude.

+
+
+
+
+
+ +
+
+

Sports & Athletics

+

+ Demonstrating discipline, teamwork, and resilience through competitive sports at the SGFI Yoga State Level Competition. +

+
+
+
+ SGFI STATE TEAM +
+

SGFI STATE TEAM

+

Our SGFI Team for state-level Yoga competition.

+
+
+ +
+ NATIONAL SELECTED TEAM TEAM +
+

FINAL SELECTED MEMBERS

+

Final selected members for National competition, SGFI Yoga.

+
+
+ +
+ +
+ Swipe to explore +
+
+ +
+
+
+

Positions of Responsibility

+
+

+ Showcasing leadership and a commitment to community welfare. +

+
+ +
+
+
+

State-Level Team Manager | SGFI Yoga

+ 2024 +
+
    +
  • Managed state-level logistical operations, travel coordination, and tournament compliance for junior athletes.
  • +
  • Mentored team members on performance execution and resilience, coordinating directly with coaching staff to maintain a disciplined, supportive environment.
  • +
+
+ +
+
+

Student Representative | Helping Hands NGO

+ 2024 - Present +
+
    +
  • Spearheaded a campus-wide micro-donation initiative, delivering weekly motivational addresses to student cohorts to secure funding for economically disadvantaged peers.
  • +
  • Co-organised comprehensive health and welfare initiatives, successfully executing campus blood donation and specialised eye-care camps.
  • +
+
+ +
+
+

Volunteer | National Service Scheme (NSS)

+ 2023 - 2025 +
+
    +
  • Completed a rigorous two-year Government of India community service mandate.
  • +
  • Spearheaded large-scale environmental campus cleaning drives and executed the equitable distribution of essential educational supplies to student cohorts.
  • +
+
+
+
+
+ +
+
+ +

+ "What I cannot create, I do not understand." +

+

+ — Richard Feynman +

+

+ Theoretical Physicist +

+
+
+ + + + + + + + + diff --git a/script.js b/script.js new file mode 100644 index 0000000..dda6934 --- /dev/null +++ b/script.js @@ -0,0 +1,500 @@ +/* --------------------------------------------------- + Tailwind Configuration + --------------------------------------------------- */ +tailwind.config = { + darkMode: 'class', + theme: { + extend: { + colors: { + primary: { + 50: '#eff6ff', + 100: '#dbeafe', + 400: '#60a5fa', + 500: '#3b82f6', + 600: '#2563eb', + 700: '#1d4ed8', + 900: '#1e3a8a', + }, + darkbase: '#0f172a', // Deep slate for dark mode background + darkcard: '#1e293b', // Slightly lighter slate for cards + }, + fontFamily: { + sans: ['Inter', 'system-ui', 'sans-serif'], + serif: ['Merriweather', 'Georgia', 'serif'], + } + } + } +} + +/* --------------------------------------------------- + 1. Telegram-Style Dark Mode Toggle (View Transitions) + --------------------------------------------------- */ +function toggleDarkMode(event) { + const isDark = document.documentElement.classList.contains('dark'); + + const icons = [document.getElementById('theme-icon'), document.getElementById('mobile-theme-icon')]; + icons.forEach(icon => { + if(icon) { + icon.style.transition = 'transform 0.5s ease-in-out'; + icon.style.transform = isDark ? 'rotate(0deg)' : 'rotate(360deg)'; + } + }); + + if (!document.startViewTransition) { + applyTheme(!isDark); + return; + } + + let x = window.innerWidth / 2; + let y = window.innerHeight / 2; + + if (event) { + if (event.touches && event.touches.length > 0) { + x = event.touches[0].clientX; + y = event.touches[0].clientY; + } else if (event.clientX !== undefined) { + x = event.clientX; + y = event.clientY; + } + } + + const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y)); + + const transition = document.startViewTransition(() => { + applyTheme(!isDark); + }); + + transition.ready.then(() => { + const clipPath = [ + `circle(0px at ${x}px ${y}px)`, + `circle(${endRadius}px at ${x}px ${y}px)` + ]; + + document.documentElement.animate( + { clipPath: clipPath }, + { duration: 500, easing: 'ease-in-out', pseudoElement: '::view-transition-new(root)' } + ); + }); +} + +function applyTheme(makeDark) { + const themeIcon = document.getElementById('theme-icon'); + const mobileThemeIcon = document.getElementById('mobile-theme-icon'); + + if (makeDark) { + document.documentElement.classList.add('dark'); + if(themeIcon) { themeIcon.classList.remove('fa-moon'); themeIcon.classList.add('fa-sun'); } + if(mobileThemeIcon) { mobileThemeIcon.classList.remove('fa-moon'); mobileThemeIcon.classList.add('fa-sun'); } + } else { + document.documentElement.classList.remove('dark'); + if(themeIcon) { themeIcon.classList.remove('fa-sun'); themeIcon.classList.add('fa-moon'); } + if(mobileThemeIcon) { mobileThemeIcon.classList.remove('fa-sun'); mobileThemeIcon.classList.add('fa-moon'); } + } +} + +/* --------------------------------------------------- + 4. Lightbox Gallery Logic + --------------------------------------------------- */ +let lightbox, lightboxImg; + +function openLightbox(imageSrc) { + lightboxImg.src = imageSrc; + + // Remove hidden to put it in the DOM + lightbox.classList.remove('hidden'); + + // Lock the background page from scrolling + document.body.style.overflow = 'hidden'; + + // A tiny delay ensures the CSS transition triggers properly after removing 'hidden' + setTimeout(() => { + lightbox.classList.remove('opacity-0'); + lightboxImg.classList.remove('scale-95'); + lightboxImg.classList.add('scale-100'); + }, 10); +} + +function closeLightbox() { + // Trigger the fade out and scale down animation + lightbox.classList.add('opacity-0'); + lightboxImg.classList.remove('scale-100'); + lightboxImg.classList.add('scale-95'); + + // Restore background scrolling + document.body.style.overflow = ''; + + // Wait for the CSS transition to finish (300ms) before fully hiding it + setTimeout(() => { + lightbox.classList.add('hidden'); + lightboxImg.src = ''; // Clear source to prevent ghost flashes on next open + }, 300); +} + +/* --------------------------------------------------- + DOM-Dependent Initialization + --------------------------------------------------- */ +document.addEventListener('DOMContentLoaded', () => { + + /* --------------------------------------------------- + 2. Upgraded Wave & Satellite Animation Engine + --------------------------------------------------- */ + const canvas = document.getElementById('eceCanvas'); + const ctx = canvas.getContext('2d'); + + let waves = []; + let emPulses = []; + let satellites = []; + let ambientParticles = []; + + function resizeCanvas() { + canvas.width = canvas.parentElement.offsetWidth; + canvas.height = canvas.parentElement.offsetHeight; + } + window.addEventListener('resize', resizeCanvas); + resizeCanvas(); + + // New feature: Ambient Particles for visual goodness + class Particle { + constructor() { + this.x = Math.random() * canvas.width; + this.y = Math.random() * canvas.height; + this.size = Math.random() * 2 + 0.5; + this.speedX = (Math.random() - 0.5) * 0.5; + this.speedY = (Math.random() - 0.5) * 0.5; + this.opacity = Math.random() * 0.5; + } + update() { + this.x += this.speedX; + this.y += this.speedY; + if (this.x < 0 || this.x > canvas.width) this.speedX *= -1; + if (this.y < 0 || this.y > canvas.height) this.speedY *= -1; + } + draw(ctx) { + const isDark = document.documentElement.classList.contains('dark'); + ctx.beginPath(); + ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); + ctx.fillStyle = isDark ? `rgba(96, 165, 250, ${this.opacity})` : `rgba(59, 130, 246, ${this.opacity})`; + ctx.fill(); + } + } + + // 1. Radar-Style Carrier Waves (Bold & High Contrast) + class Wave { + constructor() { this.reset(); } + reset() { + this.r = 68; + this.x = canvas.width / 2; + this.y = canvas.height / 2; + this.speed = 0.3 + Math.random() * 0.4; // Speed cut in half + this.maxR = Math.max(canvas.width, canvas.height); + } + update() { + this.r += this.speed; + if (this.r > this.maxR) this.reset(); + } + draw(ctx) { + const isDark = document.documentElement.classList.contains('dark'); + let opacity = Math.max(0, 1 - Math.pow(this.r / this.maxR, 2)); + + ctx.beginPath(); + ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2); + + // Softer base colors + ctx.strokeStyle = isDark ? `rgba(244, 209, 96, ${opacity * 0.6})` : `rgba(0, 79, 159, ${opacity * 0.4})`; + ctx.lineWidth = isDark ? 2.5 : 2.0; + + // Wider spacing on dashes + ctx.setLineDash([15, 40]); + ctx.lineDashOffset = -this.r * 0.2; + + if (isDark) { + ctx.shadowBlur = 5; // Reduced glow + ctx.shadowColor = `rgba(244, 209, 96, ${opacity * 0.5})`; + } + + ctx.stroke(); + ctx.setLineDash([]); + ctx.shadowBlur = 0; + } + } + + class EMPulse { + constructor() { this.reset(); } + reset() { + this.angle = Math.random() * Math.PI * 2; + this.radius = 40; + this.speed = 1.5 + Math.random() * 1.5; + this.amplitude = 8 + Math.random() * 5; + this.frequency = 0.08; + this.length = 150 + Math.random() * 100; + this.phase = Math.random() * Math.PI * 2; + this.maxRadius = Math.max(canvas.width, canvas.height) * 1.5; + } + update() { + this.radius += this.speed; + this.phase -= 0.15; + if (this.radius - this.length > this.maxRadius) this.reset(); + } + draw(ctx, cx, cy) { + const isDark = document.documentElement.classList.contains('dark'); + let opacity = Math.max(0, 1 - (this.radius / this.maxRadius)); + if (opacity <= 0) return; + + ctx.beginPath(); + ctx.strokeStyle = isDark ? `rgba(167, 139, 250, ${opacity * 0.9})` : `rgba(139, 92, 246, ${opacity * 0.7})`; + ctx.lineWidth = 2.5; + + if (isDark) { + ctx.shadowBlur = 12; + ctx.shadowColor = `rgba(167, 139, 250, ${opacity * 0.8})`; + } + + let startR = Math.max(0, this.radius - this.length); + let endR = this.radius; + + for(let r = startR; r <= endR; r += 2) { + let packetPos = (r - startR) / this.length; + let envelope = Math.sin(packetPos * Math.PI); + let displacement = Math.sin(r * this.frequency + this.phase) * this.amplitude * envelope; + + let px = cx + Math.cos(this.angle) * r + Math.cos(this.angle + Math.PI/2) * displacement; + let py = cy + Math.sin(this.angle) * r + Math.sin(this.angle + Math.PI/2) * displacement; + + if(r === startR) ctx.moveTo(px, py); + else ctx.lineTo(px, py); + } + ctx.stroke(); + ctx.shadowBlur = 0; + } + } + + class Satellite { + constructor(orbitRadius, tiltX, tiltY) { + this.orbitRadius = orbitRadius; + this.tiltX = tiltX; + this.tiltY = tiltY; + this.angle = Math.random() * Math.PI * 2; + this.speed = 0.0015 + Math.random() * 0.001; + this.blinkTimer = 0; + } + + get3DPos(theta) { + let bx = Math.cos(theta) * this.orbitRadius; + let by = Math.sin(theta) * this.orbitRadius; + let bz = 0; + + let y1 = by * Math.cos(this.tiltX) - bz * Math.sin(this.tiltX); + let z1 = by * Math.sin(this.tiltX) + bz * Math.cos(this.tiltX); + + let x2 = bx * Math.cos(this.tiltY) + z1 * Math.sin(this.tiltY); + let z2 = -bx * Math.sin(this.tiltY) + z1 * Math.cos(this.tiltY); + + return { x: x2, y: y1, z: z2 }; + } + + update() { + this.angle += this.speed; + this.blinkTimer++; + } + + draw(ctx, cx, cy) { + const isDark = document.documentElement.classList.contains('dark'); + const pathColor = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)'; + + let steps = 60; + ctx.beginPath(); + for (let i = 0; i <= steps; i++) { + let t = (i / steps) * Math.PI * 2; + let p = this.get3DPos(t); + if (i === 0) ctx.moveTo(cx + p.x, cy + p.y); + else ctx.lineTo(cx + p.x, cy + p.y); + } + ctx.strokeStyle = pathColor; + ctx.lineWidth = 1.5; + ctx.setLineDash([4, 4]); + ctx.stroke(); + ctx.setLineDash([]); + + let pos = this.get3DPos(this.angle); + let depthScale = 1 + (pos.z / this.orbitRadius) * 0.5; + let satRadius = 4 * depthScale; + + ctx.beginPath(); + ctx.arc(cx + pos.x, cy + pos.y, satRadius, 0, Math.PI * 2); + ctx.fillStyle = isDark ? '#60a5fa' : '#3b82f6'; + + if (isDark) { + ctx.shadowBlur = 10 * depthScale; + ctx.shadowColor = '#60a5fa'; + } + ctx.fill(); + ctx.shadowBlur = 0; + + if (this.blinkTimer % 120 < 60) { + ctx.beginPath(); + ctx.arc(cx + pos.x, cy + pos.y, satRadius * 2.5, 0, Math.PI * 2); + ctx.fillStyle = isDark ? `rgba(96, 165, 250, 0.4)` : `rgba(59, 130, 246, 0.3)`; + ctx.fill(); + } + } + } + + // Initialize Systems + for (let i = 0; i < 60; i++) ambientParticles.push(new Particle()); + for (let i = 0; i < 5; i++) setTimeout(() => waves.push(new Wave()), i * 1500); + for (let i = 0; i < 4; i++) setTimeout(() => emPulses.push(new EMPulse()), i * 2200); + + satellites.push(new Satellite(350, Math.PI / 6, Math.PI / 4)); + satellites.push(new Satellite(500, -Math.PI / 4, -Math.PI / 8)); + satellites.push(new Satellite(650, Math.PI / 2.2, 0)); + + // --- ANIMATION LOOP & OFF-SCREEN PAUSE --- + + let animationFrameId; + // FIX: Start as false so the observer triggers the first frame on load + let isAnimating = false; + + function animateCanvas() { + if (!isAnimating) return; // Immediately stop if paused + + ctx.clearRect(0, 0, canvas.width, canvas.height); + + let cx = canvas.width / 2; + let cy = canvas.height / 2; + + if (canvas.width < 768) { + cy = canvas.height * 0.30; + } + + ambientParticles.forEach(p => { p.update(); p.draw(ctx); }); + waves.forEach(wave => { wave.update(); wave.draw(ctx, cx, cy); }); + emPulses.forEach(pulse => { pulse.update(); pulse.draw(ctx, cx, cy); }); + satellites.forEach(sat => { sat.update(); sat.draw(ctx, cx, cy); }); + + animationFrameId = requestAnimationFrame(animateCanvas); + } + + // Set up the Intersection Observer + const heroSection = document.querySelector('.hero-bg'); + + // This watches the hero section. + const observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + // Wakes up the animation when visible + if (!isAnimating) { + isAnimating = true; + animateCanvas(); + } + } else { + // Puts it to sleep when out of view + isAnimating = false; + if (animationFrameId) { + cancelAnimationFrame(animationFrameId); + } + } + }); + }, { threshold: 0.01 }); + + // Start observing the hero section + if (heroSection) { + observer.observe(heroSection); + } else { + // Fallback just in case the class name changes + isAnimating = true; + animateCanvas(); + } + + /* --------------------------------------------------- + 3. UI Interactions & Chart.js Config + --------------------------------------------------- */ + const mobileBtn = document.getElementById('mobile-menu-btn'); + const mobileMenu = document.getElementById('mobile-menu'); + + mobileBtn.addEventListener('click', () => mobileMenu.classList.toggle('hidden')); + mobileMenu.querySelectorAll('a').forEach(link => { + link.addEventListener('click', () => mobileMenu.classList.add('hidden')); + }); + + const chartCtx = document.getElementById('academicChart').getContext('2d'); + + const data = { + labels: ['SSC (2022)', 'PUC (2024)', 'B.Tech (Current)'], + datasets: [{ + label: 'Normalized Score (%)', + data: [96.5, 97.9, 87.1], + borderColor: '#3b82f6', + backgroundColor: 'rgba(59, 130, 246, 0.15)', + borderWidth: 3, + pointBackgroundColor: '#ffffff', + pointBorderColor: '#3b82f6', + pointBorderWidth: 2, + pointRadius: 6, + pointHoverRadius: 8, + fill: true, + tension: 0.4 + }] + }; + + const config = { + type: 'line', + data: data, + options: { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { display: false }, + tooltip: { + backgroundColor: 'rgba(15, 23, 42, 0.95)', + titleFont: { family: 'Inter, sans-serif', size: 13 }, + bodyFont: { family: 'Inter, sans-serif', size: 14, weight: 'bold' }, + padding: 12, + displayColors: false, + callbacks: { + label: function(context) { + let raw = context.raw; + if(context.dataIndex === 0) return raw + '%'; + if(context.dataIndex === 1) return (raw/10).toFixed(2) + ' CGPA (' + raw + '%)'; + if(context.dataIndex === 2) return (raw/10).toFixed(2) + ' CGPA (' + raw + '%)'; + return raw; + } + } + } + }, + scales: { + y: { + min: 80, max: 100, + ticks: { font: { family: 'Inter, sans-serif' }, color: '#64748b' }, + grid: { color: 'rgba(148, 163, 184, 0.1)', drawBorder: false } + }, + x: { + ticks: { font: { family: 'Inter, sans-serif', weight: '500' }, color: '#475569' }, + grid: { display: false, drawBorder: false } + } + }, + interaction: { intersect: false, mode: 'index' }, + } + }; + + new Chart(chartCtx, config); + + /* --------------------------------------------------- + 4. Lightbox Gallery Logic + --------------------------------------------------- */ + lightbox = document.getElementById('lightbox'); + lightboxImg = document.getElementById('lightbox-img'); + + // Feature: Close lightbox when clicking the dark background outside the image + lightbox.addEventListener('click', (e) => { + if (e.target === lightbox) { + closeLightbox(); + } + }); + + // Feature: Close lightbox when hitting the Escape key + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && !lightbox.classList.contains('hidden')) { + closeLightbox(); + } + }); +}); diff --git a/style.css b/style.css new file mode 100644 index 0000000..7d81c46 --- /dev/null +++ b/style.css @@ -0,0 +1,57 @@ +::view-transition-old(root), +::view-transition-new(root) { + animation: none; + mix-blend-mode: normal; +} + + +.chart-container { + position: relative; + width: 100%; + max-width: 600px; + margin-left: auto; + margin-right: auto; + height: 300px; + max-height: 400px; +} + +/* Hardware Acceleration Layering */ +#eceCanvas { + /* Tells the browser this element will change constantly */ + will-change: transform, opacity; + /* Forces the browser to put the canvas on its own 3D GPU layer */ + transform: translateZ(0); + /* Ensures it never intercepts mouse clicks meant for buttons */ + pointer-events: none; +} + +/* Hide scrollbar for Chrome, Safari and Opera */ +.hide-scrollbar::-webkit-scrollbar { + display: none; +} +/* Hide scrollbar for IE, Edge and Firefox */ +.hide-scrollbar { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ +} +@media (min-width: 768px) { + .chart-container { + height: 350px; + } +} + +/* Subtle animated gradient background for the hero section to make glass pop */ +.hero-bg { + background: linear-gradient(-45deg, #f8fafc, #e2e8f0, #f1f5f9, #ffffff); + background-size: 400% 400%; + animation: gradientBG 15s ease infinite; +} +.dark .hero-bg { + background: linear-gradient(-45deg, #020617, #0f172a, #1e293b, #020617); + background-size: 400% 400%; +} +@keyframes gradientBG { + 0% { background-position: 0% 50%; } + 50% { background-position: 100% 50%; } + 100% { background-position: 0% 50%; } +}