[
  {
    "path": ".github/CODEOWNERS",
    "content": "* @Abdenasser"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "content": "# Contributing to NeoHtop\n\nThank you for considering contributing to NeoHtop! We welcome contributions from the community.\n\n## How to Contribute\n\n1. Fork the repository.\n2. Create a new branch (`git checkout -b feature/YourFeature`).\n3. Make your changes.\n4. Commit your changes (`git commit -m 'Add some feature'`).\n5. Push to the branch (`git push origin feature/YourFeature`).\n6. Open a pull request.\n\n## Code of Conduct\n\nPlease note that this project is released with a [Contributor Code of Conduct](https://www.contributor-covenant.org/version/2/0/code_of_conduct/). By participating in this project you agree to abide by its terms.\n\n## Reporting Bugs\n\nPlease use the [bug report template](./ISSUE_TEMPLATE/bug_report.md) to report any bugs you find.\n\n## Requesting Features\n\nPlease use the [feature request template](./ISSUE_TEMPLATE/feature_request.md) to suggest new features. "
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: abdenasser\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Desktop (please complete the following information):**\n - OS: [e.g. macOS]\n - Version [e.g. 22]\n\n**Additional context**\nAdd any other context about the problem here. "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Support\n    url: https://github.com/Abdenasser/neohtop/discussions\n    about: Please use discussions for questions and support. "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here. "
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "## Description\n\nPlease include a summary of the changes and the related issue. Please also include relevant motivation and context.\n\nFixes # (issue)\n\n## Type of change\n\nPlease delete options that are not relevant.\n\n- [ ] Bug fix (non-breaking change which fixes an issue)\n- [ ] New feature (non-breaking change which adds functionality)\n- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)\n- [ ] This change requires a documentation update\n\n## How Has This Been Tested?\n\nPlease describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration.\n\n- [ ] Test A\n- [ ] Test B\n\n## Checklist:\n\n- [ ] My code follows the style guidelines of this project\n- [ ] I have performed a self-review of my code\n- [ ] I have commented my code, particularly in hard-to-understand areas\n- [ ] I have made corresponding changes to the documentation\n- [ ] My changes generate no new warnings\n- [ ] I have added tests that prove my fix is effective or that my feature works\n- [ ] New and existing unit tests pass locally with my changes\n- [ ] Any dependent changes have been merged and published in downstream modules "
  },
  {
    "path": ".github/workflows/build-check.yml",
    "content": "name: Build Check\n\non:\n  pull_request:\n    branches: [main]\n    paths:\n      - \"src-tauri/**\"\n      - \".github/workflows/**\"\n\nenv:\n  CARGO_TERM_COLOR: always\n  CARGO_INCREMENTAL: 1\n  CARGO_NET_RETRY: 10\n  RUSTUP_MAX_RETRIES: 10\n  RUST_BACKTRACE: 1\n  RUSTC_WRAPPER: sccache\n  CARGO_BUILD_JOBS: 2\n\njobs:\n  build:\n    name: Build Check\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: \"lts/*\"\n          cache: \"npm\"\n\n      - name: Cache Linux Dependencies\n        id: cache-apt\n        uses: actions/cache@v3\n        with:\n          path: |\n            /var/cache/apt/archives/*.deb\n            /var/lib/apt/lists/*\n          key: ${{ runner.os }}-apt-${{ hashFiles('**/package.json', '**/Cargo.lock') }}\n          restore-keys: |\n            ${{ runner.os }}-apt-\n\n      - name: Add Ubuntu Jammy repo for WebKitGTK 4.0\n        run: |\n          echo \"deb http://archive.ubuntu.com/ubuntu jammy main universe\" | sudo tee -a /etc/apt/sources.list\n          sudo apt update\n\n      - name: Install Linux Dependencies\n        run: |\n          sudo rm -rf /var/cache/apt/archives/lock\n          sudo rm -rf /var/cache/apt/archives/partial\n          sudo rm -rf /var/lib/apt/lists/lock\n          sudo rm -rf /var/lib/apt/lists/partial\n          sudo apt-get update\n          sudo apt-get install --no-install-recommends -y \\\n            build-essential \\\n            pkg-config \\\n            libgtk-3-dev \\\n            libayatana-appindicator3-dev \\\n            librsvg2-dev \\\n            libglib2.0-dev \\\n            libjavascriptcoregtk-4.0-dev \\\n            libsoup-3.0-dev \\\n            libwebkit2gtk-4.1-dev\n\n      - name: Remove Jammy repo\n        run: |\n          sudo sed -i '/jammy main universe/d' /etc/apt/sources.list\n          sudo apt update\n\n      - name: Install Rust\n        uses: dtolnay/rust-toolchain@stable\n        with:\n          components: cargo\n          target: x86_64-unknown-linux-gnu\n\n      - name: Install sccache\n        run: |\n          SCCACHE_VERSION=v0.7.7\n          curl -L \"https://github.com/mozilla/sccache/releases/download/${SCCACHE_VERSION}/sccache-${SCCACHE_VERSION}-x86_64-unknown-linux-musl.tar.gz\" | tar xz\n          sudo mv sccache-*/sccache /usr/local/bin/sccache\n          echo \"RUSTC_WRAPPER=sccache\" >> $GITHUB_ENV\n\n      - uses: Swatinem/rust-cache@v2\n        with:\n          workspaces: \"./src-tauri -> target\"\n          shared-key: \"build\"\n\n      - name: Install Dependencies\n        run: npm ci\n\n      - name: Build Application\n        run: |\n          npm run tauri build -- \\\n            --target x86_64-unknown-linux-gnu \\\n            --bundles deb \\\n            --ci\n"
  },
  {
    "path": ".github/workflows/format-check.yml",
    "content": "name: Format Check\n\non:\n  pull_request:\n    branches: [ main ]\n\njobs:\n  format:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      \n      - name: Setup Node\n        uses: actions/setup-node@v4\n        with:\n          node-version: 'lts/*'\n          \n      - name: Setup Rust\n        uses: dtolnay/rust-toolchain@stable\n          \n      - name: Install dependencies\n        run: npm ci\n        \n      - name: Check formatting\n        run: npm run format:check\n"
  },
  {
    "path": ".github/workflows/linux-aarch64-nightly.yml",
    "content": "name: Linux (aarch64) Nightly Build\n\non:\n  workflow_dispatch:\n    inputs:\n      release_upload_url:\n        description: \"Release upload URL\"\n        required: true\n\nenv:\n  CARGO_TERM_COLOR: always\n  PKG_CONFIG_ALLOW_CROSS: 1\n  PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig\n  PKG_CONFIG: /usr/bin/aarch64-linux-gnu-pkg-config\n\njobs:\n  build:\n    name: Build Linux aarch64 Packages\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: \"lts/*\"\n          cache: \"npm\"\n\n      - name: Install Rust\n        uses: dtolnay/rust-toolchain@stable\n        with:\n          targets: aarch64-unknown-linux-gnu\n\n      - name: Configure ARM64 repositories\n        run: |\n          sudo dpkg --add-architecture arm64\n          # Remove all existing sources\n          sudo rm -rf /etc/apt/sources.list.d/*\n          sudo truncate -s 0 /etc/apt/sources.list\n          # Add only ports.ubuntu.com repository\n          sudo tee /etc/apt/sources.list << EOF\n          deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy main restricted universe multiverse\n          deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted universe multiverse\n          deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted universe multiverse\n          deb [arch=amd64] http://azure.archive.ubuntu.com/ubuntu jammy main restricted universe multiverse\n          deb [arch=amd64] http://azure.archive.ubuntu.com/ubuntu jammy-updates main restricted universe multiverse\n          deb [arch=amd64] http://azure.archive.ubuntu.com/ubuntu jammy-security main restricted universe multiverse\n          EOF\n          sudo apt-get update\n          # Install required packages including cross-compilation tools\n          sudo apt-get install -y \\\n            build-essential \\\n            pkg-config \\\n            crossbuild-essential-arm64 \\\n            gcc-aarch64-linux-gnu \\\n            g++-aarch64-linux-gnu \\\n            libgtk-3-dev:arm64 \\\n            libayatana-appindicator3-dev:arm64 \\\n            librsvg2-dev:arm64 \\\n            libglib2.0-dev:arm64 \\\n            libjavascriptcoregtk-4.0-dev:arm64 \\\n            libsoup-3.0-dev:arm64 \\\n            libwebkit2gtk-4.1-dev:arm64 \\\n            libssl-dev:arm64 \\\n            libssl-dev \\\n            openssl:arm64\n          # Configure pkg-config for cross-compilation\n          echo \"PKG_CONFIG=/usr/bin/aarch64-linux-gnu-pkg-config\" >> $GITHUB_ENV\n          echo \"PKG_CONFIG_ALLOW_CROSS=1\" >> $GITHUB_ENV\n\n      - name: Install Dependencies\n        run: npm install\n\n      - name: Setup cross-compilation environment\n        run: |\n          sudo apt-get install -y \\\n            crossbuild-essential-arm64 \\\n            pkg-config \\\n            libssl-dev:arm64 \\\n            libssl-dev \\\n            openssl:arm64 \\\n            file \\\n            desktop-file-utils \\\n            libfuse2 \\\n            qemu-user-static\n\n          # Setup pkg-config\n          sudo tee /usr/bin/aarch64-linux-gnu-pkg-config << 'EOF'\n          #!/bin/sh\n          export PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig\n          exec pkg-config \"$@\"\n          EOF\n          sudo chmod +x /usr/bin/aarch64-linux-gnu-pkg-config\n\n          # Create .cargo/config\n          mkdir -p .cargo\n          cat > .cargo/config << EOF\n          [target.aarch64-unknown-linux-gnu]\n          linker = \"aarch64-linux-gnu-gcc\"\n          ar = \"aarch64-linux-gnu-ar\"\n          EOF\n\n          # Download and setup appimagetool for ARM64\n          wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-aarch64.AppImage\n          chmod +x appimagetool-aarch64.AppImage\n          sudo mv appimagetool-aarch64.AppImage /usr/local/bin/appimagetool\n\n          # Set environment variables\n          echo \"PKG_CONFIG=/usr/bin/aarch64-linux-gnu-pkg-config\" >> $GITHUB_ENV\n          echo \"PKG_CONFIG_ALLOW_CROSS=1\" >> $GITHUB_ENV\n          echo \"OPENSSL_DIR=/usr\" >> $GITHUB_ENV\n          echo \"OPENSSL_INCLUDE_DIR=/usr/include/aarch64-linux-gnu\" >> $GITHUB_ENV\n          echo \"OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu\" >> $GITHUB_ENV\n          echo \"CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc\" >> $GITHUB_ENV\n          echo \"APPIMAGE_EXTRACT_AND_RUN=1\" >> $GITHUB_ENV\n\n      - name: Build Frontend\n        run: npm run build\n\n      - name: Build AppImage\n        run: |\n          echo \"Building AppImage for aarch64...\"\n          npm run tauri build -- --target aarch64-unknown-linux-gnu --bundles appimage\n          cd src-tauri/target/aarch64-unknown-linux-gnu/release/bundle/appimage/\n          for f in *.AppImage; do\n            echo \"AARCH64_APPIMAGE_PATH=src-tauri/target/aarch64-unknown-linux-gnu/release/bundle/appimage/$f\" >> $GITHUB_ENV\n          done\n\n      - name: Build Debian Package\n        run: |\n          echo \"Building Debian package for aarch64...\"\n          npm run tauri build -- --target aarch64-unknown-linux-gnu --bundles deb\n          cd src-tauri/target/aarch64-unknown-linux-gnu/release/bundle/deb/\n          for f in *.deb; do\n            echo \"AARCH64_DEB_PATH=src-tauri/target/aarch64-unknown-linux-gnu/release/bundle/deb/$f\" >> $GITHUB_ENV\n          done\n\n      - name: Build RPM Package\n        run: |\n          echo \"Building RPM package for aarch64...\"\n          npm run tauri build -- --target aarch64-unknown-linux-gnu --bundles rpm\n          cd src-tauri/target/aarch64-unknown-linux-gnu/release/bundle/rpm/\n          for f in *.rpm; do\n            echo \"AARCH64_RPM_PATH=src-tauri/target/aarch64-unknown-linux-gnu/release/bundle/rpm/$f\" >> $GITHUB_ENV\n          done\n\n      - name: Get version from package.json\n        id: version\n        run: echo \"version=$(node -p \"require('./package.json').version\")\" >> $GITHUB_OUTPUT\n\n      - name: Upload AppImage to Release\n        if: github.event.inputs.release_upload_url != ''\n        uses: actions/upload-release-asset@v1\n        env:\n          GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}\n        with:\n          upload_url: ${{ github.event.inputs.release_upload_url }}\n          asset_path: ${{ env.AARCH64_APPIMAGE_PATH }}\n          asset_name: NeoHtop_${{ steps.version.outputs.version }}_aarch64.AppImage\n          asset_content_type: application/x-executable\n\n      - name: Upload Debian Package to Release\n        if: github.event.inputs.release_upload_url != ''\n        uses: actions/upload-release-asset@v1\n        env:\n          GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}\n        with:\n          upload_url: ${{ github.event.inputs.release_upload_url }}\n          asset_path: ${{ env.AARCH64_DEB_PATH }}\n          asset_name: NeoHtop_${{ steps.version.outputs.version }}_aarch64.deb\n          asset_content_type: application/vnd.debian.binary-package\n\n      - name: Upload RPM Package to Release\n        if: github.event.inputs.release_upload_url != ''\n        uses: actions/upload-release-asset@v1\n        env:\n          GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}\n        with:\n          upload_url: ${{ github.event.inputs.release_upload_url }}\n          asset_path: ${{ env.AARCH64_RPM_PATH }}\n          asset_name: NeoHtop_${{ steps.version.outputs.version }}_aarch64.rpm\n          asset_content_type: application/x-rpm\n"
  },
  {
    "path": ".github/workflows/linux-x86_64-nightly.yml",
    "content": "name: Linux (x86_64) Nightly Build\n\non:\n  workflow_dispatch:\n    inputs:\n      release_upload_url:\n        description: \"Release upload URL\"\n        required: true\n\nenv:\n  CARGO_TERM_COLOR: always\n\njobs:\n  build:\n    name: Build Linux Packages\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: \"lts/*\"\n          cache: \"npm\"\n\n      - name: Install Rust\n        uses: dtolnay/rust-toolchain@stable\n\n      - name: Add Ubuntu Jammy repo for WebKitGTK 4.0\n        run: |\n          echo \"deb http://archive.ubuntu.com/ubuntu jammy main universe\" | sudo tee -a /etc/apt/sources.list\n          sudo apt update\n\n      - name: Install Linux Dependencies\n        run: |\n          sudo apt-get update\n          sudo apt-get install -y \\\n            build-essential \\\n            pkg-config \\\n            libgtk-3-dev \\\n            libayatana-appindicator3-dev \\\n            librsvg2-dev \\\n            libglib2.0-dev \\\n            libjavascriptcoregtk-4.0-dev \\\n            libsoup-3.0-dev \\\n            libwebkit2gtk-4.1-dev\n\n      - name: Remove Jammy repo\n        run: |\n          sudo sed -i '/jammy main universe/d' /etc/apt/sources.list\n          sudo apt update\n\n      - name: Install Dependencies\n        run: |\n          npm install\n\n      - name: Build Frontend\n        run: npm run build\n\n      - name: Build AppImage (x86_64)\n        run: |\n          echo \"Building AppImage for x86_64...\"\n          npm run tauri build -- --target x86_64-unknown-linux-gnu --bundles appimage\n          cd src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/\n          for f in *.AppImage; do\n            echo \"APPIMAGE_PATH=src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/$f\" >> $GITHUB_ENV\n          done\n\n      - name: Build Debian Package (x86_64)\n        run: |\n          echo \"Building Debian package for x86_64...\"\n          npm run tauri build -- --target x86_64-unknown-linux-gnu --bundles deb\n          cd src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/deb/\n          for f in *.deb; do\n            echo \"DEB_PATH=src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/deb/$f\" >> $GITHUB_ENV\n          done\n\n      - name: Build RPM Package (x86_64)\n        run: |\n          echo \"Building RPM package for x86_64...\"\n          npm run tauri build -- --target x86_64-unknown-linux-gnu --bundles rpm\n          cd src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/\n          for f in *.rpm; do\n            echo \"RPM_PATH=src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/$f\" >> $GITHUB_ENV\n          done\n\n      - name: Get version from package.json\n        id: version\n        run: echo \"version=$(node -p \"require('./package.json').version\")\" >> $GITHUB_OUTPUT\n\n      - name: Upload AppImage to Release\n        if: github.event.inputs.release_upload_url != ''\n        uses: actions/upload-release-asset@v1\n        env:\n          GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}\n        with:\n          upload_url: ${{ github.event.inputs.release_upload_url }}\n          asset_path: ${{ env.APPIMAGE_PATH }}\n          asset_name: NeoHtop_${{ steps.version.outputs.version }}_x86_64.AppImage\n          asset_content_type: application/x-executable\n\n      - name: Upload Debian Package to Release\n        if: github.event.inputs.release_upload_url != ''\n        uses: actions/upload-release-asset@v1\n        env:\n          GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}\n        with:\n          upload_url: ${{ github.event.inputs.release_upload_url }}\n          asset_path: ${{ env.DEB_PATH }}\n          asset_name: NeoHtop_${{ steps.version.outputs.version }}_x86_64.deb\n          asset_content_type: application/vnd.debian.binary-package\n\n      - name: Upload RPM Package to Release\n        if: github.event.inputs.release_upload_url != ''\n        uses: actions/upload-release-asset@v1\n        env:\n          GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}\n        with:\n          upload_url: ${{ github.event.inputs.release_upload_url }}\n          asset_path: ${{ env.RPM_PATH }}\n          asset_name: NeoHtop_${{ steps.version.outputs.version }}_x86_64.rpm\n          asset_content_type: application/x-rpm\n"
  },
  {
    "path": ".github/workflows/macos-nightly.yml",
    "content": "name: MacOS (Intel/Apple Silicon) Nightly Build\n\non:\n  workflow_dispatch:\n    inputs:\n      release_upload_url:\n        description: 'Release upload URL'\n        required: true\n\nenv:\n  CARGO_TERM_COLOR: always\n\njobs:\n  build:\n    name: Build MacOS Apps\n    runs-on: macos-latest\n    \n    steps:\n      - uses: actions/checkout@v4\n      \n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 'lts/*'\n          cache: 'npm'\n          \n      - name: Install Rust\n        uses: dtolnay/rust-toolchain@stable\n        \n      - name: Install Dependencies\n        run: |\n          rustup target add x86_64-apple-darwin\n          rustup target add aarch64-apple-darwin\n          npm install\n          \n      - name: Set up keychain\n        run: |\n          security create-keychain -p \"\" build.keychain\n          security default-keychain -s build.keychain\n          security unlock-keychain -p \"\" build.keychain\n          echo \"$MACOS_CERTIFICATE\" | base64 --decode > /tmp/certificate.p12\n          security import /tmp/certificate.p12 -k build.keychain -P \"$MACOS_CERTIFICATE_PASSWORD\" -T /usr/bin/codesign\n          security set-key-partition-list -S apple-tool:,apple: -s -k \"\" build.keychain\n        env:\n          MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}\n          MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}\n          \n      - name: Build Frontend\n        run: npm run build\n        \n      - name: Build for Intel Mac\n        run: |\n          echo \"Building for Intel Mac...\"\n          npm run tauri build -- --target x86_64-apple-darwin --bundles dmg --config \"{\\\"bundle\\\":{\\\"macOS\\\":{\\\"signingIdentity\\\": \\\"Developer ID Application: Abdenasser Elidrissi (785JV74B9Y)\\\"}}}\"\n          # Rename the Intel build and store the filename\n          cd src-tauri/target/x86_64-apple-darwin/release/bundle/dmg/\n          for f in *.dmg; do \n            mv \"$f\" \"intel-$f\"\n            echo \"INTEL_DMG_PATH=src-tauri/target/x86_64-apple-darwin/release/bundle/dmg/intel-$f\" >> $GITHUB_ENV\n          done\n        env:\n          APPLE_ID: ${{ secrets.APPLE_ID }}\n          APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}\n          APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}\n          \n      - name: Build for Apple Silicon\n        run: |\n          echo \"Building for aarch64...\"\n          npm run tauri build -- --target aarch64-apple-darwin --bundles dmg --config \"{\\\"bundle\\\":{\\\"macOS\\\":{\\\"signingIdentity\\\": \\\"Developer ID Application: Abdenasser Elidrissi (785JV74B9Y)\\\"}}}\"\n          # Rename the Apple Silicon build and store the filename\n          cd src-tauri/target/aarch64-apple-darwin/release/bundle/dmg/\n          for f in *.dmg; do \n            mv \"$f\" \"silicon-$f\"\n            echo \"SILICON_DMG_PATH=src-tauri/target/aarch64-apple-darwin/release/bundle/dmg/silicon-$f\" >> $GITHUB_ENV\n          done\n        env:\n          APPLE_ID: ${{ secrets.APPLE_ID }}\n          APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}\n          APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}\n          \n      - name: Get version from package.json\n        id: version\n        run: echo \"version=$(node -p \"require('./package.json').version\")\" >> $GITHUB_OUTPUT\n\n      - name: Upload Intel Build to Release\n        if: github.event.inputs.release_upload_url != ''\n        uses: actions/upload-release-asset@v1\n        env:\n          GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}\n        with:\n          upload_url: ${{ github.event.inputs.release_upload_url }}\n          asset_path: ${{ env.INTEL_DMG_PATH }}\n          asset_name: intel-NeoHtop_${{ steps.version.outputs.version }}_x64.dmg\n          asset_content_type: application/x-apple-diskimage\n\n      - name: Upload Silicon Build to Release\n        if: github.event.inputs.release_upload_url != ''\n        uses: actions/upload-release-asset@v1\n        env:\n          GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}\n        with:\n          upload_url: ${{ github.event.inputs.release_upload_url }}\n          asset_path: ${{ env.SILICON_DMG_PATH }}\n          asset_name: silicon-NeoHtop_${{ steps.version.outputs.version }}_aarch64.dmg\n          asset_content_type: application/x-apple-diskimage"
  },
  {
    "path": ".github/workflows/test-release.yml",
    "content": "name: Test Release Build\n\non:\n  workflow_dispatch: # Manual trigger\n\njobs:\n  create-draft:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Get version from package.json\n        id: version\n        run: echo \"version=$(node -p \"require('./package.json').version\")\" >> $GITHUB_OUTPUT\n\n      - name: Create Draft Release\n        id: create_release\n        uses: softprops/action-gh-release@v1\n        with:\n          name: \"NeoHtop v${{ steps.version.outputs.version }}\"\n          tag_name: \"v${{ steps.version.outputs.version }}\"\n          draft: true\n        env:\n          GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}\n\n      - name: Trigger MacOS Build\n        uses: benc-uk/workflow-dispatch@v1\n        with:\n          workflow: macos-nightly.yml\n          token: ${{ secrets.PAT_TOKEN }}\n          inputs: '{\"release_upload_url\": \"${{ steps.create_release.outputs.upload_url }}\"}'\n\n      - name: Trigger Windows Build\n        uses: benc-uk/workflow-dispatch@v1\n        with:\n          workflow: windows-nightly.yml\n          token: ${{ secrets.PAT_TOKEN }}\n          inputs: '{\"release_upload_url\": \"${{ steps.create_release.outputs.upload_url }}\"}'\n\n      - name: Trigger Linux x86_64 Build\n        uses: benc-uk/workflow-dispatch@v1\n        with:\n          workflow: linux-x86_64-nightly.yml\n          token: ${{ secrets.PAT_TOKEN }}\n          inputs: '{\"release_upload_url\": \"${{ steps.create_release.outputs.upload_url }}\"}'\n"
  },
  {
    "path": ".github/workflows/windows-nightly.yml",
    "content": "name: Windows (x86_64) Nightly Build\n\non:\n  workflow_dispatch:\n    inputs:\n      release_upload_url:\n        description: 'Release upload URL'\n        required: true\n\nenv:\n  CARGO_TERM_COLOR: always\n\njobs:\n  build:\n    name: Build Windows Executable\n    runs-on: windows-latest\n    \n    steps:\n      - uses: actions/checkout@v4\n      \n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 'lts/*'\n          cache: 'npm'\n          \n      - name: Install Rust\n        uses: dtolnay/rust-toolchain@stable\n        \n      - name: Install WebView2\n        run: |\n          $WebView2InstallPath = \"$env:TEMP\\MicrosoftEdgeWebview2Setup.exe\"\n          Invoke-WebRequest \"https://go.microsoft.com/fwlink/p/?LinkId=2124703\" -OutFile $WebView2InstallPath\n          Start-Process -FilePath $WebView2InstallPath -Args \"/silent /install\" -Wait\n          \n      - name: Install Dependencies\n        run: |\n          npm install\n          \n      - name: Build Frontend\n        run: npm run build\n        \n      - name: Build Windows Executable\n        shell: bash  # Force using bash shell for consistent environment variable setting\n        run: |\n          echo \"Building Windows executable...\"\n          npm run tauri build\n          echo \"WIN_EXE_PATH=src-tauri/target/release/NeoHtop.exe\" >> $GITHUB_ENV\n          \n      - name: Get version from package.json\n        id: version\n        shell: bash  # Force using bash shell\n        run: echo \"version=$(node -p \"require('./package.json').version\")\" >> $GITHUB_OUTPUT\n          \n      - name: Upload to Release\n        if: github.event.inputs.release_upload_url != ''\n        uses: actions/upload-release-asset@v1\n        env:\n          GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}\n        with:\n          upload_url: ${{ github.event.inputs.release_upload_url }}\n          asset_path: ${{ env.WIN_EXE_PATH }}\n          asset_name: NeoHtop_${{ steps.version.outputs.version }}_x64.exe\n          asset_content_type: application/vnd.microsoft.portable-executable"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nnode_modules\n/build\n/.svelte-kit\n/package\n.env\n.env.*\n!.env.example\nvite.config.js.timestamp-*\nvite.config.ts.timestamp-*\n\n## Jetbrains\n.idea/\n.run/"
  },
  {
    "path": ".husky/pre-commit",
    "content": "#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\nnpm exec lint-staged\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"plugins\": [\"prettier-plugin-svelte\"],\n  \"overrides\": [{ \"files\": \"*.svelte\", \"options\": { \"parser\": \"svelte\" } }]\n}\n"
  },
  {
    "path": ".vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\n    \"svelte.svelte-vscode\",\n    \"tauri-apps.tauri-vscode\",\n    \"rust-lang.rust-analyzer\"\n  ]\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  \"svelte.enable-ts-plugin\": true\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2024 Abdenasser\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE. "
  },
  {
    "path": "README.md",
    "content": "\n<div align=\"center\">\n  <img src=\"app-icon.png\" alt=\"NeoHtop Logo\" width=\"120\" />\n  <h1>NeoHtop</h1>\n  <p>A modern, cross-platform system monitor built on top of Svelte, Rust, and Tauri.</p>\n\n  [![License](https://img.shields.io/github/license/Abdenasser/neohtop)](https://github.com/Abdenasser/neohtop/blob/main/LICENSE)\n  [![GitHub stars](https://img.shields.io/github/stars/Abdenasser/neohtop)](https://github.com/Abdenasser/neohtop/stargazers)\n  [![GitHub issues](https://img.shields.io/github/issues/Abdenasser/neohtop)](https://github.com/Abdenasser/neohtop/issues)\n  [![GitHub release](https://img.shields.io/github/v/release/Abdenasser/neohtop)](https://github.com/Abdenasser/neohtop/releases)\n  [![Notarized by Apple](https://img.shields.io/badge/Release_Notarized_by_Apple-000000?style=flat-square&logo=apple&logoColor=white)](https://developer.apple.com/documentation/security/notarizing-macos-software-before-distribution)\n</div>\n\n<div align=\"center\">\n  <picture>\n    <!-- <source media=\"(prefers-color-scheme: dark)\" srcset=\"screenshot.png\">\n    <source media=\"(prefers-color-scheme: light)\" srcset=\"screenshot-light.png\"> -->\n    <img alt=\"NeoHtop Screenshot\" src=\"./screenshot.png\" width=\"800\">\n  </picture>\n</div>\n\n<div align=\"center\">\n  <p>If you find this project helpful, consider buying me a coffee:</p>\n  <a href=\"https://www.buymeacoffee.com/abdenasser\" target=\"_blank\"><img src=\"https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png\" alt=\"Buy Me A Coffee\" style=\"height: 60px !important;width: 217px !important;\" ></a>\n  <p>Or sponsor me on GitHub:</p>\n  <a href=\"https://github.com/sponsors/Abdenasser\" target=\"_blank\"><img src=\"https://img.shields.io/badge/Sponsor-abdenasser-white?style=flat&logo=github&logoColor=pink\" alt=\"Sponsor @abdenasser\" style=\"height: auto !important;width: 217px !important;\"></a>\n\n</div>\n\n## Table of Contents\n- [Why NeoHtop?](#why-neohtop)\n- [Features](#features)\n- [Tech Stack](#tech-stack)\n- [Getting Started](#getting-started)\n  - [Prerequisites](#prerequisites)\n  - [Installation](#installation)\n  - [Running with Sudo](#running-with-sudo)\n- [Development](#development)\n  - [Setup](#setup)\n  - [Code Formatting](#code-formatting)\n  - [Pull Requests](#pull-requests)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Why NeoHtop?\n[Read about the back story and motivation behind NeoHtop](https://www.abdenasser.com/2024/11/06/oh-boy-neohtop/)\n\n## Features\n- 🚀 Real-time process monitoring\n- 💻 CPU and Memory usage tracking\n- 🎨 Beautiful, modern UI with dark/light themes\n- 🔍 Advanced process search and filtering\n- 📌 Pin important processes\n- 🛠 Process management (kill processes)\n- 🎯 Sort by any column\n- 🔄 Auto-refresh system stats\n\n### Search Functionality\nSearch for processes by name, command, or PID. Use commas to search for multiple terms simultaneously. Regular expressions are supported for advanced filtering.\n\nExamples:\n- `arm, x86`: Returns processes with \"arm\" or \"x86\" in the name or command\n- `d$`: Lists daemons (processes ending with 'd')\n- `^(\\w+\\.)+\\w+$`: Shows processes with reverse domain name notation (e.g., com.docker.vmnetd)\n\n## Tech Stack\n- **Frontend**: SvelteKit, TypeScript\n- **Backend**: Rust, Tauri\n- **Styling**: CSS Variables for theming\n- **Icons**: FontAwesome\n\n## Getting Started\n\n### Prerequisites\n- Node.js (v16 or later)\n- Rust (latest stable)\n- Xcode Command Line Tools (for macOS)\n\n### Installation\n\n#### Manual\nDownload the latest release from the [releases page](https://github.com/Abdenasser/neohtop/releases).\n\n#### Package Managers\n\nMembers of the community have kindly published unofficial packages for various platforms and package managers.\n\nPlease note, these packages are community-maintained and not officially released, reviewed, or endorsed by NeoHtop.\nWe only provide official builds through the GitHub Releases page.\nSince these external packages are managed by third parties, we cannot guarantee their security, integrity, or update frequency.\n\nPlease use them at your own discretion.\n\n##### macOS\n\nUsing [Homebrew](https://brew.sh/).\n\n```bash\nbrew install --cask neohtop\n```\n\n##### Arch Linux (AUR)\n\nUsing the [AUR](https://aur.archlinux.org/) and [an AUR helper](https://wiki.archlinux.org/title/AUR_helpers).\n\n```bash\nyay -S neohtop\n```\n\nor\n\n```bash\nparu -S neohtop\n```\n\n##### Fedora Linux\nInstall the [Terra repository](https://terra.fyralabs.com/).\n\n```bash\ndnf install neohtop\n```\n\n##### Windows\nInstall the [Scoop repository](https://scoop.sh/), then make sure you have the Scoop extras bucket added:\n\n```bash\nscoop bucket add extras\n```\n\nThen install with:\n\n```bash\nscoop install extras/neohtop\n```\n\n##### Solus\n\n```bash\neopkg install neohtop\n```\n\n### Running with Sudo\nSome processes require monitoring with sudo privileges. To monitor these processes, launch NeoHtop with sudo:\n\n- macOS: `sudo /Applications/NeoHtop.app/Contents/MacOS/NeoHtop`\n- Linux: `pkexec /path/to/neohtop` (recommended)\n\n## Development\n\n### Setup\n```bash\n# Install dependencies\nnpm install\n\n# Run in development mode\nnpm run tauri dev\n\n# Build for production\nnpm run tauri build\n```\n\n### Code Formatting\nWe use Prettier for web code and `cargo fmt` for Rust code.\n\n```bash\n# Format all files\nnpm run format\n\n# Check formatting without making changes\nnpm run format:check\n```\n\n### Pull Requests\nBefore submitting a PR, ensure:\n1. All code is formatted (`npm run format`)\n2. The format check passes (`npm run format:check`)\n3. Your commits follow the project's commit message conventions\n\n## Contributing\nWe welcome contributions! Please see our [contributing guidelines](./.github/CONTRIBUTING.md) for more information.\n\n## License\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n"
  },
  {
    "path": "docs/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>NeoHtop - Blazing-fast system monitoring for your desktop (built with Rust, Tauri & Svelte)</title>\n  <meta name=\"description\"\n    content=\"A beautiful, efficient system monitor built with Rust and Svelte. Monitor processes, CPU, and memory usage in real-time with a modern interface.\">\n  <meta name=\"keywords\"\n    content=\"system monitor, task manager, cross-platform, process monitor, cpu usage, memory usage, rust, svelte\">\n  <meta name=\"author\" content=\"Your Name\">\n  <meta property=\"og:type\" content=\"website\">\n  <meta property=\"og:url\" content=\"https://abdenasser.github.io/neohtop/\">\n  <meta property=\"og:title\" content=\"NeoHtop - Blazing-fast system monitoring for your desktop\">\n  <meta property=\"og:description\"\n    content=\"A beautiful, efficient system monitor built with Rust and Svelte. Monitor processes, CPU, and memory usage in real-time.\">\n  <meta property=\"og:image\" content=\"https://github.com/Abdenasser/neohtop/raw/main/app-icon.png\">\n  <meta name=\"twitter:card\" content=\"summary_large_image\">\n  <meta name=\"twitter:creator\" content=\"@__abdenasser\">\n  <meta name=\"twitter:title\" content=\"NeoHtop - Blazing-fast system monitoring for your desktop\">\n  <meta name=\"twitter:description\" content=\"A beautiful, efficient system monitor built with Rust and Svelte.\">\n  <meta name=\"twitter:image\" content=\"https://github.com/Abdenasser/neohtop/raw/main/app-icon.png\">\n  <link rel=\"icon\" type=\"image/png\" href=\"favicon.ico\">\n  <link rel=\"apple-touch-icon\" href=\"apple-touch-icon.png\">\n  <link rel=\"stylesheet\" href=\"styles.css\">\n  <link rel=\"preload\" href=\"https://github.com/Abdenasser/neohtop/raw/main/app-icon.png\" as=\"image\">\n  <link rel=\"preload\" href=\"https://github.com/Abdenasser/neohtop/raw/main/screenshot.png\" as=\"image\">\n</head>\n\n<body>\n  <header class=\"glass-nav\">\n    <nav>\n      <div class=\"logo-container\">\n        <img src=\"https://github.com/Abdenasser/neohtop/raw/main/app-icon.png\" alt=\"NeoHtop\" class=\"nav-logo\">\n        <span class=\"nav-brand\">NeoHtop</span>\n      </div>\n      <button class=\"menu-button\" aria-label=\"Toggle menu\">\n        ☰\n      </button>\n      <div class=\"nav-links\">\n        <a href=\"#home\">Home</a>\n        <a href=\"#features\">Features</a>\n        <a href=\"#download\">Download</a>\n        <a href=\"#install\">Install</a>\n        <a href=\"#testimonials\">Testimonials</a>\n        <a href=\"#faq\">FAQ</a>\n        <button id=\"themeToggle\" class=\"theme-toggle\" aria-label=\"Toggle theme\">\n          <span class=\"theme-icon\">🌙</span>\n        </button>\n      </div>\n    </nav>\n  </header>\n\n  <main>\n    <section id=\"home\" class=\"hero\">\n      <div class=\"hero-content\">\n        <div class=\"hero-text\">\n          <h1 class=\"gradient-text\">Monitor Your System<br>With Style</h1>\n          <p class=\"hero-subtitle\">A beautiful, lightning-fast cross-platform system monitor.</p>\n          <div class=\"hero-cta\">\n            <a href=\"#download\" class=\"primary-button\">Download Now</a>\n            <a href=\"https://github.com/abdenasser/neohtop\" class=\"secondary-button\">\n              View on GitHub\n            </a>\n          </div>\n          <div class=\"badges\">\n            <script data-name=\"BMC-Widget\" data-cfasync=\"false\"\n              src=\"https://cdnjs.buymeacoffee.com/1.0.0/widget.prod.min.js\" data-id=\"abdenasser\"\n              data-description=\"Support me on Buy me a coffee!\" data-message=\"\" data-color=\"#FF5F5F\"\n              data-position=\"Right\" data-x_margin=\"18\" data-y_margin=\"18\"></script>\n          </div>\n        </div>\n      </div>\n      <div class=\"hero-background\">\n        <img src=\"https://github.com/Abdenasser/neohtop/raw/main/screenshot-light.png\" alt=\"NeoHtop Interface light\" />\n        <img src=\"https://github.com/Abdenasser/neohtop/raw/main/screenshot.png\" alt=\"NeoHtop Interface dark\" />\n      </div>\n    </section>\n\n    <section id=\"features\" class=\"features\">\n      <h2 class=\"section-title\">Why Choose NeoHtop?</h2>\n      <div class=\"feature-grid\">\n        <div class=\"feature-card\">\n          <div class=\"feature-icon\">🚀</div>\n          <h3>Real-time Monitoring</h3>\n          <p>Track system processes in real-time with minimal resource usage</p>\n        </div>\n        <div class=\"feature-card\">\n          <div class=\"feature-icon\">🎨</div>\n          <h3>Modern UI</h3>\n          <p>Beautiful interface with automatic dark/light theme detection</p>\n        </div>\n        <div class=\"feature-card\">\n          <div class=\"feature-icon\">🔍</div>\n          <h3>Smart Search</h3>\n          <p>Quick process search with advanced filtering options</p>\n        </div>\n        <div class=\"feature-card\">\n          <div class=\"feature-icon\">📌</div>\n          <h3>Process Pinning</h3>\n          <p>Keep important processes in view for easy monitoring</p>\n        </div>\n        <div class=\"feature-card\">\n          <div class=\"feature-icon\">⚡️</div>\n          <h3>Resource Efficient</h3>\n          <p>Built with Rust for optimal performance and low memory usage</p>\n        </div>\n        <div class=\"feature-card\">\n          <div class=\"feature-icon\">🛠</div>\n          <h3>Process Management</h3>\n          <p>View and manage processes with detailed information</p>\n        </div>\n      </div>\n    </section>\n\n    <section id=\"download\" class=\"downloads\">\n      <div class=\"download-container glass-card\">\n        <h2>Download NeoHtop <span id=\"current-version\">Loading...</span></h2>\n        <div class=\"download-stats\">\n          <span id=\"download-count\">...</span> Total Downloads\n        </div>\n        <p class=\"download-subtitle\">Choose your platform to get started</p>\n        <div class=\"download-options\">\n          <!-- macOS Downloads -->\n          <div class=\"download-group\">\n            <h3 class=\"platform-title\">macOS</h3>\n            <!-- notarized by apple badge -->\n            <div class=\"notarized-badge\">\n              <img\n                src=\"https://img.shields.io/badge/Notarized%20by%20Apple-000000?style=for-the-badge&logo=apple&logoColor=white\"\n                alt=\"Notarized by Apple\">\n            </div>\n            <div class=\"platform-options\">\n              <a href=\"\" class=\"download-button macos\" data-type=\"macos-intel\" data-version=\"latest\">\n                <span class=\"icon\">💻</span>\n                <div class=\"button-text\">\n                  <span class=\"primary\">Intel Chip</span>\n                  <span class=\"secondary\">macOS 10.15 or later</span>\n                </div>\n              </a>\n              <a href=\"\" class=\"download-button macos\" data-type=\"macos-silicon\" data-version=\"latest\">\n                <span class=\"icon\">🍎</span>\n                <div class=\"button-text\">\n                  <span class=\"primary\">Apple Silicon</span>\n                  <span class=\"secondary\">macOS 11.0 or later</span>\n                </div>\n              </a>\n            </div>\n          </div>\n\n          <!-- Windows Download -->\n          <div class=\"download-group\">\n            <h3 class=\"platform-title\">Windows</h3>\n            <div class=\"platform-options\">\n              <a href=\"\" class=\"download-button windows\" data-type=\"windows\" data-version=\"latest\">\n                <span class=\"icon\">🫣</span>\n                <div class=\"button-text\">\n                  <span class=\"primary\">Windows</span>\n                  <span class=\"secondary\">Windows 10 or later</span>\n                </div>\n              </a>\n            </div>\n          </div>\n\n          <!-- Linux Downloads -->\n          <div class=\"download-group\">\n            <h3 class=\"platform-title\">Linux</h3>\n            <div class=\"platform-options\">\n              <!-- x86_64 Downloads -->\n              <div class=\"linux-downloads\">\n                <h4>x86_64</h4>\n                <a href=\"\" class=\"download-button linux\" data-type=\"linux-deb-x64\" data-version=\"latest\">\n                  <span class=\"icon\">📦</span>\n                  <div class=\"button-text\">\n                    <span class=\"primary\">.deb Package</span>\n                    <span class=\"secondary\">Debian/Ubuntu</span>\n                  </div>\n                </a>\n                <a href=\"\" class=\"download-button linux\" data-type=\"linux-appimage-x64\" data-version=\"latest\"\n                  style=\"margin-top: 10px;\">\n                  <span class=\"icon\">🐧</span>\n                  <div class=\"button-text\">\n                    <span class=\"primary\">AppImage</span>\n                    <span class=\"secondary\">Universal Linux</span>\n                  </div>\n                </a>\n                <a href=\"\" class=\"download-button linux\" data-type=\"linux-rpm-x64\" data-version=\"latest\"\n                  style=\"margin-top: 10px;\">\n                  <span class=\"icon\">📦</span>\n                  <div class=\"button-text\">\n                    <span class=\"primary\">.rpm Package</span>\n                    <span class=\"secondary\">Fedora/RHEL x86_64</span>\n                  </div>\n                </a>\n              </div>\n\n              <!-- ARM64 Downloads -->\n              <div class=\"linux-downloads\">\n                <h4>ARM64</h4>\n                <a href=\"\" class=\"download-button linux\" data-type=\"linux-deb-arm64\" data-version=\"latest\">\n                  <span class=\"icon\">📦</span>\n                  <div class=\"button-text\">\n                    <span class=\"primary\">.deb Package</span>\n                    <span class=\"secondary\">Debian/Ubuntu ARM64</span>\n                  </div>\n                </a>\n                <a href=\"\" class=\"download-button linux\" data-type=\"linux-appimage-arm64\" data-version=\"latest\"\n                  style=\"margin-top: 10px;\">\n                  <span class=\"icon\">🐧</span>\n                  <div class=\"button-text\">\n                    <span class=\"primary\">AppImage</span>\n                    <span class=\"secondary\">Universal Linux ARM64</span>\n                  </div>\n                </a>\n                <a href=\"\" class=\"download-button linux\" data-type=\"linux-rpm-arm64\" data-version=\"latest\"\n                  style=\"margin-top: 10px;\">\n                  <span class=\"icon\">📦</span>\n                  <div class=\"button-text\">\n                    <span class=\"primary\">.rpm Package</span>\n                    <span class=\"secondary\">Fedora/RHEL ARM64</span>\n                  </div>\n                </a>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </section>\n\n    <section id=\"install\" class=\"install\">\n      <h2>Installation Guide</h2>\n      <div class=\"install-steps\">\n        <div class=\"step\">\n          <span class=\"step-number\">1</span>\n          <h3>Download</h3>\n          <p>Choose and download the appropriate version for your Mac</p>\n        </div>\n        <div class=\"step\">\n          <span class=\"step-number\">2</span>\n          <h3>Open DMG</h3>\n          <p>Double-click the downloaded .dmg file</p>\n        </div>\n        <div class=\"step\">\n          <span class=\"step-number\">3</span>\n          <h3>Install</h3>\n          <p>Drag NeoHtop to your Applications folder</p>\n        </div>\n        <div class=\"step\">\n          <span class=\"step-number\">4</span>\n          <h3>First Launch</h3>\n          <p>Right-click and choose Open to bypass Gatekeeper</p>\n        </div>\n      </div>\n    </section>\n\n    <section id=\"testimonials\" class=\"testimonials\">\n      <h2 class=\"section-title\">What People Are Saying</h2>\n      <div class=\"testimonial-grid\">\n        <blockquote class=\"twitter-tweet\">\n          <p lang=\"en\" dir=\"ltr\">Neohtop is absolutely beautiful to look at. It's a modern system monitor inspired by\n            htop, providing real-time insights into CPU, memory, disk, and network usage. A work of art! <a\n              href=\"https://t.co/TAzCIEb8uF\">pic.twitter.com/TAzCIEb8uF</a></p>&mdash; JoeyBaggaDonuts (@haxxusj) <a\n            href=\"https://twitter.com/haxxusj/status/1854590782684250487?ref_src=twsrc%5Etfw\">November 7, 2024</a>\n        </blockquote>\n\n\n        <blockquote class=\"twitter-tweet\">\n          <p lang=\"zh\" dir=\"ltr\">Htop 加强版： NeoHtop<br>基于 Svelte、Rust 和 Tauri 构建的现代化、跨平台的系统监控工具<a\n              href=\"https://t.co/OtWlxxrCHZ\">https://t.co/OtWlxxrCHZ</a> <a\n              href=\"https://t.co/2MK9n8rZVw\">pic.twitter.com/2MK9n8rZVw</a></p>&mdash; Geek (@geekbb) <a\n            href=\"https://twitter.com/geekbb/status/1854081285846888881?ref_src=twsrc%5Etfw\">November 6, 2024</a>\n        </blockquote>\n\n\n        <blockquote class=\"twitter-tweet\">\n          <p lang=\"zh\" dir=\"ltr\">💻 NeoHtop：现代跨平台系统监视器！实时追踪 CPU 和内存使用，支持进程管理。<br><br>基于 Svelte、Rust 和 Tauri\n            构建，轻量高效，非常适合日常系统监控！<br><br>👉 <a href=\"https://t.co/MaOIMMbbPV\">https://t.co/MaOIMMbbPV</a> <a\n              href=\"https://t.co/rFLyULJVei\">https://t.co/rFLyULJVei</a> <a\n              href=\"https://t.co/6c6hGOeiLa\">pic.twitter.com/6c6hGOeiLa</a></p>&mdash; 小弟调调 (@jaywcjlove) <a\n            href=\"https://twitter.com/jaywcjlove/status/1854089502853357880?ref_src=twsrc%5Etfw\">November 6, 2024</a>\n        </blockquote>\n\n\n        <blockquote class=\"twitter-tweet\">\n          <p lang=\"en\" dir=\"ltr\">neoHTOP: A modern, cross-platform system monitor built on top of Svelte, Rust and\n            Tauri<a href=\"https://t.co/MKZ53ZThKv\">https://t.co/MKZ53ZThKv</a></p>&mdash; Nitin (@gniting) <a\n            href=\"https://twitter.com/gniting/status/1853920938976223463?ref_src=twsrc%5Etfw\">November 5, 2024</a>\n        </blockquote>\n\n\n        <blockquote class=\"twitter-tweet\">\n          <p lang=\"en\" dir=\"ltr\">🚀 Introducing NeoHtop, the ultimate process monitoring tool for all your system needs!\n            🖥️ Say goodbye to clunky, outdated monitors and hello to a modern, native solution with a clean and\n            user-friendly interface. 🤩 With NeoHtop, you can easily keep track of your system's… <a\n              href=\"https://t.co/qq8cXI8Qq1\">pic.twitter.com/qq8cXI8Qq1</a></p>&mdash; Durgesh Gupta (@ilearnbydoing) <a\n            href=\"https://twitter.com/ilearnbydoing/status/1854037593987428754?ref_src=twsrc%5Etfw\">November 6, 2024</a>\n        </blockquote>\n\n\n        <blockquote class=\"twitter-tweet\">\n          <p lang=\"zxx\" dir=\"ltr\"><a href=\"https://t.co/2EoanAOvYL\">https://t.co/2EoanAOvYL</a></p>&mdash; Tom Dörr\n          (@tom_doerr) <a href=\"https://twitter.com/tom_doerr/status/1853861836736881133?ref_src=twsrc%5Etfw\">November\n            5, 2024</a>\n        </blockquote>\n\n\n        <blockquote class=\"twitter-tweet\">\n          <p lang=\"ru\" dir=\"ltr\">NeoHtop – мощный и стильный менеджер процессов<a\n              href=\"https://t.co/uiGhE2YlFC\">https://t.co/uiGhE2YlFC</a></p>&mdash; ITforNote (@itfornote) <a\n            href=\"https://twitter.com/itfornote/status/1855943550036299934?ref_src=twsrc%5Etfw\">November 11, 2024</a>\n        </blockquote>\n\n\n        <blockquote class=\"twitter-tweet\">\n          <p lang=\"en\" dir=\"ltr\">Discover NeoHtop, a modern task manager for macOS combining terminal power with a\n            user-friendly interface, built with Rust, Tauri &amp; Svelte.<br><br>{ author: <a\n              href=\"https://twitter.com/__abdenasser?ref_src=twsrc%5Etfw\">@__abdenasser</a> } <a\n              href=\"https://twitter.com/hashtag/CodeNewbie?src=hash&amp;ref_src=twsrc%5Etfw\">#CodeNewbie</a><a\n              href=\"https://t.co/rowekkvOUY\">https://t.co/rowekkvOUY</a></p>&mdash; CodeNewbie (@CodeNewbies) <a\n            href=\"https://twitter.com/CodeNewbies/status/1854886849677824003?ref_src=twsrc%5Etfw\">November 8, 2024</a>\n        </blockquote>\n\n\n        <blockquote class=\"twitter-tweet\">\n          <p lang=\"de\" dir=\"ltr\">NeoHtop: Ein Systemmonitor für macOS <a\n              href=\"https://t.co/wUEMeCKpkv\">https://t.co/wUEMeCKpkv</a></p>&mdash; Ramón Goeden 🤨 (@websenat) <a\n            href=\"https://twitter.com/websenat/status/1854134191480262993?ref_src=twsrc%5Etfw\">November 6, 2024</a>\n        </blockquote>\n\n\n        <blockquote class=\"twitter-tweet\">\n          <p lang=\"de\" dir=\"ltr\">NeoHtop: Ein Systemmonitor für macOS <a\n              href=\"https://t.co/RCjYWlC81x\">https://t.co/RCjYWlC81x</a></p>&mdash; CaschysBlog (@CaschysBlog) <a\n            href=\"https://twitter.com/CaschysBlog/status/1854110661502017689?ref_src=twsrc%5Etfw\">November 6, 2024</a>\n        </blockquote>\n\n\n        <blockquote class=\"twitter-tweet\">\n          <p lang=\"en\" dir=\"ltr\">NeoHtop offers a modern interface with additional features like process pinning, smart\n            search, and themes while maintaining high performance through its Rust backend. It's designed to be more\n            user-friendly and efficient than traditional system monitors.<a\n              href=\"https://t.co/c4niSeqw0p\">https://t.co/c4niSeqw0p</a> <a\n              href=\"https://t.co/hnqrfSiSFG\">pic.twitter.com/hnqrfSiSFG</a></p>&mdash; Hustle Hacker (@HustleHackerAI)\n          <a href=\"https://twitter.com/HustleHackerAI/status/1854352028304040139?ref_src=twsrc%5Etfw\">November 7,\n            2024</a>\n        </blockquote>\n\n\n        <blockquote class=\"twitter-tweet\">\n          <p lang=\"ja\" dir=\"ltr\">NeoHtopめちゃかっこいい。macOSでも動く。Apple\n            Silicon版もちゃんとある。手元で動かしてみたけどアクティビティモニタより好きかも。<br><br>Abdenasser/neohtop: 💪🏻 htop on steroids <a\n              href=\"https://t.co/u70aTS1rKK\">https://t.co/u70aTS1rKK</a> <a\n              href=\"https://t.co/c0iyjiW73q\">pic.twitter.com/c0iyjiW73q</a></p>&mdash; Isao Shimizu (@isaoshimizu) <a\n            href=\"https://twitter.com/isaoshimizu/status/1854097990698586584?ref_src=twsrc%5Etfw\">November 6, 2024</a>\n        </blockquote>\n\n\n        <blockquote class=\"twitter-tweet\">\n          <p lang=\"ja\" dir=\"ltr\">見た目好みで使ってみてるシステムモニター、<a\n              href=\"https://t.co/7lHLB8WtVk\">https://t.co/7lHLB8WtVk</a><br>トグルボタンのアクティブ状態をアイコンを45度傾けるという方法で示してて、特殊すぎて２度見した\n            <a href=\"https://t.co/JFC6ueyfBF\">pic.twitter.com/JFC6ueyfBF</a>\n          </p>&mdash; UMERUMA (@umeruma) <a\n            href=\"https://twitter.com/umeruma/status/1855209294888902865?ref_src=twsrc%5Etfw\">November 9, 2024</a>\n        </blockquote>\n\n\n        <blockquote class=\"twitter-tweet\">\n          <p lang=\"en\" dir=\"ltr\">🖥️ <a\n              href=\"https://twitter.com/hashtag/NeoHtop?src=hash&amp;ref_src=twsrc%5Etfw\">#NeoHtop</a>: Cross-platform\n            system monitor combining <a\n              href=\"https://twitter.com/hashtag/Svelte?src=hash&amp;ref_src=twsrc%5Etfw\">#Svelte</a>, <a\n              href=\"https://twitter.com/hashtag/Rust?src=hash&amp;ref_src=twsrc%5Etfw\">#Rust</a>, and <a\n              href=\"https://twitter.com/hashtag/Tauri?src=hash&amp;ref_src=twsrc%5Etfw\">#Tauri</a> for a modern\n            monitoring experience <a\n              href=\"https://twitter.com/hashtag/opensource?src=hash&amp;ref_src=twsrc%5Etfw\">#opensource</a> <a\n              href=\"https://twitter.com/hashtag/devops?src=hash&amp;ref_src=twsrc%5Etfw\">#devops</a> <br><br>🚀 Key\n            features:<br>Real-time process monitoring<br>CPU &amp; memory usage tracking<br>Process search &amp;\n            filtering<br>Dark/light theme support<br><br>💻 Tech stack:…</p>&mdash; Micha(el) Bladowski 🇩🇪 🇺🇦\n          (@michabbb) <a href=\"https://twitter.com/michabbb/status/1853971838768173409?ref_src=twsrc%5Etfw\">November 6,\n            2024</a>\n        </blockquote>\n\n      </div>\n    </section>\n\n    <section id=\"faq\" class=\"faq\">\n      <h2 class=\"section-title\">Frequently Asked Questions</h2>\n      <div class=\"faq-list\">\n        <div class=\"faq-item\">\n          <button class=\"faq-question\">\n            <span class=\"question-text\">How does NeoHtop compare to Activity Monitor?</span>\n            <span class=\"faq-icon\">⌄</span>\n          </button>\n          <div class=\"faq-answer\">\n            <p>NeoHtop offers a modern interface with additional features like process pinning, smart search, and themes\n              while maintaining high performance through its Rust backend. It's designed to be more user-friendly and\n              efficient than traditional system monitors.</p>\n          </div>\n        </div>\n\n        <div class=\"faq-item\">\n          <button class=\"faq-question\">\n            <span class=\"question-text\">Is NeoHtop resource intensive?</span>\n            <span class=\"faq-icon\">⌄</span>\n          </button>\n          <div class=\"faq-answer\">\n            <p>No, NeoHtop is built with Rust and optimized for minimal resource usage, typically using less than 1% CPU\n              and minimal memory. It's designed to be lightweight while monitoring your system.</p>\n          </div>\n        </div>\n\n        <div class=\"faq-item\">\n          <button class=\"faq-question\">\n            <span class=\"question-text\">Does NeoHtop work on all macOS versions?</span>\n            <span class=\"faq-icon\">⌄</span>\n          </button>\n          <div class=\"faq-answer\">\n            <p>NeoHtop supports macOS 10.15 (Catalina) and newer versions. It's optimized for both Intel and Apple\n              Silicon Macs, with native support for both architectures.</p>\n          </div>\n        </div>\n\n        <div class=\"faq-item\">\n          <button class=\"faq-question\">\n            <span class=\"question-text\">Can I customize the interface?</span>\n            <span class=\"faq-icon\">⌄</span>\n          </button>\n          <div class=\"faq-answer\">\n            <p>Yes, NeoHtop offers various customization options including:\n            <ul>\n              <li>Dark/Light theme switching</li>\n              <li>Customizable columns and metrics</li>\n              <li>Adjustable refresh rates</li>\n              <li>Process grouping options</li>\n            </ul>\n            </p>\n          </div>\n        </div>\n\n        <div class=\"faq-item\">\n          <button class=\"faq-question\">\n            <span class=\"question-text\">Is NeoHtop open source?</span>\n            <span class=\"faq-icon\">⌄</span>\n          </button>\n          <div class=\"faq-answer\">\n            <p>Yes, NeoHtop is completely open source and available on GitHub. You can contribute to the project, report\n              issues, or suggest new features through our GitHub repository.</p>\n          </div>\n        </div>\n      </div>\n    </section>\n\n    <!-- Google tag (gtag.js) -->\n    <script async src=\"https://www.googletagmanager.com/gtag/js?id=G-88HFXRBNLS\"></script>\n    <script>\n      window.dataLayer = window.dataLayer || [];\n      function gtag() { dataLayer.push(arguments); }\n      gtag('js', new Date());\n\n      gtag('config', 'G-88HFXRBNLS');\n    </script>\n    <script src=\"main.js\"></script>\n  </main>\n  <footer class=\"footer\">\n    <div class=\"footer-content\">\n      <div class=\"footer-section\">\n        <h3>NeoHtop</h3>\n        <p class=\"footer-description\">\n          A modern system monitor built with Rust and Svelte.\n          Open source and free to use.\n        </p>\n      </div>\n\n      <div class=\"footer-section\">\n        <h4>Links</h4>\n        <ul class=\"footer-links\">\n          <li>\n            <a href=\"https://github.com/abdenasser/neohtop\" target=\"_blank\" rel=\"noopener\">\n              <span class=\"icon\">📦</span> GitHub Repository\n            </a>\n          </li>\n          <li>\n            <a href=\"https://github.com/abdenasser\" target=\"_blank\" rel=\"noopener\">\n              <span class=\"icon\">👨‍💻</span> Creator\n            </a>\n          </li>\n          <li>\n            <a href=\"https://github.com/abdenasser/neohtop/issues\" target=\"_blank\" rel=\"noopener\">\n              <span class=\"icon\">🐛</span> Report Issue\n            </a>\n          </li>\n        </ul>\n      </div>\n\n      <div class=\"footer-section\">\n        <h4>Tech Stack</h4>\n        <ul class=\"tech-stack-list\">\n          <li>\n            <a href=\"https://www.rust-lang.org/\" target=\"_blank\" rel=\"noopener\">\n              <span class=\"icon\">🦀</span> Rust\n            </a>\n          </li>\n          <li>\n            <a href=\"https://tauri.app/\" target=\"_blank\" rel=\"noopener\">\n              <span class=\"icon\">⚡</span> Tauri\n            </a>\n          </li>\n          <li>\n            <a href=\"https://svelte.dev/\" target=\"_blank\" rel=\"noopener\">\n              <span class=\"icon\">🎯</span> Svelte\n            </a>\n          </li>\n        </ul>\n      </div>\n    </div>\n\n    <div class=\"footer-bottom\">\n      <p>Made with <span class=\"heart\">❤️</span> and <span class=\"coffee\">☕</span> by\n        <a href=\"https://github.com/abdenasser\" target=\"_blank\" rel=\"noopener\">Abdenasser</a>\n      </p>\n    </div>\n  </footer>\n</body>\n<script async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\n\n</html>"
  },
  {
    "path": "docs/main.js",
    "content": "// ===============================\n// Theme Management\n// ===============================\nconst themeToggle = document.getElementById('themeToggle');\nconst prefersDark = window.matchMedia('(prefers-color-scheme: dark)');\n\nfunction setTheme(isDark) {\n  document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');\n  themeToggle.querySelector('.theme-icon').textContent = isDark ? '☀️' : '🌙';\n  localStorage.setItem('theme', isDark ? 'dark' : 'light');\n}\n\n// Initialize theme\nconst savedTheme = localStorage.getItem('theme');\nif (savedTheme) {\n  setTheme(savedTheme === 'dark');\n} else {\n  setTheme(prefersDark.matches);\n}\n\n// Theme event listeners\nthemeToggle.addEventListener('click', () => {\n  const isDark = document.documentElement.getAttribute('data-theme') === 'dark';\n  setTheme(!isDark);\n});\n\nprefersDark.addEventListener('change', (e) => {\n  if (!localStorage.getItem('theme')) {\n    setTheme(e.matches);\n  }\n});\n\n// ===============================\n// Version and Download Management\n// ===============================\nasync function fetchDownloadStats() {\n  try {\n    const releasesResponse = await fetch('https://api.github.com/repos/abdenasser/neohtop/releases');\n    const releases = await releasesResponse.json();\n    const githubDownloads = releases.reduce((total, release) => {\n      const releaseDownloads = release.assets.reduce((sum, asset) =>\n        sum + asset.download_count, 0);\n      return total + releaseDownloads;\n    }, 0);\n\n    const brewResponse = await fetch('https://formulae.brew.sh/api/analytics/install/homebrew-core/365d.json');\n    const brewData = await brewResponse.json();\n    const brewInstalls = brewData.formulae?.neohtop?.[0]?.count || 0;\n\n    const totalDownloads = githubDownloads + brewInstalls;\n    document.getElementById('download-count').textContent = new Intl.NumberFormat().format(totalDownloads);\n  } catch (error) {\n    console.error('Failed to fetch download stats:', error);\n    document.getElementById('download-count').textContent = 'N/A';\n  }\n}\n\nasync function updateVersion() {\n  try {\n    const response = await fetch('https://api.github.com/repos/Abdenasser/neohtop/releases/latest');\n    const data = await response.json();\n    const version = data.tag_name;\n    const versionNumber = version.match(/\\d+\\.\\d+\\.\\d+/)?.[0];\n\n    if (versionNumber) {\n      document.getElementById('current-version').textContent = \"v\" + versionNumber;\n      updateDownloadLinks(versionNumber);\n    }\n  } catch (error) {\n    console.error('Failed to fetch version:', error);\n  }\n}\n\nfunction updateDownloadLinks(versionNumber) {\n  const platformUrls = {\n    'macos-intel': `intel-NeoHtop_${versionNumber}_x64.dmg`,\n    'macos-silicon': `silicon-NeoHtop_${versionNumber}_aarch64.dmg`,\n    'windows': `NeoHtop_${versionNumber}_x64.exe`,\n    'linux-deb-x64': `NeoHtop_${versionNumber}_x86_64.deb`,\n    'linux-appimage-x64': `NeoHtop_${versionNumber}_x86_64.AppImage`,\n    'linux-rpm-x64': `NeoHtop_${versionNumber}_x86_64.rpm`,\n    'linux-deb-arm64': `NeoHtop_${versionNumber}_aarch64.deb`,\n    'linux-appimage-arm64': `NeoHtop_${versionNumber}_aarch64.AppImage`,\n    'linux-rpm-arm64': `NeoHtop_${versionNumber}_aarch64.rpm`\n  };\n\n  document.querySelectorAll('.download-button').forEach(link => {\n    const platform = link.getAttribute('data-type');\n    if (platformUrls[platform]) {\n      link.href = `https://github.com/Abdenasser/neohtop/releases/download/v${versionNumber}/${platformUrls[platform]}`;\n    }\n  });\n}\n\n// ===============================\n// UI Interactions\n// ===============================\n// FAQ Accordion\ndocument.querySelectorAll('.faq-question').forEach(button => {\n  button.addEventListener('click', () => {\n    const faqItem = button.parentElement;\n    const isActive = faqItem.classList.contains('active');\n    document.querySelectorAll('.faq-item').forEach(item => item.classList.remove('active'));\n    if (!isActive) faqItem.classList.add('active');\n  });\n});\n\n// Download tracking\ndocument.querySelectorAll('.download-button').forEach(button => {\n  button.addEventListener('click', (e) => {\n    gtag('event', 'download', {\n      'event_category': 'App',\n      'event_label': button.getAttribute('data-type'),\n      'value': button.getAttribute('data-version')\n    });\n  });\n});\n\n// Smooth scroll\ndocument.querySelectorAll('a[href^=\"#\"]').forEach(anchor => {\n  anchor.addEventListener('click', function (e) {\n    e.preventDefault();\n    const target = document.querySelector(this.getAttribute('href'));\n    if (target) {\n      target.scrollIntoView({ behavior: 'smooth', block: 'start' });\n    }\n  });\n});\n// ===============================\n// Animations\n// ===============================\nconst observer = new IntersectionObserver(\n  (entries) => {\n    entries.forEach(entry => {\n      if (entry.isIntersecting) {\n        entry.target.classList.add('visible');\n      }\n    });\n  },\n  { threshold: 0.1 }\n);\n\ndocument.querySelectorAll('.feature, .step, .download-button').forEach(el => {\n  observer.observe(el);\n});\n\n// ===============================\n// Initialization\n// ===============================\ndocument.addEventListener('DOMContentLoaded', () => {\n  updateVersion();\n  fetchDownloadStats();\n});\n\n\n// ===============================\n// Mobile Navigation\n// ===============================\n\ndocument.addEventListener('DOMContentLoaded', () => {\n  const menuButton = document.querySelector('.menu-button');\n  const navLinks = document.querySelector('.nav-links');\n\n  menuButton.addEventListener('click', () => {\n    navLinks.classList.toggle('active');\n  });\n\n  // Close menu when clicking outside\n  document.addEventListener('click', (e) => {\n    if (!navLinks.contains(e.target) && !menuButton.contains(e.target)) {\n      navLinks.classList.remove('active');\n    }\n  });\n});"
  },
  {
    "path": "docs/styles.css",
    "content": ":root {\n  --primary-color: #6366f1;\n  --secondary-color: #818cf8;\n  --background: #ffffff;\n  --text-primary: #1f2937;\n  --text-secondary: #4b5563;\n  --card-background: rgba(255, 255, 255, 0.8);\n}\n\n[data-theme=\"dark\"] {\n  --background: #0f172a;\n  --text-primary: #f1f5f9;\n  --text-secondary: #cbd5e1;\n  --card-background: rgba(30, 41, 59, 0.8);\n}\n\n* {\n  margin: 0;\n  padding: 0;\n  box-sizing: border-box;\n  scroll-behavior: smooth;\n}\n\nbody {\n  font-family: 'Inter', system-ui, sans-serif;\n  background: var(--background);\n  color: var(--text-primary);\n  line-height: 1.6;\n  transition: background-color 0.3s, color 0.3s;\n  margin: 0;\n  padding: 0;\n  min-height: 100vh;\n  width: 100%;\n}\n\n/* Header & Navigation */\nheader {\n  background: var(--card);\n  position: sticky;\n  top: 0;\n  z-index: 100;\n  backdrop-filter: blur(10px);\n  border-bottom: 1px solid var(--border);\n}\n\nnav {\n  max-width: 1200px;\n  margin: 0 auto;\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n}\n\n.logo-container {\n  display: flex;\n  align-items: center;\n  gap: 0.75rem;\n}\n\n.nav-logo {\n  width: 32px;\n  /* Adjust size as needed */\n  height: 32px;\n  object-fit: contain;\n}\n\n.nav-brand {\n  font-size: 1.25rem;\n  font-weight: 600;\n  color: var(--text-primary);\n}\n\n.nav-links {\n  display: flex;\n  align-items: center;\n  gap: 2rem;\n}\n\n.nav-links a {\n  color: var(--text-primary);\n  text-decoration: none;\n  font-weight: 500;\n  transition: color 0.2s;\n}\n\n.nav-links a:hover {\n  color: var(--primary-color);\n}\n\n.theme-toggle {\n  background: transparent;\n  border: none;\n  cursor: pointer;\n  padding: 0.5rem;\n  color: var(--text-primary);\n}\n\n/* Theme Toggle */\n.theme-toggle {\n  background: none;\n  border: none;\n  color: var(--text);\n  cursor: pointer;\n  padding: 0.5rem;\n  border-radius: 50%;\n  transition: background-color 0.2s;\n}\n\n.theme-toggle:hover {\n  background: var(--hover);\n}\n\n/* Main Content */\nmain {\n  max-width: 1200px;\n  margin: 0 auto;\n  padding: 2rem;\n  padding-top: 64px;\n  min-height: 100vh;\n  display: flex;\n  flex-direction: column;\n  width: 100%;\n  /* Should match the height of your nav */\n}\n\n/* Sections */\nsection {\n  margin: 6rem 0;\n  scroll-margin-top: 5rem;\n}\n\n/* Hero Section */\n.hero {\n  height: 600px;\n  width: 100%;\n  display: flex;\n  align-items: center;\n  overflow: hidden;\n}\n\n.hero-content {\n  flex: 0 0 50%;\n  padding: 2rem;\n  z-index: 2;\n  position: relative;\n}\n\n.hero-content::before {\n  content: '';\n  position: absolute;\n  top: -50px;\n  left: -50px;\n  width: calc(100% + 100px);\n  height: calc(100% + 100px);\n  background: linear-gradient(to right,\n      var(--background) 0%,\n      var(--background) 60%,\n      transparent 100%);\n  z-index: -1;\n}\n\n.hero-background {\n  flex: 0 0 90%;\n  height: 100%;\n  display: flex;\n  align-items: center;\n  justify-content: flex-end;\n  margin-right: -40%;\n  padding-right: 40%;\n}\n\n.hero-background img {\n  max-width: 200%;\n  max-height: 200%;\n  width: auto;\n  height: 100%;\n  object-fit: contain;\n}\n\n.hero-background img[src*=\"screenshot.png\"] {\n  display: none;\n}\n\n.hero-background img[src*=\"screenshot-light.png\"] {\n  display: block;\n}\n\n/* Dark mode */\n[data-theme=\"dark\"] .hero-background img[src*=\"screenshot.png\"] {\n  display: block;\n}\n\n[data-theme=\"dark\"] .hero-background img[src*=\"screenshot-light.png\"] {\n  display: none;\n}\n\n.gradient-text {\n  font-size: 3rem;\n  font-weight: 800;\n  line-height: 1.2;\n  margin-bottom: 1rem;\n}\n\n.hero-subtitle {\n  font-size: 1.125rem;\n  color: var(--text-secondary);\n  margin-bottom: 1.5rem;\n}\n\n.hero-cta {\n  display: flex;\n  gap: 1rem;\n  margin-bottom: 1.5rem;\n}\n\n.hero-image {\n  width: 100%;\n}\n\n.floating-screenshot {\n  width: 100%;\n  height: auto;\n  max-width: 600px;\n  border-radius: 12px;\n  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);\n  animation: float 6s ease-in-out infinite;\n}\n\n/* Responsive design */\n@media (max-width: 1024px) {\n  .hero {\n    flex-direction: column;\n    height: auto;\n    min-height: auto;\n  }\n\n  .hero-content {\n    flex: 0 0 100%;\n    width: 100%;\n    padding: 3rem 2rem;\n    text-align: center;\n  }\n\n  .hero-background {\n    flex: 0 0 100%;\n    margin-right: 0;\n    padding-right: 0;\n  }\n\n  .hero-background img {\n    width: 100%;\n    height: auto;\n    max-height: 400px;\n    object-fit: contain;\n  }\n\n  .hero-content::before {\n    display: none;\n    /* Remove the gradient since content and image are now stacked */\n  }\n\n  .hero-cta {\n    justify-content: center;\n  }\n\n  .tech-stack {\n    justify-content: center;\n  }\n}\n\n@media (max-width: 640px) {\n  .hero {\n    padding: 2rem 1rem;\n  }\n\n  .hero-content {\n    padding: 2rem 1rem;\n  }\n\n  .gradient-text {\n    font-size: 2.5rem;\n  }\n\n  .hero-cta {\n    flex-direction: column;\n  }\n}\n\n.logo {\n  width: 120px;\n  height: 120px;\n  margin-bottom: 1rem;\n  transition: transform 0.3s;\n}\n\n.logo:hover {\n  transform: scale(1.05);\n}\n\n.badges {\n  display: flex;\n  gap: 0.5rem;\n  justify-content: center;\n\n  /* Centered only on tablets and smaller screens */\n  @media (min-width: 1024px) {\n    justify-content: flex-start;\n    /* Align to the start on larger screens */\n  }\n\n  margin-top: 1rem;\n}\n\n.badge {\n  background: var(--primary);\n  color: white;\n  padding: 0.25rem 0.75rem;\n  border-radius: 9999px;\n  font-size: 0.875rem;\n}\n\n/* Features */\n.feature-grid {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n  gap: 2rem;\n  margin-top: 2rem;\n}\n\n.feature {\n  background: var(--card);\n  padding: 2rem;\n  border-radius: 12px;\n  transition: transform 0.2s;\n  border: 1px solid var(--border);\n}\n\n.feature:hover {\n  transform: translateY(-4px);\n}\n\n/* Download Section */\n.download-options {\n  display: flex;\n  gap: 1.5rem;\n  justify-content: center;\n  margin: 2rem 0;\n  flex-wrap: wrap;\n  padding: 0 1rem;\n}\n\n.download-button {\n  background: var(--primary-color);\n  color: white;\n  padding: 1rem 1.5rem;\n  border-radius: 8px;\n  text-decoration: none;\n  display: flex;\n  align-items: center;\n  gap: 1rem;\n  transition: all 0.2s;\n  min-width: 250px;\n}\n\n.download-button .button-text {\n  display: flex;\n  flex-direction: column;\n  gap: 0.25rem;\n}\n\n.download-button .primary {\n  font-weight: 600;\n  font-size: 1rem;\n}\n\n.download-button .secondary {\n  font-size: 0.85rem;\n  opacity: 0.9;\n}\n\n/* New styles for nested links */\n.download-button .secondary a {\n  color: inherit;\n  text-decoration: none;\n  padding: 2px 6px;\n  border-radius: 4px;\n  transition: all 0.2s;\n  display: inline-block;\n}\n\n.download-button .secondary a:hover {\n  background-color: rgba(255, 255, 255, 0.2);\n  transform: translateY(-1px);\n}\n\n.download-button:hover {\n  transform: translateY(-2px);\n  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n}\n\n.download-button .icon {\n  font-size: 1.5rem;\n}\n\n.button-text {\n  display: flex;\n  flex-direction: column;\n}\n\n.button-text .primary {\n  font-weight: 600;\n}\n\n.button-text .secondary {\n  font-size: 0.875rem;\n  opacity: 0.8;\n}\n\n/* Primary button style (can be used for other buttons too) */\n.primary-button {\n  background: var(--primary-color);\n  color: white;\n  padding: 0.75rem 1.5rem;\n  border-radius: 8px;\n  text-decoration: none;\n  font-weight: 500;\n  transition: all 0.2s;\n}\n\n.primary-button:hover {\n  background: var(--secondary-color);\n  transform: translateY(-2px);\n}\n\n/* Secondary button style */\n.secondary-button {\n  background: rgba(99, 102, 241, 0.1);\n  color: var(--primary-color);\n  padding: 0.75rem 1.5rem;\n  border-radius: 8px;\n  text-decoration: none;\n  font-weight: 500;\n  transition: all 0.2s;\n}\n\n.secondary-button:hover {\n  background: rgba(99, 102, 241, 0.2);\n  transform: translateY(-2px);\n}\n\n@media (max-width: 640px) {\n  .download-options {\n    flex-direction: column;\n    align-items: stretch;\n  }\n\n  .download-button {\n    justify-content: center;\n  }\n}\n\n/* Installation Steps */\n.install-steps {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n  gap: 2rem;\n  margin-top: 2rem;\n}\n\n.step {\n  background: var(--card-background);\n  padding: 2rem;\n  border-radius: 12px;\n  position: relative;\n  border: 1px solid rgba(255, 255, 255, 0.1);\n  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),\n    0 2px 4px -1px rgba(0, 0, 0, 0.06);\n  transition: transform 0.2s ease;\n}\n\n.step:hover {\n  transform: translateY(-4px);\n}\n\n.step-number {\n  position: absolute;\n  top: -1rem;\n  left: -1rem;\n  background: var(--primary-color);\n  color: white;\n  width: 2rem;\n  height: 2rem;\n  border-radius: 50%;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  font-weight: bold;\n  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\n}\n\n.step h3 {\n  margin-bottom: 1rem;\n  font-size: 1.25rem;\n  font-weight: 600;\n  color: var(--text-primary);\n}\n\n.step p {\n  color: var(--text-secondary);\n  line-height: 1.5;\n}\n\n/* Dark mode adjustments */\n[data-theme=\"dark\"] .step {\n  border-color: rgba(255, 255, 255, 0.1);\n  background: rgba(30, 41, 59, 0.8);\n}\n\n@media (max-width: 768px) {\n  .install-steps {\n    grid-template-columns: 1fr;\n  }\n}\n\n/* Keyboard Shortcuts */\n.shortcuts {\n  background: var(--card);\n  border-radius: 12px;\n  padding: 2rem;\n  margin-top: 2rem;\n  border: 1px solid var(--border);\n}\n\n.shortcut-grid {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n  gap: 1rem;\n}\n\n.shortcut {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: 0.5rem;\n  border-radius: 6px;\n}\n\n.shortcut:hover {\n  background: var(--hover);\n}\n\n.key {\n  background: var(--code-bg);\n  padding: 0.25rem 0.5rem;\n  border-radius: 4px;\n  font-family: monospace;\n  font-size: 0.875rem;\n}\n\n/* FAQ Section */\n.faq {\n  max-width: 800px;\n  margin: 4rem auto;\n  padding: 0 2rem;\n}\n\n.faq-list {\n  display: flex;\n  flex-direction: column;\n  gap: 1rem;\n}\n\n.faq-item {\n  background: var(--card-background);\n  border: 1px solid rgba(255, 255, 255, 0.1);\n  border-radius: 12px;\n  overflow: hidden;\n  transition: all 0.3s ease;\n}\n\n.faq-question {\n  width: 100%;\n  padding: 1.5rem;\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  background: none;\n  border: none;\n  cursor: pointer;\n  text-align: left;\n  color: var(--text-primary);\n  font-size: 1.1rem;\n  font-weight: 500;\n}\n\n.faq-icon {\n  font-size: 1.5rem;\n  transition: transform 0.3s ease;\n}\n\n.faq-item.active .faq-icon {\n  transform: rotate(180deg);\n}\n\n.faq-answer {\n  max-height: 0;\n  overflow: hidden;\n  transition: max-height 0.3s ease-out;\n  padding: 0 1.5rem;\n}\n\n.faq-item.active .faq-answer {\n  max-height: 500px;\n  /* Adjust based on content */\n  padding: 0 1.5rem 1.5rem;\n}\n\n.faq-answer p {\n  color: var(--text-secondary);\n  line-height: 1.6;\n}\n\n.faq-answer ul {\n  margin-top: 0.5rem;\n  margin-left: 1.5rem;\n  color: var(--text-secondary);\n}\n\n.faq-answer li {\n  margin-bottom: 0.5rem;\n}\n\n/* Dark mode adjustments */\n[data-theme=\"dark\"] .faq-item {\n  border-color: rgba(255, 255, 255, 0.1);\n  background: rgba(30, 41, 59, 0.8);\n}\n\n@media (max-width: 768px) {\n  .faq {\n    margin: 3rem auto;\n  }\n\n  .faq-question {\n    padding: 1.25rem;\n    font-size: 1rem;\n  }\n}\n\n/* Footer */\nfooter {\n  border-top: 1px solid var(--border);\n  margin-top: 6rem;\n  padding-top: 3rem;\n}\n\n.footer-content {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n  gap: 2rem;\n  margin-bottom: 2rem;\n}\n\n.footer-section {\n  display: flex;\n  flex-direction: column;\n  gap: 0.5rem;\n}\n\n.footer-section a {\n  color: var(--text);\n  text-decoration: none;\n  opacity: 0.8;\n}\n\n.footer-section a:hover {\n  opacity: 1;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n  nav {\n    flex-wrap: wrap;\n    gap: 0.5rem;\n  }\n\n  .download-options {\n    flex-direction: column;\n  }\n\n  .feature-grid {\n    grid-template-columns: 1fr;\n  }\n\n  .install-steps {\n    grid-template-columns: 1fr;\n  }\n}\n\n/* Animations */\n@keyframes fadeIn {\n  from {\n    opacity: 0;\n    transform: translateY(20px);\n  }\n\n  to {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n\n.feature,\n.step,\n.download-button {\n  animation: fadeIn 0.5s ease-out;\n}\n\n.screenshot {\n  width: 100%;\n  max-width: 1200px;\n  margin: 2rem auto;\n  padding: 0 1rem;\n}\n\n.screenshot-img {\n  width: 100%;\n  height: auto;\n  border-radius: 8px;\n  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n}\n\n.glass-nav {\n  backdrop-filter: blur(12px);\n  background: var(--card-background);\n  position: fixed;\n  width: 100%;\n  top: 0;\n  z-index: 1000;\n  border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n  padding: 1rem 2rem;\n  box-sizing: border-box;\n  box-shadow: none;\n}\n\n[data-theme=\"dark\"] .glass-nav {\n  border-bottom: 1px solid rgba(255, 255, 255, 0.1);\n  background: rgba(30, 41, 59, 0.8);\n  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\n}\n\n.tech-badge {\n  background: rgba(99, 102, 241, 0.1);\n  color: var(--primary-color);\n  padding: 0.5rem 1rem;\n  border-radius: 9999px;\n  font-weight: 500;\n  margin-right: 0.5rem;\n}\n\n.feature-card {\n  background: var(--card-background);\n  border-radius: 16px;\n  padding: 2rem;\n  transition: transform 0.2s;\n}\n\n.feature-card:hover {\n  transform: translateY(-5px);\n}\n\n@keyframes float {\n  0% {\n    transform: translateY(0px);\n  }\n\n  50% {\n    transform: translateY(-20px);\n  }\n\n  100% {\n    transform: translateY(0px);\n  }\n}\n\n/* Features Section */\n.features {\n  padding: 4rem 2rem;\n}\n\n.section-title {\n  text-align: center;\n  margin-bottom: 3rem;\n  font-size: 2.5rem;\n  font-weight: 700;\n}\n\n.feature-grid {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n  gap: 2rem;\n  max-width: 1200px;\n  margin: 0 auto;\n}\n\n.feature-card {\n  background: var(--card-background);\n  padding: 2rem;\n  border-radius: 12px;\n  border: 1px solid rgba(255, 255, 255, 0.1);\n  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),\n    0 2px 4px -1px rgba(0, 0, 0, 0.06);\n  transition: transform 0.2s ease;\n}\n\n.feature-card:hover {\n  transform: translateY(-4px);\n}\n\n.feature-icon {\n  font-size: 2.5rem;\n  margin-bottom: 1rem;\n}\n\n.feature-card h3 {\n  font-size: 1.25rem;\n  font-weight: 600;\n  margin-bottom: 0.75rem;\n  color: var(--text-primary);\n}\n\n.feature-card p {\n  color: var(--text-secondary);\n  line-height: 1.5;\n}\n\n/* Dark mode adjustments */\n[data-theme=\"dark\"] .feature-card {\n  border-color: rgba(255, 255, 255, 0.1);\n  background: rgba(30, 41, 59, 0.8);\n}\n\n@media (max-width: 768px) {\n  .feature-grid {\n    grid-template-columns: 1fr;\n  }\n\n  .section-title {\n    font-size: 2rem;\n  }\n}\n\n/* Footer Styles */\n.footer {\n  background: var(--card-background);\n  border-top: 1px solid rgba(0, 0, 0, 0.1);\n  padding: 4rem 2rem 2rem;\n  margin-top: 4rem;\n  width: 100%;\n  box-sizing: border-box;\n  box-shadow: none;\n}\n\n[data-theme=\"dark\"] .footer {\n  background: rgba(30, 41, 59, 0.8);\n  border-top: 1px solid rgba(255, 255, 255, 0.1);\n}\n\n.footer-content {\n  max-width: 1200px;\n  margin: 0 auto;\n  display: grid;\n  grid-template-columns: 2fr 1fr 1fr;\n  gap: 3rem;\n  margin-bottom: 3rem;\n}\n\n.footer-section h3 {\n  font-size: 1.5rem;\n  font-weight: 600;\n  margin-bottom: 1rem;\n  color: var(--text-primary);\n}\n\n.footer-section h4 {\n  font-size: 1.1rem;\n  font-weight: 600;\n  margin-bottom: 1rem;\n  color: var(--text-primary);\n}\n\n.footer-description {\n  color: var(--text-secondary);\n  line-height: 1.6;\n  margin-bottom: 1rem;\n}\n\n.footer-links,\n.tech-stack-list {\n  list-style: none;\n  padding: 0;\n}\n\n.footer-links li,\n.tech-stack-list li {\n  margin-bottom: 0.75rem;\n}\n\n.footer-links a,\n.tech-stack-list a {\n  color: var(--text-secondary);\n  text-decoration: none;\n  display: flex;\n  align-items: center;\n  gap: 0.5rem;\n  transition: color 0.2s ease;\n}\n\n.footer-links a:hover,\n.tech-stack-list a:hover {\n  color: var(--primary-color);\n}\n\n.footer-bottom {\n  max-width: 1200px;\n  margin: 0 auto;\n  padding-top: 2rem;\n  border-top: 1px solid rgba(0, 0, 0, 0.1);\n  text-align: center;\n  color: var(--text-secondary);\n}\n\n[data-theme=\"dark\"] .footer-bottom {\n  border-top: 1px solid rgba(255, 255, 255, 0.1);\n}\n\n.footer-bottom p {\n  margin-bottom: 0.5rem;\n}\n\n.footer-bottom a {\n  color: var(--primary-color);\n  text-decoration: none;\n}\n\n.footer-bottom a:hover {\n  text-decoration: underline;\n}\n\n.heart {\n  color: #ff4b4b;\n  display: inline-block;\n  animation: heartbeat 1.5s ease infinite;\n}\n\n.coffee {\n  display: inline-block;\n  animation: wiggle 1s ease infinite;\n}\n\n@keyframes heartbeat {\n\n  0%,\n  100% {\n    transform: scale(1);\n  }\n\n  50% {\n    transform: scale(1.1);\n  }\n}\n\n@keyframes wiggle {\n\n  0%,\n  100% {\n    transform: rotate(0deg);\n  }\n\n  25% {\n    transform: rotate(-10deg);\n  }\n\n  75% {\n    transform: rotate(10deg);\n  }\n}\n\n/* Responsive adjustments */\n@media (max-width: 768px) {\n  .footer-content {\n    grid-template-columns: 1fr;\n    gap: 2rem;\n  }\n\n  .footer {\n    padding: 3rem 1.5rem 1.5rem;\n  }\n}\n\n/* Dark mode adjustments */\n[data-theme=\"dark\"] .footer {\n  background: rgba(30, 41, 59, 0.8);\n  border-color: rgba(255, 255, 255, 0.1);\n}\n\n/* Common card styles */\n.feature-card,\n.step,\n.faq-item {\n  background: var(--card-background);\n  border-radius: 12px;\n  border: 1px solid rgba(0, 0, 0, 0.1);\n  transition: transform 0.2s ease;\n  box-shadow: none;\n}\n\n/* Dark mode specific adjustments */\n[data-theme=\"dark\"] .feature-card,\n[data-theme=\"dark\"] .step,\n[data-theme=\"dark\"] .faq-item {\n  border-color: rgba(255, 255, 255, 0.1);\n  background: rgba(30, 41, 59, 0.8);\n  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.2);\n}\n\n/* Hover states */\n.feature-card:hover,\n.step:hover {\n  transform: translateY(-4px);\n  border-color: var(--primary-color);\n}\n\n.faq-item.active {\n  border-color: var(--primary-color);\n}\n\n/* Optional: Add subtle hover effect to nav links */\n.nav-links a {\n  position: relative;\n  padding-bottom: 2px;\n}\n\n.nav-links a::after {\n  content: '';\n  position: absolute;\n  bottom: 0;\n  left: 0;\n  width: 0;\n  height: 2px;\n  background: var(--primary-color);\n  transition: width 0.3s ease;\n}\n\n.nav-links a:hover::after {\n  width: 100%;\n}\n\n/* Add this to your CSS */\n.ph-badge {\n  display: inline-block;\n  transition: transform 0.2s ease;\n}\n\n.ph-badge:hover {\n  transform: translateY(-2px);\n}\n\n/* If you want to adjust for dark mode */\n[data-theme=\"dark\"] .ph-badge img {\n  filter: invert(1);\n  /* Optional: if you want to invert colors in dark mode */\n}\n\n.coming-soon-badge {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.5rem;\n  padding: 0.5rem 1rem;\n  background: #ff6154;\n  /* Product Hunt color */\n  color: white;\n  border-radius: 8px;\n  text-decoration: none;\n  font-weight: 500;\n  transition: transform 0.2s ease;\n}\n\n.coming-soon-badge:hover {\n  transform: translateY(-2px);\n}\n\n.trust-badge {\n  margin-top: 1.5rem;\n  padding: 0.75rem;\n  background: rgba(255, 255, 255, 0.1);\n  border-radius: 8px;\n  display: flex;\n  align-items: center;\n  gap: 0.5rem;\n  font-size: 0.9rem;\n}\n\n.verified-icon {\n  color: #34C759;\n  font-weight: bold;\n}\n\n.verified-text {\n  color: var(--text-color);\n}\n\n.learn-more {\n  color: var(--primary-color);\n  text-decoration: none;\n  margin-left: 0.5rem;\n}\n\n.learn-more:hover {\n  text-decoration: underline;\n}\n\n/* Responsive adjustments */\n@media (max-width: 768px) {\n  .hero {\n    height: 500px;\n  }\n\n  .hero-content,\n  .hero-background {\n    flex: 0 0 100%;\n  }\n}\n\n.download-button.windows {\n  background: #00a4ef;\n}\n\n.download-button.windows:hover {\n  background: #0090d5;\n}\n\n.download-button.linux {\n  background: #E95420;\n}\n\n.download-button.linux:hover {\n  background: #C7431B;\n}\n\n.download-options-group {\n  display: flex;\n  flex-direction: column;\n  gap: 0.25rem;\n}\n\n.download-option {\n  display: flex;\n  align-items: center;\n  gap: 0.5rem;\n  font-size: 0.85rem;\n}\n\n.download-option .format {\n  color: rgba(255, 255, 255, 0.8);\n  min-width: 65px;\n}\n\n.download-option .separator {\n  color: rgba(255, 255, 255, 0.4);\n  font-size: 0.7rem;\n}\n\n.download-option a {\n  color: inherit;\n  text-decoration: none;\n  padding: 2px 6px;\n  border-radius: 4px;\n  transition: all 0.2s;\n}\n\n.download-option a:hover {\n  background-color: rgba(255, 255, 255, 0.2);\n  transform: translateY(-1px);\n}\n\n.download-button.linux .secondary {\n  line-height: 1.6;\n  font-size: 0.85rem;\n}\n\n.download-button.linux .secondary a {\n  color: inherit;\n  text-decoration: none;\n  padding: 2px 6px;\n  border-radius: 4px;\n  transition: all 0.2s;\n  white-space: nowrap;\n}\n\n.download-button.linux .secondary a:hover {\n  background-color: rgba(255, 255, 255, 0.2);\n  transform: translateY(-1px);\n}\n\n.download-button.linux .secondary .separator {\n  opacity: 0.7;\n  margin: 0 2px;\n}\n\n.downloads {\n  padding: 2rem 0;\n}\n\n.download-container {\n  max-width: 900px;\n  margin: 0 auto;\n  padding: 2rem;\n  text-align: center;\n}\n\n.download-container h2 {\n  font-size: 2.5rem;\n  margin-bottom: 1rem;\n  background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));\n  background-clip: text;\n  -webkit-background-clip: text;\n  -webkit-text-fill-color: transparent;\n}\n\n.download-subtitle {\n  color: var(--text-secondary);\n  margin-bottom: 3rem;\n}\n\n.download-options {\n  display: flex;\n  flex-direction: column;\n  gap: 2.5rem;\n}\n\n.download-group {\n  display: flex;\n  flex-direction: column;\n  gap: 1rem;\n}\n\n.platform-title {\n  font-size: 1.2rem;\n  color: var(--text-secondary);\n  text-align: left;\n  margin-bottom: 0.5rem;\n}\n\n.platform-options {\n  display: flex;\n  gap: 1rem;\n  justify-content: center;\n}\n\n.download-button {\n  background: var(--primary-color);\n  color: white;\n  padding: 1rem 1.5rem;\n  border-radius: 12px;\n  text-decoration: none;\n  display: flex;\n  align-items: center;\n  gap: 1rem;\n  transition: all 0.2s;\n  border: 1px solid transparent;\n  min-width: 250px;\n}\n\n.download-button:hover {\n  transform: translateY(-2px);\n  background: var(--secondary-color);\n  box-shadow: 0 4px 12px rgba(99, 102, 241, 0.2);\n}\n\n.download-button .icon {\n  font-size: 1.5rem;\n}\n\n.button-text {\n  display: flex;\n  flex-direction: column;\n  gap: 0.25rem;\n  text-align: left;\n}\n\n.button-text .primary {\n  font-weight: 600;\n  font-size: 1rem;\n}\n\n.button-text .secondary {\n  font-size: 0.85rem;\n  opacity: 0.9;\n}\n\n.linux-options {\n  display: flex;\n  flex-direction: column;\n  gap: 1.5rem;\n}\n\n.format-group {\n  display: flex;\n  flex-direction: column;\n  gap: 0.5rem;\n}\n\n.format-label {\n  font-size: 0.9rem;\n  color: var(--text-secondary);\n  text-align: left;\n}\n\n.format-buttons {\n  display: flex;\n  gap: 1rem;\n  justify-content: center;\n}\n\n.format-buttons .download-button {\n  min-width: 150px;\n}\n\n/* Dark mode adjustments */\n[data-theme=\"dark\"] .download-button {\n  background: rgba(30, 41, 59, 0.8);\n  border-color: rgba(255, 255, 255, 0.1);\n}\n\n[data-theme=\"dark\"] .download-button:hover {\n  border-color: var(--primary-color);\n  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n}\n\n.version-info {\n  text-align: center;\n  margin: 1rem 0;\n  font-size: 0.9rem;\n  color: var(--text-secondary);\n}\n\n#current-version {\n  font-weight: 600;\n  color: var(--primary-color);\n}\n\n/* Download Section Responsive Styles */\n@media (max-width: 768px) {\n  .download-options {\n    flex-direction: column;\n    gap: 2rem;\n  }\n\n  .download-group {\n    width: 100%;\n  }\n\n  .platform-options {\n    flex-direction: column;\n  }\n\n  .download-button {\n    width: 100%;\n    margin: 0.5rem 0;\n  }\n\n  .linux-downloads {\n    width: 100%;\n    margin-top: 1rem;\n  }\n\n  .linux-downloads h4 {\n    margin-bottom: 0.5rem;\n  }\n\n  /* Adjust text size for better readability on mobile */\n  .button-text .primary {\n    font-size: 0.9rem;\n  }\n\n  .button-text .secondary {\n    font-size: 0.8rem;\n  }\n}\n\n/* Extra small devices */\n@media (max-width: 480px) {\n  .download-container {\n    padding: 1rem;\n  }\n\n  .download-stats {\n    font-size: 0.9rem;\n  }\n\n  .platform-title {\n    font-size: 1.2rem;\n  }\n}\n\n.download-stats {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.5rem;\n  padding: 0.5rem 1rem;\n  background: rgba(var(--primary-color-rgb), 0.1);\n  border-radius: 6px;\n  margin: 1rem 0;\n  font-size: 0.9rem;\n}\n\n#download-count {\n  font-weight: bold;\n  color: var(--primary-color);\n  font-size: 1.1rem;\n}\n\n/* Adjust the existing download-subtitle margin */\n.download-subtitle {\n  color: var(--text-secondary);\n  margin-bottom: 2rem;\n  margin-top: 0.5rem;\n}\n\n/* Testimonials Section */\n.testimonials {\n  padding: 4rem 0;\n  background: var(--background);\n  max-width: 1200px;\n  margin: 0 auto;\n}\n\n.testimonial-grid {\n  column-count: 3;\n  column-gap: 2rem;\n  margin-top: 3rem;\n  padding: 0 2rem;\n}\n\n/* Ensure Twitter embeds stack properly */\n.twitter-tweet {\n  margin: 0 0 2rem 0 !important;\n  width: 100% !important;\n  break-inside: avoid;\n  display: inline-block;\n}\n\n/* Responsive adjustments */\n@media (max-width: 1024px) {\n  .testimonial-grid {\n    column-count: 2;\n  }\n}\n\n@media (max-width: 768px) {\n  .testimonial-grid {\n    column-count: 1;\n  }\n}\n\n/* Mobile Navigation Styles */\n@media (max-width: 768px) {\n  .glass-nav {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    padding: 1rem 2rem;\n  }\n\n  .menu-button {\n    display: block;\n    background: none;\n    border: none;\n    color: var(--text-primary);\n    font-size: 1.5rem;\n    cursor: pointer;\n    padding: 0.5rem;\n    z-index: 101;\n  }\n\n  .nav-links {\n    position: fixed;\n    top: calc(60px + 1rem);\n    left: 0;\n    right: 0;\n    background: var(--card-background);\n    padding: 1.5rem;\n    flex-direction: column;\n    align-items: center;\n    gap: 1rem;\n    transform: translateY(-150%);\n    transition: transform 0.3s ease;\n    backdrop-filter: blur(12px);\n    visibility: hidden;\n    opacity: 0;\n    z-index: 100;\n    border-bottom: 1px solid rgba(255, 255, 255, 0.1);\n  }\n\n  .nav-links.active {\n    transform: translateY(0);\n    visibility: visible;\n    opacity: 1;\n  }\n}\n\n/* Hide menu button on larger screens */\n@media (min-width: 769px) {\n  .menu-button {\n    display: none;\n  }\n}"
  },
  {
    "path": "jsconfig.json",
    "content": "{\n  \"extends\": \"./.svelte-kit/tsconfig.json\",\n  \"compilerOptions\": {\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"resolveJsonModule\": true,\n    \"skipLibCheck\": true,\n    \"sourceMap\": true,\n    \"strict\": true,\n    \"moduleResolution\": \"bundler\"\n  }\n  // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias\n  // except $lib which is handled by https://kit.svelte.dev/docs/configuration#files\n  //\n  // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes\n  // from the referenced tsconfig.json - TypeScript does not merge them in\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"neohtop\",\n  \"version\": \"1.2.0\",\n  \"description\": \"\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite dev\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\",\n    \"check\": \"svelte-kit sync && svelte-check --tsconfig ./jsconfig.json\",\n    \"check:watch\": \"svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch\",\n    \"tauri\": \"tauri\",\n    \"format\": \"prettier --write ./src && cargo fmt --manifest-path src-tauri/Cargo.toml\",\n    \"format:check\": \"prettier --check ./src && cargo fmt --manifest-path src-tauri/Cargo.toml -- --check\",\n    \"prepare\": \"husky install\"\n  },\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"@fortawesome/fontawesome-svg-core\": \"^6.6.0\",\n    \"@fortawesome/free-solid-svg-icons\": \"^6.6.0\",\n    \"@tauri-apps/api\": \"^2.0.3\",\n    \"@tauri-apps/plugin-os\": \"^2.0.0\",\n    \"@tauri-apps/plugin-shell\": \"^2.2.1\",\n    \"simple-icons\": \"^13.15.0\",\n    \"svelte-fa\": \"^4.0.3\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/adapter-static\": \"^3.0.5\",\n    \"@sveltejs/kit\": \"^2.7.0\",\n    \"@sveltejs/vite-plugin-svelte\": \"^5.0.3\",\n    \"@tauri-apps/cli\": \"^2.0.4\",\n    \"husky\": \"^8.0.0\",\n    \"lint-staged\": \"^15.2.10\",\n    \"prettier\": \"^3.3.3\",\n    \"prettier-plugin-svelte\": \"^3.2.7\",\n    \"svelte\": \"^5.0.0\",\n    \"svelte-check\": \"^4.0.0\",\n    \"typescript\": \"^5.5.0\",\n    \"vite\": \"^6.3.5\"\n  },\n  \"lint-staged\": {\n    \"src/**/*.{js,ts,jsx,tsx,svelte}\": [\n      \"prettier --write\"\n    ],\n    \"src-tauri/**/*.rs\": [\n      \"cargo fmt --manifest-path src-tauri/Cargo.toml --\"\n    ]\n  }\n}\n"
  },
  {
    "path": "src/App.svelte",
    "content": ""
  },
  {
    "path": "src/app.css",
    "content": ":root {\n  /* Default theme values will be overridden by theme store */\n  --base: #1e1e2e;\n  --mantle: #181825;\n  --crust: #11111b;\n  --text: #cdd6f4;\n  --subtext0: #a6adc8;\n  --subtext1: #bac2de;\n  --surface0: #313244;\n  --surface1: #45475a;\n  --surface2: #585b70;\n  --overlay0: #6c7086;\n  --overlay1: #7f849c;\n  --blue: #89b4fa;\n  --lavender: #b4befe;\n  --sapphire: #74c7ec;\n  --sky: #89dceb;\n  --red: #f38ba8;\n  --maroon: #eba0ac;\n  --peach: #fab387;\n  --yellow: #f9e2af;\n  --green: #a6e3a1;\n  --teal: #94e2d5;\n}\n\nbody {\n  margin: 0;\n  padding: 0;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial,\n    sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\";\n  background-color: var(--base);\n  color: var(--text);\n  -webkit-font-smoothing: antialiased;\n  overflow: hidden;\n  user-select: none;\n}\n\n/* Global scrollbar styles */\n* {\n  scrollbar-width: thin;\n  scrollbar-color: var(--surface2) var(--mantle);\n}\n\n::-webkit-scrollbar {\n  width: 8px;\n  height: 8px;\n}\n\n::-webkit-scrollbar-track {\n  background: var(--mantle);\n  border-radius: 4px;\n}\n\n::-webkit-scrollbar-thumb {\n  background: var(--surface2);\n  border-radius: 4px;\n  transition: background 0.2s ease;\n}\n\n::-webkit-scrollbar-thumb:hover {\n  background: var(--surface1);\n}\n\n::-webkit-scrollbar-corner {\n  background: var(--mantle);\n}\n\n/* Glassy theme */\n\n[data-theme=\"glassy\"] body {\n  background: transparent !important;\n}\n\n[data-theme=\"glassy\"] .toolbar {\n  position: relative;\n  background: rgba(24, 24, 37, 0.5) !important;\n  border: 1px solid rgba(255, 255, 255, 0.1) !important;\n  z-index: 9;\n}\n\n[data-theme=\"glassy\"] .stat-panel {\n  background: rgba(24, 24, 37, 0.2) !important;\n  z-index: 100;\n}\n\n[data-theme=\"glassy\"] .panel-header {\n  border-color: rgba(255, 255, 255, 0.1) !important;\n}\n\n[data-theme=\"glassy\"] .col-actions {\n  background: rgba(24, 24, 37, 0.2) !important;\n  border-bottom: 1px solid rgba(232, 232, 232, 0.1) !important;\n  border-left: 1px solid rgba(232, 232, 232, 0.1) !important;\n}\n\n[data-theme=\"glassy\"] .search-input,\n[data-theme=\"glassy\"] .btn-toggle,\n[data-theme=\"glassy\"] .btn-action,\n[data-theme=\"glassy\"] .info-button,\n[data-theme=\"glassy\"] .btn-page,\n[data-theme=\"glassy\"] .theme-button,\n[data-theme=\"glassy\"] .usage-pill,\n[data-theme=\"glassy\"] .bar-container,\n[data-theme=\"glassy\"] .select-input {\n  background: rgba(24, 24, 37, 0.2) !important;\n  z-index: 100;\n}\n\n[data-theme=\"glassy\"] .btn-clear {\n  z-index: 100;\n}\n\n[data-theme=\"glassy\"] tr.pinned,\n[data-theme=\"glassy\"] tr:hover {\n  background: rgba(24, 24, 37, 0.3) !important;\n}\n\n[data-theme=\"glassy\"] th {\n  background: rgba(24, 24, 37, 0.5) !important;\n}\n\n[data-theme=\"glassy\"] td {\n  border-bottom: 1px solid rgba(232, 232, 232, 0.1) !important;\n  background: rgba(24, 24, 37, 0.2) !important;\n}\n"
  },
  {
    "path": "src/app.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"%sveltekit.assets%/favicon.png\" />\n    <meta name=\"viewport\" content=\"width=device-width\" />\n    <title>NeoHtop</title>\n    %sveltekit.head%\n  </head>\n\n  <body data-sveltekit-preload-data=\"hover\">\n    <div style=\"display: contents\">%sveltekit.body%</div>\n  </body>\n</html>\n"
  },
  {
    "path": "src/lib/components/AppInfo.svelte",
    "content": "<script lang=\"ts\">\n  import { getVersion } from \"@tauri-apps/api/app\";\n  import { onMount } from \"svelte\";\n  import { ThemeSwitcher } from \"$lib/components\";\n  import { faInfo } from \"@fortawesome/free-solid-svg-icons\";\n  import Fa from \"svelte-fa\";\n  import { ASCII_ART, APP_INFO } from \"$lib/constants\";\n\n  let version = \"\";\n  let latestVersion = \"\";\n  let showInfo = false;\n  let hasUpdate = false;\n\n  async function checkLatestVersion() {\n    try {\n      const response = await fetch(\n        \"https://api.github.com/repos/abdenasser/neohtop/releases/latest\",\n      );\n      const data = await response.json();\n\n      // Extract version number from tag (e.g., \"1.0.6\" from \"macos-nightly-1.0.6\")\n      const versionMatch = data.tag_name.match(/\\d+\\.\\d+\\.\\d+/);\n      if (!versionMatch) {\n        console.warn(\n          \"Unexpected version format in latest release:\",\n          data.tag_name,\n        );\n        return;\n      }\n\n      latestVersion = versionMatch[0];\n\n      // Extract version number from current version\n      const currentVersionMatch = version.match(/\\d+\\.\\d+\\.\\d+/);\n      if (!currentVersionMatch) {\n        console.warn(\"Unexpected current version format:\", version);\n        return;\n      }\n\n      // Compare only the version numbers\n      hasUpdate = currentVersionMatch[0] !== latestVersion;\n    } catch (error) {\n      console.error(\"Failed to check latest version:\", error);\n      latestVersion = \"\";\n      hasUpdate = false;\n    }\n  }\n\n  onMount(async () => {\n    try {\n      version = await getVersion();\n      await checkLatestVersion();\n    } catch (error) {\n      console.error(\"Failed to initialize version info:\", error);\n      version = \"\";\n    }\n  });\n</script>\n\n<div class=\"app-info\">\n  <ThemeSwitcher />\n  <button\n    class:info-button={true}\n    class:has-update={hasUpdate}\n    on:click={() => (showInfo = !showInfo)}\n    aria-label=\"Toggle app info\"\n  >\n    <span class=\"icon\" class:update-available={hasUpdate}>\n      <Fa icon={faInfo} />\n    </span>\n  </button>\n\n  {#if showInfo}\n    <!-- svelte-ignore a11y_no_static_element_interactions -->\n    <div class=\"info-panel\" on:mouseleave={() => (showInfo = false)}>\n      <div class=\"info-content\">\n        <pre class=\"ascii-art\">{ASCII_ART}</pre>\n        <div class=\"details\">\n          <div class=\"detail-row\">\n            <span>NeoHtop v{version}</span>\n            {#if hasUpdate}\n              <a\n                href={`https://github.com/abdenasser/neohtop/releases/latest`}\n                class=\"update-button\"\n                target=\"_blank\"\n                rel=\"noopener noreferrer\"\n              >\n                Update to v{latestVersion}\n              </a>\n            {/if}\n          </div>\n          <div class=\"detail-row\">\n            <span class=\"label\">app</span>\n            <span class=\"separator\">::</span>\n            <span class=\"value\">{APP_INFO.name}</span>\n          </div>\n          <div class=\"detail-row\">\n            <span class=\"label\">source</span>\n            <span class=\"separator\">::</span>\n            <a\n              href={APP_INFO.github}\n              class=\"value\"\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n            >\n              {APP_INFO.github}\n            </a>\n          </div>\n          <div class=\"detail-row\">\n            <span class=\"label\">stack</span>\n            <span class=\"separator\">::</span>\n            <span class=\"value\">{APP_INFO.stack.join(\", \")}</span>\n          </div>\n        </div>\n      </div>\n    </div>\n  {/if}\n</div>\n\n<style>\n  .app-info {\n    display: flex;\n    gap: 8px;\n    position: relative;\n  }\n\n  .info-button,\n  :global(.theme-button) {\n    height: 28px;\n    padding: 0 12px;\n    font-size: 12px;\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    color: var(--text);\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.2s ease;\n    box-sizing: border-box;\n  }\n\n  .info-button:hover,\n  :global(.theme-button:hover) {\n    background: var(--surface1);\n  }\n\n  .icon {\n    display: inline-flex;\n    align-items: center;\n    font-size: 10px;\n    color: var(--subtext0);\n  }\n\n  .icon.update-available {\n    color: var(--red);\n  }\n\n  .info-panel {\n    position: absolute;\n    top: 100%;\n    right: 0;\n    margin-top: 4px;\n    padding: 16px;\n    background: var(--base);\n    border: 1px solid var(--surface0);\n    border-radius: 6px;\n    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n    z-index: 100;\n    min-width: 400px;\n  }\n\n  .info-content {\n    display: flex;\n    gap: 24px;\n  }\n\n  .ascii-art {\n    font-family: monospace;\n    font-size: 8px;\n    line-height: 1;\n    color: var(--mauve);\n    margin: 0;\n    padding: 0;\n    white-space: pre;\n  }\n\n  .details {\n    display: flex;\n    flex-direction: column;\n    gap: 8px;\n    padding: 8px 0;\n  }\n\n  .detail-row {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    font-family: monospace;\n    font-size: 13px;\n  }\n\n  .label {\n    color: var(--green);\n    min-width: 80px;\n  }\n\n  .separator {\n    color: var(--subtext0);\n  }\n\n  .value {\n    color: var(--text);\n  }\n\n  .detail-row span {\n    color: var(--text);\n    font-weight: 500;\n  }\n\n  .info-button.has-update {\n    border-color: var(--red);\n  }\n\n  .info-button.has-update:hover {\n    background: color-mix(in srgb, var(--red) 10%, transparent);\n  }\n\n  .info-button.has-update .icon {\n    color: var(--red);\n  }\n\n  .update-button {\n    display: inline-flex;\n    align-items: center;\n    padding: 4px 8px;\n    font-size: 12px;\n    color: var(--base);\n    background: var(--red);\n    border-radius: 4px;\n    text-decoration: none;\n    margin-left: 8px;\n    transition: all 0.2s ease;\n  }\n\n  .update-button:hover {\n    background: color-mix(in srgb, var(--red) 90%, white);\n    transform: translateY(-1px);\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/ThemeSwitcher.svelte",
    "content": "<script lang=\"ts\">\n  import { themeStore } from \"$lib/stores\";\n  import { overlayStore } from \"$lib/stores/overlay\";\n  import { themes } from \"$lib/definitions\";\n  import Fa from \"svelte-fa\";\n  import {\n    faChevronDown,\n    faChevronRight,\n    faChevronLeft,\n  } from \"@fortawesome/free-solid-svg-icons\";\n  import { platform } from \"@tauri-apps/plugin-os\";\n  import { THEME_GROUPS } from \"$lib/constants\";\n  import { onDestroy } from \"svelte\";\n\n  let containerElement: HTMLDivElement;\n  let overlayElement: HTMLDivElement;\n  let optionsContainer: HTMLDivElement;\n  let canScrollLeft = false;\n  let canScrollRight = false;\n\n  $: showMenu = $overlayStore === \"theme\";\n\n  const themeGroups = [\n    ...THEME_GROUPS,\n    ...(platform() === \"windows\" || platform() === \"macos\"\n      ? [\n          {\n            label: \"Glassy\",\n            themes: [\"glassy\"],\n          },\n        ]\n      : []),\n  ];\n\n  function updateOverlayPosition() {\n    if (overlayElement && containerElement) {\n      const toolbarContent = containerElement.closest(\".toolbar-content\");\n      if (toolbarContent) {\n        const toolbarRect = toolbarContent.getBoundingClientRect();\n        const containerRect = containerElement.getBoundingClientRect();\n\n        const leftOffset = containerRect.left - toolbarRect.left;\n        const rightOffset = toolbarRect.right - containerRect.right;\n        const topOffset = containerRect.top - toolbarRect.top;\n\n        overlayElement.style.left = `-${leftOffset}px`;\n        overlayElement.style.right = `-${rightOffset}px`;\n        overlayElement.style.top = `-${topOffset}px`;\n      }\n    }\n  }\n\n  function updateScrollButtons() {\n    if (optionsContainer) {\n      canScrollLeft = optionsContainer.scrollLeft > 0;\n      canScrollRight =\n        optionsContainer.scrollLeft <\n        optionsContainer.scrollWidth - optionsContainer.clientWidth;\n    }\n  }\n\n  function scrollLeft() {\n    if (optionsContainer) {\n      optionsContainer.scrollBy({ left: -200, behavior: \"smooth\" });\n      setTimeout(updateScrollButtons, 100);\n    }\n  }\n\n  function scrollRight() {\n    if (optionsContainer) {\n      optionsContainer.scrollBy({ left: 200, behavior: \"smooth\" });\n      setTimeout(updateScrollButtons, 100);\n    }\n  }\n\n  function toggleThemeMenu(event: Event) {\n    event.stopPropagation();\n    if (showMenu) {\n      overlayStore.close();\n    } else {\n      overlayStore.open(\"theme\");\n      setTimeout(() => {\n        updateOverlayPosition();\n        updateScrollButtons();\n      }, 0);\n    }\n  }\n\n  function selectTheme(themeName: string) {\n    themeStore.setTheme(themeName);\n    overlayStore.close();\n  }\n\n  function handleClickOutside(event: MouseEvent) {\n    if (\n      showMenu &&\n      containerElement &&\n      !containerElement.contains(event.target as Node)\n    ) {\n      overlayStore.close();\n    }\n  }\n\n  function setupClickOutside() {\n    if (typeof document !== \"undefined\") {\n      document.addEventListener(\"click\", handleClickOutside);\n    }\n  }\n\n  function cleanupClickOutside() {\n    if (typeof document !== \"undefined\") {\n      document.removeEventListener(\"click\", handleClickOutside);\n    }\n  }\n\n  $: if (showMenu) {\n    setTimeout(setupClickOutside, 0);\n  } else {\n    cleanupClickOutside();\n  }\n\n  onDestroy(() => {\n    cleanupClickOutside();\n  });\n</script>\n\n<div\n  class=\"theme-switcher\"\n  class:active={showMenu}\n  bind:this={containerElement}\n>\n  <button\n    class=\"theme-button\"\n    class:active={showMenu}\n    on:click={toggleThemeMenu}\n    aria-label=\"Toggle theme menu\"\n  >\n    <div class=\"current-theme\">\n      <div class=\"theme-preview\" style:background={$themeStore.colors.base}>\n        <div\n          class=\"preview-color\"\n          style:background={$themeStore.colors.blue}\n        ></div>\n        <div\n          class=\"preview-color\"\n          style:background={$themeStore.colors.red}\n        ></div>\n        <div\n          class=\"preview-color\"\n          style:background={$themeStore.colors.green}\n        ></div>\n      </div>\n    </div>\n    <span class=\"icon\">\n      {#if showMenu}\n        <Fa icon={faChevronDown} />\n      {:else}\n        <Fa icon={faChevronRight} />\n      {/if}\n    </span>\n  </button>\n\n  {#if showMenu}\n    <div\n      class=\"touchbar-full-overlay\"\n      bind:this={overlayElement}\n      on:click={() => overlayStore.close()}\n      on:keydown={(e) => e.key === \"Escape\" && overlayStore.close()}\n      role=\"dialog\"\n      aria-label=\"Theme selection\"\n      tabindex=\"-1\"\n    >\n      {#if canScrollLeft}\n        <button\n          class=\"scroll-chevron scroll-left\"\n          on:click|stopPropagation={scrollLeft}\n        >\n          <Fa icon={faChevronLeft} />\n        </button>\n      {/if}\n\n      <div\n        class=\"touchbar-horizontal-options\"\n        bind:this={optionsContainer}\n        on:scroll={updateScrollButtons}\n      >\n        {#each themeGroups as group}\n          {#each group.themes as themeName}\n            {@const theme = themes[themeName]}\n            <button\n              class=\"touchbar-option\"\n              class:active={$themeStore.name === theme.name}\n              on:click|stopPropagation={() => selectTheme(theme.name)}\n              title={theme.label}\n            >\n              <div class=\"theme-preview\" style:background={theme.colors.base}>\n                <div\n                  class=\"preview-color\"\n                  style:background={theme.colors.blue}\n                ></div>\n                <div\n                  class=\"preview-color\"\n                  style:background={theme.colors.red}\n                ></div>\n                <div\n                  class=\"preview-color\"\n                  style:background={theme.colors.green}\n                ></div>\n              </div>\n              <span class=\"theme-label\">{theme.label}</span>\n            </button>\n          {/each}\n        {/each}\n      </div>\n\n      {#if canScrollRight}\n        <button\n          class=\"scroll-chevron scroll-right\"\n          on:click|stopPropagation={scrollRight}\n        >\n          <Fa icon={faChevronRight} />\n        </button>\n      {/if}\n    </div>\n  {/if}\n</div>\n\n<style>\n  .theme-switcher {\n    position: relative;\n  }\n\n  .theme-button {\n    display: flex;\n    align-items: center;\n    gap: 6px;\n    padding: 0 12px;\n    height: 28px;\n    font-size: 12px;\n    color: var(--text);\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.2s ease;\n    box-sizing: border-box;\n  }\n\n  .theme-button:hover {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .theme-button.active {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .icon {\n    font-size: 10px;\n    color: var(--subtext0);\n  }\n\n  .touchbar-full-overlay {\n    position: absolute;\n    top: -0px;\n    height: 44px;\n    background: var(--mantle);\n    border: none;\n    border-radius: 0;\n    box-shadow: none;\n    z-index: 1000;\n    display: flex;\n    align-items: center;\n    padding: 0 8px;\n    gap: 8px;\n  }\n\n  .scroll-chevron {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: 28px;\n    height: 28px;\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    color: var(--text);\n    cursor: pointer;\n    transition: all 0.15s ease;\n    flex-shrink: 0;\n    font-size: 10px;\n    animation: optionSlideIn 0.2s ease-out;\n    animation-fill-mode: both;\n    animation-delay: 0ms;\n  }\n\n  .scroll-chevron:hover {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .touchbar-horizontal-options {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    flex: 1;\n    overflow-x: auto;\n    overflow-y: hidden;\n    scrollbar-width: none;\n    -ms-overflow-style: none;\n    padding: 0 4px;\n  }\n\n  .touchbar-horizontal-options::-webkit-scrollbar {\n    display: none;\n  }\n\n  .touchbar-option {\n    padding: 0 8px;\n    height: 28px;\n    font-size: 12px;\n    color: var(--text);\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.15s ease;\n    white-space: nowrap;\n    flex-shrink: 0;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    gap: 6px;\n    min-width: fit-content;\n    box-sizing: border-box;\n    animation: optionSlideIn 0.2s ease-out;\n    animation-fill-mode: both;\n  }\n\n  .touchbar-option:nth-child(1) {\n    animation-delay: 20ms;\n  }\n  .touchbar-option:nth-child(2) {\n    animation-delay: 40ms;\n  }\n  .touchbar-option:nth-child(3) {\n    animation-delay: 60ms;\n  }\n  .touchbar-option:nth-child(4) {\n    animation-delay: 80ms;\n  }\n  .touchbar-option:nth-child(5) {\n    animation-delay: 100ms;\n  }\n  .touchbar-option:nth-child(6) {\n    animation-delay: 120ms;\n  }\n  .touchbar-option:nth-child(7) {\n    animation-delay: 140ms;\n  }\n  .touchbar-option:nth-child(8) {\n    animation-delay: 160ms;\n  }\n  .touchbar-option:nth-child(9) {\n    animation-delay: 180ms;\n  }\n  .touchbar-option:nth-child(10) {\n    animation-delay: 200ms;\n  }\n\n  @keyframes optionSlideIn {\n    from {\n      opacity: 0;\n      transform: translateY(-8px) scale(0.9);\n    }\n    to {\n      opacity: 1;\n      transform: translateY(0) scale(1);\n    }\n  }\n\n  .touchbar-option:hover:not(.disabled) {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .touchbar-option.active {\n    background: var(--blue);\n    color: var(--base);\n    border-color: var(--blue);\n  }\n\n  .theme-preview {\n    display: flex;\n    gap: 2px;\n    padding: 2px;\n    border-radius: 3px;\n    border: 1px solid var(--surface1);\n  }\n\n  .preview-color {\n    width: 8px;\n    height: 8px;\n    border-radius: 1px;\n  }\n\n  .theme-label {\n    font-size: 12px;\n  }\n\n  .current-theme {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/TitleBar.svelte",
    "content": "<script lang=\"ts\">\n</script>\n\n<div class=\"title-bar\" data-tauri-drag-region>\n  <div class=\"title\">\n    <img src=\"/32x32.png\" alt=\"NeoHtop\" class=\"app-icon\" />\n    <div class=\"neon\">NeoHtop</div>\n  </div>\n</div>\n\n<style>\n  .title-bar {\n    height: 32px;\n    /* background: var(--mantle); */\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    padding: 0 12px;\n    -webkit-user-select: none;\n    user-select: none;\n    position: relative;\n    overflow: hidden;\n  }\n\n  .title {\n    display: flex;\n    align-items: center;\n    position: relative;\n    height: 100%;\n  }\n\n  .neon {\n    font-family: \"Courier New\", monospace;\n    font-size: 14px;\n    font-weight: bold;\n    color: var(--text);\n  }\n\n  .app-icon {\n    width: 24px;\n    height: 24px;\n    margin-right: 4px;\n    display: flex;\n    align-items: center;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/index.ts",
    "content": "export * from \"./toolbar\";\nexport * from \"./process\";\nexport * from \"./stats\";\nexport * from \"./modals\";\nexport { default as AppInfo } from \"./AppInfo.svelte\";\nexport { default as TitleBar } from \"./TitleBar.svelte\";\nexport { default as ThemeSwitcher } from \"./ThemeSwitcher.svelte\";\n"
  },
  {
    "path": "src/lib/components/modals/KillProcessModal.svelte",
    "content": "<script lang=\"ts\">\n  import { Modal } from \"$lib/components\";\n\n  interface Process {\n    pid: number;\n    name: string;\n  }\n\n  export let show = false;\n  export let process: Process | null = null;\n  export let onClose: () => void;\n  export let onConfirm: () => Promise<void>;\n  export let isKilling = false;\n</script>\n\n<Modal {show} title=\"Confirm Action\" maxWidth=\"400px\" {onClose}>\n  {#if process}\n    <div class=\"confirm-content\">\n      <p class=\"confirm-message\">Are you sure you want to end this process?</p>\n      <div class=\"process-info\">\n        <span class=\"process-name\">{process.name}</span>\n        <span class=\"process-pid\">(PID: {process.pid})</span>\n      </div>\n      <div class=\"confirm-actions\">\n        <button class=\"btn-secondary\" on:click={onClose} disabled={isKilling}>\n          Cancel\n        </button>\n        <button class=\"btn-danger\" on:click={onConfirm} disabled={isKilling}>\n          {#if isKilling}\n            <div class=\"spinner\"></div>\n            <span>Ending...</span>\n          {:else}\n            End Process\n          {/if}\n        </button>\n      </div>\n    </div>\n  {/if}\n</Modal>\n\n<style>\n  .confirm-content {\n    display: flex;\n    flex-direction: column;\n    gap: 16px;\n  }\n\n  .confirm-message {\n    color: var(--text);\n    margin: 0;\n    font-size: 14px;\n  }\n\n  .process-info {\n    background: var(--mantle);\n    padding: 12px;\n    border-radius: 6px;\n  }\n\n  .process-name {\n    color: var(--text);\n    font-weight: 500;\n    font-size: 14px;\n  }\n\n  .process-pid {\n    color: var(--subtext0);\n    font-size: 12px;\n    margin-left: 8px;\n  }\n\n  .confirm-actions {\n    display: flex;\n    justify-content: flex-end;\n    gap: 12px;\n  }\n\n  .btn-secondary {\n    padding: 8px 16px;\n    font-size: 13px;\n    color: var(--text);\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.2s ease;\n  }\n\n  .btn-secondary:hover {\n    background: var(--surface1);\n  }\n\n  .btn-danger {\n    padding: 8px 16px;\n    font-size: 13px;\n    color: var(--base);\n    background: var(--red);\n    border: none;\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.2s ease;\n    display: inline-flex;\n    align-items: center;\n    gap: 8px;\n  }\n\n  .btn-danger:disabled {\n    opacity: 0.7;\n    cursor: not-allowed;\n  }\n\n  .btn-danger:hover {\n    background: color-mix(in srgb, var(--red) 90%, white);\n  }\n\n  .spinner {\n    width: 16px;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/modals/Modal.svelte",
    "content": "<script lang=\"ts\">\n  export let show = false;\n  export let maxWidth = \"600px\";\n  export let title: string;\n  export let onClose: () => void;\n</script>\n\n{#if show}\n  <!-- svelte-ignore a11y_click_events_have_key_events -->\n  <!-- svelte-ignore a11y_no_static_element_interactions -->\n  <div class=\"modal-backdrop\" on:click={onClose}>\n    <div class=\"modal\" on:click|stopPropagation style=\"--max-width: {maxWidth}\">\n      <div class=\"modal-header\">\n        <h2>{title}</h2>\n        <button class=\"btn-close\" on:click={onClose}>×</button>\n      </div>\n      <div class=\"modal-content\">\n        <slot />\n      </div>\n    </div>\n  </div>\n{/if}\n\n<style>\n  .modal-backdrop {\n    position: fixed;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    background: rgba(0, 0, 0, 0.5);\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    z-index: 1000;\n  }\n\n  .modal {\n    background: var(--base);\n    border-radius: 8px;\n    width: 100%;\n    max-width: var(--max-width);\n    max-height: 90vh;\n    overflow: auto;\n    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);\n  }\n\n  .modal-header {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    padding: 16px;\n    border-bottom: 1px solid var(--surface0);\n  }\n\n  .modal-header h2 {\n    margin: 0;\n    font-size: 18px;\n    color: var(--text);\n  }\n\n  .btn-close {\n    background: transparent;\n    border: none;\n    color: var(--overlay0);\n    font-size: 24px;\n    cursor: pointer;\n    padding: 4px 8px;\n  }\n\n  .btn-close:hover {\n    color: var(--text);\n  }\n\n  .modal-content {\n    padding: 16px;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/modals/ProcessDetailsModal.svelte",
    "content": "<script lang=\"ts\">\n  import { Modal } from \"$lib/components\";\n  import { formatBytes } from \"$lib/utils\";\n  import type { Process } from \"$lib/types\";\n  import Fa from \"svelte-fa\";\n  import {\n    faMemory,\n    faMicrochip,\n    faCodeFork,\n    faTerminal,\n    faList,\n  } from \"@fortawesome/free-solid-svg-icons\";\n\n  export let show = false;\n  export let process: Process | null = null;\n  export let onClose: () => void;\n  export let processes: Process[] = [];\n  export let onShowDetails: (process: Process) => void;\n\n  $: childProcesses = process\n    ? processes.filter((p) => p.ppid === process.pid)\n    : [];\n</script>\n\n<Modal\n  {show}\n  title={`${process ? process.name.slice(0, 10) : \"Unknown Process\"} - Process Details`}\n  maxWidth=\"1000px\"\n  {onClose}\n>\n  {#if process}\n    <div class=\"modal-content\">\n      <!-- Header Stats -->\n      <div class=\"header-stats\">\n        <div class=\"stat-item\">\n          <div class=\"stat-label\">PID</div>\n          <div class=\"stat-value\">{process.pid}</div>\n        </div>\n        <div class=\"stat-item\">\n          <div class=\"stat-label\">Status</div>\n          <div\n            class=\"stat-value status\"\n            class:running={process.status === \"Running\"}\n          >\n            {process.status}\n          </div>\n        </div>\n        <div class=\"stat-item\">\n          <div class=\"stat-label\">CPU</div>\n          <div class=\"stat-value\">{process.cpu_usage.toFixed(1)}%</div>\n        </div>\n        <div class=\"stat-item\">\n          <div class=\"stat-label\">Memory</div>\n          <div class=\"stat-value\">{formatBytes(process.memory_usage)}</div>\n        </div>\n      </div>\n\n      <!-- Main Content -->\n      <div class=\"content-grid\">\n        <!-- Left Column -->\n        <div class=\"content-column\">\n          <!-- Process Info -->\n          <div class=\"card\">\n            <div class=\"card-header\">\n              <Fa icon={faMicrochip} />\n              <span>Process Information</span>\n            </div>\n            <div class=\"card-content\">\n              <div class=\"info-grid\">\n                <div class=\"info-item\">\n                  <span class=\"info-label\">Name</span>\n                  <span class=\"info-value\">{process.name}</span>\n                </div>\n                <div class=\"info-item\">\n                  <span class=\"info-label\">User</span>\n                  <span class=\"info-value\">{process.user}</span>\n                </div>\n                <div class=\"info-item\">\n                  <span class=\"info-label\">Parent PID</span>\n                  <!-- svelte-ignore a11y_click_events_have_key_events -->\n                  <!-- svelte-ignore a11y_no_static_element_interactions -->\n                  <span\n                    class=\"info-value clickable\"\n                    on:click={() => {\n                      const parent = processes.find(\n                        (p) => p.pid === process.ppid,\n                      );\n                      if (parent) onShowDetails(parent);\n                    }}\n                  >\n                    {process.ppid}\n                  </span>\n                </div>\n                <div class=\"info-item\">\n                  <span class=\"info-label\">Session ID</span>\n                  <span class=\"info-value\">{process.session_id}</span>\n                </div>\n              </div>\n            </div>\n          </div>\n\n          <!-- Resource Usage -->\n          <div class=\"card\">\n            <div class=\"card-header\">\n              <Fa icon={faMemory} />\n              <span>Resource Usage</span>\n            </div>\n            <div class=\"card-content\">\n              <div class=\"resource-grid\">\n                <div class=\"resource-item\">\n                  <div class=\"resource-header\">\n                    <span>CPU Usage</span>\n                    <span class=\"resource-value\"\n                      >{process.cpu_usage.toFixed(1)}%</span\n                    >\n                  </div>\n                  <div class=\"progress-bar\">\n                    <div\n                      class=\"progress-fill\"\n                      style=\"width: {process.cpu_usage}%\"\n                      class:high={process.cpu_usage > 50}\n                      class:critical={process.cpu_usage > 80}\n                    ></div>\n                  </div>\n                </div>\n                <div class=\"resource-item\">\n                  <div class=\"resource-header\">\n                    <span>Memory Usage</span>\n                  </div>\n                  <div class=\"memory-stats\">\n                    <div>Physical: {formatBytes(process.memory_usage)}</div>\n                    <div>Virtual: {formatBytes(process.virtual_memory)}</div>\n                  </div>\n                </div>\n                <div class=\"resource-item\">\n                  <div class=\"resource-header\">\n                    <span>Disk I/O</span>\n                  </div>\n                  <div class=\"disk-stats\">\n                    <div>Read: {formatBytes(process.disk_usage[0])}</div>\n                    <div>Written: {formatBytes(process.disk_usage[1])}</div>\n                  </div>\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <!-- Right Column -->\n        <div class=\"content-column\">\n          <!-- Command -->\n          <div class=\"card\">\n            <div class=\"card-header\">\n              <Fa icon={faTerminal} />\n              <span>Command</span>\n            </div>\n            <div class=\"card-content\">\n              <div class=\"command-text\">{process.command}</div>\n              <div class=\"path-text\">{process.root}</div>\n            </div>\n          </div>\n\n          <!-- Child Processes -->\n          {#if childProcesses.length > 0}\n            <div class=\"card\">\n              <div class=\"card-header\">\n                <Fa icon={faCodeFork} />\n                <span>Child Processes ({childProcesses.length})</span>\n              </div>\n              <div class=\"card-content\">\n                <table class=\"process-table\">\n                  <thead>\n                    <tr>\n                      <th>Name</th>\n                      <th>PID</th>\n                      <th>CPU</th>\n                      <th>Memory</th>\n                    </tr>\n                  </thead>\n                  <tbody>\n                    {#each childProcesses as child}\n                      <tr\n                        class=\"clickable\"\n                        on:click={() => onShowDetails(child)}\n                      >\n                        <td>{child.name}</td>\n                        <td>{child.pid}</td>\n                        <td>{child.cpu_usage.toFixed(1)}%</td>\n                        <td>{formatBytes(child.memory_usage)}</td>\n                      </tr>\n                    {/each}\n                  </tbody>\n                </table>\n              </div>\n            </div>\n          {/if}\n\n          <!-- Environment Variables -->\n          {#if process.environ.length > 0}\n            <div class=\"card\">\n              <div class=\"card-header\">\n                <Fa icon={faList} />\n                <span>Environment Variables</span>\n              </div>\n              <div class=\"card-content\">\n                <div class=\"env-list\">\n                  {#each process.environ as env}\n                    <div class=\"env-item\">{env}</div>\n                  {/each}\n                </div>\n              </div>\n            </div>\n          {/if}\n        </div>\n      </div>\n    </div>\n  {/if}\n</Modal>\n\n<style>\n  /* Base Modal Content */\n  .modal-content {\n    display: flex;\n    flex-direction: column;\n    gap: 24px;\n    font-size: 13px;\n    color: var(--text);\n  }\n\n  /* Header Stats */\n  .header-stats {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));\n    gap: 16px;\n    padding: 16px;\n    background: var(--surface0);\n    border-radius: 8px;\n  }\n\n  .stat-item {\n    display: flex;\n    flex-direction: column;\n    gap: 4px;\n  }\n\n  .stat-label {\n    font-size: 12px;\n    color: var(--subtext0);\n    font-weight: 500;\n  }\n\n  .stat-value {\n    font-size: 16px;\n    font-weight: 600;\n  }\n\n  .stat-value.status {\n    color: var(--subtext0);\n  }\n\n  .stat-value.status.running {\n    color: var(--green);\n  }\n\n  /* Main Content Grid */\n  .content-grid {\n    display: grid;\n    grid-template-columns: minmax(300px, 0.4fr) minmax(400px, 0.6fr);\n    gap: 24px;\n  }\n\n  .content-column {\n    display: flex;\n    flex-direction: column;\n    gap: 24px;\n    min-width: 0; /* Prevent overflow issues */\n  }\n\n  /* Cards */\n  .card {\n    background: var(--surface0);\n    border-radius: 8px;\n    overflow: hidden;\n    min-width: 0; /* Prevent overflow issues */\n  }\n\n  .card-header {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    padding: 12px 16px;\n    background: var(--surface1);\n    color: var(--subtext0);\n    font-weight: 500;\n  }\n\n  .card-header :global(svg) {\n    width: 14px;\n    height: 14px;\n    color: var(--blue);\n  }\n\n  .card-content {\n    padding: 16px;\n    overflow: auto;\n  }\n\n  /* Info Grid */\n  .info-grid {\n    display: grid;\n    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n    gap: 16px;\n  }\n\n  .info-item {\n    display: flex;\n    flex-direction: column;\n    gap: 4px;\n  }\n\n  .info-label {\n    color: var(--subtext0);\n    font-size: 12px;\n  }\n\n  .info-value {\n    color: var(--text);\n  }\n\n  .info-value.clickable {\n    cursor: pointer;\n    color: var(--blue);\n  }\n\n  .info-value.clickable:hover {\n    text-decoration: underline;\n  }\n\n  /* Resource Usage */\n  .resource-grid {\n    display: flex;\n    flex-direction: column;\n    gap: 16px;\n  }\n\n  .resource-item {\n    display: flex;\n    flex-direction: column;\n    gap: 8px;\n  }\n\n  .resource-header {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    color: var(--subtext0);\n    font-size: 12px;\n  }\n\n  .resource-value {\n    color: var(--text);\n  }\n\n  /* Progress Bar */\n  .progress-bar {\n    height: 6px;\n    background: var(--surface1);\n    border-radius: 3px;\n    overflow: hidden;\n  }\n\n  .progress-fill {\n    height: 100%;\n    background: var(--blue);\n    transition: width 0.2s ease;\n  }\n\n  .progress-fill.high {\n    background: var(--yellow);\n  }\n\n  .progress-fill.critical {\n    background: var(--red);\n  }\n\n  /* Memory and Disk Stats */\n  .memory-stats,\n  .disk-stats {\n    display: grid;\n    grid-template-columns: 1fr 1fr;\n    gap: 8px;\n    color: var(--text);\n  }\n\n  /* Command and Path */\n  .command-text,\n  .path-text {\n    word-break: break-all;\n    white-space: pre-wrap;\n  }\n\n  .path-text {\n    margin-top: 8px;\n    font-size: 12px;\n    color: var(--subtext0);\n  }\n\n  /* Process Table */\n  .process-table {\n    width: 100%;\n    border-collapse: collapse;\n  }\n\n  .process-table th {\n    text-align: left;\n    padding: 8px;\n    color: var(--subtext0);\n    font-weight: 500;\n    border-bottom: 1px solid var(--surface1);\n  }\n\n  .process-table td {\n    padding: 8px;\n    border-bottom: 1px solid var(--surface1);\n  }\n\n  .process-table tr:last-child td {\n    border-bottom: none;\n  }\n\n  .process-table tr.clickable {\n    cursor: pointer;\n  }\n\n  .process-table tr.clickable:hover {\n    background: var(--surface1);\n  }\n\n  /* Environment Variables */\n  .env-list {\n    display: flex;\n    flex-direction: column;\n    gap: 4px;\n    max-height: 200px;\n    overflow-y: auto;\n    margin: -16px;\n    padding: 16px;\n  }\n\n  .env-item {\n    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,\n      \"Liberation Mono\", \"Courier New\", monospace;\n    padding: 4px 8px;\n    border-radius: 4px;\n    color: var(--subtext1);\n    font-size: 12px;\n  }\n\n  .env-item:hover {\n    background: var(--surface1);\n  }\n\n  /* Update scrollbar styles to match the container edges */\n  .env-list::-webkit-scrollbar {\n    width: 8px;\n    height: 8px;\n  }\n\n  .env-list::-webkit-scrollbar-track {\n    background: var(--surface0);\n    border-radius: 0;\n  }\n\n  .env-list::-webkit-scrollbar-thumb {\n    background: var(--surface2);\n    border-radius: 4px;\n    border: 2px solid var(--surface0);\n  }\n\n  .env-list::-webkit-scrollbar-thumb:hover {\n    background: var(--surface1);\n  }\n\n  /* Scrollbar Styles */\n  :global(.modal-content *::-webkit-scrollbar) {\n    width: 8px;\n    height: 8px;\n  }\n\n  :global(.modal-content *::-webkit-scrollbar-track) {\n    background: var(--mantle);\n    border-radius: 4px;\n  }\n\n  :global(.modal-content *::-webkit-scrollbar-thumb) {\n    background: var(--surface2);\n    border-radius: 4px;\n  }\n\n  :global(.modal-content *::-webkit-scrollbar-thumb:hover) {\n    background: var(--surface1);\n  }\n\n  /* Responsive Design */\n  @media (max-width: 900px) {\n    .content-grid {\n      grid-template-columns: 1fr;\n    }\n\n    .header-stats {\n      grid-template-columns: repeat(2, 1fr);\n    }\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/modals/index.ts",
    "content": "export { default as Modal } from \"./Modal.svelte\";\nexport { default as ProcessDetailsModal } from \"./ProcessDetailsModal.svelte\";\nexport { default as KillProcessModal } from \"./KillProcessModal.svelte\";\n"
  },
  {
    "path": "src/lib/components/process/ActionButtons.svelte",
    "content": "<script lang=\"ts\">\n  import {\n    faThumbtack,\n    faInfoCircle,\n    faXmark,\n  } from \"@fortawesome/free-solid-svg-icons\";\n  import Fa from \"svelte-fa\";\n  import type { Process } from \"$lib/types\";\n\n  export let process: Process;\n  export let isPinned: boolean;\n  export let onTogglePin: (command: string) => void;\n  export let onShowDetails: (process: Process) => void;\n  export let onKillProcess: (process: Process) => void;\n</script>\n\n<td class=\"col-actions\">\n  <div class=\"action-buttons\">\n    <button\n      class=\"btn-action pin-btn\"\n      class:pinned={isPinned}\n      on:click={() => onTogglePin(process.command)}\n      title={isPinned ? \"Unpin\" : \"Pin\"}\n    >\n      <Fa icon={faThumbtack} />\n    </button>\n    <button\n      class=\"btn-action info-btn\"\n      on:click={() => onShowDetails(process)}\n      title=\"Show Details\"\n    >\n      <Fa icon={faInfoCircle} />\n    </button>\n    <button\n      class=\"btn-action kill-btn\"\n      on:click={() => onKillProcess(process)}\n      title=\"End Process\"\n    >\n      <Fa icon={faXmark} />\n    </button>\n  </div>\n</td>\n\n<style>\n  td {\n    padding: 6px 12px;\n    border-bottom: 1px solid var(--surface0);\n    color: var(--text);\n    z-index: 1;\n  }\n  .col-actions {\n    position: sticky;\n    right: 0;\n    z-index: 2;\n    background: var(--base);\n    border-left: 1px solid var(--surface0);\n    width: 120px;\n  }\n\n  .action-buttons {\n    display: flex;\n    gap: 4px;\n    align-items: center;\n    justify-content: center;\n  }\n\n  .btn-action {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    border: none;\n    cursor: pointer;\n    background: transparent;\n    border-radius: 6px;\n    width: 28px;\n    height: 28px;\n    transition: all 0.2s ease;\n    position: relative;\n    overflow: hidden;\n  }\n\n  .btn-action::before {\n    content: \"\";\n    position: absolute;\n    inset: 0;\n    opacity: 0.1;\n    transition: opacity 0.2s ease;\n  }\n\n  .btn-action:hover::before {\n    opacity: 0.15;\n  }\n\n  .pin-btn {\n    color: var(--sapphire);\n  }\n\n  .pin-btn::before {\n    background: var(--sapphire);\n  }\n\n  .pin-btn.pinned {\n    color: var(--blue);\n    transform: rotate(45deg);\n  }\n\n  .pin-btn.pinned::before {\n    background: var(--blue);\n    opacity: 0.15;\n  }\n\n  .info-btn {\n    color: var(--lavender);\n  }\n\n  .info-btn::before {\n    background: var(--lavender);\n  }\n\n  .kill-btn {\n    color: var(--red);\n    border: 1px solid color-mix(in srgb, var(--red) 30%, transparent);\n  }\n\n  .kill-btn:hover {\n    color: var(--base);\n    background: var(--red);\n  }\n\n  .kill-btn:hover::before {\n    opacity: 1;\n  }\n\n  .btn-action:hover {\n    box-shadow: 0 0 12px color-mix(in srgb, currentColor 20%, transparent);\n  }\n\n  .btn-action:active {\n    transform: translateY(1px);\n  }\n\n  .pin-btn.pinned:active {\n    transform: rotate(45deg) translateY(1px);\n  }\n\n  .btn-action:focus {\n    outline: none;\n    box-shadow: 0 0 0 2px color-mix(in srgb, currentColor 30%, transparent);\n  }\n\n  .btn-action:disabled {\n    opacity: 0.5;\n    cursor: not-allowed;\n  }\n\n  .btn-action:disabled:hover {\n    transform: none;\n    box-shadow: none;\n  }\n\n  .btn-action:disabled::before {\n    display: none;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/process/ProcessIcon.svelte",
    "content": "<script lang=\"ts\">\n  import * as SimpleIcons from \"simple-icons\";\n\n  export let processName: string;\n  export let size: number = 16;\n\n  function handleImageError(event: Event) {\n    const img = event.target as HTMLImageElement;\n    img.src = getIconForProcess(\"default\");\n    img.onerror = null;\n  }\n\n  function getIconForProcess(name: string): string {\n    // First try with com.company.something pattern\n    if (name.startsWith(\"com.\")) {\n      const companyName = name.replace(/^com\\.([^.]+)\\..*$/, \"$1\");\n      const formattedCompanyName =\n        companyName.charAt(0).toUpperCase() + companyName.slice(1);\n      const companyIconKey = `si${formattedCompanyName}`;\n      const companyIcon =\n        SimpleIcons[companyIconKey as keyof typeof SimpleIcons];\n\n      if (companyIcon) {\n        // Use theme color instead of brand color\n        const color = getComputedStyle(document.documentElement)\n          .getPropertyValue(\"--text\")\n          .trim();\n        const svg =\n          typeof companyIcon === \"object\" && \"svg\" in companyIcon\n            ? companyIcon.svg\n            : \"\";\n        const svgWithColor = svg.replace(\"<svg\", `<svg fill=\"${color}\"`);\n        return `data:image/svg+xml;base64,${btoa(svgWithColor)}`;\n      }\n    }\n\n    // If no company icon found, fall back to original implementation\n    const cleanName = name\n      .replace(/\\.(app|exe)$/i, \"\")\n      .replace(/[-_./\\\\]/g, \" \")\n      .split(\" \")[0]\n      .trim()\n      .toLowerCase();\n\n    const formattedName =\n      cleanName.charAt(0).toUpperCase() + cleanName.slice(1);\n    const iconKey = `si${formattedName}`;\n    let simpleIcon = SimpleIcons[iconKey as keyof typeof SimpleIcons];\n\n    // Default icon if no match found\n    if (!simpleIcon) {\n      simpleIcon = SimpleIcons.siGhostery;\n    }\n\n    // Use theme color instead of brand color\n    const color = getComputedStyle(document.documentElement)\n      .getPropertyValue(\"--text\")\n      .trim();\n\n    const svg =\n      typeof simpleIcon === \"object\" && \"svg\" in simpleIcon\n        ? simpleIcon.svg\n        : \"\";\n    const svgWithColor = svg.replace(\"<svg\", `<svg fill=\"${color}\"`);\n    return `data:image/svg+xml;base64,${btoa(svgWithColor)}`;\n  }\n</script>\n\n<img\n  class=\"process-icon\"\n  src={getIconForProcess(processName)}\n  alt=\"\"\n  height={size}\n  width={size}\n  on:error={handleImageError}\n/>\n\n<style>\n  .process-icon {\n    width: 16px;\n    height: 16px;\n    object-fit: contain;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/process/ProcessRow.svelte",
    "content": "<script lang=\"ts\">\n  import type { Process, Column } from \"$lib/types\";\n  import { ProcessIcon, ActionButtons } from \"$lib/components\";\n\n  export let process: Process;\n  export let columns: Column[];\n  export let isPinned: boolean;\n  export let isHighUsage: boolean;\n\n  export let onTogglePin: (command: string) => void;\n  export let onShowDetails: (process: Process) => void;\n  export let onKillProcess: (process: Process) => void;\n</script>\n\n<tr class:high-usage={isHighUsage} class:pinned={isPinned}>\n  {#each columns.filter((col) => col.visible) as column}\n    <td class=\"truncate\">\n      {#if column.id === \"name\"}\n        <div class=\"name-cell\">\n          <ProcessIcon processName={process.name} />\n          <span class=\"process-name\">{process.name}</span>\n        </div>\n      {:else if column.format}\n        {@html column.format(process[column.id])}\n      {:else}\n        {process[column.id]}\n      {/if}\n    </td>\n  {/each}\n  <ActionButtons\n    {process}\n    {isPinned}\n    {onTogglePin}\n    {onShowDetails}\n    {onKillProcess}\n  />\n</tr>\n\n<style>\n  td {\n    padding: 6px 12px;\n    border-bottom: 1px solid var(--surface0);\n    color: var(--text);\n    z-index: 1;\n  }\n\n  .truncate {\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    max-width: 0;\n  }\n\n  tr:hover {\n    background-color: var(--surface0);\n  }\n\n  .high-usage {\n    background-color: color-mix(in srgb, var(--red) 10%, transparent);\n  }\n\n  .high-usage:hover {\n    background-color: color-mix(in srgb, var(--red) 15%, transparent);\n  }\n\n  tr.pinned {\n    background-color: color-mix(in srgb, var(--blue) 10%, transparent);\n  }\n\n  tr.pinned:hover {\n    background-color: color-mix(in srgb, var(--blue) 15%, transparent);\n  }\n\n  .name-cell {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/process/ProcessTable.svelte",
    "content": "<script lang=\"ts\">\n  import type { Process, Column } from \"$lib/types\";\n  import { TableHeader, ProcessRow } from \"$lib/components\";\n\n  export let processes: Process[];\n  export let columns: Column[];\n  export let systemStats: { memory_total: number } | null;\n  export let sortConfig: { field: keyof Process; direction: \"asc\" | \"desc\" };\n  export let pinnedProcesses: Set<string>;\n\n  export let onToggleSort: (field: keyof Process) => void;\n  export let onTogglePin: (command: string) => void;\n  export let onShowDetails: (process: Process) => void;\n  export let onKillProcess: (process: Process) => void;\n</script>\n\n<div class=\"table-container\">\n  <table>\n    <TableHeader {columns} {sortConfig} {onToggleSort} />\n    <tbody>\n      {#each processes as process (process.pid)}\n        <ProcessRow\n          {process}\n          {columns}\n          isPinned={pinnedProcesses.has(process.command)}\n          isHighUsage={process.cpu_usage > 50 ||\n            process.memory_usage / (systemStats?.memory_total || 0) > 0.1}\n          {onTogglePin}\n          {onShowDetails}\n          {onKillProcess}\n        />\n      {/each}\n    </tbody>\n  </table>\n</div>\n\n<style>\n  .table-container {\n    flex: 1;\n    overflow-x: auto;\n    overflow-y: auto;\n    scrollbar-width: thin;\n    scrollbar-color: var(--surface2) var(--mantle);\n  }\n\n  .table-container::-webkit-scrollbar {\n    width: 8px;\n    height: 8px;\n  }\n\n  .table-container::-webkit-scrollbar-track {\n    background: var(--mantle);\n    border-radius: 4px;\n  }\n\n  .table-container::-webkit-scrollbar-thumb {\n    background: var(--surface2);\n    border-radius: 4px;\n    transition: background 0.2s ease;\n  }\n\n  .table-container::-webkit-scrollbar-thumb:hover {\n    background: var(--surface1);\n  }\n\n  .table-container::-webkit-scrollbar-corner {\n    background: var(--mantle);\n  }\n\n  table {\n    width: max-content;\n    min-width: 100%;\n    table-layout: fixed;\n    border-collapse: collapse;\n    font-size: 13px;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/process/TableHeader.svelte",
    "content": "<script lang=\"ts\">\n  import type { Process, Column } from \"$lib/types\";\n\n  export let columns: Column[];\n  export let sortConfig: { field: keyof Process; direction: \"asc\" | \"desc\" };\n  export let onToggleSort: (field: keyof Process) => void;\n\n  function getSortIndicator(field: keyof Process) {\n    if (sortConfig.field !== field) return \"↕\";\n    return sortConfig.direction === \"asc\" ? \"↑\" : \"↓\";\n  }\n</script>\n\n<thead>\n  <tr>\n    {#each columns.filter((col) => col.visible) as column}\n      <th class=\"sortable\" on:click={() => onToggleSort(column.id)}>\n        <div class=\"th-content\">\n          {column.label}\n          <span\n            class=\"sort-indicator\"\n            class:active={sortConfig.field === column.id}\n          >\n            {getSortIndicator(column.id)}\n          </span>\n        </div>\n      </th>\n    {/each}\n    <th>Actions</th>\n  </tr>\n</thead>\n\n<style>\n  th {\n    position: sticky;\n    top: 0;\n    background: var(--mantle);\n    text-align: left;\n    padding: 8px 12px;\n    font-weight: 500;\n    color: var(--subtext0);\n    border-bottom: 1px solid var(--surface0);\n    transition: background-color 0.2s ease;\n    z-index: 3;\n  }\n\n  th:last-child {\n    width: 120px;\n    min-width: 120px;\n    max-width: 120px;\n  }\n\n  .sortable {\n    cursor: pointer;\n    user-select: none;\n  }\n\n  .th-content {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n  }\n\n  .sort-indicator {\n    color: var(--overlay0);\n    font-size: 12px;\n    opacity: 0.5;\n    transition: all 0.2s ease;\n  }\n\n  .sort-indicator.active {\n    color: var(--blue);\n    opacity: 1;\n  }\n\n  .sortable:hover .sort-indicator {\n    opacity: 1;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/process/index.ts",
    "content": "export { default as ProcessTable } from \"./ProcessTable.svelte\";\nexport { default as ProcessRow } from \"./ProcessRow.svelte\";\nexport { default as TableHeader } from \"./TableHeader.svelte\";\nexport { default as ActionButtons } from \"./ActionButtons.svelte\";\nexport { default as ProcessIcon } from \"./ProcessIcon.svelte\";\n"
  },
  {
    "path": "src/lib/components/stats/CpuPanel.svelte",
    "content": "<script lang=\"ts\">\n  import { faMicrochip } from \"@fortawesome/free-solid-svg-icons\";\n  import { PanelHeader, ProgressBar } from \"$lib/components\";\n  import { formatPercentage } from \"$lib/utils\";\n\n  export let cpuUsage: number[];\n\n  $: averageUsage = formatPercentage(\n    cpuUsage.reduce((a, b) => a + b, 0) / cpuUsage.length,\n  );\n</script>\n\n<div class=\"stat-panel\">\n  <PanelHeader icon={faMicrochip} title=\"CPU Usage\" usageValue={averageUsage} />\n  <div class=\"stats-content cpu-grid\">\n    {#each cpuUsage as usage, i}\n      <div class=\"stat-item with-progress\">\n        <ProgressBar\n          label={`Core ${i}`}\n          value={usage}\n          labelWidth=\"2.5rem\"\n          valueWidth=\"2.5rem\"\n        />\n      </div>\n    {/each}\n  </div>\n</div>\n\n<style>\n  .stat-panel {\n    flex: 2.5;\n    min-width: 0;\n    background-color: var(--mantle);\n    border-radius: 6px;\n    padding: 0.75rem;\n    display: flex;\n    flex-direction: column;\n  }\n\n  .stats-content {\n    display: flex;\n    flex-direction: column;\n    gap: 0.4rem;\n  }\n\n  .cpu-grid {\n    display: grid;\n    grid-template-columns: repeat(2, 1fr);\n    gap: 0.4rem 2rem;\n    height: auto;\n    overflow: visible;\n  }\n\n  .stat-item.with-progress {\n    display: flex;\n    flex-direction: column;\n    gap: 0.2rem;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/stats/MemoryPanel.svelte",
    "content": "<script lang=\"ts\">\n  import { faMemory } from \"@fortawesome/free-solid-svg-icons\";\n  import { PanelHeader, ProgressBar, StatItem } from \"$lib/components\";\n  import { formatMemorySize, formatPercentage } from \"$lib/utils\";\n\n  export let memoryTotal: number;\n  export let memoryUsed: number;\n  export let memoryFree: number;\n\n  $: memoryPercentage = (memoryUsed / memoryTotal) * 100;\n</script>\n\n<div class=\"stat-panel\">\n  <PanelHeader\n    icon={faMemory}\n    title=\"Memory\"\n    usageValue={formatPercentage(memoryPercentage)}\n  />\n  <div class=\"stats-content\">\n    <div class=\"stat-item with-progress\">\n      <ProgressBar\n        label=\"Memory usage\"\n        value={memoryPercentage}\n        labelWidth=\"5rem\"\n        valueWidth=\"2.5rem\"\n      />\n    </div>\n    <StatItem label=\"Total\" value={formatMemorySize(memoryTotal)} />\n    <StatItem label=\"Used\" value={formatMemorySize(memoryUsed)} />\n    <StatItem label=\"Free\" value={formatMemorySize(memoryFree)} />\n  </div>\n</div>\n\n<style>\n  .stat-panel {\n    flex: 2;\n    min-width: 0;\n    background-color: var(--mantle);\n    border-radius: 6px;\n    padding: 0.75rem;\n    display: flex;\n    flex-direction: column;\n  }\n\n  .stats-content {\n    display: flex;\n    flex-direction: column;\n    gap: 0.4rem;\n  }\n\n  .stat-item.with-progress {\n    display: flex;\n    flex-direction: column;\n    gap: 0.2rem;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/stats/NetworkPanel.svelte",
    "content": "<script lang=\"ts\">\n  import { faNetworkWired } from \"@fortawesome/free-solid-svg-icons\";\n  import { PanelHeader, StatItem } from \"$lib/components\";\n  import { formatBytes } from \"$lib/utils\";\n\n  export let networkRxBytes: number;\n  export let networkTxBytes: number;\n</script>\n\n<div class=\"stat-panel\">\n  <PanelHeader icon={faNetworkWired} title=\"Network I/O\" />\n  <div class=\"network-stats\">\n    <StatItem label=\"↓ Receiving\" value={formatBytes(networkRxBytes)} />\n    <StatItem label=\"↑ Sending\" value={formatBytes(networkTxBytes)} />\n  </div>\n</div>\n\n<style>\n  .stat-panel {\n    flex: 0.8;\n    min-width: 125px;\n    background-color: var(--mantle);\n    border-radius: 6px;\n    padding: 0.75rem;\n    display: flex;\n    flex-direction: column;\n  }\n\n  .network-stats {\n    display: flex;\n    flex-direction: column;\n    gap: 0.4rem;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/stats/PanelHeader.svelte",
    "content": "<script lang=\"ts\">\n  import Fa from \"svelte-fa\";\n  import type { IconDefinition } from \"@fortawesome/free-solid-svg-icons\";\n\n  export let icon: IconDefinition;\n  export let title: string;\n  export let usageValue: string | null = null;\n</script>\n\n<div class=\"panel-header\">\n  <Fa {icon} />\n  <h3>{title}</h3>\n  {#if usageValue}\n    <div class=\"usage-pill\">{usageValue}</div>\n  {/if}\n</div>\n\n<style>\n  .panel-header {\n    display: flex;\n    align-items: center;\n    gap: 0.5rem;\n    margin-bottom: 0.75rem;\n    padding-bottom: 0.5rem;\n    border-bottom: 1px solid var(--surface0);\n    flex-shrink: 0;\n  }\n\n  .panel-header h3 {\n    font-size: 0.8rem;\n    font-weight: 600;\n    margin: 0;\n    color: var(--text);\n  }\n\n  .panel-header :global(svg) {\n    color: var(--blue);\n    width: 0.8rem;\n    height: 0.8rem;\n  }\n\n  .usage-pill {\n    margin-left: auto;\n    background: var(--surface0);\n    padding: 0.15rem 0.5rem;\n    border-radius: 1rem;\n    font-size: 0.7rem;\n    font-weight: 500;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/stats/ProgressBar.svelte",
    "content": "<script lang=\"ts\">\n  export let label: string;\n  export let value: number;\n  export let labelWidth = \"2.5rem\";\n  export let valueWidth = \"2.5rem\";\n\n  function getUsageClass(usage: number): string {\n    if (usage > 90) return \"critical\";\n    if (usage > 75) return \"high\";\n    if (usage > 50) return \"medium\";\n    return \"low\";\n  }\n</script>\n\n<div\n  class=\"progress-container\"\n  style=\"--label-width: {labelWidth}; --value-width: {valueWidth}\"\n>\n  <span class=\"label\">{label}</span>\n  <div class=\"bar-container\">\n    <div\n      class=\"usage-bar {getUsageClass(value)}\"\n      style=\"transform: translateX({value - 100}%);\"\n    ></div>\n  </div>\n  <span class=\"value\">{Math.round(value)}%</span>\n</div>\n\n<style>\n  .progress-container {\n    width: 100%;\n    display: grid;\n    grid-template-columns: var(--label-width) 1fr var(--value-width);\n    align-items: center;\n    gap: 0.3rem;\n    font-size: 0.7rem;\n  }\n\n  .label {\n    color: var(--subtext0);\n    white-space: nowrap;\n  }\n\n  .value {\n    color: var(--text);\n    text-align: right;\n    white-space: nowrap;\n  }\n\n  .bar-container {\n    height: 8px;\n    background: var(--surface0);\n    border-radius: 4px;\n    overflow: hidden;\n    position: relative;\n  }\n\n  .usage-bar {\n    position: absolute;\n    left: 0;\n    top: 0;\n    bottom: 0;\n    width: 100%;\n    transition: transform 0.3s ease;\n    transform-origin: left;\n  }\n\n  .usage-bar.low {\n    background: var(--blue);\n  }\n  .usage-bar.medium {\n    background: var(--yellow);\n  }\n  .usage-bar.high {\n    background: var(--peach);\n  }\n  .usage-bar.critical {\n    background: var(--red);\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/stats/StatItem.svelte",
    "content": "<script lang=\"ts\">\n  export let label: string;\n  export let value: string;\n</script>\n\n<div class=\"stat-item\">\n  <span>{label}</span>\n  <span>{value}</span>\n</div>\n\n<style>\n  .stat-item {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    font-size: 0.7rem;\n    line-height: 1.2;\n    margin: 0;\n    padding: 0;\n  }\n\n  .stat-item span:first-child {\n    color: var(--subtext0);\n  }\n\n  .stat-item span:last-child {\n    color: var(--text);\n    font-weight: 500;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/stats/StatPanel.svelte",
    "content": "<script lang=\"ts\">\n  export let title: string;\n  export let flex = 1;\n</script>\n\n<div class=\"stat-panel\" style=\"--flex: {flex}\">\n  <h3 class=\"panel-title\">{title}</h3>\n  <div class=\"panel-content\">\n    <slot />\n  </div>\n</div>\n\n<style>\n  .stat-panel {\n    flex: var(--flex);\n    min-width: 125px;\n    background: var(--mantle);\n    border-radius: 8px;\n    padding: 12px;\n  }\n\n  .panel-title {\n    font-size: 12px;\n    font-weight: 600;\n    color: var(--subtext0);\n    margin: 0 0 12px 0;\n  }\n\n  .panel-content {\n    display: flex;\n    flex-direction: column;\n    gap: 8px;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/stats/StatsBar.svelte",
    "content": "<script lang=\"ts\">\n  import type { SystemStats } from \"$lib/types\";\n  import {\n    CpuPanel,\n    MemoryPanel,\n    StoragePanel,\n    SystemPanel,\n    NetworkPanel,\n  } from \"$lib/components\";\n\n  export let systemStats: SystemStats | null = null;\n</script>\n\n<div class=\"dashboard-stats\">\n  {#if systemStats}\n    <div class=\"stats-layout\">\n      <CpuPanel cpuUsage={systemStats.cpu_usage} />\n\n      <MemoryPanel\n        memoryTotal={systemStats.memory_total}\n        memoryUsed={systemStats.memory_used}\n        memoryFree={systemStats.memory_free}\n      />\n\n      <StoragePanel\n        diskTotalBytes={systemStats.disk_total_bytes}\n        diskUsedBytes={systemStats.disk_used_bytes}\n        diskFreeBytes={systemStats.disk_free_bytes}\n      />\n\n      <SystemPanel uptime={systemStats.uptime} loadAvg={systemStats.load_avg} />\n\n      <NetworkPanel\n        networkRxBytes={systemStats.network_rx_bytes}\n        networkTxBytes={systemStats.network_tx_bytes}\n      />\n    </div>\n  {/if}\n</div>\n\n<style>\n  .dashboard-stats {\n    padding: 0.5rem;\n    overflow-x: auto;\n  }\n\n  .stats-layout {\n    display: flex;\n    gap: 0.75rem;\n    width: 100%;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/stats/StoragePanel.svelte",
    "content": "<script lang=\"ts\">\n  import { faHardDrive } from \"@fortawesome/free-solid-svg-icons\";\n  import { PanelHeader, StatItem } from \"$lib/components\";\n  import { formatBytes, formatPercentage } from \"$lib/utils\";\n\n  export let diskTotalBytes: number;\n  export let diskUsedBytes: number;\n  export let diskFreeBytes: number;\n\n  $: diskUsagePercentage = (diskUsedBytes / diskTotalBytes) * 100;\n</script>\n\n<div class=\"stat-panel\">\n  <PanelHeader\n    icon={faHardDrive}\n    title=\"Storage\"\n    usageValue={formatPercentage(diskUsagePercentage)}\n  />\n  <div class=\"stats-content\">\n    <StatItem label=\"Total\" value={formatBytes(diskTotalBytes)} />\n    <StatItem label=\"Used\" value={formatBytes(diskUsedBytes)} />\n    <StatItem label=\"Free\" value={formatBytes(diskFreeBytes)} />\n  </div>\n</div>\n\n<style>\n  .stat-panel {\n    flex: 0.8;\n    min-width: 125px;\n    background-color: var(--mantle);\n    border-radius: 6px;\n    padding: 0.75rem;\n    display: flex;\n    flex-direction: column;\n  }\n\n  .stats-content {\n    display: flex;\n    flex-direction: column;\n    gap: 0.4rem;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/stats/SystemPanel.svelte",
    "content": "<script lang=\"ts\">\n  import { faServer } from \"@fortawesome/free-solid-svg-icons\";\n  import { PanelHeader, StatItem } from \"$lib/components\";\n  import { formatUptime } from \"$lib/utils\";\n\n  export let uptime: number;\n  export let loadAvg: [number, number, number];\n</script>\n\n<div class=\"stat-panel\">\n  <PanelHeader icon={faServer} title=\"System\" />\n  <div class=\"system-grid\">\n    <StatItem label=\"Uptime\" value={formatUptime(uptime)} />\n    <StatItem label=\"1m Load\" value={loadAvg[0].toFixed(2)} />\n    <StatItem label=\"5m Load\" value={loadAvg[1].toFixed(2)} />\n    <StatItem label=\"15m Load\" value={loadAvg[2].toFixed(2)} />\n  </div>\n</div>\n\n<style>\n  .stat-panel {\n    flex: 0.8;\n    min-width: 125px;\n    background-color: var(--mantle);\n    border-radius: 6px;\n    padding: 0.75rem;\n    display: flex;\n    flex-direction: column;\n  }\n\n  .system-grid {\n    display: flex;\n    flex-direction: column;\n    gap: 0.4rem;\n    flex: 1;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/stats/index.ts",
    "content": "export { default as StatsBar } from \"./StatsBar.svelte\";\nexport { default as CpuPanel } from \"./CpuPanel.svelte\";\nexport { default as MemoryPanel } from \"./MemoryPanel.svelte\";\nexport { default as StoragePanel } from \"./StoragePanel.svelte\";\nexport { default as SystemPanel } from \"./SystemPanel.svelte\";\nexport { default as NetworkPanel } from \"./NetworkPanel.svelte\";\nexport { default as PanelHeader } from \"./PanelHeader.svelte\";\nexport { default as ProgressBar } from \"./ProgressBar.svelte\";\nexport { default as StatItem } from \"./StatItem.svelte\";\n"
  },
  {
    "path": "src/lib/components/toolbar/ColumnToggle.svelte",
    "content": "<script lang=\"ts\">\n  import Fa from \"svelte-fa\";\n  import {\n    faChevronDown,\n    faChevronRight,\n    faChevronLeft,\n  } from \"@fortawesome/free-solid-svg-icons\";\n  import { settingsStore } from \"$lib/stores/index\";\n  import { overlayStore } from \"$lib/stores/overlay\";\n  import { onDestroy } from \"svelte\";\n\n  export let columns: Array<{\n    id: string;\n    label: string;\n    visible: boolean;\n    required?: boolean;\n  }>;\n\n  let containerElement: HTMLDivElement;\n  let overlayElement: HTMLDivElement;\n  let optionsContainer: HTMLDivElement;\n  let canScrollLeft = false;\n  let canScrollRight = false;\n\n  $: showColumnMenu = $overlayStore === \"columns\";\n\n  function handleColumnVisibilityChange(columnId: string, visible: boolean) {\n    settingsStore.updateConfig({\n      appearance: {\n        columnVisibility: {\n          ...$settingsStore.appearance.columnVisibility,\n          [columnId]: visible,\n        },\n      },\n    });\n  }\n\n  function updateOverlayPosition() {\n    if (overlayElement && containerElement) {\n      const toolbarContent = containerElement.closest(\".toolbar-content\");\n      if (toolbarContent) {\n        const toolbarRect = toolbarContent.getBoundingClientRect();\n        const containerRect = containerElement.getBoundingClientRect();\n\n        const leftOffset = containerRect.left - toolbarRect.left;\n        const rightOffset = toolbarRect.right - containerRect.right;\n        const topOffset = containerRect.top - toolbarRect.top;\n\n        overlayElement.style.left = `-${leftOffset}px`;\n        overlayElement.style.right = `-${rightOffset}px`;\n        overlayElement.style.top = `-${topOffset}px`;\n      }\n    }\n  }\n\n  function updateScrollButtons() {\n    if (optionsContainer) {\n      canScrollLeft = optionsContainer.scrollLeft > 0;\n      canScrollRight =\n        optionsContainer.scrollLeft <\n        optionsContainer.scrollWidth - optionsContainer.clientWidth;\n    }\n  }\n\n  function scrollLeft() {\n    if (optionsContainer) {\n      optionsContainer.scrollBy({ left: -200, behavior: \"smooth\" });\n      setTimeout(updateScrollButtons, 100);\n    }\n  }\n\n  function scrollRight() {\n    if (optionsContainer) {\n      optionsContainer.scrollBy({ left: 200, behavior: \"smooth\" });\n      setTimeout(updateScrollButtons, 100);\n    }\n  }\n\n  function toggleExpanded(event: Event) {\n    event.stopPropagation();\n    if (showColumnMenu) {\n      overlayStore.close();\n    } else {\n      overlayStore.open(\"columns\");\n      setTimeout(() => {\n        updateOverlayPosition();\n        updateScrollButtons();\n      }, 0);\n    }\n  }\n\n  function handleClickOutside(event: MouseEvent) {\n    if (\n      showColumnMenu &&\n      containerElement &&\n      !containerElement.contains(event.target as Node)\n    ) {\n      overlayStore.close();\n    }\n  }\n\n  function setupClickOutside() {\n    if (typeof document !== \"undefined\") {\n      document.addEventListener(\"click\", handleClickOutside);\n    }\n  }\n\n  function cleanupClickOutside() {\n    if (typeof document !== \"undefined\") {\n      document.removeEventListener(\"click\", handleClickOutside);\n    }\n  }\n\n  $: if (showColumnMenu) {\n    setTimeout(setupClickOutside, 0);\n  } else {\n    cleanupClickOutside();\n  }\n\n  onDestroy(() => {\n    cleanupClickOutside();\n  });\n</script>\n\n<div class=\"column-toggle\" bind:this={containerElement}>\n  <button\n    class=\"touchbar-trigger\"\n    class:active={showColumnMenu}\n    on:click={toggleExpanded}\n    aria-label=\"Toggle columns\"\n  >\n    Columns\n    <span class=\"icon\">\n      <Fa icon={showColumnMenu ? faChevronDown : faChevronRight} />\n    </span>\n  </button>\n\n  {#if showColumnMenu}\n    <div\n      class=\"touchbar-full-overlay\"\n      bind:this={overlayElement}\n      on:click={() => overlayStore.close()}\n      on:keydown={(e) => e.key === \"Escape\" && overlayStore.close()}\n      role=\"dialog\"\n      aria-label=\"Column visibility options\"\n      tabindex=\"-1\"\n    >\n      {#if canScrollLeft}\n        <button\n          class=\"scroll-chevron scroll-left\"\n          on:click|stopPropagation={scrollLeft}\n        >\n          <Fa icon={faChevronLeft} />\n        </button>\n      {/if}\n\n      <div\n        class=\"touchbar-horizontal-options\"\n        bind:this={optionsContainer}\n        on:scroll={updateScrollButtons}\n      >\n        {#each columns as column}\n          <button\n            class=\"touchbar-option\"\n            class:active={column.visible}\n            class:disabled={column.required}\n            on:click|stopPropagation={() =>\n              !column.required &&\n              handleColumnVisibilityChange(column.id, !column.visible)}\n            title={column.required\n              ? \"Required column\"\n              : `Toggle ${column.label}`}\n          >\n            {column.label}\n          </button>\n        {/each}\n      </div>\n\n      {#if canScrollRight}\n        <button\n          class=\"scroll-chevron scroll-right\"\n          on:click|stopPropagation={scrollRight}\n        >\n          <Fa icon={faChevronRight} />\n        </button>\n      {/if}\n    </div>\n  {/if}\n</div>\n\n<style>\n  .column-toggle {\n    position: relative;\n    flex: 1;\n  }\n\n  .touchbar-trigger {\n    display: flex;\n    align-items: center;\n    gap: 6px;\n    padding: 0 12px;\n    height: 28px;\n    font-size: 12px;\n    color: var(--text);\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.2s ease;\n    box-sizing: border-box;\n  }\n\n  .touchbar-trigger:hover {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .touchbar-trigger.active {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .icon {\n    font-size: 10px;\n    color: var(--subtext0);\n    transition: transform 0.2s ease;\n  }\n\n  .touchbar-full-overlay {\n    position: absolute;\n    top: -0px;\n    height: 44px;\n    background: var(--mantle);\n    border: none;\n    border-radius: 0;\n    box-shadow: none;\n    z-index: 1000;\n    display: flex;\n    align-items: center;\n    padding: 0 8px;\n    gap: 8px;\n  }\n\n  .scroll-chevron {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: 28px;\n    height: 28px;\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    color: var(--text);\n    cursor: pointer;\n    transition: all 0.15s ease;\n    flex-shrink: 0;\n    font-size: 10px;\n    animation: optionSlideIn 0.2s ease-out;\n    animation-fill-mode: both;\n    animation-delay: 0ms;\n  }\n\n  .scroll-chevron:hover {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .touchbar-horizontal-options {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    flex: 1;\n    overflow-x: auto;\n    overflow-y: hidden;\n    scrollbar-width: none;\n    -ms-overflow-style: none;\n    padding: 0 4px;\n  }\n\n  .touchbar-horizontal-options::-webkit-scrollbar {\n    display: none;\n  }\n\n  .touchbar-option {\n    padding: 0 12px;\n    height: 28px;\n    font-size: 11px;\n    color: var(--text);\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.15s ease;\n    white-space: nowrap;\n    flex-shrink: 0;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    min-width: fit-content;\n    box-sizing: border-box;\n    animation: optionSlideIn 0.2s ease-out;\n    animation-fill-mode: both;\n  }\n\n  .touchbar-option:nth-child(1) {\n    animation-delay: 20ms;\n  }\n  .touchbar-option:nth-child(2) {\n    animation-delay: 40ms;\n  }\n  .touchbar-option:nth-child(3) {\n    animation-delay: 60ms;\n  }\n  .touchbar-option:nth-child(4) {\n    animation-delay: 80ms;\n  }\n  .touchbar-option:nth-child(5) {\n    animation-delay: 100ms;\n  }\n  .touchbar-option:nth-child(6) {\n    animation-delay: 120ms;\n  }\n  .touchbar-option:nth-child(7) {\n    animation-delay: 140ms;\n  }\n  .touchbar-option:nth-child(8) {\n    animation-delay: 160ms;\n  }\n  .touchbar-option:nth-child(9) {\n    animation-delay: 180ms;\n  }\n  .touchbar-option:nth-child(10) {\n    animation-delay: 200ms;\n  }\n\n  @keyframes optionSlideIn {\n    from {\n      opacity: 0;\n      transform: translateY(-8px) scale(0.9);\n    }\n    to {\n      opacity: 1;\n      transform: translateY(0) scale(1);\n    }\n  }\n\n  .touchbar-option:hover:not(.disabled) {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .touchbar-option.active {\n    background: var(--blue);\n    color: var(--base);\n    border-color: var(--blue);\n  }\n\n  .touchbar-option.disabled {\n    opacity: 0.5;\n    cursor: not-allowed;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/toolbar/FilterToggle.svelte",
    "content": "<script lang=\"ts\">\n  import Fa from \"svelte-fa\";\n  import { faFilter } from \"@fortawesome/free-solid-svg-icons\";\n  import { overlayStore } from \"$lib/stores/overlay\";\n  import { onDestroy } from \"svelte\";\n\n  export let filters: {\n    cpu: { operator: string; value: number; enabled: boolean };\n    ram: { operator: string; value: number; enabled: boolean };\n    runtime: { operator: string; value: number; enabled: boolean };\n    status: { values: string[]; enabled: boolean };\n  } = {\n    cpu: { operator: \">\", value: 50, enabled: false },\n    ram: { operator: \">\", value: 100, enabled: false },\n    runtime: { operator: \">\", value: 60, enabled: false },\n    status: { values: [], enabled: false },\n  };\n\n  let containerElement: HTMLDivElement;\n  let overlayElement: HTMLDivElement;\n\n  $: showFilters = $overlayStore === \"filters\";\n  $: hasActiveFilters = Object.values(filters).some((f) => f.enabled);\n  $: activeFilterCount = Object.values(filters).filter((f) => f.enabled).length;\n\n  const operators = [\n    { value: \">\", label: \">\" },\n    { value: \"<\", label: \"<\" },\n  ];\n\n  const statusOptions = [\n    { value: \"Running\", label: \"Running\", color: \"var(--green)\" },\n    { value: \"Sleeping\", label: \"Sleeping\", color: \"var(--blue)\" },\n    { value: \"Stopped\", label: \"Stopped\", color: \"var(--red)\" },\n    { value: \"Zombie\", label: \"Zombie\", color: \"var(--yellow)\" },\n  ];\n\n  function updateOverlayPosition() {\n    if (overlayElement && containerElement) {\n      const toolbarContent = containerElement.closest(\".toolbar-content\");\n      if (toolbarContent) {\n        const toolbarRect = toolbarContent.getBoundingClientRect();\n        const containerRect = containerElement.getBoundingClientRect();\n\n        const leftOffset = containerRect.left - toolbarRect.left;\n        const rightOffset = toolbarRect.right - containerRect.right;\n        const topOffset = containerRect.top - toolbarRect.top;\n\n        overlayElement.style.left = `-${leftOffset}px`;\n        overlayElement.style.right = `-${rightOffset}px`;\n        overlayElement.style.top = `-${topOffset}px`;\n      }\n    }\n  }\n\n  function toggleFilters(event: Event) {\n    event.stopPropagation();\n    if (showFilters) {\n      overlayStore.close();\n    } else {\n      overlayStore.open(\"filters\");\n      setTimeout(updateOverlayPosition, 0);\n    }\n  }\n\n  function toggleFilter(type: keyof typeof filters) {\n    filters[type].enabled = !filters[type].enabled;\n    filters = { ...filters };\n  }\n\n  function updateFilter(\n    type: keyof typeof filters,\n    field: string,\n    value: string | number,\n  ) {\n    if (type === \"status\" && field === \"values\") {\n      // Handle status array toggle\n      const statusValue = value as string;\n      const currentValues = filters.status.values;\n      if (currentValues.includes(statusValue)) {\n        filters.status.values = currentValues.filter((v) => v !== statusValue);\n      } else {\n        filters.status.values = [...currentValues, statusValue];\n      }\n      filters.status.enabled = filters.status.values.length > 0;\n    } else if (field === \"operator\") {\n      (filters[type as keyof Omit<typeof filters, \"status\">] as any)[field] =\n        value as string;\n    } else if (field === \"value\") {\n      (filters[type as keyof Omit<typeof filters, \"status\">] as any)[field] =\n        value as number;\n    }\n    filters = { ...filters };\n  }\n\n  function clearAllFilters() {\n    Object.keys(filters).forEach((key) => {\n      const filterKey = key as keyof typeof filters;\n      if (filterKey === \"status\") {\n        filters[filterKey].values = [];\n      }\n      filters[filterKey].enabled = false;\n    });\n    filters = { ...filters };\n  }\n\n  function getFilterLabel(type: keyof typeof filters): string {\n    const labels = {\n      cpu: \"CPU %\",\n      ram: \"RAM MB\",\n      runtime: \"Runtime min\",\n      status: \"Status\",\n    };\n    return labels[type];\n  }\n\n  function handleClickOutside(event: MouseEvent) {\n    if (\n      showFilters &&\n      containerElement &&\n      !containerElement.contains(event.target as Node)\n    ) {\n      overlayStore.close();\n    }\n  }\n\n  function setupClickOutside() {\n    if (typeof document !== \"undefined\") {\n      document.addEventListener(\"click\", handleClickOutside);\n    }\n  }\n\n  function cleanupClickOutside() {\n    if (typeof document !== \"undefined\") {\n      document.removeEventListener(\"click\", handleClickOutside);\n    }\n  }\n\n  $: if (showFilters) {\n    setTimeout(setupClickOutside, 0);\n  } else {\n    cleanupClickOutside();\n  }\n\n  onDestroy(() => {\n    cleanupClickOutside();\n  });\n</script>\n\n<div class=\"filter-toggle\" bind:this={containerElement}>\n  <button\n    class=\"filter-button\"\n    class:active={showFilters}\n    class:has-filters={hasActiveFilters}\n    on:click={toggleFilters}\n    aria-label=\"Toggle filters\"\n  >\n    <Fa icon={faFilter} />\n    Filters\n    {#if hasActiveFilters}\n      <span class=\"filter-count\">{activeFilterCount}</span>\n    {/if}\n  </button>\n\n  {#if showFilters}\n    <div\n      class=\"touchbar-full-overlay\"\n      bind:this={overlayElement}\n      on:click={() => overlayStore.close()}\n      on:keydown={(e) => e.key === \"Escape\" && overlayStore.close()}\n      role=\"dialog\"\n      aria-label=\"Filter options overlay\"\n      tabindex=\"-1\"\n    >\n      <div class=\"filter-content\">\n        <div class=\"filter-sections\">\n          <!-- Numeric Filters -->\n          <div class=\"filter-section\">\n            <span class=\"section-label\">Performance:</span>\n            <div class=\"filter-controls\">\n              {#each [[\"cpu\", \"CPU %\"], [\"ram\", \"RAM MB\"], [\"runtime\", \"Runtime min\"]] as [type, label]}\n                {@const filterKey = type as \"cpu\" | \"ram\" | \"runtime\"}\n                <div class=\"filter-control\">\n                  <button\n                    class=\"filter-toggle-btn\"\n                    class:active={filters[filterKey].enabled}\n                    on:click|stopPropagation={() => toggleFilter(filterKey)}\n                  >\n                    {label}\n                  </button>\n                  {#if filters[filterKey].enabled}\n                    <select\n                      class=\"operator-select\"\n                      bind:value={filters[filterKey].operator}\n                      on:change={(e) =>\n                        updateFilter(\n                          filterKey,\n                          \"operator\",\n                          (e.target as HTMLSelectElement).value,\n                        )}\n                      on:click|stopPropagation\n                    >\n                      {#each operators as op}\n                        <option value={op.value}>{op.label}</option>\n                      {/each}\n                    </select>\n                    <input\n                      type=\"number\"\n                      class=\"value-input\"\n                      bind:value={filters[filterKey].value}\n                      on:input={(e) =>\n                        updateFilter(\n                          filterKey,\n                          \"value\",\n                          parseInt((e.target as HTMLInputElement).value),\n                        )}\n                      on:click|stopPropagation\n                      on:focus|stopPropagation\n                      placeholder={type === \"cpu\"\n                        ? \"50\"\n                        : type === \"ram\"\n                          ? \"100\"\n                          : \"60\"}\n                    />\n                    {#if type === \"ram\"}\n                      <span class=\"unit\">MB</span>\n                    {:else if type === \"runtime\"}\n                      <span class=\"unit\">min</span>\n                    {:else}\n                      <span class=\"unit\">%</span>\n                    {/if}\n                  {/if}\n                </div>\n              {/each}\n            </div>\n          </div>\n\n          <!-- Status Filter -->\n          <div class=\"filter-section\">\n            <span class=\"section-label\">Status:</span>\n            <div class=\"status-controls\">\n              {#each statusOptions as status}\n                <button\n                  class=\"status-toggle\"\n                  class:active={filters.status.values.includes(status.value)}\n                  style=\"--status-color: {status.color}\"\n                  on:click|stopPropagation={() =>\n                    updateFilter(\"status\", \"values\", status.value)}\n                >\n                  {status.label}\n                </button>\n              {/each}\n            </div>\n          </div>\n\n          <!-- Actions -->\n          <div class=\"filter-actions\">\n            {#if hasActiveFilters}\n              <button\n                class=\"clear-all-btn\"\n                on:click|stopPropagation={clearAllFilters}\n              >\n                <Fa icon={faFilter} />\n                Clear All\n              </button>\n            {/if}\n            <div class=\"filter-summary\">\n              {#if hasActiveFilters}\n                <span\n                  >{activeFilterCount} filter{activeFilterCount > 1 ? \"s\" : \"\"} active</span\n                >\n              {:else}\n                <span>No filters applied</span>\n              {/if}\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  {/if}\n</div>\n\n<style>\n  .filter-toggle {\n    position: relative;\n  }\n\n  .filter-button {\n    display: flex;\n    align-items: center;\n    gap: 6px;\n    padding: 0 12px;\n    height: 28px;\n    font-size: 12px;\n    color: var(--text);\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.2s ease;\n    box-sizing: border-box;\n  }\n\n  .filter-button:hover {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .filter-button.active {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .filter-button.has-filters {\n    border-color: var(--blue);\n    background: var(--surface1);\n  }\n\n  .filter-count {\n    background: var(--blue);\n    color: var(--base);\n    border-radius: 10px;\n    padding: 2px 6px;\n    font-size: 10px;\n    font-weight: 600;\n    min-width: 16px;\n    text-align: center;\n  }\n\n  .touchbar-full-overlay {\n    position: absolute;\n    top: -0px;\n    height: 44px;\n    background: var(--mantle);\n    border: none;\n    border-radius: 0;\n    box-shadow: none;\n    z-index: 1000;\n    display: flex;\n    align-items: center;\n    padding: 0 16px;\n    gap: 16px;\n    overflow-x: auto;\n    overflow-y: hidden;\n    scrollbar-width: none;\n    -ms-overflow-style: none;\n  }\n\n  .touchbar-full-overlay::-webkit-scrollbar {\n    display: none;\n  }\n\n  .filter-content {\n    display: flex;\n    align-items: center;\n    gap: 32px;\n    width: 100%;\n    animation: slideIn 0.3s ease-out;\n  }\n\n  @keyframes slideIn {\n    from {\n      opacity: 0;\n      transform: translateY(-8px);\n    }\n    to {\n      opacity: 1;\n      transform: translateY(0);\n    }\n  }\n\n  .filter-sections {\n    display: flex;\n    align-items: center;\n    gap: 32px;\n    flex: 1;\n  }\n\n  .filter-section {\n    display: flex;\n    align-items: center;\n    gap: 12px;\n    flex-shrink: 0;\n  }\n\n  .section-label {\n    font-size: 12px;\n    font-weight: 500;\n    color: var(--subtext0);\n    flex-shrink: 0;\n  }\n\n  .filter-controls {\n    display: flex;\n    gap: 8px;\n    align-items: center;\n  }\n\n  .filter-control {\n    display: flex;\n    align-items: center;\n    gap: 4px;\n  }\n\n  .filter-toggle-btn {\n    padding: 4px 8px;\n    height: 26px;\n    font-size: 11px;\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 4px;\n    color: var(--text);\n    cursor: pointer;\n    transition: all 0.15s ease;\n    white-space: nowrap;\n  }\n\n  .filter-toggle-btn:hover {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .filter-toggle-btn.active {\n    background: var(--blue);\n    color: var(--base);\n    border-color: var(--blue);\n  }\n\n  .operator-select {\n    padding: 4px 8px;\n    height: 26px;\n    font-size: 11px;\n    border: 1px solid var(--surface1);\n    border-radius: 4px;\n    background: var(--surface0);\n    color: var(--text);\n    cursor: pointer;\n    transition: all 0.15s ease;\n    appearance: none;\n    -webkit-appearance: none;\n    -moz-appearance: none;\n    text-align: center;\n    min-width: 32px;\n  }\n\n  .operator-select:hover {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .operator-select:focus {\n    outline: none;\n    border-color: var(--blue);\n    background: var(--surface1);\n  }\n\n  .value-input {\n    width: 50px;\n    padding: 2px 6px;\n    height: 22px;\n    font-size: 11px;\n    border: 1px solid var(--surface1);\n    border-radius: 3px;\n    background: var(--surface0);\n    color: var(--text);\n    text-align: center;\n  }\n\n  .value-input:focus {\n    outline: none;\n    border-color: var(--blue);\n  }\n\n  .unit {\n    font-size: 10px;\n    color: var(--subtext0);\n  }\n\n  .status-controls {\n    display: flex;\n    gap: 6px;\n    align-items: center;\n  }\n\n  .status-toggle {\n    padding: 4px 8px;\n    height: 26px;\n    font-size: 11px;\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 4px;\n    color: var(--text);\n    cursor: pointer;\n    transition: all 0.15s ease;\n    white-space: nowrap;\n  }\n\n  .status-toggle:hover {\n    background: var(--surface1);\n    border-color: var(--status-color);\n  }\n\n  .status-toggle.active {\n    background: var(--status-color);\n    color: var(--base);\n    border-color: var(--status-color);\n  }\n\n  .filter-actions {\n    display: flex;\n    align-items: center;\n    gap: 12px;\n    flex-shrink: 0;\n  }\n\n  .clear-all-btn {\n    display: flex;\n    align-items: center;\n    gap: 6px;\n    padding: 4px 8px;\n    height: 26px;\n    font-size: 11px;\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 4px;\n    color: var(--text);\n    cursor: pointer;\n    transition: all 0.15s ease;\n  }\n\n  .clear-all-btn:hover {\n    background: var(--red);\n    border-color: var(--red);\n    color: var(--base);\n  }\n\n  .filter-summary {\n    font-size: 11px;\n    color: var(--subtext0);\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/toolbar/PaginationControls.svelte",
    "content": "<script lang=\"ts\">\n  import type { AppConfig } from \"$lib/types\";\n  import { settingsStore } from \"$lib/stores/index\";\n  import { overlayStore } from \"$lib/stores/overlay\";\n  import { ITEMS_PER_PAGE_OPTIONS } from \"$lib/constants\";\n  import { onDestroy } from \"svelte\";\n\n  export let itemsPerPage: number;\n  export let currentPage: number;\n  export let totalPages: number;\n  export let totalResults: number;\n\n  let containerElement: HTMLDivElement;\n  let overlayElement: HTMLDivElement;\n\n  $: isExpanded = $overlayStore === \"pagination\";\n\n  function changePage(page: number) {\n    if (page >= 1 && page <= totalPages) {\n      currentPage = page;\n    }\n  }\n\n  function updateBehaviorConfig(key: keyof AppConfig[\"behavior\"], value: any) {\n    settingsStore.updateConfig({\n      behavior: {\n        ...$settingsStore.behavior,\n        [key]: value,\n      },\n    });\n  }\n\n  function selectItemsPerPage(value: number) {\n    itemsPerPage = value;\n    updateBehaviorConfig(\"itemsPerPage\", itemsPerPage);\n    overlayStore.close();\n  }\n\n  function updateOverlayPosition() {\n    if (overlayElement && containerElement) {\n      const toolbarContent = containerElement.closest(\".toolbar-content\");\n      if (toolbarContent) {\n        const toolbarRect = toolbarContent.getBoundingClientRect();\n        const containerRect = containerElement.getBoundingClientRect();\n\n        const leftOffset = containerRect.left - toolbarRect.left;\n        const rightOffset = toolbarRect.right - containerRect.right;\n        const topOffset = containerRect.top - toolbarRect.top;\n\n        overlayElement.style.left = `-${leftOffset}px`;\n        overlayElement.style.right = `-${rightOffset}px`;\n        overlayElement.style.top = `-${topOffset}px`;\n      }\n    }\n  }\n\n  function toggleExpanded(event: Event) {\n    event.stopPropagation();\n    if (isExpanded) {\n      overlayStore.close();\n    } else {\n      overlayStore.open(\"pagination\");\n      setTimeout(updateOverlayPosition, 0);\n    }\n  }\n\n  function handleClickOutside(event: MouseEvent) {\n    if (\n      isExpanded &&\n      containerElement &&\n      !containerElement.contains(event.target as Node)\n    ) {\n      overlayStore.close();\n    }\n  }\n\n  function setupClickOutside() {\n    if (typeof document !== \"undefined\") {\n      document.addEventListener(\"click\", handleClickOutside);\n    }\n  }\n\n  function cleanupClickOutside() {\n    if (typeof document !== \"undefined\") {\n      document.removeEventListener(\"click\", handleClickOutside);\n    }\n  }\n\n  $: if (isExpanded) {\n    setTimeout(setupClickOutside, 0);\n  } else {\n    cleanupClickOutside();\n  }\n\n  onDestroy(() => {\n    cleanupClickOutside();\n  });\n</script>\n\n<div class=\"pagination-controls\">\n  <div\n    class=\"pagination-per-page\"\n    class:active={isExpanded}\n    bind:this={containerElement}\n  >\n    <button\n      class=\"touchbar-trigger\"\n      class:active={isExpanded}\n      on:click={toggleExpanded}\n    >\n      {itemsPerPage} per page\n    </button>\n\n    {#if isExpanded}\n      <div\n        class=\"touchbar-full-overlay\"\n        bind:this={overlayElement}\n        on:click={() => overlayStore.close()}\n        on:keydown={(e) => e.key === \"Escape\" && overlayStore.close()}\n        role=\"dialog\"\n        aria-label=\"Pagination controls\"\n        tabindex=\"-1\"\n      >\n        <div class=\"touchbar-horizontal-options\">\n          {#each ITEMS_PER_PAGE_OPTIONS as option}\n            <button\n              class=\"touchbar-option\"\n              class:active={option === itemsPerPage}\n              on:click|stopPropagation={() => selectItemsPerPage(option)}\n            >\n              {option}\n            </button>\n          {/each}\n        </div>\n      </div>\n    {/if}\n  </div>\n\n  <div class=\"pagination\">\n    <button\n      class=\"btn-page\"\n      disabled={currentPage === 1}\n      on:click={() => changePage(1)}\n    >\n      ««\n    </button>\n    <button\n      class=\"btn-page\"\n      disabled={currentPage === 1}\n      on:click={() => changePage(currentPage - 1)}\n    >\n      «\n    </button>\n    <div class=\"page-info\">\n      <span>Page {currentPage} of {totalPages}</span>\n      <span class=\"results-info\">({totalResults} processes)</span>\n    </div>\n    <button\n      class=\"btn-page\"\n      disabled={currentPage === totalPages}\n      on:click={() => changePage(currentPage + 1)}\n    >\n      »\n    </button>\n    <button\n      class=\"btn-page\"\n      disabled={currentPage === totalPages}\n      on:click={() => changePage(totalPages)}\n    >\n      »»\n    </button>\n  </div>\n</div>\n\n<style>\n  .pagination-controls {\n    display: flex;\n    align-items: center;\n    gap: 12px;\n  }\n\n  .pagination-per-page {\n    display: flex;\n    align-items: center;\n    position: relative;\n  }\n\n  .touchbar-trigger {\n    padding: 6px 12px;\n    height: 28px;\n    font-size: 12px;\n    color: var(--text);\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.2s ease;\n    white-space: nowrap;\n    display: flex;\n    align-items: center;\n    box-sizing: border-box;\n  }\n\n  .touchbar-trigger:hover {\n    background-color: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .touchbar-trigger.active {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .touchbar-full-overlay {\n    position: absolute;\n    top: -0px;\n    height: 44px;\n    background: var(--mantle);\n    border: none;\n    border-radius: 0;\n    box-shadow: none;\n    z-index: 1000;\n    display: flex;\n    align-items: center;\n    padding: 0 12px;\n    gap: 12px;\n  }\n\n  .touchbar-horizontal-options {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    gap: 12px;\n    width: 100%;\n    overflow-x: auto;\n    overflow-y: hidden;\n    scrollbar-width: none;\n    -ms-overflow-style: none;\n  }\n\n  .touchbar-horizontal-options::-webkit-scrollbar {\n    display: none;\n  }\n\n  .touchbar-option {\n    padding: 0 12px;\n    height: 28px;\n    font-size: 12px;\n    color: var(--text);\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.15s ease;\n    white-space: nowrap;\n    flex-shrink: 0;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    min-width: fit-content;\n    box-sizing: border-box;\n    animation: optionSlideIn 0.2s ease-out;\n    animation-fill-mode: both;\n  }\n\n  .touchbar-option:nth-child(1) {\n    animation-delay: 0ms;\n  }\n  .touchbar-option:nth-child(2) {\n    animation-delay: 40ms;\n  }\n  .touchbar-option:nth-child(3) {\n    animation-delay: 80ms;\n  }\n  .touchbar-option:nth-child(4) {\n    animation-delay: 120ms;\n  }\n\n  @keyframes optionSlideIn {\n    from {\n      opacity: 0;\n      transform: translateY(-8px) scale(0.9);\n    }\n    to {\n      opacity: 1;\n      transform: translateY(0) scale(1);\n    }\n  }\n\n  .touchbar-option:hover:not(.disabled) {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .touchbar-option.active {\n    background: var(--blue);\n    color: var(--base);\n    border-color: var(--blue);\n  }\n\n  .pagination {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n  }\n\n  .btn-page {\n    padding: 6px 10px;\n    font-size: 12px;\n    color: var(--text);\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.2s ease;\n  }\n\n  .btn-page:hover:not(:disabled) {\n    background: var(--surface1);\n  }\n\n  .btn-page:disabled {\n    opacity: 0.5;\n    cursor: not-allowed;\n  }\n\n  .page-info {\n    font-size: 12px;\n    color: var(--subtext0);\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    flex-shrink: 0;\n  }\n\n  .page-info span {\n    display: block;\n  }\n\n  .results-info {\n    color: var(--overlay0);\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/toolbar/RefreshControls.svelte",
    "content": "<script lang=\"ts\">\n  import Fa from \"svelte-fa\";\n  import { faPlay, faPause } from \"@fortawesome/free-solid-svg-icons\";\n  import type { AppConfig } from \"$lib/types\";\n  import { settingsStore } from \"$lib/stores/index\";\n  import { overlayStore } from \"$lib/stores/overlay\";\n  import { REFRESH_RATE_OPTIONS } from \"$lib/constants\";\n  import { onDestroy } from \"svelte\";\n\n  export let refreshRate: number;\n  export let isFrozen: boolean;\n\n  let containerElement: HTMLDivElement;\n  let overlayElement: HTMLDivElement;\n\n  $: isExpanded = $overlayStore === \"refresh\";\n\n  function updateBehaviorConfig(key: keyof AppConfig[\"behavior\"], value: any) {\n    settingsStore.updateConfig({\n      behavior: {\n        ...$settingsStore.behavior,\n        [key]: value,\n      },\n    });\n  }\n\n  function selectRefreshRate(value: number) {\n    refreshRate = value;\n    updateBehaviorConfig(\"refreshRate\", refreshRate);\n    overlayStore.close();\n  }\n\n  function getCurrentLabel() {\n    return (\n      REFRESH_RATE_OPTIONS.find((opt) => opt.value === refreshRate)?.label ||\n      \"1s\"\n    );\n  }\n\n  function updateOverlayPosition() {\n    if (overlayElement && containerElement) {\n      const toolbarContent = containerElement.closest(\".toolbar-content\");\n      if (toolbarContent) {\n        const toolbarRect = toolbarContent.getBoundingClientRect();\n        const containerRect = containerElement.getBoundingClientRect();\n\n        const leftOffset = containerRect.left - toolbarRect.left;\n        const rightOffset = toolbarRect.right - containerRect.right;\n        const topOffset = containerRect.top - toolbarRect.top;\n\n        overlayElement.style.left = `-${leftOffset}px`;\n        overlayElement.style.right = `-${rightOffset}px`;\n        overlayElement.style.top = `-${topOffset}px`;\n      }\n    }\n  }\n\n  function toggleExpanded(event: Event) {\n    if (!isFrozen) {\n      event.stopPropagation();\n      if (isExpanded) {\n        overlayStore.close();\n      } else {\n        overlayStore.open(\"refresh\");\n        setTimeout(updateOverlayPosition, 0);\n      }\n    }\n  }\n\n  function handleClickOutside(event: MouseEvent) {\n    if (\n      isExpanded &&\n      containerElement &&\n      !containerElement.contains(event.target as Node)\n    ) {\n      overlayStore.close();\n    }\n  }\n\n  function setupClickOutside() {\n    if (typeof document !== \"undefined\") {\n      document.addEventListener(\"click\", handleClickOutside);\n    }\n  }\n\n  function cleanupClickOutside() {\n    if (typeof document !== \"undefined\") {\n      document.removeEventListener(\"click\", handleClickOutside);\n    }\n  }\n\n  $: if (isExpanded) {\n    setTimeout(setupClickOutside, 0);\n  } else {\n    cleanupClickOutside();\n  }\n\n  onDestroy(() => {\n    cleanupClickOutside();\n  });\n</script>\n\n<div class=\"refresh-controls\">\n  <div\n    class=\"refresh-rate\"\n    class:active={isExpanded}\n    bind:this={containerElement}\n  >\n    <button\n      class=\"touchbar-trigger\"\n      class:disabled={isFrozen}\n      class:active={isExpanded}\n      on:click={toggleExpanded}\n    >\n      {getCurrentLabel()}\n    </button>\n\n    {#if isExpanded}\n      <div\n        class=\"touchbar-full-overlay\"\n        bind:this={overlayElement}\n        on:click={() => overlayStore.close()}\n        on:keydown={(e) => e.key === \"Escape\" && overlayStore.close()}\n        role=\"dialog\"\n        aria-label=\"Refresh rate controls\"\n        tabindex=\"-1\"\n      >\n        <div class=\"touchbar-horizontal-options\">\n          {#each REFRESH_RATE_OPTIONS as option}\n            <button\n              class=\"touchbar-option\"\n              class:active={option.value === refreshRate}\n              on:click|stopPropagation={() => selectRefreshRate(option.value)}\n            >\n              {option.label}\n            </button>\n          {/each}\n        </div>\n      </div>\n    {/if}\n  </div>\n\n  <button\n    class=\"btn-action\"\n    class:frozen={isFrozen}\n    on:click={() => (isFrozen = !isFrozen)}\n    title={isFrozen ? \"Resume Updates\" : \"Pause Updates\"}\n  >\n    {#if isFrozen}\n      <Fa icon={faPlay} color=\"var(--red)\" />\n    {:else}\n      <Fa icon={faPause} color=\"var(--subtext0)\" />\n    {/if}\n  </button>\n</div>\n\n<style>\n  .refresh-controls {\n    display: flex;\n    gap: 8px;\n    align-items: center;\n  }\n\n  .refresh-controls :global(svg) {\n    font-size: 14px;\n    color: var(--subtext0);\n  }\n\n  .refresh-rate {\n    display: flex;\n    align-items: center;\n    position: relative;\n  }\n\n  .touchbar-trigger {\n    height: 28px;\n    padding: 0 12px;\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    background: var(--surface0);\n    color: var(--text);\n    font-size: 13px;\n    cursor: pointer;\n    transition: all 0.2s ease;\n    white-space: nowrap;\n  }\n\n  .touchbar-trigger:hover:not(.disabled) {\n    background-color: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .touchbar-trigger.active {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .touchbar-trigger.disabled {\n    opacity: 0.7;\n    cursor: not-allowed;\n  }\n\n  .touchbar-full-overlay {\n    position: absolute;\n    top: -0px;\n    height: 44px;\n    background: var(--mantle);\n    border: none;\n    border-radius: 0;\n    box-shadow: none;\n    z-index: 1000;\n    display: flex;\n    align-items: center;\n    padding: 0 12px;\n    gap: 12px;\n  }\n\n  .touchbar-horizontal-options {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    gap: 12px;\n    width: 100%;\n    overflow-x: auto;\n    overflow-y: hidden;\n    scrollbar-width: none;\n    -ms-overflow-style: none;\n  }\n\n  .touchbar-horizontal-options::-webkit-scrollbar {\n    display: none;\n  }\n\n  .touchbar-option {\n    padding: 0 12px;\n    height: 28px;\n    font-size: 12px;\n    color: var(--text);\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.15s ease;\n    white-space: nowrap;\n    flex-shrink: 0;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    min-width: fit-content;\n    box-sizing: border-box;\n    animation: optionSlideIn 0.2s ease-out;\n    animation-fill-mode: both;\n  }\n\n  .touchbar-option:nth-child(1) {\n    animation-delay: 0ms;\n  }\n  .touchbar-option:nth-child(2) {\n    animation-delay: 40ms;\n  }\n  .touchbar-option:nth-child(3) {\n    animation-delay: 80ms;\n  }\n  .touchbar-option:nth-child(4) {\n    animation-delay: 120ms;\n  }\n\n  @keyframes optionSlideIn {\n    from {\n      opacity: 0;\n      transform: translateY(-8px) scale(0.9);\n    }\n    to {\n      opacity: 1;\n      transform: translateY(0) scale(1);\n    }\n  }\n\n  .touchbar-option:hover:not(.disabled) {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .touchbar-option.active {\n    background: var(--blue);\n    color: var(--base);\n    border-color: var(--blue);\n  }\n\n  .btn-action {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    width: 28px;\n    height: 28px;\n    border: none;\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    color: var(--text);\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.2s ease;\n  }\n\n  .btn-action:hover {\n    background: var(--surface1);\n  }\n\n  .btn-action.frozen {\n    background: var(--yellow);\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/toolbar/SearchBox.svelte",
    "content": "<script lang=\"ts\">\n  import { overlayStore } from \"$lib/stores/overlay\";\n  import { onDestroy, onMount } from \"svelte\";\n\n  export let searchTerm: string;\n\n  let containerElement: HTMLDivElement;\n  let overlayElement: HTMLDivElement;\n  let searchInputElement: HTMLInputElement;\n  let placeholderIndex = 0;\n  let placeholderInterval: NodeJS.Timeout;\n\n  $: showHelp = $overlayStore === \"searchHelp\";\n  $: hasActiveSearch = searchTerm.trim().length > 0;\n\n  const searchExamples = [\n    {\n      query: \"systemd, dbus\",\n      description: \"Multiple terms (comma-separated)\",\n      type: \"multi\",\n    },\n    {\n      query: \"d$\",\n      description: \"Processes ending with 'd' (daemons)\",\n      type: \"regex\",\n    },\n    {\n      query: \"^kernel\",\n      description: \"Kernel processes\",\n      type: \"regex\",\n    },\n    {\n      query: \"ssh.*server\",\n      description: \"SSH server processes\",\n      type: \"regex\",\n    },\n    {\n      query: \"1234\",\n      description: \"Search by PID\",\n      type: \"pid\",\n    },\n    {\n      query: \"python, node, nginx\",\n      description: \"Find web/app server processes\",\n      type: \"multi\",\n    },\n    {\n      query: \"docker, containerd\",\n      description: \"Container processes\",\n      type: \"multi\",\n    },\n    {\n      query: \"gnome, plasma\",\n      description: \"Desktop environment processes\",\n      type: \"multi\",\n    },\n  ];\n\n  const placeholders = [\n    \"Search processes...\",\n    \"Try: systemd, dbus\",\n    \"Try: d$ (daemons)\",\n    \"Try: ^kernel (regex)\",\n    \"Search by name, command, or PID\",\n    \"Try: docker, nginx\",\n  ];\n\n  function rotatePlaceholder() {\n    placeholderIndex = (placeholderIndex + 1) % placeholders.length;\n  }\n\n  function updateOverlayPosition() {\n    if (overlayElement && containerElement) {\n      const toolbarContent = containerElement.closest(\".toolbar-content\");\n      if (toolbarContent) {\n        const toolbarRect = toolbarContent.getBoundingClientRect();\n        const containerRect = containerElement.getBoundingClientRect();\n\n        const leftOffset = containerRect.left - toolbarRect.left;\n        const rightOffset = toolbarRect.right - containerRect.right;\n        const topOffset = containerRect.top - toolbarRect.top;\n\n        overlayElement.style.left = `-${leftOffset}px`;\n        overlayElement.style.right = `-${rightOffset}px`;\n        overlayElement.style.top = `-${topOffset}px`;\n      }\n    }\n  }\n\n  function handleFocus() {\n    overlayStore.open(\"searchHelp\");\n    setTimeout(() => {\n      updateOverlayPosition();\n      // Focus the enhanced search input in the overlay\n      const overlayInput = overlayElement?.querySelector(\n        \".overlay-search-input\",\n      ) as HTMLInputElement;\n      if (overlayInput) {\n        overlayInput.focus();\n      }\n    }, 0);\n  }\n\n  function handleBlur(event: FocusEvent) {\n    // Small delay to allow clicking on examples\n    setTimeout(() => {\n      const activeElement = document.activeElement;\n      if (!containerElement?.contains(activeElement as Node)) {\n        overlayStore.close();\n      }\n    }, 150);\n  }\n\n  function useExample(example: string) {\n    searchTerm = example;\n    // Keep focus on the overlay search input\n    const overlayInput = overlayElement?.querySelector(\n      \".overlay-search-input\",\n    ) as HTMLInputElement;\n    if (overlayInput) {\n      overlayInput.focus();\n      // Position cursor at end\n      setTimeout(() => {\n        overlayInput.setSelectionRange(example.length, example.length);\n      }, 0);\n    }\n  }\n\n  function handleClickOutside(event: MouseEvent) {\n    if (\n      showHelp &&\n      containerElement &&\n      !containerElement.contains(event.target as Node)\n    ) {\n      overlayStore.close();\n    }\n  }\n\n  function setupClickOutside() {\n    if (typeof document !== \"undefined\") {\n      document.addEventListener(\"click\", handleClickOutside);\n    }\n  }\n\n  function cleanupClickOutside() {\n    if (typeof document !== \"undefined\") {\n      document.removeEventListener(\"click\", handleClickOutside);\n    }\n  }\n\n  $: if (showHelp) {\n    setTimeout(setupClickOutside, 0);\n  } else {\n    cleanupClickOutside();\n  }\n\n  onMount(() => {\n    // Start placeholder rotation\n    placeholderInterval = setInterval(rotatePlaceholder, 3000);\n  });\n\n  onDestroy(() => {\n    cleanupClickOutside();\n    if (placeholderInterval) {\n      clearInterval(placeholderInterval);\n    }\n  });\n</script>\n\n<div class=\"search-box\" bind:this={containerElement}>\n  <div class=\"search-input-wrapper\">\n    <input\n      type=\"text\"\n      placeholder={placeholders[placeholderIndex]}\n      bind:value={searchTerm}\n      bind:this={searchInputElement}\n      class=\"search-input\"\n      class:has-search={hasActiveSearch}\n      on:focus={handleFocus}\n      on:blur={handleBlur}\n    />\n    {#if searchTerm}\n      <button class=\"btn-clear\" on:click={() => (searchTerm = \"\")}>\n        Clear\n      </button>\n    {/if}\n  </div>\n\n  {#if showHelp}\n    <div\n      class=\"touchbar-full-overlay\"\n      bind:this={overlayElement}\n      role=\"dialog\"\n      aria-label=\"Search help overlay\"\n    >\n      <div class=\"search-help-content\">\n        <div class=\"enhanced-search-input\">\n          <input\n            type=\"text\"\n            placeholder={placeholders[placeholderIndex]}\n            bind:value={searchTerm}\n            bind:this={searchInputElement}\n            class=\"overlay-search-input\"\n            on:blur={handleBlur}\n            autocomplete=\"off\"\n          />\n          {#if searchTerm}\n            <button\n              class=\"overlay-clear-btn\"\n              on:click={() => (searchTerm = \"\")}\n            >\n              Clear\n            </button>\n          {/if}\n        </div>\n\n        <div class=\"help-sections\">\n          <div class=\"examples-section\">\n            <span class=\"section-label\">Examples:</span>\n            <div class=\"examples-grid\">\n              {#each searchExamples.slice(0, 5) as example}\n                <button\n                  class=\"example-query\"\n                  class:regex={example.type === \"regex\"}\n                  class:multi={example.type === \"multi\"}\n                  class:pid={example.type === \"pid\"}\n                  on:click|stopPropagation={() => useExample(example.query)}\n                  title={example.description}\n                >\n                  {example.query}\n                </button>\n              {/each}\n            </div>\n          </div>\n\n          <div class=\"regex-section\">\n            <span class=\"section-label\">Regex:</span>\n            <div class=\"regex-tips\">\n              <code>^</code><span>start</span>\n              <code>$</code><span>end</span>\n              <code>.*</code><span>any</span>\n              <code>\\d+</code><span>numbers</span>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  {/if}\n</div>\n\n<style>\n  .search-box {\n    width: 240px;\n    position: relative;\n  }\n\n  .search-input-wrapper {\n    position: relative;\n    display: flex;\n    gap: 8px;\n    align-items: center;\n  }\n\n  .search-input {\n    width: 100%;\n    height: 28px;\n    padding: 0 12px;\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    font-size: 12px;\n    background-color: var(--surface0);\n    color: var(--text);\n    transition: all 0.2s ease;\n    box-sizing: border-box;\n  }\n\n  .btn-clear {\n    position: absolute;\n    right: 4px;\n    top: 50%;\n    transform: translateY(-50%);\n    padding: 4px 8px;\n    font-size: 11px;\n    color: var(--subtext0);\n    background: var(--surface1);\n    border: none;\n    border-radius: 4px;\n    cursor: pointer;\n    transition: all 0.2s ease;\n  }\n\n  .btn-clear:hover {\n    background: var(--surface2);\n    color: var(--text);\n  }\n\n  .search-input:hover {\n    background-color: var(--surface1);\n  }\n\n  .search-input:focus {\n    outline: none;\n    border-color: var(--blue);\n    box-shadow: 0 0 0 2px color-mix(in srgb, var(--blue) 25%, transparent);\n  }\n\n  .search-input.has-search {\n    border-color: var(--blue);\n    background: var(--surface1);\n  }\n\n  .touchbar-full-overlay {\n    position: absolute;\n    top: -0px;\n    height: 44px;\n    background: var(--mantle);\n    border: none;\n    border-radius: 0;\n    box-shadow: none;\n    z-index: 1000;\n    display: flex;\n    align-items: center;\n    padding: 0 12px;\n    gap: 12px;\n    overflow-x: auto;\n    overflow-y: hidden;\n    scrollbar-width: none;\n    -ms-overflow-style: none;\n  }\n\n  .touchbar-full-overlay::-webkit-scrollbar {\n    display: none;\n  }\n\n  .search-help-content {\n    display: flex;\n    align-items: center;\n    gap: 24px;\n    width: 100%;\n    animation: slideIn 0.3s ease-out;\n  }\n\n  @keyframes slideIn {\n    from {\n      opacity: 0;\n      transform: translateY(-8px);\n    }\n    to {\n      opacity: 1;\n      transform: translateY(0);\n    }\n  }\n\n  .enhanced-search-input {\n    position: relative;\n    display: flex;\n    align-items: center;\n    flex-shrink: 0;\n    min-width: 300px;\n  }\n\n  .overlay-search-input {\n    width: 100%;\n    height: 32px;\n    padding: 0 16px;\n    padding-right: 80px;\n    border: 2px solid var(--blue);\n    border-radius: 8px;\n    font-size: 13px;\n    background-color: var(--surface0);\n    color: var(--text);\n    transition: all 0.2s ease;\n    box-sizing: border-box;\n    font-weight: 500;\n  }\n\n  .overlay-search-input:focus {\n    outline: none;\n    border-color: var(--blue);\n    box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 20%, transparent);\n  }\n\n  .overlay-clear-btn {\n    position: absolute;\n    right: 8px;\n    top: 50%;\n    transform: translateY(-50%);\n    padding: 4px 10px;\n    font-size: 11px;\n    color: var(--subtext0);\n    background: var(--surface1);\n    border: none;\n    border-radius: 4px;\n    cursor: pointer;\n    transition: all 0.2s ease;\n  }\n\n  .overlay-clear-btn:hover {\n    background: var(--surface2);\n    color: var(--text);\n  }\n\n  .help-sections {\n    display: flex;\n    align-items: center;\n    gap: 32px;\n    flex: 1;\n  }\n\n  .examples-section {\n    display: flex;\n    align-items: center;\n    gap: 12px;\n    flex-shrink: 0;\n  }\n\n  .section-label {\n    font-size: 12px;\n    font-weight: 500;\n    color: var(--subtext0);\n    flex-shrink: 0;\n  }\n\n  .examples-grid {\n    display: flex;\n    gap: 8px;\n    align-items: center;\n  }\n\n  .example-query {\n    padding: 4px 10px;\n    height: 26px;\n    font-size: 11px;\n    font-family: \"SF Mono\", \"Monaco\", \"Inconsolata\", \"Fira Code\", monospace;\n    color: var(--text);\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 4px;\n    cursor: pointer;\n    transition: all 0.15s ease;\n    white-space: nowrap;\n    display: flex;\n    align-items: center;\n    box-sizing: border-box;\n  }\n\n  .example-query:hover {\n    background: var(--surface1);\n    border-color: var(--blue);\n    transform: translateY(-1px);\n  }\n\n  .example-query.regex {\n    border-color: var(--yellow);\n    color: var(--yellow);\n  }\n\n  .example-query.multi {\n    border-color: var(--green);\n    color: var(--green);\n  }\n\n  .example-query.pid {\n    border-color: var(--blue);\n    color: var(--blue);\n  }\n\n  .regex-section {\n    display: flex;\n    align-items: center;\n    gap: 12px;\n    flex-shrink: 0;\n  }\n\n  .regex-tips {\n    display: flex;\n    gap: 8px;\n    align-items: center;\n  }\n\n  .regex-tips code {\n    font-size: 11px;\n    font-family: \"SF Mono\", \"Monaco\", \"Inconsolata\", \"Fira Code\", monospace;\n    background: var(--surface0);\n    color: var(--yellow);\n    padding: 3px 6px;\n    border-radius: 3px;\n    border: 1px solid var(--surface1);\n    margin-right: 2px;\n  }\n\n  .regex-tips span {\n    font-size: 10px;\n    color: var(--overlay0);\n    margin-right: 8px;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/toolbar/StatusFilter.svelte",
    "content": "<script lang=\"ts\">\n  import { STATUS_OPTIONS } from \"$lib/constants\";\n  import type { AppConfig } from \"$lib/types\";\n  import { settingsStore } from \"$lib/stores/index\";\n  import { overlayStore } from \"$lib/stores/overlay\";\n  import { onDestroy } from \"svelte\";\n\n  export let statusFilter: string = \"all\";\n\n  let containerElement: HTMLDivElement;\n  let overlayElement: HTMLDivElement;\n\n  $: isExpanded = $overlayStore === \"status\";\n\n  function updateBehaviorConfig(key: keyof AppConfig[\"behavior\"], value: any) {\n    settingsStore.updateConfig({\n      behavior: {\n        ...$settingsStore.behavior,\n        [key]: value,\n      },\n    });\n  }\n\n  function selectOption(value: string) {\n    statusFilter = value;\n    updateBehaviorConfig(\"defaultStatusFilter\", statusFilter);\n    overlayStore.close();\n  }\n\n  function getCurrentLabel() {\n    return (\n      STATUS_OPTIONS.find((opt) => opt.value === statusFilter)?.label ||\n      \"All Statuses\"\n    );\n  }\n\n  function updateOverlayPosition() {\n    if (overlayElement && containerElement) {\n      const toolbarContent = containerElement.closest(\".toolbar-content\");\n      if (toolbarContent) {\n        const toolbarRect = toolbarContent.getBoundingClientRect();\n        const containerRect = containerElement.getBoundingClientRect();\n\n        const leftOffset = containerRect.left - toolbarRect.left;\n        const rightOffset = toolbarRect.right - containerRect.right;\n        const topOffset = containerRect.top - toolbarRect.top;\n\n        overlayElement.style.left = `-${leftOffset}px`;\n        overlayElement.style.right = `-${rightOffset}px`;\n        overlayElement.style.top = `-${topOffset}px`;\n      }\n    }\n  }\n\n  function toggleExpanded(event: Event) {\n    event.stopPropagation();\n    if (isExpanded) {\n      overlayStore.close();\n    } else {\n      overlayStore.open(\"status\");\n      setTimeout(updateOverlayPosition, 0);\n    }\n  }\n\n  function handleClickOutside(event: MouseEvent) {\n    if (\n      isExpanded &&\n      containerElement &&\n      !containerElement.contains(event.target as Node)\n    ) {\n      overlayStore.close();\n    }\n  }\n\n  function setupClickOutside() {\n    if (typeof document !== \"undefined\") {\n      document.addEventListener(\"click\", handleClickOutside);\n    }\n  }\n\n  function cleanupClickOutside() {\n    if (typeof document !== \"undefined\") {\n      document.removeEventListener(\"click\", handleClickOutside);\n    }\n  }\n\n  $: if (isExpanded) {\n    setTimeout(setupClickOutside, 0);\n  } else {\n    cleanupClickOutside();\n  }\n\n  onDestroy(() => {\n    cleanupClickOutside();\n  });\n</script>\n\n<div\n  class=\"status-filter\"\n  class:active={isExpanded}\n  bind:this={containerElement}\n>\n  <button\n    class=\"touchbar-trigger\"\n    class:active={isExpanded}\n    on:click={toggleExpanded}\n  >\n    Status: {getCurrentLabel()}\n  </button>\n\n  {#if isExpanded}\n    <div\n      class=\"touchbar-full-overlay\"\n      bind:this={overlayElement}\n      on:click={() => overlayStore.close()}\n      on:keydown={(e) => e.key === \"Escape\" && overlayStore.close()}\n      role=\"dialog\"\n      aria-label=\"Status filter options\"\n      tabindex=\"-1\"\n    >\n      <div class=\"touchbar-horizontal-options\">\n        {#each STATUS_OPTIONS as option}\n          <button\n            class=\"touchbar-option\"\n            class:active={option.value === statusFilter}\n            on:click|stopPropagation={() => selectOption(option.value)}\n          >\n            {option.label}\n          </button>\n        {/each}\n      </div>\n    </div>\n  {/if}\n</div>\n\n<style>\n  .status-filter {\n    display: flex;\n    align-items: center;\n    position: relative;\n  }\n\n  .touchbar-trigger {\n    height: 28px;\n    padding: 0 12px;\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    background: var(--surface0);\n    color: var(--text);\n    font-size: 13px;\n    cursor: pointer;\n    transition: all 0.2s ease;\n    white-space: nowrap;\n  }\n\n  .touchbar-trigger:hover {\n    background-color: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .touchbar-trigger.active {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .touchbar-full-overlay {\n    position: absolute;\n    top: -0px;\n    height: 44px;\n    background: var(--mantle);\n    border: none;\n    border-radius: 0;\n    box-shadow: none;\n    z-index: 1000;\n    display: flex;\n    align-items: center;\n    padding: 0 12px;\n    gap: 12px;\n  }\n\n  .touchbar-horizontal-options {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    gap: 12px;\n    width: 100%;\n    overflow-x: auto;\n    overflow-y: hidden;\n    scrollbar-width: none;\n    -ms-overflow-style: none;\n  }\n\n  .touchbar-horizontal-options::-webkit-scrollbar {\n    display: none;\n  }\n\n  .touchbar-option {\n    padding: 0 12px;\n    height: 28px;\n    font-size: 12px;\n    color: var(--text);\n    background: var(--surface0);\n    border: 1px solid var(--surface1);\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.15s ease;\n    white-space: nowrap;\n    flex-shrink: 0;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    min-width: fit-content;\n    box-sizing: border-box;\n    animation: optionSlideIn 0.2s ease-out;\n    animation-fill-mode: both;\n  }\n\n  .touchbar-option:nth-child(1) {\n    animation-delay: 0ms;\n  }\n  .touchbar-option:nth-child(2) {\n    animation-delay: 40ms;\n  }\n  .touchbar-option:nth-child(3) {\n    animation-delay: 80ms;\n  }\n  .touchbar-option:nth-child(4) {\n    animation-delay: 120ms;\n  }\n  .touchbar-option:nth-child(5) {\n    animation-delay: 160ms;\n  }\n  .touchbar-option:nth-child(6) {\n    animation-delay: 200ms;\n  }\n\n  @keyframes optionSlideIn {\n    from {\n      opacity: 0;\n      transform: translateY(-8px) scale(0.9);\n    }\n    to {\n      opacity: 1;\n      transform: translateY(0) scale(1);\n    }\n  }\n\n  .touchbar-option:hover:not(.disabled) {\n    background: var(--surface1);\n    border-color: var(--blue);\n  }\n\n  .touchbar-option.active {\n    background: var(--blue);\n    color: var(--base);\n    border-color: var(--blue);\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/toolbar/ToolBar.svelte",
    "content": "<script lang=\"ts\">\n  import {\n    AppInfo,\n    SearchBox,\n    RefreshControls,\n    PaginationControls,\n    ColumnToggle,\n    FilterToggle,\n  } from \"$lib/components\";\n  import { overlayStore } from \"$lib/stores/overlay\";\n\n  export let searchTerm: string;\n  export let itemsPerPage: number;\n  export let currentPage: number;\n  export let totalPages: number;\n  export let totalResults: number;\n  export let columns: Array<{\n    id: string;\n    label: string;\n    visible: boolean;\n    required?: boolean;\n  }>;\n  export let refreshRate: number;\n  export let isFrozen: boolean;\n  export let filters: {\n    cpu: { operator: string; value: number; enabled: boolean };\n    ram: { operator: string; value: number; enabled: boolean };\n    runtime: { operator: string; value: number; enabled: boolean };\n    status: { values: string[]; enabled: boolean };\n  } = {\n    cpu: { operator: \">\", value: 50, enabled: false },\n    ram: { operator: \">\", value: 100, enabled: false },\n    runtime: { operator: \">\", value: 60, enabled: false },\n    status: { values: [], enabled: false },\n  };\n\n  $: isAnyOverlayOpen = $overlayStore !== null;\n  $: activeOverlayType = $overlayStore;\n</script>\n\n<div class=\"toolbar\">\n  <div class=\"toolbar-content\" class:overlay-mode={isAnyOverlayOpen}>\n    <div class:hidden={isAnyOverlayOpen && activeOverlayType !== \"searchHelp\"}>\n      <SearchBox bind:searchTerm />\n    </div>\n\n    <div class:hidden={isAnyOverlayOpen && activeOverlayType !== \"filters\"}>\n      <FilterToggle bind:filters />\n    </div>\n\n    <div class=\"toolbar-spacer\" class:hidden={isAnyOverlayOpen}></div>\n\n    <div class:hidden={isAnyOverlayOpen && activeOverlayType !== \"pagination\"}>\n      <PaginationControls\n        bind:itemsPerPage\n        bind:currentPage\n        {totalPages}\n        {totalResults}\n      />\n    </div>\n    <div class=\"toolbar-spacer\" class:hidden={isAnyOverlayOpen}></div>\n\n    <div class:hidden={isAnyOverlayOpen && activeOverlayType !== \"columns\"}>\n      <ColumnToggle {columns} />\n    </div>\n\n    <div class:hidden={isAnyOverlayOpen && activeOverlayType !== \"refresh\"}>\n      <RefreshControls bind:refreshRate bind:isFrozen />\n    </div>\n\n    <div class:hidden={isAnyOverlayOpen && activeOverlayType !== \"theme\"}>\n      <AppInfo />\n    </div>\n  </div>\n</div>\n\n<style>\n  .toolbar {\n    padding: 8px;\n    border-bottom: 1px solid var(--surface0);\n    background-color: var(--mantle);\n  }\n\n  .toolbar-content {\n    display: flex;\n    align-items: center;\n    gap: 12px;\n    padding: 0 12px;\n    min-width: max-content;\n    height: 44px;\n    position: relative;\n  }\n\n  .toolbar-content > div {\n    display: flex;\n    align-items: center;\n  }\n\n  .toolbar-content :global(.hidden) {\n    opacity: 0;\n    pointer-events: none;\n  }\n\n  .toolbar-spacer {\n    flex: 1;\n  }\n</style>\n"
  },
  {
    "path": "src/lib/components/toolbar/index.ts",
    "content": "export { default as ToolBar } from \"./ToolBar.svelte\";\nexport { default as SearchBox } from \"./SearchBox.svelte\";\nexport { default as StatusFilter } from \"./StatusFilter.svelte\";\nexport { default as PaginationControls } from \"./PaginationControls.svelte\";\nexport { default as ColumnToggle } from \"./ColumnToggle.svelte\";\nexport { default as RefreshControls } from \"./RefreshControls.svelte\";\nexport { default as FilterToggle } from \"./FilterToggle.svelte\";\n"
  },
  {
    "path": "src/lib/constants/index.ts",
    "content": "export const ASCII_ART = `\n███╗   ██╗███████╗ ██████╗ ██╗  ██╗████████╗ ██████╗ ██████╗ \n████╗  ██║██╔════╝██╔═══██╗██║  ██║╚══██╔══╝██╔═══██╗██╔══██╗\n██╔██╗ ██║█████╗  ██║   ██║███████║   ██║   ██║   ██║██████╔╝\n██║╚██╗██║██╔══╝  ██║   ██║██╔══██║   ██║   ██║   ██║██╔═══╝ \n██║ ╚████║███████╗╚██████╔╝██║  ██║   ██║   ╚██████╔╝██║     \n╚═╝  ╚═══╝╚══════╝ ╚═════╝ ╚═╝  ╚═╝   ╚═╝    ╚═════╝ ╚═╝     \n`;\n\nexport const APP_INFO = {\n  name: \"NeoHtop\",\n  developer: \"Abdenasser\",\n  github: \"https://github.com/Abdenasser/neohtop\",\n  stack: [\"Tauri\", \"Rust\", \"Svelte\", \"TypeScript\"],\n};\n\nexport const ITEMS_PER_PAGE_OPTIONS = [15, 25, 50, 100, 250, 500];\n\nexport const REFRESH_RATE_OPTIONS = [\n  { value: 2000, label: \"2s\" },\n  { value: 3000, label: \"3s\" },\n  { value: 5000, label: \"5s\" },\n  { value: 10000, label: \"10s\" },\n  { value: 30000, label: \"30s\" },\n];\n\nexport const STATUS_OPTIONS = [\n  { value: \"all\", label: \"All Statuses\" },\n  { value: \"running\", label: \"Running\" },\n  { value: \"sleeping\", label: \"Sleeping\" },\n  { value: \"idle\", label: \"Idle\" },\n  { value: \"unknown\", label: \"Unknown\" },\n];\n\nexport const THEME_GROUPS = [\n  {\n    label: \"Dark\",\n    themes: [\n      \"catppuccin\",\n      \"dracula\",\n      \"monokaiPro\",\n      \"tokyoNight\",\n      \"solarizedDark\",\n      \"ayuDark\",\n      \"ayuMirage\",\n    ],\n  },\n  {\n    label: \"Light\",\n    themes: [\"githubLight\", \"solarizedLight\", \"oneLight\", \"ayuLight\"],\n  },\n  {\n    label: \"Warm\",\n    themes: [\"gruvbox\"],\n  },\n  {\n    label: \"Cool\",\n    themes: [\"nord\", \"oneDark\"],\n  },\n  {\n    label: \"Fun\",\n    themes: [\"bubblegum\", \"rosePine\", \"cottonCandy\", \"synthwave\", \"candyfloss\"],\n  },\n  {\n    label: \"Retro\",\n    themes: [\"terminal\", \"amber\", \"ibmPC\"],\n  },\n  {\n    label: \"Accessibility\",\n    themes: [\"highContrast\"],\n  },\n];\n"
  },
  {
    "path": "src/lib/definitions/columns.ts",
    "content": "import type { Column } from \"$lib/types\";\nimport { formatMemorySize } from \"$lib/utils\";\n\nexport let column_definitions: Column[] = [\n  { id: \"name\", label: \"Process Name\", visible: true, required: true },\n  { id: \"pid\", label: \"PID\", visible: true, required: false },\n  {\n    id: \"status\",\n    label: \"Status\",\n    visible: true,\n  },\n  { id: \"user\", label: \"User\", visible: true },\n  {\n    id: \"cpu_usage\",\n    label: \"CPU %\",\n    visible: true,\n    format: (v) => v.toFixed(1) + \"%\",\n  },\n  {\n    id: \"memory_usage\",\n    label: \"RAM\",\n    visible: true,\n    format: (v) => (v / (1024 * 1024)).toFixed(1) + \" MB\",\n  },\n  {\n    id: \"virtual_memory\",\n    label: \"VIRT\",\n    visible: true,\n    format: (v) => formatMemorySize(v),\n  },\n  {\n    id: \"disk_usage\",\n    label: \"Disk I/O (R/W)\",\n    visible: true,\n    format: (v) => {\n      const readMB = (v[0] / (1024 * 1024)).toFixed(1);\n      const writeMB = (v[1] / (1024 * 1024)).toFixed(1);\n      return `${readMB}/${writeMB} MB`;\n    },\n  },\n  { id: \"ppid\", label: \"Parent PID\", visible: false },\n  { id: \"root\", label: \"Root\", visible: false },\n  { id: \"command\", label: \"Command\", visible: false },\n  { id: \"environ\", label: \"Environment Variables\", visible: false },\n  { id: \"session_id\", label: \"Session ID\", visible: false },\n  {\n    id: \"start_time\",\n    label: \"Start Time\",\n    visible: false,\n    format: (v) => new Date(v * 1000).toLocaleString(), // v is the time where the process was started (in seconds) from epoch\n  },\n  {\n    id: \"run_time\",\n    label: \"Run Time\",\n    visible: true,\n    format: (v) => {\n      const seconds = v; // v is the time the process has been running in seconds\n      const hours = Math.floor(seconds / 3600);\n      const minutes = Math.floor((seconds % 3600) / 60);\n      const remainingSeconds = seconds % 60;\n      return `${hours}h ${minutes}m ${remainingSeconds}s`; // Format as HH:MM:SS\n    },\n  },\n];\n"
  },
  {
    "path": "src/lib/definitions/index.ts",
    "content": "export * from \"./columns\";\nexport * from \"./settings\";\nexport * from \"./themes\";\n"
  },
  {
    "path": "src/lib/definitions/settings.ts",
    "content": "import type { AppConfig } from \"$lib/types\";\n\nexport const DEFAULT_CONFIG: AppConfig = {\n  appearance: {\n    columnVisibility: {\n      name: true,\n      pid: true,\n      status: true,\n      user: true,\n      cpu_usage: true,\n      memory_usage: true,\n      virtual_memory: true,\n      disk_usage: true,\n      ppid: false,\n      root: false,\n      command: false,\n      environ: false,\n      session_id: false,\n      start_time: false,\n      run_time: true,\n    },\n  },\n  behavior: {\n    itemsPerPage: 15,\n    refreshRate: 3000,\n    defaultStatusFilter: \"all\",\n  },\n};\n"
  },
  {
    "path": "src/lib/definitions/themes.ts",
    "content": "import type { Theme } from \"$lib/types\";\n\nexport const themes: Record<string, Theme> = {\n  catppuccin: {\n    name: \"catppuccin\",\n    label: \"Catppuccin\",\n    colors: {\n      base: \"#1e1e2e\",\n      mantle: \"#181825\",\n      crust: \"#11111b\",\n      text: \"#cdd6f4\",\n      subtext0: \"#a6adc8\",\n      subtext1: \"#bac2de\",\n      surface0: \"#313244\",\n      surface1: \"#45475a\",\n      surface2: \"#585b70\",\n      overlay0: \"#6c7086\",\n      overlay1: \"#7f849c\",\n      blue: \"#89b4fa\",\n      lavender: \"#b4befe\",\n      sapphire: \"#74c7ec\",\n      sky: \"#89dceb\",\n      red: \"#f38ba8\",\n      maroon: \"#eba0ac\",\n      peach: \"#fab387\",\n      yellow: \"#f9e2af\",\n      green: \"#a6e3a1\",\n      teal: \"#94e2d5\",\n    },\n  },\n  dracula: {\n    name: \"dracula\",\n    label: \"Dracula\",\n    colors: {\n      base: \"#282a36\",\n      mantle: \"#1e1f29\",\n      crust: \"#191a21\",\n      text: \"#f8f8f2\",\n      subtext0: \"#bfbfbf\",\n      subtext1: \"#e6e6e6\",\n      surface0: \"#44475a\",\n      surface1: \"#6272a4\",\n      surface2: \"#7970a9\",\n      overlay0: \"#6272a4\",\n      overlay1: \"#7970a9\",\n      blue: \"#8be9fd\",\n      lavender: \"#bd93f9\",\n      sapphire: \"#62d6e8\",\n      sky: \"#89ddff\",\n      red: \"#ff5555\",\n      maroon: \"#ff6e6e\",\n      peach: \"#ffb86c\",\n      yellow: \"#f1fa8c\",\n      green: \"#50fa7b\",\n      teal: \"#8be9fd\",\n    },\n  },\n  monokaiPro: {\n    name: \"monokaiPro\",\n    label: \"Monokai Pro\",\n    colors: {\n      base: \"#2d2a2e\",\n      mantle: \"#221f22\",\n      crust: \"#1b1b1b\",\n      text: \"#fcfcfa\",\n      subtext0: \"#939293\",\n      subtext1: \"#c1c0c0\",\n      surface0: \"#403e41\",\n      surface1: \"#565457\",\n      surface2: \"#69676c\",\n      overlay0: \"#727072\",\n      overlay1: \"#848486\",\n      blue: \"#78dce8\",\n      lavender: \"#ab9df2\",\n      sapphire: \"#66d9ef\",\n      sky: \"#78dce8\",\n      red: \"#ff6188\",\n      maroon: \"#ff6188\",\n      peach: \"#fc9867\",\n      yellow: \"#ffd866\",\n      green: \"#a9dc76\",\n      teal: \"#78dce8\",\n    },\n  },\n  tokyoNight: {\n    name: \"tokyoNight\",\n    label: \"Tokyo Night\",\n    colors: {\n      base: \"#1a1b26\",\n      mantle: \"#16161e\",\n      crust: \"#13131a\",\n      text: \"#a9b1d6\",\n      subtext0: \"#9aa5ce\",\n      subtext1: \"#9aa5ce\",\n      surface0: \"#232433\",\n      surface1: \"#2a2b3d\",\n      surface2: \"#32344a\",\n      overlay0: \"#565f89\",\n      overlay1: \"#6b7089\",\n      blue: \"#7aa2f7\",\n      lavender: \"#bb9af7\",\n      sapphire: \"#7dcfff\",\n      sky: \"#7dcfff\",\n      red: \"#f7768e\",\n      maroon: \"#ff9e64\",\n      peach: \"#ff9e64\",\n      yellow: \"#e0af68\",\n      green: \"#9ece6a\",\n      teal: \"#2ac3de\",\n    },\n  },\n  gruvbox: {\n    name: \"gruvbox\",\n    label: \"Gruvbox Dark\",\n    colors: {\n      base: \"#282828\",\n      mantle: \"#1d2021\",\n      crust: \"#1b1b1b\",\n      text: \"#ebdbb2\",\n      subtext0: \"#a89984\",\n      subtext1: \"#bdae93\",\n      surface0: \"#3c3836\",\n      surface1: \"#504945\",\n      surface2: \"#665c54\",\n      overlay0: \"#7c6f64\",\n      overlay1: \"#928374\",\n      blue: \"#83a598\",\n      lavender: \"#d3869b\",\n      sapphire: \"#83a598\",\n      sky: \"#8ec07c\",\n      red: \"#fb4934\",\n      maroon: \"#cc241d\",\n      peach: \"#fe8019\",\n      yellow: \"#fabd2f\",\n      green: \"#b8bb26\",\n      teal: \"#8ec07c\",\n    },\n  },\n  nord: {\n    name: \"nord\",\n    label: \"Nord\",\n    colors: {\n      base: \"#2e3440\",\n      mantle: \"#272c36\",\n      crust: \"#242933\",\n      text: \"#eceff4\",\n      subtext0: \"#d8dee9\",\n      subtext1: \"#e5e9f0\",\n      surface0: \"#3b4252\",\n      surface1: \"#434c5e\",\n      surface2: \"#4c566a\",\n      overlay0: \"#616e88\",\n      overlay1: \"#7b88a1\",\n      blue: \"#88c0d0\",\n      lavender: \"#b48ead\",\n      sapphire: \"#81a1c1\",\n      sky: \"#88c0d0\",\n      red: \"#bf616a\",\n      maroon: \"#d08770\",\n      peach: \"#d08770\",\n      yellow: \"#ebcb8b\",\n      green: \"#a3be8c\",\n      teal: \"#8fbcbb\",\n    },\n  },\n  oneDark: {\n    name: \"oneDark\",\n    label: \"One Dark\",\n    colors: {\n      base: \"#282c34\",\n      mantle: \"#21252b\",\n      crust: \"#1b1f23\",\n      text: \"#abb2bf\",\n      subtext0: \"#828997\",\n      subtext1: \"#9da5b4\",\n      surface0: \"#31353f\",\n      surface1: \"#393f4a\",\n      surface2: \"#4b5263\",\n      overlay0: \"#636d83\",\n      overlay1: \"#767d8d\",\n      blue: \"#61afef\",\n      lavender: \"#c678dd\",\n      sapphire: \"#56b6c2\",\n      sky: \"#56b6c2\",\n      red: \"#e06c75\",\n      maroon: \"#be5046\",\n      peach: \"#d19a66\",\n      yellow: \"#e5c07b\",\n      green: \"#98c379\",\n      teal: \"#56b6c2\",\n    },\n  },\n  highContrast: {\n    name: \"highContrast\",\n    label: \"High Contrast\",\n    colors: {\n      base: \"#000000\", // Pure black background\n      mantle: \"#0a0a0a\", // Slightly lighter black for layering\n      crust: \"#141414\", // Even lighter black for depth\n      text: \"#ffffff\", // Pure white text\n      subtext0: \"#e0e0e0\", // Very light grey for secondary text\n      subtext1: \"#f0f0f0\", // Almost white for important secondary text\n      surface0: \"#1a1a1a\", // Dark surface for contrast\n      surface1: \"#2a2a2a\", // Lighter surface for hover states\n      surface2: \"#3a3a3a\", // Even lighter surface for active states\n      overlay0: \"#4a4a4a\", // Medium grey for overlays\n      overlay1: \"#5a5a5a\", // Lighter grey for overlay hover states\n      blue: \"#00ffff\", // Cyan for primary actions\n      lavender: \"#ff00ff\", // Magenta for accents\n      sapphire: \"#00ccff\", // Bright blue for links\n      sky: \"#00ffee\", // Bright cyan for highlights\n      red: \"#ff0000\", // Pure red for errors/warnings\n      maroon: \"#ff3333\", // Lighter red for secondary warnings\n      peach: \"#ffaa00\", // Bright orange for notifications\n      yellow: \"#ffff00\", // Pure yellow for important highlights\n      green: \"#00ff00\", // Pure green for success states\n      teal: \"#00ffcc\", // Bright teal for special actions\n    },\n  },\n  githubLight: {\n    name: \"githubLight\",\n    label: \"GitHub Light\",\n    colors: {\n      base: \"#ffffff\",\n      mantle: \"#f6f8fa\",\n      crust: \"#eaeef2\",\n      text: \"#24292f\",\n      subtext0: \"#57606a\",\n      subtext1: \"#6e7781\",\n      surface0: \"#f3f6fa\",\n      surface1: \"#eaeef2\",\n      surface2: \"#d0d7de\",\n      overlay0: \"#8c959f\",\n      overlay1: \"#6e7781\",\n      blue: \"#0969da\",\n      lavender: \"#8250df\",\n      sapphire: \"#0550ae\",\n      sky: \"#218bff\",\n      red: \"#cf222e\",\n      maroon: \"#a40e26\",\n      peach: \"#bc4c00\",\n      yellow: \"#9a6700\",\n      green: \"#1a7f37\",\n      teal: \"#0969da\",\n    },\n  },\n  solarizedLight: {\n    name: \"solarizedLight\",\n    label: \"Solarized Light\",\n    colors: {\n      base: \"#fdf6e3\",\n      mantle: \"#eee8d5\",\n      crust: \"#e4dcc9\",\n      text: \"#657b83\",\n      subtext0: \"#839496\",\n      subtext1: \"#93a1a1\",\n      surface0: \"#f7f2e4\",\n      surface1: \"#eee8d5\",\n      surface2: \"#dcd4c4\",\n      overlay0: \"#93a1a1\",\n      overlay1: \"#839496\",\n      blue: \"#268bd2\",\n      lavender: \"#6c71c4\",\n      sapphire: \"#2aa198\",\n      sky: \"#2aa198\",\n      red: \"#dc322f\",\n      maroon: \"#cb4b16\",\n      peach: \"#cb4b16\",\n      yellow: \"#b58900\",\n      green: \"#859900\",\n      teal: \"#2aa198\",\n    },\n  },\n  solarizedDark: {\n    name: \"solarizedDark\",\n    label: \"Solarized Dark\",\n    colors: {\n      base: \"#002b36\",\n      mantle: \"#073642\",\n      crust: \"#0A4C5C\",\n      text: \"#839496\",\n      subtext0: \"#657b83\",\n      subtext1: \"#586e75\",\n      surface0: \"#00313D\",\n      surface1: \"#073642\",\n      surface2: \"#083C49\",\n      overlay0: \"#586e75\",\n      overlay1: \"#657b83\",\n      blue: \"#268bd2\",\n      lavender: \"#6c71c4\",\n      sapphire: \"#2aa198\",\n      sky: \"#2aa198\",\n      red: \"#dc322f\",\n      maroon: \"#cb4b16\",\n      peach: \"#cb4b16\",\n      yellow: \"#b58900\",\n      green: \"#859900\",\n      teal: \"#2aa198\",\n    },\n  },\n  oneLight: {\n    name: \"oneLight\",\n    label: \"One Light\",\n    colors: {\n      base: \"#fafafa\",\n      mantle: \"#f0f0f0\",\n      crust: \"#e5e5e5\",\n      text: \"#383a42\",\n      subtext0: \"#4f525e\",\n      subtext1: \"#696c77\",\n      surface0: \"#f2f2f2\",\n      surface1: \"#e5e5e5\",\n      surface2: \"#d4d4d4\",\n      overlay0: \"#a0a1a7\",\n      overlay1: \"#696c77\",\n      blue: \"#4078f2\",\n      lavender: \"#a626a4\",\n      sapphire: \"#0184bc\",\n      sky: \"#0997b3\",\n      red: \"#e45649\",\n      maroon: \"#ca1243\",\n      peach: \"#d75f00\",\n      yellow: \"#c18401\",\n      green: \"#50a14f\",\n      teal: \"#0184bc\",\n    },\n  },\n  bubblegum: {\n    name: \"bubblegum\",\n    label: \"Bubblegum\",\n    colors: {\n      base: \"#ff9ac1\", // Light pink background\n      mantle: \"#ffa7cc\", // Slightly darker pink\n      crust: \"#ffb4d8\", // Even darker pink for depth\n      text: \"#2d1c2d\", // Dark purple text\n      subtext0: \"#4b384b\", // Medium purple for secondary text\n      subtext1: \"#5c465c\", // Lighter purple for tertiary text\n      surface0: \"#ffc1e0\", // Light pink surface\n      surface1: \"#ffcee7\", // Lighter pink surface\n      surface2: \"#ffdaf0\", // Even lighter pink surface\n      overlay0: \"#7e5c7e\", // Muted purple overlay\n      overlay1: \"#6e4f6e\", // Darker purple overlay\n      blue: \"#7287fd\", // Soft blue\n      lavender: \"#b4befe\", // Soft lavender\n      sapphire: \"#89dceb\", // Soft cyan\n      sky: \"#89dceb\", // Matching cyan\n      red: \"#ff8089\", // Soft red\n      maroon: \"#ff9999\", // Soft maroon\n      peach: \"#ffb4a1\", // Soft peach\n      yellow: \"#ffe5a0\", // Soft yellow\n      green: \"#a6e3a1\", // Soft green\n      teal: \"#94e2d5\", // Soft teal\n    },\n  },\n  rosePine: {\n    name: \"rosePine\",\n    label: \"Rosé Pine\",\n    colors: {\n      base: \"#191724\", // Deep purple base\n      mantle: \"#1f1d2e\", // Slightly lighter purple\n      crust: \"#26233a\", // Even lighter purple\n      text: \"#e0def4\", // Soft white text\n      subtext0: \"#908caa\", // Muted purple text\n      subtext1: \"#6e6a86\", // Darker muted text\n      surface0: \"#2a2837\", // Surface purple\n      surface1: \"#343145\", // Lighter surface\n      surface2: \"#3e3b54\", // Even lighter surface\n      overlay0: \"#524f67\", // Overlay purple\n      overlay1: \"#6e6a86\", // Lighter overlay\n      blue: \"#9ccfd8\", // Soft blue\n      lavender: \"#c4a7e7\", // Soft lavender\n      sapphire: \"#31748f\", // Deep blue\n      sky: \"#9ccfd8\", // Light blue\n      red: \"#eb6f92\", // Soft pink\n      maroon: \"#ebbcba\", // Soft rose\n      peach: \"#f6c177\", // Soft peach\n      yellow: \"#f6c177\", // Gold\n      green: \"#31748f\", // Sage\n      teal: \"#9ccfd8\", // Soft teal\n    },\n  },\n  cottonCandy: {\n    name: \"cottonCandy\",\n    label: \"Cotton Candy\",\n    colors: {\n      base: \"#f5d1eb\", // Light pink\n      mantle: \"#f7d7ee\", // Slightly darker pink\n      crust: \"#fae1f3\", // Even darker pink\n      text: \"#2d0c3a\", // Deep purple text\n      subtext0: \"#4a1259\", // Medium purple text\n      subtext1: \"#671878\", // Light purple text\n      surface0: \"#f9def1\", // Surface pink\n      surface1: \"#fde9f5\", // Lighter surface\n      surface2: \"#fff2fa\", // Even lighter surface\n      overlay0: \"#b87dd3\", // Purple overlay\n      overlay1: \"#9c5fb8\", // Darker overlay\n      blue: \"#79c7ff\", // Baby blue\n      lavender: \"#d5a6ff\", // Soft purple\n      sapphire: \"#7cb8ff\", // Light blue\n      sky: \"#89dcff\", // Bright blue\n      red: \"#ff9ed2\", // Soft pink\n      maroon: \"#ff8ac4\", // Darker pink\n      peach: \"#ffb2c7\", // Peachy pink\n      yellow: \"#ffffc2\", // Pastel yellow\n      green: \"#b6ffd7\", // Mint green\n      teal: \"#89ffea\", // Turquoise\n    },\n  },\n  synthwave: {\n    name: \"synthwave\",\n    label: \"Synthwave\",\n    colors: {\n      base: \"#2b213a\", // Deep purple\n      mantle: \"#2f2444\", // Slightly lighter purple\n      crust: \"#33274f\", // Even lighter purple\n      text: \"#ff7edb\", // Neon pink text\n      subtext0: \"#e58ee0\", // Softer pink text\n      subtext1: \"#cb9ee6\", // Lavender text\n      surface0: \"#392662\", // Surface purple\n      surface1: \"#443773\", // Lighter surface\n      surface2: \"#504785\", // Even lighter surface\n      overlay0: \"#625997\", // Purple overlay\n      overlay1: \"#7267aa\", // Lighter overlay\n      blue: \"#36f9f6\", // Cyan\n      lavender: \"#ff7edb\", // Pink\n      sapphire: \"#72f1b8\", // Mint\n      sky: \"#36f9f6\", // Bright cyan\n      red: \"#fe4450\", // Hot red\n      maroon: \"#ff558f\", // Hot pink\n      peach: \"#ff8b39\", // Orange\n      yellow: \"#fede5d\", // Yellow\n      green: \"#72f1b8\", // Neon green\n      teal: \"#36f9f6\", // Bright teal\n    },\n  },\n  candyfloss: {\n    name: \"candyfloss\",\n    label: \"Candyfloss\",\n    colors: {\n      base: \"#f8e2ff\", // Light purple\n      mantle: \"#ffe2f8\", // Pink tint\n      crust: \"#ffe9f3\", // Lighter pink\n      text: \"#5c1b99\", // Deep purple text\n      subtext0: \"#7a3aaf\", // Medium purple text\n      subtext1: \"#944bc6\", // Light purple text\n      surface0: \"#ffeaf8\", // Surface pink\n      surface1: \"#fff2fb\", // Lighter surface\n      surface2: \"#fff7fd\", // Even lighter surface\n      overlay0: \"#d59bff\", // Purple overlay\n      overlay1: \"#c77dff\", // Darker overlay\n      blue: \"#79baff\", // Soft blue\n      lavender: \"#cc8fff\", // Light purple\n      sapphire: \"#85a5ff\", // Periwinkle\n      sky: \"#8aceff\", // Light blue\n      red: \"#ff8fab\", // Soft red\n      maroon: \"#ff7fa6\", // Pink\n      peach: \"#ffb2c7\", // Peach\n      yellow: \"#fff3b2\", // Soft yellow\n      green: \"#b8ffda\", // Mint\n      teal: \"#8affef\", // Aqua\n    },\n  },\n  terminal: {\n    name: \"terminal\",\n    label: \"Green Terminal\",\n    colors: {\n      base: \"#0D1117\", // Deep black background\n      mantle: \"#161B22\", // Slightly lighter black\n      crust: \"#1B2127\", // Terminal border color\n      text: \"#00FF00\", // Classic terminal green\n      subtext0: \"#00D700\", // Dimmer green\n      subtext1: \"#00BB00\", // Even dimmer green\n      surface0: \"#1C2128\", // Slightly lifted surface\n      surface1: \"#21262D\", // Terminal input area\n      surface2: \"#282E35\", // Selected area\n      overlay0: \"#008800\", // Darker green for overlays\n      overlay1: \"#006600\", // Even darker green\n      blue: \"#00FF00\", // Keep everything in green shades\n      lavender: \"#00FF66\", // Slight variation\n      sapphire: \"#00DD88\", // Another variation\n      sky: \"#00FFBB\", // Lighter green\n      red: \"#FF0000\", // Error red (keep for errors)\n      maroon: \"#AA0000\", // Darker error\n      peach: \"#00FF99\", // Another green variation\n      yellow: \"#FFFF00\", // Warning yellow (keep for warnings)\n      green: \"#00FF00\", // Main green\n      teal: \"#00FFCC\", // Cyan-ish green\n    },\n  },\n  amber: {\n    name: \"amber\",\n    label: \"Amber Terminal\",\n    colors: {\n      base: \"#0D0904\", // Deep black with amber tint\n      mantle: \"#160E06\", // Slightly lighter black\n      crust: \"#1B1109\", // Terminal border color\n      text: \"#FFB000\", // Classic amber\n      subtext0: \"#CC8800\", // Dimmer amber\n      subtext1: \"#995500\", // Even dimmer amber\n      surface0: \"#1C1409\", // Slightly lifted surface\n      surface1: \"#211909\", // Terminal input area\n      surface2: \"#281E0A\", // Selected area\n      overlay0: \"#663300\", // Darker amber for overlays\n      overlay1: \"#442200\", // Even darker amber\n      blue: \"#FFB000\", // Keep everything in amber shades\n      lavender: \"#FFAA00\", // Slight variation\n      sapphire: \"#FF9500\", // Another variation\n      sky: \"#FFB000\", // Main amber\n      red: \"#FF3300\", // Error red (keep for errors)\n      maroon: \"#CC3300\", // Darker error\n      peach: \"#FFAA55\", // Lighter amber\n      yellow: \"#FFDD00\", // Warning yellow\n      green: \"#FFB000\", // Main amber\n      teal: \"#FFC000\", // Lighter amber\n    },\n  },\n  ibmPC: {\n    name: \"ibmPC\",\n    label: \"IBM PC\",\n    colors: {\n      base: \"#000000\", // Classic black background\n      mantle: \"#0A0A0A\", // Slightly lighter black\n      crust: \"#141414\", // Border color\n      text: \"#AAAAAA\", // Light gray text\n      subtext0: \"#888888\", // Dimmer text\n      subtext1: \"#666666\", // Even dimmer text\n      surface0: \"#1C1C1C\", // Slightly lifted surface\n      surface1: \"#212121\", // Input area\n      surface2: \"#282828\", // Selected area\n      overlay0: \"#444444\", // Overlay\n      overlay1: \"#333333\", // Darker overlay\n      blue: \"#5555FF\", // CGA blue\n      lavender: \"#FF55FF\", // CGA magenta\n      sapphire: \"#5555FF\", // Another blue\n      sky: \"#55FFFF\", // CGA cyan\n      red: \"#FF5555\", // CGA red\n      maroon: \"#AA0000\", // Darker red\n      peach: \"#FF5555\", // Another red shade\n      yellow: \"#FFFF55\", // CGA yellow\n      green: \"#55FF55\", // CGA green\n      teal: \"#55FFFF\", // Another cyan\n    },\n  },\n  glassy: {\n    name: \"glassy\",\n    label: \"Glassy\",\n    colors: {\n      base: \"#1e1e2e\",\n      mantle: \"#181825\",\n      crust: \"#11111b\",\n      text: \"#cdd6f4\",\n      subtext0: \"#a6adc8\",\n      subtext1: \"#bac2de\",\n      surface0: \"#313244\",\n      surface1: \"#45475a\",\n      surface2: \"#585b70\",\n      overlay0: \"#6c7086\",\n      overlay1: \"#7f849c\",\n      blue: \"#89b4fa\",\n      lavender: \"#b4befe\",\n      sapphire: \"#74c7ec\",\n      sky: \"#89dceb\",\n      red: \"#f38ba8\",\n      maroon: \"#eba0ac\",\n      peach: \"#fab387\",\n      yellow: \"#f9e2af\",\n      green: \"#a6e3a1\",\n      teal: \"#94e2d5\",\n    },\n  },\n  ayuDark: {\n    name: \"ayuDark\",\n    label: \"Ayu Dark\",\n    colors: {\n      base: \"#0D1017\",\n      mantle: \"#131721\",\n      crust: \"#232834\",\n      text: \"#BFBDB6\",\n      subtext0: \"#707a8c\",\n      subtext1: \"#8b939e\",\n      surface0: \"#0f1419\",\n      surface1: \"#131721\",\n      surface2: \"#212733\",\n      overlay0: \"#E6B450\",\n      overlay1: \"#434c5e\",\n      blue: \"#36a3d9\",\n      lavender: \"#d2a8ff\",\n      sapphire: \"#0f958a\",\n      sky: \"#c9d1d9\",\n      red: \"#D95757\",\n      maroon: \"#e06c75\",\n      peach: \"#f07178\",\n      yellow: \"#ffb454\",\n      green: \"#b8cc52\",\n      teal: \"#95e6cb\",\n    },\n  },\n  ayuMirage: {\n    name: \"ayuMirage\",\n    label: \"Ayu Mirage\",\n    colors: {\n      base: \"#242936\",\n      mantle: \"#1A1F29\",\n      crust: \"#232834\",\n      text: \"#CCCAC2\",\n      subtext0: \"#707a8c\",\n      subtext1: \"#8b939e\",\n      surface0: \"#0f1419\",\n      surface1: \"#131721\",\n      surface2: \"#212733\",\n      overlay0: \"#FFCC66\",\n      overlay1: \"#434c5e\",\n      blue: \"#36a3d9\",\n      lavender: \"#d2a8ff\",\n      sapphire: \"#0f958a\",\n      sky: \"#c9d1d9\",\n      red: \"#FF6666\",\n      maroon: \"#e06c75\",\n      peach: \"#f07178\",\n      yellow: \"#ffb454\",\n      green: \"#b8cc52\",\n      teal: \"#95e6cb\",\n    },\n  },\n  ayuLight: {\n    name: \"ayuLight\",\n    label: \"Ayu Light\",\n    colors: {\n      base: \"#FCFCFC\",\n      mantle: \"#8A91991A\",\n      crust: \"#eaeef2\",\n      text: \"#5C6166\",\n      subtext0: \"#57606a\",\n      subtext1: \"#6e7781\",\n      surface0: \"#f3f6fa\",\n      surface1: \"#eaeef2\",\n      surface2: \"#d0d7de\",\n      overlay0: \"#FFAA33\",\n      overlay1: \"#6e7781\",\n      blue: \"#0969da\",\n      lavender: \"#8250df\",\n      sapphire: \"#0550ae\",\n      sky: \"#218bff\",\n      red: \"#E65050\",\n      maroon: \"#a40e26\",\n      peach: \"#bc4c00\",\n      yellow: \"#9a6700\",\n      green: \"#1a7f37\",\n      teal: \"#0969da\",\n    },\n  },\n};\n"
  },
  {
    "path": "src/lib/stores/index.ts",
    "content": "export * from \"./processes\";\nexport * from \"./theme\";\nexport * from \"./settings\";\nexport * from \"./overlay\";\n"
  },
  {
    "path": "src/lib/stores/overlay.ts",
    "content": "import { writable } from \"svelte/store\";\n\ntype OverlayType =\n  | \"pagination\"\n  | \"refresh\"\n  | \"columns\"\n  | \"theme\"\n  | \"searchHelp\"\n  | \"filters\"\n  | \"status\"\n  | null;\n\nfunction createOverlayStore() {\n  const { subscribe, set } = writable<OverlayType>(null);\n\n  return {\n    subscribe,\n    open: (overlayType: OverlayType) => set(overlayType),\n    close: () => set(null),\n    isOpen: (overlayType: OverlayType) => {\n      let currentValue: OverlayType = null;\n      subscribe((value) => (currentValue = value))();\n      return currentValue === overlayType;\n    },\n  };\n}\n\nexport const overlayStore = createOverlayStore();\nexport default overlayStore;\n"
  },
  {
    "path": "src/lib/stores/processes.ts",
    "content": "import { writable, derived } from \"svelte/store\";\nimport type { Process, SystemStats } from \"$lib/types\";\nimport { invoke } from \"@tauri-apps/api/core\";\n\ninterface ProcessStore {\n  processes: Process[];\n  systemStats: SystemStats | null;\n  error: string | null;\n  isLoading: boolean;\n  searchTerm: string;\n  currentPage: number;\n  pinnedProcesses: Set<string>;\n  selectedProcess: Process | null;\n  showInfoModal: boolean;\n  showConfirmModal: boolean;\n  processToKill: Process | null;\n  isKilling: boolean;\n  isFrozen: boolean;\n  selectedProcessPid: number | null;\n  sortConfig: {\n    field: keyof Process;\n    direction: \"asc\" | \"desc\";\n  };\n}\n\nconst initialState: ProcessStore = {\n  processes: [],\n  systemStats: null,\n  error: null,\n  isLoading: true,\n  searchTerm: \"\",\n  currentPage: 1,\n  pinnedProcesses: new Set(),\n  selectedProcess: null,\n  showInfoModal: false,\n  showConfirmModal: false,\n  processToKill: null,\n  isKilling: false,\n  isFrozen: false,\n  selectedProcessPid: null,\n  sortConfig: {\n    field: \"cpu_usage\",\n    direction: \"desc\",\n  },\n};\n\nfunction createProcessStore() {\n  const { subscribe, set, update } = writable<ProcessStore>(initialState);\n\n  // Define all methods first\n  const setIsLoading = (isLoading: boolean) =>\n    update((state) => ({ ...state, isLoading }));\n\n  const getProcesses = async () => {\n    try {\n      const result = await invoke<[Process[], SystemStats]>(\"get_processes\");\n      update((state) => {\n        let updatedSelectedProcess = state.selectedProcess;\n        if (state.selectedProcessPid) {\n          updatedSelectedProcess =\n            result[0].find((p) => p.pid === state.selectedProcessPid) || null;\n        }\n\n        return {\n          ...state,\n          processes: result[0],\n          systemStats: result[1],\n          error: null,\n          selectedProcess: updatedSelectedProcess,\n        };\n      });\n    } catch (e: unknown) {\n      update((state) => ({\n        ...state,\n        error: e instanceof Error ? e.message : String(e),\n      }));\n    }\n  };\n\n  const killProcess = async (pid: number) => {\n    try {\n      update((state) => ({ ...state, isKilling: true }));\n      const success = await invoke<boolean>(\"kill_process\", { pid });\n      if (success) {\n        await getProcesses();\n      } else {\n        throw new Error(\"Failed to kill process\");\n      }\n    } catch (e: unknown) {\n      update((state) => ({\n        ...state,\n        error: e instanceof Error ? e.message : String(e),\n      }));\n    } finally {\n      update((state) => ({ ...state, isKilling: false }));\n    }\n  };\n\n  const toggleSort = (field: keyof Process) => {\n    update((state) => ({\n      ...state,\n      sortConfig: {\n        field,\n        direction:\n          state.sortConfig.field === field\n            ? state.sortConfig.direction === \"asc\"\n              ? \"desc\"\n              : \"asc\"\n            : \"desc\",\n      },\n    }));\n  };\n\n  const togglePin = (command: string) => {\n    update((state) => {\n      const newPinnedProcesses = new Set(state.pinnedProcesses);\n      if (newPinnedProcesses.has(command)) {\n        newPinnedProcesses.delete(command);\n      } else {\n        newPinnedProcesses.add(command);\n      }\n      return { ...state, pinnedProcesses: newPinnedProcesses };\n    });\n  };\n\n  const setSearchTerm = (searchTerm: string) =>\n    update((state) => ({ ...state, searchTerm, currentPage: 1 }));\n\n  const setIsFrozen = (isFrozen: boolean) =>\n    update((state) => ({ ...state, isFrozen }));\n\n  const setCurrentPage = (currentPage: number) =>\n    update((state) => ({ ...state, currentPage }));\n\n  const showProcessDetails = (process: Process) => {\n    update((state) => ({\n      ...state,\n      selectedProcessPid: process.pid,\n      selectedProcess: process,\n      showInfoModal: true,\n    }));\n  };\n\n  const closeProcessDetails = () => {\n    update((state) => ({\n      ...state,\n      showInfoModal: false,\n      selectedProcess: null,\n      selectedProcessPid: null,\n    }));\n  };\n\n  const confirmKillProcess = (process: Process) => {\n    update((state) => ({\n      ...state,\n      processToKill: process,\n      showConfirmModal: true,\n    }));\n  };\n\n  const closeConfirmKill = () => {\n    update((state) => ({\n      ...state,\n      showConfirmModal: false,\n      processToKill: null,\n    }));\n  };\n\n  const handleConfirmKill = async () => {\n    let processToKill: Process | null = null;\n\n    let currentState: ProcessStore | undefined;\n    const unsubscribe = subscribe((state) => {\n      currentState = state;\n    });\n    unsubscribe();\n\n    if (currentState?.processToKill && \"pid\" in currentState.processToKill) {\n      processToKill = currentState.processToKill;\n    }\n\n    if (!processToKill?.pid) {\n      return;\n    }\n\n    try {\n      await killProcess(processToKill.pid);\n    } finally {\n      update((state) => ({\n        ...state,\n        showConfirmModal: false,\n        processToKill: null,\n      }));\n    }\n  };\n\n  // Return all methods\n  return {\n    subscribe,\n    set,\n    update,\n    setIsLoading,\n    getProcesses,\n    killProcess,\n    toggleSort,\n    togglePin,\n    setSearchTerm,\n    setIsFrozen,\n    setCurrentPage,\n    showProcessDetails,\n    closeProcessDetails,\n    confirmKillProcess,\n    closeConfirmKill,\n    handleConfirmKill,\n  };\n}\n\nexport const processStore = createProcessStore();\n"
  },
  {
    "path": "src/lib/stores/settings.ts",
    "content": "import { writable } from \"svelte/store\";\nimport type { AppConfig } from \"$lib/types\";\nimport { DEFAULT_CONFIG } from \"$lib/definitions/settings\";\n\nfunction createSettingsStore() {\n  const { subscribe, set, update } = writable<AppConfig>(DEFAULT_CONFIG);\n\n  return {\n    subscribe,\n    init: () => {\n      if (typeof window !== \"undefined\") {\n        const stored = localStorage.getItem(\"neohtop_config\");\n        if (stored) {\n          try {\n            const config = JSON.parse(stored);\n            set({ ...DEFAULT_CONFIG, ...config });\n          } catch (e) {\n            console.error(\"Failed to parse stored config:\", e);\n            set(DEFAULT_CONFIG);\n          }\n        }\n      }\n    },\n    updateConfig: (newConfig: Partial<AppConfig>) => {\n      update((config) => {\n        const updated = { ...config, ...newConfig };\n        if (typeof window !== \"undefined\") {\n          localStorage.setItem(\"neohtop_config\", JSON.stringify(updated));\n        }\n        return updated;\n      });\n    },\n  };\n}\n\nexport const settingsStore = createSettingsStore();\n"
  },
  {
    "path": "src/lib/stores/theme.ts",
    "content": "import { writable } from \"svelte/store\";\nimport { themes } from \"$lib/definitions/themes\";\nimport type { Theme } from \"$lib/types\";\nfunction createThemeStore() {\n  // Default theme\n  const defaultTheme = themes.catppuccin;\n\n  // Initialize with default theme\n  const { subscribe, set } = writable<Theme>(defaultTheme);\n\n  // Initialize theme on client-side only\n  if (typeof window !== \"undefined\") {\n    const storedTheme = localStorage.getItem(\"theme\");\n    if (storedTheme && themes[storedTheme]) {\n      set(themes[storedTheme]);\n    }\n  }\n\n  return {\n    subscribe,\n    setTheme: (themeName: string) => {\n      const theme = themes[themeName];\n      if (theme) {\n        if (typeof window !== \"undefined\") {\n          localStorage.setItem(\"theme\", themeName);\n          // Add this line to set the data-theme attribute\n          document.documentElement.setAttribute(\"data-theme\", themeName);\n        }\n        set(theme);\n        applyTheme(theme);\n      }\n    },\n    init: () => {\n      const storedTheme =\n        typeof window !== \"undefined\" ? localStorage.getItem(\"theme\") : null;\n      const theme = (storedTheme && themes[storedTheme]) || defaultTheme;\n      if (typeof window !== \"undefined\") {\n        // Add this line to set the data-theme attribute on init\n        document.documentElement.setAttribute(\n          \"data-theme\",\n          storedTheme || \"catppuccin\",\n        );\n      }\n      applyTheme(theme);\n    },\n  };\n}\n\nfunction applyTheme(theme: Theme) {\n  if (typeof window !== \"undefined\") {\n    const root = document.documentElement;\n    Object.entries(theme.colors).forEach(([key, value]) => {\n      root.style.setProperty(`--${key}`, value);\n    });\n  }\n}\n\nexport const themeStore = createThemeStore();\n"
  },
  {
    "path": "src/lib/types/index.ts",
    "content": "// Create a new types file to centralize interfaces\nexport interface Process {\n  pid: number;\n  ppid: number;\n  name: string;\n  cpu_usage: number;\n  memory_usage: number;\n  status: string;\n  user: string;\n  command: string;\n  threads?: number;\n  environ: string[];\n  root: string;\n  virtual_memory: number;\n  start_time: number;\n  run_time: number;\n  disk_usage: [number, number]; // [read_bytes, written_bytes]\n  session_id?: number;\n}\n\nexport interface SystemStats {\n  cpu_usage: number[];\n  memory_total: number;\n  memory_used: number;\n  memory_free: number;\n  memory_cached: number;\n  uptime: number;\n  load_avg: [number, number, number];\n  network_rx_bytes: number;\n  network_tx_bytes: number;\n  disk_total_bytes: number;\n  disk_used_bytes: number;\n  disk_free_bytes: number;\n}\n\nexport interface Column {\n  id: keyof Process;\n  label: string;\n  visible: boolean;\n  required?: boolean;\n  format?: (value: any) => string;\n}\n\nexport interface Theme {\n  name: string;\n  label: string;\n  colors: {\n    base: string;\n    mantle: string;\n    crust: string;\n    text: string;\n    subtext0: string;\n    subtext1: string;\n    surface0: string;\n    surface1: string;\n    surface2: string;\n    overlay0: string;\n    overlay1: string;\n    blue: string;\n    lavender: string;\n    sapphire: string;\n    sky: string;\n    red: string;\n    maroon: string;\n    peach: string;\n    yellow: string;\n    green: string;\n    teal: string;\n  };\n}\n\nexport interface AppConfig {\n  appearance: {\n    columnVisibility: Record<string, boolean>;\n  };\n  behavior: {\n    itemsPerPage: number;\n    refreshRate: number;\n    defaultStatusFilter: string;\n  };\n}\n\nexport interface ColumnDefinition {\n  id: string;\n  label: string;\n  visible: boolean;\n  required?: boolean;\n}\n\nexport interface StatusOption {\n  value: string;\n  label: string;\n}\n\nexport interface RefreshRateOption {\n  value: number;\n  label: string;\n}\n\nexport interface ToolBarProps {\n  searchTerm: string;\n  statusFilter: string;\n  itemsPerPage: number;\n  currentPage: number;\n  totalPages: number;\n  totalResults: number;\n  columns: ColumnDefinition[];\n  refreshRate: number;\n  isFrozen: boolean;\n}\n\nexport interface SortConfig {\n  field: keyof Process;\n  direction: \"asc\" | \"desc\";\n}\n"
  },
  {
    "path": "src/lib/utils/index.ts",
    "content": "import type { Process } from \"$lib/types\";\nimport type { SortConfig } from \"$lib/types\";\n\nexport interface ProcessStatus {\n  label: string;\n  emoji: string;\n  color: string;\n}\n\nexport function formatMemorySize(bytes: number): string {\n  const gb = bytes / (1024 * 1024 * 1024);\n  return `${gb.toFixed(1)} GB`;\n}\n\nexport function formatPercentage(value: number): string {\n  return `${value.toFixed(1)}%`;\n}\n\nexport function formatUptime(seconds: number): string {\n  const days = Math.floor(seconds / 86400);\n  const hours = Math.floor((seconds % 86400) / 3600);\n  const minutes = Math.floor((seconds % 3600) / 60);\n  return `${days}d ${hours}h ${minutes}m`;\n}\n\nexport function getUsageClass(percentage: number): string {\n  if (percentage >= 90) return \"critical\";\n  if (percentage >= 60) return \"high\";\n  if (percentage >= 30) return \"medium\";\n  return \"low\";\n}\n\nexport function formatBytes(bytes: number): string {\n  const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n  let value = bytes;\n  let unitIndex = 0;\n\n  while (value >= 1024 && unitIndex < units.length - 1) {\n    value /= 1024;\n    unitIndex++;\n  }\n\n  return `${value.toFixed(1)} ${units[unitIndex]}`;\n}\n\nexport function formatDate(timestamp: number) {\n  return new Date(timestamp * 1000).toLocaleString();\n}\n\n// Debounce utility to reduce frequency of expensive operations\nexport function debounce<T extends (...args: any[]) => any>(\n  func: T,\n  wait: number,\n): (...args: Parameters<T>) => void {\n  let timeout: NodeJS.Timeout;\n  return (...args: Parameters<T>) => {\n    clearTimeout(timeout);\n    timeout = setTimeout(() => func(...args), wait);\n  };\n}\n\n// Cache for compiled regex patterns\nconst regexCache = new Map<string, RegExp>();\n\nexport function filterProcesses(\n  processes: Process[],\n  searchTerm: string,\n  filters: {\n    cpu: { operator: string; value: number; enabled: boolean };\n    ram: { operator: string; value: number; enabled: boolean };\n    runtime: { operator: string; value: number; enabled: boolean };\n    status: { values: string[]; enabled: boolean };\n  },\n): Process[] {\n  // Early return for empty search and no active filters\n  if (\n    searchTerm.length === 0 &&\n    !Object.values(filters).some((f) => f.enabled)\n  ) {\n    return processes;\n  }\n\n  // Pre-process search terms once\n  const terms =\n    searchTerm.length > 0\n      ? searchTerm.split(\",\").map((term) => term.trim())\n      : [];\n\n  return processes.filter((process) => {\n    // Apply status filter\n    if (filters.status.enabled && filters.status.values.length > 0) {\n      if (!filters.status.values.includes(process.status)) {\n        return false;\n      }\n    }\n\n    // Apply CPU filter\n    if (filters.cpu.enabled) {\n      const cpuValue = process.cpu_usage;\n      if (!compareValue(cpuValue, filters.cpu.operator, filters.cpu.value)) {\n        return false;\n      }\n    }\n\n    // Apply RAM filter (convert bytes to MB)\n    if (filters.ram.enabled) {\n      const ramMB = process.memory_usage / (1024 * 1024);\n      if (!compareValue(ramMB, filters.ram.operator, filters.ram.value)) {\n        return false;\n      }\n    }\n\n    // Apply runtime filter (convert to minutes)\n    if (filters.runtime.enabled) {\n      const runtimeMin = process.run_time / 60;\n      if (\n        !compareValue(\n          runtimeMin,\n          filters.runtime.operator,\n          filters.runtime.value,\n        )\n      ) {\n        return false;\n      }\n    }\n\n    // Skip search if no terms\n    if (terms.length === 0) {\n      return true;\n    }\n\n    // Cache lowercase values\n    const processNameLower = process.name.toLowerCase();\n    const processCommandLower = process.command.toLowerCase();\n    const processPidString = process.pid.toString();\n\n    // Check each term\n    return terms.some((term) => {\n      const termLower = term.toLowerCase();\n\n      // Try exact matches first (faster)\n      if (\n        processNameLower.includes(termLower) ||\n        processCommandLower.includes(termLower) ||\n        processPidString.includes(term)\n      ) {\n        return true;\n      }\n\n      // Try regex match last (slower)\n      try {\n        let regex = regexCache.get(term);\n        if (!regex) {\n          regex = new RegExp(term, \"i\");\n          regexCache.set(term, regex);\n        }\n        return regex.test(process.name);\n      } catch {\n        return false;\n      }\n    });\n  });\n}\n\n// Helper function to compare values based on operator\nfunction compareValue(\n  value: number,\n  operator: string,\n  target: number,\n): boolean {\n  switch (operator) {\n    case \">\":\n      return value > target;\n    case \"<\":\n      return value < target;\n    case \"=\":\n      return value === target;\n    case \">=\":\n      return value >= target;\n    case \"<=\":\n      return value <= target;\n    default:\n      return true;\n  }\n}\n\n// Create a Map for quick pinned status lookup\nconst isPinned = new Map<string, boolean>();\n\nexport function sortProcesses(\n  processes: Process[],\n  sortConfig: SortConfig,\n  pinnedProcesses: Set<string>,\n): Process[] {\n  // Clear the cache before sorting\n  isPinned.clear();\n\n  return [...processes].sort((a, b) => {\n    // Cache pinned status\n    let aPin = pinnedProcesses.has(a.command);\n    isPinned.set(a.command, aPin);\n\n    let bPin = pinnedProcesses.has(b.command);\n    isPinned.set(b.command, bPin);\n\n    // Quick pin comparison\n    if (aPin !== bPin) {\n      return aPin ? -1 : 1;\n    }\n\n    // Only compute direction once\n    const direction = sortConfig.direction === \"asc\" ? 1 : -1;\n    const aValue = a[sortConfig.field];\n    const bValue = b[sortConfig.field];\n\n    // Special handling for disk_usage which is an array [read_bytes, written_bytes]\n    if (sortConfig.field === \"disk_usage\") {\n      const aRead = (aValue as [number, number])[0];\n      const aWrite = (aValue as [number, number])[1];\n      const bRead = (bValue as [number, number])[0];\n      const bWrite = (bValue as [number, number])[1];\n\n      // Smart sorting: analyze if this is a read-heavy or write-heavy comparison\n      const totalReads = aRead + bRead;\n      const totalWrites = aWrite + bWrite;\n\n      if (totalWrites > totalReads * 1.5) {\n        // Write-heavy scenario: prioritize writes, use reads as tiebreaker\n        if (aWrite !== bWrite) {\n          return direction * (aWrite - bWrite);\n        }\n        return direction * (aRead - bRead);\n      } else if (totalReads > totalWrites * 1.5) {\n        // Read-heavy scenario: prioritize reads, use writes as tiebreaker\n        if (aRead !== bRead) {\n          return direction * (aRead - bRead);\n        }\n        return direction * (aWrite - bWrite);\n      } else {\n        // Balanced I/O: sort by total, use max as tiebreaker\n        const aTotalDisk = aRead + aWrite;\n        const bTotalDisk = bRead + bWrite;\n        if (aTotalDisk !== bTotalDisk) {\n          return direction * (aTotalDisk - bTotalDisk);\n        }\n        // Tiebreaker: use the dominant operation\n        const aMaxDisk = Math.max(aRead, aWrite);\n        const bMaxDisk = Math.max(bRead, bWrite);\n        return direction * (aMaxDisk - bMaxDisk);\n      }\n    }\n\n    // Type-specific comparisons\n    if (typeof aValue === \"string\") {\n      return direction * aValue.localeCompare(bValue as string);\n    }\n    return direction * (Number(aValue) - Number(bValue));\n  });\n}\n"
  },
  {
    "path": "src/routes/+layout.js",
    "content": "// Tauri doesn't have a Node.js server to do proper SSR\n// so we will use adapter-static to prerender the app (SSG)\n// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info\nexport const prerender = true;\nexport const ssr = false;\n"
  },
  {
    "path": "src/routes/+layout.svelte",
    "content": "<script>\n  import \"../app.css\";\n</script>\n\n<slot />\n"
  },
  {
    "path": "src/routes/+page.svelte",
    "content": "<script lang=\"ts\">\n  import { onMount, onDestroy } from \"svelte\";\n  import { debounce } from \"$lib/utils\";\n  import {\n    StatsBar,\n    ToolBar,\n    TitleBar,\n    ProcessTable,\n    ProcessDetailsModal,\n    KillProcessModal,\n  } from \"$lib/components/index\";\n  import { themeStore, settingsStore, processStore } from \"$lib/stores/index\";\n  import { column_definitions } from \"$lib/definitions/columns\";\n  import { filterProcesses, sortProcesses } from \"$lib/utils\";\n  import type { Process } from \"$lib/types\";\n\n  $: ({\n    processes,\n    systemStats,\n    error,\n    searchTerm,\n    isLoading,\n    currentPage,\n    pinnedProcesses,\n    selectedProcess,\n    showInfoModal,\n    showConfirmModal,\n    processToKill,\n    isKilling,\n    isFrozen,\n    sortConfig,\n  } = $processStore);\n\n  let intervalId: NodeJS.Timeout;\n  let lastProcessCount = 0;\n  let cachedFilteredProcesses: Process[] = [];\n  let cachedSortedProcesses: Process[] = [];\n\n  // Initialize filters object for the new FilterToggle\n  let filters = {\n    cpu: { operator: \">\", value: 50, enabled: false },\n    ram: { operator: \">\", value: 100, enabled: false },\n    runtime: { operator: \">\", value: 60, enabled: false },\n    status: { values: [], enabled: false },\n  };\n\n  $: columns = column_definitions.map((col) => ({\n    ...col,\n    visible:\n      col.required ||\n      ($settingsStore.appearance.columnVisibility[col.id] ?? col.visible),\n  }));\n  $: itemsPerPage = $settingsStore.behavior.itemsPerPage;\n  $: refreshRate = $settingsStore.behavior.refreshRate;\n\n  // Throttled filtering to reduce CPU usage\n  const debouncedFilter = debounce(() => {\n    cachedFilteredProcesses = filterProcesses(processes, searchTerm, filters);\n  }, 100);\n\n  // Only recalculate filtering when inputs actually change\n  $: if (\n    processes.length !== lastProcessCount ||\n    searchTerm ||\n    Object.values(filters).some((f) => f.enabled)\n  ) {\n    lastProcessCount = processes.length;\n    debouncedFilter();\n  } else if (\n    processes.length === lastProcessCount &&\n    !searchTerm &&\n    !Object.values(filters).some((f) => f.enabled)\n  ) {\n    // No filters applied, use all processes directly\n    cachedFilteredProcesses = processes;\n  }\n\n  // Cache sorted results to avoid re-sorting unchanged data\n  $: if (cachedFilteredProcesses && (sortConfig || pinnedProcesses.size > 0)) {\n    cachedSortedProcesses = sortProcesses(\n      cachedFilteredProcesses,\n      sortConfig,\n      pinnedProcesses,\n    );\n  } else {\n    cachedSortedProcesses = cachedFilteredProcesses;\n  }\n\n  $: totalPages = Math.ceil(cachedFilteredProcesses.length / itemsPerPage);\n  $: paginatedProcesses = cachedSortedProcesses.slice(\n    (currentPage - 1) * itemsPerPage,\n    currentPage * itemsPerPage,\n  );\n\n  $: {\n    if (searchTerm || itemsPerPage) {\n      currentPage = 1;\n    }\n  }\n\n  $: {\n    if (intervalId) clearInterval(intervalId);\n    if (!isFrozen) {\n      // Use adaptive refresh rate - slightly slower for 1s to reduce CPU usage\n      const adaptiveRefreshRate = refreshRate === 1000 ? 1500 : refreshRate;\n      intervalId = setInterval(() => {\n        processStore.getProcesses();\n      }, adaptiveRefreshRate);\n    }\n  }\n\n  onMount(async () => {\n    try {\n      await processStore.getProcesses();\n    } catch (error) {\n      console.error(\"Failed to load processes:\", error);\n    } finally {\n      processStore.setIsLoading(false);\n    }\n\n    settingsStore.init();\n    themeStore.init();\n  });\n\n  onDestroy(() => {\n    if (intervalId) clearInterval(intervalId);\n  });\n</script>\n\n{#if isLoading}\n  <div class=\"loading-container\">\n    <div class=\"loading-content\">\n      <img src=\"128x128.png\" alt=\"NeoHtop Logo\" class=\"logo\" />\n    </div>\n  </div>\n{:else}\n  <div class=\"app-container\">\n    <TitleBar />\n    <main>\n      {#if systemStats}\n        <StatsBar {systemStats} />\n      {/if}\n\n      <ToolBar\n        bind:searchTerm={$processStore.searchTerm}\n        bind:itemsPerPage\n        bind:currentPage={$processStore.currentPage}\n        bind:refreshRate\n        bind:isFrozen={$processStore.isFrozen}\n        bind:filters\n        {totalPages}\n        totalResults={cachedFilteredProcesses.length}\n        bind:columns\n      />\n\n      {#if error}\n        <div class=\"alert\">{error}</div>\n      {/if}\n\n      <ProcessTable\n        processes={paginatedProcesses}\n        {columns}\n        {systemStats}\n        {sortConfig}\n        {pinnedProcesses}\n        onToggleSort={processStore.toggleSort}\n        onTogglePin={processStore.togglePin}\n        onShowDetails={processStore.showProcessDetails}\n        onKillProcess={processStore.confirmKillProcess}\n      />\n    </main>\n  </div>\n{/if}\n\n<ProcessDetailsModal\n  show={showInfoModal}\n  process={selectedProcess}\n  {processes}\n  onClose={processStore.closeProcessDetails}\n  onShowDetails={processStore.showProcessDetails}\n/>\n\n<KillProcessModal\n  show={showConfirmModal}\n  process={processToKill}\n  {isKilling}\n  onClose={processStore.closeConfirmKill}\n  onConfirm={processStore.handleConfirmKill}\n/>\n\n<style>\n  :global(:root) {\n    --base: #1e1e2e;\n    --mantle: #181825;\n    --crust: #11111b;\n    --text: #cdd6f4;\n    --subtext0: #a6adc8;\n    --subtext1: #bac2de;\n    --surface0: #313244;\n    --surface1: #45475a;\n    --surface2: #585b70;\n    --overlay0: #6c7086;\n    --overlay1: #7f849c;\n    --blue: #89b4fa;\n    --lavender: #b4befe;\n    --sapphire: #74c7ec;\n    --sky: #89dceb;\n    --red: #f38ba8;\n    --maroon: #eba0ac;\n    --peach: #fab387;\n    --yellow: #f9e2af;\n    --green: #a6e3a1;\n    --teal: #94e2d5;\n  }\n\n  :global(body) {\n    margin: 0;\n    padding: 0;\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial,\n      sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\";\n    background-color: var(--base);\n    color: var(--text);\n    -webkit-font-smoothing: antialiased;\n    overflow: hidden;\n    user-select: none;\n  }\n\n  main {\n    flex: 1;\n    display: flex;\n    flex-direction: column;\n    min-width: min-content;\n    overflow: hidden;\n  }\n\n  .app-container {\n    height: 100vh;\n    display: flex;\n    flex-direction: column;\n  }\n\n  .alert {\n    margin: 8px;\n    padding: 8px 12px;\n    background-color: var(--surface0);\n    border: 1px solid var(--red);\n    border-radius: 6px;\n    color: var(--red);\n    font-size: 13px;\n  }\n\n  .loading-container {\n    width: 100vw;\n    height: 100vh;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    background: linear-gradient(135deg, var(--base) 0%, var(--mantle) 100%);\n    position: relative;\n    overflow: hidden;\n  }\n\n  .loading-content {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    z-index: 2;\n  }\n\n  .logo {\n    width: 128px;\n    height: 128px;\n    filter: drop-shadow(0 0 5px var(--text)) drop-shadow(0 0 10px var(--text))\n      drop-shadow(0 0 20px var(--blue)) drop-shadow(0 0 40px var(--blue));\n    animation: neonPulse 2s ease-in-out infinite;\n  }\n\n  @keyframes neonPulse {\n    0%,\n    100% {\n      filter: drop-shadow(0 0 5px var(--text)) drop-shadow(0 0 10px var(--text))\n        drop-shadow(0 0 20px var(--blue)) drop-shadow(0 0 40px var(--blue));\n    }\n    50% {\n      filter: drop-shadow(0 0 10px var(--text))\n        drop-shadow(0 0 20px var(--text)) drop-shadow(0 0 40px var(--blue))\n        drop-shadow(0 0 80px var(--blue));\n    }\n  }\n</style>\n"
  },
  {
    "path": "src-tauri/.cargo/config.toml",
    "content": "[target.x86_64-apple-darwin]\nrustflags = [\n  \"-C\", \"link-arg=-undefined\",\n  \"-C\", \"link-arg=dynamic_lookup\",\n]\n\n[target.aarch64-apple-darwin]\nrustflags = [\n  \"-C\", \"link-arg=-undefined\",\n  \"-C\", \"link-arg=dynamic_lookup\",\n]\n"
  },
  {
    "path": "src-tauri/.gitignore",
    "content": "# Generated by Cargo\n# will have compiled files and executables\n/target/\n\n# Generated by Tauri\n# will have schema files for capabilities auto-completion\n/gen/schemas\n"
  },
  {
    "path": "src-tauri/Cargo.toml",
    "content": "[package]\nname = \"neohtop\"\nversion = \"1.2.0\"\ndescription = \"A cross-platform system monitor\"\nauthors = [\"you\"]\nedition = \"2021\"\n\n[build-dependencies]\ntauri-build = { version = \"2\", features = [] }\n\n[dependencies]\nserde_json = \"1.0\"\nserde = { version = \"1.0\", features = [\"derive\"] }\ntauri = { version = \"2.1.1\", features = [\"macos-private-api\"] }\nsysinfo = { version = \"0.35.2\", features = [\"disk\", \"multithread\", \"network\", \"system\"] }\ntauri-plugin-shell = \"2\"\ntauri-plugin-os = \"2\"\nwindow-vibrancy = \"0.5.2\"\n\n[features]\ndefault = [ \"custom-protocol\" ]\ncustom-protocol = [ \"tauri/custom-protocol\" ]\n\n[profile.release]\npanic = \"abort\"            # Strip expensive panic clean-up logic\ncodegen-units = 1          # Compile crates one after another so the compiler can optimize better\nlto = \"fat\"                # More aggressive link-time optimization\nopt-level = 3              # Optimize for maximum performance\nstrip = true               # Remove debug symbols\nincremental = false         # Disable incremental compilation\n"
  },
  {
    "path": "src-tauri/build.rs",
    "content": "fn main() {\n    tauri_build::build()\n}\n"
  },
  {
    "path": "src-tauri/capabilities/default.json",
    "content": "{\n  \"$schema\": \"../gen/schemas/desktop-schema.json\",\n  \"identifier\": \"default\",\n  \"description\": \"Capability for the main window\",\n  \"windows\": [\n    \"main\"\n  ],\n  \"permissions\": [\n    \"core:default\",\n    \"core:app:allow-version\",\n    \"core:window:allow-start-dragging\",\n    \"core:window:allow-maximize\",\n    \"core:window:allow-minimize\",\n    \"core:window:allow-close\",\n    \"shell:default\"\n  ]\n}"
  },
  {
    "path": "src-tauri/src/commands.rs",
    "content": "//! Tauri command handlers\n//!\n//! This module contains the command handlers that are exposed to the frontend\n//! through Tauri's IPC mechanism. These commands provide the interface between\n//! the frontend and the system monitoring functionality.\n\nuse crate::monitoring::{ProcessInfo, ProcessMonitor, SystemStats};\nuse crate::state::AppState;\nuse tauri::State;\n\n/// Retrieves the current list of processes and system statistics\n///\n/// # Arguments\n///\n/// * `state` - The application state containing system monitoring components\n///\n/// # Returns\n///\n/// A tuple containing:\n/// * A vector of process information\n/// * Current system statistics\n///\n/// # Errors\n///\n/// Returns an error string if:\n/// * Failed to acquire locks on system state\n/// * Failed to collect process information\n#[tauri::command]\npub async fn get_processes(\n    state: State<'_, AppState>,\n) -> Result<(Vec<ProcessInfo>, SystemStats), String> {\n    let mut sys = state.sys.lock().map_err(|e| e.to_string())?;\n    let mut disks = state.disks.lock().map_err(|e| e.to_string())?;\n    let mut networks = state.networks.lock().map_err(|e| e.to_string())?;\n    sys.refresh_all();\n    disks.refresh(true);\n    networks.refresh(true);\n\n    let mut process_monitor = state.process_monitor.lock().map_err(|e| e.to_string())?;\n    let mut system_monitor = state.system_monitor.lock().map_err(|e| e.to_string())?;\n\n    let processes = process_monitor.collect_processes(&sys)?;\n    let system_stats = system_monitor.collect_stats(&sys, &networks, &disks);\n\n    Ok((processes, system_stats))\n}\n\n/// Attempts to kill a process with the specified PID\n///\n/// # Arguments\n///\n/// * `pid` - Process ID to kill\n/// * `state` - The application state\n///\n/// # Returns\n///\n/// * `true` if the process was successfully killed\n/// * `false` if the process couldn't be killed or wasn't found\n///\n/// # Errors\n///\n/// Returns an error string if failed to acquire lock on system state\n#[tauri::command]\npub async fn kill_process(pid: u32, state: State<'_, AppState>) -> Result<bool, String> {\n    let sys = state.sys.lock().map_err(|e| e.to_string())?;\n    Ok(ProcessMonitor::kill_process(&sys, pid))\n}\n"
  },
  {
    "path": "src-tauri/src/main.rs",
    "content": "#![cfg_attr(not(debug_assertions), windows_subsystem = \"windows\")]\n//! NeoHtop - A modern system monitor built with Tauri\n//!\n//! This is the main entry point for the application. It sets up the Tauri\n//! application, initializes plugins, and configures window effects.\n\nmod commands;\nmod monitoring;\nmod state;\nmod ui;\n\nuse state::AppState;\nuse tauri::Manager;\n\n/// Main entry point for the application\n///\n/// # Panics\n///\n/// Will panic if:\n/// - Unable to create the main window\n/// - Failed to apply window effects\n/// - Failed to initialize the application state\nfn main() {\n    #[cfg(target_os = \"linux\")]\n    if std::env::var(\"XDG_SESSION_TYPE\").unwrap_or_default() == \"wayland\" {\n        std::env::set_var(\"WEBKIT_DISABLE_DMABUF_RENDERER\", \"1\");\n    }\n\n    tauri::Builder::default()\n        .setup(|app| {\n            let window = app.get_webview_window(\"main\").unwrap();\n            ui::setup_window_effects(&window).expect(\"Failed to apply window effects\");\n            Ok(())\n        })\n        .plugin(tauri_plugin_shell::init())\n        .plugin(tauri_plugin_os::init())\n        .manage(AppState::new())\n        .invoke_handler(tauri::generate_handler![\n            commands::get_processes,\n            commands::kill_process,\n        ])\n        .run(tauri::generate_context!())\n        .expect(\"error while running tauri application\");\n}\n"
  },
  {
    "path": "src-tauri/src/monitoring/mod.rs",
    "content": "//! System monitoring functionality\n//!\n//! This module provides types and functionality for monitoring system resources\n//! and processes. It includes process monitoring, system statistics collection,\n//! and data structures for representing system state.\n\nmod process_monitor;\nmod system_monitor;\nmod types;\n\npub use process_monitor::ProcessMonitor;\npub use system_monitor::SystemMonitor;\npub use types::*; // Re-export all types\n"
  },
  {
    "path": "src-tauri/src/monitoring/process_monitor.rs",
    "content": "//! Process monitoring functionality\n//!\n//! This module handles monitoring and managing system processes, including\n//! collecting process information and managing process lifecycle.\n\nuse super::{ProcessData, ProcessInfo, ProcessStaticInfo};\nuse std::collections::HashMap;\nuse std::ffi::OsString;\nuse std::fmt::Debug;\nuse std::time::{SystemTime, UNIX_EPOCH};\nuse sysinfo::ProcessStatus;\n\nfn os_string_vec_to_string_vec(v: &[OsString]) -> Vec<String> {\n    v.iter()\n        .map(|c| c.to_string_lossy().into_owned())\n        .collect::<Vec<_>>()\n}\n\n/// Monitors and manages system processes\n#[derive(Debug)]\npub struct ProcessMonitor {\n    /// Cache for static process information to avoid redundant allocations\n    process_cache: HashMap<u32, ProcessStaticInfo>,\n}\n\nimpl ProcessMonitor {\n    /// Creates a new process monitor instance\n    pub fn new() -> Self {\n        Self {\n            process_cache: HashMap::new(),\n        }\n    }\n\n    /// Collects information about all running processes\n    ///\n    /// # Arguments\n    ///\n    /// * `sys` - System information provider\n    ///\n    /// # Returns\n    ///\n    /// A vector of process information, or an error string if collection failed\n    pub fn collect_processes(&mut self, sys: &sysinfo::System) -> Result<Vec<ProcessInfo>, String> {\n        let current_time = Self::get_current_time()?;\n        let processes_data = self.collect_process_data(sys, current_time);\n        Ok(self.build_process_info(processes_data))\n    }\n\n    /// Attempts to kill a process\n    ///\n    /// # Arguments\n    ///\n    /// * `sys` - System information provider\n    /// * `pid` - Process ID to kill\n    ///\n    /// # Returns\n    ///\n    /// Boolean indicating whether the process was successfully killed\n    pub fn kill_process(sys: &sysinfo::System, pid: u32) -> bool {\n        sys.process(sysinfo::Pid::from(pid as usize))\n            .map(|process| process.kill())\n            .unwrap_or(false)\n    }\n\n    /// Gets the current system time in seconds since UNIX epoch\n    fn get_current_time() -> Result<u64, String> {\n        SystemTime::now()\n            .duration_since(UNIX_EPOCH)\n            .map(|d| d.as_secs())\n            .map_err(|e| format!(\"Failed to get system time: {}\", e))\n    }\n\n    /// Collects raw process data from the system\n    fn collect_process_data(&self, sys: &sysinfo::System, current_time: u64) -> Vec<ProcessData> {\n        sys.processes()\n            .iter()\n            .map(|(pid, process)| {\n                let start_time = process.start_time();\n                ProcessData {\n                    pid: pid.as_u32(),\n                    name: process.name().to_string_lossy().into_owned(),\n                    cmd: os_string_vec_to_string_vec(&process.cmd()),\n                    user_id: process.user_id().map(|uid| uid.to_string()),\n                    cpu_usage: process.cpu_usage(),\n                    memory: process.memory(),\n                    status: process.status(),\n                    ppid: process.parent().map(|p| p.as_u32()),\n                    environ: os_string_vec_to_string_vec(&process.environ()),\n                    root: process\n                        .root()\n                        .map(|p| p.to_string_lossy().into_owned())\n                        .unwrap_or_default(),\n                    virtual_memory: process.virtual_memory(),\n                    start_time,\n                    run_time: if start_time > 0 {\n                        current_time.saturating_sub(start_time)\n                    } else {\n                        0\n                    },\n                    disk_usage: process.disk_usage(),\n                    session_id: process.session_id().map(|id| id.as_u32()),\n                }\n            })\n            .collect()\n    }\n\n    /// Builds process information from raw process data\n    fn build_process_info(&mut self, processes: Vec<ProcessData>) -> Vec<ProcessInfo> {\n        processes\n            .into_iter()\n            .map(|data| {\n                let cached_info =\n                    self.process_cache\n                        .entry(data.pid)\n                        .or_insert_with(|| ProcessStaticInfo {\n                            name: data.name.clone(),\n                            command: data.cmd.join(\" \"),\n                            user: data.user_id.unwrap_or_else(|| \"-\".to_string()),\n                        });\n\n                ProcessInfo {\n                    pid: data.pid,\n                    ppid: data.ppid.unwrap_or(0),\n                    name: cached_info.name.clone(),\n                    cpu_usage: data.cpu_usage,\n                    memory_usage: data.memory,\n                    status: Self::format_status(data.status),\n                    user: cached_info.user.clone(),\n                    command: cached_info.command.clone(),\n                    threads: None,\n                    environ: data.environ,\n                    root: data.root,\n                    virtual_memory: data.virtual_memory,\n                    start_time: data.start_time,\n                    run_time: data.run_time,\n                    disk_usage: (data.disk_usage.read_bytes, data.disk_usage.written_bytes),\n                    session_id: data.session_id,\n                }\n            })\n            .collect()\n    }\n\n    /// Formats process status into a human-readable string\n    pub fn format_status(status: ProcessStatus) -> String {\n        match status {\n            ProcessStatus::Run => \"Running\",\n            ProcessStatus::Sleep => \"Sleeping\",\n            ProcessStatus::Idle => \"Idle\",\n            _ => \"Unknown\",\n        }\n        .to_string()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use sysinfo::System;\n\n    /// Tests creation of a new process monitor\n    #[test]\n    fn test_process_monitor_creation() {\n        let monitor = ProcessMonitor::new();\n        assert!(monitor.process_cache.is_empty());\n    }\n\n    /// Tests process collection functionality\n    #[test]\n    fn test_process_collection() {\n        let mut monitor = ProcessMonitor::new();\n        let mut sys = System::new();\n        sys.refresh_all();\n\n        let result = monitor.collect_processes(&sys);\n        assert!(result.is_ok());\n    }\n}\n"
  },
  {
    "path": "src-tauri/src/monitoring/system_monitor.rs",
    "content": "//! System statistics monitoring\n//!\n//! This module handles collection and monitoring of system-wide statistics\n//! including CPU, memory, network, and disk usage.\n\nuse super::SystemStats;\nuse std::fmt::Debug;\nuse std::path::Path;\nuse std::time::Instant;\nuse sysinfo::{Disk, Disks, Networks, System};\n\n/// Monitors system-wide statistics\n#[derive(Debug)]\npub struct SystemMonitor {\n    /// Tracks network usage between updates\n    last_network_update: (Instant, u64, u64),\n}\n\nimpl SystemMonitor {\n    /// Creates a new system monitor instance\n    ///\n    /// # Arguments\n    ///\n    /// * `sys` - System information provider for initial readings\n    pub fn new(networks: &Networks) -> Self {\n        let (initial_rx, initial_tx) =\n            networks\n                .iter()\n                .fold((0, 0), |(initial_rx, initial_tx), (_, data)| {\n                    (\n                        initial_rx + data.total_received(),\n                        initial_tx + data.total_transmitted(),\n                    )\n                });\n\n        Self {\n            last_network_update: (Instant::now(), initial_rx, initial_tx),\n        }\n    }\n\n    /// Collects current system statistics\n    ///\n    /// # Arguments\n    ///\n    /// * `sys` - System information provider\n    pub fn collect_stats(\n        &mut self,\n        sys: &System,\n        networks: &Networks,\n        disks: &Disks,\n    ) -> SystemStats {\n        let (network_rx, network_tx) = self.calculate_network_stats(networks);\n        let (disk_total, disk_used, disk_free) = self.calculate_disk_stats(disks);\n        let load_average = System::load_average();\n\n        SystemStats {\n            cpu_usage: sys.cpus().iter().map(|cpu| cpu.cpu_usage()).collect(),\n            memory_total: sys.total_memory(),\n            memory_used: sys.used_memory(),\n            memory_free: sys.total_memory() - sys.used_memory(),\n            memory_cached: sys.total_memory()\n                - (sys.used_memory() + (sys.total_memory() - sys.used_memory())),\n            uptime: System::uptime(),\n            load_avg: [load_average.one, load_average.five, load_average.fifteen],\n            network_rx_bytes: network_rx,\n            network_tx_bytes: network_tx,\n            disk_total_bytes: disk_total,\n            disk_used_bytes: disk_used,\n            disk_free_bytes: disk_free,\n        }\n    }\n\n    /// Filters disks based on platform-specific criteria\n    #[cfg(not(target_os = \"windows\"))]\n    fn filter_disks(disks: &[Disk]) -> impl Iterator<Item = &Disk> {\n        disks\n            .iter()\n            .filter(|disk| disk.mount_point() == Path::new(\"/\"))\n    }\n\n    /// Windows-specific disk filtering\n    #[cfg(target_os = \"windows\")]\n    fn filter_disks(disks: &[Disk]) -> impl Iterator<Item = &Disk> {\n        disks.iter()\n    }\n\n    /// Calculates network usage rates\n    fn calculate_network_stats(&mut self, networks: &Networks) -> (u64, u64) {\n        let (current_rx, current_tx) =\n            networks\n                .iter()\n                .fold((0, 0), |(current_rx, current_tx), (_, data)| {\n                    (\n                        current_rx + data.total_received(),\n                        current_tx + data.total_transmitted(),\n                    )\n                });\n\n        let elapsed = self.last_network_update.0.elapsed().as_secs_f64();\n        let rx_rate = ((current_rx - self.last_network_update.1) as f64 / elapsed) as u64;\n        let tx_rate = ((current_tx - self.last_network_update.2) as f64 / elapsed) as u64;\n\n        self.last_network_update = (Instant::now(), current_rx, current_tx);\n        (rx_rate, tx_rate)\n    }\n\n    /// Calculates disk usage statistics and returns `(total, used, free)`.\n    fn calculate_disk_stats(&self, disks: &Disks) -> (u64, u64, u64) {\n        Self::filter_disks(disks).fold((0, 0, 0), |(total, used, free), disk| {\n            (\n                total + disk.total_space(),\n                used + (disk.total_space() - disk.available_space()),\n                free + disk.available_space(),\n            )\n        })\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use sysinfo::System;\n\n    /// Tests creation of system monitor\n    #[test]\n    fn test_system_monitor_creation() {\n        let networks = Networks::new();\n        let monitor = SystemMonitor::new(&networks);\n        assert!(monitor.last_network_update.1 >= 0);\n        assert!(monitor.last_network_update.2 >= 0);\n    }\n\n    /// Tests system statistics collection\n    #[test]\n    fn test_stats_collection() {\n        let mut networks = Networks::new();\n        let mut monitor = SystemMonitor::new(&networks);\n        networks.refresh(true);\n        let sys = System::new_all();\n        let disks = Disks::new_with_refreshed_list();\n\n        let stats = monitor.collect_stats(&sys, &networks, &disks);\n        assert!(!stats.cpu_usage.is_empty());\n        assert!(stats.memory_total > 0);\n    }\n}\n"
  },
  {
    "path": "src-tauri/src/monitoring/types.rs",
    "content": "use serde::Serialize;\nuse std::fmt::Debug;\nuse sysinfo::{DiskUsage, ProcessStatus};\n\n/// Internal representation of process data collected from the system\n/// This struct is used internally and not exposed directly to the frontend\n#[derive(Clone, Debug)]\npub(crate) struct ProcessData {\n    /// Process ID\n    pub pid: u32,\n    /// Name of the process\n    pub name: String,\n    /// Complete command line arguments\n    pub cmd: Vec<String>,\n    /// User ID that owns the process\n    pub user_id: Option<String>,\n    /// CPU usage as percentage (0-100)\n    pub cpu_usage: f32,\n    /// Physical memory usage in bytes\n    pub memory: u64,\n    /// Current process status\n    pub status: ProcessStatus,\n    /// Parent process ID\n    pub ppid: Option<u32>,\n    /// Environment variables\n    pub environ: Vec<String>,\n    /// Root directory of the process\n    pub root: String,\n    /// Virtual memory usage in bytes\n    pub virtual_memory: u64,\n    /// Process start time (Unix timestamp)\n    pub start_time: u64,\n    /// Process running time in seconds\n    pub run_time: u64,\n    /// Disk I/O statistics\n    pub disk_usage: DiskUsage,\n    /// Session ID of the process\n    pub session_id: Option<u32>,\n}\n\n/// Static information about a process that doesn't change frequently\n/// Used for caching purposes to avoid frequent updates of stable data\n#[derive(Clone, Debug)]\npub struct ProcessStaticInfo {\n    /// Process name\n    pub name: String,\n    /// Full command string\n    pub command: String,\n    /// Username of the process owner\n    pub user: String,\n}\n\n/// Process information exposed to the frontend via Tauri\n/// Contains formatted and filtered process data for UI consumption\n#[derive(Serialize, Debug)]\npub struct ProcessInfo {\n    /// Process ID\n    pub pid: u32,\n    /// Parent process ID\n    pub ppid: u32,\n    /// Process name\n    pub name: String,\n    /// CPU usage as percentage (0-100)\n    pub cpu_usage: f32,\n    /// Physical memory usage in bytes\n    pub memory_usage: u64,\n    /// Process status as string\n    pub status: String,\n    /// Username of the process owner\n    pub user: String,\n    /// Full command string\n    pub command: String,\n    /// Number of threads (if available)\n    pub threads: Option<u32>,\n    /// Environment variables\n    pub environ: Vec<String>,\n    /// Root directory of the process\n    pub root: String,\n    /// Virtual memory usage in bytes\n    pub virtual_memory: u64,\n    /// Process start time (Unix timestamp)\n    pub start_time: u64,\n    /// Process running time in seconds\n    pub run_time: u64,\n    /// Disk I/O statistics (read bytes, written bytes)\n    pub disk_usage: (u64, u64),\n    /// Session ID of the process\n    pub session_id: Option<u32>,\n}\n\n/// System-wide statistics exposed to the frontend\n/// Provides overall system resource usage and performance metrics\n#[derive(Serialize, Debug)]\npub struct SystemStats {\n    /// CPU usage per core as percentage (0-100)\n    pub cpu_usage: Vec<f32>,\n    /// Total physical memory in bytes\n    pub memory_total: u64,\n    /// Used physical memory in bytes\n    pub memory_used: u64,\n    /// Free physical memory in bytes\n    pub memory_free: u64,\n    /// Cached memory in bytes\n    pub memory_cached: u64,\n    /// System uptime in seconds\n    pub uptime: u64,\n    /// Load averages for 1, 5, and 15 minutes\n    pub load_avg: [f64; 3],\n    /// Total bytes received over network\n    pub network_rx_bytes: u64,\n    /// Total bytes transmitted over network\n    pub network_tx_bytes: u64,\n    /// Total disk space in bytes\n    pub disk_total_bytes: u64,\n    /// Used disk space in bytes\n    pub disk_used_bytes: u64,\n    /// Free disk space in bytes\n    pub disk_free_bytes: u64,\n}\n"
  },
  {
    "path": "src-tauri/src/state.rs",
    "content": "//! Application state management\n//!\n//! This module handles the global application state, including system monitoring\n//! and process tracking capabilities.\n\nuse crate::monitoring::{ProcessMonitor, SystemMonitor};\nuse std::sync::Mutex;\nuse sysinfo::{Disks, Networks, System};\n\n/// Global application state\n///\n/// Maintains thread-safe access to system information and monitoring components\n#[derive(Debug)]\npub struct AppState {\n    /// System information handler\n    pub sys: Mutex<System>,\n    /// Networks information handler\n    pub networks: Mutex<Networks>,\n    /// Networks information handler\n    pub disks: Mutex<Disks>,\n    /// Process monitoring component\n    pub process_monitor: Mutex<ProcessMonitor>,\n    /// System statistics monitoring component\n    pub system_monitor: Mutex<SystemMonitor>,\n}\n\nimpl AppState {\n    /// Creates a new instance of the application state\n    ///\n    /// Initializes system monitoring and process tracking components\n    ///\n    /// # Returns\n    ///\n    /// A new `AppState` instance with initialized monitors\n    pub fn new() -> Self {\n        let sys = System::new_all();\n        let disks = Disks::new_with_refreshed_list();\n        let networks = Networks::new_with_refreshed_list();\n\n        Self {\n            process_monitor: Mutex::new(ProcessMonitor::new()),\n            system_monitor: Mutex::new(SystemMonitor::new(&networks)),\n            sys: Mutex::new(sys),\n            disks: Mutex::new(disks),\n            networks: Mutex::new(networks),\n        }\n    }\n}\n"
  },
  {
    "path": "src-tauri/src/ui/mod.rs",
    "content": "//! User interface functionality\n//!\n//! This module handles UI-specific functionality, including window effects\n//! and platform-specific visual customizations.\n\nmod window;\npub use window::setup_window_effects;\n"
  },
  {
    "path": "src-tauri/src/ui/window.rs",
    "content": "//! Window effects and customization\n//!\n//! Provides platform-specific window effects like transparency and vibrancy.\n\nuse tauri::WebviewWindow;\n\n#[cfg(target_os = \"windows\")]\nuse window_vibrancy::apply_acrylic;\n#[cfg(target_os = \"macos\")]\nuse window_vibrancy::{apply_vibrancy, NSVisualEffectMaterial, NSVisualEffectState};\n\n/// Applies Windows-specific window effects\n#[cfg(target_os = \"windows\")]\npub fn setup_window_effects(window: &WebviewWindow) -> Result<(), Box<dyn std::error::Error>> {\n    apply_acrylic(window, Some((0, 0, 25, 125)))?;\n    Ok(())\n}\n\n/// Applies macOS-specific window effects\n#[cfg(target_os = \"macos\")]\npub fn setup_window_effects(window: &WebviewWindow) -> Result<(), Box<dyn std::error::Error>> {\n    apply_vibrancy(\n        window,\n        NSVisualEffectMaterial::HudWindow,\n        Some(NSVisualEffectState::Active),\n        None,\n    )?;\n    Ok(())\n}\n\n/// No-op for platforms without specific window effects\n#[cfg(not(any(target_os = \"windows\", target_os = \"macos\")))]\npub fn setup_window_effects(_window: &WebviewWindow) -> Result<(), Box<dyn std::error::Error>> {\n    Ok(())\n}\n"
  },
  {
    "path": "src-tauri/tauri.conf.json",
    "content": "{\n  \"$schema\": \"../node_modules/@tauri-apps/cli/config.schema.json\",\n  \"build\": {\n    \"beforeBuildCommand\": \"npm run build\",\n    \"beforeDevCommand\": \"npm run dev\",\n    \"frontendDist\": \"../build\",\n    \"devUrl\": \"http://localhost:1420\"\n  },\n  \"bundle\": {\n    \"active\": true,\n    \"icon\": [\n      \"icons/32x32.png\",\n      \"icons/128x128.png\",\n      \"icons/128x128@2x.png\",\n      \"icons/icon.icns\",\n      \"icons/icon.ico\"\n    ],\n    \"macOS\": {\n      \"hardenedRuntime\": true,\n      \"entitlements\": null,\n      \"providerShortName\": null\n    },\n    \"targets\": [\"app\", \"dmg\"]\n  },\n  \"productName\": \"NeoHtop\",\n  \"mainBinaryName\": \"NeoHtop\",\n  \"version\": \"1.2.0\",\n  \"identifier\": \"com.neohtop.dev\",\n  \"plugins\": {\n    \"os\": {\n      \"all\": true\n    }\n  },\n  \"app\": {\n    \"macOSPrivateApi\": true,\n    \"windows\": [\n      {\n        \"fullscreen\": false,\n        \"theme\": \"Dark\",\n        \"height\": 900,\n        \"resizable\": true,\n        \"title\": \"NeoHtop\",\n        \"width\": 1280,\n        \"minWidth\": 1120,\n        \"minHeight\": 700,\n        \"titleBarStyle\": \"Overlay\",\n        \"hiddenTitle\": true,\n        \"transparent\": true\n      }\n    ],\n    \"security\": {\n      \"csp\": null\n    }\n  }\n}\n"
  },
  {
    "path": "svelte.config.js",
    "content": "// Tauri doesn't have a Node.js server to do proper SSR\n// so we will use adapter-static to prerender the app (SSG)\n// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info\nimport adapter from \"@sveltejs/adapter-static\";\nimport { vitePreprocess } from '@sveltejs/vite-plugin-svelte';\n\n/** @type {import('@sveltejs/kit').Config} */\nconst config = {\n  kit: {\n    adapter: adapter(),\n    alias: {\n      $lib: 'src/lib'\n    }\n  },\n  preprocess: vitePreprocess()\n};\n\nexport default config;\n"
  },
  {
    "path": "vite.config.js",
    "content": "import { defineConfig } from \"vite\";\nimport { sveltekit } from \"@sveltejs/kit/vite\";\n\nconst host = process.env.TAURI_DEV_HOST;\n\n// https://vitejs.dev/config/\nexport default defineConfig(async () => ({\n  plugins: [sveltekit()],\n  resolve: {\n    alias: {\n      $lib: \"/src/lib\",\n    },\n  },\n  // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`\n  //\n  // 1. prevent vite from obscuring rust errors\n  clearScreen: false,\n  // 2. tauri expects a fixed port, fail if that port is not available\n  server: {\n    port: 1420,\n    strictPort: true,\n    host: host || false,\n    hmr: host\n      ? {\n        protocol: \"ws\",\n        host,\n        port: 1421,\n      }\n      : undefined,\n    watch: {\n      // 3. tell vite to ignore watching `src-tauri`\n      ignored: [\"**/src-tauri/**\"],\n    },\n  },\n}));\n"
  }
]