@buildbase/sdk 0.0.47 → 0.0.49
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/AGENTS.md +119 -0
- package/CHANGELOG.md +42 -0
- package/README.md +198 -0
- package/dist/css/styles.css +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +403 -4
- package/dist/index.mjs +1 -1
- package/dist/react/index.cjs +36 -0
- package/dist/react/index.d.ts +123 -35
- package/dist/react/index.mjs +5 -5
- package/package.json +11 -9
- package/dist/index.js +0 -1
- package/dist/react/index.js +0 -36
- /package/dist/data/{index.js → index.cjs} +0 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# AGENTS.md — `@buildbase/sdk`
|
|
2
|
+
|
|
3
|
+
Machine-friendly reference for AI coding agents working **with** this SDK (in a consumer app) or **on** this repo. Dense by design. For prose, examples, and props tables see [README.md](./README.md); for internals see [docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md) and [docs/ERROR_CODES.md](./docs/ERROR_CODES.md).
|
|
4
|
+
|
|
5
|
+
BuildBase is a multi-tenant SaaS platform SDK: auth, workspaces, subscriptions/billing (Stripe), quotas/usage, credits, feature flags, RBAC, notifications, i18n, and server-side agent (OAuth2 / discovery) tooling.
|
|
6
|
+
|
|
7
|
+
## The one rule: two entry points, pick by runtime
|
|
8
|
+
|
|
9
|
+
| Import | Runtime | Contains |
|
|
10
|
+
| ----------------------- | ---------------- | ----------------------------------------------------------------------- |
|
|
11
|
+
| `@buildbase/sdk` | **Server** / any | Zero React. `BuildBase()` factory, API classes, webhooks, agent tooling, pure utils, enums, types. |
|
|
12
|
+
| `@buildbase/sdk/react` | **Client** | Everything in core **re-exported** + React providers, hooks, gate components. |
|
|
13
|
+
| `@buildbase/sdk/data` | any | Static datasets: `countries`, `currencies`, `languages`, `timezones`, `betaFormSchema`. |
|
|
14
|
+
| `@buildbase/sdk/css` | build | `import '@buildbase/sdk/css'` — required once for component styling. |
|
|
15
|
+
|
|
16
|
+
- **In a React component / client hook → import from `@buildbase/sdk/react`.** It contains the whole core surface too, so you rarely need both.
|
|
17
|
+
- **In an API route, server action, webhook, cron, or Node/edge → import from `@buildbase/sdk`.** Never import `/react` on the server.
|
|
18
|
+
- Default export of both `@buildbase/sdk` and `@buildbase/sdk/react` is the `BuildBase` server factory.
|
|
19
|
+
- ESM + CJS dual-published; peer dep React 18 or 19; Node ≥ 18.
|
|
20
|
+
|
|
21
|
+
## Client setup (React)
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import '@buildbase/sdk/css';
|
|
25
|
+
import { SaaSOSProvider } from '@buildbase/sdk/react';
|
|
26
|
+
|
|
27
|
+
<SaaSOSProvider serverUrl={process.env.NEXT_PUBLIC_BUILDBASE_URL!} orgId={process.env.NEXT_PUBLIC_BUILDBASE_ORG_ID!} locale="en">
|
|
28
|
+
{children}
|
|
29
|
+
</SaaSOSProvider>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Everything below `SaaSOSProvider` can use the hooks and gate components. **Prefer SDK hooks over reaching into internal context/Redux.**
|
|
33
|
+
|
|
34
|
+
## Server setup
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import BuildBase from '@buildbase/sdk';
|
|
38
|
+
export const { auth, workspace, subscription, usage, credits, plans, invoices,
|
|
39
|
+
users, features, settings, notification, permissions, withSession, client } = BuildBase({
|
|
40
|
+
serverUrl: process.env.BUILDBASE_URL!,
|
|
41
|
+
orgId: process.env.BUILDBASE_ORG_ID!,
|
|
42
|
+
getSessionId: async () => (await cookies()).get('bb-session-id')?.value ?? null, // Next.js
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Express / no cookie context: omit `getSessionId`, call `withSession(sessionId)` per request.
|
|
47
|
+
Config also accepts: `timeout`, `maxRetries`, `debug`, `headers`, `onError(err, ctx)`, `fetch`.
|
|
48
|
+
|
|
49
|
+
## Export map (what lives where)
|
|
50
|
+
|
|
51
|
+
### `@buildbase/sdk` (core / server) — non-React
|
|
52
|
+
|
|
53
|
+
- **Factory:** `BuildBase` (also default export) → `{ auth, workspace, subscription, usage, credits, plans, invoices, users, features, settings, notification, permissions, withSession, client }`.
|
|
54
|
+
- **API classes:** `BaseApi` (extend for custom APIs), `AuthApi`, `UserApi`, `WorkspaceApi`, `SettingsApi`, `PushApi`.
|
|
55
|
+
- **Webhook verification (Node only):** `verifyWebhookSignature`, `parseWebhookEvent`. Verify against the **raw** request body (`await req.text()`), not the parsed JSON.
|
|
56
|
+
- **Agent readiness (framework-agnostic, returns plain `DiscoveryDocument`):** `resolveWellKnown` (dispatch all `.well-known/*`), `fetchAgentReadiness` (fail-soft, cached), `clearAgentReadinessCache`, `buildAgentCard`, `buildProtectedResourceMetadata`, `buildAgentSkillsIndex`, `buildSkillMd`, `buildSecurityTxt`, `buildLlmsTxt`, `sha256Digest`. Types: `AgentReadyConfig`, `AgentReadinessBundle`, `AgentSkill`, `DiscoveryDocument`.
|
|
57
|
+
- **OAuth2 app-bridge:** `handleAppTokenRequest`, `handleAppRevokeRequest` (one-call handlers), `bearerChallenge` (RFC 9728/6750 401), `verifyAppTokenRequest`, `verifyAppRevokeRequest`, `verifyClientJwt`, `extractBearerToken`, `appTokenSuccess`, `appTokenFailure`, `AppBridgeError`. Types: `AppTokenRequestClaims`, `AppRevokeRequestClaims`, `AppTokenResult`, `AppTokenResponseBody`, `HandlerResult`.
|
|
58
|
+
- **Currency & pricing utils (pure):** `formatCents`, `formatOverageRate`, `formatOverageRateWithLabel`, `formatQuotaIncludedOverage`, `formatQuotaWithPrice`, `getCurrencySymbol`, `getCurrencyFlag`, `getQuotaUnitLabelFromName`, `getQuotaDisplayValue`, `CURRENCY_DISPLAY`, `CURRENCY_FLAG`, `PLAN_CURRENCY_CODES`, `PLAN_CURRENCY_OPTIONS`.
|
|
59
|
+
- **Pricing variants (multi-currency):** `getPricingVariant`, `getBasePriceCents`, `getStripePriceIdForInterval`, `getQuotaOverageCents`, `getQuotaDisplayWithVariant`, `getAvailableCurrenciesFromPlans`, `getDisplayCurrency`, `getBillingIntervalAndCurrencyFromPriceId`.
|
|
60
|
+
- **Seat pricing:** `calculateBillableSeats`, `calculateSeatOverageCents`, `calculateTotalSubscriptionCents`, `getPerSeatPriceCents`, `getSeatPricing`.
|
|
61
|
+
- **RBAC (pure):** `hasPermission`, `resolvePermissions`, `resolveMaxUsers`, `validateInvite`, `DEFAULT_ROLE_PERMISSIONS`, `Permission` (enum).
|
|
62
|
+
- **URL / auth-intent / redirects:** `BB_PARAM`, `BBAction`, `BBScreen`, `BBStatus`, `createBBUrl`, `readBBParams`, `cleanBBParams`, `createCheckoutRedirectUrls`, `createCreditPurchaseRedirectUrls`, `safeRedirect`, `validateRedirectUrl`, `saveAuthIntent`, `consumeAuthIntent`, `clearAuthIntent`.
|
|
63
|
+
- **Context invalidation (call after server mutations to refetch client contexts):** `invalidateSubscription`, `invalidateQuotaUsage`, `invalidateCreditBalance`.
|
|
64
|
+
- **Events:** `EventEmitter`, `eventEmitter` (singleton), `SDKEvent` (enum).
|
|
65
|
+
- **Push:** `PushApi`, `PUSH_SERVICE_WORKER_SCRIPT`.
|
|
66
|
+
- **Enums:** `ApiVersion`, `AuthStatus`, `BillingIntervals`, `CreditBucketSource`, `CreditBucketStatus`, `CreditTransactionType`, `DunningState`, `InvoiceStatuses`, `SubscriptionItemType`, `SubscriptionStatus`.
|
|
67
|
+
|
|
68
|
+
### `@buildbase/sdk/react` — client-only additions (core is re-exported here too)
|
|
69
|
+
|
|
70
|
+
- **Providers:** `SaaSOSProvider` (root), `SubscriptionContextProvider`, `QuotaUsageContextProvider`, `CreditBalanceContextProvider`, `PushNotificationProvider`.
|
|
71
|
+
- **State hooks:** `useSaaSAuth`, `useSaaSWorkspaces`, `useSaaSOs`, `useSaaSSettings`, `useUserAttributes`, `useUserFeatures`, `useTranslation`, `usePermissions`, `useSeatStatus`, `useTrialStatus`, `useFullScreenLoader`.
|
|
72
|
+
- **Subscription/billing hooks:** `usePublicPlans`, `useSubscription`, `useSubscriptionContext`, `useSubscriptionManagement`, `usePlanGroup`, `usePlanGroupVersions`, `usePublicPlanGroupVersion`, `useCreateCheckoutSession`, `useUpdateSubscription`, `useCancelSubscription`, `useResumeSubscription`, `useBillingPortal`, `useInvoices`, `useInvoice`.
|
|
73
|
+
- **Quota hooks:** `useQuotaUsageContext`, `useRecordUsage`, `useQuotaUsageStatus`, `useAllQuotaUsage`, `useUsageLogs`.
|
|
74
|
+
- **Credit hooks:** `useCreditBalance`, `useCreditBalanceContext`, `useConsumeCredits`, `usePurchaseCredits`, `useCreditPackages`, `usePublicCreditPackages`, `useCreditTransactions`, `useExpiringCredits`.
|
|
75
|
+
- **Push hooks:** `usePushNotifications`.
|
|
76
|
+
- **Gate components (conditional render by state):**
|
|
77
|
+
- Auth: `WhenAuthenticated`, `WhenUnauthenticated`
|
|
78
|
+
- Roles: `WhenRoles`, `WhenWorkspaceRoles`, `WhenPermission`
|
|
79
|
+
- Features: `WhenUserFeatureEnabled`, `WhenUserFeatureDisabled`, `WhenWorkspaceFeatureEnabled`, `WhenWorkspaceFeatureDisabled`
|
|
80
|
+
- Subscription: `WhenSubscription`, `WhenNoSubscription`, `WhenSubscriptionToPlans`
|
|
81
|
+
- Trial: `WhenTrialing`, `WhenNotTrialing`, `WhenTrialEnding`
|
|
82
|
+
- Quota: `WhenQuotaAvailable`, `WhenQuotaExhausted`, `WhenQuotaOverage`, `WhenQuotaThreshold`
|
|
83
|
+
- Credits: `WhenCreditsAvailable`, `WhenCreditsExhausted`, `WhenCreditsLow`
|
|
84
|
+
- **UI components:** `WorkspaceSwitcher`, `PricingPage`, `CreditStorePage`, `CreditBalance`, `CreditActionsProvider`, `BetaForm`, `FullScreenLoader`.
|
|
85
|
+
- **Misc:** `SUPPORTED_LOCALES`, `SETTINGS_SCREENS`, `SettingsScreen`, `workspaceSettingsManager`.
|
|
86
|
+
|
|
87
|
+
### `@buildbase/sdk/data`
|
|
88
|
+
|
|
89
|
+
`countries`, `currencies`, `languages`, `timezones`, `betaFormSchema` (Zod), type `BetaFormValues`.
|
|
90
|
+
|
|
91
|
+
## Server actions cheat-sheet
|
|
92
|
+
|
|
93
|
+
`workspace`: `list get create update delete` · `users`: `list invite remove updateRole getProfile updateProfile` · `subscription`: `get checkout update cancel resume getBillingPortalUrl` · `plans`: `getGroup getVersions getPublic getVersion` · `invoices`: `list get` · `usage`: `record recordBatch getQuota getAll getLogs` · `credits`: `getBalance consume purchase getPackages getTransactions getExpiring getBuckets getPublicPackages` · `settings`: `get` · `features`: `list update` · `notification`: `send(workspaceId, event, userId?, data?)` · `permissions`: `check(workspaceId, userId, permission) resolve(workspaceId, userId)`.
|
|
94
|
+
|
|
95
|
+
## Internationalization (i18n)
|
|
96
|
+
|
|
97
|
+
- 8 locales: `en es fr de ja zh hi ar`. English is bundled; others lazy-load. `SUPPORTED_LOCALES` lists them.
|
|
98
|
+
- All message catalogs are typed `: SDKMessages` (see `src/i18n/types.ts`) — **the type system guarantees every locale has the complete key set**; a missing/extra key fails `tsc`.
|
|
99
|
+
- Client: `const { t, locale, dir, fmtNum, fmtCents } = useTranslation()`. `t('a.b.c', { count })` is ICU MessageFormat with compile-time-checked keys. `dir` is `'rtl'` for Arabic. Hindi/Arabic render native numerals.
|
|
100
|
+
- Set the active locale via `SaaSOSProvider locale="…"` (accepts regional tags like `zh-TW`, resolved to the nearest supported locale).
|
|
101
|
+
- Only **user-facing UI strings** are translated. Server/machine output (JWT error codes, discovery JSON, webhook codes) is intentionally **not** localized.
|
|
102
|
+
|
|
103
|
+
## Gotchas (read before you touch)
|
|
104
|
+
|
|
105
|
+
- **Server vs client imports** — importing `@buildbase/sdk/react` on the server pulls React in; keep server code on `@buildbase/sdk`.
|
|
106
|
+
- **Webhooks** — always `verifyWebhookSignature`/`parseWebhookEvent` against the raw body string. In Next.js App Router use `await req.text()`, not `req.json()`.
|
|
107
|
+
- **After a server-side mutation** that changes subscription/quota/credits, call the matching `invalidate*` helper so client contexts refetch.
|
|
108
|
+
- **Agent-readiness fetches are fail-soft** — a platform outage yields `{ enabled: false }`, never a 500. Don't add your own error handling expecting throws.
|
|
109
|
+
- **New crypto is dependency-free pure JS** (`src/lib/sha256.ts`) so it behaves identically on browser/edge/Node — don't swap in Web Crypto / Node `crypto` without matching outputs.
|
|
110
|
+
- **Prefer SDK hooks** (`useSaaS*`, `useSubscription*`, etc.) over `useAppSelector`/internal context so consumer code stays stable across internal refactors.
|
|
111
|
+
|
|
112
|
+
## Working on this repo
|
|
113
|
+
|
|
114
|
+
- `npm run build` — rollup build of all entry points into `dist/` (also runs on `prepublishOnly`).
|
|
115
|
+
- `npx tsc --noEmit` — typecheck (also the i18n completeness guarantee).
|
|
116
|
+
- `npm run format` — Prettier + organize-imports.
|
|
117
|
+
- `npm run dev` / `npm run watch:push` — watch build (+ `yalc push` for local consumers).
|
|
118
|
+
- No test runner is configured; verify changes via `tsc`, `build`, and a consumer app.
|
|
119
|
+
- Source layout: `src/api` (API clients + pure billing utils), `src/contexts` + `src/providers` (React state), `src/hooks`, `src/components` (incl. `ui/` primitives), `src/lib` (framework-agnostic utils, webhooks, agent tooling, crypto), `src/i18n` (catalogs + `useTranslation`).
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.0.49] - 2026-07-07
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Server-side agent-readiness discovery** (`@buildbase/sdk`): framework-agnostic helpers to make a consuming app "agent ready" — `resolveWellKnown`, `fetchAgentReadiness`, `clearAgentReadinessCache`, `buildAgentCard`, `buildProtectedResourceMetadata`, `buildAgentSkillsIndex`, `buildSkillMd`, `buildSecurityTxt`, `buildLlmsTxt`, `sha256Digest`; types `AgentReadyConfig`, `AgentReadinessBundle`, `AgentSkill`, `DiscoveryDocument`. Serves Agent Card, OAuth protected-resource metadata (RFC 9728), Agent Skills, `security.txt` (RFC 9116), and `llms.txt`. Fetches are fail-soft and cached in-memory.
|
|
13
|
+
- **Server-side OAuth2 app-bridge** (`@buildbase/sdk`): verify BuildBase's signed `applicationTokenUrl`/`applicationRevokeUrl` webhook requests and shape the exact response the platform expects — `handleAppTokenRequest`, `handleAppRevokeRequest`, `bearerChallenge`, `verifyAppTokenRequest`, `verifyAppRevokeRequest`, `verifyClientJwt`, `extractBearerToken`, `appTokenSuccess`, `appTokenFailure`, `AppBridgeError`; types `AppTokenRequestClaims`, `AppRevokeRequestClaims`, `AppTokenResult`, `AppTokenResponseBody`, `HandlerResult`. HS256 JWT verification is timing-safe with no `alg` confusion.
|
|
14
|
+
- **Dependency-free SHA-256 / HMAC-SHA256** (`src/lib/sha256.ts`): pure-JS implementation (no Web Crypto, no Node `crypto`) shared by the discovery and app-bridge toolkits, so digests are identical on every runtime (browser, edge, Node 18+).
|
|
15
|
+
- **README**: new "Webhook Verification", "Agent Readiness (Discovery)", and "OAuth2 App Bridge" sections, plus server-only toolkits in the API Reference.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **Workspace → Users crash**: a member whose `name` is null/undefined (common with OAuth/passkey signups) no longer crashes the entire member list; `getUserDisplay` now falls back to the "unknown user" label.
|
|
20
|
+
- **Duplicate `onError` callbacks**: network/timeout failures routed through `fetchJson` invoked the `onError` callback twice (double Sentry capture / double error toast). The callback now fires at most once per failure, regardless of code path.
|
|
21
|
+
- Corrected the `agent-discovery` module JSDoc example, which referenced a non-existent `agentReady()` factory; it now uses the actual `resolveWellKnown` / `buildLlmsTxt` API.
|
|
22
|
+
- **AI-agent docs**: added `AGENTS.md` (shipped in the package) — a dense reference of both entry points, the full export map, the i18n contract, and gotchas.
|
|
23
|
+
|
|
24
|
+
## [0.0.19] - 2025-02-07
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- **Multi-currency support**: New `currency-utils` with `CURRENCY_DISPLAY`, `CURRENCY_FLAG`, `PLAN_CURRENCY_CODES`, `PLAN_CURRENCY_OPTIONS`, `formatCents`, `formatOverageRate`, `formatOverageRateWithLabel`, `formatQuotaIncludedOverage`, `getCurrencyFlag`, `getCurrencySymbol`, `getQuotaUnitLabelFromName`.
|
|
29
|
+
- **Pricing variant utilities**: New `pricing-variant-utils` with `getPricingVariant`, `getBasePriceCents`, `getStripePriceIdForInterval`, `getQuotaOverageCents`, `getQuotaDisplayWithVariant`, `getAvailableCurrenciesFromPlans`, `getDisplayCurrency`, `getBillingIntervalAndCurrencyFromPriceId`; types `IPricingVariant`, `PlanVersionWithPricingVariants`, `QuotaDisplayWithOverage`.
|
|
30
|
+
- **API types**: `IPricingVariant`, `IStripePricesByInterval`, `IQuotaOveragesByInterval`, `IQuotaOveragePriceIdsByInterval`; plan/plan-version types now support `pricingVariants` and per-interval quotas.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- **Plan and subscription types**: `IPlanVersion` uses `pricingVariants` (multi-currency) instead of single `basePricing`/`stripePrices`; `quotas` unified to `IQuotaByInterval`; `IQuotaIntervalValue` overage/priceId optional for public plans.
|
|
35
|
+
- **Public plans**: `IPublicPlanVersion` uses `pricingVariants` and `IQuotaByInterval`; removed `IPublicPlanPricing`, `IPublicPlanQuotaValue`; added `notes` to `IPublicPlansResponse`.
|
|
36
|
+
- **Workspace**: Refactored workspace hooks to simplify dependencies and state management; `SubscriptionDialog` and `SettingsSubscription` updated for multi-currency and new types; `SettingsGeneral` and `SettingsInvoices` adjustments.
|
|
37
|
+
- **Quota utils**: `quota-utils` API updates and alignment with pricing variant overage display.
|
|
38
|
+
- **Docs**: README added "Multi-Currency & Pricing Utilities" section and API reference for currency/pricing-variant/quota utilities; `ARCHITECTURE.md` documents API utilities and type exports; `ERROR_CODES.md` unchanged.
|
|
39
|
+
|
|
40
|
+
### Removed
|
|
41
|
+
|
|
42
|
+
- Legacy types: `IQuotaValue`, `IPublicPlanPricing`, `IPublicPlanQuotaValue` (replaced by pricing variants and `IQuotaByInterval`).
|
package/README.md
CHANGED
|
@@ -36,6 +36,9 @@ Also works server-side (Next.js API routes, Express, Hono) — see [Server-Side
|
|
|
36
36
|
- [API Reference](#-api-reference)
|
|
37
37
|
- [Best Practices](#-best-practices)
|
|
38
38
|
- [Server-Side Usage](#server-side-usage)
|
|
39
|
+
- [Webhook Verification](#webhook-verification)
|
|
40
|
+
- [Agent Readiness (Discovery)](#agent-readiness-discovery)
|
|
41
|
+
- [OAuth2 App Bridge](#oauth2-app-bridge)
|
|
39
42
|
|
|
40
43
|
## 🚀 Features
|
|
41
44
|
|
|
@@ -2017,6 +2020,15 @@ All SDK API clients extend a shared base class and are exported from the package
|
|
|
2017
2020
|
| `WorkspaceApi` | Workspaces, subscription, invoices, quota usage, users |
|
|
2018
2021
|
| `SettingsApi` | Organization settings |
|
|
2019
2022
|
|
|
2023
|
+
Server-only toolkits (framework-agnostic, zero React) are exported from `@buildbase/sdk`:
|
|
2024
|
+
|
|
2025
|
+
| Export group | Purpose |
|
|
2026
|
+
| ------------------------ | ---------------------------------------------------------------------------------------------------------- |
|
|
2027
|
+
| `BuildBase()` factory | Session-scoped server actions — see [Server-Side Usage](#server-side-usage) |
|
|
2028
|
+
| Webhook verification | `verifyWebhookSignature`, `parseWebhookEvent` — see [Webhook Verification](#webhook-verification) |
|
|
2029
|
+
| Agent readiness | `resolveWellKnown`, `buildAgentCard`, `buildLlmsTxt`, … — see [Agent Readiness](#agent-readiness-discovery) |
|
|
2030
|
+
| OAuth2 app bridge | `handleAppTokenRequest`, `handleAppRevokeRequest`, `bearerChallenge`, … — see [OAuth2 App Bridge](#oauth2-app-bridge) |
|
|
2031
|
+
|
|
2020
2032
|
### Components
|
|
2021
2033
|
|
|
2022
2034
|
| Component | Purpose |
|
|
@@ -2795,6 +2807,192 @@ BuildBase({
|
|
|
2795
2807
|
})
|
|
2796
2808
|
```
|
|
2797
2809
|
|
|
2810
|
+
## Webhook Verification
|
|
2811
|
+
|
|
2812
|
+
BuildBase signs every outbound webhook with HMAC-SHA256 over `<timestamp>.<rawBody>`. Verify it before trusting the payload. **Node.js only** (uses the built-in `crypto` module).
|
|
2813
|
+
|
|
2814
|
+
Always verify against the **raw** request body — parse only after verification succeeds.
|
|
2815
|
+
|
|
2816
|
+
```ts
|
|
2817
|
+
import { parseWebhookEvent, verifyWebhookSignature } from '@buildbase/sdk';
|
|
2818
|
+
|
|
2819
|
+
// One-step: verify + parse (returns null when invalid)
|
|
2820
|
+
app.post('/webhooks/buildbase', (req, res) => {
|
|
2821
|
+
const event = parseWebhookEvent({
|
|
2822
|
+
body: req.rawBody, // raw string, NOT the JSON-parsed object
|
|
2823
|
+
signature: req.headers['x-buildbase-signature'], // "sha256=<hex>"
|
|
2824
|
+
timestamp: req.headers['x-buildbase-timestamp'],
|
|
2825
|
+
secret: process.env.BUILDBASE_WEBHOOK_SECRET!,
|
|
2826
|
+
});
|
|
2827
|
+
|
|
2828
|
+
if (!event) return res.status(401).json({ error: 'Invalid webhook' });
|
|
2829
|
+
|
|
2830
|
+
switch (event.event) {
|
|
2831
|
+
case 'subscription.created':
|
|
2832
|
+
// event.data.subscription ...
|
|
2833
|
+
break;
|
|
2834
|
+
case 'workspace.member_added':
|
|
2835
|
+
// event.data.targetUser ...
|
|
2836
|
+
break;
|
|
2837
|
+
}
|
|
2838
|
+
res.json({ received: true });
|
|
2839
|
+
});
|
|
2840
|
+
```
|
|
2841
|
+
|
|
2842
|
+
`verifyWebhookSignature(options)` → `boolean` — use directly when you want to control parsing yourself.
|
|
2843
|
+
|
|
2844
|
+
| Option | Type | Notes |
|
|
2845
|
+
| --------------- | ------------------- | ----------------------------------------------------------- |
|
|
2846
|
+
| `body` | `string` | Raw request body, byte-for-byte as sent. |
|
|
2847
|
+
| `signature` | `string \| null` | `x-buildbase-signature` header (`sha256=<hex>`). |
|
|
2848
|
+
| `timestamp` | `string \| null` | `x-buildbase-timestamp` header. |
|
|
2849
|
+
| `secret` | `string` | Your endpoint's signing secret. |
|
|
2850
|
+
| `maxAgeSeconds` | `number` (def. 300) | Replay window. Set to `0` to skip the timestamp age check. |
|
|
2851
|
+
|
|
2852
|
+
> **Next.js App Router:** read the raw body with `await req.text()` — do not use `req.json()`, which discards the exact bytes the signature was computed over.
|
|
2853
|
+
|
|
2854
|
+
## Agent Readiness (Discovery)
|
|
2855
|
+
|
|
2856
|
+
Make a consuming app [agent ready](https://isitagentready.com) by serving the standard machine-readable discovery documents an AI agent looks for — Agent Card, OAuth protected-resource metadata (RFC 9728), Agent Skills, `security.txt` (RFC 9116), and `llms.txt` — with the BuildBase server as the source of truth. Framework-agnostic and zero React: every function returns a plain `DiscoveryDocument` (`{ status, contentType, body, cacheControl }`); you wire it into your own router.
|
|
2857
|
+
|
|
2858
|
+
```ts
|
|
2859
|
+
// lib/agent-ready.ts
|
|
2860
|
+
import type { AgentReadyConfig } from '@buildbase/sdk';
|
|
2861
|
+
|
|
2862
|
+
export const agentConfig: AgentReadyConfig = {
|
|
2863
|
+
serverUrl: process.env.BUILDBASE_URL!,
|
|
2864
|
+
orgId: process.env.BUILDBASE_ORG_ID!,
|
|
2865
|
+
siteUrl: 'https://imejis.io',
|
|
2866
|
+
site: { name: 'Imejis', description: 'Generate images from templates via API.' },
|
|
2867
|
+
// skills, security, cacheTtlSeconds are all optional
|
|
2868
|
+
};
|
|
2869
|
+
```
|
|
2870
|
+
|
|
2871
|
+
Serve every `.well-known/*` document from one catch-all route via `resolveWellKnown`:
|
|
2872
|
+
|
|
2873
|
+
```ts
|
|
2874
|
+
// app/.well-known/[...path]/route.ts (Next.js App Router)
|
|
2875
|
+
import { resolveWellKnown } from '@buildbase/sdk';
|
|
2876
|
+
import { agentConfig } from '@/lib/agent-ready';
|
|
2877
|
+
|
|
2878
|
+
export async function GET(req: Request) {
|
|
2879
|
+
const doc = await resolveWellKnown(new URL(req.url).pathname, agentConfig);
|
|
2880
|
+
if (!doc) return new Response('{"error":"not_found"}', { status: 404 });
|
|
2881
|
+
return new Response(doc.body, {
|
|
2882
|
+
status: doc.status,
|
|
2883
|
+
headers: { 'Content-Type': doc.contentType, 'Cache-Control': doc.cacheControl },
|
|
2884
|
+
});
|
|
2885
|
+
}
|
|
2886
|
+
```
|
|
2887
|
+
|
|
2888
|
+
`resolveWellKnown` handles `agent.json`, `oauth-protected-resource` (+ per-resource paths), the `oauth-authorization-server` pointer, the Agent Skills index + `SKILL.md`, and `security.txt`. Serve `llms.txt` from its own route (it lives at the site root, not under `.well-known`):
|
|
2889
|
+
|
|
2890
|
+
```ts
|
|
2891
|
+
// app/llms.txt/route.ts
|
|
2892
|
+
import { buildLlmsTxt, fetchAgentReadiness } from '@buildbase/sdk';
|
|
2893
|
+
import { agentConfig } from '@/lib/agent-ready';
|
|
2894
|
+
|
|
2895
|
+
export async function GET() {
|
|
2896
|
+
const doc = buildLlmsTxt(agentConfig, await fetchAgentReadiness(agentConfig));
|
|
2897
|
+
if (!doc) return new Response('Not found', { status: 404 });
|
|
2898
|
+
return new Response(doc.body, { headers: { 'Content-Type': doc.contentType } });
|
|
2899
|
+
}
|
|
2900
|
+
```
|
|
2901
|
+
|
|
2902
|
+
`fetchAgentReadiness` is **fail-soft** — any network/HTTP/parse error resolves to `{ enabled: false }`, so a discovery route never 500s and never leaks that the platform is down; agents simply see the app as not (yet) agent-ready. Results are cached in-memory for `cacheTtlSeconds` (default 300s); call `clearAgentReadinessCache()` to reset (mainly for tests).
|
|
2903
|
+
|
|
2904
|
+
**Functions:** `resolveWellKnown`, `fetchAgentReadiness`, `clearAgentReadinessCache`, `buildAgentCard`, `buildProtectedResourceMetadata`, `buildAgentSkillsIndex`, `buildSkillMd`, `buildSecurityTxt`, `buildLlmsTxt`, `sha256Digest`. **Types:** `AgentReadyConfig`, `AgentReadinessBundle`, `AgentSkill`, `DiscoveryDocument`.
|
|
2905
|
+
|
|
2906
|
+
## OAuth2 App Bridge
|
|
2907
|
+
|
|
2908
|
+
BuildBase runs the full OAuth2 authorization flow (login, consent, code, PKCE, refresh rotation) but never mints the access token itself — on the token grant it calls **your** backend to mint the token the agent will carry. It makes signed webhook-style calls to two endpoints your OAuth2 client registers:
|
|
2909
|
+
|
|
2910
|
+
- `applicationTokenUrl` — mint an access token for a user (**required**)
|
|
2911
|
+
- `applicationRevokeUrl` — invalidate a user's token on revocation (optional)
|
|
2912
|
+
|
|
2913
|
+
Both requests carry `Authorization: Bearer <JWT>`, an HS256 JWT signed with your client secret. This toolkit verifies those requests (timing-safe, no `alg` confusion) and shapes the exact response body the platform expects, so you write only the part that's yours: minting/invalidating a token in your own format.
|
|
2914
|
+
|
|
2915
|
+
```ts
|
|
2916
|
+
// applicationTokenUrl handler (Next.js Pages Router)
|
|
2917
|
+
import { handleAppTokenRequest } from '@buildbase/sdk';
|
|
2918
|
+
|
|
2919
|
+
export default async function handler(req, res) {
|
|
2920
|
+
const { status, body } = await handleAppTokenRequest({
|
|
2921
|
+
authorization: req.headers.authorization,
|
|
2922
|
+
clientSecret: process.env.BUILDBASE_CLIENT_SECRET!,
|
|
2923
|
+
mintToken: (user) => ({
|
|
2924
|
+
token: signMyAccessToken(user, { aud: user.resource }), // your token, your format
|
|
2925
|
+
expiresIn: 3600,
|
|
2926
|
+
}),
|
|
2927
|
+
});
|
|
2928
|
+
res.status(status).json(body); // 401 + failure body when verification fails
|
|
2929
|
+
}
|
|
2930
|
+
```
|
|
2931
|
+
|
|
2932
|
+
```ts
|
|
2933
|
+
// applicationRevokeUrl handler
|
|
2934
|
+
import { handleAppRevokeRequest } from '@buildbase/sdk';
|
|
2935
|
+
|
|
2936
|
+
export default async function handler(req, res) {
|
|
2937
|
+
const { status, body } = await handleAppRevokeRequest({
|
|
2938
|
+
authorization: req.headers.authorization,
|
|
2939
|
+
clientSecret: process.env.BUILDBASE_CLIENT_SECRET!,
|
|
2940
|
+
onRevoke: async ({ userId, clientId, reason }) => {
|
|
2941
|
+
await revokeMyTokensFor(userId, clientId);
|
|
2942
|
+
},
|
|
2943
|
+
});
|
|
2944
|
+
res.status(status).json(body);
|
|
2945
|
+
}
|
|
2946
|
+
```
|
|
2947
|
+
|
|
2948
|
+
When an agent calls your protected API without a valid token, reply with an RFC 9728 / RFC 6750 challenge that points it at your protected-resource metadata, bootstrapping OAuth discovery:
|
|
2949
|
+
|
|
2950
|
+
```ts
|
|
2951
|
+
import { bearerChallenge } from '@buildbase/sdk';
|
|
2952
|
+
|
|
2953
|
+
const c = bearerChallenge({
|
|
2954
|
+
resourceMetadataUrl: 'https://imejis.io/.well-known/oauth-protected-resource',
|
|
2955
|
+
error: 'invalid_token',
|
|
2956
|
+
});
|
|
2957
|
+
res.writeHead(c.status, c.headers).end(c.body);
|
|
2958
|
+
```
|
|
2959
|
+
|
|
2960
|
+
### Serving multiple clients
|
|
2961
|
+
|
|
2962
|
+
Each integration (an AI agent, Zapier, n8n, …) is its own BuildBase OAuth2 client with its own id/secret, but they can all share one set of endpoints: BuildBase sends the caller's `clientId` as a query param, so verify each request with the secret that matches it.
|
|
2963
|
+
|
|
2964
|
+
```ts
|
|
2965
|
+
const SECRETS: Record<string, string> = {
|
|
2966
|
+
[process.env.AGENT_CLIENT_ID!]: process.env.AGENT_CLIENT_SECRET!,
|
|
2967
|
+
[process.env.ZAPIER_CLIENT_ID!]: process.env.ZAPIER_CLIENT_SECRET!,
|
|
2968
|
+
};
|
|
2969
|
+
|
|
2970
|
+
const clientSecret = SECRETS[String(req.query.clientId)];
|
|
2971
|
+
if (!clientSecret) {
|
|
2972
|
+
return res.status(401).json({ success: false, token: '', message: 'unknown_client' });
|
|
2973
|
+
}
|
|
2974
|
+
const { status, body } = await handleAppTokenRequest({ authorization: req.headers.authorization, clientSecret, mintToken });
|
|
2975
|
+
```
|
|
2976
|
+
|
|
2977
|
+
Adding a new integration is then just: register it in BuildBase, point its `applicationTokenUrl` at the same endpoint, and add its `id → secret` to the map. Selecting the secret by `clientId` is safe — the `clientId` is public and only *picks* the key; the HS256 signature check is still the real gate.
|
|
2978
|
+
|
|
2979
|
+
### `applicationProfileUrl` (userinfo)
|
|
2980
|
+
|
|
2981
|
+
If your client also registers an `applicationProfileUrl`, treat it as a userinfo / token-validation endpoint: validate the access token **you** minted (with your own verifier — *not* the client secret) and return the profile.
|
|
2982
|
+
|
|
2983
|
+
```ts
|
|
2984
|
+
import { extractBearerToken } from '@buildbase/sdk';
|
|
2985
|
+
|
|
2986
|
+
const token = extractBearerToken(req.headers.authorization);
|
|
2987
|
+
const claims = verifyMyAccessToken(token); // your token, your key
|
|
2988
|
+
if (!claims) return res.status(401).json({ error: 'invalid_token' });
|
|
2989
|
+
return res.json({ id: claims.id, email: claims.email /* … */ });
|
|
2990
|
+
```
|
|
2991
|
+
|
|
2992
|
+
The one-call handlers cover the common path; the underlying pieces are exported for custom flows: `verifyAppTokenRequest` / `verifyAppRevokeRequest` (verify → claims), `verifyClientJwt`, `extractBearerToken`, and the response builders `appTokenSuccess` / `appTokenFailure`. Verification throws `AppBridgeError` (with a machine-readable `code` like `invalid_signature`, `token_expired`, `invalid_algorithm`). HMAC verification uses the SDK's dependency-free pure-JS HMAC-SHA256, so it behaves identically under ESM, CJS, a bundler, or bare Node.
|
|
2993
|
+
|
|
2994
|
+
**Types:** `AppTokenRequestClaims`, `AppRevokeRequestClaims`, `AppTokenResult`, `AppTokenResponseBody`, `HandlerResult`.
|
|
2995
|
+
|
|
2798
2996
|
## 🤝 Contributing
|
|
2799
2997
|
|
|
2800
2998
|
1. Fork the repository
|
package/dist/css/styles.css
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
.saas-os-ui *,.saas-os-ui :after,.saas-os-ui :before{--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:rgba(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: }.saas-os-ui ::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:rgba(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: }/*
|
|
2
2
|
! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com
|
|
3
|
-
*/.saas-os-ui *,.saas-os-ui :after,.saas-os-ui :before{border:0 solid #e5e7eb;box-sizing:border-box}.saas-os-ui :after,.saas-os-ui :before{--tw-content:""}.saas-os-ui,.saas-os-ui :host{-webkit-text-size-adjust:100%;font-feature-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-variation-settings:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}.saas-os-ui{line-height:inherit;margin:0}.saas-os-ui hr{border-top-width:1px;color:inherit;height:0}.saas-os-ui abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.saas-os-ui h1,.saas-os-ui h2,.saas-os-ui h3,.saas-os-ui h4,.saas-os-ui h5,.saas-os-ui h6{font-size:inherit;font-weight:inherit}.saas-os-ui a{color:inherit;text-decoration:inherit}.saas-os-ui b,.saas-os-ui strong{font-weight:bolder}.saas-os-ui code,.saas-os-ui kbd,.saas-os-ui pre,.saas-os-ui samp{font-feature-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em;font-variation-settings:normal}.saas-os-ui small{font-size:80%}.saas-os-ui sub,.saas-os-ui sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}.saas-os-ui sub{bottom:-.25em}.saas-os-ui sup{top:-.5em}.saas-os-ui table{border-collapse:collapse;border-color:inherit;text-indent:0}.saas-os-ui button,.saas-os-ui input,.saas-os-ui optgroup,.saas-os-ui select,.saas-os-ui textarea{font-feature-settings:inherit;color:inherit;font-family:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;margin:0;padding:0}.saas-os-ui button,.saas-os-ui select{text-transform:none}.saas-os-ui button,.saas-os-ui input:where([type=button]),.saas-os-ui input:where([type=reset]),.saas-os-ui input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}.saas-os-ui :-moz-focusring{outline:auto}.saas-os-ui :-moz-ui-invalid{box-shadow:none}.saas-os-ui progress{vertical-align:baseline}.saas-os-ui ::-webkit-inner-spin-button,.saas-os-ui ::-webkit-outer-spin-button{height:auto}.saas-os-ui [type=search]{-webkit-appearance:textfield;outline-offset:-2px}.saas-os-ui ::-webkit-search-decoration{-webkit-appearance:none}.saas-os-ui ::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}.saas-os-ui summary{display:list-item}.saas-os-ui blockquote,.saas-os-ui dd,.saas-os-ui dl,.saas-os-ui figure,.saas-os-ui h1,.saas-os-ui h2,.saas-os-ui h3,.saas-os-ui h4,.saas-os-ui h5,.saas-os-ui h6,.saas-os-ui hr,.saas-os-ui p,.saas-os-ui pre{margin:0}.saas-os-ui fieldset{margin:0;padding:0}.saas-os-ui legend{padding:0}.saas-os-ui menu,.saas-os-ui ol,.saas-os-ui ul{list-style:none;margin:0;padding:0}.saas-os-ui dialog{padding:0}.saas-os-ui textarea{resize:vertical}.saas-os-ui input::-moz-placeholder,.saas-os-ui textarea::-moz-placeholder{color:#9ca3af;opacity:1}.saas-os-ui input::placeholder,.saas-os-ui textarea::placeholder{color:#9ca3af;opacity:1}.saas-os-ui [role=button],.saas-os-ui button{cursor:pointer}.saas-os-ui :disabled{cursor:default}.saas-os-ui audio,.saas-os-ui canvas,.saas-os-ui embed,.saas-os-ui iframe,.saas-os-ui img,.saas-os-ui object,.saas-os-ui svg,.saas-os-ui video{display:block;vertical-align:middle}.saas-os-ui img,.saas-os-ui video{height:auto;max-width:100%}.saas-os-ui [hidden]:where(:not([hidden=until-found])){display:none}.saas-os-ui{--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%;--secondary-foreground:222.2 84% 4.9%;--muted:210 40% 96%;--muted-foreground:215.4 16.3% 46.9%;--accent:210 40% 96%;--accent-foreground:222.2 84% 4.9%;--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:0.5rem}.saas-os-ui .dark{--background:222.2 84% 4.9%;--foreground:210 40% 98%;--card:222.2 84% 4.9%;--card-foreground:210 40% 98%;--popover:222.2 84% 4.9%;--popover-foreground:210 40% 98%;--primary:210 40% 98%;--primary-foreground:222.2 47.4% 11.2%;--secondary:217.2 32.6% 17.5%;--secondary-foreground:210 40% 98%;--muted:217.2 32.6% 17.5%;--muted-foreground:215 20.2% 65.1%;--accent:217.2 32.6% 17.5%;--accent-foreground:210 40% 98%;--destructive:0 62.8% 30.6%;--destructive-foreground:210 40% 98%;--border:217.2 32.6% 17.5%;--input:217.2 32.6% 17.5%;--ring:212.7 26.8% 83.9%}.saas-os-ui *{border-color:hsl(var(--border))}.saas-os-ui{background-color:hsl(var(--background));color:hsl(var(--foreground))}.saas-os-ui .container{width:100%}@media (min-width:640px){.saas-os-ui .container{max-width:640px}}@media (min-width:768px){.saas-os-ui .container{max-width:768px}}@media (min-width:1024px){.saas-os-ui .container{max-width:1024px}}@media (min-width:1280px){.saas-os-ui .container{max-width:1280px}}@media (min-width:1536px){.saas-os-ui .container{max-width:1536px}}.saas-os-ui .sr-only{clip:rect(0,0,0,0);border-width:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.saas-os-ui .pointer-events-none{pointer-events:none}.saas-os-ui .visible{visibility:visible}.saas-os-ui .static{position:static}.saas-os-ui .fixed{position:fixed}.saas-os-ui .absolute{position:absolute}.saas-os-ui .relative{position:relative}.saas-os-ui .sticky{position:sticky}.saas-os-ui .inset-0{inset:0}.saas-os-ui .end-2{inset-inline-end:.5rem}.saas-os-ui .end-8{inset-inline-end:2rem}.saas-os-ui .left-\[50\%\]{left:50%}.saas-os-ui .right-4{right:1rem}.saas-os-ui .start-0{inset-inline-start:0}.saas-os-ui .start-3{inset-inline-start:.75rem}.saas-os-ui .top-0{top:0}.saas-os-ui .top-1\/2{top:50%}.saas-os-ui .top-4{top:1rem}.saas-os-ui .top-\[50\%\]{top:50%}.saas-os-ui .z-10{z-index:10}.saas-os-ui .z-20{z-index:20}.saas-os-ui .z-30{z-index:30}.saas-os-ui .z-50{z-index:50}.saas-os-ui .m-0{margin:0}.saas-os-ui .-mx-1{margin-left:-.25rem;margin-right:-.25rem}.saas-os-ui .mx-auto{margin-left:auto;margin-right:auto}.saas-os-ui .my-1{margin-bottom:.25rem;margin-top:.25rem}.saas-os-ui .my-2{margin-bottom:.5rem;margin-top:.5rem}.saas-os-ui .my-2\.5{margin-bottom:.625rem;margin-top:.625rem}.saas-os-ui .my-4{margin-bottom:1rem;margin-top:1rem}.saas-os-ui .-mb-px{margin-bottom:-1px}.saas-os-ui .mb-0\.5{margin-bottom:.125rem}.saas-os-ui .mb-1{margin-bottom:.25rem}.saas-os-ui .mb-1\.5{margin-bottom:.375rem}.saas-os-ui .mb-2{margin-bottom:.5rem}.saas-os-ui .mb-2\.5{margin-bottom:.625rem}.saas-os-ui .mb-3{margin-bottom:.75rem}.saas-os-ui .mb-4{margin-bottom:1rem}.saas-os-ui .me-1\.5{margin-inline-end:.375rem}.saas-os-ui .me-2{margin-inline-end:.5rem}.saas-os-ui .ml-1{margin-left:.25rem}.saas-os-ui .ms-1{margin-inline-start:.25rem}.saas-os-ui .ms-1\.5{margin-inline-start:.375rem}.saas-os-ui .ms-2{margin-inline-start:.5rem}.saas-os-ui .ms-auto{margin-inline-start:auto}.saas-os-ui .mt-0\.5{margin-top:.125rem}.saas-os-ui .mt-1{margin-top:.25rem}.saas-os-ui .mt-1\.5{margin-top:.375rem}.saas-os-ui .mt-2{margin-top:.5rem}.saas-os-ui .mt-3{margin-top:.75rem}.saas-os-ui .mt-4{margin-top:1rem}.saas-os-ui .mt-6{margin-top:1.5rem}.saas-os-ui .mt-auto{margin-top:auto}.saas-os-ui .line-clamp-1{-webkit-line-clamp:1}.saas-os-ui .line-clamp-1,.saas-os-ui .line-clamp-2{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.saas-os-ui .line-clamp-2{-webkit-line-clamp:2}.saas-os-ui .block{display:block}.saas-os-ui .inline{display:inline}.saas-os-ui .flex{display:flex}.saas-os-ui .inline-flex{display:inline-flex}.saas-os-ui .table{display:table}.saas-os-ui .grid{display:grid}.saas-os-ui .hidden{display:none}.saas-os-ui .aspect-square{aspect-ratio:1/1}.saas-os-ui .h-1\.5{height:.375rem}.saas-os-ui .h-10{height:2.5rem}.saas-os-ui .h-12{height:3rem}.saas-os-ui .h-16{height:4rem}.saas-os-ui .h-2{height:.5rem}.saas-os-ui .h-2\.5{height:.625rem}.saas-os-ui .h-24{height:6rem}.saas-os-ui .h-3{height:.75rem}.saas-os-ui .h-3\.5{height:.875rem}.saas-os-ui .h-32{height:8rem}.saas-os-ui .h-4{height:1rem}.saas-os-ui .h-48{height:12rem}.saas-os-ui .h-5{height:1.25rem}.saas-os-ui .h-6{height:1.5rem}.saas-os-ui .h-64{height:16rem}.saas-os-ui .h-8{height:2rem}.saas-os-ui .h-9{height:2.25rem}.saas-os-ui .h-\[1px\]{height:1px}.saas-os-ui .h-\[20px\]{height:20px}.saas-os-ui .h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.saas-os-ui .h-full{height:100%}.saas-os-ui .h-px{height:1px}.saas-os-ui .h-screen{height:100vh}.saas-os-ui .max-h-24{max-height:6rem}.saas-os-ui .max-h-\[300px\]{max-height:300px}.saas-os-ui .min-h-0{min-height:0}.saas-os-ui .min-h-\[3rem\]{min-height:3rem}.saas-os-ui .min-h-full{min-height:100%}.saas-os-ui .w-10{width:2.5rem}.saas-os-ui .w-12{width:3rem}.saas-os-ui .w-16{width:4rem}.saas-os-ui .w-2\.5{width:.625rem}.saas-os-ui .w-24{width:6rem}.saas-os-ui .w-3{width:.75rem}.saas-os-ui .w-3\.5{width:.875rem}.saas-os-ui .w-32{width:8rem}.saas-os-ui .w-4{width:1rem}.saas-os-ui .w-44{width:11rem}.saas-os-ui .w-48{width:12rem}.saas-os-ui .w-5{width:1.25rem}.saas-os-ui .w-6{width:1.5rem}.saas-os-ui .w-72{width:18rem}.saas-os-ui .w-8{width:2rem}.saas-os-ui .w-9{width:2.25rem}.saas-os-ui .w-\[1px\]{width:1px}.saas-os-ui .w-\[36px\]{width:36px}.saas-os-ui .w-full{width:100%}.saas-os-ui .w-screen{width:100vw}.saas-os-ui .min-w-0{min-width:0}.saas-os-ui .min-w-\[160px\]{min-width:160px}.saas-os-ui .min-w-\[80px\]{min-width:80px}.saas-os-ui .min-w-\[8rem\]{min-width:8rem}.saas-os-ui .min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.saas-os-ui .min-w-full{min-width:100%}.saas-os-ui .max-w-2xl{max-width:42rem}.saas-os-ui .max-w-fit{max-width:-moz-fit-content;max-width:fit-content}.saas-os-ui .max-w-full{max-width:100%}.saas-os-ui .max-w-lg{max-width:32rem}.saas-os-ui .max-w-none{max-width:none}.saas-os-ui .max-w-xl{max-width:36rem}.saas-os-ui .flex-1{flex:1 1 0%}.saas-os-ui .flex-shrink-0,.saas-os-ui .shrink-0{flex-shrink:0}.saas-os-ui .border-separate{border-collapse:separate}.saas-os-ui .border-spacing-0{--tw-border-spacing-x:0px;--tw-border-spacing-y:0px;border-spacing:var(--tw-border-spacing-x) var(--tw-border-spacing-y)}.saas-os-ui .-translate-y-1\/2{--tw-translate-y:-50%}.saas-os-ui .-translate-y-1\/2,.saas-os-ui .translate-x-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.saas-os-ui .translate-x-0{--tw-translate-x:0px}.saas-os-ui .translate-x-\[-50\%\]{--tw-translate-x:-50%}.saas-os-ui .translate-x-\[-50\%\],.saas-os-ui .translate-y-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.saas-os-ui .translate-y-0{--tw-translate-y:0px}.saas-os-ui .translate-y-\[-50\%\]{--tw-translate-y:-50%}.saas-os-ui .transform,.saas-os-ui .translate-y-\[-50\%\]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.saas-os-ui .animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(1turn)}}.saas-os-ui .animate-spin{animation:spin 1s linear infinite}.saas-os-ui .cursor-default{cursor:default}.saas-os-ui .cursor-pointer{cursor:pointer}.saas-os-ui .touch-none{touch-action:none}.saas-os-ui .select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.saas-os-ui .list-inside{list-style-position:inside}.saas-os-ui .list-decimal{list-style-type:decimal}.saas-os-ui .grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.saas-os-ui .grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.saas-os-ui .grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}.saas-os-ui .flex-col{flex-direction:column}.saas-os-ui .flex-col-reverse{flex-direction:column-reverse}.saas-os-ui .flex-wrap{flex-wrap:wrap}.saas-os-ui .items-start{align-items:flex-start}.saas-os-ui .items-center{align-items:center}.saas-os-ui .items-baseline{align-items:baseline}.saas-os-ui .justify-end{justify-content:flex-end}.saas-os-ui .justify-center{justify-content:center}.saas-os-ui .justify-between{justify-content:space-between}.saas-os-ui .gap-0\.5{gap:.125rem}.saas-os-ui .gap-1{gap:.25rem}.saas-os-ui .gap-1\.5{gap:.375rem}.saas-os-ui .gap-2{gap:.5rem}.saas-os-ui .gap-3{gap:.75rem}.saas-os-ui .gap-4{gap:1rem}.saas-os-ui .gap-6{gap:1.5rem}.saas-os-ui .gap-x-0{-moz-column-gap:0;column-gap:0}.saas-os-ui .gap-x-0\.5{-moz-column-gap:.125rem;column-gap:.125rem}.saas-os-ui .gap-x-1{-moz-column-gap:.25rem;column-gap:.25rem}.saas-os-ui .gap-x-1\.5{-moz-column-gap:.375rem;column-gap:.375rem}.saas-os-ui .gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.saas-os-ui .gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.saas-os-ui .gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.saas-os-ui .gap-y-0\.5{row-gap:.125rem}.saas-os-ui .gap-y-1{row-gap:.25rem}.saas-os-ui .gap-y-2{row-gap:.5rem}.saas-os-ui .gap-y-2\.5{row-gap:.625rem}.saas-os-ui .gap-y-3\.5{row-gap:.875rem}.saas-os-ui .space-x-0>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(0px*(1 - var(--tw-space-x-reverse)));margin-right:calc(0px*var(--tw-space-x-reverse))}.saas-os-ui .space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.saas-os-ui .space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.375rem*var(--tw-space-y-reverse));margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.75rem*var(--tw-space-y-reverse));margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .space-y-3\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.875rem*var(--tw-space-y-reverse));margin-top:calc(.875rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.25rem*var(--tw-space-y-reverse));margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.5rem*var(--tw-space-y-reverse));margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-bottom-width:calc(1px*var(--tw-divide-y-reverse));border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)))}.saas-os-ui .divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(243 244 246/var(--tw-divide-opacity,1))}.saas-os-ui .overflow-auto{overflow:auto}.saas-os-ui .overflow-hidden{overflow:hidden}.saas-os-ui .overflow-x-auto{overflow-x:auto}.saas-os-ui .overflow-y-auto{overflow-y:auto}.saas-os-ui .overflow-x-hidden{overflow-x:hidden}.saas-os-ui .truncate{overflow:hidden;white-space:nowrap}.saas-os-ui .text-ellipsis,.saas-os-ui .truncate{text-overflow:ellipsis}.saas-os-ui .whitespace-nowrap{white-space:nowrap}.saas-os-ui .rounded{border-radius:.25rem}.saas-os-ui .rounded-\[inherit\]{border-radius:inherit}.saas-os-ui .rounded-full{border-radius:9999px}.saas-os-ui .rounded-lg{border-radius:var(--radius)}.saas-os-ui .rounded-md{border-radius:calc(var(--radius) - 2px)}.saas-os-ui .rounded-none{border-radius:0}.saas-os-ui .rounded-sm{border-radius:calc(var(--radius) - 4px)}.saas-os-ui .rounded-xl{border-radius:.75rem}.saas-os-ui .border{border-width:1px}.saas-os-ui .border-2{border-width:2px}.saas-os-ui .border-b{border-bottom-width:1px}.saas-os-ui .border-b-2{border-bottom-width:2px}.saas-os-ui .border-l{border-left-width:1px}.saas-os-ui .border-t{border-top-width:1px}.saas-os-ui .border-amber-200{--tw-border-opacity:1;border-color:rgb(253 230 138/var(--tw-border-opacity,1))}.saas-os-ui .border-amber-300{--tw-border-opacity:1;border-color:rgb(252 211 77/var(--tw-border-opacity,1))}.saas-os-ui .border-blue-200{--tw-border-opacity:1;border-color:rgb(191 219 254/var(--tw-border-opacity,1))}.saas-os-ui .border-blue-300{--tw-border-opacity:1;border-color:rgb(147 197 253/var(--tw-border-opacity,1))}.saas-os-ui .border-blue-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.saas-os-ui .border-border{border-color:hsl(var(--border))}.saas-os-ui .border-destructive\/50{border-color:hsl(var(--destructive)/.5)}.saas-os-ui .border-emerald-200{--tw-border-opacity:1;border-color:rgb(167 243 208/var(--tw-border-opacity,1))}.saas-os-ui .border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity,1))}.saas-os-ui .border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1))}.saas-os-ui .border-gray-50{--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity,1))}.saas-os-ui .border-green-200{--tw-border-opacity:1;border-color:rgb(187 247 208/var(--tw-border-opacity,1))}.saas-os-ui .border-green-300{--tw-border-opacity:1;border-color:rgb(134 239 172/var(--tw-border-opacity,1))}.saas-os-ui .border-input{border-color:hsl(var(--input))}.saas-os-ui .border-primary{border-color:hsl(var(--primary))}.saas-os-ui .border-purple-200{--tw-border-opacity:1;border-color:rgb(233 213 255/var(--tw-border-opacity,1))}.saas-os-ui .border-red-100{--tw-border-opacity:1;border-color:rgb(254 226 226/var(--tw-border-opacity,1))}.saas-os-ui .border-red-200{--tw-border-opacity:1;border-color:rgb(254 202 202/var(--tw-border-opacity,1))}.saas-os-ui .border-red-300{--tw-border-opacity:1;border-color:rgb(252 165 165/var(--tw-border-opacity,1))}.saas-os-ui .border-slate-100{--tw-border-opacity:1;border-color:rgb(241 245 249/var(--tw-border-opacity,1))}.saas-os-ui .border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity,1))}.saas-os-ui .border-transparent{border-color:transparent}.saas-os-ui .border-l-transparent{border-left-color:transparent}.saas-os-ui .border-t-transparent{border-top-color:transparent}.saas-os-ui .bg-amber-100{--tw-bg-opacity:1;background-color:rgb(254 243 199/var(--tw-bg-opacity,1))}.saas-os-ui .bg-amber-50{--tw-bg-opacity:1;background-color:rgb(255 251 235/var(--tw-bg-opacity,1))}.saas-os-ui .bg-amber-50\/50{background-color:rgba(255,251,235,.5)}.saas-os-ui .bg-amber-500{--tw-bg-opacity:1;background-color:rgb(245 158 11/var(--tw-bg-opacity,1))}.saas-os-ui .bg-background{background-color:hsl(var(--background))}.saas-os-ui .bg-background\/80{background-color:hsl(var(--background)/.8)}.saas-os-ui .bg-blue-100{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity,1))}.saas-os-ui .bg-blue-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.saas-os-ui .bg-blue-50\/30{background-color:rgba(239,246,255,.3)}.saas-os-ui .bg-blue-50\/50{background-color:rgba(239,246,255,.5)}.saas-os-ui .bg-blue-50\/80{background-color:rgba(239,246,255,.8)}.saas-os-ui .bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.saas-os-ui .bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.saas-os-ui .bg-border{background-color:hsl(var(--border))}.saas-os-ui .bg-destructive{background-color:hsl(var(--destructive))}.saas-os-ui .bg-destructive\/10{background-color:hsl(var(--destructive)/.1)}.saas-os-ui .bg-emerald-100{--tw-bg-opacity:1;background-color:rgb(209 250 229/var(--tw-bg-opacity,1))}.saas-os-ui .bg-emerald-50{--tw-bg-opacity:1;background-color:rgb(236 253 245/var(--tw-bg-opacity,1))}.saas-os-ui .bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.saas-os-ui .bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.saas-os-ui .bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity,1))}.saas-os-ui .bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.saas-os-ui .bg-gray-50\/50{background-color:rgba(249,250,251,.5)}.saas-os-ui .bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.saas-os-ui .bg-green-100{--tw-bg-opacity:1;background-color:rgb(220 252 231/var(--tw-bg-opacity,1))}.saas-os-ui .bg-green-50{--tw-bg-opacity:1;background-color:rgb(240 253 244/var(--tw-bg-opacity,1))}.saas-os-ui .bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.saas-os-ui .bg-green-600{--tw-bg-opacity:1;background-color:rgb(22 163 74/var(--tw-bg-opacity,1))}.saas-os-ui .bg-muted{background-color:hsl(var(--muted))}.saas-os-ui .bg-popover{background-color:hsl(var(--popover))}.saas-os-ui .bg-primary{background-color:hsl(var(--primary))}.saas-os-ui .bg-primary\/10{background-color:hsl(var(--primary)/.1)}.saas-os-ui .bg-primary\/5{background-color:hsl(var(--primary)/.05)}.saas-os-ui .bg-purple-100{--tw-bg-opacity:1;background-color:rgb(243 232 255/var(--tw-bg-opacity,1))}.saas-os-ui .bg-purple-50{--tw-bg-opacity:1;background-color:rgb(250 245 255/var(--tw-bg-opacity,1))}.saas-os-ui .bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity,1))}.saas-os-ui .bg-red-50{--tw-bg-opacity:1;background-color:rgb(254 242 242/var(--tw-bg-opacity,1))}.saas-os-ui .bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.saas-os-ui .bg-red-600{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.saas-os-ui .bg-secondary{background-color:hsl(var(--secondary))}.saas-os-ui .bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.saas-os-ui .bg-transparent{background-color:transparent}.saas-os-ui .bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.saas-os-ui .bg-yellow-100{--tw-bg-opacity:1;background-color:rgb(254 249 195/var(--tw-bg-opacity,1))}.saas-os-ui .bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity,1))}.saas-os-ui .fill-primary{fill:hsl(var(--primary))}.saas-os-ui .object-contain{-o-object-fit:contain;object-fit:contain}.saas-os-ui .object-cover{-o-object-fit:cover;object-fit:cover}.saas-os-ui .p-0{padding:0}.saas-os-ui .p-1{padding:.25rem}.saas-os-ui .p-2{padding:.5rem}.saas-os-ui .p-3{padding:.75rem}.saas-os-ui .p-4{padding:1rem}.saas-os-ui .p-5{padding:1.25rem}.saas-os-ui .p-6{padding:1.5rem}.saas-os-ui .p-8{padding:2rem}.saas-os-ui .p-\[1px\]{padding:1px}.saas-os-ui .px-0\.5{padding-left:.125rem;padding-right:.125rem}.saas-os-ui .px-1{padding-left:.25rem;padding-right:.25rem}.saas-os-ui .px-1\.5{padding-left:.375rem;padding-right:.375rem}.saas-os-ui .px-2{padding-left:.5rem;padding-right:.5rem}.saas-os-ui .px-2\.5{padding-left:.625rem;padding-right:.625rem}.saas-os-ui .px-3{padding-left:.75rem;padding-right:.75rem}.saas-os-ui .px-4{padding-left:1rem;padding-right:1rem}.saas-os-ui .px-5{padding-left:1.25rem;padding-right:1.25rem}.saas-os-ui .px-6{padding-left:1.5rem;padding-right:1.5rem}.saas-os-ui .py-0\.5{padding-bottom:.125rem;padding-top:.125rem}.saas-os-ui .py-1{padding-bottom:.25rem;padding-top:.25rem}.saas-os-ui .py-1\.5{padding-bottom:.375rem;padding-top:.375rem}.saas-os-ui .py-12{padding-bottom:3rem;padding-top:3rem}.saas-os-ui .py-16{padding-bottom:4rem;padding-top:4rem}.saas-os-ui .py-2{padding-bottom:.5rem;padding-top:.5rem}.saas-os-ui .py-2\.5{padding-bottom:.625rem;padding-top:.625rem}.saas-os-ui .py-3{padding-bottom:.75rem;padding-top:.75rem}.saas-os-ui .py-4{padding-bottom:1rem;padding-top:1rem}.saas-os-ui .py-6{padding-bottom:1.5rem;padding-top:1.5rem}.saas-os-ui .py-8{padding-bottom:2rem;padding-top:2rem}.saas-os-ui .pe-4{padding-inline-end:1rem}.saas-os-ui .pe-8{padding-inline-end:2rem}.saas-os-ui .ps-10{padding-inline-start:2.5rem}.saas-os-ui .ps-2{padding-inline-start:.5rem}.saas-os-ui .pt-1{padding-top:.25rem}.saas-os-ui .pt-2{padding-top:.5rem}.saas-os-ui .pt-3{padding-top:.75rem}.saas-os-ui .pt-4{padding-top:1rem}.saas-os-ui .text-center{text-align:center}.saas-os-ui .text-start{text-align:start}.saas-os-ui .text-end{text-align:end}.saas-os-ui .align-top{vertical-align:top}.saas-os-ui .align-middle{vertical-align:middle}.saas-os-ui .font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.saas-os-ui .text-2xl{font-size:1.5rem;line-height:2rem}.saas-os-ui .text-3xl{font-size:1.875rem;line-height:2.25rem}.saas-os-ui .text-4xl{font-size:2.25rem;line-height:2.5rem}.saas-os-ui .text-\[10px\]{font-size:10px}.saas-os-ui .text-\[11px\]{font-size:11px}.saas-os-ui .text-base{font-size:1rem;line-height:1.5rem}.saas-os-ui .text-lg{font-size:1.125rem;line-height:1.75rem}.saas-os-ui .text-sm{font-size:.875rem;line-height:1.25rem}.saas-os-ui .text-xl{font-size:1.25rem;line-height:1.75rem}.saas-os-ui .text-xs{font-size:.75rem;line-height:1rem}.saas-os-ui .font-bold{font-weight:700}.saas-os-ui .font-medium{font-weight:500}.saas-os-ui .font-semibold{font-weight:600}.saas-os-ui .uppercase{text-transform:uppercase}.saas-os-ui .lowercase{text-transform:lowercase}.saas-os-ui .capitalize{text-transform:capitalize}.saas-os-ui .leading-none{line-height:1}.saas-os-ui .leading-relaxed{line-height:1.625}.saas-os-ui .leading-tight{line-height:1.25}.saas-os-ui .tracking-tight{letter-spacing:-.025em}.saas-os-ui .tracking-wide{letter-spacing:.025em}.saas-os-ui .tracking-wider{letter-spacing:.05em}.saas-os-ui .tracking-widest{letter-spacing:.1em}.saas-os-ui .text-amber-600{--tw-text-opacity:1;color:rgb(217 119 6/var(--tw-text-opacity,1))}.saas-os-ui .text-amber-700{--tw-text-opacity:1;color:rgb(180 83 9/var(--tw-text-opacity,1))}.saas-os-ui .text-amber-800{--tw-text-opacity:1;color:rgb(146 64 14/var(--tw-text-opacity,1))}.saas-os-ui .text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.saas-os-ui .text-blue-700{--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity,1))}.saas-os-ui .text-blue-800{--tw-text-opacity:1;color:rgb(30 64 175/var(--tw-text-opacity,1))}.saas-os-ui .text-destructive{color:hsl(var(--destructive))}.saas-os-ui .text-destructive-foreground{color:hsl(var(--destructive-foreground))}.saas-os-ui .text-emerald-500{--tw-text-opacity:1;color:rgb(16 185 129/var(--tw-text-opacity,1))}.saas-os-ui .text-emerald-600{--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1))}.saas-os-ui .text-emerald-700{--tw-text-opacity:1;color:rgb(4 120 87/var(--tw-text-opacity,1))}.saas-os-ui .text-foreground{color:hsl(var(--foreground))}.saas-os-ui .text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.saas-os-ui .text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.saas-os-ui .text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.saas-os-ui .text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity,1))}.saas-os-ui .text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.saas-os-ui .text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity,1))}.saas-os-ui .text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.saas-os-ui .text-green-400{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.saas-os-ui .text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.saas-os-ui .text-green-600{--tw-text-opacity:1;color:rgb(22 163 74/var(--tw-text-opacity,1))}.saas-os-ui .text-green-700{--tw-text-opacity:1;color:rgb(21 128 61/var(--tw-text-opacity,1))}.saas-os-ui .text-green-800{--tw-text-opacity:1;color:rgb(22 101 52/var(--tw-text-opacity,1))}.saas-os-ui .text-muted-foreground{color:hsl(var(--muted-foreground))}.saas-os-ui .text-popover-foreground{color:hsl(var(--popover-foreground))}.saas-os-ui .text-primary{color:hsl(var(--primary))}.saas-os-ui .text-primary-foreground{color:hsl(var(--primary-foreground))}.saas-os-ui .text-purple-600{--tw-text-opacity:1;color:rgb(147 51 234/var(--tw-text-opacity,1))}.saas-os-ui .text-purple-700{--tw-text-opacity:1;color:rgb(126 34 206/var(--tw-text-opacity,1))}.saas-os-ui .text-purple-800{--tw-text-opacity:1;color:rgb(107 33 168/var(--tw-text-opacity,1))}.saas-os-ui .text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.saas-os-ui .text-red-600{--tw-text-opacity:1;color:rgb(220 38 38/var(--tw-text-opacity,1))}.saas-os-ui .text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity,1))}.saas-os-ui .text-red-800{--tw-text-opacity:1;color:rgb(153 27 27/var(--tw-text-opacity,1))}.saas-os-ui .text-secondary-foreground{color:hsl(var(--secondary-foreground))}.saas-os-ui .text-slate-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.saas-os-ui .text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.saas-os-ui .text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.saas-os-ui .text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.saas-os-ui .text-slate-700{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity,1))}.saas-os-ui .text-slate-900{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.saas-os-ui .text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.saas-os-ui .text-yellow-800{--tw-text-opacity:1;color:rgb(133 77 14/var(--tw-text-opacity,1))}.saas-os-ui .underline-offset-4{text-underline-offset:4px}.saas-os-ui .opacity-0{opacity:0}.saas-os-ui .opacity-100{opacity:1}.saas-os-ui .opacity-50{opacity:.5}.saas-os-ui .opacity-70{opacity:.7}.saas-os-ui .shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.saas-os-ui .shadow,.saas-os-ui .shadow-\[0_2px_4px_-2px_rgba\(0\2c 0\2c 0\2c 0\.06\)\]{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.saas-os-ui .shadow-\[0_2px_4px_-2px_rgba\(0\2c 0\2c 0\2c 0\.06\)\]{--tw-shadow:0 2px 4px -2px rgba(0,0,0,.06);--tw-shadow-colored:0 2px 4px -2px var(--tw-shadow-color)}.saas-os-ui .shadow-\[2px_0_4px_-2px_rgba\(0\2c 0\2c 0\2c 0\.06\)\]{--tw-shadow:2px 0 4px -2px rgba(0,0,0,.06);--tw-shadow-colored:2px 0 4px -2px var(--tw-shadow-color)}.saas-os-ui .shadow-\[2px_0_4px_-2px_rgba\(0\2c 0\2c 0\2c 0\.06\)\],.saas-os-ui .shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.saas-os-ui .shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.saas-os-ui .shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.saas-os-ui .shadow-md,.saas-os-ui .shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.saas-os-ui .shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.saas-os-ui .outline-none{outline:2px solid transparent;outline-offset:2px}.saas-os-ui .outline{outline-style:solid}.saas-os-ui .ring-0{--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(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)}.saas-os-ui .ring-offset-background{--tw-ring-offset-color:hsl(var(--background))}.saas-os-ui .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)}.saas-os-ui .backdrop-blur-sm{--tw-backdrop-blur:blur(4px);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)}.saas-os-ui .transition-all{transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.saas-os-ui .transition-colors{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.saas-os-ui .transition-opacity{transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.saas-os-ui .transition-shadow{transition-duration:.15s;transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1)}.saas-os-ui .transition-transform{transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.saas-os-ui .duration-200{transition-duration:.2s}.saas-os-ui .duration-500{transition-duration:.5s}.saas-os-ui .file\:border-0::file-selector-button{border-width:0}.saas-os-ui .file\:bg-transparent::file-selector-button{background-color:transparent}.saas-os-ui .file\:text-sm::file-selector-button{font-size:.875rem;line-height:1.25rem}.saas-os-ui .file\:font-medium::file-selector-button{font-weight:500}.saas-os-ui .placeholder\:text-muted-foreground::-moz-placeholder{color:hsl(var(--muted-foreground))}.saas-os-ui .placeholder\:text-muted-foreground::placeholder{color:hsl(var(--muted-foreground))}.saas-os-ui .hover\:border-gray-300:hover{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity,1))}.saas-os-ui .hover\:bg-accent:hover{background-color:hsl(var(--accent))}.saas-os-ui .hover\:bg-amber-100:hover{--tw-bg-opacity:1;background-color:rgb(254 243 199/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-blue-100:hover{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-blue-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-destructive\/90:hover{background-color:hsl(var(--destructive)/.9)}.saas-os-ui .hover\:bg-gray-200:hover{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-gray-50\/50:hover{background-color:rgba(249,250,251,.5)}.saas-os-ui .hover\:bg-gray-700:hover{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-green-100:hover{--tw-bg-opacity:1;background-color:rgb(220 252 231/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-green-700:hover{--tw-bg-opacity:1;background-color:rgb(21 128 61/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-muted:hover{background-color:hsl(var(--muted))}.saas-os-ui .hover\:bg-primary\/90:hover{background-color:hsl(var(--primary)/.9)}.saas-os-ui .hover\:bg-red-100:hover{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-red-50:hover{--tw-bg-opacity:1;background-color:rgb(254 242 242/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-red-700:hover{--tw-bg-opacity:1;background-color:rgb(185 28 28/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-secondary\/80:hover{background-color:hsl(var(--secondary)/.8)}.saas-os-ui .hover\:bg-slate-50\/50:hover{background-color:rgba(248,250,252,.5)}.saas-os-ui .hover\:text-accent-foreground:hover{color:hsl(var(--accent-foreground))}.saas-os-ui .hover\:text-blue-700:hover{--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity,1))}.saas-os-ui .hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.saas-os-ui .hover\:text-red-700:hover{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity,1))}.saas-os-ui .hover\:text-slate-900:hover{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.saas-os-ui .hover\:underline:hover{text-decoration-line:underline}.saas-os-ui .hover\:opacity-100:hover{opacity:1}.saas-os-ui .hover\:shadow-sm:hover{--tw-shadow:0 1px 2px 0 rgba(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)}.saas-os-ui .focus\:bg-accent:focus{background-color:hsl(var(--accent))}.saas-os-ui .focus\:text-accent-foreground:focus{color:hsl(var(--accent-foreground))}.saas-os-ui .focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.saas-os-ui .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)}.saas-os-ui .focus\:ring-1:focus,.saas-os-ui .focus\:ring-2:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.saas-os-ui .focus\:ring-2: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(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.saas-os-ui .focus\:ring-primary:focus{--tw-ring-color:hsl(var(--primary))}.saas-os-ui .focus\:ring-red-600:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(220 38 38/var(--tw-ring-opacity,1))}.saas-os-ui .focus\:ring-ring:focus{--tw-ring-color:hsl(var(--ring))}.saas-os-ui .focus\:ring-offset-2:focus{--tw-ring-offset-width:2px}.saas-os-ui .focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.saas-os-ui .focus-visible\:ring-1:focus-visible{--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)}.saas-os-ui .focus-visible\:ring-2:focus-visible{--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(2px + 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)}.saas-os-ui .focus-visible\:ring-ring:focus-visible{--tw-ring-color:hsl(var(--ring))}.saas-os-ui .focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px}.saas-os-ui .focus-visible\:ring-offset-background:focus-visible{--tw-ring-offset-color:hsl(var(--background))}.saas-os-ui .disabled\:pointer-events-none:disabled{pointer-events:none}.saas-os-ui .disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.saas-os-ui .disabled\:opacity-50:disabled{opacity:.5}.saas-os-ui .group:hover .group-hover\:bg-slate-50\/80{background-color:rgba(248,250,252,.8)}.saas-os-ui .peer:disabled~.peer-disabled\:cursor-not-allowed{cursor:not-allowed}.saas-os-ui .peer:disabled~.peer-disabled\:opacity-70{opacity:.7}.saas-os-ui .aria-selected\:bg-accent[aria-selected=true]{background-color:hsl(var(--accent))}.saas-os-ui .aria-selected\:text-accent-foreground[aria-selected=true]{color:hsl(var(--accent-foreground))}.saas-os-ui .data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.saas-os-ui .data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y:0.25rem}.saas-os-ui .data-\[side\=bottom\]\:translate-y-1[data-side=bottom],.saas-os-ui .data-\[side\=left\]\:-translate-x-1[data-side=left]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.saas-os-ui .data-\[side\=left\]\:-translate-x-1[data-side=left]{--tw-translate-x:-0.25rem}.saas-os-ui .data-\[side\=right\]\:translate-x-1[data-side=right]{--tw-translate-x:0.25rem}.saas-os-ui .data-\[side\=right\]\:translate-x-1[data-side=right],.saas-os-ui .data-\[side\=top\]\:-translate-y-1[data-side=top]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.saas-os-ui .data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y:-0.25rem}.saas-os-ui .data-\[state\=checked\]\:translate-x-4[data-state=checked]{--tw-translate-x:1rem}.saas-os-ui .data-\[state\=checked\]\:translate-x-4[data-state=checked],.saas-os-ui .data-\[state\=unchecked\]\:translate-x-0[data-state=unchecked]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.saas-os-ui .data-\[state\=unchecked\]\:translate-x-0[data-state=unchecked]{--tw-translate-x:0px}.saas-os-ui .data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:hsl(var(--primary))}.saas-os-ui .data-\[state\=open\]\:bg-accent[data-state=open]{background-color:hsl(var(--accent))}.saas-os-ui .data-\[state\=unchecked\]\:bg-input[data-state=unchecked]{background-color:hsl(var(--input))}.saas-os-ui .data-\[state\=open\]\:text-muted-foreground[data-state=open]{color:hsl(var(--muted-foreground))}.saas-os-ui .data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}@media (min-width:640px){.saas-os-ui .sm\:mt-0{margin-top:0}.saas-os-ui .sm\:block{display:block}.saas-os-ui .sm\:inline{display:inline}.saas-os-ui .sm\:max-h-\[500px\]{max-height:500px}.saas-os-ui .sm\:min-h-\[600px\]{min-height:600px}.saas-os-ui .sm\:w-56{width:14rem}.saas-os-ui .sm\:w-auto{width:auto}.saas-os-ui .sm\:min-w-\[600px\]{min-width:600px}.saas-os-ui .sm\:min-w-\[800px\]{min-width:800px}.saas-os-ui .sm\:flex-initial{flex:0 1 auto}.saas-os-ui .sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.saas-os-ui .sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.saas-os-ui .sm\:flex-row{flex-direction:row}.saas-os-ui .sm\:flex-col{flex-direction:column}.saas-os-ui .sm\:items-start{align-items:flex-start}.saas-os-ui .sm\:items-end{align-items:flex-end}.saas-os-ui .sm\:items-center{align-items:center}.saas-os-ui .sm\:justify-end{justify-content:flex-end}.saas-os-ui .sm\:justify-between{justify-content:space-between}.saas-os-ui .sm\:gap-1{gap:.25rem}.saas-os-ui .sm\:gap-1\.5{gap:.375rem}.saas-os-ui .sm\:gap-2{gap:.5rem}.saas-os-ui .sm\:gap-3{gap:.75rem}.saas-os-ui .sm\:gap-4{gap:1rem}.saas-os-ui .sm\:gap-y-4{row-gap:1rem}.saas-os-ui .sm\:space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.saas-os-ui .sm\:space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .sm\:space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.5rem*var(--tw-space-y-reverse));margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .sm\:rounded-lg{border-radius:var(--radius)}.saas-os-ui .sm\:border-0{border-width:0}.saas-os-ui .sm\:p-4{padding:1rem}.saas-os-ui .sm\:p-5{padding:1.25rem}.saas-os-ui .sm\:p-6{padding:1.5rem}.saas-os-ui .sm\:px-1\.5{padding-left:.375rem;padding-right:.375rem}.saas-os-ui .sm\:px-4{padding-left:1rem;padding-right:1rem}.saas-os-ui .sm\:px-5{padding-left:1.25rem;padding-right:1.25rem}.saas-os-ui .sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.saas-os-ui .sm\:py-5{padding-bottom:1.25rem;padding-top:1.25rem}.saas-os-ui .sm\:py-6{padding-bottom:1.5rem;padding-top:1.5rem}.saas-os-ui .sm\:py-8{padding-bottom:2rem;padding-top:2rem}.saas-os-ui .sm\:pt-0{padding-top:0}.saas-os-ui .sm\:text-start{text-align:start}.saas-os-ui .sm\:text-2xl{font-size:1.5rem;line-height:2rem}.saas-os-ui .sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}.saas-os-ui .sm\:text-sm{font-size:.875rem;line-height:1.25rem}.saas-os-ui .sm\:text-xl{font-size:1.25rem;line-height:1.75rem}.saas-os-ui .sm\:text-xs{font-size:.75rem;line-height:1rem}}@media (min-width:768px){.saas-os-ui .md\:block{display:block}.saas-os-ui .md\:hidden{display:none}.saas-os-ui .md\:w-full{width:100%}}@media (min-width:1024px){.saas-os-ui .lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}.saas-os-ui .rtl\:left-4:where([dir=rtl],[dir=rtl] *){left:1rem}.saas-os-ui .rtl\:right-auto:where([dir=rtl],[dir=rtl] *){right:auto}.saas-os-ui .\[\&_\[cmdk-group-heading\]\]\:px-2 [cmdk-group-heading]{padding-left:.5rem;padding-right:.5rem}.saas-os-ui .\[\&_\[cmdk-group-heading\]\]\:py-1\.5 [cmdk-group-heading]{padding-bottom:.375rem;padding-top:.375rem}.saas-os-ui .\[\&_\[cmdk-group-heading\]\]\:text-xs [cmdk-group-heading]{font-size:.75rem;line-height:1rem}.saas-os-ui .\[\&_\[cmdk-group-heading\]\]\:font-medium [cmdk-group-heading]{font-weight:500}.saas-os-ui .\[\&_\[cmdk-group-heading\]\]\:text-muted-foreground [cmdk-group-heading]{color:hsl(var(--muted-foreground))}.saas-os-ui .\[\&_\[cmdk-group\]\:not\(\[hidden\]\)_\~\[cmdk-group\]\]\:pt-0 [cmdk-group]:not([hidden])~[cmdk-group]{padding-top:0}.saas-os-ui .\[\&_\[cmdk-group\]\]\:px-2 [cmdk-group]{padding-left:.5rem;padding-right:.5rem}.saas-os-ui .\[\&_\[cmdk-input-wrapper\]_svg\]\:h-5 [cmdk-input-wrapper] svg{height:1.25rem}.saas-os-ui .\[\&_\[cmdk-input-wrapper\]_svg\]\:w-5 [cmdk-input-wrapper] svg{width:1.25rem}.saas-os-ui .\[\&_\[cmdk-input\]\]\:h-12 [cmdk-input]{height:3rem}.saas-os-ui .\[\&_\[cmdk-item\]\]\:px-2 [cmdk-item]{padding-left:.5rem;padding-right:.5rem}.saas-os-ui .\[\&_\[cmdk-item\]\]\:py-3 [cmdk-item]{padding-bottom:.75rem;padding-top:.75rem}.saas-os-ui .\[\&_\[cmdk-item\]_svg\]\:h-5 [cmdk-item] svg{height:1.25rem}.saas-os-ui .\[\&_\[cmdk-item\]_svg\]\:w-5 [cmdk-item] svg{width:1.25rem}
|
|
3
|
+
*/.saas-os-ui *,.saas-os-ui :after,.saas-os-ui :before{border:0 solid #e5e7eb;box-sizing:border-box}.saas-os-ui :after,.saas-os-ui :before{--tw-content:""}.saas-os-ui,.saas-os-ui :host{-webkit-text-size-adjust:100%;font-feature-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-variation-settings:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}.saas-os-ui{line-height:inherit;margin:0}.saas-os-ui hr{border-top-width:1px;color:inherit;height:0}.saas-os-ui abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.saas-os-ui h1,.saas-os-ui h2,.saas-os-ui h3,.saas-os-ui h4,.saas-os-ui h5,.saas-os-ui h6{font-size:inherit;font-weight:inherit}.saas-os-ui a{color:inherit;text-decoration:inherit}.saas-os-ui b,.saas-os-ui strong{font-weight:bolder}.saas-os-ui code,.saas-os-ui kbd,.saas-os-ui pre,.saas-os-ui samp{font-feature-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em;font-variation-settings:normal}.saas-os-ui small{font-size:80%}.saas-os-ui sub,.saas-os-ui sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}.saas-os-ui sub{bottom:-.25em}.saas-os-ui sup{top:-.5em}.saas-os-ui table{border-collapse:collapse;border-color:inherit;text-indent:0}.saas-os-ui button,.saas-os-ui input,.saas-os-ui optgroup,.saas-os-ui select,.saas-os-ui textarea{font-feature-settings:inherit;color:inherit;font-family:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;margin:0;padding:0}.saas-os-ui button,.saas-os-ui select{text-transform:none}.saas-os-ui button,.saas-os-ui input:where([type=button]),.saas-os-ui input:where([type=reset]),.saas-os-ui input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}.saas-os-ui :-moz-focusring{outline:auto}.saas-os-ui :-moz-ui-invalid{box-shadow:none}.saas-os-ui progress{vertical-align:baseline}.saas-os-ui ::-webkit-inner-spin-button,.saas-os-ui ::-webkit-outer-spin-button{height:auto}.saas-os-ui [type=search]{-webkit-appearance:textfield;outline-offset:-2px}.saas-os-ui ::-webkit-search-decoration{-webkit-appearance:none}.saas-os-ui ::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}.saas-os-ui summary{display:list-item}.saas-os-ui blockquote,.saas-os-ui dd,.saas-os-ui dl,.saas-os-ui figure,.saas-os-ui h1,.saas-os-ui h2,.saas-os-ui h3,.saas-os-ui h4,.saas-os-ui h5,.saas-os-ui h6,.saas-os-ui hr,.saas-os-ui p,.saas-os-ui pre{margin:0}.saas-os-ui fieldset{margin:0;padding:0}.saas-os-ui legend{padding:0}.saas-os-ui menu,.saas-os-ui ol,.saas-os-ui ul{list-style:none;margin:0;padding:0}.saas-os-ui dialog{padding:0}.saas-os-ui textarea{resize:vertical}.saas-os-ui input::-moz-placeholder,.saas-os-ui textarea::-moz-placeholder{color:#9ca3af;opacity:1}.saas-os-ui input::placeholder,.saas-os-ui textarea::placeholder{color:#9ca3af;opacity:1}.saas-os-ui [role=button],.saas-os-ui button{cursor:pointer}.saas-os-ui :disabled{cursor:default}.saas-os-ui audio,.saas-os-ui canvas,.saas-os-ui embed,.saas-os-ui iframe,.saas-os-ui img,.saas-os-ui object,.saas-os-ui svg,.saas-os-ui video{display:block;vertical-align:middle}.saas-os-ui img,.saas-os-ui video{height:auto;max-width:100%}.saas-os-ui [hidden]:where(:not([hidden=until-found])){display:none}.saas-os-ui{--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%;--secondary-foreground:222.2 84% 4.9%;--muted:210 40% 96%;--muted-foreground:215.4 16.3% 46.9%;--accent:210 40% 96%;--accent-foreground:222.2 84% 4.9%;--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:0.5rem}.saas-os-ui .dark{--background:222.2 84% 4.9%;--foreground:210 40% 98%;--card:222.2 84% 4.9%;--card-foreground:210 40% 98%;--popover:222.2 84% 4.9%;--popover-foreground:210 40% 98%;--primary:210 40% 98%;--primary-foreground:222.2 47.4% 11.2%;--secondary:217.2 32.6% 17.5%;--secondary-foreground:210 40% 98%;--muted:217.2 32.6% 17.5%;--muted-foreground:215 20.2% 65.1%;--accent:217.2 32.6% 17.5%;--accent-foreground:210 40% 98%;--destructive:0 62.8% 30.6%;--destructive-foreground:210 40% 98%;--border:217.2 32.6% 17.5%;--input:217.2 32.6% 17.5%;--ring:212.7 26.8% 83.9%}.saas-os-ui *{border-color:hsl(var(--border))}.saas-os-ui{background-color:hsl(var(--background));color:hsl(var(--foreground))}.saas-os-ui .container{width:100%}@media (min-width:640px){.saas-os-ui .container{max-width:640px}}@media (min-width:768px){.saas-os-ui .container{max-width:768px}}@media (min-width:1024px){.saas-os-ui .container{max-width:1024px}}@media (min-width:1280px){.saas-os-ui .container{max-width:1280px}}@media (min-width:1536px){.saas-os-ui .container{max-width:1536px}}.saas-os-ui .sr-only{clip:rect(0,0,0,0);border-width:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.saas-os-ui .pointer-events-none{pointer-events:none}.saas-os-ui .visible{visibility:visible}.saas-os-ui .static{position:static}.saas-os-ui .fixed{position:fixed}.saas-os-ui .absolute{position:absolute}.saas-os-ui .relative{position:relative}.saas-os-ui .sticky{position:sticky}.saas-os-ui .inset-0{inset:0}.saas-os-ui .end-2{inset-inline-end:.5rem}.saas-os-ui .end-8{inset-inline-end:2rem}.saas-os-ui .left-\[50\%\]{left:50%}.saas-os-ui .right-4{right:1rem}.saas-os-ui .start-0{inset-inline-start:0}.saas-os-ui .start-3{inset-inline-start:.75rem}.saas-os-ui .top-0{top:0}.saas-os-ui .top-1\/2{top:50%}.saas-os-ui .top-4{top:1rem}.saas-os-ui .top-\[50\%\]{top:50%}.saas-os-ui .z-10{z-index:10}.saas-os-ui .z-20{z-index:20}.saas-os-ui .z-30{z-index:30}.saas-os-ui .z-50{z-index:50}.saas-os-ui .m-0{margin:0}.saas-os-ui .-mx-1{margin-left:-.25rem;margin-right:-.25rem}.saas-os-ui .mx-auto{margin-left:auto;margin-right:auto}.saas-os-ui .my-1{margin-bottom:.25rem;margin-top:.25rem}.saas-os-ui .my-2{margin-bottom:.5rem;margin-top:.5rem}.saas-os-ui .my-2\.5{margin-bottom:.625rem;margin-top:.625rem}.saas-os-ui .my-4{margin-bottom:1rem;margin-top:1rem}.saas-os-ui .-mb-px{margin-bottom:-1px}.saas-os-ui .mb-0\.5{margin-bottom:.125rem}.saas-os-ui .mb-1{margin-bottom:.25rem}.saas-os-ui .mb-1\.5{margin-bottom:.375rem}.saas-os-ui .mb-2{margin-bottom:.5rem}.saas-os-ui .mb-2\.5{margin-bottom:.625rem}.saas-os-ui .mb-3{margin-bottom:.75rem}.saas-os-ui .mb-4{margin-bottom:1rem}.saas-os-ui .me-1\.5{margin-inline-end:.375rem}.saas-os-ui .me-2{margin-inline-end:.5rem}.saas-os-ui .ml-1{margin-left:.25rem}.saas-os-ui .ms-1{margin-inline-start:.25rem}.saas-os-ui .ms-1\.5{margin-inline-start:.375rem}.saas-os-ui .ms-2{margin-inline-start:.5rem}.saas-os-ui .ms-auto{margin-inline-start:auto}.saas-os-ui .mt-0\.5{margin-top:.125rem}.saas-os-ui .mt-1{margin-top:.25rem}.saas-os-ui .mt-1\.5{margin-top:.375rem}.saas-os-ui .mt-2{margin-top:.5rem}.saas-os-ui .mt-3{margin-top:.75rem}.saas-os-ui .mt-4{margin-top:1rem}.saas-os-ui .mt-6{margin-top:1.5rem}.saas-os-ui .mt-auto{margin-top:auto}.saas-os-ui .line-clamp-1{-webkit-line-clamp:1}.saas-os-ui .line-clamp-1,.saas-os-ui .line-clamp-2{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.saas-os-ui .line-clamp-2{-webkit-line-clamp:2}.saas-os-ui .block{display:block}.saas-os-ui .inline{display:inline}.saas-os-ui .flex{display:flex}.saas-os-ui .inline-flex{display:inline-flex}.saas-os-ui .table{display:table}.saas-os-ui .grid{display:grid}.saas-os-ui .hidden{display:none}.saas-os-ui .aspect-square{aspect-ratio:1/1}.saas-os-ui .h-1\.5{height:.375rem}.saas-os-ui .h-10{height:2.5rem}.saas-os-ui .h-12{height:3rem}.saas-os-ui .h-16{height:4rem}.saas-os-ui .h-2{height:.5rem}.saas-os-ui .h-2\.5{height:.625rem}.saas-os-ui .h-24{height:6rem}.saas-os-ui .h-3{height:.75rem}.saas-os-ui .h-3\.5{height:.875rem}.saas-os-ui .h-32{height:8rem}.saas-os-ui .h-4{height:1rem}.saas-os-ui .h-48{height:12rem}.saas-os-ui .h-5{height:1.25rem}.saas-os-ui .h-6{height:1.5rem}.saas-os-ui .h-64{height:16rem}.saas-os-ui .h-8{height:2rem}.saas-os-ui .h-9{height:2.25rem}.saas-os-ui .h-\[1px\]{height:1px}.saas-os-ui .h-\[20px\]{height:20px}.saas-os-ui .h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.saas-os-ui .h-full{height:100%}.saas-os-ui .h-px{height:1px}.saas-os-ui .h-screen{height:100vh}.saas-os-ui .max-h-24{max-height:6rem}.saas-os-ui .max-h-\[300px\]{max-height:300px}.saas-os-ui .min-h-0{min-height:0}.saas-os-ui .min-h-\[3rem\]{min-height:3rem}.saas-os-ui .min-h-full{min-height:100%}.saas-os-ui .w-10{width:2.5rem}.saas-os-ui .w-12{width:3rem}.saas-os-ui .w-16{width:4rem}.saas-os-ui .w-2\.5{width:.625rem}.saas-os-ui .w-24{width:6rem}.saas-os-ui .w-3{width:.75rem}.saas-os-ui .w-3\.5{width:.875rem}.saas-os-ui .w-32{width:8rem}.saas-os-ui .w-4{width:1rem}.saas-os-ui .w-44{width:11rem}.saas-os-ui .w-48{width:12rem}.saas-os-ui .w-5{width:1.25rem}.saas-os-ui .w-6{width:1.5rem}.saas-os-ui .w-72{width:18rem}.saas-os-ui .w-8{width:2rem}.saas-os-ui .w-9{width:2.25rem}.saas-os-ui .w-\[1px\]{width:1px}.saas-os-ui .w-\[36px\]{width:36px}.saas-os-ui .w-full{width:100%}.saas-os-ui .w-screen{width:100vw}.saas-os-ui .min-w-0{min-width:0}.saas-os-ui .min-w-\[160px\]{min-width:160px}.saas-os-ui .min-w-\[80px\]{min-width:80px}.saas-os-ui .min-w-\[8rem\]{min-width:8rem}.saas-os-ui .min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.saas-os-ui .min-w-full{min-width:100%}.saas-os-ui .max-w-2xl{max-width:42rem}.saas-os-ui .max-w-fit{max-width:-moz-fit-content;max-width:fit-content}.saas-os-ui .max-w-full{max-width:100%}.saas-os-ui .max-w-lg{max-width:32rem}.saas-os-ui .max-w-none{max-width:none}.saas-os-ui .max-w-xl{max-width:36rem}.saas-os-ui .flex-1{flex:1 1 0%}.saas-os-ui .flex-shrink-0,.saas-os-ui .shrink-0{flex-shrink:0}.saas-os-ui .border-separate{border-collapse:separate}.saas-os-ui .border-spacing-0{--tw-border-spacing-x:0px;--tw-border-spacing-y:0px;border-spacing:var(--tw-border-spacing-x) var(--tw-border-spacing-y)}.saas-os-ui .-translate-y-1\/2{--tw-translate-y:-50%}.saas-os-ui .-translate-y-1\/2,.saas-os-ui .translate-x-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.saas-os-ui .translate-x-0{--tw-translate-x:0px}.saas-os-ui .translate-x-\[-50\%\]{--tw-translate-x:-50%}.saas-os-ui .translate-x-\[-50\%\],.saas-os-ui .translate-y-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.saas-os-ui .translate-y-0{--tw-translate-y:0px}.saas-os-ui .translate-y-\[-50\%\]{--tw-translate-y:-50%}.saas-os-ui .transform,.saas-os-ui .translate-y-\[-50\%\]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.saas-os-ui .animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(1turn)}}.saas-os-ui .animate-spin{animation:spin 1s linear infinite}.saas-os-ui .cursor-default{cursor:default}.saas-os-ui .cursor-pointer{cursor:pointer}.saas-os-ui .touch-none{touch-action:none}.saas-os-ui .select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.saas-os-ui .list-inside{list-style-position:inside}.saas-os-ui .list-decimal{list-style-type:decimal}.saas-os-ui .grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.saas-os-ui .grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.saas-os-ui .grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}.saas-os-ui .flex-col{flex-direction:column}.saas-os-ui .flex-col-reverse{flex-direction:column-reverse}.saas-os-ui .flex-wrap{flex-wrap:wrap}.saas-os-ui .items-start{align-items:flex-start}.saas-os-ui .items-center{align-items:center}.saas-os-ui .items-baseline{align-items:baseline}.saas-os-ui .justify-end{justify-content:flex-end}.saas-os-ui .justify-center{justify-content:center}.saas-os-ui .justify-between{justify-content:space-between}.saas-os-ui .gap-0\.5{gap:.125rem}.saas-os-ui .gap-1{gap:.25rem}.saas-os-ui .gap-1\.5{gap:.375rem}.saas-os-ui .gap-2{gap:.5rem}.saas-os-ui .gap-3{gap:.75rem}.saas-os-ui .gap-4{gap:1rem}.saas-os-ui .gap-6{gap:1.5rem}.saas-os-ui .gap-x-0{-moz-column-gap:0;column-gap:0}.saas-os-ui .gap-x-0\.5{-moz-column-gap:.125rem;column-gap:.125rem}.saas-os-ui .gap-x-1{-moz-column-gap:.25rem;column-gap:.25rem}.saas-os-ui .gap-x-1\.5{-moz-column-gap:.375rem;column-gap:.375rem}.saas-os-ui .gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.saas-os-ui .gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.saas-os-ui .gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.saas-os-ui .gap-y-0\.5{row-gap:.125rem}.saas-os-ui .gap-y-1{row-gap:.25rem}.saas-os-ui .gap-y-2{row-gap:.5rem}.saas-os-ui .gap-y-2\.5{row-gap:.625rem}.saas-os-ui .gap-y-3\.5{row-gap:.875rem}.saas-os-ui .space-x-0>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(0px*(1 - var(--tw-space-x-reverse)));margin-right:calc(0px*var(--tw-space-x-reverse))}.saas-os-ui .space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.saas-os-ui .space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.375rem*var(--tw-space-y-reverse));margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.75rem*var(--tw-space-y-reverse));margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .space-y-3\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.875rem*var(--tw-space-y-reverse));margin-top:calc(.875rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.25rem*var(--tw-space-y-reverse));margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.5rem*var(--tw-space-y-reverse));margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-bottom-width:calc(1px*var(--tw-divide-y-reverse));border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)))}.saas-os-ui .divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(243 244 246/var(--tw-divide-opacity,1))}.saas-os-ui .overflow-auto{overflow:auto}.saas-os-ui .overflow-hidden{overflow:hidden}.saas-os-ui .overflow-x-auto{overflow-x:auto}.saas-os-ui .overflow-y-auto{overflow-y:auto}.saas-os-ui .overflow-x-hidden{overflow-x:hidden}.saas-os-ui .truncate{overflow:hidden;white-space:nowrap}.saas-os-ui .text-ellipsis,.saas-os-ui .truncate{text-overflow:ellipsis}.saas-os-ui .whitespace-nowrap{white-space:nowrap}.saas-os-ui .rounded{border-radius:.25rem}.saas-os-ui .rounded-\[inherit\]{border-radius:inherit}.saas-os-ui .rounded-full{border-radius:9999px}.saas-os-ui .rounded-lg{border-radius:var(--radius)}.saas-os-ui .rounded-md{border-radius:calc(var(--radius) - 2px)}.saas-os-ui .rounded-none{border-radius:0}.saas-os-ui .rounded-sm{border-radius:calc(var(--radius) - 4px)}.saas-os-ui .rounded-xl{border-radius:.75rem}.saas-os-ui .border{border-width:1px}.saas-os-ui .border-2{border-width:2px}.saas-os-ui .border-b{border-bottom-width:1px}.saas-os-ui .border-b-2{border-bottom-width:2px}.saas-os-ui .border-l{border-left-width:1px}.saas-os-ui .border-t{border-top-width:1px}.saas-os-ui .border-dashed{border-style:dashed}.saas-os-ui .border-amber-200{--tw-border-opacity:1;border-color:rgb(253 230 138/var(--tw-border-opacity,1))}.saas-os-ui .border-amber-300{--tw-border-opacity:1;border-color:rgb(252 211 77/var(--tw-border-opacity,1))}.saas-os-ui .border-blue-200{--tw-border-opacity:1;border-color:rgb(191 219 254/var(--tw-border-opacity,1))}.saas-os-ui .border-blue-300{--tw-border-opacity:1;border-color:rgb(147 197 253/var(--tw-border-opacity,1))}.saas-os-ui .border-blue-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.saas-os-ui .border-border{border-color:hsl(var(--border))}.saas-os-ui .border-destructive\/50{border-color:hsl(var(--destructive)/.5)}.saas-os-ui .border-emerald-200{--tw-border-opacity:1;border-color:rgb(167 243 208/var(--tw-border-opacity,1))}.saas-os-ui .border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity,1))}.saas-os-ui .border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1))}.saas-os-ui .border-gray-50{--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity,1))}.saas-os-ui .border-green-200{--tw-border-opacity:1;border-color:rgb(187 247 208/var(--tw-border-opacity,1))}.saas-os-ui .border-green-300{--tw-border-opacity:1;border-color:rgb(134 239 172/var(--tw-border-opacity,1))}.saas-os-ui .border-input{border-color:hsl(var(--input))}.saas-os-ui .border-primary{border-color:hsl(var(--primary))}.saas-os-ui .border-purple-200{--tw-border-opacity:1;border-color:rgb(233 213 255/var(--tw-border-opacity,1))}.saas-os-ui .border-red-100{--tw-border-opacity:1;border-color:rgb(254 226 226/var(--tw-border-opacity,1))}.saas-os-ui .border-red-200{--tw-border-opacity:1;border-color:rgb(254 202 202/var(--tw-border-opacity,1))}.saas-os-ui .border-red-300{--tw-border-opacity:1;border-color:rgb(252 165 165/var(--tw-border-opacity,1))}.saas-os-ui .border-slate-100{--tw-border-opacity:1;border-color:rgb(241 245 249/var(--tw-border-opacity,1))}.saas-os-ui .border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity,1))}.saas-os-ui .border-transparent{border-color:transparent}.saas-os-ui .border-l-transparent{border-left-color:transparent}.saas-os-ui .border-t-transparent{border-top-color:transparent}.saas-os-ui .bg-amber-100{--tw-bg-opacity:1;background-color:rgb(254 243 199/var(--tw-bg-opacity,1))}.saas-os-ui .bg-amber-50{--tw-bg-opacity:1;background-color:rgb(255 251 235/var(--tw-bg-opacity,1))}.saas-os-ui .bg-amber-50\/50{background-color:rgba(255,251,235,.5)}.saas-os-ui .bg-amber-500{--tw-bg-opacity:1;background-color:rgb(245 158 11/var(--tw-bg-opacity,1))}.saas-os-ui .bg-background{background-color:hsl(var(--background))}.saas-os-ui .bg-background\/80{background-color:hsl(var(--background)/.8)}.saas-os-ui .bg-blue-100{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity,1))}.saas-os-ui .bg-blue-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.saas-os-ui .bg-blue-50\/30{background-color:rgba(239,246,255,.3)}.saas-os-ui .bg-blue-50\/50{background-color:rgba(239,246,255,.5)}.saas-os-ui .bg-blue-50\/80{background-color:rgba(239,246,255,.8)}.saas-os-ui .bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.saas-os-ui .bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.saas-os-ui .bg-border{background-color:hsl(var(--border))}.saas-os-ui .bg-destructive{background-color:hsl(var(--destructive))}.saas-os-ui .bg-destructive\/10{background-color:hsl(var(--destructive)/.1)}.saas-os-ui .bg-emerald-100{--tw-bg-opacity:1;background-color:rgb(209 250 229/var(--tw-bg-opacity,1))}.saas-os-ui .bg-emerald-50{--tw-bg-opacity:1;background-color:rgb(236 253 245/var(--tw-bg-opacity,1))}.saas-os-ui .bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.saas-os-ui .bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.saas-os-ui .bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity,1))}.saas-os-ui .bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.saas-os-ui .bg-gray-50\/50{background-color:rgba(249,250,251,.5)}.saas-os-ui .bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.saas-os-ui .bg-green-100{--tw-bg-opacity:1;background-color:rgb(220 252 231/var(--tw-bg-opacity,1))}.saas-os-ui .bg-green-50{--tw-bg-opacity:1;background-color:rgb(240 253 244/var(--tw-bg-opacity,1))}.saas-os-ui .bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.saas-os-ui .bg-green-600{--tw-bg-opacity:1;background-color:rgb(22 163 74/var(--tw-bg-opacity,1))}.saas-os-ui .bg-muted{background-color:hsl(var(--muted))}.saas-os-ui .bg-popover{background-color:hsl(var(--popover))}.saas-os-ui .bg-primary{background-color:hsl(var(--primary))}.saas-os-ui .bg-primary\/10{background-color:hsl(var(--primary)/.1)}.saas-os-ui .bg-primary\/5{background-color:hsl(var(--primary)/.05)}.saas-os-ui .bg-purple-100{--tw-bg-opacity:1;background-color:rgb(243 232 255/var(--tw-bg-opacity,1))}.saas-os-ui .bg-purple-50{--tw-bg-opacity:1;background-color:rgb(250 245 255/var(--tw-bg-opacity,1))}.saas-os-ui .bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity,1))}.saas-os-ui .bg-red-50{--tw-bg-opacity:1;background-color:rgb(254 242 242/var(--tw-bg-opacity,1))}.saas-os-ui .bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.saas-os-ui .bg-red-600{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.saas-os-ui .bg-secondary{background-color:hsl(var(--secondary))}.saas-os-ui .bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.saas-os-ui .bg-transparent{background-color:transparent}.saas-os-ui .bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.saas-os-ui .bg-yellow-100{--tw-bg-opacity:1;background-color:rgb(254 249 195/var(--tw-bg-opacity,1))}.saas-os-ui .bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity,1))}.saas-os-ui .fill-primary{fill:hsl(var(--primary))}.saas-os-ui .object-contain{-o-object-fit:contain;object-fit:contain}.saas-os-ui .object-cover{-o-object-fit:cover;object-fit:cover}.saas-os-ui .p-0{padding:0}.saas-os-ui .p-1{padding:.25rem}.saas-os-ui .p-2{padding:.5rem}.saas-os-ui .p-3{padding:.75rem}.saas-os-ui .p-4{padding:1rem}.saas-os-ui .p-5{padding:1.25rem}.saas-os-ui .p-6{padding:1.5rem}.saas-os-ui .p-8{padding:2rem}.saas-os-ui .p-\[1px\]{padding:1px}.saas-os-ui .px-0\.5{padding-left:.125rem;padding-right:.125rem}.saas-os-ui .px-1{padding-left:.25rem;padding-right:.25rem}.saas-os-ui .px-1\.5{padding-left:.375rem;padding-right:.375rem}.saas-os-ui .px-2{padding-left:.5rem;padding-right:.5rem}.saas-os-ui .px-2\.5{padding-left:.625rem;padding-right:.625rem}.saas-os-ui .px-3{padding-left:.75rem;padding-right:.75rem}.saas-os-ui .px-4{padding-left:1rem;padding-right:1rem}.saas-os-ui .px-5{padding-left:1.25rem;padding-right:1.25rem}.saas-os-ui .px-6{padding-left:1.5rem;padding-right:1.5rem}.saas-os-ui .py-0\.5{padding-bottom:.125rem;padding-top:.125rem}.saas-os-ui .py-1{padding-bottom:.25rem;padding-top:.25rem}.saas-os-ui .py-1\.5{padding-bottom:.375rem;padding-top:.375rem}.saas-os-ui .py-12{padding-bottom:3rem;padding-top:3rem}.saas-os-ui .py-16{padding-bottom:4rem;padding-top:4rem}.saas-os-ui .py-2{padding-bottom:.5rem;padding-top:.5rem}.saas-os-ui .py-2\.5{padding-bottom:.625rem;padding-top:.625rem}.saas-os-ui .py-3{padding-bottom:.75rem;padding-top:.75rem}.saas-os-ui .py-4{padding-bottom:1rem;padding-top:1rem}.saas-os-ui .py-6{padding-bottom:1.5rem;padding-top:1.5rem}.saas-os-ui .py-8{padding-bottom:2rem;padding-top:2rem}.saas-os-ui .pe-4{padding-inline-end:1rem}.saas-os-ui .pe-8{padding-inline-end:2rem}.saas-os-ui .ps-10{padding-inline-start:2.5rem}.saas-os-ui .ps-2{padding-inline-start:.5rem}.saas-os-ui .pt-1{padding-top:.25rem}.saas-os-ui .pt-2{padding-top:.5rem}.saas-os-ui .pt-3{padding-top:.75rem}.saas-os-ui .pt-4{padding-top:1rem}.saas-os-ui .text-center{text-align:center}.saas-os-ui .text-start{text-align:start}.saas-os-ui .text-end{text-align:end}.saas-os-ui .align-top{vertical-align:top}.saas-os-ui .align-middle{vertical-align:middle}.saas-os-ui .font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.saas-os-ui .text-2xl{font-size:1.5rem;line-height:2rem}.saas-os-ui .text-3xl{font-size:1.875rem;line-height:2.25rem}.saas-os-ui .text-4xl{font-size:2.25rem;line-height:2.5rem}.saas-os-ui .text-\[10px\]{font-size:10px}.saas-os-ui .text-\[11px\]{font-size:11px}.saas-os-ui .text-base{font-size:1rem;line-height:1.5rem}.saas-os-ui .text-lg{font-size:1.125rem;line-height:1.75rem}.saas-os-ui .text-sm{font-size:.875rem;line-height:1.25rem}.saas-os-ui .text-xl{font-size:1.25rem;line-height:1.75rem}.saas-os-ui .text-xs{font-size:.75rem;line-height:1rem}.saas-os-ui .font-bold{font-weight:700}.saas-os-ui .font-medium{font-weight:500}.saas-os-ui .font-semibold{font-weight:600}.saas-os-ui .uppercase{text-transform:uppercase}.saas-os-ui .lowercase{text-transform:lowercase}.saas-os-ui .capitalize{text-transform:capitalize}.saas-os-ui .leading-none{line-height:1}.saas-os-ui .leading-relaxed{line-height:1.625}.saas-os-ui .leading-tight{line-height:1.25}.saas-os-ui .tracking-tight{letter-spacing:-.025em}.saas-os-ui .tracking-wide{letter-spacing:.025em}.saas-os-ui .tracking-wider{letter-spacing:.05em}.saas-os-ui .tracking-widest{letter-spacing:.1em}.saas-os-ui .text-amber-600{--tw-text-opacity:1;color:rgb(217 119 6/var(--tw-text-opacity,1))}.saas-os-ui .text-amber-700{--tw-text-opacity:1;color:rgb(180 83 9/var(--tw-text-opacity,1))}.saas-os-ui .text-amber-800{--tw-text-opacity:1;color:rgb(146 64 14/var(--tw-text-opacity,1))}.saas-os-ui .text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.saas-os-ui .text-blue-700{--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity,1))}.saas-os-ui .text-blue-800{--tw-text-opacity:1;color:rgb(30 64 175/var(--tw-text-opacity,1))}.saas-os-ui .text-destructive{color:hsl(var(--destructive))}.saas-os-ui .text-destructive-foreground{color:hsl(var(--destructive-foreground))}.saas-os-ui .text-emerald-500{--tw-text-opacity:1;color:rgb(16 185 129/var(--tw-text-opacity,1))}.saas-os-ui .text-emerald-600{--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1))}.saas-os-ui .text-emerald-700{--tw-text-opacity:1;color:rgb(4 120 87/var(--tw-text-opacity,1))}.saas-os-ui .text-foreground{color:hsl(var(--foreground))}.saas-os-ui .text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.saas-os-ui .text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.saas-os-ui .text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.saas-os-ui .text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity,1))}.saas-os-ui .text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.saas-os-ui .text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity,1))}.saas-os-ui .text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.saas-os-ui .text-green-400{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.saas-os-ui .text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.saas-os-ui .text-green-600{--tw-text-opacity:1;color:rgb(22 163 74/var(--tw-text-opacity,1))}.saas-os-ui .text-green-700{--tw-text-opacity:1;color:rgb(21 128 61/var(--tw-text-opacity,1))}.saas-os-ui .text-green-800{--tw-text-opacity:1;color:rgb(22 101 52/var(--tw-text-opacity,1))}.saas-os-ui .text-muted-foreground{color:hsl(var(--muted-foreground))}.saas-os-ui .text-popover-foreground{color:hsl(var(--popover-foreground))}.saas-os-ui .text-primary{color:hsl(var(--primary))}.saas-os-ui .text-primary-foreground{color:hsl(var(--primary-foreground))}.saas-os-ui .text-purple-600{--tw-text-opacity:1;color:rgb(147 51 234/var(--tw-text-opacity,1))}.saas-os-ui .text-purple-700{--tw-text-opacity:1;color:rgb(126 34 206/var(--tw-text-opacity,1))}.saas-os-ui .text-purple-800{--tw-text-opacity:1;color:rgb(107 33 168/var(--tw-text-opacity,1))}.saas-os-ui .text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.saas-os-ui .text-red-600{--tw-text-opacity:1;color:rgb(220 38 38/var(--tw-text-opacity,1))}.saas-os-ui .text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity,1))}.saas-os-ui .text-red-800{--tw-text-opacity:1;color:rgb(153 27 27/var(--tw-text-opacity,1))}.saas-os-ui .text-secondary-foreground{color:hsl(var(--secondary-foreground))}.saas-os-ui .text-slate-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.saas-os-ui .text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.saas-os-ui .text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.saas-os-ui .text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.saas-os-ui .text-slate-700{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity,1))}.saas-os-ui .text-slate-900{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.saas-os-ui .text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.saas-os-ui .text-yellow-800{--tw-text-opacity:1;color:rgb(133 77 14/var(--tw-text-opacity,1))}.saas-os-ui .underline-offset-4{text-underline-offset:4px}.saas-os-ui .opacity-0{opacity:0}.saas-os-ui .opacity-100{opacity:1}.saas-os-ui .opacity-50{opacity:.5}.saas-os-ui .opacity-70{opacity:.7}.saas-os-ui .shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.saas-os-ui .shadow,.saas-os-ui .shadow-\[0_2px_4px_-2px_rgba\(0\2c 0\2c 0\2c 0\.06\)\]{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.saas-os-ui .shadow-\[0_2px_4px_-2px_rgba\(0\2c 0\2c 0\2c 0\.06\)\]{--tw-shadow:0 2px 4px -2px rgba(0,0,0,.06);--tw-shadow-colored:0 2px 4px -2px var(--tw-shadow-color)}.saas-os-ui .shadow-\[2px_0_4px_-2px_rgba\(0\2c 0\2c 0\2c 0\.06\)\]{--tw-shadow:2px 0 4px -2px rgba(0,0,0,.06);--tw-shadow-colored:2px 0 4px -2px var(--tw-shadow-color)}.saas-os-ui .shadow-\[2px_0_4px_-2px_rgba\(0\2c 0\2c 0\2c 0\.06\)\],.saas-os-ui .shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.saas-os-ui .shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.saas-os-ui .shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.saas-os-ui .shadow-md,.saas-os-ui .shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.saas-os-ui .shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.saas-os-ui .outline-none{outline:2px solid transparent;outline-offset:2px}.saas-os-ui .outline{outline-style:solid}.saas-os-ui .ring-0{--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(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)}.saas-os-ui .ring-offset-background{--tw-ring-offset-color:hsl(var(--background))}.saas-os-ui .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)}.saas-os-ui .backdrop-blur-sm{--tw-backdrop-blur:blur(4px);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)}.saas-os-ui .transition-all{transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.saas-os-ui .transition-colors{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.saas-os-ui .transition-opacity{transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.saas-os-ui .transition-shadow{transition-duration:.15s;transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1)}.saas-os-ui .transition-transform{transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.saas-os-ui .duration-200{transition-duration:.2s}.saas-os-ui .duration-500{transition-duration:.5s}.saas-os-ui .file\:border-0::file-selector-button{border-width:0}.saas-os-ui .file\:bg-transparent::file-selector-button{background-color:transparent}.saas-os-ui .file\:text-sm::file-selector-button{font-size:.875rem;line-height:1.25rem}.saas-os-ui .file\:font-medium::file-selector-button{font-weight:500}.saas-os-ui .placeholder\:text-muted-foreground::-moz-placeholder{color:hsl(var(--muted-foreground))}.saas-os-ui .placeholder\:text-muted-foreground::placeholder{color:hsl(var(--muted-foreground))}.saas-os-ui .hover\:border-gray-300:hover{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity,1))}.saas-os-ui .hover\:bg-accent:hover{background-color:hsl(var(--accent))}.saas-os-ui .hover\:bg-amber-100:hover{--tw-bg-opacity:1;background-color:rgb(254 243 199/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-blue-100:hover{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-blue-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-destructive\/90:hover{background-color:hsl(var(--destructive)/.9)}.saas-os-ui .hover\:bg-gray-200:hover{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-gray-50\/50:hover{background-color:rgba(249,250,251,.5)}.saas-os-ui .hover\:bg-gray-700:hover{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-green-100:hover{--tw-bg-opacity:1;background-color:rgb(220 252 231/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-green-700:hover{--tw-bg-opacity:1;background-color:rgb(21 128 61/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-muted:hover{background-color:hsl(var(--muted))}.saas-os-ui .hover\:bg-primary\/90:hover{background-color:hsl(var(--primary)/.9)}.saas-os-ui .hover\:bg-red-100:hover{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-red-50:hover{--tw-bg-opacity:1;background-color:rgb(254 242 242/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-red-700:hover{--tw-bg-opacity:1;background-color:rgb(185 28 28/var(--tw-bg-opacity,1))}.saas-os-ui .hover\:bg-secondary\/80:hover{background-color:hsl(var(--secondary)/.8)}.saas-os-ui .hover\:bg-slate-50\/50:hover{background-color:rgba(248,250,252,.5)}.saas-os-ui .hover\:text-accent-foreground:hover{color:hsl(var(--accent-foreground))}.saas-os-ui .hover\:text-blue-700:hover{--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity,1))}.saas-os-ui .hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.saas-os-ui .hover\:text-red-700:hover{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity,1))}.saas-os-ui .hover\:text-slate-900:hover{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.saas-os-ui .hover\:underline:hover{text-decoration-line:underline}.saas-os-ui .hover\:opacity-100:hover{opacity:1}.saas-os-ui .hover\:shadow-sm:hover{--tw-shadow:0 1px 2px 0 rgba(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)}.saas-os-ui .focus\:bg-accent:focus{background-color:hsl(var(--accent))}.saas-os-ui .focus\:text-accent-foreground:focus{color:hsl(var(--accent-foreground))}.saas-os-ui .focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.saas-os-ui .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)}.saas-os-ui .focus\:ring-1:focus,.saas-os-ui .focus\:ring-2:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.saas-os-ui .focus\:ring-2: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(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.saas-os-ui .focus\:ring-primary:focus{--tw-ring-color:hsl(var(--primary))}.saas-os-ui .focus\:ring-red-600:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(220 38 38/var(--tw-ring-opacity,1))}.saas-os-ui .focus\:ring-ring:focus{--tw-ring-color:hsl(var(--ring))}.saas-os-ui .focus\:ring-offset-2:focus{--tw-ring-offset-width:2px}.saas-os-ui .focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.saas-os-ui .focus-visible\:ring-1:focus-visible{--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)}.saas-os-ui .focus-visible\:ring-2:focus-visible{--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(2px + 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)}.saas-os-ui .focus-visible\:ring-ring:focus-visible{--tw-ring-color:hsl(var(--ring))}.saas-os-ui .focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px}.saas-os-ui .focus-visible\:ring-offset-background:focus-visible{--tw-ring-offset-color:hsl(var(--background))}.saas-os-ui .disabled\:pointer-events-none:disabled{pointer-events:none}.saas-os-ui .disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.saas-os-ui .disabled\:opacity-50:disabled{opacity:.5}.saas-os-ui .group:hover .group-hover\:bg-slate-50\/80{background-color:rgba(248,250,252,.8)}.saas-os-ui .peer:disabled~.peer-disabled\:cursor-not-allowed{cursor:not-allowed}.saas-os-ui .peer:disabled~.peer-disabled\:opacity-70{opacity:.7}.saas-os-ui .aria-selected\:bg-accent[aria-selected=true]{background-color:hsl(var(--accent))}.saas-os-ui .aria-selected\:text-accent-foreground[aria-selected=true]{color:hsl(var(--accent-foreground))}.saas-os-ui .data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.saas-os-ui .data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y:0.25rem}.saas-os-ui .data-\[side\=bottom\]\:translate-y-1[data-side=bottom],.saas-os-ui .data-\[side\=left\]\:-translate-x-1[data-side=left]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.saas-os-ui .data-\[side\=left\]\:-translate-x-1[data-side=left]{--tw-translate-x:-0.25rem}.saas-os-ui .data-\[side\=right\]\:translate-x-1[data-side=right]{--tw-translate-x:0.25rem}.saas-os-ui .data-\[side\=right\]\:translate-x-1[data-side=right],.saas-os-ui .data-\[side\=top\]\:-translate-y-1[data-side=top]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.saas-os-ui .data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y:-0.25rem}.saas-os-ui .data-\[state\=checked\]\:translate-x-4[data-state=checked]{--tw-translate-x:1rem}.saas-os-ui .data-\[state\=checked\]\:translate-x-4[data-state=checked],.saas-os-ui .data-\[state\=unchecked\]\:translate-x-0[data-state=unchecked]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.saas-os-ui .data-\[state\=unchecked\]\:translate-x-0[data-state=unchecked]{--tw-translate-x:0px}.saas-os-ui .data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:hsl(var(--primary))}.saas-os-ui .data-\[state\=open\]\:bg-accent[data-state=open]{background-color:hsl(var(--accent))}.saas-os-ui .data-\[state\=unchecked\]\:bg-input[data-state=unchecked]{background-color:hsl(var(--input))}.saas-os-ui .data-\[state\=open\]\:text-muted-foreground[data-state=open]{color:hsl(var(--muted-foreground))}.saas-os-ui .data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}@media (min-width:640px){.saas-os-ui .sm\:mt-0{margin-top:0}.saas-os-ui .sm\:block{display:block}.saas-os-ui .sm\:inline{display:inline}.saas-os-ui .sm\:max-h-\[500px\]{max-height:500px}.saas-os-ui .sm\:min-h-\[600px\]{min-height:600px}.saas-os-ui .sm\:w-56{width:14rem}.saas-os-ui .sm\:w-auto{width:auto}.saas-os-ui .sm\:min-w-\[600px\]{min-width:600px}.saas-os-ui .sm\:min-w-\[800px\]{min-width:800px}.saas-os-ui .sm\:flex-initial{flex:0 1 auto}.saas-os-ui .sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.saas-os-ui .sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.saas-os-ui .sm\:flex-row{flex-direction:row}.saas-os-ui .sm\:flex-col{flex-direction:column}.saas-os-ui .sm\:items-start{align-items:flex-start}.saas-os-ui .sm\:items-end{align-items:flex-end}.saas-os-ui .sm\:items-center{align-items:center}.saas-os-ui .sm\:justify-end{justify-content:flex-end}.saas-os-ui .sm\:justify-between{justify-content:space-between}.saas-os-ui .sm\:gap-1{gap:.25rem}.saas-os-ui .sm\:gap-1\.5{gap:.375rem}.saas-os-ui .sm\:gap-2{gap:.5rem}.saas-os-ui .sm\:gap-3{gap:.75rem}.saas-os-ui .sm\:gap-4{gap:1rem}.saas-os-ui .sm\:gap-y-4{row-gap:1rem}.saas-os-ui .sm\:space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.saas-os-ui .sm\:space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .sm\:space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.5rem*var(--tw-space-y-reverse));margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)))}.saas-os-ui .sm\:rounded-lg{border-radius:var(--radius)}.saas-os-ui .sm\:border-0{border-width:0}.saas-os-ui .sm\:p-4{padding:1rem}.saas-os-ui .sm\:p-5{padding:1.25rem}.saas-os-ui .sm\:p-6{padding:1.5rem}.saas-os-ui .sm\:px-1\.5{padding-left:.375rem;padding-right:.375rem}.saas-os-ui .sm\:px-4{padding-left:1rem;padding-right:1rem}.saas-os-ui .sm\:px-5{padding-left:1.25rem;padding-right:1.25rem}.saas-os-ui .sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.saas-os-ui .sm\:py-5{padding-bottom:1.25rem;padding-top:1.25rem}.saas-os-ui .sm\:py-6{padding-bottom:1.5rem;padding-top:1.5rem}.saas-os-ui .sm\:py-8{padding-bottom:2rem;padding-top:2rem}.saas-os-ui .sm\:pt-0{padding-top:0}.saas-os-ui .sm\:text-start{text-align:start}.saas-os-ui .sm\:text-2xl{font-size:1.5rem;line-height:2rem}.saas-os-ui .sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}.saas-os-ui .sm\:text-sm{font-size:.875rem;line-height:1.25rem}.saas-os-ui .sm\:text-xl{font-size:1.25rem;line-height:1.75rem}.saas-os-ui .sm\:text-xs{font-size:.75rem;line-height:1rem}}@media (min-width:768px){.saas-os-ui .md\:block{display:block}.saas-os-ui .md\:hidden{display:none}.saas-os-ui .md\:w-full{width:100%}}@media (min-width:1024px){.saas-os-ui .lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}.saas-os-ui .rtl\:left-4:where([dir=rtl],[dir=rtl] *){left:1rem}.saas-os-ui .rtl\:right-auto:where([dir=rtl],[dir=rtl] *){right:auto}.saas-os-ui .\[\&_\[cmdk-group-heading\]\]\:px-2 [cmdk-group-heading]{padding-left:.5rem;padding-right:.5rem}.saas-os-ui .\[\&_\[cmdk-group-heading\]\]\:py-1\.5 [cmdk-group-heading]{padding-bottom:.375rem;padding-top:.375rem}.saas-os-ui .\[\&_\[cmdk-group-heading\]\]\:text-xs [cmdk-group-heading]{font-size:.75rem;line-height:1rem}.saas-os-ui .\[\&_\[cmdk-group-heading\]\]\:font-medium [cmdk-group-heading]{font-weight:500}.saas-os-ui .\[\&_\[cmdk-group-heading\]\]\:text-muted-foreground [cmdk-group-heading]{color:hsl(var(--muted-foreground))}.saas-os-ui .\[\&_\[cmdk-group\]\:not\(\[hidden\]\)_\~\[cmdk-group\]\]\:pt-0 [cmdk-group]:not([hidden])~[cmdk-group]{padding-top:0}.saas-os-ui .\[\&_\[cmdk-group\]\]\:px-2 [cmdk-group]{padding-left:.5rem;padding-right:.5rem}.saas-os-ui .\[\&_\[cmdk-input-wrapper\]_svg\]\:h-5 [cmdk-input-wrapper] svg{height:1.25rem}.saas-os-ui .\[\&_\[cmdk-input-wrapper\]_svg\]\:w-5 [cmdk-input-wrapper] svg{width:1.25rem}.saas-os-ui .\[\&_\[cmdk-input\]\]\:h-12 [cmdk-input]{height:3rem}.saas-os-ui .\[\&_\[cmdk-item\]\]\:px-2 [cmdk-item]{padding-left:.5rem;padding-right:.5rem}.saas-os-ui .\[\&_\[cmdk-item\]\]\:py-3 [cmdk-item]{padding-bottom:.75rem;padding-top:.75rem}.saas-os-ui .\[\&_\[cmdk-item\]_svg\]\:h-5 [cmdk-item] svg{height:1.25rem}.saas-os-ui .\[\&_\[cmdk-item\]_svg\]\:w-5 [cmdk-item] svg{width:1.25rem}
|