slothquery 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- slothquery-1.0.0/MANIFEST.in +1 -0
- slothquery-1.0.0/PKG-INFO +22 -0
- slothquery-1.0.0/README.md +229 -0
- slothquery-1.0.0/backend/app/__init__.py +1 -0
- slothquery-1.0.0/backend/app/cli.py +26 -0
- slothquery-1.0.0/backend/app/database.py +24 -0
- slothquery-1.0.0/backend/app/dist/assets/index-BDTPNUTQ.css +1 -0
- slothquery-1.0.0/backend/app/dist/assets/index-DKvMVJoY.js +269 -0
- slothquery-1.0.0/backend/app/dist/assets/logo-RBZv3XvP.png +0 -0
- slothquery-1.0.0/backend/app/dist/index.html +14 -0
- slothquery-1.0.0/backend/app/main.py +79 -0
- slothquery-1.0.0/backend/app/models.py +90 -0
- slothquery-1.0.0/backend/app/schemas.py +119 -0
- slothquery-1.0.0/backend/slothquery.egg-info/PKG-INFO +22 -0
- slothquery-1.0.0/backend/slothquery.egg-info/SOURCES.txt +19 -0
- slothquery-1.0.0/backend/slothquery.egg-info/dependency_links.txt +1 -0
- slothquery-1.0.0/backend/slothquery.egg-info/entry_points.txt +2 -0
- slothquery-1.0.0/backend/slothquery.egg-info/requires.txt +10 -0
- slothquery-1.0.0/backend/slothquery.egg-info/top_level.txt +1 -0
- slothquery-1.0.0/setup.cfg +4 -0
- slothquery-1.0.0/setup.py +31 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
recursive-include backend/app/dist *
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: slothquery
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Local-first organizational intelligence platform
|
|
5
|
+
Author: Ayush Thakur
|
|
6
|
+
Author-email: ayush01thakur@gmail.com
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Requires-Dist: fastapi
|
|
9
|
+
Requires-Dist: uvicorn
|
|
10
|
+
Requires-Dist: pydantic
|
|
11
|
+
Requires-Dist: sqlalchemy
|
|
12
|
+
Requires-Dist: cryptography
|
|
13
|
+
Requires-Dist: chromadb
|
|
14
|
+
Requires-Dist: litellm
|
|
15
|
+
Requires-Dist: sentence-transformers
|
|
16
|
+
Requires-Dist: sqlglot
|
|
17
|
+
Requires-Dist: python-multipart
|
|
18
|
+
Dynamic: author
|
|
19
|
+
Dynamic: author-email
|
|
20
|
+
Dynamic: requires-dist
|
|
21
|
+
Dynamic: requires-python
|
|
22
|
+
Dynamic: summary
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# SlothQuery
|
|
4
|
+
|
|
5
|
+
**Local-first organizational intelligence platform for SQL engineers and data analysts.**
|
|
6
|
+
|
|
7
|
+
SlothQuery transforms your raw SQL queries, business rules, table schemas, and analyst notes into a searchable, AI-powered knowledge base — so your team never has to rediscover the same logic twice.
|
|
8
|
+
|
|
9
|
+
[](https://python.org)
|
|
10
|
+
[](https://fastapi.tiangolo.com)
|
|
11
|
+
[](https://react.dev)
|
|
12
|
+
[](https://typescriptlang.org)
|
|
13
|
+
[](https://sqlite.org)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## What is SlothQuery?
|
|
20
|
+
|
|
21
|
+
SlothQuery is a **local-first** knowledge retrieval system for data teams. Instead of storing queries in a flat file or Notion doc, SlothQuery extracts structured intelligence from each query — business intent, schema entities, business rules, transformations — and makes all of it searchable and retrievable at chat time.
|
|
22
|
+
|
|
23
|
+
Think of it as **institutional memory for your SQL stack**, powered by an LLM that only ever answers from your own grounded knowledge — never from hallucinated context.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Tech Stack
|
|
28
|
+
|
|
29
|
+
| Layer | Technologies |
|
|
30
|
+
|---|---|
|
|
31
|
+
| **Backend** | Python · FastAPI · SQLAlchemy · SQLite · ChromaDB · LiteLLM |
|
|
32
|
+
| **Frontend** | React · TypeScript · Vite · Tailwind CSS · Axios · Lucide Icons |
|
|
33
|
+
| **AI / Retrieval** | BGE-small-en-v1.5 (local embeddings) · LiteLLM (multi-provider LLM) · ChromaDB (vector search) |
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Features
|
|
38
|
+
|
|
39
|
+
### Knowledge Studio
|
|
40
|
+
- Add SQL queries with title, description, dialect, tags, and analyst comments
|
|
41
|
+
- Human-in-the-loop AI extraction — review and approve extracted business intent, schema entities, business rules, metric transformations, and ambiguities before saving
|
|
42
|
+
- Organize knowledge into domain Vaults (e.g. Marketing, Finance, Product)
|
|
43
|
+
- Business Rules Playbooks — consolidated business logic documentation
|
|
44
|
+
- Table Schema documentation with join patterns and naming conventions
|
|
45
|
+
- Analyst Notes — freeform knowledge about metrics, caveats, and patterns
|
|
46
|
+
- Delete queries (with ChromaDB sync) and delete entire vaults (full cascade)
|
|
47
|
+
|
|
48
|
+
### Chat Interface
|
|
49
|
+
- Grounded AI chat — every answer is retrieved from your knowledge base; the LLM never invents tables or metrics
|
|
50
|
+
- Multi-vault context — query across multiple vaults in a single conversation
|
|
51
|
+
- Dialect-aware SQL generation — Snowflake, BigQuery, PostgreSQL, Trino, Redshift
|
|
52
|
+
- Tag filtering — narrow retrieval to specific topic tags
|
|
53
|
+
- Markdown-rendered responses with bold, italic, lists, and SQL code blocks with one-click copy
|
|
54
|
+
- Auto-named persistent chat history
|
|
55
|
+
- Onboarding guard — if your knowledge base is empty, SlothQuery guides you to add content first
|
|
56
|
+
|
|
57
|
+
### LLM Provider Management
|
|
58
|
+
- Supports OpenAI, Anthropic, Google Gemini, Groq, OpenRouter, DeepSeek
|
|
59
|
+
- API keys are encrypted with Fernet symmetric encryption before being written to SQLite — never logged or exposed to the frontend
|
|
60
|
+
- Test Connection before saving
|
|
61
|
+
- Dynamic provider switching without restarting the app
|
|
62
|
+
- Last active provider automatically restored on restart
|
|
63
|
+
|
|
64
|
+
### Knowledge Portability
|
|
65
|
+
- Export your entire knowledge base or individual vaults as a `.slothkb` archive
|
|
66
|
+
- Import and automatically re-index embeddings
|
|
67
|
+
- Re-index — rebuild the entire ChromaDB vector store from SQLite at any time
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Architecture
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
UI (React)
|
|
75
|
+
↓
|
|
76
|
+
API (FastAPI)
|
|
77
|
+
↓
|
|
78
|
+
Services (chat · extraction · retrieval · provider · vector_store)
|
|
79
|
+
↓
|
|
80
|
+
Repositories (SQLAlchemy)
|
|
81
|
+
↓
|
|
82
|
+
Storage (SQLite + ChromaDB)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
- **Local-first** — all data lives in `~/Documents/SlothQuery/` on your machine
|
|
86
|
+
- **SQLite** is the source of truth for all structured data
|
|
87
|
+
- **ChromaDB** is derived state — always rebuildable from SQLite via Re-index
|
|
88
|
+
- **No cloud dependency** — works fully offline once the embedding model is cached
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Getting Started
|
|
93
|
+
|
|
94
|
+
### Prerequisites
|
|
95
|
+
- Python 3.10+
|
|
96
|
+
- Node.js 18+
|
|
97
|
+
- An API key from any supported LLM provider
|
|
98
|
+
|
|
99
|
+
### 1. Clone the repository
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
git clone https://github.com/your-username/slothquery.git
|
|
103
|
+
cd slothquery
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 2. Set up the Backend
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
cd backend
|
|
110
|
+
|
|
111
|
+
# Create and activate a virtual environment
|
|
112
|
+
python -m venv venv
|
|
113
|
+
|
|
114
|
+
# Windows
|
|
115
|
+
.\venv\Scripts\activate
|
|
116
|
+
|
|
117
|
+
# macOS / Linux
|
|
118
|
+
source venv/bin/activate
|
|
119
|
+
|
|
120
|
+
# Install dependencies
|
|
121
|
+
pip install -r requirements.txt
|
|
122
|
+
|
|
123
|
+
# Start the backend server
|
|
124
|
+
uvicorn app.main:app --reload --port 8000
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
> First run downloads the BGE-small-en-v1.5 embedding model (~130MB). Subsequent starts are fast.
|
|
128
|
+
|
|
129
|
+
API available at: `http://127.0.0.1:8000`
|
|
130
|
+
Interactive docs: `http://127.0.0.1:8000/docs`
|
|
131
|
+
|
|
132
|
+
### 3. Set up the Frontend
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
cd frontend
|
|
136
|
+
npm install
|
|
137
|
+
npm run dev
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
App available at: `http://localhost:3000`
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## How to Use SlothQuery
|
|
145
|
+
|
|
146
|
+
### Step 1 — Configure an LLM Provider
|
|
147
|
+
1. Open `http://localhost:3000`
|
|
148
|
+
2. Click the **Settings** icon or click **Configure** on the amber banner
|
|
149
|
+
3. Select your provider, enter model name and API key
|
|
150
|
+
4. Click **Test & Save** — your key is encrypted and stored locally
|
|
151
|
+
|
|
152
|
+
### Step 2 — Build Your Knowledge Base
|
|
153
|
+
|
|
154
|
+
Go to **Knowledge Studio** in the left sidebar.
|
|
155
|
+
|
|
156
|
+
**Adding a Query:**
|
|
157
|
+
1. Click `+ Add Asset → Add Query`
|
|
158
|
+
2. Fill in title, vault, dialect, description, and tags
|
|
159
|
+
3. Paste your SQL and analyst comments
|
|
160
|
+
4. Click **Generate & Review Intelligence** — AI extracts context
|
|
161
|
+
5. Review the draft, edit anything incorrect, then **Approve & Save**
|
|
162
|
+
|
|
163
|
+
**Adding Playbooks, Schemas, Notes:**
|
|
164
|
+
1. Click `+ Add Asset` and choose the asset type
|
|
165
|
+
2. Name it, select a vault, write the content, and save
|
|
166
|
+
|
|
167
|
+
### Step 3 — Chat
|
|
168
|
+
|
|
169
|
+
1. Go to the **Chat** view
|
|
170
|
+
2. Ask questions or request SQL — e.g.:
|
|
171
|
+
- *"Show me the ARR calculation query"*
|
|
172
|
+
- *"Write a Snowflake query for weekly active users"*
|
|
173
|
+
- *"What business rules apply to revenue metrics?"*
|
|
174
|
+
3. SlothQuery retrieves matching context and generates a grounded response
|
|
175
|
+
4. SQL appears in a code block with a **Copy** button
|
|
176
|
+
|
|
177
|
+
> Tip: Use the **+** button in the chat input to filter by vault or tags.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Data Storage
|
|
182
|
+
|
|
183
|
+
All data is stored locally at:
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
~/Documents/SlothQuery/
|
|
187
|
+
├── slothquery.db # SQLite — queries, chats, providers (encrypted keys)
|
|
188
|
+
├── chroma_db/ # ChromaDB — vector embeddings (rebuildable)
|
|
189
|
+
└── Exports/ # .slothkb export archives
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
> The SQLite database contains encrypted API keys. Never commit it to version control — it is excluded by `.gitignore`.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Keyboard Shortcuts
|
|
197
|
+
|
|
198
|
+
| Action | Shortcut |
|
|
199
|
+
|---|---|
|
|
200
|
+
| Send chat message | `Enter` |
|
|
201
|
+
| New line in input | `Shift + Enter` |
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Roadmap
|
|
206
|
+
|
|
207
|
+
- [ ] Schema Explorer with live table preview
|
|
208
|
+
- [ ] Query versioning and diff view
|
|
209
|
+
- [ ] Team shared knowledge base sync
|
|
210
|
+
- [ ] Slack / Teams bot integration
|
|
211
|
+
- [ ] Desktop wrapper (Tauri)
|
|
212
|
+
- [ ] MCP server support for AI coding agents
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Contributing
|
|
217
|
+
|
|
218
|
+
Branch naming:
|
|
219
|
+
```
|
|
220
|
+
feat/add-schema-versioning
|
|
221
|
+
fix/resolve-chromadb-sync
|
|
222
|
+
refactor/move-embedding-service
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## License
|
|
228
|
+
|
|
229
|
+
MIT — use freely, build on top, keep it local-first.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# SlothQuery app package
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import uvicorn
|
|
2
|
+
import webbrowser
|
|
3
|
+
import threading
|
|
4
|
+
import time
|
|
5
|
+
from .main import app
|
|
6
|
+
|
|
7
|
+
def open_browser():
|
|
8
|
+
# Wait 1.5 seconds for uvicorn to initialize completely
|
|
9
|
+
time.sleep(1.5)
|
|
10
|
+
print("[*] Opening SlothQuery in default browser...")
|
|
11
|
+
webbrowser.open("http://127.0.0.1:8000")
|
|
12
|
+
|
|
13
|
+
def main():
|
|
14
|
+
print("===================================================")
|
|
15
|
+
print(" SlothQuery Local Launch ")
|
|
16
|
+
print("===================================================")
|
|
17
|
+
print("[*] Initializing local database and indexing vector store...")
|
|
18
|
+
|
|
19
|
+
# Start browser redirect in background thread
|
|
20
|
+
threading.Thread(target=open_browser, daemon=True).start()
|
|
21
|
+
|
|
22
|
+
# Launch uvicorn directly with the FastAPI app instance
|
|
23
|
+
uvicorn.run(app, host="127.0.0.1", port=8000, log_level="info")
|
|
24
|
+
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
main()
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from sqlalchemy import create_engine
|
|
3
|
+
from sqlalchemy.orm import declarative_base, sessionmaker
|
|
4
|
+
|
|
5
|
+
# Define default database path in Documents/SlothQuery
|
|
6
|
+
documents_dir = os.path.join(os.path.expanduser("~"), "Documents", "SlothQuery")
|
|
7
|
+
os.makedirs(documents_dir, exist_ok=True)
|
|
8
|
+
db_path = os.path.join(documents_dir, "slothquery.db")
|
|
9
|
+
|
|
10
|
+
SQLALCHEMY_DATABASE_URL = f"sqlite:///{db_path}"
|
|
11
|
+
|
|
12
|
+
engine = create_engine(
|
|
13
|
+
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
|
|
14
|
+
)
|
|
15
|
+
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
|
16
|
+
|
|
17
|
+
Base = declarative_base()
|
|
18
|
+
|
|
19
|
+
def get_db():
|
|
20
|
+
db = SessionLocal()
|
|
21
|
+
try:
|
|
22
|
+
yield db
|
|
23
|
+
finally:
|
|
24
|
+
db.close()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--background: 0 0% 100%;--foreground: 222.2 84% 4.9%;--card: 0 0% 100%;--card-foreground: 222.2 84% 4.9%;--popover: 0 0% 100%;--popover-foreground: 222.2 84% 4.9%;--primary: 222.2 47.4% 11.2%;--primary-foreground: 210 40% 98%;--secondary: 210 40% 96.1%;--secondary-foreground: 222.2 47.4% 11.2%;--muted: 210 40% 96.1%;--muted-foreground: 215.4 16.3% 46.9%;--accent: 210 40% 96.1%;--accent-foreground: 222.2 47.4% 11.2%;--destructive: 0 84.2% 60.2%;--destructive-foreground: 210 40% 98%;--border: 214.3 31.8% 91.4%;--input: 214.3 31.8% 91.4%;--ring: 222.2 84% 4.9%;--radius: .3rem}*{border-color:hsl(var(--border))}body{background-color:hsl(var(--background));color:hsl(var(--foreground));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.bottom-full{bottom:100%}.left-0{left:0}.left-2\.5{left:.625rem}.right-0{right:0}.right-2{right:.5rem}.top-0{top:0}.top-2{top:.5rem}.top-2\.5{top:.625rem}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.col-span-2{grid-column:span 2 / span 2}.col-span-4{grid-column:span 4 / span 4}.col-span-6{grid-column:span 6 / span 6}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-4{margin-top:1rem;margin-bottom:1rem}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-5{margin-left:1.25rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-2\.5{margin-top:.625rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-8{margin-top:2rem}.block{display:block}.inline{display:inline}.flex{display:flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-20{height:5rem}.h-24{height:6rem}.h-3\.5{height:.875rem}.h-36{height:9rem}.h-72{height:18rem}.h-96{height:24rem}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-24{max-height:6rem}.max-h-32{max-height:8rem}.max-h-40{max-height:10rem}.max-h-48{max-height:12rem}.max-h-56{max-height:14rem}.max-h-\[150px\]{max-height:150px}.max-h-\[40vh\]{max-height:40vh}.max-h-\[80vh\]{max-height:80vh}.max-h-\[85vh\]{max-height:85vh}.min-h-\[28px\]{min-height:28px}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-3\.5{width:.875rem}.w-44{width:11rem}.w-56{width:14rem}.w-64{width:16rem}.w-8{width:2rem}.w-80{width:20rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-screen{width:100vw}.min-w-0{min-width:0px}.min-w-\[240px\]{min-width:240px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-\[200px\]{max-width:200px}.max-w-\[75\%\]{max-width:75%}.max-w-\[85\%\]{max-width:85%}.max-w-\[88\%\]{max-width:88%}.max-w-full{max-width:100%}.max-w-md{max-width:28rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-none{resize:none}.list-outside{list-style-position:outside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-10{grid-template-columns:repeat(10,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.self-start{align-self:flex-start}.self-end{align-self:flex-end}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:var(--radius)}.rounded-xl{border-radius:.75rem}.rounded-b-xl{border-bottom-right-radius:.75rem;border-bottom-left-radius:.75rem}.rounded-tl-none{border-top-left-radius:0}.rounded-tr-none{border-top-right-radius:0}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-none{border-style:none}.border-amber-200\/80{border-color:#fde68acc}.border-amber-300{--tw-border-opacity: 1;border-color:rgb(252 211 77 / var(--tw-border-opacity, 1))}.border-blue-100{--tw-border-opacity: 1;border-color:rgb(219 234 254 / var(--tw-border-opacity, 1))}.border-blue-200{--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1))}.border-blue-200\/50{border-color:#bfdbfe80}.border-blue-200\/80{border-color:#bfdbfecc}.border-blue-500{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.border-emerald-200{--tw-border-opacity: 1;border-color:rgb(167 243 208 / var(--tw-border-opacity, 1))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity, 1))}.border-rose-200{--tw-border-opacity: 1;border-color:rgb(254 205 211 / var(--tw-border-opacity, 1))}.border-slate-100{--tw-border-opacity: 1;border-color:rgb(241 245 249 / var(--tw-border-opacity, 1))}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1))}.border-slate-200\/50{border-color:#e2e8f080}.border-slate-200\/80{border-color:#e2e8f0cc}.border-slate-300{--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1))}.border-slate-400{--tw-border-opacity: 1;border-color:rgb(148 163 184 / var(--tw-border-opacity, 1))}.border-slate-700\/60{border-color:#33415599}.border-slate-800{--tw-border-opacity: 1;border-color:rgb(30 41 59 / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.bg-amber-100{--tw-bg-opacity: 1;background-color:rgb(254 243 199 / var(--tw-bg-opacity, 1))}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-amber-500{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity, 1))}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity, 1))}.bg-background{background-color:hsl(var(--background))}.bg-black\/40{background-color:#0006}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-blue-50\/50{background-color:#eff6ff80}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-emerald-100{--tw-bg-opacity: 1;background-color:rgb(209 250 229 / var(--tw-bg-opacity, 1))}.bg-emerald-50{--tw-bg-opacity: 1;background-color:rgb(236 253 245 / var(--tw-bg-opacity, 1))}.bg-emerald-500{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity, 1))}.bg-emerald-600{--tw-bg-opacity: 1;background-color:rgb(5 150 105 / var(--tw-bg-opacity, 1))}.bg-indigo-100{--tw-bg-opacity: 1;background-color:rgb(224 231 255 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-rose-50{--tw-bg-opacity: 1;background-color:rgb(255 241 242 / var(--tw-bg-opacity, 1))}.bg-slate-100{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.bg-slate-100\/40{background-color:#f1f5f966}.bg-slate-100\/50{background-color:#f1f5f980}.bg-slate-200{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.bg-slate-200\/50{background-color:#e2e8f080}.bg-slate-400{--tw-bg-opacity: 1;background-color:rgb(148 163 184 / var(--tw-bg-opacity, 1))}.bg-slate-50{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.bg-slate-50\/50{background-color:#f8fafc80}.bg-slate-50\/70{background-color:#f8fafcb3}.bg-slate-800\/80{background-color:#1e293bcc}.bg-slate-900{--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity, 1))}.bg-slate-900\/10{background-color:#0f172a1a}.bg-slate-900\/40{background-color:#0f172a66}.bg-teal-100{--tw-bg-opacity: 1;background-color:rgb(204 251 241 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.object-contain{-o-object-fit:contain;object-fit:contain}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-20{padding-top:5rem;padding-bottom:5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pb-6{padding-bottom:1.5rem}.pl-1{padding-left:.25rem}.pl-3{padding-left:.75rem}.pl-8{padding-left:2rem}.pr-1{padding-right:.25rem}.pr-2{padding-right:.5rem}.pr-3{padding-right:.75rem}.pr-7{padding-right:1.75rem}.pt-2{padding-top:.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[9px\]{font-size:9px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-5{line-height:1.25rem}.leading-normal{line-height:1.5}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.text-amber-500{--tw-text-opacity: 1;color:rgb(245 158 11 / var(--tw-text-opacity, 1))}.text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-amber-800{--tw-text-opacity: 1;color:rgb(146 64 14 / var(--tw-text-opacity, 1))}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-blue-500{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity, 1))}.text-emerald-400{--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.text-emerald-500{--tw-text-opacity: 1;color:rgb(16 185 129 / var(--tw-text-opacity, 1))}.text-emerald-600{--tw-text-opacity: 1;color:rgb(5 150 105 / var(--tw-text-opacity, 1))}.text-emerald-700{--tw-text-opacity: 1;color:rgb(4 120 87 / var(--tw-text-opacity, 1))}.text-emerald-800{--tw-text-opacity: 1;color:rgb(6 95 70 / var(--tw-text-opacity, 1))}.text-indigo-700{--tw-text-opacity: 1;color:rgb(67 56 202 / var(--tw-text-opacity, 1))}.text-purple-500{--tw-text-opacity: 1;color:rgb(168 85 247 / var(--tw-text-opacity, 1))}.text-red-800{--tw-text-opacity: 1;color:rgb(153 27 27 / var(--tw-text-opacity, 1))}.text-rose-600{--tw-text-opacity: 1;color:rgb(225 29 72 / var(--tw-text-opacity, 1))}.text-rose-800{--tw-text-opacity: 1;color:rgb(159 18 57 / var(--tw-text-opacity, 1))}.text-slate-100{--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-slate-600{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.text-slate-700{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-slate-800{--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.text-teal-700{--tw-text-opacity: 1;color:rgb(15 118 110 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-\[2px\]{--tw-backdrop-blur: blur(2px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-1000{transition-duration:1s}.duration-300{transition-duration:.3s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}@keyframes enter{0%{opacity:var(--tw-enter-opacity, 1);transform:translate3d(var(--tw-enter-translate-x, 0),var(--tw-enter-translate-y, 0),0) scale3d(var(--tw-enter-scale, 1),var(--tw-enter-scale, 1),var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity, 1);transform:translate3d(var(--tw-exit-translate-x, 0),var(--tw-exit-translate-y, 0),0) scale3d(var(--tw-exit-scale, 1),var(--tw-exit-scale, 1),var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0))}}.duration-1000{animation-duration:1s}.duration-300{animation-duration:.3s}.ease-out{animation-timing-function:cubic-bezier(0,0,.2,1)}.shadow-subtle{box-shadow:0 1px 2px #0000000d}.placeholder\:italic::-moz-placeholder{font-style:italic}.placeholder\:italic::placeholder{font-style:italic}.last\:mb-0:last-child{margin-bottom:0}.focus-within\:border-slate-400:focus-within{--tw-border-opacity: 1;border-color:rgb(148 163 184 / var(--tw-border-opacity, 1))}.focus-within\:ring-1:focus-within{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-within\:ring-slate-400:focus-within{--tw-ring-opacity: 1;--tw-ring-color: rgb(148 163 184 / var(--tw-ring-opacity, 1))}.hover\:border-rose-200:hover{--tw-border-opacity: 1;border-color:rgb(254 205 211 / var(--tw-border-opacity, 1))}.hover\:bg-amber-50:hover{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.hover\:bg-amber-700:hover{--tw-bg-opacity: 1;background-color:rgb(180 83 9 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-700:hover{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.hover\:bg-emerald-700:hover{--tw-bg-opacity: 1;background-color:rgb(4 120 87 / var(--tw-bg-opacity, 1))}.hover\:bg-rose-50:hover{--tw-bg-opacity: 1;background-color:rgb(255 241 242 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-100:hover{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-200:hover{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-300:hover{--tw-bg-opacity: 1;background-color:rgb(203 213 225 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-50:hover{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-800:hover{--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.hover\:bg-white:hover{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.hover\:text-blue-700:hover{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.hover\:text-rose-600:hover{--tw-text-opacity: 1;color:rgb(225 29 72 / var(--tw-text-opacity, 1))}.hover\:text-slate-700:hover{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.hover\:text-slate-800:hover{--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.hover\:text-slate-900:hover{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-blue-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.focus\:ring-slate-400:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(148 163 184 / var(--tw-ring-opacity, 1))}.disabled\:bg-transparent:disabled{background-color:transparent}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:opacity-100{opacity:1}
|