@chfischerx/puttry 0.1.0

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.
package/.env.example ADDED
@@ -0,0 +1,41 @@
1
+ # Server
2
+ PORT=5174
3
+ HOST=0.0.0.0
4
+
5
+ # Authentication
6
+ # Set to 0 (default) to enable authentication via session password
7
+ # Set to 1 to disable authentication - all users are automatically authenticated
8
+ AUTH_DISABLED=0
9
+
10
+ # Suppress the "Authentication is disabled" warning message
11
+ # Only has effect when AUTH_DISABLED=1
12
+ # Set to 1 to hide the warning
13
+ # HIDE_AUTH_DISABLED_WARNING=0
14
+
15
+ # Session Password Authentication
16
+ # Type: xkcd (memorable words) or random (alphanumeric)
17
+ SESSION_PASSWORD_TYPE=xkcd
18
+
19
+ # Length: number of words (xkcd) or characters (random)
20
+ SESSION_PASSWORD_LENGTH=4
21
+
22
+ # 2FA/TOTP Settings
23
+ # Set to 1 to require TOTP verification on login
24
+ TOTP_ENABLED=0
25
+
26
+ # Session Password Logging
27
+ # Log the session password at server startup (for convenience)
28
+ # Set to 0 to disable, 1 (default) to enable
29
+ LOG_SESSION_PASSWORD=1
30
+
31
+ # Rate Limiting
32
+ # Global DDoS protection (all routes, 15 min window)
33
+ RATE_LIMIT_GLOBAL_MAX=500
34
+
35
+ # Session password login attempt protection (1 hour window)
36
+ RATE_LIMIT_SESSION_PASSWORD_MAX=10
37
+
38
+ # Terminal Scrollback
39
+ # Maximum number of lines to keep in each terminal's output buffer
40
+ # Default: 10000 lines
41
+ SCROLLBACK_LINES=10000
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Christian Fischer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,340 @@
1
+ # PuTTrY
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@chfischerx/puttry.svg)](https://www.npmjs.com/package/@chfischerx/puttry)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
5
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](https://nodejs.org/)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-3178c6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
7
+
8
+ A secure, browser-based terminal that keeps your server sessions alive across devices and networks. Work seamlessly across your phone, laptop, and desktop without restarting your processes.
9
+
10
+ <details>
11
+ <summary>Table of Contents</summary>
12
+
13
+ - [What is PuTTrY?](#what-is-puttry)
14
+ - [Why Web-Based Over SSH?](#why-web-based-over-ssh)
15
+ - [Getting Started](#getting-started)
16
+ - [Configuration Reference](#configuration-reference)
17
+ - [Managing Terminal Sessions](#managing-terminal-sessions)
18
+ - [Security Architecture](#security-architecture)
19
+ - [Network and Infrastructure Security](#network-and-infrastructure-security)
20
+ - [Technical Architecture](#technical-architecture)
21
+ - [Development](#development)
22
+ - [License](#license)
23
+
24
+ </details>
25
+
26
+ ## What is PuTTrY?
27
+
28
+ PuTTrY is a single-user, web-based terminal emulator that runs on your server, allowing you to access and control your terminal sessions from any browser. Unlike traditional SSH clients, PuTTrY decouples the terminal interface from your SSH credentials—your server sessions persist independently of which device you're using, and your security is managed centrally at the backend.
29
+
30
+ ### Single-User Per Instance
31
+
32
+ PuTTrY is designed to be run by a single user in their home directory. Each terminal session created via PuTTrY inherits the permissions of the user who started it—exactly the same as SSH. If multiple users on the same server want to use PuTTrY, each must run their own separate instance in their respective home directory. Multiple PuTTrY instances on the same server require different host ports. While PuTTrY can be used for ad-hoc multi-user collaboration (by sharing your session password), its core design is as a personal terminal for one user across many devices.
33
+
34
+ ### Perfect For
35
+
36
+ - **Agentic AI with long-running tasks**: Start an autonomous agent on your server from your work machine, then monitor its progress from your phone on your commute without interrupting the process
37
+ - **CLI-controlled systems**: Maintain persistent connections to command-line tools and services that expect continuous sessions
38
+ - **Cross-device workflows**: Begin work on a desktop, seamlessly continue from a laptop or mobile device without reconnecting
39
+ - **Collaborative troubleshooting**: Share your session password with a colleague to debug a problem together in real-time
40
+ - **On-the-go administration**: Interact with critical server processes from anywhere, even from devices never designed for SSH
41
+
42
+ **About the name**: PuTTrY is a homage to [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html), the pioneering SSH client created in the late 1990s that revolutionized terminal access for countless users. While PuTTrY takes a fundamentally different approach—shifting from desktop client to web-based backend—we honor the technical innovation and reliability that made PuTTY indispensable for decades. Some people still use PuTTY today. This project builds on the foundation of solutions that worked seamlessly across generations of computing.
43
+
44
+ ## Why Web-Based Over SSH?
45
+
46
+ SSH is a battle-tested tool that's been securing remote access for decades. But it's not designed for effortless access from anywhere—it requires upfront setup and key management on every device you want to use.
47
+
48
+ ### Session Continuity Across Devices
49
+
50
+ SSH ties your terminal to your client machine. Each connection is independent—if you close your laptop, your SSH session dies, even if your background process is still running on the server.
51
+
52
+ With PuTTrY, your terminal session lives on the server, independent of which device you're using:
53
+ - Start debugging a long-running process on your work desktop
54
+ - Close your laptop and seamlessly continue from your phone on the train home using the same terminal session
55
+ - Switch to your home desktop later—your session is still there, unchanged
56
+ - Return to your office desktop the next day with all your history and context intact
57
+
58
+ The process keeps running. The shell state persists. Only your browser window changes.
59
+
60
+ ### Quick, Device-Agnostic Login
61
+
62
+ SSH requires setup before your first connection: generate keys, distribute public keys, configure `~/.ssh/config`, handle different key locations on different machines. It's powerful, but not quick.
63
+
64
+ PuTTrY gets you connected with one password, anywhere. Your phone, a tablet, a borrowed laptop, a machine you've never used before—just open a browser and authenticate. No keys to distribute. No setup per device.
65
+
66
+ ### Mobile-Friendly
67
+
68
+ SSH on mobile is awkward:
69
+ - **Key distribution**: Copying SSH private keys to your phone duplicates a sensitive credential on a device with different security guarantees
70
+ - **UX friction**: Most phones aren't designed for SSH; you're fighting the platform
71
+ - **Setup burden**: Each device that needs access requires its own key configuration
72
+
73
+ PuTTrY is designed for the browser. Authenticate once, get a session token in a cookie, and continue working. Your session password lives on the server, not on your device.
74
+
75
+ ### Network Security and Infrastructure Flexibility
76
+
77
+ Exposing SSH to the internet for external access is a significant security concern. SSH servers are frequently targeted by automated attacks, and managing firewall rules and key distribution at scale creates operational risk.
78
+
79
+ PuTTrY, running as a standard web backend, can be protected using the same mature infrastructure security tooling available for any modern web application:
80
+ - **Reverse proxies and load balancers** with rate limiting and DDoS protection
81
+ - **WAF (Web Application Firewall)** rules to block malicious requests
82
+ - **IP whitelisting** and VPN tunneling for restricted access
83
+ - **Certificate management** with auto-renewal via services like Let's Encrypt
84
+ - **Cloud provider integrations** (AWS ALB, Google Cloud LB, Azure App Service, etc.) that handle HTTPS and scaling
85
+
86
+ You don't need to expose a new port to the internet or manage a separate SSH hardening strategy. PuTTrY integrates into your existing web security infrastructure.
87
+
88
+ For comprehensive guidance on HTTPS, certificate management, VPN tunneling, reverse proxies, and other deployment strategies, see [Network and Infrastructure Security](./docs/NETWORK_SECURITY.md).
89
+
90
+ ## Getting Started
91
+
92
+ ### Prerequisites
93
+
94
+ Before installing PuTTrY, ensure you have:
95
+
96
+ - **Node.js** 20 or later ([download](https://nodejs.org/))
97
+ - **npm** 10 or later (bundled with Node.js)
98
+
99
+ ### Step 1: Install
100
+
101
+ Install PuTTrY globally using npm:
102
+
103
+ ```bash
104
+ npm install -g @chfischerx/puttry
105
+ ```
106
+
107
+ ### Step 2: Configure (Recommended)
108
+
109
+ Run the interactive configuration wizard to set up PuTTrY for your environment:
110
+
111
+ ```bash
112
+ puttry configure
113
+ ```
114
+
115
+ This walks you through setting up:
116
+ - Port (default: 5174)
117
+ - Password type (random or custom)
118
+ - 2FA (TOTP or passkeys)
119
+ - Other preferences
120
+
121
+ **Note:** Configuration is optional—PuTTrY works with defaults out of the box. However, running `puttry configure` first ensures the setup matches your environment.
122
+
123
+ **Settings can be changed anytime** via the Web UI settings panel or the `puttry config set` command.
124
+
125
+ ### Step 3: Start
126
+
127
+ Start the PuTTrY server:
128
+
129
+ ```bash
130
+ puttry start
131
+ ```
132
+
133
+ PuTTrY will display:
134
+ - Your session password
135
+ - The direct URL to access PuTTrY in your browser
136
+
137
+ Open the URL in your browser to access the web interface. You're ready to create terminal sessions!
138
+
139
+ ## Configuration Reference
140
+
141
+ ### Configuration Files and Directories
142
+
143
+ On first run, PuTTrY creates a `.puttry` directory in your home folder containing:
144
+
145
+ - **`session-password.txt`**: Your session password for authentication
146
+ - **`2fa.json`**: 2FA configuration (if enabled)
147
+ - **`sessions/`**: Terminal session data
148
+
149
+ ### Port Configuration
150
+
151
+ **Each PuTTrY instance requires a unique port.** If multiple users on the same server want to run PuTTrY, each must run their own separate instance in their respective home directory with a different port number.
152
+
153
+ For example:
154
+ - User A: `puttry configure` → port 5174
155
+ - User B: `puttry configure` → port 5175
156
+ - User C: `puttry configure` → port 5176
157
+
158
+ You can set the port during `puttry configure` or later with `puttry config set PORT 5175`.
159
+
160
+ ### Environment Variables
161
+
162
+ You can customize PuTTrY's behavior by setting environment variables. A full list of supported environment variables is available in [`.env.example`](./.env.example).
163
+
164
+ > For a complete production deployment guide including systemd setup, full environment variable reference, monitoring, and backup strategies, see [docs/PRODUCTION.md](./docs/PRODUCTION.md).
165
+
166
+ ### CLI Commands
167
+
168
+ PuTTrY includes a built-in CLI tool for server management and configuration:
169
+
170
+ ```bash
171
+ puttry <command>
172
+ ```
173
+
174
+ #### Server Management
175
+
176
+ - **`puttry start`** — Start the server in the background. Displays the session password and direct link.
177
+ - **`puttry stop`** — Stop the running server gracefully.
178
+ - **`puttry restart`** — Restart the server (useful after configuration changes).
179
+ - **`puttry status`** — Show the current server status and port.
180
+
181
+ #### Password Management
182
+
183
+ - **`puttry password`** or **`puttry password show`** — Display the current session password.
184
+ - **`puttry password rotate`** — Rotate to a new session password. All active sessions are invalidated; users must log in again.
185
+
186
+ #### 2FA Management
187
+
188
+ - **`puttry totp reset`** — Clear TOTP (Time-Based One-Time Password) configuration. Users will need to re-scan the QR code on their next login to set up 2FA again.
189
+
190
+ #### Passkey Management
191
+
192
+ - **`puttry passkey list`** — List all registered passkeys with registration dates and IDs.
193
+ - **`puttry passkey reset`** — Remove all registered passkeys. Users will need to register a new passkey on their next login.
194
+
195
+ #### Configuration
196
+
197
+ - **`puttry config list`** — List all current configuration values.
198
+ - **`puttry config set KEY VALUE`** — Update a configuration value (e.g., `puttry config set PORT 5175`).
199
+ - **`puttry configure`** — Interactive configuration wizard. Walk through setup options with prompts.
200
+
201
+ #### Help
202
+
203
+ - **`puttry help`** — Display the help message with all available commands.
204
+
205
+ ## Managing Terminal Sessions
206
+
207
+ ### Creating and Deleting Sessions
208
+
209
+ PuTTrY allows you to create multiple independent terminal sessions via the Web UI. Each session is a separate terminal session running on your server. You can create, switch between, and delete sessions as needed—perfect for organizing work across different tasks.
210
+
211
+ ### Parallel Browser Connections
212
+
213
+ Multiple browsers (or tabs) can connect to the same terminal session simultaneously:
214
+
215
+ - **Shared output**: All connected browsers receive the same shell output in near-real-time
216
+ - **Synchronized view**: Watch your shell's progress from your phone while keeping your desktop browser open
217
+ - **Write lock**: Only one browser can write to a shell at any given time. This prevents chaos when multiple people are typing simultaneously.
218
+
219
+ ### Write Lock and Control
220
+
221
+ PuTTrY implements a per-shell write lock to coordinate input:
222
+
223
+ - **Current writer**: One browser has write access to the shell and can send input commands
224
+ - **Read-only viewers**: Other connected browsers have read-only access—they see all output but cannot send input
225
+ - **Taking control**: You can take the write lock from any other browser at any time. No acknowledgment or permission needed. This ensures you can always control your sessions from wherever you are
226
+
227
+ This design prevents simultaneous keyboard input from multiple sources from corrupting shell state or producing unpredictable results.
228
+
229
+ ### Collaborative Troubleshooting
230
+
231
+ You can share your session password with a trusted colleague, allowing them to connect to your PuTTrY instance from their own browser. You can then:
232
+
233
+ - Both observe the same terminal session in real-time
234
+ - Take turns writing (whoever holds the lock has control)
235
+ - Switch who's in control as you work through a problem together
236
+
237
+ > ⚠️ **Important**: The write lock coordinates input within a single terminal session only. If you and a colleague are working in different terminal sessions (different processes), there's no automatic coordination. This is intentional—PuTTrY respects standard Unix permissions. If you both edit the same file from different terminal sessions, the last write wins, just like any other collaborative editing scenario. Coordination of concurrent work on shared files must be handled outside PuTTrY (version control, file locks, etc.).
238
+
239
+ ## Security Architecture
240
+
241
+ ### How PuTTrY Secures Access
242
+
243
+ SSH's security model is sound, but managing keys across multiple machines creates friction and sprawl. Every device that needs access requires its own key configuration, and revoking access means key rotation everywhere.
244
+
245
+ PuTTrY uses a simpler model: **one password per PuTTrY instance, managed on the backend**.
246
+
247
+ #### Session Password
248
+
249
+ Your PuTTrY instance is protected by a **session password**—a persistent credential that grants access to the PuTTrY backend itself. This password:
250
+
251
+ - **Protects browser login**: When you open PuTTrY in a new browser, you enter your session password to authenticate
252
+ - **Persists until rotated**: It remains the same until you explicitly rotate it
253
+ - **Stays on the backend**: The password is stored on your server (`~/.puttry/session-password.txt`), not distributed to client machines
254
+ - **Can be rotated via Web UI or CLI**: Change your password anytime using the web interface or `puttry rotate-password` command
255
+
256
+ Once authenticated, your browser receives a session token (stored in a cookie). You stay logged in across multiple browser tabs, devices, and sessions—until you explicitly log out or your token expires.
257
+
258
+ #### Multi-Factor Authentication (2FA)
259
+
260
+ For additional security, you can require **2FA** on top of your session password:
261
+
262
+ **TOTP (Time-Based One-Time Password)**
263
+ - After entering your session password, you must provide a code from your authenticator app (Google Authenticator, Authy, etc.)
264
+ - Each code is valid for 30 seconds
265
+ - Works on any device with an authenticator app installed
266
+
267
+ **Passkey**
268
+ - Cryptographic authentication using your device's built-in security: Touch ID, Face ID, Windows Hello, or security keys
269
+ - Phishing-resistant—the server cryptographically verifies your identity, not a password
270
+ - More secure than passwords, easier than key management
271
+
272
+ ### Why This Works Better Than Key Distribution
273
+
274
+ - **One credential per server**: Your password lives on the backend; there's nothing to distribute
275
+ - **No key sprawl**: You don't need copies of your credentials on every device
276
+ - **Easy revocation**: Rotate your password or disable 2FA instantly—no client-side changes needed
277
+ - **Mobile-friendly**: Authenticate from any browser without device-specific setup
278
+ - **Instant policy updates**: Enable 2FA, change your password, or revoke access—it applies everywhere immediately
279
+
280
+ Your security is managed centrally on the server, not scattered across machines.
281
+
282
+ ## Network and Infrastructure Security
283
+
284
+ PuTTrY's built-in authentication (session password, 2FA, and passkeys) protects your instance at the application level. However, your server must accept incoming network connections to be reachable from browsers. Depending on your deployment scenario—personal use on a private network, shared infrastructure, or internet-facing production—you'll need different infrastructure-level security measures.
285
+
286
+ **Key considerations:**
287
+ - **HTTPS vs HTTP**: Always use HTTPS in production unless your server is completely isolated
288
+ - **Certificate management**: Self-signed certs for personal use, official CA-signed certs for shared access
289
+ - **Network access patterns**: Direct exposure, reverse proxy, VPN tunneling, or bastion host architecture
290
+ - **Cloud provider options**: Leverage managed services (AWS ALB, Google Cloud LB, Azure App Service, etc.) to simplify HTTPS
291
+ - **Defense in depth**: Combine application authentication with network-level protections (rate limiting, WAF, IP whitelisting)
292
+
293
+ For comprehensive guidance on HTTPS setup, certificate management, VPN tunneling, reverse proxy configuration, and bastion host architecture, see [Network and Infrastructure Security](./docs/NETWORK_SECURITY.md).
294
+
295
+ ## Technical Architecture
296
+
297
+ PuTTrY is built on a foundation of battle-tested technologies:
298
+
299
+ - **Shell Management**: [node-pty](https://github.com/microsoft/node-pty) handles real PTY sessions, so your shells behave exactly like local terminals
300
+ - **Browser Communication**: Dual WebSocket channels—a `sync` channel for coordination across browser tabs, and per-session channels for real-time terminal I/O
301
+ - **Bandwidth Efficiency**: Only the active (foreground) session streams data to your browser; background sessions are paused to minimize traffic
302
+ - **Session Continuity**: Output buffer (default 10,000 lines) preserves your recent history, allowing seamless reconnection from any device
303
+ - **Concurrency Control**: Write lock mechanism ensures only one browser controls input at a time, while others view in read-only mode
304
+ - **Terminal Emulation**: [xterm.js](https://xtermjs.org/) provides full VT102 terminal emulation in the browser with excellent performance
305
+
306
+ For detailed technical documentation on shell process management, WebSocket communication patterns, buffer management, and write locking, see [Technical Architecture](./docs/TECHNICAL_ARCHITECTURE.md).
307
+
308
+ ## Development
309
+
310
+ PuTTrY is built with modern full-stack tooling: React with TypeScript on the frontend, Express on the backend, and a custom Vite plugin that integrates both seamlessly in development.
311
+
312
+ **Quick start:**
313
+ ```bash
314
+ npm install
315
+ npm run dev
316
+ ```
317
+
318
+ The dev server runs on `http://localhost:5175` with hot module reloading (HMR) for both frontend and backend. React components update instantly; server code changes may require a refresh. The Vite plugin mounts Express as middleware and handles WebSocket upgrades for real-time terminal I/O.
319
+
320
+ **Key development workflows:**
321
+ - **`npm run dev`** – Start with HMR enabled
322
+ - **`npm run build:all`** – Build production bundles
323
+ - **`npm run lint`** – Check code style
324
+ - **`npm start`** – Run production build locally
325
+ - **`AUTH_DISABLED=1 npm run dev`** – Skip auth for testing
326
+ - **Debugging**: Browser DevTools for frontend, server logs for backend, Network tab for WebSocket activity
327
+
328
+ **Project structure:**
329
+ - `src/client/` – React frontend (components, hooks, app entry)
330
+ - `src/server/` – Express backend (routes, PTY manager, auth, WebSockets)
331
+ - `src/lib/` – Shared utilities
332
+ - `vite.config.ts`, `tsconfig.json` – Build and type configuration
333
+
334
+ The custom Vite plugin (`vite-plugin.ts`) handles the Express integration and WebSocket upgrades for `/sync` (session coordination) and `/terminal/:sessionId` (PTY I/O).
335
+
336
+ For comprehensive development documentation including setup, project structure, build processes, debugging techniques, and performance considerations, see [Development](./docs/DEVELOPMENT.md).
337
+
338
+ ## License
339
+
340
+ MIT — see [LICENSE](./LICENSE) for details.
@@ -0,0 +1,13 @@
1
+ <svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
2
+ <!-- Transparent background -->
3
+ <rect width="32" height="32" fill="none"/>
4
+
5
+ <!-- Terminal box -->
6
+ <rect x="4" y="4" width="24" height="24" rx="1.5" fill="none" stroke="#ffffff" stroke-width="1.5"/>
7
+
8
+ <!-- Greater than symbol with 90 degree angles -->
9
+ <polyline points="10,12 16,16 10,20" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="miter"/>
10
+
11
+ <!-- Underscore -->
12
+ <line x1="18" y1="20" x2="24" y2="20" stroke="#ffffff" stroke-width="2" stroke-linecap="round"/>
13
+ </svg>
@@ -0,0 +1 @@
1
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-500:oklch(63.7% .237 25.331);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-600:oklch(66.6% .179 58.318);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-600:oklch(54.6% .245 262.881);--color-slate-900:oklch(20.8% .042 265.755);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-600:oklch(44.6% .03 256.802);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}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;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{border-color:var(--border);outline-color:var(--ring)}@supports (color:color-mix(in lab,red,red)){*{outline-color:color-mix(in oklab,var(--ring) 50%,transparent)}}body{background-color:var(--background);color:var(--foreground)}}@layer components;@layer utilities{.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.inset-y-0{inset-block:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.top-0\.5{top:calc(var(--spacing) * .5)}.top-1\/2{top:50%}.top-full{top:100%}.right-0{right:calc(var(--spacing) * 0)}.right-0\.5{right:calc(var(--spacing) * .5)}.right-3{right:calc(var(--spacing) * 3)}.bottom-0\.5{bottom:calc(var(--spacing) * .5)}.left-0{left:calc(var(--spacing) * 0)}.left-0\.5{left:calc(var(--spacing) * .5)}.z-40{z-index:40}.z-50{z-index:50}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mx-1{margin-inline:calc(var(--spacing) * 1)}.mx-4{margin-inline:calc(var(--spacing) * 4)}.my-1{margin-block:calc(var(--spacing) * 1)}.-mt-24{margin-top:calc(var(--spacing) * -24)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.hidden{display:none}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-12{height:calc(var(--spacing) * 12)}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[85vh\]{max-height:85vh}.w-1{width:calc(var(--spacing) * 1)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2{width:calc(var(--spacing) * 2)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-6{width:calc(var(--spacing) * 6)}.w-8{width:calc(var(--spacing) * 8)}.w-9{width:calc(var(--spacing) * 9)}.w-10{width:calc(var(--spacing) * 10)}.w-11{width:calc(var(--spacing) * 11)}.w-20{width:calc(var(--spacing) * 20)}.w-24{width:calc(var(--spacing) * 24)}.w-32{width:calc(var(--spacing) * 32)}.w-64{width:calc(var(--spacing) * 64)}.w-80{width:calc(var(--spacing) * 80)}.w-auto{width:auto}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-sm{max-width:var(--container-sm)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[2\.75rem\]{min-width:2.75rem}.flex-1{flex:1}.flex-shrink{flex-shrink:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.translate-x-4{--tw-translate-x:calc(var(--spacing) * 4);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-col-resize{cursor:col-resize}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-col{flex-direction:column}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-border>:not(:last-child)){border-color:var(--border)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-amber-600\/50{border-color:#dd740080}@supports (color:color-mix(in lab,red,red)){.border-amber-600\/50{border-color:color-mix(in oklab,var(--color-amber-600) 50%,transparent)}}.border-border,.border-border\/50{border-color:var(--border)}@supports (color:color-mix(in lab,red,red)){.border-border\/50{border-color:color-mix(in oklab,var(--border) 50%,transparent)}}.border-destructive\/30{border-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.border-destructive\/30{border-color:color-mix(in oklab,var(--destructive) 30%,transparent)}}.border-foreground\/30{border-color:var(--foreground)}@supports (color:color-mix(in lab,red,red)){.border-foreground\/30{border-color:color-mix(in oklab,var(--foreground) 30%,transparent)}}.border-green-500\/30{border-color:#00c7584d}@supports (color:color-mix(in lab,red,red)){.border-green-500\/30{border-color:color-mix(in oklab,var(--color-green-500) 30%,transparent)}}.border-input{border-color:var(--input)}.border-t-primary{border-top-color:var(--primary)}.bg-amber-400\/40{background-color:#fcbb0066}@supports (color:color-mix(in lab,red,red)){.bg-amber-400\/40{background-color:color-mix(in oklab,var(--color-amber-400) 40%,transparent)}}.bg-background{background-color:var(--background)}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab,red,red)){.bg-black\/50{background-color:color-mix(in oklab,var(--color-black) 50%,transparent)}}.bg-border{background-color:var(--border)}.bg-card{background-color:var(--card)}.bg-destructive,.bg-destructive\/10{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.bg-destructive\/10{background-color:color-mix(in oklab,var(--destructive) 10%,transparent)}}.bg-gray-300{background-color:var(--color-gray-300)}.bg-green-500{background-color:var(--color-green-500)}.bg-green-500\/5{background-color:#00c7580d}@supports (color:color-mix(in lab,red,red)){.bg-green-500\/5{background-color:color-mix(in oklab,var(--color-green-500) 5%,transparent)}}.bg-muted,.bg-muted\/30{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.bg-muted\/30{background-color:color-mix(in oklab,var(--muted) 30%,transparent)}}.bg-muted\/50{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.bg-muted\/50{background-color:color-mix(in oklab,var(--muted) 50%,transparent)}}.bg-primary{background-color:var(--primary)}.bg-secondary{background-color:var(--secondary)}.bg-sidebar{background-color:var(--sidebar)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.fill-primary{fill:var(--primary)}.stroke-primary{stroke:var(--primary)}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0{padding-block:calc(var(--spacing) * 0)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pr-10{padding-right:calc(var(--spacing) * 10)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.text-black{color:var(--color-black)}.text-blue-600{color:var(--color-blue-600)}.text-destructive{color:var(--destructive)}.text-foreground,.text-foreground\/80{color:var(--foreground)}@supports (color:color-mix(in lab,red,red)){.text-foreground\/80{color:color-mix(in oklab,var(--foreground) 80%,transparent)}}.text-green-600{color:var(--color-green-600)}.text-muted-foreground,.text-muted-foreground\/70{color:var(--muted-foreground)}@supports (color:color-mix(in lab,red,red)){.text-muted-foreground\/70{color:color-mix(in oklab,var(--muted-foreground) 70%,transparent)}}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-red-500{color:var(--color-red-500)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.underline-offset-4{text-underline-offset:4px}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);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,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.placeholder\:text-muted-foreground::placeholder{color:var(--muted-foreground)}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media(hover:hover){.hover\:bg-accent:hover{background-color:var(--accent)}.hover\:bg-destructive\/10:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-destructive\/10:hover{background-color:color-mix(in oklab,var(--destructive) 10%,transparent)}}.hover\:bg-destructive\/20:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-destructive\/20:hover{background-color:color-mix(in oklab,var(--destructive) 20%,transparent)}}.hover\:bg-destructive\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab,var(--destructive) 90%,transparent)}}.hover\:bg-muted:hover,.hover\:bg-muted\/50:hover{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab,var(--muted) 50%,transparent)}}.hover\:bg-primary\/50:hover{background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-primary\/50:hover{background-color:color-mix(in oklab,var(--primary) 50%,transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab,var(--primary) 90%,transparent)}}.hover\:bg-red-500\/20:hover{background-color:#fb2c3633}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-500\/20:hover{background-color:color-mix(in oklab,var(--color-red-500) 20%,transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab,var(--secondary) 80%,transparent)}}.hover\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\:text-destructive:hover{color:var(--destructive)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:border-ring:focus{border-color:var(--ring)}.focus\:ring-\[2px\]:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-\[3px\]:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-ring\/50:focus{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab,red,red)){.focus\:ring-ring\/50:focus{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.focus-visible\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\:ring-\[3px\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-destructive\/20:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.focus-visible\:ring-destructive\/20:focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab,red,red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.has-\[\>svg\]\:px-1\.5:has(>svg){padding-inline:calc(var(--spacing) * 1.5)}.has-\[\>svg\]\:px-2\.5:has(>svg){padding-inline:calc(var(--spacing) * 2.5)}.has-\[\>svg\]\:px-3:has(>svg){padding-inline:calc(var(--spacing) * 3)}.has-\[\>svg\]\:px-4:has(>svg){padding-inline:calc(var(--spacing) * 4)}.aria-invalid\:border-destructive[aria-invalid=true]{border-color:var(--destructive)}.aria-invalid\:ring-destructive\/20[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.aria-invalid\:ring-destructive\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}@media(prefers-color-scheme:dark){.dark\:border-input{border-color:var(--input)}.dark\:bg-destructive\/60{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.dark\:bg-destructive\/60{background-color:color-mix(in oklab,var(--destructive) 60%,transparent)}}.dark\:bg-gray-600{background-color:var(--color-gray-600)}.dark\:bg-input\/30{background-color:var(--input)}@supports (color:color-mix(in lab,red,red)){.dark\:bg-input\/30{background-color:color-mix(in oklab,var(--input) 30%,transparent)}}.dark\:bg-slate-900{background-color:var(--color-slate-900)}.dark\:text-black{color:var(--color-black)}.dark\:text-blue-400{color:var(--color-blue-400)}.dark\:text-green-400{color:var(--color-green-400)}@media(hover:hover){.dark\:hover\:bg-accent\/50:hover{background-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.dark\:hover\:bg-accent\/50:hover{background-color:color-mix(in oklab,var(--accent) 50%,transparent)}}.dark\:hover\:bg-input\/50:hover{background-color:var(--input)}@supports (color:color-mix(in lab,red,red)){.dark\:hover\:bg-input\/50:hover{background-color:color-mix(in oklab,var(--input) 50%,transparent)}}}.dark\:focus-visible\:ring-destructive\/40:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.dark\:focus-visible\:ring-destructive\/40:focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.dark\:aria-invalid\:ring-destructive\/40[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.dark\:aria-invalid\:ring-destructive\/40[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-3 svg:not([class*=size-]){width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-4 svg:not([class*=size-]){width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.command-menu-scrollable{scrollbar-width:auto;scrollbar-color:#444 transparent}.command-menu-scrollable::-webkit-scrollbar{width:10px}.command-menu-scrollable::-webkit-scrollbar-track{background:0 0}.command-menu-scrollable::-webkit-scrollbar-thumb{background:#444;border-radius:5px}.command-menu-scrollable::-webkit-scrollbar-thumb:hover{background:#555}.data-received{animation:.5s linear infinite flicker!important}}:root{--radius:.625rem;--background:oklch(93% 0 0);--foreground:oklch(14.5% 0 0);--card:oklch(96% 0 0);--card-foreground:oklch(14.5% 0 0);--popover:oklch(96% 0 0);--popover-foreground:oklch(14.5% 0 0);--primary:oklch(20.5% 0 0);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(97% 0 0);--secondary-foreground:oklch(20.5% 0 0);--muted:oklch(97% 0 0);--muted-foreground:oklch(55.6% 0 0);--accent:oklch(97% 0 0);--accent-foreground:oklch(20.5% 0 0);--destructive:oklch(57.7% .245 27.325);--border:oklch(85% 0 0);--input:oklch(92.2% 0 0);--ring:oklch(70.8% 0 0);--chart-1:oklch(64.6% .222 41.116);--chart-2:oklch(60% .118 184.704);--chart-3:oklch(39.8% .07 227.392);--chart-4:oklch(82.8% .189 84.429);--chart-5:oklch(76.9% .188 70.08);--sidebar:oklch(90% 0 0);--sidebar-foreground:oklch(14.5% 0 0);--sidebar-primary:oklch(20.5% 0 0);--sidebar-primary-foreground:oklch(98.5% 0 0);--sidebar-accent:oklch(97% 0 0);--sidebar-accent-foreground:oklch(20.5% 0 0);--sidebar-border:oklch(92.2% 0 0);--sidebar-ring:oklch(70.8% 0 0)}.dark{--background:oklch(14.5% 0 0);--foreground:oklch(98.5% 0 0);--card:oklch(20.5% 0 0);--card-foreground:oklch(98.5% 0 0);--popover:oklch(20.5% 0 0);--popover-foreground:oklch(98.5% 0 0);--primary:oklch(92.2% 0 0);--primary-foreground:oklch(20.5% 0 0);--secondary:oklch(26.9% 0 0);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(26.9% 0 0);--muted-foreground:oklch(70.8% 0 0);--accent:oklch(26.9% 0 0);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(70.4% .191 22.216);--border:oklch(100% 0 0/.1);--input:oklch(100% 0 0/.15);--ring:oklch(55.6% 0 0);--chart-1:oklch(48.8% .243 264.376);--chart-2:oklch(69.6% .17 162.48);--chart-3:oklch(76.9% .188 70.08);--chart-4:oklch(62.7% .265 303.9);--chart-5:oklch(64.5% .246 16.439);--sidebar:oklch(20.5% 0 0);--sidebar-foreground:oklch(98.5% 0 0);--sidebar-primary:oklch(48.8% .243 264.376);--sidebar-primary-foreground:oklch(98.5% 0 0);--sidebar-accent:oklch(26.9% 0 0);--sidebar-accent-foreground:oklch(98.5% 0 0);--sidebar-border:oklch(100% 0 0/.1);--sidebar-ring:oklch(55.6% 0 0)}@keyframes flicker{0%,to{opacity:1}50%{opacity:.3}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;inset:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility,.xterm .xterm-message{position:absolute;inset:0;z-index:10;color:transparent;pointer-events:none}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}
@@ -0,0 +1,2 @@
1
+ function u(e){const t=new Uint8Array(e);let n="";for(const r of t)n+=String.fromCharCode(r);return btoa(n).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function g(e){const t=e.replace(/-/g,"+").replace(/_/g,"/"),n=(4-t.length%4)%4,a=t.padEnd(t.length+n,"="),r=atob(a),l=new ArrayBuffer(r.length),d=new Uint8Array(l);for(let o=0;o<r.length;o++)d[o]=r.charCodeAt(o);return l}function R(){return S.stubThis(globalThis?.PublicKeyCredential!==void 0&&typeof globalThis.PublicKeyCredential=="function")}const S={stubThis:e=>e};function m(e){const{id:t}=e;return{...e,id:g(t),transports:e.transports}}function y(e){return e==="localhost"||/^((xn--[a-z0-9-]+|[a-z0-9]+(-[a-z0-9]+)*)\.)+([a-z]{2,}|xn--[a-z0-9-]+)$/i.test(e)}class i extends Error{constructor({message:t,code:n,cause:a,name:r}){super(t,{cause:a}),Object.defineProperty(this,"code",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.name=r??a.name,this.code=n}}function I({error:e,options:t}){const{publicKey:n}=t;if(!n)throw Error("options was missing required publicKey property");if(e.name==="AbortError"){if(t.signal instanceof AbortSignal)return new i({message:"Registration ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else if(e.name==="ConstraintError"){if(n.authenticatorSelection?.requireResidentKey===!0)return new i({message:"Discoverable credentials were required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT",cause:e});if(t.mediation==="conditional"&&n.authenticatorSelection?.userVerification==="required")return new i({message:"User verification was required during automatic registration but it could not be performed",code:"ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE",cause:e});if(n.authenticatorSelection?.userVerification==="required")return new i({message:"User verification was required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT",cause:e})}else{if(e.name==="InvalidStateError")return new i({message:"The authenticator was previously registered",code:"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED",cause:e});if(e.name==="NotAllowedError")return new i({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if(e.name==="NotSupportedError")return n.pubKeyCredParams.filter(r=>r.type==="public-key").length===0?new i({message:'No entry in pubKeyCredParams was of type "public-key"',code:"ERROR_MALFORMED_PUBKEYCREDPARAMS",cause:e}):new i({message:"No available authenticator supported any of the specified pubKeyCredParams algorithms",code:"ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG",cause:e});if(e.name==="SecurityError"){const a=globalThis.location.hostname;if(y(a)){if(n.rp.id!==a)return new i({message:`The RP ID "${n.rp.id}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else return new i({message:`${globalThis.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e})}else if(e.name==="TypeError"){if(n.user.id.byteLength<1||n.user.id.byteLength>64)return new i({message:"User ID was not between 1 and 64 characters",code:"ERROR_INVALID_USER_ID_LENGTH",cause:e})}else if(e.name==="UnknownError")return new i({message:"The authenticator was unable to process the specified options, or could not create a new credential",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:e})}return e}class T{constructor(){Object.defineProperty(this,"controller",{enumerable:!0,configurable:!0,writable:!0,value:void 0})}createNewAbortSignal(){if(this.controller){const n=new Error("Cancelling existing WebAuthn API call for new one");n.name="AbortError",this.controller.abort(n)}const t=new AbortController;return this.controller=t,t.signal}cancelCeremony(){if(this.controller){const t=new Error("Manually cancelling existing WebAuthn API call");t.name="AbortError",this.controller.abort(t),this.controller=void 0}}}const O=new T,P=["cross-platform","platform"];function _(e){if(e&&!(P.indexOf(e)<0))return e}async function D(e){!e.optionsJSON&&e.challenge&&(console.warn("startRegistration() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information."),e={optionsJSON:e});const{optionsJSON:t,useAutoRegister:n=!1}=e;if(!R())throw new Error("WebAuthn is not supported in this browser");const a={...t,challenge:g(t.challenge),user:{...t.user,id:g(t.user.id)},excludeCredentials:t.excludeCredentials?.map(m)},r={};n&&(r.mediation="conditional"),r.publicKey=a,r.signal=O.createNewAbortSignal();let l;try{l=await navigator.credentials.create(r)}catch(c){throw I({error:c,options:r})}if(!l)throw new Error("Registration was not completed");const{id:d,rawId:o,response:s,type:w}=l;let h;typeof s.getTransports=="function"&&(h=s.getTransports());let p;if(typeof s.getPublicKeyAlgorithm=="function")try{p=s.getPublicKeyAlgorithm()}catch(c){A("getPublicKeyAlgorithm()",c)}let f;if(typeof s.getPublicKey=="function")try{const c=s.getPublicKey();c!==null&&(f=u(c))}catch(c){A("getPublicKey()",c)}let b;if(typeof s.getAuthenticatorData=="function")try{b=u(s.getAuthenticatorData())}catch(c){A("getAuthenticatorData()",c)}return{id:d,rawId:u(o),response:{attestationObject:u(s.attestationObject),clientDataJSON:u(s.clientDataJSON),transports:h,publicKeyAlgorithm:p,publicKey:f,authenticatorData:b},type:w,clientExtensionResults:l.getClientExtensionResults(),authenticatorAttachment:_(l.authenticatorAttachment)}}function A(e,t){console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${e}. You should report this error to them.
2
+ `,t)}function C(){if(!R())return E.stubThis(new Promise(t=>t(!1)));const e=globalThis.PublicKeyCredential;return e?.isConditionalMediationAvailable===void 0?E.stubThis(new Promise(t=>t(!1))):E.stubThis(e.isConditionalMediationAvailable())}const E={stubThis:e=>e};function N({error:e,options:t}){const{publicKey:n}=t;if(!n)throw Error("options was missing required publicKey property");if(e.name==="AbortError"){if(t.signal instanceof AbortSignal)return new i({message:"Authentication ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else{if(e.name==="NotAllowedError")return new i({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if(e.name==="SecurityError"){const a=globalThis.location.hostname;if(y(a)){if(n.rpId!==a)return new i({message:`The RP ID "${n.rpId}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else return new i({message:`${globalThis.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e})}else if(e.name==="UnknownError")return new i({message:"The authenticator was unable to process the specified options, or could not create a new assertion signature",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:e})}return e}async function v(e){!e.optionsJSON&&e.challenge&&(console.warn("startAuthentication() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information."),e={optionsJSON:e});const{optionsJSON:t,useBrowserAutofill:n=!1,verifyBrowserAutofillInput:a=!0}=e;if(!R())throw new Error("WebAuthn is not supported in this browser");let r;t.allowCredentials?.length!==0&&(r=t.allowCredentials?.map(m));const l={...t,challenge:g(t.challenge),allowCredentials:r},d={};if(n){if(!await C())throw Error("Browser does not support WebAuthn autofill");if(document.querySelectorAll("input[autocomplete$='webauthn']").length<1&&a)throw Error('No <input> with "webauthn" as the only or last value in its `autocomplete` attribute was detected');d.mediation="conditional",l.allowCredentials=[]}d.publicKey=l,d.signal=O.createNewAbortSignal();let o;try{o=await navigator.credentials.get(d)}catch(b){throw N({error:b,options:d})}if(!o)throw new Error("Authentication was not completed");const{id:s,rawId:w,response:h,type:p}=o;let f;return h.userHandle&&(f=u(h.userHandle)),{id:s,rawId:u(w),response:{authenticatorData:u(h.authenticatorData),clientDataJSON:u(h.clientDataJSON),signature:u(h.signature),userHandle:f},type:p,clientExtensionResults:o.getClientExtensionResults(),authenticatorAttachment:_(o.authenticatorAttachment)}}function K(){return R()?PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable():new Promise(e=>e(!1))}export{O as WebAuthnAbortService,i as WebAuthnError,E as _browserSupportsWebAuthnAutofillInternals,S as _browserSupportsWebAuthnInternals,g as base64URLStringToBuffer,R as browserSupportsWebAuthn,C as browserSupportsWebAuthnAutofill,u as bufferToBase64URLString,K as platformAuthenticatorIsAvailable,v as startAuthentication,D as startRegistration};