diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b5797a6..534972d0 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,12 @@ Created Repo from template - Landing Page Redesign - CrossWord page update +## [3.4.0] - June 27 2026 + +- Redesign Pages +- Added Featured and Category section +- Added a keyboard game. + ### [Unreleased] Here we write upgrading notes for brands. It's a team effort to make them as straightforward as possible. diff --git a/docs/architecture.md b/docs/architecture.md index 3103cff0..8f120285 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,28 +1,27 @@ -# Architecture Principles - -## Separation of Concerns - -Keep business logic, presentation, and data access separated. - -## Single Source of Truth - -Avoid duplicating ownership of the same data. - -## Predictability - -Prefer explicit flows over hidden side effects. - -## Backward Compatibility - -Consider impact on existing users and integrations before making breaking changes. - -## Security First - -Validate all external input. - -Never trust client-provided data. - -## Reuse Existing Patterns - -Before introducing a new pattern, evaluate whether an existing project pattern already solves the problem. - +# Architecture Principles + +## Separation of Concerns + +Keep business logic, presentation, and data access separated. + +## Single Source of Truth + +Avoid duplicating ownership of the same data. + +## Predictability + +Prefer explicit flows over hidden side effects. + +## Backward Compatibility + +Consider impact on existing users and integrations before making breaking changes. + +## Security First + +Validate all external input. + +Never trust client-provided data. + +## Reuse Existing Patterns + +Before introducing a new pattern, evaluate whether an existing project pattern already solves the problem. diff --git a/docs/coding-guidelines.md b/docs/coding-guidelines.md index ad91f538..67722f85 100644 --- a/docs/coding-guidelines.md +++ b/docs/coding-guidelines.md @@ -1,72 +1,72 @@ -# Coding Guidelines - -## Naming - -- Use meaningful and descriptive names. -- Avoid abbreviations unless commonly understood. -- Functions should describe actions. -- Variables should describe data. - -## Functions - -- Keep functions focused on a single responsibility. -- Prefer small, composable functions. -- Avoid deeply nested conditions. -- Reuse existing utilities where possible. - -## Comments - -- Explain why, not what. -- Remove outdated comments. -- Avoid commenting obvious code. - -## Error Handling - -- Handle errors explicitly. -- Provide actionable error messages. -- Never silently ignore failures. - -## Dependencies - -- Introduce new dependencies only when justified. -- Prefer platform-native solutions when practical. - -## Code Reviews - -- Optimize for readability. -- Avoid unnecessary complexity. -- Follow existing project conventions. - -## Development Environment - -### Use the Workspace File - -Always open the project using the provided VS Code workspace file (`*.code-workspace`). - -Benefits: - -- Consistent settings -- Recommended extensions -- Shared tasks and debugging configuration -- Reduced environment-related issues - -Open the workspace: - -```bash -code project.code-workspace -``` - -### Recommended Extensions - -Install all workspace-recommended extensions. - -These help maintain: - -- Formatting consistency -- Linting standards -- Import organization -- Code quality checks - -### Workspace Files - -Do not commit personal workspace modifications unless they benefit the entire team. +# Coding Guidelines + +## Naming + +- Use meaningful and descriptive names. +- Avoid abbreviations unless commonly understood. +- Functions should describe actions. +- Variables should describe data. + +## Functions + +- Keep functions focused on a single responsibility. +- Prefer small, composable functions. +- Avoid deeply nested conditions. +- Reuse existing utilities where possible. + +## Comments + +- Explain why, not what. +- Remove outdated comments. +- Avoid commenting obvious code. + +## Error Handling + +- Handle errors explicitly. +- Provide actionable error messages. +- Never silently ignore failures. + +## Dependencies + +- Introduce new dependencies only when justified. +- Prefer platform-native solutions when practical. + +## Code Reviews + +- Optimize for readability. +- Avoid unnecessary complexity. +- Follow existing project conventions. + +## Development Environment + +### Use the Workspace File + +Always open the project using the provided VS Code workspace file (`*.code-workspace`). + +Benefits: + +- Consistent settings +- Recommended extensions +- Shared tasks and debugging configuration +- Reduced environment-related issues + +Open the workspace: + +```bash +code project.code-workspace +``` + +### Recommended Extensions + +Install all workspace-recommended extensions. + +These help maintain: + +- Formatting consistency +- Linting standards +- Import organization +- Code quality checks + +### Workspace Files + +Do not commit personal workspace modifications unless they benefit the entire team. diff --git a/docs/git-workflow.md b/docs/git-workflow.md index 7bf4efe5..fbcd0643 100644 --- a/docs/git-workflow.md +++ b/docs/git-workflow.md @@ -1,172 +1,173 @@ -# Git Workflow - -## Branch Creation - -### Step 1: Create an Issue - -Create a GitHub issue describing the work. - -### Step 2: Wait for Issue ID Assignment - -An automated workflow will assign an issue identifier. - -Example: - -```text -RZA-260001 -``` - -Wait for the identifier before creating a branch. - -### Step 3: Create a Branch - -Valid examples: - -```text -feature/RZA-260001 -feature/RZA-260002 - -bugfix/RZA-260003 -bugfix/RZA-260004 -``` - -Rules: - -- Use only `feature/` or `bugfix/` -- Use the generated issue ID exactly as assigned -- Do not add descriptions, names, dates, or suffixes - -Invalid examples: - -```text -feature/login-screen -feature/RZA-260001-login -feature/john-RZA-260001 -bugfix/RZA-260001-test -``` - ---- - -## Back Merge - -Regularly merge the latest `develop` branch into your working branch. - -### Update develop - -```bash -git checkout develop -git pull origin develop -``` - -### Switch to your branch - -```bash -git checkout feature/RZA-260001 -``` - -### Merge develop - -```bash -git merge develop --no-commit -``` - -### Why --no-commit - -This allows you to: - -- Review incoming changes -- Resolve conflicts -- Test the application -- Create the merge commit only after verification - -### Complete merge - -```bash -git add . -git commit -git push origin feature/RZA-260001 -``` - ---- - -## Resolving Conflicts - -If conflicts occur: - -1. Open the project in VS Code. -2. Review conflicting sections. -3. Use: - - Accept Current Change - - Accept Incoming Change - - Accept Both Changes - - Compare Changes - -4. Verify the application works correctly. - -Complete the merge: - -```bash -git add . -git commit -git push -``` - ---- - -## Renaming a Branch - -Rename local branch: - -```bash -git branch -m feature/RZA-260001 -``` - -Push renamed branch: - -```bash -git push origin -u feature/RZA-260001 -``` - -Delete old remote branch: - -```bash -git push origin --delete old-branch-name -``` - -Verify: - -- New branch exists on GitHub -- Old branch is removed -- Open PRs are updated if necessary - ---- - -## Pull Requests - -Every Pull Request should include: - -### Summary - -Clearly explain: - -- What was changed -- Why it was changed -- Any limitations or considerations - -### Evidence - -Provide one or more of the following: - -- Screenshots -- Screen recordings -- API examples -- Before/After comparisons - -### Before Requesting Review - -- Latest develop branch merged -- Conflicts resolved -- Changes tested -- Screenshots attached -- Documentation updated if required -- No debug code remains +# Git Workflow + +## Branch Creation + +### Step 1: Create an Issue + +Create a GitHub issue describing the work. + +### Step 2: Wait for Issue ID Assignment + +An automated workflow will assign an issue identifier. + +Example: + +```text +RZA-260001 +``` + +Wait for the identifier before creating a branch. + +### Step 3: Create a Branch + +Valid examples: + +```text +feature/RZA-260001 +feature/RZA-260002 + +bugfix/RZA-260003 +bugfix/RZA-260004 +``` + +Rules: + +- Use only `feature/` or `bugfix/` +- Use the generated issue ID exactly as assigned +- Do not add descriptions, names, dates, or suffixes + +Invalid examples: + +```text +feature/login-screen +feature/RZA-260001-login +feature/john-RZA-260001 +bugfix/RZA-260001-test +``` + +--- + +## Back Merge + +Regularly merge the latest `develop` branch into your working branch. + +### Update develop + +```bash +git checkout develop +git pull origin develop +``` + +### Switch to your branch + +```bash +git checkout feature/RZA-260001 +``` + +### Merge develop + +```bash +git merge develop --no-commit +``` + +### Why --no-commit + +This allows you to: + +- Review incoming changes +- Resolve conflicts +- Test the application +- Create the merge commit only after verification + +### Complete merge + +```bash +git add . +git commit +git push origin feature/RZA-260001 +``` + +--- + +## Resolving Conflicts + +If conflicts occur: + +1. Open the project in VS Code. +2. Review conflicting sections. +3. Use: + + - Accept Current Change + - Accept Incoming Change + - Accept Both Changes + - Compare Changes + +4. Verify the application works correctly. + +Complete the merge: + +```bash +git add . +git commit +git push +``` + +--- + +## Renaming a Branch + +Rename local branch: + +```bash +git branch -m feature/RZA-260001 +``` + +Push renamed branch: + +```bash +git push origin -u feature/RZA-260001 +``` + +Delete old remote branch: + +```bash +git push origin --delete old-branch-name +``` + +Verify: + +- New branch exists on GitHub +- Old branch is removed +- Open PRs are updated if necessary + +--- + +## Pull Requests + +Every Pull Request should include: + +### Summary + +Clearly explain: + +- What was changed +- Why it was changed +- Any limitations or considerations + +### Evidence + +Provide one or more of the following: + +- Screenshots +- Screen recordings +- API examples +- Before/After comparisons + +### Before Requesting Review + +- Latest develop branch merged +- Conflicts resolved +- Changes tested +- Screenshots attached +- Documentation updated if required +- No debug code remains diff --git a/docs/philosophy.md b/docs/philosophy.md index c0fd0de8..169cf360 100644 --- a/docs/philosophy.md +++ b/docs/philosophy.md @@ -1,34 +1,34 @@ -# Engineering Philosophy - -## Build for the next developer - -Code is read more often than it is written. Prioritize clarity, maintainability, and consistency. - -## Prefer simplicity - -Choose the simplest solution that solves the problem. Avoid unnecessary abstractions and premature optimization. - -## Fix root causes - -Do not patch symptoms. Understand why an issue occurred and address the underlying cause. - -## Consistency matters - -Follow existing project patterns unless there is a strong reason to introduce a new approach. - -## Performance is a feature - -Consider performance, scalability, and user experience during implementation. - -## Document important decisions - -Future team members should understand why a decision was made, not just what was implemented. - -## Team Expectations - -- Ask questions early. -- Raise risks as soon as they are identified. -- Do not assume requirements. -- Communicate trade-offs clearly. -- Leave the codebase better than you found it. -- Focus on solving business problems, not showing technical cleverness. +# Engineering Philosophy + +## Build for the next developer + +Code is read more often than it is written. Prioritize clarity, maintainability, and consistency. + +## Prefer simplicity + +Choose the simplest solution that solves the problem. Avoid unnecessary abstractions and premature optimization. + +## Fix root causes + +Do not patch symptoms. Understand why an issue occurred and address the underlying cause. + +## Consistency matters + +Follow existing project patterns unless there is a strong reason to introduce a new approach. + +## Performance is a feature + +Consider performance, scalability, and user experience during implementation. + +## Document important decisions + +Future team members should understand why a decision was made, not just what was implemented. + +## Team Expectations + +- Ask questions early. +- Raise risks as soon as they are identified. +- Do not assume requirements. +- Communicate trade-offs clearly. +- Leave the codebase better than you found it. +- Focus on solving business problems, not showing technical cleverness. diff --git a/docs/review-checklist.md b/docs/review-checklist.md index a8226b5c..1d7d7311 100644 --- a/docs/review-checklist.md +++ b/docs/review-checklist.md @@ -1,17 +1,16 @@ -# Review Checklist - -Before approving a Pull Request, verify: - -- Requirements are satisfied. -- Code follows project conventions. -- No unnecessary complexity introduced. -- Error handling is present. -- Security implications considered. -- Existing functionality remains unaffected. -- Documentation updated if necessary. -- No dead code or debug code remains. -- Screenshots or testing evidence provided. -- Performance impact considered. - -If something is unclear, request clarification rather than making assumptions. - +# Review Checklist + +Before approving a Pull Request, verify: + +- Requirements are satisfied. +- Code follows project conventions. +- No unnecessary complexity introduced. +- Error handling is present. +- Security implications considered. +- Existing functionality remains unaffected. +- Documentation updated if necessary. +- No dead code or debug code remains. +- Screenshots or testing evidence provided. +- Performance impact considered. + +If something is unclear, request clarification rather than making assumptions. diff --git a/package-lock.json b/package-lock.json index de0105fe..ce47ff85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@recursivezero/abcd", - "version": "3.3.1", + "version": "3.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@recursivezero/abcd", - "version": "3.3.1", + "version": "3.4.0", "license": "MIT", "dependencies": { "@astrojs/check": "0.9.4", diff --git a/package.json b/package.json index 3996e2c0..30d41c1e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@recursivezero/abcd", - "version": "3.3.1", + "version": "3.4.0", "description": "A website for kids whio want to learn the alphabet in a fun and interactive way. It is built using Astro and TypeScript.", "homepage": "https://abcdkbd.com", "displayName": "abcd", diff --git a/public/assets/images/game-placeholder.svg b/public/assets/images/game-placeholder.svg new file mode 100644 index 00000000..807466d3 --- /dev/null +++ b/public/assets/images/game-placeholder.svg @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/public/assets/images/Number.png b/public/assets/images/games/Number.png similarity index 100% rename from public/assets/images/Number.png rename to public/assets/images/games/Number.png diff --git a/public/assets/images/OurIndia.png b/public/assets/images/games/OurIndia.png similarity index 100% rename from public/assets/images/OurIndia.png rename to public/assets/images/games/OurIndia.png diff --git a/public/assets/images/games/Stories.avif b/public/assets/images/games/Stories.avif new file mode 100644 index 00000000..2395600f Binary files /dev/null and b/public/assets/images/games/Stories.avif differ diff --git a/public/assets/images/games/akshar.avif b/public/assets/images/games/akshar.avif new file mode 100644 index 00000000..09bdd8a9 Binary files /dev/null and b/public/assets/images/games/akshar.avif differ diff --git a/public/assets/images/games/alphabet.webp b/public/assets/images/games/alphabet.webp new file mode 100644 index 00000000..ba806289 Binary files /dev/null and b/public/assets/images/games/alphabet.webp differ diff --git a/public/assets/images/games/canva.avif b/public/assets/images/games/canva.avif new file mode 100644 index 00000000..ffbf0299 Binary files /dev/null and b/public/assets/images/games/canva.avif differ diff --git a/public/assets/images/games/capital.jpg b/public/assets/images/games/capital.jpg new file mode 100644 index 00000000..9d19d05f Binary files /dev/null and b/public/assets/images/games/capital.jpg differ diff --git a/public/assets/images/games/crossword.webp b/public/assets/images/games/crossword.webp new file mode 100644 index 00000000..6837a134 Binary files /dev/null and b/public/assets/images/games/crossword.webp differ diff --git a/public/assets/images/games/draw.avif b/public/assets/images/games/draw.avif new file mode 100644 index 00000000..5504a6bd Binary files /dev/null and b/public/assets/images/games/draw.avif differ diff --git a/public/assets/images/games/gallery.avif b/public/assets/images/games/gallery.avif new file mode 100644 index 00000000..18c91877 Binary files /dev/null and b/public/assets/images/games/gallery.avif differ diff --git a/public/assets/images/glossary.png b/public/assets/images/games/glossary.png similarity index 100% rename from public/assets/images/glossary.png rename to public/assets/images/games/glossary.png diff --git a/public/assets/images/games/hide.avif b/public/assets/images/games/hide.avif new file mode 100644 index 00000000..3e05726b Binary files /dev/null and b/public/assets/images/games/hide.avif differ diff --git a/public/assets/images/games/knplay.png b/public/assets/images/games/knplay.png new file mode 100644 index 00000000..7fdef57f Binary files /dev/null and b/public/assets/images/games/knplay.png differ diff --git a/public/assets/images/games/math.avif b/public/assets/images/games/math.avif new file mode 100644 index 00000000..269bd5a0 Binary files /dev/null and b/public/assets/images/games/math.avif differ diff --git a/public/assets/images/games/nakshatra.avif b/public/assets/images/games/nakshatra.avif new file mode 100644 index 00000000..56e6665b Binary files /dev/null and b/public/assets/images/games/nakshatra.avif differ diff --git a/public/assets/images/games/ourindia.avif b/public/assets/images/games/ourindia.avif new file mode 100644 index 00000000..30ae709f Binary files /dev/null and b/public/assets/images/games/ourindia.avif differ diff --git a/public/assets/images/games/panel.avif b/public/assets/images/games/panel.avif new file mode 100644 index 00000000..85849a50 Binary files /dev/null and b/public/assets/images/games/panel.avif differ diff --git a/public/assets/images/games/poems.jpg b/public/assets/images/games/poems.jpg new file mode 100644 index 00000000..fc57e34a Binary files /dev/null and b/public/assets/images/games/poems.jpg differ diff --git a/public/assets/images/stories.webp b/public/assets/images/games/stories.webp similarity index 100% rename from public/assets/images/stories.webp rename to public/assets/images/games/stories.webp diff --git a/public/assets/images/games/vedic.png b/public/assets/images/games/vedic.png new file mode 100644 index 00000000..4631b7e8 Binary files /dev/null and b/public/assets/images/games/vedic.png differ diff --git a/public/assets/images/games/vernmala.jpg b/public/assets/images/games/vernmala.jpg new file mode 100644 index 00000000..b991ae75 Binary files /dev/null and b/public/assets/images/games/vernmala.jpg differ diff --git a/public/assets/images/games/zodiac.jpg b/public/assets/images/games/zodiac.jpg new file mode 100644 index 00000000..3a42257b Binary files /dev/null and b/public/assets/images/games/zodiac.jpg differ diff --git a/public/assets/images/hero.webp b/public/assets/images/hero.webp new file mode 100644 index 00000000..4464122d Binary files /dev/null and b/public/assets/images/hero.webp differ diff --git a/src/assets/styles/coming-soon.css b/src/assets/styles/coming-soon.css index 4c324235..06b5789d 100644 --- a/src/assets/styles/coming-soon.css +++ b/src/assets/styles/coming-soon.css @@ -1,6 +1,7 @@ .page-container { display: flex; flex-direction: column; + align-items: center; gap: 2.5rem; margin: 2rem 0; } @@ -9,6 +10,11 @@ background: var(--bg-secondary); text-align: center; border-radius: 1.5rem; + display: flex; + flex-direction: column; + align-items: center; + padding: 2rem; + width: 100%; } .logo { @@ -32,4 +38,4 @@ h1 { max-width: 500px; margin: 0 auto; line-height: 1.6; -} +} \ No newline at end of file diff --git a/src/assets/styles/footer.css b/src/assets/styles/footer.css index 62f5d826..fad1f4cf 100644 --- a/src/assets/styles/footer.css +++ b/src/assets/styles/footer.css @@ -7,6 +7,8 @@ --footer-link: #9ca3af; --footer-link-hover: #0ea5e9; --footer-border: #374151; + --footer-item-bg: #f5f5f5; + --footer-item-border: #e0e0e0; } [data-theme="dark"] { @@ -18,6 +20,8 @@ --footer-link: #7dd3fc; --footer-link-hover: #67e8f9; --footer-border: rgba(34, 211, 238, 0.14); + --footer-item-bg: rgba(255, 255, 255, 0.06); + --footer-item-border: rgba(34, 211, 238, 0.5); } [data-theme="light"] { @@ -29,12 +33,13 @@ --footer-link: #64748b; --footer-link-hover: #7c3aed; --footer-border: #e2e8f0; + --footer-item-bg: #f5f3ff; + --footer-item-border: #a78bfa; } .container__footer { background: rgba(255, 255, 255, 0.02); border-top: 2px solid var(--footer-border); - padding: 2rem 2rem 0; margin-top: 0 !important; padding-top: 1rem !important; @@ -44,7 +49,6 @@ z-index: 1; width: 100%; box-sizing: border-box; - display: flex; flex-direction: column; align-items: center; @@ -59,7 +63,6 @@ left: 5%; width: 90%; height: 2px; - background: linear-gradient(to right, transparent, #7c3aed, transparent); } @@ -269,51 +272,76 @@ line-height: 1.7; } - .footer__nav { - flex-direction: column; - gap: 16px; - display: flex; - } - - .footer__nav--item { - background: var(--color-surface, #f5f5f5); - border: 1px solid var(--color-border, #e0e0e0); - border-radius: 12px; - padding: 10px 12px; - } - - .footer__nav--title { - width: 100%; - text-align: center; - justify-content: center; - font-size: 0.8rem; - font-weight: 700; - padding: 0 0 8px 0; - pointer-events: none; - } - - .footer__nav--title .chevron { - display: none; - } - - .footer__nav--links { - flex-direction: row; - flex-wrap: wrap; - justify-content: center; - gap: 6px 12px; - padding: 0; - } - - .footer__nav--links a { - font-size: 0.75rem; - text-align: center; - white-space: nowrap; - } + .footer__nav { + display: flex; + flex-direction: column; + gap: 12px; + } + + .footer__nav--item { + background: var(--footer-item-bg); + border: 2px solid var(--footer-item-border); + border-radius: 12px; + padding: 12px 14px 14px; + } + + .footer__nav--title { + width: 100%; + text-align: center; + justify-content: center; + font-size: 0.82rem; + font-weight: 800; + letter-spacing: 2px; + padding: 0 0 8px 0; + margin-bottom: 0; + pointer-events: none; + color: var(--footer-brand); + } + + .footer__nav--title .chevron { + display: none; + } + + .footer__nav--links { + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + gap: 8px; + padding: 10px 4px 0; + } + + .footer__nav--links a { + font-size: 0.64rem; + font-weight: 600; + text-align: center; + white-space: normal; + border: 1px solid var(--footer-item-border); + border-radius: 16px; + padding: 6px 4px; + background: var(--footer-item-bg); + line-height: 1.2; + width: 92px; + flex: 0 0 92px; + display: flex; + align-items: center; + justify-content: center; + } + + .footer__nav--links a:hover { + padding-left: 14px; + background: var(--footer-highlight); + color: #fff; + border-color: var(--footer-highlight); + } .footer__nav--links a::before { display: none; } + .footer__nav--links a:hover { + padding-left: 10px; + } + .copyright { flex-direction: column; align-items: center; diff --git a/src/assets/styles/globals.css b/src/assets/styles/globals.css index 38001447..31bf8b49 100644 --- a/src/assets/styles/globals.css +++ b/src/assets/styles/globals.css @@ -23,6 +23,7 @@ html[data-theme="light"] { body { background-color: transparent !important; background-image: none !important; + font-family: 'Roboto', 'Noto Sans Devanagari', 'Mangal', 'Arial Unicode MS', sans-serif; } @layer base { @@ -187,20 +188,16 @@ body { left: 0; pointer-events: none; z-index: 0; - background-image: repeating-linear-gradient( - 60deg, + background-image: repeating-linear-gradient(60deg, transparent, transparent 28px, rgba(34, 211, 238, 0.03) 28px, - rgba(34, 211, 238, 0.03) 29px - ), - repeating-linear-gradient( - -40deg, + rgba(34, 211, 238, 0.03) 29px), + repeating-linear-gradient(-40deg, transparent, transparent 34px, rgba(34, 211, 238, 0.02) 34px, - rgba(34, 211, 238, 0.02) 35px - ); + rgba(34, 211, 238, 0.02) 35px); } [data-theme="light"] body::before { @@ -526,6 +523,7 @@ body { } @media (hover: none) and (pointer: coarse) { + button, a, [role="button"] { @@ -537,4 +535,4 @@ body { transform: none; } } -} +} \ No newline at end of file diff --git a/src/assets/styles/header.css b/src/assets/styles/header.css index a8b55afb..ab737c98 100644 --- a/src/assets/styles/header.css +++ b/src/assets/styles/header.css @@ -153,7 +153,7 @@ box-shadow: 0 3px 10px rgba(124, 58, 237, 0.04); display: flex; align-items: center; - position: fixed; + position: relative; top: var(--header-h, 5rem); left: 0; z-index: 999; @@ -693,3 +693,17 @@ padding: 1.25rem 1rem; } } + +.sidebar-mobile-wrapper { + width: 100%; + padding: 0 1rem; + margin-top: 1rem; +} + +[data-theme="light"] .header { + border-bottom: 2px solid rgba(0, 0, 0, 0.1); +} + +[data-theme="light"] .hero-search { + border-bottom: 1px solid rgba(0, 0, 0, 0.08); +} \ No newline at end of file diff --git a/src/assets/styles/keyboard-ninja.css b/src/assets/styles/keyboard-ninja.css new file mode 100644 index 00000000..4a5ccd64 --- /dev/null +++ b/src/assets/styles/keyboard-ninja.css @@ -0,0 +1,1331 @@ +/* Keyboard Ninja — viewport-fit layout, no px for sizing */ + +:root { + --kn-bg: #eef6ff; + --kn-bg-secondary: #ffffff; + --kn-text: #1f2a44; + --kn-text-muted: #5b6b8c; + --kn-accent: #ff6b6b; + --kn-accent-2: #4d96ff; + --kn-success: #2ecc71; + --kn-danger: #ff5252; + --kn-gold: #f5b700; + --kn-card-shadow: 0 10px 28px rgba(31, 42, 68, 0.14); + --kn-radius: 14px; + + --kn-reserved: 195px; + --kn-sidebar-w: clamp(220px, 22vw, 290px); + --kn-gap: clamp(0.5rem, 0.8vw, 0.85rem); + --kn-pad: clamp(0.6rem, 1.1vw, 1.1rem); +} + +@media (prefers-color-scheme: dark) { + :root { + --kn-bg: #031a20; + --kn-bg-secondary: #052e38; + --kn-text: #e0f7fa; + --kn-text-muted: #7dd3fc; + --kn-accent: #fb7185; + --kn-accent-2: #22d3ee; + --kn-success: #34d399; + --kn-danger: #f87171; + --kn-gold: #fbbf24; + --kn-card-shadow: 0 10px 28px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(34, 211, 238, 0.08); + } +} + +[data-theme="dark"], +.dark { + --kn-bg: #031a20; + --kn-bg-secondary: #052e38; + --kn-text: #e0f7fa; + --kn-text-muted: #7dd3fc; + --kn-accent: #fb7185; + --kn-accent-2: #094697; + --kn-success: #34d399; + --kn-danger: #f87171; + --kn-gold: #fbbf24; + --kn-card-shadow: 0 10px 28px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(34, 211, 238, 0.08); +} + +/* ════════════════════════════════════════════ + DESKTOP — OUTER SHELL + ════════════════════════════════════════════ */ +.kn-outer { + display: flex; + flex-direction: column; + height: calc(100dvh - var(--kn-reserved)); + max-height: calc(100dvh - var(--kn-reserved)); + overflow: hidden; + box-sizing: border-box; + font-family: "Trebuchet MS", "Segoe UI", system-ui, sans-serif; + color: var(--kn-text); +} + +.kn-topbar { + flex-shrink: 0; + height: 2.4rem; + display: flex; + align-items: center; + padding: 0 var(--kn-pad); +} + +/* ════════════════════════════════════════════ + DESKTOP — PAGE LAYOUT + ════════════════════════════════════════════ */ +.kn-page-layout { + flex: 1 1 0; + min-height: 0; + display: flex; + flex-direction: row; + align-items: stretch; + gap: var(--kn-gap); + padding: 0 var(--kn-pad) var(--kn-gap); + box-sizing: border-box; + overflow: hidden; +} + +/* ════════════════════════════════════════════ + LEFT — GAME WRAPPER + ════════════════════════════════════════════ */ +.kn-wrapper { + flex: 1 1 0; + min-width: 0; + display: flex; + flex-direction: column; + align-items: center; + gap: var(--kn-gap); + overflow: hidden; +} + +/* ════════════════════════════════════════════ + SCOREBOARD + ════════════════════════════════════════════ */ +.kn-scoreboard-wrap { + width: 100%; + max-width: 680px; + margin: 0 auto; + display: flex; + flex-direction: column; + align-items: center; + gap: 0.25rem; + flex-shrink: 0; +} + +.kn-scoreboard { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: clamp(0.35rem, 0.6vw, 0.7rem); + width: 100%; +} + +.kn-score-item { + display: flex; + flex-direction: column; + align-items: center; + background: var(--kn-bg-secondary); + border-radius: 12px; + padding: clamp(0.3rem, 0.55vh, 0.5rem) clamp(0.55rem, 1vw, 0.9rem); + box-shadow: var(--kn-card-shadow); + min-width: clamp(58px, 7vw, 82px); +} + +.kn-score-label { + font-size: clamp(0.55rem, 0.75vw, 0.7rem); + text-transform: uppercase; + letter-spacing: 0.04em; + color: var(--kn-text-muted); +} + +.kn-score-value { + font-size: clamp(0.9rem, 1.3vw, 1.15rem); + font-weight: 700; +} + +.kn-powerup-badges { + display: flex; + gap: 0.4rem; + flex-wrap: wrap; + justify-content: center; +} + +.kn-powerup-badge { + background: var(--kn-gold); + color: #2a2200; + font-size: clamp(0.6rem, 0.75vw, 0.75rem); + font-weight: 700; + padding: 0.18rem 0.5rem; + border-radius: 999px; +} + +/* ════════════════════════════════════════════ + ARENA + ════════════════════════════════════════════ */ +.kn-arena { + position: relative; + width: 100%; + flex: 1 1 0; + min-height: 0; + background: var(--kn-bg-secondary); + border-radius: var(--kn-radius); + box-shadow: var(--kn-card-shadow); + overflow: hidden; +} + +/* ════════════════════════════════════════════ + CARDS — desktop: absolute centered in arena + ════════════════════════════════════════════ */ +.kn-card { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: min(88%, 420px); + max-height: 98%; + background: var(--kn-bg-secondary); + border-radius: var(--kn-radius); + box-shadow: var(--kn-card-shadow); + padding: clamp(1.4rem, 3.5vh, 2.5rem) clamp(0.9rem, 2vw, 1.5rem); + text-align: center; + overflow-y: auto; + scrollbar-width: none; +} + +.kn-card::-webkit-scrollbar { + display: none; +} + +.kn-title { + margin: 0 0 0.35rem; + font-size: clamp(1.15rem, 2vw, 1.65rem); +} + +.kn-subtitle { + margin: 0 0 0.8rem; + color: var(--kn-text-muted); + font-size: clamp(0.75rem, 1vw, 0.92rem); +} + +.kn-high-score-badge { + background: var(--kn-gold); + color: #3d2c00; + display: inline-flex; + align-items: center; + gap: 0.4rem; + font-weight: 700; + font-size: clamp(0.68rem, 0.88vw, 0.85rem); + padding: 0.25rem 0.75rem; + border-radius: 999px; + margin-bottom: 0.5rem; + animation: kn-badge-pop 0.45s cubic-bezier(0.175, 0.885, 0.32, 1.275); +} + +@keyframes kn-badge-pop { + 0% { + transform: scale(0.4); + opacity: 0; + } + + 100% { + transform: scale(1); + opacity: 1; + } +} + +/* ════════════════════════════════════════════ + LEVEL PICKER + ════════════════════════════════════════════ */ +.kn-level-picker { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.6rem; + margin-bottom: 1.6rem; +} + +.kn-level-btn { + border: 2px solid var(--kn-accent-2); + background: transparent; + color: var(--kn-accent-2); + border-radius: 999px; + padding: clamp(0.28rem, 0.5vh, 0.42rem) clamp(0.6rem, 1vw, 0.85rem); + font-weight: 600; + font-size: clamp(0.7rem, 0.92vw, 0.84rem); + cursor: pointer; + transition: + transform 150ms ease, + background 150ms ease, + color 150ms ease; +} + +.kn-level-btn:hover { + transform: translateY(-1px); +} + +.kn-level-btn-active { + background: var(--kn-accent-2); + color: #fff; +} + +.kn-start-btn { + border: none; + background: var(--kn-accent); + color: #fff; + font-size: clamp(0.88rem, 1.15vw, 1.02rem); + font-weight: 700; + padding: clamp(0.48rem, 0.9vh, 0.68rem) clamp(1rem, 2vw, 1.75rem); + border-radius: 999px; + cursor: pointer; + box-shadow: 0 6px 16px rgba(255, 107, 107, 0.4); + transition: transform 150ms ease; +} + +.kn-start-btn:hover { + transform: translateY(-2px) scale(1.03); +} + +.kn-countdown { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: clamp(2.4rem, 4.5vw, 3.8rem); + font-weight: 800; + color: var(--kn-accent-2); +} + +/* ════════════════════════════════════════════ + STATS LIST + ════════════════════════════════════════════ */ +.kn-stats-list { + list-style: none; + padding: 0; + margin: 0 0 clamp(0.45rem, 1vh, 1rem); + display: grid; + grid-template-columns: 1fr 1fr; + gap: 0.3rem; + text-align: left; +} + +.kn-stats-list li { + background: var(--kn-bg); + border-radius: 12px; + padding: 0.35rem 0.6rem 0.3rem; + border: 1.5px solid rgba(77, 150, 255, 0.12); + font-size: clamp(0.58rem, 0.78vw, 0.7rem); + color: var(--kn-text-muted); + text-transform: uppercase; + letter-spacing: 0.06em; + transition: transform 0.15s; +} + +.kn-stats-list li:hover { + transform: translateY(-2px); +} + +.kn-stats-list li:first-child { + background: linear-gradient(135deg, #fff7e0, #fff0c2); + border-color: #f5d060; +} + +.kn-stats-list li:first-child strong { + color: #a07200; +} + +[data-theme="dark"] .kn-stats-list li:first-child, +.dark .kn-stats-list li:first-child { + background: linear-gradient(135deg, rgba(251, 191, 36, 0.18), rgba(251, 191, 36, 0.08)); + border-color: rgba(251, 191, 36, 0.4); +} + +[data-theme="dark"] .kn-stats-list li:first-child strong, +.dark .kn-stats-list li:first-child strong { + color: #fde68a; +} + +.kn-stats-list strong { + font-size: clamp(1rem, 1.7vw, 1.4rem); + font-weight: 800; + color: var(--kn-text); + display: block; + line-height: 1.1; + margin-top: 0.12rem; +} + +/* ════════════════════════════════════════════ + SIDEBAR — desktop + ════════════════════════════════════════════ */ +.kn-sidebar { + width: var(--kn-sidebar-w); + flex-shrink: 0; + background: var(--kn-bg-secondary); + border-radius: var(--kn-radius); + box-shadow: var(--kn-card-shadow); + padding: var(--kn-pad); + box-sizing: border-box; + display: flex; + flex-direction: column; + justify-content: flex-start; + overflow: hidden; +} + +.kn-panel-heading { + font-size: clamp(0.78rem, 0.95vw, 0.92rem); + font-weight: 700; + margin: 0 0 0.4rem; + flex-shrink: 0; +} + +.kn-leaderboard { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 0.22rem; + flex-shrink: 0; +} + +.kn-leaderboard-row { + display: flex; + align-items: center; + gap: 0.4rem; + background: var(--kn-bg); + border-radius: 9px; + padding: clamp(0.22rem, 0.45vh, 0.35rem) clamp(0.38rem, 0.6vw, 0.58rem); + font-size: clamp(0.7rem, 0.88vw, 0.84rem); +} + +.kn-leaderboard-rank { + font-weight: 700; + color: var(--kn-text-muted); + width: 1.6rem; + flex-shrink: 0; +} + +.kn-leaderboard-score { + font-weight: 700; + flex: 1; +} + +.kn-leaderboard-level { + color: var(--kn-text-muted); + font-size: clamp(0.6rem, 0.72vw, 0.73rem); +} + +.kn-leaderboard-empty { + color: var(--kn-text-muted); + font-size: clamp(0.7rem, 0.88vw, 0.84rem); + margin: 0; +} + +.kn-achievements-heading-row { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: clamp(0.5rem, 1vh, 0.9rem); + margin-bottom: 0.4rem; + flex-shrink: 0; +} + +.kn-achievements { + flex: 0 0 auto; + display: flex; + flex-direction: column; + gap: 0.25rem; + overflow-y: auto; + scrollbar-width: thin; + scrollbar-color: rgba(77, 150, 255, 0.2) transparent; +} + +.kn-achievements::-webkit-scrollbar { + width: 3px; +} + +.kn-achievements::-webkit-scrollbar-thumb { + background: rgba(77, 150, 255, 0.25); + border-radius: 999px; +} + +.kn-achievement-badge { + display: flex; + align-items: center; + gap: 0.42rem; + background: var(--kn-bg); + border-radius: 9px; + padding: clamp(0.25rem, 0.5vh, 0.38rem) clamp(0.38rem, 0.7vw, 0.58rem); + font-size: clamp(0.67rem, 0.84vw, 0.8rem); + color: var(--kn-text-muted); + opacity: 0.6; + flex-shrink: 0; +} + +.kn-achievement-unlocked { + opacity: 1; + color: var(--kn-text); +} + +.kn-achievement-icon { + font-size: clamp(0.82rem, 1vw, 0.98rem); + flex-shrink: 0; +} + +.kn-achievement-progress { + font-size: clamp(0.57rem, 0.68vw, 0.65rem); + margin-left: auto; + color: var(--kn-text-muted); + opacity: 0.7; + white-space: nowrap; +} + +.kn-achievement-unlocked .kn-achievement-progress { + color: var(--kn-success); + opacity: 1; + font-weight: 700; +} + +/* ════════════════════════════════════════════ + TOAST + ════════════════════════════════════════════ */ +.kn-achievement-toast { + position: fixed; + top: 1rem; + right: 1rem; + z-index: 50; + display: flex; + align-items: center; + gap: 0.55rem; + background: var(--kn-gold); + color: #2a2200; + border-radius: 13px; + padding: 0.5rem 0.85rem; + box-shadow: var(--kn-card-shadow); + animation: kn-toast-in 220ms ease; +} + +.kn-achievement-toast-icon { + font-size: clamp(1rem, 1.4vw, 1.35rem); +} + +.kn-achievement-toast strong { + display: block; + font-size: clamp(0.7rem, 0.88vw, 0.84rem); +} + +.kn-achievement-toast p { + margin: 0; + font-size: clamp(0.62rem, 0.78vw, 0.78rem); +} + +@keyframes kn-toast-in { + from { + opacity: 0; + transform: translateY(-8px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +/* ════════════════════════════════════════════ + FALLING ITEMS + ════════════════════════════════════════════ */ +.kn-falling-item { + position: absolute; + top: -12%; + transform: translateX(-50%); + display: flex; + align-items: center; + gap: 0.15rem; + padding: clamp(0.25rem, 0.5vh, 0.4rem) clamp(0.4rem, 0.75vw, 0.62rem); + background: var(--kn-accent-2); + color: #fff; + border-radius: 0; + font-size: clamp(1rem, 1.7vw, 1.35rem); + font-weight: 800; + letter-spacing: 0.04em; + box-shadow: 0 6px 14px rgba(0, 0, 0, 0.25); + animation-name: kn-fall; + animation-timing-function: linear; + animation-fill-mode: forwards; + transition: + transform 200ms ease, + opacity 200ms ease; + -webkit-user-select: none; + user-select: none; +} + +.kn-item-target { + background: var(--kn-danger); +} + +.kn-item-powerup { + background: var(--kn-gold); + color: #2a2200; + box-shadow: 0 0 16px rgba(245, 183, 0, 0.6); +} + +.kn-powerup-icon { + font-size: clamp(0.82rem, 1.1vw, 1.05rem); +} + +.kn-item-sliced { + transform: translateX(-50%) scale(1.35); + opacity: 0; +} + +.kn-char-done { + color: #ffe066; +} + +@keyframes kn-fall { + 0% { + top: -12%; + } + + 100% { + top: 102%; + } +} + +/* ════════════════════════════════════════════ + START / CHANGELEVEL CARD + ════════════════════════════════════════════ */ +.kn-start-card, +.kn-changelevel-card { + padding: clamp(0.9rem, 2.2vh, 1.8rem) clamp(0.9rem, 1.8vw, 1.6rem); + overflow: visible; +} + +.kn-start-card::before, +.kn-gameover-card::before, +.kn-changelevel-card::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 4px; + background: linear-gradient(90deg, #ff6b6b, #f5b700, #4d96ff, #2ecc71, #ff6b6b); + background-size: 200% 100%; + animation: kn-bar-slide 2s linear infinite; +} + +@keyframes kn-bar-slide { + 0% { + background-position: 0%; + } + + 100% { + background-position: 200%; + } +} + +.kn-start-card .kn-title::before { + content: "⌨️"; + display: block; + font-size: 2.8rem; + margin-bottom: 0.4rem; + -webkit-text-fill-color: initial; + animation: kn-crown-bounce 1.2s ease infinite alternate; +} + +.kn-start-card .kn-title, +.kn-changelevel-card .kn-title { + font-size: 2.2rem; + font-weight: 800; + letter-spacing: -0.5px; + background: linear-gradient(135deg, var(--kn-accent), var(--kn-accent-2)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + margin-bottom: 0.5rem; +} + +.kn-changelevel-card .kn-title-emoji { + -webkit-text-fill-color: initial; + color: initial; +} + +.kn-start-card .kn-subtitle, +.kn-changelevel-card .kn-subtitle { + font-size: 1rem; + color: var(--kn-text-muted); + margin-bottom: 1.8rem; +} + +/* ════════════════════════════════════════════ + GAME OVER CARD + ════════════════════════════════════════════ */ +.kn-gameover-card { + padding: 0.5rem 1.25rem 0.6rem; + overflow: hidden; +} + +.kn-gameover-card .kn-title::before { + content: "🏆"; + display: block; + font-size: clamp(1.3rem, 2vw, 1.8rem); + margin-bottom: 0.08rem; + animation: kn-crown-bounce 1s ease infinite alternate; + -webkit-text-fill-color: initial; +} + +@keyframes kn-crown-bounce { + from { + transform: translateY(0); + } + + to { + transform: translateY(-6px); + } +} + +.kn-gameover-card .kn-title { + font-size: clamp(1.1rem, 1.85vw, 1.55rem); + font-weight: 800; + letter-spacing: -0.5px; + background: linear-gradient(135deg, var(--kn-accent), var(--kn-accent-2)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + margin-bottom: 0.35rem; +} + +.kn-gameover-card .kn-subtitle { + display: flex; + align-items: center; + gap: 0.55rem; + font-size: clamp(0.58rem, 0.76vw, 0.72rem); + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--kn-text-muted); + margin-bottom: 0.55rem; +} + +.kn-gameover-card .kn-subtitle::before, +.kn-gameover-card .kn-subtitle::after { + content: ""; + flex: 1; + height: 1px; + background: rgba(77, 150, 255, 0.18); +} + +/* ════════════════════════════════════════════ + ACHIEVEMENT FLASH + ════════════════════════════════════════════ */ +@keyframes kn-achievement-flash { + 0% { + background: var(--kn-bg); + } + + 30% { + background: rgba(46, 204, 113, 0.25); + transform: scale(1.03); + } + + 70% { + background: rgba(46, 204, 113, 0.15); + } + + 100% { + background: var(--kn-bg); + transform: scale(1); + } +} + +.kn-achievement-flash { + animation: kn-achievement-flash 1s ease; +} + +@media (prefers-reduced-motion: reduce) { + .kn-falling-item { + animation-duration: 1ms !important; + } +} + +/* ════════════════════════════════════════════ + TABLET 521px – 900px + Sidebar side mein rehta hai, cards content ke hisaab se + ════════════════════════════════════════════ */ +@media (min-width: 521px) and (max-width: 900px) { + :root { + --kn-reserved: 178px; + --kn-sidebar-w: 190px; + } + + /* kn-outer: height hatao, clip hatao, scroll do */ + .kn-outer { + height: auto !important; + max-height: none !important; + min-height: 0 !important; + overflow: visible !important; + } + + /* layout: row mein, clip bilkul nahi */ + .kn-page-layout { + flex-direction: row !important; + align-items: flex-start !important; + overflow: visible !important; + height: auto !important; + min-height: 0 !important; + flex: none !important; + padding-bottom: 1rem; + } + + /* wrapper: grow karo, clip mat karo */ + .kn-wrapper { + flex: 1 1 0 !important; + min-width: 0 !important; + height: auto !important; + overflow: visible !important; + } + + /* arena: transparent box, visible overflow */ + .kn-arena { + position: static !important; + background: transparent !important; + box-shadow: none !important; + overflow: visible !important; + height: auto !important; + min-height: unset !important; + flex: none !important; + border-radius: 0 !important; + width: 100% !important; + } + + /* card: normal flow */ + .kn-card { + position: relative !important; + top: auto !important; + left: auto !important; + transform: none !important; + margin: 0.5rem auto !important; + width: 92% !important; + min-height: unset !important; + max-height: unset !important; + } + + /* sidebar: hard fixed width, force visible */ + .kn-sidebar { + display: flex !important; + visibility: visible !important; + width: 190px !important; + min-width: 190px !important; + max-width: 190px !important; + flex-shrink: 0 !important; + flex-direction: column !important; + overflow-y: auto !important; + overflow-x: hidden !important; + position: sticky !important; + top: 0 !important; + align-self: flex-start !important; + max-height: 85vh !important; + background: var(--kn-bg-secondary) !important; + border-radius: var(--kn-radius) !important; + box-shadow: var(--kn-card-shadow) !important; + padding: var(--kn-pad) !important; + } + + .kn-achievements { + flex: none !important; + } +} + +/* ════════════════════════════════════════════ + MOBILE ≤ 520px + ════════════════════════════════════════════ */ +@media (max-width: 520px) { + :root { + --kn-reserved: 188px; + } + + .kn-outer { + height: auto; + max-height: none; + min-height: calc(100dvh - var(--kn-reserved)); + overflow-y: auto; + } + + .kn-page-layout { + flex-direction: column; + overflow: visible !important; + padding-bottom: 1rem; + } + + .kn-wrapper { + height: auto !important; + min-height: 520px; + overflow: visible; + } + + .kn-arena { + min-height: 480px !important; + overflow: hidden !important; + background: var(--kn-bg-secondary) !important; + box-shadow: var(--kn-card-shadow) !important; + } + + .kn-card { + width: min(92%, 340px) !important; + min-height: 62% !important; + max-height: 90% !important; + top: 45% !important; + left: 50% !important; + transform: translate(-50%, -45%) !important; + position: absolute !important; + } + + .kn-start-card, + .kn-gameover-card, + .kn-changelevel-card { + min-height: 260px !important; + padding: 1rem !important; + } + + .kn-start-card .kn-title, + .kn-changelevel-card .kn-title { + font-size: 1.8rem; + } + + .kn-start-card .kn-subtitle, + .kn-changelevel-card .kn-subtitle { + margin-bottom: 1rem; + } + + .kn-level-picker { + display: flex; + justify-content: center; + gap: 0.45rem; + flex-wrap: nowrap; + } + + .kn-level-btn { + min-width: 72px; + height: 34px; + padding: 0 12px; + font-size: 0.72rem; + border-radius: 999px; + display: inline-flex; + align-items: center; + justify-content: center; + white-space: nowrap; + } + + .kn-start-btn { + min-width: 110px; + height: 42px; + padding: 0 20px; + font-size: 0.9rem; + } + + /* sidebar mobile pe neeche full width */ + .kn-sidebar { + width: 100% !important; + position: static !important; + max-height: none !important; + overflow: visible !important; + } + + .kn-stats-list { + grid-template-columns: 1fr 1fr; + gap: 0.28rem; + } + + .kn-achievement-toast { + left: 0.75rem; + right: 0.75rem; + } +} + +/* ════════════════════════════════════════════ + WINDOWS-STYLE TITLEBAR + ════════════════════════════════════════════ */ +:root { + --kn-titlebar-bg: #f3f3f3; + --kn-titlebar-text: #1a1a1a; + --kn-titlebar-h: 32px; +} + +[data-theme="dark"], +.dark { + --kn-titlebar-bg: #1e2533; + --kn-titlebar-text: #e0f7fa; +} + +@media (prefers-color-scheme: dark) { + :root { + --kn-titlebar-bg: #1e2533; + --kn-titlebar-text: #e0f7fa; + } +} + +.kn-outer { + /* titlebar height account karo */ + height: calc(100dvh - var(--kn-reserved)) !important; + max-height: calc(100dvh - var(--kn-reserved)) !important; +} + +.kn-titlebar { + flex-shrink: 0; + height: var(--kn-titlebar-h); + background: var(--kn-titlebar-bg); + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + display: flex; + align-items: center; + padding: 0 0 0 10px; + gap: 7px; + user-select: none; +} + +[data-theme="dark"] .kn-titlebar, +.dark .kn-titlebar { + border-bottom-color: rgba(255, 255, 255, 0.06); +} + +.kn-titlebar-icon { + font-size: 13px; + line-height: 1; +} + +.kn-titlebar-title { + font-size: 12px; + font-weight: 400; + color: var(--kn-titlebar-text); + flex: 1; + opacity: 0.85; + letter-spacing: 0.01em; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.kn-titlebar-controls { + display: flex; + height: var(--kn-titlebar-h); + margin-left: auto; +} + +.kn-tb-btn { + width: 46px; + height: var(--kn-titlebar-h); + display: flex; + align-items: center; + justify-content: center; + background: transparent; + border: none; + cursor: pointer; + color: var(--kn-titlebar-text); + transition: background 80ms ease; + padding: 0; +} + +.kn-tb-maximize:hover { + background: rgba(0, 0, 0, 0.08); +} + +[data-theme="dark"] .kn-tb-maximize:hover, +.dark .kn-tb-maximize:hover { + background: rgba(255, 255, 255, 0.1); +} + +/* ════════════════════════════════════════════ + MAXIMIZED STATE + ════════════════════════════════════════════ */ +.kn-sidebar { + transition: + opacity 200ms ease, + width 200ms ease; +} + +.kn-sidebar-hidden { + opacity: 0 !important; + width: 0 !important; + min-width: 0 !important; + padding: 0 !important; + overflow: hidden !important; + pointer-events: none !important; +} + +.kn-maximized .kn-wrapper { + max-width: 100%; +} + +/* Mobile pe titlebar hide karo — jagah kam hai */ +@media (max-width: 520px) { + .kn-titlebar { + display: none; + } +} + +/* ════════════════════════════════════════════ + FULLSCREEN MODE — header/footer hide + ════════════════════════════════════════════ */ +body.kn-fullscreen header, +body.kn-fullscreen nav, +body.kn-fullscreen footer, +body.kn-fullscreen .search-bar, +body.kn-fullscreen [class*="search"], +body.kn-fullscreen [class*="header"], +body.kn-fullscreen [class*="navbar"], +body.kn-fullscreen [class*="nav-"], +body.kn-fullscreen [class*="footer"] { + display: none !important; +} + +body.kn-fullscreen .kn-outer { + position: fixed !important; + inset: 0 !important; + z-index: 9990 !important; + height: 100dvh !important; + max-height: 100dvh !important; +} + +/* ════════════════════════════════════════════ + MAXIMIZE — card natural height, content center + ════════════════════════════════════════════ */ +body.kn-fullscreen .kn-card { + min-height: unset !important; + max-height: 90% !important; + width: min(88%, 480px) !important; +} + +body.kn-fullscreen .kn-start-card, +body.kn-fullscreen .kn-changelevel-card { + padding: clamp(2rem, 4vh, 3.5rem) clamp(1.2rem, 3vw, 2rem) !important; +} + +body.kn-fullscreen .kn-start-card .kn-title::before { + font-size: 3.5rem !important; +} + +body.kn-fullscreen .kn-start-card .kn-title, +body.kn-fullscreen .kn-changelevel-card .kn-title { + font-size: clamp(1.8rem, 3vw, 2.8rem) !important; +} + +body.kn-fullscreen .kn-start-card .kn-subtitle, +body.kn-fullscreen .kn-changelevel-card .kn-subtitle { + font-size: clamp(0.9rem, 1.2vw, 1.1rem) !important; + margin-bottom: 2rem !important; +} + +body.kn-fullscreen .kn-level-btn { + padding: 0.5rem 1.2rem !important; + font-size: clamp(0.82rem, 1vw, 0.96rem) !important; +} + +body.kn-fullscreen .kn-level-picker { + margin-bottom: 2rem !important; + gap: 0.75rem !important; +} + +body.kn-fullscreen .kn-start-btn { + padding: 0.75rem 2.2rem !important; + font-size: 1.05rem !important; +} + +/* Toast — maximize pe hide karo */ +body.kn-fullscreen .kn-achievement-toast { + display: none !important; +} + +/* Arena maximize button */ +.kn-arena-maximize { + position: absolute; + top: 0.5rem; + right: 0.5rem; + z-index: 10; + width: 32px; + height: 32px; + background: var(--kn-bg); + border: 1px solid rgba(100, 100, 100, 0.2); + border-radius: 6px; + color: var(--kn-text-muted); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: + background 120ms ease, + color 120ms ease; +} + +.kn-arena-maximize:hover { + background: var(--kn-accent-2); + color: #fff; + border-color: transparent; +} + +.kn-titlebar { + display: none !important; +} + +/* ════════════════════════════════════════════ + SHATTER MISS ANIMATION + ════════════════════════════════════════════ */ +.kn-shatter-wrap { + position: absolute; + width: 44px; + height: 44px; + pointer-events: none; + z-index: 5; + transform: translateX(-50%); +} + +.kn-shard { + position: absolute; + width: 22px; + height: 22px; + background: var(--kn-danger); +} + +.kn-shard-char { + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + color: #fff; + font-size: 0.65rem; + font-weight: 800; +} +/* Slice = green shards */ +.kn-shard-hit { + background: var(--kn-success) !important; +} + +@keyframes kn-shard-tl { + 0% { + transform: translate(0, 0) rotate(0deg); + opacity: 1; + } + + 100% { + transform: translate(-35px, -50px) rotate(-60deg); + opacity: 0; + } +} + +@keyframes kn-shard-tr { + 0% { + transform: translate(0, 0) rotate(0deg); + opacity: 1; + } + + 100% { + transform: translate(35px, -50px) rotate(60deg); + opacity: 0; + } +} + +@keyframes kn-shard-bl { + 0% { + transform: translate(0, 0) rotate(0deg); + opacity: 1; + } + + 100% { + transform: translate(-35px, 50px) rotate(60deg); + opacity: 0; + } +} + +@keyframes kn-shard-br { + 0% { + transform: translate(0, 0) rotate(0deg); + opacity: 1; + } + + 100% { + transform: translate(35px, 50px) rotate(-60deg); + opacity: 0; + } +} + +.kn-shard-tl { + top: 0; + left: 0; + animation: kn-shard-tl 550ms cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; +} + +.kn-shard-tr { + top: 0; + right: 0; + animation: kn-shard-tr 550ms cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; +} + +.kn-shard-bl { + bottom: 0; + left: 0; + animation: kn-shard-bl 550ms cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; +} + +.kn-shard-br { + bottom: 0; + right: 0; + animation: kn-shard-br 550ms cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; +} + +/* Flash overlay */ +@keyframes kn-miss-flash { + 0% { + opacity: 0.45; + } + + 100% { + opacity: 0; + } +} + +.kn-miss-flash { + position: absolute; + inset: 0; + background: #ef4444; + pointer-events: none; + z-index: 4; + border-radius: var(--kn-radius); + animation: kn-miss-flash 300ms ease forwards; +} +/* ════════════════════════════════════════════ + PER-ITEM COUNTDOWN + ════════════════════════════════════════════ */ +.kn-item-countdown { + position: absolute; + top: -22px; + left: 50%; + transform: translateX(-50%); + font-size: 0.75rem; + font-weight: 800; + color: #fff; + background: var(--kn-danger); + border-radius: 999px; + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + transition: opacity 150ms ease; + pointer-events: none; +} + +.kn-countdown-active { + opacity: 1; + animation: kn-countdown-pulse 1s ease infinite; +} + +@keyframes kn-countdown-pulse { + 0%, + 100% { + transform: translateX(-50%) scale(1); + } + + 50% { + transform: translateX(-50%) scale(1.25); + } +} + diff --git a/src/assets/styles/landing.css b/src/assets/styles/landing.css index 23ef136a..21b8a1d6 100644 --- a/src/assets/styles/landing.css +++ b/src/assets/styles/landing.css @@ -285,13 +285,13 @@ flex-wrap: wrap; justify-content: center; gap: 1.5rem; - padding: 0.5rem 0; + padding: 0.5rem 4rem; } .games-grid--centered .game-card { - width: 380px; - flex: 0 0 380px; + flex: 0 0 calc(33.33% - 1rem); max-width: calc(33.33% - 1rem); + min-width: 260px; } .games-grid--full { diff --git a/src/components/Categories.astro b/src/components/Categories.astro index 1df6f5ca..03185139 100644 --- a/src/components/Categories.astro +++ b/src/components/Categories.astro @@ -77,13 +77,10 @@ diff --git a/src/components/GamesGrid.astro b/src/components/GamesGrid.astro index f332736a..42a30a6f 100644 --- a/src/components/GamesGrid.astro +++ b/src/components/GamesGrid.astro @@ -6,16 +6,9 @@ interface Props { } const { games } = Astro.props; -const isCentered = games.length <= 3; --- - - -
+
We're working hard to bring you the best experience.
+Slice the falling letters before they hit the ground!
+ +Pick a new challenge and dive back in!
+ +🏆 New High Score!
+Your Stats
+