@burdenoff/microfe-auth 2026.601.2 → 2026.601.4
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.
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { useState as e } from "react";
|
|
2
|
+
import { useAppShell as t, useI18n as n } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
3
|
+
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
4
|
+
import { LanguageSwitcher as a } from "@burdenoff/fe-libs/chrome";
|
|
4
5
|
//#region src/auth/components/AuthLayout.tsx
|
|
5
|
-
var
|
|
6
|
+
var o = [
|
|
6
7
|
{
|
|
7
8
|
code: "en",
|
|
8
9
|
name: "English",
|
|
@@ -40,127 +41,129 @@ var a = [
|
|
|
40
41
|
flag: "🇸🇦"
|
|
41
42
|
}
|
|
42
43
|
];
|
|
43
|
-
function
|
|
44
|
-
let
|
|
45
|
-
|
|
44
|
+
function s({ brandInitial: t }) {
|
|
45
|
+
let [n, i] = e(!1);
|
|
46
|
+
return n ? /* @__PURE__ */ r("div", {
|
|
47
|
+
className: "auth-brand-badge flex size-10 items-center justify-center rounded-xl",
|
|
48
|
+
children: /* @__PURE__ */ r("span", {
|
|
49
|
+
className: "text-lg font-bold leading-none text-white",
|
|
50
|
+
children: t
|
|
51
|
+
})
|
|
52
|
+
}) : /* @__PURE__ */ r("img", {
|
|
53
|
+
src: "/icons/icon.svg",
|
|
54
|
+
alt: "",
|
|
55
|
+
"aria-hidden": "true",
|
|
56
|
+
className: "size-10 rounded-xl object-contain",
|
|
57
|
+
onError: () => i(!0)
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function c({ children: e, title: c, subtitle: l, productName: u, tagline: d }) {
|
|
61
|
+
let f = t(), p = u || f.productName || "Burdenoff", m = f.brandInitial || "B", h = d || f.tagline || "Enterprise platform", { t: g, locale: _, setLocale: v } = n(), y = (e, t) => {
|
|
62
|
+
let n = g(e);
|
|
46
63
|
return n === e ? t : n;
|
|
47
64
|
};
|
|
48
|
-
return /* @__PURE__ */
|
|
65
|
+
return /* @__PURE__ */ i("div", {
|
|
49
66
|
className: "min-h-screen flex relative",
|
|
50
|
-
children: [/* @__PURE__ */
|
|
67
|
+
children: [/* @__PURE__ */ i("div", {
|
|
51
68
|
className: "auth-brand-panel hidden overflow-hidden lg:flex lg:w-1/2 relative",
|
|
52
|
-
children: [/* @__PURE__ */
|
|
69
|
+
children: [/* @__PURE__ */ i("div", {
|
|
53
70
|
className: "absolute inset-0 overflow-hidden",
|
|
54
71
|
children: [
|
|
55
|
-
/* @__PURE__ */
|
|
56
|
-
/* @__PURE__ */
|
|
57
|
-
/* @__PURE__ */
|
|
58
|
-
/* @__PURE__ */
|
|
72
|
+
/* @__PURE__ */ r("div", { className: "absolute -top-40 -left-40 size-80 rounded-full bg-accent-blue/20 blur-3xl" }),
|
|
73
|
+
/* @__PURE__ */ r("div", { className: "absolute top-1/2 -right-20 size-96 rounded-full bg-accent-indigo/20 blur-3xl" }),
|
|
74
|
+
/* @__PURE__ */ r("div", { className: "absolute -bottom-40 left-1/4 size-72 rounded-full bg-accent-purple/20 blur-3xl" }),
|
|
75
|
+
/* @__PURE__ */ r("div", {
|
|
59
76
|
className: "absolute inset-0 opacity-5",
|
|
60
77
|
style: { backgroundImage: "url(\"data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='1'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E\")" }
|
|
61
78
|
})
|
|
62
79
|
]
|
|
63
|
-
}), /* @__PURE__ */
|
|
80
|
+
}), /* @__PURE__ */ i("div", {
|
|
64
81
|
className: "relative z-10 flex flex-col justify-between p-12 w-full",
|
|
65
82
|
children: [
|
|
66
|
-
/* @__PURE__ */
|
|
83
|
+
/* @__PURE__ */ i("div", {
|
|
67
84
|
className: "flex items-center gap-3",
|
|
68
|
-
children: [/* @__PURE__ */
|
|
69
|
-
className: "auth-brand-badge flex size-10 items-center justify-center rounded-xl",
|
|
70
|
-
children: /* @__PURE__ */ n("svg", {
|
|
71
|
-
className: "size-6 text-white",
|
|
72
|
-
fill: "none",
|
|
73
|
-
viewBox: "0 0 24 24",
|
|
74
|
-
stroke: "currentColor",
|
|
75
|
-
children: /* @__PURE__ */ n("path", {
|
|
76
|
-
strokeLinecap: "round",
|
|
77
|
-
strokeLinejoin: "round",
|
|
78
|
-
strokeWidth: 2,
|
|
79
|
-
d: "M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"
|
|
80
|
-
})
|
|
81
|
-
})
|
|
82
|
-
}), /* @__PURE__ */ n("span", {
|
|
85
|
+
children: [/* @__PURE__ */ r(s, { brandInitial: m }), /* @__PURE__ */ r("span", {
|
|
83
86
|
className: "text-xl font-bold text-[var(--color-text-primary)]",
|
|
84
|
-
children:
|
|
87
|
+
children: p
|
|
85
88
|
})]
|
|
86
89
|
}),
|
|
87
|
-
/* @__PURE__ */
|
|
90
|
+
/* @__PURE__ */ i("div", {
|
|
88
91
|
className: "max-w-md",
|
|
89
92
|
children: [
|
|
90
|
-
/* @__PURE__ */
|
|
93
|
+
/* @__PURE__ */ r("h1", {
|
|
91
94
|
className: "mb-4 text-4xl font-bold leading-tight text-[var(--color-text-primary)]",
|
|
92
|
-
children:
|
|
95
|
+
children: h
|
|
93
96
|
}),
|
|
94
|
-
/* @__PURE__ */
|
|
97
|
+
/* @__PURE__ */ r("p", {
|
|
95
98
|
className: "auth-brand-copy text-lg leading-relaxed",
|
|
96
|
-
children:
|
|
99
|
+
children: y("auth.layout.taglineDescription", "Unify your teams, projects, and workflows in one intelligent workspace. Built for scale with enterprise-grade security, real-time collaboration, and seamless integrations across your entire organization.")
|
|
97
100
|
}),
|
|
98
|
-
/* @__PURE__ */
|
|
101
|
+
/* @__PURE__ */ r("div", {
|
|
99
102
|
className: "mt-10 space-y-4",
|
|
100
103
|
children: [
|
|
101
104
|
{
|
|
102
105
|
icon: "workspace",
|
|
103
|
-
text:
|
|
106
|
+
text: y("auth.layout.featureWorkspace", "Modular workspace architecture")
|
|
104
107
|
},
|
|
105
108
|
{
|
|
106
109
|
icon: "realtime",
|
|
107
|
-
text:
|
|
110
|
+
text: y("auth.layout.featureRealtime", "Real-time collaboration & sync")
|
|
108
111
|
},
|
|
109
112
|
{
|
|
110
113
|
icon: "security",
|
|
111
|
-
text:
|
|
114
|
+
text: y("auth.layout.featureSecurity", "Enterprise-grade security & SSO")
|
|
112
115
|
},
|
|
113
116
|
{
|
|
114
117
|
icon: "scale",
|
|
115
|
-
text:
|
|
118
|
+
text: y("auth.layout.featureScale", "Unlimited scalability & performance")
|
|
116
119
|
}
|
|
117
|
-
].map((e) => /* @__PURE__ */
|
|
120
|
+
].map((e) => /* @__PURE__ */ i("div", {
|
|
118
121
|
className: "flex items-center gap-3",
|
|
119
|
-
children: [/* @__PURE__ */
|
|
122
|
+
children: [/* @__PURE__ */ i("div", {
|
|
120
123
|
className: "auth-highlight-chip flex size-8 items-center justify-center rounded-lg",
|
|
121
124
|
children: [
|
|
122
|
-
e.icon === "workspace" && /* @__PURE__ */
|
|
125
|
+
e.icon === "workspace" && /* @__PURE__ */ r("svg", {
|
|
123
126
|
className: "size-4 text-accent-blue",
|
|
124
127
|
fill: "none",
|
|
125
128
|
viewBox: "0 0 24 24",
|
|
126
129
|
stroke: "currentColor",
|
|
127
|
-
children: /* @__PURE__ */
|
|
130
|
+
children: /* @__PURE__ */ r("path", {
|
|
128
131
|
strokeLinecap: "round",
|
|
129
132
|
strokeLinejoin: "round",
|
|
130
133
|
strokeWidth: 2,
|
|
131
134
|
d: "M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"
|
|
132
135
|
})
|
|
133
136
|
}),
|
|
134
|
-
e.icon === "realtime" && /* @__PURE__ */
|
|
137
|
+
e.icon === "realtime" && /* @__PURE__ */ r("svg", {
|
|
135
138
|
className: "size-4 text-accent-blue",
|
|
136
139
|
fill: "none",
|
|
137
140
|
viewBox: "0 0 24 24",
|
|
138
141
|
stroke: "currentColor",
|
|
139
|
-
children: /* @__PURE__ */
|
|
142
|
+
children: /* @__PURE__ */ r("path", {
|
|
140
143
|
strokeLinecap: "round",
|
|
141
144
|
strokeLinejoin: "round",
|
|
142
145
|
strokeWidth: 2,
|
|
143
146
|
d: "M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z"
|
|
144
147
|
})
|
|
145
148
|
}),
|
|
146
|
-
e.icon === "security" && /* @__PURE__ */
|
|
149
|
+
e.icon === "security" && /* @__PURE__ */ r("svg", {
|
|
147
150
|
className: "size-4 text-accent-blue",
|
|
148
151
|
fill: "none",
|
|
149
152
|
viewBox: "0 0 24 24",
|
|
150
153
|
stroke: "currentColor",
|
|
151
|
-
children: /* @__PURE__ */
|
|
154
|
+
children: /* @__PURE__ */ r("path", {
|
|
152
155
|
strokeLinecap: "round",
|
|
153
156
|
strokeLinejoin: "round",
|
|
154
157
|
strokeWidth: 2,
|
|
155
158
|
d: "M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"
|
|
156
159
|
})
|
|
157
160
|
}),
|
|
158
|
-
e.icon === "scale" && /* @__PURE__ */
|
|
161
|
+
e.icon === "scale" && /* @__PURE__ */ r("svg", {
|
|
159
162
|
className: "size-4 text-accent-blue",
|
|
160
163
|
fill: "none",
|
|
161
164
|
viewBox: "0 0 24 24",
|
|
162
165
|
stroke: "currentColor",
|
|
163
|
-
children: /* @__PURE__ */
|
|
166
|
+
children: /* @__PURE__ */ r("path", {
|
|
164
167
|
strokeLinecap: "round",
|
|
165
168
|
strokeLinejoin: "round",
|
|
166
169
|
strokeWidth: 2,
|
|
@@ -168,7 +171,7 @@ function o({ children: o, title: s, subtitle: c, productName: l, tagline: u }) {
|
|
|
168
171
|
})
|
|
169
172
|
})
|
|
170
173
|
]
|
|
171
|
-
}), /* @__PURE__ */
|
|
174
|
+
}), /* @__PURE__ */ r("span", {
|
|
172
175
|
className: "auth-brand-copy text-sm font-medium",
|
|
173
176
|
children: e.text
|
|
174
177
|
})]
|
|
@@ -176,7 +179,7 @@ function o({ children: o, title: s, subtitle: c, productName: l, tagline: u }) {
|
|
|
176
179
|
})
|
|
177
180
|
]
|
|
178
181
|
}),
|
|
179
|
-
/* @__PURE__ */
|
|
182
|
+
/* @__PURE__ */ i("div", {
|
|
180
183
|
className: "auth-brand-copy-muted text-sm",
|
|
181
184
|
children: [
|
|
182
185
|
"© ",
|
|
@@ -186,58 +189,44 @@ function o({ children: o, title: s, subtitle: c, productName: l, tagline: u }) {
|
|
|
186
189
|
})
|
|
187
190
|
]
|
|
188
191
|
})]
|
|
189
|
-
}), /* @__PURE__ */
|
|
192
|
+
}), /* @__PURE__ */ i("main", {
|
|
190
193
|
className: "auth-shell-gradient relative flex flex-1 items-center justify-center bg-[var(--color-bg-canvas)] p-6 sm:p-12",
|
|
191
|
-
children: [/* @__PURE__ */
|
|
194
|
+
children: [/* @__PURE__ */ r("div", {
|
|
192
195
|
className: "absolute top-4 right-4 sm:top-6 sm:right-6 z-10",
|
|
193
|
-
children: /* @__PURE__ */
|
|
194
|
-
languages:
|
|
195
|
-
currentLanguage:
|
|
196
|
+
children: /* @__PURE__ */ r(a, {
|
|
197
|
+
languages: o,
|
|
198
|
+
currentLanguage: _,
|
|
196
199
|
onLanguageChange: (e) => {
|
|
197
|
-
|
|
200
|
+
v(e.code);
|
|
198
201
|
}
|
|
199
202
|
})
|
|
200
|
-
}), /* @__PURE__ */
|
|
203
|
+
}), /* @__PURE__ */ i("div", {
|
|
201
204
|
className: "w-full max-w-md",
|
|
202
205
|
children: [
|
|
203
|
-
/* @__PURE__ */
|
|
206
|
+
/* @__PURE__ */ i("div", {
|
|
204
207
|
className: "lg:hidden flex items-center justify-center gap-3 mb-8",
|
|
205
|
-
children: [/* @__PURE__ */
|
|
206
|
-
className: "auth-brand-badge flex size-10 items-center justify-center rounded-xl",
|
|
207
|
-
children: /* @__PURE__ */ n("svg", {
|
|
208
|
-
className: "size-6 text-white",
|
|
209
|
-
fill: "none",
|
|
210
|
-
viewBox: "0 0 24 24",
|
|
211
|
-
stroke: "currentColor",
|
|
212
|
-
children: /* @__PURE__ */ n("path", {
|
|
213
|
-
strokeLinecap: "round",
|
|
214
|
-
strokeLinejoin: "round",
|
|
215
|
-
strokeWidth: 2,
|
|
216
|
-
d: "M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"
|
|
217
|
-
})
|
|
218
|
-
})
|
|
219
|
-
}), /* @__PURE__ */ n("span", {
|
|
208
|
+
children: [/* @__PURE__ */ r(s, { brandInitial: m }), /* @__PURE__ */ r("span", {
|
|
220
209
|
className: "text-xl font-bold text-[var(--color-text-primary)]",
|
|
221
|
-
children:
|
|
210
|
+
children: p
|
|
222
211
|
})]
|
|
223
212
|
}),
|
|
224
|
-
/* @__PURE__ */
|
|
213
|
+
/* @__PURE__ */ i("div", {
|
|
225
214
|
className: "text-center lg:text-left mb-8",
|
|
226
|
-
children: [/* @__PURE__ */
|
|
215
|
+
children: [/* @__PURE__ */ r("h2", {
|
|
227
216
|
className: "text-2xl sm:text-3xl font-bold text-[var(--color-text-primary)] mb-2",
|
|
228
|
-
children: s
|
|
229
|
-
}), /* @__PURE__ */ n("p", {
|
|
230
|
-
className: "text-[var(--color-text-secondary)]",
|
|
231
217
|
children: c
|
|
218
|
+
}), /* @__PURE__ */ r("p", {
|
|
219
|
+
className: "text-[var(--color-text-secondary)]",
|
|
220
|
+
children: l
|
|
232
221
|
})]
|
|
233
222
|
}),
|
|
234
|
-
|
|
223
|
+
e
|
|
235
224
|
]
|
|
236
225
|
})]
|
|
237
226
|
})]
|
|
238
227
|
});
|
|
239
228
|
}
|
|
240
229
|
//#endregion
|
|
241
|
-
export {
|
|
230
|
+
export { c as AuthLayout };
|
|
242
231
|
|
|
243
232
|
//# sourceMappingURL=AuthLayout.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthLayout.js","names":[],"sources":["../../../src/auth/components/AuthLayout.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { LanguageSwitcher } from \"@burdenoff/fe-libs/chrome\";\nimport type { Language } from \"@burdenoff/fe-libs/chrome\";\nimport {\n useI18n,\n useAppShell,\n} from \"@burdenoff/fe-libs/shared/providers/shell\";\nimport type { Locale } from \"@burdenoff/fe-libs/shared/providers/shell\";\n\ninterface AuthLayoutProps {\n children: ReactNode;\n title: string;\n subtitle: string;\n productName?: string;\n tagline?: string;\n}\n\n/**\n * Supported languages for the auth pages.\n *\n * Must stay in sync with the locales actually seeded in\n * `i18n_translations` for the consumer products that mount microfe-auth.\n * If a locale is listed here but NOT seeded, selecting it sets\n * `setLocale(<code>)` on the I18nProvider, the next `exportTranslations`\n * call returns zero rows, every `tr()` falls back to its English default,\n * and the user gets an English UI under a non-English flag.\n *\n * Audited 2026-05-31 against alpha `i18n_translations`: only `en/ta/hi/\n * zh/es/ar` have actual translations (vibecontrols 40k+ rows each).\n * `fr` was previously listed but no product seeds it — selecting it\n * produced a half-translated UI. Removed for parity with the dashboard\n * `LanguageSwitcherSlot` (which is data-driven from `i18n_languages`).\n *\n * Adding a new locale requires updating BOTH:\n * - this list\n * - each consumer product's seed (e.g. vibecontrols-app/scripts/\n * build-i18n-bundle.ts + the new `<code>.ts` translation source).\n */\nconst AUTH_LANGUAGES: Language[] = [\n { code: \"en\", name: \"English\", nativeName: \"English\", flag: \"🇺🇸\" },\n { code: \"ta\", name: \"Tamil\", nativeName: \"தமிழ்\", flag: \"🇮🇳\" },\n { code: \"hi\", name: \"Hindi\", nativeName: \"हिन्दी\", flag: \"🇮🇳\" },\n { code: \"zh\", name: \"Chinese\", nativeName: \"中文\", flag: \"🇨🇳\" },\n { code: \"es\", name: \"Spanish\", nativeName: \"Español\", flag: \"🇪🇸\" },\n { code: \"ar\", name: \"Arabic\", nativeName: \"العربية\", flag: \"🇸🇦\" },\n];\n\n/**\n * Professional auth layout with split-screen design\n * Left side: Branding with gradient background\n * Right side: Auth form\n */\nexport function AuthLayout({\n children,\n title,\n subtitle,\n productName,\n tagline,\n}: AuthLayoutProps) {\n const shell = useAppShell();\n const displayName = productName || shell.productName || \"Burdenoff\";\n const displayTagline = tagline || shell.tagline || \"Enterprise platform\";\n const { t, locale, setLocale } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n\n const handleLanguageChange = (language: Language) => {\n // AUTH_LANGUAGES intentionally lists locales (e.g. \"ar\") that are seeded\n // in consumer products but not yet present in the fe-libs Locale union.\n // The runtime I18nProvider accepts any locale code, so we cast through\n // unknown to Locale to keep the picker in parity until fe-libs widens the\n // union. Keep AUTH_LANGUAGES in sync with consumer product seeds.\n setLocale(language.code as unknown as Locale);\n };\n\n return (\n <div className=\"min-h-screen flex relative\">\n {/* Left Panel - Branding */}\n <div className=\"auth-brand-panel hidden overflow-hidden lg:flex lg:w-1/2 relative\">\n {/* Decorative Elements */}\n <div className=\"absolute inset-0 overflow-hidden\">\n <div className=\"absolute -top-40 -left-40 size-80 rounded-full bg-accent-blue/20 blur-3xl\" />\n <div className=\"absolute top-1/2 -right-20 size-96 rounded-full bg-accent-indigo/20 blur-3xl\" />\n <div className=\"absolute -bottom-40 left-1/4 size-72 rounded-full bg-accent-purple/20 blur-3xl\" />\n\n {/* Grid Pattern */}\n <div\n className=\"absolute inset-0 opacity-5\"\n style={{\n backgroundImage: `url(\"data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='1'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E\")`,\n }}\n />\n </div>\n\n {/* Content */}\n <div className=\"relative z-10 flex flex-col justify-between p-12 w-full\">\n {/* Logo */}\n <div className=\"flex items-center gap-3\">\n <div className=\"auth-brand-badge flex size-10 items-center justify-center rounded-xl\">\n <svg\n className=\"size-6 text-white\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"\n />\n </svg>\n </div>\n <span className=\"text-xl font-bold text-[var(--color-text-primary)]\">\n {displayName}\n </span>\n </div>\n\n {/* Main Content */}\n <div className=\"max-w-md\">\n <h1 className=\"mb-4 text-4xl font-bold leading-tight text-[var(--color-text-primary)]\">\n {displayTagline}\n </h1>\n <p className=\"auth-brand-copy text-lg leading-relaxed\">\n {tr(\n \"auth.layout.taglineDescription\",\n \"Unify your teams, projects, and workflows in one intelligent workspace. Built for scale with enterprise-grade security, real-time collaboration, and seamless integrations across your entire organization.\",\n )}\n </p>\n\n {/* Features */}\n <div className=\"mt-10 space-y-4\">\n {[\n {\n icon: \"workspace\",\n text: tr(\n \"auth.layout.featureWorkspace\",\n \"Modular workspace architecture\",\n ),\n },\n {\n icon: \"realtime\",\n text: tr(\n \"auth.layout.featureRealtime\",\n \"Real-time collaboration & sync\",\n ),\n },\n {\n icon: \"security\",\n text: tr(\n \"auth.layout.featureSecurity\",\n \"Enterprise-grade security & SSO\",\n ),\n },\n {\n icon: \"scale\",\n text: tr(\n \"auth.layout.featureScale\",\n \"Unlimited scalability & performance\",\n ),\n },\n ].map((feature) => (\n <div key={feature.icon} className=\"flex items-center gap-3\">\n <div className=\"auth-highlight-chip flex size-8 items-center justify-center rounded-lg\">\n {feature.icon === \"workspace\" && (\n <svg\n className=\"size-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z\"\n />\n </svg>\n )}\n {feature.icon === \"realtime\" && (\n <svg\n className=\"size-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z\"\n />\n </svg>\n )}\n {feature.icon === \"security\" && (\n <svg\n className=\"size-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"\n />\n </svg>\n )}\n {feature.icon === \"scale\" && (\n <svg\n className=\"size-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z\"\n />\n </svg>\n )}\n </div>\n <span className=\"auth-brand-copy text-sm font-medium\">\n {feature.text}\n </span>\n </div>\n ))}\n </div>\n </div>\n\n {/* Footer */}\n <div className=\"auth-brand-copy-muted text-sm\">\n © {new Date().getFullYear()} Burdenoff. All rights reserved.\n </div>\n </div>\n </div>\n\n {/* Right Panel - Form */}\n <main className=\"auth-shell-gradient relative flex flex-1 items-center justify-center bg-[var(--color-bg-canvas)] p-6 sm:p-12\">\n {/* Language Switcher - Top Right */}\n <div className=\"absolute top-4 right-4 sm:top-6 sm:right-6 z-10\">\n <LanguageSwitcher\n languages={AUTH_LANGUAGES}\n currentLanguage={locale}\n onLanguageChange={handleLanguageChange}\n />\n </div>\n <div className=\"w-full max-w-md\">\n {/* Mobile Logo */}\n <div className=\"lg:hidden flex items-center justify-center gap-3 mb-8\">\n <div className=\"auth-brand-badge flex size-10 items-center justify-center rounded-xl\">\n <svg\n className=\"size-6 text-white\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"\n />\n </svg>\n </div>\n <span className=\"text-xl font-bold text-[var(--color-text-primary)]\">\n {displayName}\n </span>\n </div>\n\n {/* Header */}\n <div className=\"text-center lg:text-left mb-8\">\n <h2 className=\"text-2xl sm:text-3xl font-bold text-[var(--color-text-primary)] mb-2\">\n {title}\n </h2>\n <p className=\"text-[var(--color-text-secondary)]\">{subtitle}</p>\n </div>\n\n {/* Form Content */}\n {children}\n </div>\n </main>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AuthLayout.js","names":[],"sources":["../../../src/auth/components/AuthLayout.tsx"],"sourcesContent":["import { useState, type ReactNode } from \"react\";\nimport { LanguageSwitcher } from \"@burdenoff/fe-libs/chrome\";\nimport type { Language } from \"@burdenoff/fe-libs/chrome\";\nimport {\n useI18n,\n useAppShell,\n} from \"@burdenoff/fe-libs/shared/providers/shell\";\nimport type { Locale } from \"@burdenoff/fe-libs/shared/providers/shell\";\n\ninterface AuthLayoutProps {\n children: ReactNode;\n title: string;\n subtitle: string;\n productName?: string;\n tagline?: string;\n}\n\n/**\n * Supported languages for the auth pages.\n *\n * Must stay in sync with the locales actually seeded in\n * `i18n_translations` for the consumer products that mount microfe-auth.\n * If a locale is listed here but NOT seeded, selecting it sets\n * `setLocale(<code>)` on the I18nProvider, the next `exportTranslations`\n * call returns zero rows, every `tr()` falls back to its English default,\n * and the user gets an English UI under a non-English flag.\n *\n * Audited 2026-05-31 against alpha `i18n_translations`: only `en/ta/hi/\n * zh/es/ar` have actual translations (vibecontrols 40k+ rows each).\n * `fr` was previously listed but no product seeds it — selecting it\n * produced a half-translated UI. Removed for parity with the dashboard\n * `LanguageSwitcherSlot` (which is data-driven from `i18n_languages`).\n *\n * Adding a new locale requires updating BOTH:\n * - this list\n * - each consumer product's seed (e.g. vibecontrols-app/scripts/\n * build-i18n-bundle.ts + the new `<code>.ts` translation source).\n */\nconst AUTH_LANGUAGES: Language[] = [\n { code: \"en\", name: \"English\", nativeName: \"English\", flag: \"🇺🇸\" },\n { code: \"ta\", name: \"Tamil\", nativeName: \"தமிழ்\", flag: \"🇮🇳\" },\n { code: \"hi\", name: \"Hindi\", nativeName: \"हिन्दी\", flag: \"🇮🇳\" },\n { code: \"zh\", name: \"Chinese\", nativeName: \"中文\", flag: \"🇨🇳\" },\n { code: \"es\", name: \"Spanish\", nativeName: \"Español\", flag: \"🇪🇸\" },\n { code: \"ar\", name: \"Arabic\", nativeName: \"العربية\", flag: \"🇸🇦\" },\n];\n\n/**\n * Brand logo for the auth pages.\n *\n * Renders the host app shell's real product logo served at `/icons/icon.svg`\n * (the same asset the marketing landing page uses) so the login screen and the\n * landing page show an identical mark instead of a generic placeholder glyph.\n * Host shells that don't ship that asset (e.g. admin-app) fall back to a\n * branded initial badge rather than a broken image.\n */\nfunction BrandLogo({ brandInitial }: { brandInitial: string }) {\n const [failed, setFailed] = useState(false);\n\n if (failed) {\n return (\n <div className=\"auth-brand-badge flex size-10 items-center justify-center rounded-xl\">\n <span className=\"text-lg font-bold leading-none text-white\">\n {brandInitial}\n </span>\n </div>\n );\n }\n\n return (\n <img\n src=\"/icons/icon.svg\"\n alt=\"\"\n aria-hidden=\"true\"\n className=\"size-10 rounded-xl object-contain\"\n onError={() => setFailed(true)}\n />\n );\n}\n\n/**\n * Professional auth layout with split-screen design\n * Left side: Branding with gradient background\n * Right side: Auth form\n */\nexport function AuthLayout({\n children,\n title,\n subtitle,\n productName,\n tagline,\n}: AuthLayoutProps) {\n const shell = useAppShell();\n const displayName = productName || shell.productName || \"Burdenoff\";\n const brandInitial = shell.brandInitial || \"B\";\n const displayTagline = tagline || shell.tagline || \"Enterprise platform\";\n const { t, locale, setLocale } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n\n const handleLanguageChange = (language: Language) => {\n // AUTH_LANGUAGES intentionally lists locales (e.g. \"ar\") that are seeded\n // in consumer products but not yet present in the fe-libs Locale union.\n // The runtime I18nProvider accepts any locale code, so we cast through\n // unknown to Locale to keep the picker in parity until fe-libs widens the\n // union. Keep AUTH_LANGUAGES in sync with consumer product seeds.\n setLocale(language.code as unknown as Locale);\n };\n\n return (\n <div className=\"min-h-screen flex relative\">\n {/* Left Panel - Branding */}\n <div className=\"auth-brand-panel hidden overflow-hidden lg:flex lg:w-1/2 relative\">\n {/* Decorative Elements */}\n <div className=\"absolute inset-0 overflow-hidden\">\n <div className=\"absolute -top-40 -left-40 size-80 rounded-full bg-accent-blue/20 blur-3xl\" />\n <div className=\"absolute top-1/2 -right-20 size-96 rounded-full bg-accent-indigo/20 blur-3xl\" />\n <div className=\"absolute -bottom-40 left-1/4 size-72 rounded-full bg-accent-purple/20 blur-3xl\" />\n\n {/* Grid Pattern */}\n <div\n className=\"absolute inset-0 opacity-5\"\n style={{\n backgroundImage: `url(\"data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='1'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E\")`,\n }}\n />\n </div>\n\n {/* Content */}\n <div className=\"relative z-10 flex flex-col justify-between p-12 w-full\">\n {/* Logo */}\n <div className=\"flex items-center gap-3\">\n <BrandLogo brandInitial={brandInitial} />\n <span className=\"text-xl font-bold text-[var(--color-text-primary)]\">\n {displayName}\n </span>\n </div>\n\n {/* Main Content */}\n <div className=\"max-w-md\">\n <h1 className=\"mb-4 text-4xl font-bold leading-tight text-[var(--color-text-primary)]\">\n {displayTagline}\n </h1>\n <p className=\"auth-brand-copy text-lg leading-relaxed\">\n {tr(\n \"auth.layout.taglineDescription\",\n \"Unify your teams, projects, and workflows in one intelligent workspace. Built for scale with enterprise-grade security, real-time collaboration, and seamless integrations across your entire organization.\",\n )}\n </p>\n\n {/* Features */}\n <div className=\"mt-10 space-y-4\">\n {[\n {\n icon: \"workspace\",\n text: tr(\n \"auth.layout.featureWorkspace\",\n \"Modular workspace architecture\",\n ),\n },\n {\n icon: \"realtime\",\n text: tr(\n \"auth.layout.featureRealtime\",\n \"Real-time collaboration & sync\",\n ),\n },\n {\n icon: \"security\",\n text: tr(\n \"auth.layout.featureSecurity\",\n \"Enterprise-grade security & SSO\",\n ),\n },\n {\n icon: \"scale\",\n text: tr(\n \"auth.layout.featureScale\",\n \"Unlimited scalability & performance\",\n ),\n },\n ].map((feature) => (\n <div key={feature.icon} className=\"flex items-center gap-3\">\n <div className=\"auth-highlight-chip flex size-8 items-center justify-center rounded-lg\">\n {feature.icon === \"workspace\" && (\n <svg\n className=\"size-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z\"\n />\n </svg>\n )}\n {feature.icon === \"realtime\" && (\n <svg\n className=\"size-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z\"\n />\n </svg>\n )}\n {feature.icon === \"security\" && (\n <svg\n className=\"size-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"\n />\n </svg>\n )}\n {feature.icon === \"scale\" && (\n <svg\n className=\"size-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z\"\n />\n </svg>\n )}\n </div>\n <span className=\"auth-brand-copy text-sm font-medium\">\n {feature.text}\n </span>\n </div>\n ))}\n </div>\n </div>\n\n {/* Footer */}\n <div className=\"auth-brand-copy-muted text-sm\">\n © {new Date().getFullYear()} Burdenoff. All rights reserved.\n </div>\n </div>\n </div>\n\n {/* Right Panel - Form */}\n <main className=\"auth-shell-gradient relative flex flex-1 items-center justify-center bg-[var(--color-bg-canvas)] p-6 sm:p-12\">\n {/* Language Switcher - Top Right */}\n <div className=\"absolute top-4 right-4 sm:top-6 sm:right-6 z-10\">\n <LanguageSwitcher\n languages={AUTH_LANGUAGES}\n currentLanguage={locale}\n onLanguageChange={handleLanguageChange}\n />\n </div>\n <div className=\"w-full max-w-md\">\n {/* Mobile Logo */}\n <div className=\"lg:hidden flex items-center justify-center gap-3 mb-8\">\n <BrandLogo brandInitial={brandInitial} />\n <span className=\"text-xl font-bold text-[var(--color-text-primary)]\">\n {displayName}\n </span>\n </div>\n\n {/* Header */}\n <div className=\"text-center lg:text-left mb-8\">\n <h2 className=\"text-2xl sm:text-3xl font-bold text-[var(--color-text-primary)] mb-2\">\n {title}\n </h2>\n <p className=\"text-[var(--color-text-secondary)]\">{subtitle}</p>\n </div>\n\n {/* Form Content */}\n {children}\n </div>\n </main>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -32,7 +32,20 @@ function a() {
|
|
|
32
32
|
let e = new Uint8Array(32);
|
|
33
33
|
return crypto.getRandomValues(e), Array.from(e, (e) => e.toString(16).padStart(2, "0")).join("");
|
|
34
34
|
}
|
|
35
|
-
function o() {
|
|
35
|
+
function o(e) {
|
|
36
|
+
try {
|
|
37
|
+
return {
|
|
38
|
+
BASE_URL: "/",
|
|
39
|
+
DEV: !1,
|
|
40
|
+
MODE: "production",
|
|
41
|
+
PROD: !0,
|
|
42
|
+
SSR: !1
|
|
43
|
+
}?.[e];
|
|
44
|
+
} catch {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function s() {
|
|
36
49
|
if (typeof window > "u") return !1;
|
|
37
50
|
let e = window;
|
|
38
51
|
if (typeof e.Capacitor?.isNativePlatform == "function") try {
|
|
@@ -40,8 +53,8 @@ function o() {
|
|
|
40
53
|
} catch {}
|
|
41
54
|
return !!(typeof navigator < "u" && /Electron/i.test(navigator.userAgent || ""));
|
|
42
55
|
}
|
|
43
|
-
var
|
|
44
|
-
async function
|
|
56
|
+
var c = "vibecontrols://app/auth/oauth/callback";
|
|
57
|
+
async function l(e) {
|
|
45
58
|
if (typeof window > "u") return;
|
|
46
59
|
let t = window.__burdenoffOpenExternal;
|
|
47
60
|
if (typeof t == "function") try {
|
|
@@ -49,31 +62,27 @@ async function c(e) {
|
|
|
49
62
|
} catch {}
|
|
50
63
|
window.location.href = e;
|
|
51
64
|
}
|
|
52
|
-
function
|
|
53
|
-
let
|
|
54
|
-
let t = i[e], n =
|
|
55
|
-
VITE_GOOGLE_CLIENT_ID: void 0,
|
|
56
|
-
VITE_GITHUB_CLIENT_ID: void 0,
|
|
57
|
-
VITE_MICROSOFT_CLIENT_ID: void 0
|
|
58
|
-
}[t.clientIdEnvKey];
|
|
65
|
+
function u() {
|
|
66
|
+
let u = e(), [d, { loading: f }] = r(n), p = (e) => u.oauthClientIds?.[e] || o(i[e].clientIdEnvKey), m = (e) => {
|
|
67
|
+
let t = i[e], n = p(e);
|
|
59
68
|
if (!n) throw console.error(`OAuth client ID not configured for ${e}`), Error(`${e} OAuth is not configured. Please set ${t.clientIdEnvKey} environment variable.`);
|
|
60
69
|
let r = a();
|
|
61
70
|
localStorage.setItem("oauth_state", r), localStorage.setItem("oauth_provider", e);
|
|
62
|
-
let
|
|
63
|
-
localStorage.setItem("oauth_redirect_uri",
|
|
71
|
+
let o = s() ? c : `${window.location.origin}/auth/oauth/callback`;
|
|
72
|
+
localStorage.setItem("oauth_redirect_uri", o);
|
|
64
73
|
let u = new URLSearchParams({
|
|
65
74
|
client_id: n,
|
|
66
|
-
redirect_uri:
|
|
75
|
+
redirect_uri: o,
|
|
67
76
|
response_type: "code",
|
|
68
77
|
scope: t.scopes.join(" "),
|
|
69
78
|
state: r,
|
|
70
79
|
...e === "google" && { prompt: "select_account" },
|
|
71
80
|
...e === "google" && { access_type: "offline" }
|
|
72
81
|
});
|
|
73
|
-
|
|
82
|
+
l(`${t.authorizationUrl}?${u.toString()}`);
|
|
74
83
|
};
|
|
75
84
|
return {
|
|
76
|
-
initiateOAuth:
|
|
85
|
+
initiateOAuth: m,
|
|
77
86
|
completeOAuth: async (e, n) => {
|
|
78
87
|
let r = t.getState(), i = localStorage.getItem("oauth_state");
|
|
79
88
|
if (!i || i !== n) throw console.error("[OAuth Complete] State mismatch!", {
|
|
@@ -85,7 +94,7 @@ function l() {
|
|
|
85
94
|
localStorage.removeItem("oauth_state"), localStorage.removeItem("oauth_provider"), localStorage.removeItem("oauth_redirect_uri");
|
|
86
95
|
try {
|
|
87
96
|
r.setLoading(!0), r.setError(null);
|
|
88
|
-
let { data: t, error: n } = await
|
|
97
|
+
let { data: t, error: n } = await d({ variables: { input: {
|
|
89
98
|
provider: a.toUpperCase(),
|
|
90
99
|
code: e,
|
|
91
100
|
redirectUri: o
|
|
@@ -95,7 +104,7 @@ function l() {
|
|
|
95
104
|
throw Error(e);
|
|
96
105
|
}
|
|
97
106
|
let i = t.authenticateOAuth;
|
|
98
|
-
return i.requiresMFA ? (r.setMfaRequired(!0, i.mfaChallengeId || void 0), i) : (i.success && i.user && i.token ? (r.setUser(i.user), r.setAuthTokens(i.token, i.refreshToken || ""), r.setAuthenticated(!0), r.setMfaRequired(!1),
|
|
107
|
+
return i.requiresMFA ? (r.setMfaRequired(!0, i.mfaChallengeId || void 0), i) : (i.success && i.user && i.token ? (r.setUser(i.user), r.setAuthTokens(i.token, i.refreshToken || ""), r.setAuthenticated(!0), r.setMfaRequired(!1), u.onAuthSuccess?.(i.user, i.token, i.refreshToken || void 0)) : i.error && r.setError(i.error), i);
|
|
99
108
|
} catch (e) {
|
|
100
109
|
let t = e instanceof Error ? e.message : "OAuth authentication failed";
|
|
101
110
|
throw r.setError(t), e;
|
|
@@ -103,18 +112,14 @@ function l() {
|
|
|
103
112
|
r.setLoading(!1);
|
|
104
113
|
}
|
|
105
114
|
},
|
|
106
|
-
initiateGoogleOAuth: () =>
|
|
107
|
-
initiateGitHubOAuth: () =>
|
|
108
|
-
initiateMicrosoftOAuth: () =>
|
|
109
|
-
isProviderConfigured: (e) => !!
|
|
110
|
-
|
|
111
|
-
VITE_GITHUB_CLIENT_ID: void 0,
|
|
112
|
-
VITE_MICROSOFT_CLIENT_ID: void 0
|
|
113
|
-
}[i[e].clientIdEnvKey],
|
|
114
|
-
isLoading: d
|
|
115
|
+
initiateGoogleOAuth: () => m("google"),
|
|
116
|
+
initiateGitHubOAuth: () => m("github"),
|
|
117
|
+
initiateMicrosoftOAuth: () => m("microsoft"),
|
|
118
|
+
isProviderConfigured: (e) => !!p(e),
|
|
119
|
+
isLoading: f
|
|
115
120
|
};
|
|
116
121
|
}
|
|
117
122
|
//#endregion
|
|
118
|
-
export {
|
|
123
|
+
export { u as useOAuthOperations };
|
|
119
124
|
|
|
120
125
|
//# sourceMappingURL=useOAuthOperations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOAuthOperations.js","names":[],"sources":["../../../src/auth/hooks/useOAuthOperations.ts"],"sourcesContent":["import { useMutation } from \"@apollo/client/react\";\nimport { useAuthStore } from \"../store/authStore\";\nimport { useAuth } from \"../providers/AuthProvider\";\nimport type { AuthResult, OAuthInput } from \"../types\";\n\nimport { AuthenticateOAuthDocument } from \"../../generated/global-operations\";\n\n// =============================================================================\n// GRAPHQL RESPONSE INTERFACES\n// =============================================================================\n\ninterface AuthenticateOAuthResponse {\n authenticateOAuth: AuthResult;\n}\n\ninterface AuthenticateOAuthVariables {\n input: OAuthInput;\n}\n\n/**\n * Supported OAuth providers\n */\nexport type OAuthProvider = \"google\" | \"github\" | \"microsoft\";\n\n/**\n * OAuth configuration for each provider\n */\ninterface OAuthConfig {\n authorizationUrl: string;\n scopes: string[];\n clientIdEnvKey: string;\n}\n\nconst OAUTH_CONFIGS: Record<OAuthProvider, OAuthConfig> = {\n google: {\n authorizationUrl: \"https://accounts.google.com/o/oauth2/v2/auth\",\n scopes: [\"openid\", \"email\", \"profile\"],\n clientIdEnvKey: \"VITE_GOOGLE_CLIENT_ID\",\n },\n github: {\n authorizationUrl: \"https://github.com/login/oauth/authorize\",\n scopes: [\"user:email\", \"read:user\"],\n clientIdEnvKey: \"VITE_GITHUB_CLIENT_ID\",\n },\n microsoft: {\n authorizationUrl:\n \"https://login.microsoftonline.com/common/oauth2/v2.0/authorize\",\n scopes: [\"openid\", \"email\", \"profile\"],\n clientIdEnvKey: \"VITE_MICROSOFT_CLIENT_ID\",\n },\n};\n\n/**\n * Generate a random state parameter for CSRF protection\n */\nfunction generateState(): string {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return Array.from(array, (byte) => byte.toString(16).padStart(2, \"0\")).join(\n \"\",\n );\n}\n\n/**\n * Detect whether the bundle is running inside a native shell (Capacitor on\n * iOS/Android, or Electron). Mirrors the helper in LoginPage so OAuth\n * initiation can swap to a custom-scheme redirect_uri + system-browser\n * hand-off — the only flow OAuth providers will accept from a single-device\n * install.\n */\nfunction isNativeShell(): boolean {\n if (typeof window === \"undefined\") return false;\n const w = window as typeof window & {\n Capacitor?: { isNativePlatform?: () => boolean };\n };\n if (typeof w.Capacitor?.isNativePlatform === \"function\") {\n try {\n if (w.Capacitor.isNativePlatform()) return true;\n } catch {\n /* fall through */\n }\n }\n if (\n typeof navigator !== \"undefined\" &&\n /Electron/i.test(navigator.userAgent || \"\")\n ) {\n return true;\n }\n return false;\n}\n\n/**\n * Custom-scheme redirect URI used in native shells. The scheme is registered\n * by the host shell (Electron `setAsDefaultProtocolClient`, iOS Info.plist\n * CFBundleURLTypes, Android intent-filter). The OS routes the provider's\n * callback back to the running app, which forwards it to React Router via\n * the host's deep-link handler.\n *\n * IMPORTANT: This redirect URI MUST be registered for the OAuth client in\n * each provider's console:\n * - Google Cloud Console → Credentials → OAuth client → add\n * `vibecontrols://app/auth/oauth/callback` (Installed App).\n * - Microsoft Entra App registration → Authentication → register the\n * same custom-scheme redirect URI as a mobile/desktop redirect.\n * The backend `authenticateOAuth` mutation must also accept this redirectUri\n * verbatim during the code exchange.\n */\nconst NATIVE_OAUTH_REDIRECT_URI = \"vibecontrols://app/auth/oauth/callback\";\n\nasync function openOAuthAuthorizationUrl(authUrl: string): Promise<void> {\n if (typeof window === \"undefined\") return;\n const opener = (\n window as typeof window & {\n __burdenoffOpenExternal?: (url: string) => Promise<boolean>;\n }\n ).__burdenoffOpenExternal;\n if (typeof opener === \"function\") {\n try {\n const ok = await opener(authUrl);\n if (ok) return;\n } catch {\n /* fall through to legacy hand-off */\n }\n }\n // Browser fallback: same-window navigation (current production behavior).\n window.location.href = authUrl;\n}\n\n/**\n * Hook for OAuth authentication operations\n */\nexport function useOAuthOperations() {\n const context = useAuth();\n const [authenticateOAuthMutation, { loading }] = useMutation<\n AuthenticateOAuthResponse,\n AuthenticateOAuthVariables\n >(AuthenticateOAuthDocument);\n\n /**\n * Initiate OAuth flow by redirecting to the provider\n * @param provider - The OAuth provider to use\n */\n const initiateOAuth = (provider: OAuthProvider) => {\n const config = OAUTH_CONFIGS[provider];\n\n // Get client ID from environment\n // In Vite, environment variables are accessed via import.meta.env\n const envVars: Record<string, string | undefined> = {\n VITE_GOOGLE_CLIENT_ID: import.meta.env.VITE_GOOGLE_CLIENT_ID,\n VITE_GITHUB_CLIENT_ID: import.meta.env.VITE_GITHUB_CLIENT_ID,\n VITE_MICROSOFT_CLIENT_ID: import.meta.env.VITE_MICROSOFT_CLIENT_ID,\n };\n const clientId = envVars[config.clientIdEnvKey];\n\n if (!clientId) {\n console.error(`OAuth client ID not configured for ${provider}`);\n throw new Error(\n `${provider} OAuth is not configured. Please set ${config.clientIdEnvKey} environment variable.`,\n );\n }\n\n // Generate state for CSRF protection and store it\n // Use localStorage instead of sessionStorage for better persistence across redirects\n const state = generateState();\n localStorage.setItem(\"oauth_state\", state);\n localStorage.setItem(\"oauth_provider\", provider);\n\n // Native shells (Electron, Capacitor) can't use the current origin as the\n // redirect_uri — `vibecontrols://app` / `https://localhost` aren't valid\n // registered URIs at OAuth providers. Use a custom-scheme URL that the\n // host shell has registered as a deep-link target; the OS will route the\n // provider's callback back into the running app.\n const redirectUri = isNativeShell()\n ? NATIVE_OAUTH_REDIRECT_URI\n : `${window.location.origin}/auth/oauth/callback`;\n localStorage.setItem(\"oauth_redirect_uri\", redirectUri);\n\n // Build authorization URL\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: redirectUri,\n response_type: \"code\",\n scope: config.scopes.join(\" \"),\n state: state,\n // Google-specific: force account selection\n ...(provider === \"google\" && { prompt: \"select_account\" }),\n // Google-specific: enable offline access for refresh token\n ...(provider === \"google\" && { access_type: \"offline\" }),\n });\n\n const authUrl = `${config.authorizationUrl}?${params.toString()}`;\n\n // Hand off to the system browser in native shells (keeps the embedded\n // webview in place so the deep-link callback can return cleanly). On the\n // web this falls back to same-window navigation.\n void openOAuthAuthorizationUrl(authUrl);\n };\n\n /**\n * Complete OAuth flow by exchanging authorization code for tokens\n * Called from the callback page after provider redirects back\n * @param code - Authorization code from OAuth provider\n * @param state - State parameter for CSRF validation\n */\n const completeOAuth = async (\n code: string,\n state: string,\n ): Promise<AuthResult> => {\n const store = useAuthStore.getState();\n\n // Validate state parameter\n const storedState = localStorage.getItem(\"oauth_state\");\n if (!storedState || storedState !== state) {\n console.error(\"[OAuth Complete] State mismatch!\", {\n storedState,\n urlState: state,\n });\n throw new Error(\"Invalid OAuth state. Please try again.\");\n }\n\n // Get provider and redirect URI from localStorage\n const provider = localStorage.getItem(\"oauth_provider\") as OAuthProvider;\n const redirectUri = localStorage.getItem(\"oauth_redirect_uri\");\n\n if (!provider || !redirectUri) {\n console.error(\"[OAuth Complete] Missing provider or redirectUri\");\n throw new Error(\"OAuth session data missing. Please try again.\");\n }\n\n // Clear localStorage\n localStorage.removeItem(\"oauth_state\");\n localStorage.removeItem(\"oauth_provider\");\n localStorage.removeItem(\"oauth_redirect_uri\");\n\n try {\n store.setLoading(true);\n store.setError(null);\n\n // Call backend mutation to exchange code for tokens\n const { data, error } = await authenticateOAuthMutation({\n variables: {\n input: {\n provider: provider.toUpperCase(),\n code,\n redirectUri,\n },\n },\n });\n\n if (!data?.authenticateOAuth) {\n const errMsg =\n error?.message ?? \"OAuth authentication failed. Please try again.\";\n throw new Error(errMsg);\n }\n\n const result = data.authenticateOAuth;\n\n if (result.requiresMFA) {\n store.setMfaRequired(true, result.mfaChallengeId || undefined);\n return result;\n }\n\n if (result.success && result.user && result.token) {\n store.setUser(result.user);\n store.setAuthTokens(result.token, result.refreshToken || \"\");\n store.setAuthenticated(true);\n store.setMfaRequired(false);\n\n context.onAuthSuccess?.(\n result.user,\n result.token,\n result.refreshToken || undefined,\n );\n } else if (result.error) {\n store.setError(result.error);\n }\n\n return result;\n } catch (err) {\n const message =\n err instanceof Error ? err.message : \"OAuth authentication failed\";\n store.setError(message);\n throw err;\n } finally {\n store.setLoading(false);\n }\n };\n\n /**\n * Convenience method to initiate Google OAuth\n */\n const initiateGoogleOAuth = () => initiateOAuth(\"google\");\n\n /**\n * Convenience method to initiate GitHub OAuth\n */\n const initiateGitHubOAuth = () => initiateOAuth(\"github\");\n\n /**\n * Convenience method to initiate Microsoft OAuth\n */\n const initiateMicrosoftOAuth = () => initiateOAuth(\"microsoft\");\n\n /**\n * Check if a provider is configured (has client ID)\n */\n const isProviderConfigured = (provider: OAuthProvider): boolean => {\n const envVars: Record<string, string | undefined> = {\n VITE_GOOGLE_CLIENT_ID: import.meta.env.VITE_GOOGLE_CLIENT_ID,\n VITE_GITHUB_CLIENT_ID: import.meta.env.VITE_GITHUB_CLIENT_ID,\n VITE_MICROSOFT_CLIENT_ID: import.meta.env.VITE_MICROSOFT_CLIENT_ID,\n };\n const config = OAUTH_CONFIGS[provider];\n const clientId = envVars[config.clientIdEnvKey];\n return !!clientId;\n };\n\n return {\n initiateOAuth,\n completeOAuth,\n initiateGoogleOAuth,\n initiateGitHubOAuth,\n initiateMicrosoftOAuth,\n isProviderConfigured,\n isLoading: loading,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useOAuthOperations.js","names":[],"sources":["../../../src/auth/hooks/useOAuthOperations.ts"],"sourcesContent":["import { useMutation } from \"@apollo/client/react\";\nimport { useAuthStore } from \"../store/authStore\";\nimport { useAuth } from \"../providers/AuthProvider\";\nimport type { AuthResult, OAuthInput } from \"../types\";\n\nimport { AuthenticateOAuthDocument } from \"../../generated/global-operations\";\n\n// =============================================================================\n// GRAPHQL RESPONSE INTERFACES\n// =============================================================================\n\ninterface AuthenticateOAuthResponse {\n authenticateOAuth: AuthResult;\n}\n\ninterface AuthenticateOAuthVariables {\n input: OAuthInput;\n}\n\n/**\n * Supported OAuth providers\n */\nexport type OAuthProvider = \"google\" | \"github\" | \"microsoft\";\n\n/**\n * OAuth configuration for each provider\n */\ninterface OAuthConfig {\n authorizationUrl: string;\n scopes: string[];\n clientIdEnvKey: string;\n}\n\nconst OAUTH_CONFIGS: Record<OAuthProvider, OAuthConfig> = {\n google: {\n authorizationUrl: \"https://accounts.google.com/o/oauth2/v2/auth\",\n scopes: [\"openid\", \"email\", \"profile\"],\n clientIdEnvKey: \"VITE_GOOGLE_CLIENT_ID\",\n },\n github: {\n authorizationUrl: \"https://github.com/login/oauth/authorize\",\n scopes: [\"user:email\", \"read:user\"],\n clientIdEnvKey: \"VITE_GITHUB_CLIENT_ID\",\n },\n microsoft: {\n authorizationUrl:\n \"https://login.microsoftonline.com/common/oauth2/v2.0/authorize\",\n scopes: [\"openid\", \"email\", \"profile\"],\n clientIdEnvKey: \"VITE_MICROSOFT_CLIENT_ID\",\n },\n};\n\n/**\n * Generate a random state parameter for CSRF protection\n */\nfunction generateState(): string {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return Array.from(array, (byte) => byte.toString(16).padStart(2, \"0\")).join(\n \"\",\n );\n}\n\n/**\n * Read a Vite env var by key via a dynamic (non-statically-analyzable) lookup.\n *\n * Build-time composition compiles THIS package into its own npm dist first —\n * where `VITE_GOOGLE_CLIENT_ID` / `VITE_MICROSOFT_CLIENT_ID` are unset — and\n * only later bundles that dist into a host app shell. A direct\n * `import.meta.env.VITE_GOOGLE_CLIENT_ID` member read is statically replaced\n * with `undefined` during this package's build, so it ships dead and the host\n * shell's build value can never reach it (this is exactly why the SSO buttons\n * rendered permanently disabled).\n *\n * Reading the whole `import.meta.env` object and indexing it dynamically leaves\n * the lookup to runtime, so the value baked into `import.meta.env` by the HOST\n * app shell's build wins. Same pattern fe-libs uses for `VITE_GATEWAY_TARGET`.\n */\nfunction readViteEnv(key: string): string | undefined {\n try {\n const env = (import.meta as { env?: Record<string, string | undefined> })\n .env;\n return env?.[key];\n } catch {\n return undefined;\n }\n}\n\n/**\n * Detect whether the bundle is running inside a native shell (Capacitor on\n * iOS/Android, or Electron). Mirrors the helper in LoginPage so OAuth\n * initiation can swap to a custom-scheme redirect_uri + system-browser\n * hand-off — the only flow OAuth providers will accept from a single-device\n * install.\n */\nfunction isNativeShell(): boolean {\n if (typeof window === \"undefined\") return false;\n const w = window as typeof window & {\n Capacitor?: { isNativePlatform?: () => boolean };\n };\n if (typeof w.Capacitor?.isNativePlatform === \"function\") {\n try {\n if (w.Capacitor.isNativePlatform()) return true;\n } catch {\n /* fall through */\n }\n }\n if (\n typeof navigator !== \"undefined\" &&\n /Electron/i.test(navigator.userAgent || \"\")\n ) {\n return true;\n }\n return false;\n}\n\n/**\n * Custom-scheme redirect URI used in native shells. The scheme is registered\n * by the host shell (Electron `setAsDefaultProtocolClient`, iOS Info.plist\n * CFBundleURLTypes, Android intent-filter). The OS routes the provider's\n * callback back to the running app, which forwards it to React Router via\n * the host's deep-link handler.\n *\n * IMPORTANT: This redirect URI MUST be registered for the OAuth client in\n * each provider's console:\n * - Google Cloud Console → Credentials → OAuth client → add\n * `vibecontrols://app/auth/oauth/callback` (Installed App).\n * - Microsoft Entra App registration → Authentication → register the\n * same custom-scheme redirect URI as a mobile/desktop redirect.\n * The backend `authenticateOAuth` mutation must also accept this redirectUri\n * verbatim during the code exchange.\n */\nconst NATIVE_OAUTH_REDIRECT_URI = \"vibecontrols://app/auth/oauth/callback\";\n\nasync function openOAuthAuthorizationUrl(authUrl: string): Promise<void> {\n if (typeof window === \"undefined\") return;\n const opener = (\n window as typeof window & {\n __burdenoffOpenExternal?: (url: string) => Promise<boolean>;\n }\n ).__burdenoffOpenExternal;\n if (typeof opener === \"function\") {\n try {\n const ok = await opener(authUrl);\n if (ok) return;\n } catch {\n /* fall through to legacy hand-off */\n }\n }\n // Browser fallback: same-window navigation (current production behavior).\n window.location.href = authUrl;\n}\n\n/**\n * Hook for OAuth authentication operations\n */\nexport function useOAuthOperations() {\n const context = useAuth();\n const [authenticateOAuthMutation, { loading }] = useMutation<\n AuthenticateOAuthResponse,\n AuthenticateOAuthVariables\n >(AuthenticateOAuthDocument);\n\n /**\n * Resolve a provider's OAuth client ID.\n *\n * Priority:\n * 1. `oauthClientIds` injected by the host app shell — the only source that\n * works in published builds (see AuthRootProps.oauthClientIds for why a\n * direct `import.meta.env` read is baked dead at this package's build).\n * 2. `import.meta.env.VITE_*_CLIENT_ID` — fallback for when this package is\n * consumed from source in local dev (where the host's Vite build inlines\n * it into the same bundle).\n */\n const resolveClientId = (provider: OAuthProvider): string | undefined => {\n const fromHost = context.oauthClientIds?.[provider];\n if (fromHost) return fromHost;\n return readViteEnv(OAUTH_CONFIGS[provider].clientIdEnvKey);\n };\n\n /**\n * Initiate OAuth flow by redirecting to the provider\n * @param provider - The OAuth provider to use\n */\n const initiateOAuth = (provider: OAuthProvider) => {\n const config = OAUTH_CONFIGS[provider];\n\n // Client ID comes from the host app shell (see resolveClientId).\n const clientId = resolveClientId(provider);\n\n if (!clientId) {\n console.error(`OAuth client ID not configured for ${provider}`);\n throw new Error(\n `${provider} OAuth is not configured. Please set ${config.clientIdEnvKey} environment variable.`,\n );\n }\n\n // Generate state for CSRF protection and store it\n // Use localStorage instead of sessionStorage for better persistence across redirects\n const state = generateState();\n localStorage.setItem(\"oauth_state\", state);\n localStorage.setItem(\"oauth_provider\", provider);\n\n // Native shells (Electron, Capacitor) can't use the current origin as the\n // redirect_uri — `vibecontrols://app` / `https://localhost` aren't valid\n // registered URIs at OAuth providers. Use a custom-scheme URL that the\n // host shell has registered as a deep-link target; the OS will route the\n // provider's callback back into the running app.\n const redirectUri = isNativeShell()\n ? NATIVE_OAUTH_REDIRECT_URI\n : `${window.location.origin}/auth/oauth/callback`;\n localStorage.setItem(\"oauth_redirect_uri\", redirectUri);\n\n // Build authorization URL\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: redirectUri,\n response_type: \"code\",\n scope: config.scopes.join(\" \"),\n state: state,\n // Google-specific: force account selection\n ...(provider === \"google\" && { prompt: \"select_account\" }),\n // Google-specific: enable offline access for refresh token\n ...(provider === \"google\" && { access_type: \"offline\" }),\n });\n\n const authUrl = `${config.authorizationUrl}?${params.toString()}`;\n\n // Hand off to the system browser in native shells (keeps the embedded\n // webview in place so the deep-link callback can return cleanly). On the\n // web this falls back to same-window navigation.\n void openOAuthAuthorizationUrl(authUrl);\n };\n\n /**\n * Complete OAuth flow by exchanging authorization code for tokens\n * Called from the callback page after provider redirects back\n * @param code - Authorization code from OAuth provider\n * @param state - State parameter for CSRF validation\n */\n const completeOAuth = async (\n code: string,\n state: string,\n ): Promise<AuthResult> => {\n const store = useAuthStore.getState();\n\n // Validate state parameter\n const storedState = localStorage.getItem(\"oauth_state\");\n if (!storedState || storedState !== state) {\n console.error(\"[OAuth Complete] State mismatch!\", {\n storedState,\n urlState: state,\n });\n throw new Error(\"Invalid OAuth state. Please try again.\");\n }\n\n // Get provider and redirect URI from localStorage\n const provider = localStorage.getItem(\"oauth_provider\") as OAuthProvider;\n const redirectUri = localStorage.getItem(\"oauth_redirect_uri\");\n\n if (!provider || !redirectUri) {\n console.error(\"[OAuth Complete] Missing provider or redirectUri\");\n throw new Error(\"OAuth session data missing. Please try again.\");\n }\n\n // Clear localStorage\n localStorage.removeItem(\"oauth_state\");\n localStorage.removeItem(\"oauth_provider\");\n localStorage.removeItem(\"oauth_redirect_uri\");\n\n try {\n store.setLoading(true);\n store.setError(null);\n\n // Call backend mutation to exchange code for tokens\n const { data, error } = await authenticateOAuthMutation({\n variables: {\n input: {\n provider: provider.toUpperCase(),\n code,\n redirectUri,\n },\n },\n });\n\n if (!data?.authenticateOAuth) {\n const errMsg =\n error?.message ?? \"OAuth authentication failed. Please try again.\";\n throw new Error(errMsg);\n }\n\n const result = data.authenticateOAuth;\n\n if (result.requiresMFA) {\n store.setMfaRequired(true, result.mfaChallengeId || undefined);\n return result;\n }\n\n if (result.success && result.user && result.token) {\n store.setUser(result.user);\n store.setAuthTokens(result.token, result.refreshToken || \"\");\n store.setAuthenticated(true);\n store.setMfaRequired(false);\n\n context.onAuthSuccess?.(\n result.user,\n result.token,\n result.refreshToken || undefined,\n );\n } else if (result.error) {\n store.setError(result.error);\n }\n\n return result;\n } catch (err) {\n const message =\n err instanceof Error ? err.message : \"OAuth authentication failed\";\n store.setError(message);\n throw err;\n } finally {\n store.setLoading(false);\n }\n };\n\n /**\n * Convenience method to initiate Google OAuth\n */\n const initiateGoogleOAuth = () => initiateOAuth(\"google\");\n\n /**\n * Convenience method to initiate GitHub OAuth\n */\n const initiateGitHubOAuth = () => initiateOAuth(\"github\");\n\n /**\n * Convenience method to initiate Microsoft OAuth\n */\n const initiateMicrosoftOAuth = () => initiateOAuth(\"microsoft\");\n\n /**\n * Check if a provider is configured (has client ID)\n */\n const isProviderConfigured = (provider: OAuthProvider): boolean => {\n return !!resolveClientId(provider);\n };\n\n return {\n initiateOAuth,\n completeOAuth,\n initiateGoogleOAuth,\n initiateGitHubOAuth,\n initiateMicrosoftOAuth,\n isProviderConfigured,\n isLoading: loading,\n };\n}\n"],"mappings":"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"}
|
package/dist/microfe-auth.css
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
|
|
2
|
-
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:Inter, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";--font-mono:"JetBrains Mono", ui-monospace, monospace;--color-indigo-500:oklch(58.5% .233 277.117);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-2xl:42rem;--container-4xl:56rem;--container-5xl:64rem;--container-6xl:72rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-widest:.1em;--leading-tight:1.25;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--animate-spin:spin 1s linear infinite;--blur-sm:8px;--blur-3xl:64px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--radius:.5rem;--color-background:0 0% 100%;--color-foreground:222.2 84% 4.9%;--color-primary:221.2 83.2% 53.3%;--color-primary-foreground:210 40% 98%}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.inset-y-0{inset-block:calc(var(--spacing) * 0)}.-top-40{top:calc(var(--spacing) * -40)}.top-0{top:calc(var(--spacing) * 0)}.top-1\/2{top:50%}.top-4{top:calc(var(--spacing) * 4)}.top-full{top:100%}.-right-20{right:calc(var(--spacing) * -20)}.right-0{right:calc(var(--spacing) * 0)}.right-4{right:calc(var(--spacing) * 4)}.-bottom-40{bottom:calc(var(--spacing) * -40)}.bottom-0{bottom:calc(var(--spacing) * 0)}.-left-40{left:calc(var(--spacing) * -40)}.left-0{left:calc(var(--spacing) * 0)}.left-1\/4{left:25%}.z-10{z-index:10}.z-50{z-index:50}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mx-4{margin-inline:calc(var(--spacing) * 4)}.mx-auto{margin-inline:auto}.my-8{margin-block:calc(var(--spacing) * 8)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-10{margin-top:calc(var(--spacing) * 10)}.mt-12{margin-top:calc(var(--spacing) * 12)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.ml-3{margin-left:calc(var(--spacing) * 3)}.ml-4{margin-left:calc(var(--spacing) * 4)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.size-12{width:calc(var(--spacing) * 12);height:calc(var(--spacing) * 12)}.size-14{width:calc(var(--spacing) * 14);height:calc(var(--spacing) * 14)}.size-16{width:calc(var(--spacing) * 16);height:calc(var(--spacing) * 16)}.size-20{width:calc(var(--spacing) * 20);height:calc(var(--spacing) * 20)}.size-48{width:calc(var(--spacing) * 48);height:calc(var(--spacing) * 48)}.size-72{width:calc(var(--spacing) * 72);height:calc(var(--spacing) * 72)}.size-80{width:calc(var(--spacing) * 80);height:calc(var(--spacing) * 80)}.size-96{width:calc(var(--spacing) * 96);height:calc(var(--spacing) * 96)}.size-full{width:100%;height:100%}.h-0\.5{height:calc(var(--spacing) * .5)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-12{height:calc(var(--spacing) * 12)}.h-full{height:100%}.min-h-\[400px\]{min-height:400px}.min-h-screen{min-height:100vh}.w-1\/4{width:25%}.w-2\/4{width:50%}.w-3\/4{width:75%}.w-10{width:calc(var(--spacing) * 10)}.w-48{width:calc(var(--spacing) * 48)}.w-64{width:calc(var(--spacing) * 64)}.w-\[80px\]{width:80px}.w-\[100px\]{width:100px}.w-\[130px\]{width:130px}.w-\[180px\]{width:180px}.w-\[280px\]{width:280px}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-7xl{max-width:var(--container-7xl)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[200px\]{min-width:200px}.min-w-\[800px\]{min-width:800px}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.rotate-180{rotate:180deg}.animate-spin{animation:var(--animate-spin)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.list-inside{list-style-position:inside}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-nowrap{flex-wrap:nowrap}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.rounded{border-radius:var(--radius)}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-\[var\(--color-accent-primary\)\]{border-color:var(--color-accent-primary)}.border-\[var\(--color-border-default\)\]{border-color:var(--color-border-default)}.border-\[var\(--color-border-primary\)\]{border-color:var(--color-border-primary)}.border-\[var\(--color-border-subtle\)\]{border-color:var(--color-border-subtle)}.border-\[var\(--color-status-error-border\)\]{border-color:var(--color-status-error-border)}.border-\[var\(--color-status-success-border\)\]{border-color:var(--color-status-success-border)}.border-\[var\(--color-status-warning-border\)\]{border-color:var(--color-status-warning-border)}.border-primary{border-color:var(--color-primary)}.border-t-transparent{border-top-color:#0000}.bg-\[var\(--color-accent-primary\)\]{background-color:var(--color-accent-primary)}.bg-\[var\(--color-action-primary-bg\)\]{background-color:var(--color-action-primary-bg)}.bg-\[var\(--color-action-secondary-bg-subtle\)\]{background-color:var(--color-action-secondary-bg-subtle)}.bg-\[var\(--color-background-base\)\]{background-color:var(--color-background-base)}.bg-\[var\(--color-bg-accent\)\]{background-color:var(--color-bg-accent)}.bg-\[var\(--color-bg-canvas\)\]{background-color:var(--color-bg-canvas)}.bg-\[var\(--color-bg-disabled\)\]{background-color:var(--color-bg-disabled)}.bg-\[var\(--color-bg-muted\)\]{background-color:var(--color-bg-muted)}.bg-\[var\(--color-bg-sunken\)\]{background-color:var(--color-bg-sunken)}.bg-\[var\(--color-bg-surface\)\]{background-color:var(--color-bg-surface)}.bg-\[var\(--color-status-error-bg\)\]{background-color:var(--color-status-error-bg)}.bg-\[var\(--color-status-error-bg-subtle\)\]{background-color:var(--color-status-error-bg-subtle)}.bg-\[var\(--color-status-error-subtle\)\]{background-color:var(--color-status-error-subtle)}.bg-\[var\(--color-status-info-bg-subtle\)\]{background-color:var(--color-status-info-bg-subtle)}.bg-\[var\(--color-status-success-bg-subtle\)\]{background-color:var(--color-status-success-bg-subtle)}.bg-\[var\(--color-status-success-subtle\)\]{background-color:var(--color-status-success-subtle)}.bg-\[var\(--color-status-warning-bg\)\]{background-color:var(--color-status-warning-bg)}.bg-\[var\(--color-status-warning-bg-subtle\)\]{background-color:var(--color-status-warning-bg-subtle)}.bg-background{background-color:var(--color-background)}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab, red, red)){.bg-black\/40{background-color:color-mix(in oklab, var(--color-black) 40%, transparent)}}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab, red, red)){.bg-black\/50{background-color:color-mix(in oklab, var(--color-black) 50%, transparent)}}.bg-primary{background-color:var(--color-primary)}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.p-12{padding:calc(var(--spacing) * 12)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-12{padding-block:calc(var(--spacing) * 12)}.py-16{padding-block:calc(var(--spacing) * 16)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-12{padding-top:calc(var(--spacing) * 12)}.pr-3\.5{padding-right:calc(var(--spacing) * 3.5)}.pr-4{padding-right:calc(var(--spacing) * 4)}.pr-12{padding-right:calc(var(--spacing) * 12)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-3\.5{padding-left:calc(var(--spacing) * 3.5)}.pl-\[3\.5rem\]{padding-left:3.5rem}.pl-\[3\.25rem\]{padding-left:3.25rem}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.text-\[var\(--color-accent-primary\)\]{color:var(--color-accent-primary)}.text-\[var\(--color-action-primary-text\)\]{color:var(--color-action-primary-text)}.text-\[var\(--color-action-secondary-text\)\]{color:var(--color-action-secondary-text)}.text-\[var\(--color-status-error\)\]{color:var(--color-status-error)}.text-\[var\(--color-status-error-text\)\]{color:var(--color-status-error-text)}.text-\[var\(--color-status-info-text\)\]{color:var(--color-status-info-text)}.text-\[var\(--color-status-success\)\]{color:var(--color-status-success)}.text-\[var\(--color-status-success-text\)\]{color:var(--color-status-success-text)}.text-\[var\(--color-status-warning-text\)\]{color:var(--color-status-warning-text)}.text-\[var\(--color-text-disabled\)\]{color:var(--color-text-disabled)}.text-\[var\(--color-text-inverse\)\]{color:var(--color-text-inverse)}.text-\[var\(--color-text-link\)\]{color:var(--color-text-link)}.text-\[var\(--color-text-primary\)\]{color:var(--color-text-primary)}.text-\[var\(--color-text-secondary\)\]{color:var(--color-text-secondary)}.text-\[var\(--color-text-tertiary\)\]{color:var(--color-text-tertiary)}.text-foreground{color:var(--color-foreground)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-white{color:var(--color-white)}.text-white\/80{color:#fffc}@supports (color:color-mix(in lab, red, red)){.text-white\/80{color:color-mix(in oklab, var(--color-white) 80%, transparent)}}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.placeholder-\[var\(--color-text-secondary\)\]::placeholder{color:var(--color-text-secondary)}.opacity-0{opacity:0}.opacity-5{opacity:.05}.opacity-25{opacity:.25}.opacity-50{opacity:.5}.opacity-75{opacity:.75}.opacity-80{opacity:.8}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.blur-3xl{--tw-blur:blur(var(--blur-3xl));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,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.outline-none{--tw-outline-style:none;outline-style:none}.select-all{-webkit-user-select:all;user-select:all}@media (hover:hover){.group-hover\:scale-110:is(:where(.group):hover *){--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x) var(--tw-scale-y)}.group-hover\:bg-\[var\(--color-action-primary-bg-subtle\)\]:is(:where(.group):hover *){background-color:var(--color-action-primary-bg-subtle)}.group-hover\:bg-\[var\(--color-action-secondary-bg-subtle\)\]:is(:where(.group):hover *){background-color:var(--color-action-secondary-bg-subtle)}.group-hover\:text-\[var\(--color-text-primary\)\]:is(:where(.group):hover *){color:var(--color-text-primary)}.group-hover\:text-indigo-500:is(:where(.group):hover *){color:var(--color-indigo-500)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.peer-checked\:opacity-100:is(:where(.peer):checked~*){opacity:1}.peer-focus\:ring-2:is(:where(.peer):focus~*){--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.placeholder\:text-\[var\(--color-text-tertiary\)\]::placeholder{color:var(--color-text-tertiary)}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:border-\[var\(--color-action-primary-border\)\]:hover{border-color:var(--color-action-primary-border)}.hover\:border-\[var\(--color-action-secondary-border\)\]:hover{border-color:var(--color-action-secondary-border)}.hover\:border-\[var\(--color-border-strong\)\]:hover{border-color:var(--color-border-strong)}.hover\:bg-\[var\(--color-accent-primary-hover\)\]:hover{background-color:var(--color-accent-primary-hover)}.hover\:bg-\[var\(--color-action-primary-bgHover\)\]:hover{background-color:var(--color-action-primary-bgHover)}.hover\:bg-\[var\(--color-bg-muted\)\]:hover{background-color:var(--color-bg-muted)}.hover\:bg-\[var\(--color-bg-subtle\)\]:hover{background-color:var(--color-bg-subtle)}.hover\:bg-\[var\(--color-bg-sunken\)\]:hover{background-color:var(--color-bg-sunken)}.hover\:bg-\[var\(--color-status-error-bg-subtle\)\]:hover{background-color:var(--color-status-error-bg-subtle)}.hover\:bg-primary\/90:hover{background-color:color-mix(in srgb, 221.2 83.2% 53.3% 90%, transparent)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--color-primary) 90%, transparent)}}.hover\:text-\[var\(--color-text-primary\)\]:hover{color:var(--color-text-primary)}.hover\:text-\[var\(--color-text-secondary\)\]:hover{color:var(--color-text-secondary)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-90:hover{opacity:.9}.hover\:shadow-lg:hover{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}}.focus\:border-primary:focus{border-color:var(--color-primary)}.focus\:border-transparent:focus{border-color:#0000}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-\[var\(--color-accent-primary\)\]:focus{--tw-ring-color:var(--color-accent-primary)}.focus\:ring-primary\/20:focus{--tw-ring-color:color-mix(in srgb, 221.2 83.2% 53.3% 20%, transparent)}@supports (color:color-mix(in lab, red, red)){.focus\:ring-primary\/20:focus{--tw-ring-color:color-mix(in oklab, var(--color-primary) 20%, transparent)}}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.disabled\:shadow-none:disabled{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}@media (width>=40rem){.sm\:not-sr-only{clip-path:none;white-space:normal;width:auto;height:auto;margin:0;padding:0;position:static;overflow:visible}.sm\:top-6{top:calc(var(--spacing) * 6)}.sm\:right-6{right:calc(var(--spacing) * 6)}.sm\:col-span-2{grid-column:span 2/span 2}.sm\:block{display:block}.sm\:inline{display:inline}.sm\:h-14{height:calc(var(--spacing) * 14)}.sm\:w-12{width:calc(var(--spacing) * 12)}.sm\:w-auto{width:auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:gap-3{gap:calc(var(--spacing) * 3)}.sm\:p-12{padding:calc(var(--spacing) * 12)}.sm\:text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.sm\:text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}}@media (width>=48rem){.md\:col-span-2{grid-column:span 2/span 2}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:justify-between{justify-content:space-between}}@media (width>=64rem){.lg\:col-span-1{grid-column:span 1/span 1}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:w-1\/2{width:50%}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:text-left{text-align:left}}}.dark{--color-background:222.2 84% 4.9%;--color-foreground:210 40% 98%;--color-card:222.2 84% 4.9%;--color-card-foreground:210 40% 98%;--color-popover:222.2 84% 4.9%;--color-popover-foreground:210 40% 98%;--color-primary:217.2 91.2% 59.8%;--color-primary-foreground:222.2 47.4% 11.2%;--color-secondary:217.2 32.6% 17.5%;--color-secondary-foreground:210 40% 98%;--color-muted:217.2 32.6% 17.5%;--color-muted-foreground:215 20.2% 65.1%;--color-accent:217.2 32.6% 17.5%;--color-accent-foreground:210 40% 98%;--color-destructive:0 62.8% 30.6%;--color-destructive-foreground:210 40% 98%;--color-border:217.2 32.6% 17.5%;--color-input:217.2 32.6% 17.5%;--color-ring:224.3 76.3% 48%}body{font-feature-settings:"rlig" 1, "calt" 1}.auth-primary-button{background:var(--color-action-primary-bg);color:var(--color-action-primary-text);box-shadow:0 12px 30px var(--color-action-primary-bg);border-radius:.75rem}@supports (color:color-mix(in lab, red, red)){.auth-primary-button{box-shadow:0 12px 30px color-mix(in srgb, var(--color-action-primary-bg) 24%, transparent)}}.auth-primary-button{transition:opacity .16s,transform .16s,box-shadow .16s,background-color .16s}.auth-primary-button:hover{opacity:.96;box-shadow:0 16px 36px var(--color-action-primary-bg)}@supports (color:color-mix(in lab, red, red)){.auth-primary-button:hover{box-shadow:0 16px 36px color-mix(in srgb, var(--color-action-primary-bg) 30%, transparent)}}.auth-primary-button:focus-visible{outline:2px solid var(--color-action-primary-bg)}@supports (color:color-mix(in lab, red, red)){.auth-primary-button:focus-visible{outline:2px solid color-mix(in srgb, var(--color-action-primary-bg) 45%, transparent)}}.auth-primary-button:focus-visible{outline-offset:2px}.auth-primary-button:disabled{cursor:not-allowed;opacity:.55;box-shadow:none}.auth-brand-badge{background:linear-gradient(135deg, var(--color-action-primary-bg) 0%, var(--color-action-primary-bg) 100%)}@supports (color:color-mix(in lab, red, red)){.auth-brand-badge{background:linear-gradient(135deg, color-mix(in srgb, var(--color-action-primary-bg) 92%, white 8%) 0%, color-mix(in srgb, var(--color-action-primary-bg) 72%, var(--color-bg-surface) 28%) 100%)}}.auth-brand-badge{color:var(--color-action-primary-text);box-shadow:0 12px 30px var(--color-action-primary-bg)}@supports (color:color-mix(in lab, red, red)){.auth-brand-badge{box-shadow:0 12px 30px color-mix(in srgb, var(--color-action-primary-bg) 22%, transparent)}}.auth-brand-panel{background:radial-gradient(circle at top left, var(--color-action-primary-bg) 0%, transparent 35%), radial-gradient(circle at bottom right, var(--color-text-link) 0%, transparent 38%), linear-gradient(135deg, var(--color-bg-surface) 0%, var(--color-bg-canvas) 100%)}@supports (color:color-mix(in lab, red, red)){.auth-brand-panel{background:radial-gradient(circle at top left, color-mix(in srgb, var(--color-action-primary-bg) 20%, transparent) 0%, transparent 35%), radial-gradient(circle at bottom right, color-mix(in srgb, var(--color-text-link) 18%, transparent) 0%, transparent 38%), linear-gradient(135deg, color-mix(in srgb, var(--color-bg-surface) 92%, black 8%) 0%, color-mix(in srgb, var(--color-bg-canvas) 70%, black 30%) 100%)}}.auth-brand-panel,.auth-brand-copy{color:var(--color-text-primary)}@supports (color:color-mix(in lab, red, red)){.auth-brand-copy{color:color-mix(in srgb, var(--color-text-primary) 88%, white 12%)}}.auth-brand-copy-muted{color:var(--color-text-secondary)}@supports (color:color-mix(in lab, red, red)){.auth-brand-copy-muted{color:color-mix(in srgb, var(--color-text-secondary) 75%, white 25%)}}.auth-highlight-chip{background:var(--color-bg-surface)}@supports (color:color-mix(in lab, red, red)){.auth-highlight-chip{background:color-mix(in srgb, var(--color-bg-surface) 84%, transparent)}}.auth-highlight-chip{border:1px solid var(--color-border-subtle)}@supports (color:color-mix(in lab, red, red)){.auth-highlight-chip{border:1px solid color-mix(in srgb, var(--color-border-subtle) 65%, transparent)}}.auth-highlight-chip{-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}.auth-shell-gradient{background:linear-gradient(180deg, var(--color-bg-canvas) 0%, var(--color-bg-surface) 100%)}@supports (color:color-mix(in lab, red, red)){.auth-shell-gradient{background:linear-gradient(180deg, color-mix(in srgb, var(--color-bg-canvas) 96%, transparent) 0%, color-mix(in srgb, var(--color-bg-surface) 96%, transparent) 100%)}}.auth-hero-card{background:linear-gradient(135deg, var(--color-action-primary-bg) 0%, var(--color-text-link) 100%)}@supports (color:color-mix(in lab, red, red)){.auth-hero-card{background:linear-gradient(135deg, color-mix(in srgb, var(--color-action-primary-bg) 90%, transparent) 0%, color-mix(in srgb, var(--color-text-link) 70%, var(--color-action-primary-bg) 30%) 100%)}}.auth-hero-card{color:var(--color-action-primary-text);box-shadow:0 18px 42px var(--color-action-primary-bg)}@supports (color:color-mix(in lab, red, red)){.auth-hero-card{box-shadow:0 18px 42px color-mix(in srgb, var(--color-action-primary-bg) 26%, transparent)}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@keyframes spin{to{transform:rotate(360deg)}}
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:Inter, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";--font-mono:"JetBrains Mono", ui-monospace, monospace;--color-indigo-500:oklch(58.5% .233 277.117);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-2xl:42rem;--container-4xl:56rem;--container-5xl:64rem;--container-6xl:72rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-widest:.1em;--leading-tight:1.25;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--animate-spin:spin 1s linear infinite;--blur-sm:8px;--blur-3xl:64px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--radius:.5rem;--color-background:0 0% 100%;--color-foreground:222.2 84% 4.9%;--color-primary:221.2 83.2% 53.3%;--color-primary-foreground:210 40% 98%}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.inset-y-0{inset-block:calc(var(--spacing) * 0)}.-top-40{top:calc(var(--spacing) * -40)}.top-0{top:calc(var(--spacing) * 0)}.top-1\/2{top:50%}.top-4{top:calc(var(--spacing) * 4)}.top-full{top:100%}.-right-20{right:calc(var(--spacing) * -20)}.right-0{right:calc(var(--spacing) * 0)}.right-4{right:calc(var(--spacing) * 4)}.-bottom-40{bottom:calc(var(--spacing) * -40)}.bottom-0{bottom:calc(var(--spacing) * 0)}.-left-40{left:calc(var(--spacing) * -40)}.left-0{left:calc(var(--spacing) * 0)}.left-1\/4{left:25%}.z-10{z-index:10}.z-50{z-index:50}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mx-4{margin-inline:calc(var(--spacing) * 4)}.mx-auto{margin-inline:auto}.my-8{margin-block:calc(var(--spacing) * 8)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-10{margin-top:calc(var(--spacing) * 10)}.mt-12{margin-top:calc(var(--spacing) * 12)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.ml-3{margin-left:calc(var(--spacing) * 3)}.ml-4{margin-left:calc(var(--spacing) * 4)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.size-12{width:calc(var(--spacing) * 12);height:calc(var(--spacing) * 12)}.size-14{width:calc(var(--spacing) * 14);height:calc(var(--spacing) * 14)}.size-16{width:calc(var(--spacing) * 16);height:calc(var(--spacing) * 16)}.size-20{width:calc(var(--spacing) * 20);height:calc(var(--spacing) * 20)}.size-48{width:calc(var(--spacing) * 48);height:calc(var(--spacing) * 48)}.size-72{width:calc(var(--spacing) * 72);height:calc(var(--spacing) * 72)}.size-80{width:calc(var(--spacing) * 80);height:calc(var(--spacing) * 80)}.size-96{width:calc(var(--spacing) * 96);height:calc(var(--spacing) * 96)}.size-full{width:100%;height:100%}.h-0\.5{height:calc(var(--spacing) * .5)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-12{height:calc(var(--spacing) * 12)}.h-full{height:100%}.min-h-\[400px\]{min-height:400px}.min-h-screen{min-height:100vh}.w-1\/4{width:25%}.w-2\/4{width:50%}.w-3\/4{width:75%}.w-10{width:calc(var(--spacing) * 10)}.w-48{width:calc(var(--spacing) * 48)}.w-64{width:calc(var(--spacing) * 64)}.w-\[80px\]{width:80px}.w-\[100px\]{width:100px}.w-\[130px\]{width:130px}.w-\[180px\]{width:180px}.w-\[280px\]{width:280px}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-7xl{max-width:var(--container-7xl)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[200px\]{min-width:200px}.min-w-\[800px\]{min-width:800px}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.rotate-180{rotate:180deg}.animate-spin{animation:var(--animate-spin)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.list-inside{list-style-position:inside}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-nowrap{flex-wrap:nowrap}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.rounded{border-radius:var(--radius)}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-\[var\(--color-accent-primary\)\]{border-color:var(--color-accent-primary)}.border-\[var\(--color-border-default\)\]{border-color:var(--color-border-default)}.border-\[var\(--color-border-primary\)\]{border-color:var(--color-border-primary)}.border-\[var\(--color-border-subtle\)\]{border-color:var(--color-border-subtle)}.border-\[var\(--color-status-error-border\)\]{border-color:var(--color-status-error-border)}.border-\[var\(--color-status-success-border\)\]{border-color:var(--color-status-success-border)}.border-\[var\(--color-status-warning-border\)\]{border-color:var(--color-status-warning-border)}.border-primary{border-color:var(--color-primary)}.border-t-transparent{border-top-color:#0000}.bg-\[var\(--color-accent-primary\)\]{background-color:var(--color-accent-primary)}.bg-\[var\(--color-action-primary-bg\)\]{background-color:var(--color-action-primary-bg)}.bg-\[var\(--color-action-secondary-bg-subtle\)\]{background-color:var(--color-action-secondary-bg-subtle)}.bg-\[var\(--color-background-base\)\]{background-color:var(--color-background-base)}.bg-\[var\(--color-bg-accent\)\]{background-color:var(--color-bg-accent)}.bg-\[var\(--color-bg-canvas\)\]{background-color:var(--color-bg-canvas)}.bg-\[var\(--color-bg-disabled\)\]{background-color:var(--color-bg-disabled)}.bg-\[var\(--color-bg-muted\)\]{background-color:var(--color-bg-muted)}.bg-\[var\(--color-bg-sunken\)\]{background-color:var(--color-bg-sunken)}.bg-\[var\(--color-bg-surface\)\]{background-color:var(--color-bg-surface)}.bg-\[var\(--color-status-error-bg\)\]{background-color:var(--color-status-error-bg)}.bg-\[var\(--color-status-error-bg-subtle\)\]{background-color:var(--color-status-error-bg-subtle)}.bg-\[var\(--color-status-error-subtle\)\]{background-color:var(--color-status-error-subtle)}.bg-\[var\(--color-status-info-bg-subtle\)\]{background-color:var(--color-status-info-bg-subtle)}.bg-\[var\(--color-status-success-bg-subtle\)\]{background-color:var(--color-status-success-bg-subtle)}.bg-\[var\(--color-status-success-subtle\)\]{background-color:var(--color-status-success-subtle)}.bg-\[var\(--color-status-warning-bg\)\]{background-color:var(--color-status-warning-bg)}.bg-\[var\(--color-status-warning-bg-subtle\)\]{background-color:var(--color-status-warning-bg-subtle)}.bg-background{background-color:var(--color-background)}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab, red, red)){.bg-black\/40{background-color:color-mix(in oklab, var(--color-black) 40%, transparent)}}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab, red, red)){.bg-black\/50{background-color:color-mix(in oklab, var(--color-black) 50%, transparent)}}.bg-primary{background-color:var(--color-primary)}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.p-12{padding:calc(var(--spacing) * 12)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-12{padding-block:calc(var(--spacing) * 12)}.py-16{padding-block:calc(var(--spacing) * 16)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-12{padding-top:calc(var(--spacing) * 12)}.pr-3\.5{padding-right:calc(var(--spacing) * 3.5)}.pr-4{padding-right:calc(var(--spacing) * 4)}.pr-12{padding-right:calc(var(--spacing) * 12)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-3\.5{padding-left:calc(var(--spacing) * 3.5)}.pl-\[3\.5rem\]{padding-left:3.5rem}.pl-\[3\.25rem\]{padding-left:3.25rem}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.text-\[var\(--color-accent-primary\)\]{color:var(--color-accent-primary)}.text-\[var\(--color-action-primary-text\)\]{color:var(--color-action-primary-text)}.text-\[var\(--color-action-secondary-text\)\]{color:var(--color-action-secondary-text)}.text-\[var\(--color-status-error\)\]{color:var(--color-status-error)}.text-\[var\(--color-status-error-text\)\]{color:var(--color-status-error-text)}.text-\[var\(--color-status-info-text\)\]{color:var(--color-status-info-text)}.text-\[var\(--color-status-success\)\]{color:var(--color-status-success)}.text-\[var\(--color-status-success-text\)\]{color:var(--color-status-success-text)}.text-\[var\(--color-status-warning-text\)\]{color:var(--color-status-warning-text)}.text-\[var\(--color-text-disabled\)\]{color:var(--color-text-disabled)}.text-\[var\(--color-text-inverse\)\]{color:var(--color-text-inverse)}.text-\[var\(--color-text-link\)\]{color:var(--color-text-link)}.text-\[var\(--color-text-primary\)\]{color:var(--color-text-primary)}.text-\[var\(--color-text-secondary\)\]{color:var(--color-text-secondary)}.text-\[var\(--color-text-tertiary\)\]{color:var(--color-text-tertiary)}.text-foreground{color:var(--color-foreground)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-white{color:var(--color-white)}.text-white\/80{color:#fffc}@supports (color:color-mix(in lab, red, red)){.text-white\/80{color:color-mix(in oklab, var(--color-white) 80%, transparent)}}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.placeholder-\[var\(--color-text-secondary\)\]::placeholder{color:var(--color-text-secondary)}.opacity-0{opacity:0}.opacity-5{opacity:.05}.opacity-25{opacity:.25}.opacity-50{opacity:.5}.opacity-75{opacity:.75}.opacity-80{opacity:.8}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.blur-3xl{--tw-blur:blur(var(--blur-3xl));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,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.outline-none{--tw-outline-style:none;outline-style:none}.select-all{-webkit-user-select:all;user-select:all}@media (hover:hover){.group-hover\:scale-110:is(:where(.group):hover *){--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x) var(--tw-scale-y)}.group-hover\:bg-\[var\(--color-action-primary-bg-subtle\)\]:is(:where(.group):hover *){background-color:var(--color-action-primary-bg-subtle)}.group-hover\:bg-\[var\(--color-action-secondary-bg-subtle\)\]:is(:where(.group):hover *){background-color:var(--color-action-secondary-bg-subtle)}.group-hover\:text-\[var\(--color-text-primary\)\]:is(:where(.group):hover *){color:var(--color-text-primary)}.group-hover\:text-indigo-500:is(:where(.group):hover *){color:var(--color-indigo-500)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.peer-checked\:opacity-100:is(:where(.peer):checked~*){opacity:1}.peer-focus\:ring-2:is(:where(.peer):focus~*){--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.placeholder\:text-\[var\(--color-text-tertiary\)\]::placeholder{color:var(--color-text-tertiary)}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:border-\[var\(--color-action-primary-border\)\]:hover{border-color:var(--color-action-primary-border)}.hover\:border-\[var\(--color-action-secondary-border\)\]:hover{border-color:var(--color-action-secondary-border)}.hover\:border-\[var\(--color-border-strong\)\]:hover{border-color:var(--color-border-strong)}.hover\:bg-\[var\(--color-accent-primary-hover\)\]:hover{background-color:var(--color-accent-primary-hover)}.hover\:bg-\[var\(--color-action-primary-bgHover\)\]:hover{background-color:var(--color-action-primary-bgHover)}.hover\:bg-\[var\(--color-bg-muted\)\]:hover{background-color:var(--color-bg-muted)}.hover\:bg-\[var\(--color-bg-subtle\)\]:hover{background-color:var(--color-bg-subtle)}.hover\:bg-\[var\(--color-bg-sunken\)\]:hover{background-color:var(--color-bg-sunken)}.hover\:bg-\[var\(--color-status-error-bg-subtle\)\]:hover{background-color:var(--color-status-error-bg-subtle)}.hover\:bg-primary\/90:hover{background-color:color-mix(in srgb, 221.2 83.2% 53.3% 90%, transparent)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--color-primary) 90%, transparent)}}.hover\:text-\[var\(--color-text-primary\)\]:hover{color:var(--color-text-primary)}.hover\:text-\[var\(--color-text-secondary\)\]:hover{color:var(--color-text-secondary)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-90:hover{opacity:.9}.hover\:shadow-lg:hover{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}}.focus\:border-primary:focus{border-color:var(--color-primary)}.focus\:border-transparent:focus{border-color:#0000}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-\[var\(--color-accent-primary\)\]:focus{--tw-ring-color:var(--color-accent-primary)}.focus\:ring-primary\/20:focus{--tw-ring-color:color-mix(in srgb, 221.2 83.2% 53.3% 20%, transparent)}@supports (color:color-mix(in lab, red, red)){.focus\:ring-primary\/20:focus{--tw-ring-color:color-mix(in oklab, var(--color-primary) 20%, transparent)}}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.disabled\:shadow-none:disabled{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}@media (width>=40rem){.sm\:not-sr-only{clip-path:none;white-space:normal;width:auto;height:auto;margin:0;padding:0;position:static;overflow:visible}.sm\:top-6{top:calc(var(--spacing) * 6)}.sm\:right-6{right:calc(var(--spacing) * 6)}.sm\:col-span-2{grid-column:span 2/span 2}.sm\:block{display:block}.sm\:inline{display:inline}.sm\:h-14{height:calc(var(--spacing) * 14)}.sm\:w-12{width:calc(var(--spacing) * 12)}.sm\:w-auto{width:auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:gap-3{gap:calc(var(--spacing) * 3)}.sm\:p-12{padding:calc(var(--spacing) * 12)}.sm\:text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.sm\:text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}}@media (width>=48rem){.md\:col-span-2{grid-column:span 2/span 2}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:justify-between{justify-content:space-between}}@media (width>=64rem){.lg\:col-span-1{grid-column:span 1/span 1}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:w-1\/2{width:50%}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:text-left{text-align:left}}}.dark{--color-background:222.2 84% 4.9%;--color-foreground:210 40% 98%;--color-card:222.2 84% 4.9%;--color-card-foreground:210 40% 98%;--color-popover:222.2 84% 4.9%;--color-popover-foreground:210 40% 98%;--color-primary:217.2 91.2% 59.8%;--color-primary-foreground:222.2 47.4% 11.2%;--color-secondary:217.2 32.6% 17.5%;--color-secondary-foreground:210 40% 98%;--color-muted:217.2 32.6% 17.5%;--color-muted-foreground:215 20.2% 65.1%;--color-accent:217.2 32.6% 17.5%;--color-accent-foreground:210 40% 98%;--color-destructive:0 62.8% 30.6%;--color-destructive-foreground:210 40% 98%;--color-border:217.2 32.6% 17.5%;--color-input:217.2 32.6% 17.5%;--color-ring:224.3 76.3% 48%}body{font-feature-settings:"rlig" 1, "calt" 1}.auth-primary-button{background:var(--color-action-primary-bg);color:var(--color-action-primary-text);box-shadow:0 12px 30px var(--color-action-primary-bg);border-radius:.75rem}@supports (color:color-mix(in lab, red, red)){.auth-primary-button{box-shadow:0 12px 30px color-mix(in srgb, var(--color-action-primary-bg) 24%, transparent)}}.auth-primary-button{transition:opacity .16s,transform .16s,box-shadow .16s,background-color .16s}.auth-primary-button:hover{opacity:.96;box-shadow:0 16px 36px var(--color-action-primary-bg)}@supports (color:color-mix(in lab, red, red)){.auth-primary-button:hover{box-shadow:0 16px 36px color-mix(in srgb, var(--color-action-primary-bg) 30%, transparent)}}.auth-primary-button:focus-visible{outline:2px solid var(--color-action-primary-bg)}@supports (color:color-mix(in lab, red, red)){.auth-primary-button:focus-visible{outline:2px solid color-mix(in srgb, var(--color-action-primary-bg) 45%, transparent)}}.auth-primary-button:focus-visible{outline-offset:2px}.auth-primary-button:disabled{cursor:not-allowed;opacity:.55;box-shadow:none}.auth-brand-badge{background:linear-gradient(135deg, var(--color-action-primary-bg) 0%, var(--color-action-primary-bg) 100%)}@supports (color:color-mix(in lab, red, red)){.auth-brand-badge{background:linear-gradient(135deg, color-mix(in srgb, var(--color-action-primary-bg) 92%, white 8%) 0%, color-mix(in srgb, var(--color-action-primary-bg) 72%, var(--color-bg-surface) 28%) 100%)}}.auth-brand-badge{color:var(--color-action-primary-text);box-shadow:0 12px 30px var(--color-action-primary-bg)}@supports (color:color-mix(in lab, red, red)){.auth-brand-badge{box-shadow:0 12px 30px color-mix(in srgb, var(--color-action-primary-bg) 22%, transparent)}}.auth-brand-panel{background:radial-gradient(circle at top left, var(--color-action-primary-bg) 0%, transparent 35%), radial-gradient(circle at bottom right, var(--color-text-link) 0%, transparent 38%), linear-gradient(135deg, var(--color-bg-surface) 0%, var(--color-bg-canvas) 100%)}@supports (color:color-mix(in lab, red, red)){.auth-brand-panel{background:radial-gradient(circle at top left, color-mix(in srgb, var(--color-action-primary-bg) 20%, transparent) 0%, transparent 35%), radial-gradient(circle at bottom right, color-mix(in srgb, var(--color-text-link) 18%, transparent) 0%, transparent 38%), linear-gradient(135deg, color-mix(in srgb, var(--color-bg-surface) 92%, black 8%) 0%, color-mix(in srgb, var(--color-bg-canvas) 70%, black 30%) 100%)}}.auth-brand-panel,.auth-brand-copy{color:var(--color-text-primary)}@supports (color:color-mix(in lab, red, red)){.auth-brand-copy{color:color-mix(in srgb, var(--color-text-primary) 88%, white 12%)}}.auth-brand-copy-muted{color:var(--color-text-secondary)}@supports (color:color-mix(in lab, red, red)){.auth-brand-copy-muted{color:color-mix(in srgb, var(--color-text-secondary) 75%, white 25%)}}.auth-highlight-chip{background:var(--color-bg-surface)}@supports (color:color-mix(in lab, red, red)){.auth-highlight-chip{background:color-mix(in srgb, var(--color-bg-surface) 84%, transparent)}}.auth-highlight-chip{border:1px solid var(--color-border-subtle)}@supports (color:color-mix(in lab, red, red)){.auth-highlight-chip{border:1px solid color-mix(in srgb, var(--color-border-subtle) 65%, transparent)}}.auth-highlight-chip{-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}.auth-shell-gradient{background:linear-gradient(180deg, var(--color-bg-canvas) 0%, var(--color-bg-surface) 100%)}@supports (color:color-mix(in lab, red, red)){.auth-shell-gradient{background:linear-gradient(180deg, color-mix(in srgb, var(--color-bg-canvas) 96%, transparent) 0%, color-mix(in srgb, var(--color-bg-surface) 96%, transparent) 100%)}}.auth-hero-card{background:linear-gradient(135deg, var(--color-action-primary-bg) 0%, var(--color-text-link) 100%)}@supports (color:color-mix(in lab, red, red)){.auth-hero-card{background:linear-gradient(135deg, color-mix(in srgb, var(--color-action-primary-bg) 90%, transparent) 0%, color-mix(in srgb, var(--color-text-link) 70%, var(--color-action-primary-bg) 30%) 100%)}}.auth-hero-card{color:var(--color-action-primary-text);box-shadow:0 18px 42px var(--color-action-primary-bg)}@supports (color:color-mix(in lab, red, red)){.auth-hero-card{box-shadow:0 18px 42px color-mix(in srgb, var(--color-action-primary-bg) 26%, transparent)}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@keyframes spin{to{transform:rotate(360deg)}}
|
|
3
3
|
/*$vite$:1*/
|