From 98fa16bfc36b9ba8288eeb7cbfdbda27944e7eda Mon Sep 17 00:00:00 2001 From: DJP Date: Fri, 10 Apr 2026 12:31:43 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20complete=20Phase=201-2=20scaffold=20?= =?UTF-8?q?=E2=80=94=20backend,=20frontend,=20pipeline=20skeleton?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Full-stack Amazon AI Transcreation Platform with: - FastAPI backend (async, PostgreSQL, Redis, Celery) with 11 DB tables - JWT auth (SSO-ready abstract provider pattern) - 6-agent pipeline orchestrator with deterministic modules - Next.js 14 frontend with Amazon branding (Ember fonts, orange/dark theme) - Job wizard, monitoring HUD, output review, admin screens - 154 TM/reference files imported, 12 locales configured - Docker Compose for all services Agents 2-5 (TM retrieval, ranker, transcreator, compliance) are stubs pending Phase 3 LLM integration. Co-Authored-By: Claude Opus 4.6 --- .env.example | 19 + .gitignore | 75 +- Makefile | 35 + README.md | 179 + backend/Dockerfile | 19 + backend/alembic.ini | 40 + backend/alembic/env.py | 71 + backend/alembic/script.py.mako | 26 + backend/alembic/versions/.gitkeep | 0 .../versions/d4a016fd0817_initial_schema.py | 219 + backend/app/__init__.py | 0 backend/app/api/__init__.py | 0 backend/app/api/v1/__init__.py | 0 backend/app/api/v1/audit.py | 60 + backend/app/api/v1/clients.py | 105 + backend/app/api/v1/files.py | 179 + backend/app/api/v1/jobs.py | 206 + backend/app/api/v1/output.py | 84 + backend/app/api/v1/reports.py | 50 + backend/app/api/v1/router.py | 21 + backend/app/api/v1/users.py | 130 + backend/app/auth/__init__.py | 0 backend/app/auth/middleware.py | 33 + backend/app/auth/providers/__init__.py | 0 backend/app/auth/providers/base.py | 36 + backend/app/auth/providers/jwt_provider.py | 52 + backend/app/auth/router.py | 44 + backend/app/auth/schemas.py | 25 + backend/app/auth/service.py | 70 + backend/app/config.py | 23 + backend/app/dependencies.py | 82 + backend/app/llm/__init__.py | 0 backend/app/llm/client.py | 143 + backend/app/llm/token_tracker.py | 101 + backend/app/main.py | 63 + backend/app/models/__init__.py | 11 + backend/app/models/audit.py | 56 + backend/app/models/base.py | 30 + backend/app/models/client.py | 22 + backend/app/models/feedback.py | 43 + backend/app/models/files.py | 89 + backend/app/models/job.py | 143 + backend/app/models/output.py | 53 + backend/app/models/source.py | 30 + backend/app/models/user.py | 60 + backend/app/pipeline/__init__.py | 0 backend/app/pipeline/agents/__init__.py | 0 .../app/pipeline/agents/agent_1_validator.py | 106 + .../pipeline/agents/agent_2_tm_retrieval.py | 40 + backend/app/pipeline/agents/agent_3_ranker.py | 42 + .../pipeline/agents/agent_4_transcreator.py | 55 + .../app/pipeline/agents/agent_5_compliance.py | 52 + .../app/pipeline/agents/agent_6_formatter.py | 112 + backend/app/pipeline/agents/base.py | 62 + .../app/pipeline/agents/prompts/__init__.py | 0 backend/app/pipeline/contracts.py | 139 + backend/app/pipeline/modules/__init__.py | 0 .../app/pipeline/modules/blacklist_scanner.py | 108 + .../app/pipeline/modules/character_counter.py | 67 + .../pipeline/modules/date_format_validator.py | 121 + .../pipeline/modules/domain_substitutor.py | 110 + backend/app/pipeline/modules/excel_writer.py | 184 + .../pipeline/modules/line_break_normaliser.py | 67 + .../app/pipeline/modules/ref_file_loader.py | 177 + .../pipeline/modules/source_file_parser.py | 97 + .../app/pipeline/modules/tm_file_loader.py | 133 + backend/app/pipeline/orchestrator.py | 190 + backend/app/schemas/__init__.py | 0 backend/app/schemas/client.py | 29 + backend/app/schemas/common.py | 19 + backend/app/schemas/feedback.py | 27 + backend/app/schemas/files.py | 46 + backend/app/schemas/job.py | 94 + backend/app/schemas/output.py | 51 + backend/app/schemas/user.py | 38 + backend/app/services/__init__.py | 0 backend/app/services/audit_service.py | 77 + backend/app/services/feedback_service.py | 66 + backend/app/services/file_service.py | 234 + backend/app/services/job_service.py | 202 + backend/app/services/output_service.py | 104 + backend/app/services/report_service.py | 133 + backend/app/tasks/__init__.py | 0 backend/app/tasks/celery_app.py | 26 + backend/app/tasks/job_tasks.py | 258 + backend/app/ws/__init__.py | 0 backend/app/ws/handler.py | 47 + backend/app/ws/manager.py | 59 + backend/requirements.txt | 17 + backend/tests/__init__.py | 0 backend/tests/fixtures/__init__.py | 0 backend/tests/test_api/__init__.py | 0 backend/tests/test_auth/__init__.py | 0 backend/tests/test_modules/__init__.py | 0 backend/tests/test_pipeline/__init__.py | 0 docker-compose.yml | 71 + frontend/.env.local.example | 2 + frontend/.gitignore | 35 + frontend/Dockerfile | 15 + frontend/components.json | 16 + frontend/next.config.js | 9 + frontend/package-lock.json | 7873 +++++++++++++++++ frontend/package.json | 45 + frontend/postcss.config.js | 6 + frontend/public/fonts/Amazon-Ember-Medium.ttf | Bin 0 -> 162892 bytes frontend/public/fonts/AmazonEmber_Bd.ttf | Bin 0 -> 105504 bytes frontend/public/fonts/AmazonEmber_BdIt.ttf | Bin 0 -> 104176 bytes frontend/public/fonts/AmazonEmber_He.ttf | Bin 0 -> 100120 bytes frontend/public/fonts/AmazonEmber_Lt.ttf | Bin 0 -> 103336 bytes frontend/public/fonts/AmazonEmber_Rg.ttf | Bin 0 -> 105996 bytes frontend/public/fonts/AmazonEmber_RgIt.ttf | Bin 0 -> 104800 bytes frontend/src/app/admin/clients/page.tsx | 178 + .../src/app/admin/files/reference/page.tsx | 139 + frontend/src/app/admin/files/tm/page.tsx | 128 + frontend/src/app/admin/logs/page.tsx | 196 + frontend/src/app/admin/reports/page.tsx | 202 + frontend/src/app/admin/users/page.tsx | 121 + frontend/src/app/dashboard/layout.tsx | 11 + frontend/src/app/dashboard/page.tsx | 248 + frontend/src/app/globals.css | 175 + .../locale/[localeCode]/review/page.tsx | 192 + frontend/src/app/jobs/[jobId]/page.tsx | 196 + frontend/src/app/jobs/new/page.tsx | 92 + frontend/src/app/layout.tsx | 19 + frontend/src/app/login/page.tsx | 139 + frontend/src/app/page.tsx | 5 + frontend/src/components/admin/ClientForm.tsx | 90 + .../src/components/admin/FileUploader.tsx | 145 + frontend/src/components/admin/ReportChart.tsx | 110 + frontend/src/components/admin/UserTable.tsx | 107 + frontend/src/components/jobs/JobCard.tsx | 117 + .../jobs/JobWizard/StepConfigure.tsx | 275 + .../components/jobs/JobWizard/StepReview.tsx | 310 + .../components/jobs/JobWizard/StepUpload.tsx | 311 + .../jobs/JobWizard/WizardStepper.tsx | 69 + .../jobs/MonitoringHUD/LocaleInstanceCard.tsx | 107 + .../jobs/MonitoringHUD/ProgressBar.tsx | 31 + .../jobs/OutputPreview/ConfidenceBadge.tsx | 32 + .../jobs/OutputPreview/FeedbackButtons.tsx | 117 + .../jobs/OutputPreview/OutputRowCard.tsx | 102 + .../jobs/OutputPreview/RationaleExpander.tsx | 40 + frontend/src/components/layout/AppShell.tsx | 125 + frontend/src/components/layout/Sidebar.tsx | 167 + frontend/src/components/ui/badge.tsx | 35 + frontend/src/components/ui/button.tsx | 57 + frontend/src/components/ui/card.tsx | 78 + frontend/src/components/ui/checkbox.tsx | 29 + frontend/src/components/ui/collapsible.tsx | 9 + frontend/src/components/ui/dialog.tsx | 118 + frontend/src/components/ui/dropdown-menu.tsx | 200 + frontend/src/components/ui/input.tsx | 24 + frontend/src/components/ui/label.tsx | 25 + frontend/src/components/ui/progress.tsx | 27 + frontend/src/components/ui/radio-group.tsx | 43 + frontend/src/components/ui/select.tsx | 157 + frontend/src/components/ui/separator.tsx | 31 + frontend/src/components/ui/skeleton.tsx | 18 + frontend/src/components/ui/table.tsx | 123 + frontend/src/components/ui/tabs.tsx | 54 + frontend/src/components/ui/textarea.tsx | 23 + frontend/src/components/ui/tooltip.tsx | 27 + frontend/src/hooks/useAuth.ts | 67 + frontend/src/hooks/useFileUpload.ts | 122 + frontend/src/hooks/useJobs.ts | 206 + frontend/src/hooks/useWebSocket.ts | 70 + frontend/src/lib/api.ts | 272 + frontend/src/lib/auth.ts | 59 + frontend/src/lib/types.ts | 264 + frontend/src/lib/utils.ts | 45 + frontend/src/lib/ws.ts | 110 + frontend/tailwind.config.ts | 81 + frontend/tsconfig.json | 26 + scripts/__init__.py | 0 scripts/tm_format_migrator.py | 243 + scripts/validate_tm_files.py | 204 + seed/__init__.py | 0 seed/create_default_client.py | 224 + seed/create_test_users.py | 97 + seed/import_reference_files.py | 307 + storage/.gitkeep | 0 180 files changed, 21920 insertions(+), 39 deletions(-) create mode 100644 .env.example create mode 100644 Makefile create mode 100644 README.md create mode 100644 backend/Dockerfile create mode 100644 backend/alembic.ini create mode 100644 backend/alembic/env.py create mode 100644 backend/alembic/script.py.mako create mode 100644 backend/alembic/versions/.gitkeep create mode 100644 backend/alembic/versions/d4a016fd0817_initial_schema.py create mode 100644 backend/app/__init__.py create mode 100644 backend/app/api/__init__.py create mode 100644 backend/app/api/v1/__init__.py create mode 100644 backend/app/api/v1/audit.py create mode 100644 backend/app/api/v1/clients.py create mode 100644 backend/app/api/v1/files.py create mode 100644 backend/app/api/v1/jobs.py create mode 100644 backend/app/api/v1/output.py create mode 100644 backend/app/api/v1/reports.py create mode 100644 backend/app/api/v1/router.py create mode 100644 backend/app/api/v1/users.py create mode 100644 backend/app/auth/__init__.py create mode 100644 backend/app/auth/middleware.py create mode 100644 backend/app/auth/providers/__init__.py create mode 100644 backend/app/auth/providers/base.py create mode 100644 backend/app/auth/providers/jwt_provider.py create mode 100644 backend/app/auth/router.py create mode 100644 backend/app/auth/schemas.py create mode 100644 backend/app/auth/service.py create mode 100644 backend/app/config.py create mode 100644 backend/app/dependencies.py create mode 100644 backend/app/llm/__init__.py create mode 100644 backend/app/llm/client.py create mode 100644 backend/app/llm/token_tracker.py create mode 100644 backend/app/main.py create mode 100644 backend/app/models/__init__.py create mode 100644 backend/app/models/audit.py create mode 100644 backend/app/models/base.py create mode 100644 backend/app/models/client.py create mode 100644 backend/app/models/feedback.py create mode 100644 backend/app/models/files.py create mode 100644 backend/app/models/job.py create mode 100644 backend/app/models/output.py create mode 100644 backend/app/models/source.py create mode 100644 backend/app/models/user.py create mode 100644 backend/app/pipeline/__init__.py create mode 100644 backend/app/pipeline/agents/__init__.py create mode 100644 backend/app/pipeline/agents/agent_1_validator.py create mode 100644 backend/app/pipeline/agents/agent_2_tm_retrieval.py create mode 100644 backend/app/pipeline/agents/agent_3_ranker.py create mode 100644 backend/app/pipeline/agents/agent_4_transcreator.py create mode 100644 backend/app/pipeline/agents/agent_5_compliance.py create mode 100644 backend/app/pipeline/agents/agent_6_formatter.py create mode 100644 backend/app/pipeline/agents/base.py create mode 100644 backend/app/pipeline/agents/prompts/__init__.py create mode 100644 backend/app/pipeline/contracts.py create mode 100644 backend/app/pipeline/modules/__init__.py create mode 100644 backend/app/pipeline/modules/blacklist_scanner.py create mode 100644 backend/app/pipeline/modules/character_counter.py create mode 100644 backend/app/pipeline/modules/date_format_validator.py create mode 100644 backend/app/pipeline/modules/domain_substitutor.py create mode 100644 backend/app/pipeline/modules/excel_writer.py create mode 100644 backend/app/pipeline/modules/line_break_normaliser.py create mode 100644 backend/app/pipeline/modules/ref_file_loader.py create mode 100644 backend/app/pipeline/modules/source_file_parser.py create mode 100644 backend/app/pipeline/modules/tm_file_loader.py create mode 100644 backend/app/pipeline/orchestrator.py create mode 100644 backend/app/schemas/__init__.py create mode 100644 backend/app/schemas/client.py create mode 100644 backend/app/schemas/common.py create mode 100644 backend/app/schemas/feedback.py create mode 100644 backend/app/schemas/files.py create mode 100644 backend/app/schemas/job.py create mode 100644 backend/app/schemas/output.py create mode 100644 backend/app/schemas/user.py create mode 100644 backend/app/services/__init__.py create mode 100644 backend/app/services/audit_service.py create mode 100644 backend/app/services/feedback_service.py create mode 100644 backend/app/services/file_service.py create mode 100644 backend/app/services/job_service.py create mode 100644 backend/app/services/output_service.py create mode 100644 backend/app/services/report_service.py create mode 100644 backend/app/tasks/__init__.py create mode 100644 backend/app/tasks/celery_app.py create mode 100644 backend/app/tasks/job_tasks.py create mode 100644 backend/app/ws/__init__.py create mode 100644 backend/app/ws/handler.py create mode 100644 backend/app/ws/manager.py create mode 100644 backend/requirements.txt create mode 100644 backend/tests/__init__.py create mode 100644 backend/tests/fixtures/__init__.py create mode 100644 backend/tests/test_api/__init__.py create mode 100644 backend/tests/test_auth/__init__.py create mode 100644 backend/tests/test_modules/__init__.py create mode 100644 backend/tests/test_pipeline/__init__.py create mode 100644 docker-compose.yml create mode 100644 frontend/.env.local.example create mode 100644 frontend/.gitignore create mode 100644 frontend/Dockerfile create mode 100644 frontend/components.json create mode 100644 frontend/next.config.js create mode 100644 frontend/package-lock.json create mode 100644 frontend/package.json create mode 100644 frontend/postcss.config.js create mode 100644 frontend/public/fonts/Amazon-Ember-Medium.ttf create mode 100644 frontend/public/fonts/AmazonEmber_Bd.ttf create mode 100644 frontend/public/fonts/AmazonEmber_BdIt.ttf create mode 100644 frontend/public/fonts/AmazonEmber_He.ttf create mode 100644 frontend/public/fonts/AmazonEmber_Lt.ttf create mode 100644 frontend/public/fonts/AmazonEmber_Rg.ttf create mode 100644 frontend/public/fonts/AmazonEmber_RgIt.ttf create mode 100644 frontend/src/app/admin/clients/page.tsx create mode 100644 frontend/src/app/admin/files/reference/page.tsx create mode 100644 frontend/src/app/admin/files/tm/page.tsx create mode 100644 frontend/src/app/admin/logs/page.tsx create mode 100644 frontend/src/app/admin/reports/page.tsx create mode 100644 frontend/src/app/admin/users/page.tsx create mode 100644 frontend/src/app/dashboard/layout.tsx create mode 100644 frontend/src/app/dashboard/page.tsx create mode 100644 frontend/src/app/globals.css create mode 100644 frontend/src/app/jobs/[jobId]/locale/[localeCode]/review/page.tsx create mode 100644 frontend/src/app/jobs/[jobId]/page.tsx create mode 100644 frontend/src/app/jobs/new/page.tsx create mode 100644 frontend/src/app/layout.tsx create mode 100644 frontend/src/app/login/page.tsx create mode 100644 frontend/src/app/page.tsx create mode 100644 frontend/src/components/admin/ClientForm.tsx create mode 100644 frontend/src/components/admin/FileUploader.tsx create mode 100644 frontend/src/components/admin/ReportChart.tsx create mode 100644 frontend/src/components/admin/UserTable.tsx create mode 100644 frontend/src/components/jobs/JobCard.tsx create mode 100644 frontend/src/components/jobs/JobWizard/StepConfigure.tsx create mode 100644 frontend/src/components/jobs/JobWizard/StepReview.tsx create mode 100644 frontend/src/components/jobs/JobWizard/StepUpload.tsx create mode 100644 frontend/src/components/jobs/JobWizard/WizardStepper.tsx create mode 100644 frontend/src/components/jobs/MonitoringHUD/LocaleInstanceCard.tsx create mode 100644 frontend/src/components/jobs/MonitoringHUD/ProgressBar.tsx create mode 100644 frontend/src/components/jobs/OutputPreview/ConfidenceBadge.tsx create mode 100644 frontend/src/components/jobs/OutputPreview/FeedbackButtons.tsx create mode 100644 frontend/src/components/jobs/OutputPreview/OutputRowCard.tsx create mode 100644 frontend/src/components/jobs/OutputPreview/RationaleExpander.tsx create mode 100644 frontend/src/components/layout/AppShell.tsx create mode 100644 frontend/src/components/layout/Sidebar.tsx create mode 100644 frontend/src/components/ui/badge.tsx create mode 100644 frontend/src/components/ui/button.tsx create mode 100644 frontend/src/components/ui/card.tsx create mode 100644 frontend/src/components/ui/checkbox.tsx create mode 100644 frontend/src/components/ui/collapsible.tsx create mode 100644 frontend/src/components/ui/dialog.tsx create mode 100644 frontend/src/components/ui/dropdown-menu.tsx create mode 100644 frontend/src/components/ui/input.tsx create mode 100644 frontend/src/components/ui/label.tsx create mode 100644 frontend/src/components/ui/progress.tsx create mode 100644 frontend/src/components/ui/radio-group.tsx create mode 100644 frontend/src/components/ui/select.tsx create mode 100644 frontend/src/components/ui/separator.tsx create mode 100644 frontend/src/components/ui/skeleton.tsx create mode 100644 frontend/src/components/ui/table.tsx create mode 100644 frontend/src/components/ui/tabs.tsx create mode 100644 frontend/src/components/ui/textarea.tsx create mode 100644 frontend/src/components/ui/tooltip.tsx create mode 100644 frontend/src/hooks/useAuth.ts create mode 100644 frontend/src/hooks/useFileUpload.ts create mode 100644 frontend/src/hooks/useJobs.ts create mode 100644 frontend/src/hooks/useWebSocket.ts create mode 100644 frontend/src/lib/api.ts create mode 100644 frontend/src/lib/auth.ts create mode 100644 frontend/src/lib/types.ts create mode 100644 frontend/src/lib/utils.ts create mode 100644 frontend/src/lib/ws.ts create mode 100644 frontend/tailwind.config.ts create mode 100644 frontend/tsconfig.json create mode 100644 scripts/__init__.py create mode 100644 scripts/tm_format_migrator.py create mode 100644 scripts/validate_tm_files.py create mode 100644 seed/__init__.py create mode 100644 seed/create_default_client.py create mode 100644 seed/create_test_users.py create mode 100644 seed/import_reference_files.py create mode 100644 storage/.gitkeep diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..827d7de --- /dev/null +++ b/.env.example @@ -0,0 +1,19 @@ +# Database +DATABASE_URL=postgresql+asyncpg://transcreation:transcreation@db:5432/transcreation + +# Redis +REDIS_URL=redis://redis:6379/0 + +# Anthropic +ANTHROPIC_API_KEY=sk-ant-REPLACE_ME + +# Auth +JWT_SECRET_KEY=CHANGE_ME_TO_A_RANDOM_SECRET +JWT_ALGORITHM=HS256 +JWT_EXPIRY_HOURS=8 + +# Storage +STORAGE_ROOT=/storage + +# LLM +LLM_MODEL=claude-sonnet-4-20250514 diff --git a/.gitignore b/.gitignore index b24d71e..c205c76 100644 --- a/.gitignore +++ b/.gitignore @@ -1,50 +1,47 @@ -# These are some examples of commonly ignored file patterns. -# You should customize this list as applicable to your project. -# Learn more about .gitignore: -# https://www.atlassian.com/git/tutorials/saving-changes/gitignore - -# Node artifact files -node_modules/ -dist/ - -# Compiled Java class files -*.class - -# Compiled Python bytecode +# Python +__pycache__/ *.py[cod] - -# Log files -*.log - -# Package files -*.jar - -# Maven -target/ +*$py.class +*.so +*.egg-info/ dist/ +build/ +.eggs/ +venv/ +.venv/ -# JetBrains IDE +# Environment +.env +.env.local +.env.*.local + +# IDE +.vscode/ .idea/ +*.swp +*.swo -# Unit test reports -TEST*.xml +# Node +node_modules/ +.next/ +out/ -# Generated by MacOS +# Storage (keep structure, ignore uploaded files) +storage/* +!storage/.gitkeep + +# OS .DS_Store - -# Generated by Windows Thumbs.db -# Applications -*.app -*.exe -*.war +# Docker +docker-compose.override.yml -# Large media files -*.mp4 -*.tiff -*.avi -*.flv -*.mov -*.wmv +# Test +.coverage +htmlcov/ +.pytest_cache/ +# Misc +*.log +*.bak diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..728c537 --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +.PHONY: up down build migrate seed test shell logs + +up: + docker compose up -d + +down: + docker compose down + +build: + docker compose build + +migrate: + docker compose exec backend alembic upgrade head + +seed: + docker compose exec backend python -m seed.create_default_client + docker compose exec backend python -m seed.create_test_users + +test: + docker compose exec backend python -m pytest tests/ -v + +shell: + docker compose exec backend bash + +logs: + docker compose logs -f + +restart: + docker compose restart backend celery_worker + +db-shell: + docker compose exec db psql -U transcreation + +redis-cli: + docker compose exec redis redis-cli diff --git a/README.md b/README.md new file mode 100644 index 0000000..07d4242 --- /dev/null +++ b/README.md @@ -0,0 +1,179 @@ +# Amazon AI Transcreation Platform + +An AI-powered platform for transcreating marketing content across European locales. Built for Amazon's creative workflows, it combines Claude LLM capabilities with translation memory, glossaries, and brand voice profiles to produce culturally adapted copy at scale. + +## Tech Stack + +| Layer | Technology | +|-------------|---------------------------------------------| +| Frontend | Next.js 14, React 18, Tailwind CSS, Radix UI | +| Backend | FastAPI, Python 3.12, SQLAlchemy 2 (async) | +| Database | PostgreSQL 16 | +| Cache/Queue | Redis 7, Celery | +| LLM | Anthropic Claude (via API) | +| Infra | Docker, Docker Compose | + +## Prerequisites + +- [Docker](https://docs.docker.com/get-docker/) and Docker Compose v2 +- An [Anthropic API key](https://console.anthropic.com/) for Claude access + +## Quick Start + +```bash +# 1. Clone the repository +git clone amazon-transcreation +cd amazon-transcreation + +# 2. Configure environment +cp .env.example .env +# Edit .env and set ANTHROPIC_API_KEY, JWT_SECRET_KEY + +# 3. Start all services +docker compose up -d + +# 4. Run database migrations +make migrate + +# 5. Seed the database with the Amazon client +make seed + +# 6. Open the app +# Backend API docs: http://localhost:8000/docs +# Frontend: http://localhost:3000 +``` + +## Architecture + +``` ++---------------------------------------------------------------+ +| Frontend (Next.js) | +| Dashboard | Job Builder | Review UI | TM Manager | ++-------------------------------+-------------------------------+ + | REST + WebSocket | ++-------------------------------+-------------------------------+ +| Backend (FastAPI) | +| Auth | Jobs API | TM API | Files API | WebSocket | ++-------------------------------+-------------------------------+ + | | ++--------------+------+ +-------+----------------------------+ +| PostgreSQL | | Celery Workers | +| - clients | | - LLM transcreation tasks | +| - users | | - TM lookup & scoring | +| - jobs | | - File processing | +| - source_lines | +------------------------------------+ +| - output_rows | | +| - feedback | +----------+-------------------------+ +| - tm_file_registry| | Claude API (Anthropic) | +| - reference_files | | - Transcreation generation | +| - audit_logs | | - Quality scoring | ++---------------------+ +------------------------------------+ + | ++---------------------+ +| Storage (volume) | +| - TM files (JSONL) | +| - Reference files | ++---------------------+ +``` + +## Development + +### Backend + +```bash +# Shell into the backend container +make shell + +# Run tests +make test + +# View logs +make logs + +# Access the database +make db-shell +``` + +### Frontend + +```bash +cd frontend +npm install +npm run dev +``` + +The frontend dev server runs on port 3000 and proxies API requests to the backend on port 8000. + +### Running Tests + +```bash +# Backend tests (inside Docker) +make test + +# Frontend tests +cd frontend && npm run lint +``` + +## API Documentation + +FastAPI auto-generates interactive API documentation: + +- **Swagger UI**: [http://localhost:8000/docs](http://localhost:8000/docs) +- **ReDoc**: [http://localhost:8000/redoc](http://localhost:8000/redoc) + +## Project Structure + +``` +amazon-transcreation/ +├── backend/ +│ ├── alembic/ # Database migrations +│ ├── app/ +│ │ ├── api/v1/ # REST API routes +│ │ ├── models/ # SQLAlchemy models +│ │ ├── schemas/ # Pydantic request/response schemas +│ │ ├── services/ # Business logic +│ │ ├── tasks/ # Celery async tasks +│ │ ├── ws/ # WebSocket handlers +│ │ ├── config.py # Settings from environment +│ │ ├── dependencies.py # FastAPI dependency injection +│ │ └── main.py # Application factory +│ ├── Dockerfile +│ └── requirements.txt +├── frontend/ +│ ├── public/ # Static assets, fonts +│ ├── src/ # Next.js pages and components +│ ├── Dockerfile +│ └── package.json +├── scripts/ +│ ├── tm_format_migrator.py # Convert compact TM to multi-field JSONL +│ └── validate_tm_files.py # Audit TM files for format and coverage +├── seed/ +│ ├── create_default_client.py # Seed Amazon client + voice profiles +│ └── import_reference_files.py # Import TMs and refs to storage/ +├── storage/ # Mounted volume for TM and reference files +├── .env.example # Environment variable template +├── docker-compose.yml # Service orchestration +├── Makefile # Development shortcuts +└── README.md +``` + +## Key Concepts + +- **Client**: An organization (e.g., Amazon) with voice profiles, supported locales, and channel configurations stored as JSON settings. +- **Voice Profile**: Brand personality (Retail, Prime, Brand) that guides tone and style during transcreation. +- **Channel**: A content distribution context (Mass TV, Onsite, etc.) with its own translation memory. +- **Translation Memory (TM)**: JSONL files of previously approved source/target pairs, used for context and consistency. +- **Reference Files**: Glossaries, blacklists, date/percent format guides, and locale-specific considerations that constrain the LLM output. + +## Environment Variables + +| Variable | Description | Default | +|---------------------|--------------------------------------|------------------------------| +| `DATABASE_URL` | PostgreSQL async connection string | `postgresql+asyncpg://...` | +| `REDIS_URL` | Redis connection string | `redis://redis:6379/0` | +| `ANTHROPIC_API_KEY` | Anthropic API key for Claude | (required) | +| `JWT_SECRET_KEY` | Secret for signing JWT tokens | (required, change default) | +| `JWT_ALGORITHM` | JWT signing algorithm | `HS256` | +| `JWT_EXPIRY_HOURS` | Token expiry in hours | `8` | +| `STORAGE_ROOT` | Root path for file storage | `/storage` | +| `LLM_MODEL` | Claude model identifier | `claude-sonnet-4-20250514` | diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..9bf2a75 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.12-slim + +WORKDIR /app + +# Install system dependencies +RUN apt-get update && \ + apt-get install -y --no-install-recommends gcc libpq-dev && \ + rm -rf /var/lib/apt/lists/* + +# Install Python dependencies +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Copy application code +COPY . . + +EXPOSE 8000 + +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/backend/alembic.ini b/backend/alembic.ini new file mode 100644 index 0000000..bed1805 --- /dev/null +++ b/backend/alembic.ini @@ -0,0 +1,40 @@ +[alembic] +script_location = alembic +prepend_sys_path = . +sqlalchemy.url = driver://user:pass@localhost/dbname + +[post_write_hooks] + +[loggers] +keys = root,sqlalchemy,alembic + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = WARN +handlers = console +qualname = + +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine + +[logger_alembic] +level = INFO +handlers = +qualname = alembic + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/backend/alembic/env.py b/backend/alembic/env.py new file mode 100644 index 0000000..8da2359 --- /dev/null +++ b/backend/alembic/env.py @@ -0,0 +1,71 @@ +import asyncio +from logging.config import fileConfig + +from alembic import context +from sqlalchemy import pool +from sqlalchemy.engine import Connection +from sqlalchemy.ext.asyncio import async_engine_from_config + +from app.config import settings + +# Import all models so Alembic can discover them +from app.models import Base # noqa: F401 + +# Alembic Config object +config = context.config + +# Set the SQLAlchemy URL from settings +config.set_main_option("sqlalchemy.url", settings.DATABASE_URL) + +# Logging configuration +if config.config_file_name is not None: + fileConfig(config.config_file_name) + +# MetaData for autogenerate support +target_metadata = Base.metadata + + +def run_migrations_offline() -> None: + """Run migrations in 'offline' mode.""" + url = config.get_main_option("sqlalchemy.url") + context.configure( + url=url, + target_metadata=target_metadata, + literal_binds=True, + dialect_opts={"paramstyle": "named"}, + ) + + with context.begin_transaction(): + context.run_migrations() + + +def do_run_migrations(connection: Connection) -> None: + context.configure(connection=connection, target_metadata=target_metadata) + + with context.begin_transaction(): + context.run_migrations() + + +async def run_async_migrations() -> None: + """Run migrations in 'online' mode with async engine.""" + connectable = async_engine_from_config( + config.get_section(config.config_ini_section, {}), + prefix="sqlalchemy.", + poolclass=pool.NullPool, + ) + + async with connectable.connect() as connection: + await connection.run_sync(do_run_migrations) + + await connectable.dispose() + + +def run_migrations_online() -> None: + """Run migrations in 'online' mode.""" + asyncio.run(run_async_migrations()) + + +if context.is_offline_mode(): + run_migrations_offline() +else: + run_migrations_online() diff --git a/backend/alembic/script.py.mako b/backend/alembic/script.py.mako new file mode 100644 index 0000000..fbc4b07 --- /dev/null +++ b/backend/alembic/script.py.mako @@ -0,0 +1,26 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision | comma,n} +Create Date: ${create_date} + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +# revision identifiers, used by Alembic. +revision: str = ${repr(up_revision)} +down_revision: Union[str, None] = ${repr(down_revision)} +branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)} +depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)} + + +def upgrade() -> None: + ${upgrades if upgrades else "pass"} + + +def downgrade() -> None: + ${downgrades if downgrades else "pass"} diff --git a/backend/alembic/versions/.gitkeep b/backend/alembic/versions/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/backend/alembic/versions/d4a016fd0817_initial_schema.py b/backend/alembic/versions/d4a016fd0817_initial_schema.py new file mode 100644 index 0000000..ba15d22 --- /dev/null +++ b/backend/alembic/versions/d4a016fd0817_initial_schema.py @@ -0,0 +1,219 @@ +"""initial_schema + +Revision ID: d4a016fd0817 +Revises: +Create Date: 2026-04-10 16:25:45.318282 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'd4a016fd0817' +down_revision: Union[str, None] = None +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('clients', + sa.Column('id', sa.Uuid(), nullable=False), + sa.Column('name', sa.String(length=255), nullable=False), + sa.Column('settings', sa.JSON(), nullable=True), + sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('users', + sa.Column('id', sa.Uuid(), nullable=False), + sa.Column('email', sa.String(length=255), nullable=False), + sa.Column('name', sa.String(length=255), nullable=False), + sa.Column('password_hash', sa.String(length=255), nullable=False), + sa.Column('role', sa.Enum('admin', 'tm_manager', 'reviewer', name='user_role', create_constraint=True), nullable=False), + sa.Column('status', sa.Enum('active', 'inactive', name='user_status', create_constraint=True), nullable=False), + sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('email') + ) + op.create_table('audit_logs', + sa.Column('id', sa.Uuid(), nullable=False), + sa.Column('user_id', sa.Uuid(), nullable=True), + sa.Column('action', sa.String(length=100), nullable=False), + sa.Column('entity_type', sa.String(length=100), nullable=False), + sa.Column('entity_id', sa.String(length=255), nullable=False), + sa.Column('details', sa.JSON(), nullable=True), + sa.Column('timestamp', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.Column('ip_address', sa.String(length=45), nullable=True), + sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('jobs', + sa.Column('id', sa.Uuid(), nullable=False), + sa.Column('client_id', sa.Uuid(), nullable=False), + sa.Column('created_by', sa.Uuid(), nullable=False), + sa.Column('job_ref', sa.String(length=100), nullable=True), + sa.Column('campaign_name', sa.String(length=255), nullable=False), + sa.Column('programme', sa.Enum('retail', 'prime', 'brand', name='programme_type', create_constraint=True), nullable=False), + sa.Column('channel', sa.String(length=100), nullable=False), + sa.Column('sub_channel', sa.String(length=100), nullable=True), + sa.Column('context_prompt', sa.Text(), nullable=True), + sa.Column('job_type', sa.Enum('main', 'derived', name='job_type', create_constraint=True), nullable=False), + sa.Column('parent_job_id', sa.Uuid(), nullable=True), + sa.Column('status', sa.Enum('created', 'validating', 'queued', 'running', 'partial_complete', 'complete', 'error', 'exported', name='job_status', create_constraint=True), nullable=False), + sa.Column('total_token_usage', sa.Integer(), nullable=False), + sa.Column('total_estimated_cost', sa.Float(), nullable=False), + sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.ForeignKeyConstraint(['client_id'], ['clients.id'], ondelete='CASCADE'), + sa.ForeignKeyConstraint(['created_by'], ['users.id'], ), + sa.ForeignKeyConstraint(['parent_job_id'], ['jobs.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('reference_files', + sa.Column('id', sa.Uuid(), nullable=False), + sa.Column('client_id', sa.Uuid(), nullable=False), + sa.Column('file_type', sa.Enum('glossary', 'blacklist', 'tov_global', 'tov_supplement', 'locale_considerations', 'date_pct_formats', name='reference_file_type', create_constraint=True), nullable=False), + sa.Column('locale_scope', sa.String(length=10), nullable=False), + sa.Column('filename', sa.String(length=255), nullable=False), + sa.Column('file_path', sa.String(length=500), nullable=False), + sa.Column('uploaded_by', sa.Uuid(), nullable=True), + sa.Column('uploaded_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.Column('last_updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.Column('version', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['client_id'], ['clients.id'], ondelete='CASCADE'), + sa.ForeignKeyConstraint(['uploaded_by'], ['users.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('tm_file_registry', + sa.Column('id', sa.Uuid(), nullable=False), + sa.Column('client_id', sa.Uuid(), nullable=False), + sa.Column('locale_code', sa.String(length=10), nullable=False), + sa.Column('channel', sa.String(length=100), nullable=False), + sa.Column('filename', sa.String(length=255), nullable=False), + sa.Column('file_path', sa.String(length=500), nullable=False), + sa.Column('segment_count', sa.Integer(), nullable=False), + sa.Column('uploaded_by', sa.Uuid(), nullable=True), + sa.Column('uploaded_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.Column('last_updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.Column('version', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['client_id'], ['clients.id'], ondelete='CASCADE'), + sa.ForeignKeyConstraint(['uploaded_by'], ['users.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('user_clients', + sa.Column('user_id', sa.Uuid(), nullable=False), + sa.Column('client_id', sa.Uuid(), nullable=False), + sa.Column('role_override', sa.String(length=50), nullable=True), + sa.ForeignKeyConstraint(['client_id'], ['clients.id'], ondelete='CASCADE'), + sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('user_id', 'client_id') + ) + op.create_table('locale_instances', + sa.Column('id', sa.Uuid(), nullable=False), + sa.Column('job_id', sa.Uuid(), nullable=False), + sa.Column('locale_code', sa.String(length=10), nullable=False), + sa.Column('locale_type', sa.Enum('main', 'derived', name='locale_type', create_constraint=True), nullable=False), + sa.Column('status', sa.Enum('queued', 'running', 'complete', 'error', name='locale_status', create_constraint=True), nullable=False), + sa.Column('started_at', sa.DateTime(timezone=True), nullable=True), + sa.Column('completed_at', sa.DateTime(timezone=True), nullable=True), + sa.Column('token_usage', sa.Integer(), nullable=False), + sa.Column('estimated_cost', sa.Float(), nullable=False), + sa.Column('output_file_path', sa.String(length=500), nullable=True), + sa.Column('error_log', sa.Text(), nullable=True), + sa.Column('tm_files_loaded', sa.JSON(), nullable=True), + sa.Column('ref_files_loaded', sa.JSON(), nullable=True), + sa.Column('agent_version', sa.String(length=50), nullable=True), + sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.ForeignKeyConstraint(['job_id'], ['jobs.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('source_lines', + sa.Column('id', sa.Uuid(), nullable=False), + sa.Column('job_id', sa.Uuid(), nullable=False), + sa.Column('row_order', sa.Integer(), nullable=False), + sa.Column('en_gb', sa.Text(), nullable=False), + sa.Column('copy_type', sa.String(length=100), nullable=True), + sa.Column('creative_guidance', sa.Text(), nullable=True), + sa.Column('visual_ref', sa.String(length=500), nullable=True), + sa.Column('char_limit', sa.String(length=50), nullable=True), + sa.Column('is_display_format', sa.Boolean(), nullable=False), + sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.ForeignKeyConstraint(['job_id'], ['jobs.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('output_rows', + sa.Column('id', sa.Uuid(), nullable=False), + sa.Column('instance_id', sa.Uuid(), nullable=False), + sa.Column('line_id', sa.Uuid(), nullable=False), + sa.Column('row_order', sa.Integer(), nullable=False), + sa.Column('confidence_tier', sa.Enum('high', 'moderate', 'low', name='confidence_tier', create_constraint=True), nullable=False), + sa.Column('option_1', sa.Text(), nullable=False), + sa.Column('backtranslation_1', sa.Text(), nullable=False), + sa.Column('rationale_1', sa.Text(), nullable=False), + sa.Column('option_2', sa.Text(), nullable=True), + sa.Column('backtranslation_2', sa.Text(), nullable=True), + sa.Column('rationale_2', sa.Text(), nullable=True), + sa.Column('option_3', sa.Text(), nullable=True), + sa.Column('backtranslation_3', sa.Text(), nullable=True), + sa.Column('rationale_3', sa.Text(), nullable=True), + sa.Column('tm_entries_cited', sa.JSON(), nullable=True), + sa.Column('winning_seg_key', sa.String(length=255), nullable=True), + sa.Column('character_count_option_1', sa.Integer(), nullable=True), + sa.Column('character_count_option_2', sa.Integer(), nullable=True), + sa.Column('character_count_option_3', sa.Integer(), nullable=True), + sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.ForeignKeyConstraint(['instance_id'], ['locale_instances.id'], ondelete='CASCADE'), + sa.ForeignKeyConstraint(['line_id'], ['source_lines.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('token_usage_logs', + sa.Column('id', sa.Uuid(), nullable=False), + sa.Column('instance_id', sa.Uuid(), nullable=False), + sa.Column('agent_name', sa.String(length=100), nullable=False), + sa.Column('model', sa.String(length=100), nullable=False), + sa.Column('input_tokens', sa.Integer(), nullable=False), + sa.Column('output_tokens', sa.Integer(), nullable=False), + sa.Column('total_tokens', sa.Integer(), nullable=False), + sa.Column('estimated_cost_usd', sa.Float(), nullable=False), + sa.Column('timestamp', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.ForeignKeyConstraint(['instance_id'], ['locale_instances.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('feedback', + sa.Column('id', sa.Uuid(), nullable=False), + sa.Column('output_id', sa.Uuid(), nullable=False), + sa.Column('user_id', sa.Uuid(), nullable=False), + sa.Column('option_column', sa.Integer(), nullable=False), + sa.Column('flag_type', sa.Enum('approved', 'needs_revision', 'comment', name='flag_type', create_constraint=True), nullable=False), + sa.Column('comment', sa.Text(), nullable=True), + sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), + sa.ForeignKeyConstraint(['output_id'], ['output_rows.id'], ondelete='CASCADE'), + sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('feedback') + op.drop_table('token_usage_logs') + op.drop_table('output_rows') + op.drop_table('source_lines') + op.drop_table('locale_instances') + op.drop_table('user_clients') + op.drop_table('tm_file_registry') + op.drop_table('reference_files') + op.drop_table('jobs') + op.drop_table('audit_logs') + op.drop_table('users') + op.drop_table('clients') + # ### end Alembic commands ### diff --git a/backend/app/__init__.py b/backend/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/api/__init__.py b/backend/app/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/api/v1/__init__.py b/backend/app/api/v1/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/api/v1/audit.py b/backend/app/api/v1/audit.py new file mode 100644 index 0000000..dd80372 --- /dev/null +++ b/backend/app/api/v1/audit.py @@ -0,0 +1,60 @@ +from datetime import datetime +from typing import Any +from uuid import UUID + +from fastapi import APIRouter, Depends, Query +from sqlalchemy.ext.asyncio import AsyncSession + +from app.dependencies import get_db, require_role +from app.services.audit_service import AuditService + +router = APIRouter(prefix="/audit", tags=["audit"]) +audit_service = AuditService() + + +@router.get("/logs") +async def list_audit_logs( + user_id: UUID | None = Query(None), + action: str | None = Query(None), + entity_type: str | None = Query(None), + entity_id: str | None = Query(None), + date_from: datetime | None = Query(None), + date_to: datetime | None = Query(None), + page: int = Query(1, ge=1), + page_size: int = Query(50, ge=1, le=200), + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(require_role(["admin"])), +) -> dict[str, Any]: + """List audit logs with filters (admin only).""" + logs, total = await audit_service.list_logs( + db, + user_id=user_id, + action=action, + entity_type=entity_type, + entity_id=entity_id, + date_from=date_from, + date_to=date_to, + page=page, + page_size=page_size, + ) + + pages = (total + page_size - 1) // page_size if total > 0 else 1 + return { + "items": [ + { + "id": str(log.id), + "user_id": str(log.user_id) if log.user_id else None, + "action": log.action, + "entity_type": log.entity_type, + "entity_id": log.entity_id, + "details": log.details, + "timestamp": log.timestamp.isoformat(), + "ip_address": log.ip_address, + } + for log in logs + ], + "total": total, + "page": page, + "page_size": page_size, + "pages": pages, + } diff --git a/backend/app/api/v1/clients.py b/backend/app/api/v1/clients.py new file mode 100644 index 0000000..52f80ba --- /dev/null +++ b/backend/app/api/v1/clients.py @@ -0,0 +1,105 @@ +from uuid import UUID + +from fastapi import APIRouter, Depends, HTTPException, Query, status +from sqlalchemy import func, select +from sqlalchemy.ext.asyncio import AsyncSession + +from app.dependencies import get_db, require_role +from app.models.client import Client +from app.schemas.client import ClientCreate, ClientResponse, ClientUpdate +from app.schemas.common import PaginatedResponse + +router = APIRouter(prefix="/clients", tags=["clients"]) + + +@router.post( + "", + response_model=ClientResponse, + status_code=status.HTTP_201_CREATED, +) +async def create_client( + body: ClientCreate, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(require_role(["admin"])), +) -> ClientResponse: + """Create a new client (admin only).""" + client = Client(name=body.name, settings=body.settings) + db.add(client) + await db.flush() + return ClientResponse.model_validate(client) + + +@router.get("", response_model=PaginatedResponse[ClientResponse]) +async def list_clients( + page: int = Query(1, ge=1), + page_size: int = Query(20, ge=1, le=100), + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(require_role(["admin"])), +) -> PaginatedResponse[ClientResponse]: + """List all clients (admin only).""" + count_result = await db.execute(select(func.count(Client.id))) + total = count_result.scalar() or 0 + + result = await db.execute( + select(Client) + .order_by(Client.created_at.desc()) + .offset((page - 1) * page_size) + .limit(page_size) + ) + clients = [ClientResponse.model_validate(c) for c in result.scalars().all()] + + pages = (total + page_size - 1) // page_size if total > 0 else 1 + return PaginatedResponse( + items=clients, total=total, page=page, page_size=page_size, pages=pages + ) + + +@router.get("/{client_id}", response_model=ClientResponse) +async def get_client( + client_id: UUID, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(require_role(["admin"])), +) -> ClientResponse: + """Get a client by ID (admin only).""" + result = await db.execute(select(Client).where(Client.id == client_id)) + client = result.scalar_one_or_none() + if client is None: + raise HTTPException(status_code=404, detail="Client not found") + return ClientResponse.model_validate(client) + + +@router.put("/{client_id}", response_model=ClientResponse) +async def update_client( + client_id: UUID, + body: ClientUpdate, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(require_role(["admin"])), +) -> ClientResponse: + """Update a client (admin only).""" + result = await db.execute(select(Client).where(Client.id == client_id)) + client = result.scalar_one_or_none() + if client is None: + raise HTTPException(status_code=404, detail="Client not found") + + update_data = body.model_dump(exclude_unset=True) + for field, value in update_data.items(): + setattr(client, field, value) + + await db.flush() + return ClientResponse.model_validate(client) + + +@router.delete("/{client_id}", status_code=status.HTTP_204_NO_CONTENT) +async def delete_client( + client_id: UUID, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(require_role(["admin"])), +) -> None: + """Delete a client (admin only).""" + result = await db.execute(select(Client).where(Client.id == client_id)) + client = result.scalar_one_or_none() + if client is None: + raise HTTPException(status_code=404, detail="Client not found") + + await db.delete(client) + await db.flush() diff --git a/backend/app/api/v1/files.py b/backend/app/api/v1/files.py new file mode 100644 index 0000000..bd80cab --- /dev/null +++ b/backend/app/api/v1/files.py @@ -0,0 +1,179 @@ +from uuid import UUID + +from fastapi import APIRouter, Depends, HTTPException, Query, UploadFile, File, status +from fastapi.responses import FileResponse +from sqlalchemy.ext.asyncio import AsyncSession + +from app.dependencies import get_current_user, get_db +from app.models.files import ReferenceFileType +from app.schemas.files import ( + FileUploadResponse, + ReferenceFileResponse, + TMFileResponse, +) +from app.services.file_service import FileService + +router = APIRouter(prefix="/files", tags=["files"]) +file_service = FileService() + + +# ---- TM Files ---- + + +@router.post("/tm", response_model=FileUploadResponse, status_code=status.HTTP_201_CREATED) +async def upload_tm_file( + client_id: UUID = Query(...), + locale_code: str = Query(...), + channel: str = Query(...), + file: UploadFile = File(...), + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> FileUploadResponse: + """Upload a Translation Memory (JSONL) file.""" + if not file.filename: + raise HTTPException(status_code=400, detail="File must have a filename") + if not file_service.validate_file_extension(file.filename, [".jsonl", ".json"]): + raise HTTPException(status_code=400, detail="Only .jsonl/.json files accepted") + + tm = await file_service.upload_tm_file( + db, client_id, locale_code, channel, file.file, file.filename, + uploaded_by=current_user["user_id"], + ) + return FileUploadResponse( + id=tm.id, + filename=tm.filename, + file_path=tm.file_path, + message=f"Uploaded TM file with {tm.segment_count} segments", + ) + + +@router.get("/tm", response_model=list[TMFileResponse]) +async def list_tm_files( + client_id: UUID = Query(...), + locale_code: str | None = Query(None), + channel: str | None = Query(None), + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> list[TMFileResponse]: + """List TM files for a client.""" + files = await file_service.list_tm_files(db, client_id, locale_code, channel) + return [TMFileResponse.model_validate(f) for f in files] + + +@router.get("/tm/{file_id}/download") +async def download_tm_file( + file_id: UUID, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> FileResponse: + """Download a TM file.""" + from sqlalchemy import select + from app.models.files import TMFileRegistry + + result = await db.execute( + select(TMFileRegistry).where(TMFileRegistry.id == file_id) + ) + tm = result.scalar_one_or_none() + if tm is None: + raise HTTPException(status_code=404, detail="TM file not found") + + path = file_service.get_file_path(tm.file_path) + if path is None: + raise HTTPException(status_code=404, detail="File not found on disk") + + return FileResponse(path=str(path), filename=tm.filename) + + +@router.delete("/tm/{file_id}", status_code=status.HTTP_204_NO_CONTENT) +async def delete_tm_file( + file_id: UUID, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> None: + """Delete a TM file.""" + deleted = await file_service.delete_tm_file(db, file_id) + if not deleted: + raise HTTPException(status_code=404, detail="TM file not found") + + +# ---- Reference Files ---- + + +@router.post( + "/reference", + response_model=FileUploadResponse, + status_code=status.HTTP_201_CREATED, +) +async def upload_reference_file( + client_id: UUID = Query(...), + file_type: ReferenceFileType = Query(...), + locale_scope: str = Query(...), + file: UploadFile = File(...), + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> FileUploadResponse: + """Upload a reference file (glossary, blacklist, TOV, etc.).""" + if not file.filename: + raise HTTPException(status_code=400, detail="File must have a filename") + + ref = await file_service.upload_reference_file( + db, client_id, file_type, locale_scope, file.file, file.filename, + uploaded_by=current_user["user_id"], + ) + return FileUploadResponse( + id=ref.id, + filename=ref.filename, + file_path=ref.file_path, + message=f"Uploaded {file_type.value} reference file", + ) + + +@router.get("/reference", response_model=list[ReferenceFileResponse]) +async def list_reference_files( + client_id: UUID = Query(...), + file_type: ReferenceFileType | None = Query(None), + locale_scope: str | None = Query(None), + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> list[ReferenceFileResponse]: + """List reference files for a client.""" + files = await file_service.list_reference_files( + db, client_id, file_type, locale_scope + ) + return [ReferenceFileResponse.model_validate(f) for f in files] + + +@router.get("/reference/{file_id}/download") +async def download_reference_file( + file_id: UUID, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> FileResponse: + """Download a reference file.""" + from sqlalchemy import select + from app.models.files import ReferenceFile + + result = await db.execute( + select(ReferenceFile).where(ReferenceFile.id == file_id) + ) + ref = result.scalar_one_or_none() + if ref is None: + raise HTTPException(status_code=404, detail="Reference file not found") + + path = file_service.get_file_path(ref.file_path) + if path is None: + raise HTTPException(status_code=404, detail="File not found on disk") + + return FileResponse(path=str(path), filename=ref.filename) + + +@router.delete("/reference/{file_id}", status_code=status.HTTP_204_NO_CONTENT) +async def delete_reference_file( + file_id: UUID, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> None: + """Delete a reference file.""" + deleted = await file_service.delete_reference_file(db, file_id) + if not deleted: + raise HTTPException(status_code=404, detail="Reference file not found") diff --git a/backend/app/api/v1/jobs.py b/backend/app/api/v1/jobs.py new file mode 100644 index 0000000..e16d5d0 --- /dev/null +++ b/backend/app/api/v1/jobs.py @@ -0,0 +1,206 @@ +from datetime import datetime +from uuid import UUID + +from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Query, status +from sqlalchemy.ext.asyncio import AsyncSession + +from app.dependencies import get_current_user, get_db +from app.schemas.common import PaginatedResponse +from app.schemas.job import JobCreate, JobListResponse, JobResponse, JobUpdate, LocaleInstanceResponse +from app.services.audit_service import AuditService +from app.services.file_service import FileService +from app.services.job_service import JobService + +router = APIRouter(prefix="/jobs", tags=["jobs"]) +job_service = JobService() +file_service = FileService() +audit_service = AuditService() + + +@router.post("", response_model=JobResponse, status_code=status.HTTP_201_CREATED) +async def create_job( + body: JobCreate, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> JobResponse: + """Create a new transcreation job.""" + job = await job_service.create_job(db, body, current_user["user_id"]) + await audit_service.log( + db, "create", "job", str(job.id), current_user["user_id"], + details={"campaign_name": body.campaign_name}, + ) + return JobResponse.model_validate(job) + + +@router.get("", response_model=PaginatedResponse[JobListResponse]) +async def list_jobs( + client_id: UUID | None = Query(None), + job_status: str | None = Query(None, alias="status"), + locale: str | None = Query(None), + date_from: datetime | None = Query(None), + date_to: datetime | None = Query(None), + search: str | None = Query(None), + page: int = Query(1, ge=1), + page_size: int = Query(20, ge=1, le=100), + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> PaginatedResponse[JobListResponse]: + """List jobs with filters and pagination.""" + jobs, total = await job_service.list_jobs( + db, + client_id=client_id, + status=job_status, + locale=locale, + date_from=date_from, + date_to=date_to, + search=search, + page=page, + page_size=page_size, + ) + items = [] + for job in jobs: + item = JobListResponse( + id=job.id, + client_id=job.client_id, + created_by=job.created_by, + job_ref=job.job_ref, + campaign_name=job.campaign_name, + programme=job.programme, + channel=job.channel, + status=job.status, + total_token_usage=job.total_token_usage, + total_estimated_cost=job.total_estimated_cost, + locale_count=len(job.locale_instances) if job.locale_instances else 0, + created_at=job.created_at, + updated_at=job.updated_at, + ) + items.append(item) + + pages = (total + page_size - 1) // page_size if total > 0 else 1 + return PaginatedResponse( + items=items, total=total, page=page, page_size=page_size, pages=pages + ) + + +@router.get("/{job_id}", response_model=JobResponse) +async def get_job( + job_id: UUID, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> JobResponse: + """Get job details with locale instances.""" + job = await job_service.get_job(db, job_id) + if job is None: + raise HTTPException(status_code=404, detail="Job not found") + return JobResponse.model_validate(job) + + +@router.put("/{job_id}/source") +async def upload_source( + job_id: UUID, + file: UploadFile = File(...), + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> dict: + """Upload source xlsx file for a job.""" + if not file.filename or not file.filename.endswith(".xlsx"): + raise HTTPException(status_code=400, detail="Only .xlsx files are accepted") + + job = await job_service.get_job(db, job_id) + if job is None: + raise HTTPException(status_code=404, detail="Job not found") + + source_lines = await file_service.upload_source_file( + db, job_id, file.file, file.filename + ) + await audit_service.log( + db, "upload_source", "job", str(job_id), current_user["user_id"], + details={"filename": file.filename, "line_count": len(source_lines)}, + ) + return { + "message": f"Uploaded {len(source_lines)} source lines", + "line_count": len(source_lines), + } + + +@router.post("/{job_id}/supplementary") +async def upload_supplementary( + job_id: UUID, + file: UploadFile = File(...), + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> dict: + """Upload supplementary files for a job.""" + job = await job_service.get_job(db, job_id) + if job is None: + raise HTTPException(status_code=404, detail="Job not found") + + file_path = await file_service.upload_supplementary_file( + db, job_id, file.file, file.filename or "unknown" + ) + return {"message": "File uploaded", "file_path": file_path} + + +@router.post("/{job_id}/launch", response_model=JobResponse) +async def launch_job( + job_id: UUID, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> JobResponse: + """Validate and queue a job for processing.""" + try: + job = await job_service.launch_job(db, job_id) + except ValueError as e: + raise HTTPException(status_code=400, detail=str(e)) + if job is None: + raise HTTPException(status_code=404, detail="Job not found") + + await audit_service.log( + db, "launch", "job", str(job_id), current_user["user_id"], + ) + return JobResponse.model_validate(job) + + +@router.post("/{job_id}/cancel", response_model=JobResponse) +async def cancel_job( + job_id: UUID, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> JobResponse: + """Cancel a running job.""" + try: + job = await job_service.cancel_job(db, job_id) + except ValueError as e: + raise HTTPException(status_code=400, detail=str(e)) + if job is None: + raise HTTPException(status_code=404, detail="Job not found") + + await audit_service.log( + db, "cancel", "job", str(job_id), current_user["user_id"], + ) + return JobResponse.model_validate(job) + + +@router.post( + "/{job_id}/locales/{locale_code}/rerun", + response_model=LocaleInstanceResponse, +) +async def rerun_locale( + job_id: UUID, + locale_code: str, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> LocaleInstanceResponse: + """Re-run a single locale instance.""" + instance = await job_service.rerun_locale(db, job_id, locale_code) + if instance is None: + raise HTTPException( + status_code=404, + detail=f"Locale instance '{locale_code}' not found for job", + ) + await audit_service.log( + db, "rerun_locale", "locale_instance", str(instance.id), + current_user["user_id"], + details={"locale_code": locale_code}, + ) + return LocaleInstanceResponse.model_validate(instance) diff --git a/backend/app/api/v1/output.py b/backend/app/api/v1/output.py new file mode 100644 index 0000000..d206175 --- /dev/null +++ b/backend/app/api/v1/output.py @@ -0,0 +1,84 @@ +from uuid import UUID + +from fastapi import APIRouter, Depends, HTTPException, status +from fastapi.responses import FileResponse +from sqlalchemy.ext.asyncio import AsyncSession + +from app.dependencies import get_current_user, get_db +from app.schemas.feedback import FeedbackCreate, FeedbackResponse +from app.schemas.output import OutputPreviewResponse +from app.services.feedback_service import FeedbackService +from app.services.output_service import OutputService + +router = APIRouter(prefix="/output", tags=["output"]) +output_service = OutputService() +feedback_service = FeedbackService() + + +@router.get( + "/jobs/{job_id}/locales/{locale_code}/preview", + response_model=OutputPreviewResponse, +) +async def get_output_preview( + job_id: UUID, + locale_code: str, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> OutputPreviewResponse: + """Get preview data for a locale instance output.""" + preview = await output_service.get_preview(db, job_id, locale_code) + if preview is None: + raise HTTPException( + status_code=404, + detail="No output found for this job/locale combination", + ) + return preview + + +@router.post( + "/feedback", + response_model=FeedbackResponse, + status_code=status.HTTP_201_CREATED, +) +async def create_feedback( + body: FeedbackCreate, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> FeedbackResponse: + """Submit feedback on an output row.""" + feedback = await feedback_service.create_feedback( + db, body, current_user["user_id"] + ) + return FeedbackResponse.model_validate(feedback) + + +@router.get("/feedback/{output_id}", response_model=list[FeedbackResponse]) +async def list_feedback_for_output( + output_id: UUID, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> list[FeedbackResponse]: + """List all feedback for a specific output row.""" + items = await feedback_service.list_feedback(db, output_id=output_id) + return [FeedbackResponse.model_validate(f) for f in items] + + +@router.get("/jobs/{job_id}/locales/{locale_code}/export") +async def export_output( + job_id: UUID, + locale_code: str, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> FileResponse: + """Export output as xlsx for a locale instance.""" + file_path = await output_service.trigger_export(db, job_id, locale_code) + if file_path is None: + raise HTTPException( + status_code=404, + detail="No export available for this job/locale combination", + ) + return FileResponse( + path=file_path, + filename=f"{job_id}_{locale_code}_output.xlsx", + media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + ) diff --git a/backend/app/api/v1/reports.py b/backend/app/api/v1/reports.py new file mode 100644 index 0000000..fdee7bf --- /dev/null +++ b/backend/app/api/v1/reports.py @@ -0,0 +1,50 @@ +from datetime import datetime +from typing import Any +from uuid import UUID + +from fastapi import APIRouter, Depends, Query +from sqlalchemy.ext.asyncio import AsyncSession + +from app.dependencies import get_current_user, get_db +from app.services.report_service import ReportService + +router = APIRouter(prefix="/reports", tags=["reports"]) +report_service = ReportService() + + +@router.get("/usage") +async def get_usage_stats( + client_id: UUID | None = Query(None), + date_from: datetime | None = Query(None), + date_to: datetime | None = Query(None), + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> dict[str, Any]: + """Get usage statistics (total jobs, tokens, cost, status breakdown).""" + return await report_service.get_usage_stats( + db, client_id=client_id, date_from=date_from, date_to=date_to + ) + + +@router.get("/tokens") +async def get_token_cost_data( + client_id: UUID | None = Query(None), + date_from: datetime | None = Query(None), + date_to: datetime | None = Query(None), + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> list[dict[str, Any]]: + """Get token usage and cost data grouped by day.""" + return await report_service.get_token_cost_data( + db, client_id=client_id, date_from=date_from, date_to=date_to + ) + + +@router.get("/quality") +async def get_quality_metrics( + client_id: UUID | None = Query(None), + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(get_current_user), +) -> dict[str, Any]: + """Get quality metrics (confidence tier distribution, feedback stats).""" + return await report_service.get_quality_metrics(db, client_id=client_id) diff --git a/backend/app/api/v1/router.py b/backend/app/api/v1/router.py new file mode 100644 index 0000000..10b209f --- /dev/null +++ b/backend/app/api/v1/router.py @@ -0,0 +1,21 @@ +from fastapi import APIRouter + +from app.auth.router import router as auth_router +from app.api.v1.jobs import router as jobs_router +from app.api.v1.users import router as users_router +from app.api.v1.clients import router as clients_router +from app.api.v1.files import router as files_router +from app.api.v1.output import router as output_router +from app.api.v1.reports import router as reports_router +from app.api.v1.audit import router as audit_router + +api_v1_router = APIRouter(prefix="/api/v1") + +api_v1_router.include_router(auth_router) +api_v1_router.include_router(jobs_router) +api_v1_router.include_router(users_router) +api_v1_router.include_router(clients_router) +api_v1_router.include_router(files_router) +api_v1_router.include_router(output_router) +api_v1_router.include_router(reports_router) +api_v1_router.include_router(audit_router) diff --git a/backend/app/api/v1/users.py b/backend/app/api/v1/users.py new file mode 100644 index 0000000..3e45935 --- /dev/null +++ b/backend/app/api/v1/users.py @@ -0,0 +1,130 @@ +from uuid import UUID + +from fastapi import APIRouter, Depends, HTTPException, Query, status +from sqlalchemy import func, select +from sqlalchemy.ext.asyncio import AsyncSession + +from app.auth.service import AuthService +from app.dependencies import get_db, require_role +from app.models.user import User, UserClient, UserStatus +from app.schemas.common import PaginatedResponse +from app.schemas.user import UserCreate, UserResponse, UserUpdate + +router = APIRouter(prefix="/users", tags=["users"]) +auth_service = AuthService() + + +@router.post( + "", + response_model=UserResponse, + status_code=status.HTTP_201_CREATED, +) +async def create_user( + body: UserCreate, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(require_role(["admin"])), +) -> UserResponse: + """Create a new user (admin only).""" + # Check for duplicate email + existing = await db.execute(select(User).where(User.email == body.email)) + if existing.scalar_one_or_none() is not None: + raise HTTPException(status_code=400, detail="Email already registered") + + user = User( + email=body.email, + name=body.name, + password_hash=auth_service.hash_password(body.password), + role=body.role, + status=UserStatus.active, + ) + db.add(user) + await db.flush() + + # Associate with clients + for client_id in body.client_ids: + uc = UserClient(user_id=user.id, client_id=client_id) + db.add(uc) + + await db.flush() + return UserResponse.model_validate(user) + + +@router.get("", response_model=PaginatedResponse[UserResponse]) +async def list_users( + page: int = Query(1, ge=1), + page_size: int = Query(20, ge=1, le=100), + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(require_role(["admin"])), +) -> PaginatedResponse[UserResponse]: + """List all users (admin only).""" + count_result = await db.execute(select(func.count(User.id))) + total = count_result.scalar() or 0 + + result = await db.execute( + select(User) + .order_by(User.created_at.desc()) + .offset((page - 1) * page_size) + .limit(page_size) + ) + users = [UserResponse.model_validate(u) for u in result.scalars().all()] + + pages = (total + page_size - 1) // page_size if total > 0 else 1 + return PaginatedResponse( + items=users, total=total, page=page, page_size=page_size, pages=pages + ) + + +@router.get("/{user_id}", response_model=UserResponse) +async def get_user( + user_id: UUID, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(require_role(["admin"])), +) -> UserResponse: + """Get a user by ID (admin only).""" + result = await db.execute(select(User).where(User.id == user_id)) + user = result.scalar_one_or_none() + if user is None: + raise HTTPException(status_code=404, detail="User not found") + return UserResponse.model_validate(user) + + +@router.put("/{user_id}", response_model=UserResponse) +async def update_user( + user_id: UUID, + body: UserUpdate, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(require_role(["admin"])), +) -> UserResponse: + """Update a user (admin only).""" + result = await db.execute(select(User).where(User.id == user_id)) + user = result.scalar_one_or_none() + if user is None: + raise HTTPException(status_code=404, detail="User not found") + + update_data = body.model_dump(exclude_unset=True) + if "password" in update_data: + update_data["password_hash"] = auth_service.hash_password( + update_data.pop("password") + ) + + for field, value in update_data.items(): + setattr(user, field, value) + + await db.flush() + return UserResponse.model_validate(user) + + +@router.delete("/{user_id}", status_code=status.HTTP_204_NO_CONTENT) +async def delete_user( + user_id: UUID, + db: AsyncSession = Depends(get_db), + current_user: dict = Depends(require_role(["admin"])), +) -> None: + """Soft-delete a user by setting status to inactive (admin only).""" + result = await db.execute(select(User).where(User.id == user_id)) + user = result.scalar_one_or_none() + if user is None: + raise HTTPException(status_code=404, detail="User not found") + + user.status = UserStatus.inactive + await db.flush() diff --git a/backend/app/auth/__init__.py b/backend/app/auth/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/auth/middleware.py b/backend/app/auth/middleware.py new file mode 100644 index 0000000..552b4fd --- /dev/null +++ b/backend/app/auth/middleware.py @@ -0,0 +1,33 @@ +from uuid import UUID + +from fastapi import Depends, HTTPException, status +from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer + +from app.auth.service import AuthService + +security = HTTPBearer() +auth_service = AuthService() + + +async def decode_jwt( + credentials: HTTPAuthorizationCredentials = Depends(security), +) -> dict: + """Decode JWT from Authorization header and return user claims.""" + token = credentials.credentials + claims = auth_service.validate_token(token) + if claims is None: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Invalid or expired token", + ) + if claims.get("type") != "access": + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Invalid token type", + ) + return { + "user_id": UUID(claims["sub"]), + "email": claims.get("email", ""), + "role": claims.get("role", ""), + "name": claims.get("name", ""), + } diff --git a/backend/app/auth/providers/__init__.py b/backend/app/auth/providers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/auth/providers/base.py b/backend/app/auth/providers/base.py new file mode 100644 index 0000000..0988588 --- /dev/null +++ b/backend/app/auth/providers/base.py @@ -0,0 +1,36 @@ +from abc import ABC, abstractmethod +from typing import Any + + +class AbstractAuthProvider(ABC): + """Abstract base for authentication providers.""" + + @abstractmethod + async def authenticate(self, email: str, password: str) -> dict[str, Any] | None: + """Authenticate a user. Returns user dict or None if invalid.""" + ... + + @abstractmethod + def create_access_token(self, data: dict[str, Any]) -> str: + """Create an access token for the given data.""" + ... + + @abstractmethod + def create_refresh_token(self, data: dict[str, Any]) -> str: + """Create a refresh token for the given data.""" + ... + + @abstractmethod + def validate_token(self, token: str) -> dict[str, Any] | None: + """Validate a token and return the claims, or None if invalid.""" + ... + + @abstractmethod + def hash_password(self, password: str) -> str: + """Hash a plaintext password.""" + ... + + @abstractmethod + def verify_password(self, plain_password: str, hashed_password: str) -> bool: + """Verify a plaintext password against a hash.""" + ... diff --git a/backend/app/auth/providers/jwt_provider.py b/backend/app/auth/providers/jwt_provider.py new file mode 100644 index 0000000..3332062 --- /dev/null +++ b/backend/app/auth/providers/jwt_provider.py @@ -0,0 +1,52 @@ +from datetime import datetime, timedelta, timezone +from typing import Any + +import bcrypt +from jose import JWTError, jwt + +from app.config import settings +from app.auth.providers.base import AbstractAuthProvider + + +class JWTAuthProvider(AbstractAuthProvider): + """JWT-based authentication provider with bcrypt password hashing.""" + + def __init__(self) -> None: + self.secret_key = settings.JWT_SECRET_KEY + self.algorithm = settings.JWT_ALGORITHM + self.access_token_expiry = timedelta(hours=settings.JWT_EXPIRY_HOURS) + self.refresh_token_expiry = timedelta(days=7) + + async def authenticate(self, email: str, password: str) -> dict[str, Any] | None: + """Not used directly - authentication happens through AuthService.""" + return None + + def create_access_token(self, data: dict[str, Any]) -> str: + """Create a JWT access token (8-hour expiry by default).""" + to_encode = data.copy() + expire = datetime.now(timezone.utc) + self.access_token_expiry + to_encode.update({"exp": expire, "type": "access"}) + return jwt.encode(to_encode, self.secret_key, algorithm=self.algorithm) + + def create_refresh_token(self, data: dict[str, Any]) -> str: + """Create a JWT refresh token (7-day expiry).""" + to_encode = data.copy() + expire = datetime.now(timezone.utc) + self.refresh_token_expiry + to_encode.update({"exp": expire, "type": "refresh"}) + return jwt.encode(to_encode, self.secret_key, algorithm=self.algorithm) + + def validate_token(self, token: str) -> dict[str, Any] | None: + """Validate a JWT and return its claims, or None if invalid.""" + try: + payload = jwt.decode(token, self.secret_key, algorithms=[self.algorithm]) + return payload + except JWTError: + return None + + def hash_password(self, password: str) -> str: + """Hash a password using bcrypt.""" + return bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()).decode("utf-8") + + def verify_password(self, plain_password: str, hashed_password: str) -> bool: + """Verify a password against a bcrypt hash.""" + return bcrypt.checkpw(plain_password.encode("utf-8"), hashed_password.encode("utf-8")) diff --git a/backend/app/auth/router.py b/backend/app/auth/router.py new file mode 100644 index 0000000..c42a85d --- /dev/null +++ b/backend/app/auth/router.py @@ -0,0 +1,44 @@ +from fastapi import APIRouter, Depends, HTTPException, status +from sqlalchemy.ext.asyncio import AsyncSession + +from app.auth.schemas import LoginRequest, RefreshRequest, TokenResponse, UserClaims +from app.auth.service import AuthService +from app.dependencies import get_current_user, get_db + +router = APIRouter(prefix="/auth", tags=["auth"]) +auth_service = AuthService() + + +@router.post("/login", response_model=TokenResponse) +async def login( + body: LoginRequest, + db: AsyncSession = Depends(get_db), +) -> TokenResponse: + """Authenticate user and return access + refresh tokens.""" + result = await auth_service.login(body.email, body.password, db) + if result is None: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Invalid email or password", + ) + return TokenResponse(**result) + + +@router.post("/refresh", response_model=TokenResponse) +async def refresh_token(body: RefreshRequest) -> TokenResponse: + """Exchange a valid refresh token for a new token pair.""" + result = auth_service.refresh_tokens(body.refresh_token) + if result is None: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Invalid or expired refresh token", + ) + return TokenResponse(**result) + + +@router.get("/me", response_model=UserClaims) +async def get_me( + current_user: dict = Depends(get_current_user), +) -> UserClaims: + """Return the current authenticated user's claims.""" + return UserClaims(**current_user) diff --git a/backend/app/auth/schemas.py b/backend/app/auth/schemas.py new file mode 100644 index 0000000..7a9ab28 --- /dev/null +++ b/backend/app/auth/schemas.py @@ -0,0 +1,25 @@ +from uuid import UUID + +from pydantic import BaseModel, EmailStr + + +class LoginRequest(BaseModel): + email: EmailStr + password: str + + +class TokenResponse(BaseModel): + access_token: str + refresh_token: str + token_type: str = "bearer" + + +class RefreshRequest(BaseModel): + refresh_token: str + + +class UserClaims(BaseModel): + user_id: UUID + email: str + role: str + name: str diff --git a/backend/app/auth/service.py b/backend/app/auth/service.py new file mode 100644 index 0000000..ce446c3 --- /dev/null +++ b/backend/app/auth/service.py @@ -0,0 +1,70 @@ +from typing import Any + +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession + +from app.auth.providers.jwt_provider import JWTAuthProvider +from app.models.user import User + + +class AuthService: + """Authentication service wrapping the JWT provider.""" + + def __init__(self) -> None: + self.provider = JWTAuthProvider() + + async def login( + self, email: str, password: str, db: AsyncSession + ) -> dict[str, str] | None: + """Authenticate a user and return tokens, or None if invalid.""" + result = await db.execute(select(User).where(User.email == email)) + user = result.scalar_one_or_none() + + if user is None: + return None + if not self.provider.verify_password(password, user.password_hash): + return None + if user.status.value != "active": + return None + + token_data = { + "sub": str(user.id), + "email": user.email, + "role": user.role.value, + "name": user.name, + } + + return { + "access_token": self.provider.create_access_token(token_data), + "refresh_token": self.provider.create_refresh_token(token_data), + "token_type": "bearer", + } + + def refresh_tokens(self, refresh_token: str) -> dict[str, str] | None: + """Validate a refresh token and issue new token pair.""" + claims = self.provider.validate_token(refresh_token) + if claims is None: + return None + if claims.get("type") != "refresh": + return None + + token_data = { + "sub": claims["sub"], + "email": claims.get("email", ""), + "role": claims.get("role", ""), + "name": claims.get("name", ""), + } + + return { + "access_token": self.provider.create_access_token(token_data), + "refresh_token": self.provider.create_refresh_token(token_data), + "token_type": "bearer", + } + + def validate_token(self, token: str) -> dict[str, Any] | None: + """Validate a token and return claims.""" + return self.provider.validate_token(token) + + def hash_password(self, password: str) -> str: + """Hash a password.""" + return self.provider.hash_password(password) diff --git a/backend/app/config.py b/backend/app/config.py new file mode 100644 index 0000000..eea0d90 --- /dev/null +++ b/backend/app/config.py @@ -0,0 +1,23 @@ +from pydantic_settings import BaseSettings + + +class Settings(BaseSettings): + """Application settings loaded from environment variables.""" + + DATABASE_URL: str = "postgresql+asyncpg://transcreation:transcreation@db:5432/transcreation" + REDIS_URL: str = "redis://redis:6379/0" + ANTHROPIC_API_KEY: str = "" + JWT_SECRET_KEY: str = "CHANGE_ME_TO_A_RANDOM_SECRET" + JWT_ALGORITHM: str = "HS256" + JWT_EXPIRY_HOURS: int = 8 + STORAGE_ROOT: str = "/storage" + LLM_MODEL: str = "claude-sonnet-4-20250514" + + model_config = { + "env_file": ".env", + "env_file_encoding": "utf-8", + "extra": "ignore", + } + + +settings = Settings() diff --git a/backend/app/dependencies.py b/backend/app/dependencies.py new file mode 100644 index 0000000..2d12791 --- /dev/null +++ b/backend/app/dependencies.py @@ -0,0 +1,82 @@ +from typing import AsyncGenerator, Callable +from uuid import UUID + +from fastapi import Depends, HTTPException, status +from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer +from jose import JWTError, jwt +from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine + +from app.config import settings + +security = HTTPBearer() + +_engine = create_async_engine( + settings.DATABASE_URL, + echo=False, + pool_size=20, + max_overflow=10, + pool_pre_ping=True, +) + +_async_session_factory = async_sessionmaker( + bind=_engine, + class_=AsyncSession, + expire_on_commit=False, +) + + +async def get_db() -> AsyncGenerator[AsyncSession, None]: + """Yield an async database session.""" + async with _async_session_factory() as session: + try: + yield session + await session.commit() + except Exception: + await session.rollback() + raise + + +async def get_current_user( + credentials: HTTPAuthorizationCredentials = Depends(security), +) -> dict: + """Decode JWT from Authorization header and return user claims.""" + token = credentials.credentials + try: + payload = jwt.decode( + token, + settings.JWT_SECRET_KEY, + algorithms=[settings.JWT_ALGORITHM], + ) + user_id: str | None = payload.get("sub") + if user_id is None: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Invalid token: missing subject", + ) + return { + "user_id": UUID(user_id), + "email": payload.get("email", ""), + "role": payload.get("role", ""), + "name": payload.get("name", ""), + } + except JWTError as exc: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=f"Could not validate credentials: {exc}", + ) + + +def require_role(roles: list[str]) -> Callable: + """Dependency factory that enforces role-based access.""" + + async def _check_role( + current_user: dict = Depends(get_current_user), + ) -> dict: + if current_user["role"] not in roles: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=f"Role '{current_user['role']}' not permitted. Required: {roles}", + ) + return current_user + + return _check_role diff --git a/backend/app/llm/__init__.py b/backend/app/llm/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/llm/client.py b/backend/app/llm/client.py new file mode 100644 index 0000000..ae7c15b --- /dev/null +++ b/backend/app/llm/client.py @@ -0,0 +1,143 @@ +"""Anthropic SDK wrapper with retry logic and token tracking.""" + +import logging +import time +from typing import Any + +import anthropic + +from app.config import settings + +logger = logging.getLogger(__name__) + +# Cost per token (approximate, varies by model) +COST_PER_INPUT_TOKEN = 3.0 / 1_000_000 # $3 per 1M input tokens +COST_PER_OUTPUT_TOKEN = 15.0 / 1_000_000 # $15 per 1M output tokens + + +class LLMClient: + """Wrapper around the Anthropic SDK with retry and token tracking. + + Provides exponential backoff retry on rate limit and server errors. + Tracks token usage per call for cost monitoring. + """ + + def __init__( + self, + api_key: str | None = None, + model: str | None = None, + max_retries: int = 3, + base_delay: float = 1.0, + ) -> None: + self.api_key = api_key or settings.ANTHROPIC_API_KEY + self.model = model or settings.LLM_MODEL + self.max_retries = max_retries + self.base_delay = base_delay + + self.client = anthropic.Anthropic(api_key=self.api_key) + self.last_usage: dict[str, Any] = {} + + def create_message( + self, + system_prompt: str, + user_message: str, + max_tokens: int = 4096, + temperature: float = 0.7, + ) -> tuple[str, dict[str, Any]]: + """Send a message to Claude and return the response with usage data. + + Args: + system_prompt: The system prompt. + user_message: The user message. + max_tokens: Maximum tokens in the response. + temperature: Sampling temperature. + + Returns: + Tuple of (response_text, usage_dict). + usage_dict has keys: input_tokens, output_tokens, total_tokens, estimated_cost_usd. + + Raises: + anthropic.APIError: If all retries are exhausted. + """ + last_error = None + + for attempt in range(1, self.max_retries + 1): + try: + response = self.client.messages.create( + model=self.model, + max_tokens=max_tokens, + system=system_prompt, + messages=[{"role": "user", "content": user_message}], + temperature=temperature, + ) + + # Extract text + response_text = "" + for block in response.content: + if hasattr(block, "text"): + response_text += block.text + + # Track usage + input_tokens = response.usage.input_tokens + output_tokens = response.usage.output_tokens + total_tokens = input_tokens + output_tokens + estimated_cost = ( + input_tokens * COST_PER_INPUT_TOKEN + + output_tokens * COST_PER_OUTPUT_TOKEN + ) + + usage = { + "input_tokens": input_tokens, + "output_tokens": output_tokens, + "total_tokens": total_tokens, + "estimated_cost_usd": round(estimated_cost, 6), + "model": self.model, + } + self.last_usage = usage + + return response_text, usage + + except anthropic.RateLimitError as e: + last_error = e + delay = self.base_delay * (2 ** (attempt - 1)) + logger.warning( + f"Rate limited (attempt {attempt}/{self.max_retries}), " + f"retrying in {delay}s" + ) + time.sleep(delay) + + except anthropic.APIStatusError as e: + if e.status_code >= 500: + last_error = e + delay = self.base_delay * (2 ** (attempt - 1)) + logger.warning( + f"Server error {e.status_code} (attempt {attempt}/{self.max_retries}), " + f"retrying in {delay}s" + ) + time.sleep(delay) + else: + raise + + raise last_error # type: ignore[misc] + + async def acreate_message( + self, + system_prompt: str, + user_message: str, + max_tokens: int = 4096, + temperature: float = 0.7, + ) -> tuple[str, dict[str, Any]]: + """Async version of create_message using the async client. + + Same interface as create_message but uses asyncio. + """ + import asyncio + + # Run sync client in executor to avoid blocking + loop = asyncio.get_event_loop() + return await loop.run_in_executor( + None, + lambda: self.create_message( + system_prompt, user_message, max_tokens, temperature + ), + ) diff --git a/backend/app/llm/token_tracker.py b/backend/app/llm/token_tracker.py new file mode 100644 index 0000000..548442f --- /dev/null +++ b/backend/app/llm/token_tracker.py @@ -0,0 +1,101 @@ +"""Token usage tracking - records LLM usage to the database.""" + +import logging +from typing import Any +from uuid import UUID + +from sqlalchemy.ext.asyncio import AsyncSession + +from app.models.audit import TokenUsageLog + +logger = logging.getLogger(__name__) + + +async def record_token_usage( + db: AsyncSession, + instance_id: UUID, + agent_name: str, + usage: dict[str, Any], +) -> TokenUsageLog: + """Record token usage from an LLM call to the database. + + Args: + db: Async database session. + instance_id: The locale instance ID this usage is for. + agent_name: Name of the agent that made the call. + usage: Usage dict from LLMClient with keys: + input_tokens, output_tokens, total_tokens, + estimated_cost_usd, model. + + Returns: + The created TokenUsageLog record. + """ + log_entry = TokenUsageLog( + instance_id=instance_id, + agent_name=agent_name, + model=usage.get("model", "unknown"), + input_tokens=usage.get("input_tokens", 0), + output_tokens=usage.get("output_tokens", 0), + total_tokens=usage.get("total_tokens", 0), + estimated_cost_usd=usage.get("estimated_cost_usd", 0.0), + ) + db.add(log_entry) + await db.flush() + + logger.info( + f"Token usage recorded: agent={agent_name}, " + f"tokens={usage.get('total_tokens', 0)}, " + f"cost=${usage.get('estimated_cost_usd', 0.0):.6f}" + ) + + return log_entry + + +async def get_total_usage_for_instance( + db: AsyncSession, + instance_id: UUID, +) -> dict[str, Any]: + """Get aggregated token usage for a locale instance. + + Args: + db: Async database session. + instance_id: The locale instance ID. + + Returns: + Dict with total_tokens, total_cost, by_agent breakdown. + """ + from sqlalchemy import func, select + + result = await db.execute( + select( + func.sum(TokenUsageLog.input_tokens).label("total_input"), + func.sum(TokenUsageLog.output_tokens).label("total_output"), + func.sum(TokenUsageLog.total_tokens).label("total_tokens"), + func.sum(TokenUsageLog.estimated_cost_usd).label("total_cost"), + ).where(TokenUsageLog.instance_id == instance_id) + ) + row = result.one() + + # By-agent breakdown + agent_result = await db.execute( + select( + TokenUsageLog.agent_name, + func.sum(TokenUsageLog.total_tokens).label("tokens"), + func.sum(TokenUsageLog.estimated_cost_usd).label("cost"), + ) + .where(TokenUsageLog.instance_id == instance_id) + .group_by(TokenUsageLog.agent_name) + ) + + by_agent = { + agent_name: {"tokens": tokens, "cost": float(cost)} + for agent_name, tokens, cost in agent_result.all() + } + + return { + "total_input_tokens": row.total_input or 0, + "total_output_tokens": row.total_output or 0, + "total_tokens": row.total_tokens or 0, + "total_cost_usd": float(row.total_cost or 0.0), + "by_agent": by_agent, + } diff --git a/backend/app/main.py b/backend/app/main.py new file mode 100644 index 0000000..62132e2 --- /dev/null +++ b/backend/app/main.py @@ -0,0 +1,63 @@ +from contextlib import asynccontextmanager +from typing import AsyncGenerator + +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware +from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine + +from app.config import settings +from app.api.v1.router import api_v1_router +from app.ws.handler import ws_router + +engine: AsyncEngine | None = None + + +@asynccontextmanager +async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: + """Manage application lifespan: set up and tear down DB engine.""" + global engine + engine = create_async_engine( + settings.DATABASE_URL, + echo=False, + pool_size=20, + max_overflow=10, + pool_pre_ping=True, + ) + yield + if engine is not None: + await engine.dispose() + engine = None + + +def create_app() -> FastAPI: + """Application factory.""" + application = FastAPI( + title="Amazon AI Transcreation Platform", + description="Backend API for AI-powered marketing transcreation", + version="1.0.0", + lifespan=lifespan, + ) + + # CORS middleware (permissive for development) + application.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], + ) + + # API routes + application.include_router(api_v1_router) + + # WebSocket routes + application.include_router(ws_router) + + @application.get("/health", tags=["health"]) + async def health_check() -> dict: + return {"status": "healthy", "version": "1.0.0"} + + return application + + +app = create_app() diff --git a/backend/app/models/__init__.py b/backend/app/models/__init__.py new file mode 100644 index 0000000..8688e94 --- /dev/null +++ b/backend/app/models/__init__.py @@ -0,0 +1,11 @@ +"""SQLAlchemy models - import all models so Alembic can discover them.""" + +from app.models.base import Base, TimestampMixin # noqa: F401 +from app.models.client import Client # noqa: F401 +from app.models.user import User, UserClient # noqa: F401 +from app.models.job import Job, LocaleInstance # noqa: F401 +from app.models.source import SourceLine # noqa: F401 +from app.models.output import OutputRow # noqa: F401 +from app.models.feedback import Feedback # noqa: F401 +from app.models.files import TMFileRegistry, ReferenceFile # noqa: F401 +from app.models.audit import AuditLog, TokenUsageLog # noqa: F401 diff --git a/backend/app/models/audit.py b/backend/app/models/audit.py new file mode 100644 index 0000000..ed6c8f6 --- /dev/null +++ b/backend/app/models/audit.py @@ -0,0 +1,56 @@ +import uuid +from datetime import datetime + +from sqlalchemy import DateTime, Float, ForeignKey, Integer, JSON, String, func +from sqlalchemy.orm import Mapped, mapped_column, relationship + +from app.models.base import Base, generate_uuid + + +class AuditLog(Base): + __tablename__ = "audit_logs" + + id: Mapped[uuid.UUID] = mapped_column( + primary_key=True, default=generate_uuid + ) + user_id: Mapped[uuid.UUID | None] = mapped_column( + ForeignKey("users.id"), nullable=True + ) + action: Mapped[str] = mapped_column(String(100), nullable=False) + entity_type: Mapped[str] = mapped_column(String(100), nullable=False) + entity_id: Mapped[str] = mapped_column(String(255), nullable=False) + details: Mapped[dict | None] = mapped_column(JSON, nullable=True) + timestamp: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now(), + nullable=False, + ) + ip_address: Mapped[str | None] = mapped_column(String(45), nullable=True) + + # Relationships + user = relationship("User", back_populates="audit_logs") + + +class TokenUsageLog(Base): + __tablename__ = "token_usage_logs" + + id: Mapped[uuid.UUID] = mapped_column( + primary_key=True, default=generate_uuid + ) + instance_id: Mapped[uuid.UUID] = mapped_column( + ForeignKey("locale_instances.id", ondelete="CASCADE"), nullable=False + ) + agent_name: Mapped[str] = mapped_column(String(100), nullable=False) + model: Mapped[str] = mapped_column(String(100), nullable=False) + input_tokens: Mapped[int] = mapped_column(Integer, nullable=False) + output_tokens: Mapped[int] = mapped_column(Integer, nullable=False) + total_tokens: Mapped[int] = mapped_column(Integer, nullable=False) + estimated_cost_usd: Mapped[float] = mapped_column(Float, nullable=False) + timestamp: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now(), + nullable=False, + ) + + # Relationships + instance = relationship("LocaleInstance", back_populates="token_usage_logs") diff --git a/backend/app/models/base.py b/backend/app/models/base.py new file mode 100644 index 0000000..d815adf --- /dev/null +++ b/backend/app/models/base.py @@ -0,0 +1,30 @@ +import uuid +from datetime import datetime + +from sqlalchemy import DateTime, func +from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column + + +class Base(DeclarativeBase): + """Base class for all SQLAlchemy models.""" + pass + + +class TimestampMixin: + """Mixin that adds created_at and updated_at columns.""" + + created_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now(), + nullable=False, + ) + updated_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now(), + onupdate=func.now(), + nullable=False, + ) + + +def generate_uuid() -> uuid.UUID: + return uuid.uuid4() diff --git a/backend/app/models/client.py b/backend/app/models/client.py new file mode 100644 index 0000000..a7c3329 --- /dev/null +++ b/backend/app/models/client.py @@ -0,0 +1,22 @@ +import uuid + +from sqlalchemy import JSON, String +from sqlalchemy.orm import Mapped, mapped_column, relationship + +from app.models.base import Base, TimestampMixin, generate_uuid + + +class Client(Base, TimestampMixin): + __tablename__ = "clients" + + id: Mapped[uuid.UUID] = mapped_column( + primary_key=True, default=generate_uuid + ) + name: Mapped[str] = mapped_column(String(255), nullable=False) + settings: Mapped[dict | None] = mapped_column(JSON, nullable=True) + + # Relationships + user_clients = relationship("UserClient", back_populates="client", lazy="selectin") + jobs = relationship("Job", back_populates="client", lazy="selectin") + tm_files = relationship("TMFileRegistry", back_populates="client", lazy="selectin") + reference_files = relationship("ReferenceFile", back_populates="client", lazy="selectin") diff --git a/backend/app/models/feedback.py b/backend/app/models/feedback.py new file mode 100644 index 0000000..c9aa3c1 --- /dev/null +++ b/backend/app/models/feedback.py @@ -0,0 +1,43 @@ +import enum +import uuid +from datetime import datetime + +from sqlalchemy import DateTime, Enum, ForeignKey, Integer, Text, func +from sqlalchemy.orm import Mapped, mapped_column, relationship + +from app.models.base import Base, generate_uuid + + +class FlagType(str, enum.Enum): + approved = "approved" + needs_revision = "needs_revision" + comment = "comment" + + +class Feedback(Base): + __tablename__ = "feedback" + + id: Mapped[uuid.UUID] = mapped_column( + primary_key=True, default=generate_uuid + ) + output_id: Mapped[uuid.UUID] = mapped_column( + ForeignKey("output_rows.id", ondelete="CASCADE"), nullable=False + ) + user_id: Mapped[uuid.UUID] = mapped_column( + ForeignKey("users.id"), nullable=False + ) + option_column: Mapped[int] = mapped_column(Integer, nullable=False) + flag_type: Mapped[FlagType] = mapped_column( + Enum(FlagType, name="flag_type", create_constraint=True), + nullable=False, + ) + comment: Mapped[str | None] = mapped_column(Text, nullable=True) + created_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now(), + nullable=False, + ) + + # Relationships + output = relationship("OutputRow", back_populates="feedback") + user = relationship("User", back_populates="feedback") diff --git a/backend/app/models/files.py b/backend/app/models/files.py new file mode 100644 index 0000000..1e85b7b --- /dev/null +++ b/backend/app/models/files.py @@ -0,0 +1,89 @@ +import enum +import uuid +from datetime import datetime + +from sqlalchemy import DateTime, Enum, ForeignKey, Integer, String, func +from sqlalchemy.orm import Mapped, mapped_column, relationship + +from app.models.base import Base, generate_uuid + + +class ReferenceFileType(str, enum.Enum): + glossary = "glossary" + blacklist = "blacklist" + tov_global = "tov_global" + tov_supplement = "tov_supplement" + locale_considerations = "locale_considerations" + date_pct_formats = "date_pct_formats" + + +class TMFileRegistry(Base): + __tablename__ = "tm_file_registry" + + id: Mapped[uuid.UUID] = mapped_column( + primary_key=True, default=generate_uuid + ) + client_id: Mapped[uuid.UUID] = mapped_column( + ForeignKey("clients.id", ondelete="CASCADE"), nullable=False + ) + locale_code: Mapped[str] = mapped_column(String(10), nullable=False) + channel: Mapped[str] = mapped_column(String(100), nullable=False) + filename: Mapped[str] = mapped_column(String(255), nullable=False) + file_path: Mapped[str] = mapped_column(String(500), nullable=False) + segment_count: Mapped[int] = mapped_column(Integer, default=0) + uploaded_by: Mapped[uuid.UUID | None] = mapped_column( + ForeignKey("users.id"), nullable=True + ) + uploaded_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now(), + nullable=False, + ) + last_updated_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now(), + onupdate=func.now(), + nullable=False, + ) + version: Mapped[int] = mapped_column(Integer, default=1) + + # Relationships + client = relationship("Client", back_populates="tm_files") + uploader = relationship("User", foreign_keys=[uploaded_by]) + + +class ReferenceFile(Base): + __tablename__ = "reference_files" + + id: Mapped[uuid.UUID] = mapped_column( + primary_key=True, default=generate_uuid + ) + client_id: Mapped[uuid.UUID] = mapped_column( + ForeignKey("clients.id", ondelete="CASCADE"), nullable=False + ) + file_type: Mapped[ReferenceFileType] = mapped_column( + Enum(ReferenceFileType, name="reference_file_type", create_constraint=True), + nullable=False, + ) + locale_scope: Mapped[str] = mapped_column(String(10), nullable=False) + filename: Mapped[str] = mapped_column(String(255), nullable=False) + file_path: Mapped[str] = mapped_column(String(500), nullable=False) + uploaded_by: Mapped[uuid.UUID | None] = mapped_column( + ForeignKey("users.id"), nullable=True + ) + uploaded_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now(), + nullable=False, + ) + last_updated_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now(), + onupdate=func.now(), + nullable=False, + ) + version: Mapped[int] = mapped_column(Integer, default=1) + + # Relationships + client = relationship("Client", back_populates="reference_files") + uploader = relationship("User", foreign_keys=[uploaded_by]) diff --git a/backend/app/models/job.py b/backend/app/models/job.py new file mode 100644 index 0000000..015404b --- /dev/null +++ b/backend/app/models/job.py @@ -0,0 +1,143 @@ +import enum +import uuid +from datetime import datetime + +from sqlalchemy import ( + JSON, + DateTime, + Enum, + Float, + ForeignKey, + Integer, + String, + Text, +) +from sqlalchemy.orm import Mapped, mapped_column, relationship + +from app.models.base import Base, TimestampMixin, generate_uuid + + +class Programme(str, enum.Enum): + retail = "retail" + prime = "prime" + brand = "brand" + + +class JobType(str, enum.Enum): + main = "main" + derived = "derived" + + +class JobStatus(str, enum.Enum): + created = "created" + validating = "validating" + queued = "queued" + running = "running" + partial_complete = "partial_complete" + complete = "complete" + error = "error" + exported = "exported" + + +class LocaleType(str, enum.Enum): + main = "main" + derived = "derived" + + +class LocaleStatus(str, enum.Enum): + queued = "queued" + running = "running" + complete = "complete" + error = "error" + + +class Job(Base, TimestampMixin): + __tablename__ = "jobs" + + id: Mapped[uuid.UUID] = mapped_column( + primary_key=True, default=generate_uuid + ) + client_id: Mapped[uuid.UUID] = mapped_column( + ForeignKey("clients.id", ondelete="CASCADE"), nullable=False + ) + created_by: Mapped[uuid.UUID] = mapped_column( + ForeignKey("users.id"), nullable=False + ) + job_ref: Mapped[str | None] = mapped_column(String(100), nullable=True) + campaign_name: Mapped[str] = mapped_column(String(255), nullable=False) + programme: Mapped[Programme] = mapped_column( + Enum(Programme, name="programme_type", create_constraint=True), + nullable=False, + ) + channel: Mapped[str] = mapped_column(String(100), nullable=False) + sub_channel: Mapped[str | None] = mapped_column(String(100), nullable=True) + context_prompt: Mapped[str | None] = mapped_column(Text, nullable=True) + job_type: Mapped[JobType] = mapped_column( + Enum(JobType, name="job_type", create_constraint=True), + default=JobType.main, + nullable=False, + ) + parent_job_id: Mapped[uuid.UUID | None] = mapped_column( + ForeignKey("jobs.id"), nullable=True + ) + status: Mapped[JobStatus] = mapped_column( + Enum(JobStatus, name="job_status", create_constraint=True), + default=JobStatus.created, + nullable=False, + ) + total_token_usage: Mapped[int] = mapped_column(Integer, default=0) + total_estimated_cost: Mapped[float] = mapped_column(Float, default=0.0) + + # Relationships + client = relationship("Client", back_populates="jobs") + creator = relationship("User", back_populates="jobs_created") + parent_job = relationship("Job", remote_side="Job.id", lazy="selectin") + locale_instances = relationship( + "LocaleInstance", back_populates="job", lazy="selectin", cascade="all, delete-orphan" + ) + source_lines = relationship( + "SourceLine", back_populates="job", lazy="selectin", cascade="all, delete-orphan" + ) + + +class LocaleInstance(Base, TimestampMixin): + __tablename__ = "locale_instances" + + id: Mapped[uuid.UUID] = mapped_column( + primary_key=True, default=generate_uuid + ) + job_id: Mapped[uuid.UUID] = mapped_column( + ForeignKey("jobs.id", ondelete="CASCADE"), nullable=False + ) + locale_code: Mapped[str] = mapped_column(String(10), nullable=False) + locale_type: Mapped[LocaleType] = mapped_column( + Enum(LocaleType, name="locale_type", create_constraint=True), + nullable=False, + ) + status: Mapped[LocaleStatus] = mapped_column( + Enum(LocaleStatus, name="locale_status", create_constraint=True), + default=LocaleStatus.queued, + nullable=False, + ) + started_at: Mapped[datetime | None] = mapped_column( + DateTime(timezone=True), nullable=True + ) + completed_at: Mapped[datetime | None] = mapped_column( + DateTime(timezone=True), nullable=True + ) + token_usage: Mapped[int] = mapped_column(Integer, default=0) + estimated_cost: Mapped[float] = mapped_column(Float, default=0.0) + output_file_path: Mapped[str | None] = mapped_column(String(500), nullable=True) + error_log: Mapped[str | None] = mapped_column(Text, nullable=True) + tm_files_loaded: Mapped[dict | None] = mapped_column(JSON, nullable=True) + ref_files_loaded: Mapped[dict | None] = mapped_column(JSON, nullable=True) + agent_version: Mapped[str | None] = mapped_column(String(50), nullable=True) + + # Relationships + job = relationship("Job", back_populates="locale_instances") + output_rows = relationship( + "OutputRow", back_populates="instance", lazy="selectin", cascade="all, delete-orphan" + ) + token_usage_logs = relationship( + "TokenUsageLog", back_populates="instance", lazy="selectin", cascade="all, delete-orphan" + ) diff --git a/backend/app/models/output.py b/backend/app/models/output.py new file mode 100644 index 0000000..f3dcfdc --- /dev/null +++ b/backend/app/models/output.py @@ -0,0 +1,53 @@ +import enum +import uuid + +from sqlalchemy import Enum, ForeignKey, Integer, JSON, String, Text +from sqlalchemy.orm import Mapped, mapped_column, relationship + +from app.models.base import Base, TimestampMixin, generate_uuid + + +class ConfidenceTier(str, enum.Enum): + high = "high" + moderate = "moderate" + low = "low" + + +class OutputRow(Base, TimestampMixin): + __tablename__ = "output_rows" + + id: Mapped[uuid.UUID] = mapped_column( + primary_key=True, default=generate_uuid + ) + instance_id: Mapped[uuid.UUID] = mapped_column( + ForeignKey("locale_instances.id", ondelete="CASCADE"), nullable=False + ) + line_id: Mapped[uuid.UUID] = mapped_column( + ForeignKey("source_lines.id", ondelete="CASCADE"), nullable=False + ) + row_order: Mapped[int] = mapped_column(Integer, nullable=False) + confidence_tier: Mapped[ConfidenceTier] = mapped_column( + Enum(ConfidenceTier, name="confidence_tier", create_constraint=True), + nullable=False, + ) + option_1: Mapped[str] = mapped_column(Text, nullable=False) + backtranslation_1: Mapped[str] = mapped_column(Text, nullable=False) + rationale_1: Mapped[str] = mapped_column(Text, nullable=False) + option_2: Mapped[str | None] = mapped_column(Text, nullable=True) + backtranslation_2: Mapped[str | None] = mapped_column(Text, nullable=True) + rationale_2: Mapped[str | None] = mapped_column(Text, nullable=True) + option_3: Mapped[str | None] = mapped_column(Text, nullable=True) + backtranslation_3: Mapped[str | None] = mapped_column(Text, nullable=True) + rationale_3: Mapped[str | None] = mapped_column(Text, nullable=True) + tm_entries_cited: Mapped[dict | None] = mapped_column(JSON, nullable=True) + winning_seg_key: Mapped[str | None] = mapped_column(String(255), nullable=True) + character_count_option_1: Mapped[int | None] = mapped_column(Integer, nullable=True) + character_count_option_2: Mapped[int | None] = mapped_column(Integer, nullable=True) + character_count_option_3: Mapped[int | None] = mapped_column(Integer, nullable=True) + + # Relationships + instance = relationship("LocaleInstance", back_populates="output_rows") + line = relationship("SourceLine", back_populates="output_rows") + feedback = relationship( + "Feedback", back_populates="output", lazy="selectin", cascade="all, delete-orphan" + ) diff --git a/backend/app/models/source.py b/backend/app/models/source.py new file mode 100644 index 0000000..7feeff8 --- /dev/null +++ b/backend/app/models/source.py @@ -0,0 +1,30 @@ +import uuid + +from sqlalchemy import Boolean, ForeignKey, Integer, String, Text +from sqlalchemy.orm import Mapped, mapped_column, relationship + +from app.models.base import Base, TimestampMixin, generate_uuid + + +class SourceLine(Base, TimestampMixin): + __tablename__ = "source_lines" + + id: Mapped[uuid.UUID] = mapped_column( + primary_key=True, default=generate_uuid + ) + job_id: Mapped[uuid.UUID] = mapped_column( + ForeignKey("jobs.id", ondelete="CASCADE"), nullable=False + ) + row_order: Mapped[int] = mapped_column(Integer, nullable=False) + en_gb: Mapped[str] = mapped_column(Text, nullable=False) + copy_type: Mapped[str | None] = mapped_column(String(100), nullable=True) + creative_guidance: Mapped[str | None] = mapped_column(Text, nullable=True) + visual_ref: Mapped[str | None] = mapped_column(String(500), nullable=True) + char_limit: Mapped[str | None] = mapped_column(String(50), nullable=True) + is_display_format: Mapped[bool] = mapped_column(Boolean, default=False) + + # Relationships + job = relationship("Job", back_populates="source_lines") + output_rows = relationship( + "OutputRow", back_populates="line", lazy="selectin", cascade="all, delete-orphan" + ) diff --git a/backend/app/models/user.py b/backend/app/models/user.py new file mode 100644 index 0000000..f9ba47d --- /dev/null +++ b/backend/app/models/user.py @@ -0,0 +1,60 @@ +import enum +import uuid + +from sqlalchemy import Enum, ForeignKey, String +from sqlalchemy.orm import Mapped, mapped_column, relationship + +from app.models.base import Base, TimestampMixin, generate_uuid + + +class UserRole(str, enum.Enum): + admin = "admin" + tm_manager = "tm_manager" + reviewer = "reviewer" + + +class UserStatus(str, enum.Enum): + active = "active" + inactive = "inactive" + + +class User(Base, TimestampMixin): + __tablename__ = "users" + + id: Mapped[uuid.UUID] = mapped_column( + primary_key=True, default=generate_uuid + ) + email: Mapped[str] = mapped_column(String(255), unique=True, nullable=False) + name: Mapped[str] = mapped_column(String(255), nullable=False) + password_hash: Mapped[str] = mapped_column(String(255), nullable=False) + role: Mapped[UserRole] = mapped_column( + Enum(UserRole, name="user_role", create_constraint=True), + nullable=False, + ) + status: Mapped[UserStatus] = mapped_column( + Enum(UserStatus, name="user_status", create_constraint=True), + default=UserStatus.active, + nullable=False, + ) + + # Relationships + user_clients = relationship("UserClient", back_populates="user", lazy="selectin") + jobs_created = relationship("Job", back_populates="creator", lazy="selectin") + feedback = relationship("Feedback", back_populates="user", lazy="selectin") + audit_logs = relationship("AuditLog", back_populates="user", lazy="selectin") + + +class UserClient(Base): + __tablename__ = "user_clients" + + user_id: Mapped[uuid.UUID] = mapped_column( + ForeignKey("users.id", ondelete="CASCADE"), primary_key=True + ) + client_id: Mapped[uuid.UUID] = mapped_column( + ForeignKey("clients.id", ondelete="CASCADE"), primary_key=True + ) + role_override: Mapped[str | None] = mapped_column(String(50), nullable=True) + + # Relationships + user = relationship("User", back_populates="user_clients") + client = relationship("Client", back_populates="user_clients") diff --git a/backend/app/pipeline/__init__.py b/backend/app/pipeline/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/pipeline/agents/__init__.py b/backend/app/pipeline/agents/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/pipeline/agents/agent_1_validator.py b/backend/app/pipeline/agents/agent_1_validator.py new file mode 100644 index 0000000..d7c1cca --- /dev/null +++ b/backend/app/pipeline/agents/agent_1_validator.py @@ -0,0 +1,106 @@ +"""Agent 1: Validator + +Validates source file, loads reference files, and builds the initial +PipelineContext. This agent is deterministic (no LLM call). +""" + +from typing import Any + +from app.pipeline.agents.base import BaseAgent +from app.pipeline.contracts import ( + FileManifest, + JobParams, + ParsedJob, + PipelineContext, + SourceLineContract, +) +from app.pipeline.modules.source_file_parser import parse_source_file +from app.pipeline.modules.ref_file_loader import load_all_reference_files + + +class Agent1Validator(BaseAgent): + """Validates inputs and builds the initial pipeline context.""" + + name = "agent_1_validator" + description = "Validates source file and reference files, builds ParsedJob" + + def __init__( + self, + source_file_path: str | None = None, + source_lines: list[dict] | None = None, + file_manifest: dict[str, str | None] | None = None, + job_params: dict[str, Any] | None = None, + ) -> None: + self.source_file_path = source_file_path + self.source_lines_raw = source_lines + self.file_manifest_raw = file_manifest or {} + self.job_params_raw = job_params or {} + + def get_system_prompt(self) -> str: + return "" # No LLM call for this agent + + def build_user_message(self, context: PipelineContext) -> str: + return "" # No LLM call for this agent + + def parse_response(self, response: str, context: PipelineContext) -> Any: + return None # No LLM call for this agent + + async def run(self, context: PipelineContext) -> PipelineContext: + """Validate inputs and populate the pipeline context. + + 1. Parse source file or use pre-parsed source lines + 2. Resolve and load reference files + 3. Build initial PipelineContext + """ + # Parse source lines + if self.source_lines_raw: + raw_lines = self.source_lines_raw + elif self.source_file_path: + raw_lines = parse_source_file(self.source_file_path) + else: + raw_lines = [] + + source_lines = [ + SourceLineContract( + line_id=str(i + 1), + row_order=i + 1, + en_gb=line.get("en_gb", ""), + copy_type=line.get("copy_type"), + creative_guidance=line.get("creative_guidance"), + visual_ref=line.get("visual_ref"), + char_limit=line.get("char_limit"), + is_display_format=line.get("is_display_format", False), + ) + for i, line in enumerate(raw_lines) + ] + + # Build file manifest + file_manifest = FileManifest( + tm_files=self.file_manifest_raw.get("tm_files", []), + glossary_file=self.file_manifest_raw.get("glossary_file"), + blacklist_file=self.file_manifest_raw.get("blacklist_file"), + tov_global_file=self.file_manifest_raw.get("tov_global_file"), + tov_supplement_file=self.file_manifest_raw.get("tov_supplement_file"), + locale_considerations_file=self.file_manifest_raw.get( + "locale_considerations_file" + ), + date_pct_formats_file=self.file_manifest_raw.get("date_pct_formats_file"), + ) + + # Load reference files (for validation) + if any([ + file_manifest.glossary_file, + file_manifest.blacklist_file, + file_manifest.date_pct_formats_file, + ]): + load_all_reference_files(self.file_manifest_raw) + + # Build job params + job_params = JobParams(**self.job_params_raw) + + # Update context + context.job_params = job_params + context.source_lines = source_lines + context.file_manifest = file_manifest + + return context diff --git a/backend/app/pipeline/agents/agent_2_tm_retrieval.py b/backend/app/pipeline/agents/agent_2_tm_retrieval.py new file mode 100644 index 0000000..95dd2a3 --- /dev/null +++ b/backend/app/pipeline/agents/agent_2_tm_retrieval.py @@ -0,0 +1,40 @@ +"""Agent 2: TM Retrieval (STUB) + +Retrieves Translation Memory matches for each source line. +Currently returns empty results as a stub. +""" + +from typing import Any + +from app.pipeline.agents.base import BaseAgent +from app.pipeline.contracts import PipelineContext, TMSweepResult + + +class Agent2TMRetrieval(BaseAgent): + """STUB: TM retrieval agent returning empty sweep results.""" + + name = "agent_2_tm_retrieval" + description = "Retrieves TM matches for source lines (STUB)" + + def get_system_prompt(self) -> str: + return "You are a Translation Memory retrieval agent." + + def build_user_message(self, context: PipelineContext) -> str: + return "Retrieve TM matches for the provided source lines." + + def parse_response(self, response: str, context: PipelineContext) -> Any: + return [] + + async def run(self, context: PipelineContext) -> PipelineContext: + """STUB: Return empty TM sweep results for all source lines.""" + context.tm_sweep_results = [ + TMSweepResult( + line_id=line.line_id, + confirmed_matches=[], + pass_4_triggered=False, + pass_4_result=None, + no_match=True, + ) + for line in context.source_lines + ] + return context diff --git a/backend/app/pipeline/agents/agent_3_ranker.py b/backend/app/pipeline/agents/agent_3_ranker.py new file mode 100644 index 0000000..568dd58 --- /dev/null +++ b/backend/app/pipeline/agents/agent_3_ranker.py @@ -0,0 +1,42 @@ +"""Agent 3: Ranker (STUB) + +Ranks TM matches and declares confidence tiers for each source line. +Currently returns LOW confidence for all lines as a stub. +""" + +from typing import Any + +from app.pipeline.agents.base import BaseAgent +from app.pipeline.contracts import PipelineContext, RankingDeclaration + + +class Agent3Ranker(BaseAgent): + """STUB: Ranking agent returning LOW confidence for all lines.""" + + name = "agent_3_ranker" + description = "Ranks TM matches and declares confidence (STUB)" + + def get_system_prompt(self) -> str: + return "You are a ranking and confidence declaration agent." + + def build_user_message(self, context: PipelineContext) -> str: + return "Rank the TM matches for each source line." + + def parse_response(self, response: str, context: PipelineContext) -> Any: + return [] + + async def run(self, context: PipelineContext) -> PipelineContext: + """STUB: Return LOW confidence ranking for all source lines.""" + context.ranking_declarations = [ + RankingDeclaration( + line_id=line.line_id, + winning_entry=None, + runner_ups=[], + confidence_tier="low", + option_count=3, + is_new_creative_line=True, + notes="STUB: No TM matches available", + ) + for line in context.source_lines + ] + return context diff --git a/backend/app/pipeline/agents/agent_4_transcreator.py b/backend/app/pipeline/agents/agent_4_transcreator.py new file mode 100644 index 0000000..932dbaa --- /dev/null +++ b/backend/app/pipeline/agents/agent_4_transcreator.py @@ -0,0 +1,55 @@ +"""Agent 4: Transcreator (STUB) + +Generates transcreation drafts for each source line. +Currently returns placeholder translations as a stub. +""" + +from typing import Any + +from app.pipeline.agents.base import BaseAgent +from app.pipeline.contracts import DraftOption, DraftOutput, PipelineContext + + +class Agent4Transcreator(BaseAgent): + """STUB: Transcreation agent returning placeholder translations.""" + + name = "agent_4_transcreator" + description = "Generates transcreation drafts (STUB)" + + def get_system_prompt(self) -> str: + return "You are a creative transcreation agent." + + def build_user_message(self, context: PipelineContext) -> str: + return "Generate transcreation drafts for each source line." + + def parse_response(self, response: str, context: PipelineContext) -> Any: + return [] + + async def run(self, context: PipelineContext) -> PipelineContext: + """STUB: Return placeholder translations for all source lines.""" + locale = context.job_params.locale_code + + context.draft_outputs = [ + DraftOutput( + line_id=line.line_id, + option_1=DraftOption( + text=f"[{locale}] {line.en_gb}", + backtranslation=line.en_gb, + rationale=f"STUB: Direct placeholder for '{line.en_gb[:50]}...'", + ), + option_2=DraftOption( + text=f"[{locale} alt] {line.en_gb}", + backtranslation=line.en_gb, + rationale="STUB: Alternative placeholder", + ), + option_3=DraftOption( + text=f"[{locale} creative] {line.en_gb}", + backtranslation=line.en_gb, + rationale="STUB: Creative placeholder", + ), + tm_entries_cited=[], + adaptations_applied=[], + ) + for line in context.source_lines + ] + return context diff --git a/backend/app/pipeline/agents/agent_5_compliance.py b/backend/app/pipeline/agents/agent_5_compliance.py new file mode 100644 index 0000000..f4d6198 --- /dev/null +++ b/backend/app/pipeline/agents/agent_5_compliance.py @@ -0,0 +1,52 @@ +"""Agent 5: Compliance Checker (STUB) + +Checks transcreation drafts against compliance rules. +Currently returns PASS for all lines as a stub. +""" + +from typing import Any + +from app.pipeline.agents.base import BaseAgent +from app.pipeline.contracts import ComplianceResult, PipelineContext +from app.pipeline.modules.character_counter import count_characters + + +class Agent5Compliance(BaseAgent): + """STUB: Compliance agent returning pass for all lines.""" + + name = "agent_5_compliance" + description = "Checks compliance of transcreation drafts (STUB)" + + def get_system_prompt(self) -> str: + return "You are a compliance checking agent." + + def build_user_message(self, context: PipelineContext) -> str: + return "Check compliance for all transcreation drafts." + + def parse_response(self, response: str, context: PipelineContext) -> Any: + return [] + + async def run(self, context: PipelineContext) -> PipelineContext: + """STUB: Return pass for all compliance checks, with character counts.""" + context.compliance_results = [] + + for draft in context.draft_outputs: + char_counts: dict[str, int] = {} + + if draft.option_1: + char_counts["option_1"] = count_characters(draft.option_1.text) + if draft.option_2: + char_counts["option_2"] = count_characters(draft.option_2.text) + if draft.option_3: + char_counts["option_3"] = count_characters(draft.option_3.text) + + context.compliance_results.append( + ComplianceResult( + line_id=draft.line_id, + passed=True, + violations=[], + character_counts=char_counts, + ) + ) + + return context diff --git a/backend/app/pipeline/agents/agent_6_formatter.py b/backend/app/pipeline/agents/agent_6_formatter.py new file mode 100644 index 0000000..17b4698 --- /dev/null +++ b/backend/app/pipeline/agents/agent_6_formatter.py @@ -0,0 +1,112 @@ +"""Agent 6: Formatter + +Generates the output xlsx file and builds output row data. +This agent is deterministic (no LLM call). +""" + +from datetime import datetime, timezone +from typing import Any +from uuid import uuid4 + +from app.pipeline.agents.base import BaseAgent +from app.pipeline.contracts import PipelineContext +from app.pipeline.modules.excel_writer import generate_output_xlsx +from app.config import settings + + +class Agent6Formatter(BaseAgent): + """Formats pipeline output into xlsx and structured data.""" + + name = "agent_6_formatter" + description = "Generates output xlsx and structured output rows" + + def __init__(self, output_dir: str | None = None) -> None: + self.output_dir = output_dir or settings.STORAGE_ROOT + + def get_system_prompt(self) -> str: + return "" # No LLM call + + def build_user_message(self, context: PipelineContext) -> str: + return "" # No LLM call + + def parse_response(self, response: str, context: PipelineContext) -> Any: + return None # No LLM call + + async def run(self, context: PipelineContext) -> PipelineContext: + """Generate output xlsx and return updated context with file path. + + Returns the context as-is (output rows are built by the orchestrator + for database persistence). The xlsx file is written to disk. + """ + job_id = context.job_params.job_id + locale_code = context.job_params.locale_code + + # Build source lines for excel + source_lines_data = [ + { + "row_order": sl.row_order, + "en_gb": sl.en_gb, + "copy_type": sl.copy_type or "", + } + for sl in context.source_lines + ] + + # Build output rows for excel + output_rows_data = [] + for i, draft in enumerate(context.draft_outputs): + row: dict[str, Any] = { + "row_order": i + 1, + "line_id": draft.line_id, + "option_1": draft.option_1.text if draft.option_1 else "", + "backtranslation_1": draft.option_1.backtranslation if draft.option_1 else "", + "rationale_1": draft.option_1.rationale if draft.option_1 else "", + } + if draft.option_2: + row["option_2"] = draft.option_2.text + row["backtranslation_2"] = draft.option_2.backtranslation + row["rationale_2"] = draft.option_2.rationale + if draft.option_3: + row["option_3"] = draft.option_3.text + row["backtranslation_3"] = draft.option_3.backtranslation + row["rationale_3"] = draft.option_3.rationale + + output_rows_data.append(row) + + # Build summary + compliance_counts = {"high": 0, "moderate": 0, "low": 0} + for ranking in context.ranking_declarations: + tier = ranking.confidence_tier + if tier in compliance_counts: + compliance_counts[tier] += 1 + + summary = { + "job_id": job_id, + "campaign_name": context.job_params.campaign_name, + "locale_code": locale_code, + "channel": context.job_params.channel, + "programme": context.job_params.programme, + "total_source_lines": len(context.source_lines), + "total_output_rows": len(output_rows_data), + "high_confidence": compliance_counts["high"], + "moderate_confidence": compliance_counts["moderate"], + "low_confidence": compliance_counts["low"], + "total_tokens": 0, + "estimated_cost": 0.0, + "agent_version": "1.0.0", + "generated_at": datetime.now(timezone.utc).isoformat(), + } + + # Generate xlsx + output_path = ( + f"{self.output_dir}/jobs/{job_id}/output/" + f"{locale_code}_{job_id}_output.xlsx" + ) + + generate_output_xlsx( + output_path=output_path, + source_lines=source_lines_data, + output_rows=output_rows_data, + summary=summary, + ) + + return context diff --git a/backend/app/pipeline/agents/base.py b/backend/app/pipeline/agents/base.py new file mode 100644 index 0000000..56d8894 --- /dev/null +++ b/backend/app/pipeline/agents/base.py @@ -0,0 +1,62 @@ +"""Base agent abstract class for the transcreation pipeline.""" + +from abc import ABC, abstractmethod +from typing import Any + +from app.pipeline.contracts import PipelineContext + + +class BaseAgent(ABC): + """Abstract base class for pipeline agents. + + Each agent in the pipeline implements this interface: + 1. get_system_prompt() - Returns the system prompt for the LLM + 2. build_user_message() - Builds the user message from pipeline context + 3. parse_response() - Parses the LLM response into structured data + 4. run() - Orchestrates the agent's execution + """ + + name: str = "base_agent" + description: str = "" + + @abstractmethod + def get_system_prompt(self) -> str: + """Return the system prompt for this agent's LLM call.""" + ... + + @abstractmethod + def build_user_message(self, context: PipelineContext) -> str: + """Build the user message from pipeline context. + + Args: + context: The current pipeline context. + + Returns: + The user message string to send to the LLM. + """ + ... + + @abstractmethod + def parse_response(self, response: str, context: PipelineContext) -> Any: + """Parse the LLM response into structured data. + + Args: + response: The raw LLM response text. + context: The current pipeline context. + + Returns: + Structured data appropriate for this agent's output. + """ + ... + + @abstractmethod + async def run(self, context: PipelineContext) -> PipelineContext: + """Execute this agent and return the updated pipeline context. + + Args: + context: The current pipeline context. + + Returns: + Updated pipeline context with this agent's results. + """ + ... diff --git a/backend/app/pipeline/agents/prompts/__init__.py b/backend/app/pipeline/agents/prompts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/pipeline/contracts.py b/backend/app/pipeline/contracts.py new file mode 100644 index 0000000..024ff3e --- /dev/null +++ b/backend/app/pipeline/contracts.py @@ -0,0 +1,139 @@ +"""Pipeline data contracts - Pydantic models for inter-agent communication.""" + +from typing import Any + +from pydantic import BaseModel + + +class TMEntry(BaseModel): + """A single Translation Memory entry.""" + seg_key: str + date: str + en: str + lc: str + tx: str + nt: str = "" + channel: str = "" + sub_channel: str = "" + _text: str = "" + + model_config = {"from_attributes": True} + + +class SourceLineContract(BaseModel): + """A parsed source line from the input xlsx.""" + line_id: str + row_order: int + en_gb: str + copy_type: str | None = None + creative_guidance: str | None = None + visual_ref: str | None = None + char_limit: str | None = None + is_display_format: bool = False + + +class FileManifest(BaseModel): + """Manifest of all files loaded for a job.""" + tm_files: list[str] = [] + glossary_file: str | None = None + blacklist_file: str | None = None + tov_global_file: str | None = None + tov_supplement_file: str | None = None + locale_considerations_file: str | None = None + date_pct_formats_file: str | None = None + + +class JobParams(BaseModel): + """Parameters for a transcreation job.""" + job_id: str + client_id: str + locale_code: str + channel: str + sub_channel: str | None = None + programme: str + campaign_name: str + context_prompt: str | None = None + + +class ParsedJob(BaseModel): + """Output of Agent 1 (Validator): validated job parameters + source.""" + job_params: JobParams + source_lines: list[SourceLineContract] + file_manifest: FileManifest + + +class ConfirmedMatch(BaseModel): + """A confirmed TM match for a source line.""" + seg_key: str + pass_found: int + date: str + en: str + tx: str + nt: str = "" + channel: str = "" + sub_channel: str = "" + is_cross_channel: bool = False + + +class TMSweepResult(BaseModel): + """TM sweep results for a single source line.""" + line_id: str + confirmed_matches: list[ConfirmedMatch] = [] + pass_4_triggered: bool = False + pass_4_result: ConfirmedMatch | None = None + no_match: bool = False + + +class RankingDeclaration(BaseModel): + """Ranking decision for a single source line.""" + line_id: str + winning_entry: ConfirmedMatch | None = None + runner_ups: list[ConfirmedMatch] = [] + confidence_tier: str = "low" + option_count: int = 3 + is_new_creative_line: bool = False + notes: str = "" + + +class DraftOption(BaseModel): + """A single draft transcreation option.""" + text: str + backtranslation: str + rationale: str + + +class DraftOutput(BaseModel): + """Transcreation draft output for a single source line.""" + line_id: str + option_1: DraftOption + option_2: DraftOption | None = None + option_3: DraftOption | None = None + tm_entries_cited: list[str] = [] + adaptations_applied: list[str] = [] + + +class ComplianceViolation(BaseModel): + """A single compliance violation found during checking.""" + type: str + option_affected: int + description: str + severity: str = "warning" + + +class ComplianceResult(BaseModel): + """Compliance check result for a single source line.""" + line_id: str + passed: bool + violations: list[ComplianceViolation] = [] + character_counts: dict[str, int] = {} + + +class PipelineContext(BaseModel): + """Full pipeline context passed between agents.""" + job_params: JobParams + source_lines: list[SourceLineContract] = [] + file_manifest: FileManifest = FileManifest() + tm_sweep_results: list[TMSweepResult] = [] + ranking_declarations: list[RankingDeclaration] = [] + draft_outputs: list[DraftOutput] = [] + compliance_results: list[ComplianceResult] = [] diff --git a/backend/app/pipeline/modules/__init__.py b/backend/app/pipeline/modules/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/pipeline/modules/blacklist_scanner.py b/backend/app/pipeline/modules/blacklist_scanner.py new file mode 100644 index 0000000..218e97f --- /dev/null +++ b/backend/app/pipeline/modules/blacklist_scanner.py @@ -0,0 +1,108 @@ +"""Blacklist scanner for forbidden terms and brand violations. + +Supports: +- Exact match: term appears as-is in the text (case-insensitive). +- Root-based match: checks if the root/stem of a blacklisted term appears. +""" + +import re +from dataclasses import dataclass + + +@dataclass +class BlacklistViolation: + """A detected blacklist violation.""" + term: str + match_type: str # "exact" or "root" + position: int # character position in text + context: str # surrounding text + + +def scan_text( + text: str, + blacklist_entries: list[dict], +) -> list[BlacklistViolation]: + """Scan text against blacklist entries for violations. + + Args: + text: The text to scan. + blacklist_entries: List of dicts with keys: + - term: str (the forbidden term) + - root: str | None (optional root form for root-based matching) + - severity: str (optional) + + Returns: + List of BlacklistViolation instances found. + """ + if not text or not blacklist_entries: + return [] + + violations: list[BlacklistViolation] = [] + text_lower = text.lower() + + for entry in blacklist_entries: + term = entry.get("term", "").strip() + if not term: + continue + + root = entry.get("root", "").strip() if entry.get("root") else None + + # Exact match (case-insensitive, word boundary) + pattern = re.compile(r"\b" + re.escape(term) + r"\b", re.IGNORECASE) + for match in pattern.finditer(text): + start = max(0, match.start() - 20) + end = min(len(text), match.end() + 20) + violations.append( + BlacklistViolation( + term=term, + match_type="exact", + position=match.start(), + context=text[start:end], + ) + ) + + # Root-based match + if root: + root_pattern = re.compile( + r"\b" + re.escape(root) + r"\w*\b", re.IGNORECASE + ) + for match in root_pattern.finditer(text): + # Skip if this is already caught as an exact match + matched_text = match.group().lower() + if matched_text == term.lower(): + continue + + start = max(0, match.start() - 20) + end = min(len(text), match.end() + 20) + violations.append( + BlacklistViolation( + term=term, + match_type="root", + position=match.start(), + context=text[start:end], + ) + ) + + return violations + + +def scan_all_options( + options: list[str], + blacklist_entries: list[dict], +) -> dict[int, list[BlacklistViolation]]: + """Scan multiple text options against the blacklist. + + Args: + options: List of text options to scan (index 0 = option 1, etc.) + blacklist_entries: The blacklist entries. + + Returns: + Dict mapping option index (1-based) to violations found. + """ + results: dict[int, list[BlacklistViolation]] = {} + for i, option_text in enumerate(options): + if option_text: + violations = scan_text(option_text, blacklist_entries) + if violations: + results[i + 1] = violations + return results diff --git a/backend/app/pipeline/modules/character_counter.py b/backend/app/pipeline/modules/character_counter.py new file mode 100644 index 0000000..8f73b18 --- /dev/null +++ b/backend/app/pipeline/modules/character_counter.py @@ -0,0 +1,67 @@ +"""Unicode grapheme cluster character counting. + +Uses the grapheme library for accurate character counting that handles +multi-codepoint characters (emoji, combining marks, etc.) correctly. + +Rules: +- Strip leading/trailing whitespace before counting. +- Line breaks (\\n) count as 0 characters. +""" + +import grapheme + + +def count_characters(text: str) -> int: + """Count grapheme clusters in a string, excluding line breaks. + + Args: + text: The text to count characters in. + + Returns: + Number of grapheme clusters (visible characters), excluding line breaks. + """ + if not text: + return 0 + + # Strip whitespace + cleaned = text.strip() + + # Remove line breaks (they count as 0) + cleaned = cleaned.replace("\n", "").replace("\r", "") + + return grapheme.length(cleaned) + + +def check_character_limit(text: str, char_limit: str | None) -> tuple[int, bool]: + """Count characters and check against a limit. + + Args: + text: The text to measure. + char_limit: The character limit as a string (may be numeric or range like "20-30"). + + Returns: + Tuple of (character_count, within_limit). If no limit is set, within_limit is True. + """ + count = count_characters(text) + + if not char_limit: + return count, True + + char_limit = char_limit.strip() + + # Handle range format "20-30" + if "-" in char_limit: + parts = char_limit.split("-") + try: + lower = int(parts[0].strip()) + upper = int(parts[1].strip()) + return count, lower <= count <= upper + except (ValueError, IndexError): + return count, True + + # Handle simple numeric limit + try: + limit = int(char_limit) + return count, count <= limit + except ValueError: + return count, True diff --git a/backend/app/pipeline/modules/date_format_validator.py b/backend/app/pipeline/modules/date_format_validator.py new file mode 100644 index 0000000..62783f4 --- /dev/null +++ b/backend/app/pipeline/modules/date_format_validator.py @@ -0,0 +1,121 @@ +"""Validate date and percentage format strings against approved locale formats. + +Checks that dates and percentages in transcreated text conform to the +locale-specific format rules defined in the date/percentage format file. +""" + +import re +from dataclasses import dataclass + + +@dataclass +class FormatViolation: + """A detected date/percentage format violation.""" + found: str + expected_format: str + description: str + + +def validate_date_formats( + text: str, + approved_formats: list[dict], +) -> list[FormatViolation]: + """Validate date strings in text against approved formats. + + Args: + text: The text containing dates to validate. + approved_formats: List of dicts with keys: + - pattern: str (regex pattern for valid format) + - example: str (example of the correct format) + - description: str + + Returns: + List of FormatViolation instances. + """ + if not text or not approved_formats: + return [] + + violations: list[FormatViolation] = [] + + # Common date-like patterns to detect + date_patterns = [ + # DD/MM/YYYY, MM/DD/YYYY, YYYY/MM/DD + r"\b\d{1,2}[/\-.]\d{1,2}[/\-.]\d{2,4}\b", + # Month DD, YYYY + r"\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\.?\s+\d{1,2},?\s+\d{4}\b", + # DD Month YYYY + r"\b\d{1,2}\s+(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\.?\s+\d{4}\b", + ] + + for date_pattern in date_patterns: + for match in re.finditer(date_pattern, text, re.IGNORECASE): + found_date = match.group() + is_valid = False + + for fmt in approved_formats: + pattern = fmt.get("pattern", "") + if pattern and re.match(pattern, found_date, re.IGNORECASE): + is_valid = True + break + + if not is_valid and approved_formats: + examples = [ + fmt.get("example", "") for fmt in approved_formats if fmt.get("example") + ] + violations.append( + FormatViolation( + found=found_date, + expected_format=", ".join(examples[:3]), + description=f"Date format '{found_date}' does not match approved formats", + ) + ) + + return violations + + +def validate_percentage_formats( + text: str, + approved_formats: list[dict], +) -> list[FormatViolation]: + """Validate percentage strings in text against approved formats. + + Args: + text: The text containing percentages to validate. + approved_formats: List of dicts with keys: + - pattern: str (regex) + - example: str + - description: str + + Returns: + List of FormatViolation instances. + """ + if not text or not approved_formats: + return [] + + violations: list[FormatViolation] = [] + + # Find percentage-like patterns + pct_pattern = r"\b\d+[\.,]?\d*\s*[%%]\b" + for match in re.finditer(pct_pattern, text): + found_pct = match.group() + is_valid = False + + for fmt in approved_formats: + pattern = fmt.get("pattern", "") + if pattern and re.match(pattern, found_pct): + is_valid = True + break + + if not is_valid and approved_formats: + examples = [ + fmt.get("example", "") for fmt in approved_formats if fmt.get("example") + ] + violations.append( + FormatViolation( + found=found_pct, + expected_format=", ".join(examples[:3]), + description=f"Percentage format '{found_pct}' does not match approved formats", + ) + ) + + return violations diff --git a/backend/app/pipeline/modules/domain_substitutor.py b/backend/app/pipeline/modules/domain_substitutor.py new file mode 100644 index 0000000..07e821f --- /dev/null +++ b/backend/app/pipeline/modules/domain_substitutor.py @@ -0,0 +1,110 @@ +"""Domain substitution for Amazon locales. + +Maps Amazon.co.uk (source domain) to the correct locale-specific domain. +Handles both full domain URLs and bare "Amazon" references. + +Emerging locales: bare "Amazon" stays as "Amazon" +Non-emerging locales: bare "Amazon" -> locale-specific brand name rules apply +""" + +# Full domain map for all 12 supported locales +DOMAIN_MAP: dict[str, str] = { + "de_DE": "Amazon.de", + "fr_FR": "Amazon.fr", + "it_IT": "Amazon.it", + "es_ES": "Amazon.es", + "nl_NL": "Amazon.nl", + "pl_PL": "Amazon.pl", + "sv_SE": "Amazon.se", + "pt_BR": "Amazon.com.br", + "ja_JP": "Amazon.co.jp", + "en_AU": "Amazon.com.au", + "en_SG": "Amazon.sg", + "ar_AE": "Amazon.ae", +} + +# Emerging locales where bare "Amazon" stays as-is +EMERGING_LOCALES: set[str] = { + "pl_PL", + "sv_SE", + "nl_NL", + "ar_AE", + "en_SG", +} + +# Source domain to replace +SOURCE_DOMAIN = "Amazon.co.uk" +SOURCE_DOMAIN_LOWER = SOURCE_DOMAIN.lower() + + +def substitute_domains(text: str, locale_code: str) -> str: + """Replace Amazon.co.uk with the locale-specific domain. + + Args: + text: The text containing domain references. + locale_code: The target locale code (e.g., "de_DE"). + + Returns: + Text with domains substituted. + """ + if not text: + return text + + target_domain = DOMAIN_MAP.get(locale_code) + if target_domain is None: + return text + + # Replace full domain (case-insensitive) + result = text + idx = 0 + while True: + lower_result = result.lower() + pos = lower_result.find(SOURCE_DOMAIN_LOWER, idx) + if pos == -1: + break + result = result[:pos] + target_domain + result[pos + len(SOURCE_DOMAIN):] + idx = pos + len(target_domain) + + return result + + +def substitute_bare_amazon(text: str, locale_code: str) -> str: + """Handle bare 'Amazon' references based on locale type. + + For emerging locales: leave bare 'Amazon' as-is. + For non-emerging locales: append locale domain context if needed. + + Args: + text: The text with potential bare Amazon references. + locale_code: The target locale code. + + Returns: + Text with bare Amazon references handled. + """ + if not text: + return text + + if locale_code in EMERGING_LOCALES: + # Emerging locales: bare Amazon stays as Amazon + return text + + # For non-emerging locales, bare "Amazon" (not followed by .) + # is kept as-is since it's the brand name + return text + + +def get_locale_domain(locale_code: str) -> str | None: + """Get the domain for a locale code. + + Args: + locale_code: The target locale code. + + Returns: + The domain string or None if locale is not supported. + """ + return DOMAIN_MAP.get(locale_code) + + +def is_emerging_locale(locale_code: str) -> bool: + """Check if a locale is classified as emerging.""" + return locale_code in EMERGING_LOCALES diff --git a/backend/app/pipeline/modules/excel_writer.py b/backend/app/pipeline/modules/excel_writer.py new file mode 100644 index 0000000..1b47800 --- /dev/null +++ b/backend/app/pipeline/modules/excel_writer.py @@ -0,0 +1,184 @@ +"""Generate output xlsx files with structured output and summary tabs. + +Tab 1: 11-column output table +Tab 2: Transcreation Summary + +Column widths and formatting per specification. +""" + +from pathlib import Path +from typing import Any + +from openpyxl import Workbook +from openpyxl.styles import Alignment, Font, PatternFill +from openpyxl.utils import get_column_letter + +from app.pipeline.modules.line_break_normaliser import normalise_for_excel + +# Tab 1 column definitions +OUTPUT_COLUMNS = [ + ("EN_GB", 40), + ("Copy Type", 15), + ("Option 1", 40), + ("Back-translation 1", 40), + ("Rationale 1", 35), + ("Option 2", 40), + ("Back-translation 2", 40), + ("Rationale 2", 35), + ("Option 3", 40), + ("Back-translation 3", 40), + ("Rationale 3", 35), +] + +# Header style +HEADER_FONT = Font(bold=True, size=11, color="FFFFFF") +HEADER_FILL = PatternFill(start_color="232F3E", end_color="232F3E", fill_type="solid") +HEADER_ALIGNMENT = Alignment(horizontal="center", vertical="center", wrap_text=True) + +# Data style +DATA_ALIGNMENT = Alignment(vertical="top", wrap_text=True) + + +def generate_output_xlsx( + output_path: str, + source_lines: list[dict[str, Any]], + output_rows: list[dict[str, Any]], + summary: dict[str, Any] | None = None, +) -> str: + """Generate the output xlsx file. + + Args: + output_path: Absolute path where the xlsx should be saved. + source_lines: List of source line dicts (en_gb, copy_type, etc.). + output_rows: List of output row dicts with options, backtranslations, rationales. + summary: Optional summary data for Tab 2. + + Returns: + The absolute path to the generated file. + """ + wb = Workbook() + + # ---- Tab 1: Output Table ---- + ws1 = wb.active + ws1.title = "Transcreation Output" + + # Write headers + for col_idx, (header, width) in enumerate(OUTPUT_COLUMNS, start=1): + cell = ws1.cell(row=1, column=col_idx, value=header) + cell.font = HEADER_FONT + cell.fill = HEADER_FILL + cell.alignment = HEADER_ALIGNMENT + ws1.column_dimensions[get_column_letter(col_idx)].width = width + + # Write data rows + for row_idx, output_row in enumerate(output_rows, start=2): + # Find matching source line + source_line = _find_source_line(source_lines, output_row) + + ws1.cell( + row=row_idx, column=1, + value=normalise_for_excel(source_line.get("en_gb", "")), + ).alignment = DATA_ALIGNMENT + + ws1.cell( + row=row_idx, column=2, + value=source_line.get("copy_type", ""), + ).alignment = DATA_ALIGNMENT + + # Option 1 + ws1.cell( + row=row_idx, column=3, + value=normalise_for_excel(output_row.get("option_1", "")), + ).alignment = DATA_ALIGNMENT + ws1.cell( + row=row_idx, column=4, + value=normalise_for_excel(output_row.get("backtranslation_1", "")), + ).alignment = DATA_ALIGNMENT + ws1.cell( + row=row_idx, column=5, + value=output_row.get("rationale_1", ""), + ).alignment = DATA_ALIGNMENT + + # Option 2 + ws1.cell( + row=row_idx, column=6, + value=normalise_for_excel(output_row.get("option_2", "")), + ).alignment = DATA_ALIGNMENT + ws1.cell( + row=row_idx, column=7, + value=normalise_for_excel(output_row.get("backtranslation_2", "")), + ).alignment = DATA_ALIGNMENT + ws1.cell( + row=row_idx, column=8, + value=output_row.get("rationale_2", ""), + ).alignment = DATA_ALIGNMENT + + # Option 3 + ws1.cell( + row=row_idx, column=9, + value=normalise_for_excel(output_row.get("option_3", "")), + ).alignment = DATA_ALIGNMENT + ws1.cell( + row=row_idx, column=10, + value=normalise_for_excel(output_row.get("backtranslation_3", "")), + ).alignment = DATA_ALIGNMENT + ws1.cell( + row=row_idx, column=11, + value=output_row.get("rationale_3", ""), + ).alignment = DATA_ALIGNMENT + + # ---- Tab 2: Transcreation Summary ---- + ws2 = wb.create_sheet("Transcreation Summary") + + summary_data = summary or {} + summary_rows = [ + ("Job ID", summary_data.get("job_id", "")), + ("Campaign", summary_data.get("campaign_name", "")), + ("Locale", summary_data.get("locale_code", "")), + ("Channel", summary_data.get("channel", "")), + ("Programme", summary_data.get("programme", "")), + ("Total Source Lines", summary_data.get("total_source_lines", 0)), + ("Total Output Rows", summary_data.get("total_output_rows", 0)), + ("High Confidence", summary_data.get("high_confidence", 0)), + ("Moderate Confidence", summary_data.get("moderate_confidence", 0)), + ("Low Confidence", summary_data.get("low_confidence", 0)), + ("Total Tokens Used", summary_data.get("total_tokens", 0)), + ("Estimated Cost (USD)", summary_data.get("estimated_cost", 0.0)), + ("Agent Version", summary_data.get("agent_version", "")), + ("Generated At", summary_data.get("generated_at", "")), + ] + + ws2.column_dimensions["A"].width = 25 + ws2.column_dimensions["B"].width = 40 + + for row_idx, (label, value) in enumerate(summary_rows, start=1): + label_cell = ws2.cell(row=row_idx, column=1, value=label) + label_cell.font = Font(bold=True) + ws2.cell(row=row_idx, column=2, value=str(value)) + + # Save + Path(output_path).parent.mkdir(parents=True, exist_ok=True) + wb.save(output_path) + wb.close() + + return output_path + + +def _find_source_line( + source_lines: list[dict[str, Any]], output_row: dict[str, Any] +) -> dict[str, Any]: + """Find the source line matching an output row by row_order or line_id.""" + row_order = output_row.get("row_order") + line_id = output_row.get("line_id") + + for sl in source_lines: + if line_id and sl.get("id") == line_id: + return sl + if row_order is not None and sl.get("row_order") == row_order: + return sl + + # Fallback: match by index + if row_order is not None and 0 < row_order <= len(source_lines): + return source_lines[row_order - 1] + + return {} diff --git a/backend/app/pipeline/modules/line_break_normaliser.py b/backend/app/pipeline/modules/line_break_normaliser.py new file mode 100644 index 0000000..53c66ed --- /dev/null +++ b/backend/app/pipeline/modules/line_break_normaliser.py @@ -0,0 +1,67 @@ +"""Line break normalisation utilities. + +Three modes: +- normalise_for_query: Strip line breaks, collapse multiple spaces to single. + Used when building search queries against TM. +- normalise_for_excel: Convert \\n to openpyxl-compatible line breaks. + Used when writing output cells. +- preserve_raw: Return text as-is (identity function for pipeline clarity). +""" + +import re + + +def normalise_for_query(text: str) -> str: + """Strip line breaks and collapse spaces for TM query matching. + + Args: + text: Raw text potentially containing line breaks. + + Returns: + Single-line text with normalised whitespace. + """ + if not text: + return "" + + # Replace all line break variants with a space + result = text.replace("\r\n", " ").replace("\r", " ").replace("\n", " ") + + # Collapse multiple spaces to one + result = re.sub(r"\s+", " ", result) + + return result.strip() + + +def normalise_for_excel(text: str) -> str: + """Convert line breaks to openpyxl-compatible format. + + openpyxl uses \\n for in-cell line breaks when wrap_text is enabled. + This ensures consistent line break representation. + + Args: + text: Text with potential line breaks. + + Returns: + Text with standardised \\n line breaks. + """ + if not text: + return "" + + # Normalise all line break variants to \\n + result = text.replace("\r\n", "\n").replace("\r", "\n") + + return result + + +def preserve_raw(text: str) -> str: + """Return text as-is (identity function). + + Used in the pipeline to explicitly indicate no normalisation is applied. + + Args: + text: Any text. + + Returns: + The same text, unchanged. + """ + return text diff --git a/backend/app/pipeline/modules/ref_file_loader.py b/backend/app/pipeline/modules/ref_file_loader.py new file mode 100644 index 0000000..cb0d633 --- /dev/null +++ b/backend/app/pipeline/modules/ref_file_loader.py @@ -0,0 +1,177 @@ +"""Reference file loader. + +Loads various reference files used in the transcreation pipeline: +- Glossary (JSON): locale-specific term glossary +- Blacklist (JSON): forbidden terms and roots +- Date/Percentage formats (JSON): approved format patterns +- Locale Considerations (JSON): locale-specific rules and notes +- TOV (Tone of Voice) files (JSON): global and supplementary voice profiles +""" + +import json +from pathlib import Path +from typing import Any + + +class RefFileLoadError(Exception): + """Raised when a reference file cannot be loaded or parsed.""" + pass + + +def load_json_file(file_path: str) -> Any: + """Load and parse a JSON file. + + Args: + file_path: Absolute path to the JSON file. + + Returns: + Parsed JSON data. + + Raises: + RefFileLoadError: If file cannot be read or parsed. + """ + path = Path(file_path) + if not path.exists(): + raise RefFileLoadError(f"Reference file not found: {file_path}") + + try: + with open(path, "r", encoding="utf-8") as f: + return json.load(f) + except json.JSONDecodeError as exc: + raise RefFileLoadError(f"Invalid JSON in reference file: {exc}") + except UnicodeDecodeError as exc: + raise RefFileLoadError(f"Encoding error reading reference file: {exc}") + + +def load_glossary(file_path: str) -> list[dict[str, str]]: + """Load a glossary file. + + Expected format: list of dicts with keys like: + {"en": "source term", "tx": "translated term", "context": "usage notes"} + + Args: + file_path: Path to glossary JSON file. + + Returns: + List of glossary entry dicts. + """ + data = load_json_file(file_path) + if not isinstance(data, list): + raise RefFileLoadError("Glossary file must contain a JSON array") + return data + + +def load_blacklist(file_path: str) -> list[dict[str, str]]: + """Load a blacklist file. + + Expected format: list of dicts with keys: + {"term": "forbidden term", "root": "optional root", "reason": "why forbidden"} + + Args: + file_path: Path to blacklist JSON file. + + Returns: + List of blacklist entry dicts. + """ + data = load_json_file(file_path) + if not isinstance(data, list): + raise RefFileLoadError("Blacklist file must contain a JSON array") + return data + + +def load_date_pct_formats(file_path: str) -> dict[str, list[dict[str, str]]]: + """Load date/percentage format rules. + + Expected format: + { + "date_formats": [{"pattern": "...", "example": "...", "description": "..."}], + "percentage_formats": [{"pattern": "...", "example": "...", "description": "..."}] + } + + Args: + file_path: Path to date/pct formats JSON file. + + Returns: + Dict with "date_formats" and "percentage_formats" keys. + """ + data = load_json_file(file_path) + if not isinstance(data, dict): + raise RefFileLoadError("Date/pct format file must contain a JSON object") + return { + "date_formats": data.get("date_formats", []), + "percentage_formats": data.get("percentage_formats", []), + } + + +def load_locale_considerations(file_path: str) -> dict[str, Any]: + """Load locale-specific considerations. + + Expected format: JSON object with locale-specific rules, cultural notes, etc. + + Args: + file_path: Path to locale considerations JSON file. + + Returns: + Dict of locale considerations. + """ + data = load_json_file(file_path) + if not isinstance(data, dict): + raise RefFileLoadError( + "Locale considerations file must contain a JSON object" + ) + return data + + +def load_tov(file_path: str) -> dict[str, Any]: + """Load a Tone of Voice file (global or supplement). + + Expected format: JSON object with voice profile data. + + Args: + file_path: Path to TOV JSON file. + + Returns: + Dict of TOV profile data. + """ + data = load_json_file(file_path) + if not isinstance(data, dict): + raise RefFileLoadError("TOV file must contain a JSON object") + return data + + +def load_all_reference_files( + file_manifest: dict[str, str | None], +) -> dict[str, Any]: + """Load all reference files from a file manifest. + + Args: + file_manifest: Dict mapping file types to file paths. + Keys: glossary_file, blacklist_file, tov_global_file, + tov_supplement_file, locale_considerations_file, + date_pct_formats_file + + Returns: + Dict mapping file types to loaded data. + """ + result: dict[str, Any] = {} + + loaders = { + "glossary_file": load_glossary, + "blacklist_file": load_blacklist, + "date_pct_formats_file": load_date_pct_formats, + "locale_considerations_file": load_locale_considerations, + "tov_global_file": load_tov, + "tov_supplement_file": load_tov, + } + + for key, loader in loaders.items(): + path = file_manifest.get(key) + if path: + try: + result[key] = loader(path) + except RefFileLoadError: + result[key] = None + else: + result[key] = None + + return result diff --git a/backend/app/pipeline/modules/source_file_parser.py b/backend/app/pipeline/modules/source_file_parser.py new file mode 100644 index 0000000..724629d --- /dev/null +++ b/backend/app/pipeline/modules/source_file_parser.py @@ -0,0 +1,97 @@ +"""Parse source xlsx files into structured source line data. + +Validates the expected 5 column headers (case sensitive): +EN_GB, Copy Type, Creative Guidance, Visual Ref, Char Limit + +Skips rows where EN_GB is empty. Detects \\n in EN_GB for is_display_format. +""" + +from typing import Any + +from openpyxl import load_workbook + +REQUIRED_HEADERS = ["EN_GB", "Copy Type", "Creative Guidance", "Visual Ref", "Char Limit"] + + +class SourceFileParseError(Exception): + """Raised when the source file has validation errors.""" + pass + + +def parse_source_file(file_path: str) -> list[dict[str, Any]]: + """Parse a source xlsx file and return a list of source line dicts. + + Args: + file_path: Absolute path to the xlsx file. + + Returns: + List of dicts with keys: en_gb, copy_type, creative_guidance, + visual_ref, char_limit, is_display_format. + + Raises: + SourceFileParseError: If headers are invalid or file cannot be read. + """ + try: + wb = load_workbook(file_path, read_only=True, data_only=True) + except Exception as exc: + raise SourceFileParseError(f"Cannot open xlsx file: {exc}") + + ws = wb.active + if ws is None: + raise SourceFileParseError("Workbook has no active sheet") + + # Read and validate headers from first row + rows = ws.iter_rows(min_row=1, max_row=1, values_only=True) + first_row = next(rows, None) + if first_row is None: + raise SourceFileParseError("File is empty - no header row found") + + headers = [str(cell).strip() if cell else "" for cell in first_row] + + # Validate all required headers exist (case sensitive) + for required in REQUIRED_HEADERS: + if required not in headers: + raise SourceFileParseError( + f"Missing required header '{required}'. " + f"Found headers: {headers}. " + f"Expected: {REQUIRED_HEADERS}" + ) + + # Build column index map + col_map = {header: idx for idx, header in enumerate(headers)} + + # Parse data rows + source_lines: list[dict[str, Any]] = [] + for row in ws.iter_rows(min_row=2, values_only=True): + en_gb_idx = col_map["EN_GB"] + en_gb_raw = row[en_gb_idx] if en_gb_idx < len(row) else None + + # Skip rows where EN_GB is empty + if en_gb_raw is None or str(en_gb_raw).strip() == "": + continue + + en_gb = str(en_gb_raw).strip() + + # Detect display format: presence of \n in EN_GB text + is_display_format = "\n" in en_gb + + def _get_cell(header: str) -> str | None: + idx = col_map.get(header) + if idx is None or idx >= len(row): + return None + val = row[idx] + if val is None: + return None + return str(val).strip() or None + + source_lines.append({ + "en_gb": en_gb, + "copy_type": _get_cell("Copy Type"), + "creative_guidance": _get_cell("Creative Guidance"), + "visual_ref": _get_cell("Visual Ref"), + "char_limit": _get_cell("Char Limit"), + "is_display_format": is_display_format, + }) + + wb.close() + return source_lines diff --git a/backend/app/pipeline/modules/tm_file_loader.py b/backend/app/pipeline/modules/tm_file_loader.py new file mode 100644 index 0000000..5554f33 --- /dev/null +++ b/backend/app/pipeline/modules/tm_file_loader.py @@ -0,0 +1,133 @@ +"""Translation Memory file loader. + +Reads JSONL files in two formats: +1. Compact: {"t": "seg_key|date|en|lc|tx|nt|channel|sub_channel"} +2. Multi-field: {"seg_key": "...", "date": "...", "en": "...", ...} + +Applies a locale hard-match gate: only entries matching the target locale are returned. +""" + +import json +from typing import Any + +from app.pipeline.contracts import TMEntry + + +class TMFileLoadError(Exception): + """Raised when a TM file cannot be loaded or parsed.""" + pass + + +def load_tm_file( + file_path: str, + target_locale: str, +) -> list[TMEntry]: + """Load and parse a JSONL TM file, filtering by locale. + + Args: + file_path: Absolute path to the JSONL file. + target_locale: Target locale code (e.g., "de_DE"). Only entries + matching this locale will be returned. + + Returns: + List of TMEntry objects matching the target locale. + + Raises: + TMFileLoadError: If the file cannot be read or parsed. + """ + entries: list[TMEntry] = [] + + try: + with open(file_path, "r", encoding="utf-8") as f: + for line_num, line in enumerate(f, start=1): + line = line.strip() + if not line: + continue + + try: + data = json.loads(line) + except json.JSONDecodeError as exc: + raise TMFileLoadError( + f"Invalid JSON on line {line_num}: {exc}" + ) + + entry = _parse_entry(data, line_num) + if entry is None: + continue + + # Locale hard-match gate + if entry.lc == target_locale: + entries.append(entry) + + except FileNotFoundError: + raise TMFileLoadError(f"TM file not found: {file_path}") + except UnicodeDecodeError as exc: + raise TMFileLoadError(f"Encoding error reading TM file: {exc}") + + return entries + + +def _parse_entry(data: dict[str, Any], line_num: int) -> TMEntry | None: + """Parse a single JSON object into a TMEntry. + + Detects compact vs multi-field format automatically. + + Args: + data: Parsed JSON dict. + line_num: Line number for error reporting. + + Returns: + TMEntry or None if the entry is malformed. + """ + # Compact format: {"t": "seg_key|date|en|lc|tx|nt|channel|sub_channel"} + if "t" in data and isinstance(data["t"], str): + parts = data["t"].split("|") + if len(parts) < 5: + return None # Malformed compact entry + + return TMEntry( + seg_key=parts[0] if len(parts) > 0 else "", + date=parts[1] if len(parts) > 1 else "", + en=parts[2] if len(parts) > 2 else "", + lc=parts[3] if len(parts) > 3 else "", + tx=parts[4] if len(parts) > 4 else "", + nt=parts[5] if len(parts) > 5 else "", + channel=parts[6] if len(parts) > 6 else "", + sub_channel=parts[7] if len(parts) > 7 else "", + _text=data["t"], + ) + + # Multi-field format + if "seg_key" in data and "en" in data: + return TMEntry( + seg_key=str(data.get("seg_key", "")), + date=str(data.get("date", "")), + en=str(data.get("en", "")), + lc=str(data.get("lc", "")), + tx=str(data.get("tx", "")), + nt=str(data.get("nt", "")), + channel=str(data.get("channel", "")), + sub_channel=str(data.get("sub_channel", "")), + ) + + return None + + +def load_multiple_tm_files( + file_paths: list[str], + target_locale: str, +) -> list[TMEntry]: + """Load and merge multiple TM files. + + Args: + file_paths: List of file paths to load. + target_locale: Target locale code. + + Returns: + Combined list of TMEntry objects from all files. + """ + all_entries: list[TMEntry] = [] + for path in file_paths: + entries = load_tm_file(path, target_locale) + all_entries.extend(entries) + return all_entries diff --git a/backend/app/pipeline/orchestrator.py b/backend/app/pipeline/orchestrator.py new file mode 100644 index 0000000..25d310c --- /dev/null +++ b/backend/app/pipeline/orchestrator.py @@ -0,0 +1,190 @@ +"""Pipeline orchestrator - state machine managing the transcreation pipeline. + +States: INIT -> VALIDATE -> TM_RETRIEVE -> RANK -> TRANSCREATE -> COMPLY -> FORMAT -> DONE + +Runs agents in sequence with compliance re-draft loop (max 3 iterations). +Progress callbacks enable WebSocket updates. +""" + +import enum +import logging +from typing import Any, Callable + +from app.pipeline.contracts import FileManifest, JobParams, PipelineContext +from app.pipeline.agents.agent_1_validator import Agent1Validator +from app.pipeline.agents.agent_2_tm_retrieval import Agent2TMRetrieval +from app.pipeline.agents.agent_3_ranker import Agent3Ranker +from app.pipeline.agents.agent_4_transcreator import Agent4Transcreator +from app.pipeline.agents.agent_5_compliance import Agent5Compliance +from app.pipeline.agents.agent_6_formatter import Agent6Formatter + +logger = logging.getLogger(__name__) + +MAX_COMPLIANCE_RETRIES = 3 + + +class PipelineState(str, enum.Enum): + INIT = "INIT" + VALIDATE = "VALIDATE" + TM_RETRIEVE = "TM_RETRIEVE" + RANK = "RANK" + TRANSCREATE = "TRANSCREATE" + COMPLY = "COMPLY" + FORMAT = "FORMAT" + DONE = "DONE" + ERROR = "ERROR" + + +class PipelineOrchestrator: + """Orchestrates the transcreation pipeline through its state machine. + + Args: + job_params: Job parameters dict. + source_lines: Pre-parsed source lines (optional). + source_file_path: Path to source xlsx (optional, used if source_lines not given). + file_manifest: Dict of reference file paths. + output_dir: Directory for output files. + on_progress: Optional callback(state, message, pct) for progress updates. + """ + + def __init__( + self, + job_params: dict[str, Any], + source_lines: list[dict] | None = None, + source_file_path: str | None = None, + file_manifest: dict[str, Any] | None = None, + output_dir: str | None = None, + on_progress: Callable[[str, str, float], None] | None = None, + ) -> None: + self.job_params = job_params + self.source_lines = source_lines + self.source_file_path = source_file_path + self.file_manifest = file_manifest or {} + self.output_dir = output_dir + self.on_progress = on_progress + self.state = PipelineState.INIT + self.context: PipelineContext | None = None + + def _emit_progress(self, message: str, pct: float) -> None: + """Emit a progress callback if one is registered.""" + if self.on_progress: + try: + self.on_progress(self.state.value, message, pct) + except Exception as e: + logger.warning(f"Progress callback error: {e}") + + async def run(self) -> PipelineContext: + """Run the full pipeline from INIT to DONE. + + Returns: + The final PipelineContext with all results. + + Raises: + Exception: If any agent fails. + """ + # Initialize context + self.context = PipelineContext( + job_params=JobParams(**self.job_params), + file_manifest=FileManifest(), + ) + + try: + # VALIDATE + self.state = PipelineState.VALIDATE + self._emit_progress("Validating inputs", 0.1) + logger.info(f"[{self.job_params.get('job_id')}] VALIDATE") + + validator = Agent1Validator( + source_file_path=self.source_file_path, + source_lines=self.source_lines, + file_manifest=self.file_manifest, + job_params=self.job_params, + ) + self.context = await validator.run(self.context) + + # TM_RETRIEVE + self.state = PipelineState.TM_RETRIEVE + self._emit_progress("Retrieving TM matches", 0.25) + logger.info(f"[{self.job_params.get('job_id')}] TM_RETRIEVE") + + tm_retriever = Agent2TMRetrieval() + self.context = await tm_retriever.run(self.context) + + # RANK + self.state = PipelineState.RANK + self._emit_progress("Ranking matches", 0.4) + logger.info(f"[{self.job_params.get('job_id')}] RANK") + + ranker = Agent3Ranker() + self.context = await ranker.run(self.context) + + # TRANSCREATE + COMPLY loop + for attempt in range(1, MAX_COMPLIANCE_RETRIES + 1): + # TRANSCREATE + self.state = PipelineState.TRANSCREATE + self._emit_progress( + f"Generating transcreations (attempt {attempt})", + 0.5 + (attempt - 1) * 0.1, + ) + logger.info( + f"[{self.job_params.get('job_id')}] TRANSCREATE (attempt {attempt})" + ) + + transcreator = Agent4Transcreator() + self.context = await transcreator.run(self.context) + + # COMPLY + self.state = PipelineState.COMPLY + self._emit_progress( + f"Checking compliance (attempt {attempt})", + 0.6 + (attempt - 1) * 0.1, + ) + logger.info( + f"[{self.job_params.get('job_id')}] COMPLY (attempt {attempt})" + ) + + compliance = Agent5Compliance() + self.context = await compliance.run(self.context) + + # Check if all passed + all_passed = all( + cr.passed for cr in self.context.compliance_results + ) + if all_passed: + logger.info( + f"[{self.job_params.get('job_id')}] All compliance checks passed" + ) + break + else: + failed_count = sum( + 1 for cr in self.context.compliance_results if not cr.passed + ) + logger.warning( + f"[{self.job_params.get('job_id')}] " + f"{failed_count} compliance failures, " + f"attempt {attempt}/{MAX_COMPLIANCE_RETRIES}" + ) + + # FORMAT + self.state = PipelineState.FORMAT + self._emit_progress("Generating output file", 0.9) + logger.info(f"[{self.job_params.get('job_id')}] FORMAT") + + formatter = Agent6Formatter(output_dir=self.output_dir) + self.context = await formatter.run(self.context) + + # DONE + self.state = PipelineState.DONE + self._emit_progress("Complete", 1.0) + logger.info(f"[{self.job_params.get('job_id')}] DONE") + + return self.context + + except Exception as e: + self.state = PipelineState.ERROR + self._emit_progress(f"Error: {str(e)}", -1.0) + logger.error( + f"[{self.job_params.get('job_id')}] Pipeline error: {e}", + exc_info=True, + ) + raise diff --git a/backend/app/schemas/__init__.py b/backend/app/schemas/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/schemas/client.py b/backend/app/schemas/client.py new file mode 100644 index 0000000..3bf9de3 --- /dev/null +++ b/backend/app/schemas/client.py @@ -0,0 +1,29 @@ +from datetime import datetime +from typing import Any +from uuid import UUID + +from pydantic import BaseModel + + +class ClientCreate(BaseModel): + name: str + settings: dict[str, Any] | None = None + + model_config = {"from_attributes": True} + + +class ClientUpdate(BaseModel): + name: str | None = None + settings: dict[str, Any] | None = None + + model_config = {"from_attributes": True} + + +class ClientResponse(BaseModel): + id: UUID + name: str + settings: dict[str, Any] | None = None + created_at: datetime + updated_at: datetime + + model_config = {"from_attributes": True} diff --git a/backend/app/schemas/common.py b/backend/app/schemas/common.py new file mode 100644 index 0000000..66fef17 --- /dev/null +++ b/backend/app/schemas/common.py @@ -0,0 +1,19 @@ +from typing import Any, Generic, TypeVar + +from pydantic import BaseModel + +T = TypeVar("T") + + +class PaginatedResponse(BaseModel, Generic[T]): + items: list[T] + total: int + page: int + page_size: int + pages: int + + +class ErrorResponse(BaseModel): + detail: str + code: str | None = None + errors: list[dict[str, Any]] | None = None diff --git a/backend/app/schemas/feedback.py b/backend/app/schemas/feedback.py new file mode 100644 index 0000000..9f89f99 --- /dev/null +++ b/backend/app/schemas/feedback.py @@ -0,0 +1,27 @@ +from datetime import datetime +from uuid import UUID + +from pydantic import BaseModel + +from app.models.feedback import FlagType + + +class FeedbackCreate(BaseModel): + output_id: UUID + option_column: int + flag_type: FlagType + comment: str | None = None + + model_config = {"from_attributes": True} + + +class FeedbackResponse(BaseModel): + id: UUID + output_id: UUID + user_id: UUID + option_column: int + flag_type: FlagType + comment: str | None = None + created_at: datetime + + model_config = {"from_attributes": True} diff --git a/backend/app/schemas/files.py b/backend/app/schemas/files.py new file mode 100644 index 0000000..e6b5e35 --- /dev/null +++ b/backend/app/schemas/files.py @@ -0,0 +1,46 @@ +from datetime import datetime +from uuid import UUID + +from pydantic import BaseModel + +from app.models.files import ReferenceFileType + + +class TMFileResponse(BaseModel): + id: UUID + client_id: UUID + locale_code: str + channel: str + filename: str + file_path: str + segment_count: int + uploaded_by: UUID | None = None + uploaded_at: datetime + last_updated_at: datetime + version: int + + model_config = {"from_attributes": True} + + +class ReferenceFileResponse(BaseModel): + id: UUID + client_id: UUID + file_type: ReferenceFileType + locale_scope: str + filename: str + file_path: str + uploaded_by: UUID | None = None + uploaded_at: datetime + last_updated_at: datetime + version: int + + model_config = {"from_attributes": True} + + +class FileUploadResponse(BaseModel): + id: UUID + filename: str + file_path: str + message: str + + model_config = {"from_attributes": True} diff --git a/backend/app/schemas/job.py b/backend/app/schemas/job.py new file mode 100644 index 0000000..fbf698d --- /dev/null +++ b/backend/app/schemas/job.py @@ -0,0 +1,94 @@ +from datetime import datetime +from typing import Any +from uuid import UUID + +from pydantic import BaseModel + +from app.models.job import JobStatus, JobType, LocaleStatus, LocaleType, Programme + + +class JobCreate(BaseModel): + client_id: UUID + campaign_name: str + programme: Programme + channel: str + sub_channel: str | None = None + context_prompt: str | None = None + job_type: JobType = JobType.main + parent_job_id: UUID | None = None + job_ref: str | None = None + locale_codes: list[str] = [] + + model_config = {"from_attributes": True} + + +class JobUpdate(BaseModel): + campaign_name: str | None = None + programme: Programme | None = None + channel: str | None = None + sub_channel: str | None = None + context_prompt: str | None = None + job_ref: str | None = None + + model_config = {"from_attributes": True} + + +class LocaleInstanceResponse(BaseModel): + id: UUID + job_id: UUID + locale_code: str + locale_type: LocaleType + status: LocaleStatus + started_at: datetime | None = None + completed_at: datetime | None = None + token_usage: int = 0 + estimated_cost: float = 0.0 + output_file_path: str | None = None + error_log: str | None = None + tm_files_loaded: dict[str, Any] | None = None + ref_files_loaded: dict[str, Any] | None = None + agent_version: str | None = None + created_at: datetime + updated_at: datetime + + model_config = {"from_attributes": True} + + +class JobResponse(BaseModel): + id: UUID + client_id: UUID + created_by: UUID + job_ref: str | None = None + campaign_name: str + programme: Programme + channel: str + sub_channel: str | None = None + context_prompt: str | None = None + job_type: JobType + parent_job_id: UUID | None = None + status: JobStatus + total_token_usage: int = 0 + total_estimated_cost: float = 0.0 + locale_instances: list[LocaleInstanceResponse] = [] + created_at: datetime + updated_at: datetime + + model_config = {"from_attributes": True} + + +class JobListResponse(BaseModel): + id: UUID + client_id: UUID + created_by: UUID + job_ref: str | None = None + campaign_name: str + programme: Programme + channel: str + status: JobStatus + total_token_usage: int = 0 + total_estimated_cost: float = 0.0 + locale_count: int = 0 + created_at: datetime + updated_at: datetime + + model_config = {"from_attributes": True} diff --git a/backend/app/schemas/output.py b/backend/app/schemas/output.py new file mode 100644 index 0000000..b562736 --- /dev/null +++ b/backend/app/schemas/output.py @@ -0,0 +1,51 @@ +from typing import Any +from uuid import UUID + +from pydantic import BaseModel + +from app.models.output import ConfidenceTier + + +class OutputRowResponse(BaseModel): + id: UUID + instance_id: UUID + line_id: UUID + row_order: int + confidence_tier: ConfidenceTier + option_1: str + backtranslation_1: str + rationale_1: str + option_2: str | None = None + backtranslation_2: str | None = None + rationale_2: str | None = None + option_3: str | None = None + backtranslation_3: str | None = None + rationale_3: str | None = None + tm_entries_cited: dict[str, Any] | None = None + winning_seg_key: str | None = None + character_count_option_1: int | None = None + character_count_option_2: int | None = None + character_count_option_3: int | None = None + + model_config = {"from_attributes": True} + + +class SourceLinePreview(BaseModel): + id: UUID + row_order: int + en_gb: str + copy_type: str | None = None + creative_guidance: str | None = None + char_limit: str | None = None + + model_config = {"from_attributes": True} + + +class OutputPreviewResponse(BaseModel): + locale_code: str + instance_id: UUID + source_lines: list[SourceLinePreview] + output_rows: list[OutputRowResponse] + total_rows: int + + model_config = {"from_attributes": True} diff --git a/backend/app/schemas/user.py b/backend/app/schemas/user.py new file mode 100644 index 0000000..6af841e --- /dev/null +++ b/backend/app/schemas/user.py @@ -0,0 +1,38 @@ +from datetime import datetime +from uuid import UUID + +from pydantic import BaseModel, EmailStr + +from app.models.user import UserRole, UserStatus + + +class UserCreate(BaseModel): + email: EmailStr + name: str + password: str + role: UserRole = UserRole.reviewer + client_ids: list[UUID] = [] + + model_config = {"from_attributes": True} + + +class UserUpdate(BaseModel): + email: EmailStr | None = None + name: str | None = None + password: str | None = None + role: UserRole | None = None + status: UserStatus | None = None + + model_config = {"from_attributes": True} + + +class UserResponse(BaseModel): + id: UUID + email: str + name: str + role: UserRole + status: UserStatus + created_at: datetime + updated_at: datetime + + model_config = {"from_attributes": True} diff --git a/backend/app/services/__init__.py b/backend/app/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/services/audit_service.py b/backend/app/services/audit_service.py new file mode 100644 index 0000000..db44337 --- /dev/null +++ b/backend/app/services/audit_service.py @@ -0,0 +1,77 @@ +from datetime import datetime +from typing import Any +from uuid import UUID + +from sqlalchemy import select, func +from sqlalchemy.ext.asyncio import AsyncSession + +from app.models.audit import AuditLog + + +class AuditService: + """Service for audit log creation and retrieval.""" + + async def log( + self, + db: AsyncSession, + action: str, + entity_type: str, + entity_id: str, + user_id: UUID | None = None, + details: dict[str, Any] | None = None, + ip_address: str | None = None, + ) -> AuditLog: + """Create an audit log entry.""" + entry = AuditLog( + user_id=user_id, + action=action, + entity_type=entity_type, + entity_id=entity_id, + details=details, + ip_address=ip_address, + ) + db.add(entry) + await db.flush() + return entry + + async def list_logs( + self, + db: AsyncSession, + user_id: UUID | None = None, + action: str | None = None, + entity_type: str | None = None, + entity_id: str | None = None, + date_from: datetime | None = None, + date_to: datetime | None = None, + page: int = 1, + page_size: int = 50, + ) -> tuple[list[AuditLog], int]: + """List audit logs with filters and pagination.""" + query = select(AuditLog) + + if user_id: + query = query.where(AuditLog.user_id == user_id) + if action: + query = query.where(AuditLog.action == action) + if entity_type: + query = query.where(AuditLog.entity_type == entity_type) + if entity_id: + query = query.where(AuditLog.entity_id == entity_id) + if date_from: + query = query.where(AuditLog.timestamp >= date_from) + if date_to: + query = query.where(AuditLog.timestamp <= date_to) + + # Count + count_query = select(func.count()).select_from(query.subquery()) + total_result = await db.execute(count_query) + total = total_result.scalar() or 0 + + # Paginate + query = query.order_by(AuditLog.timestamp.desc()) + query = query.offset((page - 1) * page_size).limit(page_size) + + result = await db.execute(query) + logs = list(result.scalars().all()) + + return logs, total diff --git a/backend/app/services/feedback_service.py b/backend/app/services/feedback_service.py new file mode 100644 index 0000000..f9bc08d --- /dev/null +++ b/backend/app/services/feedback_service.py @@ -0,0 +1,66 @@ +from uuid import UUID + +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession + +from app.models.feedback import Feedback +from app.schemas.feedback import FeedbackCreate + + +class FeedbackService: + """Service for feedback CRUD operations.""" + + async def create_feedback( + self, + db: AsyncSession, + data: FeedbackCreate, + user_id: UUID, + ) -> Feedback: + """Create a new feedback entry.""" + feedback = Feedback( + output_id=data.output_id, + user_id=user_id, + option_column=data.option_column, + flag_type=data.flag_type, + comment=data.comment, + ) + db.add(feedback) + await db.flush() + return feedback + + async def list_feedback( + self, + db: AsyncSession, + output_id: UUID | None = None, + user_id: UUID | None = None, + ) -> list[Feedback]: + """List feedback entries with optional filters.""" + query = select(Feedback) + if output_id: + query = query.where(Feedback.output_id == output_id) + if user_id: + query = query.where(Feedback.user_id == user_id) + query = query.order_by(Feedback.created_at.desc()) + + result = await db.execute(query) + return list(result.scalars().all()) + + async def get_feedback( + self, db: AsyncSession, feedback_id: UUID + ) -> Feedback | None: + """Get a single feedback entry by ID.""" + result = await db.execute( + select(Feedback).where(Feedback.id == feedback_id) + ) + return result.scalar_one_or_none() + + async def delete_feedback( + self, db: AsyncSession, feedback_id: UUID + ) -> bool: + """Delete a feedback entry.""" + feedback = await self.get_feedback(db, feedback_id) + if feedback is None: + return False + await db.delete(feedback) + await db.flush() + return True diff --git a/backend/app/services/file_service.py b/backend/app/services/file_service.py new file mode 100644 index 0000000..51f071b --- /dev/null +++ b/backend/app/services/file_service.py @@ -0,0 +1,234 @@ +import os +import shutil +from pathlib import Path +from typing import BinaryIO +from uuid import UUID, uuid4 + +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession + +from app.config import settings +from app.models.files import ReferenceFile, ReferenceFileType, TMFileRegistry +from app.models.source import SourceLine +from app.pipeline.modules.source_file_parser import parse_source_file + + +class FileService: + """Service for file upload, download, path resolution, and storage management.""" + + def __init__(self) -> None: + self.storage_root = Path(settings.STORAGE_ROOT) + + def _resolve_path(self, *parts: str) -> Path: + """Resolve a storage path and ensure parent directories exist.""" + path = self.storage_root.joinpath(*parts) + path.parent.mkdir(parents=True, exist_ok=True) + return path + + async def upload_source_file( + self, + db: AsyncSession, + job_id: UUID, + file: BinaryIO, + filename: str, + ) -> list[SourceLine]: + """Upload and parse a source xlsx file, creating SourceLine records.""" + # Save to storage + file_path = self._resolve_path("jobs", str(job_id), "source", filename) + with open(file_path, "wb") as f: + shutil.copyfileobj(file, f) + + # Parse the xlsx + parsed_lines = parse_source_file(str(file_path)) + + # Delete existing source lines for this job + existing = await db.execute( + select(SourceLine).where(SourceLine.job_id == job_id) + ) + for line in existing.scalars().all(): + await db.delete(line) + + # Create new source lines + source_lines = [] + for i, row in enumerate(parsed_lines): + source_line = SourceLine( + job_id=job_id, + row_order=i + 1, + en_gb=row["en_gb"], + copy_type=row.get("copy_type"), + creative_guidance=row.get("creative_guidance"), + visual_ref=row.get("visual_ref"), + char_limit=row.get("char_limit"), + is_display_format=row.get("is_display_format", False), + ) + db.add(source_line) + source_lines.append(source_line) + + await db.flush() + return source_lines + + async def upload_supplementary_file( + self, + db: AsyncSession, + job_id: UUID, + file: BinaryIO, + filename: str, + ) -> str: + """Upload a supplementary file (TM, glossary, etc.) for a job.""" + file_path = self._resolve_path("jobs", str(job_id), "supplementary", filename) + with open(file_path, "wb") as f: + shutil.copyfileobj(file, f) + return str(file_path) + + async def upload_tm_file( + self, + db: AsyncSession, + client_id: UUID, + locale_code: str, + channel: str, + file: BinaryIO, + filename: str, + uploaded_by: UUID | None = None, + ) -> TMFileRegistry: + """Upload a TM file and create a registry entry.""" + file_path = self._resolve_path( + "clients", str(client_id), "tm", locale_code, filename + ) + with open(file_path, "wb") as f: + shutil.copyfileobj(file, f) + + # Count segments (lines in JSONL) + segment_count = 0 + with open(file_path, "r") as f: + for line in f: + if line.strip(): + segment_count += 1 + + tm_file = TMFileRegistry( + client_id=client_id, + locale_code=locale_code, + channel=channel, + filename=filename, + file_path=str(file_path), + segment_count=segment_count, + uploaded_by=uploaded_by, + ) + db.add(tm_file) + await db.flush() + return tm_file + + async def upload_reference_file( + self, + db: AsyncSession, + client_id: UUID, + file_type: ReferenceFileType, + locale_scope: str, + file: BinaryIO, + filename: str, + uploaded_by: UUID | None = None, + ) -> ReferenceFile: + """Upload a reference file and create a registry entry.""" + file_path = self._resolve_path( + "clients", str(client_id), "reference", file_type.value, filename + ) + with open(file_path, "wb") as f: + shutil.copyfileobj(file, f) + + ref_file = ReferenceFile( + client_id=client_id, + file_type=file_type, + locale_scope=locale_scope, + filename=filename, + file_path=str(file_path), + uploaded_by=uploaded_by, + ) + db.add(ref_file) + await db.flush() + return ref_file + + async def list_tm_files( + self, + db: AsyncSession, + client_id: UUID, + locale_code: str | None = None, + channel: str | None = None, + ) -> list[TMFileRegistry]: + """List TM files for a client with optional filters.""" + query = select(TMFileRegistry).where(TMFileRegistry.client_id == client_id) + if locale_code: + query = query.where(TMFileRegistry.locale_code == locale_code) + if channel: + query = query.where(TMFileRegistry.channel == channel) + + result = await db.execute(query.order_by(TMFileRegistry.uploaded_at.desc())) + return list(result.scalars().all()) + + async def list_reference_files( + self, + db: AsyncSession, + client_id: UUID, + file_type: ReferenceFileType | None = None, + locale_scope: str | None = None, + ) -> list[ReferenceFile]: + """List reference files for a client with optional filters.""" + query = select(ReferenceFile).where(ReferenceFile.client_id == client_id) + if file_type: + query = query.where(ReferenceFile.file_type == file_type) + if locale_scope: + query = query.where(ReferenceFile.locale_scope == locale_scope) + + result = await db.execute(query.order_by(ReferenceFile.uploaded_at.desc())) + return list(result.scalars().all()) + + def get_file_path(self, stored_path: str) -> Path | None: + """Resolve a stored file path and verify it exists.""" + path = Path(stored_path) + if path.exists(): + return path + return None + + async def delete_tm_file( + self, db: AsyncSession, file_id: UUID + ) -> bool: + """Delete a TM file from storage and database.""" + result = await db.execute( + select(TMFileRegistry).where(TMFileRegistry.id == file_id) + ) + tm_file = result.scalar_one_or_none() + if tm_file is None: + return False + + # Remove from filesystem + file_path = Path(tm_file.file_path) + if file_path.exists(): + os.remove(file_path) + + await db.delete(tm_file) + await db.flush() + return True + + async def delete_reference_file( + self, db: AsyncSession, file_id: UUID + ) -> bool: + """Delete a reference file from storage and database.""" + result = await db.execute( + select(ReferenceFile).where(ReferenceFile.id == file_id) + ) + ref_file = result.scalar_one_or_none() + if ref_file is None: + return False + + file_path = Path(ref_file.file_path) + if file_path.exists(): + os.remove(file_path) + + await db.delete(ref_file) + await db.flush() + return True + + def validate_file_extension( + self, filename: str, allowed_extensions: list[str] + ) -> bool: + """Validate that a file has an allowed extension.""" + ext = Path(filename).suffix.lower() + return ext in allowed_extensions diff --git a/backend/app/services/job_service.py b/backend/app/services/job_service.py new file mode 100644 index 0000000..1e51f4c --- /dev/null +++ b/backend/app/services/job_service.py @@ -0,0 +1,202 @@ +from datetime import datetime +from typing import Any +from uuid import UUID + +from sqlalchemy import func, select +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.orm import selectinload + +from app.models.job import Job, JobStatus, LocaleInstance, LocaleStatus, LocaleType +from app.models.source import SourceLine +from app.schemas.job import JobCreate, JobUpdate + + +class JobService: + """Service for Job CRUD and launch logic.""" + + async def create_job( + self, db: AsyncSession, data: JobCreate, user_id: UUID + ) -> Job: + """Create a new job with locale instances.""" + job = Job( + client_id=data.client_id, + created_by=user_id, + campaign_name=data.campaign_name, + programme=data.programme, + channel=data.channel, + sub_channel=data.sub_channel, + context_prompt=data.context_prompt, + job_type=data.job_type, + parent_job_id=data.parent_job_id, + job_ref=data.job_ref, + status=JobStatus.created, + ) + db.add(job) + await db.flush() + + # Create locale instances + for i, locale_code in enumerate(data.locale_codes): + locale_type = LocaleType.main if i == 0 else LocaleType.derived + instance = LocaleInstance( + job_id=job.id, + locale_code=locale_code, + locale_type=locale_type, + status=LocaleStatus.queued, + ) + db.add(instance) + + await db.flush() + return job + + async def get_job(self, db: AsyncSession, job_id: UUID) -> Job | None: + """Get a job by ID with locale instances.""" + result = await db.execute( + select(Job) + .options(selectinload(Job.locale_instances)) + .where(Job.id == job_id) + ) + return result.scalar_one_or_none() + + async def list_jobs( + self, + db: AsyncSession, + client_id: UUID | None = None, + status: str | None = None, + locale: str | None = None, + date_from: datetime | None = None, + date_to: datetime | None = None, + search: str | None = None, + page: int = 1, + page_size: int = 20, + ) -> tuple[list[Job], int]: + """List jobs with filters and pagination.""" + query = select(Job).options(selectinload(Job.locale_instances)) + + if client_id: + query = query.where(Job.client_id == client_id) + if status: + query = query.where(Job.status == status) + if locale: + query = query.join(LocaleInstance).where( + LocaleInstance.locale_code == locale + ) + if date_from: + query = query.where(Job.created_at >= date_from) + if date_to: + query = query.where(Job.created_at <= date_to) + if search: + query = query.where( + Job.campaign_name.ilike(f"%{search}%") + | Job.job_ref.ilike(f"%{search}%") + ) + + # Count total + count_query = select(func.count()).select_from(query.subquery()) + total_result = await db.execute(count_query) + total = total_result.scalar() or 0 + + # Apply pagination + query = query.order_by(Job.created_at.desc()) + query = query.offset((page - 1) * page_size).limit(page_size) + + result = await db.execute(query) + jobs = list(result.scalars().unique().all()) + + return jobs, total + + async def update_job( + self, db: AsyncSession, job_id: UUID, data: JobUpdate + ) -> Job | None: + """Update a job.""" + job = await self.get_job(db, job_id) + if job is None: + return None + + update_data = data.model_dump(exclude_unset=True) + for field, value in update_data.items(): + setattr(job, field, value) + + await db.flush() + return job + + async def launch_job(self, db: AsyncSession, job_id: UUID) -> Job | None: + """Validate and queue a job for processing.""" + job = await self.get_job(db, job_id) + if job is None: + return None + + if job.status != JobStatus.created: + raise ValueError( + f"Job cannot be launched from status '{job.status.value}'" + ) + + # Check source lines exist + result = await db.execute( + select(func.count()).where(SourceLine.job_id == job_id) + ) + source_count = result.scalar() or 0 + if source_count == 0: + raise ValueError("Job has no source lines. Upload source file first.") + + # Check locale instances exist + if not job.locale_instances: + raise ValueError("Job has no locale instances configured.") + + # Update status + job.status = JobStatus.queued + await db.flush() + + # Dispatch Celery tasks + from app.tasks.job_tasks import process_job + + process_job.delay(str(job_id)) + + return job + + async def cancel_job(self, db: AsyncSession, job_id: UUID) -> Job | None: + """Cancel a running job.""" + job = await self.get_job(db, job_id) + if job is None: + return None + + if job.status not in (JobStatus.queued, JobStatus.running): + raise ValueError( + f"Job cannot be cancelled from status '{job.status.value}'" + ) + + job.status = JobStatus.error + for instance in job.locale_instances: + if instance.status in (LocaleStatus.queued, LocaleStatus.running): + instance.status = LocaleStatus.error + instance.error_log = "Cancelled by user" + + await db.flush() + return job + + async def rerun_locale( + self, db: AsyncSession, job_id: UUID, locale_code: str + ) -> LocaleInstance | None: + """Re-run a single locale instance.""" + result = await db.execute( + select(LocaleInstance).where( + LocaleInstance.job_id == job_id, + LocaleInstance.locale_code == locale_code, + ) + ) + instance = result.scalar_one_or_none() + if instance is None: + return None + + instance.status = LocaleStatus.queued + instance.error_log = None + instance.started_at = None + instance.completed_at = None + instance.token_usage = 0 + instance.estimated_cost = 0.0 + await db.flush() + + from app.tasks.job_tasks import process_locale_instance + + process_locale_instance.delay(str(job_id), locale_code) + + return instance diff --git a/backend/app/services/output_service.py b/backend/app/services/output_service.py new file mode 100644 index 0000000..78ef99f --- /dev/null +++ b/backend/app/services/output_service.py @@ -0,0 +1,104 @@ +from uuid import UUID + +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.orm import selectinload + +from app.models.job import LocaleInstance +from app.models.output import OutputRow +from app.models.source import SourceLine +from app.schemas.output import ( + OutputPreviewResponse, + OutputRowResponse, + SourceLinePreview, +) + + +class OutputService: + """Service for assembling output preview data and triggering exports.""" + + async def get_preview( + self, + db: AsyncSession, + job_id: UUID, + locale_code: str, + ) -> OutputPreviewResponse | None: + """Assemble output preview data for a specific locale instance.""" + # Get the locale instance + result = await db.execute( + select(LocaleInstance) + .where( + LocaleInstance.job_id == job_id, + LocaleInstance.locale_code == locale_code, + ) + ) + instance = result.scalar_one_or_none() + if instance is None: + return None + + # Get source lines + source_result = await db.execute( + select(SourceLine) + .where(SourceLine.job_id == job_id) + .order_by(SourceLine.row_order) + ) + source_lines = [ + SourceLinePreview.model_validate(sl) + for sl in source_result.scalars().all() + ] + + # Get output rows + output_result = await db.execute( + select(OutputRow) + .where(OutputRow.instance_id == instance.id) + .order_by(OutputRow.row_order) + ) + output_rows = [ + OutputRowResponse.model_validate(row) + for row in output_result.scalars().all() + ] + + return OutputPreviewResponse( + locale_code=locale_code, + instance_id=instance.id, + source_lines=source_lines, + output_rows=output_rows, + total_rows=len(output_rows), + ) + + async def get_output_rows( + self, + db: AsyncSession, + instance_id: UUID, + ) -> list[OutputRow]: + """Get all output rows for a locale instance.""" + result = await db.execute( + select(OutputRow) + .where(OutputRow.instance_id == instance_id) + .order_by(OutputRow.row_order) + ) + return list(result.scalars().all()) + + async def trigger_export( + self, + db: AsyncSession, + job_id: UUID, + locale_code: str, + ) -> str | None: + """Trigger export generation for a locale and return the file path.""" + result = await db.execute( + select(LocaleInstance) + .where( + LocaleInstance.job_id == job_id, + LocaleInstance.locale_code == locale_code, + ) + ) + instance = result.scalar_one_or_none() + if instance is None: + return None + + if instance.output_file_path: + return instance.output_file_path + + # Export would be triggered here; for now return None indicating no export yet + return None diff --git a/backend/app/services/report_service.py b/backend/app/services/report_service.py new file mode 100644 index 0000000..1209417 --- /dev/null +++ b/backend/app/services/report_service.py @@ -0,0 +1,133 @@ +from datetime import datetime +from typing import Any +from uuid import UUID + +from sqlalchemy import func, select +from sqlalchemy.ext.asyncio import AsyncSession + +from app.models.audit import TokenUsageLog +from app.models.feedback import Feedback, FlagType +from app.models.job import Job, JobStatus, LocaleInstance, LocaleStatus +from app.models.output import OutputRow, ConfidenceTier + + +class ReportService: + """Service for aggregation queries powering reports.""" + + async def get_usage_stats( + self, + db: AsyncSession, + client_id: UUID | None = None, + date_from: datetime | None = None, + date_to: datetime | None = None, + ) -> dict[str, Any]: + """Get overall usage statistics.""" + job_query = select( + func.count(Job.id).label("total_jobs"), + func.sum(Job.total_token_usage).label("total_tokens"), + func.sum(Job.total_estimated_cost).label("total_cost"), + ) + if client_id: + job_query = job_query.where(Job.client_id == client_id) + if date_from: + job_query = job_query.where(Job.created_at >= date_from) + if date_to: + job_query = job_query.where(Job.created_at <= date_to) + + result = await db.execute(job_query) + row = result.one() + + # Status breakdown + status_query = select( + Job.status, func.count(Job.id) + ).group_by(Job.status) + if client_id: + status_query = status_query.where(Job.client_id == client_id) + status_result = await db.execute(status_query) + status_breakdown = { + status.value: count for status, count in status_result.all() + } + + return { + "total_jobs": row.total_jobs or 0, + "total_tokens": row.total_tokens or 0, + "total_cost": float(row.total_cost or 0.0), + "status_breakdown": status_breakdown, + } + + async def get_token_cost_data( + self, + db: AsyncSession, + client_id: UUID | None = None, + date_from: datetime | None = None, + date_to: datetime | None = None, + ) -> list[dict[str, Any]]: + """Get token usage and cost data grouped by date.""" + query = ( + select( + func.date_trunc("day", TokenUsageLog.timestamp).label("date"), + func.sum(TokenUsageLog.input_tokens).label("input_tokens"), + func.sum(TokenUsageLog.output_tokens).label("output_tokens"), + func.sum(TokenUsageLog.total_tokens).label("total_tokens"), + func.sum(TokenUsageLog.estimated_cost_usd).label("total_cost"), + ) + .group_by(func.date_trunc("day", TokenUsageLog.timestamp)) + .order_by(func.date_trunc("day", TokenUsageLog.timestamp)) + ) + + if client_id: + query = query.join(LocaleInstance).join(Job).where( + Job.client_id == client_id + ) + if date_from: + query = query.where(TokenUsageLog.timestamp >= date_from) + if date_to: + query = query.where(TokenUsageLog.timestamp <= date_to) + + result = await db.execute(query) + return [ + { + "date": str(row.date), + "input_tokens": row.input_tokens or 0, + "output_tokens": row.output_tokens or 0, + "total_tokens": row.total_tokens or 0, + "total_cost": float(row.total_cost or 0.0), + } + for row in result.all() + ] + + async def get_quality_metrics( + self, + db: AsyncSession, + client_id: UUID | None = None, + ) -> dict[str, Any]: + """Get quality metrics from output confidence tiers and feedback.""" + # Confidence tier distribution + tier_query = select( + OutputRow.confidence_tier, func.count(OutputRow.id) + ).group_by(OutputRow.confidence_tier) + + if client_id: + tier_query = tier_query.join(LocaleInstance).join(Job).where( + Job.client_id == client_id + ) + + tier_result = await db.execute(tier_query) + tier_breakdown = { + tier.value: count for tier, count in tier_result.all() + } + + # Feedback distribution + feedback_query = select( + Feedback.flag_type, func.count(Feedback.id) + ).group_by(Feedback.flag_type) + + feedback_result = await db.execute(feedback_query) + feedback_breakdown = { + ft.value: count for ft, count in feedback_result.all() + } + + return { + "confidence_tiers": tier_breakdown, + "feedback_distribution": feedback_breakdown, + } diff --git a/backend/app/tasks/__init__.py b/backend/app/tasks/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/tasks/celery_app.py b/backend/app/tasks/celery_app.py new file mode 100644 index 0000000..3d0325c --- /dev/null +++ b/backend/app/tasks/celery_app.py @@ -0,0 +1,26 @@ +"""Celery application configuration.""" + +from celery import Celery + +from app.config import settings + +celery_app = Celery( + "transcreation", + broker=settings.REDIS_URL, + backend=settings.REDIS_URL, + include=["app.tasks.job_tasks"], +) + +celery_app.conf.update( + task_serializer="json", + accept_content=["json"], + result_serializer="json", + timezone="UTC", + enable_utc=True, + task_track_started=True, + task_acks_late=True, + worker_prefetch_multiplier=1, + result_expires=3600, + task_soft_time_limit=1800, # 30 minutes + task_time_limit=3600, # 1 hour +) diff --git a/backend/app/tasks/job_tasks.py b/backend/app/tasks/job_tasks.py new file mode 100644 index 0000000..883e15e --- /dev/null +++ b/backend/app/tasks/job_tasks.py @@ -0,0 +1,258 @@ +"""Celery tasks for job processing.""" + +import asyncio +import logging +from datetime import datetime, timezone + +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine + +from app.config import settings +from app.models.job import Job, JobStatus, LocaleInstance, LocaleStatus +from app.models.output import ConfidenceTier, OutputRow +from app.models.source import SourceLine +from app.pipeline.orchestrator import PipelineOrchestrator +from app.tasks.celery_app import celery_app + +logger = logging.getLogger(__name__) + + +def _get_async_session_factory() -> async_sessionmaker[AsyncSession]: + """Create a fresh async session factory for use in Celery tasks.""" + engine = create_async_engine(settings.DATABASE_URL, pool_pre_ping=True) + return async_sessionmaker(bind=engine, class_=AsyncSession, expire_on_commit=False) + + +@celery_app.task(bind=True, max_retries=2) +def process_job(self, job_id: str) -> dict: + """Fan out locale instance processing for a job. + + For each locale instance in the job, dispatches a process_locale_instance task. + """ + logger.info(f"Processing job {job_id}") + + async def _process() -> dict: + factory = _get_async_session_factory() + async with factory() as db: + # Get job + result = await db.execute(select(Job).where(Job.id == job_id)) + job = result.scalar_one_or_none() + if job is None: + return {"error": f"Job {job_id} not found"} + + # Update status to running + job.status = JobStatus.running + await db.commit() + + # Get locale instances + result = await db.execute( + select(LocaleInstance).where(LocaleInstance.job_id == job_id) + ) + instances = result.scalars().all() + + # Dispatch per-locale tasks + task_ids = [] + for instance in instances: + task = process_locale_instance.delay(job_id, instance.locale_code) + task_ids.append(task.id) + + return { + "job_id": job_id, + "dispatched_locales": len(task_ids), + "task_ids": task_ids, + } + + return asyncio.run(_process()) + + +@celery_app.task(bind=True, max_retries=1) +def process_locale_instance(self, job_id: str, locale_code: str) -> dict: + """Process a single locale instance through the pipeline. + + Runs the pipeline orchestrator for the given job + locale combination. + """ + logger.info(f"Processing locale {locale_code} for job {job_id}") + + async def _process() -> dict: + factory = _get_async_session_factory() + async with factory() as db: + # Get the locale instance + result = await db.execute( + select(LocaleInstance).where( + LocaleInstance.job_id == job_id, + LocaleInstance.locale_code == locale_code, + ) + ) + instance = result.scalar_one_or_none() + if instance is None: + return {"error": f"Locale instance not found: {job_id}/{locale_code}"} + + # Get job + job_result = await db.execute(select(Job).where(Job.id == job_id)) + job = job_result.scalar_one_or_none() + if job is None: + return {"error": f"Job {job_id} not found"} + + # Update instance status + instance.status = LocaleStatus.running + instance.started_at = datetime.now(timezone.utc) + await db.commit() + + try: + # Get source lines + source_result = await db.execute( + select(SourceLine) + .where(SourceLine.job_id == job_id) + .order_by(SourceLine.row_order) + ) + source_lines = [ + { + "id": str(sl.id), + "en_gb": sl.en_gb, + "copy_type": sl.copy_type, + "creative_guidance": sl.creative_guidance, + "visual_ref": sl.visual_ref, + "char_limit": sl.char_limit, + "is_display_format": sl.is_display_format, + } + for sl in source_result.scalars().all() + ] + + # Build job params + job_params = { + "job_id": str(job.id), + "client_id": str(job.client_id), + "locale_code": locale_code, + "channel": job.channel, + "sub_channel": job.sub_channel, + "programme": job.programme.value, + "campaign_name": job.campaign_name, + "context_prompt": job.context_prompt, + } + + # Run pipeline + orchestrator = PipelineOrchestrator( + job_params=job_params, + source_lines=source_lines, + output_dir=settings.STORAGE_ROOT, + ) + context = await orchestrator.run() + + # Save output rows to database + for i, draft in enumerate(context.draft_outputs): + # Find matching source line + source_line_id = None + if i < len(source_lines): + source_line_id = source_lines[i].get("id") + + # Get confidence tier + tier = "low" + if i < len(context.ranking_declarations): + tier = context.ranking_declarations[i].confidence_tier + + # Get character counts + char_counts = {} + if i < len(context.compliance_results): + char_counts = context.compliance_results[i].character_counts + + output_row = OutputRow( + instance_id=instance.id, + line_id=source_line_id, + row_order=i + 1, + confidence_tier=ConfidenceTier(tier), + option_1=draft.option_1.text if draft.option_1 else "", + backtranslation_1=draft.option_1.backtranslation if draft.option_1 else "", + rationale_1=draft.option_1.rationale if draft.option_1 else "", + option_2=draft.option_2.text if draft.option_2 else None, + backtranslation_2=draft.option_2.backtranslation if draft.option_2 else None, + rationale_2=draft.option_2.rationale if draft.option_2 else None, + option_3=draft.option_3.text if draft.option_3 else None, + backtranslation_3=draft.option_3.backtranslation if draft.option_3 else None, + rationale_3=draft.option_3.rationale if draft.option_3 else None, + tm_entries_cited=draft.tm_entries_cited if draft.tm_entries_cited else None, + character_count_option_1=char_counts.get("option_1"), + character_count_option_2=char_counts.get("option_2"), + character_count_option_3=char_counts.get("option_3"), + ) + db.add(output_row) + + # Update instance status + instance.status = LocaleStatus.complete + instance.completed_at = datetime.now(timezone.utc) + output_path = ( + f"{settings.STORAGE_ROOT}/jobs/{job_id}/output/" + f"{locale_code}_{job_id}_output.xlsx" + ) + instance.output_file_path = output_path + instance.agent_version = "1.0.0" + + await db.commit() + + # Check if all instances are complete + await _check_job_completion(db, job_id) + + return { + "job_id": job_id, + "locale_code": locale_code, + "status": "complete", + "output_rows": len(context.draft_outputs), + } + + except Exception as e: + logger.error( + f"Error processing {locale_code} for job {job_id}: {e}", + exc_info=True, + ) + instance.status = LocaleStatus.error + instance.error_log = str(e) + instance.completed_at = datetime.now(timezone.utc) + await db.commit() + + # Check if job should be marked as partial/error + await _check_job_completion(db, job_id) + + return { + "job_id": job_id, + "locale_code": locale_code, + "status": "error", + "error": str(e), + } + + return asyncio.run(_process()) + + +async def _check_job_completion(db: AsyncSession, job_id: str) -> None: + """Check if all locale instances are done and update job status accordingly.""" + result = await db.execute( + select(LocaleInstance).where(LocaleInstance.job_id == job_id) + ) + instances = list(result.scalars().all()) + + if not instances: + return + + all_complete = all(i.status == LocaleStatus.complete for i in instances) + all_done = all( + i.status in (LocaleStatus.complete, LocaleStatus.error) + for i in instances + ) + any_error = any(i.status == LocaleStatus.error for i in instances) + + job_result = await db.execute(select(Job).where(Job.id == job_id)) + job = job_result.scalar_one_or_none() + if job is None: + return + + if all_complete: + job.status = JobStatus.complete + # Sum up token usage + job.total_token_usage = sum(i.token_usage for i in instances) + job.total_estimated_cost = sum(i.estimated_cost for i in instances) + elif all_done and any_error: + any_complete = any(i.status == LocaleStatus.complete for i in instances) + if any_complete: + job.status = JobStatus.partial_complete + else: + job.status = JobStatus.error + + await db.commit() diff --git a/backend/app/ws/__init__.py b/backend/app/ws/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/ws/handler.py b/backend/app/ws/handler.py new file mode 100644 index 0000000..6f93ebe --- /dev/null +++ b/backend/app/ws/handler.py @@ -0,0 +1,47 @@ +from fastapi import APIRouter, Query, WebSocket, WebSocketDisconnect + +from app.auth.service import AuthService +from app.ws.manager import manager + +ws_router = APIRouter() +auth_service = AuthService() + + +@ws_router.websocket("/ws/jobs/{job_id}") +async def websocket_endpoint( + websocket: WebSocket, + job_id: str, + token: str = Query(...), +) -> None: + """WebSocket endpoint for real-time job progress updates. + + Authentication is performed via query parameter token. + """ + # Validate token + claims = auth_service.validate_token(token) + if claims is None: + await websocket.close(code=4001, reason="Invalid or expired token") + return + + await manager.connect(job_id, websocket) + + try: + # Send initial connection message + await manager.send_personal( + websocket, + { + "type": "connected", + "job_id": job_id, + "message": "Connected to job progress stream", + }, + ) + + # Keep connection alive and listen for client messages + while True: + data = await websocket.receive_text() + # Currently we don't process incoming messages, + # but the loop keeps the connection alive + except WebSocketDisconnect: + manager.disconnect(job_id, websocket) + except Exception: + manager.disconnect(job_id, websocket) diff --git a/backend/app/ws/manager.py b/backend/app/ws/manager.py new file mode 100644 index 0000000..569eb92 --- /dev/null +++ b/backend/app/ws/manager.py @@ -0,0 +1,59 @@ +import json +from typing import Any + +from fastapi import WebSocket + + +class ConnectionManager: + """Manage WebSocket connections grouped by job_id.""" + + def __init__(self) -> None: + self._connections: dict[str, list[WebSocket]] = {} + + async def connect(self, job_id: str, websocket: WebSocket) -> None: + """Accept a websocket connection and register it for a job.""" + await websocket.accept() + if job_id not in self._connections: + self._connections[job_id] = [] + self._connections[job_id].append(websocket) + + def disconnect(self, job_id: str, websocket: WebSocket) -> None: + """Remove a websocket connection from a job's connection list.""" + if job_id in self._connections: + self._connections[job_id] = [ + ws for ws in self._connections[job_id] if ws != websocket + ] + if not self._connections[job_id]: + del self._connections[job_id] + + async def broadcast(self, job_id: str, message: dict[str, Any]) -> None: + """Broadcast a JSON message to all connections for a job.""" + if job_id not in self._connections: + return + + payload = json.dumps(message) + disconnected: list[WebSocket] = [] + + for websocket in self._connections[job_id]: + try: + await websocket.send_text(payload) + except Exception: + disconnected.append(websocket) + + # Clean up dead connections + for ws in disconnected: + self.disconnect(job_id, ws) + + async def send_personal( + self, websocket: WebSocket, message: dict[str, Any] + ) -> None: + """Send a message to a specific websocket.""" + await websocket.send_text(json.dumps(message)) + + def get_connection_count(self, job_id: str) -> int: + """Get the number of active connections for a job.""" + return len(self._connections.get(job_id, [])) + + +# Singleton instance +manager = ConnectionManager() diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 0000000..cfed061 --- /dev/null +++ b/backend/requirements.txt @@ -0,0 +1,17 @@ +fastapi>=0.111.0 +uvicorn[standard]>=0.29.0 +sqlalchemy[asyncio]>=2.0.30 +asyncpg>=0.29.0 +alembic>=1.13.0 +celery[redis]>=5.4.0 +redis>=5.0.0 +pydantic[email]>=2.7.0 +pydantic-settings>=2.2.0 +python-jose[cryptography]>=3.3.0 +bcrypt>=4.0.0 +python-multipart>=0.0.9 +openpyxl>=3.1.0 +grapheme>=0.6.0 +anthropic>=0.25.0 +websockets>=12.0 +httpx>=0.27.0 diff --git a/backend/tests/__init__.py b/backend/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/tests/fixtures/__init__.py b/backend/tests/fixtures/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/tests/test_api/__init__.py b/backend/tests/test_api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/tests/test_auth/__init__.py b/backend/tests/test_auth/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/tests/test_modules/__init__.py b/backend/tests/test_modules/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/tests/test_pipeline/__init__.py b/backend/tests/test_pipeline/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..67c8457 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,71 @@ +version: "3.9" + +services: + db: + image: postgres:16 + restart: unless-stopped + environment: + POSTGRES_USER: transcreation + POSTGRES_PASSWORD: transcreation + POSTGRES_DB: transcreation + ports: + - "5492:5432" + volumes: + - pgdata:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U transcreation"] + interval: 5s + timeout: 5s + retries: 5 + + redis: + image: redis:7-alpine + restart: unless-stopped + ports: + - "6389:6379" + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 5s + retries: 5 + + backend: + build: + context: ./backend + dockerfile: Dockerfile + restart: unless-stopped + ports: + - "8040:8000" + env_file: + - .env + volumes: + - ./backend:/app + - ./storage:/storage + - ./seed:/app/seed + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload + + celery_worker: + build: + context: ./backend + dockerfile: Dockerfile + restart: unless-stopped + env_file: + - .env + volumes: + - ./backend:/app + - ./storage:/storage + - ./seed:/app/seed + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + command: celery -A app.tasks.celery_app worker --loglevel=info --concurrency=4 + +volumes: + pgdata: diff --git a/frontend/.env.local.example b/frontend/.env.local.example new file mode 100644 index 0000000..3729a5b --- /dev/null +++ b/frontend/.env.local.example @@ -0,0 +1,2 @@ +NEXT_PUBLIC_API_URL=http://localhost:8000 +NEXT_PUBLIC_WS_URL=ws://localhost:8000 diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000..72e1136 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,35 @@ +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..bed7d22 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,15 @@ +FROM node:20-alpine AS builder +WORKDIR /app +COPY package.json package-lock.json* ./ +RUN npm ci +COPY . . +RUN npm run build + +FROM node:20-alpine AS runner +WORKDIR /app +ENV NODE_ENV production +COPY --from=builder /app/public ./public +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/.next/static ./.next/static +EXPOSE 3000 +CMD ["node", "server.js"] diff --git a/frontend/components.json b/frontend/components.json new file mode 100644 index 0000000..556d973 --- /dev/null +++ b/frontend/components.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "src/app/globals.css", + "baseColor": "slate", + "cssVariables": true + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils" + } +} diff --git a/frontend/next.config.js b/frontend/next.config.js new file mode 100644 index 0000000..275d14a --- /dev/null +++ b/frontend/next.config.js @@ -0,0 +1,9 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + output: 'standalone', + images: { + domains: ['localhost'], + }, +}; + +module.exports = nextConfig; diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000..9efca44 --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,7873 @@ +{ + "name": "amazon-transcreation-frontend", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "amazon-transcreation-frontend", + "version": "0.1.0", + "dependencies": { + "@radix-ui/react-checkbox": "^1.0.4", + "@radix-ui/react-collapsible": "^1.0.3", + "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-label": "^2.0.2", + "@radix-ui/react-progress": "^1.0.3", + "@radix-ui/react-radio-group": "^1.1.3", + "@radix-ui/react-select": "^2.0.0", + "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-tabs": "^1.0.4", + "@radix-ui/react-tooltip": "^1.0.7", + "axios": "^1.6.0", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "date-fns": "^3.6.0", + "lucide-react": "^0.370.0", + "next": "^14.2.0", + "react": "^18.3.0", + "react-dom": "^18.3.0", + "recharts": "^2.12.0", + "tailwind-merge": "^2.2.0" + }, + "devDependencies": { + "@types/node": "^20.12.0", + "@types/react": "^18.3.0", + "@types/react-dom": "^18.3.0", + "autoprefixer": "^10.4.0", + "eslint": "^8.57.0", + "eslint-config-next": "^14.2.0", + "postcss": "^8.4.0", + "tailwindcss": "^3.4.0", + "typescript": "^5.4.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "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/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz", + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "license": "MIT" + }, + "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, + "license": "Apache-2.0", + "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, + "license": "Apache-2.0", + "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, + "license": "BSD-3-Clause" + }, + "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, + "license": "ISC", + "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.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@next/env": { + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz", + "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.35.tgz", + "integrity": "sha512-Jw9A3ICz2183qSsqwi7fgq4SBPiNfmOLmTPXKvlnzstUwyvBrtySiY+8RXJweNAs9KThb1+bYhZh9XWcNOr2zQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "10.3.10" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.33.tgz", + "integrity": "sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.33.tgz", + "integrity": "sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.33.tgz", + "integrity": "sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz", + "integrity": "sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.33.tgz", + "integrity": "sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.33.tgz", + "integrity": "sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.33.tgz", + "integrity": "sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz", + "integrity": "sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.33.tgz", + "integrity": "sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "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, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@radix-ui/number": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", + "license": "MIT" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz", + "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", + "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", + "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", + "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", + "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz", + "integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", + "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", + "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.8.tgz", + "integrity": "sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.3", + "@radix-ui/react-primitive": "2.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-context": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz", + "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", + "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", + "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", + "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", + "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz", + "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "license": "MIT" + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.16.1.tgz", + "integrity": "sha512-TvZbIpeKqGQQ7X0zSCvPH9riMSFQFSggnfBjFZ1mEoILW+UuXCKwOoPcgjMwiUtRqFZ8jWhPJc4um14vC6I4ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz", + "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==", + "dev": true, + "license": "MIT", + "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==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", + "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.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==", + "devOptional": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.1.tgz", + "integrity": "sha512-eSkwoemjo76bdXl2MYqtxg51HNwUSkWfODUOQ3PaTLZGh9uIWWFZIjyjaJnex7wXDu+TRx+ATsnSxdN9YWfRTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.58.1", + "@typescript-eslint/type-utils": "8.58.1", + "@typescript-eslint/utils": "8.58.1", + "@typescript-eslint/visitor-keys": "8.58.1", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.58.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.58.1.tgz", + "integrity": "sha512-gGkiNMPqerb2cJSVcruigx9eHBlLG14fSdPdqMoOcBfh+vvn4iCq2C8MzUB89PrxOXk0y3GZ1yIWb9aOzL93bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.58.1", + "@typescript-eslint/types": "8.58.1", + "@typescript-eslint/typescript-estree": "8.58.1", + "@typescript-eslint/visitor-keys": "8.58.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.1.tgz", + "integrity": "sha512-gfQ8fk6cxhtptek+/8ZIqw8YrRW5048Gug8Ts5IYcMLCw18iUgrZAEY/D7s4hkI0FxEfGakKuPK/XUMPzPxi5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.58.1", + "@typescript-eslint/types": "^8.58.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.1.tgz", + "integrity": "sha512-TPYUEqJK6avLcEjumWsIuTpuYODTTDAtoMdt8ZZa93uWMTX13Nb8L5leSje1NluammvU+oI3QRr5lLXPgihX3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.58.1", + "@typescript-eslint/visitor-keys": "8.58.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.1.tgz", + "integrity": "sha512-JAr2hOIct2Q+qk3G+8YFfqkqi7sC86uNryT+2i5HzMa2MPjw4qNFvtjnw1IiA1rP7QhNKVe21mSSLaSjwA1Olw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.58.1.tgz", + "integrity": "sha512-HUFxvTJVroT+0rXVJC7eD5zol6ID+Sn5npVPWoFuHGg9Ncq5Q4EYstqR+UOqaNRFXi5TYkpXXkLhoCHe3G0+7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.58.1", + "@typescript-eslint/typescript-estree": "8.58.1", + "@typescript-eslint/utils": "8.58.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.1.tgz", + "integrity": "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.1.tgz", + "integrity": "sha512-w4w7WR7GHOjqqPnvAYbazq+Y5oS68b9CzasGtnd6jIeOIeKUzYzupGTB2T4LTPSv4d+WPeccbxuneTFHYgAAWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.58.1", + "@typescript-eslint/tsconfig-utils": "8.58.1", + "@typescript-eslint/types": "8.58.1", + "@typescript-eslint/visitor-keys": "8.58.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.1.tgz", + "integrity": "sha512-Ln8R0tmWC7pTtLOzgJzYTXSCjJ9rDNHAqTaVONF4FEi2qwce8mD9iSOxOpLFFvWp/wBFlew0mjM1L1ihYWfBdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.58.1", + "@typescript-eslint/types": "8.58.1", + "@typescript-eslint/typescript-estree": "8.58.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.1.tgz", + "integrity": "sha512-y+vH7QE8ycjoa0bWciFg7OpFcipUuem1ujhrdLtq1gByKwfbC7bPeKsiny9e0urg93DqwGcHey+bGRKCnF1nZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.58.1", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "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, + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "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, + "license": "ISC", + "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, + "license": "MIT" + }, + "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, + "license": "Python-2.0" + }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.4.27", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz", + "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==", + "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" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.1", + "caniuse-lite": "^1.0.30001774", + "fraction.js": "^5.3.4", + "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/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.2.tgz", + "integrity": "sha512-byD6KPdvo72y/wj2T/4zGEvvlis+PsZsn/yPS3pEO+sFpcrqRpX/TJCxvVaEsNeMrfQbCr7w163YqoD9IYwHXw==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz", + "integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.17", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.17.tgz", + "integrity": "sha512-HdrkN8eVG2CXxeifv/VdJ4A4RSra1DTW8dc/hdxzhGHN8QePs6gKaWM9pHPcpCoxYZJuOZ8drHmbdpLHjCYjLA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "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" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001787", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001787.tgz", + "integrity": "sha512-mNcrMN9KeI68u7muanUpEejSLghOKlVhRqS/Za2IeyGllJ9I9otGpR9g3nsw7n4W378TE/LyIteA0+/FOZm4Kg==", + "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" + } + ], + "license": "CC-BY-4.0" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "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, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "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==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.334", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.334.tgz", + "integrity": "sha512-mgjZAz7Jyx1SRCwEpy9wefDS7GvNPazLthHg8eQMJ76wBdGQQDW33TCrUTvQ4wzpmOrv2zrFoD3oNufMdyMpog==", + "dev": true, + "license": "ISC" + }, + "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, + "license": "MIT" + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz", + "integrity": "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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-config-next": { + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.35.tgz", + "integrity": "sha512-BpLsv01UisH193WyT/1lpHqq5iJ/Orfz9h/NOOlAmTUq4GY349PextQ62K4XpnaM9supeiEn3TaOTeQO07gURg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "14.2.35", + "@rushstack/eslint-patch": "^1.3.3", + "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.0.0-canary-7118f5dd7-20230705", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz", + "integrity": "sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==", + "dev": true, + "license": "MIT", + "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/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "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, + "license": "BSD-2-Clause", + "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-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, + "license": "Apache-2.0", + "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, + "license": "BSD-2-Clause", + "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/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/fast-equals": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.0.tgz", + "integrity": "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "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, + "license": "MIT", + "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, + "license": "ISC", + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "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, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "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, + "license": "ISC" + }, + "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, + "license": "MIT", + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.7", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", + "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "ISC", + "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, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "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, + "license": "MIT", + "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==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "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, + "license": "ISC" + }, + "node_modules/lucide-react": { + "version": "0.370.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.370.0.tgz", + "integrity": "sha512-659R7tNK+QY3Af/hikV/+MdIWOQJ5GDfKdrs+5k08hWPlWNAoshUtvNuGl9PMeC3J1NZ07bUnyWd0eJR2okHOg==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "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, + "license": "MIT" + }, + "node_modules/next": { + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.35.tgz", + "integrity": "sha512-KhYd2Hjt/O1/1aZVX3dCwGXM1QmOV4eNM2UTacK5gipDdPN/oHHK/4oVGy7X8GMfPMsUTUEmGlsy0EY1YGAkig==", + "license": "MIT", + "dependencies": { + "@next/env": "14.2.35", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.33", + "@next/swc-darwin-x64": "14.2.33", + "@next/swc-linux-arm64-gnu": "14.2.33", + "@next/swc-linux-arm64-musl": "14.2.33", + "@next/swc-linux-x64-gnu": "14.2.33", + "@next/swc-linux-x64-musl": "14.2.33", + "@next/swc-win32-arm64-msvc": "14.2.33", + "@next/swc-win32-ia32-msvc": "14.2.33", + "@next/swc-win32-x64-msvc": "14.2.33" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "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" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-exports-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", + "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-exports-info/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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/node-releases": { + "version": "2.0.37", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz", + "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "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==", + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "ISC", + "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, + "license": "MIT", + "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/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "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, + "license": "BlueOak-1.0.0", + "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/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", + "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==", + "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" + } + ], + "license": "MIT", + "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, + "license": "MIT", + "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-import/node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "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/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "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" + } + ], + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "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, + "license": "MIT", + "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" + } + ], + "license": "MIT" + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-smooth": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", + "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==", + "license": "MIT", + "dependencies": { + "fast-equals": "^5.0.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "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==", + "license": "BSD-3-Clause", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recharts": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz", + "integrity": "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==", + "license": "MIT", + "dependencies": { + "clsx": "^2.0.0", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.21", + "react-is": "^18.3.1", + "react-smooth": "^4.0.4", + "recharts-scale": "^0.4.4", + "tiny-invariant": "^1.3.1", + "victory-vendor": "^36.6.8" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "license": "MIT", + "dependencies": { + "decimal.js-light": "^2.4.1" + } + }, + "node_modules/recharts/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "2.0.0-next.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.6.tgz", + "integrity": "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "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, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "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, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "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/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" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.1.tgz", + "integrity": "sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dev": true, + "license": "MIT", + "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.7", + "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 || ^5.0 || ^6.0", + "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/tailwindcss/node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "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/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, + "license": "MIT" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "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, + "license": "Apache-2.0" + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "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==", + "license": "0BSD" + }, + "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, + "license": "MIT", + "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, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT" + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "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" + } + ], + "license": "MIT", + "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, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "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, + "license": "MIT" + }, + "node_modules/victory-vendor": { + "version": "36.9.2", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", + "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, + "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, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "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.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "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, + "license": "ISC" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..3b8f325 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,45 @@ +{ + "name": "amazon-transcreation-frontend", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "next": "^14.2.0", + "react": "^18.3.0", + "react-dom": "^18.3.0", + "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-select": "^2.0.0", + "@radix-ui/react-checkbox": "^1.0.4", + "@radix-ui/react-radio-group": "^1.1.3", + "@radix-ui/react-tabs": "^1.0.4", + "@radix-ui/react-tooltip": "^1.0.7", + "@radix-ui/react-progress": "^1.0.3", + "@radix-ui/react-collapsible": "^1.0.3", + "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-label": "^2.0.2", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "tailwind-merge": "^2.2.0", + "lucide-react": "^0.370.0", + "recharts": "^2.12.0", + "axios": "^1.6.0", + "date-fns": "^3.6.0" + }, + "devDependencies": { + "typescript": "^5.4.0", + "@types/node": "^20.12.0", + "@types/react": "^18.3.0", + "@types/react-dom": "^18.3.0", + "tailwindcss": "^3.4.0", + "postcss": "^8.4.0", + "autoprefixer": "^10.4.0", + "eslint": "^8.57.0", + "eslint-config-next": "^14.2.0" + } +} diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js new file mode 100644 index 0000000..12a703d --- /dev/null +++ b/frontend/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/frontend/public/fonts/Amazon-Ember-Medium.ttf b/frontend/public/fonts/Amazon-Ember-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8c731e964ee1c8322fd20b78ee21d74b1f74dfea GIT binary patch literal 162892 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 literal 0 HcmV?d00001 diff --git a/frontend/public/fonts/AmazonEmber_Bd.ttf b/frontend/public/fonts/AmazonEmber_Bd.ttf new file mode 100644 index 0000000000000000000000000000000000000000..aee22007e4ad3cadd7e6afe7efd3848d884c9906 GIT binary patch literal 105504 zcmb@v33yaR)<0ZTH%UYGPN&n^)7?qBvvk%@r?ZoUkev{c5R$MZAwa|cA;buXY$CD= z7!h#+0e8e@9ASKYQ4tjdmBD2kM-k9LMaKmZ9Cf7o|Es#UlMd><&+|QBwEFfv_tdFV zr_MQb>Qvo^P(nx$K0JuNtg)(M#-SZY30-}Gkg)WMvT^05fnzTb@M`Qcq}0AR$SoCp4yIuHV$Z9Jr5wYWvK29lf1L|8$uUzgGwu zRX1~>Uk^C`LL%|OX7|pSCvHhdFs^h?$D&?bLFz>!YcviujF(5sP5T8Rm3ubl<7Cuvs_Vk2!o}JgR zxR*J}F5s^NzJ7kkyjh>GT{Vf2J?N9itlkBS`gi>8++so=swX5gu(xj(=Ldfwq4=Qq z51(wybLBaY%?K#COh!wnN623-6}$QMJR_ucfjgQo4#gkpNpCsz;2|H+ z|LPebD2Ye%2m6jg@L7&=m_$?~o>Ramk=O)whq541(te`%%qMzW%aoF@T*tZH z^Y0v&<5c_(oWqh7ILGDp8OlAU$LqRaX^;(=y46C#iW@R7DR$Yk?U&Nd19d3fIkRXyT*S86}zQ2ZRDM}>DtGGW4K8r{beGU4!8?YEsFSX-(8rMiXzgD^42v`+(Zz8_zJyOf= zBwo^U=<5LSK=FoNnwSw~4k@SqfR1*dM4^9cfYT)I%c+Tsp(f|YtQ%t^m$^W8$h##l(G=wAw?4}`U~0#h3$R=y_-gS>0#jBO`<8+leYl#2mc`? zL|m&$B;>&LLx)m@@&-y2iVB765Qlrxmr1BcCi>S$vM~)u4FMc;lVO9?F)9}F&YM=n&_dx$6wq4XzI+@Q1?37Hz+Z@-o_Zh8KMAM45{3)k0^l0X?}b zS*9+XbkRloiVh0>nw8dDEJaQIX`x_GsMGCAD!xQj?EdX~j`sGW z>_eNU6@9D{_QLg@_m}g_eIBoeJ^=Sdlv{xRq_}ckxNP{9>j=g|T={)Bj43ZHyd@x>)!@H0-S%J_Y@dEYPnHFpu^FR*fzriZQa=L^M{%5xU%L;3*n;j&3aU$x-r z2>Qt7`3PZR++ReWz5$P^WGqc}e!~5gWCm^nXmvR+uqKpQ;PDXdC!-&{pE zZ-)`)WUo*pPYlPT*i0M zz&yy~RuV6)E(jS-{7@r} z!jt<25FPDRoWvx zDm^JZB^{GaNPqVT@Cfw?^T_eY^_bu>!(*n$bso1x-yFRw`Uky_K2WdK8}%lAy56eK z(--Q?^bPu6{c`;Z{bv1s{c{FSgT|mU7!4*vs$rs`$Pl1}nS37JAV$PHvS`tdIPg@vLY|HF>5 zW9$QoNM4e+=!XgY=tn=+pdXv1+ob!Yedx!Zq~quZ@d!je!qJaBk9v-2GEI}4mx z7dn1I339A(s2v@SKvx|?K3z-5S@l^&IfR_~@~q+P$7g4q`RiGqvxR3)o;i88@64ah zAmTXl-I?$3dE%2TXP~cV$QgEK)af5j|L62qgq;5T^gmCZJ^kM4yweemFxUqFgZ2|? zK>jZ7vEG(3WSC@O4vDZI+0&@=9EY(^tVI6ckEIHXTKO@edAC0Xi~O&D5-h`?tS9qG zJ=qG~x`S*dw~^~%HG^1x--(sCirmPp1)8@PISL;#A2V-1=_MP<&GcJxnOr2h$!79D z4WqK zdK>MbkI+jrmHr93ynybbPt(ifCTgX((>}VN{z&_&fhN%HbSZs?9)``vP!nyWchY6_ zAR}}Ky^;P8qcn>ip?A@h^ndBgjFDwDm)=cpqR%sl-b~|}C;fnaL4RgmbON15=h7SK z1M~n>Gc7$qKc;`Br)e6s(SOkMuq71>V8OJWPNyg78Tt_Y3;hop#e!G}ZKjp`hSN-%L+8Wu zw9*>-4*i5i&}5oIKcZjJE6kfNrt4`eHPc?Yinh^OSoNoLAze)$qlaiYZGyM@C#|59 z=-=o$nnCUK&-4{~ivEi_m=B9$db)&epbfNxK2BetPtX_XPxLyvmT8!d{+)hK6Uj6( zhb$s}kxUKyg*(ghsjIi2zi;jLSDrT_8M|W$H;N= z26>abMNW{vl9S|Z@(y{Iyhr{vVkF-uf5+sI1`Z&-o(xEH?RCurHv zh{v7q9zU=Hu;pCh4d1evT%i`Sno{_bJtP3Rk}dESPjj2#+9`AqdI`%Wu;!o01hSCq zBKOfK8V&8dANuM|Cc?u!2tV@!yo>BrZsQ&W13V~v$?dSw`=EPoDSB8yyP=D(jT}Ev_V>nwq3hgyIcFT_N4Z!5Z@4ENO?$C$lW1Fb-}t$-9Fu=P)lfW zXj^Dk=={*tp(jEwgn5VQ!d2nR&5=hV9Z{C3by3HogQHWU%c8rZ zw?`j|{yh5InBbVyn97)SF|Wk@sE^c_>$~;4^oR5x>d)zaGMu=J{5a5 zj>M(M6~)!YHOIBb^~bG?8;si(w=eEs+>y8waUaHg9(OU$5$_!z5^s!8jn9iOk8g;d z9zQpJAbxfH=J>ngABulE{)PDC@$bif8vkwlFD5TjkSW@fWXds>o9az%rrD-G({j@W z({|Hd(-WrWOh--cm`~=3ukQoNk_KUS}RO?=tT*A2c5^pD=%D{@i@g>`3rV z2uUy|q$cDglqWPKOi!4bFp#i1VRORW2@fSao$x}!@r3siK27*G;g>|O#Gu6J#H7T6 z#Ja?m#JP#f5;r97NZgyaKk?bbR}xPqo=QBQcqxe_`6h)X#U-UD6(m(AH6^tt^&~A$ zT9dRj>E5JAlAcLAob+bW2TA9WE+qY$JSsUjIWM_Ad2aHiw$bIBKy zf3=LV1Y7hLizUZWW~sMKwRBthEh{aXEITX@Se~*Rvb=72&vMrCbqY%fO);jVrsSoR zr!=HYPnnxCkg_^ubILO*AEum34NQ$pO-SuZ?M+>lx-NBV>NBZ_Qr}FynEFdvbXr~7 z?6j3>yVD*?dn)bOv^Ue zvbJZvl6BseVC%H)uB_nF+|xgX|{JWF0}UQ1qAUT@yAymfio z@^3EM?*tb`L*r6)}hzhctKVa5;7_$@68BMmVY-?tSHrQ)(LS|+H zil6wzH-Z(Kz-8XZsCZxoQSnb?U?~Z8c3@_{8!b8#?4NfbW3DZu0u1#J=$X=4}JX>?Rb$OLhKTn&`Byc%55PD z_zTHX=zT%o)My-8m)wXj65+JdortOgue#t6Yo=Z66)T9?ZC0JipK62vWzeI4z^eCE zoYHTG8{vG~!Kb&(X9NX#v&Qa5^~6X%X^10BqoHrQF)GXSG4xf3XiVv=D%&}EvRSFEZcSnQbLdm#FnbyN z5{)d?>Y$kT_?RH9AedV1z`~g0&`rQGVHL)8#}Dxy*NO4YAEbMrf6%EgLd?k1%$9Y7 zVO5MVi*|m`Ea-<1dP3qegG1c4mBtrlWfk(WV%_@X%h#{FruU}Ry}he%>Ro*3 z$tMmSdg94LP%Nwu2)!SBqu|q^R@v-UH4S+B<(pV+PG8HF8Z-wSI~t8ZdsxwGil|U# zf2uNQ4YndC#OI}|%DJ{=#-hCCb7_$ya^;GQRI{bq#s-q(=T6S*y|ul+XVq;j@uuX2 zcuubn{ClI#2;4+dZLmMZXxgAQN>9Ls!Di6Xg7*0(%NnQ8=&dXsTU6pVM*U~Uzp*ge z=Gi@|barmyLX+K=mg32#zSK8g$Rz}Prh~3GmnSILs8wy%#%j%KiMBePr+MpIT2?%_ z{#yEyqpWxR&(z!Tqv&5Q_)*LJ*oU}K*)-^(3I+k&7aZme)E5;OkF9PCqU#+OeG*gV zEGu3*abEjIQ%-ia)w_)*_C4UesJ*m1KZ(nYkwnlnL2hAO->A{cjTpR&kfctV3PV;! zL#mJ@o!KzaYeL<$zM@6rSF9X&^K{Epee|Rm8Tl+be|8RQn%$eUV9K~_3m<)W@srbo z)!n`Uj?cro+U8j?LXfK&jfTi$X{B6((sJtIc#wYgGb`zzcjZ~69Eb@##R(gTLq>_v zU@tTd=cbrzDwW+G)_c$=c|_7^a7YYQ#)kRiWmXieT{^ICY`!)9#yPWBI?l%!^KJ)!H-1@rkZ5F3Xmg8k-vZQLIfHm_8=m zYT~5_u=B+^eaczJGWvbW`S*MN6tQGt{|~SjLKULQ>HZVQldAM=zDuQ zX7=#Xv}8;H{)ZlvId{-_8pmx~C)@P@Ucaino0{S$<~jPgZc>sDoSA3`HiNlDD7lx) z%1s&?fOfo8V`Hk~3ae_G9(Q~&vno79TO8xmh8El6JH|CtwoZ--(uM|u&N%Qp8*M=@ zI(H+64aY(QRWjx0D>4c)LfLTpUbgp#5OPekjZqKpYumZ-?^P+jCJ(HZ`l6oY+C zUb-SuR!E%f(!-Or;fDm)AW z$j39!d5pFrSHWX1jK0+-5C5*NuIXJ}_U^`R{4elu%B7vGfrN-1lFOr}jK)UTQ=aoP zz~4qZR)9TaFMN&{bW@!($met#a-T#8rtMZRsax09HodlX&yuxkm-KJk2+N?vA9zO< zJdCZ`3h%G-udSWl*0zV^a9nP;I4?q%O5sdJGEnVX;ake+S{je+uS!IkGAtjknF7x` zgf|X#XA8WnAy^#n7E7V1Ya4=90Iy5nWe>rU0P7d@;PaJsGf=l*;N=X#(tvlZz{Ae2 zf|mf;d;!ZFg5@F4*^W$^isTQ&kO68()=dTJx$5R2ciGNf#K|NM+kpmoS*!5#w!pFfhMx-1apA~q zxp2774$H@db5PL9`3)Ut66nZs{@Vx~w|)s6xnHl2z;WxBz>)ifXd3-;wKd$Y3O72h zjKCS@86n&dKgUPlaJw6p&y9+FHsoDW9e4D*xWhV#@2 z9B%W&{H#>?k@Y$6H~et@S*ghR6G6v?Gc0GW8!MSCLz!n6j++bxjyx8!Zn$tp^6cUV z!6(MTg)_`^nj1gwkHF!63;lw(usfGCt(1Y4uo-6v4V6u?2~D;0+p6oT8p~p*)Ge4cJ}%K<`7|~mHevPBQMO(~ zr1Vli%;e%py`z>a9hKOdJo>Pop}DwmfzJ(eOtd-RF^^2z5|t3R-!lz!VT*G)_LL4F zK8V3dR~zS|hz_x#&c^CjrRA-w5k=GDzJcuS>gr-kL3&DQYRMz1>FKGf@9?^LX>H$F zukAZVX*&X_<2@;$BUE)Ky`!+qn;N~#U=Ebe1Wb?hA>#UYIWjAtX3U9lgCYz`#T<-@ z453a)Frs)B(>qekCfYSg<&!(NGHZIQc}m<|pO>DZhS>i8?#Oz(hqq^sJ~uSK%^Dsy zKSrQH`X*S)Xt9?Skyc! zXtZ~*ck`kpk@JIc^PAD08oXP1?>LCYOET1&%lxmuMfOVBWZ-=GkTX}4#z7X^RSOs#bYzO zTWt2lV~;I+?6G+Vdk^A&fk$JRKfRsL^BTlv1qdBtdwbDsw2k!%XlzD&c0Cz~*?lqg z@=pu+UjUZ?UyS`CFMMtj@-HB*fVU70!I4Ucp06tGR;*NF`D#VgW^25C%sVtFqdTKz z$C$r6zO=PY>z&s-X%aq=+K|v*GwQd4=K#J&h??bNdkVP4p&AeDWmzl;Eul1waGJ3>u6nmt`zC$bf7u_@xhiW}-Db&Wi z97Qw_XxkJdH<{dlzTbG2Ot`E#eEBdObd$-y5uv@v`@@xnD@-&DX$&LHKH-7!bnoWyqZreJ3^XBneZ>y2VjW}EAC7cX`4rn1~dg+nA zKCbtA=Wcog>)jNbW+9raY`cJLj zgF<~{qsFGsiA$><-sTRC^~xWJIV`JW^$dYj@Im%#|X~rg760 zcbj~1Y+c=0ULvBSBT(qhy3*1*QDS3aVtL^jaZ zLYDbdO&@Ps&~eT7Th4T|1HXPopAPJ6>tFTjKY5=5@sWo*5q$3A)+85L)R0xhs$%W2 zDh(b~Ml^PYP3wv1j<^wJ_?zEMrAMrG5Pttz{gR{C!D zJ$R6R&qI~1D z3UFfFpMJ&PL4l938Ps&pv5&s<#*@7cgiI3AI_JW7|K##1?wTQCUE}GdDGTI$amE}v z>2}9sRHxjsvdo0U44&VdkSBO>yDY7`?h6JT5P) zWzqFFIZHAhHpJONQ-e%NsU~yEGwTX-%adwaCyukvGLF8txGlBp%h_#;g!g@@oXna<4plFAOA!7}p2=1mbP z{!@Ed>?}=qL`1k|RxInC>Yox(M5lNd!rOwqy;BYLC4PQO?1oft@8Gs@gU0~Z8%mO} zBJbwsc;&Tz5-mEqcroS-LXP1CQ9jn4Yk;;;-~uL{r}-SWkRqdU{uuW=Jg?A8Cqge_ zD>@-fyH%t(bw|r8E6X+(l#~=~o$_Ek8Q?7WM4bI}B0t zqYQVn&Q^DNj@_M+>+heNv3o2m1ab;QTYYj{8Vq^}=!N7{EuuQ!fa1l$0C)DdU@I%| zkD6j%{-&+W9Do0uOjlb8WDZVf?Zj-3%p4y`9zx2S2rnm4To0cxMp2Q!2o{r~b@^g(24$yo^Jg4t+1n3%nlf#PVCY(Ou zdo{brWifZ79?KQ*`vm+x4u`L^I8D<1>_L))nVWdZv9F6=n1pP#;#2N|&Tf_D9G+si zLOWs7S$JzE*2wSZfeF(ZXAL|yb=l{)A9yRTr#!Vx9bRXysn72&s7MN!ZIiT`7@K~} zE#3QOZQ7d>C*i1OjNRBDH9fxV@gp#Hhhri`_M$8rT6c!2Y<=5UMiCY-Tlpto1tXHiec?SEvs(I8oFvJV5! zptw&)j2wgaP`K|(rpWeiS<1c(IEbNeulPN=4%cDWeH-i^I;@j4R!Q?FmS21JY{ikp zmmFgpW4Im%0jE^PiJ(%fM%pcK*hP-O5uuxiS#ehG0NVD(s>Y1@o`?KaiC)O~CT-`X z2QN8hJkhdi7thS$9H0?=Nn#yThdTaPxkU2ab2+iEY#vEiav}4pTg1MIaDLI_w&WSq@ zKEtufiCvFAaqz*G2~+aA=XA}|-^5IGP$f1$2-o(}vm!QV#kH;P9%F79Fx zU}SQSQ~&cl4?nzPcJqOQ?7*KNe&_%zaacbNK85z{Q8^U#5NqH>fYu-uxd!;$*BvK* z{+VX71N{&5ALvILGOh=3kwYHBRoByJ9G{*$2fQcxd3YfDbQvcS5A*pj9vN}&pA}2z zQ{qtH=;JZTtEq3=>alyDJg|RYQg`Em?m5?bKHB4WFf8)mBTxTtVxM8b^+5ykTy1Za z`NW|G#CrVv0yb-ZaeTdfI}P4W&5nPt1CGyWIN!CUqzRnxeJjj^kcPTxJ0DHJL!95y z8vw^VDDQRRVKC3#hvZnZQ@4L+%!^y%ZyQ73cclE_;|n56zxSdJw1v~sSVzMNsOz`? z=TWqmiA`BF{CAq@c)@Wit#bTjs7?s#Kv#JkNOU{J-t3i^vEWl^N`ZKeCU6b|1BD(T z(V%9V?pk}-ng^bLVGlj)I7aObJ%|s`4X(XtK3&-S;SF3A~JDpXYyo&+pH0bS>%0W_owr6_k_FV&e_o@f6^%f%a#oc+;GFd z{0CZ_@9&%cKwI+zE?pZd`rPgY5P<8j>qqIaZ9Jj zjNSZG;LYQIPL7yv%Ium|2^9~ zyRVrummTQqENG8#yiffcKhW#uVyA_VRXXGt1v$ov_-@!jhgNIcaCu5j=GpxB*1C4>rM2aV{Ca-uHK%#FVZg^I#l|WQ3qv#F8#zziJcSSPk3F8WaTrv zh90|Z%Y&bse00T%2j4wMaS9fb==e`QaU5`Lm-__UVm+vb9Gq1x=iId4efHqy!JS`H zLJv3&(K1JsL&il+huKQ@LpHI|k4V>q)zjnjvSTNm-9!J@-{VMz(_+}~zCceie^>x& z8L&POK33%2!~y|3u^6@xtr}}uyA5uar!V}5Y1#&c?_Q_&}O;wGRw#MO|8rnYPks|=uv5m zDz&2C<%3amrjCVKoyDp35q>vhrCPFcY+3A_<5F1E<|PxBRp_HK>Fx-}&k?l^jkR1C zEzZmIFE|GTuOI(=PL&6;e~G9~T)JxAlB%NojPlZwvW$|DK=rznD>myp)D`3XYb!7% zb3Q=}=MK&xmgLzzzJ?Mj1NdlYlR49_hB$akM(^`2nlz@}HqbF4Z}8i6OEP%0r{s)T zJaO3_DO9==IWv-u3Y$=0U+1FxJ^cYP7c-?e&tTUM^U4=-Dl?pr)t2>VkIM05TVp%2 zR@}Vix|!E{c^u2g^?2n}X?|EoQ1FJES8kp+DTc&am*8aHX*0vk25K- z=HVF^D@NIpl#GkJHZ0E_KW#zp^rY%2pT+AIcTApHS(@LfOVcFU+cS%-8~X<~M@Ly4 ziA&cdcg7Ts>j?1sF>KrTYVcbQA?t-6z{iVYR$|`bOl#G2b6mVVdvLIMdc}A;A<<-X ztiiZ{Q#iiDu@-zHm?2-VuP}ch(&saX%S%+!L2GVY(A<7?*FkVx<}Gwku>txA5O_5Lzb>05>p|x_og^ zLPdf`8)+=bq0U-MymX6~&T%K?Y=n<}5d6UX#b=p#s&aUaM6)la$WIu{zM1Z zdVVrUSZ*N_;z;_6kX3}rbRc`|q>1AvhAiH&L2rsl@YB{e{ktu2(}tc4`f$v6pizo( z4MH9gQL^xO^2`aZ2@|7t`?q$K)ee?tWe#SKn^-{y9DkmOgANYL{Tlyu79#3`k}`K5 zJ#x>y1$Vv#D_ldD0Zq)WQYh$OJ$KSCT3T9Ut_w@DL`9V}uab}u6EGac`6jM1?)8$tVO(=(@o73ff>Cw5jK!eBiHpmp| zYJ*l!RafXP$B#6inkJO0)KWQKQDZBmMe4G>ddcL|Pw8!Ge;LAeN5*xRMkN~g|i z@3{6#V?V9$r?!iC-g%L(eEV(3N}Afx;CP42(t4h3&FevFHS}FPgXf@o8q8wlw`2+<2X=Vs37(9 zvE^sv*N%xx%o;Pkvhh~OYnvm@hKR5T+Ge!a)3U~Ro71%w(fvP_H#FR=%kl~dMrMz< z6^FLgp)Kx*VQm!qkajmu?4AinhWfeto2JibY@9K@Dc)d=i!&N%a6>~@S6l0xIjwD7 zO;$UPfbCXj57$_GSO5ytLQ!#3(jxpezk4Azx z!TB5Rl#`lpJZ5>7uF}PtW3|ZrA>vD>)Mwm+l7ikU`Lk)x>`5p--Ik2>(lWc=VAiPP zXh8mgin95|@@M+omX>RHDWP5|iRmG8XUw=QI#9$=;Kxl?NqijtFKH<}c_mZM5qJeh zeakSGeN>dj^&|04Kr!JhO* z=r!gx&!L#jrXEUFYw7%{O?j61@NvpTGoxEG(`zhikgwb~V@)9B>nS`rGGrP_V^-xi#!N@k~bzzaMifn8W}&gV+h`H_78T4(!5;Ul96|tYs<+!dKoFwgTGpC}^9IlSSShpC4ZZ=S=V# z3f$RAkCL^-tk4ioIIWR9Xv~kNy7FXar_vaIkK80v%NTZh#ue`}ljZ9AA@d&xWfM>&7q_ zI=$Zw9r&4e)7=;Pg5GFi?NChJw$8D!7PEnV@R0@~Jog(M=L~R66l*H*7JxU3d0Tlj zj(k85iniQzYkjQ65{p9P67~8-UO*#{<^cCN-l$h&pH`-cc5x4y|D}y;v~&tFmXeRG z9^@-GoC)RYH4aBUa^z}lc!frtLn|}6A5EBZ9*1nqh51Q!_ z6JL~k)jFNG)qu8meB@f~54R*Y@9qe&@>g1+&4aH{KiB%0rvQ{D9F*SfnCG@yMibbJ z`5AB0UqprwK1RtZ47bC(Fk%@y+{~&~bdPIE>)sKh8QfR6q74L+j|jOzvVSDG;YNSk zxsg)*{eE60&i|v&(s}R`&*PQF+$e;2T0A70|#`<_dasJWf%zMZ}H_jvw%3 zju$Jh+%V(T+NxVSH&oKYjyM1FADZ>+$!RUEoikfnrqxVsexPr`{jF1L9eVzg(_9$Nd&J79bXqr@9L86w*hz0i7X>5WYVh2za7W3MTUULS6atE}F> z^R}WJ6R={R(=>KguC6D*Zfo+Kc4YLZ3AK(I`rw8;4H0wE9z$M+=OdJyB=Q+z**2V* zl!kMXbXG!j#GorNd99L<@Ie+rdU_}?Ngo?ZNbq;6E=Y-3|MTAsC_;Y_Q*oYgfX~1q zC^`A(O1*N|Jd}AAA*dO`LHI2y=umnOhI~ZOOdfJYr@p| ztz!zZvg>E*`$F}VVct@5)?_1HY0Z<4B{TncV@1#G{FEX)&mA_#r8iX6PWKMaNR8=G zhdIiO;rdjmMsK8(i}Tf3f$_B+ay-%k@EwIwu<*#;Z6PUlz-zb%@vgj&%qDwsdv5mn zzMF39TbrA^z7wfS$15J=>q@2=I~{d%=gz06G7CJ91$1}cwtV^4?(TWBf^#(`1)MdJ zBBGUr*&?S|4n63HEy5DzNF8sBYVih(IB(%v$U`bhR>kf**CNtn*>wEueshM_zcfBG zt*?DtRYP`sa=5{qm8MS&$1AaUIh)tBi>>2R%9DaZ{ll^0P?1*M8g)%%ba+rikT!Bm zBHn`!HH5^P$4_ts(|;{rFLbjUyvzenA_wH=(zWXHArH=yTn?M>O31mka?E4i+>7F@ z>Bt-*b$<34UimzYc?Y=ln2-1#7BUD1%JY1D6Dt@Ifs&|X%<&F(v%=SWrpNIki!GO) zcVLgwkxoxu>H1-`&qAM61Zvdz5n^VZ4@PoG=N2>nUS{}vC2Ag#A67zW`rL>#F<9jN z0grm<2C{eZ+sB+wC3QH|76wB}0P$;h-foZT~6pK`NTE7-GLoaP?8CD2>IYd zBlmawlrd&dNK5v2eDfHd1?xhqwyl16$9B?snmL0&)n`_%;=56B_NmkVw0QBKrt@qLmltv);#?i#7%M+-j1lGMjSbrV z*4FKN_R#cy*{-qTw9lpKbEm&1_CRqq)%jQK1D+NUKK!7(6R4d1<hVpevKJH`Ubg$LTdu3> zEslv=lUDDjyREW%u%cRS_cCjTFBb3Djo5b?K2`ij`!73o43?I6 zl`DlS_sR*%`PU8EJpVdg&cF`mV8^tyi!5w=OO7iKI|{MqIPeD_z-eOHIHWT&seA-i z4Gn{>t;(Lkx{N95NR^(mO|iW#_71rJ{t!9(c<6jMkKS-lNKOLEr^i7R0~f60ISxL4 zW>ttiHFxdxO}T0L8TPf;*A=AHdF>4|A${+;Tj!lO?)nv5;_}lA$1Pg9#gIcyrl>bU z953G&6MakrU$e_`hD^jSwjy7t685Sxb5|^~je!SY`poNSBBs2c6Zu~NMw^*o+4QZ*5xMv=|vRU=oR&P?DFyn_e%;++-u3P`IDE)G@q^$@N~d&1_1CA3LKIJzOTUN zYp%a4@FW4p`8Vb-WdV+qHRwP&1-#txDe^7n06#0>g*43t=lf=W%WJVh{2CUg&+#!2 z0sc<~AF&JI*^W>7J`Lbs$Z)bnz>R=oF9z`Q3jA{c_XZq$CxCycz<xcm=24WsRyS5p`?PH-1h6 zD@bupLWEXs3S#F;2p)RydBui<6Xj#M#`wo@jTtw}?GQ!F4Kc&&Q&8Y`qJocw1vZL3 zdC2wyw973O;R)bIz}?3p55Gso;og9|k3}AS9gM>ZFxIQsVbD1u=oHay0$vaJUa_t} zs=((A!QI#Un68H4h_68Bn1bIi1jl(8z~55f(*!&n^xbv4h`Mz9QyvEZU)Jp+3f+dz zm|!cfw-Xw*l%Eaq{c`|y`AfvZ`in}&8m zhpC2)+!Vc3I(H6(U zJ8JPLWA46rDNV+Qw0f1&ZZ&IRVW6j?vxT?h?RtU0?b2%K{2|a%;Wr{MopIa5In8R& zbj=Ghm3e{ZFG2ee7+=8onw!&?`4?vs1s%Cx za}+q|bEAOEe9oaVpW+;sL@_S!3p$;2v}l)~hx(g<%f7dh1}ku!K@#u}6@0AZz-Kka zrHR8S@=f5U6Th;^;XD^QQQ8jr^87m!^C{2omZQIVK}Vi{J9!iaxHumo;O7+ji839~ z-zVT-DD=M+aDGPOVF8!tt_KMxfu=@nP0&1Z$`-cBX$<>T!oIzKkru?&T^ZO3+8lYQyI?roFd>d zpR>hWK%HY?^ZAO+BRHVi)|Jp^(3< zpBsntbEF<_q(Tq*zb`;e3Hi%S1p%)^62Jnl!0z#nu(9rL$A`PwK=;c=Cp{*$tirbEnvY;IzlHM)GH@>5vQ1{N`=USY>e*P0K?VtCz3_Giw9A-M+KkF-CPr zT8=5$JH{9qAifBm$FpC_pQT&>Z@QFC1l=5yCdfNv_`6gSWenD&<-`a141E!OSiu_U zXW&YPbIB9_pTD0g`~O{T{=X42arysUBm6(dKMVpYx=YqW%ojKVFX+gz+%Dxe z3b@{G6>!A&0>78H%k_cI6>wQ^@f)v#AAVl_KLY-$f}bwnvOe>6k1KH5ugd&4BF3V?+EFUMl6m5_=T;_j|+kCfK zz>f*~dq&J_9AD;t&j@?uaGB3NBm6)2OR|0K9I~&=^dsSyWdFZ&g#YLGvj5*H+a3Hi zUzc(CDZ$T9?iV3{j1v6(Uck8rfgEK2?|c*e68=z`FLugy>U(-~pEoWATo zcPjQ91OM>2Xjk_CJ4g6`jxXEw&JlLa;j;hVIl`_v{9A>8+5gMuoca1umd|ckKF+h? zU#vG3{&&0PJKkTh-jwIH-R|?6fXn>vcK1I5F7vrt@&9iAM3T>|RjgbycI=v!h{vwI zb{}}8&Mf$oH)VgK;8fi-n3p$rlSFTAY`of^$a|W+-aGiW94501!pGT=vC^qhBjb|8 z6Is|BzQNpl1Wpc_4EoSZX#`Hr^S;3cWSq%t0eO@iL)-`)gZ5F{z!tQ%DbJAqdsJHJ z_Ds@=XYj4-*#i0z>Z$N6-!A{~doUgwHo5tRqi()oqp;l<(U^)J#lOMBeRe%$A1dI7 z6}XtY&b0Y6>f|4qS%6y!MvK5`-WlzqS(Bj#idm;3dGGAI9tfvObvvTt}}#GK6W zj|=*5jPL;*F8hEt6n=QD=Wgq-4%zx;>{nlaZ~lj%^STmyVlG7t$ZbXT0k0}PfX8~f z1-=~Xy{_-U;u;aA5cgI;ft@MRKfsw&j@MMQ*!MMU^%3ah}Ppz#a2 z7xoKJ>Y{;+kV2uVQEH$br6r!2-Wu62#kp#4zqB+zZ*^`l*MaT$Rf7{~Uq!zg@)7Vw zu#Y<-SJ^(k8DSqBei-el=r@XeU?#%*og6OP$2TMFgTrO}_-2HCaJXzA-;9{cIb5F0 zzZo%?bGSU0e=}k(=YB%w^TG%|Ib7!R!XLym7nGO=ewF46KOysfVFdr2j?Djs5&Uzw z%>M)NJwo3(zO3(GkI;7xm-YQ?_qkTI zE6=rGyU(=(F3+`J^B5XqF3+{U4DtEh2tGMn=JPxEn1gXRMp|f!iPLfZ8~mqnxWfN; zBlzd|GXLL=;Ge@~{=ZY^;Qg$QG$HSVEd!yym@4^UDdh-^dlrd0_rV^UrM*|_wzKX!~W`5M1_CD!ZrWZL$^akoFsIE`6;@=P3f|L3mss7Lpp%>TLoO? z(}BNE$WV@t_o6Q%J_h_YS+<~`F7U;i1Gqfr2w#qW!$OfQIEobb^7~L6F5*AHgB3V` z&xgZ>%mEiNm)FSxE_^NibtkNo;iqn7RpcfqMfOwfQglCbonKj*&xB4ytv~GcqS|UC9-)Uu!9h=Qda7ain3i~)WJw2C~0zn(}ML(WoRrCP(QsLhX zk$s+oe_L%V)d7;OTf8eERA8NPar+9|XWXmsEf2rrakNAea zX`Kb8G8HjkCt-P1Di=gj)RpD@?Q3dUwd&xoNQUeWZy_jt0+JamWF^n994_nw@FW43 zb4Le<@FNs_(O=}Zy+nWIcc}SqU5T?u{MV0_qe#hA{G=A&0jh(;REH>To0~#uWI@sPHGm75bxz16#jy9@`v#599QhM$5E6+PlKlK#* z{@G7$l!tT}Lt&qy?ZcvN^ijOa3D0Gvl2rr3*wMjDojA`Rc~N%Zz7My4c;5xe_IHE03(Ua zIX|?erm^*dH0Jg}$0xUAdntx~g7dp)9eSWEGR2+<@#Zoe`A#<6rTk9z8`LJ=$)4nR zOwDTzp&OzDQnG^_-#_&5 zy1m~;71rhGBYIf0f%!T%(19zTmQ+N88?1J+oS#Z*>|M~nzpsq_0P)Ti{|!GefcS}h zoO&_id>9lEd;2=tch`dt-nBw}(6rXclUp5cPi}3UY#(*!%{SjUs;No7PNGX%W_UW* zdCs80o-dT%hmA!9V6JPy99jA3y#dD|Ps9|9X2TH2MI<0}=7p zebCE5gqJcn1B2`h1z2?nlSD-bdzRcCXx) zs~vu=AAAGz>o%IqwLlZEPFODyD{`&3UOZd-?JB35M69xV-oQmIo-6}_V zlBr!dJ{;-!+c7$0THnn#_x@-JZq69gGR*H3)RPv1^XV z8+IU1Ku&oG0gZ(g!&AD8KuU9&*pYb&enSF_~l4 zvF<6H(CP&$rw=2}dj+XnkOt;~#Twy#D%S z%dWrvMzq2Gx&{4~r6`}{#IJ&ZHhvI<|1^&c=ZRh_8k^TU{_@tQ+n+pb%c-f!!JFiv zU1fM(5+dZU|DVpbzGD^kC&zpKpvwn};r9T(XKCzT^4VlhzUtsEM62?b#4lyT4dOVZ zP*FZ!)VlV@qBT7aJUk{N)Q81SG`_uVW*Ij2yww*mh4+9Ud>$h0&09hMbdCf4;mU&4O9l?2=J%iaLUeC*qUUA*Y z*In`G%U9oi^6lF7#UJqdqVvm-@I%@xyw~3goHukXvc{dbODixe?OgQy@`bBrZYVC9 zRkb>=cuJy-O7R*@0vPqkdMAe*ujw;dGWE+|q#Es-U6sSXuqZ{3G-(xgn!d_eF;QUhrWjanj z$JNId)mEkZVup^l3bb9Ch|-{{@Ht6(ty`uXSCg4jXj6@f_rxDx@Xr5Q2Tu13DUQHBs$ON zBYE$zbsL1VoWJn&$ozHs&Aag3zzaHC1z|>-8tf~cjK1)w5BNO*yB?1O4Ox%Vo`v3H zX*eS%;fI&$$1c-5+wC}$`2jLn=&&M;w}CoSml3J7MO~S&b7<3!HWIyz=sSoqs8xH?KU#Rke9u=@BzVx!!pv=zUZ_TfNNH z`Iu|j`>tix@JcyQVCdhX9DlI&$M~60W%8;?dcjw?q2X6>sy=Xk(dgRJ3tzF~F z8Z$7*1ewW=*XZFJR;*jM;+?3$UHSP zz?5osu2`{d{qhg>r@MA_es5ORP>|}ndByw%hf9qDsxP{JO2to6kDynAqc1Z93tEO=AlR#^Q+U*dUKred~EAo_Kys?fm%*7tWtw3)*-? z#g`#P=O+m(IIg^8dJ@Hj!1Qz-bYyG)dRF!NEAAgLY|7*XZ^X|moVB=9KmNF`%O2+R zrC^1A%tL8v1n6L^i!}%>QxP^wb*tTn*wY!Sy`Ir?XGaVhxn#j>4;H1SuUI_o^p2WM zlP@SQC@L8;Y`FKxU(G#cm?wGq@T!`ysHO9$O8>LZ?A+Y?%M2?NjB88BrQ)Z@N*`-vOz~?ZGDJ`BlI(IYb*5lKtuJoPoQ+#Ehfb`Fe#-jvvx}PjDh~>RPsaNhQizII#k}JhJh~y<}5sO2b#0= zE1h}4SxfjsBrv0!Y}q+ZMNo;habBZBOKzvG>xR!9nLmEW=~E}qp50P9Zo;%#b2n}q zUpA%s+&5$6*F}eKE+}eRmp9h8E~9?Q#HGIYRWnz$$$DFK3X(CtJnCceWO=@7P;QTU zH+Y@Hdi^GF4biC7bFZ*Kq+e;)B0bi8VX!ssL4O9e3I(>yl_u!D<;jPyajYc_NRA$O z-8G(ZGXh2v;&f~0_pnX3^E1->ldA&s@Sb69E;w7n(0Hc!OX){U7QH|DUy zs+s3!W|fRO-=9@D_Wa_ioUELz`Lo0%!>HkYy!if7`DJ-Shvx}xk!M7L zHZ2dxIui`2f6BSdTXy!PtMmJ(YkAxIy?C2liXQ@RgW;EDy_p-IQNhD%?K=Zk$0)Nk z(&L5jBg1fquKwPS?|$$mv1!+|9$KQEe{qdHV&?e9g)#TscFQAa9liyJcT_DHn$jWm z5*LFi-pepAKf(35W5W&CPx9Ka&xPwfoKNtc@4|OAFn$HO>HVS~nD2sbLHgD9o^Sr= zENVaX)b`(9f>*1evQR02eaYhMQ5iU(^pU)?J%qdxxjVs`y17Ol#W#+Sx3+!Gd)vNC zOjh8n4fg6BqN0l7yt&CUDDRYi0$t1%u&Dy3Ca*6TS=_px4&#Z3msU+1f61d}+&f3k z{@{{V%EyFtz92@zeh_`%r;@(wFHE0?^zz!+ivr&t#7v0(?Zk0A##N9|?Zj=T9NS)! zlfI^KLSukjWYdPGO|cDOpo#b6fNig^5?L0@KRZdMzi`REOI`@Rw$Hv@;-dU+SCy(RT%7Ocix+a;$YaY`d-L+yl>Lc%z4?#y9YdhM0kwt|w zs9j<~t$py~xmj4fXQakFh_~>!^=T_>qMA)|&X=EKoLIYE&tZ)Mp4!JEmP4l~=`PRA zd8O5`-gU~(U8mGcoLW4u#=G~W35AKP#D3Qa=lNG96qK#yn6CoW-$ORW47hJk^MUS_U!?=>$dxl-ab-$T# zHRr74xQ-*APn22?z+y>MkDO;g-aTYxC~v8|Zr-`^u=VSf@58&qGb^gAb=Q6O-3Lnn z%l7Vle|zO*X|Jx&Q0RlzUs<{|puaLe>}X*F^~yDCR$d_bD*zWji@IE*=PVrBQ8J?e z6OVnY0^=?qi}2`a3578k>BXZGhUfUkChuYn+4FOz&+%`3Gs;^Rw&lFVi~I?3oj@xh8xPxD$Qm*Bhse59}!5HY@42b$|*a4{Nq+>)qm|=g(kgyWn<&Y4brGi zlj0eX^&(a@C>N;(c(cRuOS3cd0ND?nr@L)i6_}2G-&0jrMzNdnXW9W zm{2Ztz@h`an@act<}x0C|P&*#itjp2wP@6GiG?qval6q@x19V$%ALl z9-JIAeV$GGPo%wWfB5*kBf^#&S8irzuFEVBJHq^P&XkyhfkXWMAp;X)rl9!({d1A) zI@E*hWWMXP6XnnhFP8Eme0E4Zq7a|;Fqdf51NF0eR}s$ld@sULBZPCkiuwV!k#o>mM`Rau_W22e<?gwT2A@hsaQWbf*6~)pbOiEBy+*$MCDc0v&gQ`ca z2%1x!f7za=8?8OnW43LDa(K|HsxI#6kUSTo7NP4LsUI*7l<6tlv2)Nls2|#ewl!h2 z_;=S``@O$h{TGw+B@BpA=55Q~2d5By5D)c1#HN)p*`Oo)=)t3ku&mI|k%Q-Riax2c zM*n`x7Ci(<#+EHowjS7q(>}m9(DwPk_NrnY&#|o17lV-p>6hk$d}a!ke`!zL17+Ty z-u$p$x$*BGv~;}nSqGwno~(C7*Tf^bCb*8obrY}g)ZyB}E0A9auQ5=1U<%`K{Vwu@ z+&r^H%&g<{H~0Wi5g-ivDI9N-t~~wJi^fm9XyW*bPCfmW*qtZ;p|fgMw1x~ldRA5E zA5PvGdke~fcJ_nTCy-IgOlf;qv}gnN04zWf{8Xggv3TXAs?KMwt*l;faYNn3i>oWI z?R=(c(n>R@edE&O^IBTR>{wWT+0uoVZ&piXxq!0My6gFg=u z{S|6xI11@xsN?XiX~kU`;IE~!q7nIqyy=_v?85T#;RTzIY#+CFN^?ng^!X73lf2>K zDZaRv&YQ+ejf$Ht-&=@?FByOA`NzyZp{8T}sO(iIm1bl{Mn;&(RSPH0UpjNvQj|gL z1mxqLJ_*|Vuv^Ht_yDeFU#yY>#!Ia^eTrN?Nz=DC;rqAaW-lyRGdXwG;L#-|6K76N zO&wd7H*93d9`j_!>FbwHJj@qgS2MAG!l0Bt>p6obmX=Q5FtI3aTqW1i8Yp}rW!>Nk zDY?Upt4M4!;Y)?a3t7g)F3+5GSIo&BHa70N$w$o%4|DISJWG2A3|S(uLSM1T2YV8je!!_uLLmjQvHyBP2u{@lgo=rTaR2(Go%)u zjL#if-!Lk#aNO)A$qBys(+Z}?#!ntKWp-wLRP5lCL1`O?;F~LW?__?3`Z>Jg%UdYc z%y~LsFhE`!IBbS!ndrSbKQ#_-wu=^S+y0S0{^V^1)tMawllRQX8#ve(6*cIn#f{Hx zXlm+ssJ65$DKcwg*7C8WAC0~#Kz*#GRCeh zo-ub)_2XM#+uM+HF@3|kgrFbj$v=tQU=!%e9wUCBN_e=|Ky6s*=ZNXH_iZi z-g5s-M|Xa*)#>vWQHC+S`%%Yj|=JI)cB#wO|b<UwxI-SM2XJqrN`dPY|C3Uv%Y> zEH%yOuhVuNZdM)cbXr&E(U3@Q`m1!DQIpVqMaVx+MrM#-_2g7g+@EyX=FK}w)>IC! z86+l_*KgRPpWVLeylwNgPKRL=Fr(QEuDMpq1MC6MZKOyJ0?*Mfv2_)cVZiPe_(q^1 zGgA|W`qRorR0OOokBAsF&}qTcbYDbx{FoWX1Pm`PO!r2515M}fsoAJI?Jv{f2g@y) z;mg5bOSCuuzVzI%5fj?x9DVA=r)$@f=>sFqD9T@}&l`Mr+4Sa#=WIFQ>`hmdE{nf% zhG5tpjQcl16N8B}h?PeL^z&~l8^37wh5FUo(z3JDq7rA%|6mh@N0n?0_JG@xk60S0W4?6ypv~FpIW=! zp3bSMs;cSyb5%`E)t*OO)yFQFee5jP(MJb-kLVZXEOm9>=UVb7*OEE#N*{)Ijb=TN zU&?^oJnZveEu`0Ai#)}VK#5oY;_#UJOJh=oq$c@>4INQ3G9z{4>9Vuipk6z zRh~aMr(=)qI3cqr-LoM!qpD`g2c6enUNk1oG)DMmO_FEmM+S#C^&Ci;gIyyjB_$l(}xs}JFlQ(%;NHjc~MdG zBFh@9=U!bp_pBM^lZx^#xFD}+Qu&Ot=9XSPcWUE=%F@zG+y7$oq#SvJA3Hn{BRvHj z9;b0CY6t)3HKw5Nu)E$qtC(Rh17tQ4Ac^A^&q+m>Jd zdcc5Rv)oNfgmW94Trv09d(S|~bPd?;;IL%S;m?|)JnY2D$h7uQ4#f4~VxkD*>%TQK|~CwwBqIfpYG`=Er5 zW8*;RXEFQv-35u2Jv}ly|NH5oQ3tUslxpk$I8lLoMD} zMEmgRsMq!DogJZDX<{+#ddHC_Y z_g45C)jAw&aknE_hE|06alHW{?eIyACX~~Uyc*QeYBR3IC-*in|5mtue5q8*(t&>i zYrF~PHq=_Ebk}el!demf)n)9z4x^E>4)mqK&!ibrI)33^U#h`v$4o$Gg_>!vbk<+Ym2|S zc}+u`e`;$}y?<##TYDpdusANrx3_tBjNGki-E>@A-#gGV%89h$3<*3 z4o_VcX8CK?53~!?oiKH?cIzl_%69;S2ka6Lkg)T8uhJqF(+ z7_0MjfiA=wVKGd$jnk#N3^K)V$kqO$%k_BmSG5n8ekvd;lHFKSbfuoEtMEO%YCT=g z&@=TcU885~IeM<1r|0Vhn7L0?r>RTyLS3sDsfYDqJk_zVU2!4Cbr)6}(U8ec2Je~zKDb()j-9`c zs2kNyDqAnr%k*J-xn2S5%`5d0_>$Wyy;|2nn!Hxm>ju3}ug7k&M!iuVrJHoKZUHwO ziZw+p?4yssI&u_j8;-#k9!nll2Ka*X~7*k3ylPh7Q{u4bs2u((~L zW`m#1RrAz*^zA}bs}?~vxdc3InL11@S1Z)vY9+n^w^O&O@2RUG4L)0)h3`*ZsxDWT z={DW2eu%HUU8#PeJM?CKj6N2tlKZeWxf|cmds1)F$LX#5J9?WwUY`Iv-rMy_>UDjx zK1H9ZPlLJt)1e`i9Ow{T5B;3q>GNS}co*i4 z3)IK@LVXdwCHEWkeSHZmI=!tg)tBkZ^%eR`e8KiA^)8<3f9b2C<^6r^cl?3APXAC} zuYaU(&^PLv@MM3XZ`QZyAM0E7ZTfb7hrUzarSI1F=zH~j`hNWrb&h^OKd2v4??8U~ zC3wK|`eFT3^^$%>?^dtsN7e83WBPIZgnklpMx*KkPwCJ<(@(48p!xT#Issp|`$RvF zFD&fA&bgQL%lZ{ng)b)l7$r-&aTJ4^*4}P=BP3(Z5yS(Z5sM^~d`6 zsu?SqE$Voz%l@c8RqyG~^q=(S`p@`Y;a^pk-lzYj|E~X`|Eb>B|I%Nm5A~P$l2aER zSu9_S!MCX0CJge}4~*A@rcN>g)dOabNmc)VL^us^W*KIP`ZdtKOp^sUbdDK{6;&?2z&!%^ z!dqsPT8rJgV^oXD!!Fx=NS)*jzZlY@ai-Li;R}T0Vac?@Of=Y#YNnV)aWmcOy*o|Ln z>P>@LXV#kyrqOIPM?v=7Y+6jK*<_A}oVgt~IyXai;8?T89A~zg@0e}ocyod|(QJps zrjyMnz_Cv=JIv{@H+7~t%baa?nsZ>|@;q}szP7asD8@yw`gn=?uDR4)W-d2Zm@8p* z>nd}#xyF1SGX5W!>&y?$_2x(B26Lmi$=qyifraN=&28p(bBDRp+$HY`=3aB3x!?T6 zJYXIK7X7gKDR!OjHjlzu+2iI3^CYa3{S4pDeFl5$pEJ*!7t9{>qIt=@Y+g}Un4gct=5_N1_Ex@Weg!?_x6Iq-9Z1dJgZ9a9pxgZcv}ivvzcs&ue$?+FY5RluqxsZ) zhJ6H|n?IYsn7^8R=5P2i#6O_3_OGzKmd#B~-pwtIh51F(MT;iO^IpWp{+G*+YwhD3I3Xlt-x5$jqv zxAAVoy2fLic_btrS{Q0CO3%&9|} zQ-?CA4rNXq%A7isIdv$T>d>!p&TPBF{IY6$UCMm(^QST$&de8QC*M*h-%=;vQYYV1 zC*M*h-%=;vQYYV1C*M*h-%=;v(rRf*EIHchBhZrcv`f&s#&sPVB#55&D7LQkM@sWr zuf#;dc5H~0hNiDQQo^K-J2pfiz2j|y=AOR$!vhIJjh z6~{|140#>d-V{g`yQXgKQQepEYua$#&=E|U-~@Chj+KyxV1zhccHfR#gNL=j=9{>F zb7NC`W6OGkI7Jx{4C+q8XiW{xt=-u&8iTr{dFw3I0X^G;HL`70;5hJ?j)rVBD+ESm=tL#m!YnxV8RW2U9pKw%eljHzOEDO#Y zEBS>*rDj%*drp08hiTmCZo)aLrEXJedq-Ou%_0Q_3hC| ztq1GE2YFiR8`rw3Th_Z8TGo4}t!-u}FpQ`hER498P%12#xN2OO3GLh>jn3(moE zL0IU7jq47x?T>h6&b>0Z7h}_w<+ZhLZmCb`aTQEkFwSzJfSCKxYI}Zg#}Z+m96XXP#)#2cFwb$^AhJQITnm_=oUKp6gl*YY>yQb+c8s6V#5my zIA%b<(p%@yX>iVs_8jM&^Uw!P4ejmT%{DxuZY??lF%zplTF=X zPk4qoD(&f5d)msAx2}QbsMZk5t)aAHHiuqCtZ%D3#?~|F3#sQ+&oTykmfO>@_H-Oi zc3kBbI&DxW=^{EBo9ZpSpijc1s@68Pt=-(buBl;5)Qk}S%n*M~h<{Ote_4osdAHv) zi&=P<@D#PS`%cvQ5dVe{|Hcr1dx-zo5dU%Aeov##VKYxoeXE@MRt4LssG!6?9|a|O z?HgL#I-HorPR!z9%)+X2Pjelf&lWtkb#kh8^j16P zSYPb!JeAzsl}e!?5Tq%hjOvE&Y^%8edYk}$aAZ6-W)g!1Ic$719l*z zW1Xrxj3l3oBw|^8BWAny#&%ETnl{YWo@#rVWl!_%X$eme#|9(U+3*H?YP6?Td)myC zlbgfJ^2y2~tMTmCt(7S@a#pvus@prG+qACj77%eAAvSe=RQHT#0b55^=UOT5%!g*8Ji^Ctrtu7CU^pxX{VB(8;&Z$+yt* z>Ec2s-$FZ&6&E`B7drVDI{6nm`4>9*7drVDIr$ek`4>6$F0%Z*xX8&LHsM(xhp!hq z^9S}p0=oVYP=0Av|&?c)H(r0y#tDS z2aM|-P})17tam_V?||vO0*ZT=qqui2#l49Zm-nX8JD1|B-Z83!0k$dgohG--vi#zF zr-|({4%bdo=Q~ZE?=*G3({=ey*Ooh7>nu5nOP%}n#V5bG#L3553KW+(`II89L6=1D1nqJ?x7W%In35BK*c3a z{1PXAiBqqVY0)xViiD#c*Ve?L61WKR-D11Q1@*wd57esK8C%^w7FOA`X+xcRYC}g| z*o?a7<~r7+sJz%)y{Wws>r3|v+;Uap_Tmljxo3f^hRv?qw5bjYo8~q3b!P5nGjFpw ztkFBaxl!f^v!KycyP-8~QRDjNI@jX5&E6%Jlxx9;MpqS%1?`PCn@Sd}u%K{USRKo; zM#`~X$`MxI(9}`qZE#AlRZ1Z@J6MWFDaBDNMH5S5=}oONEt}1jMsKSvimPoytEXMc zQ4q$Hs{_T^>=b7cin105F2h=z8`e8@pH>=C*V5X7_n}57q|~-!ku!>lN=stN&t)N) zhsF0%i9Ii+C&D16Z*8~5DlU!*%w`OYWTVp??KCql!mB&#=!uY4w)dSzwHHo9@*;A+ z6xoJL^gs@APNcwfBwN={Ee3Z^I7>H~bqQ57yW#y%YX(^p)_7Y}W<3?$z)^ zwhRBY`U&_&4(oyh_Gj=v4e6^3(%0X^|B3zs{D0Jcg#T0h8T@}TQ2;3*(^M`~5L{}<*L@V^ce*aevyXv!W2xbhP>QeWwL zSGlK6pR-tPktbcH$~aT!Hq~{ssOun|cVVXRt7Oa}el;G`h+tEKhhwh;Z~;H$^-}~} zVTcBbk_r5<67qN(Vt^QA0U4YM`MeEr0XNBpe7_3vdMS$ybpuPufy{pzWcb~oVZc|0 z0tcvuTz`{_s9aHvGT@aLWvHr!d*qDD8Gd#0?8+5>bi)$N=h?-z zv;CqK$+CHX)C>cnFdYbi4eFDAuehKrrS4k+321HSs)PDf57( z*bw=W?O5O|^MSvtUc0G%lbK3)Cf#{-7t>uq*Tz{#e-qs{x?AX;K=)L-XVE>M?j>}u ztZ!*;HrLX$okX{W?ozsI=(f<^N_Pj{U39OadlTJzk7{UZaXm)&X}WvpzDoB^y6@8cknSgR zKd1Y5x}D;>-E<@A#?wuvn3UA-OuRmqx*%pVVGjzhSQCu>!X`W*H3pC-O+Rl>6X!zT?nFe`k!^Z zr2n6C-9RwIfj>qfm;a4^Y5h=M`%U}Zn4jFhsD%?Bsy~dF_t#B*sJZPgK6XK}h5j>c z6u7y3?Rq?BpBl_RD}V!T#9j>9uj5f`qSA)mU6rxw)Xlfr=j4oJ&OG{zJMH<*k?!N1Ov}upT(yPGEF9fx+Es?j}{C?EDe>Q#}xF zJutOjn0lAnmFV)j@?2%EsV+CJ6X7d^-KL%0f7b$puXCLWJBA2#?RIs#)7)9^neI#6 zyWvXuu#I77guRXb`(Yo4eddY8mxA*=6`qZrGd$0Fe(N3Po#Nf< zJ=J@a_ZIKl-oJ+@hv$Unh0hFM6TVYtpuJx1+KY9~IL!7MSaKxX7FgxRj%N4`X3Se_KgUUb+GE7$2CuUgJ zUb6)LwyxXFRyEvgQ$BNnsxY@9>>2o`L|jxuQ{{Bm4hiQ^U=x8ji0h5AygGQ3V2AJSwXjZf!veS*8gaTjA0?r_kx z^rZAYgk&)Nboizt#shMV7R->lXgOP&z3LBL`w$+E^wBt?)bDZk6C8g8jZ<-)hT{qx zC>Qn``1B*FF;;RWj8xu136gOKf!c4)r8b>X{mf-#}jDa>>Z|!=+ zY{O{rVpQxi!*PtmQHEm*j#?aBIXXSaH3Fk&58_>qc%Y1<8kASzyc$Pa*8>yLtOkWzx9TAFlTC%8eTAW9wEUj^yA) zYuI+~F27K)@srSg!WpFf9&p-E`VuJ+R)$=w5iWU3AFe_<8>Aix+lnW1n<_LXpw+e` z%$7p(Y+>E-T%jHCbRuK{I1+jbw509#nFi249oMXpx&f_m6OLPO+=@e<@ZpGG0osMw zk6(y7-i93R#Bmo!b(HkExfRE4pm7JvbSKJrAL#xB$5R*w&!DW&<9LB%&BlyG%)N~9 zBw{^-<9X1E#~xUpxe4XD6~}F$c?Z(p2|sc|>`%;tI3C8a8)1**{3MQNkmvI_zeM`i zBBqp0a(@uVZshYg&QF1UTyT7XBRS>W8&Y1OzmKtn?o()=XK+TzQ1&;lqx)LWx(Qde z;(qoPv`9y2bf+E8 zbT0EGa=?sWUc$%~3xE&5joC6EJh&PE80=$BYIzs_LttU{VMq!d#XnO$r=EvI z;6?m%)XT8-Jrw)1euY{2L;Oc#{`rF%B|9$FXpJ40Di1p@V^uzOP^Mw$bEeKzC9--_ z$*Yllb!rZFy}hjF>DRE+ZN7dRd)XG~cd?Ugp?)9x*J?F(qNzo) z8%!<1>TDRk`cPmB)M427Riu_<=U1s(fz{f0bp-Z$O;tx?uUEBNg|%C)S}ps!R2_D8 zEyupG)dstPv43l$T8AB6O=`XD-NN3qZQwW?v0rPuItshAc3^MWncyL<*r#>2+Jqfi z7hs<}c4MhF?8UlPbzmpf^=dPAVEtGfgFRTcsbjGV>n^ng`>*a(-@y*7pQvrvgY}>~ z9{aC$s}r#Q>Tz`oC#yK?kz-M~=aE;j&-?F$K_ihL8^NFwL5Bvf@xJWOt<%y9LU3-z**R_jJ zkm6k@A@8WJH$aa+a82Cr+S4UEGx*`Y(3EwnTwO1;Mpk zUe+A{_kV{}%Wo;)JR}|$=+bY+7z-4p`~0=)(w+Q&&WH8Ez8>ofyPmk6s}UdGfd1G1 z`dQojudPepf@75^E4~cg35>qL*+z%{vHTFP!tu!}!KSbQeO;TTC!IhnYH))dSC)am zK4&M_V7QZa@Or=bbM<0Zt$kOePV&Hbv>XjV0q*{K|q>?v;KuIkXxLr@+zn9^VS%OQ5G@C!P7w)jf_6c3QsVtD#@X1;< z10}#)heVY=LKtGf_lCqkm`x*htnUe-Epd^C_k1=H&epdSgr-m)PO8$vKGaIyE9E^E6njvzqut5XDVvg3 z2>D6P`_}QR>(b4QoVu{zdY7PQUF?Vni~^}~NL^6A(7K?G{nW+Db$@jUsaL3%`7!`) zfwaAU-E|4M!;uhj-OFp!boZ$A#D0Du{TCV|5I=C1JxWQC%Y-9RBqWw$ki5p>Di`Qg z1oRiTVBgI){0BfrcQJDNE~IpWD5XnNSK*%y&D3kqqSrx6H-u8UY)a{d!9vIFpmHbv z!=eBB6Ey;w&R#VJn$AGRpq2Ns!uNNupC}(C5ERJ`*dLREv#qDdOouwPm3q2a&oI{0!+LsI!*JFxf;Eg_-6GW` z_(!pB(X3mHx*Y#lV0~ADqV!%o>lV+tMFLN_0r917(X3kxkcC?i|5p6tSU1tuz7wgW zKO><*{t#N>r}z(mM)zZIpTs{A8nMs9|2+N!D2?^uyJ;_Bl)a39GQQ3D3S_%K$A2JX zw69_`{R00~^*a7(_-e+R7)K(v9gO`|zlQ%U{L_Hhy@Rp#u6hstz0h>dz&ASH$K4O` z&!B{N2)<7G5&XZ!-;Xbp{tgsA#y=C-;wO*`i~Khm_~IYo{}lfm%7TYFJtPw0p|+nW z7aj^Ndwg*QI`*m1y&tRx0}D*kel=KU=`2`4&DPm!05t7~sZ^b-bJY;w@W6hdZ9fLC z$c}x`wl6{)Xx!uOI6V$@N_8nHh%`A3diUiBuh!LwBa&qw^z3IM1iJRP3vGMQnXBh2 zKV;4GkZQi3uM(hdU#pTRcNSwPi*Z+^&x4^QzZ7&<>Xo2#1SHX^*b8tZsMSFpoeAyu zMx@=SHzH1}ZiU;X+d!usy6P#=QtwcMpr?Ke>UFH%g1g7*<8XJY-U>R)-OT)??QWh2z1vkgL}EY9I2qg4w^sEKS0{+U@~|B zG}o_(d!xQlCF+}?zdiuE>$iZ~kM)m1?N&(J2SJbhHpIVE--)|->AP_EZhbfC-=psX z<@@#hsLM})@#aFW{Xv901nqV|wAvp=jz0y~oTYc`-H87vwA*vBi{dfV^l|+-Vm^T# zmYL9G-vi1b&G$iH{THDBhJFJ%{t6oF1N5(+~eUHvZd5`Fay{Tm>`eoFiY z&>r&|FW|zlHAl5dAx7ujfL0{bTrluYZp?pX<*-`LEDf9{`>8eW3g| z{WsL~@4yTOL4W-pxce{tFWmi7e+jo!cOp&~(B@PzKLP7D+JI9+qus#oGA@-Vn(ZnJ zb~inUBiijlpxusr4A5|ogg*+qLNj6AFHu3C-6SI<1$#qtuoE;5Hfz#Nx=Ml$dj|YN zpvlgCC5Vqd{8_+vhZDmX0gd+IY9w^oN2^iLWFM+C; z)HL6e0XHpxZuonoc{H>)(2s)(3Jv4M`eDkJhy0!{bnYCN>vXQ*+|c%P}Db!cjE zcea_W%0>4b{&{8|;y?o){)J{C{DPNEfG+$ZAf$`UVuUO)OVmW@#VM62 zuP`grWYLm`{|Ivg=pSj0gnyM;rKSL7S*+ro6IJ(K$~e()zGQ$K+8a@9`)S{TzES4>c4}#g4WD{e*N*F zc_MJ!nb5M|u4X~g{v_1yWOFiTLgQZ5h|WFyrvnq74bA&A5MOYeIncU4AAZ4g=8E<` z;#_1dLdeC~%UcEw{L9etmz&GszrtLB*7%v3XVSnGuR0_$hIKglY{{^UJQ>Lzc4QuYk{W)_l6T1Du}Tje+O z3zQ^4u4nzFJUxH5z9>VVJ3Zs=_o`>frS9^E?4Wv*>JTXRd^6f_mixUSWwGy!-MxVF z^lp>x^nuz3Lk_tFL`u8gQ-#oQ_Ge+>4HErt$Fz+lWt7ou$0Vf+!Q55X8Ql_s?$H0H z59R9FqyNp!19=@x3BEE;Pma^4rvrKQbH<46*`xi$=@aB|vp{$-zwT#2WKDu@OH3)f z>}A2Z>rax#84qlIJ~4ge4-)M_zd}-V+J&+nkxA{r(d3nzy2fA|F{{T@SpX||6J+69|0Au9PN8$mp?!IN~9CT%l?dQjy`|29? zN=cq5JC5y7X2HS$Pn7<~UwEQ$K$$P3j+iSkBDhAt9Y|(*d?F!T9U;;}hve5e_2LJ8 zB=Y;GiIj)l2DhU{LsFr(km}0JXy-<>EY<{FZ?XQ8we&MMf}JgKS7gq1j=-}Esdcwh zUSc1_4^Md{D8lYGe=G}XBCRc)N9G{xs$qUMZ|McBZ34M=eZ=0E#NbnSvJSZfq4l?g zu(VhL8-TK~Uu;W>YfHw_7$`|FZBHa17`%T^AIuP(9Vinetf)OO7K}uUMNqJ9AZt66 zf+5mA*b(Z)laYAB*PNYg?Lvzgcs6X9k58YS7n~A=M(*K1xW$5Sje<7&9KJPE=kcx7UwHKQ9SrC3Le*5h3;+u2&pM!hS z4~=sOrSD0kpDR1>^mAiBLEmKFk_9+%UkSl}^0vWt?Q*~<`@M;$F_iCdbRT5?p<_;F z^SBdjS&sDUjep zcU;3hu9^!OeK~e&S3?TF5R&&rYB?nAtJRT^q@Sc3A>BSxoeYWgW$HA@rteqhQ;vK+ zrN%!JYpCi5$cW!kH|cjE1%80?-v=S*{Vik2E6$_yvQGFL8+}BtWjhcKPHMtgl!}@6Mf!CM^cZelWFu%P=0Ft6SC zd$>d1OOz&DJq}y65yWaD)l>LKsh{B=t)5oTAY9O!80@8g4#&zlZ-2qCI|KJ&>0Z=Sd^ZlZF0Eg8bW}G$}d-_67#(fhrnykq0@r z%@E=?e(vxe3_Ho`h!3qsNY?R(-;WV6gd@O%5ik_8c34h^Bz~k8BxjT!r6Q;cFqo*0 zU+gHW7-(DOBU})k1XxstmX{WsCkErD1T+Qb@e|=0q6Oi}B*GI0JId2lJaL``;yh`< zd1fIO(IyxIv}ZO_&B18PBF^K|3t(m01N+Jgk(XdTiNt&c66XnrMdW2F3i_UhA@}8a zIpVC)D^wgTBp;4k1O-YU3gjmWlqwdJQ8qz=TttDwU@Q43&~MUBNZYKNL8k?llOu=@ z#pq3X6Q~^xo5t}(iV}$w`G^!H!=~|O;17Zqd59Oq5HCt3UgQT}^c^)2){VEJC6Cv~ zBVWOeh7ddQ6FbTzc9a!@5m|J|1)Ij_gXRVL0+d9Mq8K7YiA0KgM2eD$6#0o1rNYkf zrJyf(Q6@1W7crtR*f;(m=m=62E_RMVP4J>f;zcpAc6>AHC8$v%Q6nEwqhz8+F0p`& z_<|k95IagFcH{?kbPwuvuf7-cx(_%~8gV2)pZrWd`FHrRkmF$a_*IldaHIs{NQv_K1GKH6NiO|MSV8u{3i6wXFUV31k)=c+ zOK+hh!dX(mS>D6Q*$aFri#U>>I8rLPjKz*zuz37u(D{r03+M=r6hj;-kvNi%I8rik zB$xiD{wHDzniQ_TfKB8GVoEW@loE+4`H3l|l5=H(b9s~>2$C1bPdK<(8o5{|xEM5y zU?DjkIzkDslN@FefhL8+KJoySBKpXPpJbBMKv+snMk+y;Ttt==?GK0m-*SV4$<6>l%yYr7#1f0lA7MnvJw(YxNALpd5)kY^g7|nO@$o3)r?$9x9Qk!T z`E>#@^ayh8MDlANxwDUac>uYvkNnq1&YMKen@rA|Le4vooOcj8Zz?(OU~=9xa^7?z z>6zrS8AQ@E$y>Ym>HFZPf}Z=yRWr#|{Y1~Rh@NKjp68M;ck^FAI9-+oGDzIqrv*1pCvKieZtK^AoBPRClgUqg#LY8xDG>9F z5KihNCru(JO(rMJBv$SxR-Q$yJcB$mk$f|Sd^3|+c^0wq4DwJPd1VrLWiokXI(cO# z5%X;F%0%)?A9F!o!{OwHK61kpa>I0@=lD)LaPv^!=O=ES zMch1_xOon7^I_zP>BP-5iJNB=H%}xt^pP8;kQ)vnHyliEm`-k(>F`0p&9jM{=a45R zk|+Ae4SnQ;1IPz`LgUAO5lMg161Nz7TQ^*0+iJoT?Hy`0}J;BYhh?{2< zH_ss-OebzWq6aq=+&r7OxsO~giCiz4TrY)OFO6I;k(|y)PM1OqJ(H^^Khg6nqURYz z&$Ef14|3L~^~=TaihWyF^Yi6)m5N45y^1meYGi4+$R|E(bY zJCQi=Bx1Oeh}BLeN;@S4lg$mmWG5<h%C6+dFP%7j|B}9Tu`DqVY z-^PpJXbG15f4-DXnZDu)4fcam@?cH=TNMc4X+U{ohl5y9>F0<2>)650@gP!Td4`>m z3$6j&f!Ky5gjBskV$+Yk5=aAt(8d-Sk0Xnhy&=Igh++5SODc{{q!YwRC{eO46qu9j z<`0oP~RQg%O~0w^6&YRv^#qS{YS5+_drAh9TA-lDS1$PrceGBM?qZYX_Z>^ z%a{73{H6kWw_1>{gZc)q55^PVu})l|bwDY5%f~I}50PE>iE%Jl{TJdmGgUCB-q*n! z->`2BKV5zlE}d5$N69>b?1RJ zVlhl%2Hc0yFFH&dA)L*w#|V{gwCFd+ku&EV7+I7xUf&-|4O+oH zZ+#;iFk}o;5>rE&q}64|!zZ!=ur*;?tRSScvXTh4jg(nd62hVWyU6lH&H%BLrUBlMGWzd=ZAcavDIBJLZ3(QHRPLi$;~ zq1}ZWS?qbg)B`vA+XE-}dd(?;=!bMB-wMpJLNjF7nB^viM6SQceS5{utacY;e<{8y zj58$0aLAq_CyBj7Y~Q)t&09jLO1uN@yD`vu6S=;EeEL&mD0_~i)H#~kTCud>l}P(t z1MuxraA(Mmi=hW2^5bOrZYfZe#n6-*MEUMu$X|B=!Lgc2mut~65`Cbd&;)t}Qtd~f z_cMyRKBH-^YYg>x@*so!P>rROv549^#gq<~K&vJUay8MRDW~?#cuM;wP^wn}otQ#s znUunQ*F1c;u|m~CVmAdk3i!4nbSCgcMd&Dq=En+rIq^K`MqFwxh2Dc$%~}KOV-aia zrDR@HGH)oEcTqC$rer>hl6f~J^B%SizbXq$m15(}%hm~J>qM}1BH21oY#l?%xu)dY zP)@EXCpT;<7bVr2l4=(v)ox0vJ#0G{wX|H6HoMt^(bT2VlnJ{i6LzyTquH7+wq^`l zGlmjfO^L3dMAt=$u7~X#&GvP%eWR(h#P4y!j-#}4G+WulR`#%!UDP~^HQBJC7H4uy z4lEQ7HAA7JB=*!2@qNu)XfugMl8-Xgcr((BgdWoMIRI&y|7#zPyQWvBH+fUQCkjZzBE_^kowDdIsWKnMcFF#cY9l9QrkZ{hEw^Jqx*u zwY4O%h>P%Z%sI&STyrkM&qJ>#vDcH>>(G0}*gY7;OWyng8nN3q_1_@oWxlQxV`+E6}exqQ-whhSjCLol%6+@UapNSL3y5{6KlG=sYmGO10P zPE>3JQL$vAVrfLhvWSXh5*5oNDwaZ2ESacS7IztB@aawGUIUAeWpS@TGO@7~Vq;m< zCe0v1mdWQlo6mVV5i%dKu`E9G*?i{HiH#)_6-yy1mPS-8i#rIcHfavAF(0w9WMX5< zJ@7Eu7chcISTZrNG-6;`+zVj!NHd6sWpXb-7WV>VlFMY1%jA&D3?-MzB_5VWJS>YG zCx>{Lk9b&eA0#Y|NLUv41z0`OEOMwEa;Txi!+gZUl8J{U6Aw!w9+un(1M?9BOD6i2 zM)WI-n12R2-AH0!S>$)w^2b~vUTH+UvdAk(67k9+$IKz($XF;$8*Bz4FL^ z$5B(Xl$xSt)D*2C9#&3G(Mi-49ZyZs3Dgv=AWk-snxYld6rDs((F$scPBNk?I+-Zi z6l#i2GNLJ3NlnoTYKl&!rf3B*wkm3hR!~!P0yRY|s3|&)nxfUz6rD~@(Nb!PPNJsh zcxs1M5TC2!{E<(TZU#}hnMCQv5~V93N;ivhNj|Z<8fu45qIT$PYKP7tdN+~Up%v5) zolEV|3hISUBAz#odZCl37doGMp%v5%okYFR3gUc))C;X3+Bb!Ip$n)Nx`2A23#k`s zHA45V3o2Tm%c=Rfl$xK*sQGyq^*onT!*c~SJeO0qb2;@n52rroVIkPz@DS|K>T@oq zKIc;Eb1tJk=W^--1sZWJP26B!9oh}MS47a&cr?=anOP>x*T5b8-823O}o1?h(%N7z1bR_RaBlBw#t zl5efDmz}Z#zC&HfcO{XRiChCezQY1LaMIq6AggT>kkuSe-XV1f)E+eC%IZvzwsnxB z4R>-3+_LQ^_r8%|&o?8%*+i40_s@Bs?-lH%WoxqD-M!N*=0RRco7kF3t8`P7(SUjf zTU#&^Tm@SuB&PEg9S9*sN!dq3>mZASXaQQ1BG7C5NgdE6rflUa;_in;XmGHX`JNe4 z4(Xx3y%dr(kdkRc4kdlHKWVbuKOi-vwS8@4iR~egk2!Cz2dJl{s<2Onle?gM^5k1e zp(UDb^9ZSBNPYJ2{cq}9?7tLp=TJ+2U}|6Q?je`Kd4|y|-I5^m&3;<7e>v@bi;Cxt ze0;wVLT(@~Ik6p0mdhRJc{{+U3!w_H)DUuDJP{%dw$DvJvd@r2!Mg{Qhou^lytg;- zEZW)}au0!=Lm``#L!X)6S$)NIkYfrB;Z=5Lg>e0^s0CA^_1H(*czWgewNG;2Jms!^ zzWd($CPM6(wX!#xj}7^^Xb0M+ySGqV?jP7M*^oU%f!QiFb^ zIkPDbEq#zsKb~)nQZM3Pqu2J|zP)Joy8P;=?yF;jk_>I{9^oOf>(FrVf8Db8rgNa{ z&|37@Z+*i;Qyhr$f$sH3qi1aeAruPz#YCu;qW4^MH31DtGK)aIeF3_jWBc9{o zwD}73p6f>L{bA{0w*dJIs_*=4FM_(vJrDHPr#)*CSn&kXAI!NIg@Z}*4aW(zU4X+0 z`GYSN+QwOZ@2^<>_i1SCo_w@dJ0H|c!FeaJg8esUK$a@-Zq|G6N^o3+mi=q_TMiwK~6M`^j+#dv$gNn-Y|)gk#ZbZ)O9@*X zC2Y}@u*Flt77hv9VTixnEJrS4i!A{Xw!;y!5*FDKAZI%gbi@{0BqeN#l&}q;R4oej z*VZ9i?5{;p!sg@maKg<|<|u^AS8>AGcF~l!B~jXz3~AeDw6EA=OJQqO4}kSZHqHk8hk&7GPiVmjpr(SZAmP$rBmjX&Ynw0&+R-YWT;ygN)REzghcZx zjM$Hd*pHXkPdKrk2x32x#D1cP{X`S{i6QnAP3$Lz*iS669}lq~FR`C+Vm}eYej?fMoPYki2SYkgGr3~0d73-UEA=pVACB^ZS6emzpoJdLW07{B|loTgX zQk=wboXl~Y!f`y1<9HAy#i<<4$&?fiprm*(CBM9A{EeoJ&b@Cdct`N{TZnDfUxR zoXK%Kg5!83$MGmiiqj}5&gPgNf-&6y4Ucsg*<(1SGcl%{;1|n+!}0yj7Wl=oU=qi4 z9>?@pN|1dV)5#pu`II0haby>8WM@-?T*&cVLhCCHf^<;9dBXL5X(aC~QTe2?S! z&gS?or5rhvBRiWTJCh?jg(EwYBYP-E_85-rGLGpoN|Vbuvdd^+u$-DDOlKIg6aM(56Tp%x21y>6(p>oVRnth)i7nNz1C?5lYOvNf_222#^%8pA8WnfDl{0k zFJVa$D4C_it3W^WOb}c(1%d-9o!&!murz@vJO@H;kMjyS^xWwb7;oJPgXI^x0cn5t z?H;~B4mOZikm2-s9(o}n9QOgrTpindBxifrGVpoelVQUh7tcetg(Af1Wt&LK5_qzJ za6qDmIHJ`c`^fNZMy?C7LPRXFWwZ}rcmv=e&j!AhDLbZ_xAW}ao;;a75RA~4k-J~x z*Yhdri%iH^3P=|ZaxB?WuxxnZLVFTdePlgB>IYHyetP<=Eb#Q8DlOe3;LtAmaJxfF zeo${}6!KpLhpRq5Y)nJ2tE=_#i0uh~kuVKe@;(LH>l%K0WZ?Z`>Y) zZ7j#_pYyf!NWhEGC#>(?{f9Wbg!Uo#AM4-ghy73u8D#;E@U`j?LMJq*0L?(y*P?9` z_s*gBbs!6#L-YOm93zxukT1!IvxuT_zrYb1wXfePD@T*{3l*6oyRRfww}mhnt%Bu! zb8C=*e8njpW{pF@ft*Cav^}ro>foNLzUe|jLVGln1BLn}dUw3xY@a@BjS!muZEttk z4l3tBtD!Gst`V--moxUH6q-Zm3=`__nF3dVeEQt@8UYTk3ao{M!UFcgf&*x6^~@)< z4)6!Lg2mE$#&xc~$r|*V0Rnq)jelq67g`6EzDJI|S7f2Bgl8Z~kF@)c(fQr-x^Sn~JsO*_ooVs1f*eBC*mR{gzv_m1GZH@@Qz ztNu}Z_m1YfcZ|8)+@oS?+dqz9fQ~ovHa>_J{u8**E0JG=9$+3a4?$k|uz47g2(kH} z%$;8;wD~`fHvg0P4nK%rj85f_u)%zvPvgF@!Ppn}Gf2FihW&qhuN?OOhwu&G&z)j} z`JSK2uK;9m*H|`pjivC-KL@SzCR*cH=GUm*Tjnja!`tR$~8F*ks+oCJv7>=hrj;Ab+r?LByB&Bflr!7#nF?;(UZ^7 zGm4`ppQC3Kq_MJZUsf>&mQdV~&nie}?}7cOhhW1gAN$JVRgF&6KDAV*z^dJHXmI4H z!)cRl73|Ozsnyu)JwvU-KJHrBBU}oLZ_U`3eVppR{^*NomGCaL6MKz+t-gmH!JXSs@(0n7BMP4iiw^U+|LOiqSVmZ4SWei$u#sUo zD1p{fbQK~S*yIW=%M-AAXv^ZF6)iXIWQEZlp@%vGUTOq{bI*SSckf3c|LY*N4wk~b zRjH6;s&|s-DepAz0&k6XrFW@!gLjR$!`tF{!@JeH-81D?A*yWu|Nxxw>_=XuW?p7T9tdEWMX?0Fyl8$6$RzVPhxh9iy78|(FZQ$1HQ z#;M*i{O?70At(>?+=|$jc&_!_fLa+nUQbX;Pt=p-3JvuT>Y`xT>r?E-Pr{e1il|*s zg0WMMcGY^d{wZs<6<^6xu9eR5;eY5X^eyc+_wDX?-EX?DbMJJ2;{MS6x%(lUA9HuQ z{~qRc-y0SwM_9ajYuI%6V`0f*Y3`@pH@Wt?Uv(SzcGt&Y!`(jkJMe!M|5Uf%b+>z% z>nV4kd$hX@=V|Uq?gj1|_fprDt}ESpTxYp2bzd5m<=*Pv1}xW);0S3u&(!{hV@PTtbPtQ`99HqK&nsmXTX@EO$_vc2AV;bM+ck1z@#oQ--Wfj zSIw)iohi0WA41P6_G~eANXD^$OWD6=L{Fws|EZdqPt&38G)m1NZZeBlNey^=so(2v!VJYC7Cl>(2D!wq)xPwmmd1B`xJKZAR2 z+9*}DA*!Ln^B%(F8*eVe35S0J4hJCp7%y7$n%lkOSfLKh6K zZimf8t!L4{L|m?tweG^oRht~T7mBMsrhlNg`nPniq5HPD>eu3$MEVt0M_RoAL{Tf| zrEekqt#o6V%Z2o7x;HXpH*^uT9>EZN*9-oMbVu^8Ev<_oxpW88Ev1_#u6mLF2>SQY z@1vW^kSpjH9X+j|r#qhRRB_dZbbm+p7M8^37|l4)?L(X|=>CK5_voH4u0D(YcTE@K zTqJeZBk8_o{s{ja^cS;D9-)6W{XgK{YK9cjokjOt-o2XsIdmtBi~f>UJ&&o*VE8Dy z7tqb8yNT}Y;;Jj?Kc4Pzx_NYeMRz>it#lP>9w~mz+LHEDx)1X1M!H^C80vBh`*%fG zD&lZd=mduRgYN6%>JfCO(zT;y6#e7rme3tW3OCSSM0YIR=fzcz)BhUde8`aV7&4On zzte9+q8V~2V}8N#A#~5ByNvEay0hq>LARLhOu83|tFEAXHA6PhUC)q*=)awA9o=)f z?m_&^=ntoR1l^5ve?@l=-Ez8H#RU_HG{?j|pxo1@&snUlUwd3zlS*CR)^L=1wyCb8 z1z(LUR<5ZtYW*sC?(AuPwO~>0RKJ4!v8#*glhNQD32GTE*)^-<)j8^W_y*|1yc-2> zFh)(p%IQeNKS7-fO#N2qIogyitgI%f0qQWkL$sxUxE?2A7 zCbeCiudV@}zFXEnj1dDqmX8?#TBoW`9j#6Ru0IC|{T;CJ9EcMQi_Z$&uo8TAjcQXT zV|95gkod=d@JCdxsP?PzRh5hVYDHBo+-)-|XZY1avnyA?3iI6gbNs5acK%$y&RC2% zddlM3*?zs+$=i#aWm&*ZQ`B13u1--Gs=4Y1K=&W#{aEngB78-y3f7)i0FCTWr^3?e zJg%Xha41BeRddudta}^OW_23AzdB$25NqEjo%@lh1YbO@#yq!99iw(&ufhU+dG%h{ zsh0MM#j0)`(Aw!(w;Zn4L5@4YU& zcmOL|OCb*P%t!^x&FU!i9d$Oo6}tpqfqf7*v+ezOH353Ju<5Lt)HdwcxKb^}{)mU5 z(fY#Lx~2~IOKbmMcjp0CHMTYElbiw^s(^@qNL56H96Bh7G(oX9z(F{Q;#@^k z^i#)C$AVY}X?A5)96>}yY^c}(kwI*X1rh8zqvE&rN)8?!oqO;1&&>1u7oPJb+1c6I zS=m{8?Uj`zG$~SW3waOOjC_WCgKQ%d3Xo!?7E%vsgfv51A#IV4NcZsYxCEgWG6X3@ zE=O)d9z)h6Ul5AakQT^3$dSlc?WEHXwc?bCb`2_h2`HoPDMv9SI z5%JPEB|W4O(hO;Zv_(21-H~2Me`FAHI5HSH0U3duf=q}?3=LPBflNa#M`j}Pk^7LP z$O>c)@(!{E`5U3K2&s)UMq0xGg(^EEJ(0f1Amngl2yzlK3K@%(AyZyWpQ_mIuVXUI3mHfdr+yovxRMrtAT zkVZ%|q!rQ@>4YSO^h4&*lUPD;&>elSf9@JF?B`2+QG>ouA9}AZt^3+G|E=jX zd=a7po^8TETB5$1PrgP2%lWG)fOe_`)`<%2<^RX|Ka%aI>*VtM{TY$3(MCz@Aj$m; z9H#>LI8Vm6#6S7hl6X8R^n3m_B$hCR_V8arH7x(HqdJ!V*HIPA|LaIxwG=vR|9rZ^ zxZ)caSuBIG#YPxg>;eyM33zwUgYT#w{GQFc7rb|rfKsD$;Vml`lnuN!r4Qu`Z$1g8 zCQ*~&UHuEFr znO1$GMzeEjqtzy}dDP0dX$wvT>LPUmbsKe0ZfUam9Q9S|a9aO;^pqn8w#i(ORyR%WmI+_%2}k4o}z`YZKoeEO&Nimpl7% z)1hqs&f~cCncOssOFzgi8-S0SY;Q1}n{xRL!nozh+%%q>o`LeMVZ5FTW6^vVO>Tn` z;SLzn?Se7=9vGb$!1#I}jB^jbNR@_dR>7#3^mxk9D!^9<|HR)2(tz(ujKlYh5wE;I z+@s;)d&h{^Q4A^L;7w%2tJxpkMMi_=Bu3k%2kg5i58m+)o&k6V3akO2A=ou!4g2k;%|oQz?t%fwjTj){T95x#Tp{jC&Ask zH1H?4@vZm){6zj7{%U>}|Czu@;4g?0tPpGz?1N*|hP|6X-Rxn!>kZ@G;n0qUfR#4_ zrzSA!CCjGZ10hp07?G2yIe0|K)B=12WNHcHbTaJ*=Sa+zITBM$zz0Isn1P>!-D2|Z za*oCnQ}BndIVW;CBXDX7R0b=A_#4>uleqQpt)tKOISy0I!E3_qD-x%cFve$dlAa=r zTSu-74e&saHI^{S|Cl3|oBx`0dT`RQ=A_e;la381onD-DY&q%JanfOaCmm}}IyRhi zY{8#F>Y5wl+eA;##Iq5ia z(sAXaqnMMGjuR&xXHGhnGB2 z>TSrJDm@&UEnAEeGAa7Cd&F z!Q+_^`grF1 z4}Sje>kq#G_>o%vd-)(j2mWa&u^-SI{%I)H2j~m`G?eTIByol`lul$40RQk*-hZ?Y z8u|rtzl+?tf^TL)?T8&fqLE17*8|Gqb9cnZeJn9(?^y7jl72&eugezv%wAAOZ>XCu z)X5*}5&)%rDUI!u*#74KWjhI+PY3V;JAoh91w65Ca138c`+R?2%JZePKVv)6pFZO~ z2T9S;W{6d01V3`05%eB>JCF}=8Ek;>3DOWZK>Gfl;b(z4SbeKUnP8sV@U=mjcbhT- zk~}0Q4gH`NJn0n%Pk2R;rxoE@#mRIGJkd23o=%K|r@5r?93TzP3Hs1}(7E@g2k`j# z1f>!_ZKjORmZ`u~Wg&3?f;|PLUJ%&Ek9hI$y-HQyGKeAR#LI`fQKr1T z5I3@hR|s(<8z7S8GJTnMlCGtj!AlRL(e`KrXz_RlTm|odtKuDSb-V+vNs&9?9q4$bh#YDLFNFL`oq%V92bSNT z8#e0#*S2U+qv1HNV|{NxE!T))$B&N!!{g`Z_98ybC9*r#wjuF~q80?d@CF1p9^`-$=D?5cP zDEb<#C$$ZNQb$93BFDmTX|AxujxR_G+cyxKU7m*qtxWdM`dG+zAW=Bpn~(=;0o#zW zwNST^HJdTuMxI7N??=vJFyxV^(O{>CK&l>Sbb0E3 zcJAco`;ThKwx&L~S9`1-IZjezb}VcU^L)^baIEm|(1~yk=F)Q^+JG_GxZ;Y2<1kF=?0D zOQS)9WkJbCT+LjdG(Pm{R^aV`?<^{$QegE^&`YuB*agb@JM^wDDWd3Tq#$0YT1l7gQt_pyO?b;7Re4{kr<3cvd35?2Z%-T;yL0o z`|c2xIE~jEBaA#yyLh5r=?llF%3in7m%w!heaTWdN1Lck5LuN)!T2Bgl9Lc$RY6to zL~x~priC`s3Ng-Vv>NoL`f%RGAWKfdU>mZMb5)cu^bsFZSqXpBp7M7{7}^O$HIdeG z2ABc%ni1#?ces`Z!&M#z*Z&M&DzpV+iKtN!bwqj5V*h=oNw8(*{FSPPXBHS&IjH|&;yg-{9KjjW??ftRisB3j>o zpH2Y23@z}~k@w14fv?UH-p=g>-nt;LlY+q}iU6A`0sI`_fTv?IylZ`@X{6?52Tr6BJTrJELW(o6!yM+6MhlHiVa$$w=lCVZtFT5jc5R z=!R<>vHT`v3DJrmH^Opc1@aQ|3bG1WgRDa~ARCcQ$Yx{IL!L&SMP5KwA}=B@A*+!k(6bN;5SAlJUqj9>VJ+slj;ur8M&3o< zM?OG4L^dH?ku_LC9kK!0h-^ZZKwn1oOIVI1V-2!j!YjxsWC`?lBqw1RvK(1~yo9X5 zoOQ?sWFxW(N%~Ei*Mh9U{B_8BWCOAh*@Qd>eJj)oS&A$}RwL_>wa9v8E3yRoVyHh_ zVla=bxCYajFb(EO8r_}LgPw-8#FU;~I<#-vnzT;ZAJ@)7`r_IFNPk=#h_ohkr5%xh z$Pqva#$xRwLfmExG6$K5+=(ne9^leRoeFS&f6f^3&mVz{p@!8sx`BQidv6UmTJT@c zc~Eb#E@(2Ulc$kmA!%fci{sI_l%I9+0=knU; zcDBzIw9i5L|M7U0y>|moN>Gz15{v%ju?xtR>P>k<4cXBFd!*h(df1b|NQ3J4$&yd| zk`dUi;Z!uW4DLH_p-xffsK?Y3TAl6;d;2piTedD|aeol$h*m4qi?v=m8^Dx|L*cKp zHj~y_L!@Gz9+3W8ol>H+()2$tY5H$zijt@@Dk5P|4L)rEQKq3HaZeH4NKJF0DM8i< zW*B3mkYbc=oN5H8jQkG)(=-W!S!2QVD}$dW`DaWO3KQri6%Kx8@}x&?txK$4%Dwt+ z)$b!)v(j`HFloZkOq#$mi+t^c=G)}&XVlwkM+u=G^Dbh&_@e|O9eUIVi58xD9+_k^Tq>2B_CK9yKZS{zR)?P zyZVVa3lCcUa_aRW@tWgZ_b&ZDYDoC44LMP*fkB}>r^GNvfl=~miFIIs^(>2Zo{?A7 z=Xc38J?cx(yUjo6_qNjLur1@}l=A=>n zAQ5jy4TRf82cGZ{z~_gsd3VtyO9DPEI>zXcwU%UAjS-8K;i41@mH5g`7m}_a&=ctX zbX3PaZFWN5vMKlH@shnAp4YT#GF{1PbAdjim#TZ<)La9f^Bbm*w<{m`Y-xtp!>7Zv z7sbB#k9o|N!~tAKGMg?AO$L-V!GvdOYex01J}#Mm$7Pl`%P zgzLdJJTaCTK{hoJ1Th1c0FmmX^Z+XTeLSV4Pcv?ei@XXnrPq^`n8aO?|Du5^wl&Zh z(AFs4((R>1R;JdkRSz4rjq8x$nYW~^V&JZKC!X~`Z1Q;Nt}E-a?_Sfd-8CqyAXhfm zZb5d9+I8OStq(KaMTZ0{T{4_?`Ss=J)5k9Fyjg$YP{*5_lI+Y+pEAGPt&1KrXRKdq z=X!rNhjoqWUCyiS&zgv5k@s%1>E#el-pA2~VFq`%a}H#8z* zmP!9a>GT9nSxOi?IC-Eft=d=n#D*p%nb<36x)^D^f+7H2$2dzQperR#jt(xM>+BU5 znRykT*5cpP?gorLsfk#pLw_mOlPG7dmS5Cx?J7N58bOZhGi5G;c1#N7>vV5Fv=Ncv z(-R}Vc4U$cj3(JasH4odxH-GoySl)&{Ks0ayjOL{WgEK%HQPHqns{g|6_Ou1Z*1>` z@SS(-Jx*I6I_q$CR-^mlK8*Q-<@*`kgZmbp@K`fau=(ct8>*JZrVWuj<~VKJKJwA4 z*Y<8z-A1k1-TJmIIQ`n@7rbwmS*soK7F2HSD|pqC`fNw*@GUV>b)^Qo$Jg0JH5p7j z{ENY`0X(~a(;3rii+Y@Cc@q^U-njqyyP4l)zsY%4c;b0c%F5$g?^)Vz-1b;IGJeV{ zZQl_I%$gG$dj|LPP?imNRywTU=%PzO-GiqVI-T6Kx0B?J>US->=Q#`iM>*r7`(DdM z#{!$SzK?$Gw|w1sUAH^V3k&BMxV+bUHLXLYjL~b;S)J2&f%*`+*0Tpm*(&I-_q#&v zzmN5+xzn<6VrKFE8S5vXzyFE;x>8NJIB!1$Abx(fO-9!&2nw=9=*C%H2F*nKD2Dr})> z1w==*Yqo);920>rN+Ues_`(vLMC`E|>| z=$0teY>~TQ=<<$uaB^9-XJd2>UFwH=TX^*(v9LI2mkxynM6iwvgw$a{ZrgZVW$Xw<5Pk59)fNO^=%{RQHl0 zEt9XBes^qt<4cvtSG0DFI8gfJ{8-hR-fNB4SOngzY<|BrV5P2~hP$)0&Tqe8cE7V# z*L(+i7RhE*XX}izIkhOKaQ!aPf<<$ui{2g84bnItUw+f$C+%r39y}f9Wo8w4tINPe z+Z@k}vTtaITuyh6;5$jB$?=b#EgYILVJCmY?v>`@UG+9zDB33scfb8&vSBBo)0z=2 zpy9xxpdYXr4$l5(mgC>1;2aredpC&-kQj3gii>}bmQABf6c3&?x73NbrHtlQ!=`IZ zWAp>J{NvHJi2>M>eBTv=N8?EIy^bLo+0 zBeiPx&8s>#-DBX~)5#}1XYMrM7n)49o6_^glZ)q+A2u#HUhCIgy2B;-^`dUqYJ0uf z-sz{ViOz%bJN1psSoO1Y{P^s)#kW)&=Kk_+$J>w2xmVxO&erKwyL|6NZI3Kvq4L3T zd6BLHzxBpBlP1Yd_RC8QGYmV~RXWkYyObUlxowZR{*-q!`P&E0O+E43&X9LoymBi# z>$UAW(>ftZy(Rfb=Brs5B|j=fXLnS;krjN(cedCw%xYqBKcx}D7dy;xm7RR^p)h8} zcMD`q>kRkO6hCL)F=pNo1*P*voiguRat)gc<}GCArKReADbJSZ+{nM>tfoPWW-UX3 zkl}-ZQ#{3TE60A|^L-VbE8l6K+M={${ogjqA~}r{#-_{QnWI*EUcs;`W5~ebzdt5Axk!=6K`C(EQ%A^q1?_ zo9|9O^qXJ4%JB_pTJ!xfVuo7Ma~7Bty0w@+aS!a6-|5>zxyiE#BsCu`M%HA(E1JjX z5Orhu$-s{PY1glm3PuguCon=|tg^agS)`lE?GqSmDVinG5lK$HB+g$QX2nrToxV8C z`rPlKSg3->gPE5qw`Rb;k}-*lg?t(8EB&w7S9Z*R_FQzjr@Zd}mTfgLCSDeq7#A54 z1O6B|F4-q$;TP@3kHcb*wZnX_8%xD1YO80wtlQe@XjNv9&ol$tQN@M%9ZhYMTdkX( zuJaITZ(TU|?xfs8X^e>pKQi}x{<5PHJAR#XImP>8WSLRVsVi6bl)PSdIfZ^O=W=sy z-M~Q$kIf&l(Nk<1%uE@5Cu+%=DL3*=w+LP)HW$?DMy@IOK|gue*xTE0pET8uIW^;L z6_`Q^1*fv64oR--`)$&Tlm~B$_Ul$eYrAP&Jrc2focry;DJpfA|Ja^?;X$6x+jy_4 zjSpQaHLdTQX}OnKbg85{?tWx_vf(kav-_`WFn6Szl>*v&AJTm5^wVF<0CS<>x2!bi_$*1U8^OTm??CLvxIU6Bgs?zEyLDgp_(Xnq}dK5@)Xrlr*+c-BGUL_OiVB zs>)|LCuu z43fA;x9xULs)`{0=5N$DBih8n1_$ivmNQfkQ;?er?0#$?%!#P^Nu~4TVnksQGNQR-1_IzgF{cP2^+FVfBy3z zv-d9` zI;7+Gt>$KvUEe1!jk8HD-#hM@gLtm`-6a*)r-w&LAC5Ln>NR6(r`YWN0hg~2I$K*} zek8DO(v+@&AG%N3Fg|jbX7NhT*uGf_>Wezs*H_nVSe@j0|7@~Q)9ukB3!hfE9b*iG XzZqy(^HL+~lq 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
h2k1850m|A%8WnpQv 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%0AWz5oJ&#Mix^=DPpan4sJ#l|$p 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 literal 0 HcmV?d00001 diff --git a/frontend/public/fonts/AmazonEmber_He.ttf b/frontend/public/fonts/AmazonEmber_He.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b44ad9f1d141a8490b5816efd8f4389cf480d1d2 GIT binary patch literal 100120 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 literal 0 HcmV?d00001 diff --git a/frontend/public/fonts/AmazonEmber_Lt.ttf b/frontend/public/fonts/AmazonEmber_Lt.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a32aee2a85f262080d3bf2b22db0cc540f29fcbe GIT binary patch literal 103336 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

^f+-)ZdS8I*mev43Z< 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 wzK3)OHB4sIFp*KiBt{J_j2b30YM8>Pp_Ng? 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 aB5d2ThJ!DM?0Y)yk$F<@#`k7$-2Ve|&CT=x literal 0 HcmV?d00001 diff --git a/frontend/src/app/admin/clients/page.tsx b/frontend/src/app/admin/clients/page.tsx new file mode 100644 index 0000000..5404632 --- /dev/null +++ b/frontend/src/app/admin/clients/page.tsx @@ -0,0 +1,178 @@ +"use client"; + +import React, { useState } from "react"; +import { AppShell } from "@/components/layout/AppShell"; +import { ClientForm } from "@/components/admin/ClientForm"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Plus, Building2, Pencil } from "lucide-react"; +import type { Client } from "@/lib/types"; + +const mockClients: Client[] = [ + { + id: "client-001", + name: "OMG", + code: "OMG", + voice_profile: { + tone: "Professional, authoritative, yet approachable", + style: "Concise marketing copy with strong CTAs", + guidelines: "Always lead with benefit statements. Use active voice. Avoid superlatives unless data-backed.", + examples: ["Shop the deals you love", "Your everyday essentials, delivered fast"], + }, + created_at: "2026-01-10T00:00:00Z", + is_active: true, + }, + { + id: "client-002", + name: "Mindshare", + code: "MND", + voice_profile: { + tone: "Bold, energetic, youthful", + style: "Short punchy copy, emoji-friendly for social", + guidelines: "Maximum impact in minimum words. Sport and entertainment focus. Use colloquial language where appropriate.", + }, + created_at: "2026-01-20T00:00:00Z", + is_active: true, + }, + { + id: "client-003", + name: "PHD", + code: "PHD", + voice_profile: { + tone: "Warm, friendly, trustworthy", + style: "Informative yet engaging", + guidelines: "Focus on value proposition. Use second person (you/your). Emphasize convenience and reliability.", + }, + created_at: "2026-02-05T00:00:00Z", + is_active: true, + }, + { + id: "client-004", + name: "EssenceMediacom", + code: "EMC", + voice_profile: { + tone: "Premium, aspirational", + style: "Sophisticated marketing language", + guidelines: "Luxury and exclusivity messaging. Avoid discount language. Focus on experience and quality.", + }, + created_at: "2026-02-15T00:00:00Z", + is_active: false, + }, +]; + +export default function ClientsPage() { + const [clients] = useState(mockClients); + const [dialogOpen, setDialogOpen] = useState(false); + const [editClient, setEditClient] = useState(null); + + const handleEdit = (client: Client) => { + setEditClient(client); + setDialogOpen(true); + }; + + const handleAdd = () => { + setEditClient(null); + setDialogOpen(true); + }; + + return ( + +
+
+

+ Manage client configurations and voice profiles +

+ +
+ +
+ {clients.map((client) => ( + + +
+
+
+ {client.code} +
+
+ {client.name} + + {client.is_active ? "Active" : "Inactive"} + +
+
+ +
+
+ + {client.voice_profile && ( +
+
+ + Tone + +

+ {client.voice_profile.tone} +

+
+
+ + Style + +

+ {client.voice_profile.style} +

+
+
+ + Guidelines + +

+ {client.voice_profile.guidelines} +

+
+
+ )} +
+
+ ))} +
+ + + + + + {editClient ? `Edit ${editClient.name}` : "Add New Client"} + + + setDialogOpen(false)} + onCancel={() => setDialogOpen(false)} + /> + + +
+
+ ); +} diff --git a/frontend/src/app/admin/files/reference/page.tsx b/frontend/src/app/admin/files/reference/page.tsx new file mode 100644 index 0000000..ff276b5 --- /dev/null +++ b/frontend/src/app/admin/files/reference/page.tsx @@ -0,0 +1,139 @@ +"use client"; + +import React, { useState } from "react"; +import { AppShell } from "@/components/layout/AppShell"; +import { FileUploader } from "@/components/admin/FileUploader"; +import { Card } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { formatDate } from "@/lib/utils"; +import { Upload, Trash2, FileText, Download } from "lucide-react"; +import type { ReferenceFile } from "@/lib/types"; + +const mockRefFiles: ReferenceFile[] = [ + { id: "ref-001", name: "Brand_Guidelines_v3.pdf", file_type: "PDF", locale_code: undefined, client_id: undefined, file_path: "/files/ref/Brand_Guidelines_v3.pdf", uploaded_by: "Sarah Chen", uploaded_at: "2026-02-10T10:00:00Z" }, + { id: "ref-002", name: "Glossary_Master.xlsx", file_type: "XLSX", locale_code: undefined, client_id: undefined, file_path: "/files/ref/Glossary_Master.xlsx", uploaded_by: "Sarah Chen", uploaded_at: "2026-02-15T14:30:00Z" }, + { id: "ref-003", name: "StyleGuide_de-DE.pdf", file_type: "PDF", locale_code: "de-DE", client_id: undefined, file_path: "/files/ref/StyleGuide_de-DE.pdf", uploaded_by: "Emily Brown", uploaded_at: "2026-03-01T09:00:00Z" }, + { id: "ref-004", name: "StyleGuide_fr-FR.pdf", file_type: "PDF", locale_code: "fr-FR", client_id: undefined, file_path: "/files/ref/StyleGuide_fr-FR.pdf", uploaded_by: "Emily Brown", uploaded_at: "2026-03-01T09:05:00Z" }, + { id: "ref-005", name: "OMG_Voice_Profile.docx", file_type: "DOCX", locale_code: undefined, client_id: "client-001", file_path: "/files/ref/OMG_Voice_Profile.docx", uploaded_by: "James Miller", uploaded_at: "2026-03-10T11:00:00Z" }, + { id: "ref-006", name: "Prime_Terminology.xlsx", file_type: "XLSX", locale_code: undefined, client_id: undefined, file_path: "/files/ref/Prime_Terminology.xlsx", uploaded_by: "Sarah Chen", uploaded_at: "2026-03-20T15:45:00Z" }, +]; + +export default function ReferenceLibraryPage() { + const [files] = useState(mockRefFiles); + const [uploadOpen, setUploadOpen] = useState(false); + + return ( + +
+
+

+ Reference files, style guides, and glossaries +

+ +
+ + + + + + File Name + Type + Locale + Client + Uploaded By + Date + + + + + {files.map((file) => ( + + +
+ + + {file.name} + +
+
+ + {file.file_type} + + + {file.locale_code ? ( + {file.locale_code} + ) : ( + Global + )} + + + {file.client_id ? ( + OMG + ) : ( + All + )} + + + {file.uploaded_by} + + + {formatDate(file.uploaded_at)} + + +
+ + +
+
+
+ ))} +
+
+
+ + + + + Upload Reference File + + setUploadOpen(false)} + /> + + +
+
+ ); +} diff --git a/frontend/src/app/admin/files/tm/page.tsx b/frontend/src/app/admin/files/tm/page.tsx new file mode 100644 index 0000000..a69d000 --- /dev/null +++ b/frontend/src/app/admin/files/tm/page.tsx @@ -0,0 +1,128 @@ +"use client"; + +import React, { useState } from "react"; +import { AppShell } from "@/components/layout/AppShell"; +import { FileUploader } from "@/components/admin/FileUploader"; +import { Card } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { formatDate } from "@/lib/utils"; +import { Upload, Trash2, Database } from "lucide-react"; +import type { TMFile } from "@/lib/types"; + +const mockTMFiles: TMFile[] = [ + { id: "tm-001", name: "TM_de-DE_Master.tmx", locale_code: "de-DE", client_id: undefined, file_path: "/files/tm/TM_de-DE_Master.tmx", entry_count: 15420, uploaded_by: "Sarah Chen", uploaded_at: "2026-03-15T10:30:00Z" }, + { id: "tm-002", name: "TM_fr-FR_Master.tmx", locale_code: "fr-FR", client_id: undefined, file_path: "/files/tm/TM_fr-FR_Master.tmx", entry_count: 12890, uploaded_by: "Sarah Chen", uploaded_at: "2026-03-15T10:35:00Z" }, + { id: "tm-003", name: "TM_it-IT_Master.tmx", locale_code: "it-IT", client_id: undefined, file_path: "/files/tm/TM_it-IT_Master.tmx", entry_count: 11230, uploaded_by: "Emily Brown", uploaded_at: "2026-03-20T14:00:00Z" }, + { id: "tm-004", name: "TM_es-ES_Master.tmx", locale_code: "es-ES", client_id: undefined, file_path: "/files/tm/TM_es-ES_Master.tmx", entry_count: 13670, uploaded_by: "Emily Brown", uploaded_at: "2026-03-20T14:05:00Z" }, + { id: "tm-005", name: "TM_de-DE_OMG.tmx", locale_code: "de-DE", client_id: "client-001", file_path: "/files/tm/TM_de-DE_OMG.tmx", entry_count: 3240, uploaded_by: "James Miller", uploaded_at: "2026-04-01T09:00:00Z" }, + { id: "tm-006", name: "TM_nl-NL_Master.tmx", locale_code: "nl-NL", client_id: undefined, file_path: "/files/tm/TM_nl-NL_Master.tmx", entry_count: 8450, uploaded_by: "Sarah Chen", uploaded_at: "2026-04-05T11:20:00Z" }, + { id: "tm-007", name: "TM_sv-SE_Master.tmx", locale_code: "sv-SE", client_id: undefined, file_path: "/files/tm/TM_sv-SE_Master.tmx", entry_count: 7120, uploaded_by: "Sarah Chen", uploaded_at: "2026-04-05T11:25:00Z" }, + { id: "tm-008", name: "TM_pl-PL_Master.tmx", locale_code: "pl-PL", client_id: undefined, file_path: "/files/tm/TM_pl-PL_Master.tmx", entry_count: 6890, uploaded_by: "Emily Brown", uploaded_at: "2026-04-06T16:00:00Z" }, +]; + +export default function TMRegistryPage() { + const [files] = useState(mockTMFiles); + const [uploadOpen, setUploadOpen] = useState(false); + + return ( + +
+
+

+ Translation Memory files used during transcreation +

+ +
+ + + + + + File Name + Locale + Client + Entries + Uploaded By + Date + + + + + {files.map((file) => ( + + +
+ + + {file.name} + +
+
+ + {file.locale_code} + + + {file.client_id ? ( + OMG + ) : ( + Global + )} + + + {file.entry_count.toLocaleString()} + + + {file.uploaded_by} + + + {formatDate(file.uploaded_at)} + + + + +
+ ))} +
+
+
+ + + + + Upload Translation Memory + + setUploadOpen(false)} + /> + + +
+
+ ); +} diff --git a/frontend/src/app/admin/logs/page.tsx b/frontend/src/app/admin/logs/page.tsx new file mode 100644 index 0000000..1b6de87 --- /dev/null +++ b/frontend/src/app/admin/logs/page.tsx @@ -0,0 +1,196 @@ +"use client"; + +import React, { useState } from "react"; +import { AppShell } from "@/components/layout/AppShell"; +import { Card } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Input } from "@/components/ui/input"; +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { formatDateTime } from "@/lib/utils"; +import { Search } from "lucide-react"; + +interface AuditEntry { + id: string; + timestamp: string; + user: string; + action: string; + resource: string; + details: string; + level: "INFO" | "WARN" | "ERROR"; +} + +const mockAuditLogs: AuditEntry[] = [ + { id: "log-001", timestamp: "2026-04-10T09:15:00Z", user: "Sarah Chen", action: "JOB_LAUNCHED", resource: "OMG-2026-0044", details: "Job launched with 4 locales: de-DE, fr-FR, it-IT, es-ES", level: "INFO" }, + { id: "log-002", timestamp: "2026-04-10T09:14:50Z", user: "Sarah Chen", action: "FILE_UPLOADED", resource: "OMG-2026-0044", details: "Source file uploaded: DDA26_BFW_source.xlsx (42 lines)", level: "INFO" }, + { id: "log-003", timestamp: "2026-04-10T07:00:00Z", user: "James Miller", action: "JOB_CREATED", resource: "OMG-2026-0045", details: "Derived locale job created for de-AT, fr-BE, nl-BE", level: "INFO" }, + { id: "log-004", timestamp: "2026-04-09T09:45:00Z", user: "System", action: "LOCALE_ERROR", resource: "MND-2026-0012", details: "fr-FR locale failed: TM file not found for fr-FR locale", level: "ERROR" }, + { id: "log-005", timestamp: "2026-04-09T09:40:00Z", user: "System", action: "LOCALE_COMPLETE", resource: "MND-2026-0012", details: "de-DE locale completed successfully (142s, 5600/4800 tokens)", level: "INFO" }, + { id: "log-006", timestamp: "2026-04-09T08:20:00Z", user: "Sarah Chen", action: "JOB_LAUNCHED", resource: "MND-2026-0012", details: "UEFA Champions League Promo launched with 3 locales", level: "INFO" }, + { id: "log-007", timestamp: "2026-04-08T14:30:00Z", user: "Sarah Chen", action: "JOB_CREATED", resource: "OMG-2026-0044", details: "DDA 26 (BFW) job created", level: "INFO" }, + { id: "log-008", timestamp: "2026-04-06T16:42:00Z", user: "System", action: "JOB_COMPLETE", resource: "OMG-2026-0043", details: "Spring Prime Day 2026 completed all 6 locales successfully", level: "INFO" }, + { id: "log-009", timestamp: "2026-04-05T11:25:00Z", user: "Sarah Chen", action: "TM_UPLOADED", resource: "TM_sv-SE_Master.tmx", details: "7,120 entries loaded for sv-SE", level: "INFO" }, + { id: "log-010", timestamp: "2026-04-05T09:15:00Z", user: "System", action: "AUTH_FAILED", resource: "d.schmidt@amazon.com", details: "Login attempt with invalid credentials", level: "WARN" }, + { id: "log-011", timestamp: "2026-04-04T08:30:00Z", user: "System", action: "JOB_COMPLETE", resource: "PHD-2026-0008", details: "Summer Sale Landing Pages completed all 6 locales (56 lines)", level: "INFO" }, + { id: "log-012", timestamp: "2026-04-03T11:15:00Z", user: "Emily Brown", action: "JOB_CREATED", resource: "PHD-2026-0008", details: "Summer Sale Landing Pages created with 6 locales", level: "INFO" }, +]; + +const levelBadge: Record = { + INFO: "green", + WARN: "amber", + ERROR: "red", +}; + +export default function LogsPage() { + const [search, setSearch] = useState(""); + const [tab, setTab] = useState("audit"); + + const filteredLogs = mockAuditLogs.filter((log) => { + if (!search) return true; + const s = search.toLowerCase(); + return ( + log.action.toLowerCase().includes(s) || + log.resource.toLowerCase().includes(s) || + log.details.toLowerCase().includes(s) || + log.user.toLowerCase().includes(s) + ); + }); + + const errorLogs = filteredLogs.filter( + (log) => log.level === "ERROR" || log.level === "WARN" + ); + + return ( + +
+
+

+ System audit trail and error logs +

+
+ + setSearch(e.target.value)} + className="pl-9" + /> +
+
+ + + + + Audit Trail ({filteredLogs.length}) + + + Errors & Warnings ({errorLogs.length}) + + + + + + + + + Timestamp + User + Action + Resource + Details + Level + + + + {filteredLogs.map((log) => ( + + + {formatDateTime(log.timestamp)} + + {log.user} + + + {log.action} + + + + {log.resource} + + + {log.details} + + + + {log.level} + + + + ))} + +
+
+
+ + + + + + + Timestamp + Action + Resource + Details + Level + + + + {errorLogs.length === 0 ? ( + + + No errors or warnings found. + + + ) : ( + errorLogs.map((log) => ( + + + {formatDateTime(log.timestamp)} + + + + {log.action} + + + + {log.resource} + + + {log.details} + + + + {log.level} + + + + )) + )} + +
+
+
+
+
+
+ ); +} diff --git a/frontend/src/app/admin/reports/page.tsx b/frontend/src/app/admin/reports/page.tsx new file mode 100644 index 0000000..827c46c --- /dev/null +++ b/frontend/src/app/admin/reports/page.tsx @@ -0,0 +1,202 @@ +"use client"; + +import React from "react"; +import { AppShell } from "@/components/layout/AppShell"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { ReportChart } from "@/components/admin/ReportChart"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { TrendingUp, Clock, Zap, Target } from "lucide-react"; + +const jobsByWeek = [ + { name: "W10", jobs: 12, completed: 10, errors: 2 }, + { name: "W11", jobs: 18, completed: 16, errors: 1 }, + { name: "W12", jobs: 15, completed: 14, errors: 1 }, + { name: "W13", jobs: 22, completed: 20, errors: 2 }, + { name: "W14", jobs: 28, completed: 25, errors: 3 }, + { name: "W15", jobs: 24, completed: 22, errors: 1 }, +]; + +const confidenceDistribution = [ + { name: "HIGH", value: 68, fill: "#067D62" }, + { name: "MODERATE", value: 24, fill: "#F0AD4E" }, + { name: "LOW", value: 8, fill: "#CC0C39" }, +]; + +const tokensByLocale = [ + { locale: "de-DE", input: 245000, output: 198000 }, + { locale: "fr-FR", input: 238000, output: 195000 }, + { locale: "it-IT", input: 221000, output: 182000 }, + { locale: "es-ES", input: 235000, output: 190000 }, + { locale: "nl-NL", input: 156000, output: 128000 }, + { locale: "sv-SE", input: 142000, output: 118000 }, + { locale: "pl-PL", input: 134000, output: 112000 }, + { locale: "pt-PT", input: 128000, output: 105000 }, +]; + +const avgDuration = [ + { locale: "de-DE", duration: 4.2 }, + { locale: "fr-FR", duration: 4.5 }, + { locale: "it-IT", duration: 4.8 }, + { locale: "es-ES", duration: 4.1 }, + { locale: "nl-NL", duration: 3.8 }, + { locale: "sv-SE", duration: 3.6 }, + { locale: "pl-PL", duration: 4.9 }, + { locale: "pt-PT", duration: 3.7 }, +]; + +export default function ReportsPage() { + return ( + +
+
+

+ Platform usage and performance analytics +

+ +
+ + {/* Summary stats */} +
+ + +
+
+ +
+
+

119

+

Total Jobs (30d)

+
+
+
+
+ + +
+
+ +
+
+

94%

+

Success Rate

+
+
+
+
+ + +
+
+ +
+
+

4.2m

+

Avg Duration/Locale

+
+
+
+
+ + +
+
+ +
+
+

2.4M

+

Total Tokens

+
+
+
+
+
+ + {/* Charts */} +
+ + + Jobs by Week + + + + + + + + + Confidence Distribution + + + + + + + + + Token Usage by Locale + + + + + + + + + + Avg Duration by Locale (minutes) + + + + + + +
+
+
+ ); +} diff --git a/frontend/src/app/admin/users/page.tsx b/frontend/src/app/admin/users/page.tsx new file mode 100644 index 0000000..b76272a --- /dev/null +++ b/frontend/src/app/admin/users/page.tsx @@ -0,0 +1,121 @@ +"use client"; + +import React, { useState } from "react"; +import { AppShell } from "@/components/layout/AppShell"; +import { UserTable } from "@/components/admin/UserTable"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, +} from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { UserPlus } from "lucide-react"; +import type { User, UserRole } from "@/lib/types"; + +const mockUsers: User[] = [ + { id: "u-001", email: "s.chen@amazon.com", name: "Sarah Chen", role: "ADMIN" as UserRole, created_at: "2026-01-15T00:00:00Z", last_login: "2026-04-10T08:30:00Z", is_active: true }, + { id: "u-002", email: "j.miller@amazon.com", name: "James Miller", role: "MANAGER" as UserRole, created_at: "2026-02-01T00:00:00Z", last_login: "2026-04-09T14:20:00Z", is_active: true }, + { id: "u-003", email: "e.brown@amazon.com", name: "Emily Brown", role: "LINGUIST" as UserRole, created_at: "2026-02-15T00:00:00Z", last_login: "2026-04-08T11:45:00Z", is_active: true }, + { id: "u-004", email: "m.garcia@amazon.com", name: "Maria Garcia", role: "LINGUIST" as UserRole, created_at: "2026-03-01T00:00:00Z", last_login: "2026-04-07T16:00:00Z", is_active: true }, + { id: "u-005", email: "d.schmidt@amazon.com", name: "Daniel Schmidt", role: "VIEWER" as UserRole, created_at: "2026-03-15T00:00:00Z", last_login: "2026-04-05T09:15:00Z", is_active: false }, +]; + +export default function UsersPage() { + const [users] = useState(mockUsers); + const [dialogOpen, setDialogOpen] = useState(false); + const [editUser, setEditUser] = useState(null); + + const handleEdit = (user: User) => { + setEditUser(user); + setDialogOpen(true); + }; + + const handleAdd = () => { + setEditUser(null); + setDialogOpen(true); + }; + + return ( + +
+
+

+ Manage platform users and their roles +

+ +
+ + + + + + + + {editUser ? "Edit User" : "Add New User"} + + +
+
+ + +
+
+ + +
+
+ + +
+ {!editUser && ( +
+ + +
+ )} +
+ + + + +
+
+
+
+ ); +} diff --git a/frontend/src/app/dashboard/layout.tsx b/frontend/src/app/dashboard/layout.tsx new file mode 100644 index 0000000..abf46dc --- /dev/null +++ b/frontend/src/app/dashboard/layout.tsx @@ -0,0 +1,11 @@ +"use client"; + +import { AppShell } from "@/components/layout/AppShell"; + +export default function DashboardLayout({ + children, +}: { + children: React.ReactNode; +}) { + return {children}; +} diff --git a/frontend/src/app/dashboard/page.tsx b/frontend/src/app/dashboard/page.tsx new file mode 100644 index 0000000..3ecc31e --- /dev/null +++ b/frontend/src/app/dashboard/page.tsx @@ -0,0 +1,248 @@ +"use client"; + +import React, { useState } from "react"; +import Link from "next/link"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Badge } from "@/components/ui/badge"; +import { JobCard } from "@/components/jobs/JobCard"; +import { useJobs } from "@/hooks/useJobs"; +import { + PlusCircle, + Briefcase, + Play, + CheckCircle2, + AlertTriangle, + Search, + Filter, +} from "lucide-react"; + +export default function DashboardPage() { + const [search, setSearch] = useState(""); + const [statusFilter, setStatusFilter] = useState("all"); + const [clientFilter, setClientFilter] = useState("all"); + + const { jobs, loading } = useJobs(); + + // Compute stats from jobs + const stats = { + total: jobs.length, + running: jobs.filter((j) => j.status === "RUNNING").length, + completed: jobs.filter((j) => j.status === "COMPLETED").length, + errors: jobs.filter((j) => j.status === "ERROR").length, + }; + + // Filter jobs + const filteredJobs = jobs.filter((job) => { + if (search) { + const s = search.toLowerCase(); + if ( + !job.campaign_name.toLowerCase().includes(s) && + !job.job_ref.toLowerCase().includes(s) + ) { + return false; + } + } + if (statusFilter !== "all" && job.status !== statusFilter) return false; + if (clientFilter !== "all" && job.client_name !== clientFilter) return false; + return true; + }); + + const uniqueClients = Array.from(new Set(jobs.map((j) => j.client_name))); + + return ( +
+ {/* Header with action button */} +
+
+

+ Overview of all transcreation jobs +

+
+ + + +
+ + {/* Stats cards */} +
+ + +
+
+

Total Jobs

+

+ {stats.total} +

+
+
+ +
+
+
+
+ + + +
+
+

Running

+

+ {stats.running} +

+
+
+ +
+
+
+
+ + + +
+
+

Completed

+

+ {stats.completed} +

+
+
+ +
+
+
+
+ + + +
+
+

Errors

+

+ {stats.errors} +

+
+
+ +
+
+
+
+
+ + {/* Filter bar */} + + +
+
+ + Filters +
+ +
+ + setSearch(e.target.value)} + className="pl-9" + /> +
+ + + + + + {(search || statusFilter !== "all" || clientFilter !== "all") && ( + + )} + + + {filteredJobs.length} job{filteredJobs.length !== 1 ? "s" : ""} + +
+
+
+ + {/* Job list */} +
+ {loading ? ( +
+ {[1, 2, 3].map((i) => ( + + +
+
+
+
+
+
+
+
+ + + ))} +
+ ) : filteredJobs.length === 0 ? ( + + +

No jobs found matching your filters.

+ + + +
+
+ ) : ( + filteredJobs.map((job) => ) + )} +
+
+ ); +} diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css new file mode 100644 index 0000000..3b7805b --- /dev/null +++ b/frontend/src/app/globals.css @@ -0,0 +1,175 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* Amazon Ember Font Faces */ +@font-face { + font-family: "Amazon Ember"; + src: url("/fonts/AmazonEmber_Lt.ttf") format("truetype"); + font-weight: 300; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Amazon Ember"; + src: url("/fonts/AmazonEmber_Rg.ttf") format("truetype"); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Amazon Ember"; + src: url("/fonts/AmazonEmber_RgIt.ttf") format("truetype"); + font-weight: 400; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: "Amazon Ember"; + src: url("/fonts/Amazon-Ember-Medium.ttf") format("truetype"); + font-weight: 500; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Amazon Ember"; + src: url("/fonts/AmazonEmber_Bd.ttf") format("truetype"); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Amazon Ember"; + src: url("/fonts/AmazonEmber_BdIt.ttf") format("truetype"); + font-weight: 700; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: "Amazon Ember"; + src: url("/fonts/AmazonEmber_He.ttf") format("truetype"); + font-weight: 900; + font-style: normal; + font-display: swap; +} + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 0 0% 6%; + --card: 0 0% 100%; + --card-foreground: 0 0% 6%; + --popover: 0 0% 100%; + --popover-foreground: 0 0% 6%; + --primary: 36 100% 50%; + --primary-foreground: 0 0% 100%; + --secondary: 213 26% 19%; + --secondary-foreground: 0 0% 100%; + --muted: 0 0% 96%; + --muted-foreground: 0 0% 45%; + --accent: 0 0% 96%; + --accent-foreground: 0 0% 6%; + --destructive: 348 91% 42%; + --destructive-foreground: 0 0% 100%; + --border: 0 0% 90%; + --input: 0 0% 90%; + --ring: 36 100% 50%; + --radius: 0.5rem; + + /* Amazon brand colors as CSS variables */ + --amazon-orange: #FF9900; + --amazon-dark: #232F3E; + --amazon-teal: #007185; + --amazon-text: #0F1111; + --amazon-light: #F5F5F5; + --amazon-ember: #131A22; + --amazon-success: #067D62; + --amazon-error: #CC0C39; + --amazon-warning: #F0AD4E; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground font-sans; + color: var(--amazon-text); + } +} + +@layer components { + .amazon-card { + @apply bg-white rounded-lg border border-gray-200 shadow-sm; + } + + .amazon-btn-primary { + @apply bg-amazon-orange hover:bg-[#E88B00] text-white font-medium px-4 py-2 rounded-lg transition-colors; + } + + .amazon-btn-secondary { + @apply bg-amazon-dark hover:bg-amazon-ember text-white font-medium px-4 py-2 rounded-lg transition-colors; + } + + .amazon-link { + @apply text-amazon-teal hover:text-amazon-orange hover:underline cursor-pointer transition-colors; + } + + .amazon-input { + @apply border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-amazon-orange focus:border-amazon-orange transition-all; + } + + .sidebar-link { + @apply flex items-center gap-3 px-4 py-2.5 text-sm text-gray-300 hover:text-white hover:bg-white/5 rounded-lg transition-all duration-150 relative; + } + + .sidebar-link-active { + @apply text-amazon-orange bg-white/10 border-l-3 border-amazon-orange; + } + + .status-dot { + @apply w-2 h-2 rounded-full inline-block; + } + + .status-dot-success { + @apply bg-amazon-success; + } + + .status-dot-running { + @apply bg-amazon-orange animate-pulse; + } + + .status-dot-error { + @apply bg-amazon-error; + } + + .status-dot-queued { + @apply bg-gray-400; + } +} + +/* Scrollbar styling */ +::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: #d1d5db; + border-radius: 3px; +} + +::-webkit-scrollbar-thumb:hover { + background: #9ca3af; +} diff --git a/frontend/src/app/jobs/[jobId]/locale/[localeCode]/review/page.tsx b/frontend/src/app/jobs/[jobId]/locale/[localeCode]/review/page.tsx new file mode 100644 index 0000000..d00f8a7 --- /dev/null +++ b/frontend/src/app/jobs/[jobId]/locale/[localeCode]/review/page.tsx @@ -0,0 +1,192 @@ +"use client"; + +import React, { useState } from "react"; +import { useParams } from "next/navigation"; +import { AppShell } from "@/components/layout/AppShell"; +import { Card, CardContent } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; +import { OutputRowCard } from "@/components/jobs/OutputPreview/OutputRowCard"; +import { ConfidenceBadge } from "@/components/jobs/OutputPreview/ConfidenceBadge"; +import type { OutputRow, ConfidenceTier } from "@/lib/types"; +import { Download, ArrowLeft } from "lucide-react"; +import Link from "next/link"; + +// Mock output data +const mockOutputRows: OutputRow[] = [ + { + id: "row-001", + locale_instance_id: "li-1", + line_number: 1, + source_text: "Unlock deals you won't want to miss", + copy_type: "Headline", + char_limit: 45, + confidence: "HIGH" as ConfidenceTier, + rationale: "The German translation maintains the urgency and excitement of the original headline while adapting to German marketing conventions. 'Entdecken' (discover) is preferred over a literal 'unlock' as it resonates better with German consumers. All three options stay within the character limit.", + is_flagged: false, + options: [ + { option_number: 1, target_text: "Entdecken Sie Angebote, die Sie nicht verpassen wollen", back_translation: "Discover deals you don't want to miss", char_count: 55, is_within_limit: false }, + { option_number: 2, target_text: "Top-Angebote, die Sie nicht verpassen sollten", back_translation: "Top deals you shouldn't miss", char_count: 46, is_within_limit: false }, + { option_number: 3, target_text: "Angebote entdecken, die begeistern", back_translation: "Discover deals that excite", char_count: 34, is_within_limit: true }, + ], + }, + { + id: "row-002", + locale_instance_id: "li-1", + line_number: 2, + source_text: "Shop now and save big on top brands", + copy_type: "Sub-headline", + char_limit: 50, + confidence: "HIGH" as ConfidenceTier, + rationale: "Direct translation with cultural adaptation. German consumers respond well to 'Top-Marken' (top brands) and the savings message is clear and compelling.", + is_flagged: false, + options: [ + { option_number: 1, target_text: "Jetzt einkaufen und bei Top-Marken sparen", back_translation: "Shop now and save on top brands", char_count: 42, is_within_limit: true }, + { option_number: 2, target_text: "Top-Marken jetzt zum Sparpreis entdecken", back_translation: "Discover top brands now at bargain prices", char_count: 41, is_within_limit: true }, + { option_number: 3, target_text: "Grosse Ersparnis bei beliebten Marken", back_translation: "Big savings on popular brands", char_count: 37, is_within_limit: true }, + ], + }, + { + id: "row-003", + locale_instance_id: "li-1", + line_number: 3, + source_text: "Limited time offer - act fast!", + copy_type: "CTA", + char_limit: 35, + confidence: "MODERATE" as ConfidenceTier, + rationale: "The urgency messaging requires careful handling in German. 'Nur fuer kurze Zeit' is the standard phrasing for limited time offers. The exclamation in the CTA maintains energy without being too aggressive for German sensibilities. Option 2 uses a more colloquial approach that may not suit all audiences.", + is_flagged: false, + options: [ + { option_number: 1, target_text: "Nur fuer kurze Zeit - jetzt zugreifen!", back_translation: "Only for a short time - grab it now!", char_count: 39, is_within_limit: false }, + { option_number: 2, target_text: "Schnell sein lohnt sich - Angebot endet bald", back_translation: "Being fast pays off - offer ends soon", char_count: 45, is_within_limit: false }, + { option_number: 3, target_text: "Zeitlich begrenztes Angebot!", back_translation: "Limited time offer!", char_count: 28, is_within_limit: true }, + ], + }, + { + id: "row-004", + locale_instance_id: "li-1", + line_number: 4, + source_text: "Free delivery on orders over $25", + copy_type: "Body", + char_limit: 40, + confidence: "LOW" as ConfidenceTier, + rationale: "Currency conversion needed: $25 should be adapted to the local market equivalent. Using EUR 25 as approximate equivalent. However, the exact threshold should be verified with the client as local pricing may differ. Flagging for review due to currency ambiguity.", + is_flagged: true, + options: [ + { option_number: 1, target_text: "Kostenlose Lieferung ab 25 EUR Bestellwert", back_translation: "Free delivery from EUR 25 order value", char_count: 43, is_within_limit: false }, + { option_number: 2, target_text: "Gratis-Versand ab 25 EUR", back_translation: "Free shipping from EUR 25", char_count: 24, is_within_limit: true }, + { option_number: 3, target_text: "Ab 25 EUR versandkostenfrei bestellen", back_translation: "Order free shipping from EUR 25", char_count: 37, is_within_limit: true }, + ], + }, + { + id: "row-005", + locale_instance_id: "li-1", + line_number: 5, + source_text: "Your perfect gift, delivered on time", + copy_type: "Headline", + char_limit: 45, + confidence: "HIGH" as ConfidenceTier, + rationale: "Gift-giving messaging translates well into German. 'Perfekte Geschenk' is natural and the delivery promise resonates with German consumers who value reliability.", + is_flagged: false, + options: [ + { option_number: 1, target_text: "Ihr perfektes Geschenk, puenktlich geliefert", back_translation: "Your perfect gift, delivered on time", char_count: 45, is_within_limit: true }, + { option_number: 2, target_text: "Das ideale Geschenk - puenktlich bei Ihnen", back_translation: "The ideal gift - on time with you", char_count: 43, is_within_limit: true }, + { option_number: 3, target_text: "Perfekte Geschenke, rechtzeitig geliefert", back_translation: "Perfect gifts, delivered on time", char_count: 42, is_within_limit: true }, + ], + }, +]; + +export default function ReviewPage() { + const params = useParams(); + const jobId = params.jobId as string; + const localeCode = params.localeCode as string; + const [filter, setFilter] = useState("all"); + + const confidenceCounts = { + HIGH: mockOutputRows.filter((r) => r.confidence === "HIGH").length, + MODERATE: mockOutputRows.filter((r) => r.confidence === "MODERATE").length, + LOW: mockOutputRows.filter((r) => r.confidence === "LOW").length, + }; + + const filteredRows = mockOutputRows.filter((row) => { + if (filter === "all") return true; + if (filter === "flagged") return row.is_flagged; + return row.confidence === filter; + }); + + return ( + +
+ {/* Header */} +
+
+ + + +
+

+ Output Review: {localeCode} +

+

+ DDA 26 (BFW) | {mockOutputRows.length} rows +

+
+
+ +
+ {/* Confidence distribution */} +
+ + + +
+ + +
+
+ + {/* Filter tabs */} + + + + All ({mockOutputRows.length}) + + + High ({confidenceCounts.HIGH}) + + + Moderate ({confidenceCounts.MODERATE}) + + + Low ({confidenceCounts.LOW}) + + + Flagged ({mockOutputRows.filter((r) => r.is_flagged).length}) + + + + + {/* Output rows */} +
+ {filteredRows.map((row) => ( + + ))} +
+ + {filteredRows.length === 0 && ( + + +

No rows match this filter.

+
+
+ )} +
+
+ ); +} diff --git a/frontend/src/app/jobs/[jobId]/page.tsx b/frontend/src/app/jobs/[jobId]/page.tsx new file mode 100644 index 0000000..3426cb0 --- /dev/null +++ b/frontend/src/app/jobs/[jobId]/page.tsx @@ -0,0 +1,196 @@ +"use client"; + +import React from "react"; +import { useParams } from "next/navigation"; +import { AppShell } from "@/components/layout/AppShell"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { LocaleInstanceCard } from "@/components/jobs/MonitoringHUD/LocaleInstanceCard"; +import { useJob } from "@/hooks/useJobs"; +import { + Clock, + User, + FileText, + AlertTriangle, + XCircle, + StopCircle, +} from "lucide-react"; +import { formatDateTime } from "@/lib/utils"; + +const statusConfig: Record< + string, + { label: string; variant: "green" | "blue" | "amber" | "red" | "gray" | "default" } +> = { + DRAFT: { label: "Draft", variant: "gray" }, + QUEUED: { label: "Queued", variant: "blue" }, + RUNNING: { label: "Running", variant: "default" }, + COMPLETED: { label: "Completed", variant: "green" }, + PARTIAL: { label: "Partial", variant: "amber" }, + ERROR: { label: "Error", variant: "red" }, + CANCELLED: { label: "Cancelled", variant: "gray" }, +}; + +export default function JobMonitoringPage() { + const params = useParams(); + const jobId = params.jobId as string; + const { job, loading } = useJob(jobId); + + if (loading || !job) { + return ( + +
+
+
+
+
+
+ + ); + } + + const status = statusConfig[job.status] || statusConfig.DRAFT; + + return ( + +
+ {/* Job header */} + + +
+
+
+

+ {job.campaign_name} +

+ + {status.label} + + {job.context_override && ( + Override + )} +
+ +
+ {job.job_ref} + | + {job.client_name} + {job.programme} + {job.channel} + {job.sub_channel && ( + {job.sub_channel} + )} +
+ +
+ + + Created {formatDateTime(job.created_at)} + + + + {job.created_by} + + {job.total_lines && ( + + + {job.total_lines} source lines + + )} +
+
+ + {/* Actions */} +
+ {job.status === "RUNNING" && ( + + )} +
+
+ + {/* Error message */} + {job.error_message && ( +
+ + {job.error_message} +
+ )} +
+
+ + {/* Locale instances */} +
+

+ Locale Progress +

+
+ {job.locale_instances.map((li) => ( + + ))} +
+
+ + {/* Summary stats */} + + + Token Usage Summary + + +
+
+

+ {job.locale_instances.reduce( + (sum, li) => sum + li.tokens_input, + 0 + ).toLocaleString()} +

+

Input Tokens

+
+
+

+ {job.locale_instances.reduce( + (sum, li) => sum + li.tokens_output, + 0 + ).toLocaleString()} +

+

Output Tokens

+
+
+

+ {job.locale_instances.filter( + (li) => li.status === "COMPLETED" + ).length} + /{job.locale_instances.length} +

+

Locales Complete

+
+
+

+ {job.locale_instances.filter((li) => li.status === "ERROR") + .length > 0 ? ( + + + {job.locale_instances.filter( + (li) => li.status === "ERROR" + ).length} + + ) : ( + "0" + )} +

+

Errors

+
+
+
+
+
+
+ ); +} diff --git a/frontend/src/app/jobs/new/page.tsx b/frontend/src/app/jobs/new/page.tsx new file mode 100644 index 0000000..410a267 --- /dev/null +++ b/frontend/src/app/jobs/new/page.tsx @@ -0,0 +1,92 @@ +"use client"; + +import React, { useState } from "react"; +import { AppShell } from "@/components/layout/AppShell"; +import { WizardStepper } from "@/components/jobs/JobWizard/WizardStepper"; +import { StepConfigure } from "@/components/jobs/JobWizard/StepConfigure"; +import { StepUpload } from "@/components/jobs/JobWizard/StepUpload"; +import { StepReview } from "@/components/jobs/JobWizard/StepReview"; + +export interface JobFormData { + client_id: string; + client_name: string; + job_ref: string; + campaign_name: string; + programme: string; + channel: string; + sub_channel: string; + job_type: string; + locales: string[]; + source_file: File | null; + supplementary_files: File[]; + context_override: string; +} + +const initialFormData: JobFormData = { + client_id: "", + client_name: "", + job_ref: "", + campaign_name: "", + programme: "RETAIL", + channel: "", + sub_channel: "", + job_type: "MAIN", + locales: [], + source_file: null, + supplementary_files: [], + context_override: "", +}; + +export default function NewJobPage() { + const [step, setStep] = useState(0); + const [formData, setFormData] = useState(initialFormData); + + const updateFormData = (updates: Partial) => { + setFormData((prev) => ({ ...prev, ...updates })); + }; + + const steps = [ + { + label: "Configure", + component: ( + setStep(1)} + /> + ), + }, + { + label: "Upload", + component: ( + setStep(0)} + onNext={() => setStep(2)} + /> + ), + }, + { + label: "Review & Launch", + component: ( + setStep(1)} + /> + ), + }, + ]; + + return ( + +
+ s.label)} + currentStep={step} + /> +
{steps[step].component}
+
+
+ ); +} diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx new file mode 100644 index 0000000..7f3fdea --- /dev/null +++ b/frontend/src/app/layout.tsx @@ -0,0 +1,19 @@ +import type { Metadata } from "next"; +import "./globals.css"; + +export const metadata: Metadata = { + title: "Amazon Transcreation Platform", + description: "AI-powered transcreation and localization platform", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + {children} + + ); +} diff --git a/frontend/src/app/login/page.tsx b/frontend/src/app/login/page.tsx new file mode 100644 index 0000000..51ffc5e --- /dev/null +++ b/frontend/src/app/login/page.tsx @@ -0,0 +1,139 @@ +"use client"; + +import React, { useState } from "react"; +import Image from "next/image"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Card, CardContent } from "@/components/ui/card"; +import { AlertCircle, Loader2 } from "lucide-react"; + +export default function LoginPage() { + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setLoading(true); + setError(null); + + try { + // For demo, accept any credentials and redirect + await new Promise((resolve) => setTimeout(resolve, 800)); + + // Store mock auth + if (typeof window !== "undefined") { + localStorage.setItem("amazon_tc_token", "mock-jwt-token"); + localStorage.setItem( + "amazon_tc_user", + JSON.stringify({ + id: "user-001", + email: email || "s.chen@amazon.com", + name: "Sarah Chen", + role: "ADMIN", + is_active: true, + created_at: "2026-01-15T00:00:00Z", + }) + ); + window.location.href = "/dashboard"; + } + } catch { + setError("Invalid email or password. Please try again."); + } finally { + setLoading(false); + } + }; + + return ( +
+
+ {/* Logo */} +
+ Amazon +
+ + + +
+

+ Sign In +

+

+ Transcreation Platform +

+
+ + {error && ( +
+ + {error} +
+ )} + +
+
+ + setEmail(e.target.value)} + required + autoComplete="email" + /> +
+ +
+ + setPassword(e.target.value)} + required + autoComplete="current-password" + /> +
+ + +
+ +
+

+ SSO login coming soon +

+
+
+
+ +

+ Amazon Transcreation Platform v0.1.0 +

+
+
+ ); +} diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx new file mode 100644 index 0000000..a74cb27 --- /dev/null +++ b/frontend/src/app/page.tsx @@ -0,0 +1,5 @@ +import { redirect } from "next/navigation"; + +export default function Home() { + redirect("/dashboard"); +} diff --git a/frontend/src/components/admin/ClientForm.tsx b/frontend/src/components/admin/ClientForm.tsx new file mode 100644 index 0000000..16ad10d --- /dev/null +++ b/frontend/src/components/admin/ClientForm.tsx @@ -0,0 +1,90 @@ +"use client"; + +import React, { useState } from "react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Textarea } from "@/components/ui/textarea"; +import { Separator } from "@/components/ui/separator"; +import type { Client } from "@/lib/types"; + +interface ClientFormProps { + client: Client | null; + onSave: () => void; + onCancel: () => void; +} + +export function ClientForm({ client, onSave, onCancel }: ClientFormProps) { + const [name, setName] = useState(client?.name || ""); + const [code, setCode] = useState(client?.code || ""); + const [tone, setTone] = useState(client?.voice_profile?.tone || ""); + const [style, setStyle] = useState(client?.voice_profile?.style || ""); + const [guidelines, setGuidelines] = useState( + client?.voice_profile?.guidelines || "" + ); + + return ( +
+
+
+ + setName(e.target.value)} + placeholder="e.g. OMG" + /> +
+
+ + setCode(e.target.value.toUpperCase())} + placeholder="e.g. OMG" + maxLength={5} + /> +
+
+ + + +

Voice Profile

+ +
+ + setTone(e.target.value)} + placeholder="e.g. Professional, authoritative, yet approachable" + /> +
+ +
+ + setStyle(e.target.value)} + placeholder="e.g. Concise marketing copy with strong CTAs" + /> +
+ +
+ +