From 96b11e8f704a6bd6cf12fbb1d06b845a26ca98c2 Mon Sep 17 00:00:00 2001 From: Mudita Date: Sat, 23 May 2026 19:29:58 +0530 Subject: [PATCH 1/2] Fix UI/layout inconsistencies for project cards and modal rendering --- web-app/css/styles.css | 253 ++++++++++++++++++++++++++++++++++++++++- web-app/js/main.js | 50 ++------ 2 files changed, 263 insertions(+), 40 deletions(-) diff --git a/web-app/css/styles.css b/web-app/css/styles.css index 6228742..0aba5ed 100644 --- a/web-app/css/styles.css +++ b/web-app/css/styles.css @@ -3045,6 +3045,120 @@ body { } } +/* ========================================================================== + CARD AND MODAL LAYOUT STANDARDIZATION + ========================================================================== */ + +.projects-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); + gap: 1.2rem; + margin-top: 2rem; + align-items: stretch; +} + +.project-card { + min-height: 240px; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: stretch; + padding: 1.75rem 1.5rem 1.5rem; + border-radius: 28px; + background: var(--surface-color); + border: 1px solid var(--accent-border); + box-shadow: 0 18px 40px rgba(0, 0, 0, 0.08); + transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease; +} + +.project-card h3 { + margin-bottom: 0.8rem; + font-size: 1.15rem; + line-height: 1.35; + color: var(--text-color); +} + +.project-card p { + margin-bottom: 1rem; + color: var(--text-secondary); + font-size: 0.95rem; + line-height: 1.65; + flex: 1 1 auto; +} + +.project-card .btn-play { + margin-top: auto; + align-self: flex-start; +} + +.card-icon { + width: 72px; + height: 72px; + display: grid; + place-items: center; + border-radius: 22px; + background: var(--accent-soft); + color: var(--accent-color); + margin-bottom: 1.2rem; + font-size: 2rem; + flex-shrink: 0; +} + +.modal-content { + width: min(100%, 900px); + max-width: 900px; + min-width: 320px; + max-height: 92vh; + overflow-y: auto; + overflow-x: hidden; + padding: 2rem; + border-radius: 20px; + box-shadow: var(--shadow-modal); + background: var(--surface-color); + border: 1px solid var(--border-color); +} + +#modalBody { + width: 100%; + display: flex; + flex-direction: column; + gap: 1rem; + align-items: stretch; +} + +#modalBody > * { + width: 100%; + max-width: 100%; +} + +.modal-close { + z-index: 2100; +} + +@media (max-width: 768px) { + .modal-content { + width: min(100%, 92vw); + padding: 1.5rem; + max-height: 90vh; + } + + .project-card { + min-height: auto; + padding: 1.5rem 1.25rem; + } +} + +@media (max-width: 576px) { + .projects-grid { + grid-template-columns: 1fr; + gap: 1rem; + } + + .project-card { + padding: 1.25rem; + } +} + /* ========================================================================== ARCADE REDESIGN OVERRIDES ========================================================================== */ @@ -4389,4 +4503,141 @@ body { padding: 1rem; } } -} \ No newline at end of file + +/* ========================================================================== + FINAL CARD + MODAL CONSISTENCY OVERRIDES + This section is intentionally appended at the end to override earlier + duplicate card/modal definitions and enforce consistent spacing, sizing, + and responsive behavior across all project pages. + ========================================================================== */ + +.projects-grid { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)) !important; + gap: 1.2rem !important; + margin-top: 2rem !important; + align-items: stretch !important; +} + +.project-card { + min-height: 240px !important; + display: flex !important; + flex-direction: column !important; + justify-content: space-between !important; + align-items: stretch !important; + padding: 1.75rem 1.5rem 1.5rem !important; + border-radius: 28px !important; + background: var(--surface-color) !important; + border: 1px solid var(--accent-border) !important; + box-shadow: 0 18px 40px rgba(0, 0, 0, 0.08) !important; + transition: transform 0.2s ease !important; +} + +.project-card h3 { + margin-bottom: 0.75rem !important; + font-size: 1.15rem !important; + line-height: 1.35 !important; + color: var(--text-color) !important; +} + +.project-card p { + margin-bottom: 1rem !important; + color: var(--text-secondary) !important; + font-size: 0.95rem !important; + line-height: 1.6 !important; + flex: 1 1 auto !important; +} + +.project-card .btn-play { + margin-top: auto !important; + align-self: flex-start !important; +} + +.card-icon { + width: 72px !important; + height: 72px !important; + display: grid !important; + place-items: center !important; + border-radius: 22px !important; + background: var(--accent-soft) !important; + color: var(--accent-color) !important; + margin-bottom: 1.2rem !important; + font-size: 2rem !important; +} + +.modal { + display: none !important; + position: fixed !important; + top: 0 !important; + left: 0 !important; + width: 100% !important; + height: 100% !important; + background: var(--overlay-color) !important; + backdrop-filter: blur(6px) !important; + -webkit-backdrop-filter: blur(6px) !important; + z-index: 2000 !important; + animation: fadeIn 0.3s ease !important; +} + +.modal.active { + display: flex !important; + align-items: center !important; + justify-content: center !important; +} + +.modal-content { + width: min(100%, 900px) !important; + max-width: 900px !important; + min-width: 320px !important; + max-height: 92vh !important; + overflow-y: auto !important; + overflow-x: hidden !important; + padding: 2rem !important; + border-radius: 20px !important; + box-shadow: var(--shadow-modal) !important; + background: var(--surface-color) !important; + border: 1px solid var(--border-color) !important; + margin: auto !important; +} + +#modalBody { + width: 100% !important; + display: flex !important; + flex-direction: column !important; + gap: 1rem !important; + align-items: stretch !important; +} + +#modalBody > * { + width: 100% !important; + max-width: 100% !important; +} + +.modal-close { + z-index: 2100 !important; +} + +@media (max-width: 768px) { + .modal-content { + width: min(100%, 92vw) !important; + padding: 1.5rem !important; + max-height: 90vh !important; + } + + .project-card { + min-height: auto !important; + padding: 1.5rem 1.25rem !important; + } +} + +@media (max-width: 576px) { + .projects-grid { + grid-template-columns: 1fr !important; + gap: 1rem !important; + } + + .project-card { + padding: 1.25rem !important; + min-height: auto !important; + } +} diff --git a/web-app/js/main.js b/web-app/js/main.js index f6efd2a..dccbe58 100644 --- a/web-app/js/main.js +++ b/web-app/js/main.js @@ -799,18 +799,19 @@ if (stickyFilterBar && heroSection) { var modalBody = document.getElementById('modalBody'); if (!modalContent || !modalBody) return; - // Reset scroll position to top to avoid viewport clippings during calculations modalContent.scrollTop = 0; modalBody.scrollTop = 0; - // Hide scrollbars on the container - modalContent.style.overflow = 'hidden'; + modalContent.style.overflow = 'auto'; - // Reset inline styles to capture natural dimensions modalBody.style.transform = ''; modalBody.style.transformOrigin = ''; - modalBody.style.width = ''; + modalBody.style.width = '100%'; modalBody.style.height = ''; + modalBody.style.display = 'flex'; + modalBody.style.flexDirection = 'column'; + modalBody.style.alignItems = 'stretch'; + modalBody.style.gap = '1rem'; var targetEl = Array.from(modalBody.children).find(function (el) { return el.tagName.toLowerCase() !== 'style'; @@ -819,40 +820,8 @@ if (stickyFilterBar && heroSection) { targetEl.style.transform = ''; targetEl.style.transformOrigin = ''; - - var computedStyle = window.getComputedStyle(modalContent); - var paddingTop = parseFloat(computedStyle.paddingTop) || 32; - var paddingBottom = parseFloat(computedStyle.paddingBottom) || 32; - var paddingLeft = parseFloat(computedStyle.paddingLeft) || 32; - var paddingRight = parseFloat(computedStyle.paddingRight) || 32; - - var availableHeight = modalContent.clientHeight - paddingTop - paddingBottom; - var availableWidth = modalContent.clientWidth - paddingLeft - paddingRight; - - var contentHeight = targetEl.scrollHeight; - var contentWidth = targetEl.scrollWidth; - - if (contentHeight <= 0 || contentWidth <= 0) return; - - var zoom = 1; - var heightZoom = availableHeight / contentHeight; - var widthZoom = availableWidth / contentWidth; - - zoom = Math.min(heightZoom, widthZoom); - if (zoom > 1) { - zoom = 1; - } - - // Apply scale transform and origins - targetEl.style.transform = 'scale(' + zoom + ')'; - targetEl.style.transformOrigin = 'top center'; - - // Constrain wrapper block size to prevent scroll triggering - modalBody.style.height = (contentHeight * zoom) + 'px'; - modalBody.style.width = '100%'; - modalBody.style.display = 'flex'; - modalBody.style.flexDirection = 'column'; - modalBody.style.alignItems = 'center'; + targetEl.style.width = '100%'; + targetEl.style.maxWidth = '100%'; } function initModalScaling() { @@ -974,6 +943,9 @@ if (stickyFilterBar && heroSection) { modalBody.style.transformOrigin = ''; modalBody.style.width = ''; modalBody.style.height = ''; + modalBody.style.display = ''; + modalBody.style.alignItems = ''; + modalBody.style.gap = ''; } if (lastFocusedElement && typeof lastFocusedElement.focus === 'function') { lastFocusedElement.focus({ preventScroll: true }); From 8fe35c34f813debaf577f28f8ab81ab806f7e426 Mon Sep 17 00:00:00 2001 From: Mudita Date: Sat, 23 May 2026 22:27:11 +0530 Subject: [PATCH 2/2] fix(ui/search): resolve card display important block, alphabetical sorting duplicates, and sync scroll behavior --- web-app/css/styles.css | 41 ++-- web-app/index.html | 460 +++++++++++++++++++---------------------- web-app/js/main.js | 2 +- 3 files changed, 230 insertions(+), 273 deletions(-) diff --git a/web-app/css/styles.css b/web-app/css/styles.css index 0aba5ed..1466403 100644 --- a/web-app/css/styles.css +++ b/web-app/css/styles.css @@ -1849,6 +1849,10 @@ body { color: #999fee; } +.game-icon-blackjack { + color: #8b5cf6; +} + .game-icon-dice { color: #e04f4f; } @@ -4469,6 +4473,8 @@ body { .btn-play { transform: none !important; } +} + /* Fix card content alignment */ .project-card { text-align: left; @@ -4513,43 +4519,38 @@ body { .projects-grid { display: grid !important; - grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)) !important; + grid-template-columns: repeat(auto-fit, minmax(260px, 360px)) !important; + justify-content: center !important; gap: 1.2rem !important; - margin-top: 2rem !important; + margin: 0 auto 2rem !important; align-items: stretch !important; } +.projects-grid > .project-card { + justify-self: center !important; + width: 100% !important; + max-width: 360px !important; +} + .project-card { min-height: 240px !important; - display: flex !important; + display: flex; flex-direction: column !important; - justify-content: space-between !important; - align-items: stretch !important; + justify-content: flex-start !important; + align-items: flex-start !important; padding: 1.75rem 1.5rem 1.5rem !important; border-radius: 28px !important; background: var(--surface-color) !important; border: 1px solid var(--accent-border) !important; box-shadow: 0 18px 40px rgba(0, 0, 0, 0.08) !important; transition: transform 0.2s ease !important; -} - -.project-card h3 { - margin-bottom: 0.75rem !important; - font-size: 1.15rem !important; - line-height: 1.35 !important; - color: var(--text-color) !important; -} - -.project-card p { - margin-bottom: 1rem !important; - color: var(--text-secondary) !important; + margin: 0 auto !important; font-size: 0.95rem !important; line-height: 1.6 !important; - flex: 1 1 auto !important; } .project-card .btn-play { - margin-top: auto !important; + margin-top: 1rem !important; align-self: flex-start !important; } @@ -4561,7 +4562,7 @@ body { border-radius: 22px !important; background: var(--accent-soft) !important; color: var(--accent-color) !important; - margin-bottom: 1.2rem !important; + margin: 0 auto 1.2rem !important; font-size: 2rem !important; } diff --git a/web-app/index.html b/web-app/index.html index 7fb4c5b..650b417 100644 --- a/web-app/index.html +++ b/web-app/index.html @@ -1259,233 +1259,209 @@

thrive

-
-
-
🃏
-

BlackJack21

-

Beat the dealer!

- -
-
🎯
-

Number Guessing

-

Guess the secret number!

- -
-
-

Fibonacci Series

-

Generate Fibonacci sequences!

- -
-
- -
-

Rock Paper Scissors

-

Battle against the computer!

- -
-
- -
-

Dice Rolling

-

Roll the dice with 3D animation!

- -
-
- -
-

Coin Flip

-

Heads or tails with spinning animation!

- -
-
- -
-

Number Guessing

-

Guess the secret number!

- -
-
- -
-

Hangman

-

Classic word-guessing game!

- -
-
- -
-

Word Scramble

-

Unscramble words before attempts run out!

- -
-
- -
-

FLAMES Game

-

Discover your relationship status!

- -
-
- -
-

Dots & Boxes AI

-

Challenge friends or AI in this strategy game!

- -
-
- -
-

Password Forge

-

Survive evolving firewall password rules!

- -
-
- -
-

Math Quiz

-

MCQ quiz with lives and difficulty levels!

- -
-
- -
-

Snake Game

-

Classic snake game!

- -
-
- -
-

Emoji Memory Game

-

Test your memory with matching emojis!

- -
-
- -
-

Whack-a-Mole

-

Hit the moles before they disappear!

- -
-
- -
-

Flappy Game

-

Dodge the incoming balls and survive!

- -
-
- -
-

2048 Game

-

Combine tiles and reach 2048!

- -
-
- -
-

Fibonacci Series

-

Generate Fibonacci sequences!

- -
-
- -
-

AP/GP/AGP/HP Recognizer

-

Identify progression types from any sequence.

- -
-
- -
-

Pascal's Triangle

-

Beautiful hexagon visualization!

- -
-
- -
-

Armstrong Numbers

-

Check special number properties!

- -
-
- -
-

Calculator

-

Your mathematical companion!

- -
-
- -
-

Collatz Conjecture

-

Explore the 3n+1 problem!

- -
-
- -
-

Prime Analyzer

-

All-in-one prime number toolkit!

- -
-
- -
-

Projectile Motion

-

Calculate TOF, Hmax, and Range with physics!

- -
-
- -
-

Coordinate to Polar

-

Transform Cartesian (x, y) into polar (r, theta).

- -
-
- -
-

Derivative Calculator

-

Compute 1st/nth polynomial derivatives and evaluate them.

- -
-
- -
-

Morse Code

-

Translate with lights & sound!

- -
-
- -
-

Tower of Hanoi

-

Solve the classic puzzle!

- -
-
- -
-

Number Converter

-

Convert Dec, Bin, Oct, and Hex!

- -
-
- -
-

Typing Speed Tester

-

Test your typing skills!

- -
-
- -
-

Color Palette Suggestor

-

Generate palettes + CSS snippets for any website type and mood!

- -
+
+
+
+

2048 Game

+

Combine tiles and reach 2048!

+ +
+
+
+

AP/GP/AGP/HP Recognizer

+

Identify progression types from any sequence.

+ +
+
+
+

Armstrong Numbers

+

Check special number properties!

+ +
+
+
+

BlackJack21

+

Beat the dealer!

+ +
+
+
+

Calculator

+

Your mathematical companion!

+ +
+
+
+

Coin Flip

+

Heads or tails with spinning animation!

+ +
+
+
+

Collatz Conjecture

+

Explore the 3n+1 problem!

+ +
+
+
+

Color Palette Suggestor

+

Generate palettes + CSS snippets for any website type and mood!

+ +
+
+
+

Coordinate to Polar

+

Transform Cartesian (x, y) into polar (r, theta).

+ +
+
+
+

Derivative Calculator

+

Compute 1st/nth polynomial derivatives and evaluate them.

+ +
+
+
+

Dice Rolling

+

Roll the dice with 3D animation!

+ +
+
+
+

Dots & Boxes AI

+

Challenge friends or AI in this strategy game!

+ +
+
+
+

Emoji Memory Game

+

Test your memory with matching emojis!

+ +
+
+
+

Fibonacci Series

+

Generate Fibonacci sequences!

+ +
+
+
+

FLAMES Game

+

Discover your relationship status!

+ +
+
+
+

Flappy Game

+

Dodge the incoming balls and survive!

+ +
+
+
+

Hangman

+

Classic word-guessing game!

+ +
+
+
+

Math Quiz

+

MCQ quiz with lives and difficulty levels!

+ +
+
+
+

Morse Code

+

Translate with lights & sound!

+ +
+
+
+

Number Converter

+

Convert Dec, Bin, Oct, and Hex!

+ +
+
+
+

Number Guessing

+

Guess the secret number!

+ +
+
+
+

Pascal's Triangle

+

Beautiful hexagon visualization!

+ +
+
+
+

Password Forge

+

Survive evolving firewall password rules!

+ +
+
+
+

Prime Analyzer

+

All-in-one prime number toolkit!

+ +
+
+
+

Projectile Motion

+

Calculate TOF, Hmax, and Range with physics!

+ +
+
+
+

Rock Paper Scissors

+

Battle against the computer!

+ +
+
+
+

Simon Says

+

Repeat the pattern and test your memory skills!

+ +
+
+
+

Snake Game

+

Classic snake game!

+ +
+
+
+

Tower of Hanoi

+

Solve the classic puzzle!

+ +
+
+
+

Typing Speed Tester

+

Test your typing skills!

+ +
+
+
+

Whack-a-Mole

+

Hit the moles before they disappear!

+ +
+
+
+

Word Scramble

+

Unscramble words before attempts run out!

+ +
+
+ + + +
+ +
@@ -1750,38 +1726,18 @@

Stay Updated

const navSearchInput = document.getElementById("searchInput"); const heroSearchInput = document.getElementById("heroSearchInput"); - // Select all project cards - const projectCards = document.querySelectorAll(".project-card"); - - function filterCards(searchValue) { - projectCards.forEach(card => { - const title = card.querySelector("h3").textContent.toLowerCase(); - const description = card.querySelector("p").textContent.toLowerCase(); - - if ( - title.includes(searchValue) || - description.includes(searchValue) - ) { - card.style.display = "block"; - } else { - card.style.display = "none"; - } - }); - } - - // Sync both search inputs and filter cards + // Sync both search inputs and let main.js handle the filtering cleanly if (navSearchInput) { navSearchInput.addEventListener("input", () => { - const val = navSearchInput.value.toLowerCase(); if (heroSearchInput) heroSearchInput.value = navSearchInput.value; - filterCards(val); }); } if (heroSearchInput) { heroSearchInput.addEventListener("input", () => { - const val = heroSearchInput.value.toLowerCase(); - if (navSearchInput) navSearchInput.value = heroSearchInput.value; - filterCards(val); + if (navSearchInput) { + navSearchInput.value = heroSearchInput.value; + navSearchInput.dispatchEvent(new Event("input")); + } }); } diff --git a/web-app/js/main.js b/web-app/js/main.js index dccbe58..03897a3 100644 --- a/web-app/js/main.js +++ b/web-app/js/main.js @@ -738,7 +738,7 @@ if (stickyFilterBar && heroSection) { if (searchLoader) searchLoader.style.display = query ? 'block' : 'none'; debouncedSearch(query); performSearch(); - if (query && projectsSection) { + if (query && projectsSection && document.activeElement === searchInput) { projectsSection.scrollIntoView({ behavior: prefersReducedMotion() ? 'auto' : 'smooth', block: 'start'