From 594f749d4c52db978e386cae80c2c53af8f4ed1d Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 23 Feb 2026 08:37:58 -0600 Subject: [PATCH] Initial commit: HP Marketing Materials GraphRAG Chatbot Full-stack GraphRAG chatbot for HP marketing materials with: - Python/Flask backend with custom ReAct agent (LlamaIndex) - Neo4j knowledge graph + vector search hybrid retrieval - LlamaParse multimodal document processing (text + images) - React/Vite frontend with conversation management - MongoDB conversation persistence - MSAL authentication support Co-Authored-By: Claude Opus 4.6 --- .gitignore | 39 + CLAUDE.md | 118 + README.md | 244 + ai_core.py | 1374 ++++ chat-interface/.gitignore | 24 + chat-interface/.htaccess | 37 + chat-interface/DEPLOY.md | 50 + chat-interface/README.md | 72 + chat-interface/components.json | 17 + chat-interface/eslint.config.js | 38 + chat-interface/index.html | 31 + chat-interface/package-lock.json | 6784 +++++++++++++++++ chat-interface/package.json | 40 + chat-interface/postcss.config.js | 6 + .../public/images/Netflix_2015_N_logo.png | Bin 0 -> 87960 bytes chat-interface/public/images/netflix-logo.svg | 3 + chat-interface/public/vite.svg | 1 + chat-interface/src/App.css | 42 + chat-interface/src/App.jsx | 1525 ++++ chat-interface/src/App_11-19.jsx | 691 ++ chat-interface/src/assets/react.svg | 1 + chat-interface/src/auth.js | 119 + .../src/components/ChatInterface.jsx | 140 + .../src/components/ConversationManager.jsx | 206 + chat-interface/src/components/ThemeToggle.jsx | 21 + chat-interface/src/components/ui/alert.jsx | 37 + chat-interface/src/index.css | 131 + chat-interface/src/lib/utils.js | 40 + chat-interface/src/main.jsx | 75 + chat-interface/tailwind.config.js | 28 + chat-interface/update-backend.sh | 38 + chat-interface/vite.config.js | 124 + chat-interface/web.config | 46 + config.py | 103 + ...aphRAG chatbot technical documentation.pdf | Bin 0 -> 496402 bytes docs/graphRAG_chatbot_documentation.md | 666 ++ document_generator.py | 339 + graphRAG.py | 581 ++ graph_rag_integration.py | 882 +++ init_mongodb.py | 127 + json_utils.py | 133 + main.py | 168 + mongodb_utils.py | 458 ++ requirements.txt | 106 + routes.py | 1032 +++ session_manager.py | 162 + shared_state.py | 102 + utils.py | 178 + 48 files changed, 17179 insertions(+) create mode 100644 .gitignore create mode 100644 CLAUDE.md create mode 100644 README.md create mode 100644 ai_core.py create mode 100644 chat-interface/.gitignore create mode 100644 chat-interface/.htaccess create mode 100644 chat-interface/DEPLOY.md create mode 100644 chat-interface/README.md create mode 100644 chat-interface/components.json create mode 100644 chat-interface/eslint.config.js create mode 100644 chat-interface/index.html create mode 100644 chat-interface/package-lock.json create mode 100644 chat-interface/package.json create mode 100644 chat-interface/postcss.config.js create mode 100644 chat-interface/public/images/Netflix_2015_N_logo.png create mode 100644 chat-interface/public/images/netflix-logo.svg create mode 100644 chat-interface/public/vite.svg create mode 100644 chat-interface/src/App.css create mode 100644 chat-interface/src/App.jsx create mode 100644 chat-interface/src/App_11-19.jsx create mode 100644 chat-interface/src/assets/react.svg create mode 100644 chat-interface/src/auth.js create mode 100644 chat-interface/src/components/ChatInterface.jsx create mode 100644 chat-interface/src/components/ConversationManager.jsx create mode 100644 chat-interface/src/components/ThemeToggle.jsx create mode 100644 chat-interface/src/components/ui/alert.jsx create mode 100644 chat-interface/src/index.css create mode 100644 chat-interface/src/lib/utils.js create mode 100644 chat-interface/src/main.jsx create mode 100644 chat-interface/tailwind.config.js create mode 100755 chat-interface/update-backend.sh create mode 100644 chat-interface/vite.config.js create mode 100644 chat-interface/web.config create mode 100644 config.py create mode 100644 docs/graphRAG chatbot technical documentation.pdf create mode 100644 docs/graphRAG_chatbot_documentation.md create mode 100644 document_generator.py create mode 100644 graphRAG.py create mode 100644 graph_rag_integration.py create mode 100644 init_mongodb.py create mode 100644 json_utils.py create mode 100644 main.py create mode 100644 mongodb_utils.py create mode 100644 requirements.txt create mode 100644 routes.py create mode 100644 session_manager.py create mode 100644 shared_state.py create mode 100644 utils.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..db6975e --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +# Environment variables (contain API keys and credentials) +.env +.env.* +env + +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +venv/ +.venv/ +*.egg-info/ +dist/ +build/ + +# Node +chat-interface/node_modules/ +chat-interface/dist/ + +# Generated data (runtime artifacts, not source code) +uploads/ +index_storage/ +*.log + +# Large binary source documents (too large for git) +supporting_files/ + +# macOS +.DS_Store + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# Claude Code +.claude/ diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..aec3209 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,118 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +HP Marketing Materials Chatbot — a GraphRAG (Graph Retrieval-Augmented Generation) system that combines vector search with knowledge graph capabilities to answer questions about HP marketing materials and brand guidelines. Processes multimodal documents (text + images) via a custom ReAct agent. + +## Development Commands + +### Backend +```bash +pip install -r requirements.txt +python main.py # Starts Hypercorn ASGI server on localhost:8746 +``` + +### Frontend +```bash +cd chat-interface +npm install +npm run dev # Vite dev server +npm run build # Production build to dist/ +npm run lint # ESLint +``` + +### Required Services +- **Neo4j**: Port 7688, credentials `neo4j/hp-graphrag-2024` (HP-dedicated instance; port 7687 is a separate Netflix project) +- **MongoDB**: URI `mongodb://hp:hp@localhost:27017/?authSource=hp_chatbot`, database `hp_chatbot` + +### Environment Variables +Backend requires `.env` at project root with: `OPENAI_API_KEY`, `LLAMA_CLOUD_API_KEY`, `NEO4J_URL`, `NEO4J_USERNAME`, `NEO4J_PASSWORD`, `PORT` (default 8746). +Frontend uses `chat-interface/.env` with: `VITE_BACKEND_URL`, `VITE_APP_BASE_URL`. + +## Architecture + +### Request Flow +1. Frontend (`App.jsx`) sends POST to `/chat` with `{message, sessionId}` +2. `routes.py:chat()` maps session to conversation via `session_manager.py` and MongoDB +3. The global `ReActAgent2` (from `shared_state.py`) processes the query +4. Agent uses two tools: vector search (`answer_questions_from_hp_marketing_materials`) and GraphRAG hybrid search (`answerquestionswith_graphrag`) +5. Response includes text, sources, reasoning steps, and image references +6. Images are served via `/images/` from `uploads/images/` + +### Shared State Pattern (Critical) +All modules access the AI agent, vector index, and GraphRAG components through `shared_state.py` — a module with global variables and setter/getter functions. This avoids circular imports and ensures all modules reference the same instances. **Never import these globals directly from `ai_core.py`; always use `shared_state`.** + +Key globals: `global_workflow_agent`, `global_index`, `global_graph_store`, `global_graphrag_query_engine` + +### ReAct Agent (`ai_core.py`) +`ReActAgent2` is a custom LlamaIndex `Workflow` subclass implementing a ReAct loop: +- Steps: `new_user_msg` → `prepare_chat_history` → `handle_llm_input` → (tool calls via `handle_tool_calls` → loop back) → `StopEvent` +- Has a `simple_run()` method monkey-patched onto the agent at initialization time (replaces the default workflow `run`) +- Includes regex-based cleaning of LLM "thinking" artifacts from final responses +- Timeouts: `AGENT_TIMEOUT` (600s overall), `LLM_TIMEOUT` (300s per call), `TOOL_EXECUTION_TIMEOUT` (300s per tool) + +### GraphRAG System (`graph_rag_integration.py`) +Three main classes: +- **`GraphRAGExtractor`**: LlamaIndex `TransformComponent` that extracts entity-relation triplets from text nodes using LLM +- **`GraphRAGStore`**: Wraps `Neo4jPropertyGraphStore`, adds community detection (tries graspologic → python-louvain → NetworkX fallback), caches community summaries to `index_storage/graphrag_cache/` as pickle files +- **`GraphRAGQueryEngine`**: Combines vector retrieval with community-based graph retrieval, returning both contexts for synthesis + +### Startup Sequence (`main.py`) +1. MongoDB initialization (`init_mongodb.py`) +2. `initialize_global_index()` in `ai_core.py`: + - Configures LLM (chatgpt-4o-latest) and embeddings (text-embedding-3-small) + - Loads existing vector index from `index_storage/hp_docs_index/` or builds new from `supporting_files/files_for_rag_store/` + - Connects to Neo4j, creates/loads GraphRAG components + - Builds communities (from cache or fresh) + - Creates `ReActAgent2` and stores in `shared_state` + +### Frontend (React + Vite) +- Single-page app in `chat-interface/`, main component is `App.jsx` +- Auth via MSAL (`auth.js`), username sent as `X-MS-USERNAME` header +- Dev mode uses fallback `dev_user@local` username +- Conversation sidebar with auto-width resizing +- Markdown rendering via showdown, image viewer with pagination +- Styling: TailwindCSS + Shadcn/ui + Radix tooltips + +### JSON Serialization +`json_utils.py` provides `CustomJSONEncoder` and `CustomJSONProvider` that handle LlamaIndex types (ToolOutput, ReasoningSteps, ChatMessage, etc.), BSON ObjectId, and datetime. Flask is configured to use this provider globally. + +### Document Processing Pipeline +Upload → LlamaParse (dual: text + images) → Semantic splitting (`SemanticSplitterNodeParser`) → Page-based image assignment to chunks → Dual indexing (vector store + Neo4j knowledge graph) → Community detection and caching + +## API Endpoints + +| Method | Path | Purpose | +|--------|------|---------| +| POST | `/chat` | Main chat endpoint | +| GET | `/status` | System status (always returns initialized=true) | +| GET | `/images/` | Serve document images | +| GET | `/list-images` | List available images | +| GET | `/conversations` | List user conversations | +| GET | `/conversations//messages` | Get conversation messages | +| POST | `/conversations/new` | Create new conversation | +| DELETE | `/conversations/` | Delete conversation (soft by default) | +| POST | `/reset` | Reset global agent memory | +| POST | `/download-brief` | Generate Word doc from markdown | +| POST | `/capture-screenshot` | Manual LlamaParse image capture (dev only) | +| GET | `/debug-status` | Debug endpoint (dev only) | +| POST | `/reinitialize` | Force agent reinit (dev only) | + +## Key Conventions + +- Use `log_structured(level, message, data_dict)` from `utils.py` for all logging — it handles safe serialization of LlamaIndex objects +- Session management maps frontend `sessionId` to MongoDB `conversation_id` via `session_manager.py` with an in-memory cache backed by MongoDB +- The agent is a single global instance — all users share the same agent, but conversation history is loaded per-request from MongoDB +- Community summaries use `gpt-4o-mini` for cost efficiency; main agent uses `chatgpt-4o-latest` + +## Deployment + +- Backend: Set `PRODUCTION=true` env var, deploys to `https://ai-sandbox.oliver.solutions/hp_chatbot_back` +- Frontend: `npm run build`, deploy `dist/` to `/hp_chatbot/` path at `https://ai-sandbox.oliver.solutions/hp_chatbot/` +- CORS origins configured in `config.py:CORS_ALLOWED_ORIGINS` + +## Testing + +No formal test suite. Manual testing: start backend (`python main.py`), start frontend (`npm run dev`), test chat + image responses + document citations. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6a306f2 --- /dev/null +++ b/README.md @@ -0,0 +1,244 @@ +# HP Marketing Materials Chatbot + +A GraphRAG (Graph Retrieval-Augmented Generation) chatbot that answers questions about HP marketing materials and brand guidelines. Combines vector search with a Neo4j knowledge graph for more comprehensive retrieval, and processes multimodal documents (text + images) using LlamaParse. + +## Features + +- **Hybrid retrieval**: Vector search + knowledge graph community detection for richer context +- **Multimodal document processing**: Extracts text and page images from PDFs via LlamaParse +- **Custom ReAct agent**: LlamaIndex-based workflow with tool use, reasoning steps, and source citations +- **Conversation persistence**: MongoDB-backed chat history with multi-conversation support +- **Image references**: Responses include relevant document page screenshots +- **Brief export**: Download conversation summaries as Word documents + +## Prerequisites + +- **Python 3.10+** +- **Node.js 18+** +- **Neo4j** (dedicated instance on port 7688) +- **MongoDB** (with authentication configured) +- **API Keys**: OpenAI (`OPENAI_API_KEY`), LlamaCloud (`LLAMA_CLOUD_API_KEY`) + +## Quick Start + +### 1. Backend Setup + +```bash +# Create and activate a virtual environment +python -m venv venv +source venv/bin/activate # or venv\Scripts\activate on Windows + +# Install dependencies +pip install -r requirements.txt + +# Create .env file at project root +cat > .env << 'EOF' +OPENAI_API_KEY=your_openai_key +LLAMA_CLOUD_API_KEY=your_llama_cloud_key +NEO4J_URL=bolt://localhost:7688 +NEO4J_USERNAME=neo4j +NEO4J_PASSWORD=hp-graphrag-2024 +PORT=8746 +PRODUCTION=false +LOG_LEVEL=INFO +EOF + +# Start the server +python main.py +``` + +The backend runs on `http://localhost:8746`. On first startup it will: +1. Initialize MongoDB collections and indexes +2. Load or build the vector index from `supporting_files/files_for_rag_store/` +3. Connect to Neo4j and build/load the knowledge graph +4. Build community summaries (cached to `index_storage/graphrag_cache/`) + +### 2. Frontend Setup + +```bash +cd chat-interface + +# Install dependencies +npm install + +# Create .env file +cat > .env << 'EOF' +VITE_BACKEND_URL=http://localhost:8746 +VITE_APP_BASE_URL=/ +EOF + +# Start dev server +npm run dev +``` + +The frontend runs on `http://localhost:5173`. + +### 3. Database Setup + +**Neo4j:** +- Run a Neo4j instance on port 7688 (port 7687 is reserved for a separate project) +- Credentials: `neo4j` / `hp-graphrag-2024` +- The application auto-populates the graph on first index build + +**MongoDB:** +- Create a user `hp` with password `hp` and `authSource=hp_chatbot` +- Database: `hp_chatbot` +- Collections (`users`, `conversations`, `messages`) are auto-created by `init_mongodb.py` on startup + +Example MongoDB user setup: +```javascript +use hp_chatbot +db.createUser({ + user: "hp", + pwd: "hp", + roles: [{ role: "readWrite", db: "hp_chatbot" }] +}) +``` + +## Project Structure + +``` +├── main.py # Entry point, Hypercorn ASGI server +├── config.py # Centralized configuration +├── ai_core.py # ReAct agent, document processing, index init +├── graph_rag_integration.py # GraphRAG: extraction, community detection, query engine +├── routes.py # Flask API endpoints +├── shared_state.py # Global state for agent/index/graph (cross-module) +├── session_manager.py # Session-to-conversation mapping +├── mongodb_utils.py # MongoDB CRUD operations +├── json_utils.py # Custom JSON serialization for LlamaIndex types +├── document_generator.py # Markdown-to-Word document conversion +├── utils.py # Logging and file utilities +├── init_mongodb.py # Database initialization script +├── requirements.txt # Python dependencies +├── .env # Environment variables (not committed) +├── supporting_files/ +│ └── files_for_rag_store/ # HP marketing documents for indexing +├── uploads/ +│ └── images/ # Extracted document page images +├── index_storage/ +│ ├── hp_docs_index/ # Persisted vector index +│ └── graphrag_cache/ # Cached community summaries (pickle) +└── chat-interface/ # React frontend + ├── src/ + │ ├── App.jsx # Main chat interface component + │ ├── auth.js # MSAL authentication + │ ├── components/ + │ │ ├── ChatInterface.jsx + │ │ ├── ConversationManager.jsx + │ │ └── ThemeToggle.jsx + │ └── lib/utils.js + ├── package.json + └── dist/ # Production build output +``` + +## Architecture Overview + +``` +┌─────────────┐ POST /chat ┌──────────────┐ +│ React UI │ ──────────────────► │ Flask/ │ +│ (App.jsx) │ ◄────────────────── │ Hypercorn │ +│ │ JSON response │ (routes.py) │ +└─────────────┘ └──────┬───────┘ + │ + ┌──────▼───────┐ + │ Session Mgr │──── MongoDB + │ │ (conversations, + └──────┬───────┘ messages, users) + │ + ┌──────▼───────┐ + │ ReActAgent2 │ + │ (ai_core.py) │ + └──────┬───────┘ + │ + ┌────────────┼────────────┐ + │ │ + ┌──────▼──────┐ ┌──────▼───────┐ + │ Vector │ │ GraphRAG │ + │ Query Tool │ │ Query Tool │ + │ │ │ │ + │ LlamaIndex │ │ Vector + │ + │ VectorStore │ │ Community │ + │ Index │ │ Retrieval │ + └─────────────┘ └──────┬───────┘ + │ + ┌──────▼───────┐ + │ Neo4j │ + │ Knowledge │ + │ Graph │ + └──────────────┘ +``` + +## API Reference + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `POST` | `/chat` | Send a chat message. Body: `{message, sessionId}` | +| `GET` | `/status?sessionId=` | Check system initialization status | +| `GET` | `/conversations` | List user's conversations (requires `X-MS-USERNAME` header) | +| `POST` | `/conversations/new` | Create a new conversation | +| `GET` | `/conversations/:id/messages` | Get messages for a conversation | +| `DELETE` | `/conversations/:id` | Soft-delete a conversation | +| `POST` | `/reset` | Reset global agent memory. Body: `{sessionId}` | +| `GET` | `/images/:filename` | Serve a document page image | +| `GET` | `/list-images` | List all available images | +| `POST` | `/download-brief` | Generate Word doc. Body: `{brief_content, sessionId}` | + +**Authentication**: The frontend sends the MSAL username via `X-MS-USERNAME` header. In development mode (`PRODUCTION=false`), a default `dev_user@local` is used. + +## Configuration + +All configuration is centralized in `config.py`. Key settings: + +| Setting | Default | Description | +|---------|---------|-------------| +| `LLM_MODEL` | `chatgpt-4o-latest` | Main LLM for the ReAct agent | +| `EMBEDDING_MODEL` | `text-embedding-3-small` | Embedding model for vector index | +| `LLM_TEMPERATURE` | `0.3` | LLM temperature | +| `SIMILARITY_TOP_K` | `10` | Number of vector results to retrieve | +| `AGENT_TIMEOUT` | `600s` | Overall agent workflow timeout | +| `LLM_TIMEOUT` | `300s` | Per-LLM-call timeout | +| `SERVER_PORT` | `8746` | Backend server port | + +Community summaries use `gpt-4o-mini` for cost efficiency (configured in `graph_rag_integration.py`). + +## Adding Documents + +Place HP marketing documents (PDF, DOCX, PPTX, TXT) in `supporting_files/files_for_rag_store/`. On the next startup with no existing index, the system will: + +1. Parse documents with LlamaParse (text + image extraction) +2. Split into semantic chunks +3. Build a vector index (persisted to `index_storage/hp_docs_index/`) +4. Extract knowledge graph triplets and store in Neo4j +5. Run community detection and cache summaries + +To force a full reindex, delete `index_storage/hp_docs_index/` and clear the Neo4j database before restarting. + +## Deployment + +### Backend +- Set `PRODUCTION=true` environment variable +- Server binds to `0.0.0.0` in production mode +- Configure `CORS_ALLOWED_ORIGINS` in `config.py` +- Production URL: `https://ai-sandbox.oliver.solutions/hp_chatbot_back` + +### Frontend +```bash +cd chat-interface +npm run build +``` +- Deploy `dist/` contents to the `/hp_chatbot/` path +- Ensure proper MIME types for `.js` files on the web server +- Configure SPA routing (see `web.config` or `.htaccess`) +- Production URL: `https://ai-sandbox.oliver.solutions/hp_chatbot/` + +## Troubleshooting + +| Issue | Solution | +|-------|----------| +| Backend won't start | Check that Neo4j and MongoDB are running. Verify `OPENAI_API_KEY` is set in `.env` | +| "Agent unavailable" errors | Check startup logs for LLM API test failure. The `/reinitialize` endpoint (dev only) can force re-init | +| No images in responses | Verify `LLAMA_CLOUD_API_KEY` is set. Check that `uploads/images/` contains extracted images | +| CORS errors | Add the frontend origin to `CORS_ALLOWED_ORIGINS` in `config.py` | +| Slow first startup | Initial document processing and graph building can take significant time depending on document volume | +| Neo4j connection refused | Ensure Neo4j is on port 7688 (not 7687, which is a different project) | diff --git a/ai_core.py b/ai_core.py new file mode 100644 index 0000000..3564202 --- /dev/null +++ b/ai_core.py @@ -0,0 +1,1374 @@ +# hp_chatbot/ai_core.py +import os +import asyncio +import traceback +import uuid +import shutil +import re +import inspect +import json +from pathlib import Path +from typing import List, Dict, Any, Optional, Union + +import httpx +import tiktoken +import nest_asyncio +from concurrent.futures import ThreadPoolExecutor +from functools import partial + +# Import GraphRAG integration +from graph_rag_integration import ( + create_graph_components, + create_graphrag_query_engine, + generate_final_answer, + GraphRAGExtractor, + GraphRAGStore, + GraphRAGQueryEngine +) + +from llama_index.core import ( + VectorStoreIndex, + Document as LlamaIndexDocument, + Settings, + get_response_synthesizer, + load_index_from_storage, + StorageContext, + SimpleDirectoryReader # Keep if needed for fallback/other uses +) +from llama_index.core.retrievers import VectorIndexAutoRetriever, VectorIndexRetriever +from llama_index.core.query_engine import RetrieverQueryEngine +from llama_index.core.postprocessor import SimilarityPostprocessor +from llama_index.core.response_synthesizers import ResponseMode +from llama_index.llms.openai import OpenAI as LlamaOpenAI +from llama_index.embeddings.openai import OpenAIEmbedding +from llama_index.core.callbacks import CallbackManager, TokenCountingHandler +from llama_index.core.tools import QueryEngineTool, ToolMetadata, BaseTool, ToolSelection, ToolOutput +from llama_index.core.memory import ChatMemoryBuffer +from llama_index.core.llms import ChatMessage, LLM +from llama_index.core.vector_stores.types import MetadataInfo, VectorStoreInfo +from llama_index.core.agent.react import ReActChatFormatter, ReActOutputParser +from llama_index.core.agent.react.types import ( + ActionReasoningStep, + ObservationReasoningStep, + ResponseReasoningStep, + BaseReasoningStep +) +from llama_index.core.workflow import ( + Context, + Workflow, + StartEvent, + StopEvent, + step, + Event, +) +from llama_index.core.node_parser import ( + SentenceSplitter, + SemanticSplitterNodeParser, +) +from llama_parse import LlamaParse + +# Import from our modules +from utils import logger, log_structured +from config import ( + HP_DOCS_FOLDER, INDEX_PERSIST_PATH, IMAGES_DIRECTORY, + LLM_MODEL, EMBEDDING_MODEL, LLM_TEMPERATURE, LLM_TIMEOUT, AGENT_TIMEOUT, + TOOL_EXECUTION_TIMEOUT, SIMILARITY_TOP_K, SIMILARITY_CUTOFF, + LLAMA_PARSE_VENDOR_MODEL, LLAMA_PARSE_MAX_TIMEOUT, + NEO4J_URL, NEO4J_USERNAME, NEO4J_PASSWORD +) + +nest_asyncio.apply() + +# --- Global AI State --- +# Import shared state to ensure all modules access the same instances +from shared_state import ( + global_index, global_workflow_agent, + global_graph_store, global_property_graph_index, global_graphrag_query_engine, + set_global_agent, set_global_index, set_graphrag_components +) + + +# --- Token Counter --- +try: + token_counter = TokenCountingHandler( + tokenizer=tiktoken.encoding_for_model(LLM_MODEL).encode + ) +except Exception as e: + log_structured('warning', f'Could not initialize tiktoken for {LLM_MODEL}. Token counting may be inaccurate.', {'error': str(e)}) + # Fallback tokenizer if needed, or disable token counting + token_counter = TokenCountingHandler(tokenizer=lambda text: list(text.encode("utf-8"))) + + +# --- Custom ReAct Agent Workflow --- +class PrepEvent(Event): pass +class InputEvent(Event): input: list[ChatMessage] +class ToolCallEvent(Event): tool_calls: list[ToolSelection] +class FunctionOutputEvent(Event): output: ToolOutput +class CustomStartEvent(StartEvent): input_value: str = "" + + +class ReActAgent2(Workflow): + """ + Custom ReAct Agent implementation using LlamaIndex Workflows. + Includes timeout handling for LLM calls and tool execution. + """ + def __init__( + self, + llm: LLM, + tools: list[BaseTool], + memory: ChatMemoryBuffer, + timeout: float = AGENT_TIMEOUT, # Overall workflow timeout + llm_timeout: float = LLM_TIMEOUT, # Timeout for individual LLM calls + tool_timeout: float = TOOL_EXECUTION_TIMEOUT, # Timeout for individual tool calls + verbose: bool = True, # Add verbose flag + extra_context: str | None = None, + **kwargs: Any, + ) -> None: + super().__init__(timeout=timeout, verbose=verbose, **kwargs) # Pass verbose to parent + self.llm = llm + self.tools = tools or [] + self.memory = memory + self.formatter = ReActChatFormatter(context=extra_context or "") + self.output_parser = ReActOutputParser() + self.sources: List[ToolOutput] = [] # Store ToolOutput objects directly + self.llm_timeout = llm_timeout + self.tool_timeout = tool_timeout + self.verbose = verbose # Store verbose flag + + @step + async def new_user_msg(self, ctx: Context, ev: StartEvent) -> PrepEvent: + self.sources = [] # Clear sources for new message + # Store the initial input in the context + await ctx.set("user_input", ev) # Save the whole event + + # We'll set a placeholder message for now and extract the actual input in the next step + user_msg = ChatMessage(role="user", content="Placeholder") + self.memory.put(user_msg) + await ctx.set("current_reasoning", []) + if self.verbose: + log_structured('debug', 'ReActAgent: Receiving new user message', {}) + return PrepEvent() + + @step + async def prepare_chat_history(self, ctx: Context, ev: PrepEvent) -> InputEvent: + # Get the real user input from the first step and update the memory + start_event = await ctx.get("user_input") + if hasattr(start_event, "input_value"): + # Try to access input_value directly if it exists + real_user_input = start_event.input_value + else: + # Otherwise, assume the actual input is the input value provided to run() + log_structured('info', 'ReActAgent: Extracting input from workflow input', {}) + # Default to reasonable fallback if we can't extract it + real_user_input = "How can I help you with HP marketing guidelines?" + + # Update the placeholder message with the real input + messages = self.memory.get() + if messages and messages[0].role == "user" and messages[0].content == "Placeholder": + # Replace the placeholder with real input + messages[0].content = str(real_user_input) + if self.verbose: + log_structured('debug', 'ReActAgent: Updated user message with real input', {'input': real_user_input}) + + # Format the chat history for the LLM + chat_history = self.memory.get() + current_reasoning = await ctx.get("current_reasoning", default=[]) + llm_input = self.formatter.format( + self.tools, chat_history, current_reasoning=current_reasoning + ) + if self.verbose: + log_structured('debug', 'ReActAgent: Prepared chat history for LLM', {'history_len': len(llm_input)}) + return InputEvent(input=llm_input) + + @step # The timeout is managed inside the method + async def handle_llm_input(self, ctx: Context, ev: InputEvent) -> Union[ToolCallEvent, StopEvent, PrepEvent]: + chat_history = ev.input + current_reasoning = await ctx.get("current_reasoning", default=[]) + + try: + if self.verbose: + log_structured('debug', 'ReActAgent: Sending request to LLM', {'history_len': len(chat_history)}) + + response = await asyncio.wait_for( + self.llm.achat(chat_history), + timeout=self.llm_timeout + ) + reasoning_step = self.output_parser.parse(response.message.content) + current_reasoning.append(reasoning_step) + await ctx.set("current_reasoning", current_reasoning) # Update context state + + if self.verbose: + log_structured('debug', 'ReActAgent: Received LLM response', { + 'step_type': type(reasoning_step).__name__, + 'is_done': getattr(reasoning_step, 'is_done', False), + 'has_response': hasattr(reasoning_step, 'response'), + 'has_action': hasattr(reasoning_step, 'action'), + 'action': getattr(reasoning_step, 'action', None), + 'raw_content_preview': response.message.content[:300] + }) + + if reasoning_step.is_done: + # Log what we're about to return as final response + if self.verbose: + log_structured('debug', 'ReActAgent: Processing final response', { + 'raw_response_content': response.message.content, + 'reasoning_step_response': str(getattr(reasoning_step, 'response', 'NO_RESPONSE_ATTR')) + }) + + # Clean the response to remove any thinking parts + response_text = str(reasoning_step.response) + + # Check for common thinking patterns and remove them + import re # Import re within the function scope to ensure it's available + thinking_patterns = [ + r'(?i)^.*?thinking:.*?\n', # Remove lines starting with "Thinking:" + r'(?i).*?', # Remove XML-like thinking tags + r'(?i)\[thinking\].*?\[/thinking\]', # Remove bracket thinking tags + r'(?i)I\'m thinking:.*?\n', # Remove "I'm thinking:" sections + r'(?i)Let me think.*?\n', # Remove "Let me think" sections + r'(?i)Thought:.*?Action:.*?Action Input:.*', # Remove the specific pattern user reported + r'(?i)^Thought:.*', # Remove any line starting with "Thought:" + r'(?i)Action:.*?Action Input:.*', # Remove Action/Action Input patterns + r'(?i)Thought:.*?Answer:', # Remove "Thought: ... Answer:" pattern + r'(?i)^Answer:\s*' # Remove just the "Answer:" prefix + ] + for pattern in thinking_patterns: + response_text = re.sub(pattern, '', response_text, flags=re.DOTALL) + + # Remove extra newlines that might be left after cleaning + response_text = re.sub(r'\n{3,}', '\n\n', response_text) + response_text = response_text.strip() + + # Final safety check - if response still looks like thinking, provide fallback + if re.search(r'(?i)^(Thought|Action|Observation):', response_text) or not response_text: + log_structured('warning', 'ReActAgent: Final response still contains thinking patterns, using fallback', { + 'problematic_response': response_text[:200] + }) + response_text = "I found information about your query in the HP marketing materials. Please let me know if you need more specific details." + + self.memory.put(ChatMessage(role="assistant", content=response_text)) + if self.verbose: + log_structured('info', 'ReActAgent: Final response generated', { + 'response_preview': response_text[:100], + 'sources_count': len(self.sources) + }) + + # Structure the final output + final_result = { + "response": response_text, + "sources": self.sources, # Pass the collected ToolOutput objects + "reasoning": current_reasoning + } + return StopEvent(result=final_result) + + elif isinstance(reasoning_step, ActionReasoningStep): + if self.verbose: + log_structured('debug', 'ReActAgent: Action step identified', { + 'action': reasoning_step.action, + 'input': reasoning_step.action_input + }) + # Ensure action_input is a dict + action_input_dict = reasoning_step.action_input or {} + if not isinstance(action_input_dict, dict): + log_structured('warning', 'ReActAgent: action_input is not a dict, attempting to parse', {'raw_input': action_input_dict}) + try: + # Attempt basic parsing if it looks like JSON string + if isinstance(action_input_dict, str) and action_input_dict.strip().startswith('{'): + action_input_dict = json.loads(action_input_dict) + else: # Fallback: treat as a single 'query' arg if not dict/json + action_input_dict = {'query': action_input_dict} + except Exception as parse_err: + log_structured('error', 'ReActAgent: Failed to parse action_input', {'raw_input': action_input_dict, 'error': str(parse_err)}) + action_input_dict = {'query': str(action_input_dict)} # Safest fallback + + return ToolCallEvent(tool_calls=[ + ToolSelection( + tool_id="tool_" + reasoning_step.action.replace(" ", "_"), # Simple ID generation + tool_name=reasoning_step.action, + tool_kwargs=action_input_dict + ) + ]) + else: + # Handle other reasoning step types if necessary, or just proceed + if self.verbose: + log_structured('debug', 'ReActAgent: Non-action, non-done step encountered', {'step_type': type(reasoning_step).__name__}) + return PrepEvent() # Continue the loop + + except asyncio.TimeoutError: + error_msg = f"LLM call timed out after {self.llm_timeout} seconds." + log_structured('error', 'ReActAgent: LLM Timeout', {'timeout': self.llm_timeout}) + current_reasoning.append(ObservationReasoningStep(observation=error_msg)) + await ctx.set("current_reasoning", current_reasoning) + return PrepEvent() # Try again or maybe stop? Returning PrepEvent allows loop to continue. + except Exception as e: + error_msg = f"Error during LLM interaction or parsing: {str(e)}" + log_structured('error', 'ReActAgent: Error in handle_llm_input', { + 'error': str(e), 'traceback': traceback.format_exc() + }) + current_reasoning.append(ObservationReasoningStep(observation=error_msg)) + await ctx.set("current_reasoning", current_reasoning) + # Decide whether to stop or continue after error + # Returning PrepEvent allows the agent to potentially describe the error or retry + return PrepEvent() + + + @step # The timeout is managed inside the method + async def handle_tool_calls(self, ctx: Context, ev: ToolCallEvent) -> PrepEvent: + tool_calls = ev.tool_calls + tools_by_name = {tool.metadata.name: tool for tool in self.tools} # Use .name property + current_reasoning = await ctx.get("current_reasoning", default=[]) + + if self.verbose: + log_structured('debug', 'ReActAgent: Handling tool calls', { + 'call_count': len(tool_calls), + 'tool_names': [tc.tool_name for tc in tool_calls] + }) + + for tool_call in tool_calls: + tool = tools_by_name.get(tool_call.tool_name) + if not tool: + error_msg = f"Tool '{tool_call.tool_name}' not found." + log_structured('error', 'ReActAgent: Tool not found', {'tool_name': tool_call.tool_name}) + current_reasoning.append(ObservationReasoningStep(observation=error_msg)) + continue # Skip to next tool call + + try: + tool_kwargs = tool_call.tool_kwargs or {} # Ensure kwargs is a dict + if self.verbose: + log_structured('debug', 'ReActAgent: Executing tool', { + 'tool_name': tool_call.tool_name, + 'kwargs': tool_kwargs + }) + + # Execute tool potentially in thread pool with timeout + tool_func = partial(tool, **tool_kwargs) + tool_output: ToolOutput + if inspect.iscoroutinefunction(tool.call): # Check if tool's call method is async + tool_output = await asyncio.wait_for( + tool.acall(**tool_kwargs), # Use acall for async tools + timeout=self.tool_timeout + ) + else: + # Run sync tool in thread pool + with ThreadPoolExecutor() as executor: + future = executor.submit(tool_func) # tool_func already has kwargs via partial + tool_output = await asyncio.to_thread(future.result, timeout=self.tool_timeout) + + + if self.verbose: + log_structured('debug', 'ReActAgent: Tool execution successful', { + 'tool_name': tool_call.tool_name, + 'output_type': type(tool_output).__name__, + 'output_content_preview': str(tool_output.content)[:100] if tool_output else "N/A" + }) + + # Store the raw ToolOutput object which contains content, raw_output, metadata etc. + self.sources.append(tool_output) + + # Add observation step with the tool's string content + observation_content = str(tool_output.content) if tool_output and tool_output.content is not None else "Tool executed successfully but returned no content." + current_reasoning.append(ObservationReasoningStep(observation=observation_content)) + + if self.verbose: + log_structured('debug', 'ReActAgent: Added observation to reasoning', { + 'tool_name': tool_call.tool_name, + 'observation_preview': observation_content[:200] + }) + + # --- Detailed logging for image metadata --- + if hasattr(tool_output, 'raw_output') and hasattr(tool_output.raw_output, 'source_nodes'): + for node_with_score in tool_output.raw_output.source_nodes: + node = getattr(node_with_score, 'node', None) + if node and hasattr(node, 'metadata'): + if 'image_paths' in node.metadata and node.metadata['image_paths']: + log_structured('debug', 'ReActAgent: Tool output node contains image paths', { + 'tool_name': tool_call.tool_name, + 'node_id': getattr(node, 'id_', 'N/A'), + 'image_paths': node.metadata['image_paths'] + }) + + + except asyncio.TimeoutError: + error_msg = f"Tool '{tool_call.tool_name}' timed out after {self.tool_timeout} seconds." + log_structured('error', 'ReActAgent: Tool Timeout', {'tool_name': tool_call.tool_name, 'timeout': self.tool_timeout}) + current_reasoning.append(ObservationReasoningStep(observation=error_msg)) + except Exception as e: + error_msg = f"Error calling tool '{tool_call.tool_name}': {str(e)}" + log_structured('error', 'ReActAgent: Tool execution error', { + 'tool_name': tool_call.tool_name, 'error': str(e), 'traceback': traceback.format_exc() + }) + current_reasoning.append(ObservationReasoningStep(observation=error_msg)) + + # Update reasoning steps in context before returning + await ctx.set("current_reasoning", current_reasoning) + return PrepEvent() # Always return PrepEvent to continue the loop + + +# --- Document Processing --- +async def process_documents_in_directory(directory: str, session_id: Optional[str] = None) -> List[LlamaIndexDocument]: + """ + Process all documents in a directory using LlamaParse for text and images, + preserving chunk-level metadata including specific image paths per chunk. + Includes detailed logging for image metadata assignment. + + Args: + directory: The path to the directory containing documents. + session_id: Optional session identifier for context. + + Returns: + A list of LlamaIndexDocument objects representing the processed chunks, + ready for indexing. Returns an empty list on failure or if no documents + are processed. + """ + parser_text = None + parser_images = None + try: + # Ensure images directory exists + os.makedirs(IMAGES_DIRECTORY, exist_ok=True) + + log_structured('info', f'Starting document processing for directory: {directory}', { + 'session_id': session_id, + 'directory_name': os.path.basename(directory), + 'directory_exists': os.path.exists(directory), + 'files_present': os.listdir(directory) if os.path.exists(directory) else 'N/A' + }) + + if not os.path.exists(directory) or not os.path.isdir(directory): + log_structured('error', f'Directory not found or is not a directory: {directory}', {'session_id': session_id}) + return [] + if not os.listdir(directory): + log_structured('warning', f'Directory is empty, skipping: {directory}', {'session_id': session_id}) + return [] + + # --- LlamaParse Initialization --- + try: + # Separate clients recommended if making concurrent calls, but can share if sequential + custom_client_text = httpx.AsyncClient(timeout=LLAMA_PARSE_MAX_TIMEOUT) + custom_client_images = httpx.AsyncClient(timeout=LLAMA_PARSE_MAX_TIMEOUT) + + parser_text = LlamaParse( + result_type="markdown", + add_page_breaks=False, + system_prompt="Extract all content including text, tables, and formatting. Preserve structure.", + premium_mode=False, # Set based on your LlamaCloud plan + max_timeout=LLAMA_PARSE_MAX_TIMEOUT, + custom_client=custom_client_text, + verbose=True # Enable verbose logging for LlamaParse + ) + parser_images = LlamaParse( + result_type="markdown", # Less critical here, parsing for images primarily + add_page_breaks=False, + system_prompt="Generate page images of the document.", + use_vendor_multimodal_model=True, # Assuming you want LlamaParse's image gen + vendor_multimodal_model_name=LLAMA_PARSE_VENDOR_MODEL, + premium_mode=False, # Set based on your LlamaCloud plan + max_timeout=LLAMA_PARSE_MAX_TIMEOUT, + custom_client=custom_client_images, + verbose=True # Enable verbose logging for LlamaParse + ) + log_structured('info', 'Initialized LlamaParse (text & image capability)', {'session_id': session_id}) + except Exception as parser_err: + log_structured('error', f'Error initializing dual LlamaParse capability: {parser_err}. Falling back to text-only.', { + 'session_id': session_id, 'traceback': traceback.format_exc() + }) + if parser_text and hasattr(parser_text, 'aclose'): await parser_text.aclose() + if parser_images and hasattr(parser_images, 'aclose'): await parser_images.aclose() + parser_images = None # Disable image parsing + try: + # Ensure client is fresh for fallback + custom_client_text = httpx.AsyncClient(timeout=LLAMA_PARSE_MAX_TIMEOUT) + parser_text = LlamaParse( + result_type="markdown", + language="en", + add_page_breaks=False, + merge_consecutive=True, + max_timeout=LLAMA_PARSE_MAX_TIMEOUT, + custom_client=custom_client_text, + verbose=True + ) + log_structured('info', 'Initialized LlamaParse with fallback text-only parser.', {'session_id': session_id}) + except Exception as fallback_err: + log_structured('critical', f'FATAL: Error initializing fallback LlamaParse: {fallback_err}', { + 'session_id': session_id, 'traceback': traceback.format_exc() + }) + if parser_text and hasattr(parser_text, 'aclose'): await parser_text.aclose() # Cleanup + return [] + + if not parser_text: + log_structured('critical', 'FATAL: Text parser (parser_text) could not be initialized.') + return [] + + file_extractor = { + ".pdf": parser_text, ".docx": parser_text, ".doc": parser_text, + ".pptx": parser_text, ".ppt": parser_text, ".txt": parser_text, + # Add others if your LlamaParse supports them + # ".html": parser_text, ".md": parser_text, + } + supported_extensions = list(file_extractor.keys()) + + # --- Custom File Reader Async Function --- + async def custom_file_reader(): + processed_chunks: List[LlamaIndexDocument] = [] + images_by_file_and_page: Dict[str, Dict[int, str]] = {} # filename -> { page_num_1_based -> image_filename } + + all_files_paths = [] + log_structured('debug', f'Searching for supported files in: {directory}', {'extensions': supported_extensions, 'session_id': session_id}) + for ext in supported_extensions: + all_files_paths.extend(list(Path(directory).glob(f"*{ext}"))) + all_files_paths.extend(list(Path(directory).glob(f"*{ext.upper()}"))) # Case-insensitive glob + all_files_paths = sorted(list(set(all_files_paths))) # Remove duplicates and sort + + log_structured('info', f'Found {len(all_files_paths)} supported files in {directory}', {'session_id': session_id, 'files': [f.name for f in all_files_paths]}) + if not all_files_paths: + log_structured('warning', f'No supported files found in directory: {directory}', {'session_id': session_id}) + return [] + + for file_path in all_files_paths: + file_path_str = str(file_path) + filename = file_path.name + log_structured('info', f'Processing file: {filename}', {'session_id': session_id, 'path': file_path_str}) + + ext = file_path.suffix.lower() + current_text_parser = file_extractor.get(ext) + if not current_text_parser: + log_structured('warning', f'Skipping file {filename}: No parser defined for extension {ext}.', {'session_id': session_id}) + continue + + # 1. Extract Text Chunks + text_chunks: List[LlamaIndexDocument] = [] + try: + log_structured('debug', f'Calling parser_text.aload_data for {filename}', {'session_id': session_id}) + # LlamaParse aload_data returns List[Document] + text_chunks = await current_text_parser.aload_data(file_path_str) + log_structured('info', f'Extracted {len(text_chunks)} text chunks from {filename}', {'session_id': session_id}) + if not text_chunks: + log_structured('warning', f'No text chunks extracted from {filename}. File might be empty or parser issue.', {'session_id': session_id}) + # Continue to attempt image extraction for this file + except Exception as text_err: + log_structured('error', f'Error extracting text from {filename}', { + 'session_id': session_id, 'error': str(text_err), 'traceback': traceback.format_exc() + }) + continue # Skip to next file if text extraction fails critically + + # 2. Extract Images (if parser_images is available) + file_page_images: Dict[int, str] = {} # { page_num_1_based: image_filename } + if parser_images: + try: + log_structured('debug', f'Attempting image extraction for: {filename}', {'session_id': session_id}) + temp_image_dir = IMAGES_DIRECTORY / f"temp_img_{filename}_{uuid.uuid4().hex[:8]}" + os.makedirs(temp_image_dir, exist_ok=True) + + # Use synchronous methods for simplicity here, or manage async complexity + # NOTE: Check LlamaParse documentation for the best way to get images. + # This assumes get_json_result and get_images are available and work this way. + # If these are async, you'll need `await parser_images.aget_json_result(...)` etc. + # Running sync methods in executor to avoid blocking event loop + loop = asyncio.get_running_loop() + with ThreadPoolExecutor() as pool: + md_json_objs = await loop.run_in_executor(pool, parser_images.get_json_result, file_path_str) + log_structured('debug', f'Got JSON result for images from {filename}', {'session_id': session_id}) + image_dicts = await loop.run_in_executor(pool, parser_images.get_images, md_json_objs, temp_image_dir) + + log_structured('info', f'LlamaParse reported {len(image_dicts)} images potentially extracted for {filename}', {'session_id': session_id}) + + saved_image_count = 0 + for idx, img_info in enumerate(image_dicts): + # LlamaParse might return 0-based 'page' index + page_index_0_based = img_info.get('page', idx) # Default to list index if 'page' missing + page_num_1_based = page_index_0_based + 1 # Convert to 1-based for consistency + + # log_structured('debug', f'Processing image info for {filename}, index {idx}', {'img_info': img_info, 'page_1_based': page_num_1_based}) + + if 'path' in img_info and img_info['path'] and os.path.exists(img_info['path']): + source_img_path = img_info['path'] + image_filename = f"{os.path.splitext(filename)[0]}_page{page_num_1_based}_{uuid.uuid4().hex[:6]}.png" + dest_path = IMAGES_DIRECTORY / image_filename + + try: + shutil.copy2(source_img_path, dest_path) # copy2 preserves metadata + file_page_images[page_num_1_based] = image_filename # Map 1-based page num + saved_image_count += 1 + log_structured('debug', f'Saved image for {filename} page {page_num_1_based} (1-based) to {dest_path}', {'session_id': session_id}) + except Exception as copy_err: + log_structured('error', f'Error copying image for {filename} page {page_num_1_based}', {'session_id': session_id, 'error': str(copy_err)}) + else: + log_structured('warning', f'No valid image path found or file missing for image index {idx} (reported page {page_index_0_based}) from {filename}. Path: {img_info.get("path", "N/A")}', {'session_id': session_id}) + + log_structured('info', f'Successfully saved {saved_image_count} images for {filename}', {'session_id': session_id}) + images_by_file_and_page[filename] = file_page_images + + # Clean up temporary directory + try: + shutil.rmtree(temp_image_dir) + except Exception as cleanup_err: + log_structured('error', f'Error cleaning up temp image dir {temp_image_dir}', {'session_id': session_id, 'error': str(cleanup_err)}) + + except Exception as img_err: + log_structured('error', f'Error during image extraction pipeline for {filename}', { + 'session_id': session_id, 'error': str(img_err), 'traceback': traceback.format_exc() + }) + images_by_file_and_page[filename] = {} # Ensure empty dict on error + else: + log_structured('info', f'Image parsing skipped for {filename} (parser_images is None).', {'session_id': session_id}) + images_by_file_and_page[filename] = {} + + # 3. Add Metadata to Each Text Chunk + log_structured('debug', f'Assigning metadata and images to {len(text_chunks)} chunks for {filename}', {'session_id': session_id}) + for chunk_index, chunk in enumerate(text_chunks): + if not hasattr(chunk, 'metadata') or chunk.metadata is None: chunk.metadata = {} + + chunk.metadata['filename'] = filename + chunk.metadata['file_path'] = file_path_str + chunk.metadata['source'] = "document" # Or more specific if needed + chunk.metadata['type'] = os.path.basename(directory) # e.g., 'brief', 'supporting' + chunk.metadata['chunk_index'] = chunk_index + + # --- Determine 1-based Page Number --- + page_num_1_based: Optional[int] = None + page_source_key: Optional[str] = None + + # Priority: LlamaParse metadata keys + page_key_options = ['page_label', 'page_number', 'page'] # Check common keys + for key in page_key_options: + if key in chunk.metadata: + try: + page_num_1_based = int(chunk.metadata[key]) # Assume it's 1-based from LlamaParse + if page_num_1_based > 0: # Basic sanity check + page_source_key = key + chunk.metadata["source_page"] = page_num_1_based # Store consistently + log_structured('debug', f"Found page {page_num_1_based} from metadata key '{key}'", {'filename': filename, 'chunk': chunk_index, 'session_id': session_id}) + break + else: + page_num_1_based = None # Ignore non-positive page numbers + except (ValueError, TypeError): pass # Ignore if not integer + + # Fallback: If no page found in metadata, try approximation (less reliable) + # This part is optional and might be inaccurate. Consider removing if metadata is reliable. + if page_num_1_based is None: + # Simple fallback: use chunk index as a proxy (very rough) + page_num_1_based = chunk_index + 1 # Treat first chunk as page 1 approx. + chunk.metadata["source_page"] = page_num_1_based + page_source_key = "position_fallback" + log_structured('debug', f"Using position fallback for page: {page_num_1_based}", {'filename': filename, 'chunk': chunk_index, 'session_id': session_id}) + + + # --- Precise Page-Based Image Assignment --- + chunk.metadata['image_paths'] = [] # Initialize/reset + specific_image_filename = None + + if page_num_1_based is not None: + file_images_dict = images_by_file_and_page.get(filename, {}) + if file_images_dict: + # Try exact match first + if page_num_1_based in file_images_dict: + specific_image_filename = file_images_dict[page_num_1_based] + chunk.metadata['image_match_type'] = 'exact' + log_structured('debug', f'Exact page match for image page {page_num_1_based}', {'filename': filename, 'chunk': chunk_index, 'image': specific_image_filename}) + else: + # Optional: Find nearest page if exact match fails (can be noisy) + # nearest_page = min(file_images_dict.keys(), key=lambda x: abs(x - page_num_1_based)) + # if abs(nearest_page - page_num_1_based) <= 1: # Only if very close? Threshold needed. + # specific_image_filename = file_images_dict[nearest_page] + # chunk.metadata['image_match_type'] = 'nearest' + # chunk.metadata["image_nearest_page"] = nearest_page + # log_structured('debug', f'Nearest page match: requested {page_num_1_based}, using {nearest_page}', {'filename': filename, 'chunk': chunk_index, 'image': specific_image_filename}) + pass # Default: No image if no exact match + + + if specific_image_filename: + chunk.metadata['image_paths'] = [specific_image_filename] # Store as list + + # Final metadata log before adding chunk + # log_structured('debug', "Final chunk metadata check", { + # 'session_id': session_id, 'filename': filename, 'chunk': chunk_index, + # 'page': chunk.metadata.get('source_page'), 'page_src': page_source_key, + # 'image': chunk.metadata.get('image_paths'), 'match_type': chunk.metadata.get('image_match_type'), + # 'keys': list(chunk.metadata.keys()) + # }) + + processed_chunks.append(chunk) + + # --- End of file loop --- + log_structured('info', f'Finished processing files. Total chunks: {len(processed_chunks)}', {'session_id': session_id}) + return processed_chunks + + # --- Execute the async file reader --- + final_documents: List[LlamaIndexDocument] = await custom_file_reader() + + log_structured('info', 'Directory processing complete.', { + 'session_id': session_id, 'directory': directory, 'total_chunks_generated': len(final_documents) + }) + # Log sample metadata for verification + # for i, doc in enumerate(final_documents[:2]): + # log_structured('debug', f'Final Doc Sample #{i} Metadata', {'metadata': doc.metadata}) + + return final_documents + + except Exception as e: + log_structured('critical', 'FATAL Error in process_documents_in_directory', { + 'session_id': session_id, 'directory': directory, 'error': str(e), 'traceback': traceback.format_exc() + }) + return [] # Return empty list on major failure + finally: + # Ensure async clients are closed + log_structured('debug', 'Closing LlamaParse clients.', {'session_id': session_id}) + if parser_text and hasattr(parser_text, 'aclose'): + try: await parser_text.aclose() + except Exception as close_err: log_structured('error', 'Error closing parser_text client', {'error': str(close_err)}) + if parser_images and hasattr(parser_images, 'aclose'): + try: await parser_images.aclose() + except Exception as close_err: log_structured('error', 'Error closing parser_images client', {'error': str(close_err)}) + + +# --- Global Index Initialization --- +async def initialize_global_index() -> bool: + """Initialize the global index from HP documents at startup.""" + # Use shared state instead of module-level globals + + try: + # --- Configure LLM and Embedding Model --- + # Check for real API keys + openai_key = os.environ.get("OPENAI_API_KEY", "") + if not openai_key: + log_structured('critical', 'No OpenAI API key provided. Make sure OPENAI_API_KEY is set in your .env file.') + return False + + # Log the first few characters of the key for debugging (important to verify it's loaded) + key_preview = openai_key[:4] + "..." if len(openai_key) > 4 else "invalid" + log_structured('info', f'Using OpenAI API key starting with: {key_preview}') + + # Normal initialization with real API keys + try: + llm = LlamaOpenAI( + model=LLM_MODEL, + temperature=LLM_TEMPERATURE, + timeout=LLM_TIMEOUT + ) + # Test the LLM with a simple prompt to ensure it's working + test_prompt = "Say 'API key is working' if you can read this." + _ = llm.complete(test_prompt) + log_structured('info', 'Successfully tested LLM API connection') + except Exception as llm_err: + log_structured('critical', f'Failed to initialize LLM with provided API key: {str(llm_err)}') + return False + embed_model = OpenAIEmbedding(model=EMBEDDING_MODEL) + + # --- Configure Global Settings --- + Settings.llm = llm + Settings.embed_model = embed_model + Settings.callback_manager = CallbackManager([token_counter]) + # Settings.chunk_size = NODE_PARSER_CHUNK_SIZE # If using SentenceSplitter + # Settings.chunk_overlap = NODE_PARSER_CHUNK_OVERLAP + + # Use Semantic Splitter (more robust, less config needed here) + node_parser = SemanticSplitterNodeParser( + buffer_size=1, breakpoint_percentile_threshold=95, embed_model=embed_model # Adjust threshold + ) + Settings.node_parser = node_parser + # Alternatively, configure SentenceSplitter globally + # Settings.node_parser = SentenceSplitter( + # chunk_size=NODE_PARSER_CHUNK_SIZE, + # chunk_overlap=NODE_PARSER_CHUNK_OVERLAP, + # # ... other SentenceSplitter params + # ) + + # --- Load or Build Index --- + if INDEX_PERSIST_PATH.exists(): + log_structured('info', f'Loading existing index from {INDEX_PERSIST_PATH}') + storage_context = StorageContext.from_defaults(persist_dir=str(INDEX_PERSIST_PATH)) + index = load_index_from_storage(storage_context) + # Save to shared state + set_global_index(index) + log_structured('info', 'Successfully loaded existing index') + + # Attempt to load or recreate GraphRAG components + try: + log_structured('info', 'Attempting to recreate GraphRAG components from loaded index') + + # First, try to connect to Neo4j to check if it has data + from llama_index.graph_stores.neo4j import Neo4jPropertyGraphStore + property_graph_store = Neo4jPropertyGraphStore( + username=NEO4J_USERNAME, + password=NEO4J_PASSWORD, + url=NEO4J_URL + ) + log_structured('info', 'Successfully connected to Neo4j database') + + # Create temporary GraphRAGStore to check for existing data + temp_graph_store = GraphRAGStore(property_graph_store) + triplets = temp_graph_store.get_triplets() + neo4j_has_data = len(triplets) > 0 + + if neo4j_has_data: + # Neo4j already has data, just use it + log_structured('info', f'Neo4j contains {len(triplets)} triplets. Using existing data.') + graph_store, property_graph_index = create_graph_components( + llm=llm, + force_reindex=False # Use existing Neo4j data + ) + log_structured('info', 'GraphRAG components loaded from existing Neo4j data') + else: + # Neo4j is empty, need to extract nodes from the vector index to populate it + log_structured('info', 'Neo4j is empty. Extracting nodes from vector index for GraphRAG indexing.') + + # Get all nodes from the vector index + from llama_index.core.schema import TextNode + vector_nodes = [] + + # Extract nodes from the index's docstore + if hasattr(index, 'docstore') and index.docstore: + docstore_nodes = list(index.docstore.docs.values()) + vector_nodes.extend(docstore_nodes) + log_structured('info', f'Retrieved {len(docstore_nodes)} nodes from index docstore') + + # Handle cases where we can't get nodes directly + if not vector_nodes: + log_structured('warning', 'Could not retrieve nodes from vector index. GraphRAG indexing will be skipped.') + raise ValueError("No nodes could be retrieved from the vector index for GraphRAG indexing") + + # Now create GraphRAG components with the retrieved nodes + graph_store, property_graph_index = create_graph_components( + llm=llm, + nodes=vector_nodes, + max_paths_per_chunk=10, + force_reindex=True # Force indexing since Neo4j is empty + ) + log_structured('info', f'GraphRAG components created with {len(vector_nodes)} nodes from vector index') + except Exception as e: + log_structured('warning', f'Error recreating GraphRAG components: {e}. Continuing without GraphRAG.') + graph_store = None + else: + log_structured('info', f'No index found at {INDEX_PERSIST_PATH}. Creating new index from {HP_DOCS_FOLDER}') + if not HP_DOCS_FOLDER.exists() or not any(HP_DOCS_FOLDER.iterdir()): + log_structured('error', f'HP documents folder is missing or empty: {HP_DOCS_FOLDER}') + return False + + # Process documents using LlamaParse + documents = await process_documents_in_directory(str(HP_DOCS_FOLDER), session_id="global_init") + + if not documents: + log_structured('error', f'No documents processed from {HP_DOCS_FOLDER}. Index creation aborted.') + return False + + log_structured('info', 'Creating vector store index...', { + 'document_count': len(documents), + 'sample_doc_metadata': documents[0].metadata if documents else None + }) + + # Build the index using the globally configured Settings (incl. node_parser) + index = VectorStoreIndex.from_documents( + documents=documents, + show_progress=True, + # service_context=service_context, # Old way, use Settings now + ) + + # Save to shared state + set_global_index(index) + + # Persist the index + index.storage_context.persist(persist_dir=str(INDEX_PERSIST_PATH)) + log_structured('info', f'Index created and persisted to {INDEX_PERSIST_PATH}') + + # --- Create GraphRAG components --- + log_structured('info', 'Starting GraphRAG component creation') + try: + # Get nodes from the index's docstore for GraphRAG + docstore_nodes = [] + if hasattr(index, 'docstore') and index.docstore: + docstore_nodes = list(index.docstore.docs.values()) + log_structured('info', f'Retrieved {len(docstore_nodes)} nodes from index docstore for GraphRAG') + + # If docstore is empty or doesn't exist, use the original documents + nodes_for_graph = docstore_nodes if docstore_nodes else documents + log_structured('info', f'Using {len(nodes_for_graph)} nodes for GraphRAG indexing') + + # Create GraphRAG components + graph_store, property_graph_index = create_graph_components( + llm=llm, + nodes=nodes_for_graph, + max_paths_per_chunk=10, + force_reindex=True # Force indexing for new index creation + ) + log_structured('info', 'GraphRAG components created successfully') + except Exception as graph_err: + log_structured('error', f'Error creating GraphRAG components: {graph_err}', + {'traceback': traceback.format_exc()}) + # Continue without GraphRAG if there's an error + + # --- Create Retriever and Query Engine --- + vector_store_info = VectorStoreInfo( + content_info="HP marketing reference materials, including brand guidelines and supporting documents.", + metadata_info=[ + MetadataInfo(name="filename", type="str", description="Filename of the source document"), + MetadataInfo(name="source_page", type="int", description="Approximate page number in the source document"), + MetadataInfo(name="image_paths", type="list[str]", description="List of image filenames associated with this chunk"), + # Add other relevant metadata fields here + ], + ) + + all_retriever = VectorIndexAutoRetriever( + index=index, # Use the local variable, not global_index + vector_store_info=vector_store_info, + similarity_top_k=SIMILARITY_TOP_K, + verbose=True # Enable verbose logging for retriever + ) + + # Create standard vector-based query engine + all_query_engine = RetrieverQueryEngine.from_args( # Use from_args for clarity + retriever=all_retriever, + response_synthesizer=get_response_synthesizer( + response_mode=ResponseMode.COMPACT, # Or REFINE, TREE_SUMMARIZE etc. + # service_context=service_context # Old way + ), + node_postprocessors=[ + SimilarityPostprocessor(similarity_cutoff=SIMILARITY_CUTOFF), + ], + # service_context=service_context # Old way + ) + + # Create GraphRAG query engine if components were created successfully + graphrag_query_engine = None + graph_store = locals().get('graph_store', None) + property_graph_index = locals().get('property_graph_index', None) + if graph_store is not None and property_graph_index is not None: + try: + # Ensure graph communities are built before creating query engine + if not hasattr(graph_store, 'communities_built') or not graph_store.communities_built: + log_structured('info', 'Building graph communities before creating query engine') + try: + # Use gpt-4o-mini model for community summaries (set in GraphRAGStore) + # The build_communities() method will first try to load from cache + # and will only rebuild and re-cache if cache loading fails + # It also tracks if communities are already built to avoid duplicate work + graph_store.build_communities() + log_structured('info', 'Communities built successfully (loaded from cache or built new)') + except Exception as comm_err: + log_structured('error', f'Error building communities: {comm_err}', + {'traceback': traceback.format_exc()}) + # Continue with query engine creation even if communities failed + + # Create a basic VectorIndexRetriever for GraphRAG + vector_retriever = VectorIndexRetriever( + index=index, + similarity_top_k=SIMILARITY_TOP_K + ) + + # Create the GraphRAG query engine - ensure all required fields are passed directly + try: + graphrag_query_engine = create_graphrag_query_engine( + vector_retriever=vector_retriever, + graph_store=graph_store, + llm=llm, + similarity_top_k=SIMILARITY_TOP_K + ) + log_structured('info', 'GraphRAG query engine created successfully') + except Exception as e: + log_structured('error', f'Error creating GraphRAG query engine: {e}', {'traceback': traceback.format_exc()}) + # Create a direct instance without using the factory function as a fallback + from graph_rag_integration import GraphRAGQueryEngine + graphrag_query_engine = GraphRAGQueryEngine( + vector_retriever=vector_retriever, + graph_store=graph_store, + llm=llm, + similarity_top_k=SIMILARITY_TOP_K + ) + + # Store GraphRAG components in shared state + set_graphrag_components( + graph_store=graph_store, + property_graph_index=property_graph_index, + graphrag_query_engine=graphrag_query_engine + ) + + log_structured('info', 'GraphRAG query engine created successfully') + except Exception as graph_engine_err: + log_structured('error', f'Error creating GraphRAG query engine: {graph_engine_err}', + {'traceback': traceback.format_exc()}) + # Continue without GraphRAG query engine if there's an error + + # --- Create Query Engine Tools --- + query_engine_tools_react = [ + QueryEngineTool( + query_engine=all_query_engine, + metadata=ToolMetadata( + name="answer_questions_from_hp_marketing_materials", + description="USE THIS TOOL FOR ALL QUERIES - Queries HP marketing materials (brand guidelines, etc.) to answer questions about guidelines, workflows, and processes. Use this for specific lookups in the knowledge base." + ), + ), + ] + + # Add GraphRAG tool if available + if graphrag_query_engine is not None: + class GraphRAGTool(BaseTool): + def __init__(self, query_engine): + self.query_engine = query_engine + self._metadata = ToolMetadata( + name="answerquestionswith_graphrag", + description="USE THIS TOOL FOR ALL QUERIES - Queries HP marketing materials using both vector and graph-based retrieval for more comprehensive answers. Use this for complex questions that need context from multiple related documents." + ) + + @property + def metadata(self): + return self._metadata + + def __call__(self, query_str: str) -> ToolOutput: + """Run query through GraphRAG and generate synthesized answer.""" + from shared_state import global_graphrag_query_engine + + log_structured('info', 'GraphRAG Tool: Starting dual retrieval', {'query': query_str}) + + try: + # Get both vector and GraphRAG retrieval results + retrieval_result = self.query_engine.custom_query(query_str) + + # Generate synthesized answer + final_answer = generate_final_answer(query_str, retrieval_result, self.query_engine.llm) + + # Prepare the tool output + log_message = { + 'vector_context_length': len(retrieval_result.get('vector_context', '')), + 'graphrag_context_length': len(retrieval_result.get('graphrag_context', '')), + 'vector_nodes_count': len(retrieval_result.get('vector_nodes', [])), + 'community_ids': retrieval_result.get('community_ids', []) + } + log_structured('info', 'GraphRAG Tool: Retrieval complete', log_message) + + # Extract vector nodes and create a properly structured raw_output that includes source_nodes + # This allows the routes.py code to extract images from these nodes + vector_nodes = retrieval_result.get('vector_nodes', []) + + # Create a wrapper object that mimics the structure expected by routes.py for image extraction + class NodeWrapper: + def __init__(self, nodes): + self.source_nodes = nodes + + # Preserve the original retrieval_result but add the source_nodes in the expected format + modified_raw_output = retrieval_result.copy() + modified_raw_output['source_nodes'] = vector_nodes + + # Add a source_nodes property that routes.py will look for + tool_output = ToolOutput( + content=final_answer, + tool_name="GraphRAG", + raw_output=NodeWrapper(vector_nodes), + raw_input={"query": query_str} + ) + + log_structured('debug', 'GraphRAG Tool: Including image metadata in response', + {'node_count': len(vector_nodes)}) + + return tool_output + except Exception as graphrag_err: + log_structured('error', f'Error in GraphRAG tool: {graphrag_err}', + {'traceback': traceback.format_exc()}) + return ToolOutput( + content=f"I encountered an error while retrieving information: {str(graphrag_err)}. Please try again or use the standard query tool.", + tool_name="GraphRAG", + raw_input={"query": query_str}, + raw_output={"error": str(graphrag_err)} + ) + + async def acall(self, input: str) -> ToolOutput: + """Async version of __call__.""" + return self.__call__(input) + + # Create the GraphRAG tool instance and add it to tools + graphrag_tool = GraphRAGTool(graphrag_query_engine) + query_engine_tools_react.append(graphrag_tool) + log_structured('info', 'Added GraphRAG tool to query engine tools') + + # --- Initialize Global Workflow Agent --- + # We're now using shared_state rather than module globals + + try: + # Create the agent instance + agent = ReActAgent2( + llm=llm, # Use the LLM configured via Settings + tools=query_engine_tools_react, + memory=ChatMemoryBuffer.from_defaults(llm=llm, token_limit=4096), # Give memory its own LLM ref + verbose=True, # Enable agent verbose logging + timeout=AGENT_TIMEOUT, + llm_timeout=LLM_TIMEOUT, + tool_timeout=TOOL_EXECUTION_TIMEOUT + ) + + # Store in shared state + set_global_agent(agent) + + log_structured('info', 'Agent initialized successfully') + except Exception as agent_err: + log_structured('critical', f'Failed to initialize agent: {str(agent_err)}', {'error': str(agent_err)}) + return False # Signal failure + + try: + # Define a simpler version of the run method + async def simple_run(query_text): + """Simple version that doesn't rely on complex workflow steps.""" + # Import from shared state to ensure we use the current global agent + from shared_state import global_workflow_agent + + if not global_workflow_agent: + log_structured('critical', 'Agent is None in simple_run - this should never happen') + return { + "response": "The AI system is currently unavailable. Please try again later.", + "sources": [], + "reasoning": [] + } + + try: + # Don't reset memory - we want to preserve conversation context between requests + # Only reset sources to track new sources for this specific response + global_workflow_agent.sources = [] + + # 1. Add the user query to memory + user_msg = ChatMessage(role="user", content=str(query_text)) + global_workflow_agent.memory.put(user_msg) + + # 2. Format the chat history + chat_history = global_workflow_agent.memory.get() + llm_input = global_workflow_agent.formatter.format(global_workflow_agent.tools, chat_history) + + # 3. Get LLM response + response = await asyncio.wait_for( + global_workflow_agent.llm.achat(llm_input), + timeout=global_workflow_agent.llm_timeout + ) + reasoning_step = global_workflow_agent.output_parser.parse(response.message.content) + + # Add detailed logging + log_structured('debug', 'Parsed reasoning step', { + 'step_type': type(reasoning_step).__name__, + 'has_response': hasattr(reasoning_step, 'response'), + 'has_action': hasattr(reasoning_step, 'action'), + 'action': getattr(reasoning_step, 'action', None), + 'action_input': getattr(reasoning_step, 'action_input', None), + 'raw_content': response.message.content[:200] # First 200 chars for debugging + }) + + # 4. Process the response (simplified) + # Force tool usage for all queries - don't allow direct responses + if hasattr(reasoning_step, 'response') and reasoning_step.response: + # If LLM gave a direct response, we need to force tool usage instead + log_structured('debug', 'LLM provided direct response, forcing tool usage for image retrieval') + + # Force tool execution by calling GraphRAG directly + graphrag_tool = next((t for t in global_workflow_agent.tools if 'graphrag' in t.metadata.name.lower()), None) + if graphrag_tool: + try: + tool_output = await asyncio.wait_for( + graphrag_tool.acall(input=str(query_text)), + timeout=global_workflow_agent.tool_timeout + ) + global_workflow_agent.sources.append(tool_output) + + # Use the tool's response instead of the direct LLM response + response_text = str(tool_output.content) if tool_output and tool_output.content else str(reasoning_step.response) + + assistant_msg = ChatMessage(role="assistant", content=response_text) + global_workflow_agent.memory.put(assistant_msg) + return { + "response": response_text, + "sources": global_workflow_agent.sources, + "reasoning": [reasoning_step] + } + except Exception as e: + log_structured('error', f'Error forcing GraphRAG tool execution: {str(e)}') + # Fall back to direct response if tool fails + + # Fallback to cleaning the direct response + response_text = str(reasoning_step.response) + + # Check for common thinking patterns and remove them + import re # Import re within the function scope to ensure it's available + thinking_patterns = [ + r'(?i)^.*?thinking:.*?\n', # Remove lines starting with "Thinking:" + r'(?i).*?', # Remove XML-like thinking tags + r'(?i)\[thinking\].*?\[/thinking\]', # Remove bracket thinking tags + r'(?i)I\'m thinking:.*?\n', # Remove "I'm thinking:" sections + r'(?i)Let me think.*?\n', # Remove "Let me think" sections + r'(?i)Thought:.*?Answer:', # Remove "Thought: ... Answer:" pattern + r'(?i)^Answer:\s*' # Remove just the "Answer:" prefix + ] + for pattern in thinking_patterns: + response_text = re.sub(pattern, '', response_text, flags=re.DOTALL) + + # Remove extra newlines that might be left after cleaning + response_text = re.sub(r'\n{3,}', '\n\n', response_text) + response_text = response_text.strip() + + assistant_msg = ChatMessage(role="assistant", content=response_text) + global_workflow_agent.memory.put(assistant_msg) + return { + "response": response_text, + "sources": global_workflow_agent.sources, + "reasoning": [reasoning_step] + } + else: + # Handle tool calls if the response indicates an action + if hasattr(reasoning_step, 'action') and reasoning_step.action: + tool_name = reasoning_step.action + action_input = reasoning_step.action_input or {} + + # Convert to dict if needed + if not isinstance(action_input, dict): + try: + if isinstance(action_input, str) and action_input.strip().startswith('{'): + action_input = json.loads(action_input) + else: + action_input = {'query': action_input} + except: + action_input = {'query': str(action_input)} + + # Find the tool + tool = next((t for t in global_workflow_agent.tools if t.metadata.name == tool_name), None) + if not tool: + error_msg = f"Tool '{tool_name}' not found. Available tools: {[t.metadata.name for t in global_workflow_agent.tools]}" + log_structured('error', 'Tool not found in simple_run', {'tool_name': tool_name, 'available_tools': [t.metadata.name for t in global_workflow_agent.tools]}) + return { + "response": f"I tried to use a tool called '{tool_name}' but it's not available. Please try rephrasing your query.", + "sources": [], + "reasoning": [reasoning_step] + } + if tool: + try: + # Execute the tool + tool_output = await asyncio.wait_for( + tool.acall(**action_input), + timeout=global_workflow_agent.tool_timeout + ) + global_workflow_agent.sources.append(tool_output) + + # Get a final response + observation = str(tool_output.content if tool_output and tool_output.content is not None else "No content") + follow_up_msg = ChatMessage(role="user", content=f"Here is the result: {observation}\\nPlease provide a final response based on this information.") + global_workflow_agent.memory.put(follow_up_msg) + + # Call LLM again for final response + chat_history = global_workflow_agent.memory.get() + llm_input = global_workflow_agent.formatter.format(global_workflow_agent.tools, chat_history) + final_response = await asyncio.wait_for( + global_workflow_agent.llm.achat(llm_input), + timeout=global_workflow_agent.llm_timeout + ) + + # Store and return + # Clean the response to remove any thinking parts + response_text = str(final_response.message.content) + + # Check for common thinking patterns and remove them + import re # Import re within the function scope to ensure it's available + thinking_patterns = [ + r'(?i)^.*?thinking:.*?\n', # Remove lines starting with "Thinking:" + r'(?i).*?', # Remove XML-like thinking tags + r'(?i)\[thinking\].*?\[/thinking\]', # Remove bracket thinking tags + r'(?i)I\'m thinking:.*?\n', # Remove "I'm thinking:" sections + r'(?i)Let me think.*?\n', # Remove "Let me think" sections + r'(?i)Thought:.*?Answer:', # Remove "Thought: ... Answer:" pattern + r'(?i)^Answer:\s*' # Remove just the "Answer:" prefix + ] + for pattern in thinking_patterns: + response_text = re.sub(pattern, '', response_text, flags=re.DOTALL) + + # Remove extra newlines that might be left after cleaning + response_text = re.sub(r'\n{3,}', '\n\n', response_text) + response_text = response_text.strip() + + global_workflow_agent.memory.put(ChatMessage(role="assistant", content=response_text)) + return { + "response": response_text, + "sources": global_workflow_agent.sources, + "reasoning": [reasoning_step] + } + except Exception as e: + log_structured('error', f'Error executing tool: {str(e)}', {'traceback': traceback.format_exc()}) + # Error message is already clean without thinking + error_response = f"I encountered an error while processing your query: {str(e)}" + return { + "response": error_response, + "sources": [], + "reasoning": [reasoning_step] + } + + # Enhanced fallback with thinking detection + if isinstance(reasoning_step, ActionReasoningStep): + # If we reach here, it means we had an action but couldn't execute it + thinking_response = f"Thought: {getattr(reasoning_step, 'thought', '')} Action: {reasoning_step.action} Action Input: {reasoning_step.action_input}" + log_structured('warning', 'Returning raw thinking due to failed action execution', { + 'action': reasoning_step.action, + 'action_input': reasoning_step.action_input + }) + return { + "response": "I apologize, but I encountered an issue while processing your query. Please try asking your question in a different way.", + "sources": [], + "reasoning": [reasoning_step] + } + else: + # Original fallback for other types + fallback_response = "I wasn't able to find a specific answer to your question. Please try rephrasing your query." + return { + "response": fallback_response, + "sources": global_workflow_agent.sources, + "reasoning": [reasoning_step] if reasoning_step else [] + } + except Exception as e: + log_structured('error', f'Error in simple_run: {str(e)}', {'traceback': traceback.format_exc()}) + # Error response is already clean + error_response = f"I encountered an error while processing your query: {str(e)}" + return { + "response": error_response, + "sources": [], + "reasoning": [] + } + + # Replace the run method directly on the agent that is already in shared state + # We need to get the current reference from shared_state + from shared_state import global_workflow_agent as current_agent + + if current_agent is None: + log_structured('critical', 'Cannot set run method - global_workflow_agent is None') + return False + + # Attach the run method directly + current_agent.run = simple_run + + # Verify it was attached correctly + if not hasattr(current_agent, 'run'): + log_structured('critical', 'Failed to attach run method to agent') + return False + + log_structured('info', 'Successfully attached run method to agent') + + # Test the agent is working by calling a simple method + log_structured('info', 'Testing agent functionality...') + + # Test on the current_agent we imported above + if current_agent and hasattr(current_agent, 'memory') and hasattr(current_agent.memory, 'reset'): + current_agent.memory.reset() + log_structured('info', 'Agent memory reset test successful') + else: + if not current_agent: + log_structured('error', 'Agent memory test failed: agent is None') + elif not hasattr(current_agent, 'memory'): + log_structured('error', 'Agent memory test failed: agent has no memory attribute') + elif not hasattr(current_agent.memory, 'reset'): + log_structured('error', 'Agent memory test failed: agent.memory has no reset method') + else: + log_structured('error', 'Agent memory test failed: unknown reason') + return False + + except Exception as method_err: + log_structured('critical', f'Failed to set up agent run method: {str(method_err)}', + {'error': str(method_err), 'traceback': traceback.format_exc()}) + return False + + log_structured('info', 'Global index and workflow agent initialized successfully.') + # Skip test query to avoid potential errors during startup + return True + + except Exception as e: + log_structured('critical', 'Global index/agent initialization failed', { + 'error': str(e), 'traceback': traceback.format_exc() + }) + global_index = None + global_workflow_agent = None + return False \ No newline at end of file diff --git a/chat-interface/.gitignore b/chat-interface/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/chat-interface/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/chat-interface/.htaccess b/chat-interface/.htaccess new file mode 100644 index 0000000..86f3a56 --- /dev/null +++ b/chat-interface/.htaccess @@ -0,0 +1,37 @@ +# JavaScript MIME type +AddType application/javascript .js +AddType application/json .json + +# CSS MIME type +AddType text/css .css + +# Image MIME types +AddType image/svg+xml .svg +AddType image/png .png +AddType image/jpeg .jpg +AddType image/jpeg .jpeg +AddType image/gif .gif +AddType image/webp .webp + +# Font MIME types +AddType font/ttf .ttf +AddType font/otf .otf +AddType font/woff .woff +AddType font/woff2 .woff2 + +# Force JavaScript MIME type for all JS files + + ForceType application/javascript + + +# Enable mod_rewrite +RewriteEngine On +RewriteBase /netflix_chatbot/ + +# Don't rewrite files or directories +RewriteCond %{REQUEST_FILENAME} -f [OR] +RewriteCond %{REQUEST_FILENAME} -d +RewriteRule ^ - [L] + +# Rewrite everything else to index.html +RewriteRule ^ index.html [L] \ No newline at end of file diff --git a/chat-interface/DEPLOY.md b/chat-interface/DEPLOY.md new file mode 100644 index 0000000..07f228a --- /dev/null +++ b/chat-interface/DEPLOY.md @@ -0,0 +1,50 @@ +# Deployment Instructions + +## Files to Deploy +Deploy all files from the `dist` directory to your server at the path `/hp_chatbot/`. + +## Changing the Backend URL +If you need to change the backend API URL: + +1. Edit the `.env` and `.env.production` files to update the `VITE_BACKEND_URL` value +2. Or use the provided script: `./update-backend.sh` which will update the URL and rebuild the application +3. Then rebuild the application with `npm run build` + +## Important Server Configuration +The application requires proper MIME type configuration to work correctly. Depending on your server type, use one of the following: + +### Apache Server +Make sure the `.htaccess` file is included in your deployment. It contains: +- MIME type configurations +- URL rewrite rules for SPA routing +- CORS headers + +### IIS Server +Make sure the `web.config` file is included in your deployment. It contains: +- MIME type configurations +- URL rewrite rules +- CORS headers + +## Common Issues and Solutions + +### JavaScript MIME Type Error +If you get an error like: +``` +Loading module from "https://ai-sandbox.oliver.solutions/hp_chatbot/assets/index-XXXXX.js" was blocked because of a disallowed MIME type ("text/html"). +``` + +Check that: +1. Your server is serving .js files with the correct MIME type: `application/javascript` +2. The `.htaccess` or `web.config` file is properly uploaded and enabled +3. Your server allows URL rewriting and custom MIME types + +### Authentication Issues +- Make sure the Microsoft authentication is set up correctly +- The redirectUri in the MSAL configuration should match your deployment URL +- Check that cookies and localStorage are enabled in the browser + +### API Connection Issues +- The app expects the backend API to be accessible at the configured URL (default: `https://ai-sandbox.oliver.solutions/hp_chatbot_back`) +- If you need to change the backend API URL, follow the instructions in "Changing the Backend URL" section above +- In development, API calls are proxied through Vite's development server +- In production, API calls go directly to the configured backend URL \ No newline at end of file diff --git a/chat-interface/README.md b/chat-interface/README.md new file mode 100644 index 0000000..eb55104 --- /dev/null +++ b/chat-interface/README.md @@ -0,0 +1,72 @@ +# HP Marketing Materials Chatbot + +A React frontend for the HP Marketing Materials Chatbot, providing a chat interface to query the HP marketing knowledge base. + +## Features + +- Clean chat interface for asking questions about HP marketing materials +- Sources and reasoning display for transparency +- Session-based memory for contextual conversations +- Conversation management system + +## Development + +### Prerequisites + +- Node.js 18+ +- npm or yarn + +### Setup + +1. Clone the repository +2. Install dependencies: +```bash +npm install +``` + +3. Start the development server: +```bash +npm run dev +``` + +### Configuration + +The application uses environment variables for configuration. Create a `.env` file in the root directory with the following variables: + +``` +# Backend API URL +VITE_BACKEND_URL=https://ai-sandbox.oliver.solutions/hp_chatbot_back + +# Base URL for the app (changes in production) +VITE_APP_BASE_URL=/ +``` + +### Changing the Backend URL + +If you need to change the backend API URL: + +1. Edit the `.env` and `.env.production` files to update the `VITE_BACKEND_URL` value +2. Or use the provided script: `./update-backend.sh` which will update the URL and rebuild the application +3. Then rebuild the application with `npm run build` + +## Building for Production + +To create a production build: + +```bash +npm run build +``` + +The output will be in the `dist` directory, ready for deployment. + +## Deployment + +See [DEPLOY.md](./DEPLOY.md) for detailed deployment instructions. + +## Technologies Used + +- React 18 +- Vite +- TailwindCSS +- Microsoft Authentication Library (MSAL) or custom authentication +- Shadcn/ui components \ No newline at end of file diff --git a/chat-interface/components.json b/chat-interface/components.json new file mode 100644 index 0000000..ab02c33 --- /dev/null +++ b/chat-interface/components.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": false, + "tsx": false, + "tailwind": { + "config": "tailwind.config.js", + "css": "src/index.css", + "baseColor": "slate", + "cssVariables": true + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils" + } +} + diff --git a/chat-interface/eslint.config.js b/chat-interface/eslint.config.js new file mode 100644 index 0000000..238d2e4 --- /dev/null +++ b/chat-interface/eslint.config.js @@ -0,0 +1,38 @@ +import js from '@eslint/js' +import globals from 'globals' +import react from 'eslint-plugin-react' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' + +export default [ + { ignores: ['dist'] }, + { + files: ['**/*.{js,jsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + parserOptions: { + ecmaVersion: 'latest', + ecmaFeatures: { jsx: true }, + sourceType: 'module', + }, + }, + settings: { react: { version: '18.3' } }, + plugins: { + react, + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...js.configs.recommended.rules, + ...react.configs.recommended.rules, + ...react.configs['jsx-runtime'].rules, + ...reactHooks.configs.recommended.rules, + 'react/jsx-no-target-blank': 'off', + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, + }, +] diff --git a/chat-interface/index.html b/chat-interface/index.html new file mode 100644 index 0000000..014d3a8 --- /dev/null +++ b/chat-interface/index.html @@ -0,0 +1,31 @@ + + + + + + + + + HP Marketing Materials Chatbot + + + + + +
+
+

HP Marketing Materials Chatbot

+

Please sign in to access the chatbot.

+ +
+
+ + + + diff --git a/chat-interface/package-lock.json b/chat-interface/package-lock.json new file mode 100644 index 0000000..61e56bb --- /dev/null +++ b/chat-interface/package-lock.json @@ -0,0 +1,6784 @@ +{ + "name": "chat-interface", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "chat-interface", + "version": "0.0.0", + "dependencies": { + "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-tooltip": "^1.1.4", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "showdown": "^2.1.0" + }, + "devDependencies": { + "@eslint/js": "^9.13.0", + "@shadcn/ui": "^0.0.4", + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", + "@vitejs/plugin-react": "^4.3.3", + "autoprefixer": "^10.4.20", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "eslint": "^9.13.0", + "eslint-plugin-react": "^7.37.2", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.14", + "globals": "^15.11.0", + "lucide-react": "^0.455.0", + "postcss": "^8.4.47", + "tailwind-merge": "^2.5.4", + "tailwindcss": "^3.4.14", + "tailwindcss-animate": "^1.0.7", + "vite": "^5.4.10" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", + "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", + "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", + "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz", + "integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz", + "integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.12", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.12.tgz", + "integrity": "sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", + "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==", + "license": "MIT" + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", + "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", + "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", + "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", + "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", + "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-rect": "1.1.0", + "@radix-ui/react-use-size": "1.1.0", + "@radix-ui/rect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-context": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", + "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", + "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", + "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.4.tgz", + "integrity": "sha512-QpObUH/ZlpaO4YgHSaYzrLO2VuO+ZBFFgGzjMUPwtiYnAzzNNDPJeEGRrT7qNOrWm/Jr08M1vlp+vTHtnSQ0Uw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.0", + "@radix-ui/react-portal": "1.1.2", + "@radix-ui/react-presence": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-visually-hidden": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", + "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", + "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", + "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz", + "integrity": "sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", + "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==", + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.4.tgz", + "integrity": "sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.4.tgz", + "integrity": "sha512-j4nrEO6nHU1nZUuCfRKoCcvh7PIywQPUCBa2UsootTHvTHIoIu2BzueInGJhhvQO/2FTRdNYpf63xsgEqH9IhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.4.tgz", + "integrity": "sha512-GmU/QgGtBTeraKyldC7cDVVvAJEOr3dFLKneez/n7BvX57UdhOqDsVwzU7UOnYA7AAOt+Xb26lk79PldDHgMIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.4.tgz", + "integrity": "sha512-N6oDBiZCBKlwYcsEPXGDE4g9RoxZLK6vT98M8111cW7VsVJFpNEqvJeIPfsCzbf0XEakPslh72X0gnlMi4Ddgg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.4.tgz", + "integrity": "sha512-py5oNShCCjCyjWXCZNrRGRpjWsF0ic8f4ieBNra5buQz0O/U6mMXCpC1LvrHuhJsNPgRt36tSYMidGzZiJF6mw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.4.tgz", + "integrity": "sha512-L7VVVW9FCnTTp4i7KrmHeDsDvjB4++KOBENYtNYAiYl96jeBThFfhP6HVxL74v4SiZEVDH/1ILscR5U9S4ms4g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.4.tgz", + "integrity": "sha512-10ICosOwYChROdQoQo589N5idQIisxjaFE/PAnX2i0Zr84mY0k9zul1ArH0rnJ/fpgiqfu13TFZR5A5YJLOYZA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.4.tgz", + "integrity": "sha512-ySAfWs69LYC7QhRDZNKqNhz2UKN8LDfbKSMAEtoEI0jitwfAG2iZwVqGACJT+kfYvvz3/JgsLlcBP+WWoKCLcw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.4.tgz", + "integrity": "sha512-uHYJ0HNOI6pGEeZ/5mgm5arNVTI0nLlmrbdph+pGXpC9tFHFDQmDMOEqkmUObRfosJqpU8RliYoGz06qSdtcjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.4.tgz", + "integrity": "sha512-38yiWLemQf7aLHDgTg85fh3hW9stJ0Muk7+s6tIkSUOMmi4Xbv5pH/5Bofnsb6spIwD5FJiR+jg71f0CH5OzoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.4.tgz", + "integrity": "sha512-q73XUPnkwt9ZNF2xRS4fvneSuaHw2BXuV5rI4cw0fWYVIWIBeDZX7c7FWhFQPNTnE24172K30I+dViWRVD9TwA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.4.tgz", + "integrity": "sha512-Aie/TbmQi6UXokJqDZdmTJuZBCU3QBDA8oTKRGtd4ABi/nHgXICulfg1KI6n9/koDsiDbvHAiQO3YAUNa/7BCw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.4.tgz", + "integrity": "sha512-P8MPErVO/y8ohWSP9JY7lLQ8+YMHfTI4bAdtCi3pC2hTeqFJco2jYspzOzTUB8hwUWIIu1xwOrJE11nP+0JFAQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.4.tgz", + "integrity": "sha512-K03TljaaoPK5FOyNMZAAEmhlyO49LaE4qCsr0lYHUKyb6QacTNF9pnfPpXnFlFD3TXuFbFbz7tJ51FujUXkXYA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.4.tgz", + "integrity": "sha512-VJYl4xSl/wqG2D5xTYncVWW+26ICV4wubwN9Gs5NrqhJtayikwCXzPL8GDsLnaLU3WwhQ8W02IinYSFJfyo34Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.4.tgz", + "integrity": "sha512-ku2GvtPwQfCqoPFIJCqZ8o7bJcj+Y54cZSr43hHca6jLwAiCbZdBUOrqE6y29QFajNAzzpIOwsckaTFmN6/8TA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.4.tgz", + "integrity": "sha512-V3nCe+eTt/W6UYNr/wGvO1fLpHUrnlirlypZfKCT1fG6hWfqhPgQV/K/mRBXBpxc0eKLIF18pIOFVPh0mqHjlg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.4.tgz", + "integrity": "sha512-LTw1Dfd0mBIEqUVCxbvTE/LLo+9ZxVC9k99v1v4ahg9Aak6FpqOfNu5kRkeTAn0wphoC4JU7No1/rL+bBCEwhg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shadcn/ui": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@shadcn/ui/-/ui-0.0.4.tgz", + "integrity": "sha512-0dtu/5ApsOZ24qgaZwtif8jVwqol7a4m1x5AxPuM1k5wxhqU7t/qEfBGtaSki1R8VlbTQfCj5PAlO45NKCa7Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "5.2.0", + "commander": "^10.0.0", + "execa": "^7.0.0", + "fs-extra": "^11.1.0", + "node-fetch": "^3.3.0", + "ora": "^6.1.2", + "prompts": "^2.4.2", + "zod": "^3.20.2" + }, + "bin": { + "ui": "dist/index.js" + } + }, + "node_modules/@shadcn/ui/node_modules/chalk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@shadcn/ui/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.3.tgz", + "integrity": "sha512-NooDe9GpHGqNns1i8XDERg0Vsg5SSYRhRxxyTGogUdkdNt47jal+fbuYi+Yfq6pzRCKXyoPcWisfxE6RIM3GKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/plugin-transform-react-jsx-self": "^7.24.7", + "@babel/plugin-transform-react-jsx-source": "^7.24.7", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", + "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001679", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001679.tgz", + "integrity": "sha512-j2YqID/YwpLnKzCmBOS4tlZdWprXm3ZmQLBH9ZBXFOhoxLA46fwyBvx6toCBWBmnuwUY/qB3kEU6gFx8qgCroA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz", + "integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "clsx": "2.0.0" + }, + "funding": { + "url": "https://joebell.co.uk" + } + }, + "node_modules/class-variance-authority/node_modules/clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", + "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.55", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.55.tgz", + "integrity": "sha512-6maZ2ASDOTBtjt9FhqYPRnbvKU5tjG0IN9SztUOWYw2AzNDNpKJYLJmlK0/En4Hs/aiWnB+JZ+gW19PIGszgKg==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz", + "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.3", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.7.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.14.0", + "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.0", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.1.0", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz", + "integrity": "sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.14.tgz", + "integrity": "sha512-aXvzCTK7ZBv1e7fahFuR3Z/fyQQSIQ711yPgYRj+Oj64tyTgO4iQIDmYXDBqvSWQ/FA4OSCsXOStlF+noU0/NA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-scope": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "15.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", + "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", + "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.0.0", + "is-unicode-supported": "^1.1.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.455.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.455.0.tgz", + "integrity": "sha512-XQoi58X4COfjy6s1P4TVsXMhU2r1KsfUTRFyds/yJvdzBNOfu0F9RRIas626T8UaNZzEv4llF7ivh4uLkYp3rw==", + "dev": true, + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-6.3.1.tgz", + "integrity": "sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.0.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.6.1", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^1.1.0", + "log-symbols": "^5.1.0", + "stdin-discarder": "^0.1.0", + "strip-ansi": "^7.0.1", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-import/node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.4.tgz", + "integrity": "sha512-vGorVWIsWfX3xbcyAS+I047kFKapHYivmkaT63Smj77XwvLSJos6M1xGqZnBPFQFBRZDOcG1QnYEIxAvTr/HjA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.24.4", + "@rollup/rollup-android-arm64": "4.24.4", + "@rollup/rollup-darwin-arm64": "4.24.4", + "@rollup/rollup-darwin-x64": "4.24.4", + "@rollup/rollup-freebsd-arm64": "4.24.4", + "@rollup/rollup-freebsd-x64": "4.24.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.4", + "@rollup/rollup-linux-arm-musleabihf": "4.24.4", + "@rollup/rollup-linux-arm64-gnu": "4.24.4", + "@rollup/rollup-linux-arm64-musl": "4.24.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.4", + "@rollup/rollup-linux-riscv64-gnu": "4.24.4", + "@rollup/rollup-linux-s390x-gnu": "4.24.4", + "@rollup/rollup-linux-x64-gnu": "4.24.4", + "@rollup/rollup-linux-x64-musl": "4.24.4", + "@rollup/rollup-win32-arm64-msvc": "4.24.4", + "@rollup/rollup-win32-ia32-msvc": "4.24.4", + "@rollup/rollup-win32-x64-msvc": "4.24.4", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/showdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz", + "integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==", + "license": "MIT", + "dependencies": { + "commander": "^9.0.0" + }, + "bin": { + "showdown": "bin/showdown.js" + }, + "funding": { + "type": "individual", + "url": "https://www.paypal.me/tiviesantos" + } + }, + "node_modules/showdown/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stdin-discarder": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", + "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz", + "integrity": "sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss-animate": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", + "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders" + } + }, + "node_modules/tailwindcss/node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.4.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", + "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "dev": true, + "license": "MIT", + "dependencies": { + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/chat-interface/package.json b/chat-interface/package.json new file mode 100644 index 0000000..e3674f6 --- /dev/null +++ b/chat-interface/package.json @@ -0,0 +1,40 @@ +{ + "name": "hp-chat-interface", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-tooltip": "^1.1.4", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "showdown": "^2.1.0" + }, + "devDependencies": { + "@eslint/js": "^9.13.0", + "@shadcn/ui": "^0.0.4", + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", + "@vitejs/plugin-react": "^4.3.3", + "autoprefixer": "^10.4.20", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "eslint": "^9.13.0", + "eslint-plugin-react": "^7.37.2", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.14", + "globals": "^15.11.0", + "lucide-react": "^0.455.0", + "postcss": "^8.4.47", + "tailwind-merge": "^2.5.4", + "tailwindcss": "^3.4.14", + "tailwindcss-animate": "^1.0.7", + "vite": "^5.4.10" + } +} diff --git a/chat-interface/postcss.config.js b/chat-interface/postcss.config.js new file mode 100644 index 0000000..2e7af2b --- /dev/null +++ b/chat-interface/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/chat-interface/public/images/Netflix_2015_N_logo.png b/chat-interface/public/images/Netflix_2015_N_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ef062a7229068833bb659501027891de6cdf620d GIT binary patch literal 87960 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 K5bJc-wXU}(VcyQG{TCVOf)CLUX(>mPd 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 literal 0 HcmV?d00001 diff --git a/chat-interface/public/images/netflix-logo.svg b/chat-interface/public/images/netflix-logo.svg new file mode 100644 index 0000000..f3a8116 --- /dev/null +++ b/chat-interface/public/images/netflix-logo.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/chat-interface/public/vite.svg b/chat-interface/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/chat-interface/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/chat-interface/src/App.css b/chat-interface/src/App.css new file mode 100644 index 0000000..b9d355d --- /dev/null +++ b/chat-interface/src/App.css @@ -0,0 +1,42 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/chat-interface/src/App.jsx b/chat-interface/src/App.jsx new file mode 100644 index 0000000..8c7295e --- /dev/null +++ b/chat-interface/src/App.jsx @@ -0,0 +1,1525 @@ +/** + * HP AI Chatbot + * + * Frontend interface for the HP Marketing Materials Chatbot. + * This application provides a chat interface to query the HP marketing + * knowledge base containing HP brand guidelines and supporting documents. + * + * Key features: + * - Clean chat interface for asking questions about HP marketing materials + * - Sources and reasoning display for transparency + * - Brief download functionality to export conversations + * - Session-based memory for contextual conversations + * + */ + +import { useState, useRef, useEffect } from 'react'; +import { Send, Upload, Loader2, X, FileText, Info, PlusCircle, Trash2, Moon, Sun } from 'lucide-react'; +import ThemeToggle from './components/ThemeToggle'; +import { fetchWithTimeout } from './lib/utils'; +import { Alert, AlertDescription } from "./components/ui/alert"; +import * as Tooltip from '@radix-ui/react-tooltip'; +import showdown from 'showdown'; +import { getCurrentUser, signOut } from './auth'; +import { loadUserConversations, loadConversationMessages, createNewConversation, deleteConversation } from './components/ConversationManager'; + +// Use environment variables for backend URL +// Define backend URL dynamically based on environment +const BACKEND_URL = import.meta.env.VITE_BACKEND_URL || 'https://ai-sandbox.oliver.solutions/hp_back_v2'; +console.log('Using backend URL:', BACKEND_URL); + +// Function to get authenticated fetch defaults +const getFetchDefaults = () => { + // Get MSAL username for authentication + const username = getCurrentUser(); + + return { + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + 'X-MS-USERNAME': username || '', // Add the authenticated username to requests + } + }; +}; + +export default function ChatInterface() { + // Build timestamp to force new hash generation on rebuild - logged only once + const BUILD_TIMESTAMP = "2025-04-27T" + "FIXED_TIMESTAMP"; + // Only log in development mode and only once during initialization + if (process.env.NODE_ENV !== 'production') { + // Using useRef to ensure this only runs once + const hasLoggedTimestamp = useRef(false); + useEffect(() => { + if (!hasLoggedTimestamp.current) { + console.log('App build timestamp:', BUILD_TIMESTAMP); + hasLoggedTimestamp.current = true; + } + }, []); + } + + const [messages, setMessages] = useState([]); + const [inputMessage, setInputMessage] = useState(''); + const [isProcessing, setIsProcessing] = useState(false); + const [isInitialized, setIsInitialized] = useState(false); + const [error, setError] = useState(null); + const [isCheckingStatus, setIsCheckingStatus] = useState(true); + + // Conversation state + const [conversations, setConversations] = useState([]); + const [loadingConversations, setLoadingConversations] = useState(false); + const [activeConversation, setActiveConversation] = useState(null); + + // Sidebar resizing state + const [sidebarWidth, setSidebarWidth] = useState(320); // Default width in pixels + const [isResizing, setIsResizing] = useState(false); + const [autoWidth, setAutoWidth] = useState(true); // Auto-width flag + const minSidebarWidth = 240; + const maxSidebarWidth = 480; + const sidebarRef = useRef(null); + + // Initialize Showdown converter for markdown + const markdownConverter = new showdown.Converter({ + tables: true, + simplifiedAutoLink: true, + strikethrough: true, + tasklists: true, + emoji: true + }); + + const messagesEndRef = useRef(null); + + // Use a ref to track if we've already created a new conversation on this page load + const hasCreatedConversation = useRef(false); + + const [sessionId, setSessionId] = useState(() => { + // Check for existing session ID in localStorage + const existingSessionId = localStorage.getItem('chatSessionId'); + if (existingSessionId) { + return existingSessionId; + } + // Generate new session ID if none exists + const newSessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; + localStorage.setItem('chatSessionId', newSessionId); + return newSessionId; + }); + + // Load user conversations from the API + const loadUserConversations = async () => { + setLoadingConversations(true); + try { + const fetchOptions = getFetchDefaults(); + const response = await fetchWithTimeout(`${BACKEND_URL}/conversations`, { + ...fetchOptions, + method: 'GET' + }); + + if (response.ok) { + const data = await response.json(); + setConversations(data.conversations || []); + + // REMOVED auto-loading of the most recent conversation + // We want the user to always start with a fresh conversation when refreshing + } else { + console.error('Failed to load conversations'); + } + } catch (error) { + console.error('Error loading conversations:', error); + } finally { + setLoadingConversations(false); + } + }; + + // Load a specific conversation + const loadConversation = async (conversation) => { + try { + setIsProcessing(true); + setActiveConversation(conversation); + + // Set the session ID + setSessionId(conversation.session_id); + localStorage.setItem('chatSessionId', conversation.session_id); + + // Fetch the messages for this conversation + const fetchOptions = getFetchDefaults(); + const response = await fetchWithTimeout(`${BACKEND_URL}/conversations/${conversation.id}/messages`, { + ...fetchOptions, + method: 'GET' + }); + + if (response.ok) { + const data = await response.json(); + + // Format the messages for the UI + const formattedMessages = data.messages.map(msg => ({ + role: msg.role, + content: msg.content, + sources: msg.sources || [], + reasoning: msg.reasoning || [], + images: msg.images || [] + })); + + setMessages(formattedMessages); + setIsInitialized(true); + setError(null); + } else { + setError('Failed to load conversation messages'); + console.error('Failed to load conversation messages'); + } + } catch (error) { + setError('Error loading conversation'); + console.error('Error loading conversation:', error); + } finally { + setIsProcessing(false); + } + }; + + // Create a new conversation + const createNewConversation = async () => { + try { + setIsProcessing(true); + const fetchOptions = getFetchDefaults(); + const response = await fetchWithTimeout(`${BACKEND_URL}/conversations/new`, { + ...fetchOptions, + method: 'POST' + }); + + if (response.ok) { + const data = await response.json(); + + // Set the new session ID + setSessionId(data.session_id); + localStorage.setItem('chatSessionId', data.session_id); + + // Create a new conversation object + const newConversation = { + id: data.conversation_id, + title: "New conversation", + created_at: new Date().toISOString(), + last_updated: new Date().toISOString(), + session_id: data.session_id + }; + + // Update the conversations list + setConversations(prev => [newConversation, ...prev]); + + // Set as active conversation + setActiveConversation(newConversation); + + // Reset messages + setMessages([{ + role: 'assistant', + content: 'Welcome to the HP Marketing Materials Chatbot! How can I help you today?' + }]); + + setIsInitialized(true); + setError(null); + } else { + setError('Failed to create new conversation'); + console.error('Failed to create new conversation'); + } + } catch (error) { + setError('Error creating new conversation'); + console.error('Error creating new conversation:', error); + } finally { + setIsProcessing(false); + } + }; + + // Function to handle loading a conversation + const handleLoadConversation = async (conversation) => { + setActiveConversation(conversation); + await loadConversationMessages( + conversation, + getCurrentUser(), + setMessages, + setSessionId, + setError + ); + }; + + // Function to handle creating a new conversation + const handleCreateNewConversation = async () => { + await createNewConversation( + getCurrentUser(), + setConversations, + setActiveConversation, + setSessionId, + setMessages, + setError + ); + }; + + // Function to update conversations list (including titles) after a message is sent + const updateConversationsList = async () => { + if (activeConversation) { + try { + console.log('Updating conversations list...'); + // Get updated conversations from the server + const fetchOptions = getFetchDefaults(); + const response = await fetchWithTimeout(`${BACKEND_URL}/conversations`, { + ...fetchOptions, + method: 'GET' + }); + + if (response.ok) { + const data = await response.json(); + const updatedConversations = data.conversations || []; + + // Update the conversations list + setConversations(updatedConversations); + + // Find and update the active conversation with any title changes + const updatedActiveConversation = updatedConversations.find( + convo => convo.id === activeConversation.id + ); + + if (updatedActiveConversation) { + // Always update the active conversation to get the latest data + // This ensures titles get updated after messages are sent + setActiveConversation(updatedActiveConversation); + console.log('Updated active conversation:', + 'ID:', updatedActiveConversation.id, + 'Title:', updatedActiveConversation.title + ); + } else { + console.warn('Active conversation not found in updated list'); + } + } else { + console.error('Failed to update conversations list'); + } + } catch (err) { + console.error('Error updating conversations list:', err); + // Continue with existing data on error + } + } else { + console.warn('No active conversation to update'); + } + }; + + // Separate useEffect that only runs once on component mount + useEffect(() => { + // Flag to prevent multiple conversation creations + hasCreatedConversation.current = false; + + // Check the status of the chat system when the component mounts + const checkStatus = async () => { + setIsCheckingStatus(true); + try { + // Check if the chat system is initialized + const fetchOptions = getFetchDefaults(); + const response = await fetchWithTimeout(`${BACKEND_URL}/status?sessionId=${sessionId}`, { + ...fetchOptions, + method: 'GET' + }); + + if (response.ok) { + const data = await response.json(); + // Check for either the new property 'global_status' or the old 'initialized' property + // Enhanced logging for the status response + console.log('Status check raw response:', JSON.stringify(data)); + + // Explicitly check each property with detailed logging + const hasGlobalStatus = 'global_status' in data; + const globalStatusValue = hasGlobalStatus ? data.global_status : 'missing'; + const globalStatusMatch = globalStatusValue === 'initialized'; + + const hasInitialized = 'initialized' in data; + const initializedValue = hasInitialized ? data.initialized : false; + + console.log('Status check property analysis:', { + hasGlobalStatus, + globalStatusValue, + globalStatusMatch, + hasInitialized, + initializedValue + }); + + // Try also checking 'is_initialized' as another possible property name + const hasIsInitialized = 'is_initialized' in data; + const isInitializedValue = hasIsInitialized ? data.is_initialized : false; + + // Check session-specific initialization if available + const hasSessionInitialized = 'session_initialized' in data; + const sessionInitialized = hasSessionInitialized ? data.session_initialized : true; // Default to true if not present + const sessionStatus = data.session_status || 'unknown'; + + // OVERRIDE: ALWAYS force initialization to true + // This completely bypasses all property checks and status endpoint validation + // Complementing the backend change which now always returns initialized=true + const systemInitialized = true; + + // Log final decision with full context + console.log('Final initialization decision:', { + systemInitialized, + globalStatusMatch, + initializedValue, + isInitializedValue, + hasSessionInitialized, + sessionInitialized, + sessionStatus, + fullData: data + }); + + setIsInitialized(systemInitialized); + + if (systemInitialized) { + // First, load conversations list for the sidebar without auto-selecting any + await loadUserConversations(); + + // Only create a new conversation if we haven't already + if (!hasCreatedConversation.current) { + logToConsole('info', 'App mounted, creating a new conversation', { sessionId }); + + // Set the flag to prevent creating multiple conversations + hasCreatedConversation.current = true; + + setIsProcessing(true); + try { + const fetchOptions = getFetchDefaults(); + const response = await fetch(`${BACKEND_URL}/conversations/new`, { + ...fetchOptions, + method: 'POST' + }); + + if (response.ok) { + const data = await response.json(); + + // Set the new session ID + setSessionId(data.session_id); + localStorage.setItem('chatSessionId', data.session_id); + + // Create a new conversation object + const newConversation = { + id: data.conversation_id, + title: "New conversation", + created_at: new Date().toISOString(), + last_updated: new Date().toISOString(), + session_id: data.session_id + }; + + // Update the conversations list + setConversations(prev => [newConversation, ...prev]); + + // Set as active conversation + setActiveConversation(newConversation); + + // Reset messages + setMessages([{ + role: 'assistant', + content: 'Welcome to the HP Marketing Materials Chatbot! How can I help you today?' + }]); + } else { + console.error('Failed to create new conversation'); + } + } catch (error) { + console.error('Error creating new conversation on page load:', error); + } finally { + setIsProcessing(false); + } + } + + setError(null); + logToConsole('info', 'Chat system is ready', { sessionId }); + } else { + // System is not initialized + setError('The chat system is not yet initialized. Please try again later.'); + logToConsole('error', 'Chat system not initialized', { sessionId }); + } + } else { + console.error('Failed to check system status'); + setError('Failed to connect to the chat system. Please try again later.'); + } + } catch (error) { + console.error('Error checking system status:', error); + setError('Failed to connect to the chat system. Please try again later.'); + } finally { + setIsCheckingStatus(false); + } + }; + + checkStatus(); + + // Empty dependency array to ensure this only runs once when the component mounts + }, []); + + const logToConsole = (type, message, data = null) => { + const timestamp = new Date().toISOString(); + const logMessage = { + timestamp, + type, + message, + data + }; + console.log(JSON.stringify(logMessage, null, 2)); + }; + + const scrollToBottom = () => { + messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); + }; + + useEffect(() => { + scrollToBottom(); + }, [messages]); + + // Update the page title when active conversation changes or is updated + useEffect(() => { + if (activeConversation?.title) { + document.title = `${activeConversation.title} | HP Marketing Bot`; + } else { + document.title = 'HP Marketing Materials Chatbot'; + } + }, [activeConversation?.title]); + + // Sidebar resize handlers + const startResizing = (e) => { + setIsResizing(true); + e.preventDefault(); + }; + + const stopResizing = () => { + setIsResizing(false); + document.body.style.cursor = 'default'; + }; + + const resize = (e) => { + if (isResizing) { + document.body.style.cursor = 'ew-resize'; + const newWidth = e.clientX; + if (newWidth >= minSidebarWidth && newWidth <= maxSidebarWidth) { + setSidebarWidth(newWidth); + } + } + }; + + // Auto-resize sidebar based on conversation titles + useEffect(() => { + // Function to calculate the sidebar width based on conversation titles + const calculateSidebarWidth = () => { + if (!autoWidth || !conversations.length) return; + + // Create a temporary div to measure text width + const measureDiv = document.createElement('div'); + measureDiv.style.position = 'absolute'; + measureDiv.style.visibility = 'hidden'; + measureDiv.style.whiteSpace = 'nowrap'; + measureDiv.style.fontFamily = 'inherit'; + measureDiv.style.fontSize = '0.875rem'; // text-sm + measureDiv.style.fontWeight = '500'; // font-medium + + // Add to DOM for measurement + document.body.appendChild(measureDiv); + + // Find longest title + let maxWidth = 0; + conversations.forEach(convo => { + measureDiv.textContent = convo.title || "New conversation"; + const width = measureDiv.offsetWidth; + maxWidth = Math.max(maxWidth, width); + }); + + // Remove measurement div + document.body.removeChild(measureDiv); + + // Calculate sidebar width (add padding for buttons, icons, etc.) + // We add extra padding for the delete button and some margin + const calculatedWidth = Math.max(minSidebarWidth, Math.min(maxWidth + 100, maxSidebarWidth)); + + // Update width if it's significantly different + if (Math.abs(calculatedWidth - sidebarWidth) > 10) { + setSidebarWidth(calculatedWidth); + } + }; + + // Call the calculation function + calculateSidebarWidth(); + + // Add an event listener for window resize to recalculate if needed + if (autoWidth) { + window.addEventListener('resize', calculateSidebarWidth); + return () => window.removeEventListener('resize', calculateSidebarWidth); + } + }, [conversations, autoWidth, minSidebarWidth, maxSidebarWidth, sidebarWidth]); + + // Add event listeners for manual resize + useEffect(() => { + const handleResize = (e) => { + if (isResizing) { + document.body.style.cursor = 'ew-resize'; + const newWidth = e.clientX; + + if (newWidth >= minSidebarWidth && newWidth <= maxSidebarWidth) { + setSidebarWidth(newWidth); + // When user manually resizes, disable auto width + setAutoWidth(false); + } + } + }; + + const handleStopResizing = () => { + setIsResizing(false); + document.body.style.cursor = 'default'; + }; + + window.addEventListener('mousemove', handleResize); + window.addEventListener('mouseup', handleStopResizing); + + return () => { + window.removeEventListener('mousemove', handleResize); + window.removeEventListener('mouseup', handleStopResizing); + }; + }, [isResizing, minSidebarWidth, maxSidebarWidth]); + + const handleFilesChange = (e, type) => { + const files = Array.from(e.target.files); + logToConsole('info', `Handling ${type} files change`, { + fileCount: files.length, + fileDetails: files.map(f => ({ + name: f.name, + type: f.type, + size: f.size + })) + }); + + if (type === 'brief') { + setBriefFiles(prev => [...prev, ...files]); + } else { + setSupportingFiles(prev => [...prev, ...files]); + } + }; + + const removeFile = (fileName, type) => { + logToConsole('info', `Removing file`, { + fileName, + type + }); + + if (type === 'brief') { + setBriefFiles(prev => prev.filter(file => file.name !== fileName)); + } else { + setSupportingFiles(prev => prev.filter(file => file.name !== fileName)); + } + }; + + const resetChat = async () => { + try { + setIsProcessing(true); + logToConsole('info', 'Resetting chat session', { sessionId }); + const fetchOptions = getFetchDefaults(); + const response = await fetchWithTimeout(`${BACKEND_URL}/reset`, { + ...fetchOptions, + method: 'POST', + body: JSON.stringify({ sessionId }) + }); + + if (response.ok) { + // Reset the UI state + setMessages([{ + role: 'assistant', + content: 'Chat session has been reset. How can I help you today?' + }]); + setError(null); + setInputMessage(''); + + logToConsole('info', 'Chat session reset successfully'); + } else { + const errorData = await response.json(); + setError(errorData.error || 'Failed to reset chat'); + } + } catch (error) { + console.error('Error resetting chat:', error); + setError('Failed to reset chat. Please try again.'); + } finally { + setIsProcessing(false); + } + }; + + + const ImageViewer = ({ image, isOpen, onClose, allImages }) => { + if (!isOpen) return null; + + // Find the index of the current image in the allImages array + const currentImageIndex = allImages.findIndex(img => { + const imgFilename = typeof img === 'string' ? img : img.filename; + const selectedFilename = typeof image === 'string' ? image : image.filename; + return imgFilename === selectedFilename; + }); + + const [activeIndex, setActiveIndex] = useState(currentImageIndex >= 0 ? currentImageIndex : 0); + + // Handle both string and object formats for backward compatibility + const currentImage = allImages[activeIndex]; + const filename = typeof currentImage === 'string' ? currentImage : currentImage.filename; + const metadata = typeof currentImage === 'string' ? null : currentImage; + + const goToPrevious = (e) => { + e.stopPropagation(); + setActiveIndex((prevIndex) => (prevIndex > 0 ? prevIndex - 1 : allImages.length - 1)); + }; + + const goToNext = (e) => { + e.stopPropagation(); + setActiveIndex((prevIndex) => (prevIndex < allImages.length - 1 ? prevIndex + 1 : 0)); + }; + + return ( +
+
+ {allImages.length > 1 && ( + + )} + +
+ {metadata + {metadata && ( +
+
{metadata.document}
+
Page {metadata.page} {allImages.length > 1 ? `(${activeIndex + 1}/${allImages.length})` : ''}
+
+ )} +
+ + {allImages.length > 1 && ( + + )} + + +
+
+ ); + }; + + const MessageBubble = ({ message }) => { + const [selectedImage, setSelectedImage] = useState(null); + + const formatSources = (sources) => { + if (!sources || !Array.isArray(sources)) return []; + + return sources.map((source) => { + if (source && typeof source === 'object') { + if (source.content) { + return { + text: typeof source.content === 'string' + ? source.content + : JSON.stringify(source.content), + tool: source.tool_name || '' + }; + } + return { + text: JSON.stringify(source), + tool: '' + }; + } + return { + text: String(source), + tool: '' + }; + }).filter(source => source.text); + }; + + const formatReasoning = (reasoning) => { + if (!reasoning || !Array.isArray(reasoning)) return []; + + return reasoning.map((step, index) => { + const stepType = step.type || 'thought'; + let content = ''; + + if (step.action) { + content = `${step.action}${step.action_input ? `: ${step.action_input}` : ''}`; + } else if (step.observation) { + content = step.observation; + } else if (step.response) { + content = step.response; + } else if (step.thought) { + content = step.thought; + } + + return { + id: index, + type: stepType, + content: content, + thought: step.thought + }; + }).filter(step => step.content); + }; + + const sources = formatSources(message.sources); + const reasoningSteps = formatReasoning(message.reasoning); + const images = message.images || []; + + // Handle image click - open full-size viewer + const openImage = (image) => { + setSelectedImage(image); + }; + + // Close image viewer + const closeImage = () => { + setSelectedImage(null); + }; + + // Handle escape key to close image + useEffect(() => { + const handleEscKey = (e) => { + if (e.key === 'Escape' && selectedImage) { + closeImage(); + } + }; + + window.addEventListener('keydown', handleEscKey); + return () => window.removeEventListener('keydown', handleEscKey); + }, [selectedImage]); + + return ( +
+
+
+ + {/* Display image thumbnails if available */} + {images.length > 0 && ( +
+
Relevant Document Screenshots:
+
+ {images.map((image, idx) => { + // Handle both string and object formats for backward compatibility + const filename = typeof image === 'string' ? image : image.filename; + const metadata = typeof image === 'string' ? null : image; + + return ( +
openImage(image)} + > + {metadata + {metadata && ( +
+ pg. {metadata.page} +
+ )} +
+ ); + })} +
+
+ )} + +
+ {sources.length > 0 && ( + + + + + + + +
+

Sources Used:

+
    + {sources.map((source, idx) => ( +
  • + {source.tool && ( +
    + Tool: {source.tool} +
    + )} +
    {source.text}
    +
  • + ))} +
+
+ +
+
+
+
+ )} + + {reasoningSteps.length > 0 && ( + + + + + + + +
+

Reasoning Steps:

+
    + {reasoningSteps.map((step) => ( +
  • +
    + {step.type}: +
    +
    {step.content}
    + {step.thought && step.thought !== step.content && ( +
    + Thought: {step.thought} +
    + )} +
  • + ))} +
+
+ +
+
+
+
+ )} +
+
+ + {/* Image viewer modal */} + +
+ ); + }; + + const handleSubmit = async () => { + if (!inputMessage.trim() || isProcessing) return; + + const currentMessage = inputMessage; + setMessages(prev => [...prev, { role: 'user', content: currentMessage }]); + setInputMessage(''); + setIsProcessing(true); + + // ENHANCED DEBUGGING: Log the current state of sessionId and related variables + console.log('SUBMIT DEBUG DATA:', { + sessionId, + sessionIdType: typeof sessionId, + sessionIdLength: sessionId ? sessionId.length : 0, + hasActiveConversation: !!activeConversation, + activeConversationId: activeConversation ? activeConversation.id : null, + activeConversationSessionId: activeConversation ? activeConversation.session_id : null, + localStorageSessionId: localStorage.getItem('chatSessionId') + }); + + // Check if this is a blank chat with no active conversation - create one if needed + if (!activeConversation) { + logToConsole('info', 'No active conversation found when submitting message, creating a new one', { sessionId }); + try { + await handleCreateNewConversation(); + } catch (err) { + console.error('Error creating new conversation before sending message:', err); + // Continue with the chat request anyway, as the backend might handle this + } + } + + // ENHANCEMENT: Try to ensure we have a valid sessionId + const effectiveSessionId = sessionId || + (activeConversation ? activeConversation.session_id : null) || + localStorage.getItem('chatSessionId'); + + if (!effectiveSessionId) { + console.error('No valid sessionId found from any source'); + setError('Session ID is missing. Please refresh the page.'); + setIsProcessing(false); + return; + } + + try { + // Log the sessionId to help debug + console.log('Sending chat request with sessionId:', effectiveSessionId); + + const fetchOptions = getFetchDefaults(); + const response = await fetchWithTimeout(`${BACKEND_URL}/chat`, { + ...fetchOptions, + method: 'POST', + body: JSON.stringify({ + message: currentMessage, + sessionId: effectiveSessionId + }) + }); + + if (!response.ok) { + const errorData = await response.json(); + // If the server says chat is not initialized, reset UI to show upload screen + if (errorData.error === 'Chat system not initialized') { + setIsInitialized(false); + throw new Error('Chat system not initialized. Please upload files first.'); + } + throw new Error(errorData.error || 'Failed to get response'); + } + + const responseData = await response.json(); + + let assistantMessage; + if (responseData.status === 'success' && responseData.data) { + assistantMessage = { + role: 'assistant', + content: responseData.data.response || '', + sources: responseData.data.sources || [], + reasoning: responseData.data.reasoning || [], + images: responseData.data.images || [] + }; + } else if (responseData.result) { + assistantMessage = { + role: 'assistant', + content: responseData.result.response || '', + sources: responseData.result.sources || [], + reasoning: responseData.result.reasoning || [], + images: responseData.result.images || [] + }; + } else { + assistantMessage = { + role: 'assistant', + content: responseData.response || '', + sources: responseData.sources || [], + reasoning: responseData.reasoning || [], + images: responseData.images || [] + }; + } + + console.log('Processed assistant message:', assistantMessage); + setMessages(prev => [...prev, assistantMessage]); + setError(null); + + // Update the conversations list to get the AI-generated title + // Add a longer delay to allow backend to generate title using OpenAI + setTimeout(() => { + // Need a longer delay for OpenAI to generate the title + updateConversationsList(); + + // Check again after a bit longer in case the first attempt was too soon + setTimeout(() => { + updateConversationsList(); + }, 3000); // Check again after 3 more seconds + }, 2000); // Initial 2 second delay + + } catch (e) { + console.error('Error in chat:', e); + setError('Failed to process response. Please try again.'); + } finally { + setIsProcessing(false); + } + }; + +// Helper function to slice file into chunks and upload them +const uploadFileInChunks = async (file, fileType, sessionId, controller) => { + const chunkSize = 1024 * 1024; // 1MB chunks + const totalChunks = Math.ceil(file.size / chunkSize); + + // Step 1: Initialize the chunked upload + const fetchOptions = getFetchDefaults(); + const initResponse = await fetch(`${BACKEND_URL}/init-chunked-upload`, { + method: 'POST', + headers: { + ...fetchOptions.headers, + 'Content-Type': 'application/json' + }, + signal: controller.signal, + body: JSON.stringify({ + fileName: file.name, + fileType: fileType, // 'brief' or 'supporting' + fileSize: file.size, + mimeType: file.type, + totalChunks, + sessionId + }) + }); + + if (!initResponse.ok) { + const error = await initResponse.json(); + throw new Error(error.message || 'Failed to initialize chunked upload'); + } + + const { uploadId } = await initResponse.json(); + + // Step 2: Upload each chunk + for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) { + const start = chunkIndex * chunkSize; + const end = Math.min(start + chunkSize, file.size); + const chunk = file.slice(start, end); + + const chunkFormData = new FormData(); + chunkFormData.append('chunk', chunk); + chunkFormData.append('uploadId', uploadId); + chunkFormData.append('chunkIndex', chunkIndex); + + const fetchOptions = getFetchDefaults(); + const chunkResponse = await fetch(`${BACKEND_URL}/upload-chunk`, { + method: 'POST', + body: chunkFormData, + signal: controller.signal, + headers: { + ...fetchOptions.headers, + 'X-Requested-With': 'XMLHttpRequest' + } + }); + + if (!chunkResponse.ok) { + throw new Error(`Failed to upload chunk ${chunkIndex}`); + } + } + + // Step 3: Finalize the upload + const finalizeOptions = getFetchDefaults(); + const finalizeResponse = await fetch(`${BACKEND_URL}/finalize-upload`, { + method: 'POST', + headers: { + ...finalizeOptions.headers, + 'Content-Type': 'application/json' + }, + signal: controller.signal, + body: JSON.stringify({ uploadId }) + }); + + if (!finalizeResponse.ok) { + throw new Error('Failed to finalize upload'); + } + + return { fileName: file.name, uploadId }; +}; + +// Main function to initialize chat +const initializeChat = async () => { + if (briefFiles.length === 0) { + setError('Please upload at least one brief file.'); + return; + } + + logToConsole('info', 'Starting chat initialization', { + briefFilesCount: briefFiles.length, + supportingFilesCount: supportingFiles.length + }); + + setIsProcessing(true); + + // Create an AbortController for proper timeout handling + const controller = new AbortController(); + const timeoutId = setTimeout(() => { + controller.abort(); + logToConsole('error', 'Request timed out after 10 minutes'); + }, 600000); // 10 minute timeout + + try { + // Check for large files that might need chunked upload + const largeFiles = [...briefFiles, ...supportingFiles].filter(file => file.size > 1024 * 1024); + if (largeFiles.length > 0) { + logToConsole('info', 'Large files detected, using chunked upload approach', { + largeFiles: largeFiles.map(f => ({ name: f.name, size: f.size })) + }); + } + + // Upload all brief files + const briefUploads = []; + for (const file of briefFiles) { + if (file.size > 1024 * 1024) { // If file is larger than 1MB, use chunked upload + const result = await uploadFileInChunks(file, 'brief', sessionId, controller); + briefUploads.push(result); + } else { + // For small files, use regular upload + const smallFormData = new FormData(); + smallFormData.append('file', file); + smallFormData.append('fileType', 'brief'); + smallFormData.append('sessionId', sessionId); + + const fetchOptions = getFetchDefaults(); + const response = await fetch(`${BACKEND_URL}/upload-small-file`, { + method: 'POST', + body: smallFormData, + signal: controller.signal, + headers: { + ...fetchOptions.headers, + 'X-Requested-With': 'XMLHttpRequest' + } + }); + + if (!response.ok) { + throw new Error(`Failed to upload small file: ${file.name}`); + } + + const result = await response.json(); + briefUploads.push(result); + } + } + + // Upload all supporting files (similar approach) + const supportingUploads = []; + for (const file of supportingFiles) { + if (file.size > 1024 * 1024) { + const result = await uploadFileInChunks(file, 'supporting', sessionId, controller); + supportingUploads.push(result); + } else { + // Small file upload code similar to brief files + const smallFormData = new FormData(); + smallFormData.append('file', file); + smallFormData.append('fileType', 'supporting'); + smallFormData.append('sessionId', sessionId); + + const fetchOptions = getFetchDefaults(); + const response = await fetch(`${BACKEND_URL}/upload-small-file`, { + method: 'POST', + body: smallFormData, + signal: controller.signal, + headers: { + ...fetchOptions.headers, + 'X-Requested-With': 'XMLHttpRequest' + } + }); + + if (!response.ok) { + throw new Error(`Failed to upload small file: ${file.name}`); + } + + const result = await response.json(); + supportingUploads.push(result); + } + } + + // Now that all files are uploaded, initialize the chat + const finalizeData = { + sessionId, + briefFiles: briefUploads, + supportingFiles: supportingUploads + }; + + const finalizeOptions = getFetchDefaults(); + const finalizeResponse = await fetch(`${BACKEND_URL}/initialize-from-uploads`, { + method: 'POST', + headers: { + ...finalizeOptions.headers, + 'Content-Type': 'application/json', + 'X-Requested-With': 'XMLHttpRequest' + }, + body: JSON.stringify(finalizeData), + signal: controller.signal + }); + + // Clear the timeout + clearTimeout(timeoutId); + + if (!finalizeResponse.ok) { + const errorData = await finalizeResponse.json(); + throw new Error(errorData.error || `Server responded with ${finalizeResponse.status}`); + } + + const data = await finalizeResponse.json(); + + logToConsole('info', 'Chat initialization successful'); + setIsInitialized(true); + setMessages([{ + role: 'assistant', + content: 'Chat initialized! How can I help you?' + }]); + setError(null); + + } catch (err) { + // Clear the timeout if there's an error + clearTimeout(timeoutId); + + // Enhanced error logging + const errorDetails = { + message: err.message, + name: err.name, + stack: err.stack, + isAbortError: err.name === 'AbortError' + }; + + logToConsole('error', 'Initialization error', errorDetails); + console.error('Initialization error:', err); + + // Set appropriate error message for user + if (err.name === 'AbortError') { + setError('Request timed out. The file(s) may be too large.'); + } else { + setError(err.message || 'Failed to initialize chat'); + } + + setIsInitialized(false); + } finally { + setIsProcessing(false); + } +}; + + return ( + +
+ {/* Conversation Sidebar - Fixed to left side */} +
+
+

Conversations

+ +
+ +
+ {loadingConversations ? ( +
+ +
+ ) : conversations.length > 0 ? ( + conversations.map(convo => ( +
+
+
handleLoadConversation(convo)} + > +
{convo.title || "New conversation"}
+
+ {new Date(convo.last_updated).toLocaleDateString()} +
+
+ +
+
+ )) + ) : ( +
+ No conversations yet +
+ )} +
+ +
+
+
+ {getCurrentUser()} + +
+ + {!autoWidth && ( + + )} +
+
+
+ + {/* Resize handle */} +
+ + {/* Header with HP branding - completely rebuilt without any borders */} +
+ {/* Theme toggle in top right corner */} +
+ +
+ {/* HP Logo */} +
+ HP +
+

Marketing Bot

+
+ + {/* Main Chat Area - Centered with left margin to account for sidebar */} +
+
+
+ {isCheckingStatus ? ( +
+ +

Connecting to HP Marketing Materials Chatbot...

+
+ ) : !isInitialized ? ( +
+

HP Marketing Materials Chatbot

+

+ The system is currently initializing. Please try again later. +

+ +
+ ) : ( + <> +
+
+

+ {activeConversation?.title || "HP Marketing Materials Chatbot"} +

+
+ +
+
+

+ Ask questions about HP's marketing materials, branding guidelines, campaign strategies, and creative processes. +

+
+ +
+
+ {messages.map((message, index) => ( + + ))} +
+
+
+ +
+ setInputMessage(e.target.value)} + onKeyPress={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Prevent any default behavior + if (!isProcessing && inputMessage.trim()) { + handleSubmit(); + } + } + }} + placeholder="Type your message..." + className="flex-1 p-2 border dark:border-gray-600 dark:bg-gray-700 dark:text-white rounded focus:outline-none focus:ring-2 focus:ring-blue-500" + disabled={isProcessing} + /> + +
+ + )} + + {error && !isCheckingStatus && ( + + {error} + + )} +
+
+
+
+ + ); +} \ No newline at end of file diff --git a/chat-interface/src/App_11-19.jsx b/chat-interface/src/App_11-19.jsx new file mode 100644 index 0000000..6b8d72e --- /dev/null +++ b/chat-interface/src/App_11-19.jsx @@ -0,0 +1,691 @@ +import { useState, useRef, useEffect } from 'react'; +import { Send, Upload, Loader2, X, FileText, Info, FileDown } from 'lucide-react'; +import { Alert, AlertDescription } from "./components/ui/alert"; +import * as Tooltip from '@radix-ui/react-tooltip'; + +const BACKEND_URL = 'http://localhost:6173'; + +const fetchDefaults = { + mode: 'cors', + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + 'Accept': '*/*', + 'Access-Control-Allow-Origin': '*', + } +}; + +export default function ChatInterface() { + const [messages, setMessages] = useState([]); + const [inputMessage, setInputMessage] = useState(''); + const [isProcessing, setIsProcessing] = useState(false); + const [briefFiles, setBriefFiles] = useState([]); + const [supportingFiles, setSupportingFiles] = useState([]); + const [isInitialized, setIsInitialized] = useState(false); + const [error, setError] = useState(null); + + const messagesEndRef = useRef(null); + const fileInputBriefRef = useRef(null); + const fileInputSupportingRef = useRef(null); + + useEffect(() => { + // Enable CORS for all fetch requests + fetch.defaults = fetchDefaults; + }, []); + + const logToConsole = (type, message, data = null) => { + const timestamp = new Date().toISOString(); + const logMessage = { + timestamp, + type, + message, + data + }; + console.log(JSON.stringify(logMessage, null, 2)); + }; + + const scrollToBottom = () => { + messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); + }; + + useEffect(() => { + scrollToBottom(); + }, [messages]); + + const handleFilesChange = (e, type) => { + const files = Array.from(e.target.files); + logToConsole('info', `Handling ${type} files change`, { + fileCount: files.length, + fileDetails: files.map(f => ({ + name: f.name, + type: f.type, + size: f.size + })) + }); + + if (type === 'brief') { + setBriefFiles(prev => [...prev, ...files]); + } else { + setSupportingFiles(prev => [...prev, ...files]); + } + }; + + const removeFile = (fileName, type) => { + logToConsole('info', `Removing file`, { + fileName, + type + }); + + if (type === 'brief') { + setBriefFiles(prev => prev.filter(file => file.name !== fileName)); + } else { + setSupportingFiles(prev => prev.filter(file => file.name !== fileName)); + } + }; + + const MessageBubble = ({ message }) => { + // Helper function to safely extract source content + const formatSources = (sources) => { + if (!sources || !Array.isArray(sources)) return []; + + return sources.map((source) => { + // Handle the nested structure from the backend + if (source && typeof source === 'object') { + // Check for the different possible source structures + if (source.content) { + return { + text: typeof source.content === 'string' + ? source.content + : JSON.stringify(source.content), + tool: source.tool_name || '' + }; + } + // Fallback for other source structures + return { + text: JSON.stringify(source), + tool: '' + }; + } + // Handle string sources + return { + text: String(source), + tool: '' + }; + }).filter(source => source.text); // Remove empty sources + }; + + // Helper function to format reasoning steps + const formatReasoning = (reasoning) => { + if (!reasoning || !Array.isArray(reasoning)) return []; + + return reasoning.map((step, index) => { + // Handle the new reasoning step structure + const stepType = step.type || 'thought'; + let content = ''; + + if (step.action) { + content = `${step.action}${step.action_input ? `: ${step.action_input}` : ''}`; + } else if (step.observation) { + content = step.observation; + } else if (step.response) { + content = step.response; + } else if (step.thought) { + content = step.thought; + } + + return { + id: index, + type: stepType, + content: content, + thought: step.thought + }; + }).filter(step => step.content); + }; + + const sources = formatSources(message.sources); + const reasoningSteps = formatReasoning(message.reasoning); + + const handleDownloadBrief = async () => { + // First, send the message to generate the brief + const briefRequestMessage = "write a comprehensive, detailed, and organized marketing brief based on the entire history of this conversation"; + setMessages(prev => [...prev, { role: 'user', content: briefRequestMessage }]); + setIsProcessing(true); + + try { + // First request to generate the brief content + const response = await fetch(`${BACKEND_URL}/chat`, { + ...fetchDefaults, + method: 'POST', + body: JSON.stringify({ message: briefRequestMessage }) + }); + + if (!response.ok) { + throw new Error('Failed to generate brief'); + } + + const responseData = await response.json(); + + // Add the assistant's response to the chat + setMessages(prev => [...prev, { + role: 'assistant', + content: responseData.data.response, + sources: responseData.data.sources, + reasoning: responseData.data.reasoning + }]); + + // Then make a second request to download the document + const downloadResponse = await fetch(`${BACKEND_URL}/download-brief`, { + ...fetchDefaults, + method: 'POST', + body: JSON.stringify({ brief_content: responseData.data.response }) + }); + + if (!downloadResponse.ok) { + throw new Error('Failed to download brief'); + } + + // Get the blob from the response + const blob = await downloadResponse.blob(); + + // Create a download link and trigger it + const downloadUrl = window.URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = downloadUrl; + link.download = 'marketing_brief.docx'; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(downloadUrl); + + } catch (e) { + console.error('Error in download brief:', e); + setError('Failed to download brief. Please try again.'); + } finally { + setIsProcessing(false); + } + }; + + + return ( + +
+ {!isInitialized ? ( + // ... (initialization UI remains the same) + ) : ( + <> +
+ {messages.map((message, index) => ( + + ))} +
+
+ +
+ setInputMessage(e.target.value)} + onKeyPress={(e) => e.key === 'Enter' && handleSubmit()} + placeholder="Type your message..." + className="flex-1 p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500" + disabled={isProcessing} + /> + + +
+ + )} + + {error && ( + + {error} + + )} +
+ + ); + } + + + // return ( + //
+ //
+ //
{message.content}
+ + //
+ // {sources.length > 0 && ( + // + // + // + // + // + // + // + //
+ //

Sources Used:

+ //
    + // {sources.map((source, idx) => ( + //
  • + // {source.tool && ( + //
    + // Tool: {source.tool} + //
    + // )} + //
    {source.text}
    + //
  • + // ))} + //
+ //
+ // + //
+ //
+ //
+ //
+ // )} + + // {reasoningSteps.length > 0 && ( + // + // + // + // + // + // + // + //
+ //

Reasoning Steps:

+ //
    + // {reasoningSteps.map((step) => ( + //
  • + //
    + // {step.type}: + //
    + //
    {step.content}
    + // {step.thought && step.thought !== step.content && ( + //
    + // Thought: {step.thought} + //
    + // )} + //
  • + // ))} + //
+ //
+ // + //
+ //
+ //
+ //
+ // )} + //
+ //
+ //
+ // ); + // }; + + + + const handleSubmit = async () => { + if (!inputMessage.trim()) return; + + const currentMessage = inputMessage; + setMessages(prev => [...prev, { role: 'user', content: currentMessage }]); + setInputMessage(''); + setIsProcessing(true); + + try { + const response = await fetch(`${BACKEND_URL}/chat`, { + ...fetchDefaults, + method: 'POST', + body: JSON.stringify({ message: currentMessage }) + }); + + if (!response.ok) { + throw new Error('Failed to get response'); + } + + const responseData = await response.json(); + + // Log the full response data for debugging + console.log('Full response data:', responseData); + + // Extract the relevant data based on the response structure + let assistantMessage; + if (responseData.status === 'success' && responseData.data) { + // New response structure + assistantMessage = { + role: 'assistant', + content: responseData.data.response || '', + sources: responseData.data.sources || [], + reasoning: responseData.data.reasoning || [] + }; + } else if (responseData.result) { + // Alternative response structure + assistantMessage = { + role: 'assistant', + content: responseData.result.response || '', + sources: responseData.result.sources || [], + reasoning: responseData.result.reasoning || [] + }; + } else { + // Fallback for direct response structure + assistantMessage = { + role: 'assistant', + content: responseData.response || '', + sources: responseData.sources || [], + reasoning: responseData.reasoning || [] + }; + } + + // Log the processed message for debugging + console.log('Processed assistant message:', assistantMessage); + + setMessages(prev => [...prev, assistantMessage]); + setError(null); + + } catch (e) { + console.error('Error in chat:', e); + setError('Failed to process response. Please try again.'); + } finally { + setIsProcessing(false); + } + }; + + + + const initializeChat = async () => { + if (briefFiles.length === 0) { + setError('Please upload at least one brief file.'); + return; + } + + logToConsole('info', 'Starting chat initialization', { + briefFilesCount: briefFiles.length, + supportingFilesCount: supportingFiles.length, + briefFiles: briefFiles.map(f => ({ + name: f.name, + type: f.type, + size: f.size + })), + supportingFiles: supportingFiles.map(f => ({ + name: f.name, + type: f.type, + size: f.size + })) + }); + + setIsProcessing(true); + const formData = new FormData(); + + briefFiles.forEach(file => { + formData.append('brief', file); + logToConsole('debug', 'Appending brief file to FormData', { + fileName: file.name, + fileType: file.type, + fileSize: file.size + }); + }); + + supportingFiles.forEach(file => { + formData.append('supporting', file); + logToConsole('debug', 'Appending supporting file to FormData', { + fileName: file.name, + fileType: file.type, + fileSize: file.size + }); + }); + + try { + logToConsole('info', 'Sending initialization request to backend'); + + const response = await fetch(`${BACKEND_URL}/initialize`, { + method: 'POST', + mode: 'cors', + credentials: 'include', + body: formData, + // headers: { + // 'Accept': '*/*', + // 'Access-Control-Allow-Origin': '*', + // } + }); + + logToConsole('debug', 'Received response from backend', { + status: response.status, + statusText: response.statusText, + headers: Object.fromEntries(response.headers.entries()) + }); + + const textResponse = await response.text(); + logToConsole('debug', 'Response text received', { textResponse }); + + let data; + try { + data = JSON.parse(textResponse); + logToConsole('debug', 'Successfully parsed response JSON', { data }); + } catch (e) { + logToConsole('error', 'Failed to parse response JSON', { + error: e.message, + textResponse + }); + throw new Error('Invalid response format from server'); + } + + if (!response.ok) { + logToConsole('error', 'Backend returned error response', { + status: response.status, + error: data.error + }); + throw new Error(data.error || 'Failed to initialize chat'); + } + + setIsInitialized(true); + setMessages([{ + role: 'assistant', + content: 'Chat initialized! How can I help you?' + }]); + + setError(null); + logToConsole('info', 'Chat initialization completed successfully'); + + } catch (err) { + logToConsole('error', 'Chat initialization failed', { + error: err.message, + stack: err.stack + }); + + let errorMessage = 'Failed to initialize chat. '; + if (err.message) { + errorMessage += err.message; + } else { + errorMessage += 'Please try again.'; + } + + setError(errorMessage); + setIsInitialized(false); + } finally { + setIsProcessing(false); + } + }; + + return ( + +
+ {!isInitialized ? ( +
+

Upload Files to Start Chat

+ +
+

Brief Files (Required)

+
+ handleFilesChange(e, 'brief')} + multiple + accept=".pdf,.doc,.docx,.txt,.xls,.xlsx,.ppt,.pptx,.eml" + className="hidden" + /> + +
+
+ {briefFiles.map((file) => ( +
+ + {file.name} + +
+ ))} +
+
+ +
+

Supporting Files (Optional)

+
+ handleFilesChange(e, 'supporting')} + multiple + accept=".pdf,.doc,.docx,.txt,.xls,.xlsx,.ppt,.pptx,.eml" + className="hidden" + /> + +
+
+ {supportingFiles.map((file) => ( +
+ + {file.name} + +
+ ))} +
+
+ + +
+ ) : ( + <> +
+ {messages.map((message, index) => ( + + ))} +
+
+ +
+ setInputMessage(e.target.value)} + onKeyPress={(e) => e.key === 'Enter' && handleSubmit()} + placeholder="Type your message..." + className="flex-1 p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500" + disabled={isProcessing} + /> + +
+ + )} + + {error && ( + + {error} + + )} +
+ + ); +} diff --git a/chat-interface/src/assets/react.svg b/chat-interface/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/chat-interface/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/chat-interface/src/auth.js b/chat-interface/src/auth.js new file mode 100644 index 0000000..5caa704 --- /dev/null +++ b/chat-interface/src/auth.js @@ -0,0 +1,119 @@ +// MSAL Authentication Configuration +const msalConfig = { + auth: { + clientId: "9079054c-9620-4757-a256-23413042f1ef", + authority: "https://login.microsoftonline.com/e519c2e6-bc6d-4fdf-8d9c-923c2f002385", + redirectUri: "https://ai-sandbox.oliver.solutions/format" + }, + cache: { + cacheLocation: "sessionStorage", + storeAuthStateInCookie: true, + } +}; + +const loginRequest = { + scopes: ["user.read"] +}; + +// Initialize MSAL object +let myMSALObj = null; +let thisUser = null; + +// Initialize MSAL when loaded +export function initializeMSAL() { + if (typeof msal !== 'undefined') { + myMSALObj = new msal.PublicClientApplication(msalConfig); + + // Check if there's a cached user + const accounts = myMSALObj.getAllAccounts(); + if (accounts.length > 0) { + thisUser = accounts[0].username; + // User is already logged in, show content + showProtectedContent(); + } else { + // Need to initialize login elements if not logged in + const signinButton = document.getElementById('signin-button'); + if (signinButton) { + signinButton.addEventListener('click', signIn); + } + } + } else { + console.error("MSAL library not loaded"); + } +} + +// Sign in with popup +export function signIn() { + if (!myMSALObj) { + initializeMSAL(); + } + + myMSALObj.loginPopup(loginRequest) + .then(loginResponse => { + console.log("User logged in:", loginResponse.account.username); + thisUser = loginResponse.account.username; + sessionStorage.setItem('msalUsername', loginResponse.account.username); + showProtectedContent(); + }).catch(error => { + console.error("Error during login:", error); + }); +} + +// Show the protected content (the chat interface) +function showProtectedContent() { + const loginContainer = document.getElementById('login-container'); + const rootContainer = document.getElementById('root'); + + if (loginContainer) { + loginContainer.style.display = 'none'; + } + + if (rootContainer) { + rootContainer.style.display = 'block'; + } + + // Dispatch an event that authentication is complete + window.dispatchEvent(new CustomEvent('authenticationComplete', { + detail: { + username: thisUser + } + })); +} + +// Get current user +export function getCurrentUser() { + if (!thisUser) { + thisUser = sessionStorage.getItem('msalUsername'); + } + return thisUser; +} + +// Check if user is authenticated +export function isAuthenticated() { + if (!myMSALObj) { + initializeMSAL(); + } + + return myMSALObj?.getAllAccounts().length > 0 || !!getCurrentUser(); +} + +// Sign out +export function signOut() { + if (!myMSALObj) { + initializeMSAL(); + } + + const logoutRequest = { + account: myMSALObj.getAccountByUsername(thisUser) + }; + + myMSALObj.logout(logoutRequest).then(() => { + thisUser = null; + sessionStorage.removeItem('msalUsername'); + // Redirect to login page + window.location.reload(); + }); +} + +// Register initialization on window load +window.addEventListener('DOMContentLoaded', initializeMSAL); diff --git a/chat-interface/src/components/ChatInterface.jsx b/chat-interface/src/components/ChatInterface.jsx new file mode 100644 index 0000000..583f685 --- /dev/null +++ b/chat-interface/src/components/ChatInterface.jsx @@ -0,0 +1,140 @@ +// Use environment variables for backend URL +// Define backend URL dynamically based on environment +const BACKEND_URL = import.meta.env.VITE_BACKEND_URL || 'https://ai-sandbox.oliver.solutions/hp_back_v2'; +console.log('ChatInterface using backend URL:', BACKEND_URL); + +const initializeChat = async ({ sessionId, briefFiles, supportingFiles, setError, setIsProcessing, setIsInitialized, setMessages }) => { + if (briefFiles.length === 0) { + setError('Please upload at least one brief file.'); + return; + } + + setIsProcessing(true); + const formData = new FormData(); + + // Add session ID to the form data + formData.append('sessionId', sessionId); + + briefFiles.forEach(file => { + formData.append('brief', file); + }); + + supportingFiles.forEach(file => { + formData.append('supporting', file); + }); + + try { + console.log('Sending initialize request...'); + const response = await fetch(`${BACKEND_URL}/initialize`, { + method: 'POST', + body: formData, // No Content-Type header for FormData + credentials: 'include', // Include credentials (cookies, auth headers) + }); + + console.log('Response status:', response.status); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || 'Failed to initialize chat'); + } + + const data = await response.json(); + console.log('Response data:', data); + + setIsInitialized(true); + setMessages([{ + role: 'assistant', + content: 'Chat initialized! How can I help you?' + }]); + setError(null); // Clear any previous errors + } catch (err) { + console.error('Error:', err); + setError(err.message || 'Failed to initialize chat. Please try again.'); + } finally { + setIsProcessing(false); + } +}; + +const handleSubmit = async ({ inputMessage, sessionId, setMessages, setInputMessage, setIsProcessing, setError, logToConsole }) => { + if (!inputMessage.trim()) return; + + const currentMessage = inputMessage; + setMessages(prev => [...prev, { role: 'user', content: currentMessage }]); + setInputMessage(''); + setIsProcessing(true); + + try { + const response = await fetch(`${BACKEND_URL}/chat`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + message: currentMessage, + sessionId: sessionId + }), + credentials: 'include', // Include credentials for cross-origin + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || 'Failed to get response'); + } + + const dataString = await response.text(); // Get the response as text + const data = JSON.parse(dataString); // Parse the JSON string + + // Extract response data, checking for different response formats + let responseText = ''; + let sources = []; + let reasoning = []; + let images = []; + + if (data.data) { + // New response format + responseText = data.data.response || ''; + sources = data.data.sources || []; + reasoning = data.data.reasoning || []; + images = data.data.images || []; + } else { + // Direct response format + responseText = data.response || ''; + sources = data.sources || []; + reasoning = data.reasoning || []; + images = data.images || []; + } + + // Log the images + if (images && images.length > 0) { + logToConsole('info', 'Images received in response', { imageCount: images.length, images }); + } + + setMessages(prev => { + const newMessages = [...prev]; + newMessages.push({ + role: 'assistant', + content: responseText, + sources: sources, + reasoning: reasoning, + images: images + }); + return newMessages; + }); + setError(null); // Clear any previous error + + } catch (e) { // Include the original JSON string in the error data + console.error('Error processing chat response:', e); + logToConsole('error', 'Chat error', { + error: e.message, + stack: e.stack, + response: e.response + }); + + setError('Failed to process response. Please check the logs for details.'); // Display a more user friendly error in UI + } finally { + setIsProcessing(false); + } +}; + +// Export the functions +export { initializeChat, handleSubmit }; \ No newline at end of file diff --git a/chat-interface/src/components/ConversationManager.jsx b/chat-interface/src/components/ConversationManager.jsx new file mode 100644 index 0000000..023ca51 --- /dev/null +++ b/chat-interface/src/components/ConversationManager.jsx @@ -0,0 +1,206 @@ +// Get the backend URL from environment or use correct path as fallback +// Define backend URL dynamically based on environment +const BACKEND_URL = import.meta.env.VITE_BACKEND_URL || 'https://ai-sandbox.oliver.solutions/hp_back_v2'; +console.log('ConversationManager using backend URL:', BACKEND_URL); + +// Function to load user conversations +export const loadUserConversations = async (username, setConversations, setActiveConversation, loadConversation, setError) => { + try { + const response = await fetch(`${BACKEND_URL}/conversations`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'X-MS-USERNAME': username || '' // Add authenticated username to request + }, + credentials: 'include' + }); + + if (!response.ok) { + throw new Error('Failed to load conversations'); + } + + const data = await response.json(); + + if (data.status === 'success') { + setConversations(data.conversations || []); + + // If we have conversations and none are active, select the most recent one + if (data.conversations && data.conversations.length > 0 && setActiveConversation) { + // Sort by last_updated, newest first + const sortedConversations = [...data.conversations].sort((a, b) => + new Date(b.last_updated) - new Date(a.last_updated) + ); + + // Set the most recent conversation as active + setActiveConversation(sortedConversations[0]); + + // Load this conversation if load function provided + if (loadConversation) { + await loadConversation(sortedConversations[0]); + } + } + + return data.conversations || []; + } else { + throw new Error(data.error || 'Failed to load conversations'); + } + } catch (error) { + console.error('Error loading conversations:', error); + if (setError) { + setError('Failed to load conversations. Please try again later.'); + } + return []; + } +}; + +// Function to load a specific conversation's messages +export const loadConversationMessages = async (conversation, username, setMessages, setSessionId, setError) => { + try { + if (!conversation || !conversation.id) { + throw new Error('Invalid conversation'); + } + + const response = await fetch(`${BACKEND_URL}/conversations/${conversation.id}/messages`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'X-MS-USERNAME': username || '' // Add authenticated username to request + }, + credentials: 'include' + }); + + if (!response.ok) { + throw new Error('Failed to load conversation messages'); + } + + const data = await response.json(); + + if (data.status === 'success') { + // Format the messages for the UI + const formattedMessages = data.messages.map(msg => ({ + role: msg.role, + content: msg.content, + sources: msg.sources || [], + reasoning: msg.reasoning || [], + images: msg.images || [] + })); + + setMessages(formattedMessages); + + // Set the session ID if provided + if (setSessionId && conversation.session_id) { + setSessionId(conversation.session_id); + localStorage.setItem('chatSessionId', conversation.session_id); + } + + return formattedMessages; + } else { + throw new Error(data.error || 'Failed to load conversation messages'); + } + } catch (error) { + console.error('Error loading conversation messages:', error); + if (setError) { + setError('Failed to load conversation messages. Please try again later.'); + } + return []; + } +}; + +// Function to create a new conversation +export const createNewConversation = async (username, setConversations, setActiveConversation, setSessionId, setMessages, setError) => { + try { + const response = await fetch(`${BACKEND_URL}/conversations/new`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-MS-USERNAME': username || '' // Add authenticated username to request + }, + credentials: 'include' + }); + + if (!response.ok) { + throw new Error('Failed to create new conversation'); + } + + const data = await response.json(); + + if (data.status === 'success') { + // Create a new conversation object + const newConversation = { + id: data.conversation_id, + title: "New conversation", + created_at: new Date().toISOString(), + last_updated: new Date().toISOString(), + session_id: data.session_id + }; + + // Update the conversations list + setConversations(prev => [newConversation, ...prev]); + + // Set as active conversation + setActiveConversation(newConversation); + + // Set the session ID + if (setSessionId) { + setSessionId(data.session_id); + localStorage.setItem('chatSessionId', data.session_id); + } + + // Reset messages with welcome message + if (setMessages) { + setMessages([{ + role: 'assistant', + content: 'How can I help you today?' + }]); + } + + return newConversation; + } else { + throw new Error(data.error || 'Failed to create new conversation'); + } + } catch (error) { + console.error('Error creating new conversation:', error); + if (setError) { + setError('Failed to create new conversation. Please try again later.'); + } + return null; + } +}; + +// Function to delete a conversation +export const deleteConversation = async (conversationId, username, setConversations, setError) => { + try { + if (!conversationId) { + throw new Error('Invalid conversation ID'); + } + + const response = await fetch(`${BACKEND_URL}/conversations/${conversationId}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + 'X-MS-USERNAME': username || '' // Add authenticated username to request + }, + credentials: 'include' + }); + + if (!response.ok) { + throw new Error('Failed to delete conversation'); + } + + const data = await response.json(); + + if (data.status === 'success') { + // Remove the conversation from the list + setConversations(prev => prev.filter(convo => convo.id !== conversationId)); + return true; + } else { + throw new Error(data.error || 'Failed to delete conversation'); + } + } catch (error) { + console.error('Error deleting conversation:', error); + if (setError) { + setError('Failed to delete conversation. Please try again later.'); + } + return false; + } +}; \ No newline at end of file diff --git a/chat-interface/src/components/ThemeToggle.jsx b/chat-interface/src/components/ThemeToggle.jsx new file mode 100644 index 0000000..e2fe897 --- /dev/null +++ b/chat-interface/src/components/ThemeToggle.jsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { useTheme } from '../main'; +import { Moon, Sun } from 'lucide-react'; + +export default function ThemeToggle() { + const { darkMode, setDarkMode } = useTheme(); + + return ( + + ); +} diff --git a/chat-interface/src/components/ui/alert.jsx b/chat-interface/src/components/ui/alert.jsx new file mode 100644 index 0000000..8437323 --- /dev/null +++ b/chat-interface/src/components/ui/alert.jsx @@ -0,0 +1,37 @@ +import * as React from "react" +import { cn } from "../../lib/utils" + +const Alert = React.forwardRef(({ className, variant = "default", children, ...props }, ref) => { + const variantClasses = { + default: "bg-gray-100 text-gray-900", + destructive: "bg-red-100 text-red-900", + } + + return ( +
+ {children} +
+ ) +}) +Alert.displayName = "Alert" + +const AlertDescription = React.forwardRef(({ className, ...props }, ref) => ( +
+)) +AlertDescription.displayName = "AlertDescription" + +export { Alert, AlertDescription } + diff --git a/chat-interface/src/index.css b/chat-interface/src/index.css new file mode 100644 index 0000000..5e4ccd3 --- /dev/null +++ b/chat-interface/src/index.css @@ -0,0 +1,131 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + --border: 214.3 31.8% 91.4%; + --radius: 0.5rem; + } + + .dark { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + --border: 217.2 32.6% 17.5%; + } + + body { + @apply bg-black text-foreground; + border: none !important; + border-top: none !important; + border-bottom: none !important; + } +} + +/* Netflix theme colors */ +.netflix-red { + color: #E50914; +} + +.netflix-bg { + background-color: #141414; +} + +/* Prevent any border from appearing */ +.no-borders, .no-borders::before, .no-borders::after { + border: none !important; + border-top: none !important; + border-bottom: none !important; + border-left: none !important; + border-right: none !important; + outline: none !important; +} + +/* Markdown content styling */ +.markdown-content { + @apply text-base leading-relaxed; +} + +.markdown-content h1 { + @apply text-2xl font-bold mt-4 mb-2; +} + +.markdown-content h2 { + @apply text-xl font-bold mt-3 mb-2; +} + +.markdown-content h3 { + @apply text-lg font-bold mt-3 mb-1; +} + +.markdown-content p { + @apply my-2; +} + +.markdown-content ul { + @apply list-disc pl-5 my-2; +} + +.markdown-content ol { + @apply list-decimal pl-5 my-2; +} + +.markdown-content li { + @apply my-1; +} + +.markdown-content a { + @apply text-blue-600 hover:underline; +} + +.markdown-content code { + @apply font-mono bg-gray-200 px-1 py-0.5 rounded text-sm; +} + +.markdown-content pre { + @apply bg-gray-800 text-white p-3 rounded my-3 overflow-auto; +} + +.markdown-content pre code { + @apply bg-transparent text-white text-sm; +} + +.markdown-content blockquote { + @apply border-l-4 border-gray-300 pl-4 my-3 italic text-gray-700; +} + +.markdown-content table { + @apply border-collapse border border-gray-300 my-3 w-full; +} + +.markdown-content th { + @apply border border-gray-300 bg-gray-100 p-2 font-semibold; +} + +.markdown-content td { + @apply border border-gray-300 p-2; +} + +/* Different background for assistant markdown vs user text */ +.bg-blue-500 .markdown-content { + @apply text-white; +} + +.bg-blue-500 .markdown-content code { + @apply bg-blue-600 text-white; +} + +.bg-blue-500 .markdown-content a { + @apply text-white underline; +} + +.bg-blue-500 .markdown-content blockquote { + @apply border-white/50 text-white/90; +} + diff --git a/chat-interface/src/lib/utils.js b/chat-interface/src/lib/utils.js new file mode 100644 index 0000000..d510289 --- /dev/null +++ b/chat-interface/src/lib/utils.js @@ -0,0 +1,40 @@ +// Original utils.js file content +import { clsx } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs) { + return twMerge(clsx(inputs)) +} + +/** + * Enhanced fetch function with a 300-second timeout + * @param {string} url - URL to fetch + * @param {Object} options - Fetch options + * @returns {Promise} - Fetch promise with timeout + */ +export async function fetchWithTimeout(url, options = {}) { + const timeout = 300000; // 300 seconds in milliseconds + + const controller = new AbortController(); + const { signal } = controller; + + const timeoutId = setTimeout(() => { + controller.abort(); + }, timeout); + + try { + const response = await fetch(url, { + ...options, + signal, + }); + + clearTimeout(timeoutId); + return response; + } catch (error) { + clearTimeout(timeoutId); + if (error.name === 'AbortError') { + throw new Error(`Request timed out after ${timeout / 1000} seconds`); + } + throw error; + } +} \ No newline at end of file diff --git a/chat-interface/src/main.jsx b/chat-interface/src/main.jsx new file mode 100644 index 0000000..3e85a5a --- /dev/null +++ b/chat-interface/src/main.jsx @@ -0,0 +1,75 @@ +import React, { useEffect, useState, createContext, useContext } from 'react' +import ReactDOM from 'react-dom/client' +import App from './App' +import './index.css' +import { initializeMSAL, isAuthenticated } from './auth' + +// Initialize MSAL +initializeMSAL(); + +// Create Theme Context +export const ThemeContext = createContext(); + +export const ThemeProvider = ({ children }) => { + const [darkMode, setDarkMode] = useState(() => { + // Check local storage for user preference + const savedMode = localStorage.getItem('darkMode'); + return savedMode === 'true'; + }); + + // Apply dark mode class to html element + useEffect(() => { + if (darkMode) { + document.documentElement.classList.add('dark'); + } else { + document.documentElement.classList.remove('dark'); + } + // Save preference to localStorage + localStorage.setItem('darkMode', darkMode); + }, [darkMode]); + + return ( + + {children} + + ); +}; + +// Custom hook for using theme context +export const useTheme = () => useContext(ThemeContext); + +const AuthenticatedApp = () => { + const [authenticated, setAuthenticated] = useState(isAuthenticated()); + + useEffect(() => { + // Listen for authentication complete event + const handleAuth = () => { + setAuthenticated(true); + }; + + window.addEventListener('authenticationComplete', handleAuth); + + // Check if already authenticated + if (isAuthenticated()) { + handleAuth(); + } + + return () => { + window.removeEventListener('authenticationComplete', handleAuth); + }; + }, []); + + // The App component will only be rendered when user is authenticated + return authenticated ? ( + + + + ) : null; +}; + +ReactDOM.createRoot(document.getElementById('root')).render( + + + , +) + diff --git a/chat-interface/tailwind.config.js b/chat-interface/tailwind.config.js new file mode 100644 index 0000000..2955b1a --- /dev/null +++ b/chat-interface/tailwind.config.js @@ -0,0 +1,28 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + "./index.html", + "./src/**/*.{js,jsx,ts,tsx}", + ], + darkMode: 'class', // Enable class-based dark mode + theme: { + extend: { + colors: { + border: "hsl(var(--border))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))" + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + }, + }, + plugins: [], +} + diff --git a/chat-interface/update-backend.sh b/chat-interface/update-backend.sh new file mode 100755 index 0000000..71e7e06 --- /dev/null +++ b/chat-interface/update-backend.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# This script updates the backend URL and rebuilds the application + +# Define the backend URL +BACKEND_URL="https://ai-sandbox.oliver.solutions/netflix_back_v2" + +# Create or update the environment files +echo "# Backend API URL +VITE_BACKEND_URL=${BACKEND_URL} + +# Base URL for the app (changes in production) +VITE_APP_BASE_URL=/" > .env + +echo "# Production backend API URL +VITE_BACKEND_URL=${BACKEND_URL} + +# Base URL for the app in production +VITE_APP_BASE_URL=/netflix_v2/" > .env.production + +# Update components files +for file in src/components/ChatInterface.jsx src/components/ConversationManager.jsx src/App.jsx; do + # Replace hardcoded backend URL references + sed -i '' "s|const BACKEND_URL = ['\"]\/netflix_back_v2['\"]|const BACKEND_URL = import.meta.env.VITE_BACKEND_URL || '${BACKEND_URL}'|g" $file + sed -i '' "s|console.log('.*using backend URL (hardcoded):|console.log('Using backend URL:|g" $file +done + +# Update vite.config.js to use the replacement plugin +sed -i '' 's|plugins: \[react()\],|plugins: [react(), replaceBackendUrl],|g' vite.config.js +sed -i '' 's|code: src.replace(/\['"'\]\/netflix_back\['"'\]/g, '"\/netflix_back_v2"'),|code: src.replace(/\['"'\]\/netflix_back\['"'\]/g, `"${BACKEND_URL}"`),|g' vite.config.js + +# Force a complete rebuild by removing all assets +rm -rf dist/assets/* + +# Rebuild the application +npm run build + +echo "Update complete! The backend URL has been set to ${BACKEND_URL}" \ No newline at end of file diff --git a/chat-interface/vite.config.js b/chat-interface/vite.config.js new file mode 100644 index 0000000..51bb0ed --- /dev/null +++ b/chat-interface/vite.config.js @@ -0,0 +1,124 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import path from 'path' + +export default defineConfig(({ mode }) => { + const baseUrl = mode === 'production' ? '/hp_chatbot/' : '/'; + + // Create a replace plugin to ensure all '/hp_back' gets replaced with the full URL + const replaceBackendUrl = { + name: 'replace-backend-url', + transform(src, id) { + if (id.endsWith('.js') || id.endsWith('.jsx')) { + return { + code: src.replace(/['"]\/hp_back['"]/g, '"https://ai-sandbox.oliver.solutions/hp_back_v2"'), + map: null + }; + } + } + }; + + return { + plugins: [react(), replaceBackendUrl], + base: baseUrl, + server: { + port: 5173, + proxy: { + // New MongoDB conversation endpoints + '/conversations': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + }, + '/conversations/new': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + }, + + // Original endpoints + '/chat': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + }, + '/status': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + }, + '/initialize': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + }, + '/reset': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + }, + '/download-brief': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + }, + '/init-chunked-upload': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + }, + '/upload-chunk': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + }, + '/finalize-upload': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + }, + '/upload-small-file': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + }, + '/initialize-from-uploads': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + }, + '/images': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + }, + '/list-images': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + }, + '/capture-screenshot': { + target: 'https://ai-sandbox.oliver.solutions/hp_back_v2', + changeOrigin: true, + secure: true, + timeout: 300000 // 5 minutes timeout + } + } + } + }; +}) + diff --git a/chat-interface/web.config b/chat-interface/web.config new file mode 100644 index 0000000..75ec618 --- /dev/null +++ b/chat-interface/web.config @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config.py b/config.py new file mode 100644 index 0000000..df7a987 --- /dev/null +++ b/config.py @@ -0,0 +1,103 @@ +# hp_chatbot/config.py +import os +from pathlib import Path +from dotenv import load_dotenv +import sys + +# Load environment variables from .env file +env_path = Path(__file__).resolve().parent / '.env' +if env_path.exists(): + # Force reload to ensure environment variables are set + load_dotenv(dotenv_path=env_path, override=True) + print(f"Loaded environment variables from {env_path}") +else: + print(f"WARNING: .env file not found at {env_path}", file=sys.stderr) + +# --- Directory Paths --- +BASE_DIR = Path(__file__).resolve().parent + +UPLOAD_DIR = BASE_DIR / 'uploads' +CHUNK_FOLDER = UPLOAD_DIR / 'chunks' +UPLOAD_METADATA_FOLDER = UPLOAD_DIR / 'metadata' +IMAGES_DIRECTORY = UPLOAD_DIR / 'images' + +SUPPORTING_FILES_DIR = BASE_DIR / 'supporting_files' +HP_DOCS_FOLDER = SUPPORTING_FILES_DIR / 'files_for_rag_store' + +INDEX_STORAGE_DIR = BASE_DIR / 'index_storage' +INDEX_PERSIST_PATH = INDEX_STORAGE_DIR / "hp_docs_index" + +LOG_FILE_PATH = BASE_DIR / 'app.log' + +# Create necessary directories +os.makedirs(CHUNK_FOLDER, exist_ok=True) +os.makedirs(UPLOAD_METADATA_FOLDER, exist_ok=True) +os.makedirs(INDEX_STORAGE_DIR, exist_ok=True) +os.makedirs(IMAGES_DIRECTORY, exist_ok=True) + +# --- Application Settings --- +ALLOWED_EXTENSIONS = {'pdf', 'doc', 'docx', 'txt', 'xls', 'xlsx', 'ppt', 'pptx', 'eml'} +APPLICATION_ROOT = os.environ.get('APPLICATION_ROOT', '') # For running behind proxy +MAX_CONTENT_LENGTH = 500 * 1024 * 1024 # 500MB limit (adjust as needed) + +# --- API Keys --- +# Load from environment variables or use defaults (replace placeholders or set env vars) +OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY", "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") +ANTHROPIC_API_KEY = os.environ.get("ANTHROPIC_API_KEY", "") +LLAMA_CLOUD_API_KEY = os.environ.get("LLAMA_CLOUD_API_KEY", "") + +# Ensure required keys are set +if not OPENAI_API_KEY: + print("ERROR: OPENAI_API_KEY not set in environment or .env file. This is required.", file=sys.stderr) + print("Please add OPENAI_API_KEY=your_key to your .env file.", file=sys.stderr) + print(f"Current environment keys: {list(filter(lambda k: 'key' in k.lower(), os.environ.keys()))}", file=sys.stderr) + +# Always set environment variables, even if empty - the error messages will be handled by the code +os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY +os.environ["ANTHROPIC_API_KEY"] = ANTHROPIC_API_KEY +os.environ["LLAMA_CLOUD_API_KEY"] = LLAMA_CLOUD_API_KEY + +# Print API key status for debugging +print(f"OpenAI API key {'is set' if OPENAI_API_KEY else 'is NOT set'}", file=sys.stderr) + +# --- AI Model Configuration --- +LLM_MODEL = "chatgpt-4o-latest" # Or "gpt-4o" etc. +EMBEDDING_MODEL = "text-embedding-3-small" +LLM_TEMPERATURE = 0.3 +LLM_TIMEOUT = 300.0 # 5 minutes +AGENT_TIMEOUT = 600.0 # 10 minutes for the agent run +TOOL_EXECUTION_TIMEOUT = 300.0 # 5 minutes for individual tool calls + +# --- LlamaParse Configuration --- +LLAMA_PARSE_VENDOR_MODEL = "openai-gpt4o" # Verify model name +LLAMA_PARSE_MAX_TIMEOUT = 3600 # 1 hour + +# --- Indexing Configuration --- +# NODE_PARSER_CHUNK_SIZE = 2048 # Example if using SentenceSplitter +# NODE_PARSER_CHUNK_OVERLAP = 20 +# Use Semantic Splitter by default (see ai_core.py) +SIMILARITY_TOP_K = 10 +SIMILARITY_CUTOFF = 0.0 # Adjust if needed + +# --- CORS Configuration --- +CORS_ALLOWED_ORIGINS = ["http://localhost:5173", "https://ai-sandbox.oliver.solutions"] # HP chatbot CORS origins +CORS_SUPPORTS_CREDENTIALS = True + +# --- Server Configuration --- +SERVER_HOST = "0.0.0.0" if os.environ.get("PRODUCTION", "false").lower() == "true" else "localhost" +SERVER_PORT = int(os.environ.get("PORT", "8746")) # Port for HP chatbot (unique from Netflix) +USE_RELOADER = os.environ.get("PRODUCTION", "false").lower() != "true" +LOG_LEVEL = os.environ.get("LOG_LEVEL", "INFO") # Changed default to INFO + +# Hypercorn specific timeouts (in seconds) +KEEP_ALIVE_TIMEOUT = 300 +READ_TIMEOUT = 300 +WRITE_TIMEOUT = 300 + +# --- MongoDB Configuration --- +# Assumes mongodb_utils handles connection details (e.g., via environment variables) + +# --- Neo4j Configuration --- +NEO4J_URL = os.environ.get("NEO4J_URL", "bolt://localhost:7688") # Separate Neo4j instance for HP +NEO4J_USERNAME = os.environ.get("NEO4J_USERNAME", "neo4j") +NEO4J_PASSWORD = os.environ.get("NEO4J_PASSWORD", "hp-graphrag-2024") # HP-specific password \ No newline at end of file diff --git a/docs/graphRAG chatbot technical documentation.pdf b/docs/graphRAG chatbot technical documentation.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9f361bf62f6be2d911b104e367c94544b2deabea GIT binary patch literal 496402 zcmbSyV{~QRwrwi5DzX&&wJ6qERFO-&0l9iz$urjwaCJ;9^w6y(p zwEg#O>Hqt#1j1$xw${ep=--+9u1_rFgNDC(Q&JDC4F z@^_~44z@4>}n)yEkH`FI!gr*mgC7_qHb+FdA`i~Ri|Ckmrb1SFs z+~~!uzLO9!HncS|hNhP>wlQ@wBVgv>WZ~l@aCG{vwKcR`#ze+O6mCnT@70vz`~z^g zL;;0@K#joDAKoP>*!>^vshFS_K&f6ndV+~0fI_OL=(Q*a<}91jgnoXn0fUp}A4#uM zhwNP+P0U?~z-veJO+H&jprP-<#~+VF{5C#c)fc+oRJVS=%!Ab1-4Q*zYU9UN*GFAs z_Sf^pW3jH?+r^hnY?FjJH5gkAln<)pjTvba$ic)9Mq7BK+Q|mUf4M!MJQhdW!?b(7 zKA^b>_oBHIFY|e|e5`o5y=Py{@!S5;3f^TLoUqOQbbb5#6#6D%$M~!Sw+!*lho~*4 zyA0di=M6?jEaFVk5)lh?ixFB2kCL1}6_}%1ztAxz@Iy^}cW(i5Hjx&QUYyRklZ{zh z)}?Z_A+rTOW(*M|s6cgkK?^jQST$aI75Uw=x_g~QkS_PR0{SlK52H4mR%>`~A@LRZ zZ|!P_gV*O9gR-;Xqw-1*A70#=D92HJ~_|Qe{ zmxeGt7)!~t_@-WX7pk{nxpl-^H;E=YP-Wcy)fYU*(92%&nBb;Tb$4y~-Ng(X0&wu| zQF>A(qvE}fc|QI8p05l3`;Mf>n55(BP&qWf*!wP0DTbJ}z%jHwP`F%6VVHUy)B#(k zZUhPYj#q^@S%c&Oa~+VR+!gC#qEy$RnV-($&d7t6VM)v`Y;AP-i&hgmRi;MHvm?o+ za>H8A7S6gT-ujoi(cKUej{2ME(~RdFg-CM2vsZX^rOY!P*FDd2A3Wbv91hu9Esd}R zFd@g?0I?D|GQ$cOoP6WIMn*{GeX^~=LhzUzGAA0uGaWCvv%r(xTg%xZ4RMnVzO2whpF@&qTAQz9H^36VQ1Z)TSF*PK_1UOzpuqczZ$ zT7<&Q(&zZG@OjGQJ_A--CscX+P8*&azYwc`H@!VA)sefOuiQ1;_Us&cWP3swyAZw_ z5g0#R6&N$T)gQd?pKx3?sU3E#5R0>=(dHFf-bna);!uyXh0V-!r7b z_PC!de{4NquXyE&Gk|IDOc>Mqh(*7FTqrEsGQQCG&l5x9|Neo<$S_p6ZJZoxIPO*f zTQ?TR6ttAi<|YKx0sIP=h*(@ow`8X7R_E5K7C^U9sFLJ%=u6MUP@2D0?m+jtj89KJ zR_;%tlc@EI(S*{DUO0LdUOzTa4WrOGd%7xwM>nN^_VwrQMD@mm=eU_vl=OiNh7Ek} zUE9?A(wgqCH?g%Yx-?1U-6neH=aWUTY@64S;?LCLwJUbWV}QtJOkIGCS|fdv{IcL< zOvL?&)K4xMQjt_k89OSLrLWI88&%kPPT)BH)G}rSq6@Es<2W7_@LpO0C;KmJ+uz!p zmtM*xxwJ#mWd;m*>Q!TWfx?;Uux0q0lmkppDEWqA9pl^jigeiV!VmY%d>GVyxuCcQ zIkehumHU~EXb~ZUG2Zu!y(wCcEKq;%_)w5bTRye8$eur} zp#krSb@I)1K|-{$87VS0in~yp{&^C@m%m)RjTRG# z=s5_av>6c>XLMUJU_?3kvm%vU!Qz(8a7Y8l+|jZydG=0^aDxH5JZf#T(2FibdFu;x z*Ym4DVEy@F*~}vRW;ki{3NO6J z^$fpr;x}yWF3EKG#L~dbBiQlV4XFL~{!K_SN|qK?&|FeWGk|CN@c^8(Rh|ir*sE?f zF2j_D#?|z{)3D(YOt8rsJ20hQW^GK7(YI)IZII~bQY0(foQ8bD|6C8*9yXN1RCc+?i* znj#Mm;|EG9U!3ha=1ljkx7D$?^r-k|O!$TUb~L%Eojh_CX)4hu5oQ$pKqZDg4u;--|QbQCd{1vzJ%fn~d3EFm*O4?$TwOn{b^uyfxnw zW5JjgFpk+6HzG=_iy)eU z>5&w*q)vkJ;Nq`VCI*H>;vp#MDEWx6-b(?G5-~}v;3%g;;z;z{03MQI;s~j|v^@FF zhvOeYRrP`dUKPwYp$7xR0g`Sa+7yFT03yi#xm;o*(JCl;e6ALFP1Y=j%yt_)qP=aY>|atn)KuK_-UA{2r#f0 z3jpD_9pvwWOW0%2Ncas2KHv_CE!QjZRK!DK;dEkB2e0EoKv+wUpVk0CgQst+#D@w+8 z4f5wXE9l*4c`R1jU1i0RE7BC6;JWS(iMa0!PL1~(_k?3Jh=NB@Wf)v{*AQbj{F65h zJ>HteR||2#Mx!@S<*LhcIsR|%SJi0j4xH0K@sgia^2KVD0IM_rPXO0ILoj(+I@kpo z;i^wYiCjG()2xt7VFB2*?5DC<4?x=}_%y+!?5qZ$U93>C28Mbj%qm=?@2{U(yC84x zHZbkzHf6W?yn^U1((mgbBG;?~!fl^vSGvnA*pOZXrhh$D22Q<98M^Uit&f3C^`-~T z4c0<&1H>JKdX6FzB5zWosMaHw3&Aq3m;56hNgu3DyWdD%t-FdUy+V1<%G;HF*{h}v zrU(~=T-g(*2lf%EtX6bO$^|P#E-niLSN{GEhKXUJ?rO^*+`*{=N1i`>)D!#&BaT${CBj}LB#k;~iy1|o2xF8GSl3wQGW&gzYo;^z?6W$=crKA0n z^VmJ%$U(%Nj(T*Zn!;2Ui8(&wLnF&kZOjqg(w**t3n7bkn6rZ5$PU~Ao_bi+L|~F3 zKq~}wpDWUTovwrczYNm=?kDWpyb?&y&QFlB9qs^S=enJ%(BPf>&@{bvaOYk(I%)T; z79!9Kht#RjyK(9PN1d^|j46t&JHK7dYLuy$i2pJzqK;E|aE-8LT*rlJ9B)KJw^|FB zsU=jFgIIeqHVEt~ybSBcY~l75D=NgGcaPWy?%{iD1blLA+n8jqlhfGm>N44#_RYPl zW92v|e{F`GvweheK6r7dR?xj2%~}rgL>2kxH0e)Lt1VMBM==|tFLGbn80iP;-V8NG zNb3B0^pd^2;FCW$he={ZrBKK(!|sQ*A1yUSjKnX)&ea6M&xf^RE3J`Y@z#ixi`I?# zn?%R2w{5Zq^_r^Ln?#kEMI$tF7?_f%8sC+?L<_Dfo*xZcz3BLt!+GB#qc0 z`M0u7h=brl8-_$o9HMFVWqo0DjN!ZUbj2LFVVF*^Ah1Reh2Y{Fq`?|}j={F41|Ypi zFnwc4%su9CCxMEAg_u1UNhX2AuY*l#L5ao3s#$sbdz7!K|F8AUc`$s8D`GN?Y^!Fi zipu!E1QiP###etv6!$^7fCMHM4_3PTdH@>tu&pQhjk5(lZ(o3z=RN1vz6`AqG%!bX z!&y?a$D}y(o1YRdmv_ywNf?iSLcX`9`oltd4K9xz>>NE+7DS*Ek>=~?@e=r(_?_{V zVSLYH#Ma`O@h-92pCu_}wyjz~qIIK6S=|iszR^fp`@U68wXjHIp7LWF1U`*Md^KqL zW9WG&YUK#M8EUMcB{Z{!v)T-oi9-GA0ZOGXqj0Rg?@naxe2n>XKcdz1WX+`8ioAV) z-?U@D?6yW9S5Kl_sWN4C1J%J_4du=fH!~!L!a`Akx(B!{iDGs)B92B#5f@-pDQYds z2D`^eujv1LO+v(~6-U1Yh4Tv8Z<6qvDWS??G}V9Y~AjI z`*fk1Iu*ZUNMTYkv^@~f5zg?suH8!{F4Bgm-fp>HraY6o=DgmuaYDL&1$NF#%~&YQ zy?*f5=C&vPOPK##K>u5!GqU_gqYDfEOQZj{QkM}XVEC5aQvZdj|Keq32w0%$6$J^L z9Gt&Z`Tr{A+5QvkpQJn^8z(FK|J3pqUfR{TEm0e9FQ^YV-B_`CB*++`$Cu_)cO-E8 z5F9Orpcg+(ZomBWBuW1~*jwSh-Q$v!3|_36I$i-J^Xet&B$c*}F0yHD?B5XAhb+GJ z_U-Kz{d2Hml%^D;&DTwr&gYQN%IC$wmM#a0Bx@7-(iZ+|HJ_I|RO7?fN0ZOy;nvqp zHT~E1l=<7z*Bw!-y__@iUZle5mX3d#O|IB`SO0uA&)DaluCDjT-T^+}V&v%K(3Vcg zQU=>hWQ6nE-q;xb;P640jnDfPdR~k~*h2llMf6w8hhaqO8atMh3euP8d2|7yGUcBt z+gZ!#b`7+S+n{63?BND4LO(;f@w4z0ofm&cTM5`Wi3RoopLlv&&jt;mYOfoQx4d8t zgTUX1=noT_4`b!6r>nciVlS)UCL_uhWu0T_ie5?&i!UM9kR&tXUz%e}mwcKbBgR6pKW{%S9C|9oB?c_=&7 z#V>I;C@RWmBnUb~Q?r1W2)D~I*(?dPU=(Y0(p#)^)x+xRI4o1APnr;#*HWg7zdj7t z4WToTF;Si}yt%~ozDW0)mPFjOIPl1NK3Hgaf0RlrHu*&_X^dhFD6{8`&cXpO&1y_i z`AGYGbh5m~XCWt(h%0s6py@Py7&huyeU;1gq;F*5s`z~E9q8(O9(+F;p&USnoc5cc zL_t~{+^z{ilS*+(i{lTayu(7kp0D=@L2Rr3i)z#6XMMLa%E0JlMw)1A5(ZHHl!uWH z&`SBnYaa^$sg1|4qsv$vl1iC4c9hpGamyBw@tN^-6KE6G=wH0CUccV1 z!u)+EHNWsrc|UbJrWIJThve4H1Sx|d#oWGZWl|tM98G`}lE>&3zrLVWD~bq3eeLSn z6XX03KrN9DE;Qc7^c6j@40Fcasrv;h>ueGzO0cNAWIfnLJHl^C#6IB$J5H?C$Z`cb zBw=o@52{YKawKgHJ}(^|^LsTb?Mnz3@KeH{f?zL<8w5;}*e6i{BXIQ6@}ypC^KH~8 z+6n9?DnIrwxd`=4mQ>$SJB^l9(=)p+nd4e}SM=yyGcS#4d`_>b=CGKSNa{{Zj0jCB z9}VyB%0=NmEGTnD#Zab-JbPqb02aQQ-J(~z$cGTJ<0!QU_G z75C37Pcx?!gz9C_9*y6vQA*}7rd}{@AZW*wWdV?97Y%w$M6xNn?Xa0b!7~x;j#S2&t9VmRV3{B9fD} zgex2NX%%3V4U{EFL-N$!q-(*Y3-`%7lHQKSjvnPAfTIR8;;j8xp$k(4Afxyg<&&EgtiJwKLi>2+3KTF(7SQ&8BBYDSMGP_v$x!xdB9_XOvO;bosZalg zmMoE&um5;KmWmujs)$L0RGoc1TiWvFTJHd{ZB$cYjjmH;$Otf^MzsQzJge+eKYXux zM{9Lm?FBip$olISK^WdyLZd>l=6l_x{dv`kd!3WnSJI!iM7e5Jy$AB4plB0Tb@mi# zYNeej;i?wzFOB>3^qfZFO5>iGoG~>AfF=~kIfi0YYJ1(CDOWHbcS=E}I%Pf-1tA&M zo{SJJ%g9FyR2$2;m&Rp!de#DqSW^5jiXLQ2g;f#}w7sI}HmY^i$2;p5UBtH~l2j*@ z+-GOF(V+NSvfSuK)p9%Cjj5*Zpp1GgD*3{gSX9Gh?UD?2B##!jm*w9v*Xe1g=ratE zbc6jG{|uUs{ism^{H}z5TKMqPyhe|i!o@4ti3ej;Q(1A4muh%K&L^QG&D>P9lpJi7 z98N7y3I?;MH}y;%TK8!{eWLyJR7F4L)BM9ZqXL|4hUS4DUqZ&6@TSpVtMUBOs1U4zYVJz=r2K2I&2~skEZA(&mi5a_1E^cr0?AI!nql3&F-XVo1UIf zdZ&a0d!Rcl5(9)sM3H$U1HRI`5X+VI(^L08IT?XaIA?~a;fSyXXbxiVZYud~Xd~J3 z>jlw`J-)Fo*SoOusq)S9w`p|(o^DyS>WS9gRPm9A`-7T*SI6_+8h>`y)j^`+kAsKZ zDcdj4-<`?H(O~;a;rv}6cPB48SvW8;|F5INg%+bj|M~v-UlBZMe0Bfbc@pH|EA~pr z;=3yq=}b7zIu^~6dR~R0V}16d%1wUO&ogWz0n7NDNeWe-`K~1-8mY<92RHNsb!PvGKfYpq-3KRGKhvV#Xu5K`r%Tb z_@*YU_FWg&@CJv0g|$N2=cHgq$^$EI1Og~Z6+lrp@pm{!e~c{`P!`QYvBq~0fl#p~VvXOO{2C?FKO2<&-gfC`{I{S44Jh}QEjdQOY&aqD6~P{1p-1W0)0OsN&+VNM0+WP%1%5RLv5P?=%{rxCaghzHk- zREcQ1bzO?EphQh=p*-v1VgF`An?wMD9=Zr|u#TQ$AZ>6Z_}#CkfVMom)9qaNe}>6< z!BHH5Qu90|m{s)GZ5#lW2*rG_AT-~1OhLHn7y%6miTY5D8@+#?&|yW5Lv0`l$P)?b z?MDh!`4_gl=V#^2N2btYm!-~eTgVMjH)k+?G7VxO)t&$}A)l7dCBpmLnEdNI1Oywa zavLaQfGNc1%%vUv=p_>bO4uu0Pg^dIWfB9l+=-7n+9P z^ZCuz1!cs98FqZ=qv4tC{4{AdbSKKO=s2KeH14~|2-|&Uizis#R630yE6}mh~ zx7=B+`RDq@dXI)M-8x8`Kynd49%8ZB`w&Nrh%Vtmu@3aSK}i;%=IsU zFVOpcf(Gm#wK$P3Qi(3qdeBge#*Q(q4H2Z~MyZs|HlN{#b)E~N(X;W#P(bJa#DEys|a5x6U5FwWc z0%@NClqpg$o2+VdD(o{j{ce_j9@Pz3`=tji^QZ!UwxZ zF8GbxYaJ@mC1H~|dW3UiAhCAFQwsD%(;|K2vFg!C_NGWhIDR08FXWVJ&ky&6v5G%5 z9`l=?`j9;SLS^Yi1IW;@&OPdXoOE{4o)BW-`S1KQ)V*{w(PeHS+dTff01c3k2)4sB z|EO~cBgBNT7W77jpH+M;B}~+lepCfkG%o;YczXqu`dM!MiD?M5I*GZQ8ac!a=w=p z*yXI{3`CtTj6GE&SX~0E#wuUM_b<36QeLATVKkn9gp3h?0Bh(X?}LB>JeIUf$UcZ@ zEbJCJK1C9UC#CZVghd3Q1@TV}V1F!92@$CtQACav5=fRon~o-e&1*pEiv5086@bev|Ha}E zY;`Xmv)m5kn2Mn&Qv5**Ugt@b1CY1~>=jh=H)rKV&B3WVZ0!E}R00u)0cOX6AhkeS z=-TrNj4+BGEx5cu2*0j@{AWm(1&4hbx7HL~GwDW_SW5-!n()=Ehd)_06QE4kcfmvn z^9z0A1t--(Ammu#3Y4c!kg$#xgyX3FIw>@P4}#0{*QU2pcX&531O{B4^5RgVABIQh- z1~RCe>;OetZX*ijH4U=No8e z15^t13J*eW#|@j|cEMoR+tAkyvj!hP`Y*!nUqokLH`MHe<_0_n5lrtgT8txfVyP`+ zs2XFnRm(=SZ;U#7n7V&GGqCy&MP3$4tN`O-N|P1jnFp14*tHn53r0dHmi*oFX0}B) zRG^mIU!?$ZNrp|kG~tRcr9hnD-o5;U1A)SYv`7vjEM30c3=|IJSjjPlVJ*^A2XsX{ zAU*stP{}%=r3qoX6n*bwUS5im!puA@eg6!pCWt$oT3a081z_8=Rmx5%AW63ki+za^ z!&CytwBihU_&~eqlXQ@l61yougeeuhh%93Io+(znh%#jQ&@r90TTu)mErCM2cvQom zNBC4&2DewGC`zAk6HpCAO+q8)ieUIej9<7@Bub)MW;GXg7YKych`|2@U;KmwR(=&0 zn>6})8A>- zqQ_<-)hO({H!h&P0!B)1S{l&S3A7ZHXq$>~88r4UQGDN1zQ%Y{?bH6=Cq9aucoE&z zAy0h=@+tg(H-bpTURcFqF_>L`6kxnGVK6^T;l01I4;jwx=m4(@Vlosuf8pm8wQI3+CGL zHie6!ENB?(`iJq;s{#X*ImR^CKcBPL_;=AS!sne?3*1P~s$O-sBquoj{1ho&MxaWA zGz~06wM^3=#LTn0Wp4cxOBLQwiG@ea`kY1DbC54%?2=q_CGA*(oot^{(`05#W-UKx zdccN7h=_T_z4-f@e6#LRs#PCcGI{`^Tm`mNH0!%GDwu}w$?W#AKortz&o3uW`uIC9 zO=uxuD|n?zv||i(34Ru?BIMODf|Hh&-T9IrYs}+^i|G7dT4Mr7KaTWPnQ##DgYzHF zzocb0ww_AUTr_D$T9OEc#_EfBvDS%{xJH_fu! zuBtAzD0OuSP5Mli#I{t&&^<*Hpx&qCPVWyy#bJ){DE1v{rN|XPz8uJO%;C24*RqmV zOddWf8%8G-u*p~&wsgz%+<+@+>(LMEoO^Cc)txTipI`b1Omx`ke`QHS1?c(n*Q?Pu z?Ne)AR}EaK2m|cBsp+;*?&kwq2?rMZsj-j?ov3MuVHbO&U<;$$-z@QS9=7M7?;_OI9B3nQ)K>dWuNYdJ?Pf>G>&t~b>rFEccwSZCraBe$6CxP8` zYtDNr&bFDgP@9`qmA?kJ?GJM8mkvqsQFvc@hZYqsbfXU6l9F-va=EP z<SaoU}yNr*x4gUPRG@bK=#s*N}c&BVNlu=Dor3UKL=^Z z;aEB7JvSi_$nzupVHHdgm9_#yBGn^iHX)jY_4>WjC<1%ytC*9wOwfbO1dO>)N);gr zGsxx}Au^aDgqjyN7Oe(ShcpmDPNWWFMpOZ%Kpn(NHi})6szhl|oocT>TbxXS;hOL> zuwfqgEJ-SKJQ0gbDyeT_lrI(NzvgsV2^nu<8dV;1C&_2&$CIn@<@) zEhK1oS+MP^QlU{D4Sytu8DCX8_!4K#kMMQ)-o)p9@a`oq5B1b8+0)l*s0 zO3ZKlT>|{Hxfeq&nn6pM>F6>ES7!XQy!8UfCcD#F-3-Yw{y}{*y_N*Bq?VGbQDHzH zy}MJ&`&XVyoUa5kw2V{#Y7+;c8EZ_bJ`I}#MLM)_&@6;e3`x@?BCcgeLIPT)R4Bl4 z9e9LN^59gQBR0?swGDMii(s^;W=b{p!E%Gzwp{eW=rEk)cCisPYqfbo183D#+drSF7 zV%3Z>!%G3e70QYmnoLx(7^!v+Y)gF5%j-fZWL3-tCCeu|X?)sC`u2aRV)UlBU&tPg|^byABL>fIjRx2FtBk&((qf$sxqir_|qST(ky8KLdh?uN9)>*MEUP|?X-7znIO~1 zs&eQ%eaj~CspUO2^vMSFRI1LK;y%`3KR!>4IjKBQXC}t7SJrx&c(YrZxY#V4-z3bh zaA31G660977*{Wy4rW#&cIw_tTHqT<)?D!A+{_UE8o556$~(;*UOIOnHag;?5NSFR zoMG_P&f2j^rxMF*Xw7)dDjk-HP|X~+C2{^Xe{N5e?WQc~Ug$rq!bpNYmiK!Uj zyVwR31zPCE)@!?_{lHX2t9&$n#hih?`0L5XS1>&BkwITP65u5=gCyn}&YF)9B1SED zQ^P8phP(6nuCp^GAiSxP!J-#0CZJ5-ZQyq0mn=uIsp8p4;1Rv&z?btD`rMD{kA%q; zP#Y3M>M>Url4fmq!6L*<7Afx708uj&HCQR$HjzXpy}Y-3XhN6XGBllv@aT-t#Jt%U zVSoR~g%|mIeLjtO>v11%&rNt&<=n?rpXb>~>`!WIrePwTi#e*tPE>B-^tW$Kk$so3c}t1+UmO zfr%1R(O8-=FC2pbGW!;6u`m;b3w{qVIRn(BbS0$~7ENhv%ZLq{nw`uMVh^?p0rm~- zcI^gnF>lm5h+7z=JkdGI6B189@(xTJB3>`BhXh@4$TS06v;vP6{eguHT|@{2C0k21 zLno4USjTY)2i~p)>C!2%JEZJSc)@WAy!0kLG-`Yy_t2j<%D1(iYsX;a19WL24Cw`n zzNnMJT5IRpJ3L0CQv1E`!?32S_lQ&MwV2FpF?cpoG*GtMDyTwXV88DLy?%yEmeQ5k z_F~bd|2>sE-uwNvc0$w)Nakj=nAR#qU7cD@3%}5A6La%9_CwvOp47PcIGsNb$9?qy zdzMqB?swJ5Wc<_zsvy{kL`6Sn(?95a@56Ai|HP`Mn{*{!1A7fI-xl&>H_gay|5c5J z(DTWM{;T#gtzl9z+i@-E6%S0SqzkAo2pV2prG#JL7~_PyT_d(rxDoXPU%@W;6`oPG zV!y`u+c8-C+wuDfm=*1ktH|!KhvWvk+D|5Gy2UM8d9H!iF|`(7XG~V~4ZQQMh`{7R zEyBCH61w)s!KH!SF}b!HFH9%$jK?pGohvzi{i*lpig6xk&?)4ezarN(NdI5WuXp4g zp5?GJ^FPe5;sM6g#)c8yLXzUMz6D#3H4jAv_h^|94bsYcnvMh`!-mp#2grPNHI~f{n2;(2&y16R5#L`S4!Za8i+9 zDaEka`1a9iZ9jg^(}t&QOLh#ss-Wd!K`4gAn{BO zE4WLe0AxZ}1%=DaL5dPqy=H4`*J>XfwF#y)cX@1b)c^L_j<@&{18v~$(CwJ-X9p({ zPNdo=pxYQ4|5(WongM9+Rw1gBHf>#`4)S#XSttvT+6&>~x{1eWCOe#>v;%z>?(VA% zgb~Ydk_(oDsfsRuCv-0kf|&^EXj+8pjMJVOI1;V#YQ`i&lb15$4KuBre4)T_jKSJq zIu?yI_giU#rvNu3AJ0kqP32nuu$O{~TO+9nE$=>5A&YWybEfQZkW$wo4F?x}3^-i{ zAaw%faxI;MzS1gQKTGxC02Ni(mVVM8IuovLq8wSo#>H4*6V-#KN+oJ0-TQnLnz6z^ z&BGT+~Mt{bIB|=n2Uik z6e|JqvY6Bp_fJ7_oGsgu=HO`+=4RKse`GhDf^hwY`a;|{cyuEO5P)h44QPH+ZaW&_ zQW4J$3na=lC3I&rgkuBujM+fNYI2R@mRszpk*d~+fGoXAVFL6+P0|ocCP0D*-^$$j zMqRjZZ>a=2xGNgBaR-@ zt;zI7DIG1~&6}!Qp1^>@3+D_O22ouSQOdJ9%h=b2Pi4L6_1}|#;<+)qMn&lc(RACm z`t?}LBv#XFRXKvSM2TQyEwO{=v&?-S0)s4aqTQ}!oHQ>}wc$jq{)WJ5VHL7T26JiP zY1H(#>Lx8aL%fZq=2^5|*O+rQH6&{kRQ(`~IcN?sdYkssg}y=zxgWw{-j}JuiuLx0 z65kg?W6R~mITJ>QbtOjQ_G?0LAaNA?48UV~go^F9*sY*-26mRsim*?nd3d(ZHbEBH ztw#;<67v@n#i=r;`Bgsx!${gdL)?uThzunmI=dVJ4+#~{*iu6Wkqw$E;k~dL68zUne_Kf$pak#!kjbJ2A+HjY@yPD=U6@SMJI5dZssSJn6ig9i=wNhC31V?8I4i;Yx&wQ@Ik zOSPq$w2C^g9UUf>uP(K~J(f0Vs?cY}?k_GimhcnzaoV)!=1coFK-Pyq5xd&LF7W30 zej`RAR5L}!l5ON(z*G2kL`xO)UV2*~=)PWO!dtHnxmyr$Yi)57zIsEu4ZF)_oJiee z=v(h8y0)$iYJqae9JT*azrS+YeJZV-(4cqq3GrJcDn-IL_w_qA14H6&z6aaKvm=T3 z6J{XbWhou}SvwnQP$p|<$y`6gZD-64-}sP>hORGa3o(u~pYn)i#%d0+(OUqCk#l1t_xK#waj-%>lhPh}szA-A?&i@b-t4v2Q{&}9 zvyRbcPWDvO0+TGcVR(*~1Am9z;T0uLjQ1nPZe7~Nl9~DUQdqf9;5fupnO_P@FJ>F{ zB27J|P0(eSH9Z3twVmp<>+=Tm8mi>EQ^mx1$;N6?x>)s8&IS>*?HZ`*xD6wasT^UO z0#LhQ(`LkSq!6K)UFSVKw2a}2$KfE*4^6VL7(MWFa9wSM5X_nYszF(X2gI5H8N!@c zm}UJ%-)KHPTOQrGNy;i;+zf(-+Ff85qrg4~r(4GfhtS^Tc_+x_9{%1NQv4cCc(Bbf zm}Oda`uGRLT5PrkN}AWOWo%Mt2CX05G+fjekl#LnXEo4mz>k9+DnA{5aJ${jJG52! zZuq_(gQC}9qh&C?xNWfXk1rBmVpjJZ#i&JSx7$GT0zslzqz7vO)>xaax2E0H#L=s; zd7vzlb!5YVJ6rdaW(l>}D;C8-hGnsh(I6>wGgv{OvK&vTKjyAecT{NlW#$A{v&y$Z z&P)UW-`n%!b*(Xt((YQ#@TrX=33Czju?S1aPC;ko-KbSp)rY?!msClUxo6jqC$yS7 zn_6jstL?lVreK#;*{kd}T%Vzrk}Xu4JC&Myor}*fE2|k9^B-89RO&AwR>BsK%(Qx5 z`OLyw^}O)ctzpKY7oW^y`oYfLoKAk4A}l`r5e-rE%J#)LW>(oEx6nk!t$j_I9r~u; z;=fj8OXuAFoHJT5*ZAFmTHK z*x2knc*-rNdRO}zb?Ak?9ku{*{U*_Y8ERp|Cx6vgaQS9nnz1<{XY*!Zn$o#O&e>no zM!S~ZhdE4F&Q83kkBu;MQyfDH@+A}GH=kZ? z(9`6D5fQvFf#-($frjm!yF>+B_R!}n?*Hqk^#u=6`4jNm;2={ibavg2qb|Dgd~_jl0lZp zTr^OM#_W{pOByrix78~%nPf0cnPP$buwVP@3td7XIVoc@ii|j9dUNfHKRD}y&`yeZ z47+TrjGKDgsRO%bRl-vO3dO3oi`Lg|4sq%llLAp_?WclRy`gMS?Te^u2+H~jneP_3 zr*vr4SyV@`K*T(JTAK>VFeq^PCIHw%g{eb?ia>%k%5`!z~>+^es zu)INSg=6p!QVx<3z-afNRVWRVWtInlnMms$DfCveNe zvWNG=kFtsWy#9;c(tmr}EE3aw@=(MgmlfEW{Q%fehC}NQ6gRmk&>I1Y;OwM2&IV63 zFNv9eJo;3T3bWtriXZWejuJ5)SHIbc?yAk7-zzPJr%n(yjJf znA1G|n6EQ{ZL33IHJ6TU1FK^sv(L6?S01!Em&-pCf3f+*YU3yGw;@MhHf1lhBY2|; zr!@z!ux;!MjPM>E+-r}*7=#U)X$^O}26NVJzU7FE}D)I16o z8}{2HN?wp?dTY%wKE|>a>lRCzmTJamB$8|Fcq}X11WrBxn?5Q0?-68t9KghM8t%`> zXx6K~hEv9q7*&DsbmeZCl~KGp_=W`m$u#G(W58Nu{Nz}cuu-s_=ACEq%uH6BuH3L1 z7@ZxaZ54z^=V|k{MZHmqB6E2a~Ff98N@e9zh-r)3822Kh4IXz>KD<4pQ3t8p@^uA(RA zt?^dn`*UzPIhmV*|NjopUnFEHO+%*VBsS(WOURJ~sx6`(-wTAc!j*$pdqWVi(bXy3 z&C;;+2{pB~GU?Sz*Tq-}fbX3b7M zZJ(EKNLVyj_^qj= z=RF&8hJH-JT(@7a$LwErnwO78u_1|+-~+zZWCR5l?3~swxu?Re-`bzTCmD|GfUubd z455PgN6A6!kB{6BXl*5P?617!^`Qj?$Wfw*&ZicWC7s&$)w1z|pM4fOeLbBsp2$2)P%xGL1Gp(e12Ekz+_2qAMV0FVE zw14yeHoWI?jIt=lJ(RT`*0L;k|K{}iwOr;v5i;Yz*NLRL4)ED2!^+>Ov?zxfo>SXj zR_ooG&(_%xaw{X{xoUc?S0orPp+BO_zwEhuEtxMYxp0}rmQ4hxo&Y$lLlhXZ9`{T; zhN9~gh}j9mD?f%aFSsLaI>_N2^{;CCDloM@Qgqtj<>qQmEM(_?(P!&^E)ozLs66q1 zzijU+5oRh;hK$AGXyn|6w7=AF*S$8NwR8zui`zL0_Bv|376_2W%X|+%&UWF!fpIR9o(YjJg|Mc^4T!9-?^ZeBCkwXw@3f7{_@u9ihkqX2k+8c>C-9k zcOOm+X zONa24dX%v3lUT@Rz71Z{BbghIrtHIT)6*Y_;TdNaop4EWuE!Pnzqu1&<)H# zCW#2kw81W8JCVyf?mae)ESd<*aIQGmgkGAWYg^>!XuSGO$Ea`gOe;5Pv@h=VJnjRtA@YabBT}``iWjGQ%%Rz|D=A<5 zmNW0VZPXEGxBFTm;gW22?lhOR>8@_3;aoAUM7KfilVY!$Dl)o%9zJogP#odQst=h@E>Rvdxj5H zrngfA!pc|MwWsKS3jFQbRT#k0698b!2>@*1;Nix!zohrD_X!PJltU$U$?_aVRo`tl za;*$3%Y}w^_<-R35;Fvg+>C9^!CRz5vx#+o>G@0LcA7ePcki>wWsk)VM0? zu*s;nDxAGLUaPVAZGi*oB<$G0h85nSH?*o8xIbOe7+)X(p#T|0yS|<3ae^SBkJ;#^ zO`L3dWJr zw<{SIvCoS)#^w!P`@v-w`ym*^HFPZUsNnO6x(~BnWWzp>9ERq)Ler>VhQL$TK!W-L zudrwANDt5z7mywB`VYB&aCM7PtPLmaE&4d^1Dd!8TP;HFv%_nn=02iW%gTY@v($hw zlOxUv$BpwDd#b_wV|pikg-gpA=KOYRgj%o~pE5C5>!%Lx-!^Mw3!s46}6SvfTJ3tJ4 zan>_}*yI$_scgyTG>@=9nZqF!vS@g~VZDElr(a~2)E6Z4-VrQ)?@~b1fae%u2Ch0pIm!MhR zCO^l^WDUhdPs5(W@2s-zSU%K(jw4%@g_4R4jL27&l0;N(IgZ((i~T{27F4EDvTQky z8{k&blnuGCDw50z?y8Uz;DV^5Z#$_PGiwesFfoh4&F6~2EoF~kxocMc`gi6?Mi&fz zl8WL_uM6*8c^jwfk%5I#e9llVo_;_RE4YotPhz_Q>TjiP_FP0AL61mm95=Lj9p4z% z@IV^yggl|A@_!n!gG{(U=;6b~PPly2^EwzF^jeL^f5K;cLj8-N&J9j)8bk2y0r3=UFPESfU=6C?vNLctSg3CyBH5drE$7s)uUz z<;iTm0y(P0u$%ILFrCT@V=-rnUac%tTD9BzK~_iI__3QvGKg z$LU1pBzOcgy+=UPYYH^IQ$W)j1~k2c8qyETY+OTz+s8bJDHWMND*?f7&v+4**XwAW zLBNh={2aUb9jn=|qnwCLzc^Ci$Us&QcnmXlL3142`W@-~Jw!2m{oaZUJz;9vr%QsZZk^V{7Q-r_`^*85^;=kmVKHxi$N{UL*ApiA7uX zu*~mZo-L7f)m{h+1suXX0`6@ml{HmGFI<2_x5c_gUbCKxiplP3zIuycDvW!Twt|*J zY7dh1N%SsOU2RKRj3tfnXv?aDZ=2T1x8R!^8e}rtRR^$}ah%te+$ngl6IXa{(+;?9 z9qe4!_|A6>P3(PpD;DKq-9RJFA5(oN-p;jRcqtb;a+u#7vH>*G=PGRm?A7JGhAk!B z4np(joyj%bO}BV%)VaMl9qrTGRbEG$)Vki52W9fS{w=qlok#ON&)3X3HZ{ba86R2eab`n@ zpD$LP#!ozNvR3=gprRYU?3yNh#5Xm!Jokmut<@27k(d+r2cH~K%W6}3Wg zU1R;+VX$yX6JlO!0z8$V;PT2CgYtDSAwI**V)5ChK4I|@b?lmUJiG4u=Tbc>5Rzd_uaKbB0lae|`5^PZP}<^Q(JE4f5vqGG4JbK?|Z><*UKLdhX|XhuorYtj}AOPtrYYq!4A3&w(vU- zsGFNY!dKlRluF>{$t-}{byy(!!OddX1+Ut;b9LVw4t@(VrBe%|`=l~b?F_!J z#f0i}X9Uz!Zwh)0YZ7Hp{mfP~(|wT_!03Fqx*>_4inOm-^x2<7*qqAYn1JZE>#MLt zoVQ%+Gsl)`#cO|OY(>Y0ftoy%{r*yFJJa#EzG*iso7(s_|7cI!Cii>F3%1=2 z{;023{L2n>pS19o#l5cvPiCZ9DG5{}+~;!!;_0JJ@m@pfPn|72q{X)_koHl!yv+06 zCD?k*T+DBOs(omSOnX#=POPT@ReLC$pc7 zS`D?~EhlKYZ(XG%K1+LC3$a7T0LdN)@N>)77uITh8?w9ifNoH}@dK@I!Wi!~OO7yc z8yr;!9&`d@|A18AX;K|wkh0xD|JZCdXibx`q&upQpJ?^JZi1S(;4$L}mrh?24>C^s0x3+yFP>DFOrC()<3-xlo z;ws>)(XO#k5#+(IP~_6C@ejIKq*QRu6j@`Ql5GdI@#!qdI0;{Qoe1jf?+kb+&xJu zfs=R!qw%#pZOqktr$MU++n~Z2NKI#bV1I1*|5igG4$?s(61E5Y)<(qVcY%4oxZDOU zYV8@HrsU4zM&i!qR@>r6!W-g%Z|X3FYB0g4JNG#6WnB=8(~iNLsJ@FcaUB7aaPf#| zaJ$Sbc!0}y;BzAZi{CkH!G%k(;$Pbv><7(GF!@MwQ#5nWsj1%^*<612C=Z%hus^f8 zfEPcJ{ZHrZt-Vn7PL9HcMW5wiV0S<5)1aK9Urm?rOBNqy`u;9t6!5_pJOawpZLaHS zM0@F=;CZ<$<`gqavG=`0|K5LFxPa$Y{H4jTIp*e+^`#=NQ7R~oQMm| zeD+L5<4-j|>`A&HZ3Z10l@SJM@O4yCTy{KKJ#~Vhhv3`~4RMY8##9&Yo;auP4RL>a zY>7@P(+8qfzJ=0NmjOaeN;x_+vXA^Gof`ss%aEXw747}zs+Yl%1f4?W3T_1R1YP_U zpr_?DPMw))jZ`Uu@3&(G?Lrj(RLjAhU`g0-OjXZ%tV*qQI{<&I+2>!MTJ2TnGtE`2 zHd=ws2uUXpo5JUwNY9*XRD>%1#gXrHd^?hd_B29Ek?nK<60M6H_4!Hr9HhM~l#a@y z%Snms%V)DX76X}<@2!*X{O-)RB=-uacWK^15L2-1wBidshBsqfHD1B1r~V0Zvcg=6 zHl0HxjKLFl9c3DqeFI-log?58Q+_%(t4uh!BujNx8>4Z=F_((ZO%T{vMo&uE@A|Y!rG0~ z9G1F2j1+u~G~V_&irGJ^Qm!?T_sJZY5}|2=@t#ow`=kcgo0RX>k2G z$F}&xeo7^ot=pGM%{CbS^}D2PcVbFEKbUU+ES_+Zr`XwP$pdU52gJepgUKxQ&1)!ZXc~Z5I3zXMQ#ltSa8GoI}CMc-SXpSzT3py>`mP*x$(WViy?z*;3eVNTA2Jfc>@3MJAnQGUx z#4~iqxawAF)+Lg|eUIL(ms%X&OIDk_N!T_}PU_2$YRdwgy$0rWt+ebzljt)Y_MQ^r z+vxr=g=54387#Px75lsA%!0k`yMpK<{MZVXPRfs-XoHBzVQeLp_lLJJi@)=l3=-oI zg^gN_u&FqbvKzdfnrGRXMb^f21Pl@n0rKUpn8hCUkxDf-@l&j#eAvqLHu0yRg@0u* zS$kZW4ZiR3k9EyV)~mC!W6Vih7zoJn5n~)Yv|3@J$nEoX?<-bwJNXPnrrjF^q#`fSPbGU7uI^d?Mhp`FNhz&HcP3vF`cYN{q%qE}|t{kJJ1(Fps6Q@nm@a zT9j*ZO!;^@n}5sA`Mecc?zQFnxCJ-fuU%;+Vt<^!lJ#YUobLgGSBk56@lF104IlTq zYr4_)bh&mN;mChPIsIRR*SjM3@a$ZO_fcKM_Mqiumfe~tH8WnH=i3~>``8Y6vz)v( zeYiUICU6&XPPXsDYoTo6-wsMRr=)#M$UVDa6%%u*Ff&J=#ABK_JmA-2*!W>O)t8B< zt+$`zq8MwR!@R6`sYoD}4GG0ZCsU+5!s&!FO%B#&k_aJv-vB}jxZfE_+ww*E(l#(9 zC@HFZIl2o)zxwblvzJfOpNlZ{7!my+esQ0}haL&opL!~CrIgW8(ZzPaQe zEJtNQ5^cm0Uq>gY zSuWVaj+|!G=zM&tz0VsXaeLk5;(QE+*MW%y-wt}7{nMiqX-%XJ*F6s@4JSMewWyfR z(vQ=f(u&62J?(T;yO@W)o_X-c=v;{I;z|p8=nHVCXbibUQif0-bLs^evbC&0Zjz*9 z^TnByc#JWO(K?clkIJ6s(B*?mO3$4&gQm6*lRB|+wsyK&Bp^~@nFjL8B?ERWP*cHA zC!OffWv&C`Um#^u_}d1C7Od%5TRz`evY|x#XJY7g`0kIXWkT{_zWo*e8?l)GT`@j# zV8a+etv5AXk!n21j?+P0u`btzoF~p439sWgnLmXd8ZofJHYnVoDHeNQxK|l1E@Ft& z1X!!yLfTqD0Rxl|K@PIa17^y3(+JbN$&fxsA^g)hDV9YAx@Gx=igRCe&rY|x=fVg~ zyr`=olAVMcO2=*kGU6QI^_81{M7ekraF?xD=&2+$na=qM^M7fQ&NTzY6u^r zZa-1_RuEOGkbDVn+-5Vg!Bfl$vm8U!mv$${E#g5|yWl9|nKfz>)0PI?(?e@0;hC+Z zlx5)_Oe#qt$Hr#>05>*DO{CnPqX4kLz3Y=1xA&kYZY-8#g-U;kHlyJ(yPg^Ez`)jH*v)LH$bWSi8n#H&UnlJ#@I z=o#U1(t~blBKOa3z?c~61<=a#%l%eH?{vw8t{id-@U=G5hqVvow8LR(0YnWHq}wOJ z!0pvWp%YL7wI7h~jVo$XTfT!H)H;>mrc5Rc)H|mP&AF!}N7>4-`s8JKi9(305JBJDz{G~r&&RdaiLR-&i{Y4v6uR2W0{_b~q9jwMNW^>C36;Hz zPruY?{@qb(Dp14cUO;=VM!F2;#a&{kz+EDlB8gBHhIo9D5?%6$Qn`RbwoEOEcZQ+Z zAfI{rJ}bhQm-x6c&G;-UqWCV0YTQUBnIhVeij&@v%3SPFsa-5x@u9BlL}*DsnkA{; zLSnA6z=UqY%_5?3qVk8(29X7DdTb=Ie0N!2VW9GH}tntXo;D++d2CE;xX(lLx zgQQaq{tA7g8UG$IHW!{3QHhF%6$vI#c9)%}#GRcNg3m25x(ps(5U8g@O?~{m0U9ps zC5XN;KUjT`te=0ED>cKCRmgaDP|k>=#-o3RWXO1h9In)ufC=r;IG08fno9DeT2xNG zSDHFttUfre-ieqZg*8$ruS#Q11Lg zK~ckB;!2IU^3;nsCPu;sUfqZEtFT1$%lSm~t&OlNq`{&sPTR}i*6LN*kk6-3CvzD?vQ*O^A}Q%DikjION!wx(lGM(RpY8yaoele2WLsKbGW-QlI+AQoxk5}Ys zqe~~rku*7IGin!`9CY-O7zt7b9vI`$Wb{4ftZ>nO?E!~)y^?2%hD{F=;8y*j_bq?l z;^Z*lrPPhCiOjJvm~hpJ{>Xw*QsL1q{1g&OwC8^Qj-BMD)&Q-fEvyrEwP zz+ruwtmul+>=cze=#E%VURsUhrCGZ7#gOR0=k*cH%JD6X*|OfuMB1;h_Q&|*eOz%L ziNzu~3!G)WmA>@%sS~2{!}~bnGu+f-R7;ci+8=~bm6S)pte(vM8SQ-fle|nKh}vKx zq!P*^oEsDo8SOV{p_I(j&1V4l%4NKfN_AZB+8>c7i{Q}X@TtaAhXuv@R{HtUAU!ib z##L60PU7(E^<)s$n`P|Pxn%7@y&Nf@D$SSoSEG;nvbnFd|) zMol<2rG)FXQ*q60mXC-~B#zpQ9UG{=D_ebR=2{zKF z1(t9j7Pg6(IQ$Q<1$uiyF5uQA92DMUlX0dQ55y#erp8m!&x2l*=#?##wn3%V6P)#7 z0?u4!l5nltXsfWZNiNj0dP+gt8Q`h=ge<;#@s=lZ%QV$d>ww!$O;%3h8oJk(l9;dU z!1SG#$8^5lXoTskGt+JAu#p&n=g46L6wtTp5gZUf)pBS=lj+EmQpJfSdE^~RlUM}5 zk(4y*KIGViH{^IpL49U8@8)8uQj)ZQJ3CR(R+KK=5QC|4r|1}d$XHQdzq=ZLbe@r% zuie0uLhGphed-t1Dl4Vo3h1Od-)xq4B2e=$pyncYYss-^vm#DzQe%gf2m()FA7P|~ zZ@-oIR||_OH4S?EGm^s1q1>uC)t{1k?`={Xf0EA|e;4>Zhf4vw+tbs-TPk9>+MeUI z+*X}3e)MuAHl&<9a+{TW+7tcN4}lNovQww0iVtUVP`4d(+q8Z73h3W1eT|{fFsFG= z9uCk2RwUSPKE;eFl)#_Vf;u0aSv6a+*|bynSv8!@Vas^|5>4Pa%2gGV6=2CaMx?1X z$U26ZlpVHC7_8KhL_&1btK}sReZ!leRgX}jkW}iuZ6C{{!Jk#@wYM1!2p;~1Z)^#= zWJRmzN-4wg-7c@rrzM7fXKe8`Oo@M&sYU4(fk=mzkw0I<3IqYDqyyszCTy&-?dGT< z(MkP_1eQB0h$WTreZo@J->AYiDTd+$eUkn(2BScC=Zm*773WOWX@)Lr(W(Rj0^UPu033VXZqP`iUnvwR#GP@+>4#Sw9s&N2q zdx~Z~gu_;azenU)T$io&HLv(VdbQM}_MI*027dO&qnX$85+dmiE?hb8P9IeI{JO4W)i2hn+Iu|7G+T>!JLVB_mpDxu42W_J)bg3S}e_uqSg z1Zz}5oq7{+!>9U@e>P(x);D*M_Pott5xlQqS#_=tz;&xbNRK78!?kbQrBw^pV>UWq z!}N=QQ>da<38-qora;pzrtsaAIcp{BRH&9D;DMdBGzy{Ul~P z$c=J&5Z`Dy0>0x4z{TW4h|L6$nECU=fos@-{}UC2i^+o^Y20?leg95T!zhQ}*B7Ik z%d3&#m#FN2XY>>$OO$2*_=E@yG+x#h%3687!;XOFbqfc<>~%X12Ir;L-aFz}vq$`; zzC93%&ihb1l+IE_tni9kpgLSitnDP1riW+vLCRl#{7dVA&7WLAtv0cjfIqYtcmG#3 zvwy`!m>`VT5CQ@E@*igdJabuiil5Yq<48l41+Z^bFOR$?-jPvD$XKy?3OHtnqa&?x zl-=B#3U;iV4^!Z9<40DAYL8CHyC0)44yI=vrIAQi_=Dr1ULpj(&^3Pax7CcIn!T9r zfo=gh``P;7QCzrcnDAHdlIyirF*ScErnmPB1Aey2>?*G&wx-0eelrRSK$jO}7^3=q zUbhP2395yk3TY0K*+T2&3HqC&oZCddNu0pIPdOPxDSt!^!owjuO>`9%^)V*7%-C-i zRX(U|@!f-fyhmiHg#bNv+i*7{COv$b~X>bq|iO?c%j(;2snQLHbhL`UoF0b9n zFufv~X=!ysu)l$Zoit8@7NfktieHp{{X%VNo{>ZFtoO!PcT#_ts|IxY3-FJ zsaIzFbsT9D--3q{DU$4WwheXKUQT6R*YU5row(Z&n|+KTEjpUekgy(IFZ;g6b|+?~ zVjSf}I+@ftJNtGj300X?4M%$qI+0S9#7ldMUr%X51YJo*cap68xMen7v@p>)RC8UE z9k@TrBb=@zC_Q{mm@Q8?qxu7`Pq_z;J*M@*OGrz?e>|cC(trB+QM4d8v0WWI>*lc z2y0syF|SN_U=AqmcQ}eEF9xkxed(4eFE{}M)88PT}WdkBckQN|Mz_B;sO4tq% zF57sNNiC>gD?;%)mMI@L)>F`_Mzh0T70FIDnKNwpxgsc9Yzp z1@F#Aay$2ghNJggxFXUj)?GVU+7#*eTWgB*Sk%6D{OWYzQie_-D118R%(H^*+q^UF z@(!%$q6XXUIrs%dOSeh(OoLWp1WqxFKm(nE1h|F?@$}+i7{u`c|1yY+VHOF&&oM%t zKnE5vicjb7w8%ZP3GLL?kkUB4EB7SWCCAhO-8rDuWe7tE{LL69hB;^mze@yZKS;<1 zZ!kg_gE2Rn_N<;y~5N6E{)9Z`&`LnKu za-#BeRY$Q^e8!)kS89f6sY;9VIBrtKVs%n()<)@P$Lh|7@c~y-5s0=e&Xa_5Q_s11 zp$2e5j|$^go}?un;#?JE47?oS4_LR<@nvRV^+|a7vX4g@<(l!2t}rcE(uG5BVTB|* zu%iTL-HHun!2{wZ#f`N&&DAPZYh|pQRkEu+cFmiO4_oHWmk-OQx57ti# zwD)Y3f;(EpVJDlIi%GR#v@Mp%_*?6i&WcZQbXaB+oBwK*^HnNG*;!O|J^YUu>@Iaz#q~_9~vnvvky%+U0 zLbMjMb|sa^N#V`#;EHLrS~xCt(NaCVNO*a0@gV%M5FVHi)^NIiHzhkxCsXC#9N}#l zfAD!U9qtI6$Po0|yoRJdpaj`3+;Z@9FlDPffg1g2q^VPlYZdr$+ur# zCl^aIeCPhnEt5IE4Sv{hHP)FG-hjMYTJ!ccl>4pi+cXYrRzHYAxh>WW@2{8eq=>)< zm|gSYLrRC=JB0j=o4wY!AUR~RrSjg*^A6qSck7j>qDmy8O`)B)N4N1otUZS&3cDJ5 z(>;EJJ?DmcSm&K z8@-`$Jm^yHp|gi1eNbuJPkOgb^LJMP9-qn75RsA4oHkdihJ)Xdb*Ujfm6b)_OmXIq zK%F$U+}mSyh~XZ$3!8Qv6)K(3tx9J&YZSc)(Y`)PBaL+Fh9b-d-eo)@hzKZak!LPp z?7^n_uraH=0e=A+o|F8Jbc^tCG*?*fmJ4b%+dRI9S-jU%+g`kxoMe6kQ!>CUy2OdL zDqbxgc-<+`%b7jV;WvY%_}2R6zo|(S1XNRDdXM6Rlc<-Y*Ao{$QygX&%8rn|Il2jV z=BddrR(BP~JNsz+rS#mnIj!A)Za}iK>58;uCAtY)ax8sF65Z7Qa8c3M%ke73ITM{P za!mOPMS1q4!!)^II*fB>)s-ctPMRO~ta}h&)H%GF3+UH2P6g`r+tij4kNez-JXeA2LwuSI* z3oUm}C5TV8_wkn8ah`HjWXf!Ew+|OEeb`lqVIJWQHu1)!8l6-O(@7N6c_8Jh^hpoBhauiF04_~rn{8_;B>uBNaw5a6%{Pk*vb@tum zQ~N2iN9tyhCtQ}hr<=n2QDz*k)7~)Sy`VxzD|`jNl@gcFF7eLOLxs(2X1O9HPx8Y4 z%o<{E<81uv8?pyzz@cH+z}m6juB6{%mPGgZz-LU+L7VOG4Sr^~YaHL2-#mX`j*$_a zS@c{8K1#n2>E4&cKwey;c3-kGGPQ>CR19N2rTtBnpFRatUrA-#=IZFW_v8?IwH1BQ zBBtH?)wT_u82~Bs;M@%x#Npa*rC7TwVNPY8D#pXd?MAW}#(BaNtUik|LDbWAr`nyA zNvDOb?S}PXx7FH|emlC9)!k&}BOe}L2-2Oc=Tt4YuKeknn{k_;@k0-~<0yd&+^ORR zpEZn}XDf>wxA8G!7G~dzqP7S^t;W-s}w< z+_t)rt2atFJpQJKN#a^)J#Lq3#~44J-pd=nH%tGGPClf#kDsS0M!)v7aIu>gq+Pz$ z&xs@75z6rOC@*CDgH8Z!rEPYv2l~&3zd5Z!et|Q7y!a0AeI@u1d}3k>lWBH1{_LiP zsM~}li}w9Gx-#edyldGh?U8)F*a{S7a*`;v+bw@}_CrbpKg~j|HL+;nm3RjpvG;L3 zk0H4q2S=>X{>3$;1|gxG4n6-daLr77)Kl{2iy(}o{yWKH@1y3#RCpmp5oEx@Or6Q9 zbBMo4&dB!@&{T&6E=)-_0tb7;T*WcUZ;k~kku`3yfXd2~$VLA?Z;$o5QyCyidvx~! zB2O$Z{Mu6x71JY=nVpLIVpyXtrGuJrMp~p(ueC(kORL0=HB63`B+GPfODlw*T*qTB zih9Tz$TuA;5KMeOYxoRkI3F-a@5x$r)^Pn}h}%%sqX!<&Yw-@{ zoXXt5>r6dKWv6`cM4wP9r5hm)dM)<#%lMfK2?-*Cn0Ckk#%Sl12$EEV zTqZ9geXs)Bzpc)sMVL^c8Z)6AVH+z@-Vq_EJd1L5;fPELCuZz78OD8Bt$HM@HxB0C z2-9fcILqo&RN&04FXvw$Oz>~NEC_Q&B)YWtrC`!gz#Q=k_z?;&tuRs{lLZX^NBasU$^6F&82WJl&0nei!US^b&6B7^ji2d$qQdP_%+_N|2_%;R=x!Dd9nGvong+ zF|^&dR7)VTG{H>8AhcLj>g3xi%wsxx6A>hl^pW+pNoUZ*T8(){e)jL?feL`ba~?^x zO-y}NQJxe$s9Gv5e>0R6Ho-_tE=?-JV3w>kHC*{NDHoImOv0!t8ig0xB0DdZM<4cNi!=MHj(zWP_d6-fq5sYs^O@j##tUT5{5i#l$p&=xEe zzIdtw_2{?c#(aDTDFDiLsSe8MVNj&h(g$l9mQWOBzY#z6p*6j|E#}>XA_vC5e$hP& z>AFgd$B}yR&D8F{0?#Q!l(^!O3F|-H)u}7~l3n7$g(t$b zG8=3}PNAA4qR2I;sM!_R?<$Zt|B|3#kwM!=4$DCMX)XKfv2?T6D|66|nJJYp?sQ(s zrdeJa8PuAtklEezc4|L+lsnP&$CcD(dgs3aTfje5`8hU*FJ&NgI=ry0n9^;Le$Q_6 zl4jW_VPWszP)>3!jao9Zu`YMBWFg-Sc)7UtqAMlw5W9~##+&6Xa237^+eGgAS76Ip zA0xmnH)T=;0{Tpoy=DB+K!ee+!GvywD2Wa35Cs&|dF#<-R7(PM$L#E2oN@HfO^Z@@ z%C=QXhN4)Ye#0(1YlaDYD%c733T>0JQ_-#TT4pD^pF7y~Ujc5|+?STB1bWjHUTipNU41e_?Es+-up5{tdRO#u6?VNk*p! zi)j^ZJ;E=c$+fbBNnG5sZp}k$aqncv=B#ZiW(*Gu=on>ouS91t|F#`F`M-1izkCTT zQr&WPYlYo8Ros758;wI>6Y9_9bQKprP8>Bha=UR8tzx`KcG!WU!!yEDX${imQ>p8> zEAUO2PE6#8S3k@%~)MB*~7luC_ct+c|2@R|qKx0Arub2{uVNiH2VAE0?+uiST$BMVP`ggnW>(BKc9DUueRn(`yn~I*UE&y6*EZF z=}kR6eQq5tn6hBB7(niE=^iBXRlPKcf1vG)$oy>m(C&OSzE^ory8BJMi0HoR{;@tR zM$djVmc-T+aOj;|{ld}={$U4ZtLd#e@Z_rB{~NK{y%?C5TC>xuvdJwKS>o@siWH2~ zc~eflTj$?CDA=pr?bD)ILyW2^OYONMy0t9jfuM{yQmLn&l3Zlt^M*RoW6@$Zh{ocADB3thdZ1{L$=dzkK#MpT(6WDqEQr%n9ubv=(!~+0#{hD z%~jjUb%ejGh5w*skGkh*b#){2&~mo;_hZ$I(5=}_jFVoFRc*`dhKdBZ^XmzhE2|x<%Fdi7D3;xo+OrM$aUNTvHjmL|0O<+b%VM7U5~+axxwVvXl?HY=X5 z$#$_CQD$@x!E>tMz_g2=4V5-R@*Vrsk6T&6z&?nZX7YF%LeGa z9Enu4MfR6|XyUSHBdJ379Zv4q3gXpvxhM+3|axdydI>$%B@y2N?E?W@QSj>!8 zD9K-kXO9cXjh=5hk>;Z{d|>+7H`~ej0j3C zD!JPk6Vj{68dw0+*aNf8IU6|r6A=X_jfbUIFm|+cb}%${B;?`wM<#niMPnyI&3`7b zr&ls|b0VbwWvy>&EchR_(0|mwv|;H*+?>P|o&J&99@tcjneZQ}=@oc^AK;h-ZQTep z8Gry20|Oy53-D+$2U};me;oNg#`Dij;AjZxl^pbK9PRWSjBO0vVd;PUGZ)@Jbo@t- zdPc^7S+#2q%S6Y_!pzPJ)C|=9A2KaF6CEodEe9(rp`kS_9Va_06CooZ9VgHQBvcRs z3jYc?m;%SbOlax|%gji}#>T=3^eCCxSP40p={WwW8JND$!5G#ARvz|$r=R&B-P#&h z!2aiX{Qt!(BO}}YS6-R^%Rl~q;FXb)ESr2OR@5 zCj%QZ;lE|}UlxV`JHMWhlY!;G#_g7Mp{Z%R-j3|ERFih}P5)2=;2-#n+$Qme6mr$I zN_L|2T5Bv4;4q=c~oj zb*&2+IEi@ub8&Wt;G1)p6`Mn9Q*6OWlR`KkEi|>ZS~yV<(niV!6|y3CD`}} zvO1r@hPbcZ>WWClUrIKkv*QYSY)h6v&n>Owq3`i6h9yc8&Ru+^z=RN?no=Dl50?fd zAw^Jerw9uZ>?n-0Pdnc9CP~DfG7pIp^p_or3UEOmUc4iv(E-JZUz_h=;%P%~y5c}I zB*cs$f8&{HewM}zMM~UP1+?uMp+bfAr!_*v5;q#-E_VP{Yv+}}{LoB!IhqoWXWh#&JnWmGE6N2v&z%121i zzs4I@U&yx*SMjb1xeCt*zBA5J=qtF@4bBg27?)aH@XI7t6u86e2W@uU=xN_lk@l^z z^9_EZUe9G*=W~?;3lbp=z!t7$`CIOf=A*zH+Hx6_b!g7Ph@4|*KujO?5QL06f@E0E zK~n~fJf(ixA4Z;(qCoE==tCJBpo~QleYG$r)k;rfBH1VTV2HeH7&sk>L~S7M?Mo1i zBrDyGvb%(S>m2;fr%j{_b3+ZxPW@@H{n;ACAt9clg~bvZRDE4FVZz|`ShU-yM~oqY zkq-+hf}oIo?too`4N zSnS@ugX6^wRS*oe%AH$2`QhEj7A9!4g3=O(E8{|w0l`0BhcVOTTfs@VMSlTbrm*al zPx|RbS4@mFaY}d)*+9=4Ryt#`3tmJOko}fECo)_&owAAv%{)zs9u)uWgkLG9(avN8 zKaLd)r`KkRDXKJ)R})-}jKYjUt85*_zSbHtD!)PYV=tmE{%2^Rq%Xr7`Ub@s9vbba z3k+qja#^o&`#5ggt0#-8dX1X>rT>)D3Vlu1wZ+lr;0nEd0RzXjaczQ#{maSRmiGU} z-CKayktA880$a??%(j>rEsI%}#mvmi%uE(DSj=cKGg~ZK%*^zzy)!%A)9&7#oq5yy z@0a(gbg8m3GBP9boXCo~JLD7p^=&|=C25ofGVPBe(4U6e!uvmL zaL0b^B15M!kxny4Zmr;6jt^asjxjmG&L?vRY#U_hx;!wETQze-r{MYQ_vzOE2#?ok z>rqthR2}rjr@j}Brg)3X343kSSS4VId>(t*j1~}9sJv7|eZ0*?1G17%4o+)wF=XRO ztEhWhsftG_vkxiW8+hcJMyXPDa+L{Ne(oCD`sG3u&w6RG^X$dxK({A65;{X;^;m}% zJuDTkW!b)LcLBxWD_0h`<3%|_z-z$$09ii-ydi-X3xQWbDx+#)V9HbTl97IBvUitS zZc3XdGm?@S`Ao>#mpOWQnEy@^Pvpfgzuex{VA0D`c!KDZ9V|RD?U-5c;n=0PLJ5a# z%yb2zIL*u9fH$5cAhOPQg# z^c%@rG~ipFt$bDCw^PARb#HiQobz3N;t~A#SV=J*)FEtDnG=90Lmp30F}p7Q}Do4W|D!8vg%_ zaOoL;m5g06j2o^~2FBMhqmvPd(0Sxx50WF%AC!PXFjS$T%`Y2D;ai8)CHtG)nbf6` zqD!R3ISp1dI5!>t$=tEDyx|R6%2u(FPh7=wuLsAS*U&VOr3Cx-!pRzy6eVkj8n5Zq zw9-C?H%}n#;C|>~&g{j^f2*zUD`9*Dzw(rN){aXo>;@zy3rMx}n_Trwzeq3t@1DM) z{t8NbM+H6t6yk?Y{02ezANS8+00hQg%s=0k?*NeE{f`43!QZfeAN31a{$$C|#QMKw zD*k5$!So9t<#z?~{evGB{Ras06OH)=0wrv3p=)PsY4JmIn4oBdEX}ozExrRk^nlq) zPTRsz|F19pist+Rba167(09@`BCxgBasNp@zk#s+6K?{*Mv~gLrhfyIzQ6i`CGneC z8EFIX9l&(?y`Q0I7399R=C8OEK>fcPRp#%F{FQb6&8canEG_f_DAZqn@e8BzAH(D~ zzxYo?=qDHReUSZ!UjOxczu2?>?;Umk;V`ii03JWY^By3IAJPDb>OC_(0pRiDO8;(X zG7Hg`Kd(8p;fJo#bAXG5obT8=U#Y}p7)b1yj0N196~fCvZ| z9WgnR(YX@>F^CUShDx5#XP;Bb+C1=9Uc`JEtyMZ0afFKY}&2Due3f60bGNy>);|UCB$l#vBZ?-0+@)7TLWm_ur z-e=<>O&jzGLN!i*pv57^jCUXG%+r&?w8;|<+7z+b!%)I{EtcnSt;|ptg8+onqeYsR zV26^W!3D>nn=nM)d?}C>zwXCl6~tB<>`#WGgN3d4_H92n3}iuB5hE5fqMab!r|ff` zlGNer;G)=&2{z(BDHq{t;9URI@M2|jEc%7KZ8lNG62<7^pu_ zGD9f;28O1bgt7xQ} zRHkgcdgWI=exea;ha}JU`tvl+tI#(z}T81&J(MAKmGOy z&oxKGB`o4TW&DxtG4T$Du<2}$% zDgdMCBGFm_Ur-`?8&7trm;s6oaZ_Y(nVG0a3g*|0eNikMb&T6tDR_0US17sgZG31+8yb} z7!hL%_C*Q5e5~I4ID#ihnwj!~VUiGco&;q!R>bZk3g@?+c*c=U-kCbU9iEHg7Dnl1 zn!!9nbi@dznzsm`n~2oo^o?%{uymjwEX{A{#x{;`v|UbV9KUw&#CAG8C`UK0f#)RhCGFeL=x_SrvPxzpZ!#mjDssCl_tQrmYJ_3Y|;JG(G*$%4WM;4Qjj1KS&;R zemJs){p`5nfrOzMXc5+`k)e7ZN9^JKO7e+LW?HGEz@FB`KzY|Vg;~mU0G?H~ z0f&(kRY`?;Bs1%eK`~UR{L#a7DSGLGymq4KhQvd#25v zQJ+7_9a{Glf;(gnu(hkFs2s{pG6P3>9jv@TiMS4{ap~DzX_!grkl&%aj!2n3y82V4 zLGM9hEa`1TPssh+11AE$JR*uSM317Wx6@JGtK3zih5d<72&}kOS{Lyc2Ie(EwCD@W z8Rl8q5b3BLTA8+|c8P~E9qI&R<5Nj~%Oa@nWiq6ZWqjXOr=XwwJVv+tYeh7xlP^A%WG*6 z&ET7pQ+bzzf;F`{JeiPQW554oCO}orhf{@UKX8()L{l{&kDU5>dM;r0!%ix`JAQH3 z5ci6^kIF-Mz93>vrzO6Rl)^=w4ohoCX)DUErAo?Ys{wqtf`HXw4WVJKe zdYh2j^E*?cXi34Qa|Ot4wD)zIE>&K@*wdr-M&AeuT4SLxXwq zc`Qz+o%un)8$o=V&NQ=J|1{)oyk7BS{(EQeZc-y~C!(nYH+iqutf2 zS-D}a9!aeb_f0Jz)6veySAehhx63nMK1$tfE7`HOp%cctBX1QQpML{cYt@-?meTv~J4r2#PTAmC}_^t|s18XOE#&&U&c<0?I{S<$d(H7KBQR+ga* zQ|boAe>nFO9T4_Mq$?qf zw?og{M4pv=5~$u2=R_4)lTkE_KU_e0VY>7Wt|aT;Z$yfPZ!uaG@k#EzR@Dri2k$Q} zH&+nWs|3B~fW)ZWy4lauH$=yFQ=?TPwh>m_Z4XLF$!AEqRD|QLOVv-43J$&3X?4LF zhB(|e-Yw~ZNCTF1&a6AU`EK#J20-Q@s!3#xDTT%LvZ?VF? zh4AxKh)M9}^t6dnQepg~xJ~>%V#L9aZUSYokuq*s^9f(EtdDjV04MuM^Ht_#ABF3Y z?5psTaVE!}XAAZla1Bmg;U>qx$~W_)snCYWF;kOVGYvCSLbxJOFsnkNkhp|6SX@n` zLnT1cf+_`+&Y|d>0#A(izR8ss0GrFDiy0)D>t>#kP>ogFSx5uR|G=St^|Xh=>DbEX z?Hra^r(5?C{vIq+JjaAY!NT&4TM;SI)+~O4yvEiLm0PHY)E7NdA;Nrs)SsBDC^F&s z#+nbc9HUVtM~R=a_q}^2#DtODmN)zD`6it#9(eAXZ?T92y7YyO4EkqkFeVm$Hs>E< zicjG5#Y2ZeBd|+vla_(zqu4|{YVbQJlkx$1JSCSnbwAx#(&ZQRRntp?9)uak@mWeZ zy<;Q|Cpw~%&dyj&va8u0&K)URjGb*>S6>)165)I#jIelQmM(m7S|6BDbYbCBrP0OW z9@i8`Hb?X^bydY|b~2$LXs#H;?I|jdmgG z@N0BomdlB~3+r-@pl#T} z@7B}c6R4FB7e$$oQV;I$o{1xqhi7y*`#JL8N8m4hF%iSOKxxaTudg9sl+dIU&x=K*d*BPvb%(e$qGp`MgpYPt1x`svI|neNYSGIOG`r79IiDCWUM%>wd z!QKJr3~|oybjG4>$gt0t;e*N5tI;MWAX)O)2T%McR00A#B;>i_9mzAo6Qg~6rs-7T zDs-q^Rswt7i`5j>vMO;H)AKj!jzKKLIIhpS3o=*fi?8!0TScHhz+hN`wix4}`~+qC z6QT59$K3sof#N>`$LN{pf5{gqhE>9K(!mHhdiIQnU~mR+Y(fJV4R}780F$hgn%U;{4FUk%Jl3M|~*B)@tp1Ffr& zvcn|GhexfWB0|bc9x+8XnC#zgRWjn^)EX7#P#70^-Ke@kfNFH-3(t$)x+_W?e)$@a z?Cs@Gy5dj7?0*fNGP4i>9)CrDe-Rh?KklP{jMV^C{!>;15YhLakm$b`fd2ac(SKGD z{~A_<`JZANen|88*anvWnr-+4?tu9Rk?})lf8h=Qu?K%r*Zl|d{x`mWo#2PqzH4uC(Jq?ms}aXF{K{kb6kEdRITEB;>z0RY6l z|7kk@>$w7;5I=O{U(PfBH$wmbmH*UOvi!gA+5N?9_}3UqKw$shY0N*uhX0V}?;6YB z_$B|)ssCna{%S0LW7q#(8#eyVSOR4BLu@~cB^v=CWbG$JJHXuhusHv^0q{q&Kl85~ z`rk8_2HOB*IsCDMG(&uKc^Zhy!dnst=zSG}>~F0l>u)@rf0wX-W-ZzN)d6$#bPT^- z0ZE2-K>6|^2%g-9q`ofLI2Cwi{n;|`jKPMNhm=X%G-RDH*Org0F^7uWEVsjyJg^er5d@wuT3=O^Jv ztbdyK_wSMM&sLcTf{vd4h9nWqB#F72Ty&!p_I}<(^E#&%Ca%zHrRVL=3!(6)R$Mj% z;)h=Rbl&(Mje~z|l?kZ)r-l;{lKppv;{Uk`;eTQ{*?uo}j`cSl?>}PQen|884Cjw6 zk$)W1_6Ms>*6*tPAKLR5!^!%m`8JD83Hhz!lMYHKbc8>;ZXfi#Y{{LzX~fpQkRXyZiMx?`M&wFAP9+4 zmQR)-(e9-2o!2$Dxjc$1HOEh2TL-J~o_EXVCta3-Yec;gwYeV8kWj9)r0PW5JzIXx z)*=;;cZpj;*H=U9%e2;a=c`>~8E_}*1TawbRVM`#64;(j?ZjZkZ(|pCXs+gNk{*=Pr6pO#mN5Y^lGTMtERnjAH7-hsY z>0sLa#bDZ*clv~@{&4v9`(-_=sO>ozo)By6%4`0%M&7pYgUQ9GZ%+$(2zG!4fSUkY zJah1Pr@>{5p?Kn5v2KYt2_p&){jg@YTxEeis8#z&uUwp5VUmH4XP->pjD3ZCUNRcd z*k`1yE+&()R<`$yzk7IRXcp?af=AjY{S{_m#BE8%D|v}I|e>nmW)K~-KB8u zbJz}Qljp2d2tn!69rgwi`QrS}>#*NYLR-80o0vfitF7oqt2{)py>A4dTk)?jLr@X| zDYdEJ`p=?^({vQX3-g@G&BsS+<-NlP{1TAdISY`i#pNee*Vu6_BKZt3ws6*gAE%eAiJT07!fnQX~;vaj87VE3BG6 zDk($Dpy)Fx&wT)#_SI)^vCa01BCDAXzyj!QMki%1r9y8J%m4Ez&<&zkqi6}V8Uf8Q2uaxi!bd}3olV*h*6mzN(my)%rh&~^7MKE>&zheq zHW(d*t*mQjN3gve&d1G}=T+E>evl|u0DS|}K1Tfv5?%HX%1}F9CV^jcm>IBcfq;!v^liPj;VO0O!fL6 z)Ew$m)l+{}pW8Bf$(a!9KUkee|dWm4Lws3vWRsS^wl|$`vhS?7V!vs#Q^pm zDf~4FI*~Bm)iqH$LS(`eKiP$wic$;BEqyZcbz!+>=RV*DhCVsN2;k|`$TBnaukgaC zwun~(`QskbgULi_0u<%bc3O>~HpNt2mv#@z@KC48HK_z#)8u=Daip$ybzK_tlnn8P z5g^yMIj#YglJ$LuazFs2UYgtbpRdV2B&M^9YT zDtt76!K)I##?8z(W6gWL+*?C@B9UZm$36oKwB>oyAg80+09)KrUj4dhCXdy=7ji=k z>bZE7XZ4O2hjej)?`{l(6ggc(vbDwDk&jcaWHc#0!~r{Sk<9IZ3vr(Qt|=CQ`o$G| zT5bO*uDFA9 z6?R8)nGmaq3x|N?&!m!Owev0HU|Q)R^OIuCkmvZ#rcFXc*J)<`_zUnS%)-HWO9{%x ztkoBlVCzrLB?c8gUBV@&W4W&Nh>Tb*7hlLiBW`6p`pvG{4;44(&ec{|b*fd!jG0&URnT>pulQlzAF$~ymE?~Z*P>gT|9EeNBPHgc7tX%00o#2x- z>n4*8YPf78{ny{8z71DcY&sIe&L%IPAZkFOI*r?D)k?q}tugJbA;t0*iq@yVjwe}< zF<+@Rr2B@NBUodY^NoYGcYK@67EMnzZFtRk=Nmn`*{u0Aowm@ zezF7qS|&&9;Jrq*%+3;(bAozd3J=wR>}Y7or;RVR20(PJX14nsKng{L&V))4u#Eha z$CNW8Nbx%w(mjc?JJoI|T8S0MTPJpon31%7aBXI9tY#;L?#52ZL)t8|m*E(-IT$cS-e_@$tTXPljn8$``bRj z?D%3_jG}`Ahwl87Qyv1G*=QrZq=0Vz#i{6qsfDg+qq`A4om=28?GIEYi+Ghg`ZC9t=JBmD?Mal$ru2>=v=z|yjXHNDKzL7H56&N`7pILj zZF-(ZaK%&2=OSM9^AIKHdq^4gm!pW0McfpnFS@q(Qr-71tw`2x!Pm>Q5H|1vU!Y?9 zeLCy0bu4$??Jq6ZV6VQIDU(Nl6^HgeU#scRK4^Ue3M6cKwfdMPa}xft*|KzA&a>(A zuDQfC%TXFbRa?1VM_|RGwV=Skoo5G0tnC7?KJ*9$0k~fE3fMm3wiJ@cw$+X+m2rB( z&(Tw|!tHS^#r@0tP9%LZ4C`^36zll7nk}rA8WIgDs{T2|=!I0L9 z`v4S!F1NkBCFqqR7sD1CjpMhEfodiWM>o!TlzQ(wSz?8QKQ_o9t%)}&C=!ku)=5l(i zVK%^Kw2Ne5HoycpSeS|8G1))+93xVUNbNI z5jH=Guxj@ozl=*_Ff1b1ZeC$9xPtyTc(_nIa|eX=X^20&4Vbnus4hU0wG$O_nk=Lt z>0(YE$5CL)>S>$AxOFF~6V}c1`Ps!e6m%!44b0~+7cmJi89P!zR^d+_$6*X?`LG;G z$sW}O+`UoyqX@HZyu4+8H2Zb}uW_l( zW&Z7r7ES@K!DixaWM{`H(@Of22!u+%?|M<3XpDg@aJm(B_fPHB@vnOt5Ufs*x)U7< z!8hh#cM}-C57(`aF3~Kg=_s9=tOIAEsjCj-s?%-WMFVLKcRf4=!~@Bglk~4#>CvjH zpow1Y*hFn#KT-oDv4cz~N?#!nyh~*3B_x;jdR5kx^NELy@4RfZUo{;wFR6q}tj5?` zVm*Dcmu~OQ3e4JNABWg!tU?!y!r4gynwowLh>SWr>W}p8}W&$*-}5<`Y_0~TRMC|=DBm@ z_O|{i-MPfj7y4bfEO1il2#|?y3>#Dzh?V3qu;e3oS8nB=oN6)`LTBpzlc_Qvo-zBg z&pG<#c=XEnoMJgB4wB=SuL_zG%SEh$fr9tt&c=I+v;tzGps_vr$o4qfFf7|d4k?@ zd7Wgr9bg7`Ks-l|irrTCeX5&6((g46X4Umz+LC8QS`ZAL@Wl!!xRr18NRGmrh(0*2p6efp7|qNCLADL3_~pC6QfhQ2Qp4 zoobIwD2V~bAHu&58WHOIiz;3yL@0B7A{3QNZFC|ODkok)2>EMfA&Rzoge*5a0Y8BX z!~%`za4F1mmYA8IYWngOIBa}I$-2s#G8}CC1C<&?jvOoO;l-w2;U^dLGHw37Z`48* zxGzhDr(C1~DDv2p4{E(c?Gx*5?em;yeDj2n$jvB?FkQq2n_q30M)XrYk0#g})ge>9q*WM7uT?l?N;kczPgg^ksY?;| z3Y(Du5brE`)oKgI@4|`|?dq74e`IwYLZ5@v*_|ZYJ9X1$VEGw~r~C;V2j;}svt4_9 zvE*p_8XQMzZ-2tGz2iK!LOJ7N&(Ha>6|f%RFkx$hm3VwrQa$mgjCm)1V~+Cj)7 z88MoAgYlMw^Sr7QdN_uq6sYs`p&5=3nCw!9g=z8SeO8|m$_>ZAmB`A1X6IPoT{%*^ zT(b{Zb|z7TM&N^JH%Rx-cWp~wRKMR%Dsn^GgN<$%V451!8|HjSxY2XEK8d=R5GC zIAYG%?+={~3mDiz4i6PZXztO4H^|33czSrOo??)C}5jg zmX=-`m4=TPm8xe?sHB|c)Ru)W>F%V=eyYzpPT6*Gte|p@Vbjz4LIg)i>+5_o%9eY4 zyNndb)U3hUO*k^z18XgE)ngefhy{On54}7a+3+mjxISHbwn9_>0$zTV|K=x<%%4Ua z{abMMzl)apzWJXI0ra7TsCKPs;da%d$ObZcPki#PajuB*SK)|?VI5GNd@w>M7pS&qVFN7l%O3n=E@z-Z2U(~pFZgg4#wV29IIh}2qa zlC2*+S-$~u&@FZlp1_7%K~x4?oT@dr^wu(pvh=wla0Jq_#i|FD7c-6;=qDZVClX4( z25|u@@k1;Abs+9P#$o^}|0#>X_9yZ@zYXmCXXu=Ni2naw7K80Ktj<5eV*HTi@39zc z{}e&O_Ltr30HOVb#bEo>Vq5->#Q@0chuFTe7=T9pXy07wjx7zEXyOeDWxjQ)tk0Ayxh`z4Qlq_!A=(+KN+QeLhsya#8u{s3l9j@Fo<;<&Gxfj)MNQtZ+ z?jx@gBQ@dL@D8Cuy8S770UQRL=kxOUSXVhXOm|$KNyM0C6oK#*jJ~qx^X1eeujiAU z(*rVqtZ>&-CrBt1r)~U;SEbW z8?!6vm~Xs2@G%c`_%wSTjtQ1Y!Q))t_e&?zs4?Bh(KM%uoQz>nGcRK|P?~#XZ~APq zeJmQNe4Prf2Hm;jLlfyLq#o6UWp$N)Bk6&1N(^)Zle7dHuq*d*El(u-@;utk`mPoK zDUtcSx*{5!MXl;!z`ZMgbQ1rAbDCz#R6zi!@x>z(l2gV7Eb@t3XB(rjG_)vAsDI5G zDWvJZJlXm?f_!4~a*qIvm@P1>Ia>xE^`vT3Rh7EZ0`1TKjjf&sYGOkp@S8^W24s!OU9af~*OGs*7NhKwErOr9=AX-R8 zzn1GK?S&}#LK#zEQn1*WnVcDiOp<`0SamK6Yvq#V&GA}+f^=tUO|M;TGHAPMD+Z$| zuB7jEf3UFcF($0@9Ij%J(b-Em=ZWt6oOIny+1|1EQ*KPc7dp?pFWz+tv z4gqmg6Ilb~ZG@tBDv5VVAGBL9HWq-;)q1dqj8sl~MB;O-e)U<^pMuQPs9VLz+6+8j!FYX1y0RM@3Gp3>90^T$#i9O4f#5A)% z)%l#=wBjj@jFmf8P<5-9%YyIL>Gokgv1=?aW9*!Jh!;NXYmw5|D!zWGMSUQcDg+am zfv}-OGUqM|eoA3x5@0YE=UZ?NriYH7 zr_mFPt-9qWkgr4hjBkl5m0q;qe7?HVHBRc&o?3Ce%t4qPB?QIkT0)>B*=g!KVwa5r z!O+goE0PNgS@d=pTe91T$HD`fA*K0vJ?n@}*KWgLRCP1o8RGN$)_;!0Wv9XCUO-SdcK$|4Olsbbsw=T6j@}I zB;Bod@P$Yy$V&8JC~x3on1#fmBt(E2_I!HA2?TZ4gYBrE%;cax^0Q4BiL8b2&%wvz zROnb$1&5SMaxGeR%F*u%57N5?Vrc24p3Pn1JiCCyc`heFdM=vZeJ$b2RK4B0OREtc4_oQ$xuv$2?8w=(iHKnQ5i$Dcw%gTv*bgn1Q0$P(#X1m~=-Qea;t&q~?nuUq50tx@J6rR{t(z9uT02ZqL)WV07H&s59Ls>4F9gTVSe3071aj31RBoPthIGLh zr@&ia$APtpDNhs?I2(#Az(6ZL+NI$2*S^c%DC-c79Hlw_j);P#y~u_uRLA!oD&{nwK1JL92HhTru68@w*ETiLu~;s6;6)pvf`Ixs+T^;_<9_N#&}ok zK25QRDw4(EU57`2X)#$amM*6yp=l!$j{FqnOaaSSFxN=^L%4AEm2&H{7fKi7h~FRuy}o z5sH+|-ffpES0rH+%)TjvP(X#N4GIh0c%;0=yxD#$i&N7S>HU7wEDk7_{n4(DVS#SK zaug0MclfIH?5I-2ii3r{+AR}!1RMUv7KH_TJ@{B)R zUZ+;TE5TESipshu$II*25b4$sBwzT;)GRH1P8u#1G=mW-tCY3%p%O&k1ReJ5B#e<6J zzO9NH_I6!JX}xq+$HC=`vRIyXvFz>)Y3uHj52sS&RqML}=Xs(5HaCkDID&pEq*~*ZHRTk?`>WXGY1PTtGFT_T3)&DnJsTjwWYE1!Z%*qL7LgkUID>&uLTsu2JSq zdF1kiK=OEj#@sqhGF=Ak%@^*`bA?s26SKp%%Y{Q(V|MZr1u(f>g!YAk3o32G%-9}PuCUL@Y1A`i8#s(J+EJ7jqEmkf#t;O z$>ifklzOkR0_|6Kw{H8zbuX4DCY(bP)WNO=8sn}G>3XY!4JP``AgqS8?*g7S9a)}}&L{#qhvUJAb?7&P=>xPU zHH67AnmpBn&S=MOg9qUneQD-ocKUAv7wnhj<#&n84}F`?(+>Gk32pAoPq?EE6raFq ztLCJ-3r1`V$j{#vHrC89wnQ*xU^HX#dN3ip1$UEoFubhq8W0ZZoV)D{j9|Hkv*1{S zkiCC%@qlaL<_`06kMW$_!P4HLX~ZJ zID65c(s`wHC`I?O7#hjTs^zsoxq%)Q-qPig{UjN5y`!}s%6*V>qhHFu!ZVNAR9pg# zOg?)Q$)8(r-A8Og^YLEOE%PW+5`qEL(vuLxxrDNfMX=;{utG09QKund{YXP%DX8XQg)^x?>Oq4miKX5RRHtSCtCQl4 zX<@R$172aVhTv%KCoxqRey*Kfkjm+b_Vy?_Xs5`PbNg zfsy^uii(B)mp4)a+!H@-F@$8m#%T58&7(3x-O;f{1>*4V#IEvt*n6*pI;aWKuN*J% z;1@x|VZ&i1$@^tA2p<`zaE%cyj@P&A^*tc9g6|5nyXxAH4dE>`HKjdyw{Tgy$b7y& z@9;{!T*Du=0p6ky6065NcWJG7qZ8nVn8V-qs4AQNwCZUAU-fb~Hl_Kjyx{rVHdU@E z<$2f2dValSNv<*_DEXe)q4#?0>QYJQ_~q-D$GKn#zv&$DuIsJUMNLHeVNTGcfc@iu zQhpQ+$s|X@OHqg?^OdMRHV;pS4du;+j3qwj7%I%Mm2tO~y>VQ6+tWzR`zZZ-BJ4C{-ux{0($F<=#mk5y7|1& zJ9l$1LEhX$N@%hc2cF7IV{_FaF$T#@0#@}w`K_(T9$3K6maEr9poqpw-p~ybC^b2?@hS#(^33fgs|a=7Q!H+T(E&FUuO-Az*}=A88iL!c)<6#(HX5@>aEzPHdEHym{>=fAb7HMX zFXpB2S4>{bg%fO_G4AXFJ4P8AC`i?xzx+I@3U7HmTzw<;o!`>)Cnl zw5kg*2Kjx{<^E?kqoqQ&0&mMnt6YcDTKThzv~9B}B2LNuQeWa`gprVP3xh5TJF_CX zR?(j5mD+bM)2U~Ku(C5OK+HB@nN^t&gy!ec?RTdXa0+g>WNcYZyOE}gV8?fj80|q; zT6326of1NFP}afRmb^s}nW*x;Mu%^wQ`WlB$*bi%HM3q;xS2jd5La{9!t%4#r=D>~cOT4z_A@x+#>|XQS4d<9+`9~XckC{13 z)XSay6J5_n=(ha})z{BzPwt1bj_XS94xii8Ket6bZP7dyOIxDu+FspMwk`Q1N*PHI0)vEZ(=2f?XXndw)ffA|{rWVu=K`4!5rV^~g z((EU~OdP?H+B);D&|t4OA0)@!M0TD`N!;8S);{mt(mgol!||x%GK1~(##AzlYVdJT zg!g{3!j`NAl{0{M^gHw+g)x%jiS)9V{gSQ+QSlC0A~ArNSv0-RNB~%nJzEswbl6B6 zG~N!%ja!s0DZGXD6$LN)RWv6-%)0{)uW_DathSpW(@1CO|PFS6geFR=47`?hCvsVa^{ug9FII+lFE3=KtLqNLf1EmY15l< zRs|h)YS76ikDlV4C9%Q^2a&E_+jSW2L3AQMx|9QFl5hauFxJ76Cl5l;DQgRYSr~i! z4yUQ{Bcp9amMJo=*!%(#>j4x|*ufNdQ+aor*L4NnfuG08LQkH0xx)=SGwKEU?-t&& zE45}*)}HILv*nhWE|WV4BJKtPoz|IX{iaq56)j+zJ>68*(7}`{`3X5Zr0p|(8;Ea z?5G;fco{Kw44AM;6s~eu^#o4P1}9m^`m}>M@imOq&ipWb@fRIl@10wsmX6HhY?dmK zblUQI_$!o4^xrM3f^Fhn#+D4d`k!8ipusY%Ud+ia*t0yJON~-M*N6zyrQKTnWP2rV z6emweZ5-GSJJl2L9u)@bM-hlqRl|VDq9=^JU?8)XXRh6j>)W0LySJlryc>5kd~_B) zcxhLimV72XwVFbkc3Xe9JYlw)o`SZT-h#Gbe}iqs?!|4zz5_fDa6hMv`wHRjawpz+ zQneyq012Z$xVf$Ns6T4_Zh5ZQ15r=HrSFi*NYxErH$7h()C$h}OZvz2I5x{sL$WrJZak8W&U5tSbMlHu32{H6 z94><>qW7X1zULMox#_rbD)zu}%Sph~aspDVbS<6bdfOS5D;3dhY_ z5AQh)cCA-&4@9n9nMU*v$&7J zhPWp9;5~jCwBN3%2p zYd@Ss#akG$)X-bVyd6K=FujWC~Lx|*E4 zh*5%1%~zCwl+-y-3SU@<%TJ=2KCrAkCM_KdoIjz)1}VI1n7WVV4dBn8V2i}VFr~$U zTe974FBTPJX+D2nx_Z4@#Rz%Bqq1F9bfzLyKeYS=%Dn|jfzNjbGzc!k<8=-k2cPK% z^y{~l9)P~uJ*;tMX{rO6fd;w6+$7=Wzc}cSTaC?j*mb#G19Qv%f9$;la2-pQEh;99 znOPPyS7f~UXk?Fc=snmJHZl&^M_?koF|8b zZ~SpO!&)sBitvzq6QIjWv})jED_9dKplUYm`2@U>&w-q+e_a6Tn;w&f0_<+rx_bed zLXPwf9QN$wh|>A4hIQ{s>FFb(6MdshPnO67R{Xi}i~xgJZ{DgeF{F6b6&?sN<2lj+ zb7Q|Is`eiyZ`lhRD(BYm9&O?Ik9XlF8UB2)c~`JcA3OK%Z)^DPlBQdFGx+cEms`C0 zTOaY4xj5zO{jy|FlE1uJ`s0+v|H$7K{M~m8f9a~T6|WYdfVnmrcVT-L(GTgJY&r9g zET|mL@VeRH7|Lc~H9M1k*L^wym{FGTJtIZ=%$h3@lZbT>r0@bR#j|kGg#L@h7j&Vx3&Y1hEKzxwT_>oAD+#hTuAD`Sl=PBg`KTvs2K3d)~`gRFxVpqyL zHCZ-kXrAH~QS{RPVd@Zj;s;GI=^594bmsv_*$)Y@(y!!@jDycf8LQq!BWc*br{ozL zFxd8cNQi`AT#H~^;HR9MfYi%;$@D*1se0hrxYu}YGjXnb(emK<=uQ7EYHlrj0p5Sh z1vWEyehvJVPONL?iLkLW9Ig9umU%uM92PC#lShPYjYF^tnEMtN_7G8qF)h$Yd3*wD z(#fSG5?HXwo@fOZVxPpVMqr)C3-Ej;6CbR5RlK%PNM9N5Fw=B6N}wO zw3sXR@RmG&^xs}O<-w-|E@=Cx5q-lqf?HAeplw)Uzj^s--1tG8)Pr~Wm5PIa#3oi_ z9H~*V91>c?Aj>|^$1w;q76*y{E&{LAwQ(3D9Hw&fzg){=waE?ghip0)92oQ;VH_DaOFN1|FApHlRIKTX*5x-4`lD ziCgs5vKub_Iy$W0op-KruM@p4Zv}1O>BIggy=qHb=)!EX8I(JUDa96mE<6yL8u5#I zK1zODR`t%K1ZIq@yY(igdM z2#+`!>1gQCgU6V9qRVPuzU}D&mZ)n23fwg@GJ^S3cVn%_Y(U@G-cJl_qdI8v2HarY zk^bH(?ihkQJ_&h@7CYCJ?pls4P4FNoD`e7@8$3{ks0w=giWpp+R+N`Z$AS4!x`vS% zDML_bq^i#MKqrfs)P8J*{%|tT#76y#f7O_-%Y-G7D{QYId{=5|si}Z2XMqhTbg!b& zHU`5WQ@H~})jH-FVzA|v` zENuck-#f9XG@OqX08TX_e=qZewrr9RKWuD0m_xMbJ7yc=H|8UQ{uB$-kbC^%NfqhK zF4Y>_?kWD@hIp#DjlslY#yym6s!~?Y0!n*H?xqxYZ!IMz{Hpa&L#k#(zgTXJnw})d zE-kKhf*QhZW}wdNELSXxDQmiaP|stx)tYXQTHO(`TGe;o1F+f+Cg_~$?i)w?r83uy z?)!MTt~6+x*th$R8{J?RX4dtL z=$5qMHk^;t!0U3H@+EDJ8#UD>TB~QFT=Ra zWYGs}zV>8q9N_}_=dVF2`QgCg9El$bG=2&#o)U}XHM^G2jmGwz+0PXvV12lInHuQO z!lm^0#SB&VYWD4)iy`{_-Z;hqQMzJc zQNA}##NpBV&6RBwNdz!Ubbko25l8$r{=gLB{@!+b=HQ+!!NSLOv&o^jCjz5Po)~W~+UE zv80x4e#Q@3Lb_iyetZ@grY*6O0fzCzNo||JS|p2hzp4>T@vqG@WVKrYj>35+bc~) zB(Y-NyoXHMLi5@5x$6&XCAJ#waLXz?Yfcj$stC4qY&npPyD^8FyHVT@p+;QkYC#q} z-w;$EEfZDrsdtOpHMBy9eKNN&@L{dKt#Mp9d^r*tJt?6ymTEOm{CdpsiB0->qz-cw z-IMng#9p-MWB;7&p{pGb=h|G&kh2XAqCv zjl5Ial3C4~bxWp8NjJ9ohb+)mgzBP_Ozq)X|C&p#La;V}?J`1$OMhigsg1>QBhbO- z@1p%sUlyAcj1l4HoELB8W+$*3&yK0~V&@?j<@J1q9YnT$EoJ)8j?ISz_L}|cv{8d} z6JlOKJx`W7=@VJ(Vo}}k*^FZcNX+8*n-W6T7H9EI9uO6W=fW>}w9Aa@t`fGNu9CuI^K3{BPe$E3ASv_huw_O^CtxZY0ptVS1GsLUGj znY>W)*tkJ{ofSJ{w>8uzz~11H{zYX zCNko^8aEPr_GG@YwyynlkJFI$Gy+NAwUo*=F;&OAnL%4GNI248u^lUOM4-Rf@Ik9z z)TT=&0HN%9nv&dTW?2|aw-t;a((W>=ft4rw~r}Le?)`2;p=){`imew=^!&9gsOYY~E#o;cy$DO${C*WFwlcF^x*P_K9 z@b}Cu6&8lTtFEoqs!n+a#!cn+{dx#;*x4K@|@ne&zD;}SShcyen`;R_Ba#oy< z=J=SfYgI5HM%}s<5uka7Xns}hI5in^N?fqg{kY|CF)Tq%b??}J#zL6`H1T3+E`)a} z?n_|r)mCXf|zai|W{>g-yMpy+`CurqgzfcgC4l?9Qv`&Zf)$1jw-|8*J- z|LENa$KPAQ6-p1c) zg8ofw% z|GzwEMuy+KD*o4w?!O~C1B~|5Za;|5fL8u&=r2TP0OtIJo&P?j|389&|Cr8M5;{Px zWm@>JOy^Jl(^(=4QTNxWgpuJldnW!-&Fl;ee*-@!84}TW9CkiuXDZu^{54I&Hoy=N zd2z)P`cRc;)rD|E*tyHE1Pp#s41U}3hlyrOytPx<^Wmf0$Ro*JWXzEW`7djR^zP3F zy%S1LH}^*;4LEogA>U!TmX2;;8=sH(G`%~Xovz;UivwbUd%tc=RVS6R?3leikI-Yh zK0j78WO+l+SG?N$do<}NHcDP37uvnf86XJ^zlX=91Dz@yaS<<1YJm2Bz4`v~^<>Yu zRfDBS)qLgVz?yxYbGKZr_Uh%~`sO=^xzN+z(O2)4bXIUZDqgMc57%e&+NFUS(Wv^& z1+a$rAGBqdz&yWB{zvot9w$Eq_Aff?34sA}xqe~5Y;uxW=3xdcwYxALCu zo@r?M)ela(t;E8FM3WAGCdNX=KX}Rkiq3e@ys$bn1z17#6I8!C?CJ#Q`O7$(O#{WP z4W2Yy7Z_yKAZMCwoWzvcG$?@&dkN@s!{f!p*MnRh z?S+hq-D5v)n}#jtPmUAY&L`JmpFl0|tzf@77q>v3Hb1O*t#R4R`|z&XXPudD1B3FO zzB%WHzH#c6VY85rSG37rzYUE%KBP`@*LQw-Xrb_KRtdFC_6em-!u|SYY3FneX|t%V03fgy1uSv(s7IhND~5*MZf?eZ(f? z00*p2^qUe3m(n-MpkJ%U{Ev)AuwcFu4zKoO+MK1|`cPWCsxhrs8aP~a4!A>JW_(^K zRR?Tr_B~LdE5Ovncj1fJPN%o}-qXaT!o5lrwOHrxWE4H5xka!j_Jmt7ME#y2O~c~a zg@a&(Ap+El>-KJ|kW;Qw$?VZz+HxKQB_$=EZXDG0UDI2`xEc3Dlhq59Rmt*d`U9>+ z^)e584b>ucrq|GGo#-|12!g%blUu^hP5kFX);{p>@tTn%I0n=@nPG-WdL4#Ix3Sja z>?xUN_UF#cuATMXBYZD?Y2$=K1PzFn<2ZY)lTX;f+_%=X!5oSS2OQ|=uGjS)xgBSN z59SdI%}Sc3lh8jWv z=eF>!*)cLc9t&XCB0_MS8bjgKvf533jop#o73d@gz7o8V93}a zF4!sl(HzBSnQo%ab=A=pIz&Zg1_^ieYps+_0h$WEWPcy5LtwDxBbX6HTJ% zmQXcY5yWRoM$z)R?_koOSvqMwMM237Po=&hq^-y4m$6HKw(Wb6J~FX@?NqZy2T?qG z&{{-Z9L=&m!lK)i!q|}x!c8{gq0E`3QrnM2fJ#0MXC~9rdN|pKtOW@O!`0lUD|;^q zM?w?k+`khcebFsGK65@h=kRr=Jk_mP(2;h7E*EG=t%hkQC|7q{Qw$-&cw)7f0y9ni zg2~~FUii$(@(nR;i{U$kAt&M>zO|RD?+xyyOJ{3ysgrVOSNyXZ^MbmLQ2-VK!$XR)PpK<1@lL>v6@!$7Ux_L=5Qk!`_(ljKd%pr!c`g#xeC{(T z|Li-fb=@QJ(n`Eo=~kaY)h)g0bs|t9wPG?UKlLu50@z9)a$`k3ism(gQ5{=wgw&c| zaBhxI>o&j$AKxXzadRk+V4QD{293J{BjCl4cY})$ASX(YZwEoE?BI)6ptmI=b*9Bu zb#o@zvd+>9*{BBPCRmVf-p;O5zKh#*=9$gYpsW>;?9BXndyU)!ra1QMeke}3sdV8v zQUUbnDhsE^HmZ~~EykPVUJPRvb@I4AOebSA6-{eCOos(2LY)#o5)r^C-s(%;(rPSC z`mN?|+~*q@P15kiqteiT#a%Q_Qmv^EhA5hgiQt+Zej(u>V?uJ24}!|)I?2p8GeZcI zJkf#qZb&8>SScxp>*zw5X-OwpEJH1f;OOJZJ}Npj{@+p`5PR|;LEPtryM^Y2H)+j@ zHz4Sd@z+H*;j|XJSXfP5X7z_Pb%IsON>x?YXR!-v3Kl_k7Hx*p3XGImVeyI=^c+hV zgkxFZmP0YUXj`iZP&#w2Ki1Ab#@ojgA%w-_?_WY$kJ@lMUpi9FUS&Bv^bP3eYUFDo zk%*+GMG8FDy#1DPiRFJIITE|%xxEvIfsEKnNO%VdOoR&swIR+A1qlLjT!aICI}@45 z=}0n^)Es*r(;VxvMc}hZus+;j>jz6qCmy6*#$xrf1u?vC^&EqW_?+0Qvm#z!iB1+2 z&`(yqz!_(0A!dL=e+}A^Z-wde8_4CYyigsgpeFn5fHbQi zC&}EwG^-!MKFXZN9FjRp-o!1x9TcyZj)^@_I3#PxjWPgn9IE(&Lq7O!)6ZaZR`OOU z8i#_!^;#IBZNCN#>`3f$04rq?Ni7|8A9@^xzB=(IS6@vUu46skPP$!`W4%@KLA&<_ z!m0{wDeqydq;B*$JLw8QkM%eU+!*l`cn;;+9pAq>)|;-}0?9KE9nQnC>j`MFL&!4@ zUmd2<85?xb#T#BIKGY%~Twua2LUCGYtO(Hb18&*-PQQ?vu@Mh6{|H?QlYwCDGkfHx zN*9Wffc9Coh8vtW#asuro?R1y(kZWwuC0q{kcO@``-nI6Lnh(7*XuSzMC(aiO$a1B z7Xz$37j{ZnKDJ?uvs*(%Wc(xn@mBfvyGq5(0InU0W`#@xoE-@laTAGFI)A0bJdcY? zxlCC^pj2?^g+WR16eCdZ?nZJyr|Jp62t_`>9L0E$28AP#v9E%D8()(Kjph=_7df-( zS5HCRke!adpf6=y_9bRql5)#s_AdKm1}rl{K_gJohBhSBH<}(YI`@?G59GDj08iHm z8&1PD>2_;2K~C3*SR0~N0tWp;#--p26>J&iB*M=zzw_pd2+k8U414e^3`@CUXtdt9 zFyE&EUXwFd=8BMk%mxT~w&E3Y`fMx%0p>x-G=W8XW#mi~h#h|BTFA5M|{SShQBYw3`B z(c?<>e)M+^);6s%ZOr%d!~pkk$!SX;Ey7b!2V{JRebQAsWn?Q3YG?!w>d=Ptx>}?+ z-}zX_2+h)L|Dbt!o<4LlW!(&+>5dCBz2_ySL9MR_+u1r@q~@+Mb_5`i$hQLpTmat~FpJ7w^{qg2G3`de7yN22M8T!KjOG1_NfRU2r*Q zC;ogJASIYW2kJnf=ENtW70H(rD>82&rAtVDGHkp`RLd|`gN>ykw2XmFMVuxT#?5EVgiNj1xPrG&^X*fF!;Va~q>4mAfk*Nb> z*{G!%`kfE@fyi+3>=Yk1;Pa`pl37fa*C6t#zGW-rzey;z2vk5j)$gRzsxEk|PZ2xL zlCTT?bxlNonN2C5IZ7DRxOXgbbY00a)0gI&SxC#oZd$<9Gfr65gjj3=fXXnEAL=83 zO{0u)K$SNDrLN>C$>?_~M154`hy)%ng;gEb@3g}P4SSURIN)Q51v&?!Offs`M3LBo zS()DN^SJ?8(vScY1~BhdyU(%E_QZ1b`&fKa5ujAXQK4ALu>E@U1&vdWy~UF+nep9M zs;gGUI+4XWptVmt5{MS-ZJqZ6#uvi2UW>tFxnHY_7G<2M;i@{>El%7f+H>o2Odh;%Zk96+veWqh z+sdv2#{4JY(k~(y!Ih|SvzOeoWuo&y`7)J>2J*=UI5$rU)Vjp*`8Vi#MKpnnNHl28 zya(|5sq8q)@JXR|$|Omm&tE=7p~cHt>sjEBLJH~WDtfn<86#FY$X5|btKdA2i8e5> z$sM-q2o;~QN2SYAL*W#cPz{8l?F;QK1U}1rJ&D)Am_MHh60WcAF*4kMn5_t?h(J!z z9$QL4h)R->#XC`v8S|V4p1k=ily5ER!@PUZB`NIKZBWA8$;_F?)wA49NEFq-X(k*)n`qX;rRW~BD`os6>dT9btIP{{wD4*6ib(YFXvFE zeOvDYHe;pYTu|#IxuejF_bc$^Q&RAh#j%Fv&#}yu(m}X4ZBxX$tTC%MkaPw}Y6S}D ziV=hy>vG70n*%p|#Lg{oa!wogHj$pf#LgkPK@b+u@N*DO>xiCftF%fd{R_1ckQ6qi_Y2zuDe6OevWU^FLa94NuOV;oXmJ|gd_5ubsK zgF1|S(Nah3U6=KvB)EHSyPvnDsfSKOq`vz!Zo`L2ore58yZ}DQhDdpdXk0?}l6j8; zDSBIo+&f*u*ix2;;E;>=+DahXepU``oDxLqsw1JAF%CvU53)n$55h(>FBnEk4su29 z3?jnWj9WnxdyJifjj1QG#3HoRSY+;0g%1h8j{)xY5Y{-3j(*?U_YxB-s4*(m+vmZL zyCbwR%vceU>p!j12zH?IneD*;8`DP7H?M=4nhGkQAT6aYuyDnddWI!XxK1DS9gTbr zE(&$PHj%>;(@rSYWzwvtU}R;Ny{*-E*a_~vfx84@aJt0nBXvQ?uqyObk@5R0NmrrJ zkx#)$He?v$%=}^vNHC!hz(_8V@;+>ks+y=k5A30Ubs0(c=~OEVFj(clPR=1=4Snum zI{e5HhfpdSikxE?ipLhcje=8+T$-we5@A5yC3wlzCEkbmF>4$BoP)VN4YLqq-J9`Xe*TA zUNOyue^%qzHdI^;Guw$th64@L@uHpW+(c-t-V?85go(8GgX_s)4f(3vlSjVoB7La& z_(`-CU%NeOCSiL^hMVA)8{T8->K!uvHSA2}z`NQCFlj2N#eP21m7h^IVjNON8c@klA9~? zLM@9s)N6CFriTo;P38D;T@+M1f^GV`tNH(7{#Q}q#eP3q7W+8XPBGH);N$i(=s>|Iv5?@# zJ!jHo(b^DGa(rlnUcjhXBf`JrLIxPWX#7mPI?_bKWgRb+eU+&A3Ep<>><+A} zM(Kz1D0K?|CP!h>w*5*{Flw>tfLV&FuS)GZ&KCGXOl$`En#^?tctdkf@E0*_u{IND z;>}Y(PtWnI5VEQPt2E7BiQ)_&ZC zxR)(O7I?nFPga<6U{~g*ViTAd+ShvzT(v1K8{^?<_*lRM^Kt}4Dy#Oaah6TkyOq)J zC0sC5<6M@>g0a49+L0b}CFJvM^Qe$4CY8j-VAoVr6WFniQmOQ`?wWb{8L04Xn^h|h zm3s`%imE7~PRNvm5Wpx{U=}N3rkbe?V!c(c7-mv2-__bryw!laB2ppQ$SjF+`hAB!Tt`k7HfN_c55-kImQ{LQaSOUi7cSaTcwtX9pZ8N}> z0)x=B#E=cOukw|;kU)bx&@euIwBzs-wwD19%Tnu9n1OmGn&sjZ4dCvgLAE9t5nroU z1$;VnMVC-fi?zr_gGNY24`o;Tu#xw{!72wWi_nBs3b{6}4o1!PjUh!;`QR6{j3lIS zm^d1p50Vy8byB^Rp`_spDT&Hs-_n#x)$PknzGj*Ox}{EBZOyFkL2s+wHZlNGEmn0; zjdanD78&0}WHVBEO0>Qv@=e*HzyWPt0NK1*on_OUMe4b-Rfogzq6!+=k5SkR;b@XC zRNm+GaVycjOm|~`imLhE67QmyKhyjZ=IMm9!$?>b1r9%{N%D#Bx z0~ORT1FK~!JAz=c0GpxLvaB5Sz>ZfnK2Aus2RnZj$4nuXYmS8QOwanL z_kw~f;BSWfz{MvG5s$(h4~9%WWs6F~>qtt9?-d|Z0+|0`6c{{0S-1ss_CwQ^h$cLg zq9*f@@seD1d7GBUg0-r2X-6S_V)KDr5KDPdU$IsFaP~N*YV91XJm0`U(;xR~XIYO2 zc^%&5zc66ZIE2;^VZA~3rzw+UT!7MWTp>8N80>dbZ!4{1-Yt;?_7_{sryAo8&VL;b z(rbmIsc0@%puqQ2GEeOH)0AWrcTI?ufqEKO$(JljLK)#5d~&rpvk}@%!gmkx-?%g{DPxdwZgf;YS{UDI5j}< z@_sjm-4dqb8#kDF+#7ju9x&@L1YPA#A|DCNFtaE~I}$hg9gC)5{zP19U^h^P!oJ*1TSY+%QMYT-~(@i#V)*|F~l z^e!vu50CnMvL1SgRs;R>*2#gfTo!^>GK=^K`8yP)>1dIcNz|1W*sotqF5=&;v>)t| z%#b>xhmag$Eym6(>bG7mx^pIruPGc{buGW_b`|R^zj%MJIkqOfwp6Y#`s5u!BD$NY%x`sc1{1lnI09`TqI5~;D0@l=mW zCm&euNvJ)pOdkkti7MMePHJW`JlvlPUME>Zd^P!kFP@xu1$z!TC5Um(b9p!QI!=ZJ zeFTJ1a+P-T|ihVEHm;7%04sq9WuVIxtjadBj zGSuj3f=H|7`&9>rc?H7jbJ?U37b!|B9I=ZhBcmS|n01EYhpIPk=Wp$4tIUNyg?*?x zifG6~L~EV9(@2M1rJL$n4wO1~DuP+n8bNMr6QFW)Uryf7=e0YB|1h|I@-RJh6i!)x z$Lf|bA|htZ01i_=75>%`uO+r1!9Q$;PGMu&&>YOUDr#LVG)miQ47;OlgUU+`5R3iZ z2nYk?F=hV~QR%LaR;$BwMjP#?T9G0|y_UjMm%7(OAp>Ua6Q?&6k6Q+!S_a_)QUC zZ#llZ4jG1ixFoH4dIeX8(P8+#7j?f#RsFw3ZuuLLIqAPq@pEq2`&|`3jx_LGmwoQ9 zYJXPoi-@CfHTtRIH)rxg#c%2IWZ|m9Q0ObU6-L7FT^@}pqfRGWhaoQR?-}_2ZT8SF z^p?Mo@pGzK{398^4NBvYgi7pjjcuJHlv@-&)ohl7wwi73Gl^88Zq}XWS4N>l2b{)0 z$6mwzcV6;+?jL4_sW+#7%J_Z05tT}ZR~4Uw_#nezXsXOMn4tW+-m@FPuGP31Mu0v{ z^YnW?@oyv={Vl(Rk%5KqNB%QM;lGpN!tz(;upf*EKow#?4-ABM#sJ0vGoi6P;Gg+X z`|na*7#aSJETI31T7HZSzmR_Z88N><+4GNBE{qKSB?b*6!(Ulaf8n|OLY(WBv9_*VHz@g}#o z6al~Q2PuIC@@GeU{++pn@i%;ze=WP{UqfPK_?t+GKX9~%0TJxcvu_SKYoahdk>HC{ z8h0l}v0mkqH$x~Arqg1op7S8Hh<#SNUM%lxt1Pt(U!!jDG^vYttPo^AxrF>!#nD6H z{^+X8uBLil3g{7V{`89}I022S4G6L!_Vn-B_~`1myqDx#Q28 zxc@;U1=RlgNXq!X-}C!#jqS(C_=^MfPa)|~d;TGkGXCPX{Bwo>6@UJWq>R4+|Gx`K z0fzgN@qQvHprwpITl*`L0$_;oClvjULeijuA4r;$^H(H=1t6(k7vlZz%`LxpME@$Q z|4WecAIZx9YZj!8|27BlUt-{2VDx|Pf|TjsMoIts=%9>%LGdI1J7JXL4`7t(f4^(} z-wUHmzxcub6w>{)=O4l-(=V>wKUetACk{Vv^gqKW)4$CP`uhbbz;KK|jrS8q0WD?x z+1lTMQNUW2@dpn5kAhKA(Vs9H_*WRk{IMX-MFRaD7-jm!*ZOzDDEt5Ck>&+{EJ#7m z+ych~E!d9gRtUC_wH|!dA7=Q|UxiG%5Mw6Avq3LMr@mnnnpBI+b{Gm*09K@1K7bYJ zVC+|*eB&Ycu>sddK^EJ)x=Stho>qu@6v_POS!!Miibf!BNSw^yGx9G!=l@$q{%tf2 zm-G)2V}KAXi2i4;Vd>xlsVCzv+yWCfo1h_cLe#bGe1i&9toGti+D5(!$3&vxsM1|n zisnv#i8OyR?sxShHJn1$64W?x#+-0c&eKpC)p(6JfDq>L;R9SPX{I?K(mZ*Rx^->m zfsbM6Qg%0V!TYgkh}7v}0*^b6jX-h;*gKF?5*n}H>xzGyv;GT~G6DQ^K>mZ-<3DvP z{F6&kK<&T3BxU*^H`G?QBe|*96j*x}@kHXC}GX3HV|8sEn6C_~hl@xx| z^XDG_Gx9P2;@|yqh5s1Re?p+Yl=yG+g?_qt^E~C0YJp~6O4Wr zOaD_t;2%9jWBtujn}6_dS2XDdmc|zS8B3M=7k~g@8lZ;+_B)dc^KU$^e^fa;Gt1xZ zX5?8cCu6rd+oL|@@G+FoAO-dZYHQqc^@E7J&5ZERcK5S=Apq>DNGP^itHaZ`fz^IQ zEs^{z9writx=cz#+$p%9Lx-WmA4ZI4QA=Y2Y;ju(j9Mh=dU5w}2uP1pVjgw4qc zS3pe7!E;xArY!B|kR0JVT)X$d;VFk6+`wE?2T;cf7puW2#zV&MY}v@6@+YIrZFv=k zU69+aA|cmIXvBhv3c9%l{GC^YC@Igb8=JqnL`9(_j~+ln1w-OUS+i?W@b3%f2a|$c zjjem80O7zruzM0VBAjj@J75ddjCvP>PI&FdY#CvNy!j?}p{ephZu z!Nc8ZeDtM-=1Hr19R>*Zdxx3aN#~kZ+lLnNhb{HzgBrf}RX?!~?Li?s;J!o!JNF5B z8XF3h)Z))IT}zo0ym5Fb#OFQUAb2|a-N)SJ~P?k^2>vC1Kimh1#-)S@X*AR zxEj~brUagcax_FREF2&c3)vb#<~T#H*I;m&Z>aHUWN(A}YSB`(hRsozCo0%s;F}Qr zU6Wd=l?W>>6I!`3IZ82gY{?S$7e9yhAu;LKlJsl}!qmzG*GL6cWs_kUiSZJNNokJ4 zbL({{qNQk_12e0)>)MS8veDrCUG99>Zs=Hfv3nfJ&+vYF2HxTe*x&a_!4*c>xSJ#7 zlfQ)b37b^pr_dDh6;t`Fhs*zdFhwAH8-(x@38X0`;p4K7N=mDwiugFWsG#o~-;iM> zL0d+99n0KC)YcFi)NntDFHnla{l|hD+1l1fT`j0SCyz)1F<_ONB47@o*`+Qbs7=G- zPKZcELm@SI6(AVH`^%;|YxBz<7<#sS;b?qZz#(*l#w+WfK;=5t6}s^JbO&-vcR;E} zmZ++^!l1t6t)ey1DD7~E;|*{mY6L-s5NJKCp|!CA9L<_R!l)vfdhm4R-Lw3By2@R9 z#9%0xNpVqGl`hF|s=ok)az%|Yhdyr~I4ToWb<&!?Tg{NvnMZg$+)ZRq0cfx;H z*%`N`)QDTqmGT=Ix!$B+G;d&ZG-_sr z>s4gofX>GcdHwF9d7_Y_c@T8Uc@Wc@dHs_S;*P|sv0>yX3?*M@TeU0|cI z10avaI-QCZdnF|384_VGhArWGTr^Sggg-F4j_}I=AzFb(#GNH)(FoaG(sN8 z=vJ74yB<^8g7-beR|le3^{=%!(Y!z!I-GB?vUO1pKm^-~=!(6;nsseJzLS9^;AM#K zGocN>QJ9K`=O%cTO=C;Wor;ge#=@h8+jOr=ZADmh_aNUbDwU*qe^zJSL_Ps_$;2s%8@pF)rxK*!QN zTemu09b4gxXyPKJY}xFy3af^t^Tj*d0qngXZ-IUf1i`fDZy589ghA|CrOxZ|wn5vP zDB!yT0|FnLVhi~Zw|3K)9eK2jGp$jd%N^}>o##&{e7kA)SJk`EGJSHDImIMKfZ->LNbdMKpAnz<$vZtsMQDB+0wsMtY=g~rTd)Y|XPSHS zoBKHFmhJpl7s;oXsHqFM{xM;Sa1Cr3ZCBN1nn*+Kye%9MM38$zyR(cGa(Ra{%wR(s z(~M9Y&HImE{bxQVl&#_VgS6Sf!f+?oazcQc;QD9pt56PAazH%Rgy-FeViYOCBC-vv z^E=1h@G^1HzC}yInvtj?X)RIxAQEa@jOg+x%6QXY&W=s*Dtl8hSq8tM8VvH5X zO(zOLddHW8+BPX*!qicZTJ68hT=pFa+$lh-V|EKv#&_m+vg7J`2~!l$pzJgJr=UIy zPc=gHSksdC>4nnFkn`^e%--$yrjMRBYmyq?t*9cN;XjVQn%rm8 z;6I)s5*_TnAK-000-H+C$arT${*Bw+y0Kqozc||X^YBoSW#78b|Ch+PRZxO_LbR26MZFF!^wAXqLn-d7}mPb)2bHvcwI+-ZuIXURL4d8Nr9u-(jlR z15%QL&b&rmQ=g9`iy|br&X|Su_HiPMv`1WL!u!M8$ID7DaLK&PE_c;PeriKX_06~7*oKFZ zy*K#^&R_0IV&`nfcO9@6X!X-akj(%>yzPQ!BU!BC-Gz?g0?9zEH9dqc7p6m~BIt}1 zR^eOAt%Hbu9%?Wl!9u=$;I>k`o7MChoQR>lHL>Aaxb^`MGRN`UQoKPl6LA>Y20*}~ zGNDqSqHoLLT!1$?#)-4%O$f*61i0rP5~vjeNu2)+*558ciwc=3)*mp??L& zb5zFTZNx4~Sa=;(RJ{3mIdiW6LF&-=U^UgCl}pso5h3#BbY3Y7BgF_jF^TB<1q&vO zSQ?xRgB)BWb^=Dy2Lnd3(-<7>YoK4)kjSp4fCy5V2v46wPNrV7k}PA!tm6A{HwATl zdD&;+l1xz{Wu8=-GB<1}wHu`Y-NbmTiVrgWY(|H&RM@n-lvXUm+fnj7@zE@*tyJW` z;Nt^JsLeDNWp(Nf0k(=VAd&nfcEl35#-q!PU1U&=l;qPhFVY;)=XvR1E;;F79ttw3 zx=h&0J9)S0y1q4b)fu#cP~ zp*>V&R=3UDOFH@r!f3PNS6M|8i!l_?FtFJ#9}B*9J5ZB&vrk+>4~P26%b?OFpom~F zSPPRb-uja72v3nwxqgrV8~0yJKX#w4jXfr0AVMzz0 zVH^CTAxD_Li5ARiTyG!@lkPVs=HiKNnc&*0GC9vialNYih}k}VDNg6b1owYCcVnw2 zWwNR9kc@LoyqZ5;Hu`xls`9?c&=7 z9a>!1XTv!t0z$zbC8k2gCIWDRTDI}HWk0{$jsku}xvG#_~pUsn3XFbQ|3*uvF)Vs{i@5gD#( z>S#^28)#&#eEt*OJLO{7xgpdcEk=SRa|Lj#}hGQuX1`2<_=}5!}5H z-b*b*$5~VOCJrCM_SV&h7UGH2XzLSWL}=N51zk!Eq6dDv2N4tD-bIWLxS>kzN*3UA zGw#HRB4`@l7ZXWCx$+b~H38R&12&P4QdA~wrK#@uNk$nk7x5;PLBtVZ;mENXOEP~_ z@S&YzBO7Zyjy6-U8fF!$`JNTU7Q>?Gv7;w_fi@V2qo)2wJW-2G)S+iBurEC3 z;AIU>gWJM7v1?H$#0Q=_P73ddX|4(tEmBQ08b?ag(^cQv7%wx;as>w~yO;)5tf!e< zeY}QO>$Ddn(OcHJbMz7D>_Ur(jgB!$hI>;(93o9%7$U)|D*+<^88{q4M1;p3G9iwC z(RJ)IEC;9FkZlw{Z5YPo9jotKAhT>X2(wP+Qj_L1q(Sf!tWp+|6nSapIrL{1VJxI6 z30@qe#A?`S+1ke(kgzqfB{Rv@hW*KS7%o&sWuJDAh`G|xu_=p5)19ZwyAvlzuNLUouOmy=` zW5&c&iOxOND)qjzG#SOFJ!RbC2&9m-#pM};t!Jg<*+*GJZd<*-{IV*{;{`G@{LCTJ z)xBtun2Ou8I{zWPzztI?`B|dMuw{9CR7Wdb5(ltCtE9Dn62!@o~K)ds`#Q>JI%zKY}l5p#>19V3kkR z$U03#_zrFpyoQ64OW44#{(#ts-@YnGs#3C({g-uWiY66Q3-@HVG?|1yu z-H_@Ygu3My!1s)spmtULkYLsClElozah9%I-<3h8h5NflnAiq?+Mpl55-9GQ;{DRx zxC8eFo!rZKe)EhV!jcGB_c;WC1bZ+QhqTo5`-@i2q`-h!Jy11MGU)3{^UmB&R#19e(<4>I^pFxQC z8M+L8J2xf{jeZs8ViAU|?YUV`Zl(r_XCPeyuMS%R&k{6r+>ObIj-!A6el*gQWne*? zLUJw}J5LR^cy!yYdQNHgxOKZ1i@SOo7p!AZfdf2wa(UB)i2P*5PzzXJmS`k;dC`tY~*8>#E7}LM8k%-(Nx+P z3mdO-zgBgROCgrKCBoKVCO-~P$|M;GLsx%1?<13zb9nN__6x50&E5Z@?ks>S z>5&BOHno|VnVFdx+stidW@ct)W@dc0+jg6o+suq@W;*|KvAeS~|4!WOZS3AfSgw*v z&w8a&Wu~PsQ}PM77=Fn$Pv28(mS2-?lS-$7Z{Ujt z%sRg^Q%um(8<#+@FlX?+a4m@x~{6zQwX$IqQ<&=|#p+{xWr1oo=*< z8b24`eSc|%C|r}x>IlD)LOxWuxY#Coxbn?1C2?xx&um0;n}e5ud;4a;$tjrGP@(sBs>UA+ z4E%v=lQ4CaX(+rD>IM7`Bfx;ysnH$Q)h6O44lYh+I1WV_@nlxh5Sb=g87l3f4Q?v zonWhxsqkOVl?DQY5`Q(R&`f)NdMAEK$*JU@DCYb zt@^y1$?iWJ~NDa{nAWp=*(0HT2`eTZ`k_}h=^M2kKL1uatg!wG&t zX-e_#iAW`#WFoKiNIum4)AA!Fg|6RZsn^czfRllm;@ck+d$VvZiPG_$nc5MLCB-ZE zeRS>ZD)#ZG?|#`pg@oK1O>;`irQvzm0p27oEg6if>AXjV&OLcWD(E36s?9KP8n`TO zf8274B9WD*RCt{wC26muG$pJHZ86J|EZq-|Ozr2Ln&PHN9cf55bTYL8uQ|nZ@XE@H z`T~K<6f9Vp0#UW#TrvYy?PDS7^clKFKRTHj!9HV~tK^iEEKFu+i}JxWbc=GNTyuwG z!nik*2|Otam7`~F=FW!(!$nA8t59===|;baCoU3GgWsQ-ttR}E;<_7sO_Vgt(Ns<- z3IArHVGdRa{U2$=JbGaya-E;od)^pm!E)f|6fb?!Qh@FlXy0a-k8ce|ij=}+e`ZuK z2hpxJ%U)!-tti)Vl4Nq24B5_&lT}+ut&mj8>NWDz9oq!zvN78@w2)0vUU-sakM?Is zlIJ;+;p+Q2l4T3gGaW;KuzrceeclX^2U?^g4yL)38gaNxK?kGu^q&%3YZ!LYv5iQ~8;nTI zD{M&2b?PK0Tb3jyFe4H&`1eU^ZGvaV8V3V{`g1?G1_DO6G6X&B7GZ1>BTV~Ub8sx& zwv=5mhFEgtjO9-g8qoo#m68*N7EfyJD`xYkT~6KEOcId;UIW zk)rOzBCGdX*)`7fOckU0+_F~kA&^6r@rTu}twK)Vbhf=uC}sCT@$xw?yNai^rH@e zZhwJ`f|oVn7qt8ja{dQ3X0^*NU-EU$eA{U7+UScZ0gw)pu!NLKv4L)d@$g7Mz~xzgO9;m=W49V5mArc7Tf z?m#Eo-GCH6qo2PCqEHD5@sW@hMgL6yB{nlTBw(3CC9TPT%3~*V+`rmL(Ws!AgfYMT zkmDN0Hjd-@Zn*O8E@u_2c=m?`v?>gS9Z07+4$7Z(@c;i%#y?sVXJq+zzC$WepMEV2 zFe0wL0}~P$+~K=>&|Im(@B-gLP|Ei|NKsUj_j%TiZzrMc?V%~nfu*BuBmipsTKG=f z+p^G*NtL3oAvZaoBg?WvD-RFppl>xGEp>8Em_#M;s4Y}PNO|cKmgpw4!zVw~%mldg zCMCI)rzOAuS{nqYW>10e{MbK^B#EPM!4S!4ZvX6A{2dSS-$!))jb{tC7m0-b43hgFV?-=}$L0J}q|aaa^FKs#S^kPX z`R7BSfAaAEI)?rQBVzeG$oIeN`TZ?M^x1Kr^5Ks!_=k_^=biqM{xanM_HFodCT0FN zAnL#3ZTLq*i}nA^N0cn&4~(cD@GlsV%pk-c6cH)n*FTXhEdOI5^nZ)v1tHSA?Qly5pz^6k+p-@A zfr}*%X98|I$&INLwS_;`DCVfkVvd%&xc2k#RUp+yc?Gy88okaZjf+BE&91rS)DuDS z=^zUFuMVPouUVJ9$ROZeU!dq{PX27D{||!Ee5*qKE$L-iCi9wEj=kDB2%tG(7y@ z)F{%Y8VxQ-MEn!k!unUX)<15W1y?G)24e9 z;RiG}G8aCZJf9WL(m+=4{gCha`|f6o?}kseySNPH5yQ?z+@ zkC!L(6`!|m?7;?o2_S46zLB<%HhZ+VSZt4O{b2n7xN&gS~qP+`w{erw>Q`g8}!gXQmawA zpSbeJNNwr-UsL@p7J1KNb#3KyZTNja&0>d5@8L_ZFoTwIG#TWc@bL)uo8*cO-EcKTIl z@Vc#}1vBxQbkx7|C_{&$@CqUK@!`M!#s1W{;Naj;o224MqLUC`g?Ibg9R&_b$~?bG zzH=OFU1>r#(JZ7M)NjwN*zz`rU{$96o*)>605dycO1NKZkc1+37zMih0+XhrOz53h@3;Ao-Yz{~!|Z4i&KfVFCb!nC?r2 zwqsquKm@+%xoU<`=i0&oj?QIpi?f~_oWxa=nO%i7H5Rh@B-}hHJ*a~V&UEeC)>(u6 z5(byX(15#HG>DcT?Z)Oc$4E#0<0GT-LA)=rw5wIOqa zzA(LDRdeJQ9T|!gjS$0lTDILX@GFf@Iv{@5-LM_2(uu=EDB-hn`m>Lw>^Tq~8!o}k z*YnhBKAdqMuU}`5M<)Di6>aJ7%H=!LWk~3kf@=Z~7SSh5db6dshsd#yM?RW5qPGoFs?AXw_TyjG5NDD}a@MFkMbOjKJ~R3Oft6u)J5)qjZ4nSL zesDEHERc4GR75Olhy!Ecy{#f;*aSmDvIr*2TnXSk@+ z2?7Hg2I|M+P!>{3O`S+(X*$Cx)xgGdn>!s(n+dYCuqbI7P}5f48wb z?Wc2Fo}vXQ-ST7lJuQ*nQf($vq-51)K*%s~K#k^7#E~`7+nJQnsE(1X=!h1nu81{h zfM_5!p+VCiSI!k#0W&%b(O*RMCT8S}f~IGd@1f($+7Zcd}6s%diF zSVc~O2D)v`TH{2gzmLjG+BE)kho&9G&xA@ivMRF=0lDI!L7OAYoUuDMP~tWvkmB6c zF_;iHyT9mGzf@tG(W~@L6r4Xx?8>v0FfE*3-Kl2SVx-aojbmN+b4jv$c)#s4Ir+xl zgwG8>^_%Z`ov=9Y*<*3Cm*#(m<81!yJ+=^%Ls(J=?4RcNvU$u&*-FId&BlxxJYZbs z-^nHOhzoM|41th+TvZ{RLQb+PfwKoSMG+ja4Kwb^=)TC&PlH8%$=oZ(W(#%$&{i`) zc6Bp=nC5-{HiKw-fr)eickwGH;)OslyTc5@20o+fYoH5s!;W3;HSu?tA&mM4iUm!L zr5Xf0B}$W?+$8YJ*bbM`C6zF?a_mU9Iwe}LS_})O>K@LiItPAqJb^*GuF}+Qyr%J| zb_ZEB$=NloK_j%cgxgY(?GY1Gk1$=~TM93@uNP@6%lUz;BQ7SF%DdkkNKIkWL%w~G z3BGyZuFK->+7Oo`sie!sZT3BWdR|Aunf{>^Q;J~)l_6hI1*pr86jRCWyRhHOTWF8m zJwE2{OftmfmK3O4LIu(#p-S>VbJO;(c>zx}HDG4{_+RFE^}^mP{&JP9rDFGkgU)~S zoc;%0KNps|x{{Ii zlwhpadmxR*0wG>wA(-K{>PrKfaM9J@5cujumf|jA{ZY@5QFhLcR*w+f zBs-rKP8H}<$tBe3N>+VbVCp?BN=^70BL4>Eet;L0$i|;^&Z`wem&6!}%+MP>$Rm`0Lw)-_pA`8w?cj$3v^d#F@QToWe zxv3}b;%auyc;>7j$xQ>J$W5j42Mtq;tQN-t82wn;Rl%hP?~t+Vt;IE^K`Q0+0mpL_ z=M-dR(tS@?e{YEmh=5RPcA5c2p@^yiEu5m_@i{|81D}+nIXxffSApUpkV3f)yEdo8ruWn=ybJfM#fOtpf0YZ)aj~FTFVrd`btVy;&53@T~Wj# z4GpJnnLNYdd#^729%wwD3!n60NWW&$^J)JWMi++Fz&VgWr!R?PD8YCVk?26*hFU*G zS3CMX#~9>v+n|DD*G^TWXd?CQEsv_H7Z)1f`=~q={-STB3)UQ99NPB~s8Yb`dXf5V z7M;<4#piSi3$>v3DP;#$gqC~PzF$*;Y7WcG6URRNb2FQvLU8;1-unG89*fS!kRw)z z3s$zMEi>a)X6a><#Jha8eet^+>mB?ngHKsO-p6tchpvT1w_AtOqG^f19IK zGbBYtiz)i+s(Kby2qoD~Q0@#MQXXAXlL~i2+ZmKRkvC{j;3V2!DPBieS=uTj0`#c? z2Nk~tS;dHVQW-Kq zEz>H@7HxHTWSe#Mc6QRt&JEmkUcZWRtT>|}SiY!-*U!#c=_i$~gefCOx?2*#w=-5& zAbdj)_?5Werc%y#R^f*ns-nZ)RcYZmyAaIqR7aON+2|bZe18vyxl0x4eCP7Bn)=6> z+e&c9gOo@pY%n~W(+iRC@eN1YT}?)({(IZ|0`FW$y3g#jYr6G*_HVkPw+_JR5jV2; zy-De;3*9TvoQgMH@Q+%<@uH1Da9;oFUymW?T~aYRn9fe5j=S?14On*`qq1^*b~&cN zpmJR{Y~08^kyyis!%(LiU_%>0qT)x9j~~S-i8yKkY^;mLz?W6mhUmm{YWO}-R^un=0{S%g21YB5x!2^a*=OGLrdCg`Gw#vW3Ib^KG z6-}QppC5@6aJq_seD`h@7#K`6t`r&|oQ@M5_l`Q?4e3Oozyw&4M&@Bs*9_!63p?%X zw=}^Q7YC%|3tvriX^4QXROgFwqgY__NEZlLf=@Atw&KP z2t+OHvE&?v(DKXZsa!#jI>O{}*JgJ6QT?llvFz7q#Ls*jmg(kpJ__csUb~+)c|Vyt z7QkK4+gS?gq}_%m=elL5f7K}h%eJSW}HoNO#KRX~v*_;W(quMeqAh6rT=@|TVIcK?|5 z{dEQbd|V4>`{5CfofH~;G$C;F7wp0B1t}O%wuwae0`e-ut6~mcgVEBD>aV{bE5MXY zY=r!9#G-}@j7MA**?@3U1S~=+(9IC$o*H8p(!najtb+C;5gnc}k%_H%-NPAP>W|Hc zNlFv#w2adg2bEck{WQksv|8@yWvpAXL?j{-^KU-U_(DDh+jE#%%6lfNx7W$w zbzg*p6RAB8s+@2`^b-t~Dxqoz%-labzqy~W$H-3tPfw+2W`trEV~t`~z)+#czfPe@ zFjb*Qu3Lq~*Du_Ui(B^arwj84!gRnSLb0G%*cw9HVsed$ube7&>=lKFbKF{?cr=Q* zx~Dvl@9tBi%=(1x+anXzS5 zv%Q#~vfuYDXW%qCEvj)QAi+1s?djL^ytG?j7rlm`F$e5M<%}(HD-@r3goE0xD4tH*i=W5xTAK#@z8icjxY``KbM@VYF zhWk3i0jCHMBZ@Su-ro$(I=T!5BM=MMB458O1b9L(7n0sDMG{=?`b6z1Qg!uj?C{Fw zUU~}42TTQJ4ynmgyuRiRH~sk7#FxGuLV8=|PORm3rx1@Kwk2&@eY3CpX!2Wqm%NgN ze>rjATfUdxY3{!fn1z{(PrbZ~wjstExRhu`#5M4u27X1J@)-1+cN_?QSWJKpHLPi4 zz;_q`<{m*s=L4kB^t?5H@z2)Artos0)$j{#%mL;ZL4|&dqo!M{Asy=*MjeY~RilX` z9pMnuQcN&8A@%3H)K16_EFxvKIMPKb4^)$$b*^)koKeNZaU9V3F8$k8qNO-Aazmt= zUzvPCyWTGbu!9kY8>ZC|M#1vfG=)0km%om~KtgpJN3CjhKXc(Qz&LELMGL@GrA~4z z5oLgi273S)1TVJlqO<@v3ze@RfRvjU&u zr;XAzEE79SbTk#xNO|^6&|Xlk>Y#Pgsll5S-Gh)I!cRCSNV5bawwO%y&z)o-J~#c- zz>=X4K`0!HU-a;bcc z?)B+yt4-C}@jPx# zeDJT$mba}M^9fa3lw^@~X$v(G>2i&}ZO)y*xx%hamb2uZDQwCBp?%qpqTGr9++^dZM z@Akr;MK@(!SI+{rr?Y#&g;9)cvHx#g;>C483^dpftIAUtqh<&gen9(v&fjR^RMy z;cd0);#_EP%8qc#(`@tUa6jl~-5#lLoy|yI_)z!krT^# zdS2d*XKI_rCO{wG!IbL+>Y0D~(}UP%g7#R=6k-e-kGyp0+Rk9T31N~}-A#kq!Y-cq z8Szr5k9k=u}$7%Uh#j9z8U9XB(`)no> zFSS8bGAp#ft7(K0?JMooy+u8yCrZGxLg}OkKk41tOBnhh$yf!ad1 z0M7+f^W6qizpF#FKxt5Ud)F1ys2{?1I9Lla(*0Ty98=81QKokupUf%VTYhSr7pESZ ztC3qRN=)H8M=-1$KXAz|d#BK>o!Y&ku5j)bXpifdAf>3^;MTUH6C{i`Y9dR`%e&E> z&xuSW7&{C~Qwx-iON_kselSObaIiwlPmh6QJa7T724qj0Hw}`^wQD$);AW-CdvZ!z znK(BXsIUB_vos4A)vEBvK@O|72yx2m{dSVb+C*Yfk9jDFtu~1*TuI=`RQ3f8nfpa! zG8VEb35HI!0K}U5MQ~HjG$a^xohgEZe;=#PmM_m|MvD($G{F0|*axA$NirDt{yF%{ zBTgCt1uEdE)ho0vXK#mOYb(J={Kw}R4MWO}r$?8dyrXOw;GWU{eq$(T(i6on!F{{8 zfVtL0X8aH}MzUbzCN0VgoxcidLQX08U`r{O3`;ebtn2frqZAAd5(4GS28+rxo<(KU z#-}nYFg!Hs@?Xh!L>sW4Pi|WZ+Y{M{O&jY~Uf}ykX~qh41vV!wqu{DOsWRbO?Gt7wW}3 zKng2uFv4{S#{xcOs=M9O<;YZ6>OrYxsSfy_`@30g8F%?P<^6qng*LbH!#CI$lIzcA zQ~zoy_#e%taxyUdyHM%_I_oh;lnz}}r5uYXA;AQXiK;2>mMsq+)$y-D)>G=L6H?qh zz9SI?eh|ZFH8nJ~v=5Wz^zy)0AXi_$922m;caQ15KaZ62O9!5w{t?LF2w7r8m(j!b z?dmVV4gONrBN|0|#lCnWUvGSIoLQsu_VICEyXf`4+q#fP8yE5D~at@OwX=!W4nUbkE9 zua~`#yXXDSDbJ_k)Win^A)rIy(Ks3VZPN>H99?JHLAT=%V}F;+*iD-+z{zv3cQ0;q zcOE~$E@OT{!Jvi$biM>Y^XW~%m@F#lGkEj|02|OPs!@%T>M}TU092nliuV-+93baV zfwU<|68!Rg@wI!i3~iCyXP+ypo2C=|Mh>Y3iWdCmgXo@z!9*4nBfo&c;ne_1T$Idn zxq-zM)YP`_4c$=lcA)Tz2_{TU7EVc`im6BNp)1*554c~7vd1&X%nS>u2S;cg?Nx%{ z7cbP{_11kcDHiW_kXDZxg{-b7qB=zoGocxc8ey+z_AU*7)3rTVKhOzqNoUfs<7?6I zM2XrsZJu&rv#TN?l>-T-#Hh!fEshwUc zx~Tc1zY}(ubC4O(eh=xs>=Bz}!E4Rd<6&%D;jD`|;_;lcaSt_=aLU-gkX z$oZZ**uFNzA#bRAg{QmsV`b>4GPhi=VSIODCwk|Q{0TD_dt)c_D8%WDWNfV>{jVwO zwEgHWH=$xzJHj}HZYfw@RSS;CB(jei5_sB`IDt;_-XsrrV#JLU`4L3E0^z$l&z@b> z5k*t#=>b=cc(M<8S|3pxu!1Ph1|lALIS74U!8ujdlmu&nAc%*PfqbAHNP`A<%YMs} z26=#Tf=>~s2~mj08QQ@+z~FsWii;%}+QQqz;0eU(^Nb^|`^xF_>=DU0_W1~JC@2M@ zg1;*2py^XS8(2iwUr%eRfIt=!;v|y<&8Xuyk2A8tLCKnjGFZh4l*cn5^-^RBK#7Yk zhcG~D&4nTUP=7j=%^|MqKUs(1p~zq|+?!ES!z+wxEJ;SphQDK)6>$oih`^mu87^ol z&r9PVzz`kWdmNMAW|RzKObHJUjA#2UgVWUC!WauNG{x3Cky?E!k-sou^0q+gDO`OK zA+Rt}de$NxmSJ^>=zW4fUO}%FhD@A1=A!%g)K2k{cg!9Y2*Dd8uZHmToPZ7i`Ri{#8jtz81cp9WqY1^$LSBG^k{rZWC8Q`k{H z{E8$q#kIBn^J~HK4nvWul3U-`*o+tTnAa{ogw@dN7?m~0PU4mUZUbI7ahmfq?NoJ& z7S=Ith$43O4a70r4MBpb>03XUtr2d6d^23y3jziOyO}TkJx6_$+z@an&izd4UwOTM z4D9SbCFcySMa8T4rgh&Hgt;U!n0P2!?kMWXKo<75d>tvn6smmS`*v;ZUJ#LxLt%P`* zcx1yu6FOu!@=@m#psTw%P?r<>G^6V@4$)DN zXaae827TL|;&X>@oXe_ed7S^i?o(_^CnL|t5-z`klXdsNk|mz{8q)aL@!K$t z+1oHm8-181P9e-PZXwLT7eUN2S1_iac-v7u%vt&Y%vp$TGKG+5{sS-)p!joUMH=`L z3M_OX{#~;-IPj3+TZd_!P{cAN&Xp?=`f?v)(2&@3{e)2ZhC-adF+h$7ob$pMU=by^ z5=#(f()&R%k{5Mw`ot2j%wk~%rq6OHFWnpC9e{hklCkk>`6B0YKy-SOjpoLUo>Bf){E?;6POREciZ$S>R{=a;zJf82i+*KRCfvTsF4tDweRd_Abj)t!Lu^{u z+wKckVDoo71kG5PD^$zXM@_9asIowN;MkM-#iLl9uK%zgdLeaC##kD7yD+6XWBB{i zO|IIus3!H3jGVR&4`8YC)R-iZpJ?8O69f-yyrnaNd%>)}>l5acc-@E1oR zxr_>cJi!Em+DTsr%|v1v7lwsO;yAv_5ywgA&ZGTAGbOBRHK4&RVLVihkwl+nP zUbdk|)A4={G|=rWGu#|o!7q-tlWBMBhhY+k1@x!&I7Lm)fy1rC$c+QBT;0!O)5{MJhg7+UM9iCzCY)pIiYZc7`>>_4lq$ViNwndqR8Q)7g`hK}LDNZ6Q zb>f&%q=L|RYn=jx=1?jPB_I5N7uT{Jj?|0o+GI!tcgIi2xM59>u&6A7ms}QvjSgFQ z6-$h+!_Xp#w86vdEIdXa&G&AlA$Bohil3wce$tiL%#AR^uTYG3oKO;khSu4wKdy{w>nm%#C)1S8bvueK=i~LRbRX zk!OkYR8oJs;*n=fWY4sD^Th~VJ;X5R+JjXpB$UPj?|Si}hQV3?hIH2$kUP|t=b*IM z7vuc#hpbc-ume$6{>1MXyPRRMSr5ZTy#7308%XloiZLhadoNC;l}yM}-GpD2cxOB7 z{iiC5m)vRs@7{F(Oa3a!~6pJ93HU z7QUX}w|1moEN*P z&*JK{!{reaNd`}?MZi?e0BF-RLnew>@m&j+7QJ!?et>Ivd@C)d`ARZyF+fL&6dBu6 zqKFqP0kX6}<;y5VC6%$@9F4IpY2Y<1>F;f|z1+PJ!l#LKr0CTqb9yw`rMVjmqE0{> z6(_c{mVL{&Kxsfimd~sg@AK($aEDr-*0s_hIVJ zO&n_<1@4t9A?_8c80V&Cr+qUev2!zF+=Uqt$Ay`cgyurpKniiKg~pf`t7=^9r(hSB zQ~8yNB^>Vwbb=>nO?z)it&o29EHJ8VtPcvhO8&)g0y3g31KTu-SYzhm)k9nQ$bQDq zFBc$)AGy9H>6bctlv#6|8%G>y6ebSd8MmQS?tM~Ag5$#yl%wg98egOz-OpjCqhiqF z%oNCaI7xRX=S<@@n|dyMPc%Th^QW^c!yE3x%5GBRW$$N-HrGVhA-vIwTgtjSpoW-EZA1sLZFamVFy@d?l5 zQC9Jsg&8Z4jQShvmYc=Z$HHE*E=aCn*DIBTFd5<#84f1c8n-xG@Ta)A8KD90y^hBW zxa)~6xh~A4W)H*0443PPC8EuNMVh@#eAuU)3#`%vrs$W6ljuSz>1g3diIuC;%aYKr z92t3};0!)?XIqcbw2@nb`opse`FPtRZ7(cO@VgjJ`zqE>ZW9Y}vH@BwH0EMZBbF*| zGOnMg77az*B|Aa~=N+P8hNCe!A{d3QkfP7hxd72bszN8Bl;_0d z&!2Wk?N%Zg6UgE5McD+=$ZFF?^Kc>Njo1Tnp%Qm^=KAt0P@ zNK5B;k<$pFMWVXO<373LQg3kR)B9y;GlC0V;^x4g_5dKIOQOPVbhZ5JK-4SMP9|2= zhj6R_OE!s7OwF)b@XF{KKelP7SyRAARr)4{)X=KG&_RhNohJ2*mIetxSdwwiAH$=w zt32sP#kY`|Y6UTESha)iNK_XXa5vzyH?lURm=}^)9zc|$w4OKoXD>vZ3Glq3fs7;L zMKCgh``M2g?{o?N$1mJj*&5t632aob?{JSC;y5(tK;(?po|XQJp_Z{>mFMr24cO-4 zKo(&o-+mq8Xm)7_B+;pvCFaH!oo%fVbCRJmPRqS+SeSH=ya>>6@sSIztlF%6Ot{Yk zLL!o838V4VL8Z7WNLa7|S+3Nhg?#WY@vz`n@m&hqPk;d9-fS#+nc3C3_sX&1YjP~{ z=woM+AL-rXKLt)8w>17yEPph4AbgWO@s$sQE{l$(yWU+0h8ZUq6Af^}8s*3`V>d?_ zxm~YhA?zON0mF&s!6M>Oz83deA6IxP6f?Ld)Q3~x1LXM}=-JuKt-&2j1ddI93zrR^ zHrFbr=d%$C%3MvurnsNS`I@bu_r;IK;NPz}RA(_aMtJli#)T^b$L9)3Z+3Ogl?r9f zy(>M=OJ~2GPYM(4-%C5K^M|B3@nfCL^V*nyf0)oGSq}|mHMRAP7;A;70aw@NYdxt; zBoIAg!gc*QYFVEMY|<`Gv|xg!=LlW%yz*d();ykUS~n2q4(zS!~CY zY7{p$A`XS3P|(K1#$3Kd5Jr&EeXE0K(p$-C25H{;!p|xSFOU>A{EV`{$=fh)D)j9w z*V6`i)jH6%bb*<2b2SlsYIV$f!~xSZT7YS*VEg>#@B2bZH2XrrUgtsur01Wmq@%$p zE6LEb$e8Gw2g-C!FtyqeFQf2vujGr(&_VYL&gbknA95$Js!UHW7dtgSf|*A$6F?3} z{NyVa#6u^Yx!`K+4&yiP>>c4~CLadueof!5L2(zIIY4F?jSD$f=B{G2h2SDfy7tIVEDC;S={e>%g;*Zv5qk3m!Uv+%bXg-a6Zg zn<96yX4EZ&d&C6ZRW)Ipx*R6SRD~{viLbJ#ndLf_-|Y8&%67z^+7VgC>4R2GW>3p7#yAcq+9rMF5%)qdP=%w?tJ3A~*nLvVDJ+zygd7WEt~GT*U;{-#B1Mjnqe_CxQtvnkppZBRCA z_3}DUynA}Pc3)IrNvm%Ng6{UewCma9;8J$!etetdG8Dp~<($q&VPYi>TO>QWhvaJQ zC3^8$N7VsHFzX;hrEotdM|#W2sOw_pcaSMY?uu#(AG>;zm>YBzy?I@J-4iA1aMC05 zNV=x;!;IR_vO8fo1TgUiKCcl77?Ogg0JY@HGtj8vC&)dna!VwhW8A!27= zv~1Zof$p8rqj>06s8D>=D$UZRuCaI6-rwd>hu z-KvHQcs-%4+x^OhoRVuq=SoZ3WiOEX(!NvOXTCj!gQynYYqtvBhS*|>x~1I1l( z;Vggj8@)c55ZLmz0L48aSgBcmJ4-&%`%by&F#f!^FzVTu=T32AT>M`8sI&1Tn=>!| zJ&IhgfMzM0fUtd9{E~Hn_(^aD5{W1nXDsefTc=JRd=57x=-5ai4es-RC*14AL?RPH zsK0?Z>n6xtq!4E!Q7JVM=dlWdj(`Ybp4NcnL8!^dBGP0EF*e_r&t`xq?BBl4C2G)T zgA$IE^AB7Ai5)HU1lCJ~TSg!q@^?MEU)4 z`Z&^yP*T&J393fG2NIgQkl^C8Es~%47Tti!_;zpi>!pcF$>l-fJ(Y6~#e%Ckjn=Dy z4T;?bqDYr>%BEwG0=zjjk?0aN+2G7~@)X85Wf~68+t4_Y`Ndih&Mc{Z5#(Zb6bBr4 zFHYM!ek| zoCtok)V++HXdYDGD!LhC&zBRV^{-BLezbu(`*-*~d zmQhTwuhA&A7dFqfSBn?wxIRzQHj|rI0SWmuM%vwI+>)9LoT#oMskt93;20lg7kua(MR> zdWb(0H)Sg9Y5HgJ=cT3WB4fE{z{oa~t1w zCyC-*UMSm-@e4@jVnwn`hGZu)yC}t&yw$5XJztb4Qi}Bx>(G5W)S+`CWvtOu zZ7;N$mWtB0)`d)xmXK`J9!*P6l{VzMLy9YbRa`0i!kn#hQ5@Z(S0en|d&aCegWjcB z8Y$UnSfslo*@H8$!hs&$B!PahwHeZcbw#^Ebfu~BY6Y?+spH}3)78h%sj#nXeJyJ=XI`VDeBF~hQOpbI>kLW$(5MHvY5EMY26(riaa1>)$> z1?HGfU26ZUp#k4HP&H@I;$^f{TgYK@Uon_OpHAnPMy4mpoNb9t$D^XgZM+0mCo!h2aihDGxbhBM20n(wfg_d%}PQiP39 zJP(hz4rb?FMWf^lgYGUqtH>KCUVPy@}gEs6{?&e)1w_6GJ^GO1&rfwgZWzhSa z64N(1;>#^VDi0>a#$irbC6iZ*AM<;P$EIUdHUc`zWsBkp3b&kK?ixy{!pFID%lw@el)j@~kVgeI&nL-t1d!+$_y-p6`Mj zvTW8WIBwyBjj`&2T`^R5!N%Zn#>UWo&ZZo@(cCF5tp?+_ZlkAsXwFb)&CY<9)>L^8 zF4lSu-kT!(W8LNmA8Y9H#U-$2lp}Mq1zWW*`Vg5X%gZ74ZQgK>d)TKX*t*u zE{oj0F6ZT%IM0-gJ@>s=Y*+Q}7gwk{_EhqrH^2u5MTvW=>Ro~w0>i^E6}B1@0t5-i z*WaDYYW{kfaB)ogiyjO&?SkdN*BUzQ)7d`aOpr^9X?2&HA`j4#xdb5$Oy6cx zz+HMUUl@G&qbrfMbdBX(ma-Op9#$ovpr$vou8X>!EI{RV$t|NI6puP^G?SZ_ez6so zGPrOyxl?=un53-)Il=0(U!(y>9CK^wbMy9DcR3X^?iw`e?a#mw!{2XnVhXDoSbBv*)Kn zev4U{@h_5nV{jq)#$fSTez?hJ!N!2%`u_IPA7ZYIr-gwN3nfzAah zsm?756-J50`#`Pj{-79zSWuE<{z`&U^`TCXkJ15prcqUFi|l-cMHuBvTKmx6 z&%c0fstQDGZ>%%fU@$c`KA?<68jq}eQ$XScPAZl(|Bcor31znI7Rj@sT%^0E8^hEj zc-ASZZ7F<-WH7yw(R!#=q0#!7Thi+NbAU)$_)#V*LKrkQD>Vpy_zSJe$w{|GaTMD| znb(_U1kT7GYgvoMX0hv|eji-OW`r#@i0e&$lG=p98F-+Eso+WUq)v@O{>tA83BQ+Z2jrN9FDSb|bUOM`fG-?g|LYZ@9XVf+b$@7H;v+&kGX5aiRerUZ zwATT2#N&7X%9Vl&)ef=s9HCEG9-t>dr7KxifRleP_P!-MK${b@y)8?(S7pU0vO~*S`?g!7NDm!L37V zv3VRNaDe3nQeJ?g?ht_~pIG_z{L+a^cHED=%$eP0(&k>gz@&KCHOUec!By;|va*vYs~u3wm(tZF;ouuACojbEX?QyYp&87%g0KA>$NAbxRXEDBN?JB5fgvwieR>XCDXpsCu%*B2!%xgnu$oZE#> z%#+L4SmrIld9YIBI@i9k?hgC@gj(k!F1NuBE_d!dF87pIc`lkOVhfv{)o$QnfbGaN zAga74GFZPR&RB+Y5T-)k%=a)DmE%H*bI!i#V1RtS{V`d=4m{GJr`9BD?3Jj5W8_tQl_)XB7#*Y~OX z=VzjJ{DYn26w&eoYKd@01J82gookJb?%resMc}@)d<-w@VxqB^ zL;ZFu-2_odZ&C`}luJjjfrvf->{5uHx2j~*9hscV1kZPds;^?#46I4?giRTPI!^k^ z^7RE!roKy$^{11%)V^FaDl{xKUHCBIZ(tEpiXwWv2(W%sU|Kc1}f52ZU`>v_D@^QiJ zN5+pw$Nf{2zNd%p%axd5MbC`+Jw5K*q5FB+f+Lbn8QkoB=^NwBxfcmIy+4WxxM_s~>vHX8r%sQnrQI@^ytxO}fZQmL2&<&B zdMsKNOsA2@BMP1I+?`$ED>)d#cW`Ev#XLwwl6CES2zVfG_jz`evHy&!!+v_Rk>qdD z(!%-)6){0LyoR*|8w#f0(5lqO9J%WhgGjyyD?21@F>2iN&0W;AhMv+n^$vQ-w#q)z zA~GmE6X8I5h8Nv=gQ}u`N-cs24f{s?@@Mmot=ySc5{`x7SZ~v`=!)wbT6;n=97+UD zIW$yqdb@FJDTGg~K=Wm+yd)=OZLDk3(va$kfqvTnFsB zdMtJ7eJ&X3@XKnb1?{`BYN(QXnsx3jDXLngv?!0r0*;lJjhIn%j$`5JaEMk{RYD6X zxaQ5zu<2{0SQRJ7WjT&vZM8WO5dumzvAtuL6m4Lkt~GTKU21p|+*|30YH7s5tRKrO z=Y;VB^2!|GGw2qXMB3U~sNJ!h<4@nG_HN})F9ArAm&AlG4vtnDR~YnQ)Z^#^q{y#L z1oYrKY`Hs%o>do`?9cZqitkkrUudt(iZz2UD{_7}p{R~*#=8%Z2+<4x$=)K8 z&rmSg>ze_A73Uw}VETy1pXM9Jix?OtV8qc+@!`iAp6$6Wc@)5Mv`)k z=7NY#=VCg{HPZ~NZUWaTS}HfHn$%a31UHcUdx-*B9)!N#fK{DBJ%RhKLOgvXgH*Ke=i429ILH4{h{><2!)VVZ-j` z{L4)McVk*f02qZRIw$=JRxS1Dc`xSU`f_^b95=h;v`~X&Kbs`ATew+)HhTTW*j!uV zj^j$<=>1#)>`^S9uhY(2D3VN|R)wYH`RpG^lxnlA$CkAbBKQp=sNI(zpP* zMf^aj#`g!1ogLH2Yk<8tdwaxaNUvUk`5q+ho+Hp$@k*EIU+{qww7z2)S4zT=DXIam1~~YZubnOku#ioB*x2mzITs(@JRPU}( zEDD>LI64lF(ucp58Qi0T<1C6bFbc-TI`_=rN-|ga)z!nLMNXpgV&{=;u+t+|7x!~6 ziGf}|8pGSh#R5z+4LE%enM;XF*>W+VKlNLk?I#{bPp7li?kus5WX&=`!-w-l!QWV9 z!%l8s-3ck1Oi->sVDp{dc%asf`Vf(tq#MOLMGhob-s7LsK&MmAv$v|lp87YsIvIF% z3f2veVa?qwfVbF0KRNDZbsdjd*Ae#gZM+`VE^N|$emzl2JfBgdXEp-KM;P%SM@b1h z!7J)|w~=~P2!3|7J>+rJmv7es0bIJ{V2HY+H?z@9+ zpJc&G^#s^TH8MbHM4r$mJi+lu!hDL%k=OpRY2~Q+tr$7hG&c)YhKIqyGymNKXUw+d z^45feyEEI4+2&FeuP0%XQv^p@0Q-A-d}z!@Xh-Hrzx>S--0Xk?R$0LtxT+D^boZT8 z_@^#j)!AItCupRK?V0%*=**tsv3GuxV?75L;01!zS#+y!criO}&=(ugnVT49tvW|y zrYu56-*xV9bQa!duFaHAK9#DtI`y-7UEjwpePV1rPfq34_lk0;Us`0WZe74I0RI#T4RE*mJRJO+fRJGfIS_>YQ zsz=7~0`~*RxYVj(NmKb|vea9A{1Kshbo0_?GwJvR3$(Nc`NeTo5A9TnsYxQ%Q$ky- zFb_9cg<+-mqD2gaBQeA1H2Gnr#4wMbJXEJCRl{f!o+WW1!qc2WG$&OPLtTRw^l-`H zMX_djQ!ra^Z*h#N5qWE?_44c-67N(RPgaNIhwsDYiuurHq%zYx9vj;ZGw&0 z40aC;l3b|qX-jD(vDA;!oLq)+>4wYHljtcjcAtvK6FRTK<~vBXfuiyS{ zwu61VDc0=T@-`u{Q|fHBm7LO>1kFo1y4pL_CBa+ZnM{PexHIa5{d9f^%$nQsJD@sZ z0sueSnDizBs|jA@&aSO&6Ouax-h($Ke*^r6+{jBSBSo)E?GzQg2F<29ifQ<_)Vu=( zVEIjSz3XuGX?KAYA%xRQzV)s%?N9z(*_KMNA>^d)&9d~Ohp5}Nyw6dy!@n=bGGKP# zwUs5|c{Nzkzq9*P%XlWVQE{JdSwZ7#fxCl*s(4mp5iTHy@z5bHc|mn)I7#N4Mzx=l zP60i|>f$=C>fkzFFP39jLFG5kVGVi|%uX_y zeG2m4Wh7ciIOyB&G%fD6&q}Vp7EMZzbapK&iD4WptBo&|5{FQ8o%n?Ik|^6Kno!D3 zM#APD7EnLf*Go~phm{AT;e;$+CC~9M<(@}S5xOx5{1V^V(fwq>M`KstEZcY7Kz9nzL}^kpECwUi=n4YQb@#iUu2{&j;!Vf>A7C zs=H%WV6V)hqvX9z(A)8cA#ZX}TQ#0tZ4XvfjLU$bo&ixUk)d9naVz#P51Vf&Y5WriFJOanb3+1w3>MPs@ z-YzjI|1+sq!f<7ko22y5Q2^d8$CLY#6x(F`7bt+szuXRFOvONFG>|c_E(U!-#z3mg z2}KTp$zr$y86)V;;T^{_GS)9Z{mOCKnX(A}`jOfv(<|YNgciB!CaW>p?kvz1`^3QgpO4QZaD`Xfr5^iUSx_P28OU3{p10 z8-;&MMSe@AfR3oe+?^#I*K^ZvabjCdL*9!glTe?UzD! zCT0K!7c;OEBEYsxY@MBej>dmApyKT4V&tr7;P|tY5$IFaz|aZ6paRSAs|>)z_On?a z{^jrZQ~x2-{DhPO!bbgiDBvUhPNx5!IDaF=3sHc+)_;=uB@YB-`$^PasD%G_0{uq! zeP{<>uS z?&|&@3CH{w2*>Ev z+&}$u{|jmx(9iPku9h``UY7svX!&pS`a6|?uD^fz9tTpBnF9a}e_dc${!kUM{soHt zR|m=eDS-iww7*ddmwLwlDW^0)D|fzvQ_9zu;Pc+XYT!-XMe`2|L0r)a)g~301Q9-@*;fy*BOoDH~ZlqIl}%IIKuHSQ1Sm` ziuq4D!pQ~zhJU8~A5CfhF&_LyOM>$cEeVdlKzGjn9ZP}}Xkh*}`%7?g0f6D3$^Li6 z|L;zZTt7_-ScZQTLe4)T#?LPN-R|Ui8IS+VYJrLI#mxTA8UhZ%zh;vD-CqAw(flil z`Hz$_un%0!0AK)e=q1kr0EWM=5||kOaPH;$3+!NG{Life{!}S2F#?TV;PvzAHJF%y zXzjr3w@*MzjOll4OoIt%WxQNJY4iV*bN_X!{r|zmzbW%S<0!D4=|y~i*T2EvpB55O zGX8P6G5z5>@1MpS(@zuPe|x|IZ4Rbib_dXoVgf=Rzg+(w6aRG3{RP(jp#}8USoFd$ zpauAH{S-*xC*TtFcRLXHi5>XqH(TN_&EHHvA&CE#nSZz@{by$Wv^oC+%zSy0zo-`f z5?}tzdi@iN_0NXU|A(RT#|A7D^Iy@8|0xsp-=OxNOhRlg+amwgz6jeNnlns)xWfGx zDf~l&#_45W$_2Oy1~da?ER3B1+CS$rp!R+lIe=dp9q@B^KpDXNv$KF-iVg6S(8_?H z2C6b}f9r3XR=?XUzi(Qxy>#VY;6ftw|}>InAl%b-EVdLP80?WO)X$4a61pc_z(B~ zi+Lns;A~)RXZAuAGvJ0L6Wed|q^OD0%Ld@j%7NNM-NMAp#8J`F#MA`13HaOA=C9TC zzx)f9LDa&@-rB%J)XqrN!r9sc0Ng$_`Dq9LPUxRYlHdCL%VPm>FN&Fs3pj56yW>Vc zHOcx9NIyqj9$uK+*avP(JyfTQD`exoq@mcUa zARN{~>?_3g##pKV=2dt(s2VU%ae`}z?+y@9$g0daB(?yeirUL529nTjQzPCEDb|^x=Wyt7~6^jF#3% zg-y`+%^KyV-uXHx4h;v(RcBmMge zoa9e$XVgtOL92&eF<-9Ft7!db1*R?=FHu+=6!~sE|~s1v{wO$=#a>x9RTOa&?=>9?Oc!`j9X5; zZx52$e(=N7 zI;K{@IMFP*Y#{RGov{j{2LZoBL&biVZW{of>6NVm{$bOnfBCDkF2L;;oiIx$t{@aA0a%*7U?-oq2wuUuMRp*sY921B zQj9~&d+L6w0rbaRax0p{ z&Z{bE$|Ip4z6NXw7R_;N1$41YY-lj0-c>6v1UO6(zQ#Iw zjUn@`3QueyARWY;s&4;hPc~?gr@ZuoB`i!s+^HMrl@t?uBtUs+e zelownlKd9*Nk)tSkwi3Mj4lNRB3G^X zZxieKN^2kdA38jm{4x&9Wqrk)?LN%r7kn%vqa<&BI|?q*x@20PBG=0qpj$NEkD3qO z#MZW8sxY^LpY+fcOL{K4G`kLSuPtwBj`&WCcWpt%qBF}haoCB*q__ty>j`d9QNUyu zoV>T&FJJxw z8pTLfn*Gs7mZWLcH#=K#Q4Ya0def{Ty7cV0>!n_54jxU=EnXFPVOE?36@!>hOBrl=Y8#+3D<(%fI-})ZRXk~%!JqK!#T*ZB;^?CNuiH(87y2?_+ zk(oV}uFPTVB6PpjM22_mM-2j{(H9asYv-MC8;_pmEySx z*NH~^K-#Z zkn1G~+UXKkJ5i8T*V$*H_091qc@NdA${l0YVEORbn4IUw~2M9_nxwCy>+A*8+$C86pu&xoqKC+QrU=Vv{;&*?(# zHo)#hq0~B|U+!sqW!pz^L)#SRTeWOg)nP*=K~8f!`GD_{d%hpUVTT?%fjp-Y-J!AUH8i)>ugnZdObtMi z3KxfCD%)G{j?1t{>m`SE-h&->s_}kDlI9dy zV1VR!LbN%Q-q6l~k!CzFf{~~USsYxu8be|Ityk#MoCH2uYK9m^eB!2+Wr50`tE<3b z_i|F`1tsU22&Ch;V79r)H>bD_XsPa!ASIMoar2wDXHd22!Fxh?nFaBci9T_jCcf5g zhm`zjzHl6ICp@pa4a>VNoej}+`*?0}S5~QN;&P24JwgKqY#l%B?*X`j8zx$IaqrC7 z(<+P=WO^o`_el2G_P}l-J(?QC@OZ8y53lC3jqFY+Z}9XPyAT8{nb6*BsF!!BxWgT< zdV58-!`%~$3@|c>Wk{HQ@Yn?6L*KG^M7IjH0rXUgX93)i>XS^)?3prH<5s&z7l_Tl zwndA3h<6~5DLzu|Cd_!<(sTG%$Z&O3iyi#&<#BqruMuKk4+FLzU;5q=7yNkzFh3bFXACdE4SbGHg{?YxRv z`succNAX!{Wl2OSlC1cA>$FhLf^nBAVmb=GSIS}FaOxz2wqzS&nO*^~n4~PBnyd4# zlLXN|x?kcW$92B4A=Orr&FV5lFj>#-uodl>aBjSK%|~$j!8DGFZ_sprL4{#P#-}`I zaaWxgG~JvlQ<6v@aNnDg4(4x^mN?@5AVme=zu&0IeDx}od}p9)Eztzl{jQB7sE4M zh4+f`b|+FWtkB}YA~g`igjEXjl!s}uAd;fLjdfln5Ots* zJSEZXu5izOEkQYYqcA4-NX?G1bmRY73XB9;V3kGiDzi?={VB~; zG-Kp%E#W3!SsBuP~ypRQQiJ{bJCw ztMu059J)OcH}D}H(+*p41_f!dWGW{FJ~1WT($b0w?4VvOgN(S-hiZo++%<;aIHFIX zUFN;EDY4d$Lz#4*p${h_Zsr@{~@BFmU_#Kg?l_;lqtKK14J^$9HbZ zxu9Q9Sa`u`Be!5zttxP05$`G6)R$^F%}g7}$ZU2nXBgO5Bkvh*YJYCFpla zP8>V8;#va3=K^kgMB+t1c)LM{DgEv$73R2jzo|_>OOm)XZk+5@Y2?hN?$2N7li^IU z-}VojJP2ptw9A)B$^cy>gH59s5Z@ZN(hiVw%b=!nkWy2_sHem;at?*4*j%D-;7Y=_ z>H?O|oiIu$H{zA!K7bcM&udasQ&)Gz`FH9(GXz_9RmCIi?FpLR2~I~iXQ1+Yq@rGT zPc(%bZn6mXcb}V3jLQZ-T$Z5@7&TaGs-XO~AR9qy(V+Z!p%B#wsK(hB-KuIO26?#c zaBo-T@Mnbi`ThZrGe^kM)PBEXdOsP&<`y1H0!Gxq(`;B{4Pxd(*#9x7@Od0L!e%slV_h29XN!=pMV_-9ZVsjbhcyf#9To`+eebE9t|!YgI}y}KqfDMBXDt%iw&ER1zNzG<#V^!ANYn`Utg3gl}Q-JPn#cmHtN_# zryG`+;>SKOBp5tzFlYCvF1Equm-XeYcLwTCaKjJS<<%!fosH*4)m^w)JccC=ljFwKlOz&FJD=GLuWh(aLzRqahHpmm*S?o}|7|7X8BX-_)Q2&mEVj!pwxDfoBgkmJ|171ST2j2i?^iw-VbfG7N zLB-+r4hyPnJtJ)Crkhbas%PAy{7B!ZHL4B0T+pJ^Dr8}D6&V2RZN7tVP z`SyVyFddk3vumg+;cFxBf{L;n* zSp)!WLaV^_YvBplXK0mMkkchlf%h_uQAA%~%kDq{m#Qa^<~{IjL{5zH$9+0F{Q_OQ zI^6;yc=X%Z25o72;W9U78t*l|i0DOVS3-uELXNwH+1f#!Zuxb>JiHhxh4EG*#4Ove zlh63f`#{^E-fS?pLCvl@0;AGf7mfbwRZpFc=V&~8jAx#tRhlPi+isF4>Lf#^XY`?O zqXIpSIwJx-a+W?Um0Q{Cm^yuK8|pe^ZblHct1UIkBX(V=ZE%en;%#tl`Zy~=JT;NN z{w>uRz{mk@CFq?!3ovqkTM4?KdhjV?Re)jeT%yxrlLx@c;Xz{jh_bb7J5pQ72 zO`kiq+qpuu*2r_{yPH0ZfOofj?%>y_KnE8;Hi!)92v>>L6>h+up$|>~z^EqNH?Xfd z+&5GpKfpJ%eU|R<&HbEz-;KO=Pxh_6b(h|aJZ~7IFOsj?c~Nz2dx)**%{zD8%m+T+06Ab3 zA@}h10U`ai#T`-M#O;(f@8NB0&Nf3{M0-GTbr3MBNo)^zb3*2eS5jW3 z8}ifJqX^v7+M_s5;CtLP>8*Eos_}Sk5WT`VZV(>`?9Ptn^0(ieVy;Ac zyQkarnYkz1_4%*~yuZFVxWVVSJ-7iqKA$}y=U=T_1MqKFP0!X6%Oc2IT&B=mrJqX6Obc z`#jkJUhgD%Jc8kND0EHc36&G^EcxkR(s#0mNXh#SWx9yyHc{bO{Bm#QVX(-z;_jkK zE&Hi{f3jWK`|eGt!n5?{9`N+~W0~IVMOUeUK*8OG$e$#~w^a(yM7I}w&wc!lD$_;2 zrFR!gr3x#+I$x5HcNcG;FZZ6ovfGZH4YHpWe7*0U)v|q5FZU$=F?l|id~QGAdk5_1 zOZH%rL*BfKwWhDykB`EKbC@uo=yEF|BRKD{M!rQP2*oU?I>N24kE95r zdXodGpnzw z23FO66&<;Lm|<>p)0v+6yFT@UiNopvUpv*i2G#R3D|#Uta2Mw-`%^~LfmI`nss|Wg zyu-$u>&iJaxKivc)u2T<6nbrnqpj!24ssTgcAB8qE_SgNV7;1wsZYz*yKIeqJ?Y$|0DWZl?1} znzrnf0mf^Pc|{F!r#xiXGE*r@^?_}P;m60}7~?H;bzBV$r!q23Q(ojDN{jymSUFFZzUWUmBp;JFuVF_g1Ob2 z0F95^#O$Ziu*DKBuaX(T^U#q*e47#KvXq2O-9<9je~&igpgP+z?K!PC8VhytELNWKT2b?d#Ykpw|o+ zS{cx_rPn1Yc9^725{IWWsV$S{^yThxBVE|+Na(~fGkcC$qsxPiQze_O&G8T-R-$&V zz2chgl7rn?iZtRVHDP5`FyaR%NMNKtD;rpp64L@MOqxZg!rH`EP=@Gy{PH^AK(1PW zom~3#x9mkf$qB8X+q;>-E z^?4TWG*=^J^gHyUU_98PLK}A!Snmu>BW(0$i&sxkwrCXc**WP<=&(nTDLu%YC>5{p zNN_=(P=$Oe`1R(+pM_^hVPGGfy0Z&J_ZH-Rn+@lsBZPKw7ciyN4ih2okSzcbIo}Wu z(UD#6>B>U9lZSfl}VP_O!XC~oK1jLD?qF5xNRf3_q zVIKxj_9sys`j-Rfl5x?WIQNdS}L z*F1L#_4x{#FNuiB{CH70f%o776XPYj8V>rBx8=bP6>Ycdg=V$oAN=($*CiD#3N}kL zc8!+0=i?P;!S_>`z#Bd**cc>|elKdU&tB;CwuCFgU*oR_S`C=$T-T6Hba zT{P&;DlP`SXbCLV*Q!n+9jXz+qeT;xWj@AZ8o|@`-hRTavtUvmH?+>_aSz87DNAa& zHgFp^wAaGNCDZ(5^r`F<-X{f%Erf+7Ez9x9@$w1lZ@eF4Im}(Hii?<2(^LhtzVD>j zsh#(D*CLG@I-u>v>*OZUm?ImRBPU=^8sZjoe5mMiq6)DdBUae@fWWmmgRfjtWQHtt z=}efQ3>w5582Pj|DF1B#aVi`5KK_I@JCQRrifDU zs$G=&GMOsq36*?IFVFZ!23^c%NGY#?nAKcxll|GAd{RK?^e%*!a2z6Iy-dAD4r@P; z;!JYKiDFkwAXQU3!8*zqlS&CS$~amnZ!=7C+xVlh0z0XSsMw~1`>rRIv54q=ndm_F zeTNZ>Nf|1+6{)mhSX`mxwm!M^Xqa(Zp=w(Hydqf#x52CEki1b39nsWc(SfWnKK{0tJo*)a4lVIb4M5CQ3O|EQ#e4$wF@G2O> zOUHxEsKn71%L0Itp7<`YW01~6iNHgrNpnCwsr0RAf)%e)Ge3IOCt3(;?PXn)EXSmY zyhxQa<~(O_QLZ=h6v1KQ6N0mL>iaB7G-fnPaVSco{h_5I` zRX)+w3{pOCj|AalR@Ls}UX3O@gcX`*V)eWjY)Bn~T3YV1msgCOn1ZSl5LBEQbnXj$ zX%#@tFQi<4)zd%5DlHI2dcYY)TGm{{bmE&*7zO=dl=vKrk5;$X;%Zvf>S~%bBw3HU zi@-Mf@YGs|)pu16&-Z+jng!fC6*KENU7bL8v+T+m|Lo8%CmUmzxNSemy}?wttJh3q zvXoRrSj5tcZaOLxV+$d%=%W5YR1aaRow!^F+6viQP4x+~SviMRR4*~FN_zZ_Sh4U? znQ3A5{atVrccghacO#MO1ZTjP(p;|jMb1tO8v=UxW~-FhFH{~8;I)_ze!bP>93<9f zQHn|)i5`idE}zEZ29^Yh z(6xUtJr`9Tx1Aa;uT0hCvs-Ruzno;RIx?0Xz8{&o(zbYdxIGtT7hpsxhTDm(f=iCf zoT^qTtAGhfE5lR5BJ^sFVyd^v*VRMYS{j*-@=HsdE|7DklmV*FmdEiaVn6uDM4!nbp#lbMcj}T2Rnn*Gaxct_ZI#z16 zAe=`=;~^PoI-S@W5<4*q32_Nsi4uyz77l^91g&CT65Efl4-(i5py$!Fd320b6(}G~ zug6zJViQ#BHxQMe!EwRPLrbglXw&iE+`;sW;(g#&z*uqh61rR5L4Z!3orysl78qss zeJ>?8`X==*=wephSfHo@xEMb7xHPdjMN@#J6SvMID;yWM5ThcjMK@wJ|A;M=Cr{c( zwJ84ZEuPV#i=dj2?wF3qhEJKlv=JX;>&w=R5ik;gZDp^b>#{mWmE_zuSn3mI_VJh4 z$87YMt_>V5Ake3R_kfcORaAy$q&=?&rKqu-hed+@`hlvVX^sHfW@(Xi@J|I(g zdiP>$gLIl$(ueN3rzf{2VgYhHKTJsFc?h}{oQdQl2sX`+CPEb&65i?#ifDs0nDv>t zo_3~+@moO0LZlLdv32mby}4A0w2@fr!rW1E$!5FsjQILVb*zE=7lAkzo>FC$-Cz}9 z-z+cUHe=ZkHD`9=a|@={AjidYlr4eYKXE1{N!DRf*|cb6Q2j=C9m$EMwS^sEmGlfP zC?iEJJSD4krTp67DqL!tbCWHgPP{WFq3q4%5R<)?oGf1M&X;qFW*u?3j;>5qf5f2~ z9IDvD*vj{`zN&pVTNcdm3ghLh-YjjW!#Tthw4!6sJ8NvWnfg`=gOGk9^o2T9aN`50 zGFCL69+o^FPf0FZWFHClKy^@G&Q>40WkD_pTO60%k z6)%DKprfu&R%E!#pmsD}e%A7mA%XUd&n@pQ9ogE_w_Uso83LKiGW(cqh{wglqtAA! z{36*V!^|c;wVCHzw|98Pne4g;jy)|p^Q<8z{R^*eb#HASWe%G-oBSh*6C&&U4|@$1 zL%q$Npw!G6AyCNUh3Vb03RpshuX37xc){Tq5hp47^O%Rlm45@g%ktAiOr=~$R#lRM zpe7?Ht`m`YttFFUKT=yFbyDy@y*wwxEx z@U@~od+8d|(!3^+j|lMbEnIPflJm~H-8XmA-Mdhlm47li)+RgHpp}ux($n=hy;+MH z(pG*L>%MA#x~V5n*>^oVXOB@=J$HXmPSt@)$8pqzE7|Fcs8%$<}2mh>A*xFs8@^pW%mhLo(v zHnSx=wmS4Ei8)b8DH;{Q4?-{wg_{-^t_GM_%}l3cx^tqf)nWK%SwVit3hTG0Wc-u- zu{4B8`BGUz5COY6-NT4rHQ4APettNCHttvz+&%1p6Xg<~+r=#vE8G@jOm$0INa zi-#s)ro!Q0*rPV_5`aXwnusHbVbuq2Tfb8>kg{MZ%ZW%cEF*k=-SDI4M`ij78M|@< z-o2pa%F}Qg*kW3P`uOItXMTJVzZ|{06;Z0^Q|i4g{g<24e7!!O@JDA;d$`b>V=%|) zRtN_Tg28VxwSG!ph(&7c^aGj9jZ;xer}x%#;#~+wTn&hvJXfBB4Chy(8rI4kQrIqEo(hSS`i?Og$ z7HO{O6NR}i)t=LCgpH3R>2q_V;347~Z49xP7)c4}P(e#8Qv77w4iPhQZSO9E82BDf zf@R7^@ie~^+c|g&ELW3pPbPi4&$^H;_c+-cyu+aYD{dBF+@zCykF^p~NnMv=ar@<} z^D|u3!9`3Ok5~E#&n0A(ypjE0Mlh;VMbk{)wB{vy$h?7rhRiT|63grJk!0-^=I*zJ z?XOQKrtmH~D3(8zj`I+B=J)U}^R9Sh-Xfk`)>&VrL?Xrym@`qN=!{0Xmj$r$aN|#{ zz3-!)GGR_f%VCMYQ=*VnM`QbvnK7RWW7W*Y!y0EQRTks!1;M|6PLWYwFCib8jmNFiV{%BqYp3&!iFA_VD7i7x<2H@$_#^xm1MkD* z0z>co#%mCE?k@)2nmeJ5;y{7IQ%?4*%Emj}I)EzxZPHySwVSQ_X2m92h=ZE1wR=JT zChn64g=4~I5Ik;02)bZOM)5*QQ&z)-YqP&JtJ3Vf2Jl2yFS~U?Zf?|8el%<1brO*U zO;xJ;7q_pbflBcdRU_JmawiM@m2*^k+jHi7smJZl7MxV0n@|NE6ZSWXlG}l%=JC$d zj-@Pn<(sk8W~N@|OD2=aWHS^`%L06-pw9?Ti>P)Ao@6Dow?PG1@lm)@)Ey;K&Zd^N zXt-!t-|%)x)B4!PtRfX4RvIU!E;@-DbW}X47&%i2aT73Pk;n@n&5DR*iuUSDI*~9_ z=sG4CSzB~C@CX5H4n~U>hgUpuuSdX+7^d$4KS; zzLdU&xa&%i^r1m@ZQ-mdD3HV^ zaN>Nc>su(Gl7EVDh6N=fEiEG*5zvW-R@07#51dRU;wIt@nWLbVzqiq8^~JFm>UC?@ zTW=DjKizD0-`lvHS9>hlRDi1xOZ-vDDZ8%dc_JKzwwfT|G~+lDHDwctcOwJ^61 z_&C12n_-Y@k-gVC=Ll7@L9ZE%agjYOON~_UucSb__B{yn3?wuMn z$tx6m$mk33?uvE`yBq=T?|9G`E8IZ(_@%d2m&Pe;VrPb;N5E!Ie3(n#rZzIwt-r~; z+k@#w;XGT|sbL7K+e!7l&|kZOp`GQs{mNB${(J|2iWX)r)tgU3Q4SocvKE~9lEh^# z`dcd@mK%dVrdQ0Ghnm%WrmEH2r_tpm_VA6#_(W8!u;UwMK55o*?Ll-!^tvJNM6Fo0 zv!p7&riRJgoYEKWw}#U~&61wW`iiQ0RG?P;?XXlbbRu0uJYrtg&X!%JZc)CwiJgf{ zGW^i;Yv%qQQY)0nb(f&7fOAnXqcM}VKf!uz76$sx;?eqRx}N!^POZs}PbYB?fj%F% zi!!s>d2H0u5=>9`g(+kdlT)}?2|$ZPSNYaoAKQo2;$!?!O#9eL$D5>mL+?OkQNF8| zkHmBQW7tu3u1A03^&{haX=lH~1gV_UR6yk5t7U?k> zI)miQ+34>`9g@A;h_ALTS;96d2n}a1g6G)iNGVKehbXeNb>;g%Kim^~dTsTIN`Tg2 z87k=3dyzG{udSDsdKeNdK}trQVRE9tK)eBwzUJyJao z_{}|Jgm4T$L8BYCfVpB>-<}LRLolPGYBGd(uLHre^HMZ>6Z2pPKY>tZ?T7uO`n3TE z-zJ4E=ffztiv{0aM>M!2rym(vGtJ=rgA=rxO$ z$;bZ>VQ&EzN7Lo;1_=ZR?hxGF-QC^Y-Q6JscXxMp2=4AMxVyUrhdX(9zi)T%K6~#> zKV7G*>eO`A^eO0`{{34xP)VWy3V1$LYKs^}9{<3`yK>u;I=}2Yy*y`ShC29XT+8#Z z3Twr4ud0*kBvyQU8oE6mz{O@CWlnIpPP2pKLtjB&QIE4|m*@ zV_q4DnJ7KL^9CodT>-E<51Zx)NLXTpRq4Xzx}2%_H$I;)j(~5&ZUToJdDaZPt-8e* zj_Q}mZX+Sa8gUs1gN`9T&_Fmbz9&9IMaO`L0cu1UXWSJ0x^I*5tORPm&8!o_ijiV2 z23c?7Sk_}w8b=MK<~m>nP?y5A1$0?z7F0N>y+-0D=kVxmWo~45QohEdi#5ey;4N|6 zemA=s+03#Lb@g@i`BQ#gQtxJBRWBq#(HnmLa_)*sVbvMWO0ht3$pcXpiXvzczi8QD zLRwPz!~_eD6|rE~97KxBwl-poT_<8;GZLS8E++#eLz$f=n64x)nYd^>cKymEk!URT zQ+na~m6Y*unzs(qpJsDvb zJ&F_4QkzQN-02yv2gbufb32;fjx$L?qB9CqSVqHf5exnd7a7~~2SO1e zT*)9f{E~`7)0SP}W|B)inoe#Dtv%S7yP_=hd0KylH!B+YQ(_v8!)j!2?WZXsaS++D z>^s_hD~CMA>(%#sq`Eb?CO++FZ~r`U;5JBJ)#;~bd*Sl<2N$eYvM!)#$KFt7q$WIn{!qD}KVog~^5lbc(%jk7(I5}$tE%buy_O?0w61!lg zakv<^s+$%`iTD#Nquf;6Eoix7?+N6D*MePId|)Fl4syhI!|i5^M4WC0jIoJqEX;G& zJPU(wcICJ$W3!-D%&nQB+%LqJ+^^7YxJ7TXhC{!ex7;hJtK38Nu|pxdMytG4cG$Wc zb*MEk{73wvLa~gctgTG(s41OntIQ)L7tg7)a4u6xIYD8LMV4*OW#&n8=r?C^CGQzs zMP>5M{y(sik7hv0G^Zh&GoNiLq{vR^>)*?6TOzBa8!!+dgj+NPjNT%xW*>M^-ubaEL?NWrrs{M@S~oH zXDq9)1)T+}c=0aa=?QzBX4;txhP=2-EA^A65nGn1YosWT<0H1pa;;6x>urx}by=r& z6F5LhErg@S(8$-=?{+i6ffgJI)OvcE-dSuq`!06foI{*>Da~E z_67TXxxSX?3F>y|=I8IL4PJa^I$39*GtbBU75oE!1ja?D>r27)m&sw9(nI5O2hWV- z&1|V=sahBD0(K0PqMj9T*cL$!k#SfB&I06G6(scZ6eZDFa0y@hq zy555fWd;R#_U1%^9*rbytvUsetdbe9X3NAOz0aQzaUB8~f zHbL4HKfsV~G|AV%;BPSNX-d+j8QC-&!=UV$%s{pOxI;Rulm)b;=~~TTZ72u|qP1{p z8=zacy0oz^-ah1;Zwt{i@mt6U@s6Qtld zb$SB+5&N@xZt|NjV$cwAl>mx2LkOIrh}MDk*6bz1rfWBU_dB-EGEPcbyhpOvZBnB2G`G|daMoNK=2DtibSC`W+=y*u>BEH`j|f}jI{^sI6}C!|Z_DZibq`!?ig88NuC z(94_&qgUp;kYQ?i_tXns#hEd;FM^{RJL@RF#pVg}t+#<9`5urUa1ovM>^` zH3L#vK)(0yJ_-J#07b*f$VSV-$N?0wpkZQTrDbMiW@iR!`uxMPGtkpAvM_Nl08zHT z9zaCPgb~Pw{e!vvcM|P?X>$Cn{U1L6)pMZZf2w{68aSE!t?_@1fRc-$vxhx!e1s%~ z|5p2pn*oOdxTS0-CLt_iU=I||G6s%=g|o*$*-9Qxz)_H}HMRRIuA*pSX5r-Q=z&iz zU~Fe-LIF)D=V)x=XklxHPyR1AV5X9by}h-G&EMgq|4T}$;cGDgF*-IjT6QMjnCSp_ z7nsAuL`zT4#?GMgS0@E1gTlthNXx*=#=-Vi`$UWFU$y@$Uk4uu;%c$7veI&JF#aRC z^j|K2wYKPi&2z9b>)^Ap<7=_7u+jplK_CSD?*jb)%A@}u_J4B*D(L*@UILFbpa9dq zx7gV^fO|*Jz^a4K&VbL(^xv8V%429T{i_)0^zWYiR~;ST*DS1t&&Kk1JpN7W{Us{@ z^LYOMLiCsz{s*9^6F+Vnh>sHd$o+LZZ4i85jT)$!85S0ytGEVfzilo-iDZn{liOX&EE)pD`6Mc4o8;#=Wv=3Tm~%p5ZdNX6$xPTd)6Y0c)a zv*uj5Q}0<6QnYgvalN<(62+i#^eD3!k~oPX8U>da<*hgesT88mpNt5-n2_J(*OuHA zQnTB?2Fa+C-QTK%V85=KcnKTcL=HkU&2+>bH?-#)r(I~0*LN~VUxcNK-2vP?g`{|=^2=LdGUb}YGPmm?Vfqw0p*RNvdH$<-CW-0x%EiBkR{70 zMMg}V708c|TK~=XXRRz&6u1UBx;TDlzM%GscF$M0FiuLasTpSku2Q3Q(P5JwoMr-O zXj)8pL^i-fQ91H}S!UXi$JW)WZ};Q-F^VL&z_Hu0J15X)Hp+Fn^gHugdi5C4uQ$aa`i!Uohd{3=F!X?O1NO*MX=#0g3Y5 zdE>bIqve+h9t-!y1O|O7$4I9L3Ur_POBxKFb@$VbTBPbv3sCXbuTqCo&!%WAUuN1t zxE*#fBeWK%y%6~oL7vd2TkUt!KOE|b4k zwda=e3xuV-xd1WLcjHawJuBs1(NcZ`Q3BI1<#;Dd+x)%!P>R2`k7~d{uZ@rr)xs09NZGpaheS~`2^kPd6|992Co-J&Js{K7*xg&Px-1K@w~Z(Gsr?>-BCTrr0lAnSs4f-%np zq|H+D(rp8@B=81g8VNP<+P|OeGv@@WoC{bR!W&Y0Az<$_lFH=K<*(t_LOSrYf9F&Q zs?IBeU~FM>;B{oMq@T_oVH02h&2ot+&1Bve*vkyVH3l*F1F(ZDU4ehrW=TCr zIMMr+yhok7_iJiMSZZ`yYD|%Ou!#Dv!RtJfe)+&1j9^3Hb83^Wm?<%xpjI8AG#T)S z{7|j-`Knezen<}xP7Eqi_cBuVf;JL8q8v;&z2owt6nqmQ4}hPmL%7>{4f*3!+KWUj zQh_ur@TwotpQz&P52z?p4|J+SxKJ-< zsYFFcv`iL4fKX<7}<$gpfxHK}|7)ribz1ad2E*|?)?uAtysLKMdm7wPUavDy(8WI zgod-Fni~AS22l%gf!^!)vFae*#5 z+%WF){ij37(|smthoh#68h5izQc#`4Mn;Rm#&Ao4A2jA6-j)? z5>}TIoU;;LzyYF9wq7#I{uQ%UeB_1&Gc4(S@Er1;ToMJvR~=avX`Vq1!bfs?UdrFX zK2AOg(l*e-7K`6F()mEoj-thH#t8(WZ?W_5ikTN^!YwT|7c<1h9!*}zQ%vBV7X2c~ zEuijwp2xYIAg)U5C$Z!B6R-BNlHUyt$dQU@93`gZ!;FHp z0SwBH;T&>B9o2fI_Xl;KSz)4dA$+~3MdUs1lrWnvG48=qfA%QvL{?g9{AFCWKUfSRjmIzU zNmM7cdp&{;vUfyJaE2cR3{XrCaMgWtPcU75OU_M=SbOxaRM*@RM7&7E9Q!t>c@@W$ zhp^v;SkfJMlZ{~VLk-|@hZEefuL{s}5V#}=kViO-k)P8~Pq^DsS|e5lJ4TWIJlYff zq~6cNfj4B+?X6grV&5eaDU8b$OO9O|;VDcJJxRIeQk~Qt{22J-)GKVaOJ)&&PqTi# z%cdT-up9_E6QuJ*wb{4y1VI*>7Kslt>O(B)Ihvv@#B^-DD#K|PSlo(Ok9$sNpY2S}&Jm^>2@ zjgT`&WXhn$n;6ry2EF-n%jpv3B-BtO>OtU$Se+QR1=1E(94FnIdcyd`UKV+s@V?-_ z$NCC%o3N7xP#CSIzNV5RoBd(PsW)XEfinteNLbOR96)s%T*q8zwxw#$@(SiEE?1sZ zYATPuR=ZWJ&^wtv`_uvr3koyOms*8jAyf~OX+eK9f^^++=m=E1R_ln+{XyosOX3?Z zBUt!rJ^_L;?kzb}D16w490HEUhulFW~IdfX_Ndoq_mQ>J8=!*Up0fcnmyV(#^Ln>3+pfvW}RHb3HDJw%ps?CJ%A?zW&Q{aiwLS=-E zSxN)d3fFSTiq5&!x?KxQD@^NaYe@_4CCeqTo1%z{u1a~iyi2xa#i^0*V9HI@8|R12 z2eu291c}Fhly`~N#yl7f;DpuEOf7-;i$!1%R0aZ})hM$e$yRQ-L~PIic?wemCgejc z>)<8&3OWDU=pH%Av{6$yV|_v{I>RlA{?Ob~(9!TH#xDns!7j z5Q}pMlAxFVF+^7Y@ou&J-i|bU4aU3or&hp~8XrfN+VIK*Uh+T@?4GD3PfFF6}Uub$mWx1E2yR0U&iqdq2hPC*VntZ3_M{%R{2u z6xc4p6pJCN{1 z6^+Qm0pr)_`vj( z-$wQRDd+G#9#G@W7(O4LW=z}FZ^samDuIbLD$Bnb1ugye5dypdqzp#XqxjwZ42`+y zqJ??CxWvhCkrN6Loe}Sd9RzM3UN+217-Gais@Hi&_{`-rhhMER%caoDAYP zcQpoU#I<~(+k0e(A@oAjtDslqJ!?94KK&pwi)QoEtdHuJ~^ znLgepj5hN~LZdu(N&nP+xBO6k$0DiVtx)MerAGIp;hWvO-OpL`8F+&9@AMeogXh+k&h9yrbf*P|HSRrm=7FZ!FF3diO!@cr z7a96AU)<7_Zwa&d+*R6kGuZbXy*&ccEBnO@j^QDR76+;s3#JPz)|%=~Wvm&n5EWCVH$9+!=|{je*A5!t z2|Rz;bKz9aoi%G+sAg?c`>Q0FHm@DLT(H7hkKC4kuKKC@K`Sb9SLeOVaf{!yD9Tc~ zwfvwB0X|WqFYlpUn-&AdGldA&b>HOq%R66{JAEMm56=Qu;IW*Dr={e}$=+RC2W`Pp zMTk_+!GouPD`qDxpEgD^a%{?UHx%fbFM&(xhct*U!G-hQNXDtmL%O2U!}Y0?qLPxq zL#iSVh`W3y9(d$u<8ChkziF`^#;N#kyfk0ELyLnl!SYy3L_m}{%V7x&sC8NLeWGgRY-++YMhqO`j%q`0>A_Ors${$3~}*8G1awWyt@`&;PYf zFklZ74(%8&i>GI+YMac&wiHaQWnybf+o3VFUa4rDn`a8X{ZxVqAFP;|gbI%>_(LPI ze%HXHBVd#ic-+S`CrUrs=zuvt3N0sakxAO5O!N;F}T{i&n*r} zh$KZ5zY&SLE9_=*8V-CjPX0y|PNvU(D1wEb^Y-ad+TY^9QV@bbwxF*)dF)V<6obKI zc>nG5c(x294hxgVleu2(Ni2mWA7#u5FL=b?2m=VAX1ppc1zat}TPKS{t+>Y`%?MJF znWh#d)RNbsqMZ<1*GiHZgvh)=!I8N35xj$=X9DEx z`$^uv!LI{=Je&hGHvnEdNbLp0LOjlwpHs024^9ap&i3_f)gziLcJF> z5%SosL3%MT28vVL=W6l?N;VRA*ctKLS z!7hWJqgOcXcb1NSp%)4>%Lm$a3?ipO$iZuP6RR{lj zie#!Akrw$E6slVF7jX0fl^5`oT$vYes-!1H>LlJ?6LnIYz60|VID;glnjsN@fU|y( zGlJT-;R$~A00}@qyJ$eosK^;%X5xd-{ZYkT7JhWiNArog^T;_Y#@j^phiS|;p_ z;mcL>#Pb{Q0lY5zLl!L)+vP$r=1!na@7-qYf$>~1`D0@Hrh6Pc;E#zq)I9!s2bCp0Id_sulS>Wgy}8=vv@;*2%4g#9XI0!sG3^SkS>y z-Vk&UTnv)AE3HPz-TZDu4@r9Zwi)*kK3%K#Ld84W4yXX)sS-82QXO=i;k@4Xo#EYk zLMJLe2Db{;9KJ&qs@KM((kbcShPJJ%PhX(Cu+~6Lv;k-IU!k z`t}%{ki3Nw0i=Lzss!B*F>i{lAYWIkt{|wMxSxL@T~YU&SjlI(EMN8U{a&~%-v>PB zJGMxP-yJZu0;W~R_cf?lA4&N@K-Kw0EnN0fa`r^;JwTSP`1rm6=urNDBwe4!_n#zL zzSn+QC4Pm+_c170n-$0Rx*{cyl$`HB^XK6IelXqfJ=q8R;z`X1aKo>BPL7=OJuv^j zCj)-YFP|=)@7uuiKbENzoCSzO#B+VzI6YxgTz|XmQ)65ZusDyx2sV@mhr>A93LSq2 zv(gr=Qv=+vC~AdE^mWDc8}J641_iIsIzBJ$`iSOP_{9{ z1@|A}4(*%>h)sp;?HT3{#hD0T=X4KA@=S$nWA*`{GIu zuTOXPg`L^}w+HPIM0^5Fzc#29k1O?6Ani5n)zGw8yUOHp(DG1M{!ljcn?L>oeY0B{ z>gM{aNj+-Bg6W|uGh_2F!ZB%KcqT*?sZ<&DNo!Ex#|5kR+6M)}>S!9(wXRNB|BPAr z31`~R|HzdFi!Z5b%u4=*-DWM@`ch#?8X@RrQAwUD?VPqT7`5PfXoz6S+kgS`ZGzI2 z0YE_Slr|_H(39Ce5g>3q8}TEU*z&_W1puCgs<%T8 zl_Ar9pfGUcUNclE3{F_f@9k1Tvh-4^)DQ5HuiFO+Z^4 ztLnovC?ZmcO&F`PAB375qPQ{P4&hLtO~f$iB9w*PxLQOyPOmdm$Ot&OokR_)$T5!7 zr)fYy$5~uCwnn6IPwi6(jb1sHjDS}$M0Gt$3?*e^m4!HrDcuq$j1^KvN*Do*;0QEn z=ug7&Ves!s+T=`;d;+>ib z2uaPa%>R`if}xjO)1!9jHKJxy%=WV%tqmm5HWynS4o@e9unmq-CnU;QCz2*c^>NO1 zWH0|X_u^Ptk){!+N)oye=TNC=I8hn36C&Y+1k`+MJV@RYE7Im*^ zU6^7()T!M%7airy!3sdtpOI9{OR5&7y5O%6oRw6|Ptpxn^~BUf4OcCC05YrOn#Yul zGYjTQ(AEz5G>WPVk8ZNpT zE!y@Y3OYz!O`x!X000;I*Ay&F0WJc{{Dp+Ye=@lEcpl)s0&E_eH>)(O^eszUAw>At|#Q?Uu6`#_2E zHw$N5g-)j~VMXoz?MuTSSbD21U_wFs3X$4m_fz9o)>G*NHnGaae(xHDiNXVB zeTJ#8HT`AH6J<3UhguG6 z3<0i6n#KFAL_mIsn}u`&W!G3zdIWWs7-bx8Y}sRkR0Bbr)}oK#o1m?Wb4%46hDx<5Oxy>0^NKZk_Q4i zH5?d~=Aq?K)~UE@m0{{Et0Lh+xF8LbgJYoKO{$PDPf2Bnt(xsa=%rio@T*BJX)O$>0djo`rH^Wa+ zZ)tDpz9@LxOi#|dQOy-qmJO?=ixo|lO`1if3(BxfJhTtt1kYZA?UK)x@`Gax6@`<^ z(H6I0!jkhS$Ouggu#E<*>Hvg`w1{9Q?^)zIP>1|1Myj!|L-D0eAh2`8qGEwqyB*9d znz)vsw^3%S7sUI);?Bb4l1oES#cYFN#9M8oA|JlSWW6j)CC&i|(=1D3gg{oc+)+(q zSe^3J%8$enGg62T^6_M}@%S*}+Bh^+GhIMM$UZwyMS8V$` zDgCr~>~UprRlJbEQ(Pb*2J6hSJ&q|Sqo9AN*k2p$v1HjS1Z%5Z&FD+@zj_x+3=ztJgLn$;k)42$YHAOB&7gpInV4#-O8-*`*r*O7AW7lGNBjdt?x%Bo0)_Z>yH<}kYy#GFdQ)4@&E!`4A9 zeYp7XabAPMM}-a#KYuyU;4+ut%1bp>69tPNvh?+EUbL;8GNasYcCig8Ev51yX_Dk< zBIBr~ve2!lO@ppBYNIm#&l090spS%3+-hgNS~j#SKB*zGEaIYRC8H!2&d0cDVT(fq zZuRBO*-E2)SPpi~7DU%UDi*h&2v1Bjk`M zjei}6A&qfiu=z=1aH-#FC8>sT{%)pTP6JTpI((y4OIfSA)ODraJXt*mU2cvbm&6{|#6X?ofs(m1?ib$m#J?$)_CYtQ+ zYjH(MEz_6D{dK70W4C2~PUTWYNnaHyJQ)<|GgKM%6?>ekffI&vT*aZx>``d5(Qt>r zgDMJ@cOaLi(K;0IBG2RkF>v2@^kM^DN=6CmG7&jXp13iR{Ov`|G=ZQv$MC$qS2KlT zp&4FA{Pv^1S2DSYEJA2JWF#3Li6UqmHQ$(IbiM5OXr_ysxI4SX`;DeMZ}jKzvQ8qg zvUjFx7^}VYFaKmSWN_T3a4GpiD5St(;V|sW*k@rAzXRgCo3XI>q|);98s?nJ^O_&J z`^`@@8om)ZKL;i7=A0DwuaUj2(#%Iw^#d0$%068Id$KIwO&GJ6gf4&)|=MpMc5k#sM z7wH`Q?fwpL>5UfyFA4Q0z!hN8g%wOf!+7UX( zkuQrsW=4Y(NZ^o8VF?aP0dO`iHHDu9mpTf?!V_bUxjb*ZoB?*}Fzh`WdD3P$V{QFC z;q-9HH@tjI(#b^SV1PHGDZjR!52akY9~P#n^{thqf1PoAGAYR_+sn2jd{NqNwFt`U zyFnmfe}uS@GFufvIuk0NM?vtvm(4nfE_3oF^F+^y*+Oum~nj9@Ry zo08~{jTGV!X|cHQj+75+Qqr~-9;aIC_7uus_tLlUKjwrWQYg#qhNuzpp-jMcyc9}c$Lk}D^5mIEy z;&cH|hwmu2V|6Y4(DPV*p$QuK<2pU%QTel2tgI8PaigS$NH~|Z6ta#3->v+U8E{yp z1{BCuJR%e&%8A+&$Vhd!Biw^y=FZv_Rb`|Yn{5oYh@I}j4#RwgU*#A4xaZeh$%%zH zX1P1QO%}GcrrA@nZU+p0@18zzcIef|7cybsk_sPRrX-A%>3A{O4H(d@j}HtpIP2IQ zc-@4g^V~i_=b~E`Rhr`dgV`E4K^QSwr8O13NZ0vtHxLsx-Mvmdeopg+Eo2Rh3A_?b z%CY6g1!nd0xi?SBQMrATlV~PPmUd7DwTa9a&blcMnR@-V(#doa#tNPlE_Xs0*A!9o zWHFLe&bNUhx?830!P9_gZR6rY_KleXY+iOv4;~q2w&tvFO)}?7XsSu|)idj&={6sR zDRUMs%O1}QzA8O()FgukM&=gm7!z<1ws{sYP1=Zd6y$pJH|0*gOP>&<&)4<04h>XP zbg8U|3bt~V*J%Sg-MpSEN9)1d{yvAsWwV@j&o*nWbhTI}n60S#F%Dk2{h|(y=|&zd z$zzoEg`sP`3ej`))@UTk6{CRBEgWWg=S(!t{JWR$A`r7Z80t|mPx8bO;2SeVd_KZs z;Ht9Rx*i?3^QqLRL6bK1W8h>D0|3gFmU+ZGO8t^5LKJ8b%2z7PDQyjoj?#f$w9$uV9ILlv6KAXB1KTTU-9gnIUkNm3qni+iF3ywQJ+7G&T zo_sz@(;AjQjM1ARzbBIyTu{P=aA;72YCxk@oLAGc$64)jw&+G9x1d!gaShes{KyMr zlvg^`0TrHwDHhXpapXH7gQiAn=x_c`n^+Vu)>7{1j%Z=4g#{fXN$orCLL9PoXT(EJ z2r#&$e}s@0?|t8mTx(gIZ$7hQtGDdKULf7fy694G=o_o4)jn@Y)+x~~>0We?a>??k zGODtwdeyASZZ5y*STcB6?X(R^X-36h&IZkPFuj^VGN07UNuC{3yrhyup3?+q&T#@b z=ajn|jVzcaGdG|NvDm>;{rx+7l+<{-fh zY-uQHsbI&YxD=J%LY$Ud;xrv)3{`eVh20EMF+WbGvLN}q&+BwwOs_7g>Sjg;b_cS; zypW_uqKtRop(NsEeLoXAicKUwv)2l)4T4gOcH1sCY!AOjXO4GHDpZh+>oXG$Qjdp2 zSsw9K8kWSWGPCp2PFi#7SS$Lq#>!Rg3FJL{(4?pviySyFtK3S$xtmKkq;dZ~*WXsX z`ab5(d#w-d4UZR_^pL15|Baz{tSZSWK-;{mO-*vwLhS#cks@m2;=DImD&S zn$nMxK0P^Yp{8SPKJB6Q>B^5cJ4FwaZUIL-MOUAGpc~_0^AlNZvdDP%w8E!-a4mu{ zzzo0R*}P7Sr0_3c%7&}8!L;$GVyyn=op__bj|w=%WMpClLk+gi6wJg%Z|2&5UAYl)Gh-9@sg zuC4H&hVu-8TFE*rO-sifQIK*3<@s6zKjz)vSe%6*CQLfkz&7e_Xt;GVqv$bb3xi_^ zha=fnlqaOBCeo0fgYu9=0PJL86x2YGPr$YQglZgOil@=G zGn6S3U2ek6r&Qm0g@P7o^u~VQIE4~lP|Y$ZaslMi6|l@_qS@w+=OJ+cAG|^lha)q; z(+`|UQKf$0Qo*JqB|R+{BKB7Na7{^2A(r}0Pl}M^HlB{n7WE<1@_I#MrHc2?Q-_S6 zvuxM?c1tycei(y4+c{p7aIL(1H?X$fKQCiNmxhF!V~E3Qc}U`C?c>_JM2ES0m~5&X z*Z_^L{j?vff|n^5O0D<&Wvyy?NNSKjuQ-%u7mKAT9d1$-wubP>q#@>*P?bY#$GK&+ zy@MjYrAkK(ihwUOi5X2~UEFT~Tw7fIe8HukvAt?B^F`rqXlT9PgBq?~b!CR0m$^Kd z3Z+-j)-GL=8=WIQLtG~>LzvIu>y=+TUgQQf&LLwf&$WIh`!BUStj%*pE*7)W>6z>9 zg$ZUm)-BW44TqFFgFB-sw;wsBvZc-to!LKcHCUr`kC@I`kc={I5ts%NhZ2)fidl+? zf?gEE6*-kW6_-&2eXc#ixp{Dhh^RoXt`E8!1Cq1NWiKs#!WrdRSu?f_-6)h)RV{C{ zCPcADVqtRu84}S`u6rgGoE^j^$KmgO-tQYKf0%8jN9A&UFr4){v3ctP<9^8Afq$2$ zKM$ffCFwbP^?$J2_$3}ZK-hG3pciSDqof+j3O2K4;+0(Fn=ci?!G%9=KwV?l!nu3;&ijIopu4v}W zD<_nVo*^RfMKi-+T`IwSj2W-mVYWdFQ=nrS@4(oadvaB(&!WWz(sc*7{{ z$z|z{v}wJdx+bP7%f&~?GMUara-($MY|+ro^`JCuu=jT2Iai$s$G}eE{Fn0j9BjpX zC%d+qLbjtQbkmgb339-{!SYgu)+4$=< zVIxbzVLGWoGk+6*drxamCwY=pbgo9-*_dQ_6&e#LX0LU~=v+eU?{jHZJBdP@!a?#;+ABc&w=zM%=hh48EpQ z8}#G$2}-SrRER*%W+4TeH-#wF$05{*Ak;SM+_$6u+!`=AchC{zp=ZDc#g_~U<;g2bHG3CtAMU=>FHC~LiPiream6(ag)&`Pkz>jMhw>bx9F_E)j z4}w|=qt1#}N?5dJbqn2fiq55P#>t8?8oY~(Ei?I-Ey&r=dtT0%pNF>`8sBg#2; zA5-AqW;7Mg>z_tX^82PF-jq9?7LCGkkfsN!iL-sJ3@*kvtZI1OHq+auBV(=eNkw;C zgVN=G+rCcjLi#-}`)Khi(BK#}tT5CPC2`NdHr#ir*Hp9!Ih7bRcu+mo{&ASx3vN-X z`kml#|6Qfi)$v8O-*&<{Tj^xpwp>(WoZCfgBL4 zTf|>bF@{*O6ycdLyJ~LDpjfa*sYTPyLt&t3sPY5OqN{L^fQSuB=&QuBtV*sqV|riK ztE%A1d$R3PwquZI0(Es;x{X#l+GKRP?NYo*k_+bxJ6p z;yesiLF*@}QV_GWQLd5kRe#hdY`aGYGy+(uCb317Jd+e`=gHaZP@<|S2U#!_)@7uG z@+1u@6kMg4Lqe%{yUz8?sQ2{W#x^aaG}-posny0+ZNWQrZtklJ!5*M zM*Q7BS+-KLKEKl_-@ahMuqsWDZFAc|&@O5Nh+E;55OcW|Hdh%ibVM4J$aG}Y@eOpA z_RTkLuwo%mIUPL}Wht0qK-VtTIR#bnZ+Y}nrI>jBBvX@K@$CQ&EYCO5$I_)AG_yGQydd=hv+ei zQ9Js1PHacZyO@(#omK36;hH&YXAe)I-?JxZy&WM@-}YCQ#G(DL9L<_dv@QYCVI znH~F}-;7CiuI(KO%zsdf4e@0pphoMDCHpIA;WKF;ZExVJ=vLDnyNpYU?cKO{vcZw{ zOJoj+&`2`AtIEw%TsV2lf2O`pyoUs{R($M9C5S%Ge83kuN$xR3@m7Y?)v4=@rBw-b zxi@*3M_4J{CtJk%C@i+N!U#q{tK8Ba?PgZz`E)Czj$okZtCejTvH^b5sbl?K@mn-W ziM4dmoSGOs&|vK^&u*sU3yCeszQTV?T^zQP_I?N6aHu)eX>if^thQhlV_*21)emO2 z^)OPv)+ORR@EW2emwhvkeMi}DM-Qm*^_%v2bj>|3E=w)mYo ze9&8b6#e>7BUM?#O9f?KMT%rLf{9kno9hQjg(M8b?NV-Jmdfl zkpUDZ4$EvN&hNYN0|vHo zpJZA?P1T)se#kf<*Oh=(m!&^`6raedl%IUkx1qbuyLI{4SSv~A^q_Q8({;(hSxZf5*&aDT{o}ZgmgB6JG}2k>E_RhH$Qo&4SZ;5mdoBR6<+7HIbTDf?ulRS>L782$ zGW1efvl^o-!>hwf<&Dv;vPI}h6;wkZ?QF`JX(eL6@K&WZy3T(_e*P!e9Kw^juDI!)RjGjCf}cFS$0&s+rZ` zTDi(8tE$6UPRA#w%cw$Bk%>An=AIz&keJ6e>xw2Nu5fRVcgZ?TaBgC6j8%749c6Z# z2Ab6zykxWS(Mf2}_%gg(Xm3Kjlet(j=1}MgQ>ms&mPTgbXvZGxUt0G6Cxac zkm%yRa)PD zE3DP1Z)vUax&l-)F2es`vKg3^|#x^6d0Z3ZHY<5ln({i*50J~KGXd07cd-7)hEox{zwk z7aFCEfg-0%UBckbBn8Uex=_SG@cOmrU3L=4@6XY9gc!9E#GhDQUTRbQm2@c&Ysx3! zUSwRLpzijW?3dsiRiD$3*+D)5xI1M_10KxGhB+3QC(&(og{_sgYTG4oR$B#EPI%^9 z^LU4_m9glPaFu!`wPiUfUm7zsYPCu_)uz;u$fw$jQRmclwST*5D5@!#hmJ?+V#&sY zbmz_S);^e{CZVdJvZ6Mq6Iyxat)a9gBqMj~h~g74COK_#Gdp^|E^EcvZ_?=OB)wa6 zo>}R1z0azn(CkVuRuGn62cg7zCAqztn;y2RwYaXfI#h74LI*+4ZO+lZL(^~#84y|T zSubLmQbMD&*h|tdZP9P3X5I=#it_HkW^2h_^A(jrD3|7%Wpic&jIlXqG#z6^m1eC~ zVJSPlJPWc{)hsS+nekr3n5rAt#@@QUOL#7_0!=kG4jABYEe{IEX9~CYl}Y@#YcppD z$1Y2-$jD%kj$ojs+i%y}k7`VU+}Nh2-f8A?*%RDbeMP^_q}^5?y*hAv{Gh;>fu!3R zAFBJUhQdz?` zpZrZIQyIGCuBO$heqw!Qc?NsNOJ&7EB#v(Kp6nX`9rR~JaY;sz!MTc$WSZuB0q+%pyvtlVp;P!}qn+QM(y*9!pCC ztgegqwRyWR6+0^)f6jFi2N2uVE!$q2w`Fb^yV_Qzv%OH; zJ*ZE)pW9fn#$}E$Owe~Qt*5q)yjgSAN0q>arZ(3b(H?(TmRTOHm}@16N0#zI zqjGx2-H4|Hc}#7}BH@wj67=6`?J8H6u*SnU;q2EOBAQ9}C-iS4relj(H&&_DS8Sca zH1{(bZxuf$6~9L79$1|z8;XXrR};YQ<46*{ki&)9_{$b80aM14drDXO?oH?nTYN+G zYxFuyt1)-ljcMq3Za!OG6JtBrg$FmHXL3SGhraQE!e70nR?U z0smy=Q;rI~%`|-k5~1ubDbvR9SE+D+C_EMWrxDYRDa#xqFfY*4)HQKk$8sdn(o?Wp z$Gj@WNXTXRmstj=OpQZjbmxy#x}5E=BZ2iGZX2HtSzjpL=Z#s%q6Ol-ZiSbYzdsvQ z*j7x%z2TVI&Ev_1jjAtu^J$$hD4v}?g0jQ+4RBv~*&UG3Jv?QFT~*9kIFr-L zT{pLvZXHazpLkmhg>~WX)lo;f>NzHE(Q@35hZRq}9#>OYgKnt+8L3F`a)DdtqLb%2 zw>Jp`^V8_8MZw$wTMKliyVwW0jXHzp^!h-i_)Bpe`uv@>Ox-xaPvIl*&B0AzI9(Jc zpX&sF))nS?_CM$hH@AGPhFP#}RjgbN8s*t-7%;U554IVbq-~r!3TO+vr_K*;=xSMY z3}6W=rfAr=Z_F133bhN!mQVqLjG6L;c!o|J(z7PnJ7o=a^;dOFG>@=vqHnx!3|wHH zfXhZSfJWztm%~v!!yG(K?lL@1aTk_hnx}Et=U5TnwzoFN&LhRu4z`^wmvOzSx+JJv z+teUJ-6~2>hjLJ?qf}l~5%Ywg+T(G9QX^U0O#3+-6_xXEsv3M<*44~(UlVecgYK?G z3YP&p5-+dqXB|Tv@S3#Px`kEztTrv@k7dUi6Q&V!Wn2}K>L%t{&EKSc&$6)zxP+YCtt1}I+g{YHA<%px zih`ht8`Mw_4#lwq&Div|rrrrHbX8a;-mB5;Y-$At&SuTZ6^`&AO^n*%$|?SUOOR|_ zhm-VU>AR5Tzs|1i&Kjc&Aq~x9^!EF^9zTV9@IgXSyIR`dU|Eg790_S+5%$}} zPVx4FXt%Z9n5}zCZqz8^g!paft5m$w!)7mh*N#_>iK|o7f<}W1ODwY7SUx7RPJ&9H zQbxuoY>~v4q8f&B_z61^`}{jp#uxAx9Pc2WW%o&WGJie~DxS3?`B0c4IXY6bOye4T zBV)iO+q8b zbo3y`oIDWKX3@c5YH}6p1k~K7^`fbxG45?bt&O^oxz{kK{9l=hq9HWpm_d{@jR**% ziHb?|BAM2j(qknZAb5>4gFfj4PS#tV_{;j)HT5p_v@46C*7Gne6s!lKoPk81qp(8> z+{&f)l5(pN>?vfYkTu63olUfZDP8gl)UscZgX&~OG4-5uWB^n1C#x2J&4&ES+r#XW^xrS@oW;Oc@OtS+vJ? zg+Wez{>qW|8A{@w`u z4*}cW(4R+3Qp!`7DVBBd%2X1HFo}|fzv44`xw;D7HJ)^m*hB^YycgRR^yC@~cazb~ zCiL2g$!3n69ONvJI(WV`F0>F8yG=hPZ_Poi@aSq4_SPo(j}dmz&VL@9fh|D@NCn|2 zKYsunxP1v1|9SlTo+pPj#vS|c_QkLz+XM3JQa{002J3HOonDsV=!!>c!L32f`M!`8 zR1FAKrFVEUhOIIe!Cn?;%LETJZz*p{Fun|Ljr(ZSTvVC)Q8tDfq-AlOBo#@41V&N{ zR{oA<tR+#4s`5bhfEfJE&!69zXi3yoMy%-j)?hY$r&P*fM1nFdY=E>?26O|8wd~ z|F(H27NrN0yRGp-kQXyJbYyokv2|L?234DFCIxg2YbLkh^Pho@Z`0*poW(zy#Jbu~GbYUgW<#0{=@R`Ty4K z`A<*}{l9xW|AKb@H#+B=?fG8pU!Ko@4fy

LX3}>Hm;k8%O;>L0wcGh=2dEE;L@q2KYx;)*+diE}Yr`G!F*!@Gh{XTj;8o3u? zYgv=y_?9F%xO#bDlC8Z{XD_J=^!e$|7_#{lQoS?R96^(Aw?eIb{jjQ)6FRU*l0sTf z#6O*n)tLAccVoWHzh{?B#gL?FT%V|08OPa}wf(8HMH#GAvIKAeAqpC`iHQ63%zxFf zF?Da7GTvWK4%5^uKKKcs{m5e!YcY=hmy`Hq=)o^NEX8zX=U*X+%z7#%#EQ7UMvKgW z*U;Gs-sM#1+Qkaky86@go7%Ch%?j71WrGpT^xx7hL$;CKnkR;qfe2CyDK;sV-N9E) zdo?IqIKzz3&dPPo4tGKtAWeKeZBi=Oi6~Vn6#1_?;$hs-=skpymI@**&>%#(nARTD z(2uW3=c47SBwCe17fW|gbUki%_^QXagpNo1^FNfTSX+rSs>{mB9ojYwsyi!;1gF{x z3!k#jPO>x4FTDT0cfKW8TbY=J7u7GYOJr7+MZNPeq-$KYJNJWv+!Xr>QRxP-%oA1& zU1yl4n&=w*ly1h=Wwz;XA4uq|6wfXJHR1biZ>}_U<$)T;@^&IMW`6oY# ziK8M~O3kox+T1Sa_}5!2r*Uvp^K~|URK%vBae39u8m21BDo7b=rmP~(c$1-1W36{{ zY%7eFj1Aiql#ynl&nR-3hn@pQEO|4=8wBb&(XSWkK_bZE>f=Wbn|yz+#C8B0Uv>cl z^t%rM+Yhn&lMBr7@a6Y!;z2zr$=||%^=YdRf1y}{*su4X2$0Qal>7W5M*2;gHjd=% z+uJ1nn;bpmPSs-?-RVB%?v>nIeQW}`GbEMToV-P;J*z|8Ak3Q3783oEQB%`52Mk0p zAfNpm*XMml&+L6g_8*V^?P1(j3@-cI=+$4cUsz9@ytmgwaW&sy%Y2Uk&%7@uEjvE& z__dz-IaP+HK+uc58(rMt_EGi$bJn%m(*)p491DqWXUXNsXKPE(Y%^>IqOE_M={o6_ zDXUf9`n~Ib?7QY|tzc?mvh4pMbK$Y$eM(Q6*)<;fD>?`~R$8_yTU&+LGj`0X8G8}< zXmjh277qvRgK(S(+Dn6_XK{t(`EhrGUH4WBcFf+6LpIWKryVa6CIxB?htjzaXWD9)66bDL;M^=-yg6pSBaP%klV}p); zXl!azDUnM~zC5oSpAg78U`z_owe`;N^z~?X0(SN8^BHuZAfyMs*HFDkaOg>i>^UHTz-xLVB^IUre+ZPP_e2vNzxg$|~ z#75tJ424);0l2vEw@4s^wU=+vBqJdTvdk|qx&DuD!%^{?{T^<|aESvzY|psMt3DC$ zP*&$qy6Y3C{$XhxUQdeMr1<$E1*l%Hn`?{6n8vH8c$Dvs9FNQ28|CA_HIrx88r~a~ zYYjC$)M^98y11D;bv^nzE9ssQcyTJH6jAgcYwCJn$WP4;VS4$38e~)A)nc1z=AxfT= zZA(R#ZYlg86S9~4%R3l3C(DsMw+8XQz#gbFPaQB7YG=Cn+2;I zaU7DQ1yM2xD_nr8cnFEGpom&{s*+8jw!^K&8Q<@RzC9;^qP7L&8qzHl7G*@V<(P%O_m z@_DY3!^rqH%nuq)hauo?pg!lSS{)I5>lE$drP7f%V9{@3j5oOuq>2 zj`y5*phAX4qar|HuyC#m)zb|~s}qCq#MrY2}H8?L-Sw{B5TSfoBq%k~>0(({?(siNr7Mt$i0xk>pGjabY3)ek`g z)U&v(EB;Kj1Erz>6M%vVFu>Phm>SJuN(lE4+D9qWut|OH)d~acifag_mS5i#l48Rp z=j}3Fp%>>#r@Hl1n8zrfXG0F$P|IVwBayPbNuz8bdy{*RX@u9y6BA2g!a@EXi<=fl zBT^|xhclnIOSG4jnv-$xv7jY71C>N^Nwle}f#QMee9?AoX%K5L)XwTY%1s~}$4oD; z2z`!NK;PC&LYEU>0MEe0a`op*!#w&>7fk;xvquSvA+<6)($ckVI66@8{=7frS&jDv zxcP|Uw$7N_-k-zM=Cr+?FToRRo5%qYE3ZqVXMv^rD9=oTb0q8~gm;Hw6Fhbsv2C66OGC;JHQu9WtV#BusAM^{WBA86aZCJ6RlyN9}B=u$W<>doA8&C z)=u_dQy@$N%@Yd$cuad9n0%nJV_0ZtXMi;-WSaJ4;li67pxlL8q^wR{?sG2Hy-30R zrMailDDB0!9_~7@bt->szej%y3ApaPpO3kv?WKHywG&{A+yS*cnCTsPiP?RAVL%^| zMz>@8Ex-mm--`463tlqQG^jq4v|^2+{;xekYzoz&`#c<^I4C;ju{|f-;2*uo1nk4Uz>lS#*f}S93$*(oFD3_jrfbquhXjb^w2pKt z88vs~>KJO>IJw0I@(%xIZaEvKlR2Q}?$FSC5{>qof7 z^A_Q?d=2U*Gt{R6VKnhioWiO&-f+y?SpUKMlVh5#_%yIGcYbF%PH&gVTlAU!8Tehr zG#m}^sU3dp5wlMtm93nu>U$5QvzP}gQ^0SaFFP&&E+z{l=a)4n(whYl36hYYPUN{= z4@*{%hhmv8I@x$zZ6J(!llp z|3}?B2U+qw3chXIwr$(CZB5(mp0;hspeRY}16#8mZvWQJ#&XErcimM&17{wom$} z^hKGp2|d=#3GvXo0VBTznI_-e(cxqTiirl_VbXmnG=VfPO$OIq&31cDr#AC6RK}d7 zo(Ng(wQ#evI$UMUex80Z9e_p$K+}A?A%n16mCzYbSIzsvh7Uz&(lSOiH_fE~gTU7O zwQzM35^)M04jRr^nQ9FW9FzTNQcnj>PnM)=@D966zwcDzJ7zO9gW(<|Vc(P~~Zj^xk)c+9mAM>hsoD;1AV} z=eH%B}g-ydJu*aSodtDBs{Og!e=(mQNg-p&wMrj3{vjjB2@s zH}jZVIo{s<0!`!h6vxdM9Y$#>!GOl#z(13M15<)sMA?&*q5>PDfP>tr?hnBTYzGyc z-lsSs&=pn~d3QDS>iknY98-@pPv4d^(HfxaA02SXdN(o1N-chP#4rh;DW+*BCj=w` zW%)E|hI#_Jz>Z|)yCAY#VT(3MiLnS##}N%bm)S%egVT!<4~tU$gm8cw8zoN>&C0+4 zEJ@y|#>~#%U%M7w|1RM8p-QzJFeyuz(PBmp7aUOO9`5a&f$+yHHHv85%JFo_9=+n! zXQ3hzgkvvYSl^m1AG0^q`$6bIA3qLvALWzxy7c42@MybiH{|B)n^1DL&9p4WCL(T! z6+q&|sOpu{E3;9R}3fwobuESkn zM;Auzk#H8<06vEz;DOYETLY2y`a^);T5qi?u{$q|Z%$y=5h04{j!QE}kn~=#{5n0S z@fD=hGG*_dolc2_2ESii++J+GTV+W@lkB}}&5>9~LX)z~Ca9Lkn5W0bzYO+Re=<6A z6L+46INDkb*N{UJuE!4B<3*ZQOvMUyq`(-@x3FliYHDqUz55eH0w0`S?V^g=WOqLv zj%Q|bi_d0*?XQ1hD&l*yyl=Bnoa_Gux_p85Z|+McXGc>*n|~~rtp8XL|B*8OBY^$y zLRdLN8&d-M|5?ZQf4=nguj29FIUoN&6qJ9}y8qnsxAgXJuKeF5y=D5=uKvG@Rb7Jr zeH-n!?UwypPt453z^qH~ziXlWYv}#QEBn8&&VGAkIsX6m$}<1gcxBoDX;J^FNR*TH zUp1n-@iP(MUfJOrj|k3|&;*R;tpJE2BKKAPstxeEu~V>R3?rWBN9ly+VBWO7x2zo# zCgIBCb&Df^-&M(`(>!%8t*p`^s32}Qsl=c_m403oj-gddq3`so1Sf| zSNg*%RtWC1l9ysKNahQWP1$&HC{c`RLW(Ocx=4$6JAQcOUi81Xu^SeUpoTf9yQSm= zi!}}KHAl!Bb^972bcIF}dhe(j>J41s%siuxr6D}9CTYB=@M92X?k$Eh$nmB$n0v(T z-z})w_VrI%>!RgomJ3`BRSk7~6{HSYWSKGLUvAKIhZE2Lqf_=@GW(zI>%YV)`?u>* z`j%>|*s0oD{#C+$cN2fF{_px1j(^Jje>i2o)!To);Qv`w;ACfE`q#Q}<>}$AJhcAh zcAQ0HlXy&`o6thYX=$M`Kd;n+M#Wo98v(keW!<*eB9L$0fPxZVY;RggajJ?^1MR6R zAUdzaKqG|;B8r%-r-DEMQD6az>JT_RkyX;%eg3xHwp z0s`VM0)U9Y#l-1y{<2a9pbC%_HIAvoaoIP<4?qd)|B~;pAY~rcP60M*3J^H5#i;E& z{yC@a@4%BcmCInf-_&aB&Vo5R1;(-?LsOjwh%E$QwA(C`<+&16T#By%aH7-8lkffB z)PCG&DGlI2MQ}PXAvNOnu)LNHP!2NN+0|9GI4|r6L|_cyOq0vzRl_Mb3*ZdwU$0ym zOC3EO11bOnz*Levot=MH&IyXZ4e;_fZ)xiA!rKWL01*etT%tZ{rdy9jfT_c8thN>v zR4DuifCxx%$qE4UkjD_n00!u7&9%#Ivg>dvKuCyL2vDzc2>?q0QZ~qS>-7nUD6rCV zhGruDY&t=IPtsh3D_TK{)v=zU!&$kSbQ{PgS4)-iS*5I=bB$_V^74}+;3FhNv3n(=vro*?Mn?%@tC}_vpFFVCIO64@t7+l#$IF$Z0wyi z3rneEmRp|daOFt|K|P9Pk+)K{@&F*A<3#1{54l*dGRsgc!5Q9%rA_H4(E|L51s>9Al@ilt-07z9#!(SNAZ;_vQVE`Y6J>p4~2;ltbt+xA;pLUS`iLc z_#zQT2tamlmM4P{As)yi%25%};J*=vku=1{hQ)z^m(&aa9v7^c7NjIIgm7q#GR^>v znih1{hRftxPP~D;6&KNtQIH}xV!auRNg=$$rapo3lSyU}M@E#=EdM5VTUyKEZ$~N)CS>PASPRmu5OKC?;m7(pasPl{E&LBs5lN&xo6?p3S*bcr8lL_21h`=} zAsrKvJiF4BfkmlP1l$j=?nS9M8@3n}8%mHAwE$|eW4|Tx)hisxbtQ^|?-dzLF~3*) z!8WiVb$03mH0JI`tgjAIi3LBue2(rnv?G1Eo(E-UUdY_FAbpUP0V#6zgmk1P z=`!G*hP3eu7W3n^r1a0(Qlq%lQ_`WWWcYTCE|=RKiL>)ar%7pHATJ%;uvv6WL{wcG zsdC#K0vcAqiY04-03?#r7O=EQPw61N=O+7B(%}8I(%KEBjk3ais?<1RUy9jII zhBj4kgI|A-2GvxGR3&NrA&dzL>3F;CnjggoE%@l^Uhwy!e#{2>8@8%P7*(yJsd3E4 zi6bfLxMNKo1MVIpFf@@r{bNPOcdOyAH zJ3&VJO1l<3v0-%(RH3s$l5SpEkuvcKI{>|5rJMEU-BL98eGOR*4JFpu+N7EeN=in% zBA$|2`P5ga50i3wO2uQ|y>6>({dDfs)Fhdd55jA}>${3E(&7gGmho6bw{|Nd<7C__ z!1{JaRp0!LqnRkDHz}vfrT8)|hm~av(HP5GNvW!o$thrMTw5q8Fk|ifD%Db{3eMC! zv8EWBJz7WjJ8Dv2kF3j)Frn65vLXkyl#mJsO9whRzJ#Q-6MX(I2Db!$lFlNj^NER< zKfba7hbfi5{<%qQ*gdxTN?0^=WD@-Tkvwu*!c+26+9ux(;buKKG>mSe_K5ei_SlP* zbQ>|x_6bH3PJz!GL+zBj_}8zomLieVNbcut|A2bQa5}%E-~Gp3QS}b23JKkO{Iq)+ z9cZ#DfGa937FzW54xI@|KbCMMlk{&aKQf9=!#3}J`67Mvlucy(@gUyv7!XGvZ&xMl ztDl;%OZ~B2+I$|6z)#ev5LPG{J`7p0Y&V9tU^U4c4Azsji;mo6r4S2$`Y-^UDILZ$ zOP{>CIO&s5x6SE|{A{KrdcjLl|<34s-VaShDdRdc#vb8|fE`KqE3^Mt0Z|Pb|jV zz>~lwPw%f?%LS50(3SfnJpcrVPygsu88SoW$6Z)QNH*&}xW#>1jrhP327Gu!&L)iL z);c6&1|Y1%T|%S*tN5r=f?Z0S0Mu3^LRX@U)zwsupyGZ+nh_-o#8?`b0q0F|utrXd zK;?b?Iq*OSZnHQkwb5&H_y+UeG_DYK^*fu;dW3C`}RdI;Hrbr)QI)gAsj1bWB(Qe|o^3T@y zOJrQo&4kg5j1fu>SaEva24(e17g)h$E5zm|jsJv+xS{N-@x*F*%lQ^Tp9ytHtkT1o z03*Z{yZgtoZ4X)^NhgdcFh#iLFPtIw)11bKU7yC>rUfOtqk!8dxR1G7<%I_Oh0#a! zSaGwk*4bO^_3hkp=#h&V5i^w&NRKMsVNR6{J={D*{f=vsd{sYA`TsWJA}>kCP;H>PXs)m7@;IHtW!1AxEetGEh!^OaVGs3GhoU>NgOjFOP5ZG^BVQM zt6G0d9kX=|^A@2~QXp=ww7C}ZngevEz?HHqG<7D^6~-@WexUdeorN?EkPJiWfMSOd z6-sB&Zj;uaehzjEM*bd1iLh5~qherGagMkx5PyhZj~Lp=xrMy#a@S)PyN@}}VpHLk z?Uccu^{u?9zNp16!LFg6uU`JvHe5*8;d<4>);4YZjt4WWkE6C8_-G2n5Z)=gA%q;l zpohs%2iTHOn*}XOab28TdMx}HrEMeeJQa54_es#p{|F)^iH#aGS?_+aU6;58{R|S` zj1+TVr!BmJ++a}uK>&RwS`El5!i$~A9*iP5qolqEQCIFwO+GMamSWTqBaMi1WjeTe_}Hq50N3UDI5{>XFc)(d9u%t z5rsTBb#Uu}!ABE=NN+xh;3zEwR3jwan(=xbB?3Po9AT7#Bn;La;yzeqE;zIfqLBe? zY!wdMmB^pQ5W=hvj2tX+tO($u4)5ZY!ivC%j*Jkgb>FosRLh1B)}VkaD`}61;MW2R zP~n=B#t7NI>mxye25(B^3xomjv>_{7Lb0ryF&NG>2>F=7lz^uOa~$a$)hi^f#!kO_v`+)T@}bLSi-$M*+J#R^oXgHmRDc4!DoLr9l9EYA2_)3oX-3oNMpubO zSBXav6lpjF2q58TkZ{USa8`*p>cs7Lefs+3>jQ+B#sh#CK*4iRa4dGQ@&gTOgD_pxwUR^ds15mxbla*tM z)-Cg_3PVCHXLv1{TpX5{TeUQCa+gR<*>*3jWWix>XC1>>v0ZFfFL#?eIkW;!S(XkS zFDArkjV&k`Tj{DbAw)j~TPRE-6bPR3r9u2e#tx!*4yI5L#HLXMnOKg=StNggAPN%z z4Y;*$;QG0UF;%XapEMU)*DKkRA3cS&-p0C_^=h&_^#Ic{%e*Q)Baml)is_k=GfcGJ zJCemlkjS<>c5#Nc?my53h;9ko)bx{WR`~&iS5m%TM4li$M}Um?r;#U+yk6?lEOMKK zynwj;EOOjwsrO8|Bc1uYyx>{sgR;Z}2L!KN?0`t@&spOKjLJfBtJk8^YXwj{M+JK_ z5YQhw3Uwl-V5gzqvmP9-5qJW!#TV%a@jm8+!)hf@uVElsGNL4>0Y0oNFI{X$rSkv$ zUhw=hiC-2j_!DQz8#3paH0wE;_h+^s2yY0+6D9e9VtKZ3RUo!sKK72HQ;$fOKK@K_ z^g(xYg_ZJw0>u+$;8gMS?2WZy1v4-72M=(T=G+6XCx9Bq8R2V6#xLoo$}{ct6$cv2*0N056dR1i5GpLq#a5IuDh{*io< zgjePHu~JOMWS;YeFQaNQ&GS?x^>=rVR{A%x+^y*E?lw^wHJy3pbYDgEc#@fgUo}4T z_&eK>Yn?9-FPWX8;u~ci*L1*iyWED zs|b?ul+p#LxD%w(9~6NWRhi2|GY%`pmTCCT%6?qHekjXolAQ~Yxfmk42=?Ng_wQYB zmK>v;uTzb%V~=pSWA!xuFmw8)y|Z|x$v)SuA@XFzx)rJHOfN#R&`pu=<&btA41l~9 zIr%;0(1GsaOi!oRYVJ(m#36bhSf_PFh81gq6)S@kYlIam%7TY($o8 zB^E8OigN-FsvJluLCDpyZIXK9KB1xg%u6I$b0$!YTMGZ(?9d( z=FB5!o!-g;AY`4+Zm{YY$T{BhR$$e=gpB*cIvvcjcCBO3GsihpLp7d(+Nug7QjnHK z%u|@nzNXIQbZML|B`P4_!p(fu%E_Ej?Rop7gqgG0AyyCC&p&ohuurFP}VpMsq8{8*Seu%U^a6cMYX zR5Gp4Pp|?i=_IH1ch6uX-l3`A;t(Dzc8357C$-q2UG)uL;}UNEL2&q2D{bHiJ*4m+ zFTn4X+g<)K(Z8Q=k6&B{K9w|NM?d)dGFIf(K_Kp+frD-fiXGlHXW$Tw^gQ)(k*?vFr6DVE@vUf9^p!FhOYQLksY37oh`J;fWhUd=i| z?r>W#Mv?XRV&V`;%3L7{2`jQC+H_q+M>ez0V{lcmE2E&6O8Tio|sGL^IA^43Mv z_w%fr7&;QZ$I2?nT)k}Nng?n!;xtxOk-5WFWyLboZqF`y+ zhC^_2XWnj<)&Oc#t*=h7*+cjxs2xsHlG~i5-=DS>ZSU1%l8??Ee(fT&$&al%d@DI< z@832}IX@k)aoRg}()bl(_s)H6!Q z=yv=qEXDj--QU`+p$}Xm2(S^4|GdCn1Ns(v`BzAdOO5YSAy!aj@zcUqSVO+~pPC^KS@-n-$Z zpUmL!b<}BMO11`@4Qoj;EXs9+l7CTpfYF+@f8)ZcUFq<9^r2_GKyu zIVr%Hkvok||17w*z*Isj96qJhWzfv4`@Oj6bw9O74C%R(Aa%`D&OTiigs5g*XiHTz zP@gc;1?Tt~`}T+f1Q0SJ+KeE{48@oW%@BGJcE#-v_FySqvqv$tsA%-4^<~a{p?Yjt zb|@U~{*4Fps>fVad0-G+QC`MfsEU+DmGGhnSCrTf34b5OA53#VbQFwY#Iz8M1HIA+ zHVm^s819$}-Fi3qCbdrpOxPZ<4omAhJ7|;=J;j64&zbDg z9-0@lex2skYBBMbfUe~s3J=VT$V(HU8-q+}#Fbsyxea1HNeCYoc#L`# zAry74b0`Tx2$djUH4j+S33|_y>{C0*{b*(DhaGnHTok&a=aUQ4w}%awCFf*NSbL@k zEiEni^n*;!wuo7|){#gRtGRzAk_$y#$FFbDcx>Ks+4Ln5V_%o0^BUa6m!98v8jO^@ z+_T$gaeN&Uc?N|YhNMQcveg^Q%F24N^S?rQbe+XVrb=+8zfTpJZr+pvyjGUL<*ycu z1{kqCWf9R8RGx8lKPN~C*Iu5|JNf7R6Q~%TlvyK{cVUo3LQC&y*dm8}m{$AGfxc!queKsudkpsp zT)+-###x0*RaYr9Dbv!mgd82euzO(%+e6x^LvMX5c)fM4{63?6t6-_HF&XW1OND+K z#HL=vv5DvI9~NcF^2v1!S_ZInwWuyAUuA4~GhKXonOf=dow+5suBm3RuBq4lpEjMg zaed~a@VQ19_rs!%(K~UXTiOa`^t{_Ex95d@Q$K<;7y=Ok|lvwOZ-YxyaTM z-(tq^*gxp(HJx5##wOx}^7uIIjtlp8JiNp89!_e*Z5_dH)3RxIts@mgaDI-4PJ7Uu zxtfaWxFChACq_*raC-aDTy!+UCBJW5*96_mJYmJO1UlM;qsaot5V6)t#|_bObuTmM z#9HSJA_?n8k>GtbPxkZD zu$`hOqKs-@)b4Q|`om7k=MP73=bWP4MCq8-L~EkFmN6>gL0N74VTSD$#W%%(_iPmf z>LP!S%!|!eE*pd)*>ImRhvgqhl~RQ25_5H6(4r3AIj4`a;f*;K*Yp<}C5HAAdz6v) z()IMS=CDe(07zDba|*d8u=p=g8usL?8u{~RYyoLhpmUn(KBBQ6EH^juaA1=zpAvV7e?y@+~WYO!ti8+$J$%FS~^kJ5IW;k|1CM*cC3&c8f$d;Z}f z%kK?0zLOuBU`8%vNP<_~T0E;@t6{fl;=YlGNdv>iM*@W=^oPL$G@Fb?X133O0Sg|= zsE8me0CCX(#igIFBl62K+*(11FoFTYo7P8iYC0`2Md}bDn1ja@$O=S<;B^U}e zjxR#7bge|&iRtGJQfLb~6NArqy5zw9~ z96jdzNkT;6{81D&=CL#1=-Jssr^gWJJYVA2B5!b+7ZNeIrm-YDm_|3!GO=!$ycGH% z94^x{t+yz}IG%Eu2v$;^v+z-!bKt%t`{2d`tdvqmLF^ z{I8AAk7n6!iQC5h$4YkojRzFevw@Wo|FR!F()TzxCMx%nYk>XdD8x4i^`W6$1qGLA zaHxi4iq5Oidmvoe{<;coAQgGjOfi<;DZe=yipcdh$gl42!smtxjA|v1JnG$C%FgT9 z_FuxfLkdF<9A4ufwB1)U2uVZ}ky;X21q@&#P!O?9!^1c*Y$IS|!(iAkfgdnQ1K33% zcM#+T24tmBAlc4Q6D4APpCJ>li5^ceqf0Loi_Tj~CQ-SdvbiLzLRcq6uWONo+eBNh z$$IvQ;Dy8&Ed|-V6^`v&^K1HM(ura!Fv?$9#B=htOIRgM)2+DOTcJt3Q zuWZ<^TexHs=_u0WyTz)Ah@LlHyUX`gDqfV(m2Y*OFRNy=Z^`qwKaS6O;gu1;u084c zUSO3cRa|d9J-lY*r_ViXq-I=WEI1zp0>dw|{MOw-aMg>NU(5&YNXQplbjk=zL_z*J z=;BHtX2c?9h2xOnE?&gAC>Td@D=M?qCkaI8$-GTh({9oc}63pGliTW0mxX z>L5=h8&1f{MM_0ZCXQz_mRbsN;BxRMk@nzd?UnPf_|^2W@b%TAQSMlHv)n_@0(z5b z*I}%f%2{Vl(shEahT&cfj#;UYktqg;@;IjGNJ>IFQ_{bP63tq=EKWsSD(EXXTnfmOMNOmF{dpDOx;dQGa14V#SZC-#9yY-YdzP zp@}{?idqs{xLj|eN#`mVZd8;EcWsy8_9xt^NAy_h{jpChK3nO%ojL^K{Efk%7-e!Y zgdvMtWltPjzzOyPHq6QS0K+mmEDv<6LsJK?x}`R#C#FLFx~lsggtaO9n8p2?N$U$cuPaKL#-3b~aBO);BjyUZdUHk6 z4|%78IWw^OB^E+Tqd+tS_d{#1>4uFkPEq$&PX!TGNU3M&p5T~dxF z8q6dscVZlF3C=B5W9uZhg3Klgo>N!1q&qhH9JQKG&OKf_ioZr;hw|Q?i zO7*$Kc061kH#21K(RoD0r0#9;yG{=q+R2#r(Mn7gOa9tC%4-nMJPPmIU(hG{!`N$wmJ`4I#%*qFO3$n%Dn zy=%r_z|7TvKL?8UNZe7e87X%Og*2D0E0{3enNQsrVB)@pT0{`8E9gd2j~^FddkOv^ z!1M;l8{bb?m^$uN$lV#mciKls49mOrB%$u1|6sIJm^;oqo9PpaJsav1`zc|(LyUZO z$xU%O@k;0j4^%;>N8~dL^EQH{SrgGTU%+9JsP4g(9i#Vh*YN-s=lO-`VN4G z`$p&tc*Gi^DF*acL1lU|9!be6x^P4<_Am5ObRrpYgzas`T9zktKI37Vu zD!svm8}HM?nOyN28RE0WgU8JavwUJW(+2rQaMLFFMzYf;rw!>!>YUo37gjkZ2d*x0 zuGL<=Wz0|N0GL-fX$ECn(IQp!!lAx*jG5U(NRx)|U)XMSGxo9Lsrz!SU=s|f*?o?i zL(>MJ$Mwt_;hk%iDu#UA(O&ib*?m+r2Bi-8XblT(_>rrYRl`QESU>90Sa$(w3}M|7 z{7hk=v9AqFf5(mE4=cGs{ix5%?kCph!}?93R;R2HntX|}To{o(xZ^<29X?X`eRM$O z2lUjK=#EsmCTZP^<%%S42+RGm^cH~or{AuiE6~iY-6crQknp84PiW|x15a%8B?sF+ zqAO0O$|n$>>Bue7a{Yljq@Vdnz2*`90i!F9_HPbuIQ|@i5yfcoRmR0#Nmm%{`k%PM zv^i$E2H2l{e8aBEJptycBM`fqkBqLnoZmr(H#%EGY&~}7s<=BUeO>JDjPa*k(MQDd z-$-u|wZ_bE5O%w!kBE;((A*I|zZ(nPk(VxWS8MNp%M8B;wO7Z_Z`rIgdEtz(D@V9j zr_XQc^bG%S1OZfzc&+xGJ7^r;7?W3yfUi!S-xBJXira(KHoz;!uB?VWlRwtMJD|8+ z0(%$T#omIw0puFczX6QY#rpUkP<^4;HNe{gy{&=X0m>=0P>{Gg7L!2(JzKmYKfMvcO`EeF{URxPICiwdv=>0;^^xq*% za=&m({66grUf0xQa+ly1_}`FazGQ|TW_&}>%vEIg7r+)~%F=wrh8~!07(O0u7`g?A z9>7o+us?wrKN7#>)AYXdWxnW3zD5jR{a*P#_|X@>taCsAdmLj)&!61bvoBzx=M<0s zh`cefbN)k_{R6%I!>|6|&Fua~=>COD{x6n|{}0UW-(2}Wli6kdMg{-jX$crP z379zkVNbuALJ@TWc2)+ye*?7t-YO#p<3Bh3pOJ%1f6pTLf0%CfEZw+1t3d*UkQ=@s z95?vLjBc>}HrT`2t$Ans-cu4(EL3ASkGBFz<68F z*on$9jb#M3SY(MIxbAE9ZB+PA=}{x!sPfFJjEJbG+5c#*ZVmaR8-wf+&`r3Rc6wc$ zSQ0&6cEF=>o0< zIY@#4gvdM%Aj%p#G6@z4%J*zE6?@o1i2ab51HOH>nuAr4L9lGXTCQsdszB<1hzRK< z#X;8gT-B{Uj_K!Dznq&FznM4Qo2$dccGVNLEiRYoa^=zrY!H7r0K_zo<}RbTP``U1 z65u?K;j&xU#2U?KR0SSLdmV1`+soqqwS8lNKY(qn)0z{+t)Y4!AayE$cTLKvIW5oW z#6WYnF}Lsr}%n1Zd0SmXT^X9ceLLI2hglWq2%p*ZZhs9>@HECt3omQ@QM3 z*OfCkt6*_#0D;Fdx$GO7@hZfBAOtm=@RFnz zWfn>KgEW@^Mv^O*OB9)EkXR$V)BDp=5{-{32!*&w);-Ugu0k~+;T7Ss3NRS-Kyd(* z2sXQ!Sc5~Z!++f104W#>08NAuqlgi0%m}%_2o7C`Vs1=oYs~tGDm#oaE!u+vccP(q z*z0SL`2_v_Wo6>yYyQOekx)H>dQALMSpM?Qiz{SM2I5`yvR5)zGTa6~vdmN1&#;j+zPBz+|A6$U!~!S-!t2pJ z5G>o#JruU8i9H}WAxk)PuQ>?{f7;NAIzWsVQw{$$jiB4K5X`htQ;Q)Wnm)`h1A^Cl z{_p;Sst)MD;~I%(M2cpJ2j=XLGl((+eCeJHO}{nGK-`yxI*1Pg9y9~^L>)-AMu2iX zj?dT8ORm)~ctn*v{#RoJqO_2gw9rxdZPI{vjqjz0#`mmgW|}u*C*}(_vFUm((_)V- zrn>E@{YDxY;GO2+-MQX+2lwsUy20MywFa3Rx+Tv>oChK#EEUPjVtl#N=|>cvRUh)7JBat-#dbt17B6W_!By zH7y&8>~i--x+v5zqJyCCg!}w=PX4s%ddP*^wrbLv$+A*5kU%BnHSw`^a3;vHln#kl zU#>E_;%DMYlAAq^TgZuBq&cayJG9xMrnVU3vHLQtuOp+miJuyYR1a(`+1n>fuF4CIj zO2f@VY=m-3a$<9JbFC3;zW-8eIfOXogwf z`e}a$B{lntGUC^a^tcrJc?^v)`}!s4pwU(IB)8Tuqug|zgK~^xN*#LyZl)Y-DX|lg zrHo}*v86Wy@I9FER#smhMJJY|=2_dr=68-j&!3MTySyT#%;d;RJMf}uKB3MRaW21{ z%{ZBzI3BirqGF669+s6Ak6q&NWXqIDOQnTT5HB!Y^fCDI*Ht}K!9)+GoX5kMUJew6 zu%vHs6m6=jVMR9p{-R0jr!*~|bKW=%x%2@k1=)zFl4mQiWTrklrF4)tC$-@v700)W z5uK1?cZxid%S00Yy6hmY_5F-vxqX+q?XrGpE3bD*G-nezUtv9Q=eAv+xo$WLj7|A| zgS$NnMkwKg0Snc|a)rZrLBZH*SywdVt`#+*Q+8s8vTzt;4Hq6IcQIw$Sf>~%=64{B zd4S**LC(*c;x+XUcQ|ts`g!?jUTdyN9+jDbhU~oAlzy>n$xn^VPP(#N-)`bc5^V`P zH#*8v!d?{Yt`%k;71MXw!j3}b^1xU8uNF*+*V`LHQuyKqFcpdKc!rH|f5SfB&kmk|)(z#9Ss zTywp~v`)Ep=?P+B18s-ZVow^>&((_}xsJ@I4wkHygVen^V} zwY^x4kjx;mc#KlaosVZQ#jI#t1V%h=32@o{XZ(+B`0&^)@~9*|=4+Pu;Y0)kA>`u& zGHYVsF$}C^Gt7f%+~0XH)UzSjb1}550WhBt>|vr@CYz=>0rNNs-_AD=n81M9*!%gC;ijtgT>apoydY!ZUz3MRW<7&@9AAmgbem&V=(Kfbos4N69z(*UBxh_wRvhT~b{;w?Z$Q zCzq|Ot;}e*-4J}hAOta5GGjI~V?woEu6IcIJyat?J|qHC6AaEA88Y(3;G*Cvf*xY@ z#LUs$=gzNS9x>NA^|2F_MJeI;?6pl$O- zFo;%$u%KSoNPSoR^^@1as%dy;3s=TxzgHvWOHNM z8gi$h1$$DeF^^{iw*~FsU-Oub;g@7H^Pu}&8RBe#5l@Wx*(ivDj(bM)B%36Da{43b ztCUvm+Ru&87+aEGL{aGQlFFmrG{Y}#Ahg3&RY_QbsbiK1qcDR*A8lwSkf=r|EBit; z12jp-(B7*dFd@(f^)P%v4m_F?B?n@gL7Dcz>x4$2XuZM6_F#I0W*%5myDVd3$9uv8 z-oLz{%&^=J#12@p40QsTjMl4+BG78x?)<#Zs#pJl(B4*=3E|J zxRUjr?r%XQvYwwip6LNXBx8-TpQ%a;rrS23!8cC>g*L;K?Q!4?82JX?FsPmL8oYqE zETYg-jEbA!6QjMN80HvuG=jq2Vf>UxCe;#7zdLwS>%R6h@luS5V2>?md)k_Qnj(A1 z>A~VQ6oY$+jH!$>{e9H0Yo_|8rYu-R05Z%7BI<5+`34xxBvYvHjMZog=!Po6kfEy2 zkXKYROGQrzRb-XKf=4=a6N-QWh&a&30ty6F!T8nvO{?YSg3}fH{qDH$ z>K@01!-bpLQ^}(iEFA!Btl_%STSbI@^%MTUGpmkS#{b=W;_&9Va^u{a&*^pU)_*y= zgbyDIaK*2d)%h-fu$}XI{{ivZ-KTd%=Z2?~u~AJR581h8tC5wlffxi#DvDUb{WXOO z1ch))7!{&`0EO~E_2jwrTdP|S*0y@|;!po^gM0UjeW5Qs(9gt#0BC+YA71uB1DLXM;Gz$zaWfE zWI@$)^?SzsKTkJ=HB>`BO?}>;sA5N;5oaPtt|*#T1`izEq3-wR97PywY#IKhrScb~ zSMw zrK6%n-J{2s^z`InWhT7HNv6m51A*%H@q!y=D2??Oo=k(^2NxK|&pzHD36j*W0V>#@RrIVG~_+E`=i4^;Oi6~r7YwOy(zCdaQ zjvmiCaMT>jKyY}mCL$L1UJRICH5uerYpLh{PCVpSqn=rGmD7!!Nq9Tdh~W3f{5=)1 zFdN4X>dS$NAP9(Y&L{{(8bl&@i7HYjmhOX$k}6 zP=#J;Vj;j32+&mm6a#*0#JgYxFOn*FdbIa8h2Mewbndt9yTOF+gakD1igfObiof?w z`XVbq=-D9jMzdm$XkOwUh590|0?Lu@}zxHnkt6+roNb9-@DhVR&N zH`+a4a!Cc za>(2j)3OhQa-<_C%Ir#sxBO>!Jd)QYOeBifs6bc{Q0bJ1xs5 zJ`}PyGUs-S;Df$#)`@W1`Jnp>=L3#D{}FZK%zu9BYyHf)CHG`Zz7;!j<~!=lza{@P z=ks9m%692YKYpgSIM>aQemxX|e|zOj&sXY|Kiln0@BE4u+3hg;o9h*g!YA?sWXQa}a&6s{s3uU#*l0Fgt8r{9Dm1TT?nV9oSr3(GXkFlFsZIXSOuOorHzy z*L_MI;5N?i%L}}1(bs|**L!%cc&GfwBBxGav*-vf^+o(!fhb#nlFsll&gxzynA5Y_ zSK)|z-^qx4u=Ik?;9g&a`>dbVt|6qoF2*_0~kUw&y)dtu(*7nxO}jV z9&X}J{cNZlL!$TKI&eV@J8+MjxzA5sWr{W&n6_dnPhCfyxoNF)v0dTV7sPL~AR!i9 zy$2UM9YP_?gZEU74(n0NA%MdPM^uW4gk#EA5!T}J$_HK8)ryEL&>fczjY}NP(hPbrOy1zd%-XBJ&1pOQwv_vf*{SGiaFNj5l_Rhmg6G!d2d9gpv z)+FW{8N+j6<8!9?p4CilT%EimB{_ucq)6XVf;L*>TSg={Q0861Ei=W}=?H8pCA4WR zxx<@CCAGtvP~%!qEWMIoJ{8mc8+UIR6-mr6Y7PSo1I*yixVyXS;O_43(zwIm?(Xh` zySux)H4cNjF7Ms_Ub){ryZiH=`=e8-s!mSQU6pjFlIK|!v$&bEu~guly~j59h^cRg zYlJWlk8dQLMI%@!{Sn!Sr#TYuo@IqOnGhwyhQn0R%eyXzRu9kXE8*xdvRRR=9+}tIuV=T= z^KWX-j9y=HZlOKji8=(beIvZ;5g=57X2pTz#epUHf$XVhyT3F-rpyV9-Z``9$jOuT zbgl^A4fb1-vxd))kZ+-J(ZgoVD0ShF#l0%*ltY$bhx@OPT^gFBj_J$EoldAq~ zd0Gc@Y89%^md8ZXYiCPVS$weaWe~8{li~h^cZolh$43ef|A|B#MUN4o;?0LZfGk;# zkOz-1MY$@-^eGawl}!k0Ld5d0kbGR5{(UK$`-4QY7fLWXNH@|*XcqTflw1&R8EF%z zmHE}mZBS^nFPelgpgy=snEiNhdi&CU3OK7A`lF?k#}iDlF<=Tl5;_}q7xJbSlB~f* zD6TfRnAjv}D2VoFG)yLvOoNG(kz_Niqe3&QBuflW9mzW1tr>f&u;eeMUN6D+88xsf zJ9np`aoI%5C5oS;LdG!)xe1i=Bo%v90t3eOX^!y|Mhxbp@#3tZq!xZ7i46C}ac3w2 zk_W*AMzI31AWq{LlW1uWT${#={2G0Cp8!L?iR; z1yyF&-b0S^N!3H_gAxp$lP%u^Y^it0C-0!c;wmh*1_Cc1Z^KqU0ugUe^Xrs%a?ko*&F3lmSKNB+k{l6Lpwpg)c>~qDMPm z%3@`Kn5W!U(WTwd$)E#IM6Id61CfyUL*fI(eB;L-LkqY??T_W-B;6#xK82Dd6xN(y zTD!I#8DH(yL)jx_{(Wr1Su^JHTPKsHqG7{6+%Dl`h%)G4bO9rJ4NtKm9 zD*i}DH!8CnZz-{cDys~vVk*AbhLx*dp)abiSeB5>b-ZC1oRos{@Ub4e?qRZOg&@X?^;pQgfuuCbASF%QE$ z0Y4(YHN|>32)lotN5uNQcg>_Z6;S2fQ*x$jX=!=-xtp9lf}RyPviRXh55ixojy-_A%AEAuDiH^_?tBGN_XCV_MIYYuDGzh&Y7M2gYcl8Dc)DvF*r#ETnU z^gOTMbiIyaCxHg8wbHy8LyauqC8KmA)JO8MHM6Ab4|RO`mr0=iF)@P7%i_G7jTD?T zCBmjeE|S)4`jIzb<;V{bEgx1zEs}Pby}r-HQ6PBZ$RHLM1jW8X@6C^!F$ix*F!cy# zvxl+O2cCSz({6{g)d$sdh4XrexkdD)>k7y3JNgzuzdo zNE3z7z%v}3aFC7s*Zku*APVLd{_kHPOB5m#&q!W!#!eAk;)p8wUVWs2LBxc-Xdr|! z_Pt;z5Mo~pQ*;{7co6Xif9e$~<@D4eOd>g3=P%S}tYC(iJ^^$+Y!Md9$UgK4N|5Bd z9XkYgBppLSpT-Zy&VGgx*3N$VAFQ21I2I9fF}(;N*dIf3AlL~0KUa_-x#}B?FSp&j#>mg+zvb3kbVL1`;cJ*@H>cM^${DHJtKr+@GvEy z<}-*ejGUqm>?{3zSn^|ze)6c_F@lYg!M_igzUN2?oD?%V4>3MMmH|0FLM9_*WUx3T zuynB4td|+2n9;v8l49fOXEOe|$kZxB&(lxQ&hLuhAZO+g-GO255&gz4?}|ZYfEq-U zF}UN&jDe>QCc_A4K#&$0ZO0iLPQUi}JscPYL@?Eh0wPGVYlXE82AlP8g9NGj%s*rM zb{q#-c-vCc^t|2bYG$6kbv4tjcvN<+SG+0)HCMcoJs5*8?8$vM)%~t`hlZtBytMq` zz%Ky%$;Fqqx)NgCL9AmEV0EcEwQ>=?!qzd}Y0n7^K%>j)J!}f4VVC5Cu z;tn?mM=R(i(gnyd$+p>p+T865rMmm;^I)LzAeUOS@}Rd?%|Ud5&gxEXA$!S2>uz^5z(^T?~qn7Z4OQ}kGo-C_!!L??b)5wlya8)c1AXz2D{Vwh6=5jdSjs}QkJ(3UIb{AL6v^~@V*l|UA4!ZPS z*J}@jvdh0BeUC_wWV^x-{uHAQrn`RkVcrzNY{IlPAhKcE?(Sey;Xg4?PmmLrodQ);m2KvjcOu8=+~I)gT^6RsE^-OeE6 zGlAeMB%S?B7H*sNfTgQ|E2Pct_(4h6_`aq~7ZAzWfa2#4mMm6Vb#&jG>*8{#%VkCl z^2M&3A=xJA@{10=^RCy~X8_)AcGe%fY}_8=kL?|h909mu&|!7nMs7Da>n_H2HfX8= z&(@E=`pP?0J_yU+zr%NxcJ;Nh`*aZY5y=*vZks+>cZUY#hTWqBa`TLAiafmfxyhQ< z*R*WP9eh!}HbA1l_`W`%ClL%@@(Vq)Pi-@GajyG=FXZtZ&*jb6bCn=eG9$6@3bn z-kP$0_O_XO_<*lJuKMsXnsfQ6lK#+5f9IPl`jCB?`#4;^{n#u1e-2()KQn#sRUaq# zj6~tUA}zJ$|^`$GQG7&T9B?f(^v!y2|`#fdZ1B!Z6h zFvgZu^ADpSTrnmMnp>-dzT9rL)=_sb%2ZbKR_>eXzF}TY7;Aqrc4TVfx&2 zauVGi-BqO-LJi?`y+tK)6dILuaTSzs%23jkJOq40&-hwRYDZ4Ouz^ByG|KPPQxn$# zA!fkPJYkv`V#VLo!x*j1g}p{k#a!AXs75rrV%I2sm@(S=i3Vv{xk|}f1D>*K4o0!_}C&jZ!nViT)?vaH7Ow_bn&Oe zP&@L7GqcjdnJcsM*%c0ppAD~@pItW^p)-84B!=O$*9^ecuOCL=vOdUHq5WFk+U zMZnoZD~mfC9}3bof!%tO{3`XA{O%04Jn`pr0OR4~nqAaJD!zt$hI_5IREmG5>0p#t|MRPkYf1-6BBRJqQO}UlReddGdeYrg zk=L`yoEmrf0l-L6*SEM7sayv&c2N>u+z)}ETeQ5{`S6UVdJu=#jeHeFt0r`31{`SyK zr5phZIoauAE}6;nW1bZ@BD-Igj2Dqg4}kA}b=?)M$cTaD7@%#FMaaU#iNpwC2yAN{ z1MlYeruGPWa7&Nk^0LT^9_8;w&p2CIdVv_X4{o(aoem44A-@}6Od%y!~i z>qyFYS^gtE1mE2JqF|mr!C^bLE85o9`c54)Mwj6fyEbYC`s;g}Q~#3}B@RzPzIa6> z!~YjkUvU~*u&}bJt;w$3PBpoqhYQ&f&-+oro@WVvN3^5_UbyS}=8 zI&)4h#n*2WHp!a^k~qhpOtt0#)Orsyp4P0RP-tk(s}Q50K6{^{kF_wo?_(oixnIyl zXvl!QLU~#dPFvosuB(x?S=_Cr*%vnjvA45WTD`^1K5?c~N2mGadnk>o6fi4}>KHBs zvu6m#jTjM`?`Z0=g8nLX>w?H{m)K$7SQ?c|MCcqBjskZuJEpbc%L`&h;)g)aBVj|Q zR|f+D-u3K=;lLS#TGa4OnI)d5UXG~_#?Gl*P-I`UEFUPK_Nduq_-}bty4_pm##^B^ za<;nLSk|lSOaN1x=CE%#9iEj+>m&+gxoT9Z5A<3^wy`IUKdGFi=&aW7;*TT`h02wQw zu{Nqjb#21yz3DxW)HkyPlXr;b0+e_r+l+RSi5 z{)c$+^{85W#jzftT}B$e?rd_ZU3#R<#hA{-Xx1rKNeF2M@s5!q8kPP1_m-Pa2|>o7 zV-KI+WT;k7`XHVdX?&*pA%sa!+Mo;WB&I`0Ifa|=@4gCAIJ#5)pFnp@OsHE?#W7h0 zsWgr2GFUTX;YnEvN*UsBDnBum)OW626NLy>$lJ7aqL21}Q4Ya`Bh}&7WWA0*NuFnO znlDbD3&#U8oO=LEn@@j9W?5hS9|~=&Fr;*B&A1NZEGw(t4zi~(I^5`ut_0D!zxKFzMD)Y+h~%bECF`-I zHLfqOvCP9WO&##hL5-suNq_jh%ZobV-vG^YTsoU8xyaS=JTKemR@OFcJjqcd*0y_3 zDQNU<5wN7D(uClV!DX}B$|SHYFllg2Imf)49H%SQ_;E0vk4)5^NX(*Td(mjsO#|(N z0~o2$4NM|fg}I4$Q}=QwvI?_Uqql2F2{C8X{%T~kNq`RIP8otVq6^GKCvr(^-Rp53 zN^n?$HR3(Y3~e1!tWL12*jO6uM2tGXc-Kf~geY-1==5^(XLqh$DXG43^dAfzI{S3J z44hvi@$w$@+&oytHojE@Z6DxWbi^z0ppkvdw%#u(qLBgVhfz#$VFW<*=bW^pLJ8$^ zjoqei63-fv5*8Ky>kB;uBtuEe>gf__8h`}m2VK*Sf(z-abnplD4Xn|2 zmzRr+x`7X~Y_d15m-e&GwISwFL70?#b~UKX$!s)ta16X+ChD`FFL8w=$}9%b$2Ggl zvlvB#d!y0^tr4%}+d?nF{YK6;<;I_^eWcda zJVr0;q|4M1Gpt385qGSe{4-8&trNY?7V&?bKO<Q*QR zKsaozJX;NGk%DFjNufBHUd&bC!h~3zg)uCNsoZGlJ)qcgGVmY;?=&8VClFv_Wv|i>84c15DxISYQ$BsTX04m32UnZBGj#ppE zj?0=ZYhoS}$dbp))IJS=IH9lMMbX}RcLB=CTCA2iRd8+mQkc~Xc!Mqp;v3DQ?o>&K)V9Y)u! zY?#7Voa$4@N>ZzGCdP^PxcddQf||>R1BNmf?j3gYIZEwWvkvzA<)LXk5n6s%pzJ0% zBh+TCi_GpJAodkRNfCe5CryB+8A0bOxK4FNq@@f`+8S1XTES-KJ|Q)J;{AKHQQKORhj0x;P7W7 z+vVbksKw^xcFdW(>$DUHKg9?eg>yjvdrT@8g$q-e6<{@VLu&b#0|i9LWQ_V%pb%3{ z3o7zyN3Tbf+GDSjX@_caz{T>Lk~6J$ZK>ZI{1Kj1q&y8VHfAc@EEkJySrbRqiU(7N zdh>{TvbSotLG5!xpyTgqInKG-`BjsSwd?9uVUJ~lD>d4hc2P*posoNzd)U8znMOx% zrHOA(CrucVHMmXsd~gDR8;Zq3#MDX^OAJ7kQjv%h>+O`_e#){32jfLalNHx&G-Gc+dQ=eZZ=f>A;K;a= zuR6IbM{!v8-RHnMj=wx`iz!MHT`_J1<&Tc6N95~#!{W$wHhe$yam#->HOA9^-qzd+ zeg#Zwd3FeWpwQ!t_gTLodg7$;ashvA%y$(5%5TMwDAE5$*xQ3vD zf=RhdpNa!axByTl!79U4>!L@9*>LbRnjM?sxU595SutK6-sv(<+CPGrA=i%HDjs;! zW@2YCmK=W#<6ZyCTS>1qiD-I6v7VqkG!F6{Uzi>}TG)*%t4~w|*GGE{AuCf$!<>|I zP6^;ibdQarq%1W6XOc%u_zqyU$xK85bf4)3KGM5AuFmMnEogS7#ev%3q^33FMu=!c zi`~(-*}I|2N*l`ylY(JV!)gX-n+C_+gQ&2+*-^-!L&li-VHxcdSQlnnzm>c=?7E-g z^^173mo!vmIk+uhIo29qMo3PzMUP)@wxkAx@>73WUe`9ZPGW-_C&+x7jrLyK1eR5E z%+haR+WXTe?MnO4=^h>)ieDw)*fecwHceR|E4(VqeS&pwnY?eI1In+ZReB8I&HJU} zE4k%ka;@zUlVg*SI)I2@JA&x5s}1LTdz7iANd$Mw?(pAH>Z0Bg7DS5s2HpmE*LA6l zEFxwziXVk-IF3hY$oLLOe_(*XZMawbZV-73w~lZ4L>dXgh=lyaam%saIYTC;?$N6lctWgp8V(~So0?qk0U8pi8Yc$PEzJH0H=ad zQD#zIFSq*%RBbhky8nrF{S}bu^jfjK9Y&Gwe2!w%+P;5VHbch#Q4(pxyMK)*133_K zKGHk1OOKKhKrPOaJ`q*1!umg(y`vnvA*-7{;0kaHi2V?!z*2KO=63j7yXU;-mRwZ zG~j{oV#p$FAG+YgcVJPwFi4BV6$yq zW|#a2z`E(8{-O@cnZc^6PPQJ_`E$7N3znt_LHWcak2ROe*4esb-AjDoSiW++=g3|F zZlSq;cvH{kT=@8YyWQB~b zh{eMu|L{Ir{af{AdL|Vvf`rb=@_R3`EKiRLq2-s~Z)M@(GHjMQ?y}l2l;SObYCyQ*B2`HOS5x{Gov`oa` zqvOs9Y6B~)C_3!r76|U|{Jt+2B@Kg|TB@g9DCm}EE5Z#7qy^8QPmH}_OL4vPvdiB+VWJ^r_Z}-MQt|6oT;0g2kWJ(SzCAHsy~%s%m1N$%^B^5gs3GB zPpjxB3Bl@L>#tuXI0x**UB!qIi1cgkdds8Kc>^+Oare`QpGYk#lw&nnYldn=c`OZL zDPjj*$z|x@s2-9QoUd4b+NREIBkFx*p~f^L?Y|RkdgPDQ+T3nTuHrMfx?I9TFShjT zThI_XV;g&!%;O5_h4bNl&7{rvBVUX? z60VY}7BHu-RmeEBsIIl2;3|?}T0rZJraF>G9%|pfDUz^jpSqZnNt039LC{V{82*Yg3SQcQg4|**Yft1kY09d6vbsS|e)&}O! zQ5V+?MVg6EfB4f=gZ-du8&8+WBzoH#5%&uEga|WM`t+=jM$8MYua#rHsAWLJ%*?s| z$l71`$PDSn%s?`%i55FEq7m=k`1|WrNbzHe`Dt2}8gObk%^O3w?~aDmq<~h7@k(@c zgz!_6Qet8el%ds$z4z!=K-^zjmo4wy`oFFmjT7zwH8~iMhn*->J4XVrf+bHlgCHUsu&`&U#N=nQ}ExlL{sBx z_nn>d!!Eg;878&rQ*G6a4`Db6-~=PMJ5U$b&tpqXvBW3Ps|p9x|0n~md|mmyhF-jd zo`W5Ue{~dzN!>vbmErfp{Hjft&V-3I1na8&8y0_ewYJNAe)rAl>JDxfLHz-nm(`2Q z)y&^%cE=#okv{UiHj0z{w4|?>^JH7#r|8ssM7}BBRxE)uML1n2ub5wZ>-NmaXQ(&$ zNWHJO0QqEvuos?)KS#m~4M|h6t0!AeJbZHFt1`H21o*DWHbbBC4z2ZZ?UU=neGMjS zQ}mQO1mMoFzoH=HLTRj!KpS8(8YntS*?bqAN^3mjuQIl&x)ftvnPg1$O;#~a~%2awPzzDccqJ<_J!~W+y3!36EPnDB$gIn*^7@vy<=u`6m;p8!}0Xx;o z>)GSbwAn?$YPmdX$;LL$+wnD zl80wFe82u>%#EU39RA^q$6dsG)}{U?!H!rKHDkP{WuwZU`H`Q`v|HZUJIF+&$rJm) zpih-5Zn;T=x|J~Rx$I-Jt^R>dV5$e|LH_54>UT?wB0Zc#RquEQjKkm~D_4#Q4WNfT zZuek%90$O}Fy7DIGn7Ev&HZDG08jg*Z6f*J=}{<~pK1fQGF_CF3%dmw{A00Z`hB3r z?$(~VKZDe{AmihtMC$TH)IE5?vdseC!4zcLLaj6nG;5JGbBdr0w^eY~-xaRH=y)E)!FF)lJyQ`~HUkZ3wx%ES7kH9XhH z@5N!e%H!B_KfYHN)_Lz0^K{8{kgPZslrE8O&v@M=kycB0C2%UIm1PlT=7m|=7!bR; z-{p+L7&XaEuRY;8EfxCs#Jf(u?bUj1WNNN0Y0Y+;-=#UHiH22im%n6I;$*)@p&*>X zPIX<*Ze{zxp;)#8Lgazy8RYoI1(o$j#?K7T?AjIK1w_o)$Cjb{s?Ai_qI-0a711d{ zuE7w|H@E;R=1jBH{Y+FXGtP}#e%&)3o@GS0frh0fwo8c~u%+LAZ-_*@p`qeD$GGHh zGos-`$4qw*6WMz%rzXMDmjPq89bXEJjz181 z@}wj1z-^eOJFFqBOy>_8(G0Q?C&jl*XdFj?fAEejBWuljKmzWvApy~^mUgjFAE8WG zT0f#o?_;xt0UmzgAD9|@HNv9O7sCcR(ej_Gj}mCs!*G68&1gC-#aJFxZ8ThtdmT=; zmt}*_>r}YyrmhzwH((38D$}{2>_I_XZCzbwj|AFVur7aHub+IlKi12~lPbR*Dels< zUs_q1x#7+TBO#af$L=a!DFIu^%i-cJ6#lruEx_~$jb}Vf&-0#2_bZ`~5V_S)Uu7>z zh<1e8Dn#j!N*@q@)U{BxX~lW8#3N@IX1xyBANy`Px?*rW^fmXv#Q>M^p6e{F4*5o0 z8zM5@Mj0uw^5u-04DWFI(B?B;XR8s3g0l7~5s;gjB5>?wuTokMjJ4Y^04EXty&|83 zL$I6kEe5&eb|LN=oMmPrJMFzU^HdAr;pdYcIk&)`GIwxZ+Yex&N4r9dOtDfGewuC4 z=XEccZk%PDYOHOhQ9?V9mIly3(_kZG1+1;y8_RDA2s1T^+^qMn^Ntygg|CKrS8W)y z6iwX~`W*QrJ7@1t?zVkSynN-^Ii3UEpxoov;1-lX9mi`2@0p<^oeG4x$Gk>dIghH# zG0iDqH<=mW$JvD+ct3%m{h+u_W;_Ufb9xVbkAH)Ia(Omx<2%#c-8uyHy_dhvf2eY1 zzDdclx~JGP*k=}eUl^hNCE)l=of-JqH6}(dXk!K$SuZN{<;O|Oyz`G|o z;1ygie+kd^KCttJ2zxE%)>Ve|XwMMs_EaCf9lg+J+>Nd#dqccW$flEj<@P(8nnqqr z%!`Ydxw0!UQH7?^|5HsS;Vxrm7r-O`kB2Y4xRlVBMR@}x$`hzKsP&b3fBaOc#mo>r z)u+P3wTQ=zIWvjQAkpKl>ykrIR$9u|o=#VYxV8EYK;JFrY(PC}R@+5(x>H|A`S1bf zRu&l9iqDfqjHP7pnPa4TtVMAnNqdhvn}BFVviOnKNwiLefp(Kd;AGs{xsr{8#onk= zS#t$GX^R9h+(zl)v7eS%Bt-7Lyq^%IqF+HbDm0-*IHWv!oraWG1OBmMg@wJs55kJW zIt-o>6+`vzMb449y)xzU=`sEqR3}B91~N;FFyw)^qwX?+g|6k82lqz`VqC>C%O+j- zb2qAQgFYYgk;uXDv@Px@Pd=H)VwxI&jHYQ21-wrC+cO4i7N^hQ>0Zk8@z_BmC+R`B zDt4PiZ%U$9??}yI)rGyi8LUu8#G8~`n;`mRp*VJS4*eghySepPqm381C+#$&_ zOdAmkcT$PP4KhNwGSOG=*0g%dS~B94PhAL1=mJI)f*`{}`Q5~*LZP&JRfrtnsP*T4 zFXv3b$TywDwc?y28Qa@<_GBWlcr!)NQfIRTJl3n@OE*?SAUK3DdIK0^X@AGVsK1)` zQHR6f&2g#Cnfl$=;HlVFo`m5hYFzkkbYB%<3@WOM$5{S& z0ATC>xYKTw?YG8u)OWBUaHu7dAiSZfwR!h)RS4D@#|#JavSLdeAF7F{C-2$R6ee=b zea60!t5i6roH$M-T*Mt6xaT&`$Sf*GpFfNI;Fb!)+}5c{e(BR8gLlN;fVsE7`O9+x z?V;TgV@lh3urG;4cN6d@0xu}p(KXcNmv0q!Dl#@ZN{%FW6XYxy5&k!7;N4MwE>a1i zQ*x^=>OxkiAP*;SZ`T7e`lROh$urlUPHlgO#mVo(G+Y)<!d^hA>tZky|Fw~D*;QW4d+h*a*ovWEJD7dHOosbFZR0SM-6pbgs;RccPE z5us&_QoK-!Qh&cJrR@1e?#0GVNrh1zj>p0_5jct8FVV=sv$h5KeD{o8N@Q?mL(ldR z41;f}#h9AR<&ZO!w-g~NKzLD_2-O}%bW<1G0@|awDwtT_x3aUO&ZB(Nddwg5g9Z_- z{^L23Mc?j}>?yVNG;%7tSN5!0XX}6QXle>BPD=(zCN>l~o!|le-5c&r*K^-cqsg%v zOs`!2{(KdDLAfyB0#&P&3Cwz4nt8=cmoLpOqkiopPoyCDq>K z<8QMjT>0$-heCmYhYI4gDJ#xzn|pAXZx>?cVtMVAQSip}%6}+G6}1+$%E|xVz6s1WeLMzP5z7QsAh7?XGNEFVqCYE6!d9sr2T}MM$u-&9JbC6CgF*) zHBgEsK^%lhRsusNnylliv6QAML<1Kr!Tfr$sHwxwKhqWnZaofTZLcCbqGeAN^iEurLJD?%fYlqymH=ech zUgy|qMbZS`Nk4Ad$~I<62v?!l?m2(MbWHng@%?bt*t7Y_Z z7zUUYSR@g#ileS`>^EXB=tICs5qIkD8 zXlu{Q;hFoDJtfXr)~)@H{&pSvxb}1%OP)>p`c|<`D_MvS!&T)_1OE5$nZf%P^D(K} zxAk@{4MAmCGR3M!jkZzeKg&#fTa*<%x=f#6fXrT~xJD zD%r*HsDLC#Ddb|aI_z-lLykob=3r77d@J@^@Ehdv^kz-XEN-nV9@=6&z3j8I3%f-K zMOuNlk_z&;GIP?pfxKh5U>?JWHR2wO5%i%VnT4~)VPv=g6nShJQw0UBxPoQoa1xt_ zmI{^h5&b4ImUziIshB7W7;^cHypi+j<%-w443+Q!BL$QqP8lvP=szt{M=G;c#zSBb zmO<&vpK?tOvU~>jMF_ST_ z4Hr74187~=fm;EfPQLS(H%~}c-4w*{&1XTA*DRNfe`5p1>ppu}d^20aiJk2s(ft;M~IeRE88OsDAjq*+=NauO?YQC*ji(EG( z3GXV&WIf7Td)kirqW(4*L#~PXp6K8h5_EMv_-v4!ZwUPBwlwgnz|mIY`ktTPaBHRN zD!4&4(d8u?iR+a&+roDN1`)YW@En|v3b9>PhFfMzEL2y&E4nI&L>`A+ODt@rjcZHCkISeHv(%`BgDMekH-fpfRNUHeh#i+2naF)ga3s@-l``efWe=g z*p7ypsD_#d=~L1`4B^{LrPNkiC>JJvw;xktsLfb<%DEQoB(>42nbJ#oHbt}yQ3-*; zXnc`WX)k|HDXI&ij@p%4?plq)XDscsl9P@ejrGl@i^VSWwJH`HdF`pp-eOUB0ZZL# z^57>GA>eots%w^o67ltIP^a5kJKc=>oYm+mg4@bb3&w5cCsXAk8pg zso}wqO{%oBA#MQsJ3-(pszC`7a+K4M%zXTu@c0A9@h{B_{>*8Oz9cf8zd~u4gu1o+ zZOLi*$2*hPnZms5*w~_XQFi7#J$<*tEZ(>7rF^MhzPv(qnn(NocZdoDJJY|oCI7;x z{2xLZV*dw}bSw z46JM%{}34d%g6aYCHu@slkLAOp#LWD{P*Pl%JyH`{4?|ah1Qet-#n%NhD7?OyYydJ zBz(sIDx)_3C-F-2pS$?%OiZ-&^la=5+W4QOozHLMU#Zzy@HLtK?KInGx_{Q-pKsH~ z=lDm}{+a*(O<-c7{|^Gwzlm}G-v~@h4F5ss(T zIf|CB|6%|?ufUK5L|gCdjaMjzt?ty{Y%gZ0sF-SC`CSXoSN84e--rd=qN{V%X{_79 zxQ?9FlFOV&6~WW*RHqJ1vS2~0&O{>)5-Vi4CNSPb>G8O>)g)&dmY0L~jt(^GH2M=8 zEwqKduLPQ9$A_VJaiRk(qhuaF{Z>A$x<|4YUh44tBrfuoz6gBP@jpml|J_b3Z1XAUG`BIurxQ0awsACfbfXdbByAZx7#iCc>DxH|Bb5WbCIkEb zkOcpy*z@x;`k$JHe-j7)7r=>$k%9UD1K`9+&%yQ|me;d(4^I@~d$!jb zr~r<`#!QzPR{fni-(wWtuI+X=$<=K?2!wK-F*ksY^Z9k=)CAN?CFEcl+GLm66BC~g zBaGP9m$+uTp7y7gbv_wLF*4uLKv=-ILsi1{7kg6Qvp|3o^~XWgdFB@`Wc)EYEzimJ z!=-^O@S~0|@2)fL`__b0+AuMWUq%ORXf^A{+1{Lt+W|+A zznRB>*RUPSTp~PqJlgvfkPvv_94a&oD~5N=^Vo@0MZwk;MX2WJMqha#F^RR%Cpnh8 z2Y)_7*>5_Hn`r=Z44GvjhK6Ua2NMgNi;4FmOu!G5Pl-@x$Dx`I9CD-`+MfrZj1RUO zMLBP8RXWr=yi1b~1&@BDmqXGt?;HuY4{3vBnweMois}wqtj>`($EtR-nJRr?%njsT zGmYZzQ>yB?%>z*vU#xsyAI9F>4ckHBrgfH;mR&Ck2^17vHz_>YSsj}xbVDxLd=oyl zWjxg+YIvTE);7=97^)_Vqd(|zmRK}y_-?QHAX*V6IEbJP+vlq9E^xvWEvdxKX_I3NUi!hl_jenNRO%0B$gP~w@ zn_8yXF$H`izS~LCr*io&tRrO%;&fBnK%X3o6kr~MH%BgRFV%~9_-gunB5H@bCC zn9Cd(0u?m-Lz>-|? zfob6|hDNU(J9UQNqr*7}MGzy{%0g2IhamDXjblHJpCwilXWAZ$>!Ed;M2k;5PdAfR zVKr_O?l_fV<9Ie9Ppa5bJV9uvgX^Gl6};^9!9^J{?SiAD)rRs!wTp-%kb|K6`g(?j zlA02FJ_oYql1xPDjZK=8(lWauM;(Pom8DHs?CEDAP&>%ntK!}?5wdc&%z1P}#dm-^ zftFLYnZ^BnmWJ$iwQ?@>B{p-<2pKsQnF}az11Gb+6E~Q%O|I4V^JDH`%aGU^ic9Rm z=MquQ(Ao^i^&4=q)#x)!3nF&i%dY12N02&%cSaZ*Sc)?8`|T_g*+m@6?#u*O7PAyH z(PjmiC@8HWCbDOk_2s27w^|oDB)Y2Rh90p^)zn{T3<_A*KL$cw4t{Ph?6Y?TX3gIj zsVx{7ZO%ASBZZ=(98nTRM5o^3MzCCl<@HK}>KWG$ly>Xw{gC=@i_lY-xXXweO6XB$ zp&kdD!|K9e1ZyTSq{X#*R?Ii#Bnc-NR?7}=aVM^_iVhudCoo8De+GxaWYaHF+DeV% zygRUaQ6Qs5g&}Tz#B|`NZm~11vm469GwNHP##mvQX8Mxcln37gDbyrfNmEC{6`El( z*&Ci;nZf}UV@WL|#zKJ{q=Kb~L(36Gdq4A}A~-b3NI)hI*O4iWuAI zD{@qZ`GjP<`Lf-zW|>YjmKmrZdvj0)hvib5>~K1I)^e-!-~MVwp!Mmh8}QG~S@rIZ zstpmmBKRun^l5iTe$eVY)|>&dtwj`vCLm5;I8c*(&>A`(%fw24QR__-apnS3lw3oUCHOXAFMExUSskNYN{_5i%I}VcAO% z6cRoW0|s^{RG-O@ZMI82v~zqLqrTud`c%8mY5C2euPSXyFDQm~Sh&+!gsPTUJAE{+ zV0`#EK8N4S=uwMzn5nyq&jgt*ANcz%)aWsbk?;=m>F#$mzjO`$eI#o6_0pqeTQz81 zBFuBrU|LT^-Yvb(>79K`Y%>67FgrPeMu4oYCP}oaW6ftj69IKaz9SZJYafr$3)u|k z68psi46x1i$b-}`p}Fk(ZvG{n0SjP=v1mY~Lu$jAxiy40OS{Ay1WhqK#7*5>T;L~_ zi^X2fs^S4<`iTRU`Z~BUmf6EIo*i2(yxw=k*lhCXURInj~$Ct13;LEUv2AswG=a$KHAWg4a7N0LEDjrg;Tu4_o>!i=yy} zSGpN7uqSJYzMVmT^YfkxU1wRJTK|%rekA!?A-&KkOzFoCNmUKgv@3AC4gHGh)3@~a zZ3~gCloWR4jacM)7@(A=?ucof?=t=KmVq^KV>D}rvKhDzxn91`^?LUj*~?7;+{^8+ zLXIZUS<0H#f%3;G9Uc&(?p1Dv#JXg@-?nwdx&Yy|zQ9MWGHr6IW|od@K5-D)-ZEXr++zlb6`31T2GoJaT)(7WK{#(4ze4&9tR3~~?-B?g5xNoovKSVc6)TFF8%Z?+Ye}mh zZHjFhwjBZA175dpLQzgrW9HsDl4gnmrY(;x+?l-mcmmEj5ib~C+Fc+pvNFAo*GQ0`WLnrn+>PKD{T}Cd8%!-3SBkc!h3w%K{nvIYe({LPcht{;N~x5K&}>F z>K@WrS&>*Oaa8p{w$kVc;-x$l4_|vB!uSyat?~Beu=MD<_d^`W(jJdT<}0qrL2UuT z5D*+QNdAn>r&~5)snZwlN3lLG`+5Kr5XZ56$*)6A*k0V%ZtvHerK?}cm)ue2B+cJ~ zkBHgVYb{zf*g0MqYW;6fTsg|-!a_5q7`OsZXuHIok?>cn&O3z;d*?^M%S8+Bq~3YTh=Pf|xg<_9NCVJ95J#(|d&GC2I>J5Bsr?@yG220Rvvg zV?;q5w!)x6MRr$$?vU+X_V&kcmj!0%eluFvfbJzcHmONojKd`-Z{LFuF$jU5Ag@G} zg)|o$Fl*8X3lc}LUiSA?(qEU8P15729F%SbU{%BV3=r%Ro9;$0i;`c(|FVbUB_ceT z37Mk@NM0hu4zm+63Y`_CIp-iyRu1AUhv~dRUhEKI`}CslYbGZ-(FM5CRCUzmcU( zKFzlc5?$lE?7zFn!~Dcie!k}sOXQLB*Tc;nQTzPv(qmk)G688_xW2D5ybE%~5sT-U zC9(6@iO8Ej931^Zj;NA>as|FbzD%@rzh6Y)Y+E&u+P5tXQzbWT2`TFsMuI z(mS-L4|OI5YR4R2+H(=OX3R}OaHOnTEIqE(dW2e3a#T#vEnD;1?W=rsL2jNobiq*S zzQbW>Bsx{pX6V+fO_#BRe1P&BQq9=;yxYC~OQ=O8BM>Q+WErw%180Pa$C{QSgPq}s zyPRIaBuz9SkdrM~nU5%Db^ku>&)Dg8dlyj){>9&)QGH**=M*V27=(t3c98?5Z3KFu zec5pbuh<_46eoOfJxduo4_;z_39nw1y*Ds8m1jdNGHpv%EnGXqW@w?;ZCk#4mpTBx zC3AVhWfCs?N1BvMkJoSS0zI3ja8IIt6AonV3tu{k-1iOe+`@SWY^0=^Gu9985)%_K zGFIbv;9CKcu>?;!PdXt_uPW~X3e!wr*$94r@g?s)wt1s_hRz*y_=uz&WpIgNhK!ta z_-Mi0!s)3q1=dDM0h0Mr`#9Y4@o8zJX9P1c)smSQyCrt&smg+7FAHmX>z>Pq7#iHiT8=IB)!pt?&?W?kVsi zcasP~yUN!}{wEFs&-+8J;NGKG1o`&1I?}N)8sg3}jR;b(u%lqBS=!h1suY zggMB$z+)i^&-MkZ#)Fct(g6{D_lpbXDkW(Tsf7hsSBlLCmRXpKmzS5~&}8+Shp4L_ z4HIu6i7Jb10%OV8F(db!twIa7>1cgs{Kcs3n2f>~R8$OC`KiPZ9nh3$N|2g~iHTP= z_VAmqmfO3$haiFni|)SU}H(Ce5uXp zgig-<+*}eSUDYkfUh?nZH{tL%UrCqoij{h$HKpJ}v*ZVG5kvb7dg9TNBNE3WukTI% z`@S;)54M(R3Q8Lr8_h)<*`RQgRPY$Wld<*-N_|tQ%tR-{2sXn|X)iJpL8#>7k+26( z;(Mxl#wP69sy?dNp~56UEF4M88$B@-6BDiLQfVedT@CJXYgH31=FwcBo*pBuJNW^u3OV*)pC6DZIu?pTJ|Bh8X)AkQ=pdBq zIoc{^L=}av63kqJJeR1EqLDJTu<-Af$JPAFS2=TRYd_n&i5s{*MN2mYH#E@E!b zBaXlBxfceB!YdN$p4DdlbXbI9u1|!aXrrA{fbh9aV!q@n7I{=F0wu^Gu|SnKl1AJz zRLMUM#91nu_JCNfSnU&NDcWSG7zlrkA1NICl~bfZdM<}j-AdmG!LqT28H*hxs1&LM z63ok2f2BTQ7UvCez^NeYbtkv|mE{VHo@*KU6ZIZMnrYmh@Kf&wsprB1O`0BJ5j1Y)Gz4p=jfR+PK^roUR&Pp zcKx=r?RZYyN~B@=`PWjn%;yh&t@7(Pt6J$VGV@>6A?X3kmSrcyA?g9lH`uC4U@hRZ zQJ}K#UYppKeP^{+do@OX7urV9c1YVs&^NFNwCMn2JO2^Q>yXe)?6z%cBX}`b)A-&x z6y_J<0`gsp&}n*aMQ*XU+;tQ0BUe^$@M@PD!1Z*Y~cY#f@IpqnVA~26thv?^D}wHcTHuRUkdSn3BdWcQ6MV zCOx(tL8FWZ&d#87(B>73tGQnv{c=$kum|V5;;G<)>La|QiSruIvx&0~f6Cl$$Az!r z{2#u%{AwWoQ^EuEM*l4c|0x6Ya^O1%-~Bt2rQL60z1fYwtL|D}5SLpf=PsQQ8jVZW zL?8KG(T~^V&G>$tJMZptt5E`Hi>|v6oz>@qf>$9Act|+cLT592eWC6uUWmj7H4k_K z96JhE$qyRd;XWY!Yut@Ry@5k_2`^0jEx@_j-7f#Rnm6#VN#h#xqq-|xWVxm*+|RJ* z0s9Mh=bY&Yn%KN%>nG9|(INjpf@#vY;uo0L`-l7_=>;YD6)I-(7NpRaa?L8Rpf`x> zUECE3=3U(t2`R9o7ZAeKnDSvY=QmSK%whdv&{s_S!I|+9WiZ$C{KcET_?LPqMDDZ1 zVD8i63-|+%<2~oAdf2maC-TKdYmfDDIo|2}iv3KM?`jY-K9auP!(#oS5h8c_A83bQ z{V~i3@#-D&SChZN+$%!HhS~C+Kwt4Cr}fLn=NGsKL`L`RXCKG=!haPFn-{k)vy-*Q zn_p&mzs!EU`tqxXpMGX@$Zt!{u9gOfpaMsU&QYyR zEHn8*yAL?EtJt)w#rO3R9TG|Sj}f*^r)wh|28^Rkdd+38Z0`@nL``|)fA$L!YK;rQ zItGlJw`dbi1Fg}em#GxFLX_v0sn&Wq4ER@rN>->+w+M{8a%=(yIsEG+mLb;BP1q+n zoFn$5J&{+xfhXDgwX%j_YX(DrU;Q&-4bhF)-e=Ku_K#?!T;nrWC~1%g(m#+Nmf8y? z>rBYn6nTgJfyDiXDY7BI7Yd#i3c~3M#PT@NHxuOA*N&|EhK+IGP_;9++%qCBSpUlV z`VP;`5bKKzhr-0Nd-(@^S+gE6u}C=~rVQ}#fiv|=!Z zPGJMi{DgI`t?8v?GV&WVxEh+I^^=~|6%Yn4;}NK_TKu`2e)ogUmsW&a%FcE_rvqm_Q=(9%(d<`^&7JB;z*Ef z&)M?8IE{g60d<2Xh0aR5Cw)dRBgc0PmJS@q(F;HK!w0 zj3PdaV-mDuFu}d*d5KjliM|ZdE84PVR&}XW19Z(;rz_g;GuS$T%FWOil-5w7WtK{# zvD)mapYx-u=k|E}iW%d&-cfF>Da)ReMtZYc9J ziUBNml*jX}%p}6C7QBEyn7_<|M@Xl|m|=C`Z6t5TGfjaw9`GZ}1TSFZciOrhw>ndU ztVo;*$_vYS)py`Up5I)kj$hxvpBjXJ8lhYI35ush9SI2m-Fbc8FU~Kdum`h`b=khK z(r(j-ituUOBD-f5FUZ3`GsB!)RmW?x%qq$*+8*FB<3py!wEex7#tQ*-LYnTo##gaCh+JIBfb zjo*Y_v#oRfF3z-zGbX>y3+QLWHS(fd^Cxn@2qI zj)}AMik6Crvq*`vMKtU*80~2A0H|PBVdgIp9KMSHz6(5DC=Vg}k8sMDE;De}1xb2| zn+8xKv`vs$?WEW~DRj((2w%c1AhXRz^8#(Mz)4flEu?jii{TSke}bQ=wwYV`f)M_n z3URbNhH-Ag%el*j z&|=n#*8jC3gjWmIxgdsDSt(irpv9JQm)oHS7TIZ<83Xgj6xWK5SZF>TlWzRH%#YLx zr6^)8sBsPcsy+4op|6|zqhS~UR`XW`x|2Wy-yW(Qp%tMGS{Huc4`Hm>EQ1F3iBBW= zoH^9NEc}mROicy)+BEeo3vIA}l3g6B9Xaa13NS6P4pEBXPJ<_U=fHckj?hc{*d`h` z8dvTbft%JRtV%@!Q6L0fZD#XyJLVm=z|Nk0%oj42;kHT1g&CUS85)|ZTue6Ug7OOe z=khc6rXNix0_!sFm?eO1o5YykM$v@Y3f^t3V4rK` zB-!e2mh9%vpPC8-cVd?mKlXl@cdw>7jw-qot4;r-=`Gk>@k2LSWtO3*s-OFdCZkg~ zs5Nvp9J$>fwdq|{bDr*#8jYbu9$!g4=Vh|r*tNt_#W$#R>o6w!sbOG`B-~8gz+NjmqpL?0ejlIm*aq+MXm&CAytVh_YJbXEcw_IV}z+e0A

>cWU6rqeA(k)(pLL{db1_e)qVM+YN{+9G4QlNgF2oJC=4RnlgtH9> z9hR(G_u;g)sFoGPEL83EYQ z@qI}x3B$>Ugio$VB9{rHSThXqS<{V7JcY;1Z6g6iet`NYo>Cj(J`T$zA*VTx>Mt+# z%<|1c5MFu)z7b56p<=1eSL5DsZkt607gD$$LO7Q^6Baf1h-2G)Uds3X>sLZ_3v{bj zOcQs*^lZljOoaQe#F$6-zP(1WygJ(Jrr8w2wV~rR?;YS3^}<`s%ET4d8nRgj{gX_l zX0xV^k0R@bUinRdUQn+&Qb)!uB1RVyp^D?e>{uC@`D1rPP-TX>7gIS; zfXjVPETG10>DXoA^#6OAi#Pxs>)2DU%OWDoVPbbmwwK6~xnqd4sW>=&=sDBI$R&7# zgD0__#fBH=2KGnXK`J{Rqv`h;*81?1h?DytNaD$WPdY0a`mcp8MUd;wuwpVRAL9Xh zOrO$>Fw;CvMd}RB_leB8!U}2Gtj95I8uS30U6mZ`O+1|#v5go8CkQbX62b$i$% zLrlR%GAWER1x0a`zln;KO*4rUfJ1pFi|ZsuSsU{?3OBQhH7Vu)uWt-k-#NPO8L zA@p?dq!T9Fow8P*_$ibNC}#9O(Fu;u{w=<;18~MwpD}q6h-N%xWNw~v)>2T9?)Ll2 z9#baS`vwl-3L|3TP}NdGmum1glR_0B_Aj#Dh5IyoQO#xF8Pi2AZAbfZF*E?zx%{}eLnzo`mc$p4NDk2@ z)sP>?B-^qVHRzI1B@z_b_Pj63&8{qtFvrFjomZq)f}>RX=EM@5#1hSZB~L>GCGuz0 z-oVnh{Py=4#-RiQ&9NP>R{9Qn+lhsMmK-=R1}q=ZoOo{Ljp(Op1uls(iwTkRy&X61 z_?{Eq-pV1YeGdm0VfL)x!t;8f@BG5zLiIrexdzWCTfHjDeo)-^2MSxnEB&{v3^zR>*}#t5qALW{((Dby$e7@f0Fs2yHuRH;%~qrKU3V{SpDC9SPJjRw~yj9Iv*c7fOt7BQU! z5i?ESz1+_3KvS2t=QBja=eYO?Y_Xtv<}d(T=((W!+;T*eqg9{NWM@t*=Wb|BQ?eYT zgx4Qc@ojiIp#t#UEpl7+hyeTmevW5h^n0FC#Jp&~IS7fKskr0YGroOT`0_%gO1*Qy zf&|pc%Yo@P6_)t{0^~(+;iXa&HPdxICwGc^^NGZx5z)WEH2xlD$W$(r?wnR0?s~WX z$r@wAm}2$oC7{lL#iZ;VkMD;=BZY@VCP}4;R&h@VJ(SDWLNtwJKULEVz*TZWG8ykb z?yj)pgiAc+0-rf~gh4I2RgI91oXX;XBX>xzlCBq(E|LdIuUc?$@hBu=WM6@eX&vIw zEwPx8TmfWWx04^{{mam?*t~<u;gff{GRL-O7@Qm|%N zup~_|^T%;NF)vKBUb4G?G!;7(Q_rtr3eTr=iA80TT!oxlw{LGNZ?1*Egh(ICT*lys zgrPBn>qV;^JQMKf7}O(5uv@TNFx{|f=r8E7l6Gbdwa-SBa|;uTrxUrl>PpP_#tUnm zWmpDQW?Jo(!I_v4#PPFh*NJCAWHyrv39YzC4%l&jRFEV?f~E$%YT zMa*WL$&Izhj>g?oJvXCfqjnd)DIa_4VJJiP2o78l3w_r_V%ocPyLFRhsyk%xCQK8j z;a-574He0q7Q2v+!ke~^Ad^2R{g@|{Z>(^2o8RDC5-R2n6S*%ICv=FfF>Q+&AHPoW z;ph(dN2i%CKilO20C#|`SETz%DsOiprNhm}c;3Em{akJGbw+*X5ecFj8;K*26crjH ze~5kmdW1pR3H(lP&yA}5CLoxTfj`O8mf3w%FI^oyyo*-j8|TjC0HGz6-~TZDR^Q+8 z4>3jHX*8#Uab0q5lIxDPEqI(1J7Kd@ke=f@-bzsBE%E6rg4cP~p7-z6Zc85=ZpHkK zx4@=%ydPN0-%;!*tG5L2iSA&5?m_*uW}b7~52Wu*9nMX%4u@Qsh9q_kzk*1!=DmuF zokPOV=n!XO$EtogB=eN1ED7&pH`!}K-Rm`@1ESspa#l}K?-ZwaO#Mn%fA z^a=kE8c?@Xu^Atff}crIfbWu6-1Ra>_9R;nq@Fz;yiI?*%#k*sa>PE_i08ueN9us-qv zBR=;G@pxjhde!&0s@-^MQQ*Ms+AH^W4o@9V1G7`JeVKdNJ!lma)k$i`WC=`H zbS+IyeHMe&s|5`fkF(r}F6=lLBlgaCamr5Jjw>X*3KxI64?u!e}b+Zd3E>xJH&(Y$Ep` zR(gbFwj7GE_+9KF>sPm5jb3)kzhypoI6Cu&)v06PygcWolRI>#DUE#H*>ke?;>hwT zz+sBcfX88D&RM;T7jTwqmD{veEewLJvpC8tEK{nM23JZcxtF^FFLaavDcM|LOkY2z z;TE>!aqSZ3gOF|(5q&L3-06QkN2f|jINcW{&yD_j)DMVfdo9R(a;JXjk~MgmQ2C!r zxHphJga{E)9@8pVQ8(@XU=MK=t8SkPw$yxiHb)+>JI7mYY~Dz-Pxs&`6NL)TY{2`c zVHPV^jk;7`8uXB`oycR54k$$cWfcp6ngoQLa}Prhd_z^fgUESN8EC7W84 zre<}jl>q_yk7}24<(JY@EnIdUx`C$dY|_#Xfi5mf_1TC5Dk(PN*zW0`pR5@w<~)aq z#!jhNj^V0?0x^txSdxbsDKqdYpv3L_D5hXHmrlbqH zhB32Bx~h0K)eYa<@onNM8d9LSdngdvnpyT!wRWlk6iw@O#v;!lF-szvOT}U$^*{{G zrKOm2b)Ii{_*%; zV7zLw^GVr&HKWmdA5K$Pq!zbym1zS7T)s8+16SSs(WjOvZxzSD;b zT_qZ@)e4i`Iz_Bb(;`#7!WO*LtWh*?G80oQt+GRN%^Kcu_riW!N(pJsR-Hb+42ZC>npO@Q7}; zRb8e9sC4taPZF7IwpDvk9m&SVOe&1N6QDfSHfr5!cfr--*`QfyTTmu-)uxM#j)KFI z7)blKLo?-F8Ce#YFsGlDdZR`1YX>aNI}_GY}djSbrD1FvY-v>BjPUWqtI73)(OVeKh*~mz!n2?z6hv#k*K&M}VP; zp@yN3AtmnfOfmz^hTlnDc7z-B#82^fL?NO2+agQ_JqSdi)qjN_(ns-3_&<{ZYi zgEZ8{G8(vfu#!9~zcb?TrkC9g;O6Kcw2)svboh1mp22yNz$zX3GGxX@IHdD@hfX+a z;O9L2%zcoM+~FMRWv+vc1Y_>8G6R^f8}8`$JsFKM+vL7~OUd^5eOt6Um99E7VD}ij zvDwMfJ-koo9^u6?qwVebeizKqz+8=;#`4U6MV7-gPhT^oN!Ska=zej(e#*(Hb<1nRTXaD*DA>&R|Y|^y7%`CoNPcyt#ko zk_jbJg*8JHi;oJ3bw|I6a#mn}>rX{7q)X^4`J}(7A3$&>s=GUFKC9v(8EbZ9b~b+Z z_IsO0n@4d$2SF=e0Bwn*WK8FadI=q8&FD}}XX$PJb@_XlO9pxjbv0R*F-w}Hy80e< z^V0ks|MMOUF<<%OxJ8=B>OC zZ8Xw*p6n9a`Xgw>E)<*eEmse)n|j6t;M#QTb}6{4?V|5o=vH9K5KUNNdKpi806qYb zgq)=rW7c=CxaiN5q7w*Y&QrJ_QyIpJ_Wfm8ZDVa=b#n~jy@^InYNr~Rn)I!D)<1Hy zTIe|{hD;lHD)llpQxbOWV$~H=LOuBuh1>AJA6gsVKU~#ZS0EoUD6DT_2z8R z&9v9CsH9ujWcx@juV22F>@tmBtjA~b_`B<@37w7*Upw2mW(|90pQ(57Ky!UKfsPub zG?@`Y0o6t?MBRamA8&S9Qv!3I`_KHq&GRnfMXkfd?$?%Es}i|U-yI|0 z*T$5ZjVpD}`}+*EPZF1mbPr;v4oC z*pk@Qi^|)^{4lt$kZ-6(TNU}I&FMyM(~5Wcdt>FnmGEiX#jS9}%@n&zrP|atRXZBGHc(!buAiVm) z(5V&%SbbBSxTe8oj#JXxzGjJfWr_x4R+F?|FsHu6i@T09dLbv=c64NVN7nib>(W9-HTsmB=TTbkk zmNDF-R-U-;ymCrit)k@W7E)F2^`$4^4i6_p(C3j5a#&tG@WIMbMi5FDon-aiy2 zb@>WNA2HXU76C^#<&cOrYFBc5=eBp3*J5vsxioTq_`($(fgWM0H^8&vyEw$PzT!Cx zFfs_Tp~g~tuWU+0K|_h=wc=kxv*2EvMUy%weh7V4xC@DS_Uz)HEKGSUG>(`wgk%Vb zFiZ6mm4sv<&429=(uPJ#@T?EYln_Vs?z8)R=C&PIK)=7n__i(Xqc6s`KxlxPU`X3y z{}VL=j{uW>plLFDi^d4T5yKURuCVo?j_%lO!vDAUyeCFr^p|^}`Gbil_dp6NCdG(# zJ@j^xIEe(B0K1>{yWY#pTUU}_oZrY>{ykwQZI{i4)jI;Q^eokdkZ*!VpbN}W-{nt1 zi+5IPOeZaGpjO>S@+Z2VCYh+${qM5ni)+=Eb#ZRNZc-s$RpeS08h zd{{uWf3hIsJU-;2p|Z-cA6U~2QW6I(1Pd$59OPHf7Qke8uYTKk#gQkL(pW^4V z*SolHYk~45^rmTLI3L)`nX9Bqm^fvH^7bf3-8lHm;>qtbd{=l3m2iK2v?`zem7jE0 z&3sIqd|<|!onA1#3YsN9q9Mk3?hJ_glA8h|oMFa=#GQ=P9E`!$6&EL^4YhO=b=gec zX^c(3DF0q&G1(rQju#oS)3_@oUke%!Zoeq(I6+7~knNrS-S|_US9QT?gdmMRI`+n9 zqTZz|X;eL53#iugn!mW!NCRvR*wT2JXCOvRKc#+sH%|Af_N&WzhWL666O)}Hdn~xN zv6-LqM=X9>=>4rw5DoaXoQfz)HfU+|gb-J#?UrI3`*844fX=6L>O;ps&O`6z%V7g# zJ5>35KiUf80^hVm(!W!HV*_2maPj|eCx?b_%>AYE8UtS;Z zW17savzc{cc-9duM=KLN}W7Em& zHoXMxI-{DGvWt#HK6BZpFEayw&MEN@7hRls!#<_xU?DmikgSu`^$nwkV}fJqVM5+U{!{O#ntg#yfePI$m3>t6U?QAF%Xc>!(~2y` zfZPww3~as^%|gu|NU86n%*)AAELr3{24Pos;&az}Dxx@6S`>c$1nk+jD@dyW3H7&gZS8mkF(TUq)_qXnC!UapT z*7nyGQN!P>xH_tC&Nn6uOS)bg0jJOB5TUjT-kDF#4m8)3xD$`F0f=*;MLUq^r%yWr zzuaq3#qJ>4ALMylxoA_j2D?0?IIpxs=~aU z?c60KOF?s9SFjE5_U~fC@>LW6^mMG?lLt|y?r4<3mp%wd2!*0(uU*{$~U6EYqmzWV_35wbzuU?#+;y6ytW-FGr%q zN9cw|g;oy{&jxu0N6w7&iHVEC<~7PShIbMvo3yMnXN(AK36BE*1g*e(V>^*8Td5nI z6T_J%@g^O}4v|lZg%4C$9mW~L>8;=qXYQ9pY!jhLP|A0z55PE+d@1Z_V}3~=_~e83C6y}aVMOUJ#N0#^jD8n#=r*srie_XKIxcy3N7hl3Yc#yM0pwG47P zXqJ#lgT0_byZ4t4rfgOAO_h{#Q=SuLm+x8StCoGl)%ZUNY+Dvr6E4eGn}^b(DP*1S zYG2J~`a~j9g}zm_tO5!++gED>HDip4ta9)3c#P7l1WI+Lu?jppPKGNRPLn|QC+Fqs z`YC)AtVEXjU)LNojW&n*sASj~HQkZ1s%aO3AI7aav{F;63Vvi|NjbLi-oEQ(J1cVv zYsFwm0Dil*OulCChqR`qpiFJYsdt5q7Xef$ifco|r6f*yGVE$icHcL&b=yMlJ91xS z@30D!Bm&wkjFKJ810EHRI4_5a?kGlK$8nHV$G#)xEw>gCUeWFRpJ1bW-#sN^})LHLY+4yk;bH_IoP1T=QazNm+<}*Mwx&Yys9xQ>nlSt zGe?gvo`Fk|6Ug4eYpBnPR4E~+LL1q;IQ~f}{<}X(Q3gO4Z~pQ3RhQA3Z=TLPA99>VIai^$rhy?&sJwsomh>S@45m;9pddt|J6UIX&a`atLN?G zMugw(64Y%wAp%HCJ4jTu_BUwgR`6n+`q;kq;)yI&&wD zR0!<=N<5_w%6dA_p$DooS=b1d4@I4G)~&hs&uGs6p`E8JuKqZKA=yovg?a8ks>rn8 zRF%R%uYK^HOvsw;jBGpCzEA&IRKl4!bQx2qfh4xcC!2;efakbRym;D;B7bUM2R3KC>C7`$Ephpz5K=yiDA`1r1=U+7RGza|O3LnkM`_D>u% zTKp0jC=J~oJH8H*e5BbJo2V<6brNf2NZ}%6WA=Q8aOmP&F9ZaE;W#Kmj(l-H?I5mg znAHwrgA|FDk{mGJ_C11s1$FNXt`*uJpZePaJ7N1f-ahyYd;IXWXH_=P+(A7e=;zMZ z{q7kxb*5KL@YX$02nKN$rRn)V;x2MS#|pM-SD?X9>&m*nRBm&8I6s=iRDMbI8!kF{ zGf8iI=^cd~zGZUNZCQKg>2rO*aBt-D81tm4Y4JYlJ_cm8ZI5WMC;Vc}AyjC2rm#Ol*j?h}#d zQ!2zlocY=c_UOl!O9hR^5v&fg-$V%~@Z^k}QAY2INnuc^qv1vm|JW|&Q%Z)?Go+BB zB7YL#9N~a_wj_FDr%SdulK4gY6r}tljLS2!HiLDMQ;08`#tre>N|!vPJBZ zk{IuCjX7m(5&`2ozOG^X|FVrY;mmg#&PaGgr5x!L`Xdp|XYrH*-jdjp&ub`ayI5r2 zNQBqEr3JItuQMkyWZ6fwtN!MeXKqW~`5C>{p9PZlZm@UiY)~&VNUxU}$hP)-`2E1U zM*3l~PvfSFJDNS7JrbhWOxwZb_49T2Oh=3Hl!`t}*wvwV^D};5B}hSi#-8iPHLV~W zn%>;Kte8nrR@^rSgNf*)i_t|QLV=<{fq;%R`}*GMa%YWZ-*Plhx;#fnH^Q=(bA$fHY$nQUX3s}c z;m?e8xBe0BJ5@xGriZ{LuZ)iDm#5+qyz)*bwKU45s*XWk&Z3{YAue;BPW`@T9b?H% z`pqZ1SrF*!?h7r|$EgiYHK7hm==3G7Htz@h`+t0>*Nw5l^8#%%W3*?IdU^aKQS2cl zPBD1;{N^<$-Bx&rmAS=|!K84`aBct`0chZNExOGVtI}bUHRW`~?zT{arO3~*hYw~a zHJNU;KdBlX=Ry#lXPg4Zd|wwmE1FLd&(XJ}bq?e?CH6$V1!by21B zkpESG>xBMo%u*iF1p*C&H0?6KAs#D6^2FgXERoIqYC7iW_$Yt!IVDGj`9O$%1mzGt zG75mRdo9&$HkiG?baB0_Z4q7Tc^pn{C^RQ$KQFRQArQGA;PPx_ZBUO0uza^DMLTz^ zNyE)TA3zNqsdz3`nHd>ZI~3=o->5*Lb(-el{d;GsW-&36is&Q*tDZ)bzwDsUES@bxxA#Pgq{hwdm<(> zqf{Co4<0v>tNAaKoiQ5?O@&PBoAGJ8ekF>VRW4;k;GNxD`L+Jj@RgI#KHQOsS5ec9 zUIk}eb2z?NaH2bBsz6yX2BekMkzY}t) zU79=-clL*AM)`#(A1c&dY}ek>Q1be)vZU{3gq!OrPD^~wr9ugjyr#`2wg z$In5*o=1b;_{VxVVHg6=D~lJN*v1iy{T|Fo-86lf;Jlvl(44M1pt@S=arl)iban{i zBSgEUdaj$-C#8#_e!`vWT`_CfbaUKgMn2S!i=fG zD*cs&bN_VqVqSqhBWfxwXTsKU&DPdt&F;d2FJ3^o;-Sy>wBp*1!?(r3oX)Js(6)RL z*p{>)?}D%qE>tNd$xyush&f$%Pg2RrJQ=fdE~|B?V^at&F8k>sU9JUD1*Kd{kO9t6 zr3y>Ns^&}Km?3eLs6V;y=qp!$CgKyt5+zztDl63F_>G|dul$sxOHr~=iwpLh_AZHk zuoO$uAfl4mKg1C=NJ)*rPA<5SY8w4i8Z4@Cj8s|Qa39RXpI%vpW%H8L#XiDy(GODu z)z#l$fQ6fG^k`CtdYGn#9kUQ8oU=?NerX5F7GjhXz)^F=CdD<^<#hEwERBz^$DTun zuodx1NCAH+Dfp+6jsB8Mdr!tb3F1a^{{-J+`~|5V#~g5sVrZM+3vAM?X0Q6)md`fk zsIy8Cv6#uwB5hN76Y=Nv9TR?M#7jA5j%9UO z<91GmhOYZz6rB0!dV6PHec2$}-E)KO>jAmoT9eaDC4PlblgjvL)9r!a+mjy>>5IN! z=1@$XLO$dRGN(?UWv=>Y$g0S#@VbG3K|U8cYaAvJ@3&Yjn1lEpr5V3!8m~T; z$ZDF$fO!!%)&Sjnnk!PaUEz?`Rx)mYsthiVN)rml+#{cKa#`KDP3tET-W0xU%#0nM zWhUDo0v2w%k`Wtzza#}GvV5`1Z73*tlDK_xQ|EW0ydvJU<6kmM>^IOrX;06gaNT7k zGW%##1X*fR`}S0s7jD7$`-IV)ScV-r2fYaPzifBD&i#ThwhapVQ*H{;|X%mPm~%rTZ2rUK|ox*NU@sr4#_2s1t}FL_tPOrDqM;-s(7Sk7#@!{ zs;#aZPeQoTIyXo+2G0bhX>2uC)AWTx5%be+B!3^}7n!}JFjTqYcuE>CCmA_#IG)B3 zAv2PKS;1<@wzK|U+=8XPmb~hiw576;_TE^1Iv{PUQx@JB)nM3R?ahzYvIk#X8+HEA zcLa*W6qwyMNcL)7?|EP}o zI?!nvs|<{V@A!qCN&VSR?=u-jbH&@V|1!g29aw=;7?}E2(ys>Ks5oUG4=GO4#SH1JsHV1mc1{1QyB-pJcuZC(;EIOnU7&u?Mjm+**dv1$martr>-I*77pfNaSY|=QudN;Ugh9k_^>#K1 zrNDS~4DPnND9Yb>?%Dl(a6&n48ima<{(f@9&U6qWr2NC3OW#*@6Nwt zD#U?q?;@Sn_kinV>O?Ajtb9yKiAM1J-!RGC$mPWS4qvWNyA+TXb1jC z^c4=$DKsh6X^&X@A7gI;9LKLL{3bCoGc&`QnK7oAnVFdx*9pPi2|y;a*7D-gH5-zi%7 zAljdaA#;)v$&|$&)&*`gZjl`l2FXKFBMB)($kN+$hR@(y>zTV)TlzK#iETLlNOUDg zN_e#t-~GW;j=6K_9g|rkN zkQ?0NKO-BFDG+S2D`4i?>5JHI*c_6M_C~ZsJin}?irQ9tg>>;Sty5!L4LZLea{A|= zl%dDzZBR}T=O`@L{O~h6lrF&s?4hvIF3D#}*VQ;uOp7BtOko|WsvE`J-D2KeJInhg1391A#aAFwX^MuFoKo5R*V+hIZ-$P@>M(-QgU!SRd9Bk>CeI^FaP zrPPLoB9WXSk2y=EiswWqr%))%<3`Zy6$;{8QCxNqB=y^e7Hu^~t(0lB(F|2nPWSyD*1HugfEg{50zasZt zS>#_k$jl=sGiA|A{FLeFQDKjve)ix&XMyaly$vWD`oo3(4_>v*{$_p5JhL zN*k2JrgpH?_m>V?!XSH2AA8VpzP+`6QMjF5ce|T~1$2{hfsA^SMrq)1thvWCK{_fyKE)GD@+e0+> zE!-=)*kRzuXJnLv{|&VS@cad?{x8Jre+KGGi2mIeL|v?n?U=+I?aUO^;8~>Xj4fSB z0c`LrqJKe_Zto;hPG&Z4b`FmJW?Qsi=dcojK`Wq~$vrQ%ua!i&U41i;bI^myMT; zmz0T}n~Rx)i{qV_$;QgcN(x{Furjl8vhxDo*_nT9yi-!m*+>CAe^HtL1FOsPpZffN z>inzc?-l?0=6_&y|Dy-~A%Kd@O8jm1F9`JA9q*EwqqMAqg0a)Th@bzZR`qs$_kyg0 zg(Ine0E>#brM0V@i#I8)sF|aQIUPKUl8c$S%U@6^?SF$p-<7KFPEK~__J2M6mkP_G zNviu78T-H4x`21K?mxuY_YVAno7E>}WB)hU?YsC6vHho{KIuD@m!0?DK)f99_WvVI z_aA=kKfv05HS*rzzXN>#A>;m=-Ty@J{g>`vHvd!G@3y(Pn0a~G0KBBU9PG?I9Nb)7 z|3&rH{RgJ|Z~Wl@yY8R9|67fJL4*JC+rM@0U-tgBmxqV)bPJd|H~Ku(*2Xu|BqtT#S-#v4Y?Hn=IS_#uj}@_GY{44>zPg*S4QpmWc`!xpH99o0cWZCa_yaMpYX0` zih31TGJ4wVQfvAMjkk8;#ACK{+l$!~f2b1F)^c+5kaFr@QTT=F5>M|rz7j^y?(MBt zMrxK3vC^WEuUw8YauMP3y)P&Iti(W5cx+1HFZHG#N>X=!Je}dE7Amsut;F%wZ8Yst z>K<}Rv-Q;mZxJA_k{|y=#Qb}K|F3}gf8zlE$Dr~58wUJ0R;m1dV8DM*_rC|UcX;$a z$MoMYU^X5uHlFvGW^LzY?n3%EOuLy&n7`&>@{-#z9 z^7&|&>)yM4x!%kD_Az4$Vt3S%MZogam1aW&dL;b=DE;7l@-HllT2KaFs_Ue#$6X6f z7x%~c^bZgO`{TLYZvJx1cl{5wROoh9HQYwv?UT+i&aC9^&)(>tJq5|-5Ob^MVjcr?}jqcM}nq(Mu* zeVsw9?gy3r6&z+8ZCqc|aSu{0$c$Hbk)V&59;o`j4@23R5BQu9f|y^dX#3Sfawzu2 zK81e>I0`?_eA^-qVk`D#jIezO=)cFY?$~d!rLIXjyv2F3m-34EvA+=!6wJMLt!xaC z%R|ShehCm?1P!1meHW1}O2h*Y3NK4q$TL0PH-MGL95i%-!X%YF2dhY?XI zqF5K?YTT7bv3{X~lFT3$J_48pCwcmdKXUk%v5&#gNK{!~_pC~W&A^!BMkMh-l^F|A zn^Nzad}Qun(~I5Hn#zr2jh@Eo|1w-RWK3>hf;~A{XsQL4egjTbVLaT)rJo1~lx_wW zkbQyVtT$teUfnpHGmpi(v1tZdJVz2L{h*%2(#?_!dgSx z(kp&V8!G{oXARuEX}cUem5&E-_c}^l2YEuZ3EcyR+ks1OPWg~QA=a@wh44ni=cD^@ zu`Nv5Wwj;>Tr8XNDQ4FuEQE00wHDWGRUaZu(DqHJC;M^bhtwL4&{iH|za_9j=d*wd zgu#V`a)5|M<{lHqez8U)r<(Tuj7aR9P%54anlr7i-tGrRu6t8foQ7Ihgy{$<9)g&e z1Iv37->XpABEpwx6bQ5-vvE;`KAIb<*e$IfNv)ABdB#c5Sqy8$c849x!8YM|uSui% z)9TQZ*GC;z0{@S#=`u6NZ=GLefKG5vxnB(9?BB|K-x$(4I8CLCEuGUjuA#c6}o)>1n!9IWX}V@L`%0#looB2>NMV{ukl#q9d6bm9o>kopI> zs>r8I+?)J4y|L5BP>iuEaaO-9UL%50HKIkBenj{?Ih?q-yzXh24%gLb+`bWd>)P-0DP!j$cLxO%5su@0W+2=XUny>+6 z$9@-0qEgO>q`I9!o7ht8;H4TWDw0aAcX6}e!OB~%Eab(?#Z!#qA*R7{*tgo+0VK2c zS2P4hWR4qACzzl!>4j#2zB>7HhVS#BAf z5UQUyGetn4#EEUI)sCZuucOXvILj7XE_xPu0rpLNHv#z&Z5t9 zQcCbjjxsZ;aY%Ia^>vMu<5GQ6sd$ERjk)t2QwU{qhqZ?}oYz^F5vs48bn<%GN0(2@ zy02O{3|EPw|d)Ov~lV?6K=sKh4=K9 z4jH+9wv{K*7mD6rku`Ir7huTg8;G!q9)bo;v%%V0Ai+y4&C9$WPnm_1Re4^v3Xr>I z2D-t=Bk*&y^~_~fAcbUB(KkavLw0suis8np&( zSi{m`QquGiOJ@$nm~u*E{c$%E$=L~D(!J&6$kDiZHOrEDDjO-k+T=|q(gB?{@*zg+ zB}}8a8q$aanX2ikN;=E-4$mfLWUNOm97Of$#GeoI6kHGHrtose&)*bWy2$)?Tb?V0#FJY9Yu=e?aaO9P77+#K{Bx0_vS z+XdVNTLM9V++~U#8+%UQZiI}N7rZLIiWno+00LCh3};+QuPcBI zNSt^dXL7L}F*4zy5zTa1Ohj6F4P@o=qd$>!-b)ONK>JAuGWl@JwZ ziyWnm`@CjO)}vC<#so!Xw_$Oz^**4+h#&Z<27;{xq3C=a-dYrgIq09ns12d#wC~d8pc$N zBg0=}hd=4bDbA)F@!dtG7r~cp`7u(S`Gf|13n&U8c@6r}=jwwae`$(sVO;iFa+CH- z{24&Rz2k98!TmjfENXTp{zuCm0!%w4(sdBPM_jPXfZ=<+4+y|_~<2gSgcMoqwhI`3oG$w5%a*s&6@q7~vlorNx zKqtX8RJS0HWCxHeZX5fF6PlrBicFHaj!>Cl{e|{=d|lrqCHhP=>w2WwM_8c#5W^!+ zNUeyzIxtqkP*S-Ux{kE2_F7ed|??gN5_ECo`vd36Ig;#}u{QP`2q-ofRvPX{3I5P-G3O9;v zG3SNtM>se9y%f6$aK=GjC^+B|!ZeIiYc;eO1gQN;!GrpR%&BsFASMvs(Z?g>BiW-w zJB9s5R0kR(xP4?FAhr&>+A#ep>0WTNsHpdnaGUe?3joV z(oLeKM|wu(Mdy8CFfS4?>{3x2dsBm^7f<=~3$jGE)nK{s6u@DMklSba;Of}@ z^%O?~_O{QoC0-*^2+Zb>SCSFD+=r`!Fby+e)0Sgb3I$Smr1U|@ixD@;`7M!GaB_&| z^OZFsmO7a=;cm*OUGWdu2hMHPL(IHz-Ha0>lsr;$k8so*Z!>y*%~auC6Fh zWY~oLdsu=K?_`N%0S1lstcl?-#xFFX+X8J_rrndIeRTcHtr< z0h|8_@haepddgDVsI*0NDbUR5#^)IZ4MgJP?YKU}^`IU(SD|eTP|h7M9@g}Slke_$ z2kZZqO3s|V2a!Ye;C#Tzw^8u7g2akL*kg#=+RLq#(-prV-dkcuns z{+?hn)5bQ>6f1<*hL+GaiW-L?wnzrsTH)s7V>SVRpUOMj{BX=9(J&>07&9=TP_aal zGG;6|7^x{X7;g*7qG>>13cf>|rbQ&B21tpIg1-1zMaD+-SuZh`nsQJcrCZ?|vwf$Q z>i>}8ee__Aj|e?uWW>Q3`}9@Rj6$7MG{ge%hL2C3p&-RxRPf0HL%wv!s+_g_dpW)Y zE@X`83m#JYVBb>OH@-*Qk~bM~uq6KX@1MW_vM#45C6E|Wz~)LyD$))_LPB_7Zy^pY z6|VLV=uZ_#mVEsvtr!+(5nN&%`i@0JgxqY4fJLbyuhh}Q7<~48AwYsXzYgTgG0vJf zUO!6NOKU^To}Xcs9OW(({HbQP*PM#oJ;F34zMEr-Qy00&_@j%~sLwO&ghq_X&(Ex5 zij`2T8CaE3Gh97EL93(YRQ(#axFtI*FgeKWF=Q(r(uov-3+>C$l@p~)c5GGks}>My zmAw|m{h9^jiw8nd{Z`LZ_`FVgJOXw-_?yNhIXgh>S&q|anA^)O@eC?%&SXOev zOBd}e98=>dtN3oc%a$CWh{F$lRc?ex{2cA;R-UxeDM9_n865M*raSDtVKP1UwpJ}$ z?))#>_yHO&L`wbVwFE?+R!hD!k>MfoH*D$4ezB&*hC+~jxq4FlP`g(u7Zx-wdWuD3 zC8W}Dt$IPr#%{}a_Uz-d%&@NByXo^jv7kSisNSN1VPrl*uq?L@cRhQ5v;>GL^oBkq zz|`_hFgo|bGk}MR^oSn^DL>U}DHfxNQDQP0aXgEB{9C+#=U(?EfI?uXWdmhN0J|GF z)6^SrRmd|2kE9=92yxfC!^Q-< z*~DtBX+X3R&c=-?Gq4aPRch1iys>LeS_nX$A zDPHKbd!ljFnBd+jwUzc(+&|kUn$C4Z&c61}fX$fpXwz7(m^LMR-mo!Ki{qABF98}* zxtN0b;FpM{cZ|vB)Xwau!WKtE$BiyzN~a0b{^c^VZ5yZcQ7 zpT=})G*k*O0B?lJK!l@NEwT|EEn*&yVLl1K!V)R3=`KvE;|W8xP$Hh#OEOFv`Rg#G z;qon-1oOzypt>rKV$W;R6cqdvUCxm>m-}7O&>$Iar!Rr|!sL-g4Acmc+1tOT&uPMh zmRN2+Vu9T#UBq?6#mJg>iodWiNpSP(?KKsYh~Yw-6GnuyV#6BSq4q5?*SZ$ri4ntc zkfEf*d0XLJ)ryYvdyt{DhYK`a!g_abGVU4&Cj#BYi0>M($uwa-!o*jm#d?8bkR-Hr zAuxt;#D^g;pTt67%tK&yAWU1b7B?zlN0U3`Lvi zT)OE^Br9A`G8_zMW^Uh58?3qcm{Jq5lO->F`zlJ1BYI+(S#i$Kn2eofrXpR{@vTHk z?lHc=p*LM5O#*e+Ojm&*F4+#5Pcplb`R>D zKJ;a58YUZC1l@}q`Q8Xx-RPr&nf-CNz{s%vz^oL*ObKl+jA(QAToJAv zr}VO;N}`QhID4#Zu|(Oq9WkMZe6f*>$Xk>WC`ajuwJ%u#jdVG%KS)**&PAiojjILL zA>z(OGtPUx+F&N!P_RLQi8JyWJz`+!l_LTzxs4tlFto}I61BPTyp`~L*bxHkY&z;| zMG1*Nge(|(XqMY3zn#A?>Py!7aU==?lKX7>QNtyvgeU003ykg`QN{x5zP|AWd+w4+ z80Js8?S`|?N#uPzY?wY|pFV7$EeZrmyfszypn-rZM;@qQhaM?2XXPcUfOv;t#5SVE z*|WqWkE{&<|1PdgVZsg+1ZpACLu}do4l%^nYq8OXOVwY=#?afLO3X?TFnM}i%pJ^% z$$xYmSd=30A`LxFz1hY^o}+F5s}Rl)+P~U7Ptm_xzq^hrvy9+}M!daIR)|0E>uV=( zy(hCb)xtQK5#NWt$@Pib--z85;gHL+40!pFN%)XGZSp7Go_P`t4i<29Qe+;g654D? zt>lrOVaPrS7I%g>8h&2UOuWMf1yEZnCEk%*Pf?u7f?j#>ZjxDlChzX=M9<5zSO*3- z3V&W%mGRAK9G3C@XpNHm-7HIrPqAWCR#1rx$^5f4MYbZbiUWa75!xIGmbnNGc1e+9 z=~h+tpoB8c4*tM0(chbKVna=SugmC=7L3VUq_pJ&#=M&;BQ1;-3bz1bdc0?Q zr1HehlBK+qsGAM#x4Vv0tlaph)cm~dkM;G*itvQZ+U0y*t^szw1GHaCYv?nX2GNjte1 zN^1m#SS5rwcmu5O2)S6Fn@W((vH%R>Xmu zDc?CVlNpsAl<`xXe~Fan(J7OEmKjz56g|7iY6V@{YsdONURfr^FaHQ_sk4zMU)#){ z!xktjj*W-uZBT>=8b2XS!KGD{q?g83kXFK%k}C5U?>lVhtDs0Ov^L3MWulS)5f`Snn1P=nGc#`;GKyqf*zi5|qep2IR@joJ0fCYA z%r9F4f-QH$FDF0T5$iM)%AZj3c@Z#%nJ=6l*XEdtXgG_Bf7#2YHpJ$x^6=g2dK@;T z`Y9mKFWOVRnaP^=YZ${mwgr$^;zZ1Ga>XkqR}i8YUrmAAend7D*BMump%_O1Yspwb zJ*A;pq`EA;pct*~mcDtvdk%JWo7LELZ&OKHU9~H<^ZEGXQ&s z=iH;C$JxN?-5YbL@#u&Pi}vFPE|}ZWiA9i6c}4GwKB=ThwjR^|QqTD+62Aq>&Xe{c z`2KN^i;FV!{fQ_?IZ~R8Z>eAjlQuB}PTRNgcRfBv*!NOBvkdPiu;jE*V%wRpoXF}2 zWinL^S;^_!Xf!f+{3$+qEAZyC6{6E=Mw>mM;kL`kwW~Pcq4QSpceBvnDNWj8sEjXi zpI6pN-FfTpA8G)qv*}P&zKXkI*%FUhsRMM>V;4qtWfT$ghK9NAIE=J*E{`(ZFgWpu z`U$cil7@^O?6**vJ7^?3(xIE8NKtxHtmHF``c={nS%0hXHM-H-qW5N3ovQJz?snc3 z%NP-Oldcv^0!vP3jAa-NKuwUp!L9C@-A(V?pxg>Ji!tI3$ViPXz zH~L%-K6QR$oqj3F3MH!Sar*3aL!1B4ptgXTOX-Xb)IoM>bjdU z8`)B4T9IT!;;XkAUv@5B?;PQbex( z+>33hWxX_~b^&oK(Ld5kV&119}D1l4}PGD5ae}lzw zxgpt%P<;!wKfNW{43~Q&7V>)60F~Z|KR(=EpzX5ae0=fUB`XgEq5_R~k2lCd5?_g~ z&=$JIF^ykzF-Z#p$GGCb&5;y_Z_we9#~b;uP+;!E(3V%E)vKco(qOR{*w0^zNkr*@ z{>oJ(qIl?Fv>Wk?0LT~R?{5Tqhm~&xShTZmai4EyQA|GoA!ZDPW9iinfdJT4aQByq zEhEI~xA0`1s$P*7LmoVJa5pPt=uKb&_B?n|#-#R@Gh&m;l@sP_h}&y8yCM~4Vk9A zVo`5mzR1b%I-x7hcMq7wF7N}OOm7tB_b%OH=lN%XoWVF&170r(^8H?&7?wsMuTZ6? zUtgiJShe3iS-S8*sNMwTT8c{1Qz6CcpwY~CM6ezzDHUJdf2$^`q-v}*D+g|Y| zx15l(Zl+jqERSITC=*~yp7j1}R@FDeYv;58)C1G^1c65{av5A^B^mQdhrLDkqT1-( zg6n#tR14{P`xGcKTPa%&YfTxTQPBsf6<8Jr7V$*KobUc{^V*xr*NNieVl9_NI_2#I+{ zxMyCgIxy0REdu^qb7Pj;-m~w>GAKeW~=Km%&SHBUJMb&I@NpME7Bh3CipD?&!rj{Xi^7Bj79i z@7+r#fr{>s=07R#Lhme?!7IK0{(XfStkXgEcY$Q;xVEa60b+let^oqD z+ylJhG0PSz@NGc%UBGudVc9bDk`9Ce@;-C_o;4gmJDoQi;Px^MMBCW*e}VD?`hyW3 zh@Wn8E+K@b4SNy@J+>%byxn$!UIpCzs)XN!xnAC2vR|j(_PJh2x>rgA?-00N8Zhj@ zy@s_%dAUZj!jD*7FFnfHU57l`uQM!5Hwi5YZ-qxZ>FaNy}J zd2r`<^g8L&x=2AW((U2e+MVIzFcMU3&)Vs0s&x#jh8uj2oE#496<7|S$#f$}#Zs8N zhIp15<=HR3lT1_&GDg@win|TN9R(}tthRVJ8)-geT~*!LZW3#9XPcTTd@Xe{hI;aL z4zauS=c^2Br7A5AFBc9`^mU9}(hc;J^b5C_+IHs&ri8Z={y8F{_y9SOo^qaSt8ptX?g9(6i-+ctJ*Cjrs|M5n>~$$ zXb7KJDq`OK>hm)0sO>v*Zs%C}8A6HvNP}b0xE*C}>hb=Z^Jx@D$*$9UqER#O(C1+6 zyrvzA)Toev{TFkX5lBLuu4oQSr^x%FdX6f>*$Loed6;5vIjn~6W&iR3Q z+drB_oh%@UDJ@YZH5K1fp;>;V_l9m=uwv1s*S1E9)2805tCe#wsXk9AZQ$&jCj`5{ zuPi3+?d^fv;k-QV#Zq>w^c5@iu|Cw zqMyC&wqF*fpY2J`<+?A7WV^wm_?E(t%R6F={6}DSrXW{#lJ@==&`54f>45AkUJ?7p z(bBBythx@?(rYI!nbC|n_5QB-<9hrbm8EUt2KJt67{IcuIz)vic;Di+GY?+#a8ZW1 zuQJ~AJ;4z4JAbSOi0NwZ#n>Npt)7E%Rwsol_ioFY-_EkmH@+roBJ#Q4L~g9jzc6P8 zTKGLQ_9i=al|Ct3>+US1v0v2C`W3$9#7(?}M|s>Yn<{Eg9{_Koy{B6#sF_cu0&ab9 zNEP0F7@_Bv!-xPJaT1Rh_F$TV4y7U1kfj~f%6C~Pmm0#EAG76wz++bnq}6^? z25;Q4vR)h@j_+s31F8eNx5mCgga?@_OS`-b^jxaaRe%ry`4cd%C z1O94O>$^d5jmnZclifWlV-vq789euIw;l*%5Ezk|hbc;jz>vHLi?UkM)Fnr|ri zT&uUGdG{|LjV}^NX4MwG7A|@dJiZ}?Jc7$W8b_Q1GKwG)CuqIK*2Em^5i;b0{10eA z;83D8oM~XjZ7}L`vLzO|cl~FX4pt3R>@Zd&94^&hw$%wKv03nY$f$>k05w$HpPHFy#7>bd6}3j=NDZSUWu|wdP|Maa z$h>VRLp}v}LJY!wg=8P$l%A5zs49v=j9fMcWEqOUsPVzm|B`H$K9VbXWYb0YhFn+Z zXOybX6F1r2<$DiqZdCa}(ktXYU%~r8EHEUKUS&1lTTY~hJGz`v3aDf7<4pBCCScouW7k0;| zD!gY#LGQUkyY9JAnz8#7ZHz)TF2+0~W>0XNAg*(K^706Y=!~?uqRw4eK~oil!uE^q zSXgae*Nd$6>OFJ0q+bu1v#Zlg8-x9%E@*teAJ1<<@b2*biG^nVO3T{~fr9lt*mNB<@ zm79OOAUJZe8xzLx4rIXu#n88I_R;=QlN?is7iw=u!Igr|suSrnu<-)P$I(En!s6S| zwN7OpuX0u(@K#^;B+t=8PYnd#ny5N~p9RAb#BV!JQMESl>;#YVGF>Z!LmGVCx~%07 zma0lGKWU;jp*Iy)R8(+Eix=yeQD==gq((%$EHPLMWF=^uapFCYw()hta)w zWyl#$qvK+DK{o|P`JsS^vRw|?l_OQP?h4vdPEVF1_wX%#K3tJ}TI1R8ARy>I4e0Xa zY<-Ao&r&=Il)P65aa9(Xk3A2!x3>|ajc}$bbg!8kGrX+_-IO;X8SEyLB)`9l_n8nP zbXLrgU>_)WaYd z)6QnBG`{h5p>)lwbbV{8k^i|v&^x-{5U(K@Uw~6!ltYk5xJ5?aM&Cl$TF<_H{wklz zp5N+au2g$szjl4Uan;@sRvDf~+0mb@s&&y{mH>Z3$9eb!qnOR4^ zsW7SiD67n{?J#_C2vdPqLHKz$P`1{mMC?JZPXX#pLV-B44IYy{WrB|;0-=lS+m|LjaAML13Si~$|>jz5g~IMh#7o(VWW`%zAY$KWfugG>H9I_Y9_~(-j zDdrIL3Vo4#9k||lt73+(?ppqu@jz$Fqsc2hleu2cOt+ee&MHQqt_q-Uu5H?`p{woW zeJVA^)TFEDO<;c4zF}rfc@8`9V$*>V1>ygUT-Omu$dq53!i=DYl^>k3s*V z0<89WQm7bIWThWqw@k>rM_UEF<{&DCf%8kXbaxA(U^DBg9vgscl97W!PyR@uh&ejL zNVAT7eF_fkEluW<{sqmeBKPOkb4t7;k+s10H-tz) zz)YvgRK=tIHVfnX+dt{j+sNpiwS&o=ygp%Ty=KcpKmFKdp$y-uW@kC}Kdf$Aee;`| z<#->23}x8rD?~vc5?WBy`!2yg29(tW3UmAbxU7+1Jk zrDQ)yfr3)o!^B0?6N_@SH26(xzkPo$BD3e+i_FrDzXC|<-0A%Lfadf9A$-1?mGRXU_DXme|I*TZYLa`{|&D+%m5 zfl92eFe@_wWAv+b?-@>7FVIZ^)9>tWz4@Oab`Ru#uyCZoK&j?suE>w%Y}Cno#MrKa zdnDh%$Bwj9fzQZuWcxF2JQ*I+_)45D?EU#8joLK3E|j&86i6pSLN5lm^Ri8_t-`4b zm+3Gt3ntL@DiyAj)43{4efjRGHhVi?ywVTmN)epFxZY34vP<_I<)B>rrPg$1K0Lli z$YSU?Ud7JliE74R==(4!b}oFFp*g+c-NIhL`I9;$jR=X6(xwfaByb$_T%@q6;pD@r z)6HhH#rS7VZaVp+mZqOvROnW50Lg6|jX_}udW6hEx^QvYMgHcoJvZM%XHku+xjnZA z|Gu7&ViTu7uDJvN_4ac?t{c2SwYi!uJ8g$wzOUz%8p0d~s)CP7kb;(iokl*7&#kWK zQ3nP><^%luKCBOhJ?<>;!X4-PBI68uPzoC|7 z7RX+&m;7lus6?X4+ep#WChm05LjmCpDgf7JHPb3J z9u$vrZ)(%1TnBo~jn|h?qeUX zS(S8546Ll1*Bk@n*G>G!?L4w;I07Z0Y+n&qKdqW`^-8^;=GoS*eY32d(1o+I*>1OT3_Nc)`R#62axm2{ z!we7-JB&v1gqak)s95~%b;UgnA2*Ex|HM`&$VTOzmlU0rQ36u2OoHZtfmA9>j>Gtt z9C9$dtP;aFwoJH&wnEXF+pu`=JUKjBBk*?VpVKZ}3|uSt(r36+{U_m$1@Q+GoxgQ( zNsTWnkrAH42@^$58Ke@o;?Eq@N3GYn7eQXT`AE6iEDnNCqRA$}87xfs-|!(B>)5l6 z>mG&6$#)jM?fQsRnet{KS{^X$upSNz8Tc#a)S@25ll5h{HObUN&h4qrYm;1pu}2p}Uu%C%>c&kT08%SY3Hahp0I6W0VT+t8T$1gO-AD!|w zL2~_Eu==K>Iq{LplJj(|DAcY`#uh_|0wSYn2*!+N+`yQ|uPMVbjRhf8C%5bLmg@RW z@3)`aa%uG?g&gxkKg9cd>Zf1r)sI`h-6gcxjcI=d2#4?)_-r{&bzFmH?Ixv8Ufxk9j@yBbZJ$oHtJ%ry%xAMngd1+K| zzH%=Y7&TeTp}6(B5YS~CmYD4tQaGC2SbTf`aAiGeCt{xVn4=UOzEv4Mm`aCG_aM$_ zg&Lz-&%v95w~Y$d%Fy_UO8bl6GP~-Q0Xx<%d#Z9RX&wc49*d!Yx%x%s=h!1YRt;MP z%6O-|a7T4*r_B$V)$jkK7x1yCwmuROkC=0LC?`alb5$!+ZChMRk~=$CgtIrN`nBFR zoYzENcP>VyK6_0s)wwKi>R(L5?Tf0`wC#$r&AVP$pp$5j0JZaU1gb zO}>zxT1GVL`ydgU$nNv1n_Q14>0f8af{na!4NvV}tQ{g%=q0dX7xk2>Qj4hp+MqezGyCiowag zJd$huqn6R3U#lFi-8~?7#~p%}=qK6p>?}^`R>@y7S?2D2{FM^zBR63Iec3XEvNtNB z5`|LydPVbYHs8J}jK5SEJ10!q_)=@_&z;tPAA!#Nm30i;!@T;5QWSlVK_gMZ76V&- zsR)7|T1^9RFjM4Ix&Pfs@{H(YVef&Zd$aK)F9c2I6ynmjw_SWGKy|rU_$L8WnRzFA&TytF-jvFnoo%{&Ph=nU*1)I zgW&C~{w^*J6FCZ*PT+@={U{jS+{nx*Z{;gmDOwU(D48PpX?9ym= z>`*h@BSF`r@d}RHWOonCPF#Iw;q^c52vnzHVxK^&YAMFlMH*TTCP`1j^_B3j5u# zBxN#!f@RlyR)5xT#04;`{2A8($5jpB63*7u74pqu8p$==X_^?a&z?x9)h0CFX96^( zd-JbVyo~p`6Y;2ou1rG62O`%tQWIQS-_`~Rcmm+}tb`_(c&CEk`S0&{cspa)mkH$e z`f*qc&whSIP`M!HdrP&=YdL&P^IUwpybw-Flf99hJFjvdOWpOuc(xr_`M3- zy5Dq1a^T-?d(ZSw(qm@Xbk5m zs4m>Ex@?f56m@K-T38P?G;mnIgJmF8AD&kk>&~u!qlR21--^Fi zhNVmaRiY6oRz>~FYE9K+WcNHD8TI^#xp15IHfG(QhV$yCGE}6|GEnN+%v6a~+8n<= z%ZIcm>amm#5N!u2|0W|wryHnk(OqMSCg<-p_rplIQrPvwh>QI`!j!#ax;&7ppEHs& zGU7!W&-t9=8)MV<@ID4iW`F4)Qd&IBSt%?IeuX&lfdoAg zBlQ7om74a4MP;p{L@&uOP0AW4OpRZKv{5dpd@3m>E){jXUIn!S5Al~tRckEC<%F6h z5jNh5I<|P0)|do)&?Un$VJNNkV(Jl`(7PmlvR)- zGRXO{B(Ws`)Og>%nsI!uC&h;iryY&%HDc?fEsbKT_)NZGxlf=)hrVx6n+8W;^Ak0O z4jP}rj7f%RD7b#YtzJ0YIj%+`^HL}ez|&If+Kjgb1)Q>bBxSogHAsubD+S=cU**JG zGcf~oT6*?KFjrFJJJz09V)V0_~7pbF`ej9r3*u^ zFR%&Y6;!SB-^sX}r4&ytJa;w5to@awGiV4XGI8}xF?6zJ80xz#lWvKKl5EI+TpT(z z?7krX(3zy{FxwxMQsoL-lwlJdk>$IK9@uo#tb{IWh=9OeIlZjU?q0$zpM=)MXMYmG z_So_njXy4usH^!cPYkZ|C0>3FxL;3~T@COHDQ;sq%u*1?anI}By>basbJl;hiW$I4 zBAHV|`bD^;hCEXI0=5J_j|VHV?O&;_6el(+uFyp76#Ik7WMO3yN<3uKB|hO+Bm&G% zW!Lgs-(znz#B#9sDKK)lYNdI&O2>hvGA;8YcEfmtk4W$%w*CcNtC>5d>EMog3LV|5 zge9^!EK6OC^ZwPua|=y_#)z{sY~k+mk6N=SendeS5*wXB2HqjFir6Ta0f=Lm+=PD6 z2`Gv67Pn7%o&dHo1a$)87ju&vy+l0NKg-!OwkqyN!c4~SPV>;hN|gRCKL*Q2>SYkr zMkdcP>6v_ypk2PluX`GcF5#^Lc;Bh0Ppc(no$jC%4qsDS2+AH393F7Xhd@2jAAy;T z4Z~0mHmI8f;~!?Jx?rKkPkV!NabOlVAUVOS$B~W_1R@xG@E05-3^s{*%NYBnz|;g zq5%)3iw5<|X=Uxk!u|fwQCQL1J=4lAVi|f|E1ijcp8P z*fle6Hfi)-LU2&pf)KjU1TQ7wXp*Fbi>-XxFLV4>h1Ik5i}_BIrOigZ_4xc^)Ma~s zPL+jiaQYL5!MScmi>C3mLHJSm``2fqUkA9c{cDx1&NY203*BS#6BJNrIkq!t@eHF#FfDPkuj z?eTSa#*?9;&o8avPnCgc$8j!|Z}tUo4IVd69{=~V1e50lq+5jH6qXB{BF$Xkz{5Be zcfsDf5qGd?-50`72!6Y3Ow23uVbSh+d1`V`sj~|4NPJC66R3)a_T9Gq2+ixVg`s z!x*W~<|;C?G1WA=thvU^Q0+@O~9LjjRWx)NVY zIbOb&r1RTb+fz08seQozk8t(x#r4*ort_&p*&5Zy`MkxKZ3u0`hbxZ>8;JrY-baJ! z29HlMEI~$8B6(=Qp7?`gn$$g11xn>Q6+&i3^eJqdn0g!Ta_IT5rkYHshy$2r`*>16 zt$qaKUiI@*0{2$~m#2i<$o;b$?^R$j8%}uI)180r8B~vG4Ud#5IsHVjQUK!A-5X{U zYp!}9HnrieTvt|&^{ZAN8kQR~qTn zbZcZ~UsB&UgY)}53OvCe*&&VBSDcu~$>-kV3LE|2x#zTJxw(@$2Ke(S@0MNJ-a?;e z1Eua6Do3y458uQpG!$chA4MD;yY0Bmx?Q`C3G@rN=Q`(F=X&RwyZX5n#1SoE-r#Am zPApkv5#{MO^0c+&cWyQh{Xfjzb#UZBo*?SB-L~7z%*@Qp%*@Qp3~gp+W@ct+Gcz+| zyWFNW!_~~)?ac1mxO?&bdJz>FQb{SPvZO32EA#vD%y6LZXgj;~zr`SA{h{lrw^Vum zlMn$dzg_Eo3&~nFM4=idv&sMoGTAcCxYye`z|)4J(Fe*k!!*}vW3168|=%RdeTg7 z0L*y34`&3+l=(T5kqk0+E?}CweYbo6-kv8j$jzNALPssV#*GE7bVo}u6%SrhUUSu- zV!2B=X@B{`bXTs=Nr^#6(_~M1q%3XTJvwX87FmMdn5&!7J0HNNU!dk0;TdL@#Jdse z8XkoWk9J$Y+}H9qpBRZRnV;Z%OqU7#G>E?k{LY68qNIFlwo&c zSq`;i^@Bu49{Rb#lJSMR=gq1*=7x-tQyb4#A})5UM%&wuhz(;>(Cw_O1}rlV zMaGR5-(!?$5_9q{;|h)6*{Pw@-A(F9g(0bbrKL9tuhdOHU*#Y9@`iMyP~8P55EPj8 zP1uwDn$LXb@oY~dv!1buEie+MH_L5{@At{TIPyMNG+u8&YLmfX;c@E@60hp8eOik* z^_2?w^1Zx>PA9%MY30o7n^`n+QJCAAM4zjy^?APek;oGbf5b!*bcPOgLqm zVgiH)LZCgSe;dii=liJQU(0ym@=CftIL;5vw4YUAoH&^enQg4cgm;hNpNeT=3b-O{ z91!I-`uEuw!KZvB)*X*KE*A`X3IU^Q^cAVk^tA;l&cA`LG4UeYwYo4dK2 z`xph?w%J$*@yRPlJl?K>lj+yKUai(nqG@FqQ1*9@gDYs7@P2umUDsN_1X;`rNu4`G z_1+}a@oY@Hx74c2r1l$2mg$wKdNZK``hmYRZbC$Uo9Vo zWeI=tdSkC%ZX03bVv&>+j~-!bCMyY#6?V=({tD6_%lS68zWFlkx{Ywb zkQ)eUSP<(ZUPBG08{_)l$*FTY$I53LA_wtji?B~{NrltdN@oqR_vvr?nn8W(_j{D@ zl{bcTi}_mpux$d5jE$UlH*`yMsj>@JlGILOw}!#^TfK~_I9)Ylcgqbe7kVl@C3r75 z_3bynT_v%Y(jujMVIgDbJnMHxHp^P8Y~Qb@Y5&A~;x*|h>^HVJ8|OObU31@G4Njj@hzN;u0hl7b{B+3fBuh`~ zB-@MoVrYxfh89lG5DSu~3>(y(pHFV!Hci>vp2khITwfPTweF2*jf)NMD8Qz9>faXe zXiYtCC2)92KdLZRL@~c(@GA`ni*jY}r;Q%n%Pfs$Gn3uuSE%ubf`urhnfe(h%T|+) z)q+`t=ezTQ#TN1mE|($rz56>yeq72&b<@67xBlJIa)|Ycm4V6J3d8)%4+|%dK|%2R4@zKv!3LG10V;FzC;B1| zczhWe^cE9T<`z?CHWp5F&?YSCm2E;TZb1<$X-VDKa7kI2{Y7@gui;6nbE86ZbE5o% zK{{0Y?DXlu155^o#F8UK;)#-k^Qn}<d-4}ZdYgfp6y}fG))m<4g zXow2=V;Ku*-}q}}z6=Oekk+4K3vzk?u;0UESzZUsTl0MOuTRfFV!!*H8BWYt5Z4jS z7EFwfR~J-Kj+al;)KnDw8tayqoRk(<(;JqSOqJV_Ho+r_M%&^J`!)(8PChD|yU~lh zSzsm=q39We1Rd0%hppv|i9dL=*ztK_upVcT%4th>5Ms{Yl|BObl z)3Y#gvT;E({2$OLc2;^eHbxFkAR5KYO3(2Rdg_0pQ9!N=n45+3Kci9qBvt;CvBLb{ zecJyg8uiao`A=xnfBo$LfAgZ4fO;3nxkhl7m%k&>)(!Z_2%*+h5 znmD*PfSG~#)ql(q{>!QQ@3Q^lfd8X_fXoxHME;xo=mAA4LM|Yp#lk|*#mV~5GfGs0 zkd5&lUYD6Y5cjf%X5wN2ZtH*XLH{S4hlPdh-(?=XB$?=7M%2)!7c{N5=p@Wm1jNEt zG~MZ7r&lmrXSWchFjl?iKahU_VCIE4dUFddJxF41HMRsD&kx0QL^o~iqeE^zUU2WA zdJbA89T#pLD7$~>Imx3gH5JyriI{CAnqi$C!gPINzYk;hu;?3342N^<`)u8gbXKIx zE_0mu8-2s+F!h>+Ymr5Di1l%R*ax+%o(zEV%TPZn@~7&ffYc?DND+^RsHE5_+@X_V!xBq?;hXwS8&i&*4na;XC4_x*9M!x&p@}D z-v6d9`?qi9Usc)v33d9f7xn*J&xz|F)yRMGoc?)E{HMBx^O>{(5oRT<}Dq&~7TepZ|j+emReeQkl*;n2d z;6X(}jj!E)r>Z=!wh9bXkmwsiOs=N7)5Y1B+K&X-fK#gCQP#L_n^}RtL-Sw$PcfZK zXD9c;`Zl{OusEj%aKEEDb)ZQP2f)JWNrbILJ zz80m!d=i7Kga_WznCo#qRk^K3tn#Ro`1_BY!so{y>*U_?g-!Ju!;Q)P3xSQ)A- z1p9TM<6`$`t@O*%4WNWN;yQTxQ;KEFYs zLQgV+0|TzTAPNo$^|u(Wp7wYCAcXtFkK+a%SI6%iTa=#TEVm@{z03Bp?KgU!L-k8J zZo=Ov34SViqYIe#_Y(;X54{>ea}!I>1<LkV6nj85iPh~1N3V_t(Aoj1Zkh6_(M*D9wI~UWjAt=0QzgsuF(fp7k zs3sLdwQ~ZUGJ?pb$5uRl%r&hR6wOJYlFSD{Sq{3=jw@T{zmLtq+KtYQUhe7D{d~)e zQPT{Kzd>TPG`)$OJNvp8$+lwQNT7HR9+W&_5<)RZnoVJs%0Bjh6FS0PnlWE_uXs_K zdTaY^8;O$eiuSvT&wZU}KF0I7b}rqS;)VM2jo_?%*5QXNd=JXI&nHgd$^p-iN7d~3 zK#)z51uFaKHKqQ>8QVAHvZllnxNoQXiMaBH!+cyhgHfeiIYVCO=|eBcmfu4RXAX#K zzKI)xn417K6HM7b)ahZ+7Gw6)1Lg|Mh)>F~Zx0gSb%U6_uK4JO*3)CMuv{1RXef** z7)Q>!RdX8&U+d`EXG|HfSegM|mLt5nA))7Q3{OvO@1&}#1-K`e-_ep8VOR=3YZ$06 z84+L@4Z@ci8K1U46`4TOPrW&DFig5%Y*LWqExMl9PG>b)l8rIj6E{X|JQa}=3#386y#GI(_&-;2ujGQ{1B zTJWX8wgmO^r4hfY)fCnrq&p@9AmP)F#2%_>4o<$P#~54L%c9>4(#aJhIE=*d?qlc& zjf1g^2AJ*~OOYhC4u!A4;w4q!^EOm984G%8eJ%RmCiVG6nTUlh1Vv!OpFo27=dT^P zbKT>*kC?Xt4TE6XNYFW@ApgG$3p3W-t2w783rh+NW-sTiY22#RVR;K+58sz70H`ZCQwpDm24DMHWg~)t1bY=Mb=@mczc*?OCB*%?3EYtcm%~q zQ*PVL)SIZ0DUT{E-hXP8tg~3F|6VL;OlxcJ@m94EXqhmtiv2dnmU%OZT~NiSWl4P$ z*+j|h5AzH|!7I#rC9>8S_cHi2Yq+kd4RL(-fcvGEk|HGRa+7 z3owfjak5*7+)$SfVnvBd zEfn0;fX>r^b`G6Q20(?4uCudUfR6T`+}ftA#ZsB&2azKjg}PYA_2pwafW{_+T(md` z175DYeE-M8qCXtUidC#tS4Sn296Cqpqsm5hL;Gak-n1njja6Q88QenRf|kq~tAfVT zXQ`EJ2lwLj69tF$+kU-9y1aFa_#zO3T6$0#V3ViKb^NPsp!_#iTV>NB)_4y73cH#v zJcEvcghgTbB13+*AqZ3~@1~2^}zG%CR z-ROye0R>2=jbtyjWUkm=R65C-v)S>nQP?}giA%rLE|Hbd(2dEzZ=ibUf7B3J9ex_9 z&P}g!$i}e8+t((S(`X9()0T8=o6ucd#+*tTX{jL4asa{lo5Y!}_ ztn@w8CZpBmV(F;LB{umnzNa{SW?dOmB~#IADN`rY3|eVtQA}HDmR~mL#c_$aI!om( z1^G1kNmDr@gtMoLiVDin?4o~hadCD!JszH#1cRMEH(zn99-><6`C_aq%}$rAzn=@j zk!efZ7U;!7J4b2isg|jvRX-al$(rZ{-O(E91RY8_yS?hSziCpjfRy>J(?mI2LaUvU z(PRq+17x|GtQhbOIwo2 zjWHX$F`j-HWbw_nx{)1CP$ZRGX8V!vvH<}~9of$PXfGj2CZ9p<{__ z@nQPMSH9<1yH4Iy!ADibX6qMG1giM~ziUF^F)KDwnUzTkz_A!rqY&y&j`2Y7+;0@^0g(g?dW$)JJK4>7@iHwqx$EJXDKW!nX>slSA4$&oo`ql zjNiZf(OSJ=~o*oo={GBX9t+Vk25AH~P;r;`2 zC%WzYm&A8Tf8xE#J<4s`ZF2l8`>Wm65A~-f?NE1?(If5c0G?YO-Uzq#2s}@MKPC*1 zD1jLfshW|}#HP$IXfJ4;dD}wxMAhTTrg&b-JyMU!4CC#``Nx>x;AmC>;+7zE1xj53 z`ci+&5a#h*A^np5#eN?1>VjaLK{&JNqHx699Hco;b)IZ{Uz_aC{n=+L6s|y2|3MR~ zHn=pXevn|9=1(W$|M6U`N2ce~wcsc76m|W0?Y24QH~=XS^rIN!hzW0r2~xud9DmHZ zM`U_f=Dj2Ymckyd|M}ynaINnE$S0_emfT7|Gl#-B(12jcQvgp=VzJSc zmM?y`gwB<#H@dF4`&>!>P&Oyl#ffa&N;fKdg6_EPRNc|)+RdJ$J)dU~?<~#*+u?Y~ z7lh#G=-ul5<^AM6`2FntY>@SU?LcLLau&@2o#jxVL}<~`Du-2HT575UZc)Ay3+D!O z^{6u$AlVe(9aw#~dc@I^^t8Znjzc-}(vg58Vgu3@wJlsv^4qe|F_kj~p3LG1k)YUP z3FAWAI|Tk@Gy#Gc$>lu2)}|===OqO~U)WEO+;?*B7* zB5V#EQBQ}Vob5CB1iBrPW(|x4rA`l@ef!dW`YyYY_p5hvq(inFrgT%DcA-uTqWXp^ z%?M3v`-5g$;>RBo1TGm&IgcO3t;$^~eF_wdXyvmEf>99|28S|02+Hxmi}qx1M0DA@ z-R5U7jGtnFj}yr3Fv#@C+B0goi;m)kAG=<0?CI%|wGqRp&Clh*;RvnGQp{*MPhDh2 zy{O`3h2(bNnASmAZXuoVnXA0m?nc<9gyESE-1bBDfD0tn>=}H zB+|$tS|!OM+6iJ(sT5Pe>q0{ehNu*1Rdg|=p7F>cB~&AJEO{$~OW?~67?}eHw#k&y z(QuwH_@qRi_>nU*nKTZCE16VkpG+PZHt1XQM8(*u_h$NlMRR$JgJHTYt0SW%dGNxw zU?FBq$HCg<_0o2Rzb$hzK|)D}%^BWX7~dNL0`gLQw$hClvt-4CC&mXTfg{XFWW^s- zPyka`hh~|r4!~#bpy{b3siXqU>90ON5r;R33|aH$2}^b-Ml4$LW+?LH0neVB_?pO^Ow&>a5>d~2Q(>cYASwQv7lKHMDP$PyMMYPzERTCDX z<4T%=K^l2Fp-Icd;musLh8@UCX^LsixK|s8&RDl;7lhlmLMKm{qRWv7a@;}t2uzS> z$+8zi>6aI$YnWoGk8jkJw)?@@M(xzC-(3--%H;7W1nM@?tb=j@y02bL`~BPhUD?`gQWd)0f^;*9#v5 zhQOSmTd#2|);*k*O8J*j`%nocE_?h+7|^1E+4Sh{)o)+=!}bgC!}G)5bBDhEt>h8U zJ$&c<+-eUbIk(lJxez!sG=|UCFbwC^c6DW|4~E}>aR2@o685HZFwmC(lpo=D28G0d z>q%#hc)ASpv6NBz6nOK{c@yN7dkSh*Z;xf`AfyfZ?+d%VU_(Y!=vNXVmY_UKN@P*W za|G}}Lxj+=e~MMb3ud$rp1eS^3SXgbEA+F`l7V5<_Q$WZnLJdidlK9@(ZPYi2rQ$Y zN+pajlAM@OV1@Y5{bPUHUq8f)$1v~TJ{r7e{S}6fgv9nV|1dXhB_jB+<6PMZL`ar2 zFe1~_w-6&=>1g5#8IkH@g20HIQ3drG&SS%7#qzu48#4arp2L0+>*a@~25e3JhKE$; zY}!zCcq2kZN5{YrmyWWdgiS?HM=k1LRM!0=>O(0Us5p*3*{%tiw)n32BQAhWK=BH} za6G`jw9Q4?%+1lZaIx1R5I;yyoj2*SwjI4Bol8T;|3c{EV)w-{Wy2`pSgceLy zO-#S9==2E=LNUGKT#wwIBkEw*JlcDULDW()B9ge=9S`0XIr(DnyUQ|&~ zL0MlhZcfuc78Mn>Pd`o*l~Resx~%?mR}|k#)@R#R(*A+0stSv(y6|(H5QADe3=Ug4 zPzbFwm^uK250$Jj30XrbatFV8EiEPG7lunJDjY5C;P6t|)15J6g!A|2jn7`d)7bt1 z8(T1q#Ih%2$4|eRh=B?$T{RX=%w>^<{*s?R9lk!}dOD6;K0n?_G!HNKJS?S{%3>@3 zoQybP1|!az)A(%F4>uT*NWfR~`;`z3QR9f`@xzjYlZnHFh5c1jeXOs6RaN8G1L9bz zsi{Ano;1?pDCtH*ld-+Mn2-k$MVmG*cOR>jG(27}+=gcP`69Y5Bg^yk!k2!BEBsmqP=%Z=H}jakMXZD!Ae2^BjK(Vd7|oQP^ph1aJ; zZ^$u>siR>oTB$JxdFew^b$`5R!lloFZ>=;i7iHWVA)SGR#@_Ga%!0+<2Z&_c7sT8f z(w+^xFVbj7aLbC zDS3K6@+$0jEd1GV+$1vWq%!OU)H>TgP1)(L)8+8Q(Cld0w5i)-99`^tCOU3gxyCjJHAg0Aa1jQT;`W6@TIq1D+Sh5sF)PLU1Hp`5*#Oh4 z^Run$J|mMz7Ky^4xxTafdVidUP`XX2zAHudthFVaJsN^%W_)_afn-^?^k373t## z^ao;yzobA&tp7J*fdT?copT;QFbW!u8>xPp$e z`E*6`FX+HeGrK~Pn%IV=8Nwe+GnB>IN-`WKv^z2P7v{9Z*+h#oEd?Kg4ZwW-@fv1? zvRk*IdHjJArle;f$&Fns)JfD}jYLD#NtX#mXf!LSOj$9t9qq)G%!qF@dT3Iqf$MVZ z8l-9v#%tS(iK-Ww8S>y#j>P< z3E0?{e5Fc?zurym-*sGBo7~rLptpYD#1^E9H$;g4GGd7}98=(un}G3}RzCdVpajyj{yTvzBkIE#JpTp1vm%H!bVu8$HU3B%|xYQGFzO<8b zm`R?!^w;7Cc?(h@%04sqToz_a9sC|JfbwXJstn&UC^N)U>|ULVZI?3 zce-6QA7k&1VcSdiKK#6cV*c@n3W(%T!;(mYCD^sz{)9oyGS!GB3M8`Bo53oBSjIN- ze_=cjX}WDhp2zkBZ!iX6$#4cCgXhBc)L3|}5WeU#3KblF{DIxY_AjL+Nq)R3(+o>^ zbPTUbwue;@&-YWK=p{-cdTI@?x0ndKaT{0~O#l8jDsv<1UYmtiYI6|9SY@aj(g7|W zS|3rq&D^w!NEe5fK{vS+d;EF>ksg7cAkJbTX+Onrui$guQqsZkZXY%?^@^f40lTzu zk+4$ul0vMcA%y{)wEQXoZG$@7teAGHXnIOD>}uNbEy>B9dXVZeoMauH7^MCP+AP65 zUP+NyB`4Aqe@zgFJdPCZf{tb0F))jtnJJ5C^j2j_*p*a@2Ya5;%Cw7nHzBbF>SEwF ztcCS@dz3BYy^Kl^Phm-i`Fk=pi>QfMG??w24atv2hCY&Ci~P}lEUkmq{KRV8SDCi+ zF!?U`0#0#bp7eKBZr&fF!XjfY%I~rl(O?(uvauKY&9aSgCfbh`KPqC6323dXx5wcq z_Er@PPquHA3=9$uWdBuUQ2cu6_;69a-F%On)l!==8dke)2=G6rxgz|=agPBo3x zk2OmWU)h%fHLt9XH3L^#!5hu;GI?bJFx>I+Ho7DxrYbuvwq0piF>zg^r-CI`B|4b` zx)!^INPqqY!sDBw$=;T=aB(x+MaC^xOG~808LII)Zh)qq{>gJ5cKYsFmrJpTww?S{7-`hwr zi=r2`M#_X^lP|Os8!6lS)Pd2s{hi+oc^*_prl{q!JMO}ZC&`BNIm`PqIOU>gPm6xK zc$Moktm6}QJUjwH<8M5SK6=#UG#5y6h0GbJD7=r>$80x%&;)_ivdDatiS`0ao1wvI8=!j3`q~b z>~XY`I0%;Dfe`TBRQkTZ7Drq$+OdrQaZtk}33P$A05P=M8%St` zr2tUI+C+#b6nw)UiLl-)Mu2Ypvw*<_@JTsmj57xOcrA=~|6a;{6^{(~F^RYqSAbi( zi3BTH`KX{;&<{+CWZx*N6zlLt1@YhqzX2E_ij{d{tW~Y{hzf^@Ff07R3%P3s2mw5> zLx#XaqV*BaI&r>F3|XYbfeBQk)qx3_ZL_^XB=!*@W{?p;P%-8RAi#{(1|Z6dDD#9Y zF$wd8urLCrSlreFxB-Z>gOmWoQNxx;xY^YM&73m7U?)z!H;5yrutzrXb4TLY<-So; zR?FOs7$$9svhy3Dzh;#q^F;UKV+Vshd0iHKRXfzxU?9SJ#wM%8v~~gQH_Y|}ZaV?{F<`?{ z2iTeo!4ZdMiC>IahtM15lv8jUg2&<7CjWLQPOINDo&DnDp*`Lwd~|ECW+2(7{yToV zC9oaBe&G@5UR41`{4}co10Nl7TfvZy-EELR=MRFPW7{BU8fCYF!y9ygNu%yotb}8E z8&3Qoy&VVskVET^C$5JL!2#5}{2SuWVQ2sl^ZL_@a9aYOKghQk?uq?mO>l^{UGEoR z;r2|yTi_S5@*Mm~wCJh$hG=tB@CdTmsQmWL<~HFGWc2_E;8!zNyy>%EFm!g4@rcjt zsq2G)a~txA&+Yomt8Vqj2qkZMcO?Hd<&pkVCOrGL<&nN^9}A%O4nAl7$C&1`q&FI) zL3=CIPSU3PMx$ooGYrG+8F{m{|G=zf#r+ViX370ft!B;rkj-}9{m_lK95C!|+LG%D zhSQq6UO2?DPzV^-SuX($Z#_3Z!tV~`x3)K;e3kab_8T=nvb!5aKcerh9QdqP^@cv( z20fzl|6&Kw`Bn_Y-)I2nu12Fbb=HH^TR0ju!ryM9+Q0~o)a)Q1kJ#)W`4e-Z+QbzDMr9A;`_&oHau~4@m%QxC8b8Hs5%@O`B&BpB9Z0258qE+OP3T)@aDUgW<6*NvnH;#rxpd-YQf9~2W0A6@@38UK@f>FI*mFQ0zt>4PKX z;?EaB(gn|#MA=uo?3V+@(pUG^#h0Ji>(8d8|Mlh*^T){-j4AiZPuHETK029R*I@$+cyC=_0+8!|Qp`=k`oWR2bQ?ZGJ$yQCPRF)EEt8{hk zIk0j^>M^G|V5FLEjyhZ^H@pkgIM<@KvNm%;E~!M!Rt-3O)(+(qQ7KodkgJa!9FsEp zu7k@%qXo`LkN7=Nf5O#zfphLh^QA?!xvx&1?b^J%_e?1lf=!7+h+^S=#s+*$4QEmj z>NO)Wk364wxz2UxSjk>1uOjzEDX>- zYECtr>be(?9eU7!uE60V@S&*sPNSt|CZ4XbWWVDhIUEhz+}Fp(I)uLK&o&*10Z`XF zk!Lu@LT;>4Gl=eAZ ziz+VOf}U}FEX+oYO_I8Z+@x#trYowZn(or%?bfK$>MjPbfgeeQF6X+A=jjhK<@a3N zVKId%qCy{ozKGAyFCGmPxRO-)g|@P10nRN6s=L1;Y`z0zn18SR-h$dZVA zT6%2ZL18ThNL9@a|KSquOx?DQbJhsp1QCYf#Ow?%fRqa3?Zn?-(?5!(VVgXVC*!e~ z3HiKTcAI2p_rL9kRz71D{9*pW7)|pnmVZm zQmdBYnsGGySc>yB1n!8e>98C>vbB31O={eFQrF=|jv=u4S1R$VbXhCvRO8lhDVr#e zM(iX?(q0gp)vL5^*tUV3h{jK7x9|btLdc2%vRTw9x5LR6P%c7@M)GOo50cg@!}wT|)PU5wiri+DuA<-Mui<-r&xc*tfyeJ-op57w zzCCY7lS_MUdZ3g3T4ULv9*Dvq_R?uP*Zp*Y^?wa;3NW56AkN87FVwkLcqgPGwIsBx zeo@HqrWkkQrS-`p3y0Ooi<5vSW;HPBswft$iV_p$V02A;=2^%WI_FtaJaQ?GwofLa z>QIOCq+*vgi(d%aS;RV*l(j7-Qt}u+k*+_KD^ryyld>n&{ylItRHM}1vUgDl(I=#-Fe-j=)(8pmZ41{*8jKaj9N zlfL(R_j4d!fmNXC=87eo0r2_p2q@6TAY_HYOE4tEa3ECAE>hTO|Lr`E@Y=H!Hi{9RdtQ;?FQgcLtSDL~4a?u}chKbD5eMp1zBc z+ay{LQ_dDG-P?5U{T)jau0q#0RGBtZiSAIoc=1G)n|rgm`pjd4aK5xOp>FohZMK#4 zsn56avYaPLtJG%KY`@heI$j1gDJ8PW+DL?lEzs(O=Wt|NDZ=yJQb1KhLxUp`oUYQ= zRY00rDka*{3yEHxRvNd~H=6z0zw7sB_#VYqhli_BgYr2icb4rXzF2t@8cu!B5qp_| z`nPusVaWA`R^+61q#k!pudE4D`O}w$1*(PUqS~-**hAZ|lR;mR>I?A$@np>_cE{br zqy(Nl!*Q1oY3bKTF-8GVD7bK8_wn5fOLH2%Y0G>vn#>9eJloqSVjM3e^V;ZF-Dvqy z$itGN46gBOMjWi%%-hgtrOc0yI}z%Ic-Tg7(-xAh>v<&c=ooj`T>c3yQPc6llEl_% zRo`>gdV1{j)GA=5r85_E!JD&%Yy{d=9p;A@*@RtMO|E3Fu#N|HI9`WQa+vxk8M-xt z4jHVDO_mrn5DWoV6E#wV!z41KNhSNpdZ27|u4{FZ_JpHDh0caguDaK%4A z44=YHue}<(Dn-aYfd8afgvOP{vdsAuHF>IRjo4&CI-*=%M~~(()&FS>Cw2KtR!pJG z7jO{}-7*(S6XKB&@3A^p;BrSbVF|g`$Rs4rlfj#BL`_Z0!bkvfzvZa%>AX$BJHuzc zF<#r;W9o$hdDlPHu7mgT`0iULdS$`@RdujLtCDlpQTA*Om45s+>6CrMf35%9Z$Rys zscZ6+!v;U+hDLs5j>TSWhAjMUq#&CbX=~n_ z=vRofN0q4X@1*z(@5^BB}nua;n1-E03_$jX1{IB!~=!-UmRnf!t_3G zD$HIpeQVMLUB45r9j<-*-l9vhGuV9)5zC27RM(Q;OG1MS{7PsVc>H1II?3Sc{n=;xg7uUQEDNu_0ctdFe&gm z=o)Y9bA9LI_#w&y60YLwFmkSs!N}qkAH?%Xw|!cmb1=KOK|>|b`y2jp%Y~<$%QD{hL*jdI3)%U6 z+wa5yg*OM({+8^#(rSy;zV&OK2Y`5x9=!tN28>6p1<>*pD6fcC?mfV~=CWSkah#zW zJuJf0_z$#|k`2N=W8H@nUcqJq zqS-N$?~i#8_n~2soIEX&gjEf4sDFbI6;YU;5ECs3O4f8#D4uYpR*lSb9k>eqMA3UY zrL91Cz?yG$2-s1;XhBOpe9y2Z6%R$j^lQXA%hQ}RNm)+ZexuZ5bC)QRHCT=l)#?$S zWAU=`AjO5sEtI%j5S%A?0Owl3Rf*DVbd;q(G+7|7Cldf7e+>UX{_?0#Boqlz|AqV! ziI4^f(<2A=9myR|$JBB){+#i|qhf9t_m6sT^eOpd)h1-_AGz44p@D#FbFo-9AZ_3DT>boQv3tCF9g>I^r zBx=5NiOo>#m(6;it+3FF&m(iZ!bY&bW>7UFOuL+N!p)vK%B!)$U?{*f=1(Do>tX-5 z0=-CkR4a?_p6-2~+<|vxk>sZ{G9^#^E%uIJU1hCQ$)qcj=wa$~Gw}Ya_%Y(6vG(D7 zwN|fae&O%;TyIxay)8C~kdHk`=iqq|`1*Pan{a3>yQ$4fBQ4-LhQ<3cv9lU{ z#rJM==eSbTS~3a*xf0KMauiT|T~@IGJ3`Wx<)(r%niUq(X(>aQ#>GA_8kShW3^r0( zLl(KNWTHAlM`3nYDt35ONGt`GyrG@x-YF>!%)PT+4rgK=zOKo0lI>Xrw7kRq6mSv+ zh`Vl2Yr|waN6{+I)WDcFi(0M&!%`c(L~5?|JKCAGB{~~Cd-XmFuIcmyI5Dvy)8IJ{ zSyZy%1wtI~xHGkZbJXv}LTPGJuF^@CtilDng-KFjw#OBb0dw<2QaYW2_{fWc=tlX! zU@RtUrd8>Y)U1;iktxj1XQY~?KK9TS_a31y)TVo8V(lz6s!H!2t3tW(*w|uft*zJB z5-Cj}>Qb>fgn!mw`$;t^ldL6#wRjkda5MT_lQgsMRoiQmH0{|pPZzeD^WfBrNX2jH zlToYtq}FJrQiBb}M2S^S;)Pl*0wVKJ*rmD)f2Ak9y&&_xp?^mf7T;aL^_e!1l#1K5V!T%Rx%L~A*tDfS z*$>m)y}^3G{1lc@l|7>-0dCn6S?i}9^zUM-V!WMS6|&G7Z+Sk+1m3&Ho{w^q{!O** zzrVG%>a%;9^3~CNL-iam zgS#h=8wZ}c80l;q=~931^si0T2|Ir*lk->!p4Kz&+4^rxV@+FR%r!Xqy%5U?*pPV8 z{|r5${*4@MTNISj0NWH-3b##3MHSx|(}Mk{@X48`1nrLcIzH*VfW5j^w?JN~plQRH z3d6LVaQqai4T@BXGS%$S1=vkTFmy(xxp+nh56=~i)>N>&U=oX&(25l&#(J@5TvQg% z6}o14nZANmL{=&|Rj4o5LgKm6|;qs(~NL5qYPOt`Bc+#(h1c=&W&Fx)(NJ0Dq>3K3nGJ1Y7C|t z%HnVQ7i$|_rCAZy*cR68GaRj%-;-?>new@*WO553rf%eQ95TzhoRIo-kf&(AIU0Gc@WXXcjqFx{cKKm}DJ`RJYfQ1zb*>b_T~ z2T(!%_ElmL{8xp3?hzj ziINA#+Oy<>mQCa&X%%O}^d~J1E|EnhEyLXc2^*~<&x^+P(iHCOnApP)rHY0y zu5JUH-G~P{70Iq^K zE;)@8EVMkF0qGpvJ%rdAE_aHnX2wF>If{eP{S2ZDg7KvgE|%Swc6k3};sSgv9c5ip zv#-BXYLbjy=W^o0u1+?=)GE*WhIhC@y+Yo>jRu<59Bf{tJgXecEF3+fu37J9+q!2o z;3yJ`(xFN4^(~=t z!Cd*8O|#aC;`D34xF*k8v}w7thcL9Ohv+hx168Y|zmX1+hUWf9sSE9=gcqt=*g=0s ze<%1p&%T)vLK&m83*Mh9C2M3ec!i*KzDTmwPp5-n_z@`#=SQDKN(wuuZ06x>%)wy@ zs|B_&wXNibH{?f9gF&Tz8O`K@5aoSYO7MdaWk=zC)?C!V`wl)Yr8)t+II&`G8>ZbT zar`ow_Fn&)>OV0TEHAWxo7IW*Tor7q=M3H+&ykJ(pDo?G=a_GID+pJU4Ai`Dch~65 z`(<0za>{Ebx+nY93fXQf(X6sd{AXYEJ;BbG(&%&h<~Oz5!g&nT_~T?jZrfOkS}%VO zltPQ6DV*gNTi#t>x3er_nbUJ(J&X{PmxG7B6Atl7s}#i2IHOVj5;o$OWV{F!W37%M z)0BkjIxP_DsJW^t`E97WNxM2Pl$LR&$<$zQS$Nm8>zQO|DT?aEQBb@{26WZ2A$!VmB7r4egQizAYJkL=eOw->(OCK(O)q-GCI_pS_jEI#; zI>N}ho07Z~DvMAapSosZwDTZW+GYfhQ4LO4G|gU7B+$}Pw`j`>lV%V=k0*`0sFI3> z0=rL1p$Z2o|4eG!VHUXc=u)bJ5qy3EG)gT8!`X5QyE&-uYsq%c@+c>ML zUCOur5KkRUpBgxpNyg;BCKIhMPK=YRCvb3!Qqejqbd8*7*&Cwlx;l0`*UP6aobK^+ zrA91;jBGbu((VoV>~~dA#^i7|{Vtw2Fbuu`JMo{M&GSY+j}s3=k=A$qCR=PA1aCt! zJ9|4ayK3~^M>&bL#g`0m-eqHu0^BaU2J|@}uW+kd{w_nECNwk*7c8zHXz70}^`60x zmYoCs%s-ji%V~edKIB6GfdampP*`iTas@x;QY3AOCD8#(^jnHv+=gxGl!ysJIi^B{ z2uZ#RRny_Tr!X$I3cY#W->4zaC}6Nqx>rHdS`fXhkwoIu#~d`qd3`I7E-l#YSq_KZ zhPU-uj;{FGJ@3utHNYmJE3QFv_uF%EKT#S(N8{KQM}5CxbsyOD=Rq)I7GN*wK&zhN z0`Z5bUN;UArfHyJq3x5q*^|4E8JV?>4S-f1LlQj=s^q(02eC_(`w)zzv}WlEt^DU@H1*(gu%Po~CNwsuvyzpiVaAt~23ncM`R0{+k=L@ldOCe&eat?$_NldU?hu#%dkrC* zsraLKbBBmFF?Z_xS53_f7m+UodkN$z0@Q=QLOHG(RY?{}3G=yvDhhYe`C;q0>&GB? z>A@3bXUq4TVaqn#e_73EySVr;g%%&_9$+p)6m}@r^x!LiCL1yA+0h#5{4T*%84W)G@yjh7;#VuDpTt)uVjcuBjJTL^O6xb zt^B6%J(uWzLh4;I`A^Q1A%u4>=AWgKdn%^eL%Rf8n=0LdhdbB?C`kOs&b9F5U8(if z4_I3KtgTW8J1k`JY_j?24a#j$ALQi1=!|qSqg*#y!kR3;=l)~tOlFP!Q|>>)`z^yG z`Ke^}QS@eUA0*`i8Tu`n_^f?oL!Uo8sEx04iFojTKmOJrW3KT#@FZ*NJ?G+1$6e%m z{cWw2p1eG|>h_VQ6<}cn`9dUs=gXLpM)8JC8-|iUY_PDZtejK_=LC-cN5xf4W+s(7 zRX;^irD&iEK zN9Pqm;u_;gkiv+9h4up4d;dea3dN^r8~gqAqijs>Hu_-wmS#$3sy4&F=^d*Tv8Dk< zpNgjXPE|B#>;7%#T;>g8vbuT2Y$a8Fn!38Frp3?Xu=?mvW+sET{5+m~2bx%p4I7K6 z3A!!2W5Y7e0WbFJ62$d&PJaQI_`#}}lW%=J$ynyAyhfSG5@kC;d5p|-2Iz&Fh8Wh9 z{W{cUwa;`Raqty@X5JK^@qkH*d4@=Rk@y&j?Pa&1og*q6Sy_L#c9xM~=*GHOT_4k8 z9UKQIc_MEQ&{oS^ODaGlmmK)U{RTCkP~Bmqpxa@%N3hbaM5#8NiT|95D$;0GpRQ&p zy3&tO-*j4jrWyiX?&cShIo_RVOR_TZ$>Of>$E`h$@_(gDZh_ou&eelldlEzRm01Bu zoj^dF2W#Fu&J{W$m)KzhMs~U4IH@9pYI(6{PV~x(pw&lp0A`-AB{A_pF z&solvx90QRAt%(8r9QXUa&h(h?Y*Aex^=h2IlM!)hW4OaXS>xD)!t~qhcemgcz05c zneRKeF8_1bK-09V+C@_(y7jOn?BIdr&A|0!ZO>@g)IGmo!9sTZbow|B-;Eq#w}Nm- zYgb5=-$Z^*8MLkrfI~Y2FJ#X_SafJ3(!|EY&LPw%zz9EBZnJ*3XrH|+KS(K^PjkvY z&L=gn$~5bo^3C*@`RjWRnTP1}cHeX7bNEK)Z=ebLrdl|qeng9DWh=EyyTQ3jvK##F ze1mfITOkP~GhmzyqQN6p_7vV-cl}9rn zK;@YpJc>^xn_TnB!a(sR|7$ZO!huiSP9oik)R4m~x^RHBJ6MtyLyl)O0&b$6G#^KK zkL`_|s}@o7Co;GmW?n0_PLN=qF?VU2K(6aGEYt5I;ID8wJinM2OO0lqTRXyNrqQZS z#n1EKGuj_Eg6f*hw1P5ZR<%utRn<^R=|Mk)n2sM9#mDlhh)ex-TMehdf9fP{Zhv|% zk~dl1;C3SK6a9&?Ct8H=fU+g|dG#x$~Z?*NmoW^VoHq3ELI6nv{@jZ^#qH)!!3i8by z5STWk*frGC&$Te#5>;^4Z#?$%5^&EyWIAN()oS@0<9uRc7w6FK*;6`w7vkA%6ztf& ze!;$N^BLl_5_E5SZxd~k6Ki^+GX8V&u{+CrYSf80#FrBc)Q0`(Ys>2us|i`BP;KQ< zMFtw>-OB)NqkPNO@zd#QoShY8-I+2omdjBVJTQ(r8ARd z>W#4OI}YCN|JH#Va(X`l9=@Lo>-7YB=uHJ#6Y^6A%)*~quP(tVZ4-~tI_(r zHZuTx?fZ%c84wp-kW014)jj>lD<09kWH&7X6i|U=u zzV&*sOCfjLY{~2%yUs5&3j?X#=h}>mux@s0;HK|ZKD2M zI+{+cbBuGWhC#E_j-nB{RcAe7!+Y<*&3q}&^qZr6^6kZQneZf?HPlFjL*u9{X~Cr@ zFH=ZMbGBIalU!<*KZ!w=?dl-+BaJCnkCLGSCv+VR(xo`V*LxK^`cWK$Sql$0Bb%{> zZT~{gLicgXHu}@;B`24Iy%wOeQOfW9f*xP{x~zt{{l0TKN}wmzR=O{tcs@VBbo=_# z-}5$jwY8qhdJf@^*pE|pj1o0DkMSFxoGAlMHE6mhdxc_@XH+KTW;R=X2I@e>6=?J# z1QCsY4J(l=@%|1pinJZD12u~E6|v(n%DNr0<1(uI^{}J1r&dGy5TOy6y+%tg%gJ%i z!0A5MqU$MH7&QPHBo2-LKs8d&w_qcqY_wm4B6=2XlX0YGN~R*GGWeGQuPdleB&PUOxaZ^ zCx=vhWLEHRX|~!CP^cMqDi>NXlvy z{qe;A=-K)!_RKN#GQS;>iYM^H#(;PKsRr@H!}&2qr`9(~_LjFJE(BU)szl*A?}`xJ z)peBit~2}GoDX>5GZ4!bbt^DjGl{r7aLvc8$H`!UW81y=1$Z(UW8MDLMCz^OuLmJ+ zJpZSIT93`{R7*i(+mAn)qs}BTG`T~Shvc3L$cS-UVh?@qzk!$4yaMZ&NG;Ld7AG zdfA+zBKw%@tpeC`r7bL|t+m~km)s~W)`QXIhv{+1lrSnQu<(G_#B>6Nq`D5ma3#CQ zL%~y@PWq(X8k`l)LM0YTv!ZhqZ4KI)XZ`olE#zQTzXV+MU_H>5y9F$crp~9PW=t&H zpHfX5$FIU{$TBv`>|#tsk-(%xLr^4Bw1@7LgCZ&l3dMq>FfMHax1OTnXC(~6$P7h) zy=WhM1!b79ezD}3 z7!hVML;~~lws6ZD2MIFBzGOS9Z{@yGF_MUGE(EV;&8}ws)TZ57sonVT(A@tnrSU7# z{q|t(`wvGL^JFRe+Eqimp$Te(c?9dxrmnDwCX8QlCT!G9+7U6oFi71O0d@sSn`Pe# zT!rm?GSW+?Szgh;T;cTCvhB}Urum$cRmj*Z)H(-d60jaSvAq%`^SH(kmd5P*qh+wM z5cD;eS?fDj`&GkZb}KlqgUIz;F-P~uj*L66>)@NWpR3ceN;U`IeKZd{epf@-;ID#<}JYeSS6#BHh`1pp5zTlYwnCr1 z?slC{`HpzzG;zqDtz|{F;#%7EXh~>Y5^D%@dRl)?FYRh%f?5D)t6Bp6oAL&|-WzhH2j3cC zZG$Cg&~Xp*Fuq~$?{{oBiymJP*XXUE+Zi)<&JMIT3&j%oQigh@w;g3L#*n5d_d$3C zH!CeR(VSf|FdU|8Ggr+n=R#*_KNvGE(T$dfbIFkmR)~Yon2eoVOgV81ZSga6>ITX& z!al{Egnq^#0CRU^P3IQ*Nkre{J5H33a747$CrPE4t;&WHPp{;UboSzn_RR&MPxli( zzmPA{zmQ+;CoD`ynixzWi)4{l&Pjj~Jqpxl#Xn{oMv)fCz}U#6utk7Lpkkp4E|hRU z2MX%Al4puIWJh+yW}&cJ94H0CE&`B_Ag&=4(50@VS$^F2q{YaE0yNnQ2uB_WCo7wIUSx!nFMMgRcny0chBq3$%GrOZp+KkI3Z~#Zx$FHI`hvMMv z-SoMfKUX>X)#X{Tu(R7KksKIy32+YxDmt8%E;3_VgqMPR0v{XpU&o!nKta2te-%Hv&hCu?4*;&yV>PQu}UsQQz4PYS07bJ<5KN#$@)rSWkR^*9p`oPF+iQbzBit z#M(O&t=nNxwza9yKDRll%Uyu_ypA19vrljs=U5TTGZO1$gWZ~TesqTy1Y{WIiq6}P zs`k+1;(Me76y68Wa=E0j{aV-f-D4Wm;y(KOadaq%MO{|<;C`4@OvpV@-KFM=WFlHn zf?f=1f%Hzo>!=enh4$pPB7b065X|4}kS?c=F)=4xum{(p2`h>?@wteHzz?Mq?{pqi zGaDvtV(`)tVIh3P(cQSed7P-NmkE?Tg8>jl$T|Vy)@WtL$k}29 z3q&Zk$&hSVIIT)-=86F`0Q22glI(G;klZ+wh-;`p#%?{2cQ+%iPDY~;>;pF=EAm0s z8w6CXq7km@1l;iGF@uahvxpfkVt5Fkl8iuQa7ZsEmG9rNs6Q)4z(0e)KO0U+^WA8z zqBaX}+DNpp2}5w-W>@>@`IB)of!1XMUX?3nbZM5S&vglmqiKf1_!9FklxXb-lw%lK z)ePnpF@-Ue=fxJC*w@>RvR>y=;h#-h6@LAxYrLr8_`EFtK*v{E{haJ8GSjfL6pkcp z(s%zT0-e2_CC|*S?x{J2R5)^D_QmDUe=H7n_NRT-B`mJ&L*(Gmk2~z1VtFn2B!08F z26&H5k`_5-o3S}}BDkLp2JQ#?0EvlBn!HRyQ3`I=8aF6=nFYLR0iQXKFKr}Mwvxwt z>oB8(aEWgVd1ZL%Fh8~&^uHfp1x&OBjO032aHmv?P!4v%9j*W&cOcz%ffNIq+Zrkq za4@0?0;fs6y{od%!eNOA_WV`Ar}xPlG?R5`Qxrl8$Gi7|tXW=}m6gp)x|2Bz$#qU6 zGqnV%&s^JaWSE-8MZu^K(9&1H>Y{{Wv%!GKoEz>Fajn@ zW>5T!$hRNOK{0cD76tR}axeBBMrrCq&OEu7pHU>=Waf4j%EbYHVcDyE{j`_6E=-4% zZgDlk`h60lRVaVR`3&U==L)AwRBL*xZ!0Ctd(%O5-tWq|Rb5-ch_q`N5& zRKBjzzEL@I9`RWKFlHE3i6Y?GRYLw++BNSqNAMBLLISxf{3!6q z`M&hL{hVCX2GuiK!`?=66_`T^fdWEoF~94&`ML0GMuCu%-R&&2C(rxs_4@SGq>J%o zF03BWDV+ZUfj0C^$G+$B$=bdL7;BED1tj&m(}0!UcpVdq^$PZi<`);I{jg7=ik4TV zmOk@wC0~?Y5qB3Irs$;N-N?hY!%PR@yGeMIwn=Lh*4Ar;h8Oj=#zDk|`5AB<$EFa( z9~FPXq%5fPcrBF}#F?K*KgJ&@$c(tG-_(6V1vcF?MZ)TD2Nfc`ofF>TD1MXOkK@V9I z!R0Uk4B6{g0mnp#Vg>I$8993g;%+3;S9H{By|c!Wg4wKV(8a6wri-N8TkKtTD<9HcP7gIXg!UK)b_kwW!t|8o-B9+86p%_ z_5s!MV6J)<#uknJRF$tC4x=iGobpByX%HNT1$zn11(8l5_a?jJ3I17-xHjOqL7xeEQ6`^X(J(t8! z-%z4=Bfa6@&l@eT`Jv@>xn#LW-?Kt37CG8s&c>IUv)Hvam8y-X-w!h3%)b8^BN@Q{_HyIy4g;u6R`l?*xgb1mO>{ zI{^Po`a1$BN^Ob;HO+G1kf1UtS?Yuod}_2~XBTaKwUzJi>%`T>^*$j@yy|83OMeRG zZQ}&$IOWe*)LQa)HL-k3bsJSQ+|*(5RNQd1EfE~_VR5s1CE>Lab4$1Sj2IfM&?0EU zB+B#8jCcJ6=$1f&$L9=BY4Uy)(50aSvb< z!cfT!NVF@JlvYnx7mLtFzVQIk{3^xOuOJ2JJnC=-L6{hZJ2N%y;DrLI(xnfoXGWB%|oyyxicT02p* z)2g>D-8R78dYzaFr9rUcf0yu(GF|S#Ei+I?j#$;JFLgb-R5Pp8a^J#g>)1aViIR-O z)F@-vT&n*&Z~vY%W@+|mFU!`7yH*kem)uYR7FidbBSV9dc|`=KsKjI%XppXqbM%3% zzVd(-A+#Jr!^jZ9Qi3fL+AQ2!Cn6{q0plH_ZzPF@;UTR_8i zWXS3-WC2a#JInI5#xBGP;#>3 z7_Wpqg?Nd)Ai+>MTK;j6M3Pjp)a0fouKdAS;y9?($HyebL**MzlCuPx2Dkt;L(D?+ zLwEgkb#LX8Xf&alt~o3aMicIkSXK>lhmFwEmypJ)DB2B@TVB=?q(qJt{-n(;2uPL# z4+>JSnJja!^(~T1hcw+U^SmeM@YopzZCq(u-X7phI`_XB$h<%Dx5rK9^9B=a5Qp*x zAqNVhgw3?fMg_+39E(?(qPAocwY4Hyj6s>st34))z}Av|=(I8=@5LUEFdc+DQh3Tn zE=o8hNG{N#rkf3@TDXIIbSTl}1%0pQ6EaH$Zj0-th^%~%L+AEkv18Z^yl4@naV1i?g* z`V(qihDe|nqFo!DnrYq z&bmj@-bMjY;HfLO+g@J2Fnk5FFd`5XDCb4TC!_O%q{lqRGO_(e^ zkcf2hb8SW7oL#EJ=k|(+uj%V&uUe2T(tseIj^dw5-n>zFr4X)A@5QhAS}$Lws0^w zfbL5>_lb(<7S@g-8qzrn$i~R3zh0!8fPA zH!;ssPG>0K$9Y#5a0lF-PPuxbW89#G@iOZ5v@u0#WQ+|#8?y?9@L z21(dcd`V@$=P&B8`_Bj9s1;4gyzB!V#e*vNc>u}I7abXXa&}eRtn!z0u;i7kO$I+_n(uRmTM_TaTfW*>++Zv5*7eu=(mGMblXm%dBJFArPQkEVCmQ$}E* zho<{iPpyB*bdke23?n>U!5Q!PK#l`%N$G8X67UF|!sP8(iexFw`{^O?Y?8rM2rmQj zUTw8yhlE;TS!D-Y;7|qg&y$Q*EckQCexbmh%*FvezH;Ztr?jrEU#+Anty(tpvQfYa1!OdfXMIW4D2WK1GWxs&$k(z!6)gA*MSdhxYyef~ZI$~gXF2+_?_Ax1 zp3#`yP$}=wM8^t!ksTuwUzYwR7^66idHwH^zCG1SfCnqePiCsE@Z8I-lF9NPWU9AC zu!FE#=d2HIR^ivv?@v9o7tsk>_0&{Y$cJ+6~w z@KaTdy}owZZ$3bMUm&JDl>z?-Wz5C)Pk8V@S;qe!%P#W&J1qM@$jJW%mCXL{wEZ_& z_J3IAzhK$_yYByA$Fj2$>9BGBA7t@wUH+3t{+<6%7`Yx1GYb(5>%S1sS-yGX97O+Q ztg~tEFTe}RH0`cDe{|0NXu8~M)kjfnr3`Z(E$bpEpi{#Qi!Z}a}AG4#Ge z4E&#g@EqTo{qF$bnb`j;5PsHbkP&X=+7AYQL!^G6>=K5!t_=2|PJs3tw4@~o8)KC7 zs?c7**p=?Wa8TjZ)K~II&Do|Jx=-M}L>q1n_b1=X;xJ7J3&Kc)Xb?N~AHbH?1>XL5 zky_`z`udNdD3AdEJ;S4&+B&b5MeNm>UhmkgHDLAfDm|7h{hYUcWLu#A2^7|+7>(Lo z?{jf5f=TvRaa`FpJ9)J?MISxZ$5yQO?TA6qh0hLWfJ1YPQJ$<*m|Zr3^q>10fr-WFy7{Z=u&zZY`OhBl zKk4txY+RiGH}rQVHa1SCf9)cdU7kLwVk-jgzdD|uF1zjBxi@o5l6!LHxfA4}$O4ff zN&-WM$9gghwNZ&1z6tPvI1)#3Fh`M5M_dU9{3S;l5N5fhK&3yJirBiys;Wzo%m~3S z6pxKnJXqpB2KmqN&mU87o*kzu) z<}0!l`96z5{-C?hK*!UKnCuK`5@YAU-`f+8FQU`V+~2m}LF&!|j9xvXkLi6rn>M6@ z1_cFQoa~%8jQ<*fM5Jz;U4f_Pq<&rC$oI(SWBn{~DgiWXanzorF5zK;2D1*hAw!0GGI2I4E1D>m|^L#Nj zOKcz{@&kGeorcwEC`(5KIyeS)+S(JdmC+)$1C~U;Hs~rbbNt+b-Uy@>Fnpl_f)-cg z6v7GyqtEv8iKTuArUtO47*Y_;CN~xa2nYSG1DUx;BLt}+^`bCt3Nwi(cuS?wmVaG} z#t7YFd{5>$%Gs}YZDpDSa9_Pt6eOf8Oh&KbdpCL4K#-;vo`OM2X^X4~1uC_RP=QLS zH>BtfdM=r%RtyuVd?wx!y65s6HN^oY>Qz09EnuirBog8P{)P}^Mu(2{*mm#*!UO?4 zF=#gH^?vtR?SQBa^iyK#xHd zN8XvWt9I@RgU#&Pb>sGNn@Xo*ry@_%$ z1EF(FSfGqZ!HhtqnsLxYuE=S7D750RVUO+FqpD4Y^l7^wtR~Q5AG8ekAB@2FOt><2 zP_~*O_jPC=U;D3wTmn$|rC1SxSRmh|TtvD#e`XB);(92VI?X_rLjpAtFhY(AQYb5Z?=W~IRpX>b7gD72?*4WyY_ z*h7d%LHQN|8kWK1$CA!PUHNIFRxLX7WFQKOg;soc z_8Tkf@S`~&|B-1{+ZNf_Lo!wIwAXvrS3wK~RWT(XvP`3}s!g&M{`6MEO4uuCDodGg zVSjZw1n0pcy^j*gC%4a*tuV~6u1#{)+V|e-fzxuqdf$XTtF@)2vaBt_rXfQjT)Z_S zI=XJ$1{)v8mWp2Z53Y7sq=y7jprZX{ogA9Dj-!$-FN>-Q?kv>u4f0Uw`|l&J+i{gM zYwL!f{;<6wPHa9N7dyN{B}WO-1jD8_xj&5DHBlQU_b-b(IKC?Lam}j~tT`KK^)t}Z zmUh+gGSl$y1T&IF2<%}>`WjNw0_p+>J!3@{A?74pJw}%v#ZYa8b6Au$a8d3 zaGa-@&P2PQ=p+r*wDnC)L-hqgJ;3{!?Iqk05)WYIC$Nn=Z+zq|TM6G|^#?%GiPXD2 z%~cb9u_o*lb^OhtdThSmFPoRMZZ_)5H6YZuYfk8S+KxyrQ(P60x3iRQ#=2|v4=(;A zFQ1{E!}`2;D@mrWIVLBHkI!*KiA8)C934$BJ*W7izKjxpNl39eD&;&_hhpHU#5jiT zBS#YD9335W`$Y9P-Vx{A$c;o7$vR|-dc8isk<1_b-1PjE)7C|WMoa&jM7{8#jmc*( zU*x`Ic?K7QGVd$;D$Ue?vq^C?MeEV)@^@K^&3ReAs>~B2-+cPOo@McQDQ(ukk2Er` z{hIk$$_UTWEu8fGeWxBFtjC-Xs~qKg8{*fDwiQ--Xxyp(9fmGIKf?V_(c68qN~4i* zG5H!qfl9xHn`-OQj#Ec2+4Hhl?amb+WrNM7CHT?uD09BJ(?=m+7d)1;ePuu0357a* zk(XLx8iHK?S?{vdFT;@WGSx@2foim^xw*N%UyW@)WPivm{%$rAe$8l>v(84X{`iwn z6S`totT11`LSJKh#+Czi-bF#ffAl--`?liYXy|{7GFhoaRA)9&Nw3IetM$r(KCmsG z^8gBqv&GpQgcjx(&)=*RWFy0j1y4o879wR2Y+=m7nj2@V|k zftVJ1PA&r?J{K(2L)546)g#nv3DJoeF=B0TIsIvc$Zv<+1t1nX!n72Z)p>fecE-=U zem2Q@7MpcMsEtgxwRH@st!v%@aZfTOIM<(`3*ny#R_EvvfN78^iv+-dU18<)THF4j@BvFnV{PpER3-H4KPhYVUC9f#FhcmIK>rClzTuBd__ZYMF7-TtI5`Tx&Ig%+4-sl1g5 z6LTlYmme?ImUt@vd??|SCLmWx-ZXi%+UAv`WUUtDuF>s2M=h4Wn`RwrFP^ z_(mP9{l4wRXt*dbhB2jEQ8H1c5dC*#yvcFb1A>M`Udfh(O;e7S1RwDpiZ6;$DnLb` z`8?5dX*;WE`dsws^n-jy^i@&kslbVQlEy?T$%0{}v{eFz)UO3A%iJb;FWFbYnH2YN zSt>Q@RGpN^3GqXtL#o5N{;JR4Q2UeH+Z%doAAX2lD-VAb7Uvs7eFI!fiBSE(6hoEsK1DgjprY@ly-em$ ziId)z*_M%Ip9JR8K$t}KtoDiPlI@ZCRQ*)7RMl7JXU~9#h1bAF3G=TKSwcQDb&bMN zu~%%Z@{W;Piz>gx`dr|cp@1x*DbYS<(p8u|fP1C(MIYvbbS{Bz!YRNV$LR>NDfFCh z8g$^!ksUJPlC>|JU3h!|;M26B(1)~qz#)9 zk6TNQ%$&#@vYa6=J>H5EEJ|q%OI;FwgPWtUEsRM&g7ZiEXw2D>Z(_{sFB;-pXUXS8 zXqd1Fw`br?`sxB}1GuVR!nL;~K_VJQ4H?rZ!l1^3E$txvddzdFz_`Mk-oxwy*h?LA z>eQfcb)VV~GmRaTQhmSNsZddK5(EB#Y{yJhYDh;Gbz^88rJ!Fog{aUmDHMj#K2SSw z4FOYqmu;Z#JM1okBTiG{xE6cDT~Tylr>uePQMpY!DuRBM7S!hTkPbZA(Xi`s0CVrU zEWI!=_C1q70kNiPv!$9bcwMp2&CBto^>+w_<@w9?d8Kd-l zWW0fIYT(mWV0unDU2(tK(CA#Kb*P&krbegRfMX-}sA&h6+i-Typ>XKL_bWNV!+Ow* zVbCFpB_*)bih-#MaNbaG;od2sIH_^T`mA0ve^q!X4@046_Prs2VWlq)gnM&QU>v+PO zs~8v;Cw_qeOQ09S{a`<@^voxtjs{oH__e2;J#4kxMVHnyB>wq>YKuZ8sddr(jqpa@ zFReB5p1%+Yi}RW_{9~z00VQ=Bf~Ok6h!-I{cy-QQ(L93=LvxCxbyz7_3wR;-_kUb8 z8y{hfwSU8M)dSv5$G|u`^b5@XQ@3gu=npJDR z9VVDtHoo{z7*o&9@}tWW9mn>aFcv+mcn-QvXpUY91LMv?UW)6vz4W2QBh7y09rrVdsPrxYw8!Zfb0{RZe>D@PS zv0LAxduL|+{Bhu_1qAd?>Q97J{Ls)ckjgl!OI=ppmH3dZeRa+~dH&zM@#1bGzu> zthnM^uH!Iv6g@0;-M^_vMKd9NO!k+{4EH(d5BBZ#47IKi#28VaC2@Ph~q4IP6j2VJz1_->zop42E9)k2#R z#;M;`iCtk;Q9VPUpb&aj0Qh99DR>MoX5y zk&r2=gl5U3Cszhe)aEPL)%0C)ux|f(5G#7*vNebvs zHOWprR2S;?_AIE5CAo;^O7N;voaX2cca*3gH%jp?(wy3^Q=LR>=?@JPQ-U9r5fHw~ zJvw*pC&0F*fhmEh$`Am&BuoP-ea3NEXyEZ^l<{b(B+O$;{XayW_4;=ML?<4TMT9>z zr1fpmyEtjRijrFQ%Nl+N-?{0MMoq)g1JIX`Oq-b~srF^*^fhI zR_)VGks_tRoRJK9$QF#8)8bfF#CwBafnUilrJv?%rrj(~UlYq05pMw>NE@f&2`AwX zBCo(7Ks2Yo^v+&D%MU;+Uy63+kaf`neHsrya1TIyg3pT|55BMbcrJv}C;Y05zMSD# zgRg`)m){`oqPK#7fV^2>31(xV$8N1&2>`zFJ&>_Iu)^D=*8@V^z=hXy?rR9I;u2zJ zr|f~E(#n!V0-+v_$`O+)Sp~K3KC1$CaxgM}c1rOw?O1`#RIQ}`ibTXO+*L=AC=cH+ zWMp+l2Z9}tjve6=9WIEh9gy6c!Q(E7StkUvW!{E@sGHHlE)2g<^{b1$>jSUEa;^^5 zpG2a+le|HQyg}Hf$gE%orcwuH@~J-7=@kMWisYOg{;pDBBEk1V7C|5Egyz9hsYf;+ z{ZQrsTd7AdUkCx@LG0B=LLP{e?m;VnA2OC7HkLmeBi&=nI&2N4o{Jb?kuG8Ysg z&o9=hZ{gD2!!KLBt7FFydxjTM+gr(6<&4yG_j{pYM(D4GMvAyA!T_eO>OW4I)l&SA zFYfYxl*wc5X01}l($6Yz{~)g=Qe-;yDT;TQi)KpDj{$UJC7%u_oDRQ7Uz_r`Y`ddj zK%hLt{V4G_D(Fsb5)k@bp7af?@P@VQ&1o_a`u$V#ZM}p~`1eN%UwD&*)Z4!43F63- ze36cPmAbfZ$%oj&CzPc<>7~&^p2F{Y$xeCdB50foECY%tZ6zCmaY}r6JAPZyN|Tac z2qn2-O{w67x?G6*^Kcy0W&ph1igWT1HdoiwrmkjgH6oUJ$BzTfS620faz{{KoVU}( z1SR2oaa3QN&XdK2odSj8*YFI=F)V$McLgD+7KLiGT)A&KEWY31O&A?pXr*Cxq7V3v$ozh0Un*yTI=74W!Bl@TTj z(Rpq5cQfWQiCTVbul0P4KrBk4cIRyc*npjMsCtTwx~~U0779=$ zk-bAE5}Bts3*P0pYryk+Wdtc{8WdnjAc~7~P%21Xdr{K?-F`uY;J>E?tmAMV`19VB z|B3>`FdCz#($ml!IDFhokutz6&D$0p z-^9b`Tw~(XjmI@^d{6bcK~x4CLH6G@Ag$hyA&P9FN!M{Ip7QZ4q?O^1R&C(n9s~#? z$mWH=rUdGiZ zDX~jX#XS88qNMMeK&?Vu8HNd5Dd06q2$pxtz|t{j<)nEO%kv$U#gckHqc%&qKS$%` zVaX#rC#u^}aK!d%xR>Mz(Ft)XWh!i}x=55UH7N7ddLt9garZ<>9Xlw57`yp}u1*X^eeO#)N;|C_z3r|6SRohoiJOr!;H~Txw7V5sJ z&@Y<_lDj<22V zt$sJdbo5IzTlU>Ocx*X7156es-(?O3zi`6ekME;S??EA^0}PVyWGV?$?};U3Vos0H zNk4~k$?iyF1*A-P=44EG6c^`^UP|-RloFxVdAp3RQ-NXEfq|Y?4b* zLaW*>doq>SUzHCAnbhJJ+8^cd_7wAY4QRIT%Dm-v+_9Z!W#w_R-1Yjjh_>(%w6>(k z3oDbPY!{MX{SNumJa z8>+9mi@sLz5f#(waLOD_4h8r~XA;=+Fm&}5cwC!mTsL6+x<1f>TM8(cQpo{9{~4H$485Mw79CbbJX4<~1f$;$-|_gFYM6dXurheBbbZ z0Pco$cPNs+9uaz%Cw$?#_0}@j68!#&91{MsC7bJ86MXfjz zX9$>B?^UGQVT3dP8gKyq$r$nhTV5FS0ZYo5@&UVCVQN4cWprU3Gvx5ZCSDlj8#`ZN z{3Qx6Z}KHdCtl}o3|F;o6eE^`Kf)Pf8qP#eyk?X`Z-_76ILHagcELzt2=@kq3Z4^E ze?cQV!uf<=X2|=7q5_^1wz!_25y!m}ik;Ed!Kl*5!j$M*NRYfHFc&a>L6{LbUJYwu z1oH-o!xZ}g$|P&?)wd3k7mR%Y%W6dN1~Sc=>>KFpNb!c(IN!%ViZ^APUkq+hKkG<< zvu=?=v%@>IW|0x!xK2zfi24S14C?`$wQivq;k-_)8?kL;;9JxO_{JP^=KIFT)Ft@F80-o^G0~&nFw+_nnt)?8#yfIp zuM1V9)#2M-5Y_Z4yCLIu(N&{=`8b1-&3^+XztM8*c5wGlMT!`q#%B(|b zMo+Fmwn5OWg|}hQeCH6-8xbA&)Ef{TKx+&M4e@IXA-@+nrV(~1-ox>bHB;#k);UHJZqv|fMv8yw)i>-EIHvJdgZ z&u)nCP3UfdzY*^3K>95lQ8&J+(>g7P&-><21O$E8Yn^{d?ToICN$t$8_k@562W&6& zcw;u!JO85k&29~of_!4TH@M#dKKr)B@Z9U&>!H8JT;SsczRd{46GF=l!4o^dVD|-` z4f+j3TYPsY*p-F75iWtDeW6O$!O@e{=-^^P0w)YcHfdt`TH?=JEa zMczREdbS5nd_(tIBHG-~)(Qgs*%LY+@#Nay@ z1hx^ZQ6GERPY>)~oP61D?Gbd@f9{dg9msJ*=8f-tqw&Q38FzW%dNGXfgtLWqL&rO; zKe*wM)g9(um;5cjeGq5sR_hRF8&+@l^GrJH4f;Sm0xt(3JrXYm!aX7{2P8lUh9+$= z`A2BJMgPxlF>LoljR5@@Ti>L1&$(+xzaP^hxI4%nYAuxS0^KLF`@+m8lw*C8lXgeo z7Q-9cVBhwM`7_jgZIY8@r}vh?8(N}1zB|PJhTj`{d(ZcYq-W6Yi6m|p$Qya|7T6nk z8+I)=ehv1dU+4)0i{G5#y;kANzrXzJzV}bL|82DItA)V+qQG0Eg1`d{|Hoqf-v<_ z-q+*l*ZJbtxzDS=ch2Yb`Jz9){Fg!gXD|Q96931`7vWzQ>d&3nUSP6Y4%(oZ0v3T2 zIFzx!`sr>yglZ0W9bLg+A6gVd*3y(yb%_ox5kI%MXT8E7h0bBs58+PXHl`a6NS2^} ze!D$2iv17j-Z@H^r`!ANK5d+~ZQHhOo2PBt-KTBawr$(CZFf)q-aG5w=iYhNns?@( zS(6njDxxwnGon`PsH|PJKVJp?#x+Y?i8{?VqaQWL#?i6|Hm{6tdE8YvX2B%=#y#Qs zjGW_7Vfl&K3%*wNUKq<+CXW6Ly==?cRp7frl=Mlu{tP^1`E-oQ--+dyy}f4~VA3_% z^5K)(FlF+Y5(&B!)wvMPwv^q$JSMU+7OdL);eWnEg$&>?{}9;+l9rS;$TnP2D5+YA zmPM(sQ&NV_E33D<^9kwXUOKX21%M*N%GTFDb800v0k0!ACMZj^4kpHBWNHtpGY!CD zZmQurY33(MSiB!dSTJdsO+Kn>H~hE4Q<~eWo{+in`Bva1)$>Bm(9jkewM^C~G;HZt-+&#PPQw$!CB$5v*!7eltp` zz#s!kHu$Y+?Q9=keN#_Bkl+jh2~^9YDUU)?PUBGDBEC*8bYh4_3>2b{ujE|#R58m;RCCjIC~5ye z9$BfDzG)6`v3kK@id8W0i&Z>|RV*$SIvJb%(bm3ERyB53#;urZD{H7)9P<@33TkqA z1jr@}TFOXFEN{%@yySGLQi(gv@hhOQPE|pjPGu}#wb6gz$#!ON@!SvDj2xgi$kZmD zqm``#C!N$ZtmfwjWO?emdaHJU1BHc&ymOSyz&LCNE`+lqlqngUOgJ!SlQ0>37#f>B zoB5F^d^ohtLs(cJZ*AFCSy&!J?ztF6>w3^x*%if?gL0CR*`{(L@svbyd0b0JVgP6y znn5gsY0bjExC^Ed%q5eMe<8A9FfcC zsF^A>cc=A4_4S!sG8Gpmm-|x9X?J_mF??aYzUKHUYyvXZERT!gJf2zEyu()DZTK7R zc8*3!7O%+}aX?E*8xF3VZw$7#xDz;XNoI_Qzw#_&!O*%z(HJl1 z`7HHDV$UtyW;mlU#BKot#?PQ((blc! z6&d+(xP-)X5`>Cl(kGLny|j`?4b=*Bf4bI{zvqzU>Ia0t|cWoI!SiC@D;WfgpjY2!I56%2QE{S(Odp8++ zsU|5K2PQD`)t)Wky51OU*RB90Z2nMYe(?g&KJf$ZRVpu(zHEC#U@2gAz*4Sizz__-XabewXIZRHjRscV9LA$oS`e_Vgu_LIqtKjt2 zZ=1)8?YdMcZx?QS)*#&9S?x}+5ZLm~k>mpO$7PMyT46Jtd zJ%g8sMOy4;lW&>a+fA&haHQbh;l}nsa}W@;yhD}26c9~@_cQZj!s;qnRN-JG$eCdWjQxhRy$`eEv)I=m}-ssr>| z`S#{I3gm;a%72+^uIm|z#*^4ItY`G;bZzv(6ZdvSJng3}4z?qQC^PuU<&PSK%nD7S z0O3{&?-MonxD~;VLoZ{5@s@Cxak^Dgpl^Ra2dhA0C1ctL5;+yIrtsA>bIu8(3HL=MDiI|_P*PP^RVKkB zMfJ+$HAPyVN6C*Z!aB(?hN@m&$77QywRF353sc&iVMAHBENME5x|+1Ex*ma2hDK>6 zcoF|6Qz>60645gM;%NQka*q0pdMI)ZS2-Y@LtdqVto0guy&>+p{0>rNFFAlk=%kMbLwM>Q(=%A$EnmxSfSvonZH^d z37FrNS_M2czv-8-YFdJ`umXbPzRB?os4kHpCjuuz`JIz0@qQ*@ZP^53VgUV1S$TO` z1JAZprKAvlxoRlhpU1zM0ib)sddK2wt9EFsI&w{_0~}6v=M8PH-Q@K`Oz)Q@?WxU0 z{_EVD0f|p}IpDUf}$O9r6Nex3Y7=*RK!3?G`t{s9DVl(LWad389 zB6lO|K-}m7qwGR%9i~V5+>a8+x79XStgp{=&%;9_wAi>*xNK9Zp`3ukJ8o>d<36hb#KkCO*;VI9yIvVWL_?b`C>GLI zq%S6UWo=`FE(kv#sm8gv2M_C@Vc0L>i|W=3l~eXY1iu47?OD0oYQ4khIf@h{YOpnj zl`!%P#TyzFCMQb@AfCRKA|#lbnZoXtV)*it2ba?BSD-{||NoOx47PF>i zZCDG7A5ihViev;+>m%64Gw}C1?%Bhfd7izZ=iELZ-41K%?cZ;mafByLvMJsZxN8WZ zXhld(IYKoZ+Uq;i)$1xot;2r=w|P%C&3%?=+&a6c%1lKw3rrI!~png6}gL z)VCZw85yT1+J-zh7a8n{MiUL`3qza|OCX%ZS{NIbG0P#G)u<}X{k>?og46Uw0|n(; zHT?S?jham3Ek#q#XJ&?-j9yHiMPO?ov=J38s!Bo+lZNvvLkA5i%`p568DJ9zDAaOu zE0Ct_F<=f2SkwiBJA{U~ItoqCpR~C%F|$cmZMr1uXkIUdR6Vu|XybwoU}YaSzPG-z zen)f5ntV1Mr)OywWEfeIByB%=W<+ouS{EX+yv)E;o7-hw7ybOp>YeJ6s@byki0#7J z)ob)*6q)63=w?Zwrwv6Goyl3M&@@ph&-yo0$(tEm_AD!?wD4_Ztr3@AlcT?<0QNV zt--0V7R1x8iK0F|ojnxzk>AQC7sJCj-NpzHpankX+ z>~nUNY(3K(>RWP3(mJhO1w*ynhPlT~tSwfZ&)Lj{O8J#zOQuZ7ygqYl-5HW80NTcK!EEQ0p~=ndcftlI7Ohq|3FLxJ9mQ+lFVX?DA*gS~CA zBb(*csjlap+(3y_;?uhJ$6FU49bx0{8lyRs)!63p?aAWC$jK3zF33Lcch*m(apjJE zkHTgPKtX+Bu+*y+*x&V_%f}hrR?0p&mC(HmbZ$A zxazeo<#Vr}MPA(7+aBDtUL?|QU54+5$2`ItS|TKT=>3e&MnVi6k!?u7@^1u8$Vl=9 zN)+m@k*&5Vr|KAfTb?P1( z5t^}9F)9%L0C@g1=pM2sZ162BO1On9s*+GT=FAmTC_0mcAPbAnFsD;XW5&lSp7*L* z1b%yJBoF=OVay*_)gIi>SBeWg4vm|Q^%$#ogJGM1c$$WZ55MU{>)O!!&nCZ7h!lgB@!BX@aj z9G%6U#tCO&ksH`FjOtP$87)(TKCOa+5}WW(k=6Slhf#+tYx_W&UW258me;Dzd_s<& zQ(@QU-tC@yD~o(X1pCIhVs7QSE77B$*HdfDx6e=C-_R|%h(c)5WUQ5FmZKqhdN-U+ zZK-yCzYquq9VXfv&$_y4%}N;x9&qh{j0i6+E}>RzuXcsAQI1^-ElJ#sbr$kBUuS%U zzs-MrA$T-?g1)EEeMz3|(Njg)qT65|qwzjSd`wPuOGhV1zk2(kR>!;{9zZ2W| z^E50zb2e{R`y(1d$|`H>(L72feNAdGLid#(g5AGt>`$=8Wq7zTWYfBN4qMfNAB4sT z==gV{Hr}ishG8DwYQvglB7s2WvT4^(_5+1p1U0XLYPLe=SttEyOoSc6Ls1LRezC3{ zW`)Lh+b>&Nb1IurQhny{db}>Qk-mC=9m+l)!^@!E zT@`CM!i3J`Mdk(DkVKkiR zFDKEVpS5Z>J~~XNrQ)f~U0imT)^2!x033(K)pc5vtEj$g$u zmBjIrVxT+}9=oK(9?-}4Jnuw9FiPIed;6#hTA5cSMD3;!D%B8HE4Gs_69BEga8n61 zUYk-Q|F$z_TrwgC{61-z-7+(q?~pc=-rAnumULOUn!g%vz_3C;0&(nW;8QozwzO#G z*7KTZSo}y?Jge0){tT6P+Hk-M$D+iJ3m`fXoRtLq>&b_RVu;PM0|3(x9MbQPJAC2- zCz`cMM#aVo1?-k2<_iaxmDhx35<}Ju#~@P>%D|3}el0t_UKr=AQK_&X>NtDKT zW@+EVdB~TrF2sO*?r0aXgJc~kD_HEO8KX#KoM{ktgy6E)I*{4f3QVdiCu(=emfUvN zRNlVuNug+5l_y?Sa0DKY$f!Oko|Y$nwCi@95CPkbBj3oLI-Z^G`hXS9! z<@APS-K&js^{d?*HC&%$+-LJU_%P|qoU8qYn4|kH74s~Al;#hpy48hAy+SoBZ0876 z%j{Y$0%NudUyZ|A%_VD|g=!4Xxl`(Ik^RFLhEAnHf)4F4YmGr&-)MNXrp8aiu0nx` zcF5=N7XIkyyHyuG@TA>ANfVQ%=$?!aJ|xB}>ddMt#zJg@k(yV=j?6A0@*~R5Vp$F+CEy_`q;;$BcAYM5hB_An;?#RmU-vWN;apzEtaVZTrAY_ec-mD$3-R{M* z?~%VuIf%g$XpfSr(iWvTK7zY#6r2zYNePLH5SyLD%l;c1=2f&8OLNIlb=h(*rkFILdyCt##xWPRv|6J-~G>FL`=WNV)WKagg`Y9zyGR z*+%O9$T!}O`StdC30u)(xlh=w(N)XiAmM$Qp^kiOA-34H4&M6I^mL8t*>3ULudr*u z+0^~E#idr3$YE9Y2jggx>=`3drC3t| z9LrnSNpoV!Q?bEPjGZwSn`96EYX%WHMBx+I(E&NdHRS+lSdl=A!PuSyaatEDF=a!G znB)qY`lIWEPjVsJ8hLa*%s}vf8dm}58S80gFza_#ONg5htkW?mqM^oW%w7Kn?6~92 zGP+T$w3wAdv~Z^<99(m7?Dm_G`-R#&-kDApC zgYX7Us*Uw?>f#Duc+LUZlg*eF>H{W@M({Tci^!n^1Vnv`R~zH*bD8+Xa{2h1t?uK8 zoHTC^n@PsUvRzdYrx#yuMJrw|&e?+3I$oy@=cXq{dMu{Btiz}K$8pOA@#RBLrO3NT2-x1 zQnWST(%^dTSW_aRw zq&caur5Q)KqLqwm6Ls@q*BdswfOwALo$}YOo?1TsN#zB9lPJJ)8_&ZA8<7qy*)(C)=6 zKe#$15J$Jqs&Fe;4QGtw{r8f}tc~GEg6Q#AsjwNnt{$_;XWiL@Ce_ss ze<;`pf^mm^;{YS?F8~el$32n_MZHJMk36O;)UqJOJ7o;^Y(vM#ogal?S!o+ZX~2_d zEY%iIRtT&*(RdbEc_!)DKs!9#JJd^%x9|$Ut`~k09+yD>?9U+pW&HGH@geYQv$%{p z+8P!_&P+?BAkG996NX$_V2sj=MX6KDQ_Q18OLz(=W*UPrbqWRHgCJh0$!YIZ-bdPd ztqHoPRLLTfXwLVB2(G_m+u5R&=~i50|stPKD(vu2N~i4&iO_ zLozTsx5|($ip`wTv?_<4FlOF01y>7C3s>{&P|wdD_vx-{D&{+jO_|ZA>sZ_|>rv3A zo2Qmh+^474a=Ul8j@Of4MW*t=tMK)zhJes#(2J&E4m7A^VQ zS$AL9-TknazL8w@>!kh;ob6V?(N!E{)(9bP{BZV;>6Oc^)RK-pk|cjL>4<3+4?Rp6 z9M?p#+eyS=VsTy!W76sCL*wHzEPuPCK3b9yJpLFRUjKBXo+Nqypfr@e6{~&d>SNU2 zQ!X4^y>Gi>XRh?Z>-P5=RQcr|8GTb=w{jd(f+{iuxL}*ZA~)fYYPQo;sC<5K_T^M; zze{rz=F_l$?V_|~+p{gXQoZ1huL&4bV(X;PzKYW&<>{1r-`_uuty$l zigM(fm&himwU>dEt9W~EX0GF@V>|7-VQb-fDR29C$Mi?e1`=(%v+D|tF)v3*i4-nMxXcvw6 zsf(JkDLXz8Mm_CF(dw6@vP@CW2{gOggAJS*QzWI@6KoAIgSd%~2-Bph&KNE2ZahSI#V|h-(D5nfHg5T$JD9BEeN7%pWf&2NwIZCI}Sdc)Em3!ra;1lY+*WOOPAfb0FKSUseJ`CO#YwK$H;U3*G})NXi)u zJy!@#6ObqO(knOio>joY5S|OK7&D0=KVn zv2fhaml7g{%|!|Yo7yGf*Z_@YGMNsSed((CS^vF^m^~UuPUhsKBJp6Y^ehlXUgmJJ zL35N*yK{B$H9_@}->VfvUq@7P)jdWmLI+g94VGPbq}xsKd>IWWB2_JWkPmipL`?TuZ8>7DQr)1-hLx3lE-gFEHahg zul4g2ZpMVP78#9S6TG)>X~SJbL1ULUdzDsn_sdp&ha|PUutDSNjNqY*CL{=4Y2jgSIC}m_ylH5cVTTzj;-42h2aU{bZ##=o)S@I5X zINmk#bY>hj8#lW%wV_obdA(ByGH~ks*#aQDA~VtlC5FoF_mnn0YDMI2+VgSD&C_DHK)a zdF#F2#8{De#8X0NyLi)%S#_j6ovaI~-gf}tq{WqO&m39O;vTi5}6 z;RO&Vw@35Lrm!^Y3gXid5}OrhTYJ)FR?U<3C2NEp*I@x!iGNnjU15FoCU^qK`VY~s z<7s?Xqsa$8I~;`Km*`4l2GT@R{0;{rz$p81M~>SM5rV&`#OE2k&ARjBYy$%u8!F8K zhjdWl7x`+55C_=bdA?Hc1R}pW@KS-cz%Q4iO_6BHOw=L_HR=B% z|0PA5jVV&&=!feVH$ZAOk|o0lND(>d&sb&ryRO9cB5w(#H-7%D`TU_4)xili6fz8l zQdcE_>DqzHxw_cs&FipG4E1l8m49I|{HvY)r`7!PA{`{HfWCvVh>f))9_|0Mum4Rn z#D7@ye@8?7$4vNdX3y|nQ{z9;5bO-h3_q4{X6a~b|8spyeMe&P=FxIY=5a}a`sy$ zBX$_BV5CD=a$wM(BLR`^gyH1v!suY~@HSt`a^;(UW`cfqWS@=Oqpn4wb zX*5te)}Nn}eRBciq+9hyGlFO{?L6RfD8LG;k0&g3exWu1(ATt2sMp;27bbr?fzZ7G zz8gu?RK&Q1hHZjl#y0p=n%|4rZshcS_ij&Xhy2`Q(nEYv1S)e|CMCP z*w|nf4GxaXZ7K%iR}*C6^A~ATqyP+M&4jGp|7E@?rc{kU4n^QouA@J;63b5nH$ZYa zSrt|w#2wK(UkLN~wE`(zXx1eH54UHfa8!QOA#>JwDKW-6pr9VWEE!7~` z#K5nJ$%t#F8uaj_tiXJtcHni~?1j(6D{LU&E0|X3uu<=>|##$u7 zFDqUC1AVF^eUu~v`m|a!R6X>!kG(fVZr(t=zq7EPba4Dqy;@8JFXg5X21F=^!|$D!~PS9Q~g*IgA7cjS|XQPjc>8U=a{Z}ID2TZgme<2Q- zL?EQgXOiRMvlueF!CSPg$D!Iap6OSZ92ziEFrK2l(W!*-flvzySq?1{?8NE>N&ruQ z1BS&a7DLM_L38GNp2XDsXwWAlAw6HKE;QHRWo?tvvZ6!=ItcXo@~$60wrI7*0vH2E<%^reK`~wH zcTTAhf2vU4vkbA;sV8RQ2YT#dP*DELyL$Gj#%w7B^Q23G0i&1{{f)gwV8z4s?m)$n ziMwlZB{g_x750;r&?Mr5H5BY;d9CMV7!*)YBPgBLMy^KrRW$&bj&HHMv2T69h%$GH zHA5ZHc7dH#eypR$MsEUIKxVEokFXU zWF})dXO5wu5LFUds61CaLY|jt-TPCuTW_A}+0PH8Z8hSfEHAY|LP0{sF>#dXZECpA}yq~boVR_Of1zpO0iJ0EZ zxMXo(+)@>$PZ3#*wU7i$LdCVek&)6%(^8Gq>`=vp;Do2Ms75c`QXKXIC7xXnEuu4Q zD2qep_9&t(Yk{#YkX!y`!YB_PJp)8vfer24Q7O z+v|UYEBo$rCKth^~jUlX*SsXtNDeq^krh8vP>m!(S03In4o(d5TLF~&B3%3V&90t_D~P){7RSxI0Tn$KOz@ZC=$vBN8hapdP4f$OU&1?AcraA)V?)UI7HNBhTKKs6f~n zFt6~3XGe>IP>aAESsk-q*!6W~2Hmx!>O+{zTOeblV5NNCrCp)vC~y>jg*DMfaVFQ5 zye7lVfpdBRy6OS6uYa;5vW3y8(SBh}+LOuEAsWLvJeZb+>l<7Ffj6uTZkx&W zqd(+1MB5Km}6gJGJ#I!Huz6OqU2i{Y(!iX+aY>L=n^dCq>*ap9IEcXF8woLI1)Tz9F)eI3A zbrhUvX#Akbt@)|ODaT@LRa(_?o6hx{47p0xppaH@xh>+CZ~IK}Ee*^LTx@7o zN@y6cc&OA5B0_Q$`2f@&)-8rhXl(?iE(D7pJKkob`9KsBvMf&rBafXaB=}UpoxU^Z zE9|PM{S@a7`IFxkl3hRx4KD$zvCkk^T#ecijs-j#3O5YLuDL{PP@&ebyg}Yw&Rxh| zgrkU|#HZNrs4@HMa^m`<21?ta&HB>((p-_pAKTh>M-bpJB{Vf9>{ZQA^A^=|D1CrW zYe4XBl+K#jwIHklulq-;o^w?9rT#mSOV~NKc~lLS>Ui8AvOHw1MUMZ*#Pte%FrC7FOS&L%(ysaq!^`=;Hew~%l~tE30;y>{Ah~oyJ>@F`peC9l6&h56~{pFAHvU&8#a{^=mSW1C1XCy-8WV@ofFcb zAl2I}Ti=qw_S>!!LYX;!TsRUqZZ{1ql0`hC4+tORw2?#C3>CmOT;}C?Hgr*(A#*AG z!2=I|KfdAI-vNQqcFZ&d*Ev9_hQF-|>j&9e;E4|yJcHj)wFPj^VkvZuNonWZ_Bhgn z*Z2lQQmFX|gkmgPf)}7%%A)36YO&gdv3Zbikh6b?Ai6=dd-P@qso_B_Sj&0ht&o(3 z7`ML}z<#9$m$VTd< zuioqRv#SOAg6CA8dtboJ;0LdRzfaNJr+i3Hhq-l1HK z2*OvezPE*1%7=l_3O`f}Zv@a3o%y*%k-1ka@jh)D0dB;YG5Qk;Y2H{y zI$mV}NP!Ge5E>Rh*K@H%qQ>jue z+?bQp5C@#EGwk(e(~mphrF?7t^PHhU2C7nJbG^t=`zy~!p4x2DJSFmNo@3!F{p-=4 zFFW@)$H^+UJ2x`a%pbLH5fMoY`TV8w#hA$8?-HK?Ksv{H_mju9to7UG`9F;_=0aQD zD&?1_+XhT^PL-r5wi-{oSGwbG%XeSsm2;sQjXIUWNtPUyf}h=|+eQXM791&&bm+h7 zp4=%qWvWATNPp#3%%49}WERY0G-|9Evri^$P6yA|arat+9zav4>#<}mb@Nv*W9BSN zR`_)CSF4^YyLYM=hm4yD+sH8PHdxBmsQFevXA<}KUD=f_{b5Lnpi3nJZTxYB7tohT zyN7Q9RQCsO#S!fP({weZo*MfCWu=0Fs&jkFh^60B1&|_S)sn?R8l#?mTu-2B-A*GU z$!ETM6NZhkff4Gdq9SWqUzRxC7`?6nbirCZ$v9J;5c5)m&|e4D-N7E^CVdL77}3`B zPcycRhsyN%&20P+AETner+U$#_Qbey@q#H8{;usi|4WgUq+hSPQHdd>A;K+f%()-`7r zDAj}hA7VENJ9yln!McwyFQ0lJ;=nc{gPMz+jV7|yq$ zzLUvOos6VQh+H_h(V18P0l*^kN8sq;)7zeX{m)@8oao^TCie{dV#GnWTBdoIZcdr; zr$8~_k;$1>d?5k9tYyHR`&KWW7f)!RJ5QeM={=U$4gF+HAgK48<^o_ljV98AqhGJ+ z9K8M;VkO5;FDGuF-Y@l$zO{7g*Uy@rN0v5K!{PX!P%;oazF7ZsSt%I1BQw? zc7uXaxC=2liGw2ju2nmM42J;r86H|<(HQN~M6$}TxmsLr^q?^=0I(E6 zVR5*~lrAtgd>p^OR-(uSww6*TYmUitVPPP>_=0#UZ!dbB@l{8xu`$F70&i5xJ6E_m zJR4KwT@!DrL7p%E_tHa&OZTIKNJr=OmZGCeMg|Em-v8(>EI5B{D8;um2p)7R-2A9Any)G;U0ri0CocShW`m?(uOPS z$V+kJJ(2TXdu!@Wx*47C$h+Xky9t}>-Q#J)W#S0(36S8;$LlM#4VHU7|Eynh?Kks$ z;vvE5RqrIHe(NkV5Y8ZkmxiCQ1+DLdRD6P2$@>6diE7{C zYVq2^_t(3F84cDFV=MYfIPS{0-Pe)Us123B4HfZ3hiRr$P2gD|2(%4W@`R^h#%qP| zSs!sTglKcP<>DCO^*9dC3xxj-!=HEgA^$xl=bg^)Dj@jE?Dr55d0RU(3jy5*|2MyG zAR=H}c-O%E@(C1|S0c~!eDdl24I!UyE^Wgb5L#6+Ex?2D$OFj8gD}$UG5&0~O{5yo zm@U*Mgg?M$7(p8%vLorxd}a#2ivjm01oEc1gN7+sMgQZ2ct;-KuLk7o`v>ohe0~FO zJa|ku6FY*Dyp))BKp7fYOf5&2ODtvg!T;Em)j($2&GsnWET{ZqB< z6&?)33pc1gMkV#9`YW9+p8;M+#^NnuN5J-z{oQ&LB4VZc^ASYEwjo6;!s||t@L(X7 zgDO~nS`X_Dw_5*M%goCgljlOR=XD1}%_%mnSYV7`)*8~l6qiIPHm+Pyn9-0Ss4gRczd_pfI&zKuj{BK}bw823n%vPs!s1LYC64 z(YY;&BU8g;g#O^st_g+!$nRYV41eEDroc_!W27v}nVBU$nYP;X>A8%`SL9RAZT!LT zkm%g$J&8A}rFm03UmhrU;Rki58PnQy9wV#|b>fNl8kRW_gaoG}E= z%|ltx(9QAdJE#!93ZUr`gngk!7^h)FXMdpda2Vq8lKZ*YGre1y=9B=T^xw-#VxjKB3U z69{Eyj|cDt9IHG~i^pK`q$DAVLacV~3Xsuw;ug$h#SvmKQL4oYV+98}u1*TvyBlfL zfg5V+SXi=i%;f&$%;b4BdCEFX$Bo#5YATyM#%5b(nC2F{_F782Wi>GM36W(VktO(u z!?GaDW{%ExOJ}3ZqapPc@q-a^br$9E-KOaV>!Yj(YRZSscd|(fOO~j?u{LESwf6dI z##UBNf2H;>;fTH~$~L0VB+V_FEIz>NoWadMPMuwf)`dq|E3^ZN8=2P|HH6&SOH{_! z!vY)E=deo4HW0#YSf=pO+|o@kdEkY{x6sCS(jNc0be|)H&+u)iJFrq^2NML7Sl~-y_dB zRJfV6T0xwY70sI#h%qQNLr8*Ef=pGGtg*Rs9cRp*HP#)f=ODUgSAmz*$=jDt_`Bt~ zLzSaVo-qclm_s)$91WPdQQ4wpOIGuGL)T)RP8}&1&npNmFgkMA;9=ZG>83ga1*<4K zIE7-sa-)|?e(%DI8@d8lQ()<^WhjU3D3dfjsEPHbOqiUPhzDF zDL24i7p|<5Ai-Fn zBo1**K7CXsFXYxFM^TO4w7KF)aS*iiaT@JDM;P%;Wg#y6zC2f)Qn$!R&2}ZEtc@ za1L=rZ_q=;Qk`om(F5?8K0gAm0ED09o5Xh1H8UjB44L+fK)Is;81{C^9Aze5PmW_B zc>Wv&V)P^(d1j2h3WvU*`YVKrT0(XVNckP2<%oi}KeqZXuiG9gKrRn!STBL%TL3*eM9=q*7W&YR9hBm`4;`)G<462Y z?G=?muE;Y0IGAi(k1d#DTMu|F(S{D;aEwq^5PK!O5 zkzRm3xZYJOGIoqUBU0iJZO9XE&eyb@}o_-=3KP4!+V$UdcuB>qPLx+iew=wt$(SSR4nuFV4 z6G}Y80vXjz$$Cw9=xH-0p23AF`JTZhIJEs*hl*6gT!)HUfv;o5Eok?N zvNgX@DYEs5Q7E!^5U3P*dJDO_pu-boZP}B^vUebv$V2RiqcvwLu!fY?im-;RYqa#= zDN)IB_c3s)`v%AGwZf6d@GFKS4&jz|5Pq^fg+s!Me&aFGAF>5yh%GmbDo@|<7J*lA z);)=zJ;TalqAR}T2>~q--HI@KCR&wP1J`zu_5jT{FR*HbSUr_$l~_GiYWY|Lmp@q# zwpuw>Po`S2XDII;$D!Z{#4;uB-ZWPi6e|U;0pSuQt^pzo8Sb97rQFj#&PKt-aA%A9 zYV`Y!hcWM$zh(lgE$>%OM>Lpi`5h0=fYsQ$Yv?fSzVo3Mmp^C1^AFmhq$7IR^+WYT z+zmJV*7VSe$S(Pgr)h`gkh{Sk{|=|gApQ<#%{Kau24}c)jB{mZpVT({4o2Z6{0^pR z-}?~zV&^vARn84eb{GH9iYqcCvH6x2=X!u}Z2ix0{@D5pCywIQ4^_4NjwNf*#27bA zP+>LXxK`K=iuUG3xPiiEm)KJIY0tQU+~XD!NA+n>*;4UokC`j?VvwdFq4Nc-iPEDs zeb}Q$a5a4SHlYsHX2&hR>yH`p{;^}aS&c}LXq zO~xI^*6}TvtBxD?`>p>S2hTwG7!KCXEq_PF#gM40@M@%>tMY1Ow3{bdHF^6jg!4~E z{*`+%WV(|70VL}B!LFnF8OSYw=(@&4{jd)E~ zy^GmV-VyAx%YDdTQKQ=CR6Lxp^ZSeLDoANdNZ7=nG$2;^e{r$Vh=ZjK`_s)jyvtC#Kt@sp7$u_>$aNi6K?oHu=78ju;yVO`yQgbgHFNNi*OH8yl=YU=C?n2 z15Z7^QRn|j=X9Ul+Opr*gAYE%#ox3=|0I^8?gt;hBE_$L4rdrKy$~~jq!?n1xdbV)~w__K`a960Gt3sK&rVpT&6yPA66{QTv!_}QC-Q8PcEVD_py}A z;PB}1`7jRcHCZxja&rEOtDEWT?bl~s(u{9R;Q&Hi2vve3bL=B*{G+xs_Q4UD`kUS| z!O@-yPrmV7IvkxFC-7mviYB@=IWCERQ{6hSKu~0#i611Y-wJ>L#Cu_;E${=lcx(s` z*g$1+%btC!XNTYwpRk+ot9hwS$Cv$U>({547ne0DaUfSiZutU^iMbl+_Swq=zlr zyY4DVJo9>7CiOx29o1`>o?e4p+9lRI)3erT--Tr5viddB72W2kN6dyOZbOIhnE!8_ zRT2-OC-X`-W1_+aQpo!;BgW8^$vaHoYTbn~`g`?I5D5G%Uq+M#xJW6sA z9o{Cx49`4o%i&uXB}XMkwG89W_gL4Ct}ckjTQ+rx42u7Qxw{OGn`saSpTsdUGcz-c znHgecW@cuHnLTD^wquIfj+vR6nH@9UJiB%KzPtaetNU;tu1ZrpcqQmf#4*-|T4GuG@1*PBG36R#mBmWpyyj^J-RGN0z0 zCShs7%pi_aP?MN6V8x8dVYi*b4PI&V5juOOEF;qEbDCRShd<$gcQMsH#r)Wd<1_o< ze64$HI5{FPNWEI|2GzG<^y0RqOuCl!IGS6?)O{IG6G7+zJ&V|g9U#(QeDgD0#2lKK zfbxcmr@|4voUtw>G8>_^&#GAw6<$JQ01Ofyk1LNY1s68#l0<-)LW6_4Ql2JR&$g^|CO#F$Q~8_x1ZM-8yJ!fPzh)D!Q1> z3{R{I8M6MnYAM11P)HK15+)0ZUyv%iR-PmgdbkZK%koP?x~*&s>31qj$Rh&zcg=w? zY{hto#uCb-oId9k(w=c~_@-c&rb~0h^sQu^JQ(xH+2b%Sm&;Yo-dI*uI{qYlK;wf+ zr>Lf?@P?G8Dk{CnzZllobsA$;ral_91HYDzZd!eVMv;;VA2f(cA|mS?=1s>DdJHFF zkfRn-&{fRC;z`9s`b*tI!zXs(kh?k1ghdS`3YOuevY_oe<1o`>xK2j`$`05F+_)Be zEx9C$l`79UDm9dN9pc5fG8uHXn#|{TbaB^yCqiG@lkFcaA5K57VbppZ?oMwnglxJD z)EPGJD$aU3SpIc$+T?kabY9Dvr+-grjL!C$cw)!RJ$vagJtQ*vIzV^8YT4b0N#SuL zZ4@*lYg0dQ=<3y3Ko!N&seFY_=w!#*X@HU?pPCBMfSPinxt9&C5TjDaCy`^7p1{5V z=wqL7j(y}l!dG#71@Adsvc9Ox%P7O{VB%LV1=c>Jl`D@j^NXDVZ^0!9T%`e95GOE4;er7^|yfJq$+eQiwA`O zNpUG=x?(nr$sW4;P&l9DXs@Db>$S-ZT^<6T2$Sx2{+pV&w-SGsPC0#I*pb}alb10_ z$TkkX50vze=9;TEwQ#XI&drp!z${eb2(bqc_1N(Zp zS|bnP-Nx3W;s72YZNitL~?%cJ!%R>m;aU9E23Ilxjbr~8~if)Ev{gs#(&6JBz zb7;`lmM0Cb@|Eg1)fOO0Wk~3ei4*r;6pl2K)A#gA{XLF@u|aR_zFnTYjsDVt*pBta z$~!Xd+R>oHz(`xqJr+Ko`FnMqli}V1yz`q#!ApWGJ9IXMAp`4}2;CwvsNa#ob_36m zbZgkV$I!6fGFAn+WKr%_r#M<3-OmzC&oX8lb5R<58rk`^reYN~w=)g{>uYI8hj&;t z;6aPmmRaL{*(9Uq>1?w(-;lgFC9CTqZ&>z1>hxHlJ+$FwuP$IY^pvXhVX5!N#$xBG zj(XxhaUXntI(Z;Gl9ya~q&Ie#!hOJcBXc5mSNI@$NoSa{Oh<=0U~%~+f1Fc^OWD`W zO*M~&g~q-9M`g_zKc&5G3iUV!ILBs!9m%R(e_O=59m#kp$p)94XnTYPXF{fuJefE% z%@kJDba*^2z6Arkx_D(|31sQdQgO`VBV0x{T?1>E>Un*mj((rk4&GV3PBo2EeQO=_ zE+IYiR&K9`8@0dHZl4(Fue!PgOlS>W#ss!ih!J0XdDZG#{NZBqm@sPYYVMWn=MCxZ zj>M%@oFw6R;G*ft{PP#D+@bLP?qXPL`g-LXN%7TbWSffNpTu!0V#TCIdr|L?J$Qr0 zdQkm9j}Ui~74MY3^@inx9&|h7>z~^ZB-VGUt`emXVhLo6CpQ68OhA*OsE1jhU#ae7 zp3+>!dWq+U>y@M6ZbI~CBWlmePPgQfHr!fn zcOR*dpPnLw-4@T6ho-r#@)wZdJVp3FjBR_V6uYT@T<11hD>r&t{~$ApjHgr)5{~*# zQUv9hoTg{HLdxzqW`XW;u4(>Z9N)GSjTzm5aVg$F!&aUz+vhyOgNL-Wzbgv%n4$gVA& z0UWd9gvpA1{+Nifv-jGgoutG|M&@KP9Z(=88TV*(FCV6<3^pQ$O4I@C?Qtnz8tOx4 z2pKNa7xlzJGbUIly?^giNtn+kE2FKHuT~d)Rs9)RA?s7ldF{G6u;c;ejfJj0szTAV z>HI3Z;D1dmS5>~}A)!-aAIWNRcC6RFcaVLfz;8(8&ZRdqAE4%IJ?iT8IZM;mZy|iwlNsJDFg-ybcC ze8>#O;A4+KU9RPPFnV5OJ(JU9O^`!moefZU&N>okZmIFu>1ciIudmJFK21>FtHCj6 z#pX*Wvs2u`Zj!4hIjcZrojPsbU5=}q#FBkDdfxA-6Ent{#P=T@$ZJspkU$jS$0x{X zq4<*}_TVKzNUA2PAWK465XJA&-o#wfL)$==g_lyK zZ;(|`b?_%=9G~+iZKAIfQr7e5+fO$i4>YpZ9Pw5hxwYibi(|+9#X2Ic@nSigDFp^+ zd1^=%gin9QhNWbCqaaba{#Hk?QN=%>a zH76GLVfrie{Zi@wb-&N%lu96#g!g$MD@aj-plD ztn9c~;-BwyfnR1$=PGsi6%}ONnnF7}GrBuh|G@L5gSMQXYC0K-wPc|Z}^}2#AcFfG zs&|ZO(wxlFFf(h}V9gQ>5GmCjz`V;K=z1V*dWGAU&j0Km@T>Z4?KjB zW`@8*0+157QGweHtf5m8VN)aN{N5(b8Q$u3w|T?9sRecvUZs97MOXg}>@Gde%R5{AU8v`lscUdV0%+AIeFg9<9S0Qtl{ ziu7ghBt4G4v$;z8=@s9gO;ur}rnJKPjv-+anci6g%ewHu?|TuA0a{hEPINvqMg>-i z%n0=kflWm~dzACkRAqV!j$MpHaf4tx!_|E#4xSX##bNn-yZf(A1sE%6G3u~Z0_K3& zIV=AR^ykJKQ>h7c!lpHS?)=oE1)#O z*|g$*VVlx@S*-P^^<;bc-0sKIQ0=JSZV-gJelz+69WDbKOPj9magTOny=@VF-QCxl)>CzWO10QF{4an` zT+9)QEBqKoT3gBTtMVTGAB)77A6+|(bvZj-5sTc9WLvUl!c($aFbgoR&|badeL~~n zrOrWxJ$3!WTt0{Jw-o84^~d)o^UFenW_W8cW*5-uG3~NY&mt)b^E{}7z}v6tk};O4 zv60C7*HX;&53B2MvqcG5e1X8(E_NJRQ%fT*Z8H!YK$SpxDoWPf=v@-jX*N1!PD5|N z&o6<%uW#pXX)jw97k9zSD{mJ$q~Jgsz~j$-ws+H~({eh-lR4U2Fj5i);C+H=Yt-(a zts%q$?3|5!@Ue@#Z4B)MmAKpM5nG5!y4isP}-Be%R3* z^F3S;j;!{quZD1c`w-uGgs=u5@aXp=`Z$BihZrH4@Y%$%K&Up=2K=S$!p1jQt{C)! z1k7XO-$4%Pet8#k?^J7St}%W!A4Qki?dA3@MD7|M8kZ}rxG)^(Wsso|59L%?#f0b; zr>x{`#Z$cZRnt}c@Zj{|R|f>pzWDqZ){fjN4`>^+DMw>U&htsZ$3x7u;1|na>`HgH zqILU!(_K{o{K1okj1eiv1q@3BlnL3;=D`gE)EH!U5Zp}xQF%#Gc?}ZZvvs~_Bj}|n zbxB4MSr;2UH$ri*d~?IdBsyYYjUb^!TCv=;I zyB03#(9_@4>m`K4^<&fpYn3rq~k3&=0DcDFr_ zC9h+Gc?s5*(JazYY<9GvbP#8}GGt!7%s95*8G;G0$WRk_uo-@4v{-qG)UKLgw%ev7p;E4%!t zv~c}O|5Y(cWx67S7D^>idcJ&K5qekLF)0mgZ6LUyLYJ39DO|`g&f^E#K%<^SX(S)$ zjVX?(uIDucF)^8Gzkyr{zjwqaM7cRacey4QCG0IdDVuj_xw*3H7>%EcifldOyawF+c2iM>Ez!3=@4!651y{!OFmeLBcZ}Se^v9tk(K-Pek0ZAvf{J zOehJiQsKw<-^_kJNhAASM6MK7BuVnsMMaVo?ks{ew$nuLL_FRN&sbmyFu=E!yPI>a zx85i5)dwxlP-J>6CZB2}HfCJIAj{)L<5!P?87eLUh(($kh-R&^OLAix%NQ%7p+FEx z>uA9r9Ipu~@%9$VRN9n^Uci+p+%>%U^+0+=DRe@AA{x)l-t%km0Nx6m`24Z_9Ijwq z6#b#abR&mq1!)7VSg~}@IMVJHQq*u0I_8o}OT=gsI`{so+ z(|3TNOs`@+WXMT3TL4US*q=deR$P|mhJ#CZaBlS2XwlF4l=PH6Xk5&TI~51sU>+2? z1auJ8@4e^JY&+}OlG-{uHXbu{#xtbKuI9Jeh=zV}aDa|}V4RLSxO?7NYR0l$Z^RKi zAX6po-Mnp{a)BZfk4v)6xjQYWn)@YMt}43I;xb0kd|-b+~(IAOV-``d`>;5F;w_1)uj z{MAZ-!meSX1q+rgR@r%p#u&*XGUMFVW{E2)=BT^(ay}`n1krlR9WOZt zueg^vL}#nFjCgZz0a)#}&I^fk1F7yDbJm#jcz%Davwh6FlmH}$k$nasnK~^Kmqzx9 z1H7g>Lk1)(<5Zlrzbahq`YaZ(CfHP~&0?)`#Fc3f>ku5_98^aZ7OfI@v5?9hdR+rObILwVTw>$me2VNzeadL0zz}%{m7QC9DTV03hI4D8vAq zimx=SBT0js75o)PoTY2SI7yJuN!CJKhP{io%Qxnk(yZoOlRv3>lwI38&7`1r+%dgI z;4}Aot7+?R$>*<&U!Mj)pt*aEbYj;a!$tNLcQtQao>AXZS9I$)jZpCT4>^V(QWC0A zw2WfDbzjh*x}l78W{KWf$`_z^yP!ByGSro1iw4dF>+G{JDmEt_r!tUSlGX$7ACOF4 zgDd*%3T1^Ro1i+)?C*U=>~h-8rrr)98M3>&Y7ai5)Oc_I)F0C8{w*q9lFRbwbb9U7 z70`2kh@T|<`Rc~^c&c67b<2^|%dGo1BzTu;_&Oml0{5Ox{;#fxCA+TW57lMb^@U6L z4>`Ybw#s?!o!aq=JNe0s^Xz2yv9)dcn=92$(|48o)*aZ?^{_*%-3J!#KMoZ5rfKp= zGw$$L?fh;&mml-5sO+dS7Jr}atdd3#QSX@ma^wbG;H(J~(9XfF19UH~hI>a1=7*s% ztwX<xNjetH>Ai_&2ePXCF1cFK^*C;I$duHcTZ`*w&v#knzu?d2l&_dSzQ%g=s^ zw*s3x_Ky5iPFH=)e{UqA*SOt{?{#<6m$4q*4qZ?mDXb?b6;&jvKAbM`mj+EN8f6q_ z_?T$&V!@16;~-tsB9xHGoeo*v+@b9>lAJtKl*tUj^SULNk04KaAc9GhUbCh4LRdb-gut20z=CqJq{T3QDnm?F1Yva=DSMFLn*AH z-YLIXSm;Zck612ZR;@`M&H0qBqYdV{`54T*PlJ5rM`TKsXfRQ;E9I3-tLGL@&fr`J zpEI6UpWB{aoQChZ({tigOtU-55< zgnBz)jjiE$^B)eMEs8p~ML2LGpHSS+N)WTyVj*8rkZg!@@DN+vr^+qui^FrzphmBV z`EJ=DI)m@Gz_yrA=gqm-DWK3hm@!5s zR3`g?1Ve)A_hMB!p_uXTnMPL}a#ua37cbY~>(-RE>9-R)S-LSeUK&Bi(Nj=c%fC&W z6V8)xKtpeqipgB(+&;^kgwY&)6V5YS;{v&&YS(4Id)P(b9+|UN5xZXsd>HaI^}dzj zZ-;Fs>3;1H^J~sJECn+Du8X?mdsE8?^&LWYAB?mV*Og?W(x+&?scUT=&|%8Pv1E@z zKYWRnY*`WcPHKkm$Lz!7&;Wv1o+1d3Qx*?v)-Eawj7YY+#Nly@tK>9u&@8Wolpt>G z#$#yKG2J%Tql23NcdGn&=O55B_kzL*`&TCIP+RAQqN9#<)@nX-C)jtx5jCWSVKsmZ zh6-RX4|A2bDOK{P730lXkY0$aA)`~TcyLMFq|B{T6Su0)9SM;+D<7@zXtYGg2ETyc zf~tBxCLXhQJ->B4DLi{?-FlacAT`g)W7LInX>cy~ECj_VP860*bvFh?!HTJU9GVOWXd6IdddkR;jjhf9uwVOTjbZ3hp z0A~3L1kYB5B8Iz72PEK|yB5ALMiFaTP6 zPD~ym5@N!3$u8t~@s4&rzL;fr#Cjg1Oi?Jz7J7)r5m#Jjay5Qm&2x);$WxnlW5ip{ z`ANFBG3%I%ah6+)sb!aG(dsP4GwGWl697o?vkd{dJNf&Hd3qge3-2SFCe7FsRon$? z2$4rYFh=7u-hI;P4h;=H+~}i2D+k!{zyoqXoLnCOXfJhL-5Za@mg>*GpHP6)aUmR-JN;gfbQ= zr`mi~0T)oY>HiWzG^A8w{AAY%w8U4_FAo)CEB2{dI5iF!SH^cXwRq20+J6=)*14KL z6qVT-j;LSvj-b7LNg+vFYM!?_4(7F$RS*5z#*9^+DPA(8B^UGX&FO1)X?m${VARNf zOR?F{2cr$E`V2kVD%IMVs<{vBW^4OdzDREug+1tdjEyl5y+?x0S>K;=t^&I)HG+^* zM?oT~VQF^pcDyLu)xcle(#0X08X17iB2#lI71?|PI#aW`GO(c^92iy6l?^s39@NQX z!8x{}S8-Q~EAHw(>Ud&&Ve$|s^Eh%Ul?|3n+)zMqXqynh*^|6ED>fiXvQ{a&U=axz z^S%X2M96P3nI`I8UtZ!SNfl{idtuxn=)}U$UHCycd;)iKU-QnP1;-ZtPSYQY&WV#s zgRv1+U0H;vn!eA@=j)1Qj2|kJx$nb9<^uK7P|wy&LEZSVpvU30zuoCkjI)= z5!XcFt!;q%4w0-SrecQgA|4!>`>PR&=2SF_VJ}-6EW4PBV5>=Hvsq>ncWa;}4xUNC zCf<*n0&X*;&xZ8bh!CG|%&F!;Jjww2_StxCAA9Ja=Q5_u7}}Odh32*18C!=?h8H;; z7)cY%A#jWzA+_qQt8sDkcbB94JWb z>V}12=cTeu5a-moo;Sc~jd2wpCOcNhRNqnR9^KY2h8bk}CD_scT-i7;xwRLuWT)*^ zjV`+C@`Mla&fv6h5vDIXG^bZmn@g$|a;}uUIg!>2hIFh~hc+$4poUKSF}R#ntCH>p zP9tnmJ*QFSY1Y?u$JdRCFLEOsb{|{{rE=D?I}^$Cm(u>hYV{nmR31G)-Uh--%R9M- zB2_+r#DY}uZOClVA7Rhiw~$E(-cLLeBgEL2|@|eyrMkVmF6SOYVVQpdPNR3 z_me6Q+0SVGWS%#lQa*;S4C<(KD8BZZIgYB1q~_eyr5n)*q8UWbJD?|ph%%@jz&w;! z6r6;9Rb2=dM;kDS)&>d>QgIS9A+e+P){P?dy}`5?5#@k~f(7IgdHod5AdeIY4}up_ zj31>Y|GsVabwJ!J-h|0pgdM?aIjp=Pr%lsWLRE#3??|)83CXnW>v!CXz+Z)08MRnZ zCO)xSJAa+sW#V=KI$o+`l{!J-CimF5^CCdC-cM5K4TR1@m`G+?y zImZZlAMLla^gr;~`)=PcwcA$-fFr$2*TqJy--#@!>=i$v*@DR4N+T1z&Y1>OW}zum zlw&-DT1zC>Y1B~YTlX(a-o#mYOwmBoZWEMjfT=p&7)G#Zr8qc5sfYA*|4FTf@PGu%%UU(>iS zyr-~xb2BlYihMVp!9EY)5d6>FQM8M~Q;UPFI0TlUO^y zk+7(sDKW-i&Y=Ra4LL?KmYL=7l3b*elfeVn6be)B2H2!u%bc?Ycy|E&tEcJNy{N~o zj*3J(eKpV!tlK})Qc`;tZ*^v++al`Izkf$2bc^}TH0(1ENO6LE*=;omV!WG5eM!0j zZA}e4zsUwo0bh<19r-a!1a;i-Fp!I7QmkB5dCgUc*|BzyoDBOL|mKbV_;`z;^ZQt zXJuhy;AG+iWgdk8FcC2`fqobio0UuVKVyJIA5#`k*gxjae?x%S{830^ttpB)6|05W*j}`E5LKhng5j#li;sn(N>pz8M zXC~6-;NV~Y09cs+VbA^-%j@6tFpwnne}7k(h=YrW1Mu&p*Z(BGIEXj_ME`|+5pgjQ zY5x~7rc3k>`Nj5c(Ye@(v{_kM8JIxz%nSpjt+P~Rm|GNdo z4l2n18w-qy^WS|Z-Gu*Uf&G=GB`yM@MTim7Oh6)e=cPo}MK^3;(VAJ%xCYK(Pjz-> zAgemtRYB`?yh=48dDvGyFez}>2Iw0yrHC;viT{kbRxv(GE6Z?hAOAWy_<%|aGdTbW zXNKUn)1H)5^UHj9!uom;!NDG^g?uwK-Q z!b>>Pr~rqWpSW0}Xdjt+>?V1F@zb?CEW){-E0Kek{+Z&=MfyQXTrzCG^Qs3zhX%n7zr4<2t37kQLaUn)QZq~Be`{3! zb>#omrhpm%S0fjY`9;L||DF8x&-MI2<*$G0{l8uG9RJGBf5~6$>|9)+>;C^q{$gig z0{r`#aq;i+my>t<#>rjIogDW`h>I{0bci6?1d1T(t5J|>P{6lHBtdY_-e{RYgPAe#twV+D557{iDhP zK($mpyW;!z0P!!_SUhzg8}lTc^o!ItiwqVYm-m*nLtjL+d9cYf^U2)0A9kuiU+%v? zy^qtT93zHoKEwP{0}GYHr0?+fkTKuTg~6Hx2ih~_)Ois5FoE@tTDLyUnqt164yj^( z1?z$^3I#MAGU{q@+7oPR!KTSMn@y$NPs&`ZeVP51_n8G~FmD;1Pz;a-i{~`|NGwi0 zXVwQFzWQb|QVeT0>0$L+>Hp0FH=y)rN~7(EW&z$8NvHt7mFVY&;3OI^uvy^%okoYA zUGgd@_isfRM~pgb-i9AtGi!m{8vzIQU&zt~cfK3Kp>Wyb+~8N-Kw=5y=c6fq@r=y^ z2S-Ec?}Oo*@c)bShpWXJF4XeLvu{e>lH{PVRI!NaZt=yMkyXxJ#orz#Lv%1W7Y*&k zp|r!{VhWd=anWFxm+kRKe9?jlJz5&jJJ~7VyK?>=1VaHsk}y3)`mMyEzyi1B9TUDI zTp!Cpbz48@#K!CaHWu*)LrnAk;9o2y#t>#k z91Mdxbp6R1gO=}MZ!&e^M-2)ee~=Nyj zVreAcYjO2B`7M2B?|ugWFb|nqAW`eAb?S$Kh44I+%yjF8SuXc8u$TF&WVu zmDxZrAtIJIenWRJb%fzrEOLa#%;Sm~D+MaX!+Ya!{y{K+!Z2ho+g6GmB$Mp{Q8q^7 z1K)HY@ZYC#eWx)y6+?@$=#?-Hpi>Nq&5XCH?a$JPOk4pB18{V`e?BE;B#6b08O)53 zF$|b7wn^xOYW=-F$qt6{3gLXGA>Z?jQ4S3_?))vIVhuF{#5Ab3;pn86)^NE)w`W~o zk9Lj5dr;`)o89Xy_R!N}G>_r2CJm6@w>*HDjtNku+dZE(Sv!vF@AjL%+gm%I8>Eb8 zgr&k+q{0R|+pKTZ=rwVOXr5_lpw4u&~Nt#o|@pk12GLH z=O!W$GkGl~JIt;%7lI+w;LFa{74;UI6)dk3cQq7idxI?e^vF0R5Y5eh27T?GIva5@ z2fgU1&#pmBrD4S4he-qq+LE|9+ew6lvT&@pcnruXE@b^lZ@*g}4s0xt#6Xb)r%IOaVd^TxN9&nsK2OHU_pCHMMvz zu4YSu2PA6X5BrNhF=!OpQjWGHNZ5Lr*Ak(BG02MERa)O3HAN0>=44>;ky!d6L-H)5Y9B3 ziIVW|9V(I!xT4-$-b1(5=kp7xaRAZIIw(8T%ReS!=Wl@}o?g9p*f{A8W_oj=gQ$`8 zC&Uy`9VqBS%M&hG-DRfaOGc@P8qGG2MX-82m;pV;@x0ged6$*A8`W#^Ypp`~{gb!%ki=TCJN7M7p$rmy{oEWD(rlyQr7lQ`XRZ@$D`=KNT!nt4hyoIR z(da%Dh|S<0lFizpr%19GQ4A}uM5hNs9p9jF3oMOOTI$J>oo`*#*h4?b2LKT%H}~Z& zv9Q6_;i-c-D2)+E=f{&HS>w)HZO&eL_L2KQv}Wj-^mHaM?=FOiBt;%`gCLKO%=4A< zx3-9cwj1TM`&D*1%gseOZu*o_!s(>cK@{x1(_$hyV>YUY^$_dj#++VWC40HyXK26{ z5yX8}(F|J`f3ol$GIX`23JgaX0AT*4l!(7$AF;h}ePTudF(@C0$W8C3^|#8ps7(qQ zAbmz5r`sUTM_+3v+}7JL*8|5FD0L5b`SqP*iL&S|1ej~W197b{!i1cwGUZIM@W}$D zEOl~h2_9_Ok)NL*7&n=?i=2QgXT2C5eoVT^R-K+;LXRo#LSJu2>zl&gZf0n!{P;(z z-j)*_mDJ8o(n8L8_z$S=&_p=Jhfi;C_e}2l%kQ<>1@-yLyOL43t1K0D@S;{AsQ?ubjBTV*+1W@uwvIDa+~te5Cwa|mcbb(`&^eH5O3-jf8o&< zH~)g6H56e8HNeBz=G@nD1C;CpyjiR4>ga_2Ec&_7puKE+ZukbRU7V^xNe5*>VP=H+ zD(;!;8;&B|hu;DTIc$445x&RUXi#|vN!Qz{R4BVVaDJq(6(3An2g@REjJYCY%=L)r zedN4Lx+K{LbYBsn>&XcYK>|^Uk4CsB65_LXrZ~70Zau*$bYifVLbSgPU=uwcu23tT zLiomG|HK((#T;1lotcEqFSHg^hB7`}=VMklaA0iPdmwvDhP+|w=4m9ekk{x8JoLtN zrA7a}rdqwmeh$==s4W~T#@t7?p*q)y*mAN1AzrfIih$AN$`*`m0UwH5-%%rHFnyU} zogGOp2cw?C`-d^Cirb6B_9^%GLaS0S z6|Ef%?Q_PkBK3l&#cgdvzX|G?e8EKIpTGTWl8EiOyCsmBh*E@m9&S3HZK^=7IrwRgOeY1oP6i@ z;@y^cS>k=XbVoTtdmznRo~uI7E(u#?W|`cmrbTO;!k+?mYnM)KDxL0BS}(6z%bU+z ziN~xF)6LRzw;B<~9mOqhD!g=B!_%(SzPda#976at1WBBI5cFSdKmfAZ-k@=>G3rnV zq2ozd(z0X*lTJ(sEGcA0YKQOl^=>I=9=hX8M;LAqo>PKWEhHOTIWHu_X6sz&Is+z4 zCS2${V}8&0-kFb3X_AEjsnMlKi^VN}H-fO!4QleDrK0y);*&HN5CO}qncU}8gO_Z4 zE9u$h)A}ay?ELI(nsHlkTQ0;t&be+NiSuE1ZjWb!XO3rY!?tO)ZnSP~)r)c7Z}xVt z;+=>GRFiC)HCq=RGZpa7?utc`9ip>jtNwcI1$x>pvucr3KhG47Kw|758aumo0_%d$ zCk`o9D21OM?%8O+I_f$W_gU{;o8n#|;+HX5QY({LH*Y|`G-D61)`&7q6Tr)OpI|&& z>7map7<~)&B&ZgV>M|`+?AR}ylK@G3Kb+tf*DX1*uVqux6yUY)!Wxmlyzf}mOQt05 z2gD-dhOjLI^7qs_Li=Lkx1dxyVy2VpM{EC(ujx7R2>DPvE!HukVlhcfJ<;)mpCGc$ zyEXn&P2wr4wBC}#CjE%hReZJMbe^K>L-wxemvLF*pCCRa0faU|INZ}(4>0@vZ4Bu3 zEa${b#sdC)E3_VKUBm)_Y&Hg97~)9Rf%DslpokRBXnZH^#uM9O!Jpt&Xol zbKV*BY=NsSoM4KeaI7<;Y`6gsb+592RbC-&3Db=pTehV#^sbB44JKRMQ(lj}H!)pW z&tJDJXzVtgVm8+UY{DP1?Y zCu3P%$OxGS(Z||(4+hi@^|~cFh^6+d>9Rj$>qjgCkuxT|#P6z)?ZW8gK26%kgS_!Z zgSu9H61(QiUIm1=KpQJIp*>`oF&JqH`72Z5U7+FZ4n+lAD-4r7=olJYzM9JP7+5M| z>}v+%CCWUcF91yIGK+yk z%9gYE9jo`Tr?TRQoB$3R*Z2Lo)mlp&l`yFW(_RR^V^9t@3A}n-$TxF%Q@3+a<%I-} zowyBW#u>se5%#~on~QFRUHU;ND`wfG%1pcUF34?xN3qHY2;gy(z6iNAlV;VBEhnWy zbFyrUm*f#nj*o{d6q|7eI}}hU2#~(4fU-}9ez0}7hrYh|1ALyhb_uq9?eyM^7`3x7 zfwdqv$%-@JO$F#br|{*g2l)P7VW8j_gj)LTi9k%#&H{5$0gzi(`yb&@#82Rj-xhm+ zP<=1mBDj^i9n*IZd~0LRzt`SzXpm;DX)4C86O zdPZbH8Kpv4EZtYYdskZxDXGj{gBNkQp{gk;1%--@FEsygfS!jXY61}cC?@CTA}ZL4 z`^i%~{ZMD!jy`^raOatn7JF_kwHFJA8D3D5Q&dELn;9>7^BW%OPY9k0_j3iMV)Y-X zbk5+4eQW!&G`!jAO{%hgv0;q_!({7nfjvW*VZ|Bm6ow!+icgc{1T5qnRqR>F@pkd_ z1oU=-9gvIs2+~YCoeck=f|D^u{g1@Jn7)`|1xVM3@FqdPVFhH>PX~07&R}XYOVO;O z-T!>#rN8eLD#t9FuVha_-=sm8)T|Efy(vOl*&n5IhNDh!K?1^*$#7#xa&t&>|CV{f zGj9XJf0G*>bfU(kSK{E1Tv=u?HI4&Lpf>~Qom{DLVT)|4lIk7fk0dpf%2W}pMPSGT zQe^yoaFH=~C3hGkVxsgWViqT28j~}Y$mp%pc-G0^_7aWW0KvO~x(uFmy0^RG!x1u@ zi)*8MQX^|#Nl+XU?Txac=0yc_IAShyp77-kcTXx@Z|5p?f#pWNv`QnLVI{pmyDG<{ zjMh8(R=SN7q<0})ob_$Vy%Y($+$%g!MY~8v%kKJ? z-39TUn#J!zxa&eVIOEGS!&mJ^msQlRT`1Bg!h7fXLec>>r+Y_^+$FA$v{QNKiQFZd zE5XrwhyEgL?S>^ncLyHO1r^ivC8jG}>4g{VML+Xa$B?66syUcQwz&{!Cjq|^Tj#=4 zGI!CEY!?=2SK3?L%nm+Qr5)YnhMbY9rHVSk6E&Zp{byAw&-l-3 zNS-F@%$PEn{Dkl`LmjCG&l`FsjO#f0Sfo}oOE1FlPI~xG`lCmI#eU7VT1;$*tdo=A zOcl*;MO-U~f*w_JEV#&&!?HEDv5JU(q3Gb-ED9+-@ob_Th^{)IX4y{dnHS!*EfuTW z<)6KUvGh!Aq@$o$oJ~~Fx|NKQr`eOrnDcULg|ZU+WeJt*!e&0F89at3g2x8Q&IUPV zi9lvk3Rr%ZiH^|7I<%Q}R{r_E!aKg9qLLK(NTBiCV3?{6b?iibUD|#3%LX)du?uC! zvHW=n4{?u>d%2NS5r$e%CfLXTckfhZqTg3MhhCT`9?=R ziB-x*+wa%=Q!xA?v6&ZaC%PuoT+_+*;$m)nuauL!^zRXDI?+dsLrit<4{Pw+tkEHaUKayTx(=J8UZsNQK7 zk$UM*x!#ljd0L$wz9uJ5 zVCG47?Aa}n-Hp8tIi9~R1I6CShwZx=kV0KSse#r-s*z7V9okw!xkUA%!IQ}s%ctJa zBUZE|(?-hDNhfpO9T?<^xgV?>{1{|0u45j;;xNMw7H=Lgot1SuC#x zJ0I8w@zUu$XNE#N@v6^1S?L64tCEI(;!XoY>yqNG*m!9j%{TgA`u8;9BUoa8RfV?o zUp?h7tKH%Qlz4n-pLq~*PMf8JN8FoGJ=)kjJVZov6J?PP@{+oj5Vj(z{t3;f&;RQ* zEw@tc^jI=_kaXqI%1gjDZ_l2Yz&Lu4IZ==$>(Lq$_17xQetZnow1XQXiY2P^rQB3+ zq!z!6SwJ6n)3}YUc!;h5%b0{k7a1bl)W>NSCW?$AD2WE05J1IpV3IKFl7QA^eO3=Qy;$}*J7Bzk731~ zrHq*=fi<7p*@<3>2pvA(iAYb_c^MR%`;dEJ%i*J9@gXf)kgwR{qUZPaILmv=TOE$x zfzK3=tt{iMuEF&_t-yM;50BaFr}5AwrTvt1BcCD|Ijh)rRlRK!AC!n}BN}{ad5NKb zv&G_|N4G1$SYWT}qE4G*nlGfsql380!`pK0v1J+d(lCODwl=Zo#lWVimktHO?P#)y zrex>hls5P*!H+`Qk)F+IYJtMBu_Kog$1wE~^e@(T%CB|@qA(d-eQpxR0Da0#zn=s^ z6P&9!kaL-RZcy?V6xr$+6j}YO-o*>+IFRjkb^kBs-ZD6D=G*^_otT*&Gcz+gW@ct) zW{#Pe;+SJ*$IQ&kFlOd4Gw(bXfA`kEcK5};*r}N#&1tEt)H>ZIsrCIFX?UP~y{2`t ztprW&<3QWMj~pr~eh4pZb_LeVd5BN7kF=70BVWvhnG%jfPY$i1K?G%zc6(I0mQ#wN z_@gGHY)t}8PNF7L=E%gs4Ys+-xWR;|;K$b2=KUMCUx$N9uD`um!vMSXzwY?5v}y_B z=pzS1ycmT@-jv896@|A|x|)DJ@f1UP_Lb4R)tZzZ%#kisaA*67#7mMG`{?^jZ@tu^9ZlOhtEiKc&7diSOR^mr8NU5BxMU z;rL>LV6O#?yiw9A^##}gun$P8FkHy*06`|n9_u@c&mOH()6X75c*D;h2;~5e2os`L zL=mP4zwo?L^DQIn@|7)SJd4`y0?c608aO);TAXAm&JaDUhLj6eWCbOQ)DSOA32$~C%bfpp=&b?#EsV^o}tz zC;;07EdP#js{DFn!uN_Z&y?sFD=uqnum=uSV#4wYEBCvvs}DYFxT`OeE8Z_M-O|v& z7_+#Jks0@>p3w=VxR%keHo#?Oq^n0)w+GRLAOnEaBHAOv9PAhP+>(GlWcGU$(IhYc zjyc*d&V0f=*93(DWNHIsn8N+S#+lRn!f2V|L54ZrFRG{|#4pP1_q4#ET1$*yR0Tu_ zBpjfm1ru(iqy=%Z5`P@Rw%2$m4nwnV^_o_9>gjn51Bj-}xGk+ains$wXBJ)qI}QK= ztJHwV_5+JRlgeIppb6*!+6wV{jLpjM6GF8K;T|TP1>v50r6HjSy?RaX6aCLY#9fZJ z4E%vhM}FRbHHeO{v@2lik!rv%7k$?5$Q~x_ya7Irq##op<`?qni1rHIJv<2{eG}>t z+{JuAS=v#5K)D#!en27U(QYC{+HJNKB2@OdW@dJF9g&Ia^6>~NC-1o+}(fp#54+tHS04twOb#y;09s{s9uph;Us z{XxtotiL;dZ5iE(M;~_GY|VUXb$a*#Ll3(Me3K8ma(w-peL9|DospeSxISnOCcHjq zuQkD)fgay{v8L-duL#^hMj*$;Vf!nX;J_^q0XPf?MDPv4S|Pwgz9P~$Z@*^NH)?l+ z{#&>4B--QNG336d0yJ*F{;qG)e$D+*v+ShV!*~VhgAYPeHNhF|(1Q#dAh6RGtE*Sw z0jFz_7s!r>a&_sM)){trMc{+*+4BnWU|jk5j_40E11A4 z&-<`88RpuEH7>`Aoz{7LQ`RQ5;Y3}_iGFG%M4lBeSOLYy~`1e5*q7(M&ry8HMp zSh$1`o#%b~^GEi_<|lb}*Q3AN%jfCcrxVY+e_Qs4phn3jCGY#cJN^I88@zl5%9rfM zpFi1QM;fG$I304`x@2*GW060ei$imQ7|t8#Z8>`;d1!SGy}_)zS~^U3)yE{4a&MV5 zW|kFC!jDrp`W?rzCQCPvREepZ+lcu{qaf*DXP3Ha%eeaRhyRRFOTL|UJUx{h<2!7& z7%@NJ9LJ!a{vrA&-a%4jg&t??Me0TE7Ou7eLGf9(!`ic1T)^QHIE!3eyf$2gWYT#= z8oIg_A~N^yM7z|Wl{&3xo+%+!%8+k;o2B+76toVpqq+Pp8H^m_yf`*^8_eRoOI&Sx zmQdC_);w98Q=CQCr>2h;r-#sKXH8XEk$BR8JafH~U8w4J&Q63KugS@o)I*r;U#B9Gvr(>0rV{6!_^yWlE; zh@6`R`)6ypbVcLTX_wzvHg`Jr$yTuQW~88WEt-SOGVNLpu>9F2?ObXzyd5l9WCb#| z$)WHK{7wBgptdEnxyQ7b`@}TEbgRKhRI1KlHx#eF&9iB@M%o2^$kJL04|q8eCi2SiqKG1)6K!J(!qvAUj{ z8rL_)O4NuA@Z?CvRF5nbvZ7*&Yu-&Fr{qU#QRnw_&o>xNMGtBm$)PmGG&=sT zn%a~IoI`R2b|UAe8+QaJ@_X6E_j3i}!O=Xx2LV_&T3B{1yC#9C(JCs6vv0%SP$^R~ zWX(Z%^A(_b?0DJe;%p+iM}W>TSpZexZTzrCJ4@h>}9Sm3~1`7xUmol|}A z4-dM9h+l;&ALX=i($OT;Qf)tzT@-^E50~ROK-iZDH+36)u~2 zA|let8t&QgPAe71x=V(#+mX4Sc>C)4_CDg8&$q~KCZf?Vd-9>=E1WrU($b4lc6V+fp%32nWj>& zg^{}gyoP*R(XXz0^Huff92q^Zh8M`~H{vvtIPd1XQVUej7ilhLx$2+P-9!owd<4vt z9??(Oj3(bW`+feUVJI>(l>Eyo=xWnO*v_tJI`g8!rYF5<6+6sz;qd78M;yMmp(`46 z&KA{*7#uL1yergKe1=nO8joHch+|9e4X#?3xooxlblC^-)e!Ce%(ExNBhAr?CujSi zBRy4QwSLfORCkXNAgNikUeM5U>J}ZC7elGU#OJZZQ_kBld3O*vh>M=e!R04L%%`g? zf%q~}mSjg@ZHKMP)!qkHv!Th;W)ivCzAIkj+-`))Q0kl9ht=V2FH~zoT@Ap;*SeeA zA>GYI*%y8P+b_|zx6Wl9&MPC_oQ_p*UtV=b)tY)^A9t-6lo*#Y^*Kff7>E?a&Ba3b zM%aV}hFwGVP!4MPEg{?}PE_n5>v^SYUB znBLlaNyC_nYWdEm*5c-&Gy}!%(Q@aQnX9B6YVs9>DS!on+OpVmUCJzUoyuC12GD3r zx6h$nIlCxKXGwM-&nZ_mIptik*1v30vVI4wtlsl6xP0;2sVB|taNoi-TZ@c+ZI|bB zg{$==j^&?i^Sce5M&!HtU-F-y&eN9Sz9IKDzMQ{TGWJOOqFxRP*qy;#yb z^phH!wdlaPX<8D}ObLhRJKFe^ln4xFxpz9q_yz45BS_1|?k#hV!%CG0+4DB!DJ7C^ zw=e_m4y>GX+zay+7UO8V{V~dJZkiBw&^w>I*5^9T!!{ssI2N!=dl?qu)Q<6TXE@b2 zv4b@O5!~~9*z{ZTF29^>KK9sLaIK=u<7Ao)KT!d{CoE>yDhM9z)$ps&&#qkTuafF@ zt(=rQx0RPe8#KN?1S%2~wlZUixODX*kH$V!9B*|i`@X25JBrL{GX4IQ=EbM4U|zho z7b{90JS)$-;mf4)a7n2)y~^XzKTnDkf9f&%ij{n`x;UO@M(&$--s*I}x5rk``FN7> z*mr~}OPeX^F%>*pX`n!GJut>hJJfRC^h3YPTWeGcVY2Hm^K_SW>ZJ2-0kRy;CGluYI~PiAL# zDprT)#E@8aaqEU#VewQfmM9oYAa14S6c$>4er+o$J0A{K(dUEf~weO(Bb<#$ifFI@$rFz%%{>i^tl4^=0;%El#!pb{-}& zwoUd)L1MOkc0nf6hJ_loTWtQr`E6pv%w^uG{`-!7815zOM;q1oeM3ohV_d(iM}1k( z+V?rGWj5gv{O`moyRmCYK#{yBJ7XwAR>yrA=5f1@j@Cb=Bu1o7Ke$HSZO7u(ub2cv z6i%67e8w92O!)qm2EmzED(yn@W!s|PE@Pv9Wg@RkKu(s>l>Y!mjj23x*3M?1n=~A1 z0ySNx!RJ=6qZ{Fb*wsBaG|&W0^n90>sVL~I^cUzE5Dv^7+hVzm?TERRn9YjdnlSw9 z@1v_7B47KPBeS!(Dx0dayj+f6T|3-*QgHuz#mHU@EQt4slBg>K?v<7mGP;b`@SKMc z`VaZQqw@6jiWm=iN5oOIkR9qY(LHL(xBRM$mh6};p6jFNl{}mZ$L6;D;><#PqG~r; zhHvU${E9n03R?^vO&xn%A#9>A895%NPqr$GJwwbyc5DcF{X}^M_54Z2;7<$C#qN7oHrG9xA}O8zRL>&e`mlNmK1B+PH|QFD7f{7*rp= z`ucQ;-VSxjZDRffN#r$8_IJ6CT9*e0>0PUmZPfk-(ti6Zu}{8|<`iA?sVj`+;o#FD zw1<6`fG6A*_a&{GG)=_?TBn~FlQdk@1@A-i zIw>p4sY}yVwmBg4c}nk$&nlmtL&GNfe7Ia`es;=iV@kw`g{`1=O8-dhM^; zED3ro&fVV!UO$`F7pqg)lPtboQtThL>&Q>MIz7%&7Upxh+xpub!SO!Z>P>z|C)LS$ zD!UIdGCdyg8s%hbMw zm?J+dnt&*DCKxx7B^@qW)XT_?F6XUKQc=;HCoYElbaH2~jx)QXoleO*m|C>6v%Aq~ z_aK~3DHz^5dN}$ErcC|vHi{|cs=4FR;rt^Mn)aorPry&b$i54D?>T)FHXK!bi5d#s ztJ3)gcfO>NS>9YelNd#Sbdhfm8#%!c>-ei$<=2%!(l?Sq#0&4_*-406rIB6TfNk(^ zSVS#f&@8~(v;xRXHhd!37@5QcvazzhuYcJFB9mGx(X_5>UA(zv)}0@rbX-<^5m6p*0ho+bt>%;w*I-uDX7Z=&t7YiB@W7}Vz0uIal z0d*}Kpqa{x7S2d%O6{Kk?6|8~aV| z{M8A@WRUT4jVo0Td28ou4ca2MsO$hvN}OETsu`SvirsyVW-z7!psNhZofRLlyWowgS}ir&Ff| zi+wzT?ChA)ZmKqm>mKU!JC!6>JKpf}_14O<<)$;-y5HlxV@LdRznNMtIu_19a?NZ64vz3d^2pGcYrmzL`Y!> zKb=Q^$r4^lL2lhf-bX8p4&vQL!>1|T>qy{;rx#=6$YS9hX2@c!{#gE@AZSpfepG(D z@KQ`YKY`XDu2EnSk#V3<_nQ@tZ(4J(Pfe>}>Yn8+z#lPiU#-@{ArEjg)NxX6l zuSIv!@kg^H*cco8If`z{sz5d%Zdks$f<5R$D+iBR69IZy<9K5pQIEEgf$HmL323aOR-{-!OGspiPL$UHS zgZ5}7ct@C{mFZ`+8tv@V+$meDxWX}8c|AsiIKxM+E?k=Vqdz!;d^3FG#G zXm2hjl68~;at`^As}X5J?nSL+|Q=wfl$1|9LMNU_U7aPZMmmVfVd zo(PoQ_SCNeB(`{*C(GWEjAF5DA8ssbfRR-JAGRNv!<#ktayIXbZ=9FsX3F|X>+)|0 zW`o>E$sx4CX=#pn&h6WWGTO}}wIElPBJJ-=e)F>P6Y~pJzpR$5n!Jj=4!utK#`(_p zbaWc3dX$hSX-Cc$1s%#)4bw5Q)mq5v$o`UFdYoQXHDhe5`AX!5FAi5CVesj;P`~&t zr~vG4_uWYo?aBV)Qp>j1&6{zdo`~PHC03HXQeBKyXIRsWG?zR7h&LbmwW$Txl{b2i z<#HJQ&i+yRaq@xivGFswpYVb4ituXO=(FnQsehRKq5o>mYSqw2N6Sz=J6m12B6952 z*Kz#J^_-{$hNX*2qQb|9N||~~b*g!)5?%Ga!jH-|+Yh>&UI@ByZ=F6c)REg^R$mOW zw|iv)srN4Q{oAq29g~5-x18@h{^N|kazATL?kP{6tA;xA$<}JQRU1np(66{ofl1yWf1SCUm}v_Tf}M53iYD}Ok(FUb5oy_BVJzNB~FvBc+eO>dZeL^a2EX}x27?p1!^rDF`LS84{T zprdcKvYD%TE0-4&Y0qSW?)ePTmBsk0zjrCzna?lOp;lSBt$W_H%e)?ZUWED#A%0i9 zTZ>#4U|meFVaV~B3oytQStB%iw>jj9}~r0x?X)8ED~$#r6DZ z9r_wzQWF)`!!k4k_A{(hma`u%1Qc!o9u1PMQ2HJ17&L3O)TmV;(V`@o_UtYtk$R>y znJ1geL>>+w@#yZ1bE1rGwJ)uaxJp%P(`d^Kz*yHN#b_b+5f^O;e~4c^IFS)fSL3_N zc+ih7H2H-)6muMu&6Jd?U)t}_G$y}o*$QI=Qr?Z%#gBR=UK~1(bDKmY)*9nZr>v{q zEgKytJ=9&uFXn19h8-5Z?B)iG17N^yvSv8S`5I} z6Ka+quij^7^7?bOaS^#E0c%_nKBw7O+-bqrZBkCE{&D#wJhNuBCKyw=8Ss46NR(}<@HVI?^XY%dzKV`N0 z^lKZhon-(+&%GU{;c1@3-v*|VaeD(v!P=M{{fSTv!MF`4IUnip%)#sJH%$aAe@$+{ zg|}MlFhyrPmz4uh2xO|T%#9#2%K(&d*SSs4wzhF@ZxyXN8!J=K`YPGl+yi8=BN-cq zHA=y=rcBfnqkl%1h-@h=kk_~AX|w~y1=yWmU}n)p2d^VFWFtQC(yXh!UW3AitbcJt z-_~94IecGucx_U;9e&V}bvRqU%j_Z@R_JhJuj2U-fCdk6)r=D+Hz@8L)*t+~Xi5Z$ z5w%i?T)uz3Q<5_Da5?vI>HI70b}^2V{b~6ptWb5m^uf!nfsf!%J)=w54s?wq+7p&}<=fO#n!2b>q76%3J8hGXuNNGj>hG)ss=2)evABzA z*Bvhco9f*|l&4O3YSC&`bndIp{UIOnz=Oi30Sa8o)%_IkBG1I z(D-9sz4IYE1Fa;=W%-))Z(of3ZPSMQ+l||esjA9Q^5KVQ)e1&a9Mm_=>tQ43e8D-1 z6;(0HS4=_uG^Sh&TuHiWAj2kVc<&ICm7P+`(M8uvsWgeKw?(VODaq#fMou7u2mE7d zXlf|nZ$T&X!BgcaH;kKl_Rq@AnP#LpP*OWWHje#-8~C4)IZE;)25k)QIzB%ESg+nT z%Vy3Ew=dCHvTZ@t@?L@P0XG`luxVL~ew+h?_~F8@g^026RyOVqnTr&^0R2vI!&z@c zC>s*?tlr%KibZmg3l&d1du6gm?hm407A^F*f_c-a&B)}M8?k}}z;W_QADFA$0cU!os=Qc$-I#mZ_7dh2b zpgRF?o9pK&UB$11lTV&aad6#Vdk*WhPq7`yaFD66wnLYj$EYlCWHbq+8)2T&qdUVWx)eBsqo>uu3dMz?0d z!Kg3Kpi{3X=gy8Jt5_@SDWY6ixsFy1*V{T_%Wy52KZv3hZ_dX)FJH`XsBgF9XdgXs z98gWxQIk{jHixBRZZl2pw`yDyz18KYNZqR2RT(~T1e_~w471@{fjTGU=r6MPAvM2B zY0T1bwQ`D+{T8pvWI9I%j~mjPQK#tQ1d5%+loT>AS61#{PCybP)Mp7oJKH-q4h|0v zj$5gv-z9DcUG|p+7!Pmc=t1?B#-kYbs*F#rDSx-ftAQ7eO#8)? zc_0xqFEsDke3$^@Mye^)Xu#dPVp{2MDtnXj6-%IqsPNQ4n`kRn6H9F{Zmc)WVrmz6 zKO+-xWp{?#P9^Ewiv3{+U57cqUS@GYq~nPHujlkAqP?=47Sy!m@mhG{UlHKOZn)!!w6-hck=rVJm7^4D*;9wiX-~9G0WDL-UDAUGtW{rU|dq z*Yb(fCibaJJx+`D<1QUN2QO`(vDV4=qLVr`sN zg8V$Psukc!MEmXqSvGp}Ldz}#&qm{hn4T1iYjp5_K1b;dU2j#3{kaLgP3n+Vda8D^ z>2a|#loOeioQ`7mA&CLq_A*aqJO>Aq?{4)k1>V(*#%9#8j0(=CX3kdj7DQD4xf{r-;^ydRYi0+k zhKNZ(0G3gMNar7MK0A{h5r{jW^WQ9i|G^Dl0~P%X2Y?*}ApnsASXdaCIXJmFL4<*S z$O7#DDfkDK5OMx1CxG++87ly)@xONe{}3zi47Fo^z2laB`cH>v>5 zRTX{!dX|g+Tz+|ZIT?s5a2W|o;ZSk8^!I>-(W=+Wo1s8oQEMT+;G&d{292t6qJ{;d z6gE}-00!1$#3>xz<@r~89s^Zmo48r&I6Hyqndhaypo8|#lEsAdgnj4k4OT6EV4fS@ z+5I`IhQeiUnCGz5)LBSu=sTxlvX08xE!45*6D)7%~|JPp1{10N| zKjPrOr~+(k93b|||1DL3jg^DtUjyU31IAZX>_PCQs_pTiYyIMGGuxFi`y#{@QxcpQ zS?ViH^hnolLz2hQ3F3AFJ_KU40zv>stTzJ92{-FKl%;u^Dilb8?%3B`II_^$)?9=we2FbZ@GwC5wPjFiQ%(F2kjcG=`S$ zZ!`PgV_5YWI#@kl`G3fEq-kj|bn7sw&g9TW8_1*xcPqJ=$ zpIn&-G=Lp*`aDdS`=kqiCqRB_tv{mIb{^H>!AL;+qUCw;b~4#)vHnW-nt0;OlS+G@D(9I};FzodwNbJ|F_Fr@xRL z|1kOrLJB;svhB*K?kvv)35&rLf4Q;cMuVjyi-R_T8<107o4EoKH%``JykhtGcTLDW?#rXB$A>Xv8I}#MxrtM za$O>Q;-)Kq&J&8m&T^0z6f>ZF;IOeLmF|vg6@LrE`Xi2J`YLs2^$X3? zSI0t)KCtg{`KrW1Ly|FrY!d@?AjLl2kn$9<-dc>-Z;%KTSq9sLFz5AF;cUi*`_te> z>thdT^uyo{p6u&M!QAwL*O;T6D%zsCRei(bnX_AKTljq@LN~{zp*0J8x=vQZ0vs z;h&m2ghz%gCwg7!27DWg1sH}&?s$%#3AqIWk)>yGJ7n zYraR%yBn?r4==C36{{MMKe*I+4zh_QM!>h!%=4sS!ps* z^9~h_0V`~gipfN9*>c|<5Xl(?!&!3jV{(hhtV?0l#6t5{9jR*TDe$C|%J$Cs@&=}@ z`|k5ZOL`>Wd>eZv*>_%m!2CYN(k0e*iWDNbyw!o4!Fr7)jzx5gqCa@DMVvi3K26kFL-mtW8M`9!L;i9!I4kRM@hY7oEpsk^TjH&8?wdo{^c?YVmr>gB zUi_sExW}}?VNRbGHP5j}`%QEND1|A}_;rO6DnYR;7ddmM2#$8z2ZM7m-8=E2$=%s4 zm}zidSn8;1JoMDI$_?{AQ=EGGMSnV1feM8kPx~1IwUB!K`FVwX@&rdt^c@!Oz}s1S z5w)-t>K}wa5O_7oY90(iZZDD3R&%MNQ&Lzz+=61#%|U-l+c&FfLd9Kbnu)1H@Gk!E z!)9WkE0ImtZe_2?47bgs`luBOGZdS3jU|KJ>CFxI4Ou@ssI&A`0mOX8ta;HnAC2YJ zF{>+IQ3vk*=lNI{1+0xd7oN)8@>WyjP8#vqPb%A0eLm;ytmqP%8{}{1*~H(IEad>< z99a~HoNmP-cv2%Mv5KePrK;?G^~%FS!pIkjQK&T?My5Up1yW3hpH=dou50g@(7qa5 zY$5TTeN^tGt4kM9kndCBvs;~xrH0k7ipxoQaIxsIg`@sfO~c2@=-F=zL6?$DBwJg} z^*?=&d@AJGWGTCVB9~Pwa+oH$E4hAodGW5!77Oj~>(5ZH#=}HJ&{=7y;~rgQfD2!^ z8k4*8dU+dzXq4lRN;b`Oc%%&5P|8)zG*1Q-3q7L_t3*o1*jpYRjfzw`<0$)KIat`{ zE`2;xOnmQ4d@>{DW+AQcThtHbk8PO73ViMjujc_3-A`}Aa5hP0gQGjZkk`_K_fgt5cGgKH-A_SI5Dr*NWHLQ?h2JDQP^Vg-uFY- zIU%?U4_N}qbgba9-jOeTW%>4btV(YJoX3cmkvly4Ch{J04a=a zuy_oZsf(m_pJCR%LcJKWFbrMJ1jdgn-$8nR?NstsA{Ywm3DR-IGO+6iK#GV@NvJi2 zJr_Hg-;#vO6Cr;2gJf=qXy5<-M7v4JT$h+}%y5G8O#RF&XZ|Q;9tf%QhT1)35RvXF z8PSlGo7A~4!jmFj&|Mf_=mTO6a5hXrZ!1sqPhX*TQMk|L#!#jutnBmDWvz=55b=)M zJEwryz{ePOzu9!G6LXToM@04`ohy8kohzK%4=p|P9v?22+q=z+fa)>BZkl23S8#8T z_<#^SPpHf7FNi3i*pZ={k`boKqx;&<^sRw!F?_NFlnM!mb(uhl@Da*=nH!AfxS$~G z(p>X-ybO_kSK`jFO%Z=Fk6Are&iAaJw5>&W)D-ur<%Ql>T?-`iY3ec+MI}W@rnwz5 z=F(-#hI{!*Gs=rhcY><-eiO$QFMjdMs{FH@jF?eD zHw$0*brc&ft>BK}g+xz8VJ>jak|j!ZKzEfAe}iYA(w{3)V{~nXT2RJfZn?0eR@8)q zbH)S*Z51XyT1Y>^dz|?M1DK46T=j;$nTjv~VqjesIt@tXBtucVjr{r`+#w!^UL#$xTO_8X46FWdO%Y6JJ^p4oR597|xbr+|y$Imp356&Y$MmIeE8v8wV zL8et&<&P7HB7o;bK1qcC=LU^WoU&C^8LuUsO&ZBMZq~z*-F+0YgYjMe=dX)={}l1@ z;Zzt?j>8@A^(f3Hc$rk5X9N~F)byYTU*yMao-);`A^sK=xY+FfB zB)uSM51N@!7J-NlpiCJOhy*=mEy&@_NCw-`;*vT_OZ;Kg7X5_~n&o&so)5g3WRMf) z8pd=vgAR?b8I8=YV=y<69J|^Rg=hd0EAvOZ^K=dW(iI^N>3X(y&OKa1+P*VQt#C4b2hbnvVpTOYJmSf#V7i6VT5 z4wu?}$8+v$2nM9PTll%y6D5; z_VJz7zkSj^xHG&PUmW+yp^*d?K8q9dexG%=BNuBHB3EmlO|X0k8by1rRq$k3(E5zm zm4cS~19zi+%Z7Y2u01w9(|+5Ay(S(-GcE&VRKX7DczoomkOXqqj)E1g;$M6PG&jr% zFENXrXK%N2>+U;TtiM8k>j?Y;&h*`I4CxzqjTb!_BcJ{q?Wr5+gyrOIXRXqinmyOo zB@ANB>87NoLbPvXoPkr{^IH2l?kJQia6GvZq7_5Q@;sOb7dq zv8Lpz;0lo?p+yq)Va#cNj}+Y=8;vj}O^H=neE+u%;JHegzCb|C27#kHhBl~Sp`-WU zx?zeY;Pwve1W)}_1-w8>6ZYUB#NZ%R82{IYox#CDX!Mq7pFAQYgaVs?Dsh&`Qqc*k ztJ|$(N$KASF>%$>`W`gcRY!u3VKh{z^iQ*&nM{?P$A7%bygo`m=rXiW++S`Ht`r4+ z_|23caTq0~bQ7P#T>Ml&4GmUiR4mi*p<`{48cSwbgM!?XqVDLupld{AND?NZLSZ5c zWio&@%0}!-uLAaVoi^Md>D}kEYd0);UA5oPG zUgd3`lI0V$vZ)V}R=A7^hjUfIdP#8YGkTx{v8AGBf&0JvVBFJ2k_%NKO}F^9o%ZVbzU|uUDF(UFk@kOO&mcV=6_%SkdC2R z5()Ng+(m4<1+`VM)jv`c;y1Xr% z8^PZ;`bF&8plCLNkvD>!T#+)43F!X#{1HOih=y=wTs_vWEcU7Wbs-jXaiIMm68j<| z7jf|;qAO|!iN5nhf8azvrT{b{)V?NCYnXIl9ghfu=svrAY_KDqa8bw@d877{Pi2tD z7;$6v0$zt)$a@@pt|bJ|F^2{AqEUJ$R(kiBDv$9;p8raM4N_e%M;pX9p*9F|SGe*M z%$On_rda!4nl=cWw$Q_dY3Nlb+!Izn-q)Z8{M?8eX1+=hUwbA3e4aWsf?Xn>?VveN z%N~d#8)2J#HiFK_z&X!|;NxtMv>_2ZQHQRAe>QqaHY>VDhMJ|t`Zuq|1bu8cSA=}F zIu4Q(GCpq^8vzc;NcrEEtalg=0%#>IYf|-tH}7x;PS~*}{szka-4T3JKQwtY^AQqa zk|K;5_Qv?O#*y4)A+`2x?t#fFQ)<=ykFgLZa116&j2fAv>MKn~(6d_-beSfSguKKJU*Ni_Ejlz@JwAYAuUTTm_44gZVvku&&f` zI$)!?o;=cPZ~4%ni$g?EQ{l3(A|aAUFPlN5(LeLMY|`sm!SpvM-ci4iB$%K=R3%iQ zggc3fmdogXxU>W4nG$5OqVquNUb5OI3Ao_Q$WXyX<|n&t$E)NYNlCH21%aT~$wHG@ ztdP3COU{*WKt6u6hwIW!T1b4@uAe0%KJT3*7HXrO5qt{A4|3IFlOnK1+U$vr?LGV2 zAFT0Bw0}aizo<$oeW0orX11&sC2%c>J#akedZ{qZ7G52S0YSZ}^yS8a1JVa72WCjw zQpixcM&pMo&J-#O=yL&0G{!BGn%wq1lD^IpK zaQjSItwV4$a5wt z6;hl-%$DM%-?F;V*F?L>hHY#(61#8nyX=$MB7C)Y1D9ojtxwM+$VbtI!jYeS>?SEh zy_5`^rP4x?OGG5oQuBS7#IT4BoZEEu7nbej&QMTXQ9AW!MnmSS944!(v~n|PE!T+~ zU^CP`j%73O6IV0t6C?gOH5!HgS=q7PV~Z3DB10|(ZHIwOHV_^_1cRJQlzu}hC6%$? zG*8wXnL~C%Dn}${A^;FE5ztgIAbic$XAK`PHtp|uIYD>}HCAbHH&D9GZYMY_`8Ggnco`3iFD+rcGX4WY0$sdFJ^$u zBT#MMi70X!&QUmquwYq(RAqBxv5e$Y1_udqfdBivwYOUf(hF}$)2|PmAc-kFJfb+i zS1i~o8GhDu$02rJE(aIV{FO6#cwWxhQ?d_}APA6Oq4PJa#9dzQw7Idd(QS6ID!Td* zE+?pV$=_qpxOP>vqqW!#g^5Oq$w@We`)#4^Ufa%&WOJY-1$#!tf^CUnWl7cSdO#@> ztV20T9_^-$M!#ga1m;ugL!)FoZyk2^m=#x&FPcu+rZZ&(hdq)4SU^!^Fl{%4Q_J75 zMA}rEIv{C-6n|G^!d!UKd$fM5>xq`cUUkm)*XwI zgwQXqm_lG8Bc@v|EQv<`G05m7!SMX$}C^usk@p^e#lq=&HqwLat%?IvN<~YB&GVEa< zCzzr7>DhotpbMKZ>MLFvEEhuZiiKq#`os4OC+1i9v>oFI>f(YNzo_rO#{>ptb^8Pc z4=fFH4SxmH&yEQ6;^~gX88c)6C|iVkXlEw`diivR;&y3dEhLx?dLVxH3W&p**TvT& z*8_$vF&t6M>*F2S4{PFUuw7OpS|D9kQ0RIwfY85;33!8Yw`ttJEyH@^AJ&t$5WoRY z)&nrzu{mJ@Ve0PK<24cZLkdppdzTuR^+-Q*#P&TcFYq%1KbY=BwwI=Gw2G$h0f3PvrI%mwOs5!JY92a8J1FqnpDx zmByDKltBICHL`mByC=3s?YrkU56~LApvCL8&U*i5zsVDX4_0@7CrG3p_X=qD6z-vP z67<1R*a3TB_!)0d=Wz`M_8DPN>rso?ZGK4-xK-m(OVDlfIuplkOUPkJzZQ3x_$jV<8Ras9~Wo16seXr_Tiv?Z{L95Sf4@Lrgqg-9ebOys(!|RHIZv^4E zXI%ABt&TqLs(glD^~n;i;dcI&v4(erY{km_ZO54XRskogJGX4yBip^WpXprzY;_@B z0bQ%(x+7XZ-O(p&7w+I2s~4-GSC=lGRJ&g80bMa)?(tnQFL!FqSl}SsVX14h-u^h& zXmEQd&CqyI?&vl3I_!bj)@Z!_R=?G-?K5T!)GMT}SSHuC(H;!F{+8xQZLCrqi>Td=bBw$a!*Ck5UpzkwO_wdIhig(b<8k~0| zur;{s9{xta%`M<>1$x;ZdTHW(K<|YCBepv6^K|xu<^8_%GvM=X_G6U$J=SygOZO+r z@x9x5zmNPJF7UnMy*>_<_`LTwc)y4K443$k|L1u43;pN%p2Fn%ioZSz^_Spr4wU%a z%JF{X-JXGm$nm}6oi6OW@f|L_e6E!I{Fafo$Dc>`FTUSq2m4nK?|+Kk$7AZZ-|j-$ zD-q|n4Pm(75%ETfO{DQgJ*2TWUP7}kp4u&r;Js>&=QdEB$+)Sw`;&#>zXHhwo2}WO zKu3j?boN`uk5+W?8>17 zH_sm?8p$}KEpv2yd)ww7bA)YMxO}iC!!|}t!|ey%oJF#Jb)0LgG)CoK8DL-0i|T(CFxBnqQq9 zDU*%`fg^ia+A4VkRVXcv=)X?%*_HTTx `=cn7PCTcIoBYK4Cc3o1RQhaR}P1h}_ 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 literal 0 HcmV?d00001 diff --git a/docs/graphRAG_chatbot_documentation.md b/docs/graphRAG_chatbot_documentation.md new file mode 100644 index 0000000..616967f --- /dev/null +++ b/docs/graphRAG_chatbot_documentation.md @@ -0,0 +1,666 @@ +# HP GraphRAG Chatbot - Technical Documentation + +## Table of Contents + +1. [System Overview](#system-overview) +2. [Architecture](#architecture) +3. [Technology Stack](#technology-stack) +4. [Data Flow](#data-flow) +5. [Database Design](#database-design) +6. [API Reference](#api-reference) +7. [User Flow](#user-flow) +8. [Security](#security) +9. [Deployment](#deployment) +10. [Development](#development) +11. [Troubleshooting](#troubleshooting) + +--- + +## System Overview + +The HP GraphRAG Chatbot is a sophisticated conversational AI system that combines vector search with knowledge graph capabilities to answer questions about HP marketing materials and brand guidelines. It processes multimodal documents (text + images) and uses a hybrid AI agent approach for intelligent information retrieval and response generation. + +### Key Features + +- **Multimodal Document Processing**: Extracts text and images from PDFs, PowerPoint, and other marketing documents +- **GraphRAG Architecture**: Combines vector similarity search with knowledge graph community detection +- **Custom ReAct Agent**: Implements reasoning and action patterns for intelligent query processing +- **Session Management**: Maintains conversation context across multiple interactions +- **Image Display**: Shows relevant document screenshots alongside responses +- **Authentication**: Microsoft Authentication Library (MSAL) integration +- **Conversation History**: Persistent storage and retrieval of chat sessions + +--- + +## Architecture + +```mermaid +graph TB + subgraph "Frontend (React)" + FE[Chat Interface] + AUTH[MSAL Auth] + CONV[Conversation Manager] + UI[UI Components] + end + + subgraph "Backend (Python/Flask)" + API[Flask Routes] + AGENT[ReAct Agent] + GRAPH[GraphRAG Engine] + SESSION[Session Manager] + PARSE[Document Parser] + end + + subgraph "AI/ML Layer" + LLM[OpenAI GPT-4] + EMBED[Text Embeddings] + LLAMAPARSE[LlamaParse] + end + + subgraph "Data Storage" + NEO4J[(Neo4j
Knowledge Graph)] + MONGO[(MongoDB
Conversations)] + VECTOR[(Vector Index
LlamaIndex)] + FILES[File Storage
Images/Documents] + end + + FE --> API + AUTH --> API + CONV --> API + + API --> AGENT + API --> SESSION + API --> PARSE + + AGENT --> GRAPH + GRAPH --> NEO4J + GRAPH --> VECTOR + AGENT --> LLM + + PARSE --> LLAMAPARSE + LLAMAPARSE --> FILES + PARSE --> EMBED + EMBED --> VECTOR + + SESSION --> MONGO + + style FE fill:#e1f5fe + style API fill:#f3e5f5 + style AGENT fill:#e8f5e8 + style NEO4J fill:#fff3e0 + style MONGO fill:#f1f8e9 +``` + +### Component Breakdown + +#### Frontend (React) +- **Chat Interface**: Main conversational UI with message bubbles, image viewing, and input handling +- **Authentication**: MSAL-based Microsoft authentication +- **Conversation Manager**: Handles multiple conversation sessions and history +- **Theme Toggle**: Dark/light mode support + +#### Backend (Python/Flask) +- **Flask Routes**: RESTful API endpoints for chat, authentication, file serving +- **ReAct Agent**: Custom implementation with reasoning, action, and observation cycles +- **GraphRAG Engine**: Hybrid retrieval combining vector search with graph-based community detection +- **Session Manager**: Maps frontend sessions to database conversations +- **Document Parser**: LlamaParse integration for multimodal document processing + +#### Data Layer +- **Neo4j**: Stores knowledge graph with entities, relationships, and communities +- **MongoDB**: Persists user conversations, messages, and session state +- **Vector Index**: LlamaIndex-based semantic search capabilities +- **File Storage**: Local filesystem for processed images and documents + +--- + +## Technology Stack + +### Backend +- **Framework**: Flask + Hypercorn (ASGI) +- **AI/ML**: + - OpenAI GPT-4 (LLM) + - text-embedding-3-small (embeddings) + - LlamaParse (document processing) + - LlamaIndex (vector indexing) +- **Databases**: + - Neo4j (knowledge graph) + - MongoDB (conversations) +- **Languages**: Python 3.9+ + +### Frontend +- **Framework**: React 18 + Vite +- **Styling**: TailwindCSS + Shadcn/ui +- **Authentication**: Microsoft Authentication Library (MSAL) +- **Languages**: JavaScript/JSX + +### Infrastructure +- **Web Server**: Hypercorn (ASGI server) +- **Containerization**: Docker support +- **Deployment**: Azure/Cloud-based + +--- + +## Data Flow + +```mermaid +sequenceDiagram + participant User + participant Frontend + participant API + participant Agent + participant GraphRAG + participant Neo4j + participant Vector + participant OpenAI + participant MongoDB + + User->>Frontend: Send message + Frontend->>API: POST /chat + API->>Agent: Process query + + Agent->>GraphRAG: Retrieve context + GraphRAG->>Vector: Vector similarity search + GraphRAG->>Neo4j: Community detection + GraphRAG->>OpenAI: Generate synthesis + GraphRAG->>Agent: Combined context + + Agent->>OpenAI: Generate response + OpenAI->>Agent: Response + reasoning + + Agent->>API: Structured response + API->>MongoDB: Store conversation + API->>Frontend: Response with sources/images + Frontend->>User: Display response +``` + +### Document Processing Flow + +```mermaid +flowchart TD + UPLOAD[Document Upload] --> PARSE[LlamaParse Processing] + PARSE --> EXTRACT[Extract Text + Images] + EXTRACT --> SPLIT[Semantic Splitting] + SPLIT --> EMBED[Generate Embeddings] + EMBED --> VECTOR[Store in Vector Index] + SPLIT --> GRAPH[Extract Entities/Relations] + GRAPH --> NEO4J[Store in Neo4j] + EXTRACT --> IMAGES[Save Page Images] + IMAGES --> STORAGE[File Storage] + NEO4J --> COMMUNITY[Community Detection] + COMMUNITY --> CACHE[Cache Communities] +``` + +--- + +## Database Design + +### Neo4j Knowledge Graph Schema + +```mermaid +erDiagram + Entity { + string name + string label + string description + dict properties + } + + Relation { + string label + string source_id + string target_id + string description + dict properties + } + + Community { + int community_id + text summary + list entity_ids + } + + Entity ||--o{ Relation : participates_in + Community ||--o{ Entity : contains +``` + +### MongoDB Collections Schema + +```mermaid +erDiagram + Users { + ObjectId _id + string username + string email + datetime created_at + datetime last_login + } + + Conversations { + ObjectId _id + string session_id + ObjectId user_id + string title + datetime created_at + datetime last_updated + boolean is_deleted + } + + Messages { + ObjectId _id + ObjectId conversation_id + string role + text content + array sources + array reasoning + array images + datetime timestamp + } + + Users ||--o{ Conversations : owns + Conversations ||--o{ Messages : contains +``` + +--- + +## API Reference + +### Authentication +All API endpoints require authentication via `X-MS-USERNAME` header (except in development mode). + +### Core Endpoints + +#### POST /chat +Processes chat messages and returns AI responses. + +**Request:** +```json +{ + "message": "string", + "sessionId": "string" +} +``` + +**Response:** +```json +{ + "status": "success", + "data": { + "response": "string", + "sources": [ + { + "content": "string", + "tool_name": "string", + "retrieval_method": "vector_only|graphrag_hybrid" + } + ], + "reasoning": [ + { + "type": "ActionReasoningStep|ObservationReasoningStep", + "action": "string", + "observation": "string" + } + ], + "images": [ + { + "filename": "string", + "document": "string", + "page": "number", + "url_encoded_filename": "string" + } + ] + } +} +``` + +#### GET /status +Returns system initialization status. + +**Response:** +```json +{ + "global_status": "initialized", + "initialized": true, + "timestamp": "2024-01-01T00:00:00.000Z" +} +``` + +#### GET /conversations +Retrieves user's conversation history. + +**Response:** +```json +{ + "status": "success", + "conversations": [ + { + "id": "string", + "title": "string", + "created_at": "datetime", + "last_updated": "datetime", + "session_id": "string" + } + ] +} +``` + +#### GET /conversations/{id}/messages +Retrieves messages for a specific conversation. + +**Response:** +```json +{ + "status": "success", + "conversation_title": "string", + "messages": [ + { + "id": "string", + "role": "user|assistant", + "content": "string", + "timestamp": "datetime", + "sources": [], + "reasoning": [], + "images": [] + } + ] +} +``` + +#### GET /images/{filename} +Serves processed document images. + +#### POST /reset +Resets the global agent's conversation memory. + +#### DELETE /conversations/{id} +Deletes a conversation (soft delete by default). + +--- + +## User Flow + +```mermaid +flowchart TD + START([User Access]) --> AUTH{Authenticated?} + AUTH -->|No| LOGIN[MSAL Login] + LOGIN --> AUTH + AUTH -->|Yes| LOAD[Load Conversations] + + LOAD --> NEWCHAT[Create New Chat] + NEWCHAT --> INTERFACE[Chat Interface] + + INTERFACE --> INPUT[User Input] + INPUT --> PROCESS[Process with GraphRAG] + PROCESS --> RETRIEVE[Hybrid Retrieval] + RETRIEVE --> GENERATE[Generate Response] + GENERATE --> DISPLAY[Display with Images] + DISPLAY --> INPUT + + DISPLAY --> SAVE[Save to History] + SAVE --> UPDATE[Update Conversation] + + INTERFACE --> HISTORY[View History] + HISTORY --> SELECT[Select Conversation] + SELECT --> LOAD_MSG[Load Messages] + LOAD_MSG --> INTERFACE + + INTERFACE --> EXPORT[Export Brief] + INTERFACE --> DELETE[Delete Conversation] +``` + +### Detailed User Journey + +1. **Authentication**: User logs in via Microsoft MSAL +2. **Conversation Creation**: System creates new conversation or loads existing +3. **Query Processing**: + - User sends message + - GraphRAG performs hybrid retrieval + - Vector similarity search finds relevant chunks + - Knowledge graph identifies related communities + - LLM synthesizes response with reasoning +4. **Response Display**: + - Text response with markdown support + - Source attribution tooltips + - Relevant document images + - Reasoning chain (if available) +5. **History Management**: Conversations persisted and retrievable + +--- + +## Security + +### Authentication +- Microsoft Authentication Library (MSAL) integration +- Azure AD tenant-based access control +- Session-based user identification + +### Data Protection +- No sensitive data logged in plain text +- Conversation data encrypted at rest (MongoDB) +- API key management via environment variables +- CORS configuration for cross-origin requests + +### Access Control +- User-scoped conversation access +- Session-based authorization +- Development vs production mode differentiation + +--- + +## Deployment + +### Environment Configuration + +#### Backend (.env) +```bash +# API Keys +OPENAI_API_KEY=your_openai_key +LLAMA_CLOUD_API_KEY=your_llama_cloud_key +ANTHROPIC_API_KEY=your_anthropic_key + +# Database Configuration +NEO4J_URL=bolt://localhost:7688 +NEO4J_USERNAME=neo4j +NEO4J_PASSWORD=hp-graphrag-2024 + +# Server Configuration +PORT=8746 +PRODUCTION=true +LOG_LEVEL=INFO +``` + +#### Frontend (.env) +```bash +VITE_BACKEND_URL=https://ai-sandbox.oliver.solutions/hp_chatbot_back +VITE_APP_BASE_URL=/hp_chatbot/ +``` + +### Deployment Steps + +1. **Database Setup**: + - Neo4j instance on port 7688 + - MongoDB with authentication + - Initialize collections via `init_mongodb.py` + +2. **Backend Deployment**: + ```bash + pip install -r requirements.txt + python main.py + ``` + +3. **Frontend Build**: + ```bash + cd chat-interface + npm install + npm run build + # Deploy dist/ contents to /hp_chatbot/ path + ``` + +4. **Web Server Configuration**: + - Configure reverse proxy (nginx/Apache) + - Set up SSL certificates + - Configure CORS origins + +--- + +## Development + +### Backend Development + +```bash +# Setup virtual environment +python -m venv env +source env/bin/activate # or env\Scripts\activate on Windows + +# Install dependencies +pip install -r requirements.txt + +# Start development server +python main.py +``` + +### Frontend Development + +```bash +cd chat-interface +npm install +npm run dev +``` + +### Key Development Commands + +| Command | Purpose | +|---------|---------| +| `python main.py` | Start backend server | +| `npm run dev` | Start frontend dev server | +| `npm run build` | Build frontend for production | +| `npm run lint` | Lint frontend code | + +### Code Structure + +``` +hp_graphRAG_bot/ +├── Backend (Python) +│ ├── main.py # Application entry point +│ ├── ai_core.py # Core AI engine & ReAct agent +│ ├── graph_rag_integration.py # GraphRAG system +│ ├── routes.py # Flask API routes +│ ├── session_manager.py # Session management +│ ├── mongodb_utils.py # MongoDB operations +│ ├── config.py # Configuration +│ └── shared_state.py # Global state management +├── Frontend (React) +│ └── chat-interface/ +│ ├── src/ +│ │ ├── App.jsx # Main application component +│ │ ├── components/ # React components +│ │ ├── auth.js # MSAL authentication +│ │ └── lib/ # Utilities +│ └── dist/ # Production build +└── Data Storage + ├── uploads/images/ # Processed document images + ├── index_storage/ # Vector index data + └── supporting_files/ # Source documents +``` + +--- + +## Troubleshooting + +### Common Issues + +#### Backend Issues + +**Problem**: `Global workflow agent not initialized` +**Solution**: Check OpenAI API key and Neo4j connectivity +```bash +# Verify environment variables +echo $OPENAI_API_KEY +# Check Neo4j connection +curl http://localhost:7474 +``` + +**Problem**: `LlamaParse timeout during document processing` +**Solution**: Increase timeout settings in config.py +```python +LLAMA_PARSE_MAX_TIMEOUT = 7200 # 2 hours +``` + +**Problem**: `MongoDB connection failed` +**Solution**: Verify MongoDB service and credentials +```bash +# Check MongoDB status +brew services list | grep mongodb +# Test connection +mongosh mongodb://hp:hp@localhost:27017/hp_chatbot +``` + +#### Frontend Issues + +**Problem**: `CORS policy blocking requests` +**Solution**: Update CORS_ALLOWED_ORIGINS in backend config.py + +**Problem**: `Authentication failures` +**Solution**: Verify MSAL configuration and Azure AD settings + +**Problem**: `Images not loading` +**Solution**: Check image file paths and backend /images/ endpoint + +### Debug Endpoints + +**Development Mode Only:** +- `GET /debug-status` - System state inspection +- `POST /reinitialize` - Force agent reinitialization +- `POST /capture-screenshot` - Manual image extraction testing + +### Logging + +All components use structured logging: +```python +log_structured('info', 'Event description', {'key': 'value'}) +``` + +Log files locations: +- Backend: `app.log` +- MongoDB operations: `mongodb.log` + +--- + +## Performance Considerations + +### Scaling +- **Vector Index**: Consider PostgreSQL pgvector for large deployments +- **Neo4j**: Implement read replicas for query scaling +- **MongoDB**: Use connection pooling and sharding +- **Caching**: Redis for session and community caches + +### Optimization +- **GraphRAG Communities**: Pre-computed and cached +- **Image Processing**: Async processing with queue system +- **Memory Management**: Agent memory reset policies +- **Response Time**: Parallel vector and graph retrieval + +--- + +## Future Enhancements + +### Planned Features +1. **Multi-tenant Architecture**: Support multiple organizations +2. **Advanced Analytics**: Usage metrics and conversation insights +3. **Enhanced Multimodal**: Video and audio processing +4. **Real-time Collaboration**: Multi-user conversations +5. **API Extensions**: Webhook integrations and external tool calling +6. **Advanced Security**: Role-based access control and audit logging + +### Technical Debt +- Implement comprehensive test suite +- Add API rate limiting +- Improve error handling consistency +- Optimize database queries +- Add health check endpoints + +--- + +*Documentation Version: 1.0* +*Last Updated: 2024-01-01* +*System Version: HP GraphRAG Chatbot v1.0* \ No newline at end of file diff --git a/document_generator.py b/document_generator.py new file mode 100644 index 0000000..87a922b --- /dev/null +++ b/document_generator.py @@ -0,0 +1,339 @@ +# hp_chatbot/document_generator.py + +import io +import re +import markdown2 +from bs4 import BeautifulSoup +from docx import Document +from docx.shared import Inches, Pt, RGBColor +from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_BREAK +from docx.oxml.shared import OxmlElement, qn +from docx.oxml import parse_xml + +from utils import log_structured + +# --- Helper for Horizontal Line --- +def add_horizontal_line(paragraph): + """Adds a horizontal line after the specified paragraph.""" + p = paragraph._p # the lxml element beneath the paragraph + pPr = p.get_or_add_pPr() # Get or add paragraph properties element + pBdr = OxmlElement('w:pBdr') # Create paragraph border element + # Add a bottom border + bottom_bdr = OxmlElement('w:bottom') + bottom_bdr.set(qn('w:val'), 'single') # Border style + bottom_bdr.set(qn('w:sz'), '6') # Border size (in 1/8 points) + bottom_bdr.set(qn('w:space'), '1') # Space between text and border + bottom_bdr.set(qn('w:color'), 'auto') # Border color + pBdr.append(bottom_bdr) + pPr.append(pBdr) + +# --- Inline Markdown to DOCX Run Formatting --- +def process_inline_formatting(paragraph, text): + """ + Processes simple inline markdown (bold, italic, code) within text + and adds formatted runs to the paragraph. + Handles nested formatting cautiously. + """ + # Regex to find **bold**, *italic*, _italic_, `code` segments + # It captures the marker and the content separately. + pattern = r'(\*\*|`|\*|_)(.*?)(\1)' + last_end = 0 + + for match in re.finditer(pattern, text): + start, end = match.span() + marker = match.group(1) + content = match.group(2) + + # Add preceding text if any + if start > last_end: + paragraph.add_run(text[last_end:start]) + + # Add formatted run + run = paragraph.add_run(content) + if marker == '**': + run.bold = True + elif marker == '*' or marker == '_': + run.italic = True + elif marker == '`': + run.font.name = 'Courier New' + # run.font.size = Pt(10) # Optional: Set size for code + + last_end = end + + # Add any remaining text after the last match + if last_end < len(text): + paragraph.add_run(text[last_end:]) + + +# --- HTML to DOCX Conversion --- +def convert_html_to_docx(doc: Document, html_content: str): + """ + Converts basic HTML content (from markdown conversion) to Word elements. + Handles common tags like paragraphs, headings, lists, bold, italic, code. + """ + # Pre-process HTML slightly for cleaner parsing + html_content = re.sub(r'\s*\n\s*', '\n', html_content).strip() # Normalize whitespace + html_content = f"{html_content}" # Wrap in body for better parsing + soup = BeautifulSoup(html_content, 'html.parser') + + # Recursive function to handle elements + def process_element(element, current_paragraph=None, current_style=None, in_list=False): + # Skip NavigableString if it's just whitespace or newline outside pre + if isinstance(element, str): + text = str(element).strip('\n') # Keep internal spaces, strip leading/trailing newlines + if text: # Only add if there's actual content + if current_paragraph: + run = current_paragraph.add_run(text) + if current_style: + if 'bold' in current_style: run.bold = True + if 'italic' in current_style: run.italic = True + if 'code' in current_style: run.font.name = 'Courier New' + else: + # Text outside paragraph usually means an error or whitespace + # log_structured('debug', f"Orphan text node found: '{text[:50]}...'") + pass # Or create a default paragraph: doc.add_paragraph(text) + return + + # --- Block Level Elements --- + if element.name in ['p', 'div']: + # Avoid creating paragraphs for empty containers unless they contain
+ text_content = element.get_text(strip=True) + has_br = element.find('br') + if text_content or has_br: + para = doc.add_paragraph() + # Apply list indentation if necessary (though lists handle their own paras) + # if in_list: para.paragraph_format.left_indent = Inches(0.5) + new_style = current_style.copy() if current_style else set() + for child in element.children: + process_element(child, para, new_style, in_list) + # else: skip empty p/div + + elif element.name in ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']: + try: + level = int(element.name[1]) + heading = doc.add_heading(level=level) + # Process children for inline formatting within heading + new_style = current_style.copy() if current_style else set() + for child in element.children: + process_element(child, heading, new_style, in_list) + # If no children processed (just text), add it directly + if not heading.runs: + heading.add_run(element.get_text(strip=True)) + except ValueError: pass # Should not happen with h1-h6 + + elif element.name == 'ul': + for li in element.find_all('li', recursive=False): + # Each li gets its own paragraph with bullet style + para = doc.add_paragraph(style='List Bullet') + new_style = current_style.copy() if current_style else set() + for child in li.children: + process_element(child, para, new_style, in_list=True) + # If li was empty or only contained whitespace + if not para.text.strip(): + para.text = "" # Ensure empty bullet point exists + + elif element.name == 'ol': + # Numbering is handled by the 'List Number' style + for li in element.find_all('li', recursive=False): + para = doc.add_paragraph(style='List Number') + new_style = current_style.copy() if current_style else set() + for child in li.children: + process_element(child, para, new_style, in_list=True) + if not para.text.strip(): + para.text = "" # Ensure empty numbered item exists + + # Note: 'li' is handled within 'ul'/'ol' processing. + + elif element.name == 'pre': + # Often contains a 'code' element, handle that + code_tag = element.find('code') + content = code_tag.get_text() if code_tag else element.get_text() + if content.strip(): + para = doc.add_paragraph(style='CodeStyle') # Requires 'CodeStyle' to be defined + # Preserve whitespace more carefully for

+                  run = para.add_run(content.strip('\n')) # Strip outer newlines only
+                  run.font.name = 'Courier New'
+                  # run.font.size = Pt(10)
+
+        elif element.name == 'blockquote':
+              para = doc.add_paragraph(style='Quote') # Requires 'Quote' style
+              new_style = current_style.copy() if current_style else set()
+              for child in element.children:
+                  process_element(child, para, new_style, in_list)
+
+        elif element.name == 'hr':
+             para = doc.add_paragraph()
+             add_horizontal_line(para)
+
+        elif element.name == 'br':
+            if current_paragraph:
+                current_paragraph.add_run().add_break() # Add line break within paragraph
+
+
+        # --- Inline Elements ---
+        elif element.name in ['strong', 'b']:
+            new_style = current_style.copy() if current_style else set()
+            new_style.add('bold')
+            for child in element.children:
+                process_element(child, current_paragraph, new_style, in_list)
+
+        elif element.name in ['em', 'i']:
+            new_style = current_style.copy() if current_style else set()
+            new_style.add('italic')
+            for child in element.children:
+                process_element(child, current_paragraph, new_style, in_list)
+
+        elif element.name == 'code':
+            # Handle inline code - assumes it's within a paragraph already
+            if current_paragraph:
+                text = element.get_text()
+                if text:
+                    run = current_paragraph.add_run(text)
+                    run.font.name = 'Courier New'
+                    # Add specific inline code style if desired
+            else:
+                 # Code tag not within a paragraph? Create one.
+                 para = doc.add_paragraph(style='CodeStyle')
+                 run = para.add_run(element.get_text())
+                 run.font.name = 'Courier New'
+
+
+        elif element.name == 'a':
+            # Add hyperlink if possible, otherwise just text
+            text = element.get_text(strip=True)
+            href = element.get('href')
+            if current_paragraph and text:
+                # python-docx doesn't have direct hyperlink support easily added here.
+                # Simplest: add text with underline and blue color.
+                run = current_paragraph.add_run(text)
+                run.underline = True
+                run.font.color.rgb = RGBColor(0x05, 0x63, 0xC1) # Standard link blue
+                # For actual hyperlinks, more complex XML manipulation is needed.
+
+
+        # --- Body/Other Tags: Process children ---
+        elif element.name in ['body', 'span', 'div']: # Treat span/div mostly as containers
+            new_style = current_style.copy() if current_style else set()
+            for child in element.children:
+                 process_element(child, current_paragraph, new_style, in_list)
+
+        # --- Ignored Tags ---
+        elif element.name in ['script', 'style', 'head', 'meta', 'title']:
+             pass # Ignore these tags and their content
+
+        else:
+            # Unknown tag: try to process its children if it's a container,
+            # or add its text content if it's inline-like.
+            log_structured('warning', f"Unhandled HTML tag encountered: <{element.name}>", {'content_preview': element.get_text(strip=True)[:50]})
+            # Default behavior: process children recursively
+            new_style = current_style.copy() if current_style else set()
+            for child in element.children:
+                 process_element(child, current_paragraph, new_style, in_list)
+
+
+    # Start processing from the top-level elements within the parsed body
+    body = soup.find('body')
+    if body:
+        for element in body.children:
+            process_element(element)
+
+
+# --- Main Markdown to DOCX Function ---
+def create_brief_docx(brief_content_markdown: str) -> io.BytesIO:
+    """
+    Creates a Word document (.docx) in memory from markdown content.
+
+    Args:
+        brief_content_markdown: The markdown string content.
+
+    Returns:
+        An io.BytesIO buffer containing the Word document.
+    """
+    doc = Document()
+
+    # --- Define Styles (Optional but recommended) ---
+    styles = doc.styles
+    # Normal style
+    style = styles['Normal']
+    font = style.font
+    font.name = 'Calibri' # Or HP specific font if available
+    font.size = Pt(11)
+
+    # Code style (example)
+    try:
+        code_style = styles.add_style('CodeStyle', 1) # 1 for paragraph style
+        code_style.font.name = 'Courier New'
+        code_style.font.size = Pt(10)
+        # Prevent spell check for code blocks
+        code_style.element.rPr.rFonts.set(qn('w:ascii'), 'Courier New')
+        code_style.element.rPr.rFonts.set(qn('w:hAnsi'), 'Courier New')
+        # code_style.element.xpath('./w:rPr/w:lang')[0].set(qn('w:noProof'), '1') # Requires lxml maybe
+        p_fmt = code_style.paragraph_format
+        p_fmt.space_before = Pt(6)
+        p_fmt.space_after = Pt(6)
+    except ValueError:
+         log_structured('warning', "'CodeStyle' already exists. Using existing.")
+         code_style = styles['CodeStyle'] # Use existing if it fails to add
+
+    # Quote style (example)
+    try:
+         quote_style = styles.add_style('QuoteStyle', 1)
+         quote_style.font.italic = True
+         quote_style.paragraph_format.left_indent = Inches(0.5)
+         quote_style.paragraph_format.space_before = Pt(6)
+         quote_style.paragraph_format.space_after = Pt(6)
+    except ValueError:
+         log_structured('warning', "'QuoteStyle' already exists. Using existing.")
+         quote_style = styles['QuoteStyle']
+
+
+    # --- Document Header ---
+    title = doc.add_heading('Marketing Brief', 0)
+    title.alignment = WD_ALIGN_PARAGRAPH.CENTER
+
+    date_para = doc.add_paragraph()
+    date_para.alignment = WD_ALIGN_PARAGRAPH.RIGHT
+    date_run = date_para.add_run(datetime.now().strftime("%B %d, %Y"))
+    date_run.italic = True
+    # Add some space after date
+    date_para.paragraph_format.space_after = Pt(12)
+
+    # Add a horizontal line separator
+    hr_para = doc.add_paragraph()
+    add_horizontal_line(hr_para)
+    hr_para.paragraph_format.space_after = Pt(18) # Space after the line
+
+
+    # --- Convert Markdown to HTML ---
+    # Using markdown2 with recommended extras for broad compatibility
+    extras = [
+        "tables", "fenced-code-blocks", "header-ids", "footnotes",
+        "task_list", "code-friendly", "cuddled-lists", "markdown-in-html",
+        "strike", "spoiler", "target-blank-links", "smarty-pants" # Added smarty-pants
+    ]
+    html_content = markdown2.markdown(brief_content_markdown, extras=extras)
+
+    log_structured('debug', 'Converted markdown to HTML for DOCX generation', {
+        'md_preview': brief_content_markdown[:200],
+        'html_preview': html_content[:300]
+    })
+
+    # --- Convert HTML to Word Document Elements ---
+    try:
+        convert_html_to_docx(doc, html_content)
+    except Exception as conversion_err:
+         log_structured('error', "Error during HTML to DOCX conversion", {
+             'error': str(conversion_err),
+             'traceback': traceback.format_exc()
+         })
+         # Add error message to the document itself
+         doc.add_paragraph("Error: Could not fully convert content from HTML to DOCX.", style='Emphasis')
+         doc.add_paragraph(str(conversion_err))
+
+
+    # --- Save to Buffer ---
+    doc_buffer = io.BytesIO()
+    doc.save(doc_buffer)
+    doc_buffer.seek(0)
+
+    return doc_buffer
\ No newline at end of file
diff --git a/graphRAG.py b/graphRAG.py
new file mode 100644
index 0000000..c28b533
--- /dev/null
+++ b/graphRAG.py
@@ -0,0 +1,581 @@
+import os
+import json
+import re
+import asyncio
+import networkx as nx
+from collections import defaultdict
+from typing import Any, List, Callable, Optional, Union, Dict
+from dotenv import load_dotenv
+
+# Import LlamaIndex components
+from llama_index.core import Document, Settings
+from llama_index.core.node_parser import SentenceSplitter
+from llama_index.core import PropertyGraphIndex
+from llama_index.core.async_utils import run_jobs
+from llama_index.core.indices.property_graph.utils import default_parse_triplets_fn
+from llama_index.core.graph_stores.types import EntityNode, KG_NODES_KEY, KG_RELATIONS_KEY, Relation
+from llama_index.core.llms.llm import LLM
+from llama_index.core.prompts import PromptTemplate
+from llama_index.core.prompts.default_prompts import DEFAULT_KG_TRIPLET_EXTRACT_PROMPT
+from llama_index.core.schema import TransformComponent, BaseNode
+from llama_index.core.query_engine import CustomQueryEngine
+from llama_index.llms.openai import OpenAI
+from llama_index.core.llms import ChatMessage
+from llama_index.graph_stores.neo4j import Neo4jPropertyGraphStore
+from llama_index.core import SimpleDirectoryReader
+
+# Community detection (using NetworkX instead of graspologic as a fallback)
+try:
+    from community import best_partition  # python-louvain package
+except ImportError:
+    print("Community detection package not found, using NetworkX built-in community detection")
+
+# Load environment variables from .env file
+load_dotenv()
+
+# Use API key from environment as fallback
+if not os.environ.get("OPENAI_API_KEY"):
+    os.environ["OPENAI_API_KEY"] = "sk-proj-wXcoIn81Vwg4Iaw0vhmYT3BlbkFJmt1eOxeEAF1juUfhzMtk"
+
+# Define the GraphRAGExtractor class
+class GraphRAGExtractor(TransformComponent):
+    """Extract triples from a graph.
+
+    Uses an LLM and a simple prompt + output parsing to
+    extract paths (i.e. triples) and entity, relation descriptions
+    from text.
+
+    Args:
+        llm (LLM):
+            The language model to use.
+        extract_prompt (Union[str, PromptTemplate]):
+            The prompt to use for extracting triples.
+        parse_fn (callable):
+            A function to parse the output of the language
+            model.
+        num_workers (int):
+            The number of workers to use for parallel
+            processing.
+        max_paths_per_chunk (int):
+            The maximum number of paths to extract per chunk.
+    """
+
+    llm: LLM
+    extract_prompt: PromptTemplate
+    parse_fn: Callable
+    num_workers: int
+    max_paths_per_chunk: int
+
+    def __init__(
+        self,
+        llm: Optional[LLM] = None,
+        extract_prompt: Optional[Union[str, PromptTemplate]] = None,
+        parse_fn: Callable = default_parse_triplets_fn,
+        max_paths_per_chunk: int = 10,
+        num_workers: int = 4,
+    ) -> None:
+        """Init params."""
+        from llama_index.core import Settings
+
+        if isinstance(extract_prompt, str):
+            extract_prompt = PromptTemplate(extract_prompt)
+
+        super().__init__(
+            llm=llm or Settings.llm,
+            extract_prompt=extract_prompt or DEFAULT_KG_TRIPLET_EXTRACT_PROMPT,
+            parse_fn=parse_fn,
+            num_workers=num_workers,
+            max_paths_per_chunk=max_paths_per_chunk,
+        )
+
+    @classmethod
+    def class_name(cls) -> str:
+        return "GraphExtractor"
+
+    def __call__(
+        self, nodes: List[BaseNode], show_progress: bool = False, **kwargs: Any
+    ) -> List[BaseNode]:
+        """Extract triples from nodes."""
+        return asyncio.run(
+            self.acall(nodes, show_progress=show_progress, **kwargs)
+        )
+
+    async def _aextract(self, node: BaseNode) -> BaseNode:
+        """Extract triples from a node."""
+        assert hasattr(node, "text")
+
+        text = node.get_content(metadata_mode="llm")
+        try:
+            llm_response = await self.llm.apredict(
+                self.extract_prompt,
+                text=text,
+                max_knowledge_triplets=self.max_paths_per_chunk,
+            )
+            entities, entities_relationship = self.parse_fn(llm_response)
+        except ValueError:
+            entities = []
+            entities_relationship = []
+
+        existing_nodes = node.metadata.pop(KG_NODES_KEY, [])
+        existing_relations = node.metadata.pop(KG_RELATIONS_KEY, [])
+        
+        entity_metadata = node.metadata.copy()
+        for entity, entity_type, description in entities:
+            entity_metadata["entity_description"] = description
+            entity_node = EntityNode(
+                name=entity, label=entity_type,
+                properties=entity_metadata
+            )
+            existing_nodes.append(entity_node)
+
+        relation_metadata = node.metadata.copy()
+        for triple in entities_relationship:
+            subj, obj, rel, description = triple
+            relation_metadata["relationship_description"] = description
+            rel_node = Relation(
+                label=rel,
+                source_id=subj,
+                target_id=obj,
+                properties=relation_metadata,
+            )
+            existing_relations.append(rel_node)
+
+        node.metadata[KG_NODES_KEY] = existing_nodes
+        node.metadata[KG_RELATIONS_KEY] = existing_relations
+        return node
+
+    async def acall(
+        self, nodes: List[BaseNode], show_progress: bool = False, **kwargs: Any
+    ) -> List[BaseNode]:
+        """Extract triples from nodes async."""
+        jobs = []
+        for node in nodes:
+            jobs.append(self._aextract(node))
+
+        return await run_jobs(
+            jobs,
+            workers=self.num_workers,
+            show_progress=show_progress,
+            desc="Extracting paths from text",
+        )
+
+# Define the GraphRAGStore class
+class GraphRAGStore(Neo4jPropertyGraphStore):
+    community_summary = {}
+    entity_info = None
+    max_cluster_size = 5
+
+    def generate_community_summary(self, text):
+        """Generate summary for a given text using an LLM."""
+        messages = [
+            ChatMessage(
+                role="system",
+                content=(
+                    "You are provided with a set of "
+                    "relationships from a knowledge graph, each represented as "
+                    "entity1->entity2->relation-"
+                    ">relationship_description. Your task is to create a summary of "
+                    "these "
+                    "relationships. The summary should include "
+                    "the names of the entities involved and a concise synthesis "
+                    "of the relationship descriptions. The "
+                    "goal is to capture the most critical and relevant details that "
+                    "highlight the nature and significance of "
+                    "each relationship. Ensure that the summary is coherent and "
+                    "integrates the information in a way that "
+                    "emphasizes the key aspects of the relationships."
+                ),
+            ),
+            ChatMessage(role="user", content=text),
+        ]
+        response = OpenAI().chat(messages)
+        clean_response = re.sub(r"^assistant:\s*", "", str(response)).strip()
+        return clean_response
+
+    def build_communities(self):
+        """Builds communities from the graph and summarizes them."""
+        nx_graph = self._create_nx_graph()
+        
+        # Use either Leiden algorithm (from graspologic) or an alternative
+        try:
+            from graspologic.partition import hierarchical_leiden
+            community_hierarchical_clusters = hierarchical_leiden(
+                nx_graph, max_cluster_size=self.max_cluster_size
+            )
+            self.entity_info, community_info = self._collect_community_info(
+                nx_graph, community_hierarchical_clusters
+            )
+        except ImportError:
+            # Fallback to community detection using NetworkX or python-louvain
+            try:
+                from community import best_partition
+                partition = best_partition(nx_graph)
+                # Reformat partition data to expected structure
+                clusters = []
+                for node, cluster_id in partition.items():
+                    class Cluster:
+                        def __init__(self, node, cluster):
+                            self.node = node
+                            self.cluster = cluster
+                    clusters.append(Cluster(node, cluster_id))
+                self.entity_info, community_info = self._collect_community_info(
+                    nx_graph, clusters
+                )
+            except ImportError:
+                # Use NetworkX's built-in community detection
+                from networkx.algorithms import community
+                communities = community.greedy_modularity_communities(nx_graph)
+                clusters = []
+                for i, comm in enumerate(communities):
+                    for node in comm:
+                        class Cluster:
+                            def __init__(self, node, cluster):
+                                self.node = node
+                                self.cluster = cluster
+                        clusters.append(Cluster(node, i))
+                self.entity_info, community_info = self._collect_community_info(
+                    nx_graph, clusters
+                )
+                
+        self._summarize_communities(community_info)
+
+    def _create_nx_graph(self):
+        """Converts internal graph representation to NetworkX graph."""
+        nx_graph = nx.Graph()
+        triplets = self.get_triplets()
+        for entity1, relation, entity2 in triplets:
+            nx_graph.add_node(entity1.name)
+            nx_graph.add_node(entity2.name)
+            nx_graph.add_edge(
+                relation.source_id,
+                relation.target_id,
+                relationship=relation.label,
+                description=relation.properties.get("relationship_description", "No description provided"),
+            )
+        return nx_graph
+
+    def _collect_community_info(self, nx_graph, clusters):
+        """
+        Collect information for each node based on their community,
+        allowing entities to belong to multiple clusters.
+        """
+        entity_info = defaultdict(set)
+        community_info = defaultdict(list)
+
+        for item in clusters:
+            node = item.node
+            cluster_id = item.cluster
+
+            # Update entity_info
+            entity_info[node].add(cluster_id)
+
+            for neighbor in nx_graph.neighbors(node):
+                edge_data = nx_graph.get_edge_data(node, neighbor)
+                if edge_data:
+                    detail = f"{node} -> {neighbor} -> {edge_data['relationship']} -> {edge_data['description']}"
+                    community_info[cluster_id].append(detail)
+
+        # Convert sets to lists for easier serialization if needed
+        entity_info = {k: list(v) for k, v in entity_info.items()}
+
+        return dict(entity_info), dict(community_info)
+
+    def _summarize_communities(self, community_info):
+        """Generate and store summaries for each community."""
+        for community_id, details in community_info.items():
+            details_text = "\n".join(details) + "." # Ensure it ends with a period
+            self.community_summary[community_id] = self.generate_community_summary(details_text)
+
+    def get_community_summaries(self):
+        """Returns the community summaries, building them if not already done."""
+        if not self.community_summary:
+            self.build_communities()
+        return self.community_summary
+
+# Define the GraphRAGQueryEngine class
+class GraphRAGQueryEngine(CustomQueryEngine):
+    graph_store: Union[GraphRAGStore, Any]  # Accept any type of graph store
+    index: PropertyGraphIndex
+    llm: LLM
+    similarity_top_k: int = 20
+
+    def custom_query(self, query_str: str) -> str:
+        """Process query using either community-based approach or direct retrieval."""
+        # Check if we're using GraphRAGStore with communities or SimplePropertyGraphStore
+        if hasattr(self.graph_store, 'get_community_summaries'):
+            # GraphRAG approach with communities
+            entities = self.get_entities(query_str, self.similarity_top_k)
+            
+            community_ids = self.retrieve_entity_communities(
+                self.graph_store.entity_info, entities
+            )
+            community_summaries = self.graph_store.get_community_summaries()
+            community_answers = [
+                self.generate_answer_from_summary(community_summary, query_str)
+                for id, community_summary in community_summaries.items()
+                if id in community_ids
+            ]
+
+            final_answer = self.aggregate_answers(community_answers)
+            return final_answer
+        else:
+            # Simple approach for SimplePropertyGraphStore
+            # Just get relevant nodes and generate answer
+            nodes = self.index.as_retriever(
+                similarity_top_k=self.similarity_top_k
+            ).retrieve(query_str)
+            
+            if not nodes:
+                return "I couldn't find any relevant information to answer your question."
+            
+            # Combine text from all retrieved nodes
+            context = "\n\n".join([node.get_content() for node in nodes])
+            
+            # Generate answer using the LLM
+            prompt = f"Based on the following information, please answer this question: {query_str}\n\nInformation:\n{context}"
+            messages = [
+                ChatMessage(role="system", content=prompt),
+                ChatMessage(role="user", content="Please provide a comprehensive answer based on the information provided.")
+            ]
+            response = self.llm.chat(messages)
+            return str(response).strip()
+
+    def get_entities(self, query_str, similarity_top_k):
+        nodes_retrieved = self.index.as_retriever(
+            similarity_top_k=similarity_top_k
+        ).retrieve(query_str)
+
+        entities = set()
+        pattern = r"^(\w+(?:\s+\w+)*)\s*->\s*([a-zA-Z\s]+?)\s*->\s*(\w+(?:\s+\w+)*)$"
+
+        for node in nodes_retrieved:
+            matches = re.findall(
+                pattern, node.text, re.MULTILINE | re.IGNORECASE
+            )
+            for match in matches:
+                subject = match[0]
+                obj = match[2]
+                entities.add(subject)
+                entities.add(obj)
+
+        return list(entities)
+
+    def retrieve_entity_communities(self, entity_info, entities):
+        """
+        Retrieve cluster information for given entities,
+        allowing for multiple clusters per entity.
+
+        Args:
+            entity_info (dict): Dictionary mapping entities to their cluster IDs (list).
+            entities (list): List of entity names to retrieve information for.
+
+        Returns:
+            List of community or cluster IDs to which an entity belongs.
+        """
+        community_ids = []
+
+        for entity in entities:
+            if entity in entity_info:
+                community_ids.extend(entity_info[entity])
+
+        return list(set(community_ids))
+
+    def generate_answer_from_summary(self, community_summary, query):
+        """Generate an answer from a community summary based on a given query using LLM."""
+        prompt = (
+            f"Given the community summary: {community_summary}, "
+            f"how would you answer the following query? Query: {query}"
+        )
+        messages = [
+            ChatMessage(role="system", content=prompt),
+            ChatMessage(
+                role="user",
+                content="I need an answer based on the above information.",
+            ),
+        ]
+        response = self.llm.chat(messages)
+        cleaned_response = re.sub(r"^assistant:\s*", "", str(response)).strip()
+        return cleaned_response
+
+    def aggregate_answers(self, community_answers):
+        """Aggregate individual community answers into a final, coherent response."""
+        prompt = "Combine the following intermediate answers into a final, concise response."
+        messages = [
+            ChatMessage(role="system", content=prompt),
+            ChatMessage(
+                role="user",
+                content=f"Intermediate answers: {community_answers}",
+            ),
+        ]
+        final_response = self.llm.chat(messages)
+        cleaned_final_response = re.sub(
+            r"^assistant:\s*", "", str(final_response)
+        ).strip()
+        return cleaned_final_response
+
+def custom_parse_fn(response_str: str) -> Any:
+    """Custom parser for LLM responses that extract entities and relationships"""
+    json_pattern = r"\{.*\}"
+    match = re.search(json_pattern, response_str, re.DOTALL)
+    entities = []
+    relationships = []
+    
+    if not match:
+        return entities, relationships
+    
+    json_str = match.group(0)
+    try:
+        data = json.loads(json_str)
+        entities = [
+            (
+                entity["entity_name"],
+                entity["entity_type"],
+                entity.get("entity_description", f"Description of {entity['entity_name']}"),
+            )
+            for entity in data.get("entities", [])
+        ]
+        relationships = [
+            (
+                relation["source_entity"],
+                relation["target_entity"],
+                relation["relation"],
+                relation.get("relationship_description", f"Relationship between {relation['source_entity']} and {relation['target_entity']}"),
+            )
+            for relation in data.get("relationships", [])
+        ]
+        return entities, relationships
+    except (json.JSONDecodeError, KeyError) as e:
+        print(f"Error parsing response: {e}")
+        print(f"Problematic JSON: {json_str[:200]}...")
+        return entities, relationships
+
+# Define the prompt template for triple extraction
+KG_TRIPLET_EXTRACT_TMPL = """
+-Goal-
+Given a text document, identify all entities and their entity types from the text and all relationships among the identified entities.
+
+Given the text, extract up to {max_knowledge_triplets} entity-relation triplets.
+
+-Steps-
+1. Identify all entities. For each identified entity, extract the following information:
+- entity_name: Name of the entity, capitalized
+- entity_type: Type of the entity
+- entity_description: Comprehensive description of the entity's attributes and activities
+
+2. From the entities identified in step 1, identify all pairs of (source_entity, target_entity) that are *clearly related* to each other.
+For each pair of related entities, extract the following information:
+- source_entity: name of the source entity, as identified in step 1
+- target_entity: name of the target entity, as identified in step 1
+- relation: relationship between source_entity and target_entity
+- relationship_description: explanation as to why you think the source entity and the target entity are related to each other
+
+3. Output Formatting:
+- Return the result in valid JSON format with two keys: 'entities' (list of entity objects) and 'relationships' (list of relationship objects).
+- Exclude any text outside the JSON structure (e.g., no explanations or comments).
+- If no entities or relationships are identified, return empty lists: { "entities": [], "relationships": [] }.
+
+-Real Data-
+######################
+text: {text}
+######################
+output:
+"""
+
+def main():
+    print("Starting GraphRAG document processing...")
+    
+    # Load documents from specified directory
+    documents = SimpleDirectoryReader(
+        input_dir="supporting_files/files_for_rag_store"
+    ).load_data()
+    
+    print(f"Loaded {len(documents)} documents")
+    
+    # Create nodes using a sentence splitter
+    splitter = SentenceSplitter(chunk_size=1024, chunk_overlap=20)
+    nodes = splitter.get_nodes_from_documents(documents)
+    
+    print(f"Created {len(nodes)} nodes from documents")
+    
+    # Initialize the LLM
+    llm = OpenAI(model="gpt-4")
+    
+    # Create the knowledge graph extractor
+    kg_extractor = GraphRAGExtractor(
+        llm=llm,
+        extract_prompt=KG_TRIPLET_EXTRACT_TMPL,
+        max_paths_per_chunk=2,
+        parse_fn=custom_parse_fn,
+    )
+    
+    # Connect to Neo4j running in Docker
+    neo4j_username = "neo4j"
+    neo4j_password = "tavern-easy-museum-arthur-coconut-3483"
+    neo4j_url = "bolt://localhost:7687"
+    
+    print(f"Connecting to Neo4j at {neo4j_url} with username '{neo4j_username}'")
+    
+    # Create GraphRAGStore (our extended Neo4j store)
+    try:
+        graph_store = GraphRAGStore(
+            username=neo4j_username, 
+            password=neo4j_password,
+            url=neo4j_url
+        )
+        print("Successfully connected to Neo4j database")
+    except Exception as e:
+        print(f"Error connecting to Neo4j: {e}")
+        print("Falling back to in-memory graph store. Some features may be limited.")
+        # Fallback to in-memory graph store if Neo4j connection fails
+        from llama_index.core.graph_stores import SimplePropertyGraphStore
+        graph_store = SimplePropertyGraphStore()
+    
+    # Build the index
+    index = PropertyGraphIndex(
+        nodes=nodes,
+        kg_extractors=[kg_extractor],
+        property_graph_store=graph_store,
+        show_progress=True,
+    )
+    
+    print("Building graph communities...")
+    try:
+        # Build communities for graph-based querying
+        # Only for GraphRAGStore, not for SimplePropertyGraphStore
+        if hasattr(graph_store, 'build_communities'):
+            graph_store.build_communities()
+            print("Communities built successfully")
+        else:
+            print("Skipping community building (not using Neo4j)")
+    except Exception as e:
+        print(f"Error building communities: {e}")
+    
+    # Create the query engine
+    query_engine = GraphRAGQueryEngine(
+        graph_store=graph_store,
+        llm=llm,
+        index=index,
+        similarity_top_k=10,
+    )
+    
+    # Simple interactive query loop
+    print("\n--- GraphRAG Query System Ready ---")
+    print("Type 'exit' to quit")
+    
+    while True:
+        query = input("\nEnter your query: ")
+        
+        if query.lower() in ('exit', 'quit'):
+            break
+            
+        try:
+            response = query_engine.custom_query(query)
+            print("\nResponse:")
+            print(response)
+        except Exception as e:
+            print(f"Error processing query: {e}")
+    
+    print("GraphRAG session ended")
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file
diff --git a/graph_rag_integration.py b/graph_rag_integration.py
new file mode 100644
index 0000000..a0dd2e0
--- /dev/null
+++ b/graph_rag_integration.py
@@ -0,0 +1,882 @@
+"""
+HP GraphRAG Integration
+
+Integrates GraphRAG functionality into the HP RAG pipeline.
+- GraphRAG for knowledge graph construction from semantically split nodes
+- Community detection and summarization for improved context retrieval
+"""
+
+import os
+import json
+import re
+import asyncio
+import networkx as nx
+from collections import defaultdict
+from typing import Any, List, Callable, Optional, Union, Dict
+from pathlib import Path
+
+# Import LlamaIndex components
+from llama_index.core import Document, Settings
+from llama_index.core.node_parser import SentenceSplitter
+from llama_index.core import PropertyGraphIndex
+from llama_index.core.async_utils import run_jobs
+from llama_index.core.indices.property_graph.utils import default_parse_triplets_fn
+from llama_index.core.graph_stores.types import EntityNode, KG_NODES_KEY, KG_RELATIONS_KEY, Relation
+from llama_index.core.llms.llm import LLM
+from llama_index.core.prompts import PromptTemplate
+from llama_index.core.prompts.default_prompts import DEFAULT_KG_TRIPLET_EXTRACT_PROMPT
+from llama_index.core.schema import TransformComponent, BaseNode
+from llama_index.core.query_engine import CustomQueryEngine
+from llama_index.llms.openai import OpenAI
+from llama_index.core.llms import ChatMessage
+from llama_index.graph_stores.neo4j import Neo4jPropertyGraphStore
+from llama_index.core import SimpleDirectoryReader
+from llama_index.core.vector_stores.types import VectorStoreInfo, MetadataInfo
+from llama_index.core.retrievers import VectorIndexRetriever
+
+# Community detection (using NetworkX instead of graspologic as a fallback)
+try:
+    from community import best_partition  # python-louvain package
+except ImportError:
+    print("Community detection package not found, using NetworkX built-in community detection")
+
+# Import from our modules
+from utils import logger, log_structured
+from config import NEO4J_URL, NEO4J_USERNAME, NEO4J_PASSWORD
+import config
+
+# Define the GraphRAGExtractor class
+class GraphRAGExtractor(TransformComponent):
+    """Extract triples from a graph.
+
+    Uses an LLM and a simple prompt + output parsing to
+    extract paths (i.e. triples) and entity, relation descriptions
+    from text.
+
+    Args:
+        llm (LLM):
+            The language model to use.
+        extract_prompt (Union[str, PromptTemplate]):
+            The prompt to use for extracting triples.
+        parse_fn (callable):
+            A function to parse the output of the language
+            model.
+        num_workers (int):
+            The number of workers to use for parallel
+            processing.
+        max_paths_per_chunk (int):
+            The maximum number of paths to extract per chunk.
+    """
+
+    llm: LLM
+    extract_prompt: PromptTemplate
+    parse_fn: Callable
+    num_workers: int
+    max_paths_per_chunk: int
+
+    def __init__(
+        self,
+        llm: Optional[LLM] = None,
+        extract_prompt: Optional[Union[str, PromptTemplate]] = None,
+        parse_fn: Callable = default_parse_triplets_fn,
+        max_paths_per_chunk: int = 10,
+        num_workers: int = 8,
+    ) -> None:
+        """Init params."""
+        from llama_index.core import Settings
+
+        if isinstance(extract_prompt, str):
+            extract_prompt = PromptTemplate(extract_prompt)
+
+        super().__init__(
+            llm=llm or Settings.llm,
+            extract_prompt=extract_prompt or DEFAULT_KG_TRIPLET_EXTRACT_PROMPT,
+            parse_fn=parse_fn,
+            num_workers=num_workers,
+            max_paths_per_chunk=max_paths_per_chunk,
+        )
+
+    @classmethod
+    def class_name(cls) -> str:
+        return "GraphExtractor"
+
+    def __call__(
+        self, nodes: List[BaseNode], show_progress: bool = False, **kwargs: Any
+    ) -> List[BaseNode]:
+        """Extract triples from nodes."""
+        return asyncio.run(
+            self.acall(nodes, show_progress=show_progress, **kwargs)
+        )
+
+    async def _aextract(self, node: BaseNode) -> BaseNode:
+        """Extract triples from a node."""
+        assert hasattr(node, "text")
+
+        text = node.get_content(metadata_mode="llm")
+        try:
+            llm_response = await self.llm.apredict(
+                self.extract_prompt,
+                text=text,
+                max_knowledge_triplets=self.max_paths_per_chunk,
+            )
+            entities, entities_relationship = self.parse_fn(llm_response)
+        except ValueError:
+            entities = []
+            entities_relationship = []
+
+        existing_nodes = node.metadata.pop(KG_NODES_KEY, [])
+        existing_relations = node.metadata.pop(KG_RELATIONS_KEY, [])
+        
+        entity_metadata = node.metadata.copy()
+        for entity, entity_type, description in entities:
+            entity_metadata["entity_description"] = description
+            entity_node = EntityNode(
+                name=entity, label=entity_type,
+                properties=entity_metadata
+            )
+            existing_nodes.append(entity_node)
+
+        relation_metadata = node.metadata.copy()
+        for triple in entities_relationship:
+            subj, obj, rel, description = triple
+            relation_metadata["relationship_description"] = description
+            rel_node = Relation(
+                label=rel,
+                source_id=subj,
+                target_id=obj,
+                properties=relation_metadata,
+            )
+            existing_relations.append(rel_node)
+
+        node.metadata[KG_NODES_KEY] = existing_nodes
+        node.metadata[KG_RELATIONS_KEY] = existing_relations
+        return node
+
+    async def acall(
+        self, nodes: List[BaseNode], show_progress: bool = False, **kwargs: Any
+    ) -> List[BaseNode]:
+        """Extract triples from nodes async."""
+        jobs = []
+        for node in nodes:
+            jobs.append(self._aextract(node))
+
+        return await run_jobs(
+            jobs,
+            workers=self.num_workers,
+            show_progress=show_progress,
+            desc="Extracting paths from text",
+        )
+
+# Define the GraphRAGStore class (integrating with Neo4j)
+import pickle
+import os
+from pathlib import Path
+
+class GraphRAGStore:
+    community_summary = {}
+    entity_info = None
+    max_cluster_size = 5
+    property_graph_store = None
+    communities_built = False  # Track if communities have been built
+    
+    # Path for cached community data
+    CACHE_DIR = Path("index_storage/graphrag_cache")
+    COMMUNITY_CACHE_FILE = CACHE_DIR / "community_summary.pickle"
+    ENTITY_INFO_CACHE_FILE = CACHE_DIR / "entity_info.pickle"
+    
+    def __init__(self, property_graph_store):
+        """Initialize with a property_graph_store (Neo4j or in-memory)."""
+        self.property_graph_store = property_graph_store
+        self.community_summary = {}
+        self.entity_info = None
+        self.communities_built = False
+        
+        # Ensure cache directory exists
+        os.makedirs(self.CACHE_DIR, exist_ok=True)
+        
+    def add_nodes(self, nodes):
+        """Add nodes to the property graph store."""
+        return self.property_graph_store.add_nodes(nodes)
+        
+    def add_relationships(self, relationships):
+        """Add relationships to the property graph store."""
+        return self.property_graph_store.add_relationships(relationships)
+    
+    def get_triplets(self):
+        """Get triplets from the property graph store."""
+        return self.property_graph_store.get_triplets()
+
+    def generate_community_summary(self, text):
+        """Generate summary for a given text using an LLM with handling for large contexts."""
+        
+        # Check if text is too long and chunk if needed
+        if len(text) > 30000:  # Approximate character limit
+            log_structured('info', f'Community text is large ({len(text)} chars). Chunking for summarization.')
+            # Split into smaller chunks (simple approach)
+            chunks = [text[i:i+30000] for i in range(0, len(text), 30000)]
+            summaries = []
+            
+            for i, chunk in enumerate(chunks):
+                try:
+                    # Use GPT-4o-mini model for better cost efficiency
+                    llm = OpenAI(model="gpt-4o-mini")
+                    messages = [
+                        ChatMessage(
+                            role="system",
+                            content="Summarize these knowledge graph relationships concisely."
+                        ),
+                        ChatMessage(role="user", content=chunk),
+                    ]
+                    response = llm.chat(messages)
+                    summaries.append(str(response).strip())
+                    log_structured('info', f'Successfully summarized community chunk {i+1}/{len(chunks)}')
+                except Exception as e:
+                    log_structured('error', f'Error summarizing community chunk {i+1}/{len(chunks)}: {e}')
+                    
+            # Then summarize the summaries
+            if summaries:
+                final_summary_text = "\n\n".join(summaries)
+                try:
+                    llm = OpenAI(model="gpt-4o-mini")
+                    messages = [
+                        ChatMessage(
+                            role="system",
+                            content="Create a coherent summary from these partial summaries."
+                        ),
+                        ChatMessage(role="user", content=final_summary_text),
+                    ]
+                    response = llm.chat(messages)
+                    return str(response).strip()
+                except Exception as e:
+                    log_structured('error', f'Error creating final summary from chunks: {e}')
+                    # Return the concatenated summaries if we can't summarize them
+                    return final_summary_text
+            else:
+                return "Unable to generate community summary due to size limitations."
+        
+        # For normal size text, use the larger model directly
+        try:
+            # Use GPT-4o-mini model for better cost efficiency
+            llm = OpenAI(model="gpt-4o-mini")
+            messages = [
+                ChatMessage(
+                    role="system",
+                    content=(
+                        "You are provided with a set of "
+                        "relationships from a knowledge graph, each represented as "
+                        "entity1->entity2->relation-"
+                        ">relationship_description. Your task is to create a summary of "
+                        "these relationships. The summary should include "
+                        "the names of the entities involved and a concise synthesis "
+                        "of the relationship descriptions. The "
+                        "goal is to capture the most critical and relevant details that "
+                        "highlight the nature and significance of "
+                        "each relationship. Ensure that the summary is coherent and "
+                        "integrates the information in a way that "
+                        "emphasizes the key aspects of the relationships."
+                    ),
+                ),
+                ChatMessage(role="user", content=text),
+            ]
+            response = llm.chat(messages)
+            clean_response = re.sub(r"^assistant:\s*", "", str(response)).strip()
+            return clean_response
+        except Exception as e:
+            log_structured('error', f'Error generating community summary: {e}')
+            return f"Error summarizing community: {str(e)}"
+
+    def build_communities(self):
+        """Builds communities from the graph and summarizes them."""
+        # Skip if communities are already built in this session
+        if self.communities_built:
+            log_structured('info', 'Communities already built in this session, skipping rebuild')
+            return
+            
+        # First check if we can load from cache
+        if self.load_from_cache():
+            log_structured('info', 'Using cached community data instead of rebuilding')
+            self.communities_built = True
+            return
+            
+        log_structured('info', 'Building communities from graph data')
+        nx_graph = self._create_nx_graph()
+        
+        # Use either Leiden algorithm (from graspologic) or an alternative
+        try:
+            from graspologic.partition import hierarchical_leiden
+            community_hierarchical_clusters = hierarchical_leiden(
+                nx_graph, max_cluster_size=self.max_cluster_size
+            )
+            self.entity_info, community_info = self._collect_community_info(
+                nx_graph, community_hierarchical_clusters
+            )
+        except ImportError:
+            # Fallback to community detection using NetworkX or python-louvain
+            try:
+                from community import best_partition
+                partition = best_partition(nx_graph)
+                # Reformat partition data to expected structure
+                clusters = []
+                for node, cluster_id in partition.items():
+                    class Cluster:
+                        def __init__(self, node, cluster):
+                            self.node = node
+                            self.cluster = cluster
+                    clusters.append(Cluster(node, cluster_id))
+                self.entity_info, community_info = self._collect_community_info(
+                    nx_graph, clusters
+                )
+            except ImportError:
+                # Use NetworkX's built-in community detection
+                from networkx.algorithms import community
+                communities = community.greedy_modularity_communities(nx_graph)
+                clusters = []
+                for i, comm in enumerate(communities):
+                    for node in comm:
+                        class Cluster:
+                            def __init__(self, node, cluster):
+                                self.node = node
+                                self.cluster = cluster
+                        clusters.append(Cluster(node, i))
+                self.entity_info, community_info = self._collect_community_info(
+                    nx_graph, clusters
+                )
+                
+        self._summarize_communities(community_info)
+        
+        # Cache the results after building
+        self.save_to_cache()
+        
+        # Mark communities as built for this session
+        self.communities_built = True
+
+    def _create_nx_graph(self):
+        """Converts internal graph representation to NetworkX graph."""
+        nx_graph = nx.Graph()
+        triplets = self.get_triplets()
+        for entity1, relation, entity2 in triplets:
+            nx_graph.add_node(entity1.name)
+            nx_graph.add_node(entity2.name)
+            nx_graph.add_edge(
+                relation.source_id,
+                relation.target_id,
+                relationship=relation.label,
+                description=relation.properties.get("relationship_description", "No description provided"),
+            )
+        return nx_graph
+
+    def _collect_community_info(self, nx_graph, clusters):
+        """
+        Collect information for each node based on their community,
+        allowing entities to belong to multiple clusters.
+        """
+        entity_info = defaultdict(set)
+        community_info = defaultdict(list)
+
+        for item in clusters:
+            node = item.node
+            cluster_id = item.cluster
+
+            # Update entity_info
+            entity_info[node].add(cluster_id)
+
+            for neighbor in nx_graph.neighbors(node):
+                edge_data = nx_graph.get_edge_data(node, neighbor)
+                if edge_data:
+                    detail = f"{node} -> {neighbor} -> {edge_data['relationship']} -> {edge_data['description']}"
+                    community_info[cluster_id].append(detail)
+
+        # Convert sets to lists for easier serialization if needed
+        entity_info = {k: list(v) for k, v in entity_info.items()}
+
+        return dict(entity_info), dict(community_info)
+
+    def _summarize_communities(self, community_info):
+        """Generate and store summaries for each community."""
+        for community_id, details in community_info.items():
+            details_text = "\n".join(details) + "." # Ensure it ends with a period
+            self.community_summary[community_id] = self.generate_community_summary(details_text)
+
+    def save_to_cache(self):
+        """Save community data to disk cache."""
+        try:
+            # Save community summary
+            with open(self.COMMUNITY_CACHE_FILE, 'wb') as f:
+                pickle.dump(self.community_summary, f)
+            
+            # Save entity info
+            with open(self.ENTITY_INFO_CACHE_FILE, 'wb') as f:
+                pickle.dump(self.entity_info, f)
+                
+            log_structured('info', 'Successfully cached GraphRAG community data', 
+                        {'community_count': len(self.community_summary),
+                         'entity_count': len(self.entity_info) if self.entity_info else 0})
+            return True
+        except Exception as e:
+            log_structured('error', f'Error saving GraphRAG cache: {e}')
+            return False
+    
+    def load_from_cache(self):
+        """Load community data from disk cache if available."""
+        if not self.COMMUNITY_CACHE_FILE.exists() or not self.ENTITY_INFO_CACHE_FILE.exists():
+            log_structured('info', 'GraphRAG cache files not found, will build communities from scratch')
+            return False
+        
+        try:
+            # Load community summary
+            with open(self.COMMUNITY_CACHE_FILE, 'rb') as f:
+                self.community_summary = pickle.load(f)
+            
+            # Load entity info
+            with open(self.ENTITY_INFO_CACHE_FILE, 'rb') as f:
+                self.entity_info = pickle.load(f)
+                
+            log_structured('info', 'Successfully loaded GraphRAG community data from cache', 
+                        {'community_count': len(self.community_summary),
+                         'entity_count': len(self.entity_info) if self.entity_info else 0})
+            
+            # Mark communities as built when successfully loaded from cache
+            self.communities_built = True
+            return True
+        except Exception as e:
+            log_structured('error', f'Error loading GraphRAG cache: {e}')
+            # Reset to empty in case of partial load
+            self.community_summary = {}
+            self.entity_info = None
+            self.communities_built = False
+            return False
+            
+    def get_community_summaries(self):
+        """Returns the community summaries, building them if not already done."""
+        if not self.community_summary:
+            # Try to load from cache first
+            if not self.load_from_cache():
+                # If cache load fails, build from scratch
+                self.build_communities()
+                # Cache the results for next time
+                self.save_to_cache()
+        return self.community_summary
+
+# Define the GraphRAGQueryEngine class
+from typing import Dict, Any
+
+class GraphRAGQueryEngine:
+    """Query engine that combines vector retrieval with graph-based community retrieval."""
+    
+    def __init__(
+        self, 
+        vector_retriever: VectorIndexRetriever,
+        graph_store: GraphRAGStore,
+        llm: Optional[LLM] = None,
+        similarity_top_k: int = 20
+    ):
+        """Initialize with both a vector retriever and graph store."""
+        # Initialize all required fields
+        self.vector_retriever = vector_retriever
+        self.graph_store = graph_store
+        self.llm = llm or Settings.llm
+        self.similarity_top_k = similarity_top_k
+        
+        # Check if communities are built, but don't try to build them here
+        # since that might cause errors with large graphs
+        if not hasattr(self.graph_store, 'entity_info') or self.graph_store.entity_info is None:
+            log_structured('warning', 'GraphRAGQueryEngine initialized without community data. Vector retrieval will still work, but community retrieval may be limited.')
+
+    def custom_query(self, query_str: str) -> Dict:
+        """Process query using both vector retrieval and community-based approach."""
+        log_structured('info', 'GraphRAG query engine: Starting dual retrieval', {'query': query_str})
+        
+        # Step 1: Get vector search results
+        vector_nodes = self.vector_retriever.retrieve(query_str)
+        vector_context = "\n\n".join([node.node.get_content() for node in vector_nodes])
+        log_structured('info', 'GraphRAG query engine: Vector retrieval complete', 
+                     {'node_count': len(vector_nodes)})
+        
+        # Step 2: Get GraphRAG community results (if communities exist)
+        graphrag_context = ""
+        community_ids = []
+        
+        if hasattr(self.graph_store, 'entity_info') and self.graph_store.entity_info is not None:
+            try:
+                entities = self.get_entities(query_str, vector_nodes)
+                community_ids = self.retrieve_entity_communities(self.graph_store.entity_info, entities)
+                
+                try:
+                    community_summaries = self.graph_store.get_community_summaries()
+                    
+                    if community_ids:
+                        filtered_summaries = {id: summary for id, summary in community_summaries.items() 
+                                          if id in community_ids}
+                        graphrag_context = "\n\n".join(filtered_summaries.values())
+                        log_structured('info', 'GraphRAG query engine: Community retrieval complete', 
+                                    {'community_count': len(filtered_summaries)})
+                    else:
+                        log_structured('info', 'GraphRAG query engine: No relevant communities found')
+                except Exception as e:
+                    log_structured('error', f'Error getting community summaries: {e}')
+                    # Continue without graph context
+            except Exception as e:
+                log_structured('error', f'Error during community retrieval: {e}')
+                # Continue with just vector context
+        else:
+            log_structured('warning', 'GraphRAG query engine: No community data available. Using only vector retrieval.')
+        
+        # Step 3: Combine contexts and generate answer
+        combined_result = {
+            "vector_context": vector_context,
+            "graphrag_context": graphrag_context,
+            "vector_nodes": vector_nodes,
+            "community_ids": community_ids
+        }
+        
+        return combined_result
+
+    def get_entities(self, query_str, vector_nodes):
+        """Extract entities from vector nodes that match the query."""
+        entities = set()
+        
+        # Extract entities from the retrieved nodes
+        for node_with_score in vector_nodes:
+            node = node_with_score.node
+            if hasattr(node, 'metadata') and KG_NODES_KEY in node.metadata:
+                for entity_node in node.metadata[KG_NODES_KEY]:
+                    if hasattr(entity_node, 'name'):
+                        entities.add(entity_node.name)
+        
+        # If no entities were found in metadata, try extracting them from text
+        if not entities:
+            pattern = r"(?:^|\s)([A-Z][a-zA-Z0-9\s]+)(?:\s|$)"
+            for node_with_score in vector_nodes:
+                matches = re.findall(pattern, node_with_score.node.get_content())
+                entities.update(matches)
+        
+        log_structured('debug', 'GraphRAG query engine: Extracted entities', 
+                     {'entities': list(entities), 'count': len(entities)})
+        return list(entities)
+
+    def retrieve_entity_communities(self, entity_info, entities):
+        """
+        Retrieve cluster information for given entities,
+        allowing for multiple clusters per entity.
+
+        Args:
+            entity_info (dict): Dictionary mapping entities to their cluster IDs (list).
+            entities (list): List of entity names to retrieve information for.
+
+        Returns:
+            List of community or cluster IDs to which an entity belongs.
+        """
+        community_ids = []
+
+        for entity in entities:
+            if entity in entity_info:
+                community_ids.extend(entity_info[entity])
+            else:
+                # Try case-insensitive matching as fallback
+                for stored_entity, clusters in entity_info.items():
+                    if stored_entity.lower() == entity.lower():
+                        community_ids.extend(clusters)
+                        break
+
+        return list(set(community_ids))
+
+def custom_parse_fn(response_str: str) -> Any:
+    """Custom parser for LLM responses that extract entities and relationships"""
+    json_pattern = r"\{.*\}"
+    match = re.search(json_pattern, response_str, re.DOTALL)
+    entities = []
+    relationships = []
+    
+    if not match:
+        return entities, relationships
+    
+    json_str = match.group(0)
+    try:
+        data = json.loads(json_str)
+        entities = [
+            (
+                entity["entity_name"],
+                entity["entity_type"],
+                entity.get("entity_description", f"Description of {entity['entity_name']}"),
+            )
+            for entity in data.get("entities", [])
+        ]
+        relationships = [
+            (
+                relation["source_entity"],
+                relation["target_entity"],
+                relation["relation"],
+                relation.get("relationship_description", f"Relationship between {relation['source_entity']} and {relation['target_entity']}"),
+            )
+            for relation in data.get("relationships", [])
+        ]
+        return entities, relationships
+    except (json.JSONDecodeError, KeyError) as e:
+        log_structured('error', f"Error parsing response: {e}", {'json_str': json_str[:200]})
+        return entities, relationships
+
+# Define the prompt template for triple extraction
+KG_TRIPLET_EXTRACT_TMPL = """
+-Goal-
+Given a text document, identify all entities and their entity types from the text and all relationships among the identified entities.
+
+Given the text, extract up to {max_knowledge_triplets} entity-relation triplets.
+
+-Steps-
+1. Identify all entities. For each identified entity, extract the following information:
+- entity_name: Name of the entity, capitalized
+- entity_type: Type of the entity
+- entity_description: Comprehensive description of the entity's attributes and activities
+
+2. From the entities identified in step 1, identify all pairs of (source_entity, target_entity) that are *clearly related* to each other.
+For each pair of related entities, extract the following information:
+- source_entity: name of the source entity, as identified in step 1
+- target_entity: name of the target entity, as identified in step 1
+- relation: relationship between source_entity and target_entity
+- relationship_description: explanation as to why you think the source entity and the target entity are related to each other
+
+3. Output Formatting:
+- Return the result in valid JSON format with two keys: 'entities' (list of entity objects) and 'relationships' (list of relationship objects).
+- Exclude any text outside the JSON structure (e.g., no explanations or comments).
+- If no entities or relationships are identified, return empty lists: { "entities": [], "relationships": [] }.
+
+-Real Data-
+######################
+text: {text}
+######################
+output:
+"""
+
+def create_graph_components(llm, nodes=None, max_paths_per_chunk=10, force_reindex=False):
+    """
+    Create GraphRAG components for the HP RAG pipeline.
+    
+    Args:
+        llm: The LLM to use for graph extraction and querying
+        nodes: List of nodes to create the graph from (only used if indexing is needed)
+        max_paths_per_chunk: Maximum number of paths to extract per chunk
+        force_reindex: If True, always recreate the index even if content exists
+        
+    Returns:
+        tuple: (graph_store, property_graph_index)
+    """
+    log_structured('info', 'Creating GraphRAG components')
+    
+    # Note: The graph_store object created here will automatically:
+    # 1. Try to load community data from cache files when build_communities() is called
+    # 2. Save to cache after building communities if loading failed
+    
+    # Connect to Neo4j - hard error if not available
+    property_graph_store = None
+    try:
+        log_structured('info', f'Connecting to Neo4j at {NEO4J_URL}')
+        property_graph_store = Neo4jPropertyGraphStore(
+            username=NEO4J_USERNAME, 
+            password=NEO4J_PASSWORD,
+            url=NEO4J_URL
+        )
+        log_structured('info', 'Successfully connected to Neo4j database')
+    except Exception as e:
+        log_structured('critical', f'FATAL ERROR: Cannot connect to Neo4j: {e}')
+        raise RuntimeError(f"Neo4j connection failed. This application requires Neo4j to be running. Error: {e}")
+    
+    # Create GraphRAGStore wrapper
+    graph_store = GraphRAGStore(property_graph_store)
+    
+    # Check if Neo4j already has content
+    triplets = graph_store.get_triplets()
+    has_existing_content = len(triplets) > 0
+    
+    log_structured('info', f'Neo4j check: Found {len(triplets)} triplets')
+    
+    if has_existing_content and not force_reindex:
+        log_structured('info', f'Neo4j already contains {len(triplets)} triplets. Skipping indexing.')
+        
+        # Create a minimal PropertyGraphIndex without indexing
+        property_graph_index = PropertyGraphIndex(
+            nodes=[],  # Empty nodes since we're not indexing
+            property_graph_store=property_graph_store,
+        )
+        
+        # Build communities from existing data (if not already built)
+        if not graph_store.communities_built:
+            log_structured('info', 'Building graph communities from existing Neo4j data')
+            try:
+                graph_store.build_communities()
+                log_structured('info', 'Communities built successfully')
+            except Exception as e:
+                log_structured('error', f'Error building communities: {e}')
+        else:
+            log_structured('info', 'Communities already built, skipping rebuild')
+    else:
+        # Need to perform indexing
+        if not nodes:
+            log_structured('error', 'No nodes provided for indexing and Neo4j is empty or force_reindex=True')
+            raise ValueError("Nodes must be provided for indexing when Neo4j is empty or force_reindex=True")
+        
+        # Create the knowledge graph extractor
+        kg_extractor = GraphRAGExtractor(
+            llm=llm,
+            extract_prompt=KG_TRIPLET_EXTRACT_TMPL,
+            max_paths_per_chunk=max_paths_per_chunk,
+            parse_fn=custom_parse_fn,
+        )
+        
+        if has_existing_content and force_reindex:
+            log_structured('info', 'Force reindexing requested. Clearing existing Neo4j data.')
+            try:
+                # Try to clear the graph using Neo4j's native query
+                # Note: This requires the Neo4j APOC plugin to be installed
+                from neo4j import GraphDatabase
+                driver = GraphDatabase.driver(NEO4J_URL, auth=(NEO4J_USERNAME, NEO4J_PASSWORD))
+                with driver.session() as session:
+                    session.run("MATCH (n) DETACH DELETE n")
+                driver.close()
+                log_structured('info', 'Successfully cleared Neo4j database')
+            except Exception as e:
+                log_structured('warning', f'Error clearing Neo4j database: {e}. Proceeding with indexing anyway.')
+        
+        # Build the property graph index
+        log_structured('info', 'Building PropertyGraphIndex', {'node_count': len(nodes)})
+        property_graph_index = PropertyGraphIndex(
+            nodes=nodes,
+            kg_extractors=[kg_extractor],
+            property_graph_store=property_graph_store,
+            show_progress=True,
+        )
+        
+        # Build communities
+        log_structured('info', 'Building graph communities')
+        try:
+            graph_store.build_communities()
+            log_structured('info', 'Communities built successfully')
+        except Exception as e:
+            log_structured('error', f'Error building communities: {e}')
+    
+    return graph_store, property_graph_index
+
+def create_graphrag_query_engine(vector_retriever, graph_store, llm, similarity_top_k=20):
+    """
+    Create GraphRAG query engine that combines vector and graph-based retrieval.
+    
+    Args:
+        vector_retriever: VectorIndexRetriever for standard retrieval
+        graph_store: GraphRAGStore for community-based retrieval
+        llm: LLM for generating answer
+        similarity_top_k: Number of top results to retrieve
+        
+    Returns:
+        GraphRAGQueryEngine: Query engine for hybrid retrieval
+    """
+    from utils import log_structured
+    
+    try:
+        # Explicitly validate inputs before passing to constructor
+        if vector_retriever is None:
+            raise ValueError("vector_retriever cannot be None")
+        if graph_store is None:
+            raise ValueError("graph_store cannot be None")
+        if llm is None:
+            raise ValueError("llm cannot be None")
+            
+        # Log for debugging
+        log_structured('debug', 'Creating GraphRAGQueryEngine with parameters', {
+            'vector_retriever_type': type(vector_retriever).__name__,
+            'graph_store_type': type(graph_store).__name__,
+            'llm_type': type(llm).__name__,
+            'similarity_top_k': similarity_top_k
+        })
+        
+        # Create the engine
+        return GraphRAGQueryEngine(
+            vector_retriever=vector_retriever,
+            graph_store=graph_store,
+            llm=llm,
+            similarity_top_k=similarity_top_k,
+        )
+    except Exception as e:
+        log_structured('error', f'Error in create_graphrag_query_engine: {e}')
+        raise  # Re-raise the exception for proper handling
+
+def generate_final_answer(query, retrieval_result, llm):
+    """
+    Generate a final answer using both vector and graph-based context.
+    
+    Args:
+        query: The user's query
+        retrieval_result: Result from GraphRAGQueryEngine with vector and graph contexts
+        llm: LLM for generating the final response
+        
+    Returns:
+        str: The final answer
+    """
+    vector_context = retrieval_result.get("vector_context", "")
+    graphrag_context = retrieval_result.get("graphrag_context", "")
+    
+    # Log the contexts for debugging (truncated for brevity)
+    log_structured('debug', 'Generating final answer with dual context', {
+        'query': query,
+        'vector_context_length': len(vector_context),
+        'graphrag_context_length': len(graphrag_context)
+    })
+    
+    if not vector_context and not graphrag_context:
+        return "I couldn't find any relevant information to answer your question."
+    
+    # If no model was provided or we're forcing to use a specific model
+    if llm is None or not hasattr(llm, 'chat'):
+        # Fallback to gpt-4o-mini for better cost efficiency
+        llm = OpenAI(model="gpt-4o-mini")
+        log_structured('info', 'Using gpt-4o-mini model for final answer generation')
+    
+    prompt = f"""
+    Based on the following information from two different sources, please answer this question: {query}
+
+    SOURCE 1 - VECTOR RETRIEVAL:
+    {vector_context}
+
+    SOURCE 2 - KNOWLEDGE GRAPH COMMUNITIES:
+    {graphrag_context}
+    
+    Answer the question based on all the provided information. If there are differences between the sources, 
+    try to reconcile them or note the discrepancy. Please be concise and direct.
+    """
+    
+    messages = [
+        ChatMessage(role="system", content=prompt),
+        ChatMessage(role="user", content="Please provide a comprehensive answer based on all the information provided.")
+    ]
+    
+    response = llm.chat(messages)
+    
+    # Extract just the message content, not the entire response object
+    if hasattr(response, 'message') and hasattr(response.message, 'content'):
+        content = response.message.content
+    elif hasattr(response, 'content'):
+        content = response.content
+    else:
+        # Fallback: convert to string but clean it
+        content = str(response)
+    
+    # Clean any remaining thinking patterns from the response
+    import re
+    thinking_patterns = [
+        r'(?i)Thought:.*?Action:.*?Action Input:.*',  # Remove the specific pattern
+        r'(?i)^Thought:.*',  # Remove any line starting with "Thought:"
+        r'(?i)Action:.*?Action Input:.*',  # Remove Action/Action Input patterns
+        r'(?i)^(Thought|Action|Observation):.*',  # Remove ReAct patterns
+    ]
+    
+    for pattern in thinking_patterns:
+        content = re.sub(pattern, '', content, flags=re.DOTALL | re.MULTILINE)
+    
+    # Clean up extra whitespace
+    content = re.sub(r'\n{3,}', '\n\n', content)
+    content = content.strip()
+    
+    # Final safety check
+    if not content or re.search(r'(?i)^(Thought|Action|Observation):', content):
+        log_structured('warning', 'GraphRAG final answer still contains thinking patterns, using fallback')
+        content = "I found relevant information in the HP marketing materials that can help answer your question. Please let me know if you need more specific details."
+    
+    return content
\ No newline at end of file
diff --git a/init_mongodb.py b/init_mongodb.py
new file mode 100644
index 0000000..6de29cf
--- /dev/null
+++ b/init_mongodb.py
@@ -0,0 +1,127 @@
+"""
+MongoDB Initialization Script for HP Chatbot
+
+This script initializes the MongoDB database with the necessary collections for the HP chatbot.
+It creates collections for users, conversations, and messages.
+
+Usage:
+    python init_mongodb.py
+"""
+
+import pymongo
+import logging
+from datetime import datetime
+import os
+import sys
+
+# Configure logging
+logging.basicConfig(
+    level=logging.INFO,
+    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
+    handlers=[
+        logging.StreamHandler(),
+        logging.FileHandler('mongodb_init.log')
+    ]
+)
+logger = logging.getLogger(__name__)
+
+# MongoDB connection information
+MONGO_URI = "mongodb://hp:hp@localhost:27017/?authSource=hp_chatbot"  # HP user with hp_chatbot auth source
+DB_NAME = "hp_chatbot"
+
+# Collection names
+USERS_COLLECTION = "users"
+CONVERSATIONS_COLLECTION = "conversations"
+MESSAGES_COLLECTION = "messages"
+
+def init_mongodb():
+    """Initialize MongoDB database and collections."""
+    try:
+        # Connect to MongoDB
+        logger.info("Connecting to MongoDB...")
+        client = pymongo.MongoClient(MONGO_URI)
+        
+        # Test connection
+        client.admin.command('ping')
+        logger.info("Successfully connected to MongoDB")
+        
+        # Create or access database
+        db = client[DB_NAME]
+        logger.info(f"Using database: {DB_NAME}")
+        
+        # Create collections if they don't exist
+        if USERS_COLLECTION not in db.list_collection_names():
+            db.create_collection(USERS_COLLECTION)
+            logger.info(f"Created collection: {USERS_COLLECTION}")
+            
+            # Create indexes for users collection
+            db[USERS_COLLECTION].create_index("username", unique=True)
+            # Create a unique sparse index for email - only enforces uniqueness when email exists
+            db[USERS_COLLECTION].create_index("email", unique=True, sparse=True)
+            logger.info("Created indexes for users collection")
+        
+        if CONVERSATIONS_COLLECTION not in db.list_collection_names():
+            db.create_collection(CONVERSATIONS_COLLECTION)
+            logger.info(f"Created collection: {CONVERSATIONS_COLLECTION}")
+            
+            # Create indexes for conversations collection
+            db[CONVERSATIONS_COLLECTION].create_index("user_id")
+            db[CONVERSATIONS_COLLECTION].create_index("session_id", unique=True)
+            db[CONVERSATIONS_COLLECTION].create_index("created_at")
+            db[CONVERSATIONS_COLLECTION].create_index("last_updated")
+            logger.info("Created indexes for conversations collection")
+        
+        if MESSAGES_COLLECTION not in db.list_collection_names():
+            db.create_collection(MESSAGES_COLLECTION)
+            logger.info(f"Created collection: {MESSAGES_COLLECTION}")
+            
+            # Create indexes for messages collection
+            db[MESSAGES_COLLECTION].create_index("conversation_id")
+            db[MESSAGES_COLLECTION].create_index("timestamp")
+            logger.info("Created indexes for messages collection")
+        
+        logger.info("MongoDB initialization completed successfully")
+        return True
+        
+    except pymongo.errors.ConnectionFailure as e:
+        logger.error(f"Could not connect to MongoDB: {e}")
+        return False
+    except Exception as e:
+        logger.error(f"An error occurred during MongoDB initialization: {e}")
+        return False
+
+def display_collection_info(client):
+    """Display information about the collections in the database."""
+    db = client[DB_NAME]
+    
+    logger.info("=== Database Structure ===")
+    for collection_name in db.list_collection_names():
+        count = db[collection_name].count_documents({})
+        logger.info(f"Collection: {collection_name}, Documents: {count}")
+        
+        # Display indexes
+        indexes = db[collection_name].index_information()
+        logger.info(f"  Indexes: {list(indexes.keys())}")
+
+if __name__ == "__main__":
+    if init_mongodb():
+        # Display collection information
+        client = pymongo.MongoClient(MONGO_URI)
+        display_collection_info(client)
+        
+        # Add sample user if none exist (optional)
+        db = client[DB_NAME]
+        if db[USERS_COLLECTION].count_documents({}) == 0:
+            sample_user = {
+                "username": "sample_user",
+                "email": "sample@example.com",
+                "created_at": datetime.utcnow(),
+                "last_login": datetime.utcnow()
+            }
+            db[USERS_COLLECTION].insert_one(sample_user)
+            logger.info("Added sample user for testing")
+        
+        logger.info("Initialization complete. The database is ready for use.")
+    else:
+        logger.error("Failed to initialize MongoDB. See logs for details.")
+        sys.exit(1)
\ No newline at end of file
diff --git a/json_utils.py b/json_utils.py
new file mode 100644
index 0000000..2bc19bc
--- /dev/null
+++ b/json_utils.py
@@ -0,0 +1,133 @@
+# hp_chatbot/json_utils.py
+import json
+import llama_index
+from llama_index.core.tools import ToolOutput
+from llama_index.core.agent.react.types import (
+    ActionReasoningStep,
+    ObservationReasoningStep,
+    ResponseReasoningStep,
+    BaseReasoningStep,
+)
+from llama_index.core.llms import ChatMessage, LLM, ChatResponse as LlamaResponse
+from llama_index.core.base.response.schema import Response
+from flask.json.provider import JSONProvider
+from bson import ObjectId # Import ObjectId if used in responses/data
+from datetime import datetime
+
+class CustomJSONEncoder(json.JSONEncoder):
+    """
+    Custom JSON Encoder to handle LlamaIndex objects, BSON ObjectId, and other types.
+    """
+    def default(self, obj):
+        try:
+            # Specific LlamaIndex Types
+            if isinstance(obj, ToolOutput):
+                return {
+                    'content': str(obj.content) if obj.content is not None else "",
+                    'tool_name': getattr(obj, 'tool_name', None),
+                    'raw_output': str(getattr(obj, 'raw_output', None)), # Safely convert raw_output
+                    'type': 'tool_output',
+                    'metadata': getattr(obj, 'metadata', {})
+                }
+            elif isinstance(obj, (llama_index.core.llms.ChatMessage, ChatMessage)):
+                 return {
+                     'role': str(obj.role),
+                     'content': str(obj.content),
+                     'additional_kwargs': obj.additional_kwargs if hasattr(obj, 'additional_kwargs') else {}
+                 }
+            elif isinstance(obj, (LlamaResponse, Response)):
+                 return {
+                    'content': str(getattr(obj, 'response', getattr(obj, 'message', None))),
+                    'metadata': getattr(obj, 'metadata', {}),
+                    'type': 'llm_response'
+                 }
+            elif isinstance(obj, ActionReasoningStep):
+                return {
+                    'type': 'action_step',
+                    'action': obj.action,
+                    'action_input': obj.action_input, # Should be serializable dict
+                    'thought': getattr(obj, 'thought', None)
+                }
+            elif isinstance(obj, ObservationReasoningStep):
+                return {
+                    'type': 'observation_step',
+                    'observation': str(obj.observation), # Ensure observation is string
+                    'thought': getattr(obj, 'thought', None)
+                }
+            elif isinstance(obj, ResponseReasoningStep):
+                return {
+                    'type': 'response_step',
+                    'response': str(obj.response), # Ensure response is string
+                    'is_streaming': getattr(obj, 'is_streaming', False),
+                    'thought': getattr(obj, 'thought', None)
+                }
+            elif isinstance(obj, BaseReasoningStep): # Catch-all for other steps
+                 return {
+                    'type': 'base_reasoning_step',
+                    'thought': getattr(obj, 'thought', None),
+                    'is_done': getattr(obj, 'is_done', False),
+                 }
+            # Handle LlamaIndex Document/Node related objects if needed
+            elif isinstance(obj, llama_index.core.schema.Document):
+                 return {
+                     'doc_id': obj.id_,
+                     'text_preview': obj.text[:100] + "..." if obj.text else "",
+                     'metadata': obj.metadata, # Metadata should be serializable
+                     'type': 'llama_document'
+                 }
+            elif isinstance(obj, llama_index.core.schema.NodeWithScore):
+                 return {
+                     'node': self.default(obj.node), # Recursively serialize the node
+                     'score': obj.score,
+                     'type': 'node_with_score'
+                 }
+            elif isinstance(obj, llama_index.core.schema.TextNode):
+                 return {
+                     'node_id': obj.id_,
+                     'text_preview': obj.text[:100] + "..." if obj.text else "",
+                     'metadata': obj.metadata,
+                     'type': 'text_node'
+                 }
+
+            # Common Python Types
+            elif isinstance(obj, datetime):
+                return obj.isoformat()
+            elif isinstance(obj, ObjectId):
+                return str(obj)
+            elif isinstance(obj, bytes):
+                 return "" # Or encode to base64 if needed
+
+            # General Fallback for objects with __dict__
+            elif hasattr(obj, '__dict__'):
+                # Filter out private/callable attributes, be cautious with recursion
+                try:
+                    d = {k: v for k, v in obj.__dict__.items()
+                         if not k.startswith('_') and not callable(v)}
+                    # Basic check to prevent deep recursion errors
+                    if len(d) > 50: # Arbitrary limit
+                         return f""
+                    return d
+                except Exception:
+                     return f""
+
+            # Final fallback using standard JSON encoding
+            return super().default(obj)
+
+        except Exception as e:
+            # Log the error? Be careful about logging sensitive data
+            # print(f"DEBUG: JSON encoding error for type {type(obj).__name__}: {e}")
+            return f""
+
+
+class CustomJSONProvider(JSONProvider):
+    """
+    Flask JSON Provider using the CustomJSONEncoder.
+    """
+    def dumps(self, obj, **kwargs):
+        kwargs.setdefault('cls', CustomJSONEncoder)
+        kwargs.setdefault('ensure_ascii', False) # Often useful for non-English text
+        kwargs.setdefault('indent', None) # No indent for production APIs
+        return json.dumps(obj, **kwargs)
+
+    def loads(self, s, **kwargs):
+        return json.loads(s, **kwargs)
\ No newline at end of file
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..e87c3d9
--- /dev/null
+++ b/main.py
@@ -0,0 +1,168 @@
+# hp_chatbot/main.py
+
+import asyncio
+import os
+import sys
+from flask import Flask
+from flask_cors import CORS
+
+# Ensure the project directory is in the Python path
+current_dir = os.path.dirname(os.path.abspath(__file__))
+if current_dir not in sys.path:
+    sys.path.insert(0, current_dir)
+
+# Import necessary components from our modules
+from config import (
+    APPLICATION_ROOT, MAX_CONTENT_LENGTH,
+    CORS_ALLOWED_ORIGINS, CORS_SUPPORTS_CREDENTIALS,
+    SERVER_HOST, SERVER_PORT, USE_RELOADER, LOG_LEVEL,
+    KEEP_ALIVE_TIMEOUT, READ_TIMEOUT, WRITE_TIMEOUT
+)
+from utils import logger, log_structured
+from json_utils import CustomJSONProvider
+from ai_core import initialize_global_index # Import the initialization function
+from shared_state import global_workflow_agent, is_agent_available # Import shared state
+from routes import register_routes
+from init_mongodb import init_mongodb # Your MongoDB initialization script
+
+# --- Flask App Initialization ---
+app = Flask(__name__)
+
+# Apply custom JSON provider for handling special types (LlamaIndex objects, etc.)
+app.json_provider_class = CustomJSONProvider
+app.json = CustomJSONProvider(app)
+
+# Configuration
+app.config['MAX_CONTENT_LENGTH'] = MAX_CONTENT_LENGTH
+if APPLICATION_ROOT:
+    app.config['APPLICATION_ROOT'] = APPLICATION_ROOT
+    # If using APPLICATION_ROOT, you might need to adjust route prefixes
+    # or use a Blueprint with url_prefix=APPLICATION_ROOT
+    log_structured('info', f"Flask Application Root set to: {APPLICATION_ROOT}")
+
+# CORS Configuration
+CORS(app,
+     resources={r"/*": {"origins": CORS_ALLOWED_ORIGINS}},
+     supports_credentials=CORS_SUPPORTS_CREDENTIALS,
+     # Expose custom headers if needed by the frontend
+     # expose_headers=["Content-Disposition"] # Example for downloads
+)
+log_structured('info', f"CORS configured for origins: {CORS_ALLOWED_ORIGINS}")
+
+
+# --- Register Routes ---
+# Pass the app object to the function in routes.py
+register_routes(app)
+log_structured('info', "Flask routes registered.")
+
+
+# --- Startup Function ---
+async def startup_event() -> bool:
+    """Tasks to run when the application starts.
+    
+    Returns:
+        bool: True if all startup tasks completed successfully, False otherwise
+    """
+    log_structured('info', "Application startup sequence initiated.")
+    all_success = True
+
+    # 1. Initialize MongoDB Connection & Schema (using your script)
+    log_structured('info', "Initializing MongoDB connection...")
+    mongo_success = False
+    try:
+        if init_mongodb():
+            log_structured('info', "MongoDB initialized successfully.")
+            mongo_success = True
+        else:
+            log_structured('warning', "MongoDB initialization script finished, but reported issues.")
+            all_success = False
+    except Exception as db_err:
+        log_structured('critical', "FATAL: MongoDB initialization failed.", {'error': str(db_err)})
+        all_success = False
+        # We'll continue in a degraded state
+
+    # 2. Initialize Global AI Index and Agent
+    log_structured('info', "Initializing global AI index and agent...")
+    index_success = await initialize_global_index()
+    
+    # Explicitly check the status after initialization
+    if not is_agent_available():
+        log_structured('critical', "After initialize_global_index, global_workflow_agent is still unavailable, even though function may have reported success")
+        all_success = False
+    elif not index_success:
+        log_structured('warning', "AI initialization reported failure, but will continue in degraded state")
+        all_success = False
+    else:
+        log_structured('info', "AI initialization successful, global_workflow_agent is available")
+
+    log_structured('info', f"Application startup sequence complete. Overall success: {all_success}")
+    return all_success
+
+
+# --- Shutdown Function (Optional) ---
+async def shutdown_event():
+    """Tasks to run when the application stops."""
+    log_structured('info', "Application shutdown sequence initiated.")
+    # Add any cleanup tasks here (e.g., closing connections if not handled elsewhere)
+    # Note: Hypercorn might not always guarantee graceful shutdown execution.
+    log_structured('info', "Application shutdown sequence complete.")
+
+
+# --- Main Execution Block ---
+if __name__ == '__main__':
+    from hypercorn.config import Config as HypercornConfig
+    from hypercorn.asyncio import serve as hypercorn_serve
+
+    # Create Hypercorn config object
+    config = HypercornConfig()
+
+    # Basic settings
+    config.bind = [f"{SERVER_HOST}:{SERVER_PORT}"]
+    config.use_reloader = USE_RELOADER
+    config.accesslog = '-' # Log to stdout/stderr
+    config.errorlog = '-' # Log to stdout/stderr
+    config.loglevel = LOG_LEVEL.upper()
+    config.worker_class = 'asyncio'
+
+    # Timeouts (ensure these are floats or ints)
+    config.keep_alive_timeout = float(KEEP_ALIVE_TIMEOUT)
+    config.read_timeout = float(READ_TIMEOUT)
+    config.write_timeout = float(WRITE_TIMEOUT)
+
+    # Request size limits (check Hypercorn docs for exact names, might vary slightly)
+    # These might apply to HTTP/1.1 or HTTP/2 differently.
+    # config.h11_max_incomplete_size = MAX_CONTENT_LENGTH # Example for HTTP/1.1
+    # config.h2_max_concurrent_streams = 100 # Example for HTTP/2
+    # config.max_app_buffer_size = MAX_CONTENT_LENGTH # Another potential setting
+    # It's safer to configure these via a reverse proxy (like Nginx) in production.
+    # Hypercorn's defaults are usually reasonable. Let's comment these out for now.
+
+    # Assign startup and shutdown handlers
+    config.startup_hooks = [startup_event]
+    config.shutdown_hooks = [shutdown_event]
+
+    log_structured('info', f"Starting Hypercorn server on {SERVER_HOST}:{SERVER_PORT}")
+    log_structured('info', f"Reload mode: {'Enabled' if USE_RELOADER else 'Disabled'}")
+
+    # Execute startup task before running the server
+    log_structured('info', "Manually executing startup sequence before server start")
+    startup_success = asyncio.run(startup_event())
+    
+    # Double-check that the agent is initialized
+    if not is_agent_available():
+        log_structured('critical', "After startup, global_workflow_agent is still unavailable. Forcing re-initialization...")
+        # Try once more to initialize
+        index_success = asyncio.run(initialize_global_index())
+        if not index_success or not is_agent_available():
+            log_structured('critical', "Emergency initialization also failed. Server will run but chat functionality will be impaired.")
+        else:
+            log_structured('info', "Emergency initialization succeeded.")
+
+    # Run the server
+    try:
+        asyncio.run(hypercorn_serve(app, config))
+    except KeyboardInterrupt:
+         log_structured('info', "Server stopped manually (KeyboardInterrupt).")
+    except Exception as run_err:
+         log_structured('critical', "Hypercorn server failed to run.", {'error': str(run_err)})
+         sys.exit(1)
\ No newline at end of file
diff --git a/mongodb_utils.py b/mongodb_utils.py
new file mode 100644
index 0000000..75086be
--- /dev/null
+++ b/mongodb_utils.py
@@ -0,0 +1,458 @@
+"""
+MongoDB Utilities for HP Chatbot
+
+This module provides utility functions for interacting with MongoDB in the HP chatbot application.
+It includes functions for connecting to MongoDB, and managing users, conversations, and messages.
+"""
+
+import pymongo
+import logging
+from datetime import datetime
+import uuid
+from typing import Dict, List, Optional, Any, Union
+from bson.objectid import ObjectId
+import json
+
+# Configure logging
+logging.basicConfig(
+    level=logging.INFO,
+    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
+    handlers=[
+        logging.StreamHandler(),
+        logging.FileHandler('mongodb.log')
+    ]
+)
+logger = logging.getLogger(__name__)
+
+# MongoDB connection information
+MONGO_URI = "mongodb://hp:hp@localhost:27017/?authSource=hp_chatbot"
+DB_NAME = "hp_chatbot"
+
+# Collection names
+USERS_COLLECTION = "users"
+CONVERSATIONS_COLLECTION = "conversations"
+MESSAGES_COLLECTION = "messages"
+
+# Global MongoDB client
+mongo_client = None
+db = None
+
+def get_db():
+    """Get or initialize the MongoDB database connection."""
+    global mongo_client, db
+    
+    if mongo_client is None:
+        try:
+            mongo_client = pymongo.MongoClient(MONGO_URI)
+            mongo_client.admin.command('ping')  # Test connection
+            db = mongo_client[DB_NAME]
+            logger.info("Successfully connected to MongoDB")
+        except Exception as e:
+            logger.error(f"Failed to connect to MongoDB: {e}")
+            raise
+    
+    return db
+
+def close_connection():
+    """Close the MongoDB connection."""
+    global mongo_client
+    
+    if mongo_client:
+        mongo_client.close()
+        mongo_client = None
+        logger.info("MongoDB connection closed")
+
+# User functions
+def get_user_by_username(username: str) -> Optional[Dict]:
+    """Get a user by username."""
+    try:
+        db = get_db()
+        user = db[USERS_COLLECTION].find_one({"username": username})
+        return user
+    except Exception as e:
+        logger.error(f"Error getting user by username: {e}")
+        return None
+
+def create_or_update_user(username: str, email: Optional[str] = None) -> Optional[str]:
+    """Create a new user or update an existing one."""
+    try:
+        db = get_db()
+        
+        # Check if user exists
+        existing_user = db[USERS_COLLECTION].find_one({"username": username})
+        
+        if existing_user:
+            # Update last login
+            db[USERS_COLLECTION].update_one(
+                {"username": username},
+                {"$set": {"last_login": datetime.utcnow()}}
+            )
+            return str(existing_user["_id"])
+        else:
+            # Create new user
+            new_user = {
+                "username": username,
+                "created_at": datetime.utcnow(),
+                "last_login": datetime.utcnow()
+            }
+            
+            # Only include email if it's not None to avoid unique constraint issues
+            if email:
+                new_user["email"] = email
+                
+            result = db[USERS_COLLECTION].insert_one(new_user)
+            return str(result.inserted_id)
+    except Exception as e:
+        logger.error(f"Error creating or updating user: {e}")
+        # If the error is a duplicate key error, try to find the existing user
+        if "duplicate key error" in str(e) and "username" in str(e):
+            try:
+                existing_user = db[USERS_COLLECTION].find_one({"username": username})
+                if existing_user:
+                    return str(existing_user["_id"])
+            except:
+                pass
+        return None
+
+# Conversation functions
+def get_conversation(session_id: str) -> Optional[Dict]:
+    """Get a conversation by session ID."""
+    try:
+        db = get_db()
+        conversation = db[CONVERSATIONS_COLLECTION].find_one({"session_id": session_id})
+        return conversation
+    except Exception as e:
+        logger.error(f"Error getting conversation: {e}")
+        return None
+
+def get_conversation_by_id(conversation_id: str) -> Optional[Dict]:
+    """Get a conversation by its MongoDB ID."""
+    try:
+        db = get_db()
+        # Convert string ID to ObjectId
+        try:
+            obj_id = ObjectId(conversation_id)
+            conversation = db[CONVERSATIONS_COLLECTION].find_one({"_id": obj_id})
+            return conversation
+        except Exception as e:
+            logger.error(f"Error converting conversation ID to ObjectId: {e}")
+            return None
+    except Exception as e:
+        logger.error(f"Error getting conversation by ID: {e}")
+        return None
+
+def get_user_conversations(user_id: str) -> List[Dict]:
+    """Get all conversations for a user that are not marked as deleted."""
+    try:
+        db = get_db()
+        conversations = list(db[CONVERSATIONS_COLLECTION].find(
+            {
+                "user_id": user_id,
+                # Only return conversations that either don't have is_deleted or have it set to False
+                "$or": [
+                    {"is_deleted": {"$exists": False}},
+                    {"is_deleted": False}
+                ]
+            }
+        ).sort("last_updated", pymongo.DESCENDING))
+        return conversations
+    except Exception as e:
+        logger.error(f"Error getting user conversations: {e}")
+        return []
+
+def create_conversation(session_id: str, user_id: str, title: str = "New conversation") -> Optional[str]:
+    """Create a new conversation."""
+    try:
+        db = get_db()
+        
+        # Check if conversation already exists with this session_id
+        existing = db[CONVERSATIONS_COLLECTION].find_one({"session_id": session_id})
+        if existing:
+            return str(existing["_id"])
+        
+        # Create new conversation
+        new_conversation = {
+            "session_id": session_id,
+            "user_id": user_id,
+            "title": title,
+            "created_at": datetime.utcnow(),
+            "last_updated": datetime.utcnow()
+        }
+        result = db[CONVERSATIONS_COLLECTION].insert_one(new_conversation)
+        return str(result.inserted_id)
+    except Exception as e:
+        logger.error(f"Error creating conversation: {e}")
+        return None
+
+def update_conversation_title(conversation_id: str, title: str) -> bool:
+    """Update the title of a conversation."""
+    try:
+        db = get_db()
+        db[CONVERSATIONS_COLLECTION].update_one(
+            {"_id": ObjectId(conversation_id)},
+            {"$set": {"title": title, "last_updated": datetime.utcnow()}}
+        )
+        return True
+    except Exception as e:
+        logger.error(f"Error updating conversation title: {e}")
+        return False
+
+def update_conversation_timestamp(conversation_id: str) -> bool:
+    """Update the last_updated timestamp of a conversation."""
+    try:
+        db = get_db()
+        db[CONVERSATIONS_COLLECTION].update_one(
+            {"_id": ObjectId(conversation_id)},
+            {"$set": {"last_updated": datetime.utcnow()}}
+        )
+        return True
+    except Exception as e:
+        logger.error(f"Error updating conversation timestamp: {e}")
+        return False
+
+# Message functions
+def add_message(conversation_id: str, role: str, content: str, 
+                sources: Optional[List] = None, reasoning: Optional[List] = None, 
+                images: Optional[List] = None) -> Optional[str]:
+    """Add a message to a conversation."""
+    try:
+        db = get_db()
+        
+        # Prepare the message document
+        message = {
+            "conversation_id": conversation_id,
+            "role": role,
+            "content": content,
+            "timestamp": datetime.utcnow()
+        }
+        
+        # Add optional fields with serialization
+        if sources:
+            # Serialize sources
+            serialized_sources = json.loads(json.dumps(sources, default=serialize_custom_objects))
+            message["sources"] = serialized_sources
+            
+        if reasoning:
+            # Serialize reasoning steps
+            serialized_reasoning = json.loads(json.dumps(reasoning, default=serialize_custom_objects))
+            message["reasoning"] = serialized_reasoning
+            
+        if images:
+            # Serialize images
+            serialized_images = json.loads(json.dumps(images, default=serialize_custom_objects))
+            message["images"] = serialized_images
+        
+        # Insert the message
+        result = db[MESSAGES_COLLECTION].insert_one(message)
+        
+        # Update the conversation timestamp
+        update_conversation_timestamp(conversation_id)
+        
+        return str(result.inserted_id)
+    except Exception as e:
+        logger.error(f"Error adding message: {e}")
+        return None
+
+def serialize_custom_objects(obj):
+    """
+    Custom serialization function for MongoDB.
+    Handles special types like ActionReasoningStep and other custom classes.
+    """
+    if hasattr(obj, '__dict__'):
+        # For ActionReasoningStep, ObservationReasoningStep, etc.
+        if obj.__class__.__name__.endswith('ReasoningStep'):
+            result = {
+                'type': obj.__class__.__name__
+            }
+            
+            # Add attributes based on the specific type
+            if hasattr(obj, 'action'):
+                result['action'] = obj.action
+            if hasattr(obj, 'action_input'):
+                result['action_input'] = obj.action_input
+            if hasattr(obj, 'observation'):
+                result['observation'] = obj.observation
+            if hasattr(obj, 'response'):
+                result['response'] = obj.response
+            if hasattr(obj, 'thought'):
+                result['thought'] = obj.thought
+                
+            return result
+        
+        # For other objects with __dict__
+        return {k: v for k, v in obj.__dict__.items() 
+                if not k.startswith('_') and not callable(v)}
+    
+    # For objects with content property
+    if hasattr(obj, 'content'):
+        return str(obj.content)
+        
+    # For objects with string representation
+    try:
+        return str(obj)
+    except:
+        return f""
+
+def get_conversation_messages(conversation_id: str) -> List[Dict]:
+    """Get all messages in a conversation."""
+    try:
+        db = get_db()
+        messages = list(db[MESSAGES_COLLECTION].find(
+            {"conversation_id": conversation_id}
+        ).sort("timestamp", pymongo.ASCENDING))
+        return messages
+    except Exception as e:
+        logger.error(f"Error getting conversation messages: {e}")
+        return []
+
+def generate_conversation_title(conversation_id: str, content: List[Dict]) -> Optional[str]:
+    """
+    Generate a title for a conversation based on its content using AI.
+    
+    Args:
+        conversation_id: The ID of the conversation
+        content: List of messages in the conversation
+    
+    Returns:
+        A generated title, or None if generation failed
+    """
+    try:
+        from llama_index.llms.openai import OpenAI as LlamaOpenAI
+        
+        # Extract text from the conversation (first few messages)
+        conversation_text = "\n".join([
+            f"{msg['role']}: {msg['content']}" 
+            for msg in content[:5]  # Use first 5 messages or fewer
+        ])
+        
+        # Create LLM instance
+        llm = LlamaOpenAI(
+            model="chatgpt-4o-latest",
+            temperature=0.3,
+        )
+        
+        # Generate title
+        prompt = f"""
+        Based on the following conversation, generate a short, descriptive title (max 5 words):
+        
+        {conversation_text}
+        
+        Title:
+        """
+        
+        response = llm.complete(prompt)
+        title = response.text.strip()
+        
+        # Update the conversation with the new title
+        update_conversation_title(conversation_id, title)
+        
+        return title
+    except Exception as e:
+        logger.error(f"Error generating conversation title: {e}")
+        return "New conversation"  # Fallback title
+
+def delete_conversation(conversation_id: str, hard_delete: bool = False) -> bool:
+    """
+    Delete a conversation and its messages.
+    
+    Args:
+        conversation_id: The ID of the conversation to delete
+        hard_delete: If True, physically delete the records; if False, mark as deleted
+        
+    Returns:
+        True if successful, False otherwise
+    """
+    try:
+        db = get_db()
+        
+        if hard_delete:
+            # Permanently delete all messages in the conversation
+            db[MESSAGES_COLLECTION].delete_many({"conversation_id": conversation_id})
+            
+            # Permanently delete the conversation
+            db[CONVERSATIONS_COLLECTION].delete_one({"_id": ObjectId(conversation_id)})
+        else:
+            # Mark the conversation as deleted
+            db[CONVERSATIONS_COLLECTION].update_one(
+                {"_id": ObjectId(conversation_id)},
+                {"$set": {"is_deleted": True}}
+            )
+        
+        return True
+    except Exception as e:
+        logger.error(f"Error deleting conversation: {e}")
+        return False
+
+# Session state management
+def get_session_state(session_id: str) -> Optional[Dict]:
+    """
+    Get the session state from MongoDB.
+    
+    Args:
+        session_id: The session ID
+        
+    Returns:
+        The session state or None if not found
+    """
+    try:
+        conversation = get_conversation(session_id)
+        if conversation:
+            # Return a minimal session state
+            return {
+                "initialized": True,
+                "conversation_id": str(conversation["_id"]),
+                "user_id": conversation["user_id"]
+            }
+        return None
+    except Exception as e:
+        logger.error(f"Error getting session state: {e}")
+        return None
+
+def create_session_state(session_id: str, user_id: str, conversation_id: Optional[str] = None) -> Optional[Dict]:
+    """
+    Create a new session state in MongoDB.
+    
+    Args:
+        session_id: The session ID
+        user_id: The user ID
+        conversation_id: Optional conversation ID. If not provided, a new conversation will be created.
+        
+    Returns:
+        The created session state or None if creation failed
+    """
+    try:
+        if not conversation_id:
+            conversation_id = create_conversation(session_id, user_id)
+            
+        if conversation_id:
+            return {
+                "initialized": True,
+                "conversation_id": conversation_id,
+                "user_id": user_id
+            }
+        return None
+    except Exception as e:
+        logger.error(f"Error creating session state: {e}")
+        return None
+
+def update_session_state(session_id: str, state: Dict) -> bool:
+    """
+    Update the session state in MongoDB.
+    
+    Args:
+        session_id: The session ID
+        state: The new state to save
+        
+    Returns:
+        True if the update was successful, False otherwise
+    """
+    try:
+        conversation = get_conversation(session_id)
+        if conversation:
+            # If we need to store additional session state beyond the conversation
+            # we could add a separate collection for that
+            return True
+        return False
+    except Exception as e:
+        logger.error(f"Error updating session state: {e}")
+        return False
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..baafad6
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,106 @@
+aiohappyeyeballs==2.6.1
+aiohttp==3.11.16
+aiosignal==1.3.2
+annotated-types==0.7.0
+anyio==4.9.0
+asgiref==3.8.1
+asyncio==3.4.3
+attrs==25.3.0
+banks==2.1.1
+beautifulsoup4==4.13.3
+blinker==1.9.0
+certifi==2025.1.31
+charset-normalizer==3.4.1
+click==8.1.8
+colorama==0.4.6
+dataclasses-json==0.6.7
+Deprecated==1.2.18
+dirtyjson==1.0.8
+distro==1.9.0
+dnspython==2.7.0
+filetype==1.2.0
+Flask==3.1.0
+flask-cors==5.0.1
+frozenlist==1.5.0
+fsspec==2025.3.2
+future==1.0.0
+greenlet==3.1.1
+griffe==1.7.2
+h11==0.14.0
+h2==4.2.0
+hpack==4.1.0
+httpcore==1.0.7
+httpx==0.28.1
+Hypercorn==0.17.3
+hyperframe==6.1.0
+idna==3.10
+itsdangerous==2.2.0
+Jinja2==3.1.6
+jiter==0.9.0
+joblib==1.4.2
+llama-cloud==0.1.17
+llama-cloud-services==0.6.9
+llama-index==0.12.33
+llama-index-agent-openai==0.4.6
+llama-index-cli==0.4.1
+llama-index-core==0.12.33.post1
+llama-index-embeddings-openai==0.3.1
+llama-index-graph-stores-neo4j==0.4.6
+llama-index-indices-managed-llama-cloud==0.6.11
+llama-index-llms-openai==0.3.30
+llama-index-multi-modal-llms-openai==0.4.3
+llama-index-program-openai==0.3.1
+llama-index-question-gen-openai==0.3.0
+llama-index-readers-file==0.4.7
+llama-index-readers-llama-parse==0.4.0
+llama-parse==0.6.4.post1
+lxml==5.3.2
+markdown2==2.5.3
+MarkupSafe==3.0.2
+marshmallow==3.26.1
+multidict==6.3.2
+mypy-extensions==1.0.0
+neo4j==5.28.1
+nest-asyncio==1.6.0
+networkx==3.4.2
+nltk==3.9.1
+numpy==2.2.4
+openai==1.71.0
+packaging==24.2
+pandas==2.2.3
+pillow==11.1.0
+platformdirs==4.3.7
+priority==2.0.0
+propcache==0.3.1
+pydantic==2.11.2
+pydantic_core==2.33.1
+pymongo==4.7.0
+pypdf==5.4.0
+python-dateutil==2.9.0.post0
+python-docx==1.1.2
+python-dotenv==1.1.0
+python-louvain==0.16
+pytz==2025.2
+PyYAML==6.0.2
+regex==2024.11.6
+requests==2.32.3
+setuptools==79.0.0
+six==1.17.0
+sniffio==1.3.1
+soupsieve==2.6
+SQLAlchemy==2.0.40
+striprtf==0.0.26
+tenacity==9.1.2
+tiktoken==0.9.0
+tqdm==4.67.1
+typing-inspect==0.9.0
+typing-inspection==0.4.0
+typing_extensions==4.13.1
+tzdata==2025.2
+urllib3==2.3.0
+uuid==1.30
+Werkzeug==3.1.3
+wheel==0.45.1
+wrapt==1.17.2
+wsproto==1.2.0
+yarl==1.19.0
diff --git a/routes.py b/routes.py
new file mode 100644
index 0000000..18ad928
--- /dev/null
+++ b/routes.py
@@ -0,0 +1,1032 @@
+# hp_chatbot/routes.py
+
+import os
+import asyncio
+import traceback
+import uuid
+import shutil
+import urllib.parse
+from datetime import datetime
+from pathlib import Path
+
+from flask import (
+    Flask, request, jsonify, make_response, send_from_directory, send_file,
+    Blueprint # Consider using Blueprint for larger apps
+)
+from werkzeug.utils import secure_filename # Keep if file uploads are reintroduced
+
+# Import from our modules
+from utils import logger, log_structured, allowed_file # Keep allowed_file if uploads return
+from json_utils import CustomJSONEncoder # Used indirectly by make_response/jsonify with custom provider
+from session_manager import get_or_create_session_state, clear_chat_state_cache
+from ai_core import initialize_global_index # Import initialization function
+from shared_state import global_workflow_agent, global_index, is_agent_available # Import shared state variables
+from document_generator import create_brief_docx
+from config import IMAGES_DIRECTORY, HP_DOCS_FOLDER, BASE_DIR, SUPPORTING_FILES_DIR # Import necessary configs
+from llama_index.core.tools import ToolOutput  # Import ToolOutput for type checking
+from llama_index.core.llms import ChatMessage  # Import ChatMessage for memory management
+
+# Import MongoDB utilities
+from mongodb_utils import (
+    add_message, get_conversation_messages, get_user_conversations,
+    get_conversation_by_id, create_conversation, create_or_update_user,
+    delete_conversation as db_delete_conversation, # Alias to avoid conflict
+    generate_conversation_title, update_session_state
+)
+
+# Create a Blueprint or define routes on the app passed from main.py
+# Using direct app registration for simplicity here.
+# If using Blueprint:
+# api_bp = Blueprint('api', __name__)
+# @api_bp.route('/chat', methods=['POST', 'OPTIONS'])
+# async def chat(): ...
+# In main.py: app.register_blueprint(api_bp)
+
+def register_routes(app: Flask):
+
+    @app.route('/chat', methods=['POST', 'OPTIONS'])
+    async def chat():
+        """Handle chat messages, interact with the AI agent, include image handling."""
+        # Declare global variables we'll need to access
+        global global_workflow_agent
+        
+        if request.method == 'OPTIONS':
+            # Pre-flight request. Reply successfully:
+            resp = make_response(jsonify({'status': 'ok'}))
+            # Add necessary CORS headers if not handled globally by Flask-CORS middleware
+            # resp.headers['Access-Control-Allow-Origin'] = request.headers.get('Origin')
+            # resp.headers['Access-Control-Allow-Credentials'] = 'true'
+            # resp.headers['Access-Control-Allow-Methods'] = 'POST, OPTIONS'
+            # resp.headers['Access-Control-Allow-Headers'] = 'Content-Type, X-MS-USERNAME, Authorization' # Add any custom headers
+            return resp
+
+        session_id = None # Initialize for error logging
+        try:
+            data = request.get_json()
+            if not data or 'message' not in data:
+                log_structured('warning', 'Chat request missing message payload')
+                return jsonify({'error': 'No message provided'}), 400
+
+            session_id = data.get('sessionId')
+            if not session_id:
+                log_structured('warning', 'Chat request missing sessionId')
+                return jsonify({'error': 'Session ID is required'}), 400
+
+            # Use X-MS-USERNAME or a similar header for authenticated username
+            username = request.headers.get('X-MS-USERNAME') # Adjust header name if different
+            # Check if we're in development mode
+            if not username and os.environ.get("PRODUCTION", "false").lower() == "false":
+                # For local development, create a default username
+                username = f"dev_user@local"
+                log_structured('info', f'Development mode: Using default username: {username}')
+            elif not username:
+                 # Allow anonymous access based on session or return error?
+                 # For now, allow anonymous tied to session_id
+                 log_structured('info', f'Chat request from anonymous user (session: {session_id})')
+                 # username = f"anonymous_{session_id[:8]}" # Or handle as error if auth is mandatory
+                 # return jsonify({'error': 'Authentication required (X-MS-USERNAME header missing)'}), 401
+
+            log_structured('info', f'Chat request received', {'session_id': session_id, 'username': username or 'anonymous'})
+
+            # Get or create session state (maps session_id to user_id, conversation_id)
+            session_state = get_or_create_session_state(session_id, username)
+
+            # Ensure session is initialized in both development and production modes
+            if not session_state.get('initialized'):
+                log_structured('info', 'Session not yet initialized. Initializing now.', {'session_id': session_id})
+                # Initialize session properly
+                session_state['initialized'] = True
+                # Update the session state in the database to mark as initialized
+                update_session_state(session_id, {'initialized': True})
+
+            conversation_id = session_state.get('conversation_id')
+            user_id = session_state.get('user_id') # Get user_id for context if needed
+
+            if not conversation_id or not user_id:
+                 log_structured('error', 'Session state missing conversation_id or user_id', {'session_id': session_id, 'state': session_state})
+                 return jsonify({'error': 'Session setup incomplete. Please refresh or start a new chat.'}), 500
+
+            user_message = data['message']
+
+            # Store user message
+            add_message(conversation_id, 'user', user_message)
+
+            log_structured('debug', 'Starting agent workflow run', {
+                'session_id': session_id,
+                'conversation_id': conversation_id,
+                'user_id': user_id,
+                'message_preview': user_message[:100]
+            })
+
+            # Check if global agent is available using the shared state helper
+            if not is_agent_available():
+                log_structured('error', 'Global workflow agent is not initialized')
+                
+                # Try to initialize it on-demand if not available
+                try:
+                    log_structured('info', 'Attempting to initialize global index and agent on-demand')
+                    index_success = await initialize_global_index()
+                    
+                    # Let initialization complete, then check the global variable
+                    if index_success:
+                        log_structured('info', 'Index initialization reported success')
+                        
+                        # Force reload the global module variable
+                        import importlib
+                        import ai_core
+                        importlib.reload(ai_core)
+                        from ai_core import global_workflow_agent
+                        
+                        # Check if global_workflow_agent is now available
+                        if global_workflow_agent:
+                            # Test the agent with a simple function call
+                            try:
+                                # Just check if the run method exists and is callable
+                                if hasattr(global_workflow_agent, 'run') and callable(global_workflow_agent.run):
+                                    log_structured('info', 'Successfully initialized global agent on-demand')
+                                else:
+                                    log_structured('error', 'Agent initialized but run method is not callable')
+                            except Exception as agent_test_err:
+                                log_structured('error', f'Agent functional test failed: {str(agent_test_err)}')
+                        else:
+                            log_structured('error', 'Agent still not available after successful index initialization')
+                    else:
+                        log_structured('error', 'Index initialization reported failure')
+                except Exception as init_err:
+                    log_structured('error', f'Error initializing agent on-demand: {str(init_err)}')
+                
+                # Final check
+                import ai_core
+                # We're already using the global variable from the function declaration
+                # Just reassign it from the imported module
+                global_workflow_agent = ai_core.global_workflow_agent
+                if not global_workflow_agent:
+                    log_structured('critical', 'Failed to get or initialize global workflow agent')
+                    
+                    # Provide a more detailed error message for debugging
+                    error_details = {
+                        'error': 'Chat agent is not available. Please try again later.',
+                        'details': 'The AI agent failed to initialize properly. This might be due to API key issues or other backend problems.',
+                        'code': 'AGENT_UNAVAILABLE'
+                    }
+                    return jsonify(error_details), 503
+            
+            # Use the agent to process the query (with one final check to be sure)
+            if not is_agent_available():
+                log_structured('critical', 'Global agent is unavailable after initialization checks')
+                error_details = {
+                    'error': 'Chat agent became unavailable. Please try again.',
+                    'code': 'AGENT_DISAPPEARED'
+                }
+                return jsonify(error_details), 500
+            
+            # Import fresh reference to agent
+            from shared_state import global_workflow_agent
+            if global_workflow_agent is None:
+                log_structured('critical', 'Global agent is None after direct import from shared_state')
+                error_details = {
+                    'error': 'Chat agent became unavailable. Please try again.',
+                    'code': 'AGENT_DISAPPEARED'
+                }
+                return jsonify(error_details), 500
+                
+            log_structured('info', 'Running agent to process query')
+            
+            # Get a fresh reference to the agent from shared state
+            from shared_state import global_workflow_agent as current_agent
+            
+            # Double-check that the agent is available
+            if current_agent is None or not hasattr(current_agent, 'run'):
+                log_structured('critical', 'Agent disappeared at runtime: null check before .run() call')
+                return jsonify({'error': 'Chat agent became unavailable just before processing. Please try again.', 'code': 'AGENT_GONE'}), 500
+            
+            # Load conversation history into the agent's memory
+            if conversation_id:
+                try:
+                    conv_messages = get_conversation_messages(conversation_id)
+                    # Skip if we already have messages in memory (avoid duplication)
+                    if current_agent.memory and len(current_agent.memory.get()) <= 1:
+                        log_structured('info', f'Loading conversation history: {len(conv_messages)} messages', 
+                                     {'conversation_id': conversation_id})
+                        
+                        # Clear memory first to avoid duplicate history
+                        current_agent.memory.reset()
+                        
+                        # Add messages to memory in the correct order
+                        for msg in conv_messages:
+                            # Skip the current message which will be added by the agent
+                            if msg.get('content') == user_message and msg.get('role') == 'user':
+                                continue
+                            role = msg.get('role')
+                            content = msg.get('content', '')
+                            if role and content:
+                                current_agent.memory.put(ChatMessage(role=role, content=content))
+                except Exception as hist_err:
+                    log_structured('error', f'Error loading conversation history: {str(hist_err)}', 
+                                 {'conversation_id': conversation_id})
+                    # Continue without history rather than failing the request
+            
+            # Call the run method on the current agent
+            raw_response = await current_agent.run(user_message)
+
+            log_structured('debug', 'Raw response received from workflow agent', {
+                'session_id': session_id, 'conversation_id': conversation_id,
+                'response_type': type(raw_response).__name__,
+                'response_keys': list(raw_response.keys()) if isinstance(raw_response, dict) else None,
+            })
+
+            # --- Process Response and Extract Images ---
+            final_response_text = "Sorry, I encountered an issue generating a response."
+            final_sources = []
+            final_reasoning = []
+            images = []
+            seen_images = set() # Track unique images added
+
+            if isinstance(raw_response, dict):
+                final_response_text = str(raw_response.get('response', ''))
+                response_sources = raw_response.get('sources', []) # Should be list of ToolOutput
+                final_reasoning = raw_response.get('reasoning', []) # Should be list of ReasoningSteps
+
+                log_structured('debug', f'Processing {len(response_sources)} sources for metadata and images', {'session_id': session_id})
+
+                # Extract source details and potential images
+                if response_sources and isinstance(response_sources, list):
+                    for source_idx, tool_output_source in enumerate(response_sources):
+                        if tool_output_source is None:
+                            continue
+                            
+                        source_info = {'content': "Source content unavailable", 'metadata': {}} # Default
+                        if isinstance(tool_output_source, ToolOutput):
+                            source_info['content'] = str(tool_output_source.content) if tool_output_source.content else "No content"
+                            source_info['tool_name'] = getattr(tool_output_source, 'tool_name', 'unknown_tool')
+                            source_info['raw_output_preview'] = str(tool_output_source.raw_output)[:100] if hasattr(tool_output_source, 'raw_output') and tool_output_source.raw_output else "N/A"
+                            
+                            # Log GraphRAG retrieval information if present
+                            if getattr(tool_output_source, 'tool_name', '') == 'GraphRAG':
+                                raw_output = getattr(tool_output_source, 'raw_output', {})
+                                if isinstance(raw_output, dict):
+                                    # Extract and log vector and GraphRAG contexts
+                                    vector_context = raw_output.get('vector_context', '')
+                                    graphrag_context = raw_output.get('graphrag_context', '')
+                                    
+                                    # Add retrieval source information to the log
+                                    log_structured('info', 'GraphRAG Retrieval Results', {
+                                        'session_id': session_id,
+                                        'vector_retrieval_size': len(vector_context),
+                                        'graphrag_retrieval_size': len(graphrag_context),
+                                        'vector_retrieval_preview': vector_context[:200] + '...' if len(vector_context) > 200 else vector_context,
+                                        'graphrag_retrieval_preview': graphrag_context[:200] + '...' if len(graphrag_context) > 200 else graphrag_context,
+                                        'community_ids': raw_output.get('community_ids', [])
+                                    })
+                                    
+                                    # Add context source information to the source_info
+                                    source_info['retrieval_method'] = 'graphrag_hybrid'
+                                    source_info['vector_context_length'] = len(vector_context)
+                                    source_info['graphrag_context_length'] = len(graphrag_context)
+                                    source_info['used_communities'] = raw_output.get('community_ids', [])
+                            else:
+                                # Standard vector retrieval
+                                source_info['retrieval_method'] = 'vector_only'
+                            
+                            # Try accessing source_nodes from raw_output if it exists
+                            raw_output = getattr(tool_output_source, 'raw_output', None)
+                            if raw_output and hasattr(raw_output, 'source_nodes'):
+                                nodes_metadata = []
+                                # Safely iterate over source_nodes
+                                source_nodes = getattr(raw_output, 'source_nodes', [])
+                                if source_nodes:
+                                    for node_idx, node_with_score in enumerate(source_nodes):
+                                        node = getattr(node_with_score, 'node', None)
+                                        if node and hasattr(node, 'metadata'):
+                                            node_meta = node.metadata or {}
+                                            nodes_metadata.append(node_meta) # Collect metadata for source info
+                                            
+                                            # Check for images within this node's metadata
+                                            node_image_paths = node_meta.get('image_paths', [])
+                                            if isinstance(node_image_paths, list):
+                                                for img_filename in node_image_paths:
+                                                    if img_filename and isinstance(img_filename, str) and img_filename not in seen_images:
+                                                        # Ensure IMAGES_DIRECTORY is a Path object
+                                                        image_dir = Path(IMAGES_DIRECTORY)
+                                                        image_full_path = image_dir / img_filename
+                                                        
+                                                        if image_full_path.is_file():
+                                                            # Extract doc name/page from filename (adjust parsing as needed)
+                                                            doc_name = node_meta.get('filename', 'Unknown Document')
+                                                            page_num = node_meta.get('source_page', 'Unknown Page')
+
+                                                            # URL encode the filename for the frontend
+                                                            url_encoded_filename = urllib.parse.quote(img_filename)
+                                                            
+                                                            image_info = {
+                                                                'filename': img_filename,
+                                                                'url_encoded_filename': url_encoded_filename,
+                                                                'document': doc_name,
+                                                                'page': page_num,
+                                                                'source': doc_name # Redundant? Maybe use tool name?
+                                                            }
+                                                            images.append(image_info)
+                                                            seen_images.add(img_filename)
+                                                            
+                                                            # Get node ID safely
+                                                            node_id = getattr(node, 'id_', 'unknown_node')
+                                                            log_structured('info', f'Added image from node metadata: {img_filename}', {'session_id': session_id, 'node_id': node_id})
+                                                        else:
+                                                            log_structured('warning', f'Image file from metadata not found: {img_filename}', {'session_id': session_id, 'path_checked': str(image_full_path)})
+                                            else:
+                                                if node_image_paths: # Log if it exists but isn't a list
+                                                    node_id = getattr(node, 'id_', 'unknown_node')
+                                                    log_structured('warning', f"'image_paths' in node metadata is not a list.", {'session_id': session_id, 'node_id': node_id, 'metadata_value': str(node_image_paths)})
+
+                            # Add collected node metadata (or tool metadata) to the source info
+                            # Initialize nodes_metadata if it doesn't exist
+                            if not locals().get('nodes_metadata'):
+                                nodes_metadata = []
+                            source_info['metadata'] = {'nodes': nodes_metadata} if nodes_metadata else getattr(tool_output_source, 'metadata', {})
+
+                        else:
+                            log_structured('warning', f'Source element is not a ToolOutput object', {'type': type(tool_output_source).__name__})
+                            source_info['content'] = str(tool_output_source) # Fallback
+
+                        # Add the processed source info regardless of type
+                        final_sources.append(source_info)
+
+            else:
+                 # Handle cases where agent might return just a string (less ideal)
+                 final_response_text = str(raw_response)
+                 log_structured('warning', 'Agent response was not a dict, sources/reasoning unavailable.', {'response_type': type(raw_response).__name__})
+
+            log_structured('info', f'Final image count for response: {len(images)}', {'session_id': session_id, 'images': images})
+
+            # Structure the response to be sent to the frontend
+            processed_response = {
+                'response': final_response_text,
+                'sources': final_sources, # Use the processed sources
+                'reasoning': final_reasoning, # Use the extracted reasoning steps
+                'images': images # Use the validated list of image info dicts
+            }
+
+            # Store assistant response in MongoDB
+            # Note: Ensure final_sources and final_reasoning are serializable by CustomJSONEncoder
+            add_message(
+                conversation_id,
+                'assistant',
+                final_response_text,
+                sources=final_sources,
+                reasoning=final_reasoning, # Pass reasoning steps
+                images=images # Pass image info list
+            )
+
+            # Update conversation title (if needed)
+            conv_messages = get_conversation_messages(conversation_id)
+            # Generate title after first user/assistant pair usually
+            if conv_messages and len(conv_messages) == 2:
+                try:
+                    new_title = generate_conversation_title(conversation_id, conv_messages)
+                    log_structured('info', f'Generated initial conversation title: "{new_title}"', {'conversation_id': conversation_id})
+                except Exception as title_err:
+                    log_structured('error', f'Error generating conversation title: {title_err}', {'conversation_id': conversation_id})
+                    # Non-fatal error
+
+            # Use make_response to ensure custom JSON encoder is used
+            response = make_response(jsonify({
+                'status': 'success',
+                'data': processed_response
+            }))
+            response.headers['Content-Type'] = 'application/json'
+            return response
+
+        except asyncio.TimeoutError:
+             log_structured('error', 'Chat request timed out', {'session_id': session_id})
+             return jsonify({'status': 'error', 'error': 'Request timed out', 'detail': 'The request took too long to process.'}), 504 # Gateway Timeout
+        except Exception as e:
+            log_structured('error', 'Unhandled error in /chat endpoint', {
+                'session_id': session_id, 'error': str(e), 'traceback': traceback.format_exc()
+            })
+            response = make_response(jsonify({
+                'status': 'error', 'error': 'An internal server error occurred.', 'detail': str(e)
+            }), 500)
+            response.headers['Content-Type'] = 'application/json'
+            return response
+
+    @app.route('/images/', methods=['GET'])
+    def serve_image(filename):
+        """Serve an image file from the designated image directory."""
+        # Log the requested image
+        log_structured('debug', f'Image request received for: {filename}')
+        
+        # For filenames with spaces and special characters, don't use secure_filename
+        # Just check for basic path traversal attempts
+        if '..' in filename or filename.startswith('/'):
+            log_structured('warning', 'Possible path traversal attempt', {'requested': filename})
+            return jsonify({'error': 'Invalid filename'}), 400
+
+        try:
+            # Try the main images directory first (using raw filename)
+            image_path = os.path.join(IMAGES_DIRECTORY, filename)
+            if os.path.exists(image_path) and os.path.isfile(image_path):
+                log_structured('debug', f'Serving image from IMAGES_DIRECTORY: {filename}')
+                return send_from_directory(IMAGES_DIRECTORY, filename, as_attachment=False)
+            
+            # If not found, check for public images in the chat interface public directory
+            public_images_dir = BASE_DIR / "chat-interface" / "public" / "images"
+            public_image_path = os.path.join(public_images_dir, filename)
+            if os.path.exists(public_image_path) and os.path.isfile(public_image_path):
+                log_structured('debug', f'Found image in public directory: {filename}')
+                return send_from_directory(public_images_dir, filename, as_attachment=False)
+            
+            # If still not found, look for the image in supporting files
+            supporting_images_dir = SUPPORTING_FILES_DIR
+            supporting_image_path = os.path.join(supporting_images_dir, filename)
+            if os.path.exists(supporting_image_path) and os.path.isfile(supporting_image_path):
+                log_structured('debug', f'Found image in supporting files: {filename}')
+                return send_from_directory(supporting_images_dir, filename, as_attachment=False)
+            
+            # Try with URL-decoded filename
+            import urllib.parse
+            decoded_filename = urllib.parse.unquote(filename)
+            if decoded_filename != filename:
+                decoded_image_path = os.path.join(IMAGES_DIRECTORY, decoded_filename)
+                if os.path.exists(decoded_image_path) and os.path.isfile(decoded_image_path):
+                    log_structured('debug', f'Serving image with decoded filename: {decoded_filename}')
+                    return send_from_directory(IMAGES_DIRECTORY, decoded_filename, as_attachment=False)
+            
+            log_structured('error', f'Image not found in any directory: {filename}')
+            return jsonify({'error': 'Image not found'}), 404
+        except Exception as e:
+            log_structured('error', f'Error serving image {filename}', {'error': str(e)})
+            return jsonify({'error': 'Server error serving image'}), 500
+
+    @app.route('/list-images', methods=['GET'])
+    def list_images():
+        """List all available images in the images directory."""
+        try:
+            if not os.path.exists(IMAGES_DIRECTORY):
+                log_structured('error', 'Images directory does not exist', {'path': str(IMAGES_DIRECTORY)})
+                return jsonify({'status': 'error', 'message': 'Images directory not found'}), 404
+
+            image_files = []
+            valid_extensions = ('.png', '.jpg', '.jpeg', '.gif', '.webp') # Add more if needed
+            
+            # Use os.listdir which is more reliable with special characters
+            for filename in os.listdir(IMAGES_DIRECTORY):
+                file_path = os.path.join(IMAGES_DIRECTORY, filename)
+                if os.path.isfile(file_path) and os.path.splitext(filename)[1].lower() in valid_extensions:
+                    try:
+                        stat_info = os.stat(file_path)
+                        image_files.append({
+                            'filename': filename,
+                            'url': f'/images/{urllib.parse.quote(filename)}', # URL encode for safety
+                            'size': stat_info.st_size,
+                            'created': datetime.fromtimestamp(stat_info.st_ctime).isoformat()
+                        })
+                    except Exception as stat_err:
+                        log_structured('error', f'Could not get stats for image file: {filename}', {'error': str(stat_err)})
+
+            # Sort by creation time, newest first
+            image_files.sort(key=lambda x: x['created'], reverse=True)
+
+            return jsonify({
+                'status': 'success',
+                'count': len(image_files),
+                'images': image_files
+            })
+        except Exception as e:
+            log_structured('error', 'Error listing images', {'error': str(e), 'traceback': traceback.format_exc()})
+            return jsonify({'status': 'error', 'message': 'Failed to list images'}), 500
+
+
+    # Example route for manual testing (consider removing in production)
+    @app.route('/capture-screenshot', methods=['POST'])
+    async def capture_screenshot():
+        """Manually trigger LlamaParse image capture for a specific file (for testing)."""
+        # This uses parts of ai_core.process_documents_in_directory - refactor might be needed
+        # For simplicity, we'll re-implement the image parsing part here
+        # WARNING: This endpoint allows triggering processing on arbitrary paths if not secured.
+        # Consider adding authentication/authorization or removing it.
+        try:
+            data = request.get_json()
+            file_path_str = data.get('file_path') if data else None
+
+            if not file_path_str:
+                return jsonify({'status': 'error', 'message': 'Missing file_path'}), 400
+
+            # Basic check: Ensure the file is within the expected docs folder for safety
+            target_path = Path(file_path_str).resolve()
+            allowed_dir = HP_DOCS_FOLDER.resolve()
+            if not str(target_path).startswith(str(allowed_dir)):
+                 log_structured('warning', 'Attempt to access file outside allowed directory', {'requested': file_path_str, 'allowed': str(allowed_dir)})
+                 return jsonify({'status': 'error', 'message': 'File path is not allowed'}), 403
+
+            if not target_path.is_file():
+                return jsonify({'status': 'error', 'message': f'File not found: {file_path_str}'}), 404
+
+            # --- Re-initialize LlamaParse for image capture ---
+            parser_images = None
+            image_results = []
+            temp_dir = None
+            try:
+                from config import LLAMA_PARSE_VENDOR_MODEL, LLAMA_PARSE_MAX_TIMEOUT
+                import httpx
+                from llama_parse import LlamaParse # Local import for clarity
+
+                custom_client_images = httpx.AsyncClient(timeout=LLAMA_PARSE_MAX_TIMEOUT)
+                parser_images = LlamaParse(
+                    result_type="markdown", add_page_breaks=False,
+                    system_prompt="Generate page images.",
+                    use_vendor_multimodal_model=True,
+                    vendor_multimodal_model_name=LLAMA_PARSE_VENDOR_MODEL,
+                    premium_mode=False, max_timeout=LLAMA_PARSE_MAX_TIMEOUT,
+                    custom_client=custom_client_images, verbose=True
+                )
+
+                log_structured('info', f'Attempting to capture images from file: {file_path_str} (Manual Trigger)')
+                temp_dir = IMAGES_DIRECTORY / f"temp_manual_{uuid.uuid4().hex[:8]}"
+                os.makedirs(temp_dir, exist_ok=True)
+
+                # --- Execute image parsing (sync methods in thread) ---
+                loop = asyncio.get_running_loop()
+                from concurrent.futures import ThreadPoolExecutor
+                with ThreadPoolExecutor() as pool:
+                     md_json_objs = await loop.run_in_executor(pool, parser_images.get_json_result, str(target_path))
+                     image_dicts = await loop.run_in_executor(pool, parser_images.get_images, md_json_objs, str(temp_dir))
+
+                # Ensure image_dicts is not None and is a list
+                image_dicts = image_dicts or []
+                
+                log_structured('info', f'Manual capture: LlamaParse reported {len(image_dicts)} images for {target_path.name}')
+
+                # --- Process and save images ---
+                if isinstance(image_dicts, list):  # Safety check
+                    for idx, img_info in enumerate(image_dicts):
+                        if not isinstance(img_info, dict):
+                            log_structured('warning', f'Image info is not a dict: {img_info}')
+                            continue
+                        
+                        page_index_0_based = img_info.get('page', idx)
+                        page_num_1_based = page_index_0_based + 1
+                        source_img_path_str = img_info.get('path')
+
+                        if source_img_path_str and os.path.exists(source_img_path_str):
+                            source_img_path = Path(source_img_path_str)
+                            try:
+                                image_filename = f"{target_path.stem}_manual_page{page_num_1_based}_{uuid.uuid4().hex[:6]}.png"
+                                dest_path = IMAGES_DIRECTORY / image_filename
+                                shutil.copy2(source_img_path, dest_path)
+                                image_results.append({
+                                    'success': True, 'page_number': page_num_1_based,
+                                    'filename': image_filename, 'url': f'/images/{image_filename}'
+                                })
+                                log_structured('info', f'Saved manual test image for page {page_num_1_based}', {'path': str(dest_path)})
+                            except Exception as img_err:
+                                log_structured('error', f'Failed to save manual test image page {page_num_1_based}', {'error': str(img_err)})
+                                image_results.append({'success': False, 'page_number': page_num_1_based, 'error': str(img_err)})
+                        else:
+                            image_results.append({'success': False, 'page_number': page_num_1_based, 'error': 'No image path found or path invalid'})
+
+            except Exception as parse_err:
+                 log_structured('error', f'Error during manual image capture for {file_path_str}', {'error': str(parse_err), 'traceback': traceback.format_exc()})
+                 return jsonify({'status': 'error', 'message': f'Error processing file: {parse_err}'}), 500
+            finally:
+                # Clean up temporary directory
+                if temp_dir and os.path.exists(temp_dir):
+                    try: shutil.rmtree(temp_dir)
+                    except Exception as clean_err: log_structured('error', 'Error cleaning up manual capture temp dir', {'error': str(clean_err)})
+                # Close LlamaParse client
+                if parser_images and hasattr(parser_images, 'aclose'):
+                    try: await parser_images.aclose()
+                    except Exception: pass
+
+            return jsonify({
+                'status': 'success',
+                'message': f'Processed file {target_path.name}, attempted to capture {len(image_dicts or [])} images.',
+                'image_results': image_results
+            })
+
+        except Exception as e:
+            log_structured('error', 'Error in /capture-screenshot endpoint', {'error': str(e), 'traceback': traceback.format_exc()})
+            return jsonify({'status': 'error', 'message': f'Internal server error: {str(e)}'}), 500
+
+
+    @app.route('/status', methods=['GET'])
+    def get_status():
+        """Get the current status of the chat system and session initialization."""
+        # Use shared state module instead of globals
+        session_id = request.args.get('sessionId')
+
+        # SUPER SIMPLIFIED - ALWAYS RETURN INITIALIZED
+        log_structured('info', 'Status check: ALWAYS returning initialized=true')
+        
+        status_data = {
+            'global_status': 'initialized',
+            'initialized': True,
+            'is_initialized': True,
+            'timestamp': datetime.now().isoformat(),
+            'override': 'FORCE_INITIALIZED'
+        }
+
+        if session_id:
+            # Optionally check if this specific session is known (cached or in DB)
+            try:
+                 # Use the session manager, but don't force creation if it doesn't exist
+                 state = get_or_create_session_state(session_id, username=None) # Check existing without forcing creation
+                 
+                 # Check if session exists and has the required fields
+                 session_exists = state and state.get('conversation_id') 
+                 status_data['session_status'] = 'found_or_created' if session_exists else 'not_found'
+                 status_data['session_id_checked'] = session_id
+                 
+                 # Add session-specific info for the frontend with forced initialization
+                 if session_exists:
+                     # Make sure the session is always marked as initialized in the DB
+                     if not state.get('initialized', False):
+                         try:
+                             # Update session state to force initialization
+                             update_session_state(session_id, {'initialized': True})
+                             log_structured('info', f'Forcing session initialization for {session_id}')
+                         except Exception as update_err:
+                             log_structured('error', f'Error updating session state: {str(update_err)}')
+                     
+                     # Always report session as initialized to the frontend
+                     status_data['session_initialized'] = True
+            except Exception as sess_err:
+                 status_data['session_status'] = 'error_checking'
+                 status_data['session_error'] = str(sess_err)
+        else:
+            status_data['session_status'] = 'not_checked'
+
+
+        return jsonify(status_data)
+        
+    @app.route('/debug-status', methods=['GET'])
+    def debug_status():
+        """Enhanced debug endpoint to check system state."""
+        # This is a development-only endpoint; disable in production
+        if os.environ.get("PRODUCTION", "false").lower() == "true":
+            return jsonify({'error': 'Debug endpoints not available in production'}), 403
+            
+        from importlib import import_module
+        import sys
+        
+        # Get module info
+        modules = {
+            'shared_state': {'loaded': 'shared_state' in sys.modules},
+            'ai_core': {'loaded': 'ai_core' in sys.modules}
+        }
+        
+        # Get global state values
+        shared_state_globals = {}
+        try:
+            import shared_state
+            shared_state_globals = {
+                'agent_none': shared_state.global_workflow_agent is None,
+                'index_none': shared_state.global_index is None,
+                'graph_store_none': shared_state.global_graph_store is None,
+                'agent_available': shared_state.is_agent_available(),
+                'agent_type': type(shared_state.global_workflow_agent).__name__ if shared_state.global_workflow_agent else None,
+                'agent_has_run': hasattr(shared_state.global_workflow_agent, 'run') if shared_state.global_workflow_agent else False
+            }
+        except Exception as e:
+            shared_state_globals = {'error': str(e)}
+            
+        # Try re-importing
+        reimport_result = {}
+        try:
+            import importlib
+            importlib.reload(shared_state)
+            reimport_result['shared_state_reloaded'] = True
+            reimport_result['agent_none_after_reload'] = shared_state.global_workflow_agent is None
+            reimport_result['agent_available_after_reload'] = shared_state.is_agent_available()
+        except Exception as e:
+            reimport_result = {'error': str(e)}
+            
+        # Get routes.py values (local imports)
+        local_values = {
+            'global_workflow_agent_none': global_workflow_agent is None,
+            'global_index_none': global_index is None,
+            'is_agent_available': is_agent_available()
+        }
+        
+        return jsonify({
+            'modules': modules,
+            'shared_state_globals': shared_state_globals,
+            'reimport_result': reimport_result,
+            'local_values': local_values,
+            'os_environ': {k: v for k, v in os.environ.items() if not k.startswith('OPENAI') and not k.startswith('SECRET')}
+        })
+        
+    @app.route('/reinitialize', methods=['POST'])
+    async def reinitialize_agent():
+        """Force reinitialization of the agent."""
+        # This is a development-only endpoint; disable in production
+        if os.environ.get("PRODUCTION", "false").lower() == "true":
+            return jsonify({'error': 'Debug endpoints not available in production'}), 403
+        
+        from ai_core import initialize_global_index
+        
+        try:
+            # Log current state before reinitializing
+            log_structured('info', 'Reinitializing global agent', {
+                'agent_available_before': is_agent_available(),
+                'agent_none_before': global_workflow_agent is None,
+                'index_none_before': global_index is None
+            })
+            
+            # Attempt to reinitialize
+            success = await initialize_global_index()
+            
+            # Import fresh state after initialization
+            import importlib
+            import shared_state
+            importlib.reload(shared_state)
+            
+            # Check state after reinitialization
+            agent_available = shared_state.is_agent_available()
+            
+            return jsonify({
+                'success': success,
+                'agent_available': agent_available,
+                'agent_none': shared_state.global_workflow_agent is None,
+                'index_none': shared_state.global_index is None,
+                'message': 'Agent reinitialization attempted'
+            })
+        
+        except Exception as e:
+            log_structured('error', 'Error during agent reinitialization', {
+                'error': str(e),
+                'traceback': traceback.format_exc()
+            })
+            return jsonify({
+                'success': False, 
+                'error': str(e),
+                'message': 'Error during reinitialization'
+            }), 500
+
+
+    @app.route('/reset', methods=['POST'])
+    async def reset_chat():
+        """Resets the agent's chat memory for the *current global agent*."""
+        # NOTE: This resets the memory of the SINGLE global agent instance.
+        # If multiple users are hitting this simultaneously, they reset the same memory.
+        # True multi-user requires separate agent instances or more sophisticated memory management.
+        # This endpoint might be more suitable for single-user testing or demos.
+        # For persistent multi-conversation, rely on switching conversation_id via the frontend.
+        session_id = None
+        try:
+            data = request.get_json()
+            session_id = data.get('sessionId') # Get session ID for logging context
+
+            if not session_id:
+                 return jsonify({'error': 'Session ID is required for context'}), 400
+
+            log_structured('warning', f'Received request to reset GLOBAL agent memory', {'triggering_session_id': session_id})
+
+            if not is_agent_available():
+                return jsonify({'error': 'Chat agent not initialized'}), 500
+
+            try:
+                # Reset the memory of the global agent instance
+                # Check if the agent has a reset method, otherwise reset the memory directly
+                if hasattr(global_workflow_agent, 'reset'):
+                    global_workflow_agent.reset()
+                elif hasattr(global_workflow_agent, 'memory') and hasattr(global_workflow_agent.memory, 'reset'):
+                    global_workflow_agent.memory.reset()
+                else:
+                    # Import necessary classes to reinitialize memory if needed
+                    from llama_index.core.memory import ChatMemoryBuffer
+                    global_workflow_agent.memory = ChatMemoryBuffer.from_defaults(llm=global_workflow_agent.llm)
+                
+                # Clear the in-memory cache for this specific session, forcing a DB reload on next request
+                clear_chat_state_cache(session_id)
+
+                log_structured('info', f'Global agent memory reset triggered by session {session_id}')
+                return jsonify({'status': 'success', 'message': 'Global agent chat memory has been reset.'})
+            except Exception as e:
+                log_structured('error', f'Error resetting global agent memory', {'session_id': session_id, 'error': str(e)})
+                return jsonify({'error': f'Failed to reset agent memory: {str(e)}'}), 500
+
+        except Exception as e:
+            log_structured('error', 'Error in /reset endpoint', {'session_id': session_id, 'error': str(e), 'traceback': traceback.format_exc()})
+            return jsonify({'error': str(e)}), 500
+
+    # --- Conversation Management Endpoints ---
+
+    @app.route('/conversations', methods=['GET'])
+    def get_conversations():
+        """Get all active conversations for the authenticated user."""
+        username = request.headers.get('X-MS-USERNAME')
+        # Check if we're in development mode
+        if not username and os.environ.get("PRODUCTION", "false").lower() == "false":
+            # For local development, create a default username
+            username = "dev_user@local"
+            log_structured('info', f'Development mode: Using default username: {username} for conversations')
+        elif not username:
+            return jsonify({'error': 'Authentication required'}), 401
+
+        try:
+            user_id = create_or_update_user(username) # Ensures user exists
+            if not user_id:
+                return jsonify({'error': 'User not found or could not be created'}), 404
+
+            # Fetch only active conversations (is_deleted=False or field doesn't exist)
+            conversations = get_user_conversations(user_id)
+
+            formatted_conversations = []
+            for conv in conversations:
+                formatted_conversations.append({
+                    'id': str(conv['_id']),
+                    'title': conv.get('title', 'Untitled Conversation'),
+                    'created_at': conv.get('created_at', datetime.min).isoformat(),
+                    'last_updated': conv.get('last_updated', datetime.min).isoformat(),
+                    'session_id': conv.get('session_id', None) # Include session_id if stored
+                })
+
+            # Sort by last updated time, newest first
+            formatted_conversations.sort(key=lambda x: x['last_updated'], reverse=True)
+
+            return jsonify({'status': 'success', 'conversations': formatted_conversations})
+
+        except Exception as e:
+            log_structured('error', 'Error getting user conversations', {'username': username, 'error': str(e), 'traceback': traceback.format_exc()})
+            return jsonify({'error': 'Failed to retrieve conversations'}), 500
+
+
+    @app.route('/conversations//messages', methods=['GET'])
+    def get_conversation_msgs(conversation_id_str):
+        """Get all messages for a specific conversation."""
+        username = request.headers.get('X-MS-USERNAME')
+        # Check if we're in development mode
+        if not username and os.environ.get("PRODUCTION", "false").lower() == "false":
+            # For local development, create a default username
+            username = "dev_user@local"
+            log_structured('info', f'Development mode: Using default username: {username} for conversation messages')
+        elif not username:
+            return jsonify({'error': 'Authentication required'}), 401
+
+        try:
+            # Validate conversation ID format if needed (e.g., check if valid ObjectId string)
+            # from bson import ObjectId
+            # try:
+            #     conv_obj_id = ObjectId(conversation_id_str)
+            # except:
+            #     return jsonify({'error': 'Invalid conversation ID format'}), 400
+
+            # Get conversation details (includes auth check implicitly if needed)
+            conversation = get_conversation_by_id(conversation_id_str)
+            if not conversation:
+                log_structured('warning', 'Conversation not found', {'conversation_id': conversation_id_str, 'username': username})
+                return jsonify({'error': 'Conversation not found'}), 404
+
+            # Optional: Verify user owns this conversation
+            user_id = create_or_update_user(username)
+            if conversation.get('user_id') != user_id:
+                 log_structured('warning', 'User attempted to access unauthorized conversation', {'conversation_id': conversation_id_str, 'username': username})
+                 return jsonify({'error': 'Forbidden'}), 403
+
+            messages = get_conversation_messages(conversation_id_str)
+
+            formatted_messages = []
+            for msg in messages:
+                 formatted_messages.append({
+                     'id': str(msg['_id']),
+                     'role': msg.get('role'),
+                     'content': msg.get('content'),
+                     'timestamp': msg.get('timestamp', datetime.min).isoformat(),
+                     'sources': msg.get('sources', []), # Ensure these are serializable
+                     'reasoning': msg.get('reasoning', []),# Ensure these are serializable
+                     'images': msg.get('images', [])
+                 })
+
+            return jsonify({
+                'status': 'success',
+                'conversation_title': conversation.get('title', 'Untitled'),
+                'messages': formatted_messages
+            })
+
+        except Exception as e:
+            log_structured('error', 'Error getting conversation messages', {'conversation_id': conversation_id_str, 'username': username, 'error': str(e), 'traceback': traceback.format_exc()})
+            return jsonify({'error': 'Failed to retrieve messages'}), 500
+
+    @app.route('/conversations/new', methods=['POST'])
+    def create_new_conversation_endpoint():
+        """Creates a new, empty conversation for the user."""
+        username = request.headers.get('X-MS-USERNAME')
+        # Check if we're in development mode
+        if not username and os.environ.get("PRODUCTION", "false").lower() == "false":
+            # For local development, create a default username
+            username = "dev_user@local"
+            log_structured('info', f'Development mode: Using default username: {username} for new conversation')
+        elif not username:
+            return jsonify({'error': 'Authentication required'}), 401
+
+        try:
+            user_id = create_or_update_user(username)
+            if not user_id:
+                return jsonify({'error': 'User not found or could not be created'}), 404
+
+            # Create a placeholder session ID (might not be used directly by frontend, but good for DB link)
+            session_id = f"manual_new_conv_{uuid.uuid4().hex[:8]}"
+            # Create conversation with a default title
+            new_conv_title = f"New Chat ({datetime.now().strftime('%Y-%m-%d %H:%M')})"
+            conversation_id = create_conversation(session_id, user_id, title=new_conv_title)
+
+            if not conversation_id:
+                return jsonify({'error': 'Failed to create conversation'}), 500
+
+            log_structured('info', 'New conversation created manually', {'username': username, 'conversation_id': conversation_id})
+
+            # Return the ID and title of the newly created conversation
+            return jsonify({
+                'status': 'success',
+                'conversation_id': str(conversation_id),
+                'title': new_conv_title
+            })
+
+        except Exception as e:
+            log_structured('error', 'Error creating new conversation', {'username': username, 'error': str(e), 'traceback': traceback.format_exc()})
+            return jsonify({'error': 'Failed to create conversation'}), 500
+
+
+    @app.route('/conversations/', methods=['DELETE'])
+    def delete_conversation_route(conversation_id_str):
+        """Deletes (soft by default) a specific conversation."""
+        username = request.headers.get('X-MS-USERNAME')
+        # Check if we're in development mode
+        if not username and os.environ.get("PRODUCTION", "false").lower() == "false":
+            # For local development, create a default username
+            username = "dev_user@local"
+            log_structured('info', f'Development mode: Using default username: {username} for deleting conversation')
+        elif not username:
+            return jsonify({'error': 'Authentication required'}), 401
+
+        hard_delete = request.args.get('hard_delete', 'false').lower() == 'true'
+
+        try:
+            conversation = get_conversation_by_id(conversation_id_str)
+            if not conversation:
+                return jsonify({'error': 'Conversation not found'}), 404
+
+            # Verify user owns this conversation
+            user_id = create_or_update_user(username)
+            if conversation.get('user_id') != user_id:
+                 return jsonify({'error': 'Forbidden'}), 403
+
+            success = db_delete_conversation(conversation_id_str, hard_delete=hard_delete)
+
+            if success:
+                log_structured('info', f'Conversation {"hard" if hard_delete else "soft"} deleted', {
+                    'conversation_id': conversation_id_str, 'username': username
+                })
+                # Clear any cached state related to this conversation's session_id if known
+                session_id_to_clear = conversation.get('session_id')
+                if session_id_to_clear:
+                     clear_chat_state_cache(session_id_to_clear)
+                return jsonify({'status': 'success'})
+            else:
+                 log_structured('error', 'Failed to delete conversation in DB', {'conversation_id': conversation_id_str})
+                 return jsonify({'error': 'Failed to delete conversation'}), 500
+
+        except Exception as e:
+            log_structured('error', 'Error deleting conversation', {'conversation_id': conversation_id_str, 'username': username, 'error': str(e), 'traceback': traceback.format_exc()})
+            return jsonify({'error': 'Failed to delete conversation'}), 500
+
+
+    # --- Brief Download Endpoint ---
+    @app.route('/download-brief', methods=['POST', 'OPTIONS'])
+    async def download_brief():
+        """Generates and downloads a marketing brief as a Word document."""
+        if request.method == 'OPTIONS':
+             return jsonify({'status': 'ok'}) # Handle pre-flight
+
+        session_id = None
+        try:
+            data = request.get_json()
+            if not data or 'brief_content' not in data:
+                return jsonify({'error': 'No brief content provided'}), 400
+
+            session_id = data.get('sessionId', 'unknown_session') # Get session for context
+            brief_content_markdown = data['brief_content']
+
+            log_structured('info', 'Generating brief document', {'session_id': session_id})
+
+            # Create the Word document in memory using the generator function
+            doc_buffer = create_brief_docx(brief_content_markdown)
+
+            # Send the file
+            download_name = f'marketing_brief_{session_id}_{datetime.now().strftime("%Y%m%d")}.docx'
+            return send_file(
+                doc_buffer,
+                mimetype='application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+                as_attachment=True,
+                download_name=download_name
+            )
+
+        except Exception as e:
+            log_structured('error', 'Error generating or sending brief document', {
+                'session_id': session_id, 'error': str(e), 'traceback': traceback.format_exc()
+            })
+            return jsonify({
+                'status': 'error',
+                'error': 'Failed to generate brief document',
+                'detail': str(e)
+            }), 500
\ No newline at end of file
diff --git a/session_manager.py b/session_manager.py
new file mode 100644
index 0000000..8c35872
--- /dev/null
+++ b/session_manager.py
@@ -0,0 +1,162 @@
+# hp_chatbot/session_manager.py
+
+from typing import Dict, Any, Optional
+import uuid
+import time
+from datetime import datetime
+
+# Import MongoDB utilities from the separate file
+from mongodb_utils import (
+    get_db, create_or_update_user, get_user_by_username,
+    create_conversation, get_conversation, get_conversation_by_id, get_user_conversations,
+    get_conversation_messages, add_message, update_conversation_title,
+    generate_conversation_title, delete_conversation,
+    get_session_state as db_get_session_state, # Rename to avoid conflict
+    create_session_state as db_create_session_state,
+    update_session_state as db_update_session_state
+)
+
+# Import necessary components from ai_core
+# Use forward reference for ReActAgent2 if needed, or import normally if load order allows
+from ai_core import global_workflow_agent, ReActAgent2
+
+# Import logging
+from utils import log_structured
+
+# --- In-memory Session Cache ---
+# Stores session-specific data like associated conversation_id and user_id
+# Key: session_id (string), Value: dict {'conversation_id': ObjectId, 'user_id': ObjectId}
+# Note: The actual agent *instance* is now global (global_workflow_agent),
+# but its *memory* provides conversation context. Resetting the agent's memory
+# effectively resets the conversation for that agent instance.
+# We still need to map a *frontend session ID* to a *persistent conversation ID* in the DB.
+chat_state: Dict[str, Dict[str, Any]] = {}
+
+def get_or_create_session_state(session_id: str, username: Optional[str] = None) -> Dict[str, Any]:
+    """
+    Gets or creates session state, mapping session_id to user and conversation in MongoDB.
+    Returns a dictionary containing 'conversation_id' and 'user_id'.
+    The 'workflow_agent' is now global and not stored per session here.
+
+    Args:
+        session_id: The unique identifier from the frontend/client.
+        username: Optional username for linking to a user.
+
+    Returns:
+        A dictionary like {'conversation_id': ObjectId, 'user_id': ObjectId, 'initialized': bool}
+    """
+    global global_workflow_agent # Access the global agent
+
+    # 1. Check in-memory cache first
+    if session_id in chat_state:
+        cached_state = chat_state[session_id]
+        # Ensure it has the necessary keys before returning
+        if 'conversation_id' in cached_state and 'user_id' in cached_state:
+             log_structured('debug', f'Session cache hit for {session_id}', {'cached_state': cached_state})
+             cached_state['initialized'] = global_workflow_agent is not None
+             return cached_state
+        else:
+             log_structured('warning', f'Cached state for {session_id} is incomplete. Re-fetching.', {'cached_state': cached_state})
+             # Remove incomplete entry and proceed to DB check
+             del chat_state[session_id]
+
+
+    # 2. Check persistent storage (MongoDB) for this session_id
+    mongo_session_data = None
+    try:
+        mongo_session_data = db_get_session_state(session_id)
+    except Exception as db_err:
+        log_structured('error', f'Error accessing MongoDB for session {session_id}: {str(db_err)}')
+        # Continue with fallback approach
+
+    user_id = None
+    conversation_id = None
+
+    if mongo_session_data:
+        log_structured('info', f'Loaded existing session state from MongoDB for {session_id}', {
+            'db_data': mongo_session_data # Be careful logging sensitive data
+        })
+        try:
+            user_id = mongo_session_data.get('user_id')
+            conversation_id = mongo_session_data.get('conversation_id')
+        except Exception as parse_err:
+            log_structured('error', f'Error parsing MongoDB session data: {str(parse_err)}')
+            mongo_session_data = None
+
+        # Validate retrieved IDs
+        if not user_id or not conversation_id:
+             log_structured('error', f'Incomplete session data found in DB for {session_id}. Recreating.', {'db_data': mongo_session_data})
+             # Force creation of a new conversation/session state below
+             mongo_session_data = None # Treat as if not found
+
+    # 3. If not found in cache or DB, or if data was invalid, create new state
+    if not mongo_session_data:
+        log_structured('info', f'No valid session state found for {session_id}. Creating new.', {'username': username})
+
+        # Determine User ID
+        effective_username = username if username else f"anonymous_{session_id[:8]}"
+        
+        try:
+            user_id = create_or_update_user(effective_username)
+        except Exception as user_err:
+            log_structured('error', f'Failed to create user in MongoDB: {str(user_err)}')
+            # Create a temporary ID for in-memory operation
+            user_id = f"temp_user_{uuid.uuid4().hex}"
+            log_structured('info', f'Using temporary user ID: {user_id}')
+            
+        if not user_id:
+            log_structured('error', f"Failed to create or update user: {effective_username}")
+            # Create a fallback user ID for in-memory operation
+            user_id = f"fallback_user_{uuid.uuid4().hex}"
+            log_structured('info', f'Using fallback user ID: {user_id}')
+
+        # Create a new Conversation linked to this user
+        # Use a default title, it will be updated after the first interaction
+        new_conv_title = f"New Chat ({datetime.now().strftime('%Y-%m-%d %H:%M')})"
+        
+        try:
+            conversation_id = create_conversation(session_id, user_id, title=new_conv_title)
+        except Exception as conv_err:
+            log_structured('error', f'Failed to create conversation in MongoDB: {str(conv_err)}')
+            # Create a temporary conversation ID for in-memory operation
+            conversation_id = f"temp_conv_{uuid.uuid4().hex}"
+            log_structured('info', f'Using temporary conversation ID: {conversation_id}')
+            
+        if not conversation_id:
+            log_structured('error', f"Failed to create conversation for session {session_id}, user {user_id}")
+            # Create a fallback conversation ID for in-memory operation
+            conversation_id = f"fallback_conv_{uuid.uuid4().hex}"
+            log_structured('info', f'Using fallback conversation ID: {conversation_id}')
+
+        # Store the new session state linkage in MongoDB
+        try:
+            db_create_session_state(session_id, user_id, conversation_id)
+        except Exception as session_err:
+            log_structured('warning', f"Failed to persist new session state link in DB: {str(session_err)}")
+            # Continue with in-memory operation
+
+        log_structured('info', f'Created new conversation and session state link', {
+            'session_id': session_id, 'user_id': user_id, 'conversation_id': conversation_id
+        })
+
+    # 4. Store in the in-memory cache and return
+    # We store the DB IDs, not the agent object itself
+    current_state = {
+        'initialized': global_workflow_agent is not None,
+        'conversation_id': conversation_id,
+        'user_id': user_id
+    }
+    chat_state[session_id] = current_state
+
+    return current_state
+
+def clear_chat_state_cache(session_id: Optional[str] = None):
+    """ Clears the in-memory chat state cache. """
+    global chat_state
+    if session_id:
+        if session_id in chat_state:
+            del chat_state[session_id]
+            log_structured('info', f'Cleared in-memory cache for session {session_id}')
+    else:
+        chat_state = {}
+        log_structured('info', 'Cleared all in-memory session cache')
\ No newline at end of file
diff --git a/shared_state.py b/shared_state.py
new file mode 100644
index 0000000..1139126
--- /dev/null
+++ b/shared_state.py
@@ -0,0 +1,102 @@
+# hp_chatbot/shared_state.py
+"""
+Shared state module to store global variables that need to be
+accessible across different modules and ensures proper synchronization.
+"""
+
+# Store the AI agent here so it's properly shared across modules
+global_workflow_agent = None
+
+# Store the global index here
+global_index = None
+
+# Store GraphRAG components
+global_graph_store = None
+global_property_graph_index = None
+global_graphrag_query_engine = None
+
+# Helper to set the global agent
+def set_global_agent(agent):
+    """Set the global agent instance."""
+    global global_workflow_agent
+    from utils import log_structured
+    
+    if agent is None:
+        log_structured('error', 'Attempted to set global_workflow_agent to None')
+        return False
+        
+    try:
+        # Check that the agent has a run method
+        if not hasattr(agent, 'run'):
+            log_structured('error', 'Agent being set does not have a run method')
+            return False
+            
+        # Set the global agent
+        global_workflow_agent = agent
+        
+        # Verify it was set correctly
+        has_run = hasattr(global_workflow_agent, 'run')
+        success = global_workflow_agent is not None and has_run
+        
+        log_structured('info', f'Global agent set successfully: {success}', {
+            'has_run_method': has_run,
+            'agent_type': type(agent).__name__
+        })
+        
+        return success
+    except Exception as e:
+        log_structured('error', f'Error setting global agent: {str(e)}')
+        return False
+
+# Helper to set the global index
+def set_global_index(index):
+    """Set the global index instance."""
+    global global_index
+    global_index = index
+    return global_index is not None
+
+# Helper to set the GraphRAG components
+def set_graphrag_components(graph_store, property_graph_index, graphrag_query_engine):
+    """Set the global GraphRAG components."""
+    global global_graph_store, global_property_graph_index, global_graphrag_query_engine
+    
+    from utils import log_structured
+    
+    global_graph_store = graph_store
+    global_property_graph_index = property_graph_index
+    global_graphrag_query_engine = graphrag_query_engine
+    
+    components_set = (global_graph_store is not None and 
+                     global_property_graph_index is not None and 
+                     global_graphrag_query_engine is not None)
+    
+    log_structured('info', f'GraphRAG components set successfully: {components_set}')
+    return components_set
+
+# Helper to get agent status
+def is_agent_available():
+    """
+    Check if the global agent is available.
+    Uses direct reference to ensure we check the current module state.
+    """
+    from utils import log_structured
+    
+    # Access the module-level global_workflow_agent directly
+    # We are using the global_workflow_agent from this module, not importing it
+    # This avoids circular import issues and ensures we're checking the actual current value
+    
+    # IMPORTANT: Declare as global to ensure we're checking the correct module-level variable
+    global global_workflow_agent
+    
+    is_available = global_workflow_agent is not None and hasattr(global_workflow_agent, 'run')
+    
+    # Add detailed logging
+    if not is_available:
+        if global_workflow_agent is None:
+            log_structured('warning', 'Agent availability check failed: global_workflow_agent is None')
+        elif not hasattr(global_workflow_agent, 'run'):
+            log_structured('warning', 'Agent availability check failed: global_workflow_agent has no run method')
+    else:
+        log_structured('debug', 'Agent availability check passed: agent exists and has run method')
+    
+    return is_available
\ No newline at end of file
diff --git a/utils.py b/utils.py
new file mode 100644
index 0000000..f18e830
--- /dev/null
+++ b/utils.py
@@ -0,0 +1,178 @@
+# hp_chatbot/utils.py
+import logging
+import json
+import os
+import shutil
+from datetime import datetime, timezone
+from typing import Optional, Dict, Any
+from config import LOG_FILE_PATH, CHUNK_FOLDER, UPLOAD_METADATA_FOLDER, ALLOWED_EXTENSIONS
+from llama_index.core.tools import ToolOutput # Import ToolOutput for serialization check
+
+# Configure logging
+logging.basicConfig(
+    level=logging.INFO, # Set level from config later if needed
+    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
+    handlers=[
+        logging.StreamHandler(),
+        logging.FileHandler(LOG_FILE_PATH)
+    ]
+)
+logger = logging.getLogger(__name__)
+
+# Import after logger is defined to avoid circular dependency if CustomJSONEncoder uses logger
+from json_utils import CustomJSONEncoder
+
+# --- Logging Helper ---
+def log_structured(level: str, event_message: str, data: Optional[Dict[str, Any]] = None):
+    """
+    Structured logging helper
+    Args:
+        level: The logging level ('info', 'error', etc.)
+        event_message: The main message describing the event
+        data: Optional dictionary of additional data to log
+    """
+    # Basic serializer to handle common non-serializable types safely
+    def safe_serialize(obj):
+        if isinstance(obj, ToolOutput):
+             # Let CustomJSONEncoder handle ToolOutput specifics if passed directly
+             return obj # Pass it through for the encoder
+        if isinstance(obj, (datetime)):
+            return obj.isoformat()
+        if isinstance(obj, bytes):
+            return ""
+        if hasattr(obj, '__dict__') and not isinstance(obj, (ToolOutput)): # Avoid double processing ToolOutput
+            # Very basic dict representation, avoid complex objects
+            try:
+                # Limit recursion depth or complexity if needed
+                return {k: safe_serialize(v) for k, v in obj.__dict__.items() if not k.startswith('_') and not callable(v)}
+            except Exception:
+                 return f"" # Fallback for complex objects
+        # Add more types as needed (e.g., ObjectId, specific LlamaIndex objects if problematic)
+        return obj # Let JSON encoder handle the rest or fail
+
+    log_data = {
+        'timestamp': datetime.now(timezone.utc).isoformat(),
+        'event': event_message
+    }
+
+    if data is not None:
+        try:
+            # Apply safe serialization recursively to the data dictionary
+            serialized_data = json.loads(json.dumps(data, default=safe_serialize))
+            log_data['data'] = serialized_data
+        except (TypeError, OverflowError, ValueError) as json_err:
+            logger.error(f"Serialization error in log_structured for event '{event_message}': {json_err}. Logging basic info.")
+            log_data['data_serialization_error'] = str(json_err)
+            # Attempt to log basic data structure if possible
+            try:
+                basic_data = {k: str(type(v)) for k, v in data.items()}
+                log_data['data_structure'] = basic_data
+            except Exception:
+                 log_data['data_structure'] = ""
+        except Exception as e:
+            logger.error(f"Unexpected error during safe_serialize or json.dumps in log_structured: {e}")
+            log_data['logging_error'] = str(e)
+
+
+    try:
+        # Use the custom encoder for final JSON dump
+        log_string = json.dumps(log_data, cls=CustomJSONEncoder)
+        getattr(logger, level.lower())(log_string)
+    except AttributeError:
+        logger.error(f"Invalid log level: {level}. Defaulting to error.")
+        logger.error(json.dumps(log_data, cls=CustomJSONEncoder))
+    except Exception as e:
+        # Fallback logging if JSON fails completely
+        logger.error(f"FATAL: Error serializing log message with CustomJSONEncoder: {e}")
+        fallback_msg = f"{event_message}"
+        if data:
+            fallback_msg += f" | Data keys: {list(data.keys())}"
+        logger.error(fallback_msg)
+
+
+# --- Response Validation ---
+def validate_response(response: dict) -> bool:
+    """Validate the structure of a response"""
+    # Simple validation, adjust as needed
+    required_fields = {'response', 'sources', 'reasoning'}
+    return isinstance(response, dict) and all(field in response for field in required_fields)
+
+# --- File Handling Utilities (Keep if chunking/upload is potentially needed later) ---
+def get_upload_metadata(upload_id):
+    """Load metadata for an upload"""
+    metadata_path = os.path.join(UPLOAD_METADATA_FOLDER, f"{upload_id}.json")
+    if not os.path.exists(metadata_path):
+        return None
+    try:
+        with open(metadata_path, 'r') as f:
+            return json.load(f)
+    except Exception as e:
+        log_structured('error', f'Failed to load upload metadata for {upload_id}', {'error': str(e)})
+        return None
+
+def save_upload_metadata(upload_id, metadata):
+    """Save metadata for an upload"""
+    metadata_path = os.path.join(UPLOAD_METADATA_FOLDER, f"{upload_id}.json")
+    try:
+        with open(metadata_path, 'w') as f:
+            json.dump(metadata, f)
+    except Exception as e:
+        log_structured('error', f'Failed to save upload metadata for {upload_id}', {'error': str(e)})
+
+def get_chunk_path(upload_id, chunk_index):
+    """Get path for a specific chunk"""
+    upload_chunk_dir = os.path.join(CHUNK_FOLDER, upload_id)
+    os.makedirs(upload_chunk_dir, exist_ok=True)
+    return os.path.join(upload_chunk_dir, f"chunk_{chunk_index}")
+
+def combine_chunks(upload_id, destination_path):
+    """Combine all chunks into a single file"""
+    metadata = get_upload_metadata(upload_id)
+    if not metadata or 'totalChunks' not in metadata:
+        log_structured('error', f'Metadata missing or invalid for combining chunks: {upload_id}')
+        return False
+
+    upload_chunk_dir = os.path.join(CHUNK_FOLDER, upload_id)
+    try:
+        with open(destination_path, 'wb') as outfile:
+            for i in range(metadata['totalChunks']):
+                chunk_path = os.path.join(upload_chunk_dir, f"chunk_{i}")
+                if os.path.exists(chunk_path):
+                    with open(chunk_path, 'rb') as infile:
+                        outfile.write(infile.read())
+                else:
+                    log_structured('error', f'Chunk {i} missing for upload {upload_id}')
+                    # Clean up partially created file
+                    if os.path.exists(destination_path):
+                        os.remove(destination_path)
+                    return False
+        return True
+    except Exception as e:
+        log_structured('error', f'Error combining chunks for {upload_id}', {'error': str(e)})
+        # Clean up partially created file
+        if os.path.exists(destination_path):
+            os.remove(destination_path)
+        return False
+
+def clear_upload_chunks(upload_id):
+    """Remove all chunks and metadata for an upload"""
+    upload_chunk_dir = os.path.join(CHUNK_FOLDER, upload_id)
+    if os.path.exists(upload_chunk_dir):
+        try:
+            shutil.rmtree(upload_chunk_dir)
+            log_structured('info', f'Cleared chunk directory: {upload_chunk_dir}')
+        except Exception as e:
+            log_structured('error', f'Failed to remove chunk directory {upload_chunk_dir}', {'error': str(e)})
+
+    metadata_path = os.path.join(UPLOAD_METADATA_FOLDER, f"{upload_id}.json")
+    if os.path.exists(metadata_path):
+        try:
+            os.remove(metadata_path)
+            log_structured('info', f'Cleared metadata file: {metadata_path}')
+        except Exception as e:
+            log_structured('error', f'Failed to remove metadata file {metadata_path}', {'error': str(e)})
+
+
+def allowed_file(filename):
+    """Check if a filename has an allowed extension"""
+    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
\ No newline at end of file

c3X=zj&Yj6Vm5jU;7vH^Iu3j|1x?0 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