diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..846c3a5 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +node_modules +dist +.vite +.git +.gitignore +coverage +test-results +playwright-report +*.log +.env +.env.* +!.env.example diff --git a/.env.example b/.env.example index 60b7ceb..0a4b76c 100644 --- a/.env.example +++ b/.env.example @@ -1,16 +1,16 @@ -# Monynha Softwares - Environment Variables -# Copy this file to .env.local and fill in your actual values +# Public environment variables (accessible in client-side code) +VITE_SUPABASE_URL=https://your-project.supabase.co +VITE_SUPABASE_ANON_KEY=your_supabase_anon_key_here -# Resend API Key for email delivery -# Get your API key from: https://resend.com/api-keys -RESEND_API_KEY=re_your_api_key_here - -# Site URL (used for sitemap generation) -SITE_URL=https://monynha.com -VITE_SITE_URL=https://monynha.com - -# Server Port (optional, defaults to 8080) -# PORT=8080 - -# Node Environment (set to 'production' in Docker) -# NODE_ENV=production +# ⚠️ IMPORTANT: API keys are now stored in Supabase Edge Function secrets, NOT here! +# +# Configure these secrets in Supabase Dashboard: +# Dashboard → Project Settings → Edge Functions → Secrets +# +# Required secrets: +# - GEMINI_API_KEY: Get from https://aistudio.google.com/apikey +# - RESEND_API_KEY: Get from https://resend.com/api-keys +# - RESEND_FROM_EMAIL: Verified sender email (e.g., hello@monynha.com) +# - MONYNHA_INTERNAL_EMAIL: Internal team notification email +# +# DO NOT add these keys to this .env file - they belong in Supabase backend! diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1e3d333 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,103 @@ +name: CI Pipeline + +on: + push: + branches: [main, develop] + pull_request: + branches: [main, develop] + +env: + PNPM_VERSION: "10.23.0" + +jobs: + ci: + name: CI - Lint, Test & Build + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20.x + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run type checking & linting + run: pnpm lint + + - name: Run unit tests + run: pnpm test:run + env: + VITE_SUPABASE_URL: ${{ vars.VITE_SUPABASE_URL }} + VITE_SUPABASE_ANON_KEY: ${{ vars.VITE_SUPABASE_ANON_KEY }} + + - name: Build application + run: pnpm build + env: + VITE_SUPABASE_URL: ${{ vars.VITE_SUPABASE_URL }} + VITE_SUPABASE_ANON_KEY: ${{ vars.VITE_SUPABASE_ANON_KEY }} + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: dist + path: dist/ + retention-days: 7 + + security: + name: Security Scan + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + continue-on-error: true + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@0.32.0 + continue-on-error: true + with: + scan-type: 'fs' + scan-ref: '.' + format: 'sarif' + output: 'trivy-results.sarif' + severity: 'CRITICAL,HIGH' + exit-code: '0' + ignore-unfixed: true + + - name: Check if SARIF file exists + id: check_sarif + run: | + if [ -f "trivy-results.sarif" ]; then + echo "sarif_exists=true" >> $GITHUB_OUTPUT + echo "✅ Trivy scan completed" + else + echo "sarif_exists=false" >> $GITHUB_OUTPUT + echo "⚠️ Trivy scan did not produce results" + fi + + - name: Upload Trivy results to GitHub Security + uses: github/codeql-action/upload-sarif@v4 + if: steps.check_sarif.outputs.sarif_exists == 'true' + continue-on-error: true + with: + sarif_file: 'trivy-results.sarif' + + - name: Display scan summary + if: always() + run: | + echo "🔒 Security scan completed" + echo "Note: GitHub Advanced Security must be enabled to view detailed results" diff --git a/.gitignore b/.gitignore index e71c5e7..3bc77bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,30 @@ -.env -.env.local -node_modules/ -dist/ -build/ -coverage/ -.playwright-mcp/ \ No newline at end of file +# Outros +.cache/ +.next/ +.playwright-test/ +.playwright-mcp/ +*.png +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/AI_RULES.md b/AI_RULES.md index 03db161..c4cfe67 100644 --- a/AI_RULES.md +++ b/AI_RULES.md @@ -1,26 +1,67 @@ -# AI Editor Rules and Project Guidelines - -This document outlines the core technical stack and specific rules for development and modification within the Monynha Softwares codebase. These guidelines ensure consistency, maintainability, and adherence to the project's aesthetic and performance standards. - -## Core Tech Stack - -1. **Frontend:** React (v19) with TypeScript. -2. **Build Tool:** Vite. -3. **Styling:** Tailwind CSS, utilizing the custom brand color palette defined in `index.html` (`brand-black`, `brand-violet`, `brand-blue`, `brand-teal`). -4. **Animation:** Framer Motion is used for all component transitions, gestures, and complex visual effects. -5. **Routing:** Custom state-based routing managed in `App.tsx` (using the `Page` type and `setPage` handler). **Do not introduce React Router.** -6. **Icons:** Lucide React is the preferred library for all vector icons. -7. **UI Components:** Components should be built using Tailwind CSS, prioritizing the use of available shadcn/ui components as a foundation when applicable. -8. **API/Serverless:** Simple Node.js handlers in the `api/` directory are used for server-side logic (e.g., contact form submission). -9. **Code Structure:** Components reside in `src/components/` and views/pages in `src/views/`. - -## Library Usage Rules - -| Feature | Recommended Library / Tool | Specific Rule | -| :--- | :--- | :--- | -| **Animations** | `framer-motion` | Mandatory for all non-trivial animations and page transitions. | -| **Styling** | Tailwind CSS | Use utility classes exclusively. Maintain the "brutalist-futuristic" aesthetic (e.g., thick borders, high contrast, custom fonts). | -| **Icons** | `lucide-react` | Use this library for all vector icons. | -| **Standard UI** | shadcn/ui | Use pre-built components as a foundation, customizing them with Tailwind classes to match the brand aesthetic. | -| **API Calls** | Native `fetch` | Use native `fetch` for all asynchronous data operations. | -| **Contact Forms** | `api/contact.js` pattern | All contact/email submissions must route through the existing API handler structure, respecting the `RESEND_API_KEY` environment variable. | \ No newline at end of file +# Regras de IA e Desenvolvimento + +Este arquivo documenta as convenções atuais do projeto baseadas no código deste repositório. + +## Stack principal + +- React 19 +- TypeScript +- Vite 6 +- Tailwind CSS v4 via `src/styles/index.css` +- Supabase client + Supabase Edge Functions + +## Convenções de UI + +- A navegação é baseada em estado via `AppState` em `src/App.tsx`. +- Não há router; evite introduzir um sem decisão de produto intencional. +- Estilos globais e tokens de design estão em `src/styles/index.css` sob `@theme`. +- Mantenha componentes de marca (`IntroScene`, `FairyCursor`, transições do wizard) a menos que haja decisão de produto para removê-los. + +## Dados e serviços + +- Os tipos `LeadData` e `DiagnosisResult` em `src/types/index.ts` são a fonte da verdade para payloads do app. +- O frontend não chama Gemini ou Resend diretamente. +- Operações sensíveis passam pelas Edge Functions: + - `generate-diagnosis` + - `send-diagnostic-email` + - `send-contact-confirmation` + - `company-search` + +## Ambiente e secrets + +- Variáveis de ambiente do frontend: + - `VITE_SUPABASE_URL` + - `VITE_SUPABASE_ANON_KEY` +- Secrets do backend (Supabase Edge Function secrets): + - `GEMINI_API_KEY` + - `RESEND_API_KEY` + - `RESEND_FROM_EMAIL` + - `MONYNHA_INTERNAL_EMAIL` + +## Regras de qualidade de código + +- Use tipos TypeScript estritos. +- Prefira funções da camada de serviço em vez de chamar Supabase diretamente nos componentes. +- Mantenha o tratamento de erros assíncronos explícito (`try/catch`) em serviços e fluxos assíncronos. +- Mantenha o comportamento de validação do wizard estável a menos que os requisitos mudem. +- Mensagens de erro voltadas ao usuário devem seguir a voz da marca: português do Brasil, direta, com personalidade. + +## Regras de testes + +- Testes unitários ficam em `tests/unit/`. +- Specs E2E ficam em `tests/e2e/`. +- `pnpm ci` é o equivalente local das verificações principais de CI (`lint`, `test:run`, `build`). + +## Regra de documentação + +Quando a implementação mudar, atualize os docs na mesma mudança: + +- `README.md` +- `ARCHITECTURE.md` +- `docs/EDGE_FUNCTIONS.md` +- `docs/ENVIRONMENT_SETUP.md` +- `docs/SUPABASE_SETUP.md` +- `docs/SUPABASE_IMPLEMENTATION.md` +- `docs/TESTING.md` +- `CI_CD_SUMMARY.md` + diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..d4bca57 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,142 @@ +# Arquitetura do Sistema + +Este documento descreve a arquitetura atual implementada no codebase. + +## Componentes de alto nível + +- **Frontend SPA**: app React em `src/`. +- **Persistência de dados**: Supabase acessado via `src/services/supabaseService.ts`. +- **Lógica de negócio server-side**: Supabase Edge Functions em `supabase/functions/`. +- **Provedores externos (server-side)**: Gemini (`@google/genai`) e Resend. + +## Máquina de estados do frontend (`src/App.tsx`) + +`AppState` controla a navegação e modo de UI: + +- `INTRO` +- `LANDING` +- `WIZARD` +- `LOADING` +- `REPORT` +- `ABOUT` +- `LEGAL` + +As transições são animadas via `transitionTo(...)` com overlay de 600ms. + +## Jornada do usuário + +1. Animação de intro (`IntroScene`), depois landing. +2. Landing roteia para o wizard ou página about. +3. Wizard coleta dados do lead em 6 etapas. +4. Ao completar: + - muda view para `LOADING` + - chama `sendContactConfirmation(leadData)` — fallback garantido, não bloqueia o fluxo + - chama `generateDiagnosis(leadData)` + - chama `saveLead(...)` e `sendDiagnosticEmail(...)` em paralelo (`Promise.allSettled`) + - loga falhas não-bloqueantes de save/email + - transiciona para `REPORT` após delay +5. Report pode resetar para landing. + +## Comportamento do Wizard (`src/components/Wizard.tsx`) + +- Persistência de rascunho: chave `localStorage` `monynha_wizard_draft_v1`. +- Gates de validação: + - Etapa 1: email válido + - Etapa 2: nome da marca OU `no_brand=true` + - Etapa 5: texto de struggle com comprimento >= 10 +- Atalhos de teclado: + - `Enter`: avançar quando válido + - `Escape`: cancelar + +## Camada de serviços (`src/services/`) + +- `geminiService.ts` + - Invoca Edge Function `generate-diagnosis`. + - Retorna diagnóstico fallback em caso de falha. +- `supabaseService.ts` + - Cria cliente Supabase com `VITE_SUPABASE_URL` e `VITE_SUPABASE_ANON_KEY`. + - Persiste via RPC: `save_lead_with_diagnosis`. + - Fornece helpers de fetch/update/delete para leads. +- `resendService.ts` + - Invoca Edge Function `send-diagnostic-email`. +- `contactConfirmationService.ts` + - Invoca Edge Function `send-contact-confirmation`. + - Garante notificação ao lead e ao time independentemente do resultado do diagnóstico. +- `companySearchService.ts` + - Invoca Edge Function `company-search`. + +## Edge Functions + +### `generate-diagnosis` + +- Valida payload (`leadData.email`, `leadData.struggle`). +- Lê `GEMINI_API_KEY` do ambiente da function. +- Chama modelo Gemini `gemini-3-flash-preview` com: + - `tools: [{ googleSearch: {} }]` + - Schema de resposta JSON para output do diagnóstico +- Extrai fontes de grounding dos metadados do candidato. +- Retorna diagnóstico fallback em caso de erro de runtime. + +### `send-diagnostic-email` + +- Valida payload de lead + diagnóstico. +- Lê: + - `RESEND_API_KEY` + - `RESEND_FROM_EMAIL` (fallback: `hello@monynha.com`) + - `MONYNHA_INTERNAL_EMAIL` (fallback: `hello@monynha.com`) +- Calcula score/classificação do lead. +- Envia dois e-mails com helper de retry simples. + +### `send-contact-confirmation` + +- Dispara imediatamente ao receber o submit do wizard, antes do diagnóstico. +- Valida payload (`contactData.email`, `contactData.struggle`). +- Lê: + - `RESEND_API_KEY` + - `RESEND_FROM_EMAIL` (fallback: `hello@monynha.com`) + - `MONYNHA_INTERNAL_EMAIL` (fallback: `hello@monynha.com`) +- Envia dois e-mails com helper de retry: + - confirmação ao lead + - notificação interna +- Retorna flags `confirmationSent` e `internalSent` para logging. + +### `company-search` + +- Aceita um ou mais sinais de busca. +- Extração opcional de metadados de website (`title` + `description`) com timeout. +- Normaliza handle do Instagram para formato `@...`. + +### Configuração de auth + +Todos os `config.toml` das functions usam: + +```toml +[function] +verify_jwt = false +``` + +## Modelo de dados (contrato tipado) + +`src/supabase.types.ts` inclui: + +- Tabelas: `leads`, `diagnoses`, `recommendations`, `grounding_sources` +- Function: `save_lead_with_diagnosis(...)` + +O frontend persiste via RPC e lê diretamente dos helpers `leads` e `diagnoses`. + +## Testes e CI + +- Testes unitários: Vitest (`tests/unit/`). +- Specs E2E: Playwright em `tests/e2e/`. +- Workflow de CI: `.github/workflows/ci.yml` inclui: + - job `ci` (lint, testes unitários, build, upload de artefato) + - job `security` (Trivy scan) + +Veja `docs/TESTING.md` e `CI_CD_SUMMARY.md` para detalhes de comandos. + +## Atualização recente (a11y/performance) + +- Modal de time em `AboutSite` agora usa semântica de diálogo (`role="dialog"`, `aria-modal`, foco inicial no botão fechar e fechamento por `Esc`). +- Avatares remotos em componentes visuais receberam `loading="lazy"` e `decoding="async"` para reduzir custo inicial de renderização. +- Ícone decorativo de seleção no wizard recebeu `aria-hidden="true"` para evitar ruído para leitores de tela. + diff --git a/App.tsx b/App.tsx deleted file mode 100644 index 407a384..0000000 --- a/App.tsx +++ /dev/null @@ -1,106 +0,0 @@ - -import React, { useEffect, useState } from 'react'; -import { Navbar } from './components/Navbar'; -import { Footer } from './components/Footer'; -import { Logo } from './components/Logo'; -import { motion, AnimatePresence } from 'framer-motion'; - -// Views -import { HomeView } from './views/HomeView'; -import { SolutionsView } from './views/SolutionsView'; -import { LabsView } from './views/LabsView'; -import { OpenSourceView } from './views/OpenSourceView'; -import { ContactView } from './views/ContactView'; - -export type Page = 'home' | 'solutions' | 'labs' | 'open-source' | 'contact'; - -const App: React.FC = () => { - const [isLoaded, setIsLoaded] = useState(false); - const [currentPage, setCurrentPage] = useState('home'); - - useEffect(() => { - const timer = setTimeout(() => setIsLoaded(true), 2500); - return () => clearTimeout(timer); - }, []); - - const handleSetPage = (page: Page) => { - setCurrentPage(page); - window.scrollTo({ top: 0, behavior: 'smooth' }); - }; - - const renderPage = () => { - switch (currentPage) { - case 'home': return ; - case 'solutions': return ; - case 'labs': return ; - case 'open-source': return ; - case 'contact': return ; - default: return ; - } - }; - - return ( -
- - {!isLoaded && ( - - - -
- - Monynha - - -
-
-
- )} -
- - - -
- - - {renderPage()} - - -
- -
-
- ); -}; - -export default App; diff --git a/CI_CD_SUMMARY.md b/CI_CD_SUMMARY.md new file mode 100644 index 0000000..3de374f --- /dev/null +++ b/CI_CD_SUMMARY.md @@ -0,0 +1,67 @@ +# Resumo de CI e Testes + +Última verificação: 2026-03-07 + +## Workflows no repositório + +Apenas um arquivo de workflow existe: + +- `.github/workflows/ci.yml` + +Ele define dois jobs: + +1. `ci` (Ubuntu) + - Instala dependências (`pnpm install --frozen-lockfile`) + - Roda `pnpm lint` + - Roda `pnpm test:run` + - Roda `pnpm build` + - Faz upload do artefato `dist/` + +2. `security` (Ubuntu) + - Trivy filesystem scan + - Upload opcional de SARIF + +Não há workflow de deploy neste repositório no momento. + +## Verificação local de comandos (2026-03-07) + +- `pnpm lint`: passa +- `pnpm test:run`: passa (todos os testes unitários) +- `pnpm build`: passa +- `pnpm test:e2e`: requer servidor rodando na porta 4173 (use `pnpm preview` antes) + +## Configuração de testes E2E + +- `playwright.config.ts` usa `testDir: './tests/e2e'` +- Specs estão em `tests/e2e/` +- Configuração e specs estão alinhadas + +## Variáveis e secrets do GitHub necessários para CI + +De `.github/workflows/ci.yml`: + +- Variáveis de repositório: + - `VITE_SUPABASE_URL` + - `VITE_SUPABASE_ANON_KEY` +- Secret de repositório: + - `VITE_GEMINI_API_KEY` + +## Verificação local recomendada antes do push + +```bash +pnpm ci +``` + +Para rodar E2E localmente: + +```bash +pnpm preview & +pnpm test:e2e +``` + +## Atualização recente (a11y/performance) + +- Modal de time em `AboutSite` agora usa semântica de diálogo (`role="dialog"`, `aria-modal`, foco inicial no botão fechar e fechamento por `Esc`). +- Avatares remotos em componentes visuais receberam `loading="lazy"` e `decoding="async"` para reduzir custo inicial de renderização. +- Ícone decorativo de seleção no wizard recebeu `aria-hidden="true"` para evitar ruído para leitores de tela. + diff --git a/Dockerfile b/Dockerfile index a54a658..500d81a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,19 @@ -# Build stage -FROM node:20-alpine AS build -WORKDIR /app -COPY package.json pnpm-lock.yaml* package-lock.json* ./ -RUN npm install -g pnpm && pnpm install --frozen-lockfile || npm install -COPY . . -RUN pnpm run build || npm run build +# syntax=docker/dockerfile:1 -# Runtime stage -FROM node:20-alpine +FROM node:20-alpine AS build WORKDIR /app -# Copy package files and install production dependencies only -COPY package.json pnpm-lock.yaml* package-lock.json* ./ -RUN npm install -g pnpm && pnpm install --prod --frozen-lockfile || npm install --production +RUN corepack enable -# Copy built assets and server file -COPY --from=build /app/dist ./dist -COPY server.js ./ +COPY package.json pnpm-lock.yaml ./ +RUN pnpm install --frozen-lockfile -# Set environment to production -ENV NODE_ENV=production +COPY . . +RUN pnpm build -EXPOSE 8080 +FROM nginx:1.27-alpine AS runtime +COPY docker/nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=build /app/dist /usr/share/nginx/html -# Start the Express server -CMD ["node", "server.js"] +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/README.md b/README.md index 1bbb879..714cd75 100644 --- a/README.md +++ b/README.md @@ -1,463 +1,178 @@ -# Monynha Softwares +# Monynha Softwares — Lead Generator Form -
+Wizard de qualificação de leads da Monynha Softwares. O app coleta contexto do lead, gera um diagnóstico de IA via Supabase Edge Functions, persiste os dados no Supabase e dispara e-mails de diagnóstico e confirmação. -**Democratizing Technology, Empowering People** +## Preview visual -A futuristic, inclusive, and high-end digital presence for a software studio that builds custom Odoo solutions, AI-powered automation, and digital products. +### Homepage (manifesto) -[Website](https://monynha.com) • [Services](https://monynha.com/solutions) • [Contact](https://monynha.com/contact) +![Homepage da Monynha Softwares](docs/homepage.png) -
+### Intro (tela de abertura) ---- +![Tela de intro do projeto](docs/index.png) -## 🎯 About Monynha Softwares +### Wizard (captura de lead) -Monynha Softwares is a digital engineering studio dedicated to bridging the gap between complex engineering and human intuition. We specialize in: +![Tela de formulário do wizard](docs/form.png) -- **Odoo Solutions** - Custom ERP implementations, workflow automation, and resource management -- **Custom Software** - Bespoke web applications, internal dashboards, and robust APIs -- **AI & Automation** - Intelligent assistants and context-aware autonomous workflows +### Loading (processamento do diagnóstico) -Our mission is to deliver outcomes, not just code—building digital products that don't just function, they *breathe*. +![Tela de loading enquanto o diagnóstico é gerado](docs/loading.png) -### Website Preview +## O que este projeto faz -![Monynha Softwares Homepage](docs/homepage.png) +- Roda um wizard de 6 etapas para capturar perfil e contexto de negócio do lead. +- Envia imediatamente uma confirmação de contato via `send-contact-confirmation` — garantindo que o lead e o time são notificados mesmo que o diagnóstico falhe. +- Chama a Edge Function `generate-diagnosis` (Gemini + Google Search grounding) para produzir o diagnóstico. +- Persiste lead + diagnóstico via RPC Supabase (`save_lead_with_diagnosis`). +- Dispara e-mails de diagnóstico e notificação interna via `send-diagnostic-email`. +- Exibe o relatório final com pontuações, recomendações e ações de compartilhamento. ---- +## Runtime flow -## 🎨 Design & Theme +1. `INTRO` (`IntroScene`) auto-completa em ~3s (ou pode ser pulada). +2. `LANDING` apresenta as CTAs principais. +3. `WIZARD` coleta os dados e armazena rascunho em `localStorage` (`monynha_wizard_draft_v1`). +4. Ao submeter, `App.tsx` muda para `LOADING` e executa: + - `sendContactConfirmation(data)` — fallback garantido, não bloqueia o fluxo + - `generateDiagnosis(data)` + - `Promise.allSettled([saveLead(data, diagnosis), sendDiagnosticEmail(data, diagnosis)])` +5. Após um breve delay, o app transiciona para `REPORT`. +6. Rotas secundárias são controladas por estado: `ABOUT` e `LEGAL`. -### Visual Identity: Brutalist Futurism +## Tech stack -Monynha Softwares embraces a **brutalist-futuristic aesthetic** characterized by: +- React 19 + TypeScript + Vite 6 +- Tailwind CSS v4 (`@import "tailwindcss"` + `@theme` em `src/styles/index.css`) +- Supabase JS client (`@supabase/supabase-js`) +- Supabase Edge Functions (Deno) +- Gemini via `@google/genai` (dentro da Edge Function) +- Resend (dentro da Edge Function) +- Vitest + Playwright -#### Color Palette -- **Brand Black** (`#05070a`) - Deep, pure black background -- **Brand Violet** (`#8b5cf6`) - Vibrant accent color for primary interactions -- **Brand Blue** (`#3c83f6`) - Secondary accent for contrast and hierarchy -- **Brand Teal** (`#0d9488`) - Tertiary accent for visual diversity +## Pré-requisitos -#### Typography -- **Display Font**: Space Grotesk - Bold, geometric sans-serif for headlines -- **Body Font**: Inter - Clean, highly readable sans-serif for content -- **Weight Emphasis**: Bold and black weights create striking visual hierarchy +- Node.js 20+ +- pnpm 10+ +- Projeto Supabase (para persistência e functions) +- Supabase CLI (recomendado para dev/deploy local de functions) -#### Visual Elements -- **Thick Borders** - 4px solid white borders create boldness and definition -- **Text Outlines** - Transparent text with stroke creates elegant, outlined headlines -- **Glass Morphism** - Frosted glass effect (`backdrop-filter: blur(10px)`) for subtle depth -- **Decorative Blurs** - Large, soft background blurs in brand colors add atmosphere without overwhelming -- **High Contrast** - Pure white text on pure black background ensures maximum readability +## Setup local -#### Interactive Design -- **Smooth Transitions** - Framer Motion animations for fluid interactions -- **Gradient Underlines** - Animated gradient dividers provide visual interest -- **Hover States** - Inverted colors and border transformations on interactions -- **Custom Scrollbar** - Violet scrollbar thumbs maintain brand consistency - ---- - -## 🔧 Technology Stack - -| Category | Technology | Version | -|----------|-----------|---------| -| **Frontend** | React | 19.2.4 | -| **Language** | TypeScript | ~5.8.2 | -| **Build Tool** | Vite | 6.2.0 | -| **Styling** | Tailwind CSS | latest | -| **Animations** | Framer Motion | 12.33.0 | -| **Backend** | Node.js Express | 4.19.2 | -| **Routing** | Custom State-based | - | -| **Icons** | Lucide React | - | -| **UI Components** | shadcn/ui | - | -| **Deployment** | Docker | Node 20-alpine | - -### Key Libraries -- **Animation**: Framer Motion for transitions, gestures, and complex visual effects -- **Styling**: Tailwind CSS utilities with custom brand color extensions -- **Icons**: Lucide React for all vector icons -- **API**: Native `fetch` for asynchronous operations -- **UI**: shadcn/ui components customized with Tailwind - ---- - -## 📁 Project Structure - -``` -monynha-softwares/ -├── components/ # Reusable React components -│ ├── Navbar.tsx # Navigation header -│ ├── Hero.tsx # Hero section with CTA -│ ├── Services.tsx # Service offerings display -│ ├── Footer.tsx # Footer component -│ ├── Logo.tsx # Monynha logo and animation -│ ├── AISection.tsx # AI/automation section -│ ├── TeamSection.tsx # Team presentation -│ └── CTASection.tsx # Call-to-action section -├── views/ # Page views/routes -│ ├── HomeView.tsx # Homepage composition -│ ├── SolutionsView.tsx # Solutions/services detail -│ ├── LabsView.tsx # Labs/experiments showcase -│ ├── OpenSourceView.tsx # Open source projects -│ └── ContactView.tsx # Contact form page -├── api/ # Backend API handlers -│ └── contact.js # Contact form submission endpoint -├── assets/ # Static assets (images, icons) -├── public/ # Public static files -├── docs/ # Documentation -│ └── REACTBITS_INTEGRATION.md -├── scripts/ # Build and utility scripts -│ ├── generate_favicon.py # Favicon generation -│ └── generate_sitemap.mjs # Sitemap generation -├── App.tsx # Main app component with routing -├── index.tsx # React entry point -├── index.html # HTML template with Tailwind config -├── server.js # Express production server -├── vite.config.ts # Vite configuration -├── tsconfig.json # TypeScript configuration -├── package.json # Dependencies and scripts -└── Dockerfile # Docker containerization -``` - ---- - -## 📄 Pages & Routes - -### Home (`/`) -The main landing page featuring: -- Animated hero section with tagline: "Where Engineering Meets Intuition" -- Core services overview (Odoo, Custom Software, AI & Automation) -- AI capabilities showcase -- Team introduction -- Call-to-action section - -### Solutions (`/solutions`) -Detailed presentation of three core service offerings: -- **Odoo Solutions** - Enterprise resource planning and workflow automation -- **Custom Software** - Tailored web applications and dashboards -- **AI & Automation** - Applied AI and intelligent workflows - -### Labs (`/labs`) -Experimental projects and technical innovations showcase. - -### Open Source (`/open-source`) -Community-driven projects and open source contributions. - -### Contact (`/contact`) -Contact form with fields: -- Name (required) -- Email (required) -- Phone number (optional) -- Company (optional) -- Message (required) - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Node.js** 18.x or higher -- **npm** or **pnpm** (optional, but recommended) - -### Installation - -1. **Clone the repository** - ```bash - git clone https://github.com/marcelo-m7/monynha.com.git - cd monynha.com - ``` - -2. **Install dependencies** - ```bash - npm install - # or with pnpm - pnpm install - ``` - -3. **Set up environment variables** - - Create a `.env.local` file in the project root: - ```env - RESEND_API_KEY=your_resend_api_key_here - GEMINI_API_KEY=your_gemini_api_key_here - PORT=8080 - ``` - -### Development Setup - -For the contact form and API endpoints to work during development, you need to run **both servers**: - -**Option 1: Quick Development (Single Terminal)** ```bash -# Start both servers concurrently -npm run dev & npm run start +git clone https://github.com/marcelo-m7/Lead-Generator-Form.git +cd Lead-Generator-Form +pnpm install +cp .env.example .env.local ``` -**Option 2: Separate Terminals (Recommended)** - -**Terminal 1: Start the API Server** -```bash -npm start -``` -The Express server will run on `http://localhost:8080` and handle API requests. +Edite `.env.local`: -**Terminal 2: Start the Vite Dev Server** ```bash -npm run dev +VITE_SUPABASE_URL=https://your-project.supabase.co +VITE_SUPABASE_ANON_KEY=your_supabase_anon_key_here ``` -The Vite dev server will run on `http://localhost:3000` with API proxy to localhost:8080. - -> **⚠️ Important**: The contact form requires the API server running on port 8080. If you only run `npm run dev`, the form will show a 405 error. - -### Production Deployment - -1. **Build the application** - ```bash - npm run build - ``` -2. **Start the production server** - ```bash - npm start - ``` - -The production server serves both the built static files AND the API endpoints on port 8080 (or PORT from .env.local). +Suba o app: -> **Note**: Never use `npm run preview` (Vite's preview server) for production as it only serves static files and cannot handle API requests. - -For detailed development setup instructions, see [DEVELOPMENT.md](./DEVELOPMENT.md). - ---- - -## 📦 Available Scripts - -### Development ```bash -npm run dev -``` -Starts the Vite development server with hot module replacement (requires API server running separately for full functionality). - -### Backend (Development & Production) -```bash -npm run start -``` -Starts the Express production server that serves both the API and static assets on port 8080. - -### Build -```bash -npm run build -``` -Builds the production bundle and generates a sitemap using Vite and custom build scripts. - -### Preview -```bash -npm run preview -``` -Serves the production build locally for testing. - ---- - -## 🔌 API Endpoints - -### POST `/api/contact` - -Handles contact form submissions using the Resend email service. - -**Request Body:** -```json -{ - "name": "John Doe", - "email": "john@example.com", - "tel": "+1 (555) 123-4567", - "company": "Acme Inc", - "message": "I'd like to discuss Odoo implementation..." -} -``` - -**Response:** -```json -{ - "success": true, - "message": "Email sent successfully" -} +pnpm dev ``` -**Error Response (400):** -```json -{ - "error": "Missing required fields: name, email, and message are mandatory." -} -``` +O servidor de dev sobe em `http://localhost:3000`. -**Requirements:** -- `name`, `email`, and `message` are required -- Uses `RESEND_API_KEY` environment variable -- Sends email through Resend service +## Secrets do Supabase (obrigatórios no backend) -**Email Template Preview:** +Configure em Supabase Dashboard → Project Settings → Edge Functions → Secrets: -![Contact Form Email Template](docs/email-contect.png) +- `GEMINI_API_KEY` +- `RESEND_API_KEY` +- `RESEND_FROM_EMAIL` +- `MONYNHA_INTERNAL_EMAIL` ---- +Essas chaves são usadas exclusivamente pelas Edge Functions — nunca expostas no `.env` do frontend. -## 🐳 Docker Deployment - -### Build Docker Image -```bash -docker build -t monynha-softwares:latest . -``` +## Scripts -### Run Container ```bash -docker run -p 8080:8080 \ - -e RESEND_API_KEY=your_api_key \ - -e GEMINI_API_KEY=your_gemini_key \ - monynha-softwares:latest -``` - -The Dockerfile uses a two-stage build: -1. **Build Stage**: Compiles TypeScript and React code -2. **Runtime Stage**: Runs the lightweight Node.js server - -The container serves the built application on port 8080. - ---- - -## 🎬 Animation & Interactions - -Leveraging **Framer Motion** for sophisticated animations: - -### Page Transitions -- Smooth entrance animations with fade and scale effects -- Scroll-triggered reveal animations -- Page loader with animated logo and gradient underline - -### Component Animations -- Hero section particle effects and gradients -- Service cards with hover state transformations -- Text animations and reveals -- Decorative blur elements with pulsing effects - -### Best Practices -- Maximum 2-3 animated components per view for performance -- Fallback animations for users with `prefers-reduced-motion` -- Mobile-optimized animations to reduce overhead on smaller devices -- GPU-accelerated transforms for smooth 60fps performance - ---- - -## 🎨 Customization - -### Colors -Modify brand colors in `index.html` within the Tailwind configuration: -```javascript -colors: { - 'brand-black': '#05070a', - 'brand-violet': '#8b5cf6', - 'brand-blue': '#3c83f6', - 'brand-teal': '#0d9488', -} -``` - -### Typography -Adjust fonts in `index.html`: -```html - -``` - -### Global Styles -Edit the ` - - -
-
-

New Studio Signal

-
- -
-
Name / Identity
-
${name}
- -
Email Address
-
${email}
- -
Phone / WhatsApp
-
${tel || 'Not provided'}
- -
Company / Project
-
${company || 'Not provided'}
- -
-
Message Context
-

${message}

-
-
- - -
- - - `, - }), - }); - - const result = await resendResponse.json(); - - if (resendResponse.ok) { - return res.status(200).json({ success: true, id: result.id }); - } else { - console.error('[RESEND ERROR]', result); - return res.status(resendResponse.status).json({ - error: result.message || 'The email service rejected the transmission. Please check the logs.' - }); - } - } catch (error) { - console.error('[INTERNAL ERROR]', error); - return res.status(500).json({ error: 'A critical error occurred while attempting to deliver the signal.' }); - } -} \ No newline at end of file diff --git a/assets/Terci.jpeg b/assets/Terci.jpeg deleted file mode 100644 index f38fdc1..0000000 Binary files a/assets/Terci.jpeg and /dev/null differ diff --git a/assets/base-colors.png b/assets/base-colors.png deleted file mode 100644 index 193e944..0000000 Binary files a/assets/base-colors.png and /dev/null differ diff --git a/assets/favicon.png b/assets/favicon.png deleted file mode 100644 index 1aee8ba..0000000 Binary files a/assets/favicon.png and /dev/null differ diff --git a/assets/logo-favicon.svg b/assets/logo-favicon.svg deleted file mode 100644 index 98edb9b..0000000 --- a/assets/logo-favicon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/assets/marcelo.jpg b/assets/marcelo.jpg deleted file mode 100644 index c9459cc..0000000 Binary files a/assets/marcelo.jpg and /dev/null differ diff --git a/assets/mariana.png b/assets/mariana.png deleted file mode 100644 index 8ca6ae2..0000000 Binary files a/assets/mariana.png and /dev/null differ diff --git a/assets/tercio.jpg b/assets/tercio.jpg deleted file mode 100644 index b3e1d1c..0000000 Binary files a/assets/tercio.jpg and /dev/null differ diff --git a/components/AISection.tsx b/components/AISection.tsx deleted file mode 100644 index 64f46db..0000000 --- a/components/AISection.tsx +++ /dev/null @@ -1,55 +0,0 @@ - -import React from 'react'; -import { motion } from 'framer-motion'; - -export const AISection: React.FC = () => { - return ( -
-
-
- 03 -

AI as a
Collaborator

-
- - - Moving beyond the hype. We integrate intelligent assistants and autonomous workflows that understand context, nuance, and human intent. - - -
- {[ - { - title: "Intelligence", - desc: "RAG architectures that turn your company knowledge into conversational power." - }, - { - title: "Flow", - desc: "Autonomous agents that handle the mundane, so humans can handle the meaningful." - }, - { - title: "Openness", - desc: "Transparent models built on open-source foundations for ethical, long-term scaling." - } - ].map((item, i) => ( - -

{item.title}

-

{item.desc}

-
- ))} -
-
-
- ); -}; diff --git a/components/CTASection.tsx b/components/CTASection.tsx deleted file mode 100644 index 840d312..0000000 --- a/components/CTASection.tsx +++ /dev/null @@ -1,43 +0,0 @@ - -import React from 'react'; -import { motion } from 'framer-motion'; -import { Page } from '../App'; - -interface CTASectionProps { - onNavigate: (page: Page) => void; -} - -export const CTASection: React.FC = ({ onNavigate }) => { - return ( -
- {/* Decorative Geometric Overlay */} -
-
- -
- - Ready to
pulse? -
- -

- Let's build something that matters. No sales pressure, just a conversation about how we can help you grow. -

- - onNavigate('contact')} - className="inline-block px-12 py-8 bg-black text-white font-black text-2xl tracking-widest uppercase transition-all border-4 border-black" - > - Let's Build Meaningful - -
-
- ); -}; diff --git a/components/Footer.tsx b/components/Footer.tsx deleted file mode 100644 index 0046e96..0000000 --- a/components/Footer.tsx +++ /dev/null @@ -1,67 +0,0 @@ - -import React from 'react'; -import { Page } from '../App'; -import { Logo } from './Logo'; - -interface FooterProps { - setPage: (page: Page) => void; -} - -export const Footer: React.FC = ({ setPage }) => { - const currentYear = new Date().getFullYear(); - - return ( -
-
-
-
-
setPage('home')} - className="flex items-center gap-4 cursor-pointer group" - > - - - Monynha - -
-

- A modern and inclusive software studio focused on custom solutions and human-first engineering. -

-

- Portugal (Remote-first) -

-
- -
-
Navigation
-
    -
  • -
  • -
  • -
  • -
-
- -
-
Social Hub
- -
-
- -
- - © {currentYear} Monynha Softwares. Engineering with personality. - - -
-
-
- ); -}; diff --git a/components/Hero.tsx b/components/Hero.tsx deleted file mode 100644 index c83fe6a..0000000 --- a/components/Hero.tsx +++ /dev/null @@ -1,61 +0,0 @@ - -import React from 'react'; -import { motion } from 'framer-motion'; -import { Page } from '../App'; - -interface HeroProps { - onNavigate: (page: Page) => void; -} - -export const Hero: React.FC = ({ onNavigate }) => { - return ( -
- {/* Decorative Elements */} -
-
- - -
- - Human-Centered Automation - -
- -

- Where
- Engineering
- Meets Intuition -

- -
-
-

- We bridge the gap between complex engineering and human intuition. - Building digital products that don't just function — they breathe. -

-
-
- - -
-
-
-
- ); -}; diff --git a/components/Logo.tsx b/components/Logo.tsx deleted file mode 100644 index 0fb7197..0000000 --- a/components/Logo.tsx +++ /dev/null @@ -1,82 +0,0 @@ - -import React from 'react'; -import { motion, Variants } from 'framer-motion'; - -interface LogoProps { - className?: string; - animate?: boolean; - size?: 'sm' | 'md' | 'lg' | 'xl'; -} - -export const Logo: React.FC = ({ className = '', animate = false, size = 'md' }) => { - const sizes = { - sm: 'w-6 h-6', - md: 'w-10 h-10', - lg: 'w-16 h-16', - xl: 'w-32 h-32' - }; - - // Explicitly typing pathVariants to fix "Type 'string' is not assignable to type 'Easing | Easing[]'" error for 'ease' property - const pathVariants: Variants = { - hidden: { pathLength: 0, opacity: 0 }, - visible: { - pathLength: 1, - opacity: 1, - transition: { - pathLength: { duration: 1.5, ease: "easeInOut" }, - opacity: { duration: 0.5 } - } - } - }; - - return ( -
- - - - - - - - - {/* The abstract 'M' shape - fragmented and futuristic */} - - - {/* Decorative dot/pulse element */} - - - - {/* Soft Glow Layer */} - {animate && ( - - )} -
- ); -}; diff --git a/components/Navbar.tsx b/components/Navbar.tsx deleted file mode 100644 index 9076b64..0000000 --- a/components/Navbar.tsx +++ /dev/null @@ -1,238 +0,0 @@ -import React, { useState, useEffect, useCallback } from 'react'; -import { motion, AnimatePresence, Variants } from 'framer-motion'; -import { Page } from '../App'; -import { Logo } from './Logo'; - -interface NavbarProps { - currentPage: Page; - setPage: (page: Page) => void; -} - -export const Navbar: React.FC = ({ currentPage, setPage }) => { - const [isMenuOpen, setIsMenuOpen] = useState(false); - - const navItems: { label: string; value: Page }[] = [ - { label: 'Home', value: 'home' }, - { label: 'Solutions', value: 'solutions' }, - { label: 'Labs', value: 'labs' }, - { label: 'Open Source', value: 'open-source' }, - ]; - - // Lock body scroll when menu is open to prevent background movement - useEffect(() => { - const handleResize = () => { - if (window.innerWidth >= 1024 && isMenuOpen) { - setIsMenuOpen(false); - } - }; - - if (isMenuOpen) { - document.body.style.overflow = 'hidden'; - document.body.style.touchAction = 'none'; // Prevent pull-to-refresh on mobile - } else { - document.body.style.overflow = ''; - document.body.style.touchAction = ''; - } - - window.addEventListener('resize', handleResize); - return () => { - document.body.style.overflow = ''; - document.body.style.touchAction = ''; - window.removeEventListener('resize', handleResize); - }; - }, [isMenuOpen]); - - const handleNavClick = useCallback((page: Page) => { - setPage(page); - setIsMenuOpen(false); - }, [setPage]); - - const toggleMenu = useCallback((e?: React.MouseEvent) => { - e?.stopPropagation(); - setIsMenuOpen(prev => !prev); - }, []); - - // Explicitly typing menuVariants to fix "Type 'number[]' is not assignable to type 'Easing | Easing[]'" for the 'ease' property - const menuVariants: Variants = { - closed: { - opacity: 0, - y: "-100%", - transition: { - duration: 0.4, - ease: [0.32, 0, 0.67, 0], // Accelerated ease-in - when: "afterChildren" - } - }, - open: { - opacity: 1, - y: 0, - transition: { - type: "spring", - damping: 25, - stiffness: 200, - mass: 1, - when: "beforeChildren", - staggerChildren: 0.08 - } - } - }; - - // Explicitly typing itemVariants to fix "Type 'string' is not assignable to type 'AnimationGeneratorType'" for the 'type' property - const itemVariants: Variants = { - closed: { opacity: 0, y: 30, scale: 0.95 }, - open: { - opacity: 1, - y: 0, - scale: 1, - transition: { - type: "spring", - damping: 20, - stiffness: 100 - } - } - }; - - return ( - <> - - - {/* Mobile Menu Overlay */} - - {isMenuOpen && ( - - {/* Clickable Background Overlay to close when tapping empty spaces */} -
setIsMenuOpen(false)} - /> - - {/* Background Accent */} -
- -
-
- - Systems / Menu - -
    - {navItems.map((item) => ( - - - - ))} -
-
- - - - -
-
- Connect - GitHub -
-
- Signal - Email -
-
-
-
- - )} - - - ); -}; \ No newline at end of file diff --git a/components/Services.tsx b/components/Services.tsx deleted file mode 100644 index e2c033e..0000000 --- a/components/Services.tsx +++ /dev/null @@ -1,104 +0,0 @@ - -import React from 'react'; -import { motion } from 'framer-motion'; -import { Page } from '../App'; - -interface ServicesProps { - onNavigate: (page: Page) => void; -} - -export const Services: React.FC = ({ onNavigate }) => { - return ( -
- {/* Odoo Section */} -
-
-
- 01 -
-
- -

Scalability.

-

Precision.

-

Intuition.

-
- -
-

Odoo
Expertise

-

- Transforming enterprise chaos into symphonic clarity. Our custom implementations don't just manage resources—they empower your people to focus on what matters. -

-
- {['ERP Architecture', 'Custom Flows', 'API Sync', 'Live Dashboards'].map(tag => ( - - {tag} - - ))} -
-
-
-
-
- - {/* Custom Systems Section */} -
-
-
- 02 -
-
- - Engineering Personality -

Bespoke
Software

- -
-

- We don't do templates. Every line of code is written to solve your specific cultural and technical challenges. -

-
-
-
- -
-

Internal Tools

-

Optimized for operational speed.

-
-
-
- -
-

Platforms

-

Scalable market solutions.

-
-
-
- -
- -
-
-
-
-
-
- ); -}; diff --git a/components/TeamSection.tsx b/components/TeamSection.tsx deleted file mode 100644 index e3ef435..0000000 --- a/components/TeamSection.tsx +++ /dev/null @@ -1,105 +0,0 @@ - -import React from 'react'; -import { motion } from 'framer-motion'; -import marceloHeadshot from '../assets/marcelo.jpg'; -import tercioHeadshot from '../assets/tercio.jpg'; - -export const TeamSection: React.FC = () => { - const placeholderAvatar = "data:image/svg+xml;utf8,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20400%20400'%3E%3Crect%20width='400'%20height='400'%20fill='%230c0c0c'/%3E%3Ccircle%20cx='200'%20cy='150'%20r='80'%20fill='%232a2a2a'/%3E%3Cpath%20d='M80%20360c20-90%2080-130%20120-130s100%2040%20120%20130'%20fill='%232a2a2a'/%3E%3C/svg%3E"; - const team = [ - { - name: "Marcelo Santos", - role: "Founder · Software Engineer", - image: marceloHeadshot, - bio: "Focuses on automation, applied AI, and full-stack development. Marcelo combines technical depth with a product-oriented mindset.", - links: [ - { label: "LinkedIn", url: "https://www.linkedin.com/in/marcelo-m7/" }, - { label: "GitHub", url: "https://github.com/marcelo-m7" } - ] - }, - { - name: "Tércio Barreto", - role: "Collaborator · Strategy", - image: tercioHeadshot, - bio: "Brings experience in technology strategy and systems thinking, aligning technology with real-world business needs.", - links: [ - { label: "LinkedIn", url: "https://www.linkedin.com/in/t%C3%A9rcio-barreto-40a840120/" } - ] - } - ]; - - return ( -
-
-
- The Humans -

Engineering
Personality

-
- -
- {team.map((member, i) => ( - - {/* Headshot container */} -
- { - const target = event.currentTarget; - if (target.dataset.fallbackApplied) { - return; - } - target.dataset.fallbackApplied = "true"; - target.src = placeholderAvatar; - }} - className="w-full h-full object-cover grayscale group-hover:grayscale-0 group-hover:scale-110 transition-all duration-700" - /> -
-
- -
-
-

{member.name}

-

{member.role}

-

{member.bio}

-
- - -
- - ))} -
-
-
- ); -}; diff --git a/docker/nginx.conf b/docker/nginx.conf new file mode 100644 index 0000000..d6da767 --- /dev/null +++ b/docker/nginx.conf @@ -0,0 +1,16 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location = /health { + return 200 'ok'; + add_header Content-Type text/plain; + } +} diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md deleted file mode 100644 index 7fb61e5..0000000 --- a/docs/DEVELOPMENT.md +++ /dev/null @@ -1,147 +0,0 @@ -# Development Setup Guide - -This guide explains how to properly set up and run Monynha Softwares in development mode with all features working, including the contact form API. - -## Environment Setup - -1. **Create `.env.local` file** in the project root: - ```bash - cp .env.example .env.local - ``` - -2. **Configure environment variables** in `.env.local`: - ```env - RESEND_API_KEY=your_resend_api_key - GEMINI_API_KEY=your_gemini_api_key - PORT=8080 - NODE_ENV=development - ``` - - - Get `RESEND_API_KEY` from [Resend.com](https://resend.com) - - Get `GEMINI_API_KEY` from [Google AI Studio](https://aistudio.google.com) - -## Running in Development - -### Option 1: Two-Terminal Setup (Recommended for full functionality) - -**Terminal 1 - Start the API Server:** -```bash -npm run start -# or with pnpm -pnpm start -``` -The server will run on `http://localhost:8080` and handle `/api/*` requests. - -**Terminal 2 - Start the Vite Dev Server:** -```bash -npm run dev -# or with pnpm -pnpm dev -``` -The Vite dev server will run on `http://localhost:3000` and proxy API requests to the backend. - -### Option 2: Single-Terminal Setup (API calls won't work) - -If you only run: -```bash -npm run dev -``` - -The frontend will work, but API calls (like the contact form) will fail with 404 errors because there's no backend server running. Use Option 1 if you need to test the contact form. - -## What's Fixed - -✅ **Tailwind CSS Production-Ready** -- Removed CDN dependency (`cdn.tailwindcss.com`) -- Installed `tailwindcss`, `postcss`, and `autoprefixer` as dev dependencies -- Created `tailwind.config.js` with brand colors -- Created `postcss.config.js` for PostCSS processing -- CSS is now compiled during build for production - -✅ **API Proxy for Development** -- Vite dev server now proxies `/api/*` requests to the backend -- No more 404 errors when testing contact form -- Automatic logging of proxy requests - -✅ **Better Error Handling** -- ContactView now gracefully handles invalid JSON responses -- Improved error messages for users -- Better console logging for debugging - -## Tailwind CSS Changes - -The project now uses: -- **PostCSS** to compile Tailwind CSS -- **tailwind.config.js** for configuration (instead of inline in HTML) -- **index.css** for Tailwind directives (`@tailwind base; components; utilities;`) - -All custom styles (text-outline, glass, scrollbar) are defined in `index.css`. - -## Building for Production - -```bash -npm run build -``` - -This will: -1. Compile Tailwind CSS to optimized CSS -2. Build React components with Vite -3. Generate sitemap - -Then serve with: -```bash -npm run start -``` - -## Troubleshooting - -### Contact Form Returns 404 -- Make sure the API server is running on port 8080 -- Check that `RESEND_API_KEY` is set in `.env.local` - -### Contact Form Returns 405 (Method Not Allowed) -This happens when: -1. You're using `vite preview` instead of `npm start` for production -2. The API server isn't running or is unreachable -3. The proxy configuration in `vite.config.ts` is incorrect - -**Solution**: Always use `npm start` after building for production. The Express server handles both static files AND API endpoints. - -### JSON Parse Errors in Console -The frontend now handles non-JSON responses gracefully. If you see these errors: -- Check that both servers are running (dev mode) -- Check that `npm start` is running (production mode) -- Verify the API endpoint is accessible at `http://localhost:8080/api/contact` - -### Vite Dev Server Can't Proxy to API -Make sure: -- API server is running on port 8080 (Terminal 1: `npm start`) -- `vite.config.ts` has the proxy configuration: - ```typescript - server: { - proxy: { - '/api': { - target: 'http://localhost:8080', - changeOrigin: true, - } - } - } - ``` -- Check browser DevTools Network tab to confirm proxy is working - -### Tailwind Classes Not Applying -- Run `pnpm install` to ensure PostCSS plugins are installed -- Restart the dev server after installing dependencies -- Check that `index.css` is imported in `index.tsx` - -### API Endpoint Not Working -- Verify Express server is running: `npm run start` -- Check logs in terminal running the server -- Ensure `RESEND_API_KEY` is correctly set - -## Development Scripts - -- `npm run dev` - Start Vite dev server (port 3000) -- `npm run build` - Build for production -- `npm run preview` - Preview production build locally -- `npm run start` - Run Express production server diff --git a/docs/EDGE_FUNCTIONS.md b/docs/EDGE_FUNCTIONS.md new file mode 100644 index 0000000..bc70933 --- /dev/null +++ b/docs/EDGE_FUNCTIONS.md @@ -0,0 +1,197 @@ +# Referência de Edge Functions + +As Edge Functions atuais estão em `supabase/functions/`. + +## Comportamento comum + +- Runtime: Deno +- Métodos HTTP: + - `OPTIONS` para preflight + - `POST` para execução +- CORS: `Access-Control-Allow-Origin: *` +- Configuração de auth em cada `config.toml`: + +```toml +[function] +verify_jwt = false +``` + +## 1) `company-search` + +Arquivo: `supabase/functions/company-search/index.ts` + +### Input + +```json +{ + "query": "Nome da marca", + "website": "https://example.com", + "instagram": "brand_handle", + "linkedin": "https://linkedin.com/company/example" +} +``` + +Pelo menos um desses sinais é obrigatório. + +### Comportamento + +- Normaliza instagram para `@handle`. +- Se `website` existir, faz fetch do HTML com timeout de 4s. +- Extrai `` e `<meta name="description">`. +- Retorna warnings quando o fetch do website falha. + +### Output (sucesso) + +```json +{ + "success": true, + "data": { + "name": "Nome da marca", + "website": "https://example.com", + "instagram": "@brand_handle", + "linkedin": "https://linkedin.com/company/example", + "summary": "Meta description", + "signals": { + "websiteTitle": "Título do site", + "websiteDescription": "Meta description" + }, + "warnings": [] + } +} +``` + +## 2) `generate-diagnosis` + +Arquivo: `supabase/functions/generate-diagnosis/index.ts` + +### Secret obrigatório + +- `GEMINI_API_KEY` + +### Input + +```json +{ + "leadData": { + "email": "lead@example.com", + "brand_name": "Marca", + "no_brand": false, + "revenue_model": "Servico", + "decision_profile": "Faco tudo", + "website": "https://example.com", + "instagram": "@brand", + "linkedin": "https://linkedin.com/company/brand", + "struggle": "Perrengue principal do negócio" + } +} +``` + +(`revenue_model` e `decision_profile` seguem os enums do app.) + +### Comportamento + +- Usa modelo: `gemini-3-flash-preview`. +- Habilita grounding com Google Search (`tools: [{ googleSearch: {} }]`). +- Força schema de resposta JSON com campos: + - `title` + - `description` + - `scores.visibility|conversion|processes` + - `recommendations[]` +- Extrai fontes de grounding dos metadados do candidato. +- Em caso de falha, retorna diagnóstico fallback (ainda com `success: true`, mais `warning: "fallback"`). + +## 3) `send-contact-confirmation` + +Arquivo: `supabase/functions/send-contact-confirmation/index.ts` + +### Secrets obrigatórios + +- `RESEND_API_KEY` +- `RESEND_FROM_EMAIL` (fallback opcional: `hello@monynha.com`) +- `MONYNHA_INTERNAL_EMAIL` (fallback opcional: `hello@monynha.com`) + +### Input + +```json +{ + "contactData": { + "email": "lead@example.com", + "brand_name": "Marca", + "no_brand": false, + "revenue_model": "Serviço", + "decision_profile": "Faço tudo", + "website": "https://example.com", + "instagram": "@brand", + "linkedin": "https://linkedin.com/company/brand", + "struggle": "Perrengue principal" + } +} +``` + +### Comportamento + +- Disparada imediatamente ao receber o submit do wizard, antes do diagnóstico. +- Valida `contactData.email` e `contactData.struggle`. +- Envia dois e-mails com helper de retry (`sendWithRetry`): + - confirmação ao lead + - notificação interna +- Retorna flags `confirmationSent` e `internalSent` para logging granular. +- Sucesso parcial (apenas um dos e-mails enviado) retorna `success: true` com warnings. + +### Output (sucesso) + +```json +{ + "success": true, + "message": "Contact confirmation sent", + "confirmationSent": true, + "internalSent": true +} +``` + +## 4) `send-diagnostic-email` + +Arquivo: `supabase/functions/send-diagnostic-email/index.ts` + +### Secrets obrigatórios + +- `RESEND_API_KEY` +- `RESEND_FROM_EMAIL` (fallback opcional: `hello@monynha.com`) +- `MONYNHA_INTERNAL_EMAIL` (fallback opcional: `hello@monynha.com`) + +### Input + +```json +{ + "leadData": { "email": "lead@example.com", "...": "..." }, + "diagnosis": { "title": "...", "scores": { "visibility": 1, "conversion": 1, "processes": 1 }, "recommendations": [] } +} +``` + +### Comportamento + +- Calcula score/classificação do lead. +- Envia dois e-mails: + - e-mail de diagnóstico ao lead + - e-mail de notificação interna +- Usa helper de retry (`sendWithRetry`). + +## Uso no frontend + +O frontend chama as functions via `supabase.functions.invoke(...)` em: + +- `src/services/companySearchService.ts` +- `src/services/geminiService.ts` +- `src/services/resendService.ts` +- `src/services/contactConfirmationService.ts` + +## Nota operacional + +Como `verify_jwt=false`, esses endpoints não são protegidos por JWT pela config da function. Restrinja a exposição com política de rede e gerenciamento cuidadoso de chaves. + +## Atualização recente (a11y/performance) + +- Modal de time em `AboutSite` agora usa semântica de diálogo (`role="dialog"`, `aria-modal`, foco inicial no botão fechar e fechamento por `Esc`). +- Avatares remotos em componentes visuais receberam `loading="lazy"` e `decoding="async"` para reduzir custo inicial de renderização. +- Ícone decorativo de seleção no wizard recebeu `aria-hidden="true"` para evitar ruído para leitores de tela. + diff --git a/docs/ENVIRONMENT_SETUP.md b/docs/ENVIRONMENT_SETUP.md new file mode 100644 index 0000000..ad28c43 --- /dev/null +++ b/docs/ENVIRONMENT_SETUP.md @@ -0,0 +1,93 @@ +# Setup de Ambiente + +Este guia cobre variáveis de ambiente do frontend, secrets do Supabase e workflow local de functions. + +## 1) Ambiente do frontend + +Crie o arquivo de env local: + +```bash +cp .env.example .env.local +``` + +Defina os valores: + +```bash +VITE_SUPABASE_URL=https://your-project.supabase.co +VITE_SUPABASE_ANON_KEY=your_supabase_anon_key_here +``` + +Essas são as únicas variáveis de runtime do frontend necessárias no código atual. + +## 2) Secrets das Edge Functions (Supabase) + +Configure em Supabase Dashboard → Project Settings → Edge Functions → Secrets: + +- `GEMINI_API_KEY` +- `RESEND_API_KEY` +- `RESEND_FROM_EMAIL` +- `MONYNHA_INTERNAL_EMAIL` + +Alternativa via CLI: + +```bash +supabase secrets set GEMINI_API_KEY=... +supabase secrets set RESEND_API_KEY=... +supabase secrets set RESEND_FROM_EMAIL=hello@monynha.com +supabase secrets set MONYNHA_INTERNAL_EMAIL=team@monynha.com +``` + +## 3) Desenvolvimento local + +Instale e rode o app: + +```bash +pnpm install +pnpm dev +``` + +Porta padrão do Vite: `3000`. + +## 4) Execução local de Edge Functions (opcional) + +A partir da raiz do projeto: + +```bash +supabase functions serve company-search +supabase functions serve generate-diagnosis +supabase functions serve send-contact-confirmation +supabase functions serve send-diagnostic-email +``` + +As configs das functions usam `verify_jwt = false`, então chamadas manuais locais são simples. + +Exemplo de chamada local: + +```bash +curl -i --location --request POST "http://localhost:54321/functions/v1/company-search" \ + --header "Content-Type: application/json" \ + --data '{"query":"Monynha"}' +``` + +## 5) Deploy + +```bash +supabase functions deploy company-search +supabase functions deploy generate-diagnosis +supabase functions deploy send-contact-confirmation +supabase functions deploy send-diagnostic-email +``` + +## Troubleshooting + +- `GEMINI_API_KEY not configured`: secret ausente no projeto Supabase. +- `RESEND_API_KEY not configured`: secret ausente no projeto Supabase. +- Frontend não consegue persistir: verifique `VITE_SUPABASE_URL` e `VITE_SUPABASE_ANON_KEY`. +- CORS do browser: verifique URL da function deployada e headers da requisição. + +## Atualização recente (a11y/performance) + +- Modal de time em `AboutSite` agora usa semântica de diálogo (`role="dialog"`, `aria-modal`, foco inicial no botão fechar e fechamento por `Esc`). +- Avatares remotos em componentes visuais receberam `loading="lazy"` e `decoding="async"` para reduzir custo inicial de renderização. +- Ícone decorativo de seleção no wizard recebeu `aria-hidden="true"` para evitar ruído para leitores de tela. + diff --git "a/docs/MonoDossi\303\252r/Dossi\303\252 Coorporativo/Diretrizes.md" "b/docs/MonoDossi\303\252r/Dossi\303\252 Coorporativo/Diretrizes.md" new file mode 100644 index 0000000..0445609 --- /dev/null +++ "b/docs/MonoDossi\303\252r/Dossi\303\252 Coorporativo/Diretrizes.md" @@ -0,0 +1,108 @@ +**Resumo rápido —** A identidade da **Monynha Softwares** precisa unir dois eixos: (1) **design contemporâneo (shadcn/ui + Tailwind)** para entregar produtos de alto nível, e (2) **manifesto político-social** que celebra a cultura LGBTQIA+ brasileira e a criatividade popular de classes trabalhadoras. Abaixo você encontra um guia completo que amarra esses dois mundos: narrativa de marca, valores, tom de voz, diretrizes visuais (cores + tipos + ícones), acessibilidade, estratégias de inclusão e como aplicar tudo nos seus domínios. + +--- + +## 1 • Narrativa & Manifesto + +### Origem do nome + +* **“Mona”** vem do dialeto *Pajubá*, gíria de resistência usada pela comunidade LGBT no Brasil para se referir de forma afetuosa a outra pessoa — “ei, mona!” ([Wikipédia][1]) +* O sufixo **“-nynha”** dialoga com a prática onomástica popular de grafias criativas (Karolayne, Jhonatan etc.), comuns em camadas sociais de menor renda e vistas como marca de identidade e afirmação ([scispace.com][2]). +* A combinação reforça humildade (“diminutivo”) + orgulho periférico, assumindo a luta contra conservadorismos que tentam padronizar nomes, corpos e vozes. + +### Propósito + +> **“Democratizar tecnologia, combater hipocrisia e dar voz a quem cria fora do padrão.”** + +* **Democratização via open-source:** projetos como **Boteco Pro** e **EcoPool** ficam abertos a contribuições e reduzem barreiras de custo, seguindo a lógica de que ecossistemas abertos aceleram inclusão ([IT Pro][3], [Forbes][4]). +* **Resistência cultural:** manter presença pública mesmo diante de reações conservadoras fortalece representatividade queer no tech — marcas globais que sustentam inclusão, mesmo sob boicotes, ampliam recall e fidelidade ([TIME][5]). + +--- + +## 2 • Valores & Tom de Voz + +| Valor | Como aparece no conteúdo | +| --------------- | ----------------------------------------------------------- | +| **Orgulho** | Linguagem afirmativa, celebra vitórias LGBTQIA+ | +| **Honestidade** | Transparência em roadmap, pricing & dados | +| **Humildade** | Humor autodepreciativo, “fala de boteco” em posts | +| **Resiliência** | Storytelling de erros, P\&D aberto, falhas como aprendizado | +| **Acolhimento** | Tratamento neutro/inclusivo de gênero, feedback seguro | + +**Tom:** claro, didático e próximo (“fala tu, mona!”) — mistura o arquétipo **Creator** com **Everyman**, para inovar sem soar elitista ([Medium][6], [OUT loud][7]). + +--- + +## 3 • Diretrizes Visuais + +### 3.1 Cores + +| Token | HEX Light | HEX Dark | Observação | +| ------------------------ | ----------------------------------------------------------------------- | --------------------------------------- | -------------------- | +| `--primary` | `#7C3AED` | `#C4B5FD` | Violeta jovem (base) | +| `--secondary` | `#0EA5E9` | `#38BDF8` | Azul otimista | +| **Faixa Pride (acento)** | Progress Pride palette (11 cores) ([flagcolorcodes.com][8]) | Usa diagonal de 16 px em CTAs especiais | | +| `--success / --error` | Verde #22C55E / Vermelho #E40303 (cores da bandeira) ([kapwing.com][9]) | | | + +> **Uso estratégico:** a paleta arco-íris aparece em pequenos detalhes (badges, loader, evento). PFLAG recomenda “usar com parcimônia para evitar ruído visual” ([pflag.org][10]). + +### 3.2 Tipografia + +* **Inter** (texto) — alta legibilidade  +* **Space Grotesk** (títulos) — caráter geométrico diferenciado  +* **JetBrains Mono** (código) — reforça foco dev. + Todos pesos revisados para contraste ≥ 4.5:1 conforme WCAG 2.1 ([W3C][11]). + +### 3.3 Componentes shadcn /ui + +* Estender tokens via `/styles/tokens.ts`; suporte nativo descrito na doc ([ui.shadcn.com][12]). +* Botões & cards: `rounded-2xl`, `shadow-md`. +* “Badge Pride” utiliza gradiente Progress Flag, mas fallback sólido em modo high-contrast. + +### 3.4 Acessibilidade & Inclusão + +* Seguir W3C visão “Accessibility + Usability + Inclusion” ([W3C][13]). +* Escrever em linguagem simples, sem gíria exclusiva quando o público for internacional – IxDF define isso como pilar de *inclusive design* ([The Interaction Design Foundation][14]). +* Checklist de conteúdo inclusivo (alt-text, hierarquia, contraste) — ver guia AudioEye ([AudioEye][15]). + +--- + +## 4 • Aplicação nos Domínios + +| Domínio | Identidade específica | +| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **monynha.com** | Hub institucional; hero com gradiente Violeta→Azul + micro-rainbow na logo. | +| **monynha.tech** | Blog técnico; “Badge Open Source” + comentários destacando diversidade de autores. | +| **monynha.store** | Fichas de produto mostram selos “feito por devs queer & periféricos”. | +| **monynha.online** | Dashboard default dark-mode; tokens Pride usados nos gráficos de métrica. | +| **monynha.me** | UI clean; cadastro inclui pronome livre; barra de progresso colorida em Pride. | +| **monynha.website** | Ambiente de demos; banner que explica “por que demos públicas importam para democratização” com link para Forbes/ITPro sobre OSS ([IT Pro][3]). | +| **monynha.pt / .eu** | Conteúdo bilíngue (PT/EN) com ênfase em impacto social na Europa; página “Resistência” cita exemplos internacionais de inclusão de marcas ([brand the change][16]). | + +--- + +## 5 • Conteúdo & Linguagem + +* **Vocabulário-ponte:** quando usar termos de *Pajubá* (ex.: *mona*, *bafón*), ofereça tooltip com significado, educando sem excluir público novo ([Wikipédia][1]). +* **Storytelling de falhas:** publicar *post-mortems* mostrando erros e aprendizados cria confiança — prática recomendada em relatórios de autenticidade de marca ([csrwindo.com][17]). +* **Imagens & ilustrações:** representar corpos racializados, afeminados, não-binários, pessoas com deficiência (Medium/YellowChalk) ([Medium][6]). + +--- + +[1]: https://en.wikipedia.org/wiki/Pajub%C3%A1?utm_source=chatgpt.com "Pajubá" +[2]: https://scispace.com/pdf/analise-fonologica-de-nomes-proprios-de-origem-estrangeira-e-2g5y1uxqf5.pdf?utm_source=chatgpt.com "[PDF] Análise fonológica de nomes próprios de origem ... - SciSpace" +[3]: https://www.itpro.com/technology/artificial-intelligence/open-source-why-open-ecosystems-matter?utm_source=chatgpt.com "Open source: Why open ecosystems matter" +[4]: https://www.forbes.com/sites/laurencebradford/2018/03/26/how-open-source-development-is-democratizing-the-tech-industry/?utm_source=chatgpt.com "How Open-Source Development Is Democratizing The Tech Industry" +[5]: https://time.com/6269728/trans_representation_nike-budlight-backlash/?utm_source=chatgpt.com "From Bud Light to Nike, Brands Are Facing Conservative Backlash for Featuring Trans People. Why They're Sticking to Their Decisions" +[6]: https://yellowchalkuiux.medium.com/designing-with-pride-inclusive-design-experiences-for-all-efc18b4c35b?utm_source=chatgpt.com "Designing with Pride: Inclusive Design Experiences for All" +[7]: https://outloud.lgbt/case-studies/?utm_source=chatgpt.com "LGBT Inclusive Marketing Case Studies - OUT loud" +[8]: https://www.flagcolorcodes.com/progress-pride?utm_source=chatgpt.com "Progress Pride Flag Color Codes with HEX, RGB, CMYK & Pantone" +[9]: https://www.kapwing.com/resources/official-pride-colors-2021-exact-color-codes-for-15-pride-flags/?utm_source=chatgpt.com "Official Pride Colors 2025: Exact Color Codes for 15 Pride Flags" +[10]: https://pflag.org/wp-content/uploads/2023/01/PFLAG-BrandGuide-National-2024.pdf?utm_source=chatgpt.com "[PDF] Brand Style Guide | PFLAG" +[11]: https://www.w3.org/TR/WCAG21/?utm_source=chatgpt.com "Web Content Accessibility Guidelines (WCAG) 2.1 - W3C" +[12]: https://ui.shadcn.com/docs/theming?utm_source=chatgpt.com "Theming - shadcn/ui" +[13]: https://www.w3.org/WAI/fundamentals/accessibility-usability-inclusion/?utm_source=chatgpt.com "Accessibility, Usability, and Inclusion - W3C" +[14]: https://www.interaction-design.org/literature/topics/inclusive-design?srsltid=AfmBOooBP7IGdnknJg0SUBm-SeTT6eImBOwjVPFTObkP_jyGUVdGKC1L&utm_source=chatgpt.com "What is Inclusive Design? — updated 2025 | IxDF" +[15]: https://www.audioeye.com/post/9-ways-to-design-inclusive-content/?utm_source=chatgpt.com "9 Ways to Design Inclusive Content - AudioEye" +[16]: https://brandthechange.org/blog/pride-amsterdam-lgbt-brand-case-study?srsltid=AfmBOoo_gC3qcyui7eV3-QcFKCtqmHKA7GYhPubaRPxT70jTO1K6y0IQ&utm_source=chatgpt.com "New in the library: the Pride Amsterdam Brand Case Study 2024" +[17]: https://csrwindo.com/insights-new/from-ad-to-action/?utm_source=chatgpt.com "From Ad to Action: LGBTQ+ Brand Authenticity Examined - Windō" diff --git "a/docs/MonoDossi\303\252r/Dossi\303\252 Coorporativo/Identidade Visual.md" "b/docs/MonoDossi\303\252r/Dossi\303\252 Coorporativo/Identidade Visual.md" new file mode 100644 index 0000000..4cd9a88 --- /dev/null +++ "b/docs/MonoDossi\303\252r/Dossi\303\252 Coorporativo/Identidade Visual.md" @@ -0,0 +1,65 @@ +## 📌 Identidade Visual da Monynha Softwares + +### 🎯 Conceito + +Monynha é mais que software: é resistência, orgulho e democratização tecnológica. Sua identidade celebra diversidade, cultura LGBTQIA+ e origens periféricas brasileiras. A marca dialoga diretamente com comunidades sub-representadas, promovendo tecnologia aberta e acessível a todos. + +### 🌈 Valores Fundamentais + +* **Orgulho**: Celebrar abertamente identidades diversas. +* **Honestidade**: Transparência total em processos e comunicação. +* **Humildade**: Reconhecer limitações e aprender com erros. +* **Inclusão**: Promover acessibilidade e respeito às diferenças. +* **Resiliência**: Resistir às adversidades sociais e tecnológicas. + +### 🎨 Paleta de Cores + +* **Primária:** Violeta (`#7C3AED` claro / `#C4B5FD` escuro) +* **Secundária:** Azul Sky (`#0EA5E9` claro / `#38BDF8` escuro) +* **Cores Complementares:** + + * Sucesso: Verde (`#22C55E`) + * Erro: Vermelho (`#E40303`) +* **Detalhe Especial:** Progress Pride Flag (utilização pontual em detalhes visuais para destaque) + +### 🔤 Tipografia + +* **Títulos:** Space Grotesk (Geometria moderna, força criativa) +* **Corpo de Texto:** Inter (Legibilidade e clareza técnica) +* **Código:** JetBrains Mono (Identificação com desenvolvedores) + +### 🖥️ Componentes e UI + +* **Base**: Shadcn/ui com Tailwind CSS. +* **Customizações essenciais:** + + * Botões e Cards com bordas arredondadas (`rounded-2xl`). + * Elementos gráficos sutis com Progress Pride Flag (badges, loaders). + +### 📣 Tom de Voz e Linguagem + +* **Tom:** Amigável, claro, próximo e acessível ("Fala tu, mona!"). +* **Vocabulário:** Uso seletivo e educativo do Pajubá ("mona") com explicação inclusiva. +* **Linguagem Inclusiva:** Sempre respeitando gênero e diversidade de expressão. + +### 🌐 Aplicações em Domínios + +* **monynha.com:** Institucional, destaque visual de orgulho LGBTQIA+. +* **monynha.tech:** Foco técnico, divulgação inclusiva de projetos open-source. +* **monynha.store:** Produtos inclusivos e selo de diversidade. +* **monynha.online:** Dashboard acessível, dark-mode padrão e gráficos inclusivos. +* **monynha.me:** Perfis e gestão de contas com ênfase em inclusão. +* **monynha.website:** Demonstrações abertas, reforçando democratização tecnológica. + +### ♿ Acessibilidade e Inclusão + +* Contrastes visuais adequados conforme WCAG. +* Linguagem acessível e tradução contextual para inclusão total. +* Imagens e ilustrações que refletem diversidade real e interseccional. + +### 🚩 Compromissos da Marca + +* Promover conteúdos e ações inclusivas regularmente. +* Transparência nas ações e posturas públicas. +* Lutar ativamente por diversidade e equidade social, cultural e tecnológica. + diff --git "a/docs/MonoDossi\303\252r/Dossi\303\252 Coorporativo/Monynha Softwares.xlsx" "b/docs/MonoDossi\303\252r/Dossi\303\252 Coorporativo/Monynha Softwares.xlsx" new file mode 100644 index 0000000..269a815 Binary files /dev/null and "b/docs/MonoDossi\303\252r/Dossi\303\252 Coorporativo/Monynha Softwares.xlsx" differ diff --git "a/docs/MonoDossi\303\252r/Dossi\303\252 Coorporativo/Sum\303\241rio.md" "b/docs/MonoDossi\303\252r/Dossi\303\252 Coorporativo/Sum\303\241rio.md" new file mode 100644 index 0000000..a5d0117 --- /dev/null +++ "b/docs/MonoDossi\303\252r/Dossi\303\252 Coorporativo/Sum\303\241rio.md" @@ -0,0 +1,68 @@ +**Monynha Softwares — Global Impact & Brand Dossier 2025** + +## 1 • Resume + +Blueprint / **“mega-dossier”**, **(2) o que entra em cada volume** e **(3) nomes sugeridos para os documentos**, tirando inspiração das peças oficiais que essas empresas disponibilizam publicamente (brand books, ESG reports, resource centers, etc.). + +--- + +## 2 • Arquitetura do dossiê + +| **Volume** | **Objetivo** | **Paralelo de referência** | +| ----------------------------------------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| **V01 – Company Profile & Vision** | História, propósito (“democratizar tecnologia queer-periférica”), timeline e mapa de domínios | Coca-Cola “Company at a Glance” secção ([coca-colacompany.com][1]) | +| **V02 – Brand Manifesto** | Narrativa “mona + -nynha”: origem linguística, missão social | Nestlé “Purpose & Values” nas Corporate Business Principles ([nestle.com][5]) | +| **V03 – Visual Identity System** | Paleta, tipografias, grids, componentes shadcn; uso de faixa Progress Pride | Coca-Cola Brand Identity & Design Standards ([training.gattosulweb.com][4]) ; Google Material Design ([Material Design][6]) | +| **V04 – Voice & Copy Guide** | Termos de Pajubá, pronomes neutros, tom “amigona de boteco” | Exemplos de “Voice & Tone” em brand books de Slack / Uber (listas comparativas) ([Creative Soup][7]) | +| **V05 – Product & Platform Portfolio** | Visão geral de Boteco Pro, EcoPool, Facodi Digital, etc. | Google “Products & Services” cards ([About Google][3]) | +| **V06 – Open-Source & Community Impact Report** | Métricas GitHub, programa de mentoria, cases de contribuidores periféricos | Relatórios de impacto OSS citados em Content Harmony ([Content Harmony][8]) | +| **V07 – ESG & Diversity Report** | Metas de CO₂, inclusão LGBTQIA+, acessibilidade — seguindo GRI | iFood FY23 Sustainability Report ([iFood - Institucional][9]) ; Nestlé CSV 2023 ([nestle.com][10]) | +| **V08 – Governance & Compliance Handbook** | Código de Conduta, ética, LGPD / GDPR | Nestlé Corporate Business Principles ([nestle.com][5]) | +| **V09 – Tech Stack & Architecture White-paper** | Infra AWS/Edge, micro-frontends shadcn, tokens Tailwind | Google “Guidance” + Material 3 docs ([Material Design][6], [Material Design][11]) | +| **V10 – Accessibility & Inclusive-Design Guidelines** | WCAG 2.2 + best practices de contraste e linguagem | Direcionadas por exemplos na Frontify (19 guides) ([frontify.com][12]) | +| **V11 – Press & Media Kit** | Logos (svg/png), fotos equipe, releases, Q\&A | Google “Press Resources” layout ([About Google][3]) | +| **V12 – Case Studies & Impact Stories** | Histórias de devs e clientes periféricos; dados de ROI social | Coca-Cola 2022 case boxes em Sustainability Report ([coca-colacompany.com][1]) | + +--- + +## 3 • Nomes sugeridos para os documentos (exemplos de arquivo) + +| **Arquivo** | **Tipo** | **Obs.** | +| ------------------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------- | +| `Monynha_Profile_2025.pdf` | Brochura corporativa | Equivalente ao “At a Glance” da Coca-Cola([coca-colacompany.com][1]) | +| `Manifesto_Monynha_Orgulho&Diversidade.pdf` | Texto manifesto | Inspirado em brand books de grandes marcas (Relais & Châteaux) ([BB\&Co Strategic Storytelling][13]) | +| `Visual_Identity_System_v1.0.pdf` | Guia de identidade | Espelha “Brand Identity & Design Standards” Coca-Cola ([training.gattosulweb.com][4]) | +| `Tone_of_Voice_Guide.md` | Manual de escrita | Formato markdown para integração no monorepo | +| `Product_Portfolio_2025.pptx` | Deck comercial | Slides comparáveis aos kits da Nestlé CSV ([nestle.com][10]) | +| `OpenSource_Impact_Report_2025.pdf` | Relatório | Estrutura inspirada em exemplos de GitHub OSS impact ([Content Harmony][8]) | +| `ESG&Diversity_Report_2025.pdf` | Relatório GRI | Benchmark: iFood ESG ([iFood - Institucional][9]) | +| `Governance_Handbook.pdf` | Manual de compliance | Baseado no Nestlé Principles ([nestle.com][5]) | +| `Tech_Architecture_Whitepaper.pdf` | Documento técnico | Layout estilo Google white-papers ([Material Design][6]) | +| `Inclusive_Design_Guidelines.pdf` | Guia acessibilidade | Adoção de frameworks listados pela Frontify ([frontify.com][12]) | +| `PressKit_Assets.zip` | Pacote | Logos, mockups; análogo ao pacote Coca-Cola design ([www.slideshare.net][14]) | +| `Case_Studies_2025.pdf` | Book de casos | Narrativas no modelo Coca-Cola sustainability stories ([coca-colacompany.com][1]) | + +--- + +### Por que esse modelo funciona + +1. **Alinha-se a padrões globais**: grandes empresas separam identidade visual, governança e sustentabilidade em volumes distintos — ver Coca-Cola ([training.gattosulweb.com][4], [coca-colacompany.com][1]), Nestlé ([nestle.com][5], [nestle.com][10]), iFood ([iFood - Institucional][9]). +2. **Facilita atualização**: cada volume pode ganhar nova versão anual (v2.0, v3.0), como faz o Material Design ([Material Design][6]). +3. **Suporta públicos diferentes** (equipe, imprensa, investidores, devs). + +Com esse esqueleto nomeado, você pode começar pelo **V03 — Visual Identity System** (já rascunhado) ou montar a página-hub do dossiê. Me diga o volume prioritário e sigo desenvolvendo! + +[1]: https://www.coca-colacompany.com/content/dam/company/us/en/reports/coca-cola-business-sustainability-report-2022.pdf?utm_source=chatgpt.com "[PDF] The Coca-Cola Company 2022 Business & Sustainability Report" +[2]: https://about.google/brand-resource-center/?utm_source=chatgpt.com "Brand Resource Center - About Google" +[3]: https://about.google/brand-resource-center/ "Brand Resource Center" +[4]: https://training.gattosulweb.com/pluginfile.php/720/mod_resource/content/2/styleguide-coca-cola.pdf?utm_source=chatgpt.com "[PDF] Coca-Cola Zero Brand Identity and Design Standards" +[5]: https://www.nestle.com/sites/default/files/asset-library/documents/library/documents/corporate_governance/corporate-business-principles-en.pdf?utm_source=chatgpt.com "[PDF] Corporate Business Principles - Nestlé" +[6]: https://m2.material.io/design/guidelines-overview?utm_source=chatgpt.com "Guidelines - Material Design" +[7]: https://creativesoup.io/blogs/news/brand-guidelines-documents-pdf-free-download?utm_source=chatgpt.com "20 Famous Free Brand Guidelines Examples Ready For Download" +[8]: https://www.contentharmony.com/blog/great-brand-guidelines/?utm_source=chatgpt.com "36 Great Brand Guidelines Examples - Content Harmony" +[9]: https://institucional.ifood.com.br/wp-content/uploads/2024/09/iFood-Sustainability-Report-EN-FY23-Apr_22-to-Mar_23-1.pdf?utm_source=chatgpt.com "[PDF] FY23 Sustainability Report FISCAL YEAR FROM APRIL ... - iFood" +[10]: https://www.nestle.com/sites/default/files/2024-02/creating-shared-value-sustainability-report-2023-en.pdf?utm_source=chatgpt.com "[PDF] Nestlé Creating Shared Value and Sustainability Report 2023" +[11]: https://m3.material.io/?utm_source=chatgpt.com "Material Design 3 - Google's latest open source design system" +[12]: https://www.frontify.com/en/guide/brand-guidelines-examples?utm_source=chatgpt.com "19 brand guidelines that experts love - Frontify" +[13]: https://bbcostorytelling.com/wp-content/uploads/2016/05/RC_BrandBook_ENGLISH.pdf?utm_source=chatgpt.com "[PDF] BRAND BOOK - BB&Co Strategic Storytelling" +[14]: https://www.slideshare.net/slideshow/cocacola2020pdf/258067842?utm_source=chatgpt.com "Coca-Cola-2020.pdf" diff --git "a/docs/MonoDossi\303\252r/Resumo.md" "b/docs/MonoDossi\303\252r/Resumo.md" new file mode 100644 index 0000000..610de1e --- /dev/null +++ "b/docs/MonoDossi\303\252r/Resumo.md" @@ -0,0 +1,116 @@ +Aqui está uma sugestão estratégica para o **dossier institucional da Monynha Softwares**, inspirada nos modelos utilizados por grandes marcas globais como Google, iFood e Coca‑Cola, mas adaptada à narrativa e ao propósito da Monynha: + +--- + +## 📘 Nome do Dossier + +* **Monynha Softwares – Brand & Impact Book** +* **Monynha Dossier Institucional: Identidade e Impacto Social** +* **Monynha Brand & Values Dossier** + +Escolha que ressalta tanto a dimensão de design quanto o compromisso social e político da empresa. + +--- + +## Estrutura sugerida do Dossier + +1. **Capa & Sumário** + + * Logo, tagline (“Democratizar tecnologia com orgulho”), versão textual do índice. + +2. **Visão & Propósito** + + * Missão, visão e valores (diversidade, democratização, resistência). + * Origem do nome (“mona” + “-nynha”), contextualização histórico-cultural. + +3. **Posicionamento de Marca** + + * Persona da marca (Creator + Everyman consigo de linguagem inclusiva). + * Público‑alvo e personas chave (de periféricos, LGBTQIA+, devs de código aberto, etc.). ([blog.hubspot.com][1], [Studio Noel][2]) + +4. **Tom de Voz & Narrativa** + + * Diretrizes de linguagem (ex.: “mona”, linguagem educativa). + * Voz de manifesto — exemplos de frases e posts. + +5. **Identidade Visual** + + * Logo (com variantes – full, ícone, pride overlay). + * Paleta de cores (primária, secundária, Pride, estados; explicações de contraste WCAG) ([MasterClass][3], [Shopify][4]) + * Tipografia (Inter, Space Grotesk, JetBrains Mono) e diretrizes de uso. + * Ícones e ilustrações (Lucide + diversidade na comunicação visual). + +6. **Componentes UI e Tokens** + + * Exemplo de botão, cards, badges adaptados shadcn/ui. + * Arredondos, sombras, states, light/dark mode. + * Layout geral de tokens (tokens.ts + tailwind.config.js). + +7. **Aplicação por Domínio** + + * Como cada domínio expressa a marca (monynha.tech, .store, .online, etc.), conforme estrutura anterior. + +8. **Projetos & Open Source** + + * Visão geral dos projetos no GitHub (Boteco PRO, EcoPool, Barnostri, etc.) + * Estatísticas de contribuição, tecnologias usadas, versão social/educativa desses projetos médias. ([frontify.com][5], [Imagine Hub][6], [lairedigital.com][7]) + +9. **Impacto Social & Cultural** + + * Ações inclusivas (ex: Boteco Pride lives, part. em eventos). + * Testemunhos / depoimentos da comunidade. + +10. **Boas-práticas & Dos-and-Don'ts** + + * Exemplos visuais: uso correto / incorreto de logo, cores, legenda com Pride. + * Aplicação correta de pronome, alt-text e linguagem. + +11. **Assets & Recursos** + + * Links para download (logos, fontes, tokens). + * Templates (PowerPoint, redes sociais, email signatures, swag). ([frontify.com][5], [lairedigital.com][7]) + +12. **Contato & Atualizações** + + * Equipe responsável, contatos, repositório central (monynha-brand). + * Processo de atualização e versão do dossier. + +--- + +## Principais documentos que compõem o Dossiê (nome e formato) + +| Documento | Formato | Conteúdo resumido | +| ------------------------ | ------------------ | --------------------------------------------- | +| Brand & Impact Book | PDF (& versão web) | Documento principal com visão, design e valor | +| Brand Style Guide | PDF + Figma Kit | Paletas, tipografia, tokens, UI components | +| Brand Kit / Asset Pack | Zip com assets | Logos, ilustrações, ícones, fontes | +| GitHub Manifesto | Markdown | Origem do nome, manifesto social-político | +| Tone & Voice Guide | PDF ou MD | Exemplos de linguagem, tom e gírias | +| Dos & Don’ts Guide | PDF + slides | Exemplos gráficos de uso adequado/equivocado | +| Project Portfolio Deck | PPTX / Keynote | Cases open-source (Boteco, EcoPool…) | +| Social Impact Report | PDF curto | Impacto, depoimentos, métricas | +| Email Signature Template | HTML + instruções | Completo padrão para equipe | + +--- + +**Referências & boas práticas:** + +* Estrutura inspirada em brand guides como o do HubSpot, Shopify e Marq ([blog.hubspot.com][1], [Canva][8], [manypixels.co][9], [Looka][10], [Shopify][11], [Wikipédia][12], [lairedigital.com][7]) +* Abordagem leve e prática, como visto em Skype, Slack e Dropbox ([manypixels.co][9], [Marq][13], [frontify.com][5]) +* Inclusão de templates e swag para reforçar consistência ([lairedigital.com][7]) + +--- + +[1]: https://blog.hubspot.com/marketing/examples-brand-style-guides?utm_source=chatgpt.com "25 brand style guide examples I love (for visual inspiration)" +[2]: https://studionoel.co.uk/elements-of-brand-guidelines?utm_source=chatgpt.com "The 6 Elements Which Every Brand Guideline Should Have" +[3]: https://www.masterclass.com/articles/how-to-create-a-brand-guide?utm_source=chatgpt.com "How to Create a Brand Guide: 6 Components of a Brand Guide - 2025" +[4]: https://www.shopify.com/blog/brand-guidelines?utm_source=chatgpt.com "How To Create Brand Guidelines: Brand Style Guide Template" +[5]: https://www.frontify.com/en/guide/brand-guidelines-examples?utm_source=chatgpt.com "19 brand guidelines that experts love - Frontify" +[6]: https://imagine-hub.com/en/blog/how-to-create-a-company-dossier/?utm_source=chatgpt.com "5 Steps on How to Create a Company Dossier - Imagine Hub" +[7]: https://www.lairedigital.com/blog/key-elements-to-include-in-your-brand-guide?utm_source=chatgpt.com "Key Elements to Include in Your Brand Guide" +[8]: https://www.canva.com/learn/50-meticulous-style-guides-every-startup-see-launching/?utm_source=chatgpt.com "50 of the best brand style guides to inspire you - Canva" +[9]: https://www.manypixels.co/blog/brand-design/brand-guides?utm_source=chatgpt.com "15 Amazing Brand Guide Examples - ManyPixels" +[10]: https://looka.com/blog/15-brand-guidelines-examples-to-inspire-your-brand-guide/?utm_source=chatgpt.com "28 Brand Guidelines Examples to Inspire Your Brand Guide - Looka" +[11]: https://www.shopify.com/blog/branding-package?utm_source=chatgpt.com "Branding Package: What to Include, Costs, and Examples - Shopify" +[12]: https://en.wikipedia.org/wiki/Brand?utm_source=chatgpt.com "Brand" +[13]: https://www.marq.com/blog/10-examples-of-great-brand-guidelines?utm_source=chatgpt.com "8 Examples of Great Brand Guidelines - And How They Can Inspire ..." diff --git a/docs/Unified Brand and Technical Specification for Monynha.com.pdf "b/docs/MonoDossi\303\252r/Unified Brand and Technical Specification for Monynha.com.pdf" similarity index 100% rename from docs/Unified Brand and Technical Specification for Monynha.com.pdf rename to "docs/MonoDossi\303\252r/Unified Brand and Technical Specification for Monynha.com.pdf" diff --git "a/docs/Monynha Softwares \342\200\223 Dossi\303\252 Institucional de Identidade e Impacto.pdf" "b/docs/Monynha Softwares \342\200\223 Dossi\303\252 Institucional de Identidade e Impacto.pdf" deleted file mode 100644 index d72350d..0000000 Binary files "a/docs/Monynha Softwares \342\200\223 Dossi\303\252 Institucional de Identidade e Impacto.pdf" and /dev/null differ diff --git a/docs/REACTBITS_INTEGRATION.md b/docs/REACTBITS_INTEGRATION.md deleted file mode 100644 index 5786096..0000000 --- a/docs/REACTBITS_INTEGRATION.md +++ /dev/null @@ -1,369 +0,0 @@ -# React Bits Integration Documentation - -This document provides a comprehensive overview of how React Bits components are integrated into the Monynha Softwares corporate website. - -## Overview - -React Bits is a library of animated components that offers backgrounds, interactive cards, animated menus, and text effects. This project uses a curated selection of React Bits components to create an immersive and engaging user experience while maintaining excellent performance and accessibility. - -## Performance Guidelines - -Following React Bits best practices: -- **Maximum 2-3 components per page** to preserve performance -- **Fallback alternatives** for `prefers-reduced-motion` users -- **Mobile optimizations** to reduce animation overhead on smaller devices - -## Components Catalog - -### Background Components - -#### 1. LiquidEtherBackground -**Location:** `src/components/reactbits/LiquidEtherBackground.tsx` - -**Usage:** -- **Home Page Hero** - Main background animation - -**Features:** -- WebGL-based fluid animation -- Purple/blue gradient matching brand colors -- Automatic fallback to static gradient for `prefers-reduced-motion` -- Optimized rendering with Three.js - -**Props:** -```typescript -// Uses default configuration, no props needed -<LiquidEtherBackground /> -``` - -#### 2. RippleGridBackground -**Location:** `src/components/reactbits/RippleGridBackground.tsx` - -**Usage:** -- **Contact Page** - Background behind contact form - -**Features:** -- Animated grid with ripple effects -- Subtle and non-distracting -- Complements form content - -### Text Animation Components - -#### 3. SplitText -**Location:** `src/components/reactbits/SplitText.tsx` - -**Usage:** -- **Home Page** - Main hero title "Monynha Softwares / Inclusive tech that empowers" - -**Features:** -- Word-by-word text reveal. -- Stagger delay for smooth animation -- Configurable tag (h1, h2, etc.) - -**Props Example:** -```typescript -<SplitText - as="h1" - text={["Monynha Softwares", "Inclusive tech that empowers"].join("\n")} - className="mb-6 text-[clamp(2.25rem,8vw,3.75rem)] font-bold leading-[1.1] break-words text-balance items-center" -/> -``` - -#### 4. TextType -**Location:** `src/components/reactbits/TextType.tsx` - -**Usage:** -- **About Page** - Biography paragraphs - -**Features:** -- Typewriter effect -- Configurable delay and speed -- Multiple instances can run with different delays - -**Props Example:** -```typescript -<TextType - className="text-[clamp(1rem,3.3vw,1.1rem)] leading-relaxed" - text="I'm a digital artist and creative developer..." - delay={0} -/> -``` - -### Card Components - -#### 5. PixelCard -**Location:** `src/components/reactbits/PixelCard.tsx` - -**Usage:** -- **Home Page** - Featured repositories grid -- **Repositories Page** - Individual repository cards - -**Features:** -- Pixelated hover effect -- Image display with title/subtitle -- Optional footer content -- Mobile-friendly with `noFocus` prop - -**Props Example:** -```typescript -<PixelCard - imageUrl={repo.imageUrl} - title={repo.name} - subtitle={repo.description ?? "No description provided."} - footer={<span className="text-sm">{repo.language}</span>} -/> -``` - -### Gallery Components - -#### 6. RollingGallery -**Location:** `src/components/reactbits/RollingGallery.tsx` - -**Usage:** -- Optional horizontal carousel for future highlights (currently not used in any page) - -**Features:** -- Smooth horizontal scrolling -- Configurable speed -- Responsive item sizing -- Supports title, subtitle, and footer for each item - -**Props Example:** -```typescript -<RollingGallery - items={featured.map((item) => ({ - id: item.id, - title: item.name, - subtitle: item.subtitle, - imageUrl: item.imageUrl, - href: item.href, - }))} - speed={24} -/> -``` - -#### 7. SpotlightCard -**Location:** `src/components/reactbits/SpotlightCard.tsx` - -**Usage:** -- Optional highlight cards for future landing sections (currently not used in any page) - -**Features:** -- Spotlight effect following cursor -- Interactive hover states -- Customizable spotlight color - -**Props Example:** -```typescript -<SpotlightCard className="bg-surface-3/90 p-6 sm:p-8"> - <div className="flex flex-col gap-3"> - <div className="inline-flex h-14 w-14 items-center justify-center rounded-2xl bg-primary/10"> - <Sparkles className="h-7 w-7" /> - </div> - <h3>Software Development</h3> - <p>Building robust, scalable applications</p> - </div> -</SpotlightCard> -``` - -### Navigation Components - -#### 8. GooeyNav -**Location:** `src/components/reactbits/GooeyNav.tsx` - -**Usage:** -- **Navigation Component** - Main site navigation (desktop and mobile) -- Wrapped in `src/components/Navigation.tsx` - -**Features:** -- Gooey morphing effect between states -- Responsive mobile hamburger menu -- Keyboard navigation support -- Focus trap for accessibility -- Integration with FlowingMenu for mobile drawer - -**Key Features:** -- Desktop: Horizontal navigation bar with animated hover states -- Mobile: Hamburger menu opening FlowingMenu drawer -- Accessibility: Full keyboard navigation, ARIA labels, focus management - -#### 9. FlowingMenu -**Location:** `src/components/reactbits/FlowingMenu.tsx` - -**Usage:** -- **GooeyNav Mobile Menu** - Used as the mobile drawer menu - -**Features:** -- Animated marquee on hover -- Directional entrance/exit animations based on cursor position -- Active state highlighting -- GSAP-powered smooth animations -- Reduced motion support - -### UI Enhancement Components - -#### 10. GlassIcon -**Location:** `src/components/reactbits/GlassIcon.tsx` - -**Usage:** -- **Contact Page** - Email and Instagram contact cards -- **Repository Detail Page** - Repository metadata display (stars, forks, language, etc.) - -**Features:** -- Glassmorphism effect -- Icon with title and description -- Optional href for links -- Hover animations - -**Props Example:** -```typescript -<GlassIcon - icon={<Mail className="h-6 w-6" />} - title="Email" - description="contact@monynha.com" - href="mailto:contact@monynha.com" -/> -``` - -#### 11. StepperTimeline -**Location:** `src/components/reactbits/StepperTimeline.tsx` - -**Usage:** -- **About Page** - Experience and timeline section - -**Features:** -- Vertical timeline with indicators -- Step titles, subtitles, and descriptions -- Progress line connecting steps -- Responsive layout - -**Props Example:** -```typescript -<StepperTimeline - steps={experiences.map((ex) => ({ - title: ex.role, - subtitle: `${ex.organization} · ${ex.location}`, - description: ex.highlights.join(' • '), - indicator: ex.year.toString(), - }))} -/> -``` - -## Page-by-Page Breakdown - -### Home Page (`src/pages/Home.tsx`) -**React Bits Components Used: 3** -1. **LiquidEtherBackground** - Hero background -2. **SplitText** - Main title animation -3. **PixelCard** - Featured repository cards - -**Performance:** Within 2-3 component guideline (background + text + cards count as 3) - -### About Page (`src/pages/About.tsx`) -**React Bits Components Used: 2** -1. **TextType** - Biography text (multiple instances) -2. **StepperTimeline** - Experience timeline - -**Performance:** Within guideline - -### Contact Page (`src/pages/Contact.tsx`) -**React Bits Components Used: 2** -1. **RippleGridBackground** - Form background -2. **GlassIcon** - Contact method cards - -**Performance:** Within guideline - -### Repositories Page (`src/pages/Repositories.tsx`) -**React Bits Components Used: 1** -1. **PixelCard** - Repository list items - -**Performance:** Well within guideline - -### Repository Detail Page (`src/pages/RepositoryDetail.tsx`) -**React Bits Components Used: 1** -1. **GlassIcon** - Repository metadata display (stars, forks, language, etc.) - -**Performance:** Well within guideline - -### Navigation (All Pages) -**React Bits Components Used: 2** -1. **GooeyNav** - Main navigation component -2. **FlowingMenu** - Mobile menu drawer (nested in GooeyNav) - -**Performance:** Shared across all pages, optimized for performance - -## Accessibility Features - -All React Bits components in this project include: - -1. **Reduced Motion Support** - - Check for `prefers-reduced-motion` media query - - Provide static fallbacks - - Example: LiquidEtherBackground shows static gradient - -2. **Keyboard Navigation** - - All interactive components support keyboard - - Focus indicators visible - - Tab order logical - -3. **ARIA Labels** - - Proper labeling for screen readers - - Role attributes where appropriate - - Semantic HTML structure - -4. **Color Contrast** - - Meets WCAG AA standards - - Text readable against animated backgrounds - - Focus states clearly visible - -## Mobile Optimizations - -1. **Touch-friendly targets** - All interactive elements minimum 44x44px -2. **Reduced animations** - Some effects disabled on mobile for performance -3. **Responsive layouts** - All components adapt to smaller screens -4. **Performance monitoring** - Animation frames optimized for 60fps - -## Development Guidelines - -### Adding New React Bits Components - -1. **Check the 2-3 component limit per page** -2. **Add reduced motion fallback**: - ```typescript - const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches; - if (prefersReducedMotion) { - return <StaticFallback />; - } - ``` -3. **Test on mobile devices** -4. **Document in this file** - -### Testing Checklist - -- [ ] Works with keyboard navigation -- [ ] Respects `prefers-reduced-motion` -- [ ] Performs well on mobile (60fps) -- [ ] No console errors or warnings -- [ ] Accessible to screen readers - -## Future Enhancements - -Potential React Bits components to consider: - -- **Aurora Background** - Alternative to LiquidEther/Silk -- **Particles Background** - Optional atmospheric backgrounds -- **Decay Card** - Alternative card style -- **Gradient Text** - Alternative to SplitText -- **Scroll Float** - Enhanced scroll indicators - -Remember to maintain the 2-3 components per page limit when adding new components. - -## Resources - -- React Bits Website: https://reactbits.dev/ -- Component Installation: `npx shadcn@latest add https://reactbits.dev/r/[component-name]` -- Three.js Docs: https://threejs.org/docs/ -- Framer Motion Docs: https://www.framer.com/motion/ - -## Conclusion - -The React Bits integration in Monynha Softwares provides a sophisticated, performant, and accessible user experience. The careful selection and placement of components ensures visual impact without sacrificing performance or usability. \ No newline at end of file diff --git a/docs/SUPABASE_IMPLEMENTATION.md b/docs/SUPABASE_IMPLEMENTATION.md new file mode 100644 index 0000000..d1879b5 --- /dev/null +++ b/docs/SUPABASE_IMPLEMENTATION.md @@ -0,0 +1,75 @@ +# Notas de Implementação do Supabase + +Este documento explica como o código frontend atual usa o Supabase. + +## Inicialização do cliente + +`src/services/supabaseService.ts`: + +- Lê `VITE_SUPABASE_URL` e `VITE_SUPABASE_ANON_KEY` +- Cria cliente tipado com `Database` de `src/supabase.types.ts` + +## Caminho de persistência usado pelo app + +Quando o wizard completa: + +1. Confirmação de contato é disparada imediatamente via `send-contact-confirmation`. +2. Diagnóstico é gerado via Edge Function. +3. Lead + diagnóstico são salvos via RPC: + +```ts +supabase.rpc('save_lead_with_diagnosis', payload) +``` + +Os campos do payload são mapeados de `LeadData` e `DiagnosisResult`. + +## API de serviços no codebase + +Helpers disponíveis em `src/services/supabaseService.ts`: + +- `saveLead(data, diagnosis)` +- `fetchLeadByEmail(email)` +- `fetchAllLeads(limit, offset)` +- `updateLeadStatus(leadId, status)` +- `deleteLead(leadId)` + +Barrel export: `src/services/index.ts`. + +## Contrato de banco de dados tipado + +`src/supabase.types.ts` define: + +- Tabelas: + - `leads` + - `diagnoses` + - `recommendations` + - `grounding_sources` +- Function: + - `save_lead_with_diagnosis` + +O app atualmente escreve via RPC e lê diretamente pelos helpers `leads` e `diagnoses`. + +## Estratégia de tratamento de erros + +- `saveLead` lança exceção em caso de erro no RPC. +- Em `App.tsx`, save e email rodam com `Promise.allSettled`. +- Falha no save ou email loga o erro mas não bloqueia a renderização do relatório após geração do diagnóstico. +- `sendContactConfirmation` roda antes do diagnóstico e também não bloqueia o fluxo principal. + +## Implicações práticas + +- O usuário recebe o relatório desde que a geração do diagnóstico seja bem-sucedida. +- Problemas de persistência ou e-mail são efeitos colaterais não-bloqueantes. +- Falha na geração do diagnóstico retorna ao wizard com mensagem de erro. +- A confirmação de contato garante que o lead e o time são notificados independentemente do diagnóstico. + +## Nota de segurança + +As configs das Edge Functions usam `verify_jwt = false`. Trate isso como uma escolha operacional intencional e revise antes do hardening de produção. + +## Atualização recente (a11y/performance) + +- Modal de time em `AboutSite` agora usa semântica de diálogo (`role="dialog"`, `aria-modal`, foco inicial no botão fechar e fechamento por `Esc`). +- Avatares remotos em componentes visuais receberam `loading="lazy"` e `decoding="async"` para reduzir custo inicial de renderização. +- Ícone decorativo de seleção no wizard recebeu `aria-hidden="true"` para evitar ruído para leitores de tela. + diff --git a/docs/SUPABASE_SETUP.md b/docs/SUPABASE_SETUP.md new file mode 100644 index 0000000..065b421 --- /dev/null +++ b/docs/SUPABASE_SETUP.md @@ -0,0 +1,90 @@ +# Guia de Setup do Supabase + +Use este guia para conectar o app ao Supabase e validar a integração. + +## 1) Instalar dependências + +```bash +pnpm install +``` + +(`@supabase/supabase-js` já está declarado em `package.json`.) + +## 2) Configurar env do frontend + +```bash +cp .env.example .env.local +``` + +Defina: + +```bash +VITE_SUPABASE_URL=https://your-project.supabase.co +VITE_SUPABASE_ANON_KEY=your_supabase_anon_key_here +``` + +## 3) Configurar secrets das Edge Functions + +Adicione em Supabase Dashboard → Project Settings → Edge Functions → Secrets: + +- `GEMINI_API_KEY` +- `RESEND_API_KEY` +- `RESEND_FROM_EMAIL` +- `MONYNHA_INTERNAL_EMAIL` + +## 4) Deploy das functions + +```bash +supabase functions deploy company-search +supabase functions deploy generate-diagnosis +supabase functions deploy send-contact-confirmation +supabase functions deploy send-diagnostic-email +``` + +## 5) Validar integração do app + +Rode o app: + +```bash +pnpm dev +``` + +Depois submeta o wizard e confirme: + +1. Confirmação de contato chega ao e-mail do lead e ao time. +2. Diagnóstico aparece no relatório. +3. Persistência do lead ocorre (entrada criada no banco). +4. E-mail de diagnóstico é executado (notificação ao lead + interna). + +## Uso opcional no nível de serviço + +Exemplos de chamadas do código: + +```ts +import { saveLead, fetchLeadByEmail, fetchAllLeads, updateLeadStatus, deleteLead } from './src/services'; +``` + +## Troubleshooting + +- `Error saving lead to Supabase`: RPC `save_lead_with_diagnosis` ausente ou payload incorreto. +- `Function returned error`: verifique logs da Edge Function no dashboard do Supabase. +- `Missing GEMINI_API_KEY` / `RESEND_API_KEY`: defina os secrets necessários nas functions. +- Dados não lidos de volta: verifique políticas de tabela e credenciais. + +## Configuração de auth das functions + +Todos os `config.toml` das functions configuram: + +```toml +[function] +verify_jwt = false +``` + +Planeje o hardening de produção adequadamente. + +## Atualização recente (a11y/performance) + +- Modal de time em `AboutSite` agora usa semântica de diálogo (`role="dialog"`, `aria-modal`, foco inicial no botão fechar e fechamento por `Esc`). +- Avatares remotos em componentes visuais receberam `loading="lazy"` e `decoding="async"` para reduzir custo inicial de renderização. +- Ícone decorativo de seleção no wizard recebeu `aria-hidden="true"` para evitar ruído para leitores de tela. + diff --git a/docs/TESTING.md b/docs/TESTING.md new file mode 100644 index 0000000..792e16c --- /dev/null +++ b/docs/TESTING.md @@ -0,0 +1,82 @@ +# Guia de Testes + +Este guia reflete o setup atual de testes e o comportamento observado. + +## Ferramentas + +- Unitários/integração: Vitest (`vitest.config.ts`) +- Ambiente de DOM: `jsdom` +- E2E: Playwright (`playwright.config.ts`) + +## Comandos + +```bash +pnpm test # modo watch +pnpm test:run # execução única +pnpm test:coverage +pnpm test:ui +pnpm test:e2e +pnpm lint +pnpm build +pnpm ci +``` + +## Testes unitários no repositório + +- `tests/unit/types.test.ts` (6 testes) +- `tests/unit/supabaseService.test.ts` (7 testes) + +Resultado atual: + +- `pnpm test:run` → todos os testes unitários passando + +## Status E2E + +- `playwright.config.ts` usa `testDir: './tests/e2e'` +- Specs estão em `tests/e2e/smoke.spec.ts` +- Configuração e specs estão alinhadas + +Para rodar E2E localmente, o servidor de preview precisa estar rodando: + +```bash +pnpm build && pnpm preview & +pnpm test:e2e +``` + +## Configuração de runtime do Playwright (atual) + +- `webServer.command`: `pnpm dev --host 0.0.0.0 --port 4173` +- `baseURL`: `http://127.0.0.1:4173` +- Projects: + - desktop chromium + - mobile chromium + +## Comportamento no CI + +O workflow `.github/workflows/ci.yml` executa: + +- `pnpm lint` +- `pnpm test:run` +- `pnpm build` + +Não executa `pnpm test:e2e` atualmente. + +## Verificações locais recomendadas antes do push + +```bash +pnpm ci +``` + +Para validação E2E completa: + +```bash +pnpm build && pnpm preview & +pnpm test:e2e +``` + +## Atualização recente (a11y/performance) + +- Modal de time em `AboutSite` agora usa semântica de diálogo (`role="dialog"`, `aria-modal`, foco inicial no botão fechar e fechamento por `Esc`). +- Avatares remotos em componentes visuais receberam `loading="lazy"` e `decoding="async"` para reduzir custo inicial de renderização. +- Ícone decorativo de seleção no wizard recebeu `aria-hidden="true"` para evitar ruído para leitores de tela. + diff --git a/docs/cli.md b/docs/cli.md deleted file mode 100644 index efe508b..0000000 --- a/docs/cli.md +++ /dev/null @@ -1,4 +0,0 @@ -Stop-Process -Id (Get-NetTCPConnection -LocalPort 3000).OwningProcess -Force -netstat -ano | findstr :3000 -taskkill /PID 23144 /F -setup alias add hello@monynha.com marcelo@monynha.com \ No newline at end of file diff --git a/docs/email-contect.png b/docs/email-contect.png deleted file mode 100644 index 702ab21..0000000 Binary files a/docs/email-contect.png and /dev/null differ diff --git a/docs/form.png b/docs/form.png new file mode 100644 index 0000000..ab78cf5 Binary files /dev/null and b/docs/form.png differ diff --git a/docs/homepage.png b/docs/homepage.png index 1d74c98..b431db3 100644 Binary files a/docs/homepage.png and b/docs/homepage.png differ diff --git a/docs/index.png b/docs/index.png new file mode 100644 index 0000000..79a0cf8 Binary files /dev/null and b/docs/index.png differ diff --git a/docs/loading.png b/docs/loading.png new file mode 100644 index 0000000..1db8298 Binary files /dev/null and b/docs/loading.png differ diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..d5ec547 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,24 @@ +import jsxA11y from 'eslint-plugin-jsx-a11y'; +import tsParser from '@typescript-eslint/parser'; + +export default [ + { + files: ['**/*.{ts,tsx}'], + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + ecmaFeatures: { jsx: true } + } + }, + plugins: { 'jsx-a11y': jsxA11y }, + rules: { + 'jsx-a11y/alt-text': 'error', + 'jsx-a11y/anchor-is-valid': 'error', + 'jsx-a11y/click-events-have-key-events': 'warn', + 'jsx-a11y/no-static-element-interactions': 'warn' + } + }, + { ignores: ['dist/**', 'node_modules/**'] } +]; diff --git a/index.html b/index.html index 1c1fff0..c13e27a 100644 --- a/index.html +++ b/index.html @@ -1,84 +1,75 @@ - <!DOCTYPE html> -<html lang="en"> +<html lang="pt-BR"> <head> <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <title>Monynha Softwares | Democratizing technology, empowering people - - - - - - - + + Monynha Softwares | Diagnóstico Digital e Automação + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + +
+ Pular para conteúdo principal
- + diff --git a/metadata.json b/metadata.json index 55552b0..706d4b5 100644 --- a/metadata.json +++ b/metadata.json @@ -1,5 +1,5 @@ - { - "name": "Monynha Softwares", - "description": "A futuristic, inclusive, and high-end digital presence for a software studio that builds custom Odoo solutions, AI-powered automation, and digital products." -} + "name": "Monynha Softwares | Democratizando tecnologia para um futuro mais humano", + "description": "Monynha Softwares é uma empresa de tecnologia focada em diagnóstico digital e automação centrada no humano. Nossa missão é democratizar o acesso à tecnologia, criando soluções inovadoras que promovam um futuro mais humano e sustentável.", + "requestFramePermissions": [] +} \ No newline at end of file diff --git a/package.json b/package.json index b638d11..20204f9 100644 --- a/package.json +++ b/package.json @@ -1,25 +1,49 @@ { - "name": "monynha-softwares", + "name": "monynha-website", "private": true, - "version": "0.0.0", + "version": "0.0.3", + "engines": { + "node": ">=20" + }, "type": "module", "scripts": { "dev": "vite", - "build": "vite build && node scripts/generate_sitemap.mjs", + "build": "pnpm generate:sitemap && vite build", "preview": "vite preview", - "start": "node server.js" + "lint": "tsc --noEmit", + "test": "vitest", + "test:ui": "vitest --ui", + "test:run": "vitest run", + "test:coverage": "vitest run --coverage", + "ci": "pnpm lint && pnpm test:run && pnpm build", + "test:e2e": "playwright test", + "lint:a11y": "eslint .", + "generate:sitemap": "node scripts/generate-sitemap.js" }, "dependencies": { - "react-dom": "^19.2.4", - "framer-motion": "^12.33.0", + "@supabase/supabase-js": "^2.98.0", "react": "^19.2.4", - "express": "^4.19.2", - "dotenv": "^16.4.5" + "react-dom": "^19.2.4" }, "devDependencies": { + "@google/genai": "^1.41.0", + "@playwright/test": "^1.54.2", + "@tailwindcss/postcss": "^4.2.1", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.2", "@types/node": "^22.14.0", + "@typescript-eslint/parser": "^8.56.1", "@vitejs/plugin-react": "^5.0.0", + "@vitest/ui": "^4.0.18", + "autoprefixer": "^10.4.27", + "eslint": "^9.35.0", + "eslint-plugin-jsx-a11y": "^6.9.0", + "jsdom": "^24.1.3", + "postcss": "^8.5.8", + "tailwindcss": "^4.2.1", "typescript": "~5.8.2", - "vite": "^6.2.0" + "typescript-eslint": "^8.42.0", + "vite": "^6.2.0", + "vitest": "^4.0.18" } } diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..12e83b7 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,17 @@ +import { defineConfig } from '@playwright/test'; + +export default defineConfig({ + testDir: './tests/e2e', + timeout: 30_000, + use: { baseURL: 'http://127.0.0.1:4173', trace: 'on-first-retry', browserName: 'chromium' }, + webServer: { + command: 'pnpm dev --host 0.0.0.0 --port 4173', + port: 4173, + reuseExistingServer: true, + timeout: 120_000 + }, + projects: [ + { name: 'desktop-chromium', use: { viewport: { width: 1440, height: 900 } } }, + { name: 'mobile-chromium', use: { viewport: { width: 390, height: 844 }, isMobile: true, hasTouch: true } } + ] +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0b5f741..9426315 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,15 +8,9 @@ importers: .: dependencies: - dotenv: - specifier: ^16.4.5 - version: 16.6.1 - express: - specifier: ^4.19.2 - version: 4.22.1 - framer-motion: - specifier: ^12.33.0 - version: 12.33.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@supabase/supabase-js': + specifier: ^2.98.0 + version: 2.98.0 react: specifier: ^19.2.4 version: 19.2.4 @@ -24,21 +18,76 @@ importers: specifier: ^19.2.4 version: 19.2.4(react@19.2.4) devDependencies: + '@google/genai': + specifier: ^1.41.0 + version: 1.43.0 + '@playwright/test': + specifier: ^1.54.2 + version: 1.58.2 + '@tailwindcss/postcss': + specifier: ^4.2.1 + version: 4.2.1 + '@testing-library/jest-dom': + specifier: ^6.9.1 + version: 6.9.1 + '@testing-library/react': + specifier: ^16.3.2 + version: 16.3.2(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@types/node': specifier: ^22.14.0 - version: 22.19.9 + version: 22.19.13 + '@typescript-eslint/parser': + specifier: ^8.56.1 + version: 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3) '@vitejs/plugin-react': specifier: ^5.0.0 - version: 5.1.3(vite@6.4.1(@types/node@22.19.9)) + version: 5.1.4(vite@6.4.1(@types/node@22.19.13)(jiti@2.6.1)(lightningcss@1.31.1)) + '@vitest/ui': + specifier: ^4.0.18 + version: 4.0.18(vitest@4.0.18) + autoprefixer: + specifier: ^10.4.27 + version: 10.4.27(postcss@8.5.8) + eslint: + specifier: ^9.35.0 + version: 9.39.3(jiti@2.6.1) + eslint-plugin-jsx-a11y: + specifier: ^6.9.0 + version: 6.10.2(eslint@9.39.3(jiti@2.6.1)) + jsdom: + specifier: ^24.1.3 + version: 24.1.3 + postcss: + specifier: ^8.5.8 + version: 8.5.8 + tailwindcss: + specifier: ^4.2.1 + version: 4.2.1 typescript: specifier: ~5.8.2 version: 5.8.3 + typescript-eslint: + specifier: ^8.42.0 + version: 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3) vite: specifier: ^6.2.0 - version: 6.4.1(@types/node@22.19.9) + version: 6.4.1(@types/node@22.19.13)(jiti@2.6.1)(lightningcss@1.31.1) + vitest: + specifier: ^4.0.18 + version: 4.0.18(@types/node@22.19.13)(@vitest/ui@4.0.18)(jiti@2.6.1)(jsdom@24.1.3)(lightningcss@1.31.1) packages: + '@adobe/css-tools@4.4.4': + resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@asamuzakjp/css-color@3.2.0': + resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + '@babel/code-frame@7.29.0': resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} @@ -110,6 +159,10 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/runtime@7.28.6': + resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + engines: {node: '>=6.9.0'} + '@babel/template@7.28.6': resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} engines: {node: '>=6.9.0'} @@ -122,6 +175,34 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + '@esbuild/aix-ppc64@0.25.12': resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} engines: {node: '>=18'} @@ -278,6 +359,73 @@ packages: cpu: [x64] os: [win32] + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.1': + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.4': + resolution: {integrity: sha512-4h4MVF8pmBsncB60r0wSJiIeUKTSD4m7FmTFThG8RHlsg9ajqckLm9OraguFGZE4vVdpiI1Q4+hFnisopmG6gQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.39.3': + resolution: {integrity: sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@google/genai@1.43.0': + resolution: {integrity: sha512-hklCsJNdMlDM1IwcCVcGQFBg2izY0+t5BIGbRsxi2UnKi6AGKL7pqJqmBDNRbw0bYCs4y3NA7TB+fkKfP/Nrdw==} + engines: {node: '>=20.0.0'} + peerDependencies: + '@modelcontextprotocol/sdk': ^1.25.2 + peerDependenciesMeta: + '@modelcontextprotocol/sdk': + optional: true + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -294,134 +442,317 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@rolldown/pluginutils@1.0.0-rc.2': - resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==} + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@playwright/test@1.58.2': + resolution: {integrity: sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==} + engines: {node: '>=18'} + hasBin: true + + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} - '@rollup/rollup-android-arm-eabi@4.57.1': - resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + + '@rolldown/pluginutils@1.0.0-rc.3': + resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} + + '@rollup/rollup-android-arm-eabi@4.59.0': + resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.57.1': - resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==} + '@rollup/rollup-android-arm64@4.59.0': + resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.57.1': - resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==} + '@rollup/rollup-darwin-arm64@4.59.0': + resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.57.1': - resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==} + '@rollup/rollup-darwin-x64@4.59.0': + resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.57.1': - resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==} + '@rollup/rollup-freebsd-arm64@4.59.0': + resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.57.1': - resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==} + '@rollup/rollup-freebsd-x64@4.59.0': + resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.57.1': - resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.57.1': - resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.57.1': - resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} + '@rollup/rollup-linux-arm64-gnu@4.59.0': + resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.57.1': - resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} + '@rollup/rollup-linux-arm64-musl@4.59.0': + resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.57.1': - resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} + '@rollup/rollup-linux-loong64-gnu@4.59.0': + resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-loong64-musl@4.57.1': - resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} + '@rollup/rollup-linux-loong64-musl@4.59.0': + resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.57.1': - resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-ppc64-musl@4.57.1': - resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} + '@rollup/rollup-linux-ppc64-musl@4.59.0': + resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.57.1': - resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.57.1': - resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} + '@rollup/rollup-linux-riscv64-musl@4.59.0': + resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.57.1': - resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} + '@rollup/rollup-linux-s390x-gnu@4.59.0': + resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.57.1': - resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} + '@rollup/rollup-linux-x64-gnu@4.59.0': + resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.57.1': - resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} + '@rollup/rollup-linux-x64-musl@4.59.0': + resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} cpu: [x64] os: [linux] - '@rollup/rollup-openbsd-x64@4.57.1': - resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} + '@rollup/rollup-openbsd-x64@4.59.0': + resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} cpu: [x64] os: [openbsd] - '@rollup/rollup-openharmony-arm64@4.57.1': - resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==} + '@rollup/rollup-openharmony-arm64@4.59.0': + resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.57.1': - resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==} + '@rollup/rollup-win32-arm64-msvc@4.59.0': + resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.57.1': - resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==} + '@rollup/rollup-win32-ia32-msvc@4.59.0': + resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.57.1': - resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==} + '@rollup/rollup-win32-x64-gnu@4.59.0': + resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.59.0': + resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} + cpu: [x64] + os: [win32] + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@supabase/auth-js@2.98.0': + resolution: {integrity: sha512-GBH361T0peHU91AQNzOlIrjUZw9TZbB9YDRiyFgk/3Kvr3/Z1NWUZ2athWTfHhwNNi8IrW00foyFxQD9IO/Trg==} + engines: {node: '>=20.0.0'} + + '@supabase/functions-js@2.98.0': + resolution: {integrity: sha512-N/xEyiNU5Org+d+PNCpv+TWniAXRzxIURxDYsS/m2I/sfAB/HcM9aM2Dmf5edj5oWb9GxID1OBaZ8NMmPXL+Lg==} + engines: {node: '>=20.0.0'} + + '@supabase/postgrest-js@2.98.0': + resolution: {integrity: sha512-v6e9WeZuJijzUut8HyXu6gMqWFepIbaeaMIm1uKzei4yLg9bC9OtEW9O14LE/9ezqNbSAnSLO5GtOLFdm7Bpkg==} + engines: {node: '>=20.0.0'} + + '@supabase/realtime-js@2.98.0': + resolution: {integrity: sha512-rOWt28uGyFipWOSd+n0WVMr9kUXiWaa7J4hvyLCIHjRFqWm1z9CaaKAoYyfYMC1Exn3WT8WePCgiVhlAtWC2yw==} + engines: {node: '>=20.0.0'} + + '@supabase/storage-js@2.98.0': + resolution: {integrity: sha512-tzr2mG+v7ILSAZSfZMSL9OPyIH4z1ikgQ8EcQTKfMRz4EwmlFt3UnJaGzSOxyvF5b+fc9So7qdSUWTqGgeLokQ==} + engines: {node: '>=20.0.0'} + + '@supabase/supabase-js@2.98.0': + resolution: {integrity: sha512-Ohc97CtInLwZyiSASz7tT9/Abm/vqnIbO9REp+PivVUII8UZsuI3bngRQnYgJdFoOIwvaEII1fX1qy8x0CyNiw==} + engines: {node: '>=20.0.0'} + + '@tailwindcss/node@4.2.1': + resolution: {integrity: sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==} + + '@tailwindcss/oxide-android-arm64@4.2.1': + resolution: {integrity: sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.2.1': + resolution: {integrity: sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.2.1': + resolution: {integrity: sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.2.1': + resolution: {integrity: sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1': + resolution: {integrity: sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.2.1': + resolution: {integrity: sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.2.1': + resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.2.1': + resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==} + engines: {node: '>= 20'} cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.2.1': + resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.2.1': + resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.2.1': + resolution: {integrity: sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==} + engines: {node: '>= 20'} + cpu: [arm64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.57.1': - resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==} + '@tailwindcss/oxide-win32-x64-msvc@4.2.1': + resolution: {integrity: sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==} + engines: {node: '>= 20'} cpu: [x64] os: [win32] + '@tailwindcss/oxide@4.2.1': + resolution: {integrity: sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==} + engines: {node: '>= 20'} + + '@tailwindcss/postcss@4.2.1': + resolution: {integrity: sha512-OEwGIBnXnj7zJeonOh6ZG9woofIjGrd2BORfvE5p9USYKDCZoQmfqLcfNiRWoJlRWLdNPn2IgVZuWAOM4iTYMw==} + + '@testing-library/dom@10.4.1': + resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.9.1': + resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@testing-library/react@16.3.2': + resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 || ^19.0.0 + '@types/react-dom': ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -434,78 +765,342 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/node@22.19.9': - resolution: {integrity: sha512-PD03/U8g1F9T9MI+1OBisaIARhSzeidsUjQaf51fOxrfjeiKN9bLVO06lHuHYjxdnqLWJijJHfqXPSJri2EM2A==} + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/node@22.19.13': + resolution: {integrity: sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw==} + + '@types/phoenix@1.6.7': + resolution: {integrity: sha512-oN9ive//QSBkf19rfDv45M7eZPi0eEXylht2OLEXicu5b4KoQ1OzXIw+xDSGWxSxe1JmepRR/ZH283vsu518/Q==} + + '@types/retry@0.12.0': + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + + '@typescript-eslint/eslint-plugin@8.56.1': + resolution: {integrity: sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.56.1 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/parser@8.56.1': + resolution: {integrity: sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.56.1': + resolution: {integrity: sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.56.1': + resolution: {integrity: sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.56.1': + resolution: {integrity: sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.56.1': + resolution: {integrity: sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/types@8.56.1': + resolution: {integrity: sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.56.1': + resolution: {integrity: sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/utils@8.56.1': + resolution: {integrity: sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@8.56.1': + resolution: {integrity: sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vitejs/plugin-react@5.1.3': - resolution: {integrity: sha512-NVUnA6gQCl8jfoYqKqQU5Clv0aPw14KkZYCsX6T9Lfu9slI0LOU10OTwFHS/WmptsMMpshNd/1tuWsHQ2Uk+cg==} + '@vitejs/plugin-react@5.1.4': + resolution: {integrity: sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} + '@vitest/expect@4.0.18': + resolution: {integrity: sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==} + + '@vitest/mocker@4.0.18': + resolution: {integrity: sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.0.18': + resolution: {integrity: sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==} + + '@vitest/runner@4.0.18': + resolution: {integrity: sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==} + + '@vitest/snapshot@4.0.18': + resolution: {integrity: sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==} + + '@vitest/spy@4.0.18': + resolution: {integrity: sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==} + + '@vitest/ui@4.0.18': + resolution: {integrity: sha512-CGJ25bc8fRi8Lod/3GHSvXRKi7nBo3kxh0ApW4yCjmrWmRmlT53B5E08XRSZRliygG0aVNxLrBEqPYdz/KcCtQ==} + peerDependencies: + vitest: 4.0.18 + + '@vitest/utils@4.0.18': + resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + ajv@6.14.0: + resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-includes@3.1.9: + resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + ast-types-flow@0.0.8: + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} - baseline-browser-mapping@2.9.19: - resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + autoprefixer@10.4.27: + resolution: {integrity: sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axe-core@4.11.1: + resolution: {integrity: sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==} + engines: {node: '>=4'} + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + baseline-browser-mapping@2.10.0: + resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==} + engines: {node: '>=6.0.0'} hasBin: true - body-parser@1.20.4: - resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + bignumber.js@9.3.1: + resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + brace-expansion@5.0.4: + resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} + engines: {node: 18 || 20 || >=22} browserslist@4.28.1: resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + call-bound@1.0.4: resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} engines: {node: '>= 0.4'} - caniuse-lite@1.0.30001769: - resolution: {integrity: sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==} + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} - content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} + caniuse-lite@1.0.30001774: + resolution: {integrity: sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA==} - content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - cookie-signature@1.0.7: - resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} - cookie@0.7.2: - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} - engines: {node: '>= 0.6'} + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} - debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + cssstyle@4.6.0: + resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} + engines: {node: '>=18'} + + damerau-levenshtein@1.0.8: + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} @@ -516,31 +1111,68 @@ packages: supports-color: optional: true - depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} - destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dotenv@16.6.1: - resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} - engines: {node: '>=12'} + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - electron-to-chromium@1.5.286: - resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==} + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} - encodeurl@2.0.0: - resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} - engines: {node: '>= 0.8'} + electron-to-chromium@1.5.302: + resolution: {integrity: sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + enhanced-resolve@5.20.0: + resolution: {integrity: sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==} + engines: {node: '>=10.13.0'} + + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + + es-abstract@1.24.1: + resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} + engines: {node: '>= 0.4'} es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} @@ -550,10 +1182,25 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.1.0: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + esbuild@0.25.12: resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} @@ -563,51 +1210,135 @@ packages: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} - escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} - etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} + eslint-plugin-jsx-a11y@6.10.2: + resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} + engines: {node: '>=4.0'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - express@4.22.1: - resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==} - engines: {node: '>= 0.10.0'} + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - fdir@6.5.0: - resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} - engines: {node: '>=12.0.0'} - peerDependencies: - picomatch: ^3 || ^4 + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@9.39.3: + resolution: {integrity: sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' peerDependenciesMeta: - picomatch: + jiti: optional: true - finalhandler@1.3.2: - resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==} - engines: {node: '>= 0.8'} + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} - framer-motion@12.33.0: - resolution: {integrity: sha512-ca8d+rRPcDP5iIF+MoT3WNc0KHJMjIyFAbtVLvM9eA7joGSpeqDfiNH/kCs1t4CHi04njYvWyj0jS4QlEK/rJQ==} + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} peerDependencies: - '@emotion/is-prop-valid': '*' - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 + picomatch: ^3 || ^4 peerDependenciesMeta: - '@emotion/is-prop-valid': - optional: true - react: - optional: true - react-dom: + picomatch: optional: true - fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + + fraction.js@5.3.4: + resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} @@ -617,6 +1348,25 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + gaxios@7.1.3: + resolution: {integrity: sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==} + engines: {node: '>=18'} + + gcp-metadata@8.1.2: + resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} + engines: {node: '>=18'} + + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -629,64 +1379,384 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + 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 + hasBin: true + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + google-auth-library@10.6.1: + resolution: {integrity: sha512-5awwuLrzNol+pFDmKJd0dKtZ0fPLAtoA5p7YO4ODsDu6ONJUVqbYwvv8y2ZBO5MBNp9TJXigB19710kYpBPdtA==} + engines: {node: '>=18'} + + google-logging-utils@1.1.3: + resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==} + engines: {node: '>=14'} + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + has-symbols@1.1.0: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} - http-errors@2.0.1: - resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} - engines: {node: '>= 0.8'} + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + iceberg-js@0.8.1: + resolution: {integrity: sha512-1dhVQZXhcHje7798IVM+xoo/1ZdVfzOMIc8/rgVSijRK38EDqOJoGula9N/8ZI5RD8QTxNQtK/Gozpr+qUqRRA==} + engines: {node: '>=20.0.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} - iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsdom@24.1.3: + resolution: {integrity: sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^2.11.2 + peerDependenciesMeta: + canvas: + optional: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} hasBin: true + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true + jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} + + jws@4.0.1: + resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + language-subtag-registry@0.3.23: + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} + + language-tags@1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lightningcss-android-arm64@1.31.1: + resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.31.1: + resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.31.1: + resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.31.1: + resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.31.1: + resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.31.1: + resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.31.1: + resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.31.1: + resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.31.1: + resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.31.1: + resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.31.1: + resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.31.1: + resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==} + engines: {node: '>= 12.0.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} - media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - - merge-descriptors@1.0.3: - resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} - - methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -695,19 +1765,28 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} - mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} - hasBin: true - motion-dom@12.33.0: - resolution: {integrity: sha512-XRPebVypsl0UM+7v0Hr8o9UAj0S2djsQWRdHBd5iVouVpMrQqAI0C/rDAT3QaYnXnHuC5hMcwDHCboNeyYjPoQ==} + minimatch@10.2.4: + resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} + engines: {node: 18 || 20 || >=22} + + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} - motion-utils@12.29.2: - resolution: {integrity: sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==} + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} - ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -717,27 +1796,91 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + nwsapi@2.2.23: + resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==} + object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} - on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} - parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} + + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} - path-to-regexp@0.1.12: - resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -746,31 +1889,57 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} - postcss@8.5.6: - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + playwright-core@1.58.2: + resolution: {integrity: sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.58.2: + resolution: {integrity: sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==} + engines: {node: '>=18'} + hasBin: true + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.5.8: + resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} engines: {node: ^10 || ^12 || >=14} - proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} - qs@6.14.2: - resolution: {integrity: sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==} - engines: {node: '>=0.6'} + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} + protobufjs@7.5.4: + resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==} + engines: {node: '>=12.0.0'} - raw-body@2.5.3: - resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} - engines: {node: '>= 0.8'} + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} react-dom@19.2.4: resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} peerDependencies: react: ^19.2.4 + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-refresh@0.18.0: resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} engines: {node: '>=0.10.0'} @@ -779,17 +1948,66 @@ packages: resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} engines: {node: '>=0.10.0'} - rollup@4.57.1: - resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + rimraf@5.0.10: + resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} + hasBin: true + + rollup@4.59.0: + resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + rrweb-cssom@0.7.1: + resolution: {integrity: sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==} + + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} @@ -797,16 +2015,30 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - send@0.19.2: - resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} - engines: {node: '>= 0.8.0'} + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true - serve-static@1.16.3: - resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} - engines: {node: '>= 0.8.0'} + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} - setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} side-channel-list@1.0.0: resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} @@ -824,40 +2056,163 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sirv@3.0.2: + resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} + engines: {node: '>=18'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - statuses@2.0.2: - resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} - engines: {node: '>= 0.8'} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string.prototype.includes@2.0.1: + resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} + engines: {node: '>= 0.4'} + + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + tailwindcss@4.2.1: + resolution: {integrity: sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==} + + tapable@2.3.0: + resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} + engines: {node: '>=6'} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.0.2: + resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + engines: {node: '>=18'} tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} - toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} + tinyrainbow@3.0.3: + resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} + engines: {node: '>=14.0.0'} + + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} + + ts-api-utils@2.4.0: + resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + + typescript-eslint@8.56.1: + resolution: {integrity: sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.0.0' typescript@5.8.3: resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} engines: {node: '>=14.17'} hasBin: true + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} @@ -865,13 +2220,11 @@ packages: peerDependencies: browserslist: '>= 4.21.0' - utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} vite@6.4.1: resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} @@ -913,11 +2266,143 @@ packages: yaml: optional: true + vitest@4.0.18: + resolution: {integrity: sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.0.18 + '@vitest/browser-preview': 4.0.18 + '@vitest/browser-webdriverio': 4.0.18 + '@vitest/ui': 4.0.18 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.20: + resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + ws@8.19.0: + resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + snapshots: + '@adobe/css-tools@4.4.4': {} + + '@alloc/quick-lru@5.2.0': {} + + '@asamuzakjp/css-color@3.2.0': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 10.4.3 + '@babel/code-frame@7.29.0': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -1007,6 +2492,8 @@ snapshots: '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 + '@babel/runtime@7.28.6': {} + '@babel/template@7.28.6': dependencies: '@babel/code-frame': 7.29.0 @@ -1030,6 +2517,26 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@csstools/color-helpers@5.1.0': {} + + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-tokenizer@3.0.4': {} + '@esbuild/aix-ppc64@0.25.12': optional: true @@ -1108,6 +2615,83 @@ snapshots: '@esbuild/win32-x64@0.25.12': optional: true + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.3(jiti@2.6.1))': + dependencies: + eslint: 9.39.3(jiti@2.6.1) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.21.1': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.5 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.4': + dependencies: + ajv: 6.14.0 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + minimatch: 3.1.5 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.39.3': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.4.1': + dependencies: + '@eslint/core': 0.17.0 + levn: 0.4.1 + + '@google/genai@1.43.0': + dependencies: + google-auth-library: 10.6.1 + p-retry: 4.6.2 + protobufjs: 7.5.4 + ws: 8.19.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.7': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -1127,521 +2711,1740 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@rolldown/pluginutils@1.0.0-rc.2': {} + '@pkgjs/parseargs@0.11.0': + optional: true + + '@playwright/test@1.58.2': + dependencies: + playwright: 1.58.2 + + '@polka/url@1.0.0-next.29': {} + + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} - '@rollup/rollup-android-arm-eabi@4.57.1': + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + + '@rolldown/pluginutils@1.0.0-rc.3': {} + + '@rollup/rollup-android-arm-eabi@4.59.0': optional: true - '@rollup/rollup-android-arm64@4.57.1': + '@rollup/rollup-android-arm64@4.59.0': optional: true - '@rollup/rollup-darwin-arm64@4.57.1': + '@rollup/rollup-darwin-arm64@4.59.0': optional: true - '@rollup/rollup-darwin-x64@4.57.1': + '@rollup/rollup-darwin-x64@4.59.0': optional: true - '@rollup/rollup-freebsd-arm64@4.57.1': + '@rollup/rollup-freebsd-arm64@4.59.0': optional: true - '@rollup/rollup-freebsd-x64@4.57.1': + '@rollup/rollup-freebsd-x64@4.59.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.57.1': + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.57.1': + '@rollup/rollup-linux-arm-musleabihf@4.59.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.57.1': + '@rollup/rollup-linux-arm64-gnu@4.59.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.57.1': + '@rollup/rollup-linux-arm64-musl@4.59.0': optional: true - '@rollup/rollup-linux-loong64-gnu@4.57.1': + '@rollup/rollup-linux-loong64-gnu@4.59.0': optional: true - '@rollup/rollup-linux-loong64-musl@4.57.1': + '@rollup/rollup-linux-loong64-musl@4.59.0': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.57.1': + '@rollup/rollup-linux-ppc64-gnu@4.59.0': optional: true - '@rollup/rollup-linux-ppc64-musl@4.57.1': + '@rollup/rollup-linux-ppc64-musl@4.59.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.57.1': + '@rollup/rollup-linux-riscv64-gnu@4.59.0': optional: true - '@rollup/rollup-linux-riscv64-musl@4.57.1': + '@rollup/rollup-linux-riscv64-musl@4.59.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.57.1': + '@rollup/rollup-linux-s390x-gnu@4.59.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.57.1': + '@rollup/rollup-linux-x64-gnu@4.59.0': optional: true - '@rollup/rollup-linux-x64-musl@4.57.1': + '@rollup/rollup-linux-x64-musl@4.59.0': optional: true - '@rollup/rollup-openbsd-x64@4.57.1': + '@rollup/rollup-openbsd-x64@4.59.0': optional: true - '@rollup/rollup-openharmony-arm64@4.57.1': + '@rollup/rollup-openharmony-arm64@4.59.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.57.1': + '@rollup/rollup-win32-arm64-msvc@4.59.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.57.1': + '@rollup/rollup-win32-ia32-msvc@4.59.0': optional: true - '@rollup/rollup-win32-x64-gnu@4.57.1': + '@rollup/rollup-win32-x64-gnu@4.59.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.57.1': + '@rollup/rollup-win32-x64-msvc@4.59.0': optional: true - '@types/babel__core@7.20.5': - dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - '@types/babel__generator': 7.27.0 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.28.0 + '@standard-schema/spec@1.1.0': {} - '@types/babel__generator@7.27.0': + '@supabase/auth-js@2.98.0': dependencies: - '@babel/types': 7.29.0 + tslib: 2.8.1 - '@types/babel__template@7.4.4': + '@supabase/functions-js@2.98.0': dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 + tslib: 2.8.1 - '@types/babel__traverse@7.28.0': + '@supabase/postgrest-js@2.98.0': dependencies: - '@babel/types': 7.29.0 - - '@types/estree@1.0.8': {} + tslib: 2.8.1 - '@types/node@22.19.9': + '@supabase/realtime-js@2.98.0': dependencies: - undici-types: 6.21.0 + '@types/phoenix': 1.6.7 + '@types/ws': 8.18.1 + tslib: 2.8.1 + ws: 8.19.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate - '@vitejs/plugin-react@5.1.3(vite@6.4.1(@types/node@22.19.9))': + '@supabase/storage-js@2.98.0': dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) - '@rolldown/pluginutils': 1.0.0-rc.2 - '@types/babel__core': 7.20.5 - react-refresh: 0.18.0 - vite: 6.4.1(@types/node@22.19.9) - transitivePeerDependencies: - - supports-color + iceberg-js: 0.8.1 + tslib: 2.8.1 - accepts@1.3.8: + '@supabase/supabase-js@2.98.0': dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - - array-flatten@1.1.1: {} - - baseline-browser-mapping@2.9.19: {} - - body-parser@1.20.4: - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.1 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.14.2 - raw-body: 2.5.3 - type-is: 1.6.18 - unpipe: 1.0.0 + '@supabase/auth-js': 2.98.0 + '@supabase/functions-js': 2.98.0 + '@supabase/postgrest-js': 2.98.0 + '@supabase/realtime-js': 2.98.0 + '@supabase/storage-js': 2.98.0 transitivePeerDependencies: - - supports-color + - bufferutil + - utf-8-validate - browserslist@4.28.1: + '@tailwindcss/node@4.2.1': dependencies: - baseline-browser-mapping: 2.9.19 - caniuse-lite: 1.0.30001769 - electron-to-chromium: 1.5.286 - node-releases: 2.0.27 - update-browserslist-db: 1.2.3(browserslist@4.28.1) + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.20.0 + jiti: 2.6.1 + lightningcss: 1.31.1 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.2.1 - bytes@3.1.2: {} + '@tailwindcss/oxide-android-arm64@4.2.1': + optional: true - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 + '@tailwindcss/oxide-darwin-arm64@4.2.1': + optional: true - call-bound@1.0.4: - dependencies: - call-bind-apply-helpers: 1.0.2 - get-intrinsic: 1.3.0 + '@tailwindcss/oxide-darwin-x64@4.2.1': + optional: true - caniuse-lite@1.0.30001769: {} + '@tailwindcss/oxide-freebsd-x64@4.2.1': + optional: true - content-disposition@0.5.4: - dependencies: - safe-buffer: 5.2.1 + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1': + optional: true - content-type@1.0.5: {} + '@tailwindcss/oxide-linux-arm64-gnu@4.2.1': + optional: true - convert-source-map@2.0.0: {} + '@tailwindcss/oxide-linux-arm64-musl@4.2.1': + optional: true - cookie-signature@1.0.7: {} + '@tailwindcss/oxide-linux-x64-gnu@4.2.1': + optional: true - cookie@0.7.2: {} + '@tailwindcss/oxide-linux-x64-musl@4.2.1': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.2.1': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.2.1': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.2.1': + optional: true + + '@tailwindcss/oxide@4.2.1': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.2.1 + '@tailwindcss/oxide-darwin-arm64': 4.2.1 + '@tailwindcss/oxide-darwin-x64': 4.2.1 + '@tailwindcss/oxide-freebsd-x64': 4.2.1 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.1 + '@tailwindcss/oxide-linux-arm64-gnu': 4.2.1 + '@tailwindcss/oxide-linux-arm64-musl': 4.2.1 + '@tailwindcss/oxide-linux-x64-gnu': 4.2.1 + '@tailwindcss/oxide-linux-x64-musl': 4.2.1 + '@tailwindcss/oxide-wasm32-wasi': 4.2.1 + '@tailwindcss/oxide-win32-arm64-msvc': 4.2.1 + '@tailwindcss/oxide-win32-x64-msvc': 4.2.1 + + '@tailwindcss/postcss@4.2.1': + dependencies: + '@alloc/quick-lru': 5.2.0 + '@tailwindcss/node': 4.2.1 + '@tailwindcss/oxide': 4.2.1 + postcss: 8.5.8 + tailwindcss: 4.2.1 + + '@testing-library/dom@10.4.1': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/runtime': 7.28.6 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + picocolors: 1.1.1 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.9.1': + dependencies: + '@adobe/css-tools': 4.4.4 + aria-query: 5.3.2 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + picocolors: 1.1.1 + redent: 3.0.0 + + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@babel/runtime': 7.28.6 + '@testing-library/dom': 10.4.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@types/aria-query@5.0.4': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.8': {} + + '@types/json-schema@7.0.15': {} + + '@types/node@22.19.13': + dependencies: + undici-types: 6.21.0 + + '@types/phoenix@1.6.7': {} + + '@types/retry@0.12.0': {} + + '@types/ws@8.18.1': + dependencies: + '@types/node': 22.19.13 + + '@typescript-eslint/eslint-plugin@8.56.1(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.56.1 + '@typescript-eslint/type-utils': 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/utils': 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.56.1 + eslint: 9.39.3(jiti@2.6.1) + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.4.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.56.1 + '@typescript-eslint/types': 8.56.1 + '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.56.1 + debug: 4.4.3 + eslint: 9.39.3(jiti@2.6.1) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.56.1(typescript@5.8.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.56.1(typescript@5.8.3) + '@typescript-eslint/types': 8.56.1 + debug: 4.4.3 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.56.1': + dependencies: + '@typescript-eslint/types': 8.56.1 + '@typescript-eslint/visitor-keys': 8.56.1 + + '@typescript-eslint/tsconfig-utils@8.56.1(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + + '@typescript-eslint/type-utils@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/types': 8.56.1 + '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.8.3) + '@typescript-eslint/utils': 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3) + debug: 4.4.3 + eslint: 9.39.3(jiti@2.6.1) + ts-api-utils: 2.4.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.56.1': {} + + '@typescript-eslint/typescript-estree@8.56.1(typescript@5.8.3)': + dependencies: + '@typescript-eslint/project-service': 8.56.1(typescript@5.8.3) + '@typescript-eslint/tsconfig-utils': 8.56.1(typescript@5.8.3) + '@typescript-eslint/types': 8.56.1 + '@typescript-eslint/visitor-keys': 8.56.1 + debug: 4.4.3 + minimatch: 10.2.4 + semver: 7.7.4 + tinyglobby: 0.2.15 + ts-api-utils: 2.4.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.3(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.56.1 + '@typescript-eslint/types': 8.56.1 + '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.8.3) + eslint: 9.39.3(jiti@2.6.1) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.56.1': + dependencies: + '@typescript-eslint/types': 8.56.1 + eslint-visitor-keys: 5.0.1 + + '@vitejs/plugin-react@5.1.4(vite@6.4.1(@types/node@22.19.13)(jiti@2.6.1)(lightningcss@1.31.1))': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@rolldown/pluginutils': 1.0.0-rc.3 + '@types/babel__core': 7.20.5 + react-refresh: 0.18.0 + vite: 6.4.1(@types/node@22.19.13)(jiti@2.6.1)(lightningcss@1.31.1) + transitivePeerDependencies: + - supports-color + + '@vitest/expect@4.0.18': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.0.18 + '@vitest/utils': 4.0.18 + chai: 6.2.2 + tinyrainbow: 3.0.3 + + '@vitest/mocker@4.0.18(vite@6.4.1(@types/node@22.19.13)(jiti@2.6.1)(lightningcss@1.31.1))': + dependencies: + '@vitest/spy': 4.0.18 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 6.4.1(@types/node@22.19.13)(jiti@2.6.1)(lightningcss@1.31.1) + + '@vitest/pretty-format@4.0.18': + dependencies: + tinyrainbow: 3.0.3 + + '@vitest/runner@4.0.18': + dependencies: + '@vitest/utils': 4.0.18 + pathe: 2.0.3 + + '@vitest/snapshot@4.0.18': + dependencies: + '@vitest/pretty-format': 4.0.18 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.0.18': {} + + '@vitest/ui@4.0.18(vitest@4.0.18)': + dependencies: + '@vitest/utils': 4.0.18 + fflate: 0.8.2 + flatted: 3.3.3 + pathe: 2.0.3 + sirv: 3.0.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vitest: 4.0.18(@types/node@22.19.13)(@vitest/ui@4.0.18)(jiti@2.6.1)(jsdom@24.1.3)(lightningcss@1.31.1) + + '@vitest/utils@4.0.18': + dependencies: + '@vitest/pretty-format': 4.0.18 + tinyrainbow: 3.0.3 + + acorn-jsx@5.3.2(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + + acorn@8.16.0: {} + + agent-base@7.1.4: {} + + ajv@6.14.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.3: {} + + argparse@2.0.1: {} + + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + aria-query@5.3.2: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-includes@3.1.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + math-intrinsics: 1.1.0 + + array.prototype.flat@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-shim-unscopables: 1.1.0 + + array.prototype.flatmap@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-shim-unscopables: 1.1.0 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + assertion-error@2.0.1: {} + + ast-types-flow@0.0.8: {} + + async-function@1.0.0: {} + + asynckit@0.4.0: {} + + autoprefixer@10.4.27(postcss@8.5.8): + dependencies: + browserslist: 4.28.1 + caniuse-lite: 1.0.30001774 + fraction.js: 5.3.4 + picocolors: 1.1.1 + postcss: 8.5.8 + postcss-value-parser: 4.2.0 + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + axe-core@4.11.1: {} + + axobject-query@4.1.0: {} + + balanced-match@1.0.2: {} + + balanced-match@4.0.4: {} + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.10.0: {} + + bignumber.js@9.3.1: {} + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + brace-expansion@5.0.4: + dependencies: + balanced-match: 4.0.4 + + browserslist@4.28.1: + dependencies: + baseline-browser-mapping: 2.10.0 + caniuse-lite: 1.0.30001774 + electron-to-chromium: 1.5.302 + node-releases: 2.0.27 + update-browserslist-db: 1.2.3(browserslist@4.28.1) + + buffer-equal-constant-time@1.0.1: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + 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 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + caniuse-lite@1.0.30001774: {} + + chai@6.2.2: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + concat-map@0.0.1: {} + + convert-source-map@2.0.0: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css.escape@1.5.1: {} + + cssstyle@4.6.0: + dependencies: + '@asamuzakjp/css-color': 3.2.0 + rrweb-cssom: 0.8.0 + + damerau-levenshtein@1.0.8: {} + + data-uri-to-buffer@4.0.1: {} + + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decimal.js@10.6.0: {} + + deep-is@0.1.4: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + delayed-stream@1.0.0: {} + + dequal@2.0.3: {} + + detect-libc@2.1.2: {} + + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + + electron-to-chromium@1.5.302: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + enhanced-resolve@5.20.0: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.0 + + entities@6.0.1: {} + + es-abstract@1.24.1: + 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.20 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@1.7.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-shim-unscopables@1.1.0: + dependencies: + hasown: 2.0.2 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + + escalade@3.2.0: {} + + escape-string-regexp@4.0.0: {} + + eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.3(jiti@2.6.1)): + dependencies: + aria-query: 5.3.2 + array-includes: 3.1.9 + array.prototype.flatmap: 1.3.3 + ast-types-flow: 0.0.8 + axe-core: 4.11.1 + axobject-query: 4.1.0 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + eslint: 9.39.3(jiti@2.6.1) + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.5 + object.fromentries: 2.0.8 + safe-regex-test: 1.1.0 + string.prototype.includes: 2.0.1 + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint-visitor-keys@5.0.1: {} + + eslint@9.39.3(jiti@2.6.1): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.3(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.1 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.4 + '@eslint/js': 9.39.3 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.7 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + ajv: 6.14.0 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.5 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.6.1 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + eslint-visitor-keys: 4.2.1 + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + esutils@2.0.3: {} + + expect-type@1.3.0: {} + + extend@3.0.2: {} + + fast-deep-equal@3.1.3: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 - debug@2.6.9: + fetch-blob@3.2.0: dependencies: - ms: 2.0.0 + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 - debug@4.4.3: + fflate@0.8.2: {} + + file-entry-cache@8.0.0: dependencies: - ms: 2.1.3 + flat-cache: 4.0.1 - depd@2.0.0: {} + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 - destroy@1.2.0: {} + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 - dotenv@16.6.1: {} + flatted@3.3.3: {} - dunder-proto@1.0.1: + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + + fraction.js@5.3.4: {} + + fsevents@2.3.2: + optional: true + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + + gaxios@7.1.3: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + node-fetch: 3.3.2 + rimraf: 5.0.10 + transitivePeerDependencies: + - supports-color + + gcp-metadata@8.1.2: + dependencies: + gaxios: 7.1.3 + google-logging-utils: 1.1.3 + json-bigint: 1.0.0 + transitivePeerDependencies: + - supports-color + + generator-function@2.0.1: {} + + gensync@1.0.0-beta.2: {} + + get-intrinsic@1.3.0: 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 - ee-first@1.1.1: {} + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 - electron-to-chromium@1.5.286: {} + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 - encodeurl@2.0.0: {} + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 - es-define-property@1.0.1: {} + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.9 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 - es-errors@1.3.0: {} + globals@14.0.0: {} - es-object-atoms@1.1.1: + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + google-auth-library@10.6.1: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 7.1.3 + gcp-metadata: 8.1.2 + google-logging-utils: 1.1.3 + jws: 4.0.1 + transitivePeerDependencies: + - supports-color + + google-logging-utils@1.1.3: {} + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + has-bigints@1.1.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + iceberg-js@0.8.1: {} + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + internal-slot@1.1.0: dependencies: es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 - esbuild@0.25.12: + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-callable@1.2.7: {} + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-fullwidth-code-point@3.0.0: {} + + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-map@2.0.3: {} + + is-negative-zero@2.0.3: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-potential-custom-element-name@1.0.1: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.20 + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 optionalDependencies: - '@esbuild/aix-ppc64': 0.25.12 - '@esbuild/android-arm': 0.25.12 - '@esbuild/android-arm64': 0.25.12 - '@esbuild/android-x64': 0.25.12 - '@esbuild/darwin-arm64': 0.25.12 - '@esbuild/darwin-x64': 0.25.12 - '@esbuild/freebsd-arm64': 0.25.12 - '@esbuild/freebsd-x64': 0.25.12 - '@esbuild/linux-arm': 0.25.12 - '@esbuild/linux-arm64': 0.25.12 - '@esbuild/linux-ia32': 0.25.12 - '@esbuild/linux-loong64': 0.25.12 - '@esbuild/linux-mips64el': 0.25.12 - '@esbuild/linux-ppc64': 0.25.12 - '@esbuild/linux-riscv64': 0.25.12 - '@esbuild/linux-s390x': 0.25.12 - '@esbuild/linux-x64': 0.25.12 - '@esbuild/netbsd-arm64': 0.25.12 - '@esbuild/netbsd-x64': 0.25.12 - '@esbuild/openbsd-arm64': 0.25.12 - '@esbuild/openbsd-x64': 0.25.12 - '@esbuild/openharmony-arm64': 0.25.12 - '@esbuild/sunos-x64': 0.25.12 - '@esbuild/win32-arm64': 0.25.12 - '@esbuild/win32-ia32': 0.25.12 - '@esbuild/win32-x64': 0.25.12 + '@pkgjs/parseargs': 0.11.0 - escalade@3.2.0: {} + jiti@2.6.1: {} - escape-html@1.0.3: {} - - etag@1.8.1: {} - - express@4.22.1: - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.4 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.7.2 - cookie-signature: 1.0.7 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.3.2 - fresh: 0.5.2 - http-errors: 2.0.1 - merge-descriptors: 1.0.3 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.12 - proxy-addr: 2.0.7 - qs: 6.14.2 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.19.2 - serve-static: 1.16.3 - setprototypeof: 1.2.0 - statuses: 2.0.2 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 + js-tokens@4.0.0: {} + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsdom@24.1.3: + dependencies: + cssstyle: 4.6.0 + data-urls: 5.0.0 + decimal.js: 10.6.0 + form-data: 4.0.5 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.23 + parse5: 7.3.0 + rrweb-cssom: 0.7.1 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.4 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + ws: 8.19.0 + xml-name-validator: 5.0.0 transitivePeerDependencies: + - bufferutil - supports-color + - utf-8-validate + + jsesc@3.1.0: {} + + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.1 + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + jsx-ast-utils@3.3.5: + dependencies: + array-includes: 3.1.9 + array.prototype.flat: 1.3.3 + object.assign: 4.1.7 + object.values: 1.2.1 + + jwa@2.0.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@4.0.1: + dependencies: + jwa: 2.0.1 + safe-buffer: 5.2.1 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + language-subtag-registry@0.3.23: {} + + language-tags@1.0.9: + dependencies: + language-subtag-registry: 0.3.23 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lightningcss-android-arm64@1.31.1: + optional: true + + lightningcss-darwin-arm64@1.31.1: + optional: true + + lightningcss-darwin-x64@1.31.1: + optional: true + + lightningcss-freebsd-x64@1.31.1: + optional: true + + lightningcss-linux-arm-gnueabihf@1.31.1: + optional: true + + lightningcss-linux-arm64-gnu@1.31.1: + optional: true + + lightningcss-linux-arm64-musl@1.31.1: + optional: true + + lightningcss-linux-x64-gnu@1.31.1: + optional: true - fdir@6.5.0(picomatch@4.0.3): - optionalDependencies: - picomatch: 4.0.3 + lightningcss-linux-x64-musl@1.31.1: + optional: true - finalhandler@1.3.2: - dependencies: - debug: 2.6.9 - encodeurl: 2.0.0 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.2 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color + lightningcss-win32-arm64-msvc@1.31.1: + optional: true - forwarded@0.2.0: {} + lightningcss-win32-x64-msvc@1.31.1: + optional: true - framer-motion@12.33.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + lightningcss@1.31.1: dependencies: - motion-dom: 12.33.0 - motion-utils: 12.29.2 - tslib: 2.8.1 + detect-libc: 2.1.2 optionalDependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - fresh@0.5.2: {} + lightningcss-android-arm64: 1.31.1 + lightningcss-darwin-arm64: 1.31.1 + lightningcss-darwin-x64: 1.31.1 + lightningcss-freebsd-x64: 1.31.1 + lightningcss-linux-arm-gnueabihf: 1.31.1 + lightningcss-linux-arm64-gnu: 1.31.1 + lightningcss-linux-arm64-musl: 1.31.1 + lightningcss-linux-x64-gnu: 1.31.1 + lightningcss-linux-x64-musl: 1.31.1 + lightningcss-win32-arm64-msvc: 1.31.1 + lightningcss-win32-x64-msvc: 1.31.1 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 - fsevents@2.3.3: - optional: true + lodash.merge@4.6.2: {} - function-bind@1.1.2: {} + long@5.3.2: {} - gensync@1.0.0-beta.2: {} + lru-cache@10.4.3: {} - get-intrinsic@1.3.0: + lru-cache@5.1.1: 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 + yallist: 3.1.1 - get-proto@1.0.1: + lz-string@1.5.0: {} + + magic-string@0.30.21: dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 + '@jridgewell/sourcemap-codec': 1.5.5 - gopd@1.2.0: {} + math-intrinsics@1.1.0: {} - has-symbols@1.1.0: {} + mime-db@1.52.0: {} - hasown@2.0.2: + mime-types@2.1.35: dependencies: - function-bind: 1.1.2 + mime-db: 1.52.0 - http-errors@2.0.1: + min-indent@1.0.1: {} + + minimatch@10.2.4: dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.2 - toidentifier: 1.0.1 + brace-expansion: 5.0.4 - iconv-lite@0.4.24: + minimatch@3.1.5: dependencies: - safer-buffer: 2.1.2 + brace-expansion: 1.1.12 - inherits@2.0.4: {} + minimatch@9.0.9: + dependencies: + brace-expansion: 2.0.2 - ipaddr.js@1.9.1: {} + minipass@7.1.3: {} - js-tokens@4.0.0: {} + mrmime@2.0.1: {} - jsesc@3.1.0: {} + ms@2.1.3: {} - json5@2.2.3: {} + nanoid@3.3.11: {} - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 + natural-compare@1.4.0: {} - math-intrinsics@1.1.0: {} + node-domexception@1.0.0: {} - media-typer@0.3.0: {} + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 - merge-descriptors@1.0.3: {} + node-releases@2.0.27: {} - methods@1.1.2: {} + nwsapi@2.2.23: {} - mime-db@1.52.0: {} + object-inspect@1.13.4: {} - mime-types@2.1.35: + object-keys@1.1.1: {} + + object.assign@4.1.7: dependencies: - mime-db: 1.52.0 + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 - mime@1.6.0: {} + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-object-atoms: 1.1.1 - motion-dom@12.33.0: + object.values@1.2.1: dependencies: - motion-utils: 12.29.2 + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 - motion-utils@12.29.2: {} + obug@2.1.1: {} - ms@2.0.0: {} + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 - ms@2.1.3: {} + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 - nanoid@3.3.11: {} + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 - negotiator@0.6.3: {} + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 - node-releases@2.0.27: {} + package-json-from-dist@1.0.1: {} - object-inspect@1.13.4: {} + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 - on-finished@2.4.1: + parse5@7.3.0: dependencies: - ee-first: 1.1.1 + entities: 6.0.1 + + path-exists@4.0.0: {} - parseurl@1.3.3: {} + path-key@3.1.1: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 - path-to-regexp@0.1.12: {} + pathe@2.0.3: {} picocolors@1.1.1: {} picomatch@4.0.3: {} - postcss@8.5.6: + playwright-core@1.58.2: {} + + playwright@1.58.2: + dependencies: + playwright-core: 1.58.2 + optionalDependencies: + fsevents: 2.3.2 + + possible-typed-array-names@1.1.0: {} + + postcss-value-parser@4.2.0: {} + + postcss@8.5.8: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 source-map-js: 1.2.1 - proxy-addr@2.0.7: + prelude-ls@1.2.1: {} + + pretty-format@27.5.1: dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 - qs@6.14.2: + protobufjs@7.5.4: dependencies: - side-channel: 1.1.0 + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 22.19.13 + long: 5.3.2 + + psl@1.15.0: + dependencies: + punycode: 2.3.1 - range-parser@1.2.1: {} + punycode@2.3.1: {} - raw-body@2.5.3: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.1 - iconv-lite: 0.4.24 - unpipe: 1.0.0 + querystringify@2.2.0: {} react-dom@19.2.4(react@19.2.4): dependencies: react: 19.2.4 scheduler: 0.27.0 + react-is@17.0.2: {} + react-refresh@0.18.0: {} react@19.2.4: {} - rollup@4.57.1: + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regexp.prototype.flags@1.5.4: + 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 + + requires-port@1.0.0: {} + + resolve-from@4.0.0: {} + + retry@0.13.1: {} + + rimraf@5.0.10: + dependencies: + glob: 10.5.0 + + rollup@4.59.0: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.57.1 - '@rollup/rollup-android-arm64': 4.57.1 - '@rollup/rollup-darwin-arm64': 4.57.1 - '@rollup/rollup-darwin-x64': 4.57.1 - '@rollup/rollup-freebsd-arm64': 4.57.1 - '@rollup/rollup-freebsd-x64': 4.57.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.57.1 - '@rollup/rollup-linux-arm-musleabihf': 4.57.1 - '@rollup/rollup-linux-arm64-gnu': 4.57.1 - '@rollup/rollup-linux-arm64-musl': 4.57.1 - '@rollup/rollup-linux-loong64-gnu': 4.57.1 - '@rollup/rollup-linux-loong64-musl': 4.57.1 - '@rollup/rollup-linux-ppc64-gnu': 4.57.1 - '@rollup/rollup-linux-ppc64-musl': 4.57.1 - '@rollup/rollup-linux-riscv64-gnu': 4.57.1 - '@rollup/rollup-linux-riscv64-musl': 4.57.1 - '@rollup/rollup-linux-s390x-gnu': 4.57.1 - '@rollup/rollup-linux-x64-gnu': 4.57.1 - '@rollup/rollup-linux-x64-musl': 4.57.1 - '@rollup/rollup-openbsd-x64': 4.57.1 - '@rollup/rollup-openharmony-arm64': 4.57.1 - '@rollup/rollup-win32-arm64-msvc': 4.57.1 - '@rollup/rollup-win32-ia32-msvc': 4.57.1 - '@rollup/rollup-win32-x64-gnu': 4.57.1 - '@rollup/rollup-win32-x64-msvc': 4.57.1 + '@rollup/rollup-android-arm-eabi': 4.59.0 + '@rollup/rollup-android-arm64': 4.59.0 + '@rollup/rollup-darwin-arm64': 4.59.0 + '@rollup/rollup-darwin-x64': 4.59.0 + '@rollup/rollup-freebsd-arm64': 4.59.0 + '@rollup/rollup-freebsd-x64': 4.59.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 + '@rollup/rollup-linux-arm-musleabihf': 4.59.0 + '@rollup/rollup-linux-arm64-gnu': 4.59.0 + '@rollup/rollup-linux-arm64-musl': 4.59.0 + '@rollup/rollup-linux-loong64-gnu': 4.59.0 + '@rollup/rollup-linux-loong64-musl': 4.59.0 + '@rollup/rollup-linux-ppc64-gnu': 4.59.0 + '@rollup/rollup-linux-ppc64-musl': 4.59.0 + '@rollup/rollup-linux-riscv64-gnu': 4.59.0 + '@rollup/rollup-linux-riscv64-musl': 4.59.0 + '@rollup/rollup-linux-s390x-gnu': 4.59.0 + '@rollup/rollup-linux-x64-gnu': 4.59.0 + '@rollup/rollup-linux-x64-musl': 4.59.0 + '@rollup/rollup-openbsd-x64': 4.59.0 + '@rollup/rollup-openharmony-arm64': 4.59.0 + '@rollup/rollup-win32-arm64-msvc': 4.59.0 + '@rollup/rollup-win32-ia32-msvc': 4.59.0 + '@rollup/rollup-win32-x64-gnu': 4.59.0 + '@rollup/rollup-win32-x64-msvc': 4.59.0 fsevents: 2.3.3 + rrweb-cssom@0.7.1: {} + + rrweb-cssom@0.8.0: {} + + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + safe-buffer@5.2.1: {} + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + safer-buffer@2.1.2: {} + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scheduler@0.27.0: {} semver@6.3.1: {} - send@0.19.2: - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.1 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color + semver@7.7.4: {} - serve-static@1.16.3: + set-function-length@1.2.2: dependencies: - encodeurl: 2.0.0 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.19.2 - transitivePeerDependencies: - - supports-color + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 - setprototypeof@1.2.0: {} + shebang-regex@3.0.0: {} side-channel-list@1.0.0: dependencies: @@ -1671,29 +4474,182 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + sirv@3.0.2: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + source-map-js@1.2.1: {} - statuses@2.0.2: {} + stackback@0.0.2: {} + + std-env@3.10.0: {} + + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + + string.prototype.includes@2.0.1: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strip-json-comments@3.1.1: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + symbol-tree@3.2.4: {} + + tailwindcss@4.2.1: {} + + tapable@2.3.0: {} + + tinybench@2.9.0: {} + + tinyexec@1.0.2: {} tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 - toidentifier@1.0.1: {} + tinyrainbow@3.0.3: {} + + totalist@3.0.1: {} + + tough-cookie@4.1.4: + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + + tr46@5.1.1: + dependencies: + punycode: 2.3.1 + + ts-api-utils@2.4.0(typescript@5.8.3): + dependencies: + typescript: 5.8.3 tslib@2.8.1: {} - type-is@1.6.18: + type-check@0.4.0: dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 + prelude-ls: 1.2.1 + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typescript-eslint@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/parser': 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.8.3) + '@typescript-eslint/utils': 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.8.3) + eslint: 9.39.3(jiti@2.6.1) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color typescript@5.8.3: {} + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + undici-types@6.21.0: {} - unpipe@1.0.0: {} + universalify@0.2.0: {} update-browserslist-db@1.2.3(browserslist@4.28.1): dependencies: @@ -1701,20 +4657,157 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - utils-merge@1.0.1: {} + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 - vary@1.1.2: {} + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 - vite@6.4.1(@types/node@22.19.9): + vite@6.4.1(@types/node@22.19.13)(jiti@2.6.1)(lightningcss@1.31.1): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 - postcss: 8.5.6 - rollup: 4.57.1 + postcss: 8.5.8 + rollup: 4.59.0 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 22.19.9 + '@types/node': 22.19.13 fsevents: 2.3.3 + jiti: 2.6.1 + lightningcss: 1.31.1 + + vitest@4.0.18(@types/node@22.19.13)(@vitest/ui@4.0.18)(jiti@2.6.1)(jsdom@24.1.3)(lightningcss@1.31.1): + dependencies: + '@vitest/expect': 4.0.18 + '@vitest/mocker': 4.0.18(vite@6.4.1(@types/node@22.19.13)(jiti@2.6.1)(lightningcss@1.31.1)) + '@vitest/pretty-format': 4.0.18 + '@vitest/runner': 4.0.18 + '@vitest/snapshot': 4.0.18 + '@vitest/spy': 4.0.18 + '@vitest/utils': 4.0.18 + es-module-lexer: 1.7.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vite: 6.4.1(@types/node@22.19.13)(jiti@2.6.1)(lightningcss@1.31.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.19.13 + '@vitest/ui': 4.0.18(vitest@4.0.18) + jsdom: 24.1.3 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - yaml + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + + web-streams-polyfill@3.3.3: {} + + webidl-conversions@7.0.0: {} + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + + whatwg-url@14.2.0: + dependencies: + tr46: 5.1.1 + webidl-conversions: 7.0.0 + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.2 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.20 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.20: + 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 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + + ws@8.19.0: {} + + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} yallist@3.1.1: {} + + yocto-queue@0.1.0: {} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..1c87846 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + '@tailwindcss/postcss': {}, + autoprefixer: {}, + }, +} diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png deleted file mode 100644 index b10601f..0000000 Binary files a/public/apple-touch-icon.png and /dev/null differ diff --git a/public/apple-touch-icon.svg b/public/apple-touch-icon.svg new file mode 100644 index 0000000..72ee6ee --- /dev/null +++ b/public/apple-touch-icon.svg @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MONYNHA + SOFTWARES + diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png deleted file mode 100644 index 300b9ae..0000000 Binary files a/public/favicon-16x16.png and /dev/null differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png deleted file mode 100644 index 90844f0..0000000 Binary files a/public/favicon-32x32.png and /dev/null differ diff --git a/public/favicon-48x48.png b/public/favicon-48x48.png deleted file mode 100644 index 6bcf0a5..0000000 Binary files a/public/favicon-48x48.png and /dev/null differ diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index 612dc1d..0000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/public/favicon.svg b/public/favicon.svg index 98edb9b..72ee6ee 100644 --- a/public/favicon.svg +++ b/public/favicon.svg @@ -1,12 +1,100 @@ - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MONYNHA + SOFTWARES diff --git a/public/manifest.webmanifest b/public/manifest.webmanifest new file mode 100644 index 0000000..0eed751 --- /dev/null +++ b/public/manifest.webmanifest @@ -0,0 +1,13 @@ +{ + "name": "Monynha Softwares", + "short_name": "Monynha", + "description": "Diagnóstico digital e automação centrada no humano.", + "start_url": "/", + "display": "standalone", + "background_color": "#171220", + "theme_color": "#171220", + "icons": [ + { "src": "/favicon.svg", "sizes": "64x64", "type": "image/svg+xml", "purpose": "any" }, + { "src": "/apple-touch-icon.svg", "sizes": "180x180", "type": "image/svg+xml", "purpose": "any" } + ] +} diff --git a/public/og-cover.svg b/public/og-cover.svg new file mode 100644 index 0000000..d63648e --- /dev/null +++ b/public/og-cover.svg @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ONDE A ENGENHARIA ENCONTRA A INTUIÇÃO + + + + + + + + + + + + + + MONYNHA + + + SOFTWARES + + + + + + + monynha.com + + + diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..7f731d3 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://monynha.com/sitemap.xml diff --git a/public/sitemap.xml b/public/sitemap.xml new file mode 100644 index 0000000..cd6083f --- /dev/null +++ b/public/sitemap.xml @@ -0,0 +1,42 @@ + + + + https://monynha.com/ + 2026-03-07 + weekly + 1 + + + https://monynha.com/about + 2026-03-07 + monthly + 0.8 + + + https://monynha.com/projects + 2026-03-07 + monthly + 0.7 + + + https://monynha.com/privacy + 2026-03-07 + yearly + 0.3 + + + https://monynha.com/terms + 2026-03-07 + yearly + 0.3 + + + https://monynha.com/cookies + 2026-03-07 + yearly + 0.3 + + \ No newline at end of file diff --git a/scripts/generate-sitemap.js b/scripts/generate-sitemap.js new file mode 100644 index 0000000..9e203ef --- /dev/null +++ b/scripts/generate-sitemap.js @@ -0,0 +1,89 @@ +#!/usr/bin/env node +import { writeFileSync } from 'fs'; +import { join, dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +// Base URL do projeto +const BASE_URL = 'https://monynha.com'; + +// Definir as rotas do projeto +// Como é uma SPA (Single Page Application), todas as rotas são servidas pela mesma página +// mas podemos incluir as principais views para SEO +const routes = [ + { + path: '/', + changefreq: 'weekly', + priority: 1.0, + lastmod: new Date().toISOString().split('T')[0] + }, + { + path: '/about', + changefreq: 'monthly', + priority: 0.8, + lastmod: new Date().toISOString().split('T')[0] + }, + { + path: '/projects', + changefreq: 'monthly', + priority: 0.7, + lastmod: new Date().toISOString().split('T')[0] + }, + { + path: '/privacy', + changefreq: 'yearly', + priority: 0.3, + lastmod: new Date().toISOString().split('T')[0] + }, + { + path: '/terms', + changefreq: 'yearly', + priority: 0.3, + lastmod: new Date().toISOString().split('T')[0] + }, + { + path: '/cookies', + changefreq: 'yearly', + priority: 0.3, + lastmod: new Date().toISOString().split('T')[0] + } +]; + +// Gerar o conteúdo do sitemap +function generateSitemap() { + const xml = ` + +${routes.map(route => ` + ${BASE_URL}${route.path} + ${route.lastmod} + ${route.changefreq} + ${route.priority} + `).join('\n')} +`; + + return xml; +} + +// Salvar o sitemap no diretório public +function saveSitemap() { + const sitemap = generateSitemap(); + const outputPath = join(__dirname, '..', 'public', 'sitemap.xml'); + + try { + writeFileSync(outputPath, sitemap, 'utf-8'); + console.log('✅ Sitemap gerado com sucesso em public/sitemap.xml'); + console.log(`📝 ${routes.length} URLs incluídas no sitemap`); + console.log(`🔗 Base URL: ${BASE_URL}`); + } catch (error) { + console.error('❌ Erro ao gerar sitemap:', error); + process.exit(1); + } +} + +// Executar +saveSitemap(); diff --git a/scripts/generate_favicon.py b/scripts/generate_favicon.py deleted file mode 100644 index f7cf104..0000000 --- a/scripts/generate_favicon.py +++ /dev/null @@ -1,92 +0,0 @@ -from pathlib import Path -from PIL import Image, ImageDraw - -root = Path(__file__).resolve().parents[1] -public_dir = root / "public" -public_dir.mkdir(parents=True, exist_ok=True) - -sizes = { - "favicon-16x16.png": 16, - "favicon-32x32.png": 32, - "favicon-48x48.png": 48, - "apple-touch-icon.png": 180, -} - -background = (5, 7, 10, 255) -border_color = (255, 255, 255, 64) -grad_start = (139, 92, 246, 255) -grad_end = (60, 131, 246, 255) -dot_color = (139, 92, 246, 255) - -def lerp(a: int, b: int, t: float) -> int: - return int(a + (b - a) * t) - -def color_lerp(c1, c2, t: float): - return ( - lerp(c1[0], c2[0], t), - lerp(c1[1], c2[1], t), - lerp(c1[2], c2[2], t), - lerp(c1[3], c2[3], t), - ) - -def draw_gradient_path(draw: ImageDraw.ImageDraw, points, width: int): - total = sum(((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5 for (x1, y1), (x2, y2) in zip(points, points[1:])) - if total == 0: - return - traveled = 0.0 - for (x1, y1), (x2, y2) in zip(points, points[1:]): - segment = ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5 - steps = max(2, int(segment)) - for step in range(steps): - t0 = step / steps - t1 = (step + 1) / steps - sx1 = x1 + (x2 - x1) * t0 - sy1 = y1 + (y2 - y1) * t0 - sx2 = x1 + (x2 - x1) * t1 - sy2 = y1 + (y2 - y1) * t1 - ratio = (traveled + segment * t0) / total - color = color_lerp(grad_start, grad_end, ratio) - draw.line([(sx1, sy1), (sx2, sy2)], fill=color, width=width) - traveled += segment - -def render_logo(size: int) -> Image.Image: - scale = 4 - canvas = size * scale - img = Image.new("RGBA", (canvas, canvas), background) - draw = ImageDraw.Draw(img) - - border = max(1, int(2 * scale)) - draw.rectangle([border, border, canvas - border, canvas - border], outline=border_color, width=border) - - def sx(value: float) -> float: - return value * canvas / 100.0 - - stroke_width = max(1, int(10 * scale)) - points = [ - (sx(20), sx(80)), - (sx(20), sx(25)), - (sx(50), sx(55)), - (sx(80), sx(25)), - (sx(80), sx(80)), - ] - draw_gradient_path(draw, points, stroke_width) - - dot_r = sx(5) - draw.ellipse( - [sx(50) - dot_r, sx(75) - dot_r, sx(50) + dot_r, sx(75) + dot_r], - fill=dot_color, - ) - - return img.resize((size, size), Image.Resampling.LANCZOS) - -for name, size in sizes.items(): - out_path = public_dir / name - render_logo(size).save(out_path) - -ico_path = public_dir / "favicon.ico" -images = [ - Image.open(public_dir / "favicon-16x16.png"), - Image.open(public_dir / "favicon-32x32.png"), - Image.open(public_dir / "favicon-48x48.png"), -] -images[0].save(ico_path, format="ICO", sizes=[(16, 16), (32, 32), (48, 48)]) diff --git a/scripts/generate_sitemap.mjs b/scripts/generate_sitemap.mjs deleted file mode 100644 index cf3772c..0000000 --- a/scripts/generate_sitemap.mjs +++ /dev/null @@ -1,30 +0,0 @@ -import { promises as fs } from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const root = path.resolve(__dirname, '..'); -const distDir = path.join(root, 'dist'); -const siteUrl = (process.env.SITE_URL || process.env.VITE_SITE_URL || 'http://localhost:3000').replace(/\/$/, ''); - -const routes = [ - '/', -]; - -const urls = routes - .map((route) => { - const loc = `${siteUrl}${route}`; - return ` \n ${loc}\n weekly\n 0.8\n `; - }) - .join('\n'); - -const sitemap = `\n` + - `\n${urls}\n\n`; - -await fs.mkdir(distDir, { recursive: true }); -await fs.writeFile(path.join(distDir, 'sitemap.xml'), sitemap, 'utf8'); - -if (!process.env.SITE_URL && !process.env.VITE_SITE_URL) { - console.warn('Sitemap generated with default SITE_URL. Set SITE_URL to your production domain.'); -} diff --git a/server.js b/server.js deleted file mode 100644 index e4d0ca8..0000000 --- a/server.js +++ /dev/null @@ -1,171 +0,0 @@ -/** - * Monynha Softwares - Production Server - * Express server with static file serving and API endpoints - */ - -import express from 'express'; -import { fileURLToPath } from 'url'; -import { dirname, join } from 'path'; -import dotenv from 'dotenv'; - -// Load environment variables -dotenv.config({ path: '.env.local' }); - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -const app = express(); -const PORT = process.env.PORT || 8080; - -// Middleware -app.use(express.json()); -app.use(express.urlencoded({ extended: true })); - -// Logging middleware -app.use((req, res, next) => { - console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`); - next(); -}); - -// API Routes -app.all('/api/contact', (req, res, next) => { - if (req.method !== 'POST') { - res.setHeader('Allow', ['POST']); - return res.status(405).json({ - error: `Method ${req.method} Not Allowed. Use POST to submit the contact form.` - }); - } - next(); -}); - -app.post('/api/contact', async (req, res) => { - const { name, email, tel, company, message } = req.body; - - // Validate required fields - if (!name || !email || !message) { - return res.status(400).json({ - error: 'Missing required fields: name, email, and message are mandatory.' - }); - } - - const RESEND_API_KEY = process.env.RESEND_API_KEY; - - if (!RESEND_API_KEY) { - console.error('[SERVER ERROR] RESEND_API_KEY environment variable is missing.'); - return res.status(500).json({ - error: 'The email service is not properly configured on the server.' - }); - } - - try { - const resendResponse = await fetch('https://api.resend.com/emails', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${RESEND_API_KEY}`, - }, - body: JSON.stringify({ - from: 'Monynha Softwares ', - to: 'hello@monynha.com', - subject: `New contact form submission — ${name}`, - reply_to: email, - html: ` - - - - - - -
-
-

New Studio Signal

-
- -
-
Name / Identity
-
${name}
- -
Email Address
-
${email}
- -
Phone / WhatsApp
-
${tel || 'Not provided'}
- -
Company / Project
-
${company || 'Not provided'}
- -
-
Message Context
-

${message}

-
-
- - -
- - - `, - }), - }); - - const result = await resendResponse.json(); - - if (resendResponse.ok) { - console.log(`[EMAIL SENT] Contact form submission from ${name} (${email}) - ID: ${result.id}`); - return res.status(200).json({ success: true, id: result.id }); - } else { - console.error('[RESEND ERROR]', result); - return res.status(resendResponse.status).json({ - error: result.message || 'The email service rejected the transmission. Please check the logs.' - }); - } - } catch (error) { - console.error('[INTERNAL ERROR]', error); - return res.status(500).json({ - error: 'A critical error occurred while attempting to deliver the signal.' - }); - } -}); - -// Handle 404 for API routes -app.use('/api/*', (req, res) => { - res.status(404).json({ - error: 'API endpoint not found. Check the URL and try again.' - }); -}); - -// Serve static files from the dist directory -app.use(express.static(join(__dirname, 'dist'))); - -// SPA fallback - serve index.html for all other routes -app.get('*', (req, res) => { - res.sendFile(join(__dirname, 'dist', 'index.html')); -}); - -// Start server -app.listen(PORT, () => { - console.log(` -╔══════════════════════════════════════════════════════╗ -║ Monynha Softwares Server ║ -║ Running on port ${PORT} ║ -║ Environment: ${process.env.NODE_ENV || 'development'} ║ -║ API Endpoint: POST /api/contact ║ -╚══════════════════════════════════════════════════════╝ - `); - - if (!process.env.RESEND_API_KEY) { - console.warn('⚠️ WARNING: RESEND_API_KEY is not set. Contact form will not work.'); - } else { - console.log('✅ Email service configured'); - } -}); diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..8929242 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,215 @@ +import React, { useState, useEffect } from 'react'; +import Landing from './components/Landing'; +import Wizard from './components/Wizard'; +import LoadingScreen from './components/LoadingScreen'; +import Report from './components/Report'; +import IntroScene from './components/IntroScene'; +import FairyCursor from './components/FairyCursor'; +import AboutSite from './components/AboutSite'; +import LegalPages from './components/LegalPages'; +import ProjectsPage from './components/ProjectsPage'; +import { LeadData, DiagnosisResult } from './types'; +import { generateDiagnosis, sendDiagnosticEmail, sendContactConfirmation, saveLead } from './services'; + +export enum AppState { + INTRO, + LANDING, + WIZARD, + LOADING, + REPORT, + ABOUT, + PROJECTS, + LEGAL +} + +export type LegalType = 'privacy' | 'terms' | 'cookies'; + +const VIEW_META: Record = { + [AppState.INTRO]: { + title: 'Monynha Softwares | Introdução', + description: 'Conheça a Monynha Softwares e inicie seu diagnóstico digital estratégico.', + canonical: 'https://monynha.com/' + }, + [AppState.LANDING]: { + title: 'Monynha Softwares | Diagnóstico Digital e Automação', + description: 'Transforme seu caos em faturamento com diagnóstico digital estratégico e automação centrada no humano.', + canonical: 'https://monynha.com/' + }, + [AppState.WIZARD]: { + title: 'Monynha Softwares | Formulário de Diagnóstico', + description: 'Responda ao formulário da Monynha Softwares para receber um plano de ação digital personalizado.', + canonical: 'https://monynha.com/' + }, + [AppState.LOADING]: { + title: 'Monynha Softwares | Processando Diagnóstico', + description: 'Estamos processando seu diagnóstico digital personalizado.', + canonical: 'https://monynha.com/' + }, + [AppState.REPORT]: { + title: 'Monynha Softwares | Relatório de Diagnóstico', + description: 'Veja o relatório completo do seu diagnóstico com recomendações de crescimento.', + canonical: 'https://monynha.com/' + }, + [AppState.ABOUT]: { + title: 'Monynha Softwares | Sobre', + description: 'Conheça os laboratórios e a abordagem da Monynha Softwares para produtos digitais.', + canonical: 'https://monynha.com/' + }, + [AppState.PROJECTS]: { + title: 'Monynha Softwares | Criaturas do Estúdio', + description: 'Explore o ecossistema completo de produtos e experimentos da Monynha Softwares.', + canonical: 'https://monynha.com/projects' + }, + [AppState.LEGAL]: { + title: 'Monynha Softwares | Políticas Legais', + description: 'Acesse a política de privacidade, termos de uso e política de cookies.', + canonical: 'https://monynha.com/' + } +}; + +const App: React.FC = () => { + const [view, setView] = useState(AppState.INTRO); + const [isTransitioning, setIsTransitioning] = useState(false); + const [leadData, setLeadData] = useState(null); + const [diagnosis, setDiagnosis] = useState(null); + const [error, setError] = useState(null); + const [activeLegal, setActiveLegal] = useState('privacy'); + + useEffect(() => { + const meta = VIEW_META[view]; + document.title = meta.title; + + const description = document.querySelector('meta[name="description"]'); + if (description) description.setAttribute('content', meta.description); + + const canonical = document.querySelector('link[rel="canonical"]'); + if (canonical) canonical.setAttribute('href', meta.canonical); + }, [view]); + + const transitionTo = (newState: AppState) => { + setIsTransitioning(true); + setTimeout(() => { + setView(newState); + setIsTransitioning(false); + }, 600); + }; + + const startWizard = () => { + setError(null); + transitionTo(AppState.WIZARD); + }; + + const exploreMonynha = () => { + transitionTo(AppState.ABOUT); + }; + + const finishIntro = () => { + setIsTransitioning(true); + setTimeout(() => { + setView(AppState.LANDING); + setIsTransitioning(false); + }, 800); + }; + + const handleOpenLegal = (type: LegalType) => { + setActiveLegal(type); + transitionTo(AppState.LEGAL); + }; + + const handleWizardComplete = async (data: LeadData) => { + setLeadData(data); + setView(AppState.LOADING); + + // ALWAYS send contact confirmation first (fallback mechanism) + // This guarantees user and team are notified regardless of diagnosis success + try { + await sendContactConfirmation(data); + console.log('✓ Contact confirmation sent successfully'); + } catch (confirmError) { + console.error('⚠️ Contact confirmation failed:', confirmError); + // Continue anyway - don't block the diagnosis flow + } + + try { + const diagResult = await generateDiagnosis(data); + setDiagnosis(diagResult); + + const [saveResult, emailResult] = await Promise.allSettled([ + saveLead(data, diagResult), + sendDiagnosticEmail(data, diagResult), + ]); + + if (saveResult.status === 'rejected') { + console.error('Lead persistence failed:', saveResult.reason); + } + + if (emailResult.status === 'rejected') { + console.error('Diagnostic email failed:', emailResult.reason); + } + + setTimeout(() => transitionTo(AppState.REPORT), 3000); + } catch (err) { + console.error('Error processing wizard:', err); + + // Even if diagnosis fails, user already received confirmation email + // Show error but acknowledge we captured their contact + setError('Mona, o diagnóstico automático deu problema, mas já recebemos teu contato e vamos te responder em breve!'); + setView(AppState.WIZARD); + } + }; + + const handleReset = () => { + setDiagnosis(null); + setLeadData(null); + setError(null); + transitionTo(AppState.LANDING); + }; + + const handleExploreFromReport = () => { + transitionTo(AppState.ABOUT); + }; + + const handleViewProjects = () => { + transitionTo(AppState.PROJECTS); + }; + + return ( +
+ + + + ); +}; + +export default App; diff --git a/src/components/AboutSite.tsx b/src/components/AboutSite.tsx new file mode 100644 index 0000000..11fd442 --- /dev/null +++ b/src/components/AboutSite.tsx @@ -0,0 +1,564 @@ +import React, { useState, useEffect, useCallback, useRef } from 'react'; +import ProjectCarousel from './ProjectCarousel'; + +interface TeamMember { + name: string; + role: string; + bio: string; + fullBio: string; + seed: string; + specialties: string[]; +} + +interface AboutSiteProps { + onBack: () => void; + onStartWizard: () => void; + onOpenLegal: (type: 'privacy' | 'terms' | 'cookies') => void; + onViewProjects: () => void; +} + +const SECTIONS = [ + { id: 'manifesto', label: 'Manifesto' }, + { id: 'solucoes', label: 'Soluções' }, + { id: 'criaturas', label: 'Criaturas' }, + { id: 'colmeia', label: 'Time' }, + { id: 'contato', label: 'Contato' } +]; + +const TEAM_MEMBERS: TeamMember[] = [ + { + name: 'Marcelo Santos', + role: 'Fundador · Engenheiro de Software', + bio: 'Foco em automação, IA aplicada e desenvolvimento full-stack.', + fullBio: 'Marcelo combina profundidade técnica com uma mentalidade voltada para o produto, liderando a visão da Monynha. Sua paixão é o Odoo e criar arquiteturas que eliminam o atrito, permitindo que as marcas foquem no que fazem de melhor: brilhar.', + seed: 'marina', + specialties: ['Arquitetura Odoo', 'Integração de IA', 'Sistemas Full-Stack'] + }, + { + name: 'Marina Melucci', + role: 'Especialista em Presença Digital', + bio: 'Mestra da visibilidade e storytelling de impacto.', + fullBio: 'Marina entende que presença é resistência. Ela ajuda as marcas a encontrar sua voz autêntica e cortar o ruído digital com estratégias de conteúdo que constroem comunidades reais.', + seed: 'marcelo', + specialties: ['Conteúdo SEO', 'Estratégia de Branding', 'Impacto Social'] + }, + { + name: 'Tércio Barreto', + role: 'Colaborador · Estratégia', + bio: 'Especialista em estratégia tecnológica e pensamento sistêmico.', + fullBio: 'Tércio alinha a tecnologia com as necessidades reais de negócio. Ele faz a ponte entre a visão e a execução, garantindo que cada roadmap técnico esteja ancorado em crescimento estratégico e clareza operacional.', + seed: 'tercio', + specialties: ['Estratégia Tech', 'Pensamento Sistêmico', 'Operações Ágeis'] + }, + { + name: 'Samuel Souza', + role: 'UI/UX Designer', + bio: 'Criando experiências visuais que conectam e inspiram.', + fullBio: 'Samuel transforma ideias complexas em interfaces intuitivas e visualmente impactantes. Com foco em design centrado no usuário, ele garante que cada pixel conte uma história e cada interação seja memorável.', + seed: 'samuel', + specialties: ['Design de Interface', 'Prototipagem', 'Design System'] + } +]; + +const AboutSite: React.FC = ({ onBack, onStartWizard, onOpenLegal, onViewProjects }) => { + const [activeSection, setActiveSection] = useState('manifesto'); + const [selectedMember, setSelectedMember] = useState(null); + const [eggActive, setEggActive] = useState(false); + const [mobileMenuOpen, setMobileMenuOpen] = useState(false); + + const clickTracker = useRef({ count: 0, lastTime: 0 }); + const modalCloseButtonRef = useRef(null); + const lastFocusedElementRef = useRef(null); + + // Calculate navbar height for accurate offset + const getNavbarHeight = useCallback(() => { + const navbar = document.querySelector('nav'); + return navbar ? navbar.offsetHeight : 80; + }, []); + + useEffect(() => { + const handleScroll = () => { + const navbarHeight = getNavbarHeight(); + const scrollPosition = window.scrollY + navbarHeight + 40; // Add 40px buffer + + for (let i = SECTIONS.length - 1; i >= 0; i--) { + const el = document.getElementById(SECTIONS[i].id); + if (el && el.offsetTop <= scrollPosition) { + setActiveSection(SECTIONS[i].id); + break; + } + } + }; + window.addEventListener('scroll', handleScroll); + handleScroll(); + return () => window.removeEventListener('scroll', handleScroll); + }, [getNavbarHeight]); + + // Lock body scroll when mobile menu is open + useEffect(() => { + if (mobileMenuOpen) { + document.body.style.overflow = 'hidden'; + } else { + document.body.style.overflow = ''; + } + return () => { + document.body.style.overflow = ''; + }; + }, [mobileMenuOpen]); + + useEffect(() => { + if (!selectedMember) return; + + lastFocusedElementRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null; + + const focusTimer = setTimeout(() => { + modalCloseButtonRef.current?.focus(); + }, 0); + + const handleEscClose = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + setSelectedMember(null); + } + }; + + document.addEventListener('keydown', handleEscClose); + + return () => { + clearTimeout(focusTimer); + document.removeEventListener('keydown', handleEscClose); + lastFocusedElementRef.current?.focus(); + }; + }, [selectedMember]); + + const scrollTo = useCallback((id: string) => { + const el = document.getElementById(id); + if (el) { + const navbarHeight = getNavbarHeight(); + const offset = 20; // Extra spacing so title isn't flush with navbar + const top = el.offsetTop - navbarHeight - offset; + + window.scrollTo({ + top: Math.max(0, top), + behavior: 'smooth' + }); + + setActiveSection(id); + setMobileMenuOpen(false); // Close mobile menu after navigation + } + }, [getNavbarHeight]); + + return ( +
+ + + {/* Team Modal */} + {selectedMember && ( +
+ +
+ +
+
+
+ {selectedMember.name} +
+
+
+

{selectedMember.name}

+

{selectedMember.role}

+

{selectedMember.fullBio}

+
+ {selectedMember.specialties.map(s => ( + {s} + ))} +
+
+
+
+
+ )} + + {/* Navigation */} + + + {/* Mobile Menu Overlay */} + {mobileMenuOpen && ( +
+ +
+ {SECTIONS.map(s => ( + + ))} +
+
+ )} + +
+ + {/* HERO / MANIFESTO */} +
+
Automação Centrada no Humano
+

+ ENGENHARIA
+ ENCONTRA A
+ INTUIÇÃO. +

+

+ Nós conectamos o abismo entre engenharia complexa e intuição humana. + Criando produtos digitais que não apenas funcionam — eles respiram. +

+
+
+

Nossa Missão

+

Democratizar a tecnologia e combater o amadorismo. Damos voz a quem cria fora do padrão, transformando o caos em faturamento real e sustentável.

+
+
+

Personalidade na Engenharia

+

Software não é neutro. Cada linha de código é uma decisão cultural. Na Monynha, unimos rigor técnico com a sensibilidade necessária para impactar pessoas.

+
+
+
+ + {/* SOLUTIONS */} +
+
+

O que fazemos

+
+
+
+ {[ + { + title: 'Expertise Odoo', + desc: 'Transformando o caos empresarial em clareza sinfônica. Implementações customizadas que empoderam suas pessoas.', + icon: 'settings_suggest', + benefits: ['Arquitetura ERP', 'Fluxos Customizados', 'Sincronização de API'], + subtitle: 'Escalabilidade. Precisão. Intuição.' + }, + { + title: 'Software Sob Medida', + desc: 'Sem templates. Código escrito para resolver seus desafios culturais e técnicos específicos.', + icon: 'terminal', + benefits: ['Ferramentas Internas', 'Plataformas Escaláveis', 'Excelência em UX'] + }, + { + title: 'IA como Colaboradora', + desc: 'Além do hype. Integramos assistentes inteligentes que entendem contexto e intenção humana.', + icon: 'psychology', + benefits: ['Arquiteturas RAG', 'Agentes Autônomos', 'IA Open-source'] + }, + { + title: 'Presença Digital', + desc: 'SEO, Branding Digital e Visibilidade para marcas que querem dominar o feed e o mercado.', + icon: 'campaign', + benefits: ['SEO Conteúdo', 'Branding Digital', 'Impacto Visual'], + highlight: true + } + ].map((s, i) => ( +
+
+ {s.icon} +
+ {s.subtitle &&

{s.subtitle}

} +

{s.title}

+

{s.desc}

+
+ {s.benefits.map(b => ( + {b} + ))} +
+
+ ))} +
+
+ + {/* STUDIO CREATURES / CRIATURAS DO ESTÚDIO */} +
+
+
+

Criaturas do Estúdio

+
+
+

Nossos produtos estáveis e experimentos do Lab.

+

+ Explore the living ecosystem of Monynha Softwares — from production-ready platforms to experimental lab initiatives. Every creature has a purpose, a soul, and a bit of resistance coded into it. +

+
+ + {/* Project Carousel */} + +
+ + {/* TEAM / A COLMEIA */} +
+
+

A Colmeia

+
+
+
+ {TEAM_MEMBERS.map((m, i) => ( + + ))} +
+
+ + {/* CONTACT / CONTATO */} +
+
+
+ + {/* Left Content */} +
+

+ BORA SIMPLIFICAR O
+ CAOS DIGITAL? +

+ +

+ Sem pressão, só uma conversa sobre o futuro do seu negócio. +

+ + +
+ mail +
+ hello@monynha.com +
+
+ + {/* Right CTA Buttons */} +
+ + + + + + + Falar no WhatsApp + +
+ +
+
+
+ + {/* FINAL CTA */} +
+

Pronta para
brilhar?

+

Vamos construir algo que importa. Sem pressão de vendas, apenas uma conversa estratégica.

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

Um estúdio de software inclusivo sediado remotamente em Portugal (Remote-first).

+
+
+
+
Social
+ +
+
+
Monynha Ecosystem
+

Building digital products, platforms, and scalable systems.

+ +
+
+
Legal
+
    +
  • +
  • +
+
+
+
+
+

© {new Date().getFullYear()} Monynha Softwares • Engenharia com personalidade.

+

Portugal / Remoto

+
+
+
+ ); +}; + +export default AboutSite; diff --git a/src/components/FairyCursor.tsx b/src/components/FairyCursor.tsx new file mode 100644 index 0000000..315e8a8 --- /dev/null +++ b/src/components/FairyCursor.tsx @@ -0,0 +1,146 @@ +import React, { useEffect, useState, useRef } from 'react'; + +const COLORS = ['#9767e4', '#FF0080', '#00E5FF', '#FFD600', '#76FF03', '#FFFFFF']; + +const FairyCursor: React.FC = () => { + const [pos, setPos] = useState({ x: -100, y: -100 }); + const [trail, setTrail] = useState<{ id: number; x: number; y: number; color: string }[]>([]); + const [isHovering, setIsHovering] = useState(false); + const trailId = useRef(0); + const lastTrailTime = useRef(0); + + useEffect(() => { + // Check if device supports fine pointer (mouse) + const isTouch = window.matchMedia("(pointer: coarse)").matches; + if (isTouch) return; + + const handleMouseMove = (e: MouseEvent) => { + // Use requestAnimationFrame for smoother cursor tracking + requestAnimationFrame(() => { + setPos({ x: e.clientX, y: e.clientY }); + }); + + const target = e.target as HTMLElement; + const isInteractive = target.closest('button, a, input, select, textarea, [role="button"], label'); + setIsHovering(!!isInteractive); + + // Throttle trail creation for performance (max every 50ms) + const now = Date.now(); + if (now - lastTrailTime.current > 60) { + setTrail(prev => [ + ...prev.slice(-10), + { + id: trailId.current++, + x: e.clientX, + y: e.clientY, + color: COLORS[Math.floor(Math.random() * COLORS.length)] + } + ]); + lastTrailTime.current = now; + } + }; + + window.addEventListener('mousemove', handleMouseMove); + return () => window.removeEventListener('mousemove', handleMouseMove); + }, []); + + // Hide on touch devices + if (typeof window !== 'undefined' && window.matchMedia("(pointer: coarse)").matches) return null; + + return ( +
+ + + {/* Particle Trail */} + {trail.map(t => ( +
+ ))} + + {/* Fairy Cursor */} +
+
+
+
+
+
+ ); +}; + +export default FairyCursor; diff --git a/src/components/IntroScene.tsx b/src/components/IntroScene.tsx new file mode 100644 index 0000000..333c2e0 --- /dev/null +++ b/src/components/IntroScene.tsx @@ -0,0 +1,239 @@ + +import React, { useEffect, useState, useRef } from 'react'; + +interface IntroSceneProps { + onComplete: () => void; +} + +const COLORS = ['#9767e4', '#FF0080', '#00E5FF', '#FFD600', '#76FF03', '#FFFFFF']; +const SLOGAN_PRIMARY = "Monynha Softwares"; +const SLOGAN_SECONDARY = "sua presença digital"; + +const IntroScene: React.FC = ({ onComplete }) => { + const [revealedPrimary, setRevealedPrimary] = useState(0); + const [revealedSecondary, setRevealedSecondary] = useState(0); + const [fairyPos, setFairyPos] = useState({ x: -100, y: -100 }); + const [particles, setParticles] = useState<{ id: number; x: number; y: number; size: number; color: string }[]>([]); + const [isExiting, setIsExiting] = useState(false); + + const particleId = useRef(0); + const containerRef = useRef(null); + const fairyRef = useRef(null); + const primaryRef = useRef(null); + const secondaryRef = useRef(null); + + useEffect(() => { + // Total duration: 3s. Exit starts slightly before for smoothness. + const exitTimer = setTimeout(() => { + setIsExiting(true); + }, 2400); + + const finalTimer = setTimeout(() => { + onComplete(); + }, 3000); + + const interval = setInterval(() => { + if (fairyRef.current && containerRef.current) { + const fairyRect = fairyRef.current.getBoundingClientRect(); + const containerRect = containerRef.current.getBoundingClientRect(); + + const currentX = fairyRect.left - containerRect.left + fairyRect.width / 2; + const currentY = fairyRect.top - containerRect.top + fairyRect.height / 2; + + setFairyPos({ x: currentX, y: currentY }); + + if (Math.random() > 0.4) { + const newParticle = { + id: particleId.current++, + x: currentX, + y: currentY, + size: Math.random() * 3 + 1, + color: COLORS[Math.floor(Math.random() * COLORS.length)] + }; + setParticles(prev => [...prev.slice(-25), newParticle]); + } + + if (primaryRef.current) { + const pRect = primaryRef.current.getBoundingClientRect(); + const pLocalX = fairyRect.left - pRect.left + fairyRect.width / 2; + if (pLocalX > 0) { + const progress = Math.min(1, pLocalX / pRect.width); + const count = Math.ceil(progress * SLOGAN_PRIMARY.length); + setRevealedPrimary(prev => Math.max(prev, count)); + } + } + + if (secondaryRef.current) { + const sRect = secondaryRef.current.getBoundingClientRect(); + const sLocalX = fairyRect.left - sRect.left + fairyRect.width / 2; + if (sLocalX > 0) { + const progress = Math.min(1, sLocalX / sRect.width); + const count = Math.ceil(progress * SLOGAN_SECONDARY.length); + setRevealedSecondary(prev => Math.max(prev, count)); + } + } + } + }, 16); + + return () => { + clearTimeout(exitTimer); + clearTimeout(finalTimer); + clearInterval(interval); + }; + }, [onComplete]); + + return ( +
+ + +
+ + {particles.map(p => ( +
+ ))} + +
+
+
+
+
+ +
+

+ {SLOGAN_PRIMARY.split('').map((char, i) => ( + + {char} + + ))} +

+

+ {SLOGAN_SECONDARY.split('').map((char, i) => ( + + {char} + + ))} +

+
+
+ ); +}; + +export default IntroScene; diff --git a/src/components/Landing.tsx b/src/components/Landing.tsx new file mode 100644 index 0000000..f3f4f73 --- /dev/null +++ b/src/components/Landing.tsx @@ -0,0 +1,81 @@ +import React, { useState, useEffect } from 'react'; + +const PHRASES = [ + 'Onde a Engenharia Encontra a Intuição.', + 'Automação Centrada no Humano.', + 'Criando produtos digitais que respiram.', + 'O plano que sua marca merece (finalmente).', + 'Transforme seu caos em faturamento.' +]; + +interface LandingProps { + onStart: () => void; + onExplore: () => void; +} + +const Landing: React.FC = ({ onStart, onExplore }) => { + const [phrase, setPhrase] = useState(''); + const [isReady, setIsReady] = useState(false); + + useEffect(() => { + setPhrase(PHRASES[Math.floor(Math.random() * PHRASES.length)]); + const timer = setTimeout(() => setIsReady(true), 100); + return () => clearTimeout(timer); + }, []); + + return ( +
+ + + + +
+

{phrase}

+ +
+

+ MONYNHA
+ SOFTWARES +

+

+ Nós conectamos o abismo entre engenharia complexa e intuição humana.
+ Criando produtos digitais que não apenas funcionam — eles respiram. +

+
+ + +
+ +
+
+

Engenharia com personalidade. Monynha Softwares © {new Date().getFullYear()}

+ +
+
+
+ ); +}; + +export default Landing; diff --git a/src/components/LegalPages.tsx b/src/components/LegalPages.tsx new file mode 100644 index 0000000..6bc3998 --- /dev/null +++ b/src/components/LegalPages.tsx @@ -0,0 +1,200 @@ + +import React, { useEffect } from 'react'; + +interface LegalPagesProps { + type: 'privacy' | 'terms' | 'cookies'; + onBack: () => void; +} + +const LEGAL_CONTENT = { + privacy: { + title: 'Política de Privacidade', + subtitle: 'Seus dados, seu brilho, sua segurança.', + lastUpdated: '01 de Junho de 2025', + content: ( +
+
+

01. Coleta de Dados

+

+ Na Monynha Softwares, respeitamos sua existência e seus dados. Coletamos apenas o essencial para o diagnóstico: seu e-mail, nome da marca e informações de negócio que você compartilha voluntariamente no Wizard. +

+
+
+

02. Uso de Informações

+

+ Seus dados são usados exclusivamente para gerar seu Diagnóstico Estratégico AI e para nossa equipe entrar em contato caso você decida barbarizar seu negócio conosco. Jamais vendemos seus dados para terceiros. +

+
+
+

03. Armazenamento Seguro

+

+ Utilizamos infraestrutura de ponta (Supabase) para garantir que seus dados fiquem protegidos sob sete chaves digitais. Seguimos as diretrizes da LGPD brasileira e do RGPD europeu. +

+
+
+

04. Seus Direitos

+

+ Você tem o direito de solicitar a exclusão total dos seus dados de nossos servidores a qualquer momento. Basta mandar um "Mona, deleta tudo" para o nosso e-mail de contato. +

+
+
+ ) + }, + terms: { + title: 'Termos de Uso', + subtitle: 'As regras do jogo para o close certo.', + lastUpdated: '01 de Junho de 2025', + content: ( +
+
+

01. Natureza do Diagnóstico

+

+ O Wizard de Diagnóstico é uma ferramenta baseada em Inteligência Artificial para fins de consultoria inicial e marketing. As sugestões geradas não constituem um contrato de prestação de serviços final nem garantia de faturamento imediato. +

+
+
+

02. Propriedade Intelectual

+

+ Todo o design, código e a marca "Monynha Softwares" são propriedade intelectual nossa. O Diagnóstico gerado para você é de seu uso pessoal e profissional, mas a metodologia permanece nossa. +

+
+
+

03. Uso Responsável

+

+ Ao utilizar o Wizard, você se compromete a fornecer informações verídicas. Não toleramos o uso de nossa plataforma para disseminação de discurso de ódio ou atividades ilegais. +

+
+
+

04. Limitação de Responsabilidade

+

+ A Monynha Softwares não se responsabiliza por decisões de negócio tomadas exclusivamente com base no Diagnóstico AI sem uma consultoria humana personalizada subsequente. +

+
+
+ ) + }, + cookies: { + title: 'Política de Cookies', + subtitle: 'Pequenos arquivos, grandes experiências.', + lastUpdated: '01 de Junho de 2025', + content: ( +
+
+

01. O que são Cookies?

+

+ Cookies são pequenos arquivos de texto salvos no seu navegador que nos ajudam a lembrar de você e de suas preferências, como o rascunho do seu wizard. +

+
+
+

02. Cookies Essenciais

+

+ Usamos cookies técnicos necessários para o funcionamento do site, como o armazenamento local (LocalStorage) que permite que você não perca suas respostas caso a página recarregue acidentalmente. +

+
+
+

03. Cookies de Performance

+

+ Podemos utilizar ferramentas de análise (como Google Analytics) para entender como as pessoas interagem com nosso site e melhorar continuamente a experiência de uso. +

+
+
+

04. Como Gerenciar

+

+ Você pode desativar os cookies nas configurações do seu navegador a qualquer momento. Note que isso pode afetar algumas funcionalidades interativas de nossa plataforma. +

+
+
+ ) + } +}; + +const LegalPages: React.FC = ({ type, onBack }) => { + const content = LEGAL_CONTENT[type]; + + useEffect(() => { + window.scrollTo({ top: 0, behavior: 'smooth' }); + }, [type]); + + return ( +
+ + + {/* Navigation */} + + +
+
+
+ Documentação Oficial +
+

+ {content.title.split(' ').map((word, i) => ( + {word} + ))} +

+

+ {content.subtitle} +

+
+ Última atualização: {content.lastUpdated} +
+
+
+ +
+ {content.content} +
+ +
+

Alguma dúvida, mona?

+

+ Se algo não ficou claro, mande um sinal pra gente. Transparência é resistência. +

+ + Mandar E-mail + +
+ +
+

+ © {new Date().getFullYear()} Monynha Softwares • All Rights Reserved +

+
+
+
+ ); +}; + +export default LegalPages; diff --git a/src/components/LoadingScreen.tsx b/src/components/LoadingScreen.tsx new file mode 100644 index 0000000..f6a5776 --- /dev/null +++ b/src/components/LoadingScreen.tsx @@ -0,0 +1,346 @@ + +import React, { useState, useEffect, useRef } from 'react'; + +const STATUS_MESSAGES = [ + "Identificando gargalos, mona...", + "Analisando o caos operacional com carinho...", + "Preparando um diagnóstico babadeiro...", + "Sintonizando vibes corporativas de alto nível...", + "Otimizando tua estratégia pra você brilhar...", + "Praticando branding consciente e queer...", + "Consultando as cartas do faturamento...", + "Finalizando o plano que vai mudar tua vida!", + "Quase lá, respira e brilha...", + "Escaneando o LinkedIn do seu ex pra evitar gatilhos...", + "Descriptografando o segredo do sucesso (spoiler: é você)...", + "Removendo impurezas do seu funil de vendas...", + "Adicionando 15% de glitter extra no seu roadmap..." +]; + +const FAKE_LOGS = [ + "> [SYSTEM] Booting Monynha-AI-V3...", + "> [SEARCH] Crawling digital presence...", + "> [ANALYSIS] Semantic mapping of struggle...", + "> [BRAND] Detecting pride level: HIGH", + "> [TECH] Refactoring business logic...", + "> [VIBE] Calibrating aesthetic resistance...", + "> [AI] Grounding results with Google Search...", + "> [SUCCESS] Generating 100k mindset...", + "> [FINISH] Dressing plan in its best outfit..." +]; + +interface LoadingScreenProps { + isDone?: boolean; +} + +const LoadingScreen: React.FC = ({ isDone }) => { + const [progress, setProgress] = useState(0); + const [msgIndex, setMsgIndex] = useState(0); + const [logs, setLogs] = useState([]); + const [showConfetti, setShowConfetti] = useState(false); + const [burstActive, setBurstActive] = useState(false); + const [prefersReducedMotion, setPrefersReducedMotion] = useState(false); + const logContainerRef = useRef(null); + + useEffect(() => { + const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)'); + const updateReducedMotion = () => setPrefersReducedMotion(mediaQuery.matches); + + updateReducedMotion(); + mediaQuery.addEventListener('change', updateReducedMotion); + return () => mediaQuery.removeEventListener('change', updateReducedMotion); + }, []); + + useEffect(() => { + if (isDone) { + setProgress(100); + setShowConfetti(!prefersReducedMotion); + setBurstActive(!prefersReducedMotion); + return; + } + + // Progress logic + const interval = setInterval(() => { + setProgress(prev => { + if (prev >= 99) return 99; + const remaining = 100 - prev; + const increment = Math.random() * (remaining / 10); + return Math.min(prev + increment, 99); + }); + }, 400); + + // Status message cycling + const msgInterval = setInterval(() => { + setMsgIndex(prev => (prev + 1) % STATUS_MESSAGES.length); + }, 1500); + + // Log scrolling logic + const logInterval = setInterval(() => { + setLogs(prev => { + const nextLog = FAKE_LOGS[Math.floor(Math.random() * FAKE_LOGS.length)]; + const newLogs = [...prev, nextLog]; + return newLogs.slice(-5); + }); + }, 800); + + return () => { + clearInterval(interval); + clearInterval(msgInterval); + clearInterval(logInterval); + }; + }, [isDone, prefersReducedMotion]); + + useEffect(() => { + if (logContainerRef.current) { + logContainerRef.current.scrollTop = logContainerRef.current.scrollHeight; + } + }, [logs]); + + const getPhase = () => { + if (isDone) return "CONCLUÍDO: CLOSE CERTO!"; + if (progress < 30) return "Fase 1: Escaneamento de Alma"; + if (progress < 60) return "Fase 2: Processamento de Close"; + if (progress < 90) return "Fase 3: Refino Estratégico"; + return "Fase Final: Montando o Look do Sucesso"; + }; + + return ( +
+ + + {/* Confetti Rain on Completion */} + {showConfetti && [...Array(56)].map((_, i) => { + const size = Math.random() * 12 + 6; + const color = ['#9767e4', '#FF0000', '#FF7F00', '#FFFF00', '#00FF00', '#0000FF', '#FF0080', '#00E5FF'][Math.floor(Math.random() * 8)]; + const shape = Math.random() > 0.5 ? '50%' : '2px'; + return ( +
+ ); + })} + + {/* Magic Burst Wave */} + {burstActive &&
} + + {/* Decorative floating elements */} +
+
+ +
+
+ + {/* Header Section */} +
+
+
+ {!isDone && } + {isDone && } + {getPhase()} +
+

+ {isDone ? "Pronta pro" : "Segura o"}
+ {isDone ? "SHOW, mona!" : "baile, mona."} +

+
+
+ +
+
+ + {/* Progress Bar Section */} +
+
+
+
+
+
+ + {/* Fairy following progress */} +
5 ? '-20px' : '0px', + opacity: progress > 0 ? 1 : 0 + }} + > +
+
+
+
+ + {/* Sparkles trail */} + {!isDone && [...Array(4)].map((_, i) => ( +
+ ))} +
+
+
+ {isDone && ( +
+ SUCCESS! +
+ )} +
+ +
+
+ + + {isDone ? "O plano mais babadeiro da sua vida está pronto!" : STATUS_MESSAGES[msgIndex]} + +
+ {Math.round(progress)}% +
+
+ + {/* Terminal Logs Simulation */} +
+
+
+
+
+ monynha_kernel_logs.sh +
+
+ {isDone ? ( + <> +

> [SUCCESS] Diagnosis generated successfully!

+

> [SUCCESS] Lead stored in Database...

+

> [SUCCESS] Strategies polished with Gemini AI...

+

> [SYSTEM] Redirecting to report module in 3, 2, 1...

+ + ) : ( + logs.map((log, i) => ( +

{log}

+ )) + )} + {!isDone &&

_

} +
+
+ + {/* Footer of card */} +
+
+ {[1, 2, 3].map(i => ( +
+ +
+ ))} +
+ + {isDone ? "Pronta pro próximo nível?" : "Processando com inteligência queer"} + +
+
+ + {/* Floating background label */} +
+

+ {isDone ? "ABRA AS CORTINAS..." : "Sua revolução digital está sendo calculada..."} +

+
+
+
+ ); +}; + +export default LoadingScreen; diff --git a/src/components/ProjectCarousel.tsx b/src/components/ProjectCarousel.tsx new file mode 100644 index 0000000..a440b81 --- /dev/null +++ b/src/components/ProjectCarousel.tsx @@ -0,0 +1,281 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { PROJECTS } from './ProjectsPage'; + +interface ProjectCarouselProps { + onViewAll: () => void; +} + +const statusLabels = { + production: { text: 'Production', color: 'bg-primary text-white border-near-black' }, + experimental: { text: 'Experimental', color: 'bg-[#F59E0B] text-white border-near-black' }, + lab: { text: 'Lab', color: 'bg-[#667EEA] text-white border-near-black' } +}; + +const ProjectCarousel: React.FC = ({ onViewAll }) => { + const scrollContainerRef = useRef(null); + const holdScrollRef = useRef(null); + const [isHovered, setIsHovered] = useState(false); + const [canScrollLeft, setCanScrollLeft] = useState(false); + const [canScrollRight, setCanScrollRight] = useState(true); + const animationRef = useRef(); + + // Auto-scroll animation + useEffect(() => { + const container = scrollContainerRef.current; + if (!container || isHovered) return; + + const scroll = () => { + if (container.scrollLeft >= container.scrollWidth - container.clientWidth) { + // Reset to start when reaching the end + container.scrollLeft = 0; + } else { + container.scrollLeft += 0.5; // Gentle scroll speed + } + animationRef.current = requestAnimationFrame(scroll); + }; + + animationRef.current = requestAnimationFrame(scroll); + + return () => { + if (animationRef.current) { + cancelAnimationFrame(animationRef.current); + } + }; + }, [isHovered]); + + // Update scroll button states + const updateScrollButtons = () => { + const container = scrollContainerRef.current; + if (!container) return; + + setCanScrollLeft(container.scrollLeft > 0); + setCanScrollRight( + container.scrollLeft < container.scrollWidth - container.clientWidth - 10 + ); + }; + + useEffect(() => { + const container = scrollContainerRef.current; + if (!container) return; + + container.addEventListener('scroll', updateScrollButtons); + updateScrollButtons(); + + return () => container.removeEventListener('scroll', updateScrollButtons); + }, []); + + useEffect(() => { + return () => { + if (holdScrollRef.current !== null) { + window.clearInterval(holdScrollRef.current); + holdScrollRef.current = null; + } + }; + }, []); + + const scroll = (direction: 'left' | 'right') => { + const container = scrollContainerRef.current; + if (!container) return; + + const scrollAmount = container.clientWidth * 0.8; + const targetScroll = container.scrollLeft + (direction === 'left' ? -scrollAmount : scrollAmount); + + container.scrollTo({ + left: targetScroll, + behavior: 'smooth' + }); + }; + + const startHoldScroll = (direction: 'left' | 'right') => { + const container = scrollContainerRef.current; + if (!container) return; + + if (holdScrollRef.current !== null) { + window.clearInterval(holdScrollRef.current); + } + + const step = direction === 'left' ? -80 : 80; + holdScrollRef.current = window.setInterval(() => { + container.scrollBy({ left: step, top: 0, behavior: 'auto' }); + }, 16); + }; + + const stopHoldScroll = () => { + if (holdScrollRef.current !== null) { + window.clearInterval(holdScrollRef.current); + holdScrollRef.current = null; + } + }; + + return ( +
+ {/* Header with Navigation */} +
+
+

+ Nossas Criaturas +

+
+
+ +
+ {/* Navigation Buttons */} + + + + + {/* View All Button */} + +
+
+ + {/* Carousel Container */} +
setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + className="flex gap-6 overflow-x-auto hide-scrollbar scroll-smooth pb-4" + style={{ + WebkitOverflowScrolling: 'touch' + }} + > + {PROJECTS.map((project) => ( +
+ {/* Project Card */} +
+ {/* Icon & Status */} +
+
+ {project.icon} +
+ + + {statusLabels[project.status].text} + +
+ + {/* Content */} +
+
+

+ {project.title} +

+

+ {project.subtitle} +

+
+ +

+ {project.description} +

+ + {/* Tags */} +
+ {project.tags.slice(0, 3).map((tag, i) => ( + + {tag} + + ))} + {project.tags.length > 3 && ( + + +{project.tags.length - 3} + + )} +
+
+ + {/* Action Button */} + + Explorar + arrow_forward + +
+
+ ))} + + {/* View All Card (Mobile) */} +
+ +
+
+ + {/* Scroll Indicator */} +
+ {PROJECTS.map((_, index) => ( +
+ ))} +
+
+ ); +}; + +export default ProjectCarousel; diff --git a/src/components/ProjectsPage.tsx b/src/components/ProjectsPage.tsx new file mode 100644 index 0000000..b859282 --- /dev/null +++ b/src/components/ProjectsPage.tsx @@ -0,0 +1,349 @@ +import React, { useEffect, useRef } from 'react'; + +interface Project { + id: string; + title: string; + subtitle: string; + description: string; + longDescription: string; + icon: string; + color: string; + gradient: string; + status: 'production' | 'experimental' | 'lab'; + url: string; + tags: string[]; + features?: string[]; +} + +export const PROJECTS: Project[] = [ + { + id: 'boteco-pro', + title: 'Boteco PRO', + subtitle: 'boteco.pro', + description: 'A plataforma definitiva de gestão para bares e restaurantes.', + longDescription: 'Sistema completo de gestão para bares e restaurantes construído sobre Odoo ERP. Do cardápio digital ao controle de estoque, empoderamos a indústria de food & beverage com orgulho e tecnologia de ponta.', + icon: 'local_bar', + color: '#9767e4', + gradient: 'from-[#9767e4] via-[#667EEA] to-[#764BA2]', + status: 'production', + url: 'https://boteco.pro', + tags: ['Odoo ERP', 'Digital Menus', 'Stock Control', 'Analytics', 'POS'], + features: [ + 'Cardápios digitais interativos com QR Code', + 'Controle de estoque em tempo real', + 'Dashboard de vendas e analytics', + 'Gestão de mesas e pedidos', + 'Integração com delivery', + 'Relatórios financeiros completos' + ] + }, + { + id: 'facodi', + title: 'FACODI', + subtitle: 'facodi.pt', + description: 'Faculdade Comunitária Digital democratizando educação.', + longDescription: 'Democratizamos currículos universitários em playlists abertas e acessíveis. Qualquer pessoa pode brilhar na tecnologia, independentemente de background ou recursos financeiros. Educação de qualidade como direito, não privilégio.', + icon: 'school', + color: '#667EEA', + gradient: 'from-[#667EEA] to-[#764BA2]', + status: 'lab', + url: 'https://facodi.pt', + tags: ['Education', 'Open Source', 'Community', 'Tech Skills'], + features: [ + 'Currículos universitários estruturados', + 'Playlists de vídeo curadas', + 'Trilhas de aprendizado personalizadas', + 'Recursos 100% gratuitos', + 'Comunidade ativa de estudantes', + 'Certificados de conclusão' + ] + }, + { + id: 'monynha-fun', + title: 'Monynha Fun', + subtitle: 'monynha.fun', + description: 'Arquivo de videos do YouTube e indexador de playlists do Facodi.', + longDescription: 'Um arquivo vivo de videos do YouTube com indexacao de playlists da Facodi (Faculdade Comunitaria Digital). Centraliza curadoria, trilhas e colecoes para facilitar o acesso ao conhecimento aberto.', + icon: 'toys', + color: '#F59E0B', + gradient: 'from-[#F59E0B] to-[#EF4444]', + status: 'experimental', + url: 'https://monynha.fun', + tags: ['YouTube', 'Playlists', 'Facodi', 'Curadoria'], + features: [ + 'Indexacao de playlists do Facodi', + 'Arquivo organizado de videos', + 'Curadoria por trilhas de estudo', + 'Busca rapida por temas', + 'Links diretos para playlists', + 'Colecoes abertas e publicas' + ] + }, + { + id: 'odoo-integrations', + title: 'Odoo ERP Integrations', + subtitle: 'odoo.com', + description: 'Integrações enterprise conectando Odoo com ferramentas modernas.', + longDescription: 'Integrações de nível enterprise conectando Odoo com o melhor do ecossistema SaaS moderno. Stripe para pagamentos, Clerk para autenticação, Supabase como backend, e pipelines customizadas de IA.', + icon: 'hub', + color: '#8B5CF6', + gradient: 'from-[#8B5CF6] to-[#EC4899]', + status: 'production', + url: 'https://odoo.com', + tags: ['Integration', 'Stripe', 'Clerk', 'Supabase', 'AI', 'API'], + features: [ + 'Integração Stripe completa', + 'Autenticação via Clerk', + 'Backend Supabase', + 'Pipelines de IA customizadas', + 'APIs RESTful e GraphQL', + 'Webhooks e automações' + ] + } +]; + +interface ProjectsPageProps { + onBack: () => void; + onStartWizard: () => void; +} + +const statusLabels = { + production: { text: 'Production', color: 'bg-primary text-white border-near-black' }, + experimental: { text: 'Experimental', color: 'bg-[#F59E0B] text-white border-near-black' }, + lab: { text: 'Lab', color: 'bg-[#667EEA] text-white border-near-black' } +}; + +const ProjectsPage: React.FC = ({ onBack, onStartWizard }) => { + const scrollIntervalRef = useRef(null); + + useEffect(() => { + window.scrollTo({ top: 0, behavior: 'smooth' }); + }, []); + + useEffect(() => { + return () => { + if (scrollIntervalRef.current !== null) { + window.clearInterval(scrollIntervalRef.current); + scrollIntervalRef.current = null; + } + }; + }, []); + + const startScrollHold = (direction: 'up' | 'down') => { + const step = direction === 'up' ? -40 : 40; + if (scrollIntervalRef.current !== null) { + window.clearInterval(scrollIntervalRef.current); + } + scrollIntervalRef.current = window.setInterval(() => { + window.scrollBy({ top: step, left: 0, behavior: 'auto' }); + }, 16); + }; + + const stopScrollHold = () => { + if (scrollIntervalRef.current !== null) { + window.clearInterval(scrollIntervalRef.current); + scrollIntervalRef.current = null; + } + }; + + return ( +
+ {/* Header Navigation */} + + + {/* Hero Section */} +
+
+
+ Nosso Ecossistema +
+ +

+ Criaturas do
+ Estúdio +

+ +

+ Explore o ecossistema vivo da Monynha Softwares — de plataformas prontas para produção até iniciativas experimentais do Lab. Cada criatura tem um propósito, uma alma e um pouco de resistência codificada. +

+
+
+ +
+ + +
+ + {/* Projects Grid */} +
+ {PROJECTS.map((project, index) => ( +
+ {/* Gradient Glow Effect */} + {project.status === 'production' && ( +
+ )} + + {/* Project Card */} +
+
+ {/* Icon */} +
+
+ {project.icon} +
+
+ + {/* Content */} +
+
+
+

+ {project.title} +

+ + {statusLabels[project.status].text} + +
+ +

+ {project.subtitle} +

+ +

+ {project.longDescription} +

+
+ + {/* Tags */} +
+ {project.tags.map((tag, i) => ( + + {tag} + + ))} +
+ + {/* Features */} + {project.features && ( +
+ {project.features.map((feature, i) => ( +
+ check_circle + {feature} +
+ ))} +
+ )} + + {/* Action Button */} + + Visitar Projeto + arrow_outward + +
+
+
+
+ ))} +
+ + {/* CTA Section */} +
+
+

+ Tem uma ideia
revolucionária? +

+ +

+ Vamos transformar seu conceito em realidade. Cada grande projeto começa com uma conversa. +

+ + +
+
+
+ ); +}; + +export default ProjectsPage; diff --git a/src/components/Report.tsx b/src/components/Report.tsx new file mode 100644 index 0000000..fcc590c --- /dev/null +++ b/src/components/Report.tsx @@ -0,0 +1,283 @@ +import React, { useEffect, useState } from 'react'; +import { DiagnosisResult } from '../types'; + +interface ReportProps { + diagnosis: DiagnosisResult; + onReset: () => void; + onExplore: () => void; +} + +const OFFICIAL_LINKS = { + instagram: 'https://www.instagram.com/monynha_softwares/', + linkedin: 'https://www.linkedin.com/company/Monynha/', + whatsapp: 'https://wa.me/5511999999999', + website: 'https://monynha.com', + facodi: 'https://facodi.pt' +}; + +const Report: React.FC = ({ diagnosis, onReset, onExplore }) => { + const [showConfetti, setShowConfetti] = useState(false); + const [copied, setCopied] = useState(false); + + useEffect(() => { + setShowConfetti(true); + const timer = setTimeout(() => setShowConfetti(false), 6000); + window.scrollTo({ top: 0, behavior: 'smooth' }); + return () => clearTimeout(timer); + }, []); + + const openWhatsApp = () => { + const text = `Mona, acabei de fazer meu diagnóstico na Monynha Softwares! 💅\n\nMeu close estratégico foi: "${diagnosis.title}"\n\nBora transformar meu perrengue em faturamento e organizar esse babado?`; + window.open(`${OFFICIAL_LINKS.whatsapp}?text=${encodeURIComponent(text)}`, '_blank'); + }; + + const copyDiagnosis = async () => { + const textToCopy = `✨ DIAGNÓSTICO MONYNHA SOFTWARES ✨\n\nClose: ${diagnosis.title}\n\n${diagnosis.description}\n\nFaça o seu em: monynha.com`; + try { + await navigator.clipboard.writeText(textToCopy); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch (err) { + console.error('Erro ao copiar:', err); + } + }; + + return ( +
+ {/* Confetti Elements */} + {showConfetti && [...Array(40)].map((_, i) => ( +
+ ))} + + + +
+
+
+ +
+
+

Mensagem recebida!

+

Enviamos uma confirmação no teu e-mail. Nossa equipe retorna em até 48h úteis.

+
+
+
+ +
+
+
+
+ Diagnóstico Completo +
+
+ +

+ Pronto, mona.
+ Segura o close. +

+ +
+
+
+
+
+ clinical_notes +
+
+

+ {diagnosis.title} +

+

+ {diagnosis.description} +

+
+
+
+
+
+ + {/* What Happens Next Section */} +
+
+

Próximos passos do processo

+
+
+ {[ + { title: 'Análise', desc: 'Marcelo ou Tércio analisam pessoalmente os objetivos do teu projeto e avaliam como podemos ajudar.', icon: 'done_all' }, + { title: 'Alinhamento', desc: 'Marcamos um papo rápido pra garantir que nossas filosofias e expectativas estão conectadas.', icon: 'handshake' }, + { title: 'Proposta', desc: 'Você recebe um roadmap claro, focado em resultados, com cronograma e orçamento transparente.', icon: 'trending_up' } + ].map((step, i) => ( +
+
+ {step.icon} +
+

{step.title}

+

{step.desc}

+
+ ))} +
+
+ + {/* Roadmap (AI) */} +
+
+
+
+ The Roadmap +

Passos para o
Sucesso

+
+ +
+ {diagnosis.recommendations.map((rec, i) => ( +
+
+ {i + 1} +
+

"{rec}"

+
+ ))} +
+
+
+ + {/* Primary Call to Action */} +
+
+

Próxima parada: conversa de verdade

+

Recebeu nosso e-mail de confirmação. Responda diretamente ou chama no WhatsApp pra acelerar esse close.

+
+ +
+ +
+
+ + {/* Secondary CTA Section */} +
+
+
Continue explorando
+

Descubra mais sobre como a Monynha transforma desafios digitais em resultados concretos.

+
+ +
+ + + + language + Site Oficial + + + + + +
+
+
+ + +
+ ); +}; + +export default Report; diff --git a/src/components/Wizard.tsx b/src/components/Wizard.tsx new file mode 100644 index 0000000..45b3337 --- /dev/null +++ b/src/components/Wizard.tsx @@ -0,0 +1,509 @@ +import React, { useState, useEffect, useCallback, useRef } from 'react'; +import { LeadData, RevenueModel, DecisionProfile } from '../types'; + +interface WizardProps { + onComplete: (data: LeadData) => void; + onCancel: () => void; + error?: string | null; +} + +const STORAGE_KEY = 'monynha_wizard_draft_v1'; + +const TOOLTIPS_REVENUE = { + 'Serviço': 'Venda de expertise, consultoria ou mão de obra especializada.', + 'Produto': 'Venda de itens físicos ou digitais escaláveis.', + 'Assinatura': 'Pagamentos recorrentes por acesso contínuo.', + 'Outro': 'Modelos híbridos ou nichos específicos.' +}; + +const CARD_REVENUE_DESCRIPTIONS = { + 'Serviço': 'Consultoria, operação ou execução personalizada.', + 'Produto': 'Itens físicos ou digitais prontos para escala.', + 'Assinatura': 'Receita recorrente com acesso contínuo.', + 'Outro': 'Formato híbrido ou modelo fora do padrão.' +}; + +const TOOLTIPS_DECISION = { + 'Faço tudo': 'Você é a "eu-presa" e cuida do operacional ao estratégico.', + 'Prefiro contratar alguém para fazer': 'Busca especialistas para focar no seu core business.', + 'Estou mais procupade em vender': 'Foca no comercial e quer automação total na entrega.', + 'Não sei ainda, to perdide': 'Precisa de clareza sobre como delegar ou crescer.' +}; + +const CARD_DECISION_DESCRIPTIONS = { + 'Faço tudo': 'Centraliza a operação e a estratégia no dia a dia.', + 'Prefiro contratar alguém para fazer': 'Quer time ou parceiros tocando a entrega.', + 'Estou mais procupade em vender': 'Prioriza vendas e deseja execução automatizada.', + 'Não sei ainda, to perdide': 'Busca clareza para delegar e escalar.' +}; + +const AnimatedTextField: React.FC<{ + value: string; + onChange: (val: string) => void; + id?: string; + placeholder?: string; + type?: string; + className?: string; + disabled?: boolean; + autoFocus?: boolean; + inputRef?: React.RefObject; + isValid?: boolean; +}> = ({ value, onChange, id, placeholder, type = "text", className = "", disabled = false, autoFocus = false, inputRef, isValid }) => { + return ( +
+ + + onChange(e.target.value)} + className={`${className} w-full bg-transparent border-[3px] sm:border-[4px] p-3 sm:p-4 text-lg sm:text-xl font-bold rounded-xl sm:rounded-2xl focus:ring-4 focus:ring-primary/20 focus:border-primary focus:shadow-none focus:translate-x-[2px] focus:translate-y-[2px] transition-all caret-primary text-transparent selection:bg-primary/30 font-body min-h-[3rem] sm:min-h-[3.5rem]`} + /> +
+ ); +}; + +const AnimatedTextAreaField: React.FC<{ + value: string; + onChange: (val: string) => void; + id?: string; + placeholder?: string; + className?: string; + rows?: number; + autoFocus?: boolean; + textareaRef?: React.RefObject; +}> = ({ value, onChange, id, placeholder, className = "", rows = 3, autoFocus = false, textareaRef }) => { + return ( +
+ + +