diff --git a/.all-contributorsrc b/.all-contributorsrc index 1f38159..3e9a555 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1,348 +1,8 @@ { - "files": [ - "README.md" - ], - "imageSize": 100, - "commit": false, - "contributors": [{ - "login": "ashutosh1919", - "name": "Ashutosh Hathidara", - "avatar_url": "https://avatars3.githubusercontent.com/u/20843596?s=460&u=7f184b911f73ae1dc5765ab686fff2b2e984830f&v=4", - "profile": "http://ashutosh1919.github.io", - "contributions": [ - "code", - "doc", - "design", - "maintenance", - "ideas" - ] - }, + "contributors": [ { - "login": "danielmarostica", - "name": "Daniel Marostica", - "avatar_url": "https://avatars3.githubusercontent.com/u/3595998?v=4", - "profile": "https://danielmarostica.github.io/", - "contributions": [ - "doc", - "design" - ] - }, - { - "login": "dineshnadimpalli", - "name": "Dinesh Nadimpalli", - "avatar_url": "https://avatars2.githubusercontent.com/u/13104926?v=4", - "profile": "https://dineshnadimpalli.com", - "contributions": [ - "code" - ] - }, - { - "login": "jivthesh", - "name": "Jivthesh M R", - "avatar_url": "https://avatars3.githubusercontent.com/u/20579980?v=4", - "profile": "http://jivthesh.github.io", - "contributions": [ - "doc" - ] - }, - { - "login": "mrjatinchauhan", - "name": "Jatin Chauhan", - "avatar_url": "https://avatars2.githubusercontent.com/u/40722235?v=4", - "profile": "http://jatinchauhan.tech", - "contributions": [ - "code" - ] - }, - { - "login": "th3c0d3br34ker", - "name": "Jainam Desai", - "avatar_url": "https://avatars1.githubusercontent.com/u/60807938?v=4", - "profile": "https://th3c0d3br34ker.github.io/", - "contributions": [ - "code", - "question" - ] - }, - { - "login": "Tasin5541", - "name": "Miftaul Mannan", - "avatar_url": "https://avatars0.githubusercontent.com/u/42533823?v=4", - "profile": "https://miftaulmannan.wordpress.com/", - "contributions": [ - "code" - ] - }, - { - "login": "a-mishra", - "name": "Ashutosh Mishra", - "avatar_url": "https://avatars0.githubusercontent.com/u/10567548?v=4", - "profile": "http://a-mishra.github.io", - "contributions": [ - "code" - ] - }, - { - "login": "tamojit-123", - "name": "Tamojit", - "avatar_url": "https://avatars0.githubusercontent.com/u/40804626?v=4", - "profile": "http://tamojit.wixsite.com/mrtamojit", - "contributions": [ - "doc", - "code", - "design" - ] - }, - { - "login": "githubprabin143", - "name": "Prabin Karki", - "avatar_url": "https://avatars.githubusercontent.com/u/43983896?v=4", - "profile": "https://prabin-karki.com.np", - "contributions": [ - "code" - ] - }, - { - "login": "praveenscience", - "name": "Praveen Kumar Purushothaman", - "avatar_url": "https://avatars.githubusercontent.com/u/1830380?v=4", - "profile": "https://praveen.science/", - "contributions": [ - "doc" - ] - }, - { - "login": "baulml", - "name": "paul", - "avatar_url": "https://avatars.githubusercontent.com/u/33395806?v=4", - "profile": "http://baul.ml", - "contributions": [ - "code" - ] - }, - { - "login": "SandipDhang", - "name": "Sandip Dhang", - "avatar_url": "https://avatars.githubusercontent.com/u/50694884?v=4", - "profile": "https://github.com/SandipDhang", - "contributions": [ - "code" - ] - }, - { - "login": "ioribrn", - "name": "Jawad Moustadif", - "avatar_url": "https://avatars.githubusercontent.com/u/43734587?v=4", - "profile": "https://github.com/ioribrn", - "contributions": [ - "code" - ] - }, - { - "login": "priyanshk20", - "name": "Priyansh Khandelwal", - "avatar_url": "https://avatars.githubusercontent.com/u/52736997?v=4", - "profile": "https://github.com/priyanshk20", - "contributions": [ - "code", - "design" - ] - }, - { - "login": "abdslam01", - "name": "Abdessalam Bahafid", - "avatar_url": "https://avatars.githubusercontent.com/u/59281502?v=4", - "profile": "https://github.com/abdslam01", - "contributions": [ - "code" - ] - }, - { - "login": "dhruvkrishnavaid", - "name": "Dhruv Krishna Vaid", - "avatar_url": "https://avatars.githubusercontent.com/u/69188774?v=4", - "profile": "https://dhruvkrishnavaid.github.io", - "contributions": [ - "code", - "doc", - "ideas", - "question" - ] - }, - { - "login": "KasRoudra", - "name": "KasRoudra", - "avatar_url": "https://avatars.githubusercontent.com/u/78908440?v=4", - "profile": "https://kasroudra.github.io", - "contributions": [ - "code" - ] - }, - { - "login": "AlbertEinsteinTG", - "name": "Albert Einstein", - "avatar_url": "https://avatars.githubusercontent.com/u/73480087?v=4", - "profile": "https://telegram.dog/AlbertEinstein_TG", - "contributions": [ - "doc" - ] - }, - { - "login": "SurajPratap10", - "name": "Suraj Pratap", - "avatar_url": "https://avatars.githubusercontent.com/u/92919173?v=4", - "profile": "https://github.com/SurajPratap10", - "contributions": [ - "doc" - ] - }, - { - "login": "saiteja13427", - "name": "Sai Teja", - "avatar_url": "https://avatars.githubusercontent.com/u/40917760?v=4", - "profile": "https://lightmap.dev", - "contributions": [ - "code", - "doc", - "maintenance", - "ideas" - ] - }, - { - "login": "AnirudhPanda", - "name": "Anirudh Panda", - "avatar_url": "https://avatars.githubusercontent.com/u/66218496?v=4", - "profile": "https://anirudhpanda.in/", - "contributions": [ - "code" - ] - }, - { - "login": "hidayat7z", - "name": "Md Hidayat Rasool", - "avatar_url": "https://avatars.githubusercontent.com/u/63554016?v=4", - "profile": "https://hidayat7z.github.io", - "contributions": [ - "doc" - ] - }, - { - "login": "SiddhantSadangi", - "name": "Siddhant Sadangi", - "avatar_url": "https://avatars.githubusercontent.com/u/41324509?v=4", - "profile": "https://www.linkedin.com/in/siddhantsadangi/", - "contributions": [ - "doc" - ] - }, - { - "login": "vanoop729", - "name": "Anoop V", - "avatar_url": "https://avatars.githubusercontent.com/u/59723767?v=4", - "profile": "https://anoopvarghese.in/", - "contributions": [ - "code" - ] - }, - { - "login": "aash1999", - "name": "Aakash Singh", - "avatar_url": "https://avatars.githubusercontent.com/u/39939476?v=4", - "profile": "https://github.com/aash1999", - "contributions": [ - "code" - ] - }, - { - "login": "aherrera3", - "name": "AngΓ©lica Herrera Alba", - "avatar_url": "https://avatars.githubusercontent.com/u/52289646?v=4", - "profile": "https://aherrera3.github.io/", - "contributions": [ - "code" - ] - }, - { - "login": "dminkovski", - "name": "David Minkovski", - "avatar_url": "https://avatars.githubusercontent.com/u/1609264?v=4", - "profile": "https://davidminkovski.com", - "contributions": [ - "ideas", - "code" - ] - }, - { - "login": "cdigruttola", - "name": "Carmine Di Gruttola", - "avatar_url": "https://avatars.githubusercontent.com/u/9153905?v=4", - "profile": "http://cdigruttola.it", - "contributions": [ - "ideas", - "promotion" - ] - }, - { - "login": "Vyomrana02", - "name": "Vyom Rana", - "avatar_url": "https://avatars.githubusercontent.com/u/87069619?v=4", - "profile": "https://github.com/Vyomrana02", - "contributions": [ - "code" - ] - }, - { - "login": "parthrc", - "name": "Parth Chawande", - "avatar_url": "https://avatars.githubusercontent.com/u/101104958?v=4", - "profile": "https://github.com/parthrc", - "contributions": [ - "code" - ] - }, - { - "login": "0Armaan025", - "name": "Armaan", - "avatar_url": "https://avatars.githubusercontent.com/u/104704093?v=4", - "profile": "https://github.com/0Armaan025", - "contributions": [ - "doc" - ] - }, - { - "login": "varundhand", - "name": "Varun Dhand", - "avatar_url": "https://avatars.githubusercontent.com/u/110025628?v=4", - "profile": "https://varundhand.netlify.app/", - "contributions": [ - "code" - ] - }, - { - "login": "vjspranav", - "name": "VJS Pranavasri", - "avatar_url": "https://avatars.githubusercontent.com/u/17949836?v=4", - "profile": "http://vjspranav.dev", - "contributions": [ - "code" - ] - }, - { - "login": "Rahulkush1", - "name": "Rahul Kushwaha", - "avatar_url": "https://avatars.githubusercontent.com/u/90745824?v=4", - "profile": "https://rahulkush1.github.io/", - "contributions": [ - "code" - ] + "id": "Leguna", + "github": "https://github.com/Leguna" } - ], - "contributorsPerLine": 7, - "projectName": "masterPortfolio", - "projectOwner": "ashutosh1919", - "repoType": "github", - "repoHost": "https://github.com", - "skipCi": true, - "commitConvention": "angular", - "commitType": "docs" -} + ] +} \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 4652ed3..601f4a4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -4,7 +4,7 @@ module.exports = { es6: true, node: true, }, - extends: ["plugin:react/recommended"], + extends: ["react-app"], globals: { Atomics: "readonly", SharedArrayBuffer: "readonly", @@ -15,6 +15,5 @@ module.exports = { }, ecmaVersion: 2018, }, - plugins: ["react"], rules: {}, }; diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c8535fd..aa5562b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,81 +1,85 @@ -# πŸš€ Contributing to the MasterPortfolio Project +f +i -Thank you for considering contributing to the MasterPortfolio project! Your help is greatly appreciated. 😊 +If you'd like to contribute to our source code, please follow these steps: -## 🀝 How to Contribute +1. **Fork the repository**: Clone the project and create a new branch for your changes. +2. **Create an issue**: Report any issues or bugs you encounter in the GitHub issues section. +3. **Submit a pull request**: Once you've made some changes, submit them as a pull request. -Here are some fun and precise steps to get you started: +## Guidelines -1. **Fork the Repository** 🍴 +When contributing to our source code, please follow these guidelines: - - Click the "Fork" button on the top right of the [MasterPortfolio repository](https://github.com/ashutosh1919/masterPortfolio) page on GitHub. This will create a copy of the project in your own GitHub account. +- **Code style**: Adhere to the existing code style and formatting. +- **Testing**: Write unit tests for any new features or bug fixes. +- **Documentation**: Update documentation as needed to reflect changes. -2. **Clone Your Fork** πŸ§™β€β™‚οΈ +## Code of Conduct - - In your terminal, run the following command to clone your fork to your local machine: - ``` - git clone https://github.com/YourUsername/masterPortfolio.git - ``` +By contributing to this project, you agree to abide by our code of conduct. Please review it [here](CODE_OF_CONDUCT.md). -3. **Switch to the Project Directory** πŸ“ +## Contributing Guidelines for Specific Sections - - Move into the project directory using: - ``` - cd masterPortfolio - ``` +### Documentation -4. **Move to Gatsby** πŸš€ +- Ensure the changes are clearly described in the commit message. +- Write a clear and concise description of the change in the pull request. - - If you're working on this task, please help us migrate the project to Gatsby. Make the necessary changes and test everything to ensure it works smoothly. +### Code Changes -5. **Add Podcast and Video Sections** πŸŽ™οΈπŸ“Ή +- Ensure all new features or bug fixes include unit tests. +- Refactor existing code to improve readability and maintainability. - - We'd love to have sections for podcasts and videos on the portfolio. Create these sections and make sure they look fantastic. +## How We Use Your Contributions -6. **Add Tests for Automation** πŸ§ͺ +We welcome any contributions, from small bug fixes to large feature additions. When reviewing your contributions, we'll consider factors such as: - - To ensure code quality, add tests where appropriate. Use test frameworks like Jest or Cypress, and make sure the tests pass. +- **Code quality**: Will the changes improve the overall quality of the project? +- **Usefulness**: Are the changes useful and relevant to our users? -7. **Set Up Travis Workflow** πŸ€– +## Commit Messages - - Implement a Travis CI workflow to automate builds and testing. This will help ensure that changes don't break the project. +Commit messages should follow standard guidelines: -8. **Create a Branch** 🌿 +- Keep it concise. +- Use imperative mood (e.g., "Add feature X"). +- Include a brief description. - - Create a new branch for your changes with a descriptive name. For example: - ``` - git checkout -b gatsby-migration - ``` +By following these guidelines, we can ensure that your contributions are properly incorporated into the project. -9. **Make Your Changes** πŸ’‘ +### Contributing Guidelines for Contributors with Vested Interest - - Implement your awesome changes and features. +If you're contributing to our source code as part of a professional engagement or in pursuit of personal gain, please note: -10. **Commit Your Changes** πŸ“ +- **Conflicts of interest**: If you have any conflicts of interest, disclose them in the pull request. +- **Intellectual property**: Ensure that your contributions don't infringe on existing intellectual property. - - Commit your changes with a descriptive message. For example: - ``` - git commit -m "Added Gatsby migration and podcast section" - ``` +## Contributing Guidelines for New Features -11. **Push Your Changes** 🚒 +When introducing new features, consider: - - Push your changes to your fork on GitHub: - ``` - git push origin gatsby-migration - ``` +- **User feedback**: Consult with users and stakeholders to ensure the feature meets their needs. +- **Documentation**: Provide clear documentation for any new features. -12. **Create a Pull Request** πŸ™Œ +By following these guidelines, we can ensure that your contributions are of high quality and align with our project goals. - - Go to your fork on GitHub, and click the "New Pull Request" button. Follow the prompts, and submit your changes for review. +## Contributing Guidelines for Bug Fixes -13. **Celebrate** πŸŽ‰ - - You've contributed to the MasterPortfolio project! Thanks for your hard work and dedication. +When fixing bugs: -## πŸ“Œ Issues +- **Test thoroughly**: Verify that the fix doesn't introduce any regressions. +- **Document changes**: Document the bug, including any relevant information about the issue. -If you encounter any issues or have ideas for improvements, please open an [issue](https://github.com/ashutosh1919/masterPortfolio/issues) and let us know. +## Frequently Asked Questions (FAQ) -## πŸ™ Thank You +- Q: What if I encounter an issue while contributing? + A: Report it in the GitHub issues section and we'll help you troubleshoot or provide a fix. +- Q: Can I contribute to specific sections of the codebase? + A: Yes, please review our [contributing guidelines](#code-of-conduct) for specifics. -We appreciate your contribution and look forward to working together to make the MasterPortfolio project even better! πŸ˜„πŸš€ +## Maintainer's Contact Information + +If you have any questions or need assistance with contributing: + +Email: ahmadtuflihunxd@gmail.com diff --git a/src/components/competitiveSites/CompetitiveSites.js b/src/components/competitiveSites/CompetitiveSites.js index fb22748..65ee726 100644 --- a/src/components/competitiveSites/CompetitiveSites.js +++ b/src/components/competitiveSites/CompetitiveSites.js @@ -31,7 +31,12 @@ class CompetitiveSites extends React.Component { style={logo.style} data-inline="false" > - + diff --git a/src/containers/Main.js b/src/containers/Main.js index 7f48141..c615956 100644 --- a/src/containers/Main.js +++ b/src/containers/Main.js @@ -2,6 +2,7 @@ import React, { Component } from "react"; import { Route, Switch, HashRouter } from "react-router-dom"; import Home from "../pages/home/HomeComponent"; import Splash from "../pages/splash/Splash"; +import Desktop from "../pages/desktop/Desktop"; import Education from "../pages/education/EducationComponent"; import Experience from "../pages/experience/Experience"; import Opensource from "../pages/opensource/Opensource"; @@ -80,9 +81,9 @@ export default class Main extends Component {
+ } /> } /> ; + return ; } } diff --git a/src/containers/skills/IotImg.js b/src/containers/skills/IotImg.js index d5813db..c8c8607 100644 --- a/src/containers/skills/IotImg.js +++ b/src/containers/skills/IotImg.js @@ -2,7 +2,6 @@ import React, { Component } from "react"; export default class IotImg extends Component { render() { - const theme = this.props.theme; - return ; + return ; } } diff --git a/src/pages/desktop/AppWindow.js b/src/pages/desktop/AppWindow.js new file mode 100644 index 0000000..57fe1a2 --- /dev/null +++ b/src/pages/desktop/AppWindow.js @@ -0,0 +1,214 @@ +import React, { useState, useRef, useEffect } from "react"; + +export default function AppWindow({ + title, + icon, + children, + zIndex, + isActive, + defaultPos = { x: 100, y: 60 }, + defaultSize = { width: 800, height: 520 }, + onClose, + onMinimize, + onFocus, +}) { + const [pos, setPos] = useState(defaultPos); + const [isMaximized, setIsMaximized] = useState(false); + const [isMobile, setIsMobile] = useState(false); + const savedPos = useRef(defaultPos); + const dragging = useRef(false); + const dragOffset = useRef({ x: 0, y: 0 }); + + useEffect(() => { + const onMove = (e) => { + if (!dragging.current) return; + setPos({ + x: Math.max(0, e.clientX - dragOffset.current.x), + y: Math.max(0, e.clientY - dragOffset.current.y), + }); + }; + const onUp = () => { + dragging.current = false; + }; + const updateViewport = () => { + setIsMobile(window.innerWidth <= 768); + }; + + updateViewport(); + window.addEventListener("mousemove", onMove); + window.addEventListener("mouseup", onUp); + window.addEventListener("resize", updateViewport); + + return () => { + window.removeEventListener("mousemove", onMove); + window.removeEventListener("mouseup", onUp); + window.removeEventListener("resize", updateViewport); + }; + }, []); + + const onBarMouseDown = (e) => { + if (e.button !== 0 || isMaximized || isMobile) return; + dragging.current = true; + dragOffset.current = { x: e.clientX - pos.x, y: e.clientY - pos.y }; + onFocus(); + e.preventDefault(); + }; + + const toggleMax = () => { + if (isMaximized) { + setPos(savedPos.current); + setIsMaximized(false); + } else { + savedPos.current = pos; + setIsMaximized(true); + } + }; + + const viewportWidth = typeof window !== "undefined" ? window.innerWidth : 1280; + const viewportHeight = typeof window !== "undefined" ? window.innerHeight : 900; + const responsiveWidth = isMobile + ? "100vw" + : Math.min(defaultSize.width, Math.max(280, viewportWidth - 16)); + const responsiveHeight = isMobile + ? "calc(100dvh - 48px)" + : Math.min(defaultSize.height, Math.max(180, viewportHeight - 64)); + const style = isMaximized || isMobile + ? { + position: "fixed", + left: 0, + top: 0, + width: "100vw", + height: "calc(100dvh - 48px)", + borderRadius: 0, + zIndex, + maxWidth: "100vw", + maxHeight: "calc(100dvh - 48px)", + } + : { + position: "fixed", + left: Math.min(pos.x, Math.max(0, viewportWidth - responsiveWidth - 8)), + top: Math.min(pos.y, Math.max(0, viewportHeight - responsiveHeight - 56)), + width: responsiveWidth, + height: responsiveHeight, + zIndex, + maxWidth: `calc(100vw - 16px)`, + maxHeight: `calc(100dvh - 64px)`, + }; + + return ( +
+
+ {icon} + {title} +
+ + + +
+
+ +
{children}
+
+ ); +} + +function MinimizeIcon() { + return ( + + + + ); +} + +function MaximizeIcon() { + return ( + + + + ); +} + +function RestoreIcon() { + return ( + + + + + ); +} + +function CloseIcon() { + return ( + + + + + ); +} diff --git a/src/pages/desktop/Desktop.css b/src/pages/desktop/Desktop.css new file mode 100644 index 0000000..8589b83 --- /dev/null +++ b/src/pages/desktop/Desktop.css @@ -0,0 +1,1503 @@ +/* ═══════════════════════════════════════════════════════════════ + Windows 11 Desktop Clone – Desktop.css + ═══════════════════════════════════════════════════════════════ */ + +/* ── Base ──────────────────────────────────────────────────────── */ +.win11-desktop { + position: fixed; + inset: 0; + width: 100vw; + height: 100dvh; + min-height: 100dvh; + overflow: hidden; + font-family: "Segoe UI", system-ui, -apple-system, BlinkMacSystemFont, + sans-serif; + user-select: none; + /* Win11 "Bloom" wallpaper approximation */ + background: radial-gradient( + ellipse 120% 80% at 10% 65%, + rgba(0, 90, 210, 0.75) 0%, + transparent 55% + ), + radial-gradient( + ellipse 70% 90% at 90% 15%, + rgba(120, 20, 200, 0.65) 0%, + transparent 50% + ), + radial-gradient( + ellipse 60% 60% at 85% 85%, + rgba(20, 60, 190, 0.55) 0%, + transparent 50% + ), + radial-gradient( + ellipse 50% 50% at 50% 50%, + rgba(255, 110, 180, 0.08) 0%, + transparent 50% + ), + radial-gradient( + ellipse 40% 40% at 40% 30%, + rgba(30, 200, 220, 0.12) 0%, + transparent 50% + ), + #080d22; +} + +/* ── Weather Widget ─────────────────────────────────────────── */ +.desktop-weather-widget { + position: absolute; + top: 16px; + right: 16px; + z-index: 20; + width: min(280px, calc(100vw - 32px)); + padding: 14px 14px 12px; + border-radius: 16px; + background: rgba(15, 23, 42, 0.78); + border: 1px solid rgba(255, 255, 255, 0.12); + box-shadow: 0 12px 32px rgba(2, 6, 23, 0.35); + color: #f8fafc; + backdrop-filter: blur(18px); + -webkit-backdrop-filter: blur(18px); +} + +.desktop-weather-widget__header { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 10px; +} + +.desktop-weather-widget__icon { + font-size: 28px; + line-height: 1; +} + +.desktop-weather-widget__location { + font-size: 13px; + font-weight: 600; + line-height: 1.3; +} + +.desktop-weather-widget__status { + font-size: 11px; + color: rgba(248, 250, 252, 0.7); +} + +.desktop-weather-widget__body { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; +} + +.desktop-weather-widget__temp { + font-size: 26px; + font-weight: 700; +} + +.desktop-weather-widget__details { + font-size: 12px; + color: rgba(248, 250, 252, 0.85); + text-align: right; + line-height: 1.4; +} + +.desktop-weather-widget__footnote { + margin-top: 8px; + font-size: 11px; + color: rgba(248, 250, 252, 0.78); +} + +.desktop-weather-widget__button { + margin-top: 10px; + border: none; + border-radius: 999px; + padding: 7px 10px; + background: rgba(255, 255, 255, 0.16); + color: #f8fafc; + font-size: 11px; + font-weight: 600; + cursor: pointer; +} + +.desktop-weather-widget__button:hover { + background: rgba(255, 255, 255, 0.24); +} + +/* ── Desktop Icons ─────────────────────────────────────────────── */ +.desktop-icons { + position: absolute; + top: 16px; + left: 16px; + display: flex; + flex-direction: column; + gap: 6px; + z-index: 10; + flex-wrap: wrap; + max-height: calc(100vh - 80px); +} + +.desktop-icon { + display: flex; + flex-direction: column; + align-items: center; + width: 76px; + padding: 8px 6px; + border-radius: 6px; + cursor: pointer; + transition: background 0.12s; +} + +.desktop-icon:hover { + background: rgba(255, 255, 255, 0.14); +} + +.desktop-icon:active { + background: rgba(255, 255, 255, 0.24); +} + +.desktop-icon.desktop-icon--selected { + background: rgba(0, 120, 212, 0.45); + outline: 1px solid rgba(0, 120, 212, 0.8); +} + +.di-img { + font-size: 36px; + line-height: 1; + margin-bottom: 5px; + filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.6)); +} + +.di-label { + color: #fff; + font-size: 11.5px; + text-align: center; + line-height: 1.3; + text-shadow: 0 1px 4px rgba(0, 0, 0, 0.9), 0 0 8px rgba(0, 0, 0, 0.6); + word-break: break-word; +} + +/* ── Taskbar ───────────────────────────────────────────────────── */ +.taskbar { + position: fixed; + bottom: 0; + left: 0; + right: 0; + height: 48px; + background: rgba(22, 22, 22, 0.82); + backdrop-filter: blur(40px) saturate(180%); + -webkit-backdrop-filter: blur(40px) saturate(180%); + border-top: 1px solid rgba(255, 255, 255, 0.07); + display: flex; + align-items: center; + justify-content: center; + z-index: 9000; +} + +.taskbar__center { + display: flex; + align-items: center; + gap: 2px; +} + +.taskbar__right { + position: absolute; + right: 8px; + display: flex; + align-items: center; + gap: 2px; +} + +.taskbar__btn { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 44px; + height: 44px; + border: none; + background: transparent; + border-radius: 6px; + cursor: pointer; + transition: background 0.12s; + outline: none; +} + +.taskbar__btn:hover { + background: rgba(255, 255, 255, 0.09); +} + +.taskbar__btn:active { + background: rgba(255, 255, 255, 0.05); +} + +.taskbar__btn::after { + content: ""; + position: absolute; + bottom: 4px; + width: 0; + height: 3px; + border-radius: 2px; + transition: width 0.15s, background 0.15s; +} + +/* open (minimized or visible) */ +.taskbar__btn--open::after { + width: 6px; + background: rgba(255, 255, 255, 0.55); +} + +/* active (focused window) */ +.taskbar__btn--active::after { + width: 16px; + background: #0078d4; +} + +/* start button lit (menu open) */ +.taskbar__start.taskbar__btn--lit { + background: rgba(255, 255, 255, 0.12); +} + +.taskbar__app-icon { + font-size: 20px; + line-height: 1; +} + +/* Clock */ +.taskbar__clock { + color: rgba(255, 255, 255, 0.9); + font-size: 11.5px; + text-align: right; + line-height: 1.5; + padding: 4px 8px; + border-radius: 4px; + cursor: default; +} + +.taskbar__clock:hover { + background: rgba(255, 255, 255, 0.09); +} + +.taskbar__notif { + width: 36px; + height: 36px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + cursor: pointer; + transition: background 0.12s; +} + +.taskbar__notif:hover { + background: rgba(255, 255, 255, 0.09); +} + +/* ── App Window ────────────────────────────────────────────────── */ +.app-win { + display: flex; + flex-direction: column; + background: rgba(243, 243, 243, 0.96); + backdrop-filter: blur(40px) saturate(160%); + -webkit-backdrop-filter: blur(40px) saturate(160%); + border-radius: 8px; + border: 1px solid rgba(255, 255, 255, 0.2); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45), 0 2px 6px rgba(0, 0, 0, 0.25); + overflow: hidden; + min-width: 280px; + min-height: 180px; + transition: box-shadow 0.15s; + animation: win-open 0.18s cubic-bezier(0.25, 0.46, 0.45, 0.94); +} + +.app-win--active { + box-shadow: 0 16px 56px rgba(0, 0, 0, 0.55), 0 4px 10px rgba(0, 0, 0, 0.3); +} + +@keyframes win-open { + from { + opacity: 0; + transform: scale(0.94) translateY(6px); + } + to { + opacity: 1; + transform: scale(1) translateY(0); + } +} + +/* Title bar */ +.app-win__bar { + display: flex; + align-items: center; + height: 32px; + padding: 0 0 0 10px; + background: #f3f3f3; + cursor: grab; + flex-shrink: 0; + border-bottom: 1px solid rgba(0, 0, 0, 0.06); +} + +.app-win__bar:active { + cursor: grabbing; +} + +.app-win--active .app-win__bar { + background: #f8f8f8; +} + +.app-win__bar-icon { + font-size: 14px; + margin-right: 7px; + flex-shrink: 0; +} + +.app-win__bar-title { + font-size: 12px; + color: #1a1a1a; + font-weight: 400; + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* Window control buttons */ +.app-win__controls { + display: flex; + flex-shrink: 0; + margin-left: 4px; +} + +.app-win__ctrl { + width: 46px; + height: 32px; + border: none; + background: transparent; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + color: #1a1a1a; + font-size: 12px; + transition: background 0.1s, color 0.1s; + outline: none; +} + +.app-win__ctrl:hover { + background: rgba(0, 0, 0, 0.07); +} + +.app-win__ctrl--close:hover { + background: #c42b1c; + color: #fff; +} + +.app-win__ctrl svg { + pointer-events: none; +} + +/* Window body */ +.app-win__body { + flex: 1; + overflow: auto; + background: #fff; +} + +/* ── Start Menu ────────────────────────────────────────────────── */ +.start-backdrop { + position: fixed; + inset: 0; + z-index: 9100; +} + +.start-menu { + position: fixed; + bottom: 56px; + left: 50%; + transform: translateX(-50%); + width: 620px; + max-height: 620px; + background: rgba(30, 30, 30, 0.94); + backdrop-filter: blur(50px) saturate(180%); + -webkit-backdrop-filter: blur(50px) saturate(180%); + border-radius: 12px; + border: 1px solid rgba(255, 255, 255, 0.1); + box-shadow: 0 20px 70px rgba(0, 0, 0, 0.65); + z-index: 9200; + display: flex; + flex-direction: column; + padding: 20px 22px 0; + animation: start-open 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94); + overflow: hidden; +} + +@keyframes start-open { + from { + opacity: 0; + transform: translateX(-50%) translateY(12px) scale(0.97); + } + to { + opacity: 1; + transform: translateX(-50%) translateY(0) scale(1); + } +} + +.start-menu__search { + display: flex; + align-items: center; + gap: 10px; + background: rgba(255, 255, 255, 0.08); + border: 1px solid rgba(255, 255, 255, 0.12); + border-radius: 6px; + padding: 8px 14px; + margin-bottom: 18px; + cursor: text; +} + +.start-menu__search-placeholder { + color: rgba(255, 255, 255, 0.45); + font-size: 13px; +} + +.start-menu__section-label { + color: rgba(255, 255, 255, 0.85); + font-size: 12px; + font-weight: 600; + margin-bottom: 10px; + letter-spacing: 0.02em; +} + +.start-menu__grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 4px; + flex: 1; + overflow-y: auto; + margin-bottom: 8px; +} + +.start-menu__app { + display: flex; + flex-direction: column; + align-items: center; + padding: 12px 8px; + border: none; + background: transparent; + border-radius: 8px; + cursor: pointer; + transition: background 0.12s; + gap: 6px; +} + +.start-menu__app:hover { + background: rgba(255, 255, 255, 0.1); +} + +.start-menu__app:active { + background: rgba(255, 255, 255, 0.06); +} + +.start-menu__app-icon { + font-size: 28px; + line-height: 1; +} + +.start-menu__app-name { + color: rgba(255, 255, 255, 0.88); + font-size: 11.5px; + text-align: center; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 90px; +} + +.start-menu__footer { + display: flex; + align-items: center; + justify-content: space-between; + padding: 12px 0 14px; + border-top: 1px solid rgba(255, 255, 255, 0.08); + margin-top: 4px; +} + +.start-menu__user { + display: flex; + align-items: center; + gap: 10px; + color: rgba(255, 255, 255, 0.88); + font-size: 13px; + padding: 6px 8px; + border-radius: 6px; + cursor: pointer; + transition: background 0.12s; +} + +.start-menu__user:hover { + background: rgba(255, 255, 255, 0.08); +} + +.start-menu__avatar { + width: 32px; + height: 32px; + border-radius: 50%; + background: linear-gradient(135deg, #0078d4, #7c3aed); + display: flex; + align-items: center; + justify-content: center; + color: white; + font-size: 12px; + font-weight: 600; + flex-shrink: 0; +} + +.start-menu__power { + width: 36px; + height: 36px; + border: none; + background: transparent; + color: rgba(255, 255, 255, 0.75); + border-radius: 6px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.12s, color 0.12s; +} + +.start-menu__power:hover { + background: rgba(255, 255, 255, 0.1); + color: white; +} + +/* ═══════════════════════════════════════════════════════════════ + App Content Styles + ═══════════════════════════════════════════════════════════════ */ + +/* ── Resume App ────────────────────────────────────────────────── */ +.resume-app { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; +} + +.resume-app__toolbar { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 12px; + background: #f5f5f5; + border-bottom: 1px solid #e0e0e0; + flex-shrink: 0; +} + +.resume-app__toolbar-title { + font-size: 13px; + color: #555; + flex: 1; +} + +.resume-app__btn { + display: flex; + align-items: center; + gap: 5px; + padding: 5px 10px; + background: #0078d4; + color: white; + border: none; + border-radius: 4px; + font-size: 12px; + cursor: pointer; + text-decoration: none; + transition: background 0.12s; +} + +.resume-app__btn:hover { + background: #106ebe; +} + +.resume-app__frame { + flex: 1; + border: none; + display: block; +} + +/* ── About App ─────────────────────────────────────────────────── */ +.about-app { + padding: 28px 32px; + overflow-y: auto; + height: 100%; + box-sizing: border-box; +} + +.about-app__header { + display: flex; + align-items: center; + gap: 20px; + margin-bottom: 22px; +} + +.about-app__avatar { + width: 72px; + height: 72px; + border-radius: 50%; + background: linear-gradient(135deg, #0078d4 0%, #7c3aed 100%); + display: flex; + align-items: center; + justify-content: center; + color: white; + font-size: 24px; + font-weight: 700; + flex-shrink: 0; +} + +.about-app__name { + font-size: 22px; + font-weight: 600; + color: #1a1a1a; + margin: 0 0 4px; +} + +.about-app__nick { + font-size: 13px; + color: #666; + margin: 0; +} + +.about-app__bio { + font-size: 14px; + color: #444; + line-height: 1.6; + margin-bottom: 20px; +} + +.about-app__info { + display: flex; + flex-direction: column; + gap: 8px; + margin-bottom: 22px; +} + +.about-app__info-row { + display: flex; + align-items: center; + gap: 10px; + font-size: 13.5px; + color: #555; +} + +.about-app__info-row span:first-child { + font-size: 16px; +} + +.about-app__section-title { + font-size: 13px; + font-weight: 600; + color: #1a1a1a; + margin: 0 0 10px; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.about-app__skills { + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.skill-chip { + background: #e8f0fe; + color: #1a56db; + padding: 4px 10px; + border-radius: 12px; + font-size: 12px; + font-weight: 500; +} + +/* ── Projects App ──────────────────────────────────────────────── */ +.projects-app { + height: 100%; + display: flex; + flex-direction: column; + overflow: hidden; +} + +.projects-app__header { + padding: 16px 20px 12px; + border-bottom: 1px solid #ebebeb; + font-size: 16px; + font-weight: 600; + color: #1a1a1a; + flex-shrink: 0; +} + +.projects-app__list { + flex: 1; + overflow-y: auto; + padding: 8px 12px; +} + +.project-card { + display: block; + padding: 14px 16px; + border-radius: 8px; + text-decoration: none; + transition: background 0.12s; + margin-bottom: 4px; +} + +.project-card:hover { + background: #f5f5f5; +} + +.project-card__name { + font-size: 14px; + font-weight: 600; + color: #0078d4; + margin-bottom: 3px; +} + +.project-card__desc { + font-size: 13px; + color: #444; + margin-bottom: 5px; + line-height: 1.4; +} + +.project-card__tech { + display: inline-flex; + gap: 4px; + flex-wrap: wrap; +} + +.tech-tag { + background: #f0f0f0; + color: #666; + padding: 2px 7px; + border-radius: 3px; + font-size: 11px; +} + +/* ── Contact App ───────────────────────────────────────────────── */ +.contact-app { + padding: 28px 32px; + overflow-y: auto; + height: 100%; + box-sizing: border-box; +} + +.contact-app__title { + font-size: 18px; + font-weight: 600; + color: #1a1a1a; + margin: 0 0 20px; +} + +.contact-app__rows { + display: flex; + flex-direction: column; + gap: 12px; + margin-bottom: 28px; +} + +.contact-app__row { + display: flex; + align-items: center; + gap: 12px; + font-size: 14px; + color: #333; +} + +.contact-app__row span:first-child { + font-size: 18px; + width: 28px; + text-align: center; +} + +.contact-app__links-title { + font-size: 13px; + font-weight: 600; + color: #1a1a1a; + margin: 0 0 12px; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.contact-app__social { + display: flex; + flex-direction: column; + gap: 6px; +} + +.social-link { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 14px; + border-radius: 8px; + text-decoration: none; + color: #1a1a1a; + font-size: 13.5px; + transition: background 0.12s; + background: #f7f7f7; + border: 1px solid #ebebeb; +} + +.social-link:hover { + background: #eaf3fb; + border-color: #b3d4f0; + color: #0078d4; +} + +.social-link span:first-child { + font-size: 18px; +} + +/* ── News App ──────────────────────────────────────────────────── */ +.news-app { + height: 100%; + display: flex; + flex-direction: column; + overflow: hidden; + background: linear-gradient(180deg, #0f172a 0%, #111827 100%); + color: #f8fafc; +} + +.news-app__header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; + padding: 18px 20px 14px; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); + flex-shrink: 0; +} + +.news-app__title { + margin: 0 0 4px; + font-size: 20px; +} + +.news-app__subtitle { + margin: 0; + font-size: 12px; + line-height: 1.5; + color: rgba(248, 250, 252, 0.7); +} + +.news-app__actions { + display: flex; + flex-wrap: wrap; + justify-content: flex-end; + gap: 8px; +} + +.news-app__btn { + display: inline-flex; + align-items: center; + justify-content: center; + border: none; + border-radius: 999px; + padding: 8px 12px; + font-size: 12px; + font-weight: 600; + cursor: pointer; + background: rgba(255, 255, 255, 0.14); + color: #f8fafc; + text-decoration: none; +} + +.news-app__btn:hover { + background: rgba(255, 255, 255, 0.2); +} + +.news-app__btn--link { + background: linear-gradient(135deg, #38bdf8, #2563eb); +} + +.news-app__statusbar { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + gap: 8px; + padding: 10px 20px; + font-size: 12px; + color: rgba(248, 250, 252, 0.82); + background: rgba(255, 255, 255, 0.04); + border-bottom: 1px solid rgba(255, 255, 255, 0.06); + flex-shrink: 0; +} + +.news-app__list { + flex: 1; + overflow-y: auto; + padding: 12px; +} + +.news-card { + display: block; + padding: 14px 16px; + border-radius: 12px; + text-decoration: none; + color: #f8fafc; + background: rgba(255, 255, 255, 0.06); + border: 1px solid rgba(255, 255, 255, 0.08); + margin-bottom: 8px; + transition: background 0.12s, border-color 0.12s, transform 0.12s; +} + +.news-card:hover { + background: rgba(255, 255, 255, 0.1); + border-color: rgba(255, 255, 255, 0.14); + transform: translateY(-1px); +} + +.news-card__top { + margin-bottom: 10px; +} + +.news-card__title { + font-size: 14px; + font-weight: 600; + line-height: 1.45; + margin-bottom: 4px; +} + +.news-card__meta { + font-size: 11.5px; + color: rgba(248, 250, 252, 0.68); +} + +.news-card__bottom { + display: flex; + flex-wrap: wrap; + gap: 10px; + font-size: 11.5px; + color: rgba(248, 250, 252, 0.78); +} + +.news-app__empty { + min-height: 160px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + gap: 6px; + padding: 24px; + color: rgba(248, 250, 252, 0.78); +} + +.news-app__empty-title { + font-size: 15px; + font-weight: 600; + color: #f8fafc; +} + +.news-app__empty-copy { + font-size: 12px; + line-height: 1.5; + max-width: 280px; +} + +/* ── Sudoku App ───────────────────────────────────────────────── */ +.sudoku-app { + height: 100%; + box-sizing: border-box; + padding: 18px 20px 20px; + display: flex; + flex-direction: column; + gap: 14px; + background: linear-gradient(135deg, #111827 0%, #1f2937 100%); + color: #f9fafb; +} + +.sudoku-app__header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 12px; +} + +.sudoku-app__title { + margin: 0 0 4px; + font-size: 20px; +} + +.sudoku-app__subtitle { + margin: 0; + font-size: 12px; + color: rgba(255, 255, 255, 0.72); + line-height: 1.5; +} + +.sudoku-app__actions { + display: flex; + flex-wrap: wrap; + justify-content: flex-end; + gap: 8px; +} + +.sudoku-app__btn { + border: none; + border-radius: 999px; + padding: 8px 12px; + font-size: 11px; + font-weight: 600; + cursor: pointer; + background: rgba(255, 255, 255, 0.14); + color: #f9fafb; +} + +.sudoku-app__btn:hover { + background: rgba(255, 255, 255, 0.2); +} + +.sudoku-app__btn--primary { + background: linear-gradient(135deg, #38bdf8, #2563eb); +} + +.sudoku-app__statusbar { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + gap: 8px; + padding: 8px 10px; + border-radius: 8px; + background: rgba(255, 255, 255, 0.08); + font-size: 12px; + color: rgba(255, 255, 255, 0.92); +} + +.sudoku-app__message { + color: #fde68a; +} + +.sudoku-app__board { + display: grid; + grid-template-columns: repeat(9, minmax(0, 1fr)); + gap: 0; + width: min(100%, 460px); + aspect-ratio: 1 / 1; + margin: 0 auto; + background: #f8fafc; + border: 2px solid #111827; + border-radius: 8px; + overflow: hidden; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18); +} + +.sudoku-app__cell { + border: 1px solid #d1d5db; + background: #fff; + color: #111827; + font-size: 16px; + font-weight: 600; + cursor: pointer; + padding: 0; + display: flex; + align-items: center; + justify-content: center; +} + +.sudoku-app__cell:hover { + background: #fef3c7; +} + +.sudoku-app__cell--selected { + background: #dbeafe; +} + +.sudoku-app__cell--fixed { + background: #f3f4f6; + color: #111827; + font-weight: 700; +} + +.sudoku-app__cell--wrong { + color: #dc2626; +} + +.sudoku-app__cell--row-divider { + border-bottom-width: 2px; + border-bottom-color: #111827; +} + +.sudoku-app__cell--col-divider { + border-right-width: 2px; + border-right-color: #111827; +} + +.sudoku-app__keypad { + display: grid; + grid-template-columns: repeat(5, minmax(0, 1fr)); + gap: 8px; + width: min(100%, 460px); + margin: 0 auto; +} + +.sudoku-app__number { + border: none; + border-radius: 8px; + padding: 10px 0; + font-size: 14px; + font-weight: 700; + cursor: pointer; + background: rgba(255, 255, 255, 0.16); + color: #f9fafb; +} + +.sudoku-app__number:hover { + background: rgba(255, 255, 255, 0.24); +} + +.sudoku-app__number--clear { + background: rgba(249, 115, 22, 0.9); +} + +/* ── Snake App ────────────────────────────────────────────────── */ +.snake-app { + height: 100%; + box-sizing: border-box; + padding: 18px 20px 20px; + display: flex; + flex-direction: column; + gap: 14px; + background: linear-gradient(135deg, #0f172a 0%, #111827 100%); + color: #f3f4f6; +} + +.snake-app__header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 12px; +} + +.snake-app__title { + margin: 0 0 4px; + font-size: 20px; +} + +.snake-app__subtitle { + margin: 0; + font-size: 12px; + color: rgba(255, 255, 255, 0.72); + line-height: 1.5; +} + +.snake-app__stats { + display: flex; + flex-direction: column; + gap: 6px; + min-width: 108px; +} + +.snake-app__stat { + padding: 7px 10px; + border-radius: 999px; + background: rgba(255, 255, 255, 0.14); + font-size: 12px; + font-weight: 600; + text-align: center; +} + +.snake-app__board-wrap { + position: relative; + flex: 1; + display: flex; + align-items: center; + justify-content: center; + min-height: 0; +} + +.snake-app__board { + display: grid; + grid-template-columns: repeat(20, minmax(0, 1fr)); + grid-template-rows: repeat(20, minmax(0, 1fr)); + width: min(100%, 460px); + aspect-ratio: 1 / 1; + background: rgba(2, 6, 23, 0.9); + border: 2px solid rgba(255, 255, 255, 0.12); + border-radius: 10px; + overflow: hidden; + box-shadow: inset 0 0 18px rgba(0, 0, 0, 0.4); +} + +.snake-app__cell { + background: rgba(255, 255, 255, 0.03); + border: 1px solid rgba(255, 255, 255, 0.03); +} + +.snake-app__cell--head { + background: linear-gradient(135deg, #22c55e, #16a34a); + border-radius: 3px; +} + +.snake-app__cell--body { + background: linear-gradient(135deg, #4ade80, #15803d); + border-radius: 3px; +} + +.snake-app__cell--food { + background: linear-gradient(135deg, #fb923c, #ef4444); + border-radius: 50%; + transform: scale(0.78); +} + +.snake-app__overlay { + position: absolute; + inset: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 6px; + background: rgba(2, 6, 23, 0.72); + border-radius: 10px; + color: #f8fafc; + font-weight: 600; + text-align: center; + padding: 16px; + backdrop-filter: blur(4px); +} + +.snake-app__overlay-title { + font-size: 18px; +} + +.snake-app__overlay-copy { + font-size: 12px; + color: rgba(248, 250, 252, 0.82); +} + +.snake-app__controls { + display: flex; + justify-content: center; + gap: 10px; +} + +.snake-app__btn { + border: none; + border-radius: 999px; + padding: 8px 14px; + font-size: 12px; + font-weight: 600; + cursor: pointer; + background: rgba(255, 255, 255, 0.14); + color: #f8fafc; + transition: transform 0.12s ease, background 0.12s ease; +} + +.snake-app__btn:hover { + background: rgba(255, 255, 255, 0.2); + transform: translateY(-1px); +} + +.snake-app__btn--primary { + background: linear-gradient(135deg, #3b82f6, #2563eb); +} + +.snake-app__pad { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; +} + +.snake-app__pad-row { + display: flex; + gap: 8px; +} + +.snake-app__pad-btn { + width: 44px; + height: 44px; + border: none; + border-radius: 10px; + background: rgba(255, 255, 255, 0.18); + color: #f8fafc; + font-size: 18px; + cursor: pointer; +} + +.snake-app__pad-btn:hover { + background: rgba(255, 255, 255, 0.28); +} + +.snake-app__hint { + margin: 0; + text-align: center; + font-size: 12px; + color: rgba(248, 250, 252, 0.72); +} + +/* ── Mobile fallback ───────────────────────────────────────────── */ +@media (max-width: 700px) { + .win11-desktop { + padding-bottom: env(safe-area-inset-bottom); + } + + .desktop-weather-widget { + top: 10px; + right: 10px; + left: 10px; + width: auto; + max-width: none; + } + + .desktop-icons { + top: 12px; + left: 12px; + right: 12px; + bottom: 72px; + flex-direction: row; + flex-wrap: wrap; + align-content: flex-start; + gap: 8px; + max-height: none; + overflow-y: auto; + } + + .desktop-icon { + width: calc(25% - 6px); + min-width: 0; + padding: 8px 4px; + } + + .di-img { + font-size: 28px; + } + + .di-label { + font-size: 10px; + } + + .taskbar { + height: 56px; + padding-bottom: env(safe-area-inset-bottom); + } + + .taskbar__center { + max-width: calc(100vw - 140px); + overflow-x: auto; + padding: 0 6px; + } + + .taskbar__right { + right: 6px; + gap: 4px; + } + + .taskbar__clock { + font-size: 10px; + padding: 4px 6px; + } + + .taskbar__btn { + width: 40px; + height: 40px; + } + + .start-menu { + left: 8px; + right: 8px; + bottom: 64px; + width: auto; + max-width: none; + max-height: min(78dvh, 620px); + transform: none; + padding: 16px 14px 0; + } + + .start-menu__grid { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .start-menu__search-placeholder { + font-size: 12px; + } + + .start-menu__footer { + flex-direction: column; + align-items: flex-start; + gap: 10px; + } + + .about-app, + .contact-app { + padding: 16px 16px 24px; + } + + .about-app__header { + flex-direction: column; + align-items: flex-start; + gap: 12px; + } + + .about-app__name { + font-size: 20px; + } + + .projects-app__header, + .news-app__header, + .sudoku-app__header, + .snake-app__header { + flex-direction: column; + align-items: flex-start; + } + + .news-app__actions, + .sudoku-app__actions { + justify-content: flex-start; + } + + .news-app__header, + .sudoku-app__header, + .snake-app__header { + gap: 12px; + } + + .news-app__statusbar, + .sudoku-app__statusbar { + align-items: flex-start; + } + + .sudoku-app { + padding: 14px 12px 16px; + } + + .sudoku-app__board { + width: min(100%, 92vw); + } + + .sudoku-app__keypad { + width: min(100%, 92vw); + grid-template-columns: repeat(5, minmax(0, 1fr)); + } + + .snake-app { + padding: 14px 12px 16px; + } + + .snake-app__stats { + flex-direction: row; + flex-wrap: wrap; + min-width: unset; + } + + .snake-app__board { + width: min(100%, 92vw); + } + + .snake-app__pad-row { + gap: 6px; + } + + .snake-app__pad-btn { + width: 40px; + height: 40px; + } +} diff --git a/src/pages/desktop/Desktop.js b/src/pages/desktop/Desktop.js new file mode 100644 index 0000000..1d38097 --- /dev/null +++ b/src/pages/desktop/Desktop.js @@ -0,0 +1,917 @@ +import React, { useState, useCallback, useEffect } from "react"; +import "./Desktop.css"; +import AppWindow from "./AppWindow"; +import Taskbar from "./Taskbar"; +import StartMenu from "./StartMenu"; +import { greeting } from "../../portfolio"; + +/* ═══════════════════════════════════════════════════════════════ + App Content Components + ═══════════════════════════════════════════════════════════════ */ + +function ResumeApp() { + const embedUrl = greeting.resumeLink.replace("/view?usp=sharing", "/preview"); + return ( +
+
+ + πŸ“„ Ahmad Tuflihun – Curriculum Vitae + + + + + + + + Open in Drive + +
+