diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 0000000..fffa3b8
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,73 @@
+name: Deploy
+
+on:
+ push:
+ branches:
+ - main
+
+# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
+permissions:
+ contents: write
+ pages: write
+ id-token: write
+
+# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
+# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
+concurrency:
+ group: "pages"
+ cancel-in-progress: false
+
+jobs:
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ - name: Setup Node
+ uses: actions/setup-node@v4
+
+ - name: Clean dist directory
+ run: rm -rf ./code/dist
+
+ - name: Install dependencies
+ run: npm install
+ working-directory: ./code
+
+ - name: Build project
+ run: npm run build
+ working-directory: ./code
+
+ - name: Upload production-ready build files
+ uses: actions/upload-artifact@v4
+ with:
+ name: github-pages
+ path: ./code/dist
+
+ deploy:
+ name: Deploy
+ needs: build
+ runs-on: ubuntu-latest
+ if: github.ref == 'refs/heads/main'
+
+ steps:
+ - name: Download artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: github-pages
+ path: ./code/dist
+
+ - name: Deploy to GitHub Pages
+ run: |
+ git config --global user.name "github-actions[bot]"
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
+ git init
+ git remote add origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
+ git fetch origin
+ git checkout -B gh-pages
+ mv ./code/dist/* ./ # Move the contents of dist to the root
+ git add .
+ git commit -m "Deploy to GitHub Pages"
+ git push origin gh-pages --force
diff --git a/CNAME b/CNAME
new file mode 100644
index 0000000..edce9de
--- /dev/null
+++ b/CNAME
@@ -0,0 +1 @@
+accelerators.ms
\ No newline at end of file
diff --git a/SUPPORT.md b/SUPPORT.md
index 459acc3..b4fd25c 100644
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -1,13 +1,13 @@
-# Support
-
-## How to file issues and get help
-
-This project uses GitHub Issues to track bugs and feature requests. Please search the existing
-issues before filing new issues to avoid duplicates. For new issues, file your bug or
-feature request as a new issue.
-
-For help and questions about using this project, you may also file a new issue.
-
-## Microsoft Support Policy
-
-Support for this repository is limited and Microsoft does not guarantee the quality, performance, reliability, or availability of this release or its output, and does not provide any warranty or support for it.
+# Support
+
+## How to file issues and get help
+
+This project uses GitHub Issues to track bugs and feature requests. Please search the existing
+issues before filing new issues to avoid duplicates. For new issues, file your bug or
+feature request as a new issue.
+
+For help and questions about using this project, you may also file a new issue.
+
+## Microsoft Support Policy
+
+Support for this repository is limited and Microsoft does not guarantee the quality, performance, reliability, or availability of this release or its output, and does not provide any warranty or support for it.
diff --git a/code/.github/workflows/deploy.yml b/code/.github/workflows/deploy.yml
new file mode 100644
index 0000000..e765e4a
--- /dev/null
+++ b/code/.github/workflows/deploy.yml
@@ -0,0 +1,49 @@
+name: Deploy to GitHub Pages
+
+on:
+ push:
+ branches: [ website ]
+ pull_request:
+ branches: [ website ]
+
+jobs:
+ build-and-deploy:
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20'
+ cache: 'npm'
+ cache-dependency-path: './code/package-lock.json'
+
+ - name: Install dependencies
+ run: |
+ cd code
+ npm ci
+
+ - name: Build
+ run: |
+ cd code
+ npm run build
+
+ - name: Setup Pages
+ uses: actions/configure-pages@v4
+
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: './code/dist'
+
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
\ No newline at end of file
diff --git a/code/.gitignore b/code/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/code/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/code/README.SOLUTION.md b/code/README.SOLUTION.md
new file mode 100644
index 0000000..2e4648c
--- /dev/null
+++ b/code/README.SOLUTION.md
@@ -0,0 +1,132 @@
+# CSA Solution Accelerators Landing Page
+
+A modern, responsive React-based landing page showcasing Microsoft's AI Solution Accelerators. Built with React 18, TypeScript, Vite, and Tailwind CSS, this application provides an intuitive interface for exploring and discovering AI accelerators, solution areas, and implementation resources.
+
+## Features
+
+- **Modern UI/UX**: Clean, professional design using Fluent UI components and Tailwind CSS
+- **Deep Linking**: Advanced navigation system with URL synchronization and smooth scrolling
+- **Search & Filtering**: Real-time search with multi-category filtering capabilities
+- **Responsive Design**: Mobile-first approach with touch-friendly interactions
+- **Performance Optimized**: Fast loading with code splitting and lazy loading
+- **Accessibility**: WCAG 2.1 AA compliant with keyboard navigation support
+
+## Technology Stack
+
+- **Frontend**: React 18 + TypeScript
+- **Build Tool**: Vite
+- **Styling**: Tailwind CSS + Fluent UI React Components
+- **Icons**: Fluent UI React Icons
+- **Deployment**: GitHub Pages
+- **Data**: Static JSON with dynamic filtering
+
+## Getting Started
+
+### Prerequisites
+
+- Node.js 18+
+- npm or yarn package manager
+
+### Installation
+
+1. Clone the repository:
+```bash
+git clone https://github.com/your-username/csa-sas-ext-landingpage.git
+cd csa-sas-ext-landingpage
+```
+
+2. Install dependencies:
+```bash
+npm install
+```
+
+### Development
+
+To run the project locally in development mode:
+
+```bash
+npm run dev
+```
+
+This will start the development server, typically at `http://localhost:5173`. The page will automatically reload when you make changes to the code.
+
+### Building
+
+To build the project for production:
+
+```bash
+npm run build
+```
+
+This creates an optimized production build in the `dist/` directory.
+
+### Preview Build
+
+To preview the production build locally:
+
+```bash
+npm run preview
+```
+
+## Live Demo
+
+Access the live version of the application at:
+**[https://cuddly-adventure-3j22l89.pages.github.io/](https://cuddly-adventure-3j22l89.pages.github.io/)**
+
+## Project Structure
+
+```
+src/
+├── components/ # React components
+│ ├── Header/ # Navigation and header components
+│ ├── HeroSection/ # Main hero section
+│ ├── FeaturedSection/ # Featured accelerators showcase
+│ ├── DifferentiatorSection/ # Solution differentiators
+│ ├── HowItWorksSection/ # Process explanation
+│ ├── SuccessStoriesSection/ # Customer success stories
+│ ├── Footer/ # Site footer
+│ └── shared/ # Reusable component utilities
+├── data/ # Static data and generated content
+│ ├── cards/ # Individual accelerator JSON files
+│ └── generated/ # Build-time generated data
+├── hooks/ # Custom React hooks
+├── utils/ # Utility functions and helpers
+├── types/ # TypeScript type definitions
+└── assets/ # Images, icons, and static assets
+```
+
+## Key Components
+
+- **GsaCard**: Accelerator card component with hover effects and responsive design
+- **Navigation**: Sticky navigation with smooth scrolling and deep linking
+- **Search & Filters**: Advanced filtering by categories, solution areas, and technologies
+- **Responsive Grid**: Adaptive layout system for different screen sizes
+
+## Development Workflow
+
+1. **Feature Development**: Create feature branches from main
+2. **Testing**: Ensure all functionality works across browsers and devices
+3. **Code Quality**: Follow TypeScript best practices and component architecture
+4. **Performance**: Monitor bundle size and loading performance
+5. **Accessibility**: Maintain WCAG compliance standards
+
+## Contributing
+
+
+
+For major changes, please open an issue first to discuss the proposed changes.
+
+## License
+
+This project is licensed under the MIT License - see the LICENSE file for details.
+
+## Support
+
+For questions or support, please:
+- Open an issue on GitHub
+- Contact the development team
+- Check the documentation in the `/docs` folder
+
+---
+
+**Built with ❤️ by the Microsoft AI Solution Accelerators team**
diff --git a/code/README.md b/code/README.md
new file mode 100644
index 0000000..7959ce4
--- /dev/null
+++ b/code/README.md
@@ -0,0 +1,69 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
+
+```js
+export default tseslint.config([
+ globalIgnores(['dist']),
+ {
+ files: ['**/*.{ts,tsx}'],
+ extends: [
+ // Other configs...
+
+ // Remove tseslint.configs.recommended and replace with this
+ ...tseslint.configs.recommendedTypeChecked,
+ // Alternatively, use this for stricter rules
+ ...tseslint.configs.strictTypeChecked,
+ // Optionally, add this for stylistic rules
+ ...tseslint.configs.stylisticTypeChecked,
+
+ // Other configs...
+ ],
+ languageOptions: {
+ parserOptions: {
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
+ tsconfigRootDir: import.meta.dirname,
+ },
+ // other options...
+ },
+ },
+])
+```
+
+You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
+
+```js
+// eslint.config.js
+import reactX from 'eslint-plugin-react-x'
+import reactDom from 'eslint-plugin-react-dom'
+
+export default tseslint.config([
+ globalIgnores(['dist']),
+ {
+ files: ['**/*.{ts,tsx}'],
+ extends: [
+ // Other configs...
+ // Enable lint rules for React
+ reactX.configs['recommended-typescript'],
+ // Enable lint rules for React DOM
+ reactDom.configs.recommended,
+ ],
+ languageOptions: {
+ parserOptions: {
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
+ tsconfigRootDir: import.meta.dirname,
+ },
+ // other options...
+ },
+ },
+])
+```
diff --git a/code/eslint.config.js b/code/eslint.config.js
new file mode 100644
index 0000000..d94e7de
--- /dev/null
+++ b/code/eslint.config.js
@@ -0,0 +1,23 @@
+import js from '@eslint/js'
+import globals from 'globals'
+import reactHooks from 'eslint-plugin-react-hooks'
+import reactRefresh from 'eslint-plugin-react-refresh'
+import tseslint from 'typescript-eslint'
+import { globalIgnores } from 'eslint/config'
+
+export default tseslint.config([
+ globalIgnores(['dist']),
+ {
+ files: ['**/*.{ts,tsx}'],
+ extends: [
+ js.configs.recommended,
+ tseslint.configs.recommended,
+ reactHooks.configs['recommended-latest'],
+ reactRefresh.configs.vite,
+ ],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ },
+ },
+])
diff --git a/code/index.html b/code/index.html
new file mode 100644
index 0000000..d14f5e2
--- /dev/null
+++ b/code/index.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ Microsoft - AI Solution Accelerators
+
+
+
+
+
+
+
+
+
diff --git a/code/package-lock.json b/code/package-lock.json
new file mode 100644
index 0000000..4581b80
--- /dev/null
+++ b/code/package-lock.json
@@ -0,0 +1,6404 @@
+{
+ "name": "microsoft-ai-accelerators-landing",
+ "version": "0.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "microsoft-ai-accelerators-landing",
+ "version": "0.0.0",
+ "dependencies": {
+ "@fluentui/react-components": "^9.46.0",
+ "@fluentui/react-icons": "^2.0.224",
+ "framer-motion": "^10.18.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@eslint/js": "^8.56.0",
+ "@types/node": "^20.11.0",
+ "@types/react": "^18.2.48",
+ "@types/react-dom": "^18.2.18",
+ "@typescript-eslint/eslint-plugin": "^6.19.0",
+ "@typescript-eslint/parser": "^6.19.0",
+ "@vitejs/plugin-react": "^4.2.1",
+ "autoprefixer": "^10.4.17",
+ "eslint": "^8.56.0",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.5",
+ "gh-pages": "^6.1.1",
+ "globals": "^13.24.0",
+ "postcss": "^8.4.33",
+ "tailwindcss": "^3.4.1",
+ "typescript": "^5.3.3",
+ "vite": "^5.0.11"
+ }
+ },
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz",
+ "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz",
+ "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==",
+ "dev": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.0",
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-module-transforms": "^7.27.3",
+ "@babel/helpers": "^7.27.6",
+ "@babel/parser": "^7.28.0",
+ "@babel/template": "^7.27.2",
+ "@babel/traverse": "^7.28.0",
+ "@babel/types": "^7.28.0",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz",
+ "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.28.0",
+ "@babel/types": "^7.28.0",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
+ "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.27.2",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.27.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz",
+ "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "@babel/traverse": "^7.27.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
+ "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
+ "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.28.2",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.2.tgz",
+ "integrity": "sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz",
+ "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.28.0"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
+ "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
+ "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.28.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz",
+ "integrity": "sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
+ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.2",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz",
+ "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.0",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.0",
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.0",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.28.2",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz",
+ "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@ctrl/tinycolor": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
+ "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@emotion/hash": {
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
+ "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g=="
+ },
+ "node_modules/@emotion/is-prop-valid": {
+ "version": "0.8.8",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
+ "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
+ "optional": true,
+ "dependencies": {
+ "@emotion/memoize": "0.7.4"
+ }
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
+ "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==",
+ "optional": true
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
+ "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
+ "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@floating-ui/core": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.2.tgz",
+ "integrity": "sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/devtools": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@floating-ui/devtools/-/devtools-0.2.1.tgz",
+ "integrity": "sha512-8PHJLbD6VhBh+LJ1uty/Bz30qs02NXCE5u8WpOhSewlYXUWl03GNXknr9AS2yaAWJEQaY27x7eByJs44gODBcw==",
+ "peerDependencies": {
+ "@floating-ui/dom": ">=1.5.4"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.2.tgz",
+ "integrity": "sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==",
+ "dependencies": {
+ "@floating-ui/core": "^1.7.2",
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
+ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="
+ },
+ "node_modules/@fluentui/keyboard-keys": {
+ "version": "9.0.8",
+ "resolved": "https://registry.npmjs.org/@fluentui/keyboard-keys/-/keyboard-keys-9.0.8.tgz",
+ "integrity": "sha512-iUSJUUHAyTosnXK8O2Ilbfxma+ZyZPMua5vB028Ys96z80v+LFwntoehlFsdH3rMuPsA8GaC1RE7LMezwPBPdw==",
+ "dependencies": {
+ "@swc/helpers": "^0.5.1"
+ }
+ },
+ "node_modules/@fluentui/priority-overflow": {
+ "version": "9.1.15",
+ "resolved": "https://registry.npmjs.org/@fluentui/priority-overflow/-/priority-overflow-9.1.15.tgz",
+ "integrity": "sha512-/3jPBBq64hRdA416grVj+ZeMBUIaKZk2S5HiRg7CKCAV1JuyF84Do0rQI6ns8Vb9XOGuc4kurMcL/UEftoEVrg==",
+ "dependencies": {
+ "@swc/helpers": "^0.5.1"
+ }
+ },
+ "node_modules/@fluentui/react-accordion": {
+ "version": "9.8.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-accordion/-/react-accordion-9.8.1.tgz",
+ "integrity": "sha512-efB73AbXqW3xiIReslZocHAwj1vtpSF4VMZCtbU0lgieF5sfJaGLJ+F3YDYKfMhxrNEBPgdwAFgj6oYtR0h1WA==",
+ "dependencies": {
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-motion": "^9.10.0",
+ "@fluentui/react-motion-components-preview": "^0.8.0",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-alert": {
+ "version": "9.0.0-beta.124",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-alert/-/react-alert-9.0.0-beta.124.tgz",
+ "integrity": "sha512-yFBo3B5H9hnoaXxlkuz8wRz04DEyQ+ElYA/p5p+Vojf19Zuta8DmFZZ6JtWdtxcdnnQ4LvAfC5OYYlzdReozPA==",
+ "dependencies": {
+ "@fluentui/react-avatar": "^9.6.29",
+ "@fluentui/react-button": "^9.3.83",
+ "@fluentui/react-icons": "^2.0.239",
+ "@fluentui/react-jsx-runtime": "^9.0.39",
+ "@fluentui/react-tabster": "^9.21.5",
+ "@fluentui/react-theme": "^9.1.19",
+ "@fluentui/react-utilities": "^9.18.10",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-aria": {
+ "version": "9.16.0",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-aria/-/react-aria-9.16.0.tgz",
+ "integrity": "sha512-cJBs4A+z7Oqvj4TG0bcvxzwBK8GXmLRWUehF17K9YmruG5tRQDbW9z2+hmIMpEwjJo8ceiSr6SOLP1Lpp6TimQ==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-avatar": {
+ "version": "9.9.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-avatar/-/react-avatar-9.9.1.tgz",
+ "integrity": "sha512-oy/CYru5GJlLOkRlDaWs3fusD7CDqV7cYc1pO7XdF+9ya2DgvsSpbIqqfsu3wgIHAaf2P/ThmFNMJRR9Iv1Txg==",
+ "dependencies": {
+ "@fluentui/react-badge": "^9.4.1",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-popover": "^9.12.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-tooltip": "^9.8.1",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-badge": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-badge/-/react-badge-9.4.1.tgz",
+ "integrity": "sha512-qBESgWHgX/NCXSjnfchVbY/dpY06LQ/unvSH53UQ3/UkXBmQQ1ElFMwWwdmKszH7wtL1oX81x1YXZO0lHgmshA==",
+ "dependencies": {
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-breadcrumb": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-breadcrumb/-/react-breadcrumb-9.3.1.tgz",
+ "integrity": "sha512-SDu+gwu5HBYWXGg6pxuk6v7+RsRzMj4EmfsH+5NPOhHyUo71BVcYHfA16lVpF8x8BA2VxvGvVZZu26t82u9tEA==",
+ "dependencies": {
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-button": "^9.6.1",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-link": "^9.6.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-button": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-button/-/react-button-9.6.1.tgz",
+ "integrity": "sha512-YZYYjkwPrhD7SjO5slr7DViI3TkRARl+C4UA4/yjdOM9s7SRppbCZvdttp3ILU7UeUoqREiJkVS5wYMjyWYz3w==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-card": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-card/-/react-card-9.4.1.tgz",
+ "integrity": "sha512-HKjUF+iGK13VWE2JPdfjagUWXxj58WOThrcGOgwmQJJSBSfLyFSQKN+qnU4niOPqxPvoTI4elJs9R+s5s2YbjA==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-text": "^9.6.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-carousel": {
+ "version": "9.8.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-carousel/-/react-carousel-9.8.1.tgz",
+ "integrity": "sha512-3Ab329dGckxV/TDHihPR4XJu7/q0xlcELnymJVhnQjVqMVddaO5pHt8k0SLmSW9gftX97EW9SFTm3KP02Ygd5A==",
+ "dependencies": {
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-button": "^9.6.1",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-tooltip": "^9.8.1",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1",
+ "embla-carousel": "^8.5.1",
+ "embla-carousel-autoplay": "^8.5.1",
+ "embla-carousel-fade": "^8.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-checkbox": {
+ "version": "9.5.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-checkbox/-/react-checkbox-9.5.1.tgz",
+ "integrity": "sha512-qbdywMhUd68Ox9uKjO5QlMwdRxLQSJiB7FR3hWZ72j01u9jMuWA1e+8JQMJtu2BMoDdiClnZSBro3XoJI3DLBQ==",
+ "dependencies": {
+ "@fluentui/react-field": "^9.4.1",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-label": "^9.3.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-color-picker": {
+ "version": "9.2.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-color-picker/-/react-color-picker-9.2.1.tgz",
+ "integrity": "sha512-IQPnEFQV5AViBs5/Ihd/lXDYUf8MGGaKekNJzNx6pq+ociWpcJ2yvtRY6aRVWXBoEJ6DmademhGko9OY9y0/Ew==",
+ "dependencies": {
+ "@ctrl/tinycolor": "^3.3.4",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-combobox": {
+ "version": "9.16.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-combobox/-/react-combobox-9.16.1.tgz",
+ "integrity": "sha512-8lO2mkw+PXkq41QGQkVZswB+VGMNx+z0AqB6Kb+DA6pFmqOMrCwsiR6XcyyLalKVdniZ5s6dgGdyA3lOaJlJ+w==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-field": "^9.4.1",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-portal": "^9.7.1",
+ "@fluentui/react-positioning": "^9.20.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-components": {
+ "version": "9.68.0",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-components/-/react-components-9.68.0.tgz",
+ "integrity": "sha512-I4fB5ecHCTLDpYGpffeyZHLI+rhFKXLuHtBxvumOMkglzksPd0kagF9Yew4I+EBmM/53TIcxFC53J0hciqwd3w==",
+ "dependencies": {
+ "@fluentui/react-accordion": "^9.8.1",
+ "@fluentui/react-alert": "9.0.0-beta.124",
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-avatar": "^9.9.1",
+ "@fluentui/react-badge": "^9.4.1",
+ "@fluentui/react-breadcrumb": "^9.3.1",
+ "@fluentui/react-button": "^9.6.1",
+ "@fluentui/react-card": "^9.4.1",
+ "@fluentui/react-carousel": "^9.8.1",
+ "@fluentui/react-checkbox": "^9.5.1",
+ "@fluentui/react-color-picker": "^9.2.1",
+ "@fluentui/react-combobox": "^9.16.1",
+ "@fluentui/react-dialog": "^9.14.1",
+ "@fluentui/react-divider": "^9.4.1",
+ "@fluentui/react-drawer": "^9.9.1",
+ "@fluentui/react-field": "^9.4.1",
+ "@fluentui/react-image": "^9.3.1",
+ "@fluentui/react-infobutton": "9.0.0-beta.102",
+ "@fluentui/react-infolabel": "^9.4.1",
+ "@fluentui/react-input": "^9.7.1",
+ "@fluentui/react-label": "^9.3.1",
+ "@fluentui/react-link": "^9.6.1",
+ "@fluentui/react-list": "^9.4.0",
+ "@fluentui/react-menu": "^9.19.1",
+ "@fluentui/react-message-bar": "^9.6.1",
+ "@fluentui/react-motion": "^9.10.0",
+ "@fluentui/react-nav": "^9.3.1",
+ "@fluentui/react-overflow": "^9.5.1",
+ "@fluentui/react-persona": "^9.5.1",
+ "@fluentui/react-popover": "^9.12.1",
+ "@fluentui/react-portal": "^9.7.1",
+ "@fluentui/react-positioning": "^9.20.1",
+ "@fluentui/react-progress": "^9.4.1",
+ "@fluentui/react-provider": "^9.22.1",
+ "@fluentui/react-radio": "^9.5.1",
+ "@fluentui/react-rating": "^9.3.1",
+ "@fluentui/react-search": "^9.3.1",
+ "@fluentui/react-select": "^9.4.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-skeleton": "^9.4.1",
+ "@fluentui/react-slider": "^9.5.1",
+ "@fluentui/react-spinbutton": "^9.5.1",
+ "@fluentui/react-spinner": "^9.7.1",
+ "@fluentui/react-swatch-picker": "^9.4.1",
+ "@fluentui/react-switch": "^9.4.1",
+ "@fluentui/react-table": "^9.18.1",
+ "@fluentui/react-tabs": "^9.9.1",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-tag-picker": "^9.7.1",
+ "@fluentui/react-tags": "^9.7.1",
+ "@fluentui/react-teaching-popover": "^9.6.1",
+ "@fluentui/react-text": "^9.6.1",
+ "@fluentui/react-textarea": "^9.6.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-toast": "^9.6.1",
+ "@fluentui/react-toolbar": "^9.6.1",
+ "@fluentui/react-tooltip": "^9.8.1",
+ "@fluentui/react-tree": "^9.12.1",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@fluentui/react-virtualizer": "9.0.0-alpha.101",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-context-selector": {
+ "version": "9.2.3",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-context-selector/-/react-context-selector-9.2.3.tgz",
+ "integrity": "sha512-xq15d8JYGlj32q8J25Iqy4Q99rS7J8Yfw1a6HUZqbAAQBAOkwTwO3LlS8RbX7E6WPf4XSKA0p5s3refv6DYAXg==",
+ "dependencies": {
+ "@fluentui/react-utilities": "^9.23.0",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0",
+ "scheduler": ">=0.19.0 <=0.23.0"
+ }
+ },
+ "node_modules/@fluentui/react-dialog": {
+ "version": "9.14.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-dialog/-/react-dialog-9.14.1.tgz",
+ "integrity": "sha512-erXbwcyMJHfo/RC+KcAWCz3Va9xJResecWp7D14SFYI43tq498p2TxJ1FVWnPyFLruDkWlZXczzVdyK5NaHfKQ==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-motion": "^9.10.0",
+ "@fluentui/react-motion-components-preview": "^0.8.0",
+ "@fluentui/react-portal": "^9.7.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-divider": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-divider/-/react-divider-9.4.1.tgz",
+ "integrity": "sha512-F66LnrQ9ttLrXEVD52utiJKK3Bv0e1tmY+e6fJlFQ1YPqDrbI2HCTcv6rWRqnmCDEsdpLBQRGJwET7SuAQCstw==",
+ "dependencies": {
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-drawer": {
+ "version": "9.9.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-drawer/-/react-drawer-9.9.1.tgz",
+ "integrity": "sha512-hSSMEqYaT2HGOdknHouQ2/XrnQSg/qACEo8x7BSkM2sH70JlVtLzqNXwvEvWgujE3I+X/o3nlRM8jXBy9U1R1A==",
+ "dependencies": {
+ "@fluentui/react-dialog": "^9.14.1",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-motion": "^9.10.0",
+ "@fluentui/react-portal": "^9.7.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-field": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-field/-/react-field-9.4.1.tgz",
+ "integrity": "sha512-Sr/4XKvv6Mhl+BzOQav4K6hKo/gJz5tmNMXGwICPEgpyLufuWi8rCyq/CWR3e7yERCVaaTxUK0Q5NHBivBf/Ow==",
+ "dependencies": {
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-label": "^9.3.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-icons": {
+ "version": "2.0.307",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.307.tgz",
+ "integrity": "sha512-HSXrzQ6o+RWPnNy68EJN2M/Dh9LAJ8l5U9zWfwaFWDgktMF7dJxItyckA5BsH6inFisi6cqKtazsq9oZdAj32A==",
+ "dependencies": {
+ "@griffel/react": "^1.0.0",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-image": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-image/-/react-image-9.3.1.tgz",
+ "integrity": "sha512-AEmwteKuejgfoLjnqY+OWLmFgWhKfbGfwXiOwxP+36k7psLcFp9nBAZc90Eh3wnvuMgGwmbT3WOyLxP4jF5D6A==",
+ "dependencies": {
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-infobutton": {
+ "version": "9.0.0-beta.102",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-infobutton/-/react-infobutton-9.0.0-beta.102.tgz",
+ "integrity": "sha512-3kA4F0Vga8Ds6JGlBajLCCDOo/LmPuS786Wg7ui4ZTDYVIMzy1yp2XuVcZniifBFvEp0HQCUoDPWUV0VI3FfzQ==",
+ "dependencies": {
+ "@fluentui/react-icons": "^2.0.237",
+ "@fluentui/react-jsx-runtime": "^9.0.36",
+ "@fluentui/react-label": "^9.1.68",
+ "@fluentui/react-popover": "^9.9.6",
+ "@fluentui/react-tabster": "^9.21.0",
+ "@fluentui/react-theme": "^9.1.19",
+ "@fluentui/react-utilities": "^9.18.7",
+ "@griffel/react": "^1.5.14",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-infolabel": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-infolabel/-/react-infolabel-9.4.1.tgz",
+ "integrity": "sha512-oQMu15VbOBBPb0kSHelws1iMfR7dXCh1/nK4FBM7nOQCDZY1km1mbE4hYRXHHw6Z71JXpBSsN9Yb5z+59Vtbxw==",
+ "dependencies": {
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-label": "^9.3.1",
+ "@fluentui/react-popover": "^9.12.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.8.0 <19.0.0",
+ "@types/react-dom": ">=16.8.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.8.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-input": {
+ "version": "9.7.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-input/-/react-input-9.7.1.tgz",
+ "integrity": "sha512-2qzboPi/gOIEKWR8Kz18u+V/oDqp6vI5bDsT+mSDbH5qzegBOoMFUSsTH75lM/AC+fxGYLQWeUhT0yEzVhS7eg==",
+ "dependencies": {
+ "@fluentui/react-field": "^9.4.1",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-jsx-runtime": {
+ "version": "9.1.3",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-jsx-runtime/-/react-jsx-runtime-9.1.3.tgz",
+ "integrity": "sha512-MS5em+pV+xLskAF1BJCXUnfjacWX8lpjvxlaZo4rLNZxyiUPJ2C71bMFhOMsAvTWmbGaTi4CDfK6fSmBQov48Q==",
+ "dependencies": {
+ "@fluentui/react-utilities": "^9.23.0",
+ "@swc/helpers": "^0.5.1",
+ "react-is": "^17.0.2"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-label": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-label/-/react-label-9.3.1.tgz",
+ "integrity": "sha512-OqF3xrl66s8mrg56X2MtSUIArwMwFcmO2j2NBwargAreH4F/kyjzwYVe+ZImO1uRxg67sjriMXmlraebBEiOIg==",
+ "dependencies": {
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-link": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-link/-/react-link-9.6.1.tgz",
+ "integrity": "sha512-xt2SKlInnJLImmusqOTw1yR6uQBW/xjIXpQPW3tKYXABmxvjSqBK9Pru0oJJARI1nATEB1UoJ442A7eiQNqRtg==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-list": {
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-list/-/react-list-9.4.0.tgz",
+ "integrity": "sha512-NONtY5oBbmAxv/bElXHZ1IzzgtoBkDH3qYMOQx2DvOFBMSCPCHk7GQUwCAt/ACf1uer1bpFQDVcDRPyaUUPnJw==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-checkbox": "^9.5.1",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.8.0 <19.0.0",
+ "@types/react-dom": ">=16.8.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.8.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-menu": {
+ "version": "9.19.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-menu/-/react-menu-9.19.1.tgz",
+ "integrity": "sha512-DtoH1HnIStLGwV4lrDyhyPZnGUkXkEb9OpHBVHn2Jwuy2RjlRJ2HOfwXi9JUC/Mw8bwZPS4YdTGPOxUVt+jCUQ==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-portal": "^9.7.1",
+ "@fluentui/react-positioning": "^9.20.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-message-bar": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-message-bar/-/react-message-bar-9.6.1.tgz",
+ "integrity": "sha512-4pSbP7Y+Fh9exS7isez7peVtmBRNUDNuQS96w8ErAFkKly+OnM6hhuA53rCixFfP8zf2zhg4hKflRDxyItBxJw==",
+ "dependencies": {
+ "@fluentui/react-button": "^9.6.1",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-link": "^9.6.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1",
+ "react-transition-group": "^4.4.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.8.0 <19.0.0",
+ "@types/react-dom": ">=16.8.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.8.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-motion": {
+ "version": "9.10.0",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-motion/-/react-motion-9.10.0.tgz",
+ "integrity": "sha512-USC2Q6Mapg2yf1qqitwHvoTsYrojW/rRgvInTnNrydEO7xSOukV+7NwV/KsxltNYUbDKtZvtUYDZ21YtjbCKuA==",
+ "dependencies": {
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.8.0 <19.0.0",
+ "@types/react-dom": ">=16.8.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.8.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-motion-components-preview": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-motion-components-preview/-/react-motion-components-preview-0.8.0.tgz",
+ "integrity": "sha512-SrN4dokZomTFfSni4fzgqPUe6mE+lMhf0ElhffT3ULsbtCDfieOrOD6MqZo+hpX/0Zt775M22Ci2nptCG/YeBQ==",
+ "dependencies": {
+ "@fluentui/react-motion": "*",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-nav": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-nav/-/react-nav-9.3.1.tgz",
+ "integrity": "sha512-ZNKodU494j/TwuV4KeoCYZaseBJ9FhIp4KRwj5kI8rzF+65Z9jVDPV4tfJHuvAYxfGY0dgmwKM1G+IpW4k7WMg==",
+ "dependencies": {
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-button": "^9.6.1",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-divider": "^9.4.1",
+ "@fluentui/react-drawer": "^9.9.1",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-motion": "^9.10.0",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-tooltip": "^9.8.1",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-overflow": {
+ "version": "9.5.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-overflow/-/react-overflow-9.5.1.tgz",
+ "integrity": "sha512-Rqpd09jlNdcjDpyH3q8xC6L9pv8ghIEGfDextj4nDJdZfMq7fWwj8w+2LdTUmUwh/tFvbJ4N8MRk0gDBLzgRlA==",
+ "dependencies": {
+ "@fluentui/priority-overflow": "^9.1.15",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-persona": {
+ "version": "9.5.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-persona/-/react-persona-9.5.1.tgz",
+ "integrity": "sha512-SHRaVA++WlCA6ObkjsdKcwKSSmwjebArOBV2JNiApOSC84L0ngNA2utMRt5v/xF1JFSMVVSk3osWyyj3HQvdNQ==",
+ "dependencies": {
+ "@fluentui/react-avatar": "^9.9.1",
+ "@fluentui/react-badge": "^9.4.1",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-popover": {
+ "version": "9.12.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-popover/-/react-popover-9.12.1.tgz",
+ "integrity": "sha512-ycbUdkiK0TNb5lDoNvGHdl8/k3EenPrBbjUCTCQW//jegqsB+2zqZldh0vaOSLcGG2KjyOf3LOeAqME7YxSEuw==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-portal": "^9.7.1",
+ "@fluentui/react-positioning": "^9.20.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-portal": {
+ "version": "9.7.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-portal/-/react-portal-9.7.1.tgz",
+ "integrity": "sha512-fKoXeSKzPfakpoOSncQa53DbF4v0jEgn6HBuJF4gQs1FEBx5S+l7d17ci3CUeWiVRZuWdxixjZAabXuxu9ghPA==",
+ "dependencies": {
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1",
+ "use-disposable": "^1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-positioning": {
+ "version": "9.20.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-positioning/-/react-positioning-9.20.1.tgz",
+ "integrity": "sha512-ljh+A7tHWBSoKEQbeeN6+6XSCDW4gWep9IQdNKupUornsbUyqwZ8S320QkD3dFbN1Wg8Rb9IMqg0iSNZdf6aIg==",
+ "dependencies": {
+ "@floating-ui/devtools": "0.2.1",
+ "@floating-ui/dom": "^1.6.12",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1",
+ "use-sync-external-store": "^1.2.0"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-progress": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-progress/-/react-progress-9.4.1.tgz",
+ "integrity": "sha512-Yd08AvW0lERd4mAByt8S9CPgNxlBKE9JvO64n3mzOz8v5YC6LpUTJhuD6DV+UY/mOzPAJE9sfpy1gX4b4iEQRg==",
+ "dependencies": {
+ "@fluentui/react-field": "^9.4.1",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-provider": {
+ "version": "9.22.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-provider/-/react-provider-9.22.1.tgz",
+ "integrity": "sha512-/Ipm6BqyButSkvwWbQcjr08bJoNBDT3DICyXUyQvcV9WdwrjzxCNo2SrxfCYk6MJTGExm5McyJsPLW1Qu3ilTA==",
+ "dependencies": {
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/core": "^1.16.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-radio": {
+ "version": "9.5.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-radio/-/react-radio-9.5.1.tgz",
+ "integrity": "sha512-J2d7iLYxrQieK44KTtFMr8shp8le8LG+eLpy2yqgAsv2FrmLiEbz8mp89VZq+dBJcxQbFwHAal+bfveB7nkuag==",
+ "dependencies": {
+ "@fluentui/react-field": "^9.4.1",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-label": "^9.3.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-rating": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-rating/-/react-rating-9.3.1.tgz",
+ "integrity": "sha512-KwiYQvL59KhieWTR6eIHvHQzNf9AdkjSSYVSvp49Ynvc/2lh1IFU6ZbZ8MxEF1XFJlb1yCqsy5nyQFIxl+vO4Q==",
+ "dependencies": {
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.8.0 <19.0.0",
+ "@types/react-dom": ">=16.8.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.8.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-search": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-search/-/react-search-9.3.1.tgz",
+ "integrity": "sha512-J1edVrFZh433EjlV7NHxGCAf5yMjdZJkM20wfqWFQx4eA9LUEIJObXaic2KaqSGogvXKHHTXB/SYZ1AoQOmA7g==",
+ "dependencies": {
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-input": "^9.7.1",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-select": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-select/-/react-select-9.4.1.tgz",
+ "integrity": "sha512-9JqqtYD+lp4xXC/Kp2Plt9fh5GNWaIvbZoQj724AhRzNIlBxWIMpnZWpVLma1HeLeXWx4wzP+9N8j1iTjnQiJQ==",
+ "dependencies": {
+ "@fluentui/react-field": "^9.4.1",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-shared-contexts": {
+ "version": "9.24.0",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-shared-contexts/-/react-shared-contexts-9.24.0.tgz",
+ "integrity": "sha512-GA+uLv711E+YGrAP/aVB15ozvNCiuB2ZrPDC9aYF+A6sRDxoZZG8VgHjhQ/YWJfVjDXLky4ihirknzsW1sjGtg==",
+ "dependencies": {
+ "@fluentui/react-theme": "^9.1.24",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-skeleton": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-skeleton/-/react-skeleton-9.4.1.tgz",
+ "integrity": "sha512-UhI/ymAC4PKCtBpMaNLJRGxwtinFhaZPa8Yx61fjwlsLNUmsvgFo3w2mbnBi74aYJ0WPTZ0DNuI9qO/pIZe9yg==",
+ "dependencies": {
+ "@fluentui/react-field": "^9.4.1",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-slider": {
+ "version": "9.5.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-slider/-/react-slider-9.5.1.tgz",
+ "integrity": "sha512-NThzQIUfC9YJMjrTNquTZvNjIzPShfxqaZaV/1Mn30ahZoUHwUxCeNakMZQWo3+xNHcAR1G8PJ+twXyIUnPu0Q==",
+ "dependencies": {
+ "@fluentui/react-field": "^9.4.1",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-spinbutton": {
+ "version": "9.5.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-spinbutton/-/react-spinbutton-9.5.1.tgz",
+ "integrity": "sha512-d10qWQ46TYyMiR9R0x6UdP1J5X7zt72/dU6MwfSDAsoMKhb1I5P225QFEDIMlfYYSv734VptfjqrZ5wPi+3b5g==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-field": "^9.4.1",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-spinner": {
+ "version": "9.7.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-spinner/-/react-spinner-9.7.1.tgz",
+ "integrity": "sha512-fJvCf1qmH9GfJE18FF+k11iqrBn8OvuVme8WDbgf1YN9vPoK92ONCS1NZlsspYR7ady62QZyPJ2tVnAD/oN/UA==",
+ "dependencies": {
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-label": "^9.3.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-swatch-picker": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-swatch-picker/-/react-swatch-picker-9.4.1.tgz",
+ "integrity": "sha512-fnQkiCY1zgU/Gym1+NDKLGuDlZ7RVQ6P57QFzA4dA2vVKKlF+ixabRgbgNBJKYF38yqoc3DHCHG7ku7HHrw+YA==",
+ "dependencies": {
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-field": "^9.4.1",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.8.0 <19.0.0",
+ "@types/react-dom": ">=16.8.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.8.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-switch": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-switch/-/react-switch-9.4.1.tgz",
+ "integrity": "sha512-BPKBL6oUr2Gh/BiPzXJBpRqfJWc3A8pENcuwJCnU53wa5chaqggGTPVhrF36alTTg5Y6vhD3vrwxzPQ+IQBAIQ==",
+ "dependencies": {
+ "@fluentui/react-field": "^9.4.1",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-label": "^9.3.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-table": {
+ "version": "9.18.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-table/-/react-table-9.18.1.tgz",
+ "integrity": "sha512-RAwI2/246298S9DCjN9ioGTwcOM8dovtbwzKIhsgx0rMmjq6roMkpR90Hvpai14o+fumdNqol7gsVWIMUjiwRQ==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-avatar": "^9.9.1",
+ "@fluentui/react-checkbox": "^9.5.1",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-radio": "^9.5.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-tabs": {
+ "version": "9.9.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-tabs/-/react-tabs-9.9.1.tgz",
+ "integrity": "sha512-EvoaDArHkcjEA6ngJdh0Vf+DkVUyIS8FNMUwE88BDL2L47GpKbXUjUKM245j7qAV+61g7020YzLXH5wOyUxBBw==",
+ "dependencies": {
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-tabster": {
+ "version": "9.26.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-tabster/-/react-tabster-9.26.1.tgz",
+ "integrity": "sha512-uQTW73VKzUnABo6nV4Muv5W1c6RPtOjF8xq+EliZVds2kAxAUTKAr8cZUqNd8xoD4X8vtG4kNdOPyN9+OR9yjA==",
+ "dependencies": {
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1",
+ "keyborg": "^2.6.0",
+ "tabster": "^8.5.5"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-tag-picker": {
+ "version": "9.7.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-tag-picker/-/react-tag-picker-9.7.1.tgz",
+ "integrity": "sha512-kBr6Q9z8LxBdp46AnvIGwr1ZY3eRiATLCxytlRT2jb5/PxsbGAK6Q7Rf9uZzdYkKfUZEr3Jsj1YgebeId+PjoA==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-combobox": "^9.16.1",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-field": "^9.4.1",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-portal": "^9.7.1",
+ "@fluentui/react-positioning": "^9.20.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-tags": "^9.7.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-tags": {
+ "version": "9.7.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-tags/-/react-tags-9.7.1.tgz",
+ "integrity": "sha512-irIJevmTyWbUnBhLOPyabkRl+B/mgy6kOLl0bEPM7d8yl347ntPgje/x/Dm367x6IfDoFIjJD20OG5T6ZuKXVA==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-avatar": "^9.9.1",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-teaching-popover": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-teaching-popover/-/react-teaching-popover-9.6.1.tgz",
+ "integrity": "sha512-38aLOnP3Fdl+EENFxsXj+v21VC8ASC0lVk52L0NibCQlFUeWstL/B7mJRamJFWsf0U4yVzTfd+XgAKIFHiLRbg==",
+ "dependencies": {
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-button": "^9.6.1",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-popover": "^9.12.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1",
+ "use-sync-external-store": "^1.2.0"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.8.0 <19.0.0",
+ "@types/react-dom": ">=16.8.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.8.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-text": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-text/-/react-text-9.6.1.tgz",
+ "integrity": "sha512-Wjt8Wr+FfYt5WrHpif4C16HVO8bDtT59St42qKW0A9YEO50oiQDBIu0EH5b6Y2tPFHtw9Cixq0YQZS2JyRCNrg==",
+ "dependencies": {
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-textarea": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-textarea/-/react-textarea-9.6.1.tgz",
+ "integrity": "sha512-NA4DzqjEQHUaeYWTAvJXpCqYK24wYEzdCgzpsaPKudw+Yr4do+HCyzd42GL0qoG6Uuq9HbNBsancPEHtooI3PQ==",
+ "dependencies": {
+ "@fluentui/react-field": "^9.4.1",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-theme": {
+ "version": "9.1.24",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-theme/-/react-theme-9.1.24.tgz",
+ "integrity": "sha512-OhVKYD7CMYHxzJEn4PtIszledj8hbQJNWBMfIZsp4Sytdp9vCi0txIQUx4BhS1WqtQPhNGCF16eW9Q3NRrnIrQ==",
+ "dependencies": {
+ "@fluentui/tokens": "1.0.0-alpha.21",
+ "@swc/helpers": "^0.5.1"
+ }
+ },
+ "node_modules/@fluentui/react-toast": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-toast/-/react-toast-9.6.1.tgz",
+ "integrity": "sha512-aukJbAc8TuE8qU7ohQE+m10ff9gHpxegUQJI3Fy7poSY/uvzGFu9M/mr9syIqGNMLuR2IJ8j/nFtKPJvTgIvaw==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-motion": "^9.10.0",
+ "@fluentui/react-motion-components-preview": "^0.8.0",
+ "@fluentui/react-portal": "^9.7.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-toolbar": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-toolbar/-/react-toolbar-9.6.1.tgz",
+ "integrity": "sha512-DYajA8NAhJi0rukgjzhHLlw4PwK1bJWAwJEBdBPmk9cc9s37wYFhPXmqo1choM+aGjyoY8ilv4C5iCbsQPlYoA==",
+ "dependencies": {
+ "@fluentui/react-button": "^9.6.1",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-divider": "^9.4.1",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-radio": "^9.5.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-tooltip": {
+ "version": "9.8.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-tooltip/-/react-tooltip-9.8.1.tgz",
+ "integrity": "sha512-k1Lk01ZE6TiSOsLI3iM5lZltj6spVNVF1EavxjcpY2PRTYH7BPp/sb49y2Yjb6U/z4r7W5mZYfSrEvXhHUlGvA==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-portal": "^9.7.1",
+ "@fluentui/react-positioning": "^9.20.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-tree": {
+ "version": "9.12.1",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-tree/-/react-tree-9.12.1.tgz",
+ "integrity": "sha512-iC6dw1CgOn/iDplSJQFHMff97DSLH1VdkKu6jjGi55/sRY/2sMk1JfLhWhK5ruQLmlIbZ2OIEycFSsBty6/BKA==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-aria": "^9.16.0",
+ "@fluentui/react-avatar": "^9.9.1",
+ "@fluentui/react-button": "^9.6.1",
+ "@fluentui/react-checkbox": "^9.5.1",
+ "@fluentui/react-context-selector": "^9.2.3",
+ "@fluentui/react-icons": "^2.0.245",
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-motion": "^9.10.0",
+ "@fluentui/react-motion-components-preview": "^0.8.0",
+ "@fluentui/react-radio": "^9.5.1",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-tabster": "^9.26.1",
+ "@fluentui/react-theme": "^9.1.24",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-utilities": {
+ "version": "9.23.0",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-utilities/-/react-utilities-9.23.0.tgz",
+ "integrity": "sha512-OlAzxBUoHY0URL5DKt1ckV7lzFtPzWCWV8nhd+4or7KDFk8P1PL3jUo/zqCZ5yLq2KplO7/G0h3SOyeFlZte7Q==",
+ "dependencies": {
+ "@fluentui/keyboard-keys": "^9.0.8",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/react-virtualizer": {
+ "version": "9.0.0-alpha.101",
+ "resolved": "https://registry.npmjs.org/@fluentui/react-virtualizer/-/react-virtualizer-9.0.0-alpha.101.tgz",
+ "integrity": "sha512-ot8mfg759kF16NEPTfYByZm5/Sl2MmSsSw9WiMYHjG/y59QM3iKDKm2tlqeE88/HDEmYdrlRHbh7CqiJF7P+PA==",
+ "deprecated": "Deprecating react-virtualizer in Fluent core - migrating to fluentui-contrib repo for stable release",
+ "dependencies": {
+ "@fluentui/react-jsx-runtime": "^9.1.3",
+ "@fluentui/react-shared-contexts": "^9.24.0",
+ "@fluentui/react-utilities": "^9.23.0",
+ "@griffel/react": "^1.5.22",
+ "@swc/helpers": "^0.5.1"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.0 <19.0.0",
+ "@types/react-dom": ">=16.9.0 <19.0.0",
+ "react": ">=16.14.0 <19.0.0",
+ "react-dom": ">=16.14.0 <19.0.0"
+ }
+ },
+ "node_modules/@fluentui/tokens": {
+ "version": "1.0.0-alpha.21",
+ "resolved": "https://registry.npmjs.org/@fluentui/tokens/-/tokens-1.0.0-alpha.21.tgz",
+ "integrity": "sha512-xQ1T56sNgDFGl+kJdIwhz67mHng8vcwO7Dvx5Uja4t+NRULQBgMcJ4reUo4FGF3TjufHj08pP0/OnKQgnOaSVg==",
+ "dependencies": {
+ "@swc/helpers": "^0.5.1"
+ }
+ },
+ "node_modules/@griffel/core": {
+ "version": "1.19.2",
+ "resolved": "https://registry.npmjs.org/@griffel/core/-/core-1.19.2.tgz",
+ "integrity": "sha512-WkB/QQkjy9dE4vrNYGhQvRRUHFkYVOuaznVOMNTDT4pS9aTJ9XPrMTXXlkpcwaf0D3vNKoerj4zAwnU2lBzbOg==",
+ "dependencies": {
+ "@emotion/hash": "^0.9.0",
+ "@griffel/style-types": "^1.3.0",
+ "csstype": "^3.1.3",
+ "rtl-css-js": "^1.16.1",
+ "stylis": "^4.2.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@griffel/react": {
+ "version": "1.5.30",
+ "resolved": "https://registry.npmjs.org/@griffel/react/-/react-1.5.30.tgz",
+ "integrity": "sha512-1q4ojbEVFY5YA0j1NamP0WWF4BKh+GHsVugltDYeEgEaVbH3odJ7tJabuhQgY+7Nhka0pyEFWSiHJev0K3FSew==",
+ "dependencies": {
+ "@griffel/core": "^1.19.2",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0 <20.0.0"
+ }
+ },
+ "node_modules/@griffel/style-types": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@griffel/style-types/-/style-types-1.3.0.tgz",
+ "integrity": "sha512-bHwD3sUE84Xwv4dH011gOKe1jul77M1S6ZFN9Tnq8pvZ48UMdY//vtES6fv7GRS5wXYT4iqxQPBluAiYAfkpmw==",
+ "dependencies": {
+ "csstype": "^3.1.3"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
+ "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
+ "deprecated": "Use @eslint/config-array instead",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.3",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "deprecated": "Use @eslint/object-schema instead",
+ "dev": true
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.12",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
+ "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",
+ "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.29",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
+ "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-beta.27",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
+ "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==",
+ "dev": true
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.2.tgz",
+ "integrity": "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.2.tgz",
+ "integrity": "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.2.tgz",
+ "integrity": "sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.2.tgz",
+ "integrity": "sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.2.tgz",
+ "integrity": "sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.2.tgz",
+ "integrity": "sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.2.tgz",
+ "integrity": "sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.2.tgz",
+ "integrity": "sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.2.tgz",
+ "integrity": "sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.2.tgz",
+ "integrity": "sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.2.tgz",
+ "integrity": "sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.2.tgz",
+ "integrity": "sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.2.tgz",
+ "integrity": "sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.2.tgz",
+ "integrity": "sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.2.tgz",
+ "integrity": "sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.2.tgz",
+ "integrity": "sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.2.tgz",
+ "integrity": "sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.2.tgz",
+ "integrity": "sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.2.tgz",
+ "integrity": "sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.2.tgz",
+ "integrity": "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.17",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
+ "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz",
+ "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "20.19.9",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz",
+ "integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==",
+ "dev": true,
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.15",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
+ "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="
+ },
+ "node_modules/@types/react": {
+ "version": "18.3.23",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz",
+ "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.3.7",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
+ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
+ "peerDependencies": {
+ "@types/react": "^18.0.0"
+ }
+ },
+ "node_modules/@types/semver": {
+ "version": "7.7.0",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz",
+ "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz",
+ "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.5.1",
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/type-utils": "6.21.0",
+ "@typescript-eslint/utils": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.4",
+ "natural-compare": "^1.4.0",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
+ "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
+ "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
+ "dev": true,
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz",
+ "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "9.0.3",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz",
+ "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@types/json-schema": "^7.0.12",
+ "@types/semver": "^7.5.0",
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
+ "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": {
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ts-api-utils": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
+ "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz",
+ "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
+ "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
+ "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
+ "dev": true,
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz",
+ "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "9.0.3",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
+ "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/semver": {
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/ts-api-utils": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
+ "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz",
+ "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "@typescript-eslint/utils": "6.21.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
+ "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
+ "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
+ "dev": true,
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz",
+ "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "9.0.3",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz",
+ "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@types/json-schema": "^7.0.12",
+ "@types/semver": "^7.5.0",
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
+ "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/semver": {
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/ts-api-utils": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
+ "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
+ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
+ "dev": true
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz",
+ "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.28.0",
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+ "@rolldown/pluginutils": "1.0.0-beta.27",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.17.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+ "dev": true
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/arg": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
+ "dev": true
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/async": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
+ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
+ "dev": true
+ },
+ "node_modules/autoprefixer": {
+ "version": "10.4.21",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
+ "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "browserslist": "^4.24.4",
+ "caniuse-lite": "^1.0.30001702",
+ "fraction.js": "^4.3.7",
+ "normalize-range": "^0.1.2",
+ "picocolors": "^1.1.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.25.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz",
+ "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001726",
+ "electron-to-chromium": "^1.5.173",
+ "node-releases": "^2.0.19",
+ "update-browserslist-db": "^1.1.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase-css": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001731",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz",
+ "integrity": "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dev": true,
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/commander": {
+ "version": "13.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz",
+ "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
+ "dev": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "dev": true,
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
+ },
+ "node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/didyoumean": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
+ "dev": true
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dlv": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
+ "dev": true
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.192",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.192.tgz",
+ "integrity": "sha512-rP8Ez0w7UNw/9j5eSXCe10o1g/8B1P5SM90PCCMVkIRQn2R0LEHWz4Eh9RnxkniuDe1W0cTSOB3MLlkTGDcuCg==",
+ "dev": true
+ },
+ "node_modules/email-addresses": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz",
+ "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==",
+ "dev": true
+ },
+ "node_modules/embla-carousel": {
+ "version": "8.6.0",
+ "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz",
+ "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="
+ },
+ "node_modules/embla-carousel-autoplay": {
+ "version": "8.6.0",
+ "resolved": "https://registry.npmjs.org/embla-carousel-autoplay/-/embla-carousel-autoplay-8.6.0.tgz",
+ "integrity": "sha512-OBu5G3nwaSXkZCo1A6LTaFMZ8EpkYbwIaH+bPqdBnDGQ2fh4+NbzjXjs2SktoPNKCtflfVMc75njaDHOYXcrsA==",
+ "peerDependencies": {
+ "embla-carousel": "8.6.0"
+ }
+ },
+ "node_modules/embla-carousel-fade": {
+ "version": "8.6.0",
+ "resolved": "https://registry.npmjs.org/embla-carousel-fade/-/embla-carousel-fade-8.6.0.tgz",
+ "integrity": "sha512-qaYsx5mwCz72ZrjlsXgs1nKejSrW+UhkbOMwLgfRT7w2LtdEB03nPRI06GHuHv5ac2USvbEiX2/nAHctcDwvpg==",
+ "peerDependencies": {
+ "embla-carousel": "8.6.0"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "node_modules/esbuild": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.21.5",
+ "@esbuild/android-arm": "0.21.5",
+ "@esbuild/android-arm64": "0.21.5",
+ "@esbuild/android-x64": "0.21.5",
+ "@esbuild/darwin-arm64": "0.21.5",
+ "@esbuild/darwin-x64": "0.21.5",
+ "@esbuild/freebsd-arm64": "0.21.5",
+ "@esbuild/freebsd-x64": "0.21.5",
+ "@esbuild/linux-arm": "0.21.5",
+ "@esbuild/linux-arm64": "0.21.5",
+ "@esbuild/linux-ia32": "0.21.5",
+ "@esbuild/linux-loong64": "0.21.5",
+ "@esbuild/linux-mips64el": "0.21.5",
+ "@esbuild/linux-ppc64": "0.21.5",
+ "@esbuild/linux-riscv64": "0.21.5",
+ "@esbuild/linux-s390x": "0.21.5",
+ "@esbuild/linux-x64": "0.21.5",
+ "@esbuild/netbsd-x64": "0.21.5",
+ "@esbuild/openbsd-x64": "0.21.5",
+ "@esbuild/sunos-x64": "0.21.5",
+ "@esbuild/win32-arm64": "0.21.5",
+ "@esbuild/win32-ia32": "0.21.5",
+ "@esbuild/win32-x64": "0.21.5"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
+ "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
+ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.1",
+ "@humanwhocodes/config-array": "^0.13.0",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz",
+ "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.4.20",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz",
+ "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==",
+ "dev": true,
+ "peerDependencies": {
+ "eslint": ">=8.40"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.19.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
+ "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/filename-reserved-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
+ "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/filenamify": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz",
+ "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==",
+ "dev": true,
+ "dependencies": {
+ "filename-reserved-regex": "^2.0.0",
+ "strip-outer": "^1.0.1",
+ "trim-repeated": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-cache-dir": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
+ "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
+ "dev": true,
+ "dependencies": {
+ "commondir": "^1.0.1",
+ "make-dir": "^3.0.2",
+ "pkg-dir": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/avajs/find-cache-dir?sponsor=1"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/fraction.js": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
+ "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "patreon",
+ "url": "https://github.com/sponsors/rawify"
+ }
+ },
+ "node_modules/framer-motion": {
+ "version": "10.18.0",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.18.0.tgz",
+ "integrity": "sha512-oGlDh1Q1XqYPksuTD/usb0I70hq95OUzmL9+6Zd+Hs4XV0oaISBa/UUMSjYiq6m8EUF32132mOJ8xVZS+I0S6w==",
+ "dependencies": {
+ "tslib": "^2.4.0"
+ },
+ "optionalDependencies": {
+ "@emotion/is-prop-valid": "^0.8.2"
+ },
+ "peerDependencies": {
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "11.3.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz",
+ "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/gh-pages": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.3.0.tgz",
+ "integrity": "sha512-Ot5lU6jK0Eb+sszG8pciXdjMXdBJ5wODvgjR+imihTqsUWF2K6dJ9HST55lgqcs8wWcw6o6wAsUzfcYRhJPXbA==",
+ "dev": true,
+ "dependencies": {
+ "async": "^3.2.4",
+ "commander": "^13.0.0",
+ "email-addresses": "^5.0.0",
+ "filenamify": "^4.3.0",
+ "find-cache-dir": "^3.3.1",
+ "fs-extra": "^11.1.1",
+ "globby": "^11.1.0"
+ },
+ "bin": {
+ "gh-pages": "bin/gh-pages.js",
+ "gh-pages-clean": "bin/gh-pages-clean.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "dev": true,
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "dev": true,
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "1.21.7",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
+ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
+ "dev": true,
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/keyborg": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/keyborg/-/keyborg-2.6.0.tgz",
+ "integrity": "sha512-o5kvLbuTF+o326CMVYpjlaykxqYP9DphFQZ2ZpgrvBouyvOxyEB7oqe8nOLFpiV5VCtz0D3pt8gXQYWpLpBnmA=="
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lilconfig": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
+ "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antonk52"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "node_modules/mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "dev": true,
+ "dependencies": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.19",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
+ "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
+ "dev": true
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-hash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "dev": true
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.6",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-import": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
+ "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "node_modules/postcss-js": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
+ "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
+ "dev": true,
+ "dependencies": {
+ "camelcase-css": "^2.0.1"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.21"
+ }
+ },
+ "node_modules/postcss-load-config": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
+ "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "lilconfig": "^3.0.0",
+ "yaml": "^2.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ },
+ "peerDependencies": {
+ "postcss": ">=8.0.9",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "postcss": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/postcss-nested": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
+ "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "postcss-selector-parser": "^6.1.1"
+ },
+ "engines": {
+ "node": ">=12.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+ "dev": true,
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+ "dev": true
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/prop-types/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/react-dom/node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "17.0.2",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
+ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
+ },
+ "node_modules/react-refresh": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
+ "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
+ },
+ "node_modules/read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+ "dev": true,
+ "dependencies": {
+ "pify": "^2.3.0"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.10",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
+ "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.16.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.2.tgz",
+ "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.46.2",
+ "@rollup/rollup-android-arm64": "4.46.2",
+ "@rollup/rollup-darwin-arm64": "4.46.2",
+ "@rollup/rollup-darwin-x64": "4.46.2",
+ "@rollup/rollup-freebsd-arm64": "4.46.2",
+ "@rollup/rollup-freebsd-x64": "4.46.2",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.46.2",
+ "@rollup/rollup-linux-arm-musleabihf": "4.46.2",
+ "@rollup/rollup-linux-arm64-gnu": "4.46.2",
+ "@rollup/rollup-linux-arm64-musl": "4.46.2",
+ "@rollup/rollup-linux-loongarch64-gnu": "4.46.2",
+ "@rollup/rollup-linux-ppc64-gnu": "4.46.2",
+ "@rollup/rollup-linux-riscv64-gnu": "4.46.2",
+ "@rollup/rollup-linux-riscv64-musl": "4.46.2",
+ "@rollup/rollup-linux-s390x-gnu": "4.46.2",
+ "@rollup/rollup-linux-x64-gnu": "4.46.2",
+ "@rollup/rollup-linux-x64-musl": "4.46.2",
+ "@rollup/rollup-win32-arm64-msvc": "4.46.2",
+ "@rollup/rollup-win32-ia32-msvc": "4.46.2",
+ "@rollup/rollup-win32-x64-msvc": "4.46.2",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/rtl-css-js": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz",
+ "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==",
+ "dependencies": {
+ "@babel/runtime": "^7.1.2"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+ "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "peer": true,
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/string-width/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/string-width/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strip-outer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
+ "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-outer/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/stylis": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz",
+ "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ=="
+ },
+ "node_modules/sucrase": {
+ "version": "3.35.0",
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
+ "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "glob": "^10.3.10",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "bin": {
+ "sucrase": "bin/sucrase",
+ "sucrase-node": "bin/sucrase-node"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/sucrase/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/sucrase/node_modules/commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/sucrase/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/sucrase/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tabster": {
+ "version": "8.5.6",
+ "resolved": "https://registry.npmjs.org/tabster/-/tabster-8.5.6.tgz",
+ "integrity": "sha512-2vfrRGrx8O9BjdrtSlVA5fvpmbq5HQBRN13XFRg6LAvZ1Fr3QdBnswgT4YgFS5Bhoo5nxwgjRaRueI2Us/dv7g==",
+ "dependencies": {
+ "keyborg": "2.6.0",
+ "tslib": "^2.8.1"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-linux-x64-gnu": "4.40.0"
+ }
+ },
+ "node_modules/tabster/node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.40.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz",
+ "integrity": "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/tailwindcss": {
+ "version": "3.4.17",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz",
+ "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==",
+ "dev": true,
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.6.0",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.2",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.21.6",
+ "lilconfig": "^3.1.3",
+ "micromatch": "^4.0.8",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.1.1",
+ "postcss": "^8.4.47",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.2",
+ "postcss-nested": "^6.2.0",
+ "postcss-selector-parser": "^6.1.2",
+ "resolve": "^1.22.8",
+ "sucrase": "^3.35.0"
+ },
+ "bin": {
+ "tailwind": "lib/cli.js",
+ "tailwindcss": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "dev": true,
+ "dependencies": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "node_modules/thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "dev": true,
+ "dependencies": {
+ "thenify": ">= 3.1.0 < 4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/trim-repeated": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
+ "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/trim-repeated/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
+ "dev": true
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.8.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
+ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true
+ },
+ "node_modules/universalify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
+ "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/use-disposable": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/use-disposable/-/use-disposable-1.0.4.tgz",
+ "integrity": "sha512-j83t6AMLWUyb5zwlTDqf6dP9LezM9R0yTbI/b6olmdaGtCKQUe9pgJWV6dRaaQLcozypjIEp4EmZr2DkZGKLSg==",
+ "peerDependencies": {
+ "@types/react": ">=16.8.0 <19.0.0",
+ "@types/react-dom": ">=16.8.0 <19.0.0",
+ "react": ">=16.8.0 <19.0.0",
+ "react-dom": ">=16.8.0 <19.0.0"
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
+ "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true
+ },
+ "node_modules/vite": {
+ "version": "5.4.19",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz",
+ "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==",
+ "dev": true,
+ "dependencies": {
+ "esbuild": "^0.21.3",
+ "postcss": "^8.4.43",
+ "rollup": "^4.20.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ },
+ "node_modules/yaml": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",
+ "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==",
+ "dev": true,
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/code/package.json b/code/package.json
new file mode 100644
index 0000000..c577226
--- /dev/null
+++ b/code/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "microsoft-ai-accelerators-landing",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "npm run generate-cards && vite",
+ "build": "npm run generate-cards && tsc -b && vite build",
+ "lint": "eslint .",
+ "preview": "vite preview",
+ "generate-cards": "node scripts/generate-card-data.js",
+ "predeploy": "npm run build",
+ "deploy": "gh-pages -d dist"
+ },
+ "dependencies": {
+ "@fluentui/react-components": "^9.46.0",
+ "@fluentui/react-icons": "^2.0.224",
+ "framer-motion": "^10.18.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@eslint/js": "^8.56.0",
+ "@types/node": "^20.11.0",
+ "@types/react": "^18.2.48",
+ "@types/react-dom": "^18.2.18",
+ "@typescript-eslint/eslint-plugin": "^6.19.0",
+ "@typescript-eslint/parser": "^6.19.0",
+ "@vitejs/plugin-react": "^4.2.1",
+ "autoprefixer": "^10.4.17",
+ "eslint": "^8.56.0",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.5",
+ "gh-pages": "^6.1.1",
+ "globals": "^13.24.0",
+ "postcss": "^8.4.33",
+ "tailwindcss": "^3.4.1",
+ "typescript": "^5.3.3",
+ "vite": "^5.0.11"
+ }
+}
diff --git a/code/postcss.config.js b/code/postcss.config.js
new file mode 100644
index 0000000..387612e
--- /dev/null
+++ b/code/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
\ No newline at end of file
diff --git a/code/public/differentiators/accelerateValue.png b/code/public/differentiators/accelerateValue.png
new file mode 100644
index 0000000..e9a78b6
Binary files /dev/null and b/code/public/differentiators/accelerateValue.png differ
diff --git a/code/public/differentiators/compDocumentation.png b/code/public/differentiators/compDocumentation.png
new file mode 100644
index 0000000..a17d416
Binary files /dev/null and b/code/public/differentiators/compDocumentation.png differ
diff --git a/code/public/differentiators/costEstimate.png b/code/public/differentiators/costEstimate.png
new file mode 100644
index 0000000..9de83f6
Binary files /dev/null and b/code/public/differentiators/costEstimate.png differ
diff --git a/code/public/differentiators/differentiatorGradient.png b/code/public/differentiators/differentiatorGradient.png
new file mode 100644
index 0000000..c746438
Binary files /dev/null and b/code/public/differentiators/differentiatorGradient.png differ
diff --git a/code/public/differentiators/quickDeploy.png b/code/public/differentiators/quickDeploy.png
new file mode 100644
index 0000000..be97beb
Binary files /dev/null and b/code/public/differentiators/quickDeploy.png differ
diff --git a/code/public/differentiators/solutionArch.png b/code/public/differentiators/solutionArch.png
new file mode 100644
index 0000000..96e532c
Binary files /dev/null and b/code/public/differentiators/solutionArch.png differ
diff --git a/code/public/favicon.ico b/code/public/favicon.ico
new file mode 100644
index 0000000..bfe873e
Binary files /dev/null and b/code/public/favicon.ico differ
diff --git a/code/public/featured/contentprocessing.png b/code/public/featured/contentprocessing.png
new file mode 100644
index 0000000..6448807
Binary files /dev/null and b/code/public/featured/contentprocessing.png differ
diff --git a/code/public/featured/contentprocessing2.png b/code/public/featured/contentprocessing2.png
new file mode 100644
index 0000000..dd321e0
Binary files /dev/null and b/code/public/featured/contentprocessing2.png differ
diff --git a/code/public/featured/conversationknowledgemining.png b/code/public/featured/conversationknowledgemining.png
new file mode 100644
index 0000000..bb94c81
Binary files /dev/null and b/code/public/featured/conversationknowledgemining.png differ
diff --git a/code/public/featured/conversationknowledgemining2.png b/code/public/featured/conversationknowledgemining2.png
new file mode 100644
index 0000000..ac03f21
Binary files /dev/null and b/code/public/featured/conversationknowledgemining2.png differ
diff --git a/code/public/featured/multiagent.png b/code/public/featured/multiagent.png
new file mode 100644
index 0000000..dd6892b
Binary files /dev/null and b/code/public/featured/multiagent.png differ
diff --git a/code/public/featured/multiagent2.png b/code/public/featured/multiagent2.png
new file mode 100644
index 0000000..2aa95dd
Binary files /dev/null and b/code/public/featured/multiagent2.png differ
diff --git a/code/public/featured/multiagent3.png b/code/public/featured/multiagent3.png
new file mode 100644
index 0000000..c75e797
Binary files /dev/null and b/code/public/featured/multiagent3.png differ
diff --git a/code/public/icons/AI Flash Sparkle.png b/code/public/icons/AI Flash Sparkle.png
new file mode 100644
index 0000000..64876ce
Binary files /dev/null and b/code/public/icons/AI Flash Sparkle.png differ
diff --git a/code/public/icons/Editor.png b/code/public/icons/Editor.png
new file mode 100644
index 0000000..b60d06e
Binary files /dev/null and b/code/public/icons/Editor.png differ
diff --git a/code/public/icons/Email Mention.png b/code/public/icons/Email Mention.png
new file mode 100644
index 0000000..83f0653
Binary files /dev/null and b/code/public/icons/Email Mention.png differ
diff --git a/code/public/icons/Excel.svg b/code/public/icons/Excel.svg
new file mode 100644
index 0000000..4cd2f33
--- /dev/null
+++ b/code/public/icons/Excel.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/code/public/icons/Grid List.png b/code/public/icons/Grid List.png
new file mode 100644
index 0000000..12c0187
Binary files /dev/null and b/code/public/icons/Grid List.png differ
diff --git a/code/public/icons/Illustration.png b/code/public/icons/Illustration.png
new file mode 100644
index 0000000..75c130b
Binary files /dev/null and b/code/public/icons/Illustration.png differ
diff --git a/code/public/icons/PowerPoint.svg b/code/public/icons/PowerPoint.svg
new file mode 100644
index 0000000..de3c4d7
--- /dev/null
+++ b/code/public/icons/PowerPoint.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/code/public/icons/Search Progress.png b/code/public/icons/Search Progress.png
new file mode 100644
index 0000000..48faf48
Binary files /dev/null and b/code/public/icons/Search Progress.png differ
diff --git a/code/public/icons/Word.svg b/code/public/icons/Word.svg
new file mode 100644
index 0000000..b967b50
--- /dev/null
+++ b/code/public/icons/Word.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/code/public/icons/docs.svg b/code/public/icons/docs.svg
new file mode 100644
index 0000000..02bfb55
--- /dev/null
+++ b/code/public/icons/docs.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/code/public/icons/figma.svg b/code/public/icons/figma.svg
new file mode 100644
index 0000000..d308732
--- /dev/null
+++ b/code/public/icons/figma.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/code/public/icons/github.svg b/code/public/icons/github.svg
new file mode 100644
index 0000000..b27decc
--- /dev/null
+++ b/code/public/icons/github.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/code/public/icons/learn.svg b/code/public/icons/learn.svg
new file mode 100644
index 0000000..dffa9f7
--- /dev/null
+++ b/code/public/icons/learn.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/code/public/icons/pdf.svg b/code/public/icons/pdf.svg
new file mode 100644
index 0000000..7f3aed4
--- /dev/null
+++ b/code/public/icons/pdf.svg
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/code/public/icons/quote.png b/code/public/icons/quote.png
new file mode 100644
index 0000000..5a75e89
Binary files /dev/null and b/code/public/icons/quote.png differ
diff --git a/code/public/icons/youtube.svg b/code/public/icons/youtube.svg
new file mode 100644
index 0000000..1258733
--- /dev/null
+++ b/code/public/icons/youtube.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/code/public/success/successGradient.png b/code/public/success/successGradient.png
new file mode 100644
index 0000000..540b200
Binary files /dev/null and b/code/public/success/successGradient.png differ
diff --git a/code/public/vite.svg b/code/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/code/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/code/scripts/generate-card-data.js b/code/scripts/generate-card-data.js
new file mode 100644
index 0000000..8283f1a
--- /dev/null
+++ b/code/scripts/generate-card-data.js
@@ -0,0 +1,22 @@
+// scripts/generate-card-data.js
+import fs from 'fs';
+import path from 'path';
+
+const inputDir = path.resolve('src/data/cards'); // folder with individual .json files
+const outputDir = path.resolve('src/data/generated');
+const outputFile = path.resolve('src/data/generated/cards.json');
+
+// Create the generated directory if it doesn't exist
+if (!fs.existsSync(outputDir)) {
+ fs.mkdirSync(outputDir, { recursive: true });
+}
+
+const cardFiles = fs.readdirSync(inputDir).filter((file) => file.endsWith('.json'));
+
+const cards = cardFiles.map((file) => {
+ const content = fs.readFileSync(path.join(inputDir, file), 'utf-8');
+ return JSON.parse(content);
+});
+
+fs.writeFileSync(outputFile, JSON.stringify(cards, null, 2));
+console.log(`✅ Generated cards.json with ${cards.length} entries`);
diff --git a/code/src/App.css b/code/src/App.css
new file mode 100644
index 0000000..124b741
--- /dev/null
+++ b/code/src/App.css
@@ -0,0 +1,84 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+:root {
+ /* Additional spacing so sections land slightly lower than the header */
+ --nav-extra-offset: 12px;
+}
+
+#root {
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ text-align: left;
+}
+
+.logo {
+ height: 6em;
+ padding: 1.5em;
+ will-change: filter;
+ transition: filter 300ms;
+}
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+ filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ a:nth-of-type(2) .logo {
+ animation: logo-spin infinite 20s linear;
+ }
+}
+
+.card {
+ padding: 2em;
+}
+
+.read-the-docs {
+ color: #888;
+}
+
+/* Fluid gradient background shared by Header + Hero */
+.home-hero-gradient {
+ position: relative;
+ isolation: isolate; /* ensure header backdrop-blur only blurs this background */
+ /* Layered, responsive gradients */
+ --accent-pink: 255 182 193; /* light rose */
+ --accent-lilac: 205 180 219; /* soft lilac */
+ --accent-sky: 173 216 230; /* light sky */
+
+ background-image:
+ radial-gradient(60vw 60vw at 15% 10%, rgba(var(--accent-pink) / 0.35), rgba(255 255 255 / 0) 60%),
+ radial-gradient(50vw 50vw at 85% 5%, rgba(var(--accent-lilac) / 0.35), rgba(255 255 255 / 0) 55%),
+ radial-gradient(65vw 50vw at 80% 70%, rgba(var(--accent-sky) / 0.30), rgba(255 255 255 / 0) 60%);
+
+ /* Give hero breathing room so gradient is visible */
+ padding-bottom: 2rem;
+}
+
+@media (max-width: 768px) {
+ .home-hero-gradient {
+ background-image:
+ radial-gradient(80vw 80vw at 20% 8%, rgba(var(--accent-pink) / 0.38), rgba(255 255 255 / 0) 62%),
+ radial-gradient(70vw 70vw at 85% 0%, rgba(var(--accent-lilac) / 0.34), rgba(255 255 255 / 0) 58%),
+ radial-gradient(90vw 70vw at 60% 75%, rgba(var(--accent-sky) / 0.28), rgba(255 255 255 / 0) 62%);
+ padding-bottom: 1.5rem;
+ }
+}
+
+/* Ensure in-flow sections account for sticky navigation height when scrolled into view */
+.section-anchor {
+ scroll-margin-top: calc(var(--nav-height, 64px) + var(--nav-extra-offset, 0px));
+}
diff --git a/code/src/App.tsx b/code/src/App.tsx
new file mode 100644
index 0000000..cc178f9
--- /dev/null
+++ b/code/src/App.tsx
@@ -0,0 +1,500 @@
+import { useState, useRef, useEffect } from 'react';
+import type { AcceleratorCard } from './types';
+import cardsData from './data/generated/cards.json';
+import './App.css';
+import {
+ FluentProvider,
+ webLightTheme,
+ Button,
+ Title1,
+ Body1,
+ Input,
+ Menu,
+ MenuTrigger,
+ MenuPopover,
+ MenuList,
+ MenuItem,
+ Checkbox
+} from '@fluentui/react-components';
+import {
+ Search20Regular,
+ ArrowSort20Regular,
+ Dismiss20Regular,
+ ChevronDown20Regular,
+ ChevronRight20Regular
+} from '@fluentui/react-icons';
+import { MicrosoftLogo } from './assets/MicrosoftLogo';
+import Header from './components/Header';
+import HeroSection from './components/HeroSection';
+import GsaCard from './components/GsaCard/GsaCard';
+import { NavigationSection } from './components/Navigation';
+import type { NavigationTab } from './components/Navigation';
+
+import FeaturedSection from './components/FeaturedSection';
+import DifferentiatorSection from './components/DifferentiatorSection';
+import { HowItWorksSection } from './components/HowItWorksSection';
+import CustomerTrustSection from './components/CustomerTrustSection';
+import Footer from './components/Footer';
+import type { FooterLink } from './components/Footer';
+import { useNavigationWithUrl } from './hooks/useNavigationWithUrl';
+import { useSortDeepLink } from './hooks/useSortDeepLink';
+import { useSearchDeepLink } from './hooks/useSearchDeepLink';
+import { useFilterDeepLink } from './hooks/useFilterDeepLink';
+
+const cards: AcceleratorCard[] = cardsData as unknown as AcceleratorCard[];
+
+// Default differentiator accordion items
+const defaultDifferentiatorItems = [
+ {
+ id: "proven-architecture",
+ label: "Proven architecture",
+ content: "Leverage a trusted, scalable solution design based on best practices—built to ensure reliability, security, and performance, so your teams can deploy with confidence.",
+ image: "/differentiators/solutionArch.png"
+ },
+ {
+ id: "quick-deployment",
+ label: "Quick deployment",
+ content: "Deploy solutions quickly with pre-built templates and guided setup instructions.",
+ image: "/differentiators/quickDeploy.png"
+ },
+ {
+ id: "accelerated-value",
+ label: "Accelerated value",
+ content: "Get to market faster with ready-to-use solutions that can be customized to your needs.",
+ image: "/differentiators/accelerateValue.png"
+ },
+ {
+ id: "comprehensive-documentation",
+ label: "Comprehensive documentation",
+ content: "Access detailed documentation, including architecture diagrams, deployment guides, and best practices.",
+ image: "/differentiators/compDocumentation.png"
+ },
+ {
+ id: "costing-estimate",
+ label: "Costing estimate",
+ content: "Understand the cost implications upfront with detailed pricing estimates and optimization guidance.",
+ image: "/differentiators/costEstimate.png"
+ }
+];
+
+// How it works steps data
+const howItWorksSteps = [
+ {
+ icon: "/icons/Search Progress.png",
+ label: "Step 1: Browse",
+ content: "Browse available accelerators to discover ready-made solutions tailored to your customer needs."
+ },
+ {
+ icon: "/icons/Editor.png",
+ label: "Step 2: Select",
+ content: "Select the accelerator that best fits your business use case and adapt it to your needs using built-in configuration options."
+ },
+ {
+ icon: "/icons/Grid List.png",
+ label: "Step 3: Review",
+ content: "Review pre-requisites and costing to ensure alignment with your organizational needs."
+ },
+ {
+ icon: "/icons/AI Flash Sparkle.png",
+ label: "Step 4: Deploy",
+ content: "Use deployment guide to launch your solution quickly and securely."
+ }
+];
+
+
+
+ // Navigation tabs configuration
+ const navigationTabs: NavigationTab[] = [
+ {
+ value: "featured",
+ label: "Featured accelerators",
+ targetId: "featured"
+ },
+ {
+ value: "accelerators",
+ label: "All accelerators",
+ targetId: "accelerators"
+ },
+ {
+ value: "differentiators",
+ label: "Differentiators",
+ targetId: "differentiators"
+ },
+ {
+ value: "how-it-works",
+ label: "How it works",
+ targetId: "how-it-works"
+ },
+ {
+ value: "success-stories",
+ label: "Success stories",
+ targetId: "customer-trust"
+ }
+ ];
+
+ // Footer links configuration
+ const footerLinks: FooterLink[] = [
+ { text: "Sitemap", url: "https://www.microsoft.com/en-us/sitemap" },
+ { text: "Contact Microsoft", url: "https://support.microsoft.com/contactus" },
+ { text: "Privacy", url: "https://www.microsoft.com/en-us/privacy/privacystatement" },
+ { text: "Terms of use", url: "https://www.microsoft.com/en-us/legal/terms-of-use" },
+ { text: "Trademarks", url: "https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks" },
+ { text: "Safety & eco", url: "https://www.microsoft.com/en-us/legal/compliance/devices-safety-and-eco" },
+ { text: "Recycling", url: "https://www.microsoft.com/en-us/legal/compliance/recycling" },
+ { text: "About our ads", url: "https://account.microsoft.com/privacy/ad-settings/signedout?refd=www.microsoft.com&ru=https%3A%2F%2Faccount.microsoft.com%2Fprivacy%2Fad-settings%3Frefd%3Dwww.microsoft.com" }
+];
+
+// Filterable fields
+const filterableFields = [
+ "productsAndServices",
+ "industries",
+ "programmingLanguages",
+];
+
+const filterLabels: Record = {
+ productsAndServices: "Products and Services",
+ industries: "Industries",
+ programmingLanguages: "Languages",
+};
+
+const sortLabels: Record = {
+ accelerator: "A-Z",
+ acceleratorDesc: "Z-A",
+ releaseNewest: "Newest",
+ releaseOldest: "Oldest",
+};
+
+function App() {
+ const searchInputRef = useRef(null);
+ const featuredRef = useRef(null);
+ const acceleratorsRef = useRef(null);
+ const differentiatorsRef = useRef(null);
+ const howItWorksRef = useRef(null);
+ const customerTrustRef = useRef(null);
+
+ // Navigation with URL update system
+ const { currentSection, scrollToSection } = useNavigationWithUrl();
+
+ // Search and filter state
+ const { searchQuery, updateSearch, clearSearch } = useSearchDeepLink("");
+ const { sortBy, updateSort } = useSortDeepLink("releaseNewest");
+ const [collapsedSections, setCollapsedSections] = useState>({});
+
+ // Synchronized height state for cards
+ const [excerptHeights, setExcerptHeights] = useState([]);
+ const [rowHeightVersion] = useState(0);
+
+ // Dynamic filter options
+ const dynamicFilterOptions: Record = {};
+ cards.forEach((card) => {
+ filterableFields.forEach((field) => {
+ const value = card[field as keyof AcceleratorCard];
+ if (!value || typeof value === 'boolean') return;
+ const values = Array.isArray(value) ? value : [value];
+ values.forEach((item) => {
+ if (typeof item !== 'string') return;
+ if (!dynamicFilterOptions[field]) dynamicFilterOptions[field] = [];
+ if (!dynamicFilterOptions[field].includes(item))
+ dynamicFilterOptions[field].push(item);
+ });
+ });
+ });
+
+ // Filter state management
+ const { selectedItems, updateFilter } = useFilterDeepLink(dynamicFilterOptions);
+
+ // Initialize collapsed sections
+ useEffect(() => {
+ if (Object.keys(collapsedSections).length > 0) return;
+ const initialCollapseState: Record = {};
+ Object.keys(dynamicFilterOptions).forEach((category) => {
+ // Default all filter categories to open (not collapsed)
+ initialCollapseState[category] = false;
+ });
+ setCollapsedSections(initialCollapseState);
+ }, []);
+
+ // Height reporting functions
+ const reportExcerptHeight = (index: number, height: number) => {
+ setExcerptHeights(prev => {
+ const next = [...prev];
+ next[index] = height;
+ return next;
+ });
+ };
+
+ // Filter and search logic
+ const filteredCards = cards.filter((card) => {
+ const matchesFilters = filterableFields.every((field) => {
+ const cardValue = card[field as keyof AcceleratorCard];
+ const selectedForField = Object.keys(selectedItems).filter(
+ (id) =>
+ selectedItems[id] &&
+ dynamicFilterOptions[field]?.some(
+ (v) => v.toLowerCase().replace(/\s+/g, "_") === id
+ )
+ );
+
+ if (selectedForField.length === 0) return true;
+ if (!cardValue || typeof cardValue === 'boolean') return false;
+
+ const cardValuesNormalized = Array.isArray(cardValue)
+ ? cardValue.filter((v): v is string => typeof v === 'string').map((v) => v.toLowerCase().replace(/\s+/g, "_"))
+ : [cardValue.toLowerCase().replace(/\s+/g, "_")];
+
+ return selectedForField.some((selected) =>
+ cardValuesNormalized.includes(selected)
+ );
+ });
+
+ const query = searchQuery.toLowerCase().trim();
+ const matchesSearch =
+ query === "" ||
+ Object.entries(card).some(([, value]) => {
+ if (!value) return false;
+ if (typeof value === "string")
+ return value.toLowerCase().includes(query);
+ if (Array.isArray(value)) {
+ return value.some((v) => {
+ if (typeof v === "string") {
+ return v.toLowerCase().includes(query);
+ } else if (typeof v === "object" && v.label) {
+ return v.label.toLowerCase().includes(query);
+ }
+ return false;
+ });
+ }
+ return false;
+ });
+
+ return matchesFilters && matchesSearch;
+ });
+
+ // Sort cards
+ filteredCards.sort((a, b) => {
+ switch (sortBy) {
+ case "accelerator":
+ return a.accelerator.localeCompare(b.accelerator);
+ case "acceleratorDesc":
+ return b.accelerator.localeCompare(a.accelerator);
+ case "releaseNewest":
+ return new Date(b.releaseDate).getTime() - new Date(a.releaseDate).getTime();
+ case "releaseOldest":
+ return new Date(a.releaseDate).getTime() - new Date(b.releaseDate).getTime();
+ default:
+ return 0;
+ }
+ });
+
+ const handleTabSelect = (tabValue: string) => {
+ scrollToSection(tabValue);
+ };
+
+ const handleFeedbackClick = () => {
+ window.location.href = "mailto:CSAGoldStandards@service.microsoft.com?subject=Feedback%20on%20AI%20Accelerators";
+ };
+
+ return (
+
+
+
+ {/* Header - Standalone component */}
+ }
+ title="Microsoft"
+ subtitle="Solution Accelerators"
+ />
+
+ {/* Hero Section - Separate component */}
+
+
+
+ {/* In-flow Navigation section that becomes sticky when reached */}
+
+
+ {/* Featured Section */}
+
+
+ {/* Explore all accelerators - White background */}
+
+
+
+ {/* Filters Sidebar */}
+
+ {Object.entries(dynamicFilterOptions).map(([category, items]) => (
+
+
setCollapsedSections(prev => ({
+ ...prev,
+ [category]: !prev[category]
+ }))}
+ >
+ {filterLabels[category]}
+ {collapsedSections[category] ? : }
+
+ {!collapsedSections[category] && (
+
+ {items.sort().map((item) => {
+ const itemId = item.toLowerCase().replace(/\s+/g, "_");
+ return (
+
+ updateFilter(itemId, !selectedItems[itemId], category)
+ }
+ />
+ );
+ })}
+
+ )}
+
+ ))}
+
+
+ {/* Main Content */}
+
+ {/* Title above search bar */}
+
+ Explore all accelerators
+
+
+ {/* Search and Sort Bar */}
+
+
+ updateSearch(e.target.value)}
+ contentBefore={ }
+ contentAfter={
+ searchQuery ? (
+ }
+ onClick={clearSearch}
+ />
+ ) : null
+ }
+ />
+
+
+
+
+ } appearance="secondary">
+ Sort by
+
+
+
+
+ {Object.entries(sortLabels).map(([key, label]) => (
+ updateSort(key)}>
+ {label}
+
+ ))}
+
+
+
+
+
+ {/* Cards Grid */}
+
+ {filteredCards.length > 0 ? (
+ filteredCards.map((card, index) => (
+
+ ))
+ ) : (
+
+ No results found. Try adjusting your filters or search terms.
+
+ )}
+
+
+
+
+
+
+ {/* Differentiators Section */}
+
+
+ {/* How it Works Section */}
+
+
+ {/* Customer Trust & Developer Love Section */}
+
+
+ {/* Footer */}
+
+
+
+ );
+}
+
+export default App;
\ No newline at end of file
diff --git a/code/src/assets/BeautyMark.tsx b/code/src/assets/BeautyMark.tsx
new file mode 100644
index 0000000..9155770
--- /dev/null
+++ b/code/src/assets/BeautyMark.tsx
@@ -0,0 +1,20 @@
+import React from "react";
+
+const CindyCrawford: React.FC = () => {
+ return (
+
+
+
+ );
+};
+
+export default CindyCrawford;
diff --git a/code/src/assets/GoldenStandardLogo.tsx b/code/src/assets/GoldenStandardLogo.tsx
new file mode 100644
index 0000000..e95d0f7
--- /dev/null
+++ b/code/src/assets/GoldenStandardLogo.tsx
@@ -0,0 +1,14 @@
+export const GoldenStandardLogo = () => (
+
+
+
+
+
+
+
+
+
+);
\ No newline at end of file
diff --git a/code/src/assets/LoveLetter.png b/code/src/assets/LoveLetter.png
new file mode 100644
index 0000000..632ba2a
Binary files /dev/null and b/code/src/assets/LoveLetter.png differ
diff --git a/code/src/assets/MicrosoftLogo.tsx b/code/src/assets/MicrosoftLogo.tsx
new file mode 100644
index 0000000..5d2d5eb
--- /dev/null
+++ b/code/src/assets/MicrosoftLogo.tsx
@@ -0,0 +1,8 @@
+export const MicrosoftLogo = () => (
+
+
+
+
+
+
+);
\ No newline at end of file
diff --git a/code/src/assets/MsftColor.tsx b/code/src/assets/MsftColor.tsx
new file mode 100644
index 0000000..9b030d2
--- /dev/null
+++ b/code/src/assets/MsftColor.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+
+const MicrosoftLogo: React.FC = () => {
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default MicrosoftLogo;
diff --git a/code/src/assets/Octopus.png b/code/src/assets/Octopus.png
new file mode 100644
index 0000000..2394f42
Binary files /dev/null and b/code/src/assets/Octopus.png differ
diff --git a/code/src/assets/TestTube.png b/code/src/assets/TestTube.png
new file mode 100644
index 0000000..4ab57da
Binary files /dev/null and b/code/src/assets/TestTube.png differ
diff --git a/code/src/assets/Whale.png b/code/src/assets/Whale.png
new file mode 100644
index 0000000..209d2c0
Binary files /dev/null and b/code/src/assets/Whale.png differ
diff --git a/code/src/assets/bundleicons.tsx b/code/src/assets/bundleicons.tsx
new file mode 100644
index 0000000..6684487
--- /dev/null
+++ b/code/src/assets/bundleicons.tsx
@@ -0,0 +1,136 @@
+//DEV NOTES:
+//It's recommended to create bundleIcons for icons that nest within Fluent components and then import them into your project.
+// See full catalog of icons at https://react.fluentui.dev/?path=/docs/icons-catalog--docs.
+
+import {
+ ArrowExitFilled,
+ ArrowExitRegular,
+ BeakerFilled,
+ BeakerRegular,
+ BookmarkFilled,
+ BookmarkRegular,
+ CodeFilled,
+ CodeRegular,
+ CubeFilled,
+ CubeRegular,
+ DesignIdeasFilled,
+ DesignIdeasRegular,
+ DrawerArrowDownloadFilled,
+ DrawerArrowDownloadRegular,
+ FlowFilled,
+ FlowRegular,
+ FolderOpenFilled,
+ FolderOpenRegular,
+ LeafOneFilled,
+ LeafOneRegular,
+ LinkFilled,
+ LinkRegular,
+ OpenFilled,
+ OpenRegular,
+ OrganizationHorizontalFilled,
+ OrganizationHorizontalRegular,
+ PanelLeftContractFilled,
+ PanelLeftContractRegular,
+ PanelLeftExpandFilled,
+ PanelLeftExpandRegular,
+ PanelRightContractFilled,
+ PanelRightContractRegular,
+ PanelRightExpandFilled,
+ PanelRightExpandRegular,
+ PersonFilled,
+ PersonRegular,
+ PersonFeedbackFilled,
+ PersonFeedbackRegular,
+ SearchFilled,
+ SearchRegular,
+ ShareFilled,
+ ShareRegular,
+ TreeDeciduousFilled,
+ TreeDeciduousRegular,
+ TreeEvergreenFilled,
+ TreeEvergreenRegular,
+ WeatherMoonFilled,
+ WeatherMoonRegular,
+ WeatherSunnyFilled,
+ WeatherSunnyRegular,
+ DismissFilled,
+ DismissRegular,
+ DocumentSparkleFilled,
+ DocumentSparkleRegular,
+ SparkleFilled,
+ SparkleRegular,
+ StarFilled,
+ StarRegular,
+ MoreHorizontalFilled,
+ MoreHorizontalRegular,
+ ArrowResetFilled,
+ ArrowResetRegular,
+ bundleIcon,
+} from "@fluentui/react-icons";
+
+export const MoreHorizontal = bundleIcon(
+ MoreHorizontalFilled,
+ MoreHorizontalRegular
+);
+export const ArrowReset = bundleIcon(ArrowResetFilled, ArrowResetRegular);
+export const ArrowExit = bundleIcon(ArrowExitFilled, ArrowExitRegular);
+export const Bookmark = bundleIcon(BookmarkFilled, BookmarkRegular);
+export const Sparkle = bundleIcon(SparkleFilled, SparkleRegular);
+export const Star = bundleIcon(StarFilled, StarRegular);
+export const DocumentSparkle = bundleIcon(
+ DocumentSparkleFilled,
+ DocumentSparkleRegular
+);
+export const Dismiss = bundleIcon(DismissFilled, DismissRegular);
+export const DrawerArrowDownload = bundleIcon(
+ DrawerArrowDownloadFilled,
+ DrawerArrowDownloadRegular
+);
+export const Beaker = bundleIcon(BeakerFilled, BeakerRegular);
+export const Code = bundleIcon(CodeFilled, CodeRegular);
+export const Cube = bundleIcon(CubeFilled, CubeRegular);
+export const DesignIdeas = bundleIcon(DesignIdeasFilled, DesignIdeasRegular);
+export const Flow = bundleIcon(FlowFilled, FlowRegular);
+export const FolderOpen = bundleIcon(FolderOpenFilled, FolderOpenRegular);
+export const LeafOne = bundleIcon(LeafOneFilled, LeafOneRegular);
+export const Link = bundleIcon(LinkFilled, LinkRegular);
+export const Open = bundleIcon(OpenFilled, OpenRegular);
+export const OrganizationHorizontal = bundleIcon(
+ OrganizationHorizontalFilled,
+ OrganizationHorizontalRegular
+);
+export const PanelLeftContract = bundleIcon(
+ PanelLeftContractFilled,
+ PanelLeftContractRegular
+);
+export const PanelLeftExpand = bundleIcon(
+ PanelLeftExpandFilled,
+ PanelLeftExpandRegular
+);
+export const PanelRightContract = bundleIcon(
+ PanelRightContractFilled,
+ PanelRightContractRegular
+);
+export const PanelRightExpand = bundleIcon(
+ PanelRightExpandFilled,
+ PanelRightExpandRegular
+);
+export const Person = bundleIcon(PersonFilled, PersonRegular);
+export const PersonFeedback = bundleIcon(
+ PersonFeedbackFilled,
+ PersonFeedbackRegular
+);
+export const Search = bundleIcon(SearchFilled, SearchRegular);
+export const Share = bundleIcon(ShareFilled, ShareRegular);
+export const TreeDeciduous = bundleIcon(
+ TreeDeciduousFilled,
+ TreeDeciduousRegular
+);
+export const TreeEvergreen = bundleIcon(
+ TreeEvergreenFilled,
+ TreeEvergreenRegular
+);
+export const WeatherMoon = bundleIcon(WeatherMoonFilled, WeatherMoonRegular);
+export const WeatherSunny = bundleIcon(WeatherSunnyFilled, WeatherSunnyRegular);
+
+export default { bundleIcon };
diff --git a/code/src/assets/favicon.ico b/code/src/assets/favicon.ico
new file mode 100644
index 0000000..bfe873e
Binary files /dev/null and b/code/src/assets/favicon.ico differ
diff --git a/code/src/assets/react.svg b/code/src/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/code/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/code/src/components/CustomerTrustSection/CustomerTrustSection.css b/code/src/components/CustomerTrustSection/CustomerTrustSection.css
new file mode 100644
index 0000000..30bef98
--- /dev/null
+++ b/code/src/components/CustomerTrustSection/CustomerTrustSection.css
@@ -0,0 +1,99 @@
+.customer-trust-section {
+ background-image: url('/success/successGradient.png');
+ background-size: 100% 100%;
+ background-attachment: scroll;
+ background-position: center center;
+ padding: 4rem 0;
+}
+
+.trusted-customers-section {
+ margin-bottom: 0;
+}
+
+.trusted-customers-section .title-spacing {
+ margin-bottom: 3rem;
+}
+
+.loved-developers-section {
+ padding-top: 0;
+}
+
+.quotes-grid {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 1.5rem;
+ max-width: 1200px;
+ margin: 0 auto;
+}
+
+.testimonial-card {
+ background-color: white;
+ padding: 2rem;
+ border-radius: 8px;
+ height: 280px;
+ width: 100%;
+ position: relative;
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
+ display: flex;
+ flex-direction: column;
+ border: 1px solid #e5e7eb;
+ min-height: 280px;
+ overflow: hidden;
+}
+
+.quote-icon {
+ margin-bottom: 1rem;
+ display: flex;
+ align-items: flex-start;
+}
+
+.quote-icon img {
+ width: auto;
+ height: auto;
+}
+
+.quote-text {
+ flex: 1;
+ font-weight: 600;
+ line-height: 1.6;
+ margin-bottom: 1rem;
+ font-size: 0.9rem;
+ overflow: hidden;
+ display: -webkit-box;
+ line-clamp: 4;
+ -webkit-line-clamp: 4;
+ -webkit-box-orient: vertical;
+}
+
+.author-title {
+ margin-top: auto;
+ font-weight: 400;
+ color: #374151;
+ font-size: 0.875rem;
+ font-style: italic;
+ align-self: flex-start;
+ flex-shrink: 0;
+}
+
+/* Responsive grid adjustments */
+@media (max-width: 1023px) {
+ .quotes-grid {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 1rem;
+ }
+
+ .testimonial-card {
+ height: 240px;
+ }
+}
+
+@media (max-width: 767px) {
+ .quotes-grid {
+ grid-template-columns: repeat(1, 1fr);
+ gap: 1rem;
+ }
+
+ .testimonial-card {
+ height: 200px;
+ }
+}
\ No newline at end of file
diff --git a/code/src/components/CustomerTrustSection/CustomerTrustSection.tsx b/code/src/components/CustomerTrustSection/CustomerTrustSection.tsx
new file mode 100644
index 0000000..c4cb9bb
--- /dev/null
+++ b/code/src/components/CustomerTrustSection/CustomerTrustSection.tsx
@@ -0,0 +1,119 @@
+import React from 'react';
+import { Title1, Subtitle1, Button } from '@fluentui/react-components';
+import type { SuccessStoriesSectionProps } from '../../types';
+import './CustomerTrustSection.css';
+
+export interface LinkConfig {
+ text: string;
+ url: string;
+ target?: '_blank' | '_self';
+}
+
+export interface CustomerTrustSectionProps {
+ /** Main title for the trusted customers section */
+ trustedTitle: string;
+ /** Content description for trusted customers */
+ trustedContent: string;
+ /** Link configuration for trusted customers */
+ trustedLink: LinkConfig;
+ /** Title for the developer quotes section */
+ developerTitle: string;
+ /** Quotes for the developer section */
+ quotes: SuccessStoriesSectionProps['quotes'];
+ /** Additional CSS classes */
+ className?: string;
+}
+
+const CustomerTrustSection: React.FC = ({
+ trustedTitle,
+ trustedContent,
+ trustedLink,
+ developerTitle,
+ quotes,
+ className = ''
+}) => {
+ const handleLinkClick = (e: React.MouseEvent) => {
+ e.preventDefault();
+
+ if (trustedLink.url.startsWith('#')) {
+ const targetId = trustedLink.url.substring(1);
+ const targetElement = document.getElementById(targetId);
+
+ if (targetElement) {
+ targetElement.scrollIntoView({
+ behavior: 'smooth',
+ block: 'start'
+ });
+ }
+ } else {
+ if (trustedLink.target === '_blank') {
+ window.open(trustedLink.url, '_blank', 'noopener,noreferrer');
+ } else {
+ window.location.href = trustedLink.url;
+ }
+ }
+ };
+
+ return (
+
+ {/* Trusted by Customers Section */}
+
+
+
+
+
+ {trustedTitle}
+
+
+ {trustedContent}
+
+
+
+
+ {trustedLink.text}
+
+
+
+
+
+
+ {/* Loved by Developers Section */}
+ {quotes.length > 0 && (
+
+
+
+
+ {developerTitle}
+
+
+
+
+ {quotes.slice(0, 4).map((quote, index) => (
+
+
+
+
+
+ {quote.quote}
+
+
{quote.author}
+
+ ))}
+
+
+
+ )}
+
+ );
+};
+
+export default CustomerTrustSection;
\ No newline at end of file
diff --git a/code/src/components/CustomerTrustSection/index.ts b/code/src/components/CustomerTrustSection/index.ts
new file mode 100644
index 0000000..33473d1
--- /dev/null
+++ b/code/src/components/CustomerTrustSection/index.ts
@@ -0,0 +1,2 @@
+export { default } from './CustomerTrustSection';
+export type { CustomerTrustSectionProps, LinkConfig } from './CustomerTrustSection';
\ No newline at end of file
diff --git a/code/src/components/DifferentiatorSection/DifferentiatorSection.css b/code/src/components/DifferentiatorSection/DifferentiatorSection.css
new file mode 100644
index 0000000..9247f96
--- /dev/null
+++ b/code/src/components/DifferentiatorSection/DifferentiatorSection.css
@@ -0,0 +1,9 @@
+/* Enhanced background image styling for DifferentiatorSection */
+.differentiator-section {
+ background-image: url('/differentiators/differentiatorGradient.png');
+ background-size: cover;
+ background-position: center center;
+ background-repeat: no-repeat;
+ padding: 4rem 0 5rem 0;
+ position: relative;
+}
\ No newline at end of file
diff --git a/code/src/components/DifferentiatorSection/DifferentiatorSection.tsx b/code/src/components/DifferentiatorSection/DifferentiatorSection.tsx
new file mode 100644
index 0000000..f7c82de
--- /dev/null
+++ b/code/src/components/DifferentiatorSection/DifferentiatorSection.tsx
@@ -0,0 +1,228 @@
+import React, { useState } from 'react';
+import {
+ Title1,
+ Text,
+ Accordion,
+ AccordionHeader,
+ AccordionItem,
+ AccordionPanel,
+ makeStyles
+} from '@fluentui/react-components';
+import { ChevronUp20Regular, ChevronDown20Regular } from '@fluentui/react-icons';
+import './DifferentiatorSection.css';
+
+export interface DifferentiatorAccordionItem {
+ id: string;
+ label: string;
+ content: string;
+ image?: string;
+}
+
+export interface DifferentiatorSectionProps {
+ title: string;
+ content: string;
+ accordionItems: DifferentiatorAccordionItem[];
+ className?: string;
+ backgroundGradient?: 'default' | 'custom';
+}
+
+const useStyles = makeStyles({
+ contentLayout: {
+ display: 'flex',
+ flexDirection: 'column',
+ gap: '1.5rem',
+ maxWidth: '80rem',
+ margin: '0 auto',
+ padding: '0 1rem',
+ position: 'relative',
+ zIndex: 2,
+ '@media (min-width: 768px) and (max-width: 1023px)': {
+ flexDirection: 'column',
+ gap: '2rem',
+ },
+ '@media (min-width: 1024px)': {
+ flexDirection: 'row',
+ alignItems: 'stretch',
+ gap: '3rem',
+ },
+ },
+ accordionContainer: {
+ flex: '0 0 auto',
+ width: '100%',
+ '@media (min-width: 1024px)': {
+ width: '45%',
+ maxWidth: '450px',
+ },
+ },
+ imageContainer: {
+ flex: '1',
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'flex-start',
+ alignItems: 'flex-start',
+ height: '400px',
+ '@media (min-width: 768px) and (max-width: 1023px)': {
+ height: '450px',
+ },
+ '@media (min-width: 1024px)': {
+ height: '500px',
+ },
+ },
+ accordionItem: {
+ border: 'none',
+ background: 'transparent',
+ marginBottom: '1rem',
+ transition: 'all 0.2s ease-in-out',
+ borderRadius: '0',
+ borderBottom: '1px solid #e5e7eb',
+ '&:last-child': {
+ borderBottom: 'none',
+ },
+ },
+ accordionItemActive: {
+ borderLeft: `3px solid #0078d4`,
+ paddingLeft: '0.75rem',
+ backgroundColor: 'transparent',
+ borderRadius: '0',
+ },
+ accordionHeader: {
+ padding: '0.75rem 0.75rem 0.75rem 0',
+ cursor: 'pointer',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ fontWeight: '600',
+ color: '#374151',
+ fontSize: '1rem',
+ '&:hover': {
+ backgroundColor: 'transparent',
+ },
+ },
+ accordionPanel: {
+ padding: '0 0.75rem 0.75rem 0',
+ color: '#6b7280',
+ lineHeight: '1.6',
+ fontSize: '0.9rem',
+ textAlign: 'left',
+ },
+ solutionImage: {
+ width: '100%',
+ height: '100%',
+ objectFit: 'contain',
+ objectPosition: 'center',
+ maxHeight: '100%',
+ transition: 'opacity 0.3s ease-in-out',
+ },
+ sectionTitle: {
+ textAlign: 'center',
+ marginBottom: '1rem',
+ color: '#000000',
+ fontWeight: '700',
+ display: 'block',
+ width: '100%',
+ position: 'relative',
+ zIndex: 2,
+ },
+ sectionContent: {
+ textAlign: 'center',
+ marginBottom: '2rem',
+ color: '#6b7280',
+ lineHeight: '1.6',
+ fontSize: '1.1rem',
+ display: 'block',
+ width: '100%',
+ maxWidth: '800px',
+ marginLeft: 'auto',
+ marginRight: 'auto',
+ position: 'relative',
+ zIndex: 2,
+ },
+});
+
+const DifferentiatorSection: React.FC = ({
+ title,
+ content,
+ accordionItems,
+ className
+}) => {
+ const styles = useStyles();
+ const [openItems, setOpenItems] = useState>(new Set([accordionItems[0]?.id]));
+
+ const handleAccordionToggle = (_event: any, data: { value: string }) => {
+ const itemId = data.value;
+ const newOpenItems = new Set(openItems);
+ if (newOpenItems.has(itemId)) {
+ newOpenItems.delete(itemId);
+ } else {
+ newOpenItems.clear();
+ newOpenItems.add(itemId);
+ }
+ setOpenItems(newOpenItems);
+ };
+
+ // Get the currently open item to determine which image to show
+ const currentOpenItem = accordionItems.find(item => openItems.has(item.id));
+ const currentImage = currentOpenItem?.image || "/differentiators/solutionArch.png";
+ const currentImageAlt = currentOpenItem ? `${currentOpenItem.label} diagram` : "Solution architecture diagram";
+
+ return (
+
+
+ {title}
+
+
+ {content}
+
+
+
+
+
+ {accordionItems.map((item) => {
+ const isOpen = openItems.has(item.id);
+ return (
+
+
+
+ {item.label}
+
+ {isOpen ? : }
+
+
+ {item.content}
+
+
+ );
+ })}
+
+
+
+
+
+
+
+
+ );
+};
+
+export default DifferentiatorSection;
\ No newline at end of file
diff --git a/code/src/components/DifferentiatorSection/README.md b/code/src/components/DifferentiatorSection/README.md
new file mode 100644
index 0000000..88717eb
--- /dev/null
+++ b/code/src/components/DifferentiatorSection/README.md
@@ -0,0 +1,124 @@
+# DifferentiatorSection Component
+
+A modern, responsive component for displaying differentiator information with an accordion interface and solution architecture diagram. Designed with Figma-inspired styling featuring a floating card effect and gradient background.
+
+## Features
+
+- **Figma-Inspired Design**: Clean, modern appearance with floating card effect
+- **Responsive Layout**: Adapts to different screen sizes
+- **Interactive Accordion**: Smooth expand/collapse animations
+- **Configurable Content**: Fully customizable title, content, and accordion items
+- **Accessibility**: WCAG compliant with proper ARIA labels and keyboard navigation
+- **Performance Optimized**: Smooth animations and efficient rendering
+
+## Usage
+
+```tsx
+import DifferentiatorSection from './components/DifferentiatorSection';
+
+const accordionItems = [
+ {
+ id: "proven-architecture",
+ label: "Proven architecture",
+ content: "Leverage a trusted, scalable solution design based on best practices...",
+ image: "/differentiators/solutionArch.png"
+ },
+ // ... more items
+];
+
+
+```
+
+## Props
+
+### DifferentiatorSectionProps
+
+| Prop | Type | Default | Description |
+|------|------|---------|-------------|
+| `title` | `string` | - | Main section title |
+| `content` | `string` | - | Section description text |
+| `accordionItems` | `DifferentiatorAccordionItem[]` | - | Array of accordion items |
+| `className` | `string` | - | Additional CSS classes |
+| `backgroundGradient` | `'default' \| 'custom'` | `'default'` | Background gradient style |
+
+### DifferentiatorAccordionItem
+
+| Prop | Type | Default | Description |
+|------|------|---------|-------------|
+| `id` | `string` | - | Unique identifier for the accordion item |
+| `label` | `string` | - | Display text for the accordion header |
+| `content` | `string` | - | Content displayed when accordion is expanded |
+| `image` | `string` | - | Optional image path (currently uses default solutionArch.png) |
+
+## Default Configuration
+
+The component includes a default configuration that matches the current implementation:
+
+```tsx
+const defaultAccordionItems = [
+ {
+ id: "proven-architecture",
+ label: "Proven architecture",
+ content: "Leverage a trusted, scalable solution design based on best practices—built to ensure reliability, security, and performance, so your teams can deploy with confidence.",
+ image: "/differentiators/solutionArch.png"
+ },
+ {
+ id: "quick-deployment",
+ label: "Quick deployment",
+ content: "Deploy solutions quickly with pre-built templates and guided setup instructions.",
+ image: "/differentiators/solutionArch.png"
+ },
+ {
+ id: "accelerated-value",
+ label: "Accelerated value",
+ content: "Get to market faster with ready-to-use solutions that can be customized to your needs.",
+ image: "/differentiators/solutionArch.png"
+ },
+ {
+ id: "comprehensive-documentation",
+ label: "Comprehensive documentation",
+ content: "Access detailed documentation, including architecture diagrams, deployment guides, and best practices.",
+ image: "/differentiators/solutionArch.png"
+ },
+ {
+ id: "costing-estimate",
+ label: "Costing estimate",
+ content: "Understand the cost implications upfront with detailed pricing estimates and optimization guidance.",
+ image: "/differentiators/solutionArch.png"
+ }
+];
+```
+
+## Styling
+
+The component uses Fluent UI's `makeStyles` for styling with the following key features:
+
+- **Gradient Background**: Subtle gradient from white to light purple-blue
+- **Floating Card**: White card with rounded corners and shadow
+- **Responsive Layout**: Two-column on desktop, stacked on mobile
+- **Interactive Elements**: Hover effects and smooth transitions
+
+## Accessibility
+
+- Proper ARIA labels for screen readers
+- Keyboard navigation support
+- Focus indicators for interactive elements
+- Semantic HTML structure
+
+## Browser Support
+
+- Chrome (latest)
+- Firefox (latest)
+- Safari (latest)
+- Edge (latest)
+
+## Performance
+
+- Optimized animations using CSS transforms
+- Efficient state management
+- Minimal re-renders
+- Lazy loading ready for images
\ No newline at end of file
diff --git a/code/src/components/DifferentiatorSection/index.ts b/code/src/components/DifferentiatorSection/index.ts
new file mode 100644
index 0000000..891b7c7
--- /dev/null
+++ b/code/src/components/DifferentiatorSection/index.ts
@@ -0,0 +1,2 @@
+export { default } from './DifferentiatorSection';
+export type { DifferentiatorSectionProps, DifferentiatorAccordionItem } from './DifferentiatorSection';
\ No newline at end of file
diff --git a/code/src/components/FeaturedSection/FeaturedSection.css b/code/src/components/FeaturedSection/FeaturedSection.css
new file mode 100644
index 0000000..008cfea
--- /dev/null
+++ b/code/src/components/FeaturedSection/FeaturedSection.css
@@ -0,0 +1,213 @@
+.featured-section {
+ padding: 4rem 0;
+ background: linear-gradient(135deg, rgba(213, 232, 250, 0.46) 0%, rgba(231, 223, 255, 0.46) 100%);
+ width: 100%;
+}
+
+.featured-container {
+ max-width: 80rem;
+ margin: 0 auto;
+ padding: 0 1.5rem;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.featured-title {
+ text-align: center;
+ margin-bottom: 4rem;
+ font-size: 3rem;
+ font-weight: 600;
+ color: #1f2937;
+}
+
+.featured-grid {
+ display: flex;
+ flex-direction: column;
+ gap: 6rem;
+}
+
+.featured-item {
+ display: flex;
+ align-items: center;
+ min-height: 500px;
+ gap: 4rem;
+}
+
+.featured-item.image-right {
+ flex-direction: row;
+}
+
+.featured-item.image-left {
+ flex-direction: row-reverse;
+}
+
+.featured-text-content {
+ flex: 1;
+ max-width: 600px;
+}
+
+.featured-card-title {
+ font-size: 1.75rem;
+ font-weight: 600;
+ margin-bottom: 1.5rem;
+ color: #1f2937;
+ line-height: 1.2;
+}
+
+.featured-card-description {
+ color: #6b7280;
+ margin-bottom: 2rem;
+ line-height: 1.7;
+ font-size: 1.125rem;
+}
+
+.featured-subsection {
+ margin-bottom: 1.5rem;
+}
+
+.featured-subsection-title {
+ font-size: 0.875rem;
+ font-weight: 600;
+ color: #374151;
+ margin-bottom: 0.5rem;
+}
+
+.featured-chips {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.5rem;
+}
+
+.featured-chip {
+ font-size: 0.75rem;
+ background: #f9fafb;
+ color: #374151;
+ padding: 0.25rem 0.75rem;
+ border-radius: 0.375rem;
+ border: 1px solid #d1d5db;
+ display: inline-block;
+ line-height: 1.2;
+}
+
+.featured-languages {
+ color: #6b7280;
+ font-size: 0.875rem;
+ margin-bottom: 2rem;
+}
+
+.featured-button {
+ margin-top: 1rem;
+}
+
+.featured-image-container {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ position: relative;
+}
+
+.featured-image {
+ max-width: 100%;
+ max-height: 500px;
+ object-fit: contain;
+ transition: transform 0.3s ease;
+ cursor: pointer;
+}
+
+.featured-image:hover {
+ transform: scale(1.02);
+}
+
+.featured-image-placeholder {
+ width: 100%;
+ height: 300px;
+ background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%);
+ border: 2px dashed #d1d5db;
+ border-radius: 12px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #6b7280;
+ font-size: 1.125rem;
+ font-weight: 500;
+ text-align: center;
+ padding: 2rem;
+ line-height: 1.4;
+}
+
+.loading {
+ text-align: center;
+ color: #6b7280;
+ padding: 2rem;
+}
+
+/* Responsive Design */
+@media (max-width: 1024px) {
+ .featured-item,
+ .featured-item.image-right,
+ .featured-item.image-left {
+ flex-direction: column;
+ gap: 3rem;
+ text-align: center;
+ }
+
+ .featured-text-content {
+ max-width: 100%;
+ }
+
+ .featured-image-container {
+ min-height: 300px;
+ }
+}
+
+@media (max-width: 768px) {
+ .featured-section {
+ padding: 4rem 0;
+ }
+
+ .featured-container {
+ padding: 0 1rem;
+ }
+
+ .featured-title {
+ font-size: 2.5rem;
+ margin-bottom: 3rem;
+ }
+
+ .featured-grid {
+ gap: 4rem;
+ }
+
+ .featured-item {
+ min-height: auto;
+ gap: 2rem;
+ }
+
+ .featured-card-title {
+ font-size: 1.375rem;
+ }
+
+ .featured-card-description {
+ font-size: 1rem;
+ }
+}
+
+@media (max-width: 480px) {
+ .featured-container {
+ padding: 0 1rem;
+ }
+
+ .featured-title {
+ font-size: 2rem;
+ }
+
+ .featured-card-title {
+ font-size: 1.125rem;
+ }
+
+ .featured-tags {
+ gap: 0.5rem;
+ }
+}
\ No newline at end of file
diff --git a/code/src/components/FeaturedSection/FeaturedSection.tsx b/code/src/components/FeaturedSection/FeaturedSection.tsx
new file mode 100644
index 0000000..1ec8a09
--- /dev/null
+++ b/code/src/components/FeaturedSection/FeaturedSection.tsx
@@ -0,0 +1,164 @@
+import { useState, useEffect } from 'react';
+import { Button, Title1 } from '@fluentui/react-components';
+import { OpenRegular } from '@fluentui/react-icons';
+import type { AcceleratorCard } from '../../types';
+import './FeaturedSection.css';
+
+interface FeaturedSectionProps {
+ title?: string;
+ acceleratorNames: string[];
+ allCards: AcceleratorCard[]; // Pass the full cards array from App.tsx
+}
+
+// Map accelerator names to their image files (keeping this for consistent visuals)
+const ACCELERATOR_IMAGE_MAP: Record = {
+ 'Multi-Agent Custom Automation Engine': {
+ imageFile: 'multiagent.png',
+ figmaDescription: "Delegate complex, repetitive tasks to AI agents that act on your behalf—executing work efficiently, reducing manual effort, and ensuring results align with your organization's standards."
+ },
+ 'Content Processing': {
+ imageFile: 'contentprocessing.png',
+ figmaDescription: "Speed up document-heavy tasks using AI that understands text, tables, and charts—turning them into clear, usable data. Process claims, invoices, and contracts with precision and confidence."
+ },
+ 'Conversation Knowledge Mining': {
+ imageFile: 'conversationknowledgemining.png',
+ figmaDescription: "Improve contact center performance with AI-powered conversation intelligence—analyzing audio and text data on a large scale to show insights, improve service, and drive smarter decisions."
+ }
+};
+
+const FeaturedSection = ({ title = "Featured AI Accelerators", acceleratorNames, allCards }: FeaturedSectionProps) => {
+ const [featuredCards, setFeaturedCards] = useState([]);
+ const [isLoading, setIsLoading] = useState(true);
+
+ // Filter the cards array to get only the requested featured accelerators
+ useEffect(() => {
+ setIsLoading(true);
+
+ // Find cards that match the requested accelerator names and preserve order
+ const filteredCards = acceleratorNames
+ .map(name => allCards.find(card => card.accelerator === name))
+ .filter((card): card is AcceleratorCard => card !== undefined);
+
+ // Log any missing accelerators for debugging
+ const foundNames = filteredCards.map(card => card.accelerator);
+ const missingNames = acceleratorNames.filter(name => !foundNames.includes(name));
+ if (missingNames.length > 0) {
+ console.warn('Featured accelerators not found in data:', missingNames);
+ }
+
+ setFeaturedCards(filteredCards);
+ setIsLoading(false);
+ }, [acceleratorNames, allCards]);
+
+ if (isLoading) {
+ return (
+
+
+
{title}
+
Loading featured accelerators...
+
+
+ );
+ }
+
+ if (featuredCards.length === 0) {
+ return (
+
+
+
{title}
+
No featured accelerators found. Please check the accelerator names.
+
+
+ );
+ }
+
+ return (
+
+
+
{title}
+
+ {featuredCards.map((card, index) => {
+ const imageMapping = ACCELERATOR_IMAGE_MAP[card.accelerator];
+ const isImageRight = index % 2 === 0; // Alternate image position
+
+ return (
+
+ {/* Text Content */}
+
+
{card.accelerator}
+
+ {imageMapping?.figmaDescription || card.excerpt}
+
+
+ {/* Products and services */}
+ {card.productsAndServices && card.productsAndServices.length > 0 && (
+
+
Products and services
+
+ {card.productsAndServices.slice(0, 6).map((item, i) => (
+
+ {item}
+
+ ))}
+
+
+ )}
+
+ {/* Languages */}
+ {card.programmingLanguages && card.programmingLanguages.length > 0 && (
+
+
Languages
+
+ {card.programmingLanguages.join(', ')}
+
+
+ )}
+
+ {/* GitHub Button */}
+
+
+
+ {/* Image Content */}
+
+ {imageMapping ? (
+
+ ) : (
+ // For accelerators without image mapping, show placeholder
+
+ {card.accelerator}
+
+ )}
+
+
+ );
+ })}
+
+
+
+ );
+};
+
+export default FeaturedSection;
\ No newline at end of file
diff --git a/code/src/components/FeaturedSection/index.ts b/code/src/components/FeaturedSection/index.ts
new file mode 100644
index 0000000..ceae5e8
--- /dev/null
+++ b/code/src/components/FeaturedSection/index.ts
@@ -0,0 +1 @@
+export { default } from './FeaturedSection';
\ No newline at end of file
diff --git a/code/src/components/Footer/Footer.css b/code/src/components/Footer/Footer.css
new file mode 100644
index 0000000..c0cfce8
--- /dev/null
+++ b/code/src/components/Footer/Footer.css
@@ -0,0 +1,188 @@
+.footer {
+ background-color: var(--colorNeutralBackground3);
+ padding: 3rem 0 1rem 0;
+ width: 100%;
+}
+
+.footer-container {
+ width: 100%;
+ padding: 0 1.5rem;
+ max-width: 80rem;
+ margin: 0 auto;
+}
+
+.footer-top {
+ display: grid;
+ grid-template-columns: 1fr auto;
+ gap: 2rem;
+ margin-bottom: 2rem;
+ align-items: start;
+}
+
+.footer-headline {
+ flex: 1;
+ text-align: left;
+}
+
+.footer-headline h2 {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+ .footer-content {
+ display: flex;
+ align-items: flex-start;
+ gap: 0.75rem;
+ max-width: 40rem;
+ justify-self: end;
+ margin-right: -5rem;
+ }
+
+.footer-icon {
+ position: relative;
+ flex-shrink: 0;
+}
+
+.envelope-icon {
+ width: 3rem;
+ height: 3rem;
+ object-fit: contain;
+}
+
+.at-symbol {
+ position: absolute;
+ top: -0.25rem;
+ right: -0.25rem;
+ width: 0.75rem;
+ height: 0.75rem;
+ background-color: #d13438;
+ border-radius: 0.125rem;
+}
+
+ .footer-text {
+ font-size: 0.875rem;
+ line-height: 1.5;
+ color: var(--colorNeutralForeground1);
+ text-wrap: balance;
+ text-align: left;
+ }
+
+.footer-text .footer-nowrap {
+ white-space: nowrap;
+}
+
+.footer-text a {
+ color: var(--colorBrandForeground1);
+ text-decoration: underline;
+}
+
+.footer-text a:hover {
+ text-decoration: none;
+}
+
+.footer-bottom {
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ gap: 2rem;
+ margin-left: auto;
+ max-width: 28rem;
+ white-space: nowrap;
+}
+
+.footer-links {
+ display: flex;
+ gap: 2rem;
+ flex-wrap: nowrap;
+ justify-content: flex-start;
+ white-space: nowrap;
+}
+
+.footer-links a {
+ font-size: 0.875rem;
+ color: var(--colorNeutralForeground1);
+ text-decoration: none;
+ white-space: nowrap;
+}
+
+.footer-links a:hover {
+ text-decoration: underline;
+}
+
+.footer-copyright {
+ text-align: right;
+ flex-shrink: 0;
+ white-space: nowrap;
+}
+
+.copyright-text {
+ font-size: 0.875rem;
+ color: var(--colorNeutralForeground3);
+}
+
+/* Responsive design */
+@media (max-width: 1024px) {
+ .footer-top {
+ grid-template-columns: 1fr;
+ gap: 1.5rem;
+ }
+
+ .footer-content {
+ justify-self: start;
+ margin-right: 0;
+ max-width: 100%;
+ }
+}
+
+@media (max-width: 768px) {
+ .footer-top {
+ flex-direction: column;
+ align-items: flex-start;
+ text-align: left;
+ }
+
+ .footer-headline {
+ order: 1;
+ margin-bottom: 1rem;
+ max-width: 100%;
+ white-space: normal;
+ }
+
+ .footer-content {
+ order: 2;
+ max-width: 100%;
+ justify-content: flex-start;
+ }
+
+ .footer-bottom {
+ flex-direction: column;
+ align-items: flex-start;
+ text-align: left;
+ margin-left: 0;
+ max-width: 100%;
+ white-space: normal;
+ }
+
+ .footer-links {
+ justify-content: flex-start;
+ margin-bottom: 1rem;
+ flex-wrap: wrap;
+ white-space: normal;
+ }
+
+ .footer-copyright {
+ text-align: left;
+ white-space: normal;
+ }
+
+ .footer-text {
+ text-align: left;
+ }
+}
+
+@media (max-width: 480px) {
+ .footer-links {
+ gap: 1rem;
+ }
+}
\ No newline at end of file
diff --git a/code/src/components/Footer/Footer.tsx b/code/src/components/Footer/Footer.tsx
new file mode 100644
index 0000000..88c1b01
--- /dev/null
+++ b/code/src/components/Footer/Footer.tsx
@@ -0,0 +1,77 @@
+import React from 'react';
+import { Title2, Text, Link } from '@fluentui/react-components';
+import './Footer.css';
+
+export interface FooterLink {
+ text: string;
+ url: string;
+ target?: '_blank' | '_self' | '_parent' | '_top';
+}
+
+export interface FooterProps {
+ /** Main headline text (left-aligned) */
+ headline: string;
+ /** URL to the icon image (will use Illustration.png from icons folder) */
+ iconUrl?: string;
+ /** HTML content for the right side content block */
+ content: string;
+ /** Array of footer navigation links */
+ links: FooterLink[];
+ /** Custom copyright text (optional, will auto-generate with current year if not provided) */
+ copyright?: string;
+ /** Additional CSS classes */
+ className?: string;
+}
+
+const Footer: React.FC = ({
+ headline,
+ iconUrl = "/icons/Illustration.png",
+ content,
+ links,
+ copyright,
+ className = ''
+}) => {
+ // Generate copyright text with current year if not provided
+ const copyrightText = copyright || `© Microsoft ${new Date().getFullYear()}`;
+
+ return (
+
+
+
+
+ {headline}
+
+
+
+
+
+
+
+
+
+
+
+ {links.map((link, index) => (
+
+ {link.text}
+
+ ))}
+
+
+ {copyrightText}
+
+
+
+
+ );
+};
+
+export default Footer;
\ No newline at end of file
diff --git a/code/src/components/Footer/README.md b/code/src/components/Footer/README.md
new file mode 100644
index 0000000..e7dee7e
--- /dev/null
+++ b/code/src/components/Footer/README.md
@@ -0,0 +1,65 @@
+# Footer Component
+
+A configurable footer component that displays a headline, contact information with an icon, navigation links, and copyright information.
+
+## Usage
+
+```tsx
+import Footer from './components/Footer';
+
+const footerLinks = [
+ { text: "Sitemap", url: "#" },
+ { text: "Contact Microsoft", url: "#" },
+ { text: "Privacy", url: "#" },
+ { text: "Terms of use", url: "#" },
+ { text: "Trademarks", url: "#" },
+ { text: "Safety & eco", url: "#" },
+ { text: "Recycling", url: "#" },
+ { text: "About our ads", url: "#" }
+];
+
+
+```
+
+## Props
+
+### FooterProps
+
+| Prop | Type | Required | Default | Description |
+|------|------|----------|---------|-------------|
+| `headline` | `string` | Yes | - | Main headline text (centered) |
+| `iconUrl` | `string` | No | `"/icons/Illustration.png"` | URL to the icon image |
+| `content` | `string` | Yes | - | HTML content for the right side content block |
+| `links` | `FooterLink[]` | Yes | - | Array of footer navigation links |
+| `copyright` | `string` | No | Auto-generated | Custom copyright text (auto-generates with current year if not provided) |
+| `className` | `string` | No | `""` | Additional CSS classes |
+
+### FooterLink
+
+| Prop | Type | Required | Default | Description |
+|------|------|----------|---------|-------------|
+| `text` | `string` | Yes | - | Link text |
+| `url` | `string` | Yes | - | Link URL |
+| `target` | `'_blank' \| '_self' \| '_parent' \| '_top'` | No | `'_self'` | Link target attribute |
+
+## Features
+
+- **Responsive Design**: Adapts to different screen sizes
+- **Configurable Content**: All text and links can be customized
+- **Auto-generated Copyright**: Automatically uses current year if not specified
+- **HTML Content Support**: Right-side content block supports HTML
+- **Accessibility**: Proper semantic HTML and ARIA attributes
+- **Icon Integration**: Uses the envelope illustration with @ symbol overlay
+
+## Layout
+
+The footer consists of two main sections:
+
+1. **Top Section**: Headline (centered) and contact information with icon
+2. **Bottom Section**: Navigation links (left) and copyright (right)
+
+On mobile devices, the layout stacks vertically for better usability.
\ No newline at end of file
diff --git a/code/src/components/Footer/index.ts b/code/src/components/Footer/index.ts
new file mode 100644
index 0000000..a6576d0
--- /dev/null
+++ b/code/src/components/Footer/index.ts
@@ -0,0 +1,2 @@
+export { default } from './Footer';
+export type { FooterProps, FooterLink } from './Footer';
\ No newline at end of file
diff --git a/code/src/components/GsaCard/GsaCard.css b/code/src/components/GsaCard/GsaCard.css
new file mode 100644
index 0000000..93bc0ce
--- /dev/null
+++ b/code/src/components/GsaCard/GsaCard.css
@@ -0,0 +1,147 @@
+@tailwind components;
+
+@layer components {
+ .perspective-container {
+ perspective: 1200px;
+ }
+
+ .gsa-card {
+ transform: rotateX(var(--x-rotation, 0deg)) rotateY(var(--y-rotation, 0deg)) scale(1);
+ transform-style: preserve-3d;
+ transition: transform 0.3s ease;
+ will-change: transform;
+ transform-origin: center;
+ aspect-ratio: 1/1;
+ height: 380px;
+ width: 100%;
+ @apply bg-neutral-1 flex flex-col rounded-lg relative overflow-hidden border border-neutral-stroke-2;
+ }
+
+ .gsa-card.hovered {
+ transform: rotateX(var(--x-rotation, 0deg)) rotateY(var(--y-rotation, 0deg)) scale(1.02);
+ transition: transform 0.1s ease-out;
+ @apply border-neutral-stroke-1;
+ }
+
+ .gsa-card::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ border-radius: 8px;
+ pointer-events: none;
+ z-index: 2;
+ background: radial-gradient(
+ circle at var(--x, 50%) var(--y, 50%),
+ rgba(255, 255, 255, 0.5),
+ rgba(96, 96, 96, 0.3) 100%
+ );
+ mask:
+ linear-gradient(#fff 0 0) content-box,
+ linear-gradient(#fff 0 0);
+ -webkit-mask:
+ linear-gradient(#fff 0 0) content-box,
+ linear-gradient(#fff 0 0);
+ mask-composite: exclude;
+ -webkit-mask-composite: destination-out;
+ border: 1px solid transparent;
+ box-sizing: border-box;
+ }
+
+ .card-content {
+ @apply z-[1] flex flex-col h-full justify-between;
+ }
+
+ .card-inner {
+ @apply flex flex-col h-full p-3;
+ }
+
+ .card-header {
+ @apply flex justify-between items-start min-h-6;
+ }
+
+ .text-neutral-3 {
+ @apply text-neutral-foreground-3 text-sm;
+ }
+
+ .repo-excerpt {
+ @apply flex flex-col gap-1;
+ }
+
+ .truncate {
+ @apply whitespace-nowrap overflow-hidden text-ellipsis max-w-full;
+ }
+
+ .excerpt {
+ @apply text-neutral-foreground-2 text-sm;
+ display: -webkit-box !important;
+ -webkit-line-clamp: 4 !important;
+ -webkit-box-orient: vertical !important;
+ overflow: hidden !important;
+ text-overflow: ellipsis !important;
+ margin-bottom: 8px;
+ word-wrap: break-word;
+ line-height: 1.4;
+ }
+
+
+
+ .status-container {
+ @apply flex flex-col min-w-0 gap-0.5;
+ }
+
+ .status {
+ @apply flex items-center gap-1;
+ }
+
+ .status-dot {
+ @apply w-1.5 h-1.5 rounded-full inline-block;
+ }
+
+ .status-text {
+ @apply overflow-hidden text-ellipsis whitespace-nowrap max-w-full;
+ }
+
+ .card-content-main {
+ @apply flex flex-col gap-1 flex-grow;
+ }
+
+ .products-section {
+ @apply mt-1;
+ }
+
+ .github-button {
+ @apply flex w-full justify-start mt-auto pt-2;
+ }
+
+ .glow-effect {
+ @apply absolute inset-0 rounded-lg pointer-events-none z-[99];
+ transition: background 0.3s ease;
+ }
+
+ .status-indicator {
+ @apply flex items-center gap-1 text-xs px-2 py-1 rounded;
+ background-color: #f3f4f6;
+ color: #000000;
+ }
+
+ .status-icon {
+ @apply w-3 h-3;
+ color: #059669;
+ }
+
+ .languages-section {
+ @apply flex flex-col gap-1 mt-1;
+ }
+
+ .languages-text {
+ @apply text-neutral-foreground-2 text-xs;
+ line-height: 1.4;
+ }
+
+ /* Simple fix for 1200-1250px width issue */
+ @media (min-width: 1200px) and (max-width: 1250px) {
+ .gsa-card {
+ min-height: 360px;
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/src/components/GsaCard/GsaCard.tsx b/code/src/components/GsaCard/GsaCard.tsx
new file mode 100644
index 0000000..45ad613
--- /dev/null
+++ b/code/src/components/GsaCard/GsaCard.tsx
@@ -0,0 +1,162 @@
+import { useState, useRef } from "react";
+import {
+ Body1,
+ Button,
+ Caption1,
+ Caption1Strong,
+ Subtitle2,
+} from "@fluentui/react-components";
+import { OpenRegular, ShieldCheckmarkRegular } from "@fluentui/react-icons";
+import "./GsaCard.css";
+import type { AcceleratorCard, AcceleratorAsset } from "../../types";
+
+type GsaCardProps = Omit & {
+ assets?: AcceleratorAsset[];
+ rowHeightVersion?: number;
+ excerptHeight?: number;
+ reportExcerptHeight?: (index: number, height: number) => void;
+};
+
+const GsaCard = ({
+ accelerator,
+ excerpt,
+ solutionAreas,
+ productsAndServices,
+ programmingLanguages,
+ githubUrl,
+}: GsaCardProps) => {
+ const [isHovered, setIsHovered] = useState(false);
+ const boundingRef = useRef(null);
+
+
+
+ const LanguagesDisplay = ({ languages }: { languages: string[] }) => {
+ return (
+
+ Languages
+
+ {languages ? languages.join(', ') : 'No languages specified'}
+
+
+ );
+ };
+
+ return (
+
+
+
{
+ setIsHovered(true);
+ boundingRef.current = e.currentTarget.getBoundingClientRect();
+ }}
+ onMouseLeave={(e) => {
+ setIsHovered(false);
+ boundingRef.current = null;
+ e.currentTarget.style.setProperty("--x-rotation", "0deg");
+ e.currentTarget.style.setProperty("--y-rotation", "0deg");
+ }}
+ onMouseMove={(e) => {
+ if (!boundingRef.current) return;
+ const x = e.clientX - boundingRef.current.left;
+ const y = e.clientY - boundingRef.current.top;
+ const xPercentage = x / boundingRef.current.width;
+ const yPercentage = y / boundingRef.current.height;
+
+ const xRotation = (yPercentage - 0.5) * 10;
+ const yRotation = (xPercentage - 0.5) * -10;
+
+ const target = e.currentTarget as HTMLElement;
+ target.style.setProperty("--x-rotation", `${xRotation}deg`);
+ target.style.setProperty("--y-rotation", `${yRotation}deg`);
+ target.style.setProperty("--x", `${xPercentage * 100}%`);
+ target.style.setProperty("--y", `${yPercentage * 100}%`);
+ }}
+ className={`gsa-card ${isHovered ? "hovered" : ""}`}
+ >
+ {/* Card Content */}
+
+
+ {/* Header with Solution Area & Status */}
+
+
+ {Array.isArray(solutionAreas) ? solutionAreas.join(', ') : solutionAreas}
+
+
+
+ Actively maintained
+
+
+
+ {/* Content Section - This will expand to fill available space */}
+
+ {/* Title & Excerpt */}
+
+
+ {accelerator}
+
+
+
+ {excerpt}
+
+
+
+ {/* Products and Services */}
+
+
Products and Services
+
+ {productsAndServices?.slice(0, 6).map((item, i) => (
+
+ {item}
+
+ ))}
+
+
+
+ {/* Languages */}
+
+
+
+ {/* GitHub Button - This will stick to the bottom */}
+
+
+
+
+ {/* Hover Effect */}
+
+
+
+
+ );
+};
+
+export default GsaCard;
\ No newline at end of file
diff --git a/code/src/components/Header/Header.css b/code/src/components/Header/Header.css
new file mode 100644
index 0000000..4d3420d
--- /dev/null
+++ b/code/src/components/Header/Header.css
@@ -0,0 +1,27 @@
+/* Header component styles */
+.header {
+ position: relative;
+ z-index: 10;
+}
+
+/* Ensure no default solid background interrupts the shared gradient */
+header {
+ background: transparent;
+}
+
+.header-content {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+/* Responsive header styles */
+@media (max-width: 768px) {
+ .header {
+ padding: 0.75rem 1rem;
+ }
+
+ .header-content {
+ gap: 0.25rem;
+ }
+}
\ No newline at end of file
diff --git a/code/src/components/Header/Header.tsx b/code/src/components/Header/Header.tsx
new file mode 100644
index 0000000..46cf059
--- /dev/null
+++ b/code/src/components/Header/Header.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+import { Text } from '@fluentui/react-components';
+import './Header.css';
+
+export interface HeaderProps {
+ /** Logo component or image URL */
+ logo: React.ReactNode;
+ /** Main title text */
+ title: string;
+ /** Subtitle text (optional) */
+ subtitle?: string;
+ /** Additional CSS classes */
+ className?: string;
+}
+
+const Header: React.FC = ({
+ logo,
+ title,
+ subtitle,
+ className = ''
+}) => {
+ return (
+
+ );
+};
+
+export default Header;
\ No newline at end of file
diff --git a/code/src/components/Header/index.ts b/code/src/components/Header/index.ts
new file mode 100644
index 0000000..081cd8c
--- /dev/null
+++ b/code/src/components/Header/index.ts
@@ -0,0 +1,2 @@
+export { default } from './Header';
+export type { HeaderProps } from './Header';
\ No newline at end of file
diff --git a/code/src/components/HeroSection/HeroSection.css b/code/src/components/HeroSection/HeroSection.css
new file mode 100644
index 0000000..f057120
--- /dev/null
+++ b/code/src/components/HeroSection/HeroSection.css
@@ -0,0 +1,40 @@
+/* HeroSection component styles */
+.hero-section {
+ min-height: calc(100vh - 80px); /* Account for header height */
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ width: 100%;
+}
+
+.hero-content {
+ max-width: 80rem;
+ margin: 0 auto;
+ padding: 0 1.5rem;
+}
+
+/* Responsive hero styles */
+@media (max-width: 768px) {
+ .hero-section {
+ min-height: calc(100vh - 60px);
+ padding: 2rem 1rem;
+ }
+
+ .hero-content {
+ padding: 0 1rem;
+ }
+
+ .hero-title {
+ font-size: 2.75rem !important;
+ }
+}
+
+@media (max-width: 480px) {
+ .hero-section {
+ padding: 1.5rem 0.75rem;
+ }
+
+ .hero-title {
+ font-size: 2.25rem !important;
+ }
+}
\ No newline at end of file
diff --git a/code/src/components/HeroSection/HeroSection.tsx b/code/src/components/HeroSection/HeroSection.tsx
new file mode 100644
index 0000000..813c58e
--- /dev/null
+++ b/code/src/components/HeroSection/HeroSection.tsx
@@ -0,0 +1,111 @@
+import React from 'react';
+import { Subtitle1, Button } from '@fluentui/react-components';
+import VideoPlayer from '../VideoPlayer';
+import { REVERSE_SECTION_MAPPING } from '../../utils/sectionMapping';
+import './HeroSection.css';
+
+export interface LinkConfig {
+ text: string;
+ url: string;
+ target?: '_blank' | '_self';
+}
+
+export interface HeroSectionProps {
+ /** Main title with support for HTML */
+ title: string;
+ /** Content description */
+ content: string;
+ /** Link configuration */
+ link: LinkConfig;
+ /** YouTube video URL */
+ videoUrl: string;
+ /** Whether the video should autoplay */
+ videoAutoplay?: boolean;
+ /** Additional CSS classes */
+ className?: string;
+ /** Navigation callback for deep linking */
+ onNavigate?: (section: string) => void;
+}
+
+const HeroSection: React.FC = ({
+ title,
+ content,
+ link,
+ videoUrl,
+ videoAutoplay = false,
+ className = '',
+ onNavigate
+}) => {
+ const handleLinkClick = (e: React.MouseEvent) => {
+ e.preventDefault();
+
+ if (onNavigate && link.url.startsWith('#')) {
+ const targetId = link.url.substring(1);
+ const section = REVERSE_SECTION_MAPPING[targetId];
+ if (section) {
+ onNavigate(section);
+ return;
+ }
+ }
+
+ if (link.url.startsWith('#')) {
+ const targetId = link.url.substring(1);
+ const targetElement = document.getElementById(targetId);
+
+ if (targetElement) {
+ targetElement.scrollIntoView({
+ behavior: 'smooth',
+ block: 'start'
+ });
+ }
+ } else {
+ if (link.target === '_blank') {
+ window.open(link.url, '_blank', 'noopener,noreferrer');
+ } else {
+ window.location.href = link.url;
+ }
+ }
+ };
+
+ return (
+
+
+
+
+ {title.split(' ').map((part, index) => (
+
+ {part}
+ {index < title.split(' ').length - 1 && }
+
+ ))}
+
+
+ {content}
+
+
+ {link.text}
+
+
+
+ {/* Video Player */}
+
+
+
+ );
+};
+
+export default HeroSection;
\ No newline at end of file
diff --git a/code/src/components/HeroSection/README.md b/code/src/components/HeroSection/README.md
new file mode 100644
index 0000000..7d667a4
--- /dev/null
+++ b/code/src/components/HeroSection/README.md
@@ -0,0 +1,82 @@
+# HeroSection Component
+
+A reusable hero section component that displays a title, content, call-to-action button, and YouTube video player.
+
+## Props
+
+### `title: string`
+The main title with support for line breaks using ` ` tags.
+
+### `content: string`
+The descriptive content text.
+
+### `link: LinkConfig`
+Configuration for the call-to-action button:
+```typescript
+interface LinkConfig {
+ text: string; // Button text
+ url: string; // URL or anchor link
+ target?: '_blank' | '_self'; // Optional target for external links
+}
+```
+
+### `videoUrl: string`
+YouTube video URL (supports embed, watch, and short URLs).
+
+### `videoAutoplay?: boolean`
+Whether the video should autoplay when loaded. Defaults to `false`.
+
+### `className?: string`
+Optional additional CSS classes.
+
+## Usage Examples
+
+### Basic Usage
+```tsx
+
+```
+
+### External Link
+```tsx
+
+```
+
+### Anchor Link (Smooth Scroll)
+```tsx
+
+```
+
+## Features
+
+- **Smart Link Handling**: Automatically detects anchor links (`#section`) vs external URLs
+- **Smooth Scrolling**: Anchor links smoothly scroll to the target section
+- **Video Player**: YouTube video with thumbnail preview and play button (now uses the reusable VideoPlayer component)
+- **Responsive Design**: Maintains visual consistency across screen sizes
+- **TypeScript Support**: Full type safety with proper interfaces
\ No newline at end of file
diff --git a/code/src/components/HeroSection/index.ts b/code/src/components/HeroSection/index.ts
new file mode 100644
index 0000000..4561ff6
--- /dev/null
+++ b/code/src/components/HeroSection/index.ts
@@ -0,0 +1,2 @@
+export { default } from './HeroSection';
+export type { HeroSectionProps, LinkConfig } from './HeroSection';
\ No newline at end of file
diff --git a/code/src/components/HowItWorksSection/HowItWorksSection.tsx b/code/src/components/HowItWorksSection/HowItWorksSection.tsx
new file mode 100644
index 0000000..bda96b2
--- /dev/null
+++ b/code/src/components/HowItWorksSection/HowItWorksSection.tsx
@@ -0,0 +1,143 @@
+import React from 'react';
+import {
+ Title1,
+ Title3,
+ Text,
+ makeStyles,
+ tokens
+} from '@fluentui/react-components';
+
+export interface HowItWorksStep {
+ icon: string; // URL to icon image
+ label: string; // Step title (e.g., "Step 1: Browse")
+ content: string; // Step description
+}
+
+export interface HowItWorksSectionProps {
+ title: string; // Section title (e.g., "How it works")
+ steps: HowItWorksStep[]; // Array of step objects
+ className?: string; // Optional custom styling
+}
+
+const useStyles = makeStyles({
+ container: {
+ padding: '4rem 0',
+ backgroundColor: 'white',
+ },
+ content: {
+ maxWidth: '80rem',
+ margin: '0 auto',
+ padding: '0 1.5rem',
+ },
+ title: {
+ textAlign: 'center',
+ marginBottom: '4rem',
+ display: 'flex',
+ justifyContent: 'center',
+ width: '100%',
+ },
+ stepsContainer: {
+ display: 'flex',
+ flexDirection: 'row',
+ justifyContent: 'center',
+ alignItems: 'flex-start',
+ gap: '0',
+ '@media (max-width: 1023px)': {
+ flexDirection: 'column',
+ alignItems: 'center',
+ },
+ },
+ stepItem: {
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'center',
+ textAlign: 'center',
+ gap: '1rem',
+ flex: '1',
+ maxWidth: '250px',
+ '@media (max-width: 1023px)': {
+ maxWidth: '300px',
+ marginBottom: '2rem',
+ },
+ },
+ iconContainer: {
+ width: '64px',
+ height: '64px',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginBottom: '1rem',
+ position: 'relative',
+ },
+ icon: {
+ width: '100%',
+ height: '100%',
+ objectFit: 'contain',
+ },
+ stepLabel: {
+ fontWeight: '600',
+ marginBottom: '0.5rem',
+ },
+ stepContent: {
+ color: tokens.colorNeutralForeground2,
+ lineHeight: '1.5',
+ textAlign: 'center',
+ },
+ betweenStepSeparator: {
+ width: '1px',
+ height: '16rem',
+ backgroundColor: tokens.colorNeutralStroke1,
+ margin: '0 3rem',
+ alignSelf: 'center',
+ borderRadius: '0px',
+ '@media (max-width: 1023px)': {
+ display: 'none',
+ },
+ },
+});
+
+const HowItWorksSection: React.FC = ({
+ title,
+ steps,
+ className
+}) => {
+ const styles = useStyles();
+
+ return (
+
+
+
+ {title}
+
+
+
+ {steps.map((step, index) => (
+
+
+
+
+
+
+ {step.label}
+
+
+ {step.content}
+
+
+ {/* Add separator between steps (except after the last step) */}
+ {index < steps.length - 1 && (
+
+ )}
+
+ ))}
+
+
+
+ );
+};
+
+export default HowItWorksSection;
\ No newline at end of file
diff --git a/code/src/components/HowItWorksSection/README.md b/code/src/components/HowItWorksSection/README.md
new file mode 100644
index 0000000..13943ef
--- /dev/null
+++ b/code/src/components/HowItWorksSection/README.md
@@ -0,0 +1,92 @@
+# HowItWorksSection Component
+
+A reusable component for displaying a "How it works" section with configurable steps, icons, and content.
+
+## Features
+
+- **Configurable steps**: Pass an array of step objects with icons, labels, and content
+- **Responsive design**: Automatically adapts to different screen sizes (1/2/4 columns)
+- **Accessible**: Includes proper alt text and semantic HTML
+- **Customizable**: Optional className prop for additional styling
+- **Clean design**: Matches Figma design with centered title and line separators
+
+## Props
+
+### HowItWorksSectionProps
+
+| Prop | Type | Required | Description |
+|------|------|----------|-------------|
+| `title` | `string` | Yes | The main section title (e.g., "How it works") |
+| `steps` | `HowItWorksStep[]` | Yes | Array of step objects |
+| `className` | `string` | No | Optional CSS class for additional styling |
+
+### HowItWorksStep
+
+| Property | Type | Required | Description |
+|----------|------|----------|-------------|
+| `icon` | `string` | Yes | URL to the step icon image |
+| `label` | `string` | Yes | Step title (e.g., "Step 1: Browse") |
+| `content` | `string` | Yes | Step description text |
+
+## Usage
+
+```tsx
+import { HowItWorksSection } from './components/HowItWorksSection';
+
+const howItWorksSteps = [
+ {
+ icon: "/icons/Search Progress.png",
+ label: "Step 1: Browse",
+ content: "Browse available Accelerators to discover ready-made solutions tailored to your customer needs."
+ },
+ {
+ icon: "/icons/Editor.png",
+ label: "Step 2: Select",
+ content: "Select the accelerator that best fits your business use case and adapt it to your needs using built-in configuration options."
+ },
+ {
+ icon: "/icons/Grid List.png",
+ label: "Step 3: Review",
+ content: "Review pre-requisites and costing to ensure alignment with your organizational needs."
+ },
+ {
+ icon: "/icons/AI Flash Sparkle.png",
+ label: "Step 4: Deploy",
+ content: "Use deployment guide to launch your solution quickly and securely."
+ }
+];
+
+function App() {
+ return (
+
+ );
+}
+```
+
+## Styling
+
+The component uses Fluent UI's `makeStyles` for styling and includes:
+
+- **Responsive grid**: 1 column on mobile, 2 on tablet, 4 on desktop
+- **Centered layout**: Title and content are centered
+- **Line separators**: Visual dividers between icons and text
+- **Icon containers**: 64x64px containers for consistent icon display
+- **Hover effects**: Subtle animations on step items
+
+## Icon Requirements
+
+Icons should be:
+- **Format**: PNG or SVG with transparency
+- **Size**: Recommended 64x64px or larger (will be scaled down)
+- **Style**: Translucent, glassy appearance to match design
+- **Location**: Stored in `/public/icons/` directory
+
+## Accessibility
+
+- Semantic HTML structure with `` element
+- Proper alt text for all icons
+- Keyboard navigation support
+- Screen reader friendly content structure
\ No newline at end of file
diff --git a/code/src/components/HowItWorksSection/index.ts b/code/src/components/HowItWorksSection/index.ts
new file mode 100644
index 0000000..cf334fc
--- /dev/null
+++ b/code/src/components/HowItWorksSection/index.ts
@@ -0,0 +1,2 @@
+export { default as HowItWorksSection } from './HowItWorksSection';
+export type { HowItWorksSectionProps, HowItWorksStep } from './HowItWorksSection';
\ No newline at end of file
diff --git a/code/src/components/Navigation/Navigation.css b/code/src/components/Navigation/Navigation.css
new file mode 100644
index 0000000..56df7f8
--- /dev/null
+++ b/code/src/components/Navigation/Navigation.css
@@ -0,0 +1,79 @@
+/* Navigation component styles */
+.navigation-header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ background-color: white;
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
+ transform: translateY(0);
+ transition: transform 300ms ease;
+ z-index: 50;
+}
+
+.navigation-header.hidden {
+ transform: translateY(-100%);
+}
+
+.navigation-container {
+ max-width: 80rem;
+ margin: 0 auto;
+ padding: 0 1.5rem;
+}
+
+.navigation-content {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ height: 4rem;
+}
+
+.desktop-nav {
+ display: flex;
+}
+
+.mobile-nav {
+ display: none;
+}
+
+.feedback-button {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.hamburger-button {
+ min-width: auto;
+ padding: 0.5rem;
+}
+
+/* Responsive breakpoints */
+@media (max-width: 768px) {
+ .desktop-nav {
+ display: none;
+ }
+
+ .mobile-nav {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ }
+
+ .feedback-button .feedback-text-full {
+ display: none;
+ }
+
+ .feedback-button .feedback-text-mobile {
+ display: inline;
+ }
+}
+
+@media (min-width: 769px) {
+ .feedback-button .feedback-text-full {
+ display: inline;
+ }
+
+ .feedback-button .feedback-text-mobile {
+ display: none;
+ }
+}
\ No newline at end of file
diff --git a/code/src/components/Navigation/Navigation.tsx b/code/src/components/Navigation/Navigation.tsx
new file mode 100644
index 0000000..deb0bc0
--- /dev/null
+++ b/code/src/components/Navigation/Navigation.tsx
@@ -0,0 +1,121 @@
+import { useState } from 'react';
+import {
+ Button,
+ TabList,
+ Tab,
+ Menu,
+ MenuTrigger,
+ MenuPopover,
+ MenuList,
+ MenuItem
+} from '@fluentui/react-components';
+import {
+ LineHorizontal3Regular
+} from '@fluentui/react-icons';
+import './Navigation.css';
+
+export interface NavigationTab {
+ value: string;
+ label: string;
+ targetId: string;
+}
+
+export interface NavigationProps {
+ tabs: NavigationTab[];
+ selectedTab: string;
+ onTabSelect: (tab: string) => void;
+ isVisible: boolean;
+ onFeedbackClick?: () => void;
+ feedbackButtonText?: string;
+}
+
+
+
+export default function Navigation({
+ tabs,
+ selectedTab,
+ onTabSelect,
+ isVisible,
+ onFeedbackClick,
+ feedbackButtonText = "Share your feedback"
+}: NavigationProps) {
+ const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
+
+ const handleTabClick = (tab: NavigationTab) => {
+ onTabSelect(tab.value);
+ setIsMobileMenuOpen(false);
+ };
+
+ const handleFeedbackClick = () => {
+ if (onFeedbackClick) {
+ onFeedbackClick();
+ } else {
+ window.location.href = "mailto:CSAGoldStandards@service.microsoft.com?subject=Feedback%20on%20AI%20Accelerators";
+ }
+ };
+
+ return (
+
+
+
+ {/* Desktop Navigation */}
+
+ onTabSelect(data.value as string)}
+ size="medium"
+ className="!border-b-0"
+ >
+ {tabs.map((tab) => (
+ handleTabClick(tab)}
+ >
+ {tab.label}
+
+ ))}
+
+
+
+ {/* Mobile Navigation */}
+
+
setIsMobileMenuOpen(data.open)}>
+
+ }
+ className="hamburger-button"
+ aria-label="Open navigation menu"
+ />
+
+
+
+ {tabs.map((tab) => (
+ handleTabClick(tab)}
+ >
+ {tab.label}
+
+ ))}
+
+
+
+
+
+ {/* Feedback Button */}
+
}
+ onClick={handleFeedbackClick}
+ className="feedback-button"
+ >
+
{feedbackButtonText}
+
Feedback
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/code/src/components/Navigation/NavigationSection.css b/code/src/components/Navigation/NavigationSection.css
new file mode 100644
index 0000000..125f8e8
--- /dev/null
+++ b/code/src/components/Navigation/NavigationSection.css
@@ -0,0 +1,50 @@
+.navigation-section {
+ /* This section participates in normal flow like the Teams page */
+ background: transparent;
+}
+
+.navigation-sentinel {
+ position: relative;
+ height: 1px; /* minimal, just for IntersectionObserver */
+ margin-top: -1px; /* keep layout unaffected */
+}
+
+.navigation-sticky {
+ position: sticky;
+ top: 0;
+ background-color: white;
+ z-index: 40; /* below floating dialogs but above content */
+ transition: box-shadow 200ms ease;
+}
+
+.navigation-sticky.is-stuck {
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+}
+
+/* Robust fallback: when JavaScript toggles fixed mode after crossing the sentinel */
+.navigation-sticky.is-fixed {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 50;
+}
+
+/* Provide a default nav height in case ResizeObserver hasn't run yet */
+:root {
+ --nav-height: 64px;
+}
+
+/* Utility to apply to content sections so scrollIntoView lands neatly below sticky */
+.section-anchor {
+ scroll-margin-top: var(--nav-height);
+}
+
+.navigation-spacer {
+ height: 0;
+}
+
+.navigation-spacer.active {
+ height: var(--nav-height);
+}
+
diff --git a/code/src/components/Navigation/NavigationSection.tsx b/code/src/components/Navigation/NavigationSection.tsx
new file mode 100644
index 0000000..95d9f24
--- /dev/null
+++ b/code/src/components/Navigation/NavigationSection.tsx
@@ -0,0 +1,172 @@
+import { useEffect, useRef, useState } from 'react';
+import {
+ Button,
+ TabList,
+ Tab,
+ Menu,
+ MenuTrigger,
+ MenuPopover,
+ MenuList,
+ MenuItem
+} from '@fluentui/react-components';
+import { LineHorizontal3Regular } from '@fluentui/react-icons';
+import './Navigation.css';
+import './NavigationSection.css';
+
+export interface NavigationSectionProps {
+ tabs: { value: string; label: string; targetId: string }[];
+ selectedTab: string;
+ onTabSelect: (tab: string) => void;
+ onFeedbackClick?: () => void;
+ feedbackButtonText?: string;
+}
+
+export default function NavigationSection({
+ tabs,
+ selectedTab,
+ onTabSelect,
+ onFeedbackClick,
+ feedbackButtonText = 'Share your feedback'
+}: NavigationSectionProps) {
+ const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
+ const stickyRef = useRef(null);
+ const sentinelRef = useRef(null);
+ const spacerRef = useRef(null);
+
+ // Feedback click fallback
+ const handleFeedbackClick = () => {
+ if (onFeedbackClick) {
+ onFeedbackClick();
+ } else {
+ window.location.href = 'mailto:CSAGoldStandards@service.microsoft.com?subject=Feedback%20on%20AI%20Accelerators';
+ }
+ };
+
+ // Toggle stuck/fixed classes when crossing the sentinel
+ useEffect(() => {
+ const stickyEl = stickyRef.current;
+ const sentinelEl = sentinelRef.current;
+ const spacerEl = spacerRef.current;
+ if (!stickyEl || !sentinelEl) return;
+
+ const applyState = (stuck: boolean) => {
+ if (stuck) {
+ stickyEl.classList.add('is-stuck');
+ stickyEl.classList.add('is-fixed');
+ if (spacerEl) spacerEl.classList.add('active');
+ } else {
+ stickyEl.classList.remove('is-stuck');
+ stickyEl.classList.remove('is-fixed');
+ if (spacerEl) spacerEl.classList.remove('active');
+ }
+ };
+
+ const observer = new IntersectionObserver(
+ (entries) => {
+ const entry = entries[0];
+ const sentinelTop = entry.boundingClientRect.top;
+ const isAboveTop = sentinelTop <= 0; // sentinel has passed the top of the viewport
+ // Only pin when the sentinel is above the top; ignore the case when it's still below the fold
+ applyState(!entry.isIntersecting && isAboveTop);
+ },
+ { threshold: 0 }
+ );
+
+ observer.observe(sentinelEl);
+
+ // Initialize state on mount. Avoid showing fixed header when landed at top of page.
+ const initRect = sentinelEl.getBoundingClientRect();
+ const atTop = window.scrollY <= 0;
+ applyState(!atTop && initRect.top <= 0);
+
+ // Fallback for older browsers or edge cases: scroll listener
+ const onScroll = () => {
+ const rect = sentinelEl.getBoundingClientRect();
+ const atTop = window.scrollY <= 0;
+ applyState(!atTop && rect.top <= 0);
+ };
+ window.addEventListener('scroll', onScroll, { passive: true });
+ window.addEventListener('resize', onScroll);
+
+ return () => observer.disconnect();
+ }, []);
+
+ // Keep a CSS variable up to date with the sticky nav height for scroll-margin-top
+ useEffect(() => {
+ const stickyEl = stickyRef.current;
+ if (!stickyEl) return;
+ const updateVar = () => {
+ const height = stickyEl.offsetHeight || 64;
+ document.documentElement.style.setProperty('--nav-height', `${height}px`);
+ };
+ updateVar();
+ const resizeObserver = new ResizeObserver(updateVar);
+ resizeObserver.observe(stickyEl);
+ return () => resizeObserver.disconnect();
+ }, []);
+
+ return (
+
+ {/* Sentinel sits just above the sticky container */}
+
+
+
+
+ {/* Desktop Navigation */}
+
+ onTabSelect(data.value as string)}
+ size="medium"
+ className="!border-b-0"
+ >
+ {tabs.map((tab) => (
+ onTabSelect(tab.value)}>
+ {tab.label}
+
+ ))}
+
+
+
+ {/* Mobile Navigation */}
+
+
setIsMobileMenuOpen(data.open)}>
+
+ }
+ className="hamburger-button"
+ aria-label="Open navigation menu"
+ />
+
+
+
+ {tabs.map((tab) => (
+ onTabSelect(tab.value)}>
+ {tab.label}
+
+ ))}
+
+
+
+
+
+ {/* Feedback Button */}
+
}
+ onClick={handleFeedbackClick}
+ className="feedback-button"
+ >
+
{feedbackButtonText}
+
Feedback
+
+
+
+
+ {/* Spacer prevents layout jump when the header becomes fixed */}
+
+
+ );
+}
+
diff --git a/code/src/components/Navigation/README.md b/code/src/components/Navigation/README.md
new file mode 100644
index 0000000..120c9ce
--- /dev/null
+++ b/code/src/components/Navigation/README.md
@@ -0,0 +1,90 @@
+# Navigation Component
+
+A responsive navigation component that displays tabs for page navigation with a hamburger menu for mobile devices.
+
+## Features
+
+- **Responsive Design**: Automatically switches between desktop tabs and mobile hamburger menu
+- **Smooth Scrolling**: Clicking tabs scrolls to corresponding page sections
+- **Sticky Header**: Can be configured to show/hide based on scroll position
+- **Customizable**: Accepts an array of tabs and optional feedback button configuration
+
+## Props
+
+### NavigationProps
+
+| Prop | Type | Required | Default | Description |
+|------|------|----------|---------|-------------|
+| `tabs` | `NavigationTab[]` | Yes | - | Array of navigation tabs |
+| `selectedTab` | `string` | Yes | - | Currently selected tab value |
+| `onTabSelect` | `(tab: string) => void` | Yes | - | Callback when a tab is selected |
+| `isVisible` | `boolean` | Yes | - | Whether the navigation header is visible |
+| `onFeedbackClick` | `() => void` | No | - | Custom feedback button click handler |
+| `feedbackButtonText` | `string` | No | "Share your feedback" | Text for the feedback button |
+
+### NavigationTab
+
+| Prop | Type | Required | Description |
+|------|------|----------|-------------|
+| `value` | `string` | Yes | Unique identifier for the tab |
+| `label` | `string` | Yes | Display text for the tab |
+| `targetId` | `string` | Yes | ID of the element to scroll to when clicked |
+
+## Usage
+
+```tsx
+import Navigation, { NavigationTab } from './components/Navigation';
+
+const navigationTabs: NavigationTab[] = [
+ {
+ value: "featured",
+ label: "Featured accelerators",
+ targetId: "featured"
+ },
+ {
+ value: "all",
+ label: "All accelerators",
+ targetId: "accelerators"
+ },
+ // ... more tabs
+];
+
+function App() {
+ const [selectedTab, setSelectedTab] = useState("featured");
+ const [isHeaderVisible, setIsHeaderVisible] = useState(false);
+
+ const handleFeedbackClick = () => {
+ // Custom feedback handling
+ };
+
+ return (
+
+ );
+}
+```
+
+## Responsive Behavior
+
+- **Desktop (>768px)**: Shows full tab list with feedback button
+- **Mobile (≤768px)**: Shows hamburger menu with feedback button (shortened text)
+
+## Styling
+
+The component uses CSS classes for styling. Key classes:
+
+- `.navigation-header`: Main header container
+- `.desktop-nav`: Desktop navigation tabs
+- `.mobile-nav`: Mobile hamburger menu
+- `.feedback-button`: Feedback button styling
+
+## Dependencies
+
+- `@fluentui/react-components`: For UI components (TabList, Tab, Menu, Button)
+- `@fluentui/react-icons`: For icons (Mail20Regular, Hamburger20Regular)
\ No newline at end of file
diff --git a/code/src/components/Navigation/index.ts b/code/src/components/Navigation/index.ts
new file mode 100644
index 0000000..8c60e77
--- /dev/null
+++ b/code/src/components/Navigation/index.ts
@@ -0,0 +1,4 @@
+export { default } from './Navigation';
+export type { NavigationTab, NavigationProps } from './Navigation';
+export { default as NavigationSection } from './NavigationSection';
+export type { NavigationSectionProps } from './NavigationSection';
\ No newline at end of file
diff --git a/code/src/components/SuccessStoriesSection/README.md b/code/src/components/SuccessStoriesSection/README.md
new file mode 100644
index 0000000..8709888
--- /dev/null
+++ b/code/src/components/SuccessStoriesSection/README.md
@@ -0,0 +1,35 @@
+# SuccessStoriesSection Component
+
+A reusable component for displaying testimonial quotes in a grid layout with a gradient background.
+
+## Props
+
+- `title?: string` - The section title (defaults to "Loved by developers")
+- `quotes: TestimonialQuote[]` - Array of quote objects containing quote text and author
+
+## Usage
+
+```tsx
+import SuccessStoriesSection from './components/SuccessStoriesSection';
+
+const quotes = [
+ {
+ quote: "Customers have been amazed at how quickly we went from scoping to testing something.",
+ author: "Cloud Solution Architect"
+ },
+ // ... more quotes
+];
+
+
+```
+
+## Features
+
+- Responsive grid layout (1 column on mobile, 2 on tablet, 5 on desktop)
+- Gradient background
+- Quote icon for visual appeal
+- Configurable title and quotes
+- Consistent with Fluent UI design system
\ No newline at end of file
diff --git a/code/src/components/SuccessStoriesSection/SuccessStoriesSection.css b/code/src/components/SuccessStoriesSection/SuccessStoriesSection.css
new file mode 100644
index 0000000..a92a596
--- /dev/null
+++ b/code/src/components/SuccessStoriesSection/SuccessStoriesSection.css
@@ -0,0 +1,22 @@
+/* SuccessStoriesSection component styles */
+.success-stories-section {
+ /* Additional custom styles can be added here if needed */
+}
+
+/* Ensure proper spacing and alignment */
+.testimonial-card {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+}
+
+/* Quote text styling */
+.quote-text {
+ line-height: 1.6;
+ margin-bottom: 1rem;
+}
+
+/* Author name styling */
+.author-name {
+ margin-top: auto;
+}
\ No newline at end of file
diff --git a/code/src/components/SuccessStoriesSection/SuccessStoriesSection.tsx b/code/src/components/SuccessStoriesSection/SuccessStoriesSection.tsx
new file mode 100644
index 0000000..172d43d
--- /dev/null
+++ b/code/src/components/SuccessStoriesSection/SuccessStoriesSection.tsx
@@ -0,0 +1,96 @@
+import { Title1, Text, makeStyles, tokens } from '@fluentui/react-components';
+import type { SuccessStoriesSectionProps } from '../../types';
+import './SuccessStoriesSection.css';
+
+const useStyles = makeStyles({
+ successGradient: {
+ background: 'linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)',
+ },
+ testimonialCard: {
+ backgroundColor: tokens.colorNeutralBackground2,
+ padding: "2rem",
+ borderRadius: "8px",
+ height: "100%",
+ position: "relative",
+ boxShadow: tokens.shadow4,
+ display: "flex",
+ flexDirection: "column",
+ },
+ quoteIcon: {
+ color: tokens.colorNeutralForeground3,
+ marginBottom: "1rem",
+ fontSize: "3rem",
+ lineHeight: "1",
+ opacity: 0.6,
+ },
+ sectionTitle: {
+ textAlign: "center",
+ marginBottom: "4rem",
+ padding: "0 0",
+ display: "block",
+ width: "100%",
+ },
+ quotesGrid: {
+ display: "grid",
+ gridTemplateColumns: "repeat(auto-fit, minmax(250px, 1fr))",
+ gap: "1.5rem",
+ maxWidth: "1200px",
+ margin: "0 auto",
+ marginBottom: "8rem",
+ },
+ quoteText: {
+ flex: "1",
+ fontWeight: "bold",
+ lineHeight: "1.6",
+ marginBottom: "1rem",
+ },
+ authorTitle: {
+ marginTop: "auto",
+ fontWeight: "semibold",
+ },
+ "@media (min-width: 768px)": {
+ quotesGrid: {
+ gridTemplateColumns: "repeat(2, 1fr)",
+ },
+ },
+ "@media (min-width: 1024px)": {
+ quotesGrid: {
+ gridTemplateColumns: "repeat(5, 1fr)",
+ },
+ },
+});
+
+const SuccessStoriesSection = ({
+ title = "Loved by developers",
+ quotes
+}: SuccessStoriesSectionProps) => {
+ const styles = useStyles();
+
+ return (
+
+
+
+
+ {title}
+
+
+
+ {quotes.slice(0, 4).map((quote, index) => (
+
+
+ “”
+
+
+ {quote.quote}
+
+
{quote.author}
+
+ ))}
+
+
+
+
+ );
+};
+
+export default SuccessStoriesSection;
\ No newline at end of file
diff --git a/code/src/components/SuccessStoriesSection/index.ts b/code/src/components/SuccessStoriesSection/index.ts
new file mode 100644
index 0000000..1c0b4b2
--- /dev/null
+++ b/code/src/components/SuccessStoriesSection/index.ts
@@ -0,0 +1,2 @@
+export { default } from './SuccessStoriesSection';
+export type { SuccessStoriesSectionProps } from '../../types';
\ No newline at end of file
diff --git a/code/src/components/TagRow/TagRow.css b/code/src/components/TagRow/TagRow.css
new file mode 100644
index 0000000..7fef375
--- /dev/null
+++ b/code/src/components/TagRow/TagRow.css
@@ -0,0 +1,38 @@
+@tailwind components;
+
+@layer components {
+ .tag-row-header {
+ @apply flex justify-between items-center gap-1 max-h-4;
+ }
+
+ .tag-row-scroll {
+ @apply flex flex-nowrap overflow-x-auto gap-2 mt-2 select-none min-h-8 max-h-4;
+ scrollbar-width: none;
+ -ms-overflow-style: none;
+ }
+
+ .tag-row-wrap {
+ @apply flex flex-wrap overflow-visible gap-2 mt-2 select-none min-h-8;
+ max-height: none;
+ scrollbar-width: none;
+ -ms-overflow-style: none;
+ }
+
+ .tag-row-scroll::-webkit-scrollbar {
+ display: none;
+ }
+
+ .text-neutral-disabled {
+ @apply text-neutral-foreground-disabled;
+ }
+
+ .fade-left {
+ @apply absolute left-0 top-0 bottom-0 w-[60px] pointer-events-none;
+ background: linear-gradient(to left, transparent, var(--colorNeutralBackground1));
+ }
+
+ .fade-right {
+ @apply absolute right-0 top-0 bottom-0 w-[60px] pointer-events-none;
+ background: linear-gradient(to right, transparent, var(--colorNeutralBackground1));
+ }
+}
\ No newline at end of file
diff --git a/code/src/components/TagRow/TagRow.tsx b/code/src/components/TagRow/TagRow.tsx
new file mode 100644
index 0000000..e84991c
--- /dev/null
+++ b/code/src/components/TagRow/TagRow.tsx
@@ -0,0 +1,221 @@
+import React, { useRef, useState, useEffect } from "react";
+import {
+ Caption1Strong,
+ Tag,
+ Tooltip,
+ InteractionTag,
+ InteractionTagPrimary,
+ Button,
+} from "@fluentui/react-components";
+import {
+ Link16Regular,
+ Open20Regular,
+ ChevronLeft16Regular,
+ ChevronRight16Regular,
+} from "@fluentui/react-icons";
+import { getLinkIcon } from "../../utils/getLinkIcon";
+import "./TagRow.css";
+
+type TagRowProps = {
+ label: string;
+ items: string[] | { label: string; href: string; fileType?: string }[];
+ keyPrefix: string;
+ isAsset?: boolean;
+ version: number;
+ maxLines?: number;
+ hoveringCard?: boolean;
+ wrapMode?: boolean;
+};
+
+const TagRow: React.FC = ({
+ label,
+ items,
+ keyPrefix,
+ isAsset = false,
+ version,
+ maxLines = 1,
+ hoveringCard = false,
+ wrapMode = false,
+}) => {
+ const scrollRef = useRef(null);
+ const [showLeftFade, setShowLeftFade] = useState(false);
+ const [showRightFade, setShowRightFade] = useState(false);
+ const [isScrollable, setIsScrollable] = useState(false);
+
+ // Drag affordance refs
+ const isDragging = useRef(false);
+ const startX = useRef(0);
+ const scrollStart = useRef(0);
+
+ useEffect(() => {
+ const el = scrollRef.current;
+ if (!el) return;
+
+ const updateFade = () => {
+ setShowLeftFade(el.scrollLeft > 0);
+ setShowRightFade(el.scrollLeft + el.clientWidth < el.scrollWidth - 1);
+ setIsScrollable(el.scrollWidth > el.clientWidth);
+ };
+
+ updateFade();
+ el.addEventListener("scroll", updateFade);
+ window.addEventListener("resize", updateFade);
+
+ return () => {
+ el.removeEventListener("scroll", updateFade);
+ window.removeEventListener("resize", updateFade);
+ };
+ }, [items, version]);
+
+ const scrollByAmount = 200;
+
+ const handleScrollLeft = () => {
+ scrollRef.current?.scrollBy({ left: -scrollByAmount, behavior: "smooth" });
+ };
+
+ const handleScrollRight = () => {
+ scrollRef.current?.scrollBy({ left: scrollByAmount, behavior: "smooth" });
+ };
+
+ const getHostname = (url: string) => {
+ try {
+ return new URL(url).hostname.replace("www.", "");
+ } catch {
+ return url;
+ }
+ };
+
+ const renderTag = (item: any, i: number) => {
+ if (isAsset && typeof item === "object") {
+ const icon = getLinkIcon(item.href, item.fileType);
+ return (
+
+ );
+ }
+ return (
+
+ {item}
+
+ );
+ };
+
+ const handlePointerDown = (e: React.PointerEvent) => {
+ if (!isScrollable) return;
+ isDragging.current = true;
+ startX.current = e.pageX;
+ scrollStart.current = scrollRef.current!.scrollLeft;
+ };
+
+ const handlePointerMove = (e: React.PointerEvent) => {
+ if (!isDragging.current) return;
+ const dx = e.pageX - startX.current;
+ scrollRef.current!.scrollLeft = scrollStart.current - dx;
+ };
+
+ const handlePointerUp = () => {
+ isDragging.current = false;
+ };
+
+ return (
+
+
+
{label}
+ {!wrapMode && isScrollable && hoveringCard && (
+
+ }
+ onClick={handleScrollLeft}
+ disabled={!showLeftFade}
+ className={!showLeftFade ? "cursor-default" : ""}
+ />
+ }
+ onClick={handleScrollRight}
+ disabled={!showRightFade}
+ className={!showRightFade ? "cursor-default" : ""}
+ />
+
+ )}
+
+
+
+
+ {items.length === 0 ? (
+ —
+ ) : (
+ items.map((item, i) => renderTag(item, i))
+ )}
+
+
+ {!wrapMode && showLeftFade && (
+
+ )}
+
+ {!wrapMode && showRightFade && (
+
+ )}
+
+
+ );
+};
+
+export default TagRow;
\ No newline at end of file
diff --git a/code/src/components/TextSection/README.md b/code/src/components/TextSection/README.md
new file mode 100644
index 0000000..f612324
--- /dev/null
+++ b/code/src/components/TextSection/README.md
@@ -0,0 +1,38 @@
+# TextSection Component
+
+A text-focused section component similar to HeroSection but without video content. Features a title (h2), content description, and a call-to-action button.
+
+## Props
+
+- `title` (string): Main title with support for HTML ` ` tags
+- `content` (string): Content description text
+- `link` (LinkConfig): Button configuration
+ - `text` (string): Button text
+ - `url` (string): Target URL (supports internal anchors and external links)
+ - `target` (optional): Link target ('_blank' for external links)
+- `className` (optional): Additional CSS classes
+- `onNavigate` (optional): Navigation callback for deep linking
+
+## Usage
+
+```tsx
+import TextSection from '../components/TextSection';
+
+
+```
+
+## Features
+
+- Responsive design with mobile optimization
+- Support for internal anchor links and external URLs
+- HTML line break support in titles
+- Consistent styling with other section components
+- Deep linking support for internal navigation
\ No newline at end of file
diff --git a/code/src/components/TextSection/TextSection.css b/code/src/components/TextSection/TextSection.css
new file mode 100644
index 0000000..d4fe06d
--- /dev/null
+++ b/code/src/components/TextSection/TextSection.css
@@ -0,0 +1,28 @@
+/* TextSection component styles */
+.text-section {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ width: 100%;
+}
+
+.text-content {
+ max-width: 80rem;
+ margin: 0 auto;
+ padding: 0 1.5rem;
+}
+
+/* Responsive text section styles */
+@media (max-width: 768px) {
+ .text-section {
+ padding: 2rem 1rem;
+ }
+
+ .text-content {
+ padding: 0 1rem;
+ }
+
+ .text-content h2 {
+ font-size: 2.5rem;
+ }
+}
\ No newline at end of file
diff --git a/code/src/components/TextSection/TextSection.tsx b/code/src/components/TextSection/TextSection.tsx
new file mode 100644
index 0000000..9c59f85
--- /dev/null
+++ b/code/src/components/TextSection/TextSection.tsx
@@ -0,0 +1,99 @@
+import React from 'react';
+import { Title1, Subtitle1, Button } from '@fluentui/react-components';
+import { REVERSE_SECTION_MAPPING } from '../../utils/sectionMapping';
+import './TextSection.css';
+
+export interface LinkConfig {
+ text: string;
+ url: string;
+ target?: '_blank' | '_self';
+}
+
+export interface TextSectionProps {
+ /** Main title with support for HTML */
+ title: string;
+ /** Content description */
+ content: string;
+ /** Link configuration */
+ link: LinkConfig;
+ /** Additional CSS classes */
+ className?: string;
+ /** Navigation callback for deep linking */
+ onNavigate?: (section: string) => void;
+}
+
+const TextSection: React.FC = ({
+ title,
+ content,
+ link,
+ className = '',
+ onNavigate
+}) => {
+ const handleLinkClick = (e: React.MouseEvent) => {
+ e.preventDefault();
+
+ if (onNavigate && link.url.startsWith('#')) {
+ const targetId = link.url.substring(1);
+ const section = REVERSE_SECTION_MAPPING[targetId];
+ if (section) {
+ onNavigate(section);
+ return;
+ }
+ }
+
+ if (link.url.startsWith('#')) {
+ const targetId = link.url.substring(1);
+ const targetElement = document.getElementById(targetId);
+
+ if (targetElement) {
+ targetElement.scrollIntoView({
+ behavior: 'smooth',
+ block: 'start'
+ });
+ }
+ } else {
+ if (link.target === '_blank') {
+ window.open(link.url, '_blank', 'noopener,noreferrer');
+ } else {
+ window.location.href = link.url;
+ }
+ }
+ };
+
+ return (
+
+
+
+
+ {title.split(' ').map((part, index) => (
+
+ {part}
+ {index < title.split(' ').length - 1 && }
+
+ ))}
+
+
+ {content}
+
+
+ {link.text}
+
+
+
+
+ );
+};
+
+export default TextSection;
\ No newline at end of file
diff --git a/code/src/components/TextSection/index.ts b/code/src/components/TextSection/index.ts
new file mode 100644
index 0000000..cb76aaf
--- /dev/null
+++ b/code/src/components/TextSection/index.ts
@@ -0,0 +1,2 @@
+export { default } from './TextSection';
+export type { TextSectionProps, LinkConfig } from './TextSection';
\ No newline at end of file
diff --git a/code/src/components/VideoPlayer/README.md b/code/src/components/VideoPlayer/README.md
new file mode 100644
index 0000000..28c8363
--- /dev/null
+++ b/code/src/components/VideoPlayer/README.md
@@ -0,0 +1,64 @@
+# VideoPlayer Component
+
+A reusable YouTube video player component with thumbnail preview and play button overlay.
+
+## Props
+
+### `videoUrl: string`
+YouTube video URL (supports embed, watch, and short URLs).
+
+### `autoplay?: boolean`
+Whether the video should autoplay when loaded. Defaults to `false`.
+
+### `className?: string`
+Optional additional CSS classes.
+
+### `aspectRatio?: string`
+Optional aspect ratio override. Defaults to `aspect-[16/9]`.
+
+## Features
+
+- **Smart URL Parsing**: Automatically extracts video ID from various YouTube URL formats
+- **Thumbnail Preview**: Shows video thumbnail with play button overlay
+- **Click to Play**: Click the play button to start the video
+- **Autoplay Support**: Configurable autoplay behavior
+- **Responsive Design**: Maintains aspect ratio across screen sizes
+- **Customizable Styling**: Supports custom CSS classes and aspect ratios
+
+## Usage Examples
+
+### Basic Usage
+```tsx
+import VideoPlayer from './components/VideoPlayer';
+
+
+```
+
+### With Autoplay
+```tsx
+
+```
+
+### Custom Styling
+```tsx
+
+```
+
+### Different YouTube URL Formats
+The component supports various YouTube URL formats:
+- `https://www.youtube.com/watch?v=VIDEO_ID`
+- `https://youtu.be/VIDEO_ID`
+- `https://www.youtube.com/embed/VIDEO_ID`
+
+## Integration with HeroSection
+
+This component is designed to work seamlessly with the HeroSection component. The HeroSection can now use this VideoPlayer instead of having embedded video logic.
\ No newline at end of file
diff --git a/code/src/components/VideoPlayer/VideoPlayer.css b/code/src/components/VideoPlayer/VideoPlayer.css
new file mode 100644
index 0000000..61a9fde
--- /dev/null
+++ b/code/src/components/VideoPlayer/VideoPlayer.css
@@ -0,0 +1,20 @@
+/* VideoPlayer component styles */
+.video-player-container {
+ /* Additional custom styles can be added here if needed */
+}
+
+/* Ensure the video container maintains its aspect ratio */
+.video-player-container iframe {
+ border: none;
+}
+
+/* Smooth transitions for the play button hover effect */
+.video-player-container .play-button {
+ transition: all 0.2s ease-in-out;
+}
+
+/* Ensure the thumbnail image covers the entire container properly */
+.video-player-container .thumbnail-image {
+ object-fit: cover;
+ object-position: center;
+}
\ No newline at end of file
diff --git a/code/src/components/VideoPlayer/VideoPlayer.tsx b/code/src/components/VideoPlayer/VideoPlayer.tsx
new file mode 100644
index 0000000..c171847
--- /dev/null
+++ b/code/src/components/VideoPlayer/VideoPlayer.tsx
@@ -0,0 +1,81 @@
+import React from 'react';
+import './VideoPlayer.css';
+
+export interface VideoPlayerProps {
+ /** YouTube video URL (supports embed, watch, and short URLs) */
+ videoUrl: string;
+ /** Whether the video should autoplay when loaded */
+ autoplay?: boolean;
+ /** Additional CSS classes */
+ className?: string;
+ /** Optional aspect ratio override (defaults to 16/9) */
+ aspectRatio?: string;
+}
+
+const VideoPlayer: React.FC = ({
+ videoUrl,
+ autoplay = false,
+ className = '',
+ aspectRatio = 'aspect-[16/9]'
+}) => {
+ const handleVideoClick = () => {
+ const iframe = document.getElementById('youtube-iframe') as HTMLIFrameElement;
+ const preview = document.getElementById('video-preview') as HTMLDivElement;
+
+ if (iframe && preview) {
+ iframe.style.opacity = '1';
+ iframe.style.pointerEvents = 'auto';
+ preview.style.display = 'none';
+ }
+ };
+
+ // Extract video ID from YouTube URL
+ const getVideoId = (url: string): string => {
+ const match = url.match(/(?:youtube\.com\/embed\/|youtu\.be\/|youtube\.com\/watch\?v=)([^&\n?#]+)/);
+ return match ? match[1] : '';
+ };
+
+ const videoId = getVideoId(videoUrl);
+ const thumbnailUrl = `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`;
+
+ // Build the iframe src with autoplay parameter
+ const iframeSrc = `https://www.youtube.com/embed/${videoId}?rel=0autoplay=${autoplay ? '1' : '0'}`;
+
+ return (
+
+ {/* Video Preview with Play Button */}
+
+ {/* Video Thumbnail */}
+
+ {/* Play Button */}
+
+
+
+ {/* YouTube iframe */}
+
+
+ );
+};
+
+export default VideoPlayer;
\ No newline at end of file
diff --git a/code/src/components/VideoPlayer/index.ts b/code/src/components/VideoPlayer/index.ts
new file mode 100644
index 0000000..054660b
--- /dev/null
+++ b/code/src/components/VideoPlayer/index.ts
@@ -0,0 +1,2 @@
+export { default } from './VideoPlayer';
+export type { VideoPlayerProps } from './VideoPlayer';
\ No newline at end of file
diff --git a/code/src/data/cards/Agents_for_Contract_Processing.json b/code/src/data/cards/Agents_for_Contract_Processing.json
new file mode 100644
index 0000000..192892f
--- /dev/null
+++ b/code/src/data/cards/Agents_for_Contract_Processing.json
@@ -0,0 +1,67 @@
+{
+ "solutionPlays": ["Copilot for M365", "AI Powered Copilot for Business"],
+ "solutionAreas": ["AI Business Solutions"],
+ "stability": "Live",
+ "key": ["Multi-agent Custom Automation Engine", "Content Processing", "Conversation Knowledge Mining"],
+ "accelerator": "Agents for Contract Processing",
+ "programmingLanguages": ["Low Code"],
+ "excerpt": "Streamline contract processing with an AI Agent that helps employees quickly create, find, manage, and share contracts to save time and resources by automating workflows.",
+ "productsAndServices": [
+ "Copilot Studio",
+ "Power Platform",
+ "Microsoft Teams",
+ "SharePoint",
+ "Power Automate",
+ "Dataverse"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/AgentsForCP",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/AgentsForCPPitchDeck",
+ "fileType": "pptx"
+ },
+ {
+ "label": "Reprise Click-through Demo",
+ "href": "https://aka.ms/AgentsforCPReprise",
+ "fileType": ""
+ }
+ ],
+ "technicalPattern": "Risk and Compliance",
+ "foundryTemplateName": "",
+ "useCases": [
+ "This solution streamlines contract management by creating",
+ "finding",
+ "managing and sharing contracts which lead to saving time and resources by automating contract processing workflows. The solution leverages Copilot Studio",
+ "Dataverse",
+ "Power Automate",
+ "SharePoint",
+ "Microsoft Teams and a 3rd party e-signature connector.",
+
+ "Automate contract creation and approval workflows",
+ "Enable quick search and retrieval of contracts using AI-powered indexing",
+ "Streamline contract lifecycle management with automated tracking and notifications",
+ "Integrate e-signature solutions for seamless contract execution",
+ "Ensure compliance by automatically flagging contract discrepancies",
+ "Provide contract analytics and insights for better decision-making"
+ ],
+ "keywords": [
+ "User intent detection in Copilot Studio",
+ "Adaptive Cards in Copilot Studio",
+ "Publishing Copilot agent in Microsoft Teams",
+ "Capturing e-signatures using DocuSign",
+ "Configure tables in Dataverse",
+ "Using SharePoint library for document storage",
+ "Modern Work",
+ "Business Applications"
+ ],
+ "industries": [
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Professional Services"
+ ],
+ "releaseDate": "2024-03-15",
+ "updatedDate": "2025-08-15"
+}
diff --git a/code/src/data/cards/Agents_for_Enhanced_Customer_Care.json b/code/src/data/cards/Agents_for_Enhanced_Customer_Care.json
new file mode 100644
index 0000000..55e1633
--- /dev/null
+++ b/code/src/data/cards/Agents_for_Enhanced_Customer_Care.json
@@ -0,0 +1,71 @@
+{
+ "solutionPlays": [
+ "Copilot for M365",
+ "AI Powered Copilot for Business",
+ "Modernize Service"
+ ],
+ "solutionAreas": [
+ "AI Business Solutions"
+ ],
+ "stability": "Live",
+ "key": ["Multi-agent Custom Automation Engine", "Content Processing", "Conversation Knowledge Mining"],
+ "accelerator": "Agents for Enhanced Customer Care",
+ "programmingLanguages": ["Low Code"],
+ "excerpt": "Elevate customer care with an AI-powered Contact Center that identifies customer intent, creates dynamic action plans, leverages organizational knowledge and provides customer insights, leading to increased customer satisfaction.",
+ "productsAndServices": [
+ "Copilot Studio",
+ "M365 Copilot",
+ "Dynamics 365",
+ "Dynamics 365 Contact Center",
+ "Dynamics 365 Customer Service", "Power Platform"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/AgentsForEnhancedCustomerCare",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/agentsforecc",
+ "fileType": "ppt"
+ },
+ {
+ "label": "BizApps Demo Hub",
+ "href": "https://aka.ms/agentsforenhancedcustomercare",
+ "fileType": ""
+ }
+ ],
+ "technicalPattern": "Customer Engagement",
+ "foundryTemplateName": "",
+ "useCases": [
+ "This solution elevates customer care with an AI-powered Contact Center by identifying customer intent",
+ "creating dynamic action plans",
+ "leveraging organizational knowledge and providing customer specific AI insights which lead to increased customer satisfaction. The solution leverages Copilot Studio",
+ "Dynamics 365 Contact Center",
+ "Power Platform and Azure Maps.",
+
+ "Identify customer intent and provide real-time support recommendations",
+ "Automate customer inquiries with AI-powered chatbots",
+ "Generate dynamic action plans based on customer interactions",
+ "Leverage organizational knowledge to improve customer service efficiency",
+ "Provide AI-driven customer insights for personalized engagement",
+ "Optimize contact center operations with predictive analytics"
+
+ ],
+ "keywords": [
+ "GenAI-based planning and orchestration",
+ "Contact Center",
+ "Dynamically-generated action plans",
+ "orchestrate multi-step tasks",
+ "customer specific AI insights",
+ "Modern Work",
+ "Business Applications"
+ ],
+ "industries": [
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Retail",
+ "Telecommunications"
+ ],
+ "releaseDate": "2024-12-31",
+ "updatedDate": "2025-08-15"
+}
\ No newline at end of file
diff --git a/code/src/data/cards/Agents_for_HR_Service.json b/code/src/data/cards/Agents_for_HR_Service.json
new file mode 100644
index 0000000..81a9b2c
--- /dev/null
+++ b/code/src/data/cards/Agents_for_HR_Service.json
@@ -0,0 +1,74 @@
+{
+ "solutionPlays": ["Copilot for M365", "AI Powered Copilot for Business"],
+ "solutionAreas": ["AI Business Solutions"],
+ "stability": "Live",
+ "key": ["Multi-agent Custom Automation Engine", "Content Processing", "Conversation Knowledge Mining"],
+ "accelerator": "Agents for HR Service",
+ "programmingLanguages": ["Low Code"],
+ "excerpt": "This solution streamlines HR service workflows with an AI-powered assistant that delivers instant answers, automates record updates, and provides intelligent support, saving time and elevating the employee experience.",
+ "productsAndServices": [
+ "Copilot Studio",
+ "Dataverse",
+ "Power Automate",
+ "Microsoft Teams",
+ "SharePoint"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/AgentForHRS",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/AgentForHRSPitchDeck",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Risk and Compliance",
+ "foundryTemplateName": "",
+ "useCases": [
+ "Dataverse",
+ "Power Automate",
+
+ "Automate HR inquiries with AI-powered responses",
+ "Streamline employee onboarding with guided workflows",
+ "Provide instant answers to HR policy and benefits questions",
+ "Automate record updates for employee information changes",
+ "Enhance employee experience with personalized HR assistance",
+ "Integrate with existing HR systems for seamless data management"
+ ],
+ "keywords": [
+ "User intent detection in Copilot Studio",
+ "Adaptive Cards in Copilot Studio",
+ "Publishing Copilot agent in Microsoft Teams",
+ "Modern Work",
+ "Business Applications",
+ "BizApps",
+ "Service Now",
+ "ServiceNow",
+ "seamless record updates",
+ "automated support",
+ "compliance",
+ "propose a relocation", "compare benefits", "compare compensation",
+ "natural language", "Find & summarize policy info",
+ "Extend and integrate employee data", "Enable autonomous HR support",
+ "Generate HR documents", "Capture employee satisfaction", "Knowledge Retrieval", "Action Execution",
+ "System Integration",
+ "Reduced operational costs", "Faster issue resolution",
+ "Increased HR efficiency"
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2024-05-01",
+ "updatedDate": "2025-08-15"
+}
diff --git a/code/src/data/cards/Agents_for_RFP_Response.json b/code/src/data/cards/Agents_for_RFP_Response.json
new file mode 100644
index 0000000..2d6eb52
--- /dev/null
+++ b/code/src/data/cards/Agents_for_RFP_Response.json
@@ -0,0 +1,64 @@
+{
+ "solutionPlays": ["Copilot for M365", "AI Powered Copilot for Business"],
+ "solutionAreas": ["AI Business Solutions"],
+ "stability": "Live",
+ "key": ["Multi-agent Custom Automation Engine", "Content Processing", "Conversation Knowledge Mining"],
+ "accelerator": "Agents for RFP Response",
+ "programmingLanguages": ["Low Code"],
+ "excerpt": "This solution increases efficiency and precision by leveraging the deep reasoning capabilities of an autonomous AI Agent to swiftly summarize, analyze, and generate high-quality RFP responses. By integrating Copilot Studio, Power Automate, SharePoint, and Microsoft Teams, this solution streamlines workflows and ensures seamless collaboration across platforms.",
+ "productsAndServices": [
+ "Copilot Studio",
+ "Dataverse",
+ "Power Automate",
+ "Microsoft Teams",
+ "SharePoint",
+ "Outlook"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/AgentForRFPResponse",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/AgentForRFPResponsePitchDeck",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Agents for RFP Response",
+ "foundryTemplateName": "",
+ "useCases": [
+ "Automate RFP response generation with AI-driven insights",
+ "Summarize and analyze RFP requirements for quick decision-making",
+ "Enhance collaboration by integrating response workflows across Teams and SharePoint",
+ "Improve response accuracy with AI-powered content validation",
+ "Streamline approval processes with automated workflows in Power Automate",
+ "Generate high-quality proposals using AI-driven content recommendations"
+ ],
+ "keywords": [
+ "AI-powered RFP automation",
+ "Proposal generation",
+ "Business process automation",
+ "Copilot Studio integration",
+ "Enterprise collaboration",
+ "Workflow optimization",
+ "AI-driven content analysis",
+ "Microsoft Teams automation",
+ "SharePoint document management",
+ "Power Automate workflows"
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2024-05-01",
+ "updatedDate": "2025-08-15"
+}
diff --git a/code/src/data/cards/Build_your_own_copilot_-_Client_advisor.json b/code/src/data/cards/Build_your_own_copilot_-_Client_advisor.json
new file mode 100644
index 0000000..2c07a3a
--- /dev/null
+++ b/code/src/data/cards/Build_your_own_copilot_-_Client_advisor.json
@@ -0,0 +1,57 @@
+{
+ "solutionPlays": [
+ "Innovate with AI apps & agents",
+ "Unify your data platform"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": ["Multi-agent Custom Automation Engine", "Content Processing", "Conversation Knowledge Mining"],
+ "accelerator": "Build your own copilot – Client Advisor",
+ "programmingLanguages": ["Bicep", "TypeScript", "Python"],
+ "excerpt": "Save time and prepare relevant discussion topics for scheduled client meetings with an overview of daily schedules and easy navigation between client profiles and a chat interface.",
+ "productsAndServices": [
+ "Azure AI Search",
+ "Azure OpenAI Service",
+ "Azure Cosmos DB",
+ "Azure SQL Database",
+ "Azure Container Apps"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/BuildYourOwncopilot",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/BYCDeck-ClientAdvisor",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Build your own copilot",
+ "foundryTemplateName": "Improve client meetings with agents",
+ "useCases": [
+ "Improve customer meetings",
+ "Client meeting preparation",
+
+ "Prepare discussion topics for scheduled client meetings",
+ "Provide AI-driven insights on client profiles and history",
+ "Automate meeting scheduling and reminders",
+ "Generate personalized recommendations based on client interactions",
+ "Enable seamless navigation between client profiles and chat interfaces",
+ "Summarize key takeaways from client meetings for follow-up actions"
+ ],
+ "keywords": [
+ "Meeting preparation",
+ "Data and AI",
+ "Digital and App Innovation",
+"BYOC"
+ ],
+ "industries": [
+ "Financial Services",
+ "Government",
+ "Professional Services",
+ "Retail",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2024-12-31",
+ "updatedDate": "2025-08-15"
+}
\ No newline at end of file
diff --git a/code/src/data/cards/Build_your_own_copilot_-_Document_Generation.json b/code/src/data/cards/Build_your_own_copilot_-_Document_Generation.json
new file mode 100644
index 0000000..179e7d4
--- /dev/null
+++ b/code/src/data/cards/Build_your_own_copilot_-_Document_Generation.json
@@ -0,0 +1,81 @@
+{
+ "solutionPlays": [
+ "Innovate with AI apps & agents",
+ "Unify your data platform"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": ["Multi-agent Custom Automation Engine", "Content Processing", "Conversation Knowledge Mining"],
+ "accelerator": "Build your own copilot – Doc Gen",
+ "programmingLanguages": ["Bicep", "TypeScript", "Python"],
+ "excerpt": "Generate documents such as contracts, invoices, and investment proposals by finding and summarizing relevant information from from your own unstructured data.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Search",
+ "Azure Cosmos DB",
+ "Azure Container Apps"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandard/BuildYourOwnCopilotDocGen",
+ "assets": [
+ {
+ "label": "Walkthrough - Promissory Note",
+ "href": "https://aka.ms/byoc_DocumentGeneration",
+ "fileType": "pptx"
+ },
+ {
+ "label": "Grant Submission",
+ "href": "https://aka.ms/BYCDeck-GrantSubmission",
+ "fileType": "pptx"
+ },
+ {
+ "label": "Invoice",
+ "href": "https://aka.ms/BYCDeck-Invoice",
+ "fileType": "pptx"
+ },
+ {
+ "label": "Investment Proposal",
+ "href": "https://aka.ms/BYCDeck-InvestmentProposal",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Build your own copilot",
+ "foundryTemplateName": "Generate documents from your data",
+ "useCases": [
+ "Contract generation",
+ "Invoice generation",
+ "Create investment proposals",
+
+ "Automate contract generation based on predefined templates",
+ "Extract and summarize relevant information for invoice creation",
+ "Generate investment proposals using AI-driven insights",
+ "Convert unstructured data into structured documents",
+ "Ensure compliance by validating generated documents against regulations",
+ "Streamline document approval workflows with AI-powered automation"
+ ],
+ "keywords": [
+ "Document generation",
+ "Contract generation/creation",
+ "Data and AI",
+ "Digital and App Innovation",
+"BYOC"
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2024-12-31",
+ "updatedDate": "2025-08-15"
+}
\ No newline at end of file
diff --git a/code/src/data/cards/Build_your_own_copilot_-_Researcher.json b/code/src/data/cards/Build_your_own_copilot_-_Researcher.json
new file mode 100644
index 0000000..b1aecea
--- /dev/null
+++ b/code/src/data/cards/Build_your_own_copilot_-_Researcher.json
@@ -0,0 +1,59 @@
+{
+ "solutionPlays": [
+ "Innovate with AI apps & agents",
+ "Unify your data platform"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": ["Multi-agent Custom Automation Engine", "Content Processing", "Conversation Knowledge Mining"],
+ "accelerator": "Build your own copilot – Researcher",
+ "programmingLanguages": ["Bicep", "TypeScript", "Python"],
+ "excerpt": "Create your own conversational AI assistant to easily research relevant articles for any specific topic and aid with document authoring.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Search",
+ "Microsoft Fabric",
+ "Azure App Service",
+ "Prompt Flow"
+ ],
+ "githubUrl": "https://github.com/microsoft/Build-your-own-copilot-Solution-Accelerator/tree/byoc-researcher",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/BYCDeck-Researcher",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Build your own copilot",
+ "foundryTemplateName": "Find relevant information for a specific topic",
+ "useCases": [
+ "Research and Development",
+
+ "Automate research article retrieval based on specific topics",
+ "Summarize key insights from multiple sources for quick review",
+ "Assist in document authoring with AI-generated content suggestions",
+ "Enable semantic search for relevant research materials",
+ "Provide AI-driven analysis of research trends and patterns",
+ "Enhance collaboration by integrating research findings into shared platforms"
+ ],
+ "keywords": [
+ "Data processing",
+ "Semantic Search",
+ "Research analysis",
+ "Data and AI",
+ "Digital and App Innovation",
+ "BYOC"
+ ],
+ "industries": [
+ "Defense and Intelligence",
+ "Education",
+ "Financial Services",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Professional Services"
+ ],
+ "releaseDate": "2024-12-31",
+ "updatedDate": "2025-08-15"
+}
\ No newline at end of file
diff --git a/code/src/data/cards/Chat_with_your_data.json b/code/src/data/cards/Chat_with_your_data.json
new file mode 100644
index 0000000..bb468a3
--- /dev/null
+++ b/code/src/data/cards/Chat_with_your_data.json
@@ -0,0 +1,85 @@
+{
+ "solutionPlays": [
+ "Innovate with AI apps & agents"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": ["Multi-agent Custom Automation Engine", "Content Processing", "Conversation Knowledge Mining"],
+ "accelerator": "Chat with your data",
+ "programmingLanguages": ["Bicep", "TypeScript", "Python"],
+ "excerpt": "Create a conversational AI chat experience to extract key information, summarize content, and provide relevant insights from your unstructured data.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Search",
+ "Azure Cosmos DB",
+ "Azure PostgreSQL",
+ "Azure Container Apps",
+ "Azure Functions",
+ "Azure AI Document Intelligence",
+ "Azure Speech Service"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/ChatWithYourData",
+ "assets": [
+ {
+ "label": "Walkthrough - Energy",
+ "href": "https://aka.ms/CWYDDeck",
+ "fileType": "pptx"
+ },
+ {
+ "label": "Employee Onboarding",
+ "href": "https://aka.ms/CWYDDeck-EmployeeOnboarding",
+ "fileType": "pptx"
+ },
+ {
+ "label": "Contract Review",
+ "href": "https://aka.ms/CWYDDeck-ContractReview",
+ "fileType": "pptx"
+ },
+ {
+ "label": "Financial Advisor",
+ "href": "https://aka.ms/CWYDDeck-FinancialAdvisor",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Chat with your data",
+ "foundryTemplateName": "",
+ "useCases": [
+ "Employee chatbot for HR / benefits\u200b",
+ "Professional Services assistance (Legal/Tax/Audit)\u200b",
+ "Analytics and reporting\u200b",
+ "Contact center agent assistance\u200b",
+ "Employee Assist\u200b",
+
+ "Extract key information from unstructured data using AI-powered chat",
+ "Summarize lengthy documents for quick review",
+ "Provide AI-driven insights based on conversational queries",
+ "Enable interactive data exploration through natural language queries",
+ "Assist in contract review by highlighting critical clauses",
+ "Improve employee onboarding with AI-powered knowledge retrieval"
+ ],
+ "keywords": [
+ "Internal chatbot",
+ "Data and AI",
+ "Digital and App Innovation",
+ "CWYD"
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2023-12-31",
+ "updatedDate": "2025-08-15"
+}
\ No newline at end of file
diff --git a/code/src/data/cards/Code_modernization.json b/code/src/data/cards/Code_modernization.json
new file mode 100644
index 0000000..d6778eb
--- /dev/null
+++ b/code/src/data/cards/Code_modernization.json
@@ -0,0 +1,66 @@
+{
+ "solutionPlays": [
+ "Innovate with AI apps & agents",
+ "Migrate & modernize your estate"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": ["Multi-agent Custom Automation Engine", "Content Processing", "Conversation Knowledge Mining"],
+ "accelerator": "Modernize your Code",
+ "programmingLanguages": ["Bicep", "TypeScript", "Python"],
+ "excerpt": "Migrate legacy code to modern languages by leveraging a team of AI agents.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Agent Service",
+ "Semantic Kernel",
+ "Azure Container Apps",
+ "Azure Cosmos DB"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/ModernizeCode",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/ModernizeCodeDeck",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Modernize your code",
+ "foundryTemplateName": "Modernize your code with agents",
+ "useCases": [
+ "Code translation\u200b \n\nGenerate initial code drafts\u202f\u200b \n\nCode correction and refactoring\u200b \n\nRoot-cause analysis\u200b \n\nGenerate new system designs",
+
+ "Translate legacy code into modern programming languages",
+ "Generate initial code drafts based on business logic",
+ "Automate code correction and refactoring",
+ "Perform root-cause analysis for debugging and optimization",
+ "Generate new system designs using AI-driven recommendations",
+ "Improve code efficiency with AI-powered transformation tools"
+ ],
+ "keywords": [
+ "Code language modernization",
+ "summary and review of new code",
+ "business logic analysis",
+ "efficient code transformation",
+ "Data and AI",
+ "Digital and App Innovation"
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2025-03-15",
+ "updatedDate": "2025-08-15"
+}
\ No newline at end of file
diff --git a/code/src/data/cards/Content_Processing.json b/code/src/data/cards/Content_Processing.json
new file mode 100644
index 0000000..543618a
--- /dev/null
+++ b/code/src/data/cards/Content_Processing.json
@@ -0,0 +1,67 @@
+{
+ "solutionPlays": [
+ "Innovate with AI apps & agents"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": ["Multi-agent Custom Automation Engine", "Content Processing", "Conversation Knowledge Mining"],
+ "accelerator": "Content Processing",
+ "programmingLanguages": ["Bicep", "TypeScript", "Python"],
+ "excerpt": "Process claims, invoices, contracts and other documents quickly and accurately by extracting information from unstructured content and mapping it to a structured format. This template supports text, images, tables and graphs.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Content Understanding",
+ "Azure Cosmos DB",
+ "Azure Container Apps"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/ContentProcessing",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/ContentProcessingDeck",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Content processing",
+ "foundryTemplateName": "Multi-modal content processing",
+ "useCases": [
+ "Documentation of clinician-patient visit and entering summary into downstream systems",
+ "Claims processing",
+ "Invoice processing",
+ "Contract processing",
+ "ID Verification",
+
+ "Extract structured data from unstructured documents",
+ "Automate claims processing with AI-driven validation",
+ "Streamline invoice processing by mapping extracted data to financial systems",
+ "Enhance contract review with AI-powered clause analysis",
+ "Perform ID verification using AI-driven document analysis",
+ "Improve documentation workflows with automated content classification"
+ ],
+ "keywords": [
+ "Data ingestion and extraction",
+ "Verification",
+ "Review",
+ "Data and AI",
+ "Digital and App Innovation"
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2025-03-31",
+ "updatedDate": "2025-08-15"
+}
\ No newline at end of file
diff --git a/code/src/data/cards/Conversation_Knowledge_Mining.json b/code/src/data/cards/Conversation_Knowledge_Mining.json
new file mode 100644
index 0000000..d604e02
--- /dev/null
+++ b/code/src/data/cards/Conversation_Knowledge_Mining.json
@@ -0,0 +1,62 @@
+{
+ "solutionPlays": [
+ "Innovate with AI apps & agents"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": ["Multi-agent Custom Automation Engine", "Content Processing", "Conversation Knowledge Mining"],
+ "accelerator": "Conversation Knowledge Mining",
+ "programmingLanguages": ["Bicep", "TypeScript", "Python", "Jupyter Notebook"],
+ "excerpt": "Improve contact center efficiency by uncovering insights from large audio and text-based data sets using advanced content understanding capabilities.",
+ "productsAndServices": [
+ "Azure AI Content Understanding",
+ "Azure OpenAI Service",
+ "Azure AI Search",
+ "Azure AI Agent Service",
+ "Azure Container Apps",
+ "Azure SQL Database",
+ "Azure Functions"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/ConversationKnowledgeMining",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/CKMDeck",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Knowledge Mining",
+ "foundryTemplateName": "Unlock insights from conversational data",
+ "useCases": [
+ "Mining call center conversations for patterns / insights",
+ "Call center ops improvement",
+ "Call transcription and summarization",
+
+ "Analyze call center conversations for customer sentiment insights",
+ "Summarize customer interactions for improved service efficiency",
+ "Identify recurring issues in customer support calls",
+ "Optimize call center operations with AI-driven analytics",
+ "Automate transcription and summarization of customer conversations",
+ "Provide actionable insights for improving customer engagement"
+ ],
+ "keywords": [
+ "Call Center",
+ "Transcription",
+ "Call summarization",
+ "Content understanding",
+ "Call center operations",
+ "Data and AI",
+ "Digital and App Innovation"
+ ],
+ "industries": [
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Retail",
+ "Telecommunications"
+ ],
+ "releaseDate": "2024-12-01",
+ "updatedDate": "2025-08-15"
+}
\ No newline at end of file
diff --git a/code/src/data/cards/Deploy_AI_applications_in_production.json b/code/src/data/cards/Deploy_AI_applications_in_production.json
new file mode 100644
index 0000000..345f683
--- /dev/null
+++ b/code/src/data/cards/Deploy_AI_applications_in_production.json
@@ -0,0 +1,53 @@
+{
+ "solutionPlays": [
+ "Innovate with AI apps & agents",
+ "Migrate & modernize your estate"],
+ "solutionAreas": ["Cloud & AI Platforms"],
+ "stability": "Live",
+ "key": ["Multi-agent Custom Automation Engine", "Content Processing", "Conversation Knowledge Mining"],
+ "accelerator": "Deploy Your AI Application in Production",
+ "programmingLanguages": ["Bicep", "Shell", "PowerShell", "Python"],
+ "excerpt": "Create a secure, extensible and integrated environment for deploying and running AI Foundry workloads in production.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Search",
+ "Azure Cosmos DB",
+ "Azure Container Apps"
+ ],
+ "githubUrl": "https://github.com/microsoft/deploy-your-ai-application-in-production",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "http://aka.ms/aitoprodppt",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "",
+ "foundryTemplateName": "Deploy Your AI application in Production",
+ "useCases": [
+ "Create a secure environment for AI workload deployment",
+ "Integrate AI applications with existing enterprise systems",
+ "Optimize AI model performance for production environments",
+ "Ensure compliance with security and governance standards",
+ "Automate monitoring and scaling of AI applications",
+ "Enable seamless collaboration between AI and business teams"
+ ],
+ "keywords": ["Data and AI", "Digital and App Innovation"],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2024-03-31",
+ "updatedDate": "2025-08-15"
+}
diff --git a/code/src/data/cards/Document_Knowledge_Mining.json b/code/src/data/cards/Document_Knowledge_Mining.json
new file mode 100644
index 0000000..66fc8ce
--- /dev/null
+++ b/code/src/data/cards/Document_Knowledge_Mining.json
@@ -0,0 +1,84 @@
+{
+ "solutionPlays": [
+ "Innovate with AI apps & agents"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": ["Multi-agent Custom Automation Engine", "Content Processing", "Conversation Knowledge Mining"],
+ "accelerator": "Document Knowledge Mining",
+ "programmingLanguages": ["Bicep", "TypeScript", "C#", "PowerShell"],
+ "excerpt": "Ingest, extract, and classify content from a high volume of assets to gain deeper insights and generate relevant suggestions for quick and easy review.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Search",
+ "Azure AI Document Intelligence"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/DocumentKnowledgeMining",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/DKMDeck",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Knowledge Mining",
+ "foundryTemplateName": "",
+ "useCases": [
+ "Document processing and Knowledge Insights",
+ "Drug Discovery",
+ "Research",
+
+ "Extract and classify content from large document repositories",
+ "Perform entity mapping for improved document organization",
+ "Analyze key phrases and topics for research insights",
+ "Enable semantic search for quick document retrieval",
+ "Automate document summarization for efficient review",
+ "Enhance multi-modal processing with AI-driven analysis"
+ ],
+ "keywords": [
+ "Data ingestion pipeline",
+ "Entity mapping",
+ "Key phrase and topic analysis",
+ "Semantic search",
+ "Chat with Unstructured (RAG 2.0)",
+ "Image Processing",
+ "Multi-modal processing",
+ "Natural language text analysis and summarization",
+ "Data and AI",
+ "Digital and App Innovation",
+ "Banking",
+ "Data extraction",
+ "data ingestion pipeline",
+ "Entity mapping",
+ "Key phrase and topic analysis",
+ "Semantic search",
+ "Chat with Unstructured (RAG 2.0)",
+ "Image Processing",
+ "Multi-modal processing",
+ "Natural language text analysis and summarization",
+ "Prompt suggestion",
+ "ext and document data analysis",
+ "content comparison",
+ "content summarization",
+ "document processing",
+ "image processing",
+ "automated processing",
+ "insight discovery",
+ "handwriting recognition",
+ "charts", "graphs", "tables",
+ "form fields", "DKM", "KM"
+ ],
+ "industries": [
+ "Defense and Intelligence",
+ "Education",
+ "Financial Services",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Retail",
+ "Professional Services"
+ ],
+ "releaseDate": "2024-12-15",
+ "updatedDate": "2025-08-15"
+}
\ No newline at end of file
diff --git a/code/src/data/cards/Multi-agent_custom_automation_engine_.json b/code/src/data/cards/Multi-agent_custom_automation_engine_.json
new file mode 100644
index 0000000..40bfc0c
--- /dev/null
+++ b/code/src/data/cards/Multi-agent_custom_automation_engine_.json
@@ -0,0 +1,78 @@
+{
+ "solutionPlays": [
+ "Innovate with AI apps & agents"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": ["Multi-agent Custom Automation Engine", "Content Processing", "Conversation Knowledge Mining"],
+ "accelerator": "Multi-Agent Custom Automation Engine",
+ "programmingLanguages": ["Bicep", "TypeScript", "Python"],
+ "excerpt": "Enhance task planning and automation by orchestrating and managing a group of AI agents.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Agent Service",
+ "Semantic Kernel",
+ "Azure Container Apps",
+ "Azure Cosmos DB"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/MultiAgent",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/MultiAgentDeck",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Agentic workflow automaton",
+ "foundryTemplateName": "Multi-agent workflow automation",
+ "useCases": [
+ "Employee On-Boarding and self-service",
+ "Travel Booking and Expense Management",
+ "Supply Chain Planning",
+
+ "Automate employee onboarding with AI-driven workflows",
+ "Streamline travel booking and expense management",
+ "Optimize supply chain planning with AI-powered automation",
+ "Enable multi-agent collaboration for complex task execution",
+ "Improve HR processes with AI-driven task orchestration",
+ "Enhance workflow automation with intelligent agent coordination"
+ ],
+ "keywords": [
+ "Agents",
+ "Agentic",
+ "Multi-agent",
+ "Employee onboarding",
+ "HR",
+ "Data and AI",
+ "Digital and App Innovation",
+ "AI orchestration",
+ "automated processing",
+ "task automation",
+ "GenAI scaling",
+ "error reduction",
+ "resource optimization",
+ "cost efficiency",
+ "process efficiency",
+ "scalability"
+
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2025-03-31",
+ "updatedDate": "2025-08-15"
+}
\ No newline at end of file
diff --git a/code/src/data/generated/cards.json b/code/src/data/generated/cards.json
new file mode 100644
index 0000000..985fbb3
--- /dev/null
+++ b/code/src/data/generated/cards.json
@@ -0,0 +1,1097 @@
+[
+ {
+ "solutionPlays": [
+ "Copilot for M365",
+ "AI Powered Copilot for Business"
+ ],
+ "solutionAreas": [
+ "AI Business Solutions"
+ ],
+ "stability": "Live",
+ "key": [
+ "Multi-agent Custom Automation Engine",
+ "Content Processing",
+ "Conversation Knowledge Mining"
+ ],
+ "accelerator": "Agents for Contract Processing",
+ "programmingLanguages": [
+ "Low Code"
+ ],
+ "excerpt": "Streamline contract processing with an AI Agent that helps employees quickly create, find, manage, and share contracts to save time and resources by automating workflows.",
+ "productsAndServices": [
+ "Copilot Studio",
+ "Power Platform",
+ "Microsoft Teams",
+ "SharePoint",
+ "Power Automate",
+ "Dataverse"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/AgentsForCP",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/AgentsForCPPitchDeck",
+ "fileType": "pptx"
+ },
+ {
+ "label": "Reprise Click-through Demo",
+ "href": "https://aka.ms/AgentsforCPReprise",
+ "fileType": ""
+ }
+ ],
+ "technicalPattern": "Risk and Compliance",
+ "foundryTemplateName": "",
+ "useCases": [
+ "This solution streamlines contract management by creating",
+ "finding",
+ "managing and sharing contracts which lead to saving time and resources by automating contract processing workflows. The solution leverages Copilot Studio",
+ "Dataverse",
+ "Power Automate",
+ "SharePoint",
+ "Microsoft Teams and a 3rd party e-signature connector.",
+ "Automate contract creation and approval workflows",
+ "Enable quick search and retrieval of contracts using AI-powered indexing",
+ "Streamline contract lifecycle management with automated tracking and notifications",
+ "Integrate e-signature solutions for seamless contract execution",
+ "Ensure compliance by automatically flagging contract discrepancies",
+ "Provide contract analytics and insights for better decision-making"
+ ],
+ "keywords": [
+ "User intent detection in Copilot Studio",
+ "Adaptive Cards in Copilot Studio",
+ "Publishing Copilot agent in Microsoft Teams",
+ "Capturing e-signatures using DocuSign",
+ "Configure tables in Dataverse",
+ "Using SharePoint library for document storage",
+ "Modern Work",
+ "Business Applications"
+ ],
+ "industries": [
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Professional Services"
+ ],
+ "releaseDate": "2024-03-15",
+ "updatedDate": "2025-08-15"
+ },
+ {
+ "solutionPlays": [
+ "Copilot for M365",
+ "AI Powered Copilot for Business",
+ "Modernize Service"
+ ],
+ "solutionAreas": [
+ "AI Business Solutions"
+ ],
+ "stability": "Live",
+ "key": [
+ "Multi-agent Custom Automation Engine",
+ "Content Processing",
+ "Conversation Knowledge Mining"
+ ],
+ "accelerator": "Agents for Enhanced Customer Care",
+ "programmingLanguages": [
+ "Low Code"
+ ],
+ "excerpt": "Elevate customer care with an AI-powered Contact Center that identifies customer intent, creates dynamic action plans, leverages organizational knowledge and provides customer insights, leading to increased customer satisfaction.",
+ "productsAndServices": [
+ "Copilot Studio",
+ "M365 Copilot",
+ "Dynamics 365",
+ "Dynamics 365 Contact Center",
+ "Dynamics 365 Customer Service",
+ "Power Platform"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/AgentsForEnhancedCustomerCare",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/agentsforecc",
+ "fileType": "ppt"
+ },
+ {
+ "label": "BizApps Demo Hub",
+ "href": "https://aka.ms/agentsforenhancedcustomercare",
+ "fileType": ""
+ }
+ ],
+ "technicalPattern": "Customer Engagement",
+ "foundryTemplateName": "",
+ "useCases": [
+ "This solution elevates customer care with an AI-powered Contact Center by identifying customer intent",
+ "creating dynamic action plans",
+ "leveraging organizational knowledge and providing customer specific AI insights which lead to increased customer satisfaction. The solution leverages Copilot Studio",
+ "Dynamics 365 Contact Center",
+ "Power Platform and Azure Maps.",
+ "Identify customer intent and provide real-time support recommendations",
+ "Automate customer inquiries with AI-powered chatbots",
+ "Generate dynamic action plans based on customer interactions",
+ "Leverage organizational knowledge to improve customer service efficiency",
+ "Provide AI-driven customer insights for personalized engagement",
+ "Optimize contact center operations with predictive analytics"
+ ],
+ "keywords": [
+ "GenAI-based planning and orchestration",
+ "Contact Center",
+ "Dynamically-generated action plans",
+ "orchestrate multi-step tasks",
+ "customer specific AI insights",
+ "Modern Work",
+ "Business Applications"
+ ],
+ "industries": [
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Retail",
+ "Telecommunications"
+ ],
+ "releaseDate": "2024-12-31",
+ "updatedDate": "2025-08-15"
+ },
+ {
+ "solutionPlays": [
+ "Copilot for M365",
+ "AI Powered Copilot for Business"
+ ],
+ "solutionAreas": [
+ "AI Business Solutions"
+ ],
+ "stability": "Live",
+ "key": [
+ "Multi-agent Custom Automation Engine",
+ "Content Processing",
+ "Conversation Knowledge Mining"
+ ],
+ "accelerator": "Agents for HR Service",
+ "programmingLanguages": [
+ "Low Code"
+ ],
+ "excerpt": "This solution streamlines HR service workflows with an AI-powered assistant that delivers instant answers, automates record updates, and provides intelligent support, saving time and elevating the employee experience.",
+ "productsAndServices": [
+ "Copilot Studio",
+ "Dataverse",
+ "Power Automate",
+ "Microsoft Teams",
+ "SharePoint"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/AgentForHRS",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/AgentForHRSPitchDeck",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Risk and Compliance",
+ "foundryTemplateName": "",
+ "useCases": [
+ "Dataverse",
+ "Power Automate",
+ "Automate HR inquiries with AI-powered responses",
+ "Streamline employee onboarding with guided workflows",
+ "Provide instant answers to HR policy and benefits questions",
+ "Automate record updates for employee information changes",
+ "Enhance employee experience with personalized HR assistance",
+ "Integrate with existing HR systems for seamless data management"
+ ],
+ "keywords": [
+ "User intent detection in Copilot Studio",
+ "Adaptive Cards in Copilot Studio",
+ "Publishing Copilot agent in Microsoft Teams",
+ "Modern Work",
+ "Business Applications",
+ "BizApps",
+ "Service Now",
+ "ServiceNow",
+ "seamless record updates",
+ "automated support",
+ "compliance",
+ "propose a relocation",
+ "compare benefits",
+ "compare compensation",
+ "natural language",
+ "Find & summarize policy info",
+ "Extend and integrate employee data",
+ "Enable autonomous HR support",
+ "Generate HR documents",
+ "Capture employee satisfaction",
+ "Knowledge Retrieval",
+ "Action Execution",
+ "System Integration",
+ "Reduced operational costs",
+ "Faster issue resolution",
+ "Increased HR efficiency"
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2024-05-01",
+ "updatedDate": "2025-08-15"
+ },
+ {
+ "solutionPlays": [
+ "Copilot for M365",
+ "AI Powered Copilot for Business"
+ ],
+ "solutionAreas": [
+ "AI Business Solutions"
+ ],
+ "stability": "Live",
+ "key": [
+ "Multi-agent Custom Automation Engine",
+ "Content Processing",
+ "Conversation Knowledge Mining"
+ ],
+ "accelerator": "Agents for RFP Response",
+ "programmingLanguages": [
+ "Low Code"
+ ],
+ "excerpt": "This solution increases efficiency and precision by leveraging the deep reasoning capabilities of an autonomous AI Agent to swiftly summarize, analyze, and generate high-quality RFP responses. By integrating Copilot Studio, Power Automate, SharePoint, and Microsoft Teams, this solution streamlines workflows and ensures seamless collaboration across platforms.",
+ "productsAndServices": [
+ "Copilot Studio",
+ "Dataverse",
+ "Power Automate",
+ "Microsoft Teams",
+ "SharePoint",
+ "Outlook"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/AgentForRFPResponse",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/AgentForRFPResponsePitchDeck",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Agents for RFP Response",
+ "foundryTemplateName": "",
+ "useCases": [
+ "Automate RFP response generation with AI-driven insights",
+ "Summarize and analyze RFP requirements for quick decision-making",
+ "Enhance collaboration by integrating response workflows across Teams and SharePoint",
+ "Improve response accuracy with AI-powered content validation",
+ "Streamline approval processes with automated workflows in Power Automate",
+ "Generate high-quality proposals using AI-driven content recommendations"
+ ],
+ "keywords": [
+ "AI-powered RFP automation",
+ "Proposal generation",
+ "Business process automation",
+ "Copilot Studio integration",
+ "Enterprise collaboration",
+ "Workflow optimization",
+ "AI-driven content analysis",
+ "Microsoft Teams automation",
+ "SharePoint document management",
+ "Power Automate workflows"
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2024-05-01",
+ "updatedDate": "2025-08-15"
+ },
+ {
+ "solutionPlays": [
+ "Innovate with AI apps & agents",
+ "Unify your data platform"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": [
+ "Multi-agent Custom Automation Engine",
+ "Content Processing",
+ "Conversation Knowledge Mining"
+ ],
+ "accelerator": "Build your own copilot – Client Advisor",
+ "programmingLanguages": [
+ "Bicep",
+ "TypeScript",
+ "Python"
+ ],
+ "excerpt": "Save time and prepare relevant discussion topics for scheduled client meetings with an overview of daily schedules and easy navigation between client profiles and a chat interface.",
+ "productsAndServices": [
+ "Azure AI Search",
+ "Azure OpenAI Service",
+ "Azure Cosmos DB",
+ "Azure SQL Database",
+ "Azure Container Apps"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/BuildYourOwncopilot",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/BYCDeck-ClientAdvisor",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Build your own copilot",
+ "foundryTemplateName": "Improve client meetings with agents",
+ "useCases": [
+ "Improve customer meetings",
+ "Client meeting preparation",
+ "Prepare discussion topics for scheduled client meetings",
+ "Provide AI-driven insights on client profiles and history",
+ "Automate meeting scheduling and reminders",
+ "Generate personalized recommendations based on client interactions",
+ "Enable seamless navigation between client profiles and chat interfaces",
+ "Summarize key takeaways from client meetings for follow-up actions"
+ ],
+ "keywords": [
+ "Meeting preparation",
+ "Data and AI",
+ "Digital and App Innovation",
+ "BYOC"
+ ],
+ "industries": [
+ "Financial Services",
+ "Government",
+ "Professional Services",
+ "Retail",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2024-12-31",
+ "updatedDate": "2025-08-15"
+ },
+ {
+ "solutionPlays": [
+ "Innovate with AI apps & agents",
+ "Unify your data platform"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": [
+ "Multi-agent Custom Automation Engine",
+ "Content Processing",
+ "Conversation Knowledge Mining"
+ ],
+ "accelerator": "Build your own copilot – Doc Gen",
+ "programmingLanguages": [
+ "Bicep",
+ "TypeScript",
+ "Python"
+ ],
+ "excerpt": "Generate documents such as contracts, invoices, and investment proposals by finding and summarizing relevant information from from your own unstructured data.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Search",
+ "Azure Cosmos DB",
+ "Azure Container Apps"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandard/BuildYourOwnCopilotDocGen",
+ "assets": [
+ {
+ "label": "Walkthrough - Promissory Note",
+ "href": "https://aka.ms/byoc_DocumentGeneration",
+ "fileType": "pptx"
+ },
+ {
+ "label": "Grant Submission",
+ "href": "https://aka.ms/BYCDeck-GrantSubmission",
+ "fileType": "pptx"
+ },
+ {
+ "label": "Invoice",
+ "href": "https://aka.ms/BYCDeck-Invoice",
+ "fileType": "pptx"
+ },
+ {
+ "label": "Investment Proposal",
+ "href": "https://aka.ms/BYCDeck-InvestmentProposal",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Build your own copilot",
+ "foundryTemplateName": "Generate documents from your data",
+ "useCases": [
+ "Contract generation",
+ "Invoice generation",
+ "Create investment proposals",
+ "Automate contract generation based on predefined templates",
+ "Extract and summarize relevant information for invoice creation",
+ "Generate investment proposals using AI-driven insights",
+ "Convert unstructured data into structured documents",
+ "Ensure compliance by validating generated documents against regulations",
+ "Streamline document approval workflows with AI-powered automation"
+ ],
+ "keywords": [
+ "Document generation",
+ "Contract generation/creation",
+ "Data and AI",
+ "Digital and App Innovation",
+ "BYOC"
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2024-12-31",
+ "updatedDate": "2025-08-15"
+ },
+ {
+ "solutionPlays": [
+ "Innovate with AI apps & agents",
+ "Unify your data platform"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": [
+ "Multi-agent Custom Automation Engine",
+ "Content Processing",
+ "Conversation Knowledge Mining"
+ ],
+ "accelerator": "Build your own copilot – Researcher",
+ "programmingLanguages": [
+ "Bicep",
+ "TypeScript",
+ "Python"
+ ],
+ "excerpt": "Create your own conversational AI assistant to easily research relevant articles for any specific topic and aid with document authoring.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Search",
+ "Microsoft Fabric",
+ "Azure App Service",
+ "Prompt Flow"
+ ],
+ "githubUrl": "https://github.com/microsoft/Build-your-own-copilot-Solution-Accelerator/tree/byoc-researcher",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/BYCDeck-Researcher",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Build your own copilot",
+ "foundryTemplateName": "Find relevant information for a specific topic",
+ "useCases": [
+ "Research and Development",
+ "Automate research article retrieval based on specific topics",
+ "Summarize key insights from multiple sources for quick review",
+ "Assist in document authoring with AI-generated content suggestions",
+ "Enable semantic search for relevant research materials",
+ "Provide AI-driven analysis of research trends and patterns",
+ "Enhance collaboration by integrating research findings into shared platforms"
+ ],
+ "keywords": [
+ "Data processing",
+ "Semantic Search",
+ "Research analysis",
+ "Data and AI",
+ "Digital and App Innovation",
+ "BYOC"
+ ],
+ "industries": [
+ "Defense and Intelligence",
+ "Education",
+ "Financial Services",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Professional Services"
+ ],
+ "releaseDate": "2024-12-31",
+ "updatedDate": "2025-08-15"
+ },
+ {
+ "solutionPlays": [
+ "Innovate with AI apps & agents"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": [
+ "Multi-agent Custom Automation Engine",
+ "Content Processing",
+ "Conversation Knowledge Mining"
+ ],
+ "accelerator": "Chat with your data",
+ "programmingLanguages": [
+ "Bicep",
+ "TypeScript",
+ "Python"
+ ],
+ "excerpt": "Create a conversational AI chat experience to extract key information, summarize content, and provide relevant insights from your unstructured data.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Search",
+ "Azure Cosmos DB",
+ "Azure PostgreSQL",
+ "Azure Container Apps",
+ "Azure Functions",
+ "Azure AI Document Intelligence",
+ "Azure Speech Service"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/ChatWithYourData",
+ "assets": [
+ {
+ "label": "Walkthrough - Energy",
+ "href": "https://aka.ms/CWYDDeck",
+ "fileType": "pptx"
+ },
+ {
+ "label": "Employee Onboarding",
+ "href": "https://aka.ms/CWYDDeck-EmployeeOnboarding",
+ "fileType": "pptx"
+ },
+ {
+ "label": "Contract Review",
+ "href": "https://aka.ms/CWYDDeck-ContractReview",
+ "fileType": "pptx"
+ },
+ {
+ "label": "Financial Advisor",
+ "href": "https://aka.ms/CWYDDeck-FinancialAdvisor",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Chat with your data",
+ "foundryTemplateName": "",
+ "useCases": [
+ "Employee chatbot for HR / benefits",
+ "Professional Services assistance (Legal/Tax/Audit)",
+ "Analytics and reporting",
+ "Contact center agent assistance",
+ "Employee Assist",
+ "Extract key information from unstructured data using AI-powered chat",
+ "Summarize lengthy documents for quick review",
+ "Provide AI-driven insights based on conversational queries",
+ "Enable interactive data exploration through natural language queries",
+ "Assist in contract review by highlighting critical clauses",
+ "Improve employee onboarding with AI-powered knowledge retrieval"
+ ],
+ "keywords": [
+ "Internal chatbot",
+ "Data and AI",
+ "Digital and App Innovation",
+ "CWYD"
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2023-12-31",
+ "updatedDate": "2025-08-15"
+ },
+ {
+ "solutionPlays": [
+ "Innovate with AI apps & agents",
+ "Migrate & modernize your estate"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": [
+ "Multi-agent Custom Automation Engine",
+ "Content Processing",
+ "Conversation Knowledge Mining"
+ ],
+ "accelerator": "Modernize your Code",
+ "programmingLanguages": [
+ "Bicep",
+ "TypeScript",
+ "Python"
+ ],
+ "excerpt": "Migrate legacy code to modern languages by leveraging a team of AI agents.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Agent Service",
+ "Semantic Kernel",
+ "Azure Container Apps",
+ "Azure Cosmos DB"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/ModernizeCode",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/ModernizeCodeDeck",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Modernize your code",
+ "foundryTemplateName": "Modernize your code with agents",
+ "useCases": [
+ "Code translation \n\nGenerate initial code drafts \n\nCode correction and refactoring \n\nRoot-cause analysis \n\nGenerate new system designs",
+ "Translate legacy code into modern programming languages",
+ "Generate initial code drafts based on business logic",
+ "Automate code correction and refactoring",
+ "Perform root-cause analysis for debugging and optimization",
+ "Generate new system designs using AI-driven recommendations",
+ "Improve code efficiency with AI-powered transformation tools"
+ ],
+ "keywords": [
+ "Code language modernization",
+ "summary and review of new code",
+ "business logic analysis",
+ "efficient code transformation",
+ "Data and AI",
+ "Digital and App Innovation"
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2025-03-15",
+ "updatedDate": "2025-08-15"
+ },
+ {
+ "solutionPlays": [
+ "Innovate with AI apps & agents"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": [
+ "Multi-agent Custom Automation Engine",
+ "Content Processing",
+ "Conversation Knowledge Mining"
+ ],
+ "accelerator": "Content Processing",
+ "programmingLanguages": [
+ "Bicep",
+ "TypeScript",
+ "Python"
+ ],
+ "excerpt": "Process claims, invoices, contracts and other documents quickly and accurately by extracting information from unstructured content and mapping it to a structured format. This template supports text, images, tables and graphs.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Content Understanding",
+ "Azure Cosmos DB",
+ "Azure Container Apps"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/ContentProcessing",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/ContentProcessingDeck",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Content processing",
+ "foundryTemplateName": "Multi-modal content processing",
+ "useCases": [
+ "Documentation of clinician-patient visit and entering summary into downstream systems",
+ "Claims processing",
+ "Invoice processing",
+ "Contract processing",
+ "ID Verification",
+ "Extract structured data from unstructured documents",
+ "Automate claims processing with AI-driven validation",
+ "Streamline invoice processing by mapping extracted data to financial systems",
+ "Enhance contract review with AI-powered clause analysis",
+ "Perform ID verification using AI-driven document analysis",
+ "Improve documentation workflows with automated content classification"
+ ],
+ "keywords": [
+ "Data ingestion and extraction",
+ "Verification",
+ "Review",
+ "Data and AI",
+ "Digital and App Innovation"
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2025-03-31",
+ "updatedDate": "2025-08-15"
+ },
+ {
+ "solutionPlays": [
+ "Innovate with AI apps & agents"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": [
+ "Multi-agent Custom Automation Engine",
+ "Content Processing",
+ "Conversation Knowledge Mining"
+ ],
+ "accelerator": "Conversation Knowledge Mining",
+ "programmingLanguages": [
+ "Bicep",
+ "TypeScript",
+ "Python",
+ "Jupyter Notebook"
+ ],
+ "excerpt": "Improve contact center efficiency by uncovering insights from large audio and text-based data sets using advanced content understanding capabilities.",
+ "productsAndServices": [
+ "Azure AI Content Understanding",
+ "Azure OpenAI Service",
+ "Azure AI Search",
+ "Azure AI Agent Service",
+ "Azure Container Apps",
+ "Azure SQL Database",
+ "Azure Functions"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/ConversationKnowledgeMining",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/CKMDeck",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Knowledge Mining",
+ "foundryTemplateName": "Unlock insights from conversational data",
+ "useCases": [
+ "Mining call center conversations for patterns / insights",
+ "Call center ops improvement",
+ "Call transcription and summarization",
+ "Analyze call center conversations for customer sentiment insights",
+ "Summarize customer interactions for improved service efficiency",
+ "Identify recurring issues in customer support calls",
+ "Optimize call center operations with AI-driven analytics",
+ "Automate transcription and summarization of customer conversations",
+ "Provide actionable insights for improving customer engagement"
+ ],
+ "keywords": [
+ "Call Center",
+ "Transcription",
+ "Call summarization",
+ "Content understanding",
+ "Call center operations",
+ "Data and AI",
+ "Digital and App Innovation"
+ ],
+ "industries": [
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Retail",
+ "Telecommunications"
+ ],
+ "releaseDate": "2024-12-01",
+ "updatedDate": "2025-08-15"
+ },
+ {
+ "solutionPlays": [
+ "Innovate with AI apps & agents",
+ "Migrate & modernize your estate"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": [
+ "Multi-agent Custom Automation Engine",
+ "Content Processing",
+ "Conversation Knowledge Mining"
+ ],
+ "accelerator": "Deploy Your AI Application in Production",
+ "programmingLanguages": [
+ "Bicep",
+ "Shell",
+ "PowerShell",
+ "Python"
+ ],
+ "excerpt": "Create a secure, extensible and integrated environment for deploying and running AI Foundry workloads in production.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Search",
+ "Azure Cosmos DB",
+ "Azure Container Apps"
+ ],
+ "githubUrl": "https://github.com/microsoft/deploy-your-ai-application-in-production",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "http://aka.ms/aitoprodppt",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "",
+ "foundryTemplateName": "Deploy Your AI application in Production",
+ "useCases": [
+ "Create a secure environment for AI workload deployment",
+ "Integrate AI applications with existing enterprise systems",
+ "Optimize AI model performance for production environments",
+ "Ensure compliance with security and governance standards",
+ "Automate monitoring and scaling of AI applications",
+ "Enable seamless collaboration between AI and business teams"
+ ],
+ "keywords": [
+ "Data and AI",
+ "Digital and App Innovation"
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2024-03-31",
+ "updatedDate": "2025-08-15"
+ },
+ {
+ "solutionPlays": [
+ "Innovate with AI apps & agents"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": [
+ "Multi-agent Custom Automation Engine",
+ "Content Processing",
+ "Conversation Knowledge Mining"
+ ],
+ "accelerator": "Document Knowledge Mining",
+ "programmingLanguages": [
+ "Bicep",
+ "TypeScript",
+ "C#",
+ "PowerShell"
+ ],
+ "excerpt": "Ingest, extract, and classify content from a high volume of assets to gain deeper insights and generate relevant suggestions for quick and easy review.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Search",
+ "Azure AI Document Intelligence"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/DocumentKnowledgeMining",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/DKMDeck",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Knowledge Mining",
+ "foundryTemplateName": "",
+ "useCases": [
+ "Document processing and Knowledge Insights",
+ "Drug Discovery",
+ "Research",
+ "Extract and classify content from large document repositories",
+ "Perform entity mapping for improved document organization",
+ "Analyze key phrases and topics for research insights",
+ "Enable semantic search for quick document retrieval",
+ "Automate document summarization for efficient review",
+ "Enhance multi-modal processing with AI-driven analysis"
+ ],
+ "keywords": [
+ "Data ingestion pipeline",
+ "Entity mapping",
+ "Key phrase and topic analysis",
+ "Semantic search",
+ "Chat with Unstructured (RAG 2.0)",
+ "Image Processing",
+ "Multi-modal processing",
+ "Natural language text analysis and summarization",
+ "Data and AI",
+ "Digital and App Innovation",
+ "Banking",
+ "Data extraction",
+ "data ingestion pipeline",
+ "Entity mapping",
+ "Key phrase and topic analysis",
+ "Semantic search",
+ "Chat with Unstructured (RAG 2.0)",
+ "Image Processing",
+ "Multi-modal processing",
+ "Natural language text analysis and summarization",
+ "Prompt suggestion",
+ "ext and document data analysis",
+ "content comparison",
+ "content summarization",
+ "document processing",
+ "image processing",
+ "automated processing",
+ "insight discovery",
+ "handwriting recognition",
+ "charts",
+ "graphs",
+ "tables",
+ "form fields",
+ "DKM",
+ "KM"
+ ],
+ "industries": [
+ "Defense and Intelligence",
+ "Education",
+ "Financial Services",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Retail",
+ "Professional Services"
+ ],
+ "releaseDate": "2024-12-15",
+ "updatedDate": "2025-08-15"
+ },
+ {
+ "solutionPlays": [
+ "Innovate with AI apps & agents"
+ ],
+ "solutionAreas": [
+ "Cloud & AI Platforms"
+ ],
+ "stability": "Live",
+ "key": [
+ "Multi-agent Custom Automation Engine",
+ "Content Processing",
+ "Conversation Knowledge Mining"
+ ],
+ "accelerator": "Multi-Agent Custom Automation Engine",
+ "programmingLanguages": [
+ "Bicep",
+ "TypeScript",
+ "Python"
+ ],
+ "excerpt": "Enhance task planning and automation by orchestrating and managing a group of AI agents.",
+ "productsAndServices": [
+ "Azure OpenAI Service",
+ "Azure AI Agent Service",
+ "Semantic Kernel",
+ "Azure Container Apps",
+ "Azure Cosmos DB"
+ ],
+ "githubUrl": "https://aka.ms/CSAGoldStandards/MultiAgent",
+ "assets": [
+ {
+ "label": "Walkthrough",
+ "href": "https://aka.ms/MultiAgentDeck",
+ "fileType": "pptx"
+ }
+ ],
+ "technicalPattern": "Agentic workflow automaton",
+ "foundryTemplateName": "Multi-agent workflow automation",
+ "useCases": [
+ "Employee On-Boarding and self-service",
+ "Travel Booking and Expense Management",
+ "Supply Chain Planning",
+ "Automate employee onboarding with AI-driven workflows",
+ "Streamline travel booking and expense management",
+ "Optimize supply chain planning with AI-powered automation",
+ "Enable multi-agent collaboration for complex task execution",
+ "Improve HR processes with AI-driven task orchestration",
+ "Enhance workflow automation with intelligent agent coordination"
+ ],
+ "keywords": [
+ "Agents",
+ "Agentic",
+ "Multi-agent",
+ "Employee onboarding",
+ "HR",
+ "Data and AI",
+ "Digital and App Innovation",
+ "AI orchestration",
+ "automated processing",
+ "task automation",
+ "GenAI scaling",
+ "error reduction",
+ "resource optimization",
+ "cost efficiency",
+ "process efficiency",
+ "scalability"
+ ],
+ "industries": [
+ "Automotive",
+ "Defense and Intelligence",
+ "Education",
+ "Energy",
+ "Financial Services",
+ "Government",
+ "Healthcare",
+ "Industrials and Manufacturing",
+ "Non-profit",
+ "Professional Services",
+ "Retail",
+ "Telecommunications",
+ "Media and Entertainment"
+ ],
+ "releaseDate": "2025-03-31",
+ "updatedDate": "2025-08-15"
+ }
+]
\ No newline at end of file
diff --git a/code/src/global.d.ts b/code/src/global.d.ts
new file mode 100644
index 0000000..31058d4
--- /dev/null
+++ b/code/src/global.d.ts
@@ -0,0 +1,4 @@
+declare module "*.css" {
+ const content: string;
+ export default content;
+}
diff --git a/code/src/hooks/index.ts b/code/src/hooks/index.ts
new file mode 100644
index 0000000..4525974
--- /dev/null
+++ b/code/src/hooks/index.ts
@@ -0,0 +1,3 @@
+export { useIntersectionObserver } from './useIntersectionObserver';
+export { useUrlState } from './useUrlState';
+export { useNavigation } from './useNavigation';
\ No newline at end of file
diff --git a/code/src/hooks/useFilterDeepLink.ts b/code/src/hooks/useFilterDeepLink.ts
new file mode 100644
index 0000000..0a8574d
--- /dev/null
+++ b/code/src/hooks/useFilterDeepLink.ts
@@ -0,0 +1,128 @@
+import { useState, useEffect, useCallback } from 'react';
+import {
+ getFiltersFromUrl,
+ updateUrlWithFilters
+} from '../utils/sortDeepLink';
+
+export const useFilterDeepLink = (dynamicFilterOptions: Record) => {
+ const [selectedItems, setSelectedItems] = useState>(() => {
+ const urlFilters = getFiltersFromUrl();
+ const initialFilters: Record = {};
+
+ Object.entries(urlFilters).forEach(([, values]) => {
+ values.forEach(value => {
+ const itemId = value.toLowerCase().replace(/\s+/g, "_");
+ initialFilters[itemId] = true;
+ });
+ });
+
+ return initialFilters;
+ });
+
+ const updateFilter = useCallback((itemId: string, isChecked: boolean, category: string) => {
+ setSelectedItems(prev => {
+ const newSelectedItems = { ...prev };
+ if (isChecked) {
+ newSelectedItems[itemId] = true;
+ } else {
+ delete newSelectedItems[itemId];
+ }
+
+ const originalValue = itemId.replace(/_/g, " ");
+ const currentFilters = getFiltersFromUrl();
+
+ if (isChecked) {
+ if (!currentFilters[category]) {
+ currentFilters[category] = [];
+ }
+ if (!currentFilters[category].includes(originalValue)) {
+ currentFilters[category].push(originalValue);
+ }
+ } else {
+ if (currentFilters[category]) {
+ currentFilters[category] = currentFilters[category].filter(v => v !== originalValue);
+ if (currentFilters[category].length === 0) {
+ delete currentFilters[category];
+ }
+ }
+ }
+
+ updateUrlWithFilters(currentFilters);
+
+ return newSelectedItems;
+ });
+ }, []);
+
+ const clearFilters = useCallback(() => {
+ setSelectedItems({});
+ updateUrlWithFilters({});
+ }, []);
+
+ const clearCategoryFilters = useCallback((category: string) => {
+ setSelectedItems(prev => {
+ const newSelectedItems = { ...prev };
+ Object.keys(newSelectedItems).forEach(itemId => {
+ if (itemId.startsWith(category.toLowerCase().replace(/\s+/g, "_"))) {
+ delete newSelectedItems[itemId];
+ }
+ });
+
+ const filters = convertSelectedItemsToFilters(newSelectedItems, dynamicFilterOptions);
+ updateUrlWithFilters(filters);
+
+ return newSelectedItems;
+ });
+ }, []);
+
+ useEffect(() => {
+ const handlePopState = () => {
+ const urlFilters = getFiltersFromUrl();
+ const newSelectedItems: Record = {};
+
+ Object.entries(urlFilters).forEach(([, values]) => {
+ values.forEach(value => {
+ const itemId = value.toLowerCase().replace(/\s+/g, "_");
+ newSelectedItems[itemId] = true;
+ });
+ });
+
+ if (JSON.stringify(newSelectedItems) !== JSON.stringify(selectedItems)) {
+ setSelectedItems(newSelectedItems);
+ }
+ };
+
+ window.addEventListener('popstate', handlePopState);
+ return () => {
+ window.removeEventListener('popstate', handlePopState);
+ };
+ }, [selectedItems]);
+
+ return {
+ selectedItems,
+ updateFilter,
+ clearFilters,
+ clearCategoryFilters,
+ };
+};
+
+const convertSelectedItemsToFilters = (selectedItems: Record, dynamicFilterOptions: Record): Record => {
+ const filters: Record = {
+ productsAndServices: [],
+ industries: [],
+ programmingLanguages: [],
+ };
+
+ Object.entries(selectedItems).forEach(([itemId, isSelected]) => {
+ if (isSelected) {
+ const originalValue = itemId.replace(/_/g, " ");
+
+ Object.entries(dynamicFilterOptions).forEach(([category, items]) => {
+ if (items.includes(originalValue)) {
+ filters[category].push(originalValue);
+ }
+ });
+ }
+ });
+
+ return filters;
+};
\ No newline at end of file
diff --git a/code/src/hooks/useIntersectionObserver.ts b/code/src/hooks/useIntersectionObserver.ts
new file mode 100644
index 0000000..f710799
--- /dev/null
+++ b/code/src/hooks/useIntersectionObserver.ts
@@ -0,0 +1,99 @@
+import { useState, useEffect, useRef } from 'react';
+
+interface UseIntersectionObserverOptions {
+ threshold?: number;
+ rootMargin?: string;
+ onSectionChange?: (sectionId: string) => void;
+ debounceMs?: number;
+}
+
+export const useIntersectionObserver = (
+ sectionIds: string[],
+ options: UseIntersectionObserverOptions = {}
+) => {
+ const [activeSection, setActiveSection] = useState('featured');
+ const observersRef = useRef>(new Map());
+ const { onSectionChange, debounceMs = 300 } = options;
+ const debounceTimeoutRef = useRef();
+ const lastUpdateTimeRef = useRef(0);
+
+ useEffect(() => {
+ const { rootMargin = '-15% 0px -15% 0px' } = options;
+
+ const sectionStates = new Map();
+
+ const observerCallback = (entries: IntersectionObserverEntry[]) => {
+ entries.forEach((entry) => {
+ const sectionId = entry.target.id;
+ sectionStates.set(sectionId, {
+ ratio: entry.intersectionRatio,
+ isVisible: entry.isIntersecting,
+ boundingRect: entry.boundingClientRect
+ });
+ });
+
+ let bestSection = 'featured';
+ let bestScore = -1;
+
+ sectionStates.forEach((state, sectionId) => {
+ if (state.isVisible && state.ratio > 0.1) {
+ const viewportCenter = window.innerHeight / 2;
+ const sectionTop = state.boundingRect.top;
+ const sectionHeight = state.boundingRect.height;
+
+ const sectionCenter = sectionTop + sectionHeight / 2;
+ const distanceFromCenter = Math.abs(viewportCenter - sectionCenter);
+ const normalizedDistance = distanceFromCenter / window.innerHeight;
+
+ const score = state.ratio * (1 - normalizedDistance);
+
+ if (score > bestScore) {
+ bestScore = score;
+ bestSection = sectionId;
+ }
+ }
+ });
+
+ const now = Date.now();
+ if (bestScore > -1 && bestSection !== activeSection && (now - lastUpdateTimeRef.current) > 500) {
+ if (debounceTimeoutRef.current) {
+ clearTimeout(debounceTimeoutRef.current);
+ }
+
+ debounceTimeoutRef.current = setTimeout(() => {
+ setActiveSection(bestSection);
+ onSectionChange?.(bestSection);
+ lastUpdateTimeRef.current = Date.now();
+ }, debounceMs);
+ }
+ };
+
+ const timeoutId = setTimeout(() => {
+ sectionIds.forEach((sectionId) => {
+ const element = document.getElementById(sectionId);
+ if (element) {
+ const observer = new IntersectionObserver(observerCallback, {
+ threshold: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
+ rootMargin
+ });
+
+ observer.observe(element);
+ observersRef.current.set(sectionId, observer);
+ }
+ });
+ }, 100);
+
+ return () => {
+ clearTimeout(timeoutId);
+ if (debounceTimeoutRef.current) {
+ clearTimeout(debounceTimeoutRef.current);
+ }
+ observersRef.current.forEach((observer) => {
+ observer.disconnect();
+ });
+ observersRef.current.clear();
+ };
+ }, [sectionIds, options.threshold, options.rootMargin, onSectionChange, activeSection, debounceMs]);
+
+ return activeSection;
+};
\ No newline at end of file
diff --git a/code/src/hooks/useNavigation.ts b/code/src/hooks/useNavigation.ts
new file mode 100644
index 0000000..fd061e3
--- /dev/null
+++ b/code/src/hooks/useNavigation.ts
@@ -0,0 +1,94 @@
+import { useState, useEffect, useCallback } from 'react';
+
+interface UseNavigationOptions {
+ scrollOffset?: number;
+ sectionMapping?: Record;
+}
+
+export const useNavigation = (options: UseNavigationOptions = {}) => {
+ const {
+ scrollOffset = 60,
+ sectionMapping = {
+ 'featured': 'featured',
+ 'accelerators': 'accelerators',
+ 'differentiators': 'differentiators',
+ 'how-it-works': 'how-it-works',
+ 'success-stories': 'customer-trust'
+ }
+ } = options;
+
+ const [currentSection, setCurrentSection] = useState('home');
+
+ const updateURL = useCallback((section: string) => {
+ const url = section === 'home' ? '/' : `/${section}`;
+ const currentUrl = window.location.pathname;
+
+ if (currentUrl !== url) {
+ window.history.pushState({ section }, '', url);
+ }
+ }, []);
+
+ const scrollToSection = useCallback((sectionId: string) => {
+ const element = document.getElementById(sectionId);
+ if (element) {
+ const elementTop = element.offsetTop - scrollOffset;
+ window.scrollTo({
+ top: elementTop,
+ behavior: 'smooth'
+ });
+ }
+ }, [scrollOffset]);
+
+ const setSection = useCallback((section: string, source: 'click' | 'browser') => {
+ if (section === currentSection) return;
+
+ setCurrentSection(section);
+ updateURL(section);
+
+ if (source === 'click') {
+ const targetId = sectionMapping[section] || section;
+ scrollToSection(targetId);
+ }
+ }, [currentSection, updateURL, sectionMapping, scrollToSection]);
+
+ const handleHeaderVisibility = useCallback(() => {
+ const featuredElement = document.getElementById('featured');
+ const scrollPosition = window.scrollY;
+
+ if (featuredElement) {
+ const featuredTop = featuredElement.offsetTop - scrollOffset;
+ const buffer = 61;
+ const isVisible = scrollPosition > featuredTop - buffer;
+
+ return isVisible;
+ }
+ return scrollPosition > 200;
+ }, [scrollOffset]);
+
+ useEffect(() => {
+ const handlePopState = () => {
+ const path = window.location.pathname;
+ const section = path === '/' ? 'home' : path.slice(1);
+ setSection(section, 'browser');
+ };
+
+ const handleInitialURL = () => {
+ const path = window.location.pathname;
+ const section = path === '/' ? 'home' : path.slice(1);
+ setCurrentSection(section);
+ };
+
+ window.addEventListener('popstate', handlePopState);
+ handleInitialURL();
+
+ return () => {
+ window.removeEventListener('popstate', handlePopState);
+ };
+ }, [setSection]);
+
+ return {
+ currentSection,
+ navigateToSection: setSection,
+ handleHeaderVisibility
+ };
+};
\ No newline at end of file
diff --git a/code/src/hooks/useNavigationWithUrl.ts b/code/src/hooks/useNavigationWithUrl.ts
new file mode 100644
index 0000000..5bbef18
--- /dev/null
+++ b/code/src/hooks/useNavigationWithUrl.ts
@@ -0,0 +1,150 @@
+import { useState, useEffect, useCallback, useRef } from 'react';
+import { SECTION_MAPPING } from '../utils/sectionMapping';
+import { getSectionFromUrl, updateUrlWithSection } from '../utils/sortDeepLink';
+
+export const useNavigationWithUrl = () => {
+ const [currentSection, setCurrentSection] = useState('home');
+
+ // Simple section detection - just like Microsoft Teams
+ const getCurrentVisibleSection = useCallback(() => {
+ const viewportHeight = window.innerHeight;
+
+ // Check each section to see which one is most visible
+ for (const [section, sectionId] of Object.entries(SECTION_MAPPING)) {
+ const element = document.getElementById(sectionId);
+ if (!element) continue;
+
+ const rect = element.getBoundingClientRect();
+
+ // If section is visible in the middle of viewport, it's the current section
+ // Using 50% threshold for middle of screen
+ if (rect.top <= viewportHeight * 0.5 && rect.bottom >= viewportHeight * 0.5) {
+ return section;
+ }
+ }
+
+ // If no section is clearly visible, we're in home area
+ return 'home';
+ }, []);
+
+ // Simple URL update logic - now uses existing utilities
+ const updateUrl = useCallback((section: string) => {
+ updateUrlWithSection(section);
+ }, []);
+
+ // Detect whether the navigation has become sticky with light hysteresis to avoid flicker
+ const stickyStateRef = useRef(false);
+ const isNavigationSticky = useCallback(() => {
+ const sentinel = document.querySelector('.navigation-sentinel') as HTMLElement | null;
+ if (!sentinel) return false;
+ const rect = sentinel.getBoundingClientRect();
+ const top = rect.top;
+ // Hysteresis: require passing -8px to enter sticky; +12px to exit
+ const ENTER_AT = -8;
+ const EXIT_AT = 12;
+
+ if (stickyStateRef.current) {
+ if (top > EXIT_AT) stickyStateRef.current = false;
+ } else {
+ if (top <= ENTER_AT) stickyStateRef.current = true;
+ }
+ return stickyStateRef.current;
+ }, []);
+
+ // Simple scroll handler - only updates URL
+ const handleScroll = useCallback(() => {
+ // Gate updates until the navigation has actually become sticky
+ if (!isNavigationSticky()) {
+ if (currentSection !== 'home') {
+ setCurrentSection('home');
+ // Clear section parameter so the URL reflects "home"
+ updateUrlWithSection('');
+ }
+ return;
+ }
+
+ const newSection = getCurrentVisibleSection();
+ if (newSection !== currentSection) {
+ setCurrentSection(newSection);
+ updateUrl(newSection);
+ }
+ }, [currentSection, getCurrentVisibleSection, updateUrl, isNavigationSticky]);
+
+ // Handle browser back/forward - now uses existing utilities
+ const handlePopState = useCallback(() => {
+ const section = getSectionFromUrl();
+ const validSection = section || 'home';
+ setCurrentSection(validSection);
+
+ // Scroll to the section when navigating via browser back/forward
+ if (validSection !== 'home') {
+ // If nav is not yet sticky, scroll to the nav first so behavior mirrors manual scroll
+ if (!isNavigationSticky()) {
+ const nav = document.getElementById('site-nav');
+ if (nav) nav.scrollIntoView({ behavior: 'smooth', block: 'start' });
+ }
+ const sectionId = SECTION_MAPPING[validSection];
+ if (sectionId) {
+ const element = document.getElementById(sectionId);
+ if (element) {
+ element.scrollIntoView({ behavior: 'smooth', block: 'start' });
+ }
+ }
+ }
+ }, [isNavigationSticky]);
+
+ // Add scroll-to-section function for navigation clicks
+ const scrollToSection = useCallback((section: string) => {
+ const sectionId = SECTION_MAPPING[section];
+ if (!sectionId) return;
+
+ const element = document.getElementById(sectionId);
+ if (!element) return;
+ element.scrollIntoView({ behavior: 'smooth', block: 'start' });
+ }, []);
+
+ useEffect(() => {
+ // Set initial section based on URL - now uses existing utilities
+ const section = getSectionFromUrl();
+ const initialSection = section || 'home';
+ setCurrentSection(initialSection);
+
+ // Add event listeners
+ window.addEventListener('scroll', handleScroll, { passive: true });
+ window.addEventListener('popstate', handlePopState);
+
+ return () => {
+ window.removeEventListener('scroll', handleScroll);
+ window.removeEventListener('popstate', handlePopState);
+ };
+ }, [handleScroll, handlePopState]);
+
+ // Handle initial deep link navigation - now uses existing utilities
+ useEffect(() => {
+ const section = getSectionFromUrl();
+ if (!section) return;
+
+ // Use a small delay to ensure DOM is ready
+ const timer = setTimeout(() => {
+ const sectionId = SECTION_MAPPING[section];
+ if (sectionId) {
+ const element = document.getElementById(sectionId);
+ if (element) {
+ // If nav is not sticky yet, bring the nav into view first
+ if (!isNavigationSticky()) {
+ const nav = document.getElementById('site-nav');
+ if (nav) nav.scrollIntoView({ behavior: 'auto', block: 'start' as ScrollLogicalPosition });
+ }
+ element.scrollIntoView({ behavior: 'auto', block: 'start' as ScrollLogicalPosition });
+ }
+ }
+ }, 100);
+
+ return () => clearTimeout(timer);
+ }, [isNavigationSticky]); // Only run once on mount
+
+ return {
+ currentSection,
+ scrollToSection
+ };
+};
\ No newline at end of file
diff --git a/code/src/hooks/useScrollNavigation.ts b/code/src/hooks/useScrollNavigation.ts
new file mode 100644
index 0000000..54bd62b
--- /dev/null
+++ b/code/src/hooks/useScrollNavigation.ts
@@ -0,0 +1,155 @@
+import { useState, useEffect, useCallback } from 'react';
+import {
+ getSectionFromUrl,
+ updateUrlWithSection
+} from '../utils/sortDeepLink';
+import { SECTION_MAPPING } from '../utils/sectionMapping';
+
+interface UseScrollNavigationOptions {
+ defaultSection?: string;
+ scrollOffset?: number;
+ sectionMapping?: Record;
+}
+
+export const useScrollNavigation = (options: UseScrollNavigationOptions = {}) => {
+ const {
+ defaultSection = 'home',
+ scrollOffset = 60,
+ sectionMapping = SECTION_MAPPING
+ } = options;
+
+ const [currentSection, setCurrentSection] = useState(defaultSection);
+ const [isHeaderVisible, setIsHeaderVisible] = useState(false);
+ const [isNavigating, setIsNavigating] = useState(false);
+ const [isUpdatingUrl, setIsUpdatingUrl] = useState(false);
+
+ const updateUrl = useCallback((section: string) => {
+ setIsUpdatingUrl(true);
+ if (section === 'home') {
+ updateUrlWithSection('');
+ } else {
+ updateUrlWithSection(section);
+ }
+ setTimeout(() => setIsUpdatingUrl(false), 100);
+ }, []);
+
+ const scrollToSection = useCallback((sectionId: string) => {
+ const element = document.getElementById(sectionId);
+ if (element) {
+ const elementTop = element.offsetTop - scrollOffset;
+ window.scrollTo({
+ top: elementTop,
+ behavior: 'smooth'
+ });
+ }
+ }, [scrollOffset]);
+
+ const navigateToSection = useCallback((section: string) => {
+ setIsNavigating(true);
+ setCurrentSection(section);
+ updateUrl(section);
+
+ const targetId = sectionMapping[section] || section;
+ scrollToSection(targetId);
+
+ setTimeout(() => {
+ setIsNavigating(false);
+ }, 1000);
+ }, [updateUrl, scrollToSection, sectionMapping]);
+
+ const handleHeaderVisibility = useCallback(() => {
+ const scrollY = window.scrollY;
+ const featuredElement = document.getElementById('featured');
+
+ if (featuredElement) {
+ const featuredTop = featuredElement.offsetTop - scrollOffset;
+ setIsHeaderVisible(scrollY >= featuredTop);
+ }
+ }, [scrollOffset]);
+
+ const getCurrentSectionFromScroll = useCallback(() => {
+ const scrollY = window.scrollY;
+ const sections = Object.entries(sectionMapping);
+
+ const firstSection = sections[0];
+ if (firstSection) {
+ const firstElement = document.getElementById(firstSection[1]);
+ if (firstElement) {
+ const firstSectionTop = firstElement.offsetTop - scrollOffset;
+ if (scrollY < firstSectionTop) {
+ return 'home';
+ }
+ }
+ }
+
+ for (let i = sections.length - 1; i >= 0; i--) {
+ const [section, sectionId] = sections[i];
+ const element = document.getElementById(sectionId);
+ if (!element) continue;
+
+ const sectionTop = element.offsetTop - scrollOffset;
+ if (scrollY >= sectionTop) {
+ return section;
+ }
+ }
+
+ return 'home';
+ }, [sectionMapping, scrollOffset]);
+
+ const handleScrollForSectionDetection = useCallback(() => {
+ if (isNavigating) return;
+
+ const newSection = getCurrentSectionFromScroll();
+
+ if (newSection !== currentSection) {
+ setCurrentSection(newSection);
+ updateUrl(newSection);
+ }
+ }, [currentSection, getCurrentSectionFromScroll, updateUrl, isNavigating]);
+
+ useEffect(() => {
+ const handlePopState = () => {
+ if (isUpdatingUrl) return;
+
+ const sectionFromUrl = getSectionFromUrl();
+ const section = sectionFromUrl || 'home';
+ setCurrentSection(section);
+
+ if (section !== 'home') {
+ const targetId = sectionMapping[section] || section;
+ scrollToSection(targetId);
+ }
+ };
+
+ const handleInitialUrl = () => {
+ const sectionFromUrl = getSectionFromUrl();
+ const section = sectionFromUrl || 'home';
+ setCurrentSection(section);
+
+ if (section !== 'home') {
+ setTimeout(() => {
+ const targetId = sectionMapping[section] || section;
+ scrollToSection(targetId);
+ }, 100);
+ }
+ };
+
+ window.addEventListener('popstate', handlePopState);
+ window.addEventListener('scroll', handleHeaderVisibility, { passive: true });
+ window.addEventListener('scroll', handleScrollForSectionDetection, { passive: true });
+
+ handleInitialUrl();
+
+ return () => {
+ window.removeEventListener('popstate', handlePopState);
+ window.removeEventListener('scroll', handleHeaderVisibility);
+ window.removeEventListener('scroll', handleScrollForSectionDetection);
+ };
+ }, [handleHeaderVisibility, handleScrollForSectionDetection, scrollToSection, sectionMapping]);
+
+ return {
+ currentSection,
+ isHeaderVisible,
+ navigateToSection
+ };
+};
\ No newline at end of file
diff --git a/code/src/hooks/useSearchDeepLink.ts b/code/src/hooks/useSearchDeepLink.ts
new file mode 100644
index 0000000..0a8b411
--- /dev/null
+++ b/code/src/hooks/useSearchDeepLink.ts
@@ -0,0 +1,47 @@
+import { useState, useEffect, useCallback } from 'react';
+import {
+ getKeywordFromUrl,
+ updateUrlWithKeyword,
+ isValidKeyword
+} from '../utils/sortDeepLink';
+
+export const useSearchDeepLink = (defaultKeyword: string = "") => {
+ const [searchQuery, setSearchQuery] = useState(() => {
+ const urlKeyword = getKeywordFromUrl();
+ return isValidKeyword(urlKeyword) ? urlKeyword : defaultKeyword;
+ });
+
+ const updateSearch = useCallback((newKeyword: string) => {
+ if (!isValidKeyword(newKeyword)) {
+ return;
+ }
+
+ setSearchQuery(newKeyword);
+ updateUrlWithKeyword(newKeyword);
+ }, []);
+
+ const clearSearch = useCallback(() => {
+ setSearchQuery("");
+ updateUrlWithKeyword("");
+ }, []);
+
+ useEffect(() => {
+ const handlePopState = () => {
+ const urlKeyword = getKeywordFromUrl();
+ if (isValidKeyword(urlKeyword) && urlKeyword !== searchQuery) {
+ setSearchQuery(urlKeyword);
+ }
+ };
+
+ window.addEventListener('popstate', handlePopState);
+ return () => {
+ window.removeEventListener('popstate', handlePopState);
+ };
+ }, [searchQuery]);
+
+ return {
+ searchQuery,
+ updateSearch,
+ clearSearch,
+ };
+};
\ No newline at end of file
diff --git a/code/src/hooks/useSimpleUrlUpdate.ts b/code/src/hooks/useSimpleUrlUpdate.ts
new file mode 100644
index 0000000..2fa9e10
--- /dev/null
+++ b/code/src/hooks/useSimpleUrlUpdate.ts
@@ -0,0 +1,96 @@
+import { useState, useEffect, useCallback } from 'react';
+import { SECTION_MAPPING } from '../utils/sectionMapping';
+
+export const useNavigationWithUrl = () => {
+ const [currentSection, setCurrentSection] = useState('home');
+
+ // Simple section detection - just like Microsoft Teams
+ const getCurrentVisibleSection = useCallback(() => {
+ const viewportHeight = window.innerHeight;
+
+ // Check each section to see which one is most visible
+ for (const [section, sectionId] of Object.entries(SECTION_MAPPING)) {
+ const element = document.getElementById(sectionId);
+ if (!element) continue;
+
+ const rect = element.getBoundingClientRect();
+
+ // If section is visible in the middle of viewport, it's the current section
+ // Using 50% threshold for middle of screen
+ if (rect.top <= viewportHeight * 0.5 && rect.bottom >= viewportHeight * 0.5) {
+ return section;
+ }
+ }
+
+ // If no section is clearly visible, we're in home area
+ return 'home';
+ }, []);
+
+ // Simple URL update logic
+ const updateUrl = useCallback((section: string) => {
+ if (section === 'home') {
+ // Remove hash for home section
+ if (window.location.hash) {
+ window.history.replaceState(null, '', window.location.pathname);
+ }
+ } else {
+ // Add hash for other sections
+ const newHash = `#${section}`;
+ if (window.location.hash !== newHash) {
+ window.history.replaceState(null, '', newHash);
+ }
+ }
+ }, []);
+
+ // Simple scroll handler - only updates URL
+ const handleScroll = useCallback(() => {
+ const newSection = getCurrentVisibleSection();
+ if (newSection !== currentSection) {
+ setCurrentSection(newSection);
+ updateUrl(newSection);
+ }
+ }, [currentSection, getCurrentVisibleSection, updateUrl]);
+
+ // Handle browser back/forward
+ const handlePopState = useCallback(() => {
+ const hash = window.location.hash.replace('#', '');
+ const section = hash || 'home';
+ setCurrentSection(section);
+ }, []);
+
+ // Add scroll-to-section function for navigation clicks
+ const scrollToSection = useCallback((section: string) => {
+ const sectionId = SECTION_MAPPING[section];
+ if (!sectionId) return;
+
+ const element = document.getElementById(sectionId);
+ if (!element) return;
+
+ // Smooth scroll to section
+ element.scrollIntoView({
+ behavior: 'smooth',
+ block: 'start'
+ });
+ }, []);
+
+ useEffect(() => {
+ // Set initial section based on URL
+ const hash = window.location.hash.replace('#', '');
+ const initialSection = hash || 'home';
+ setCurrentSection(initialSection);
+
+ // Add event listeners
+ window.addEventListener('scroll', handleScroll, { passive: true });
+ window.addEventListener('popstate', handlePopState);
+
+ return () => {
+ window.removeEventListener('scroll', handleScroll);
+ window.removeEventListener('popstate', handlePopState);
+ };
+ }, [handleScroll, handlePopState]);
+
+ return {
+ currentSection,
+ scrollToSection
+ };
+};
\ No newline at end of file
diff --git a/code/src/hooks/useSortDeepLink.ts b/code/src/hooks/useSortDeepLink.ts
new file mode 100644
index 0000000..b73e79b
--- /dev/null
+++ b/code/src/hooks/useSortDeepLink.ts
@@ -0,0 +1,40 @@
+import { useState, useEffect, useCallback } from 'react';
+import { getSortFromUrl, updateUrlWithSort, isValidSortParam } from '../utils/sortDeepLink';
+
+export const useSortDeepLink = (defaultSort: string = "releaseNewest") => {
+ const [sortBy, setSortBy] = useState(() => {
+ const urlSort = getSortFromUrl();
+ return isValidSortParam(urlSort) ? urlSort : defaultSort;
+ });
+
+ const updateSort = useCallback((newSort: string) => {
+ if (isValidSortParam(newSort) && newSort !== sortBy) {
+ setSortBy(newSort);
+ updateUrlWithSort(newSort);
+ }
+ }, [sortBy]);
+
+ useEffect(() => {
+ const handlePopState = () => {
+ const urlSort = getSortFromUrl();
+ if (isValidSortParam(urlSort) && urlSort !== sortBy) {
+ setSortBy(urlSort);
+ }
+ };
+
+ window.addEventListener('popstate', handlePopState);
+ return () => window.removeEventListener('popstate', handlePopState);
+ }, [sortBy]);
+
+ useEffect(() => {
+ const urlSort = getSortFromUrl();
+ if (isValidSortParam(urlSort) && urlSort !== sortBy) {
+ updateUrlWithSort(sortBy);
+ }
+ }, [sortBy]);
+
+ return {
+ sortBy,
+ updateSort,
+ };
+};
\ No newline at end of file
diff --git a/code/src/hooks/useUrlState.ts b/code/src/hooks/useUrlState.ts
new file mode 100644
index 0000000..7b54b5f
--- /dev/null
+++ b/code/src/hooks/useUrlState.ts
@@ -0,0 +1,156 @@
+import { useState, useEffect, useCallback, useRef } from 'react';
+import { SECTION_MAPPING } from '../utils/sectionMapping';
+
+interface UseUrlStateOptions {
+ defaultSection?: string;
+ scrollOffset?: number;
+ sectionMapping?: Record;
+}
+
+export const useUrlState = (options: UseUrlStateOptions = {}) => {
+ const {
+ defaultSection = 'home',
+ scrollOffset = 60,
+ sectionMapping = SECTION_MAPPING
+ } = options;
+
+ const [currentSection, setCurrentSection] = useState(defaultSection);
+ const isNavigatingRef = useRef(false);
+ const navigationTimeoutRef = useRef();
+ const lastManualNavigationRef = useRef('');
+
+ const updateUrl = useCallback((section: string) => {
+ const newUrl = section === 'home' ? '/' : `/${section}`;
+ window.history.pushState({ section }, '', newUrl);
+ }, []);
+
+ const scrollToSection = useCallback((sectionId: string) => {
+ const element = document.getElementById(sectionId);
+ if (element) {
+ const elementTop = element.offsetTop - scrollOffset;
+ window.scrollTo({
+ top: elementTop,
+ behavior: 'smooth'
+ });
+ }
+ }, [scrollOffset]);
+
+ const navigateToSection = useCallback((section: string) => {
+ isNavigatingRef.current = true;
+ lastManualNavigationRef.current = section;
+ setCurrentSection(section);
+ updateUrl(section);
+ const targetId = sectionMapping[section] || section;
+ scrollToSection(targetId);
+
+ if (navigationTimeoutRef.current) {
+ clearTimeout(navigationTimeoutRef.current);
+ }
+
+ navigationTimeoutRef.current = setTimeout(() => {
+ isNavigatingRef.current = false;
+ lastManualNavigationRef.current = '';
+ }, 1500);
+ }, [updateUrl, scrollToSection, sectionMapping]);
+
+ const updateUrlFromSectionId = useCallback((sectionId: string) => {
+ if (isNavigatingRef.current) {
+ return;
+ }
+
+ const section = Object.keys(sectionMapping).find(key => sectionMapping[key] === sectionId);
+
+ if (section && section !== lastManualNavigationRef.current) {
+ setCurrentSection(section);
+ updateUrl(section);
+ }
+ }, [sectionMapping, updateUrl, currentSection]);
+
+ const handleScrollForHomePage = useCallback(() => {
+ if (isNavigatingRef.current) return;
+
+ const scrollY = window.scrollY;
+ const featuredElement = document.getElementById('featured');
+
+ if (featuredElement) {
+ const featuredTop = featuredElement.offsetTop - scrollOffset;
+
+ // If we're above the featured section, we're on the home page
+ if (scrollY < featuredTop) {
+ if (currentSection !== 'home') {
+ setCurrentSection('home');
+ window.history.pushState({ section: 'home' }, '', '/');
+ }
+ }
+ }
+ }, [currentSection, scrollOffset]);
+
+ const handleScrollForUrlUpdates = useCallback(() => {
+ if (isNavigatingRef.current) return;
+
+ const scrollY = window.scrollY;
+ const featuredElement = document.getElementById('featured');
+
+ if (featuredElement) {
+ const featuredTop = featuredElement.offsetTop - scrollOffset;
+
+ // If we're above the featured section, we're on the home page
+ if (scrollY < featuredTop) {
+ if (currentSection !== 'home') {
+ setCurrentSection('home');
+ window.history.pushState({ section: 'home' }, '', '/');
+ }
+ } else {
+ // We're in or below the featured section
+ if (currentSection !== 'featured') {
+ setCurrentSection('featured');
+ window.history.pushState({ section: 'featured' }, '', '/featured');
+ }
+ }
+ }
+ }, [currentSection, scrollOffset]);
+
+ useEffect(() => {
+ const handlePopState = () => {
+ const path = window.location.pathname;
+ const section = path === '/' ? 'home' : path.slice(1);
+ setCurrentSection(section);
+ const targetId = sectionMapping[section] || section;
+ scrollToSection(targetId);
+ };
+
+ const handleInitialUrl = () => {
+ const path = window.location.pathname;
+ const section = path === '/' ? 'home' : path.slice(1);
+ setCurrentSection(section);
+
+ if (section !== 'home' || path !== '/') {
+ setTimeout(() => {
+ const targetId = sectionMapping[section] || section;
+ scrollToSection(targetId);
+ }, 100);
+ }
+ };
+
+ window.addEventListener('popstate', handlePopState);
+ window.addEventListener('scroll', handleScrollForHomePage, { passive: true });
+ window.addEventListener('scroll', handleScrollForUrlUpdates, { passive: true });
+ handleInitialUrl();
+
+ return () => {
+ window.removeEventListener('popstate', handlePopState);
+ window.removeEventListener('scroll', handleScrollForHomePage);
+ window.removeEventListener('scroll', handleScrollForUrlUpdates);
+ if (navigationTimeoutRef.current) {
+ clearTimeout(navigationTimeoutRef.current);
+ }
+ };
+ }, [scrollToSection, sectionMapping, handleScrollForHomePage, handleScrollForUrlUpdates]);
+
+ return {
+ currentSection,
+ navigateToSection,
+ updateUrl,
+ updateUrlFromSectionId
+ };
+};
\ No newline at end of file
diff --git a/code/src/index.css b/code/src/index.css
new file mode 100644
index 0000000..af5b00d
--- /dev/null
+++ b/code/src/index.css
@@ -0,0 +1,73 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+:root {
+ font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+ overflow-x: hidden;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/code/src/main.tsx b/code/src/main.tsx
new file mode 100644
index 0000000..bef5202
--- /dev/null
+++ b/code/src/main.tsx
@@ -0,0 +1,10 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import './index.css'
+import App from './App.tsx'
+
+createRoot(document.getElementById('root')!).render(
+
+
+ ,
+)
diff --git a/code/src/types/index.ts b/code/src/types/index.ts
new file mode 100644
index 0000000..ac0fd94
--- /dev/null
+++ b/code/src/types/index.ts
@@ -0,0 +1,61 @@
+// Asset type for card resources
+export interface AcceleratorAsset {
+ label: string;
+ href: string;
+ fileType?: string;
+}
+
+// Main accelerator card interface
+export interface AcceleratorCard {
+ solutionPlays: string[];
+ solutionAreas: string[];
+ keys: string[];
+ stability: string;
+ accelerator: string;
+ excerpt: string;
+ productsAndServices: string[];
+ programmingLanguages: string[];
+ githubUrl: string;
+ assets?: AcceleratorAsset[];
+ technicalPattern?: string;
+ foundryTemplateName?: string;
+ useCases?: string[];
+ keywords?: string[];
+ industries?: string[];
+ releaseDate: string;
+}
+
+// Navigation section interface
+export interface NavigationSection {
+ id: string;
+ title: string;
+ component: React.ComponentType;
+}
+
+// Filter options interface
+export interface FilterOptions {
+ [key: string]: string[];
+}
+
+// Card variant types
+export type CardVariant = 'featured' | 'standard' | 'compact';
+export type CardSize = 'small' | 'medium' | 'large';
+
+// Extended card props interface for components
+export interface CardProps extends AcceleratorCard {
+ variant?: CardVariant;
+ size?: CardSize;
+ searchQuery?: string;
+ onClick?: () => void;
+}
+
+// Success Stories Section interfaces
+export interface TestimonialQuote {
+ quote: string;
+ author: string;
+}
+
+export interface SuccessStoriesSectionProps {
+ title?: string;
+ quotes: TestimonialQuote[];
+}
\ No newline at end of file
diff --git a/code/src/utils/getLinkIcon.ts b/code/src/utils/getLinkIcon.ts
new file mode 100644
index 0000000..d3616b9
--- /dev/null
+++ b/code/src/utils/getLinkIcon.ts
@@ -0,0 +1,43 @@
+const fileTypeIconMap: Record = {
+ pptx: "/csa-sas-ext-landingpage/icons/PowerPoint.svg",
+ ppt: "/csa-sas-ext-landingpage/icons/PowerPoint.svg",
+ xlsx: "/csa-sas-ext-landingpage/icons/Excel.svg",
+ xls: "/csa-sas-ext-landingpage/icons/Excel.svg",
+ docx: "/csa-sas-ext-landingpage/icons/Word.svg",
+ doc: "/csa-sas-ext-landingpage/icons/Word.svg",
+ pdf: "/csa-sas-ext-landingpage/icons/pdf.svg",
+ default: null,
+};
+
+export const getLinkIcon = (href: string, fileType?: string): string | null => {
+ try {
+ if (fileType && fileTypeIconMap[fileType.toLowerCase()]) {
+ return fileTypeIconMap[fileType.toLowerCase()];
+ }
+
+ // Check for service-specific icons
+ try {
+ const urlObj = new URL(href);
+ const hostname = urlObj.hostname.toLowerCase();
+
+ if (hostname.includes('github.com')) return '/csa-sas-ext-landingpage/icons/github.svg';
+ if (hostname.includes('figma.com')) return '/csa-sas-ext-landingpage/icons/figma.svg';
+ if (hostname.includes('youtube.com')) return '/csa-sas-ext-landingpage/icons/youtube.svg';
+ if (hostname.includes('docs.microsoft.com')) return '/csa-sas-ext-landingpage/icons/docs.svg';
+ if (hostname.includes('learn.microsoft.com')) return '/csa-sas-ext-landingpage/icons/learn.svg';
+ } catch {
+ // Ignore URL parsing errors
+ }
+
+ // Check file extension
+ const extMatch = href.match(/\.(pptx?|xlsx?|docx?|pdf)$/i);
+ if (extMatch) {
+ const ext = extMatch[1].toLowerCase();
+ return fileTypeIconMap[ext] || null;
+ }
+
+ return null;
+ } catch {
+ return null;
+ }
+};
\ No newline at end of file
diff --git a/code/src/utils/sectionMapping.ts b/code/src/utils/sectionMapping.ts
new file mode 100644
index 0000000..4b7d671
--- /dev/null
+++ b/code/src/utils/sectionMapping.ts
@@ -0,0 +1,23 @@
+export const SECTION_MAPPING: Record = {
+ 'featured': 'featured',
+ 'accelerators': 'accelerators',
+ 'differentiators': 'differentiators',
+ 'how-it-works': 'how-it-works',
+ 'success-stories': 'customer-trust'
+};
+
+export const REVERSE_SECTION_MAPPING: Record = {
+ 'featured': 'featured',
+ 'accelerators': 'accelerators',
+ 'differentiators': 'differentiators',
+ 'how-it-works': 'how-it-works',
+ 'customer-trust': 'success-stories'
+};
+
+export const getSectionFromId = (sectionId: string): string => {
+ return REVERSE_SECTION_MAPPING[sectionId] || sectionId;
+};
+
+export const getSectionIdFromSection = (section: string): string => {
+ return SECTION_MAPPING[section] || section;
+};
\ No newline at end of file
diff --git a/code/src/utils/sortDeepLink.ts b/code/src/utils/sortDeepLink.ts
new file mode 100644
index 0000000..a35ef1d
--- /dev/null
+++ b/code/src/utils/sortDeepLink.ts
@@ -0,0 +1,283 @@
+export const sortParamMapping: Record = {
+ releaseNewest: "newest",
+ releaseOldest: "oldest",
+ accelerator: "az",
+ acceleratorDesc: "za",
+};
+
+export const reverseSortParamMapping: Record = {
+ newest: "releaseNewest",
+ oldest: "releaseOldest",
+ az: "accelerator",
+ za: "acceleratorDesc",
+};
+
+export const getSortFromUrl = (): string => {
+ const hash = window.location.hash;
+ const params = new URLSearchParams(hash.substring(1));
+ const sortParam = params.get("sort");
+
+ if (!sortParam) return "releaseNewest";
+
+ const sortValue = reverseSortParamMapping[sortParam];
+ return isValidSortParam(sortValue) ? sortValue : "releaseNewest";
+};
+
+export const getUrlFromSort = (sortValue: string): string => {
+ const sortParam = sortParamMapping[sortValue];
+ if (!sortParam) return "";
+
+ const currentHash = window.location.hash;
+ const params = new URLSearchParams(currentHash.substring(1));
+ params.set("sort", sortParam);
+
+ return `#${params.toString()}`;
+};
+
+export const isValidSortParam = (sortValue: string | undefined): boolean => {
+ return sortValue ? Object.keys(sortParamMapping).includes(sortValue) : false;
+};
+
+export const updateUrlWithSort = (sortValue: string): void => {
+ const newHash = getUrlFromSort(sortValue);
+ if (newHash && newHash !== window.location.hash) {
+ window.history.pushState(null, "", newHash);
+ }
+};
+
+export const getKeywordFromUrl = (): string => {
+ const hash = window.location.hash;
+ const params = new URLSearchParams(hash.substring(1));
+ const keywordParam = params.get("keyword");
+
+ if (!keywordParam) return "";
+
+ try {
+ return decodeURIComponent(keywordParam);
+ } catch {
+ return "";
+ }
+};
+
+export const getUrlWithKeyword = (keyword: string): string => {
+ const currentHash = window.location.hash;
+ const params = new URLSearchParams(currentHash.substring(1));
+
+ if (keyword && keyword.trim()) {
+ params.set("keyword", encodeURIComponent(keyword.trim()));
+ } else {
+ params.delete("keyword");
+ }
+
+ const result = params.toString();
+ return result ? `#${result}` : "";
+};
+
+export const isValidKeyword = (keyword: string): boolean => {
+ return typeof keyword === "string" && keyword.length >= 0;
+};
+
+export const updateUrlWithKeyword = (keyword: string): void => {
+ const newHash = getUrlWithKeyword(keyword);
+
+ if (newHash !== window.location.hash) {
+ const newUrl = newHash ? window.location.pathname + newHash : window.location.pathname;
+ window.history.pushState(null, "", newUrl);
+ }
+};
+
+export const combineUrlParams = (sortValue: string, keyword: string): string => {
+ const params = new URLSearchParams();
+
+ if (sortValue && sortParamMapping[sortValue]) {
+ params.set("sort", sortParamMapping[sortValue]);
+ }
+
+ if (keyword.trim()) {
+ params.set("keyword", encodeURIComponent(keyword.trim()));
+ }
+
+ return `#${params.toString()}`;
+};
+
+export const updateUrlWithParams = (sortValue: string, keyword: string): void => {
+ const newHash = combineUrlParams(sortValue, keyword);
+ if (newHash !== window.location.hash) {
+ window.history.pushState(null, "", newHash);
+ }
+};
+
+export const filterParamMapping: Record = {
+ productsAndServices: "productsAndServices",
+ industries: "industries",
+ programmingLanguages: "languages",
+};
+
+export const getFiltersFromUrl = (): Record => {
+ const hash = window.location.hash;
+ const params = new URLSearchParams(hash.substring(1));
+ const filters: Record = {};
+
+ Object.entries(filterParamMapping).forEach(([internalKey, urlKey]) => {
+ const paramValue = params.get(urlKey);
+ if (paramValue) {
+ try {
+ const decodedValue = decodeURIComponent(paramValue);
+ filters[internalKey] = decodedValue.split(',').map(v => v.trim()).filter(v => v);
+ } catch {
+ filters[internalKey] = [];
+ }
+ }
+ });
+
+ return filters;
+};
+
+export const getUrlWithFilters = (filters: Record): string => {
+ const currentHash = window.location.hash;
+ const params = new URLSearchParams(currentHash.substring(1));
+
+ Object.entries(filterParamMapping).forEach(([internalKey, urlKey]) => {
+ const filterValues = filters[internalKey];
+ if (filterValues && filterValues.length > 0) {
+ const encodedValues = filterValues.map(v => encodeURIComponent(v.trim())).join(',');
+ params.set(urlKey, encodedValues);
+ } else {
+ params.delete(urlKey);
+ }
+ });
+
+ const result = params.toString();
+ return result ? `#${result}` : "";
+};
+
+export const isValidFilterParam = (filterValues: string[]): boolean => {
+ return Array.isArray(filterValues) && filterValues.every(v => typeof v === "string" && v.trim().length > 0);
+};
+
+export const updateUrlWithFilters = (filters: Record): void => {
+ const newHash = getUrlWithFilters(filters);
+
+ if (newHash !== window.location.hash) {
+ const newUrl = newHash ? window.location.pathname + newHash : window.location.pathname;
+ window.history.pushState(null, "", newUrl);
+ }
+};
+
+export const combineAllUrlParams = (sortValue: string, keyword: string, filters: Record): string => {
+ const params = new URLSearchParams();
+
+ if (sortValue && sortParamMapping[sortValue]) {
+ params.set("sort", sortParamMapping[sortValue]);
+ }
+
+ if (keyword && keyword.trim()) {
+ params.set("keyword", encodeURIComponent(keyword.trim()));
+ }
+
+ Object.entries(filterParamMapping).forEach(([internalKey, urlKey]) => {
+ const filterValues = filters[internalKey];
+ if (filterValues && filterValues.length > 0) {
+ const encodedValues = filterValues.map(v => encodeURIComponent(v.trim())).join(',');
+ params.set(urlKey, encodedValues);
+ }
+ });
+
+ return `#${params.toString()}`;
+};
+
+export const updateUrlWithAllParams = (sortValue: string, keyword: string, filters: Record): void => {
+ const newHash = combineAllUrlParams(sortValue, keyword, filters);
+ if (newHash !== window.location.hash) {
+ const newUrl = newHash ? window.location.pathname + newHash : window.location.pathname;
+ window.history.pushState(null, "", newUrl);
+ }
+};
+
+export const getSectionFromUrl = (): string => {
+ const hash = window.location.hash;
+ const params = new URLSearchParams(hash.substring(1));
+ const sectionParam = params.get("section");
+
+ if (sectionParam) {
+ try {
+ return decodeURIComponent(sectionParam);
+ } catch {
+ return "";
+ }
+ }
+
+ // Fallback for simple section URLs like #accelerators, #featured, etc.
+ const simpleSection = hash.substring(1);
+ if (simpleSection && !simpleSection.includes('=')) {
+ // Handle legacy #all URLs by redirecting to #accelerators
+ if (simpleSection === 'all') {
+ window.location.hash = 'accelerators';
+ return 'accelerators';
+ }
+ return simpleSection;
+ }
+
+ return "";
+};
+
+export const getUrlWithSection = (section: string): string => {
+ const currentHash = window.location.hash;
+ const params = new URLSearchParams(currentHash.substring(1));
+
+ if (section && section.trim()) {
+ params.set("section", encodeURIComponent(section.trim()));
+ } else {
+ params.delete("section");
+ }
+
+ const result = params.toString();
+ return result ? `#${result}` : "";
+};
+
+export const isValidSectionParam = (section: string): boolean => {
+ return typeof section === "string" && section.trim().length > 0;
+};
+
+export const updateUrlWithSection = (section: string): void => {
+ const newHash = getUrlWithSection(section);
+
+ if (newHash !== window.location.hash) {
+ const newUrl = newHash ? window.location.pathname + newHash : window.location.pathname;
+ window.history.pushState(null, "", newUrl);
+ }
+};
+
+export const combineUrlWithSection = (section: string, sortValue: string, keyword: string, filters: Record): string => {
+ const params = new URLSearchParams();
+
+ if (section && section.trim()) {
+ params.set("section", encodeURIComponent(section.trim()));
+ }
+
+ if (sortValue && sortParamMapping[sortValue]) {
+ params.set("sort", sortParamMapping[sortValue]);
+ }
+
+ if (keyword && keyword.trim()) {
+ params.set("keyword", encodeURIComponent(keyword.trim()));
+ }
+
+ Object.entries(filterParamMapping).forEach(([internalKey, urlKey]) => {
+ const filterValues = filters[internalKey];
+ if (filterValues && filterValues.length > 0) {
+ const encodedValues = filterValues.map(v => encodeURIComponent(v.trim())).join(',');
+ params.set(urlKey, encodedValues);
+ }
+ });
+
+ return `#${params.toString()}`;
+};
+
+export const updateUrlWithAllParamsAndSection = (section: string, sortValue: string, keyword: string, filters: Record): void => {
+ const newHash = combineUrlWithSection(section, sortValue, keyword, filters);
+ if (newHash !== window.location.hash) {
+ const newUrl = newHash ? window.location.pathname + newHash : window.location.pathname;
+ window.history.pushState(null, "", newUrl);
+ }
+};
\ No newline at end of file
diff --git a/code/src/utils/validateCardData.ts b/code/src/utils/validateCardData.ts
new file mode 100644
index 0000000..ec33900
--- /dev/null
+++ b/code/src/utils/validateCardData.ts
@@ -0,0 +1,62 @@
+type CardData = {
+ accelerator: string;
+ solutionPlays: string[];
+ solutionAreas: string[];
+ productsAndServices: string[];
+ assets?: { label: string; href: string }[];
+};
+
+export const validateCardData = (data: CardData) => {
+ // Validate required fields
+ if (!data.accelerator) {
+ throw new Error('Card data missing required field: accelerator');
+ }
+ if (!Array.isArray(data.solutionPlays)) {
+ throw new Error('Card data missing required field: solutionPlays (must be array)');
+ }
+ if (!Array.isArray(data.solutionAreas)) {
+ throw new Error('Card data missing required field: solutionAreas (must be array)');
+ }
+ if (!Array.isArray(data.productsAndServices)) {
+ throw new Error('Card data missing required field: productsAndServices (must be array)');
+ }
+
+ // Validate assets if present
+ if (data.assets) {
+ if (!Array.isArray(data.assets)) {
+ throw new Error('Card data assets must be an array');
+ }
+ data.assets.forEach((asset, index) => {
+ if (!asset.label) {
+ throw new Error(`Asset at index ${index} missing required field: label`);
+ }
+ if (!asset.href) {
+ throw new Error(`Asset at index ${index} missing required field: href`);
+ }
+ try {
+ new URL(asset.href);
+ } catch {
+ throw new Error(`Asset at index ${index} has invalid href: ${asset.href}`);
+ }
+ });
+ }
+
+ // Validate array contents
+ data.solutionPlays.forEach((item, index) => {
+ if (typeof item !== 'string') {
+ throw new Error(`Solution play at index ${index} must be a string`);
+ }
+ });
+
+ data.solutionAreas.forEach((item, index) => {
+ if (typeof item !== 'string') {
+ throw new Error(`Solution area at index ${index} must be a string`);
+ }
+ });
+
+ data.productsAndServices.forEach((item, index) => {
+ if (typeof item !== 'string') {
+ throw new Error(`Product/service at index ${index} must be a string`);
+ }
+ });
+};
\ No newline at end of file
diff --git a/code/src/vite-env.d.ts b/code/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/code/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/code/tailwind.config.js b/code/tailwind.config.js
new file mode 100644
index 0000000..b5106f7
--- /dev/null
+++ b/code/tailwind.config.js
@@ -0,0 +1,25 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: [
+ "./index.html",
+ "./src/**/*.{js,ts,jsx,tsx}",
+ ],
+ theme: {
+ extend: {
+ colors: {
+ 'neutral-1': 'var(--colorNeutralBackground1)',
+ 'neutral-2': 'var(--colorNeutralBackground2)',
+ 'neutral-3': 'var(--colorNeutralBackground3)',
+ 'neutral-stroke-1': 'var(--colorNeutralStroke1)',
+ 'neutral-stroke-2': 'var(--colorNeutralStroke2)',
+ 'neutral-foreground-1': 'var(--colorNeutralForeground1)',
+ 'neutral-foreground-2': 'var(--colorNeutralForeground2)',
+ 'neutral-foreground-3': 'var(--colorNeutralForeground3)',
+ 'neutral-foreground-disabled': 'var(--colorNeutralForegroundDisabled)',
+ 'brand-stroke': 'var(--colorBrandStroke1)',
+ 'brand-background': 'var(--colorBrandBackground)',
+ },
+ },
+ },
+ plugins: [],
+}
\ No newline at end of file
diff --git a/code/tsconfig.app.json b/code/tsconfig.app.json
new file mode 100644
index 0000000..227a6c6
--- /dev/null
+++ b/code/tsconfig.app.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2022",
+ "useDefineForClassFields": true,
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["src"]
+}
diff --git a/code/tsconfig.json b/code/tsconfig.json
new file mode 100644
index 0000000..1ffef60
--- /dev/null
+++ b/code/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "files": [],
+ "references": [
+ { "path": "./tsconfig.app.json" },
+ { "path": "./tsconfig.node.json" }
+ ]
+}
diff --git a/code/tsconfig.node.json b/code/tsconfig.node.json
new file mode 100644
index 0000000..f85a399
--- /dev/null
+++ b/code/tsconfig.node.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "target": "ES2023",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/code/vite.config.ts b/code/vite.config.ts
new file mode 100644
index 0000000..8efea65
--- /dev/null
+++ b/code/vite.config.ts
@@ -0,0 +1,31 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ base: './',
+ build: {
+ outDir: 'dist',
+ minify: 'esbuild',
+ rollupOptions: {
+ output: {
+ manualChunks: {
+ 'react-vendor': ['react', 'react-dom'],
+ },
+ },
+ },
+ target: 'es2015',
+ cssCodeSplit: true,
+ sourcemap: false,
+ },
+ resolve: {
+ alias: {
+ '@': '/src',
+ '@components': '/src/components',
+ '@assets': '/src/assets',
+ '@data': '/src/data',
+ '@utils': '/src/utils'
+ }
+ }
+})