@alexkroman1/aai-ui 6.11.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -3
- package/dist/_run-controls.d.ts +33 -0
- package/dist/{chat-view-ByQFf94G.js → chat-view-BKsFfFZJ.js} +57 -11
- package/dist/client-config-B4nznRvH.js +134 -0
- package/dist/client-config.d.ts +45 -2
- package/dist/client-dir.d.ts +3 -1
- package/dist/client-dir.js +3 -1
- package/dist/components/auto-scroll.d.ts +24 -13
- package/dist/components/button.d.ts +8 -4
- package/dist/components/button.js +4 -4
- package/dist/components/chat-view.d.ts +4 -3
- package/dist/components/chat-view.js +1 -1
- package/dist/components/console-shell.d.ts +71 -10
- package/dist/components/controls.d.ts +15 -4
- package/dist/components/controls.js +48 -2
- package/dist/components/form-fields.d.ts +142 -0
- package/dist/components/form-types.d.ts +6 -0
- package/dist/components/form.d.ts +38 -80
- package/dist/components/markdown.d.ts +31 -5
- package/dist/components/message-list.d.ts +21 -4
- package/dist/components/message-list.js +1 -1
- package/dist/components/sidebar-layout.d.ts +11 -0
- package/dist/components/sidebar-layout.js +2 -0
- package/dist/components/start-screen.d.ts +8 -0
- package/dist/components/start-screen.js +2 -0
- package/dist/components/tool-call-block.js +1 -1
- package/dist/components/tool-call-row.d.ts +24 -0
- package/dist/components/upload-progress.d.ts +17 -7
- package/dist/components/workflow-fields.d.ts +10 -22
- package/dist/components/workflow-progress.d.ts +29 -10
- package/dist/context.d.ts +36 -0
- package/dist/context.js +105 -14
- package/dist/default-client/assets/index-S5fkKi6B.css +2 -0
- package/dist/default-client/assets/index-fEkrcZgo.js +293 -0
- package/dist/default-client/index.html +2 -2
- package/dist/define-client.d.ts +67 -62
- package/dist/define-client.js +56 -22
- package/dist/hooks.d.ts +88 -3
- package/dist/index.d.ts +12 -11
- package/dist/index.js +501 -167
- package/dist/internal.d.ts +40 -0
- package/dist/internal.js +6 -0
- package/dist/{message-list-CpPV7dGx.js → message-list-DHddO4QC.js} +217 -72
- package/dist/{session-core-CAfYmUbg.js → session-core-C2JtLArh.js} +267 -165
- package/dist/session-core-audio-setup.d.ts +3 -0
- package/dist/session-core-messages.d.ts +3 -0
- package/dist/session-core-state.d.ts +146 -0
- package/dist/session-core-types.d.ts +77 -32
- package/dist/session-core.d.ts +3 -2
- package/dist/session-core.js +1 -1
- package/dist/{tool-call-block-D6pTEPrT.js → tool-call-block-DoF-cSIZ.js} +27 -19
- package/dist/tool-config-context-DzAofqi_.js +19 -0
- package/dist/types.d.ts +31 -5
- package/dist/types.js +5 -4
- package/dist/{controls-CjG91QJ4.js → url-chips-DpM7Oocj.js} +3 -46
- package/dist/use-conversation.d.ts +122 -0
- package/dist/use-download-url.d.ts +83 -0
- package/dist/use-workflow-form.d.ts +59 -3
- package/dist/use-workflow-run.d.ts +35 -0
- package/dist/use-workflow-stream.d.ts +36 -62
- package/dist/workflow-client.d.ts +36 -11
- package/dist/workflow-status-labels.d.ts +35 -0
- package/package.json +10 -5
- package/styles.css +14 -0
- package/dist/default-client/assets/index-DTLrhtTF.css +0 -2
- package/dist/default-client/assets/index-DXODx_9r.js +0 -293
|
@@ -46,6 +46,30 @@ export interface ToolCallRowProps {
|
|
|
46
46
|
* Colors come from the nearest theme context (see {@link useTheme}); without
|
|
47
47
|
* a provider the default AssemblyAI theme applies.
|
|
48
48
|
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```tsx
|
|
51
|
+
* import { ToolCallRow, useSession } from "@alexkroman1/aai-ui";
|
|
52
|
+
*
|
|
53
|
+
* // A custom chrome's tool log, from the snapshot's own `toolCalls`.
|
|
54
|
+
* function ToolLog() {
|
|
55
|
+
* const { toolCalls } = useSession();
|
|
56
|
+
* return (
|
|
57
|
+
* <div>
|
|
58
|
+
* {toolCalls.map((call) => (
|
|
59
|
+
* <ToolCallRow
|
|
60
|
+
* key={call.callId}
|
|
61
|
+
* title={call.name}
|
|
62
|
+
* detail={call.result}
|
|
63
|
+
* pending={call.status === "pending"}
|
|
64
|
+
* />
|
|
65
|
+
* ))}
|
|
66
|
+
* </div>
|
|
67
|
+
* );
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* @param props - See {@link ToolCallRowProps}.
|
|
72
|
+
*
|
|
49
73
|
* @public
|
|
50
74
|
*/
|
|
51
75
|
export declare function ToolCallRow({ title, detail, pending, icon, variant, className, children, }: ToolCallRowProps): ReactNode;
|
|
@@ -47,19 +47,29 @@ import type { UploadStatus } from "../use-workflow-form.ts";
|
|
|
47
47
|
* }
|
|
48
48
|
* ```
|
|
49
49
|
*
|
|
50
|
-
* @param
|
|
51
|
-
* so a page may pass its state straight through.
|
|
52
|
-
* @param onPause - The hook's `pauseUpload`. Pass it together with `onResume` to
|
|
53
|
-
* get the control; pass neither for a bar that only reports.
|
|
54
|
-
* @param onResume - The hook's `resumeUpload`.
|
|
55
|
-
* @param className - Replaces the default classes rather than extending them,
|
|
56
|
-
* so a custom chrome is not fighting a default it did not ask for.
|
|
50
|
+
* @param props - Progress-bar props.
|
|
57
51
|
*
|
|
58
52
|
* @public
|
|
59
53
|
*/
|
|
60
54
|
export declare function UploadProgressBar({ upload, onPause, onResume, className, }: {
|
|
55
|
+
/**
|
|
56
|
+
* What `useWorkflowSubmit` / `useWorkflowStream` report as `upload`.
|
|
57
|
+
* `undefined` renders nothing, so a page may pass its state straight through
|
|
58
|
+
* and never guard the element.
|
|
59
|
+
*/
|
|
61
60
|
upload?: UploadStatus | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* The hook's `pauseUpload`. **Pass it together with `onResume`** to get the
|
|
63
|
+
* pause control; pass neither for a bar that only reports. One without the
|
|
64
|
+
* other is a one-way door drawn as a toggle, so the control is hidden unless
|
|
65
|
+
* both are present.
|
|
66
|
+
*/
|
|
62
67
|
onPause?: (() => void) | undefined;
|
|
68
|
+
/** The hook's `resumeUpload`. See `onPause` — the two travel together. */
|
|
63
69
|
onResume?: (() => void) | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* **Replaces** the default classes rather than extending them, so a custom
|
|
72
|
+
* chrome is not fighting a default it did not ask for.
|
|
73
|
+
*/
|
|
64
74
|
className?: string | undefined;
|
|
65
75
|
}): ReactNode;
|
|
@@ -1,24 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* A form built from a workflow's declared input schema.
|
|
4
|
-
*
|
|
5
|
-
* `GET workflows` reports each workflow's `inputSchema` as JSON Schema — the
|
|
6
|
-
* zod schema an author wrote in `agent.ts`, converted at listing time precisely
|
|
7
|
-
* so a browser can read it. This is what reads it: one `<WorkflowFields>` and a
|
|
8
|
-
* workflow's form matches its schema by construction, so adding a field to the
|
|
9
|
-
* schema adds it to the page and nothing can drift.
|
|
10
|
-
*
|
|
11
|
-
* ## It covers SCALARS, and says so rather than guessing
|
|
12
|
-
*
|
|
13
|
-
* A string, number, integer, boolean or enum has one obvious control each. A
|
|
14
|
-
* nested object or an array does not — every choice (a JSON textarea, a repeater,
|
|
15
|
-
* a comma-separated string) is a guess about what the author meant, and a guess
|
|
16
|
-
* that produces a value the schema then rejects is worse than no field at all.
|
|
17
|
-
* So those are SKIPPED, and the fields for them are written by hand: every field
|
|
18
|
-
* in this package is a plain named control, so a hand-written one composes with
|
|
19
|
-
* a generated one inside the same {@link Form}.
|
|
20
|
-
*/
|
|
21
|
-
import type { WorkflowSummary } from "@alexkroman1/aai";
|
|
1
|
+
import type { WorkflowSummary } from "@alexkroman1/aai/workflow-api";
|
|
22
2
|
/**
|
|
23
3
|
* Render one field per scalar property of a workflow's input schema.
|
|
24
4
|
*
|
|
@@ -50,8 +30,16 @@ import type { WorkflowSummary } from "@alexkroman1/aai";
|
|
|
50
30
|
* }
|
|
51
31
|
* ```
|
|
52
32
|
*
|
|
33
|
+
* @param props - Field-set props.
|
|
34
|
+
*
|
|
53
35
|
* @public
|
|
54
36
|
*/
|
|
55
|
-
export declare function WorkflowFields({ workflow }: {
|
|
37
|
+
export declare function WorkflowFields({ workflow, }: {
|
|
38
|
+
/**
|
|
39
|
+
* The workflow whose input schema to render. A NAME is looked up here (one
|
|
40
|
+
* `GET workflows`); a {@link WorkflowSummary} the page already holds fetches
|
|
41
|
+
* nothing. `undefined` renders nothing, so a page may pass a selection
|
|
42
|
+
* straight through before one is made.
|
|
43
|
+
*/
|
|
56
44
|
workflow?: WorkflowSummary | string | undefined;
|
|
57
45
|
}): import("react").JSX.Element | null;
|
|
@@ -35,21 +35,40 @@ import type { WorkflowApi } from "../workflow-client.ts";
|
|
|
35
35
|
* }
|
|
36
36
|
* ```
|
|
37
37
|
*
|
|
38
|
-
* @param
|
|
39
|
-
* pass its state straight through before a run exists.
|
|
40
|
-
* @param api - The workflow API client, when the page holds its own. Defaults
|
|
41
|
-
* to the one `page()` installs.
|
|
42
|
-
* @param className - Replaces the default classes rather than extending them,
|
|
43
|
-
* so a custom chrome is not fighting a default it did not ask for.
|
|
44
|
-
* @param placeholder - Rendered instead of nothing while the run has said
|
|
45
|
-
* nothing yet — for a page that would otherwise reflow when the first line
|
|
46
|
-
* lands.
|
|
38
|
+
* @param props - Progress-log props.
|
|
47
39
|
*
|
|
48
40
|
* @public
|
|
49
41
|
*/
|
|
50
|
-
export declare function WorkflowProgress({ runId, api, className, placeholder, }: {
|
|
42
|
+
export declare function WorkflowProgress({ runId, api, className, placeholder, lines, }: {
|
|
43
|
+
/**
|
|
44
|
+
* The run to read. `undefined` renders nothing, so a page may pass its state
|
|
45
|
+
* straight through before a run exists.
|
|
46
|
+
*/
|
|
51
47
|
runId?: string | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* The workflow API client, when the page holds its own. Defaults to the
|
|
50
|
+
* lazily-built one every workflow hook shares.
|
|
51
|
+
*/
|
|
52
52
|
api?: WorkflowApi | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* **Replaces** the default classes rather than extending them, so a custom
|
|
55
|
+
* chrome is not fighting a default it did not ask for.
|
|
56
|
+
*/
|
|
53
57
|
className?: string | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* Rendered instead of nothing while the run has said nothing yet — for a
|
|
60
|
+
* page that would otherwise reflow when the first line lands.
|
|
61
|
+
*/
|
|
54
62
|
placeholder?: ReactNode | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* How many of the newest lines to show. Undefined (the default) shows the
|
|
65
|
+
* whole log; `1` is the newest line only.
|
|
66
|
+
*
|
|
67
|
+
* A run's narration is append-only and unbounded, so a page with a fixed slot
|
|
68
|
+
* for it — a status strip, a card footer — wants a window rather than a log.
|
|
69
|
+
* `0` renders the placeholder, which is the consistent reading of "show none"
|
|
70
|
+
* and the one that keeps a computed `lines` from silently rendering
|
|
71
|
+
* everything.
|
|
72
|
+
*/
|
|
73
|
+
lines?: number | undefined;
|
|
55
74
|
}): ReactNode;
|
package/dist/context.d.ts
CHANGED
|
@@ -74,6 +74,22 @@ export declare function useSession(): Session;
|
|
|
74
74
|
* cheap; when it returns a derived object, pass a custom `isEqual` to avoid
|
|
75
75
|
* re-renders on referentially-new-but-equal results.
|
|
76
76
|
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```tsx
|
|
79
|
+
* import { useSessionSelector } from "@alexkroman1/aai-ui";
|
|
80
|
+
*
|
|
81
|
+
* // Re-renders when `running` flips, and on nothing else — not on every
|
|
82
|
+
* // transcript delta the way `useSession()` would.
|
|
83
|
+
* function MicDot() {
|
|
84
|
+
* const running = useSessionSelector((snapshot) => snapshot.running);
|
|
85
|
+
* return <span>{running ? "●" : "○"}</span>;
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @param selector - Reads the slice out of the snapshot. Must be pure.
|
|
90
|
+
* @param isEqual - Compares two selected values. Defaults to `Object.is`.
|
|
91
|
+
* @returns The selected slice.
|
|
92
|
+
*
|
|
77
93
|
* @public
|
|
78
94
|
*/
|
|
79
95
|
export declare function useSessionSelector<T>(selector: (snapshot: SessionSnapshot) => T, isEqual?: (a: T, b: T) => boolean): T;
|
|
@@ -93,6 +109,26 @@ export declare function ThemeProvider({ value, children, }: {
|
|
|
93
109
|
* default) from the nearest theme context. Returns the default theme when no
|
|
94
110
|
* provider is present, so components can call it unconditionally.
|
|
95
111
|
*
|
|
112
|
+
* This is how a custom component stays on the agent's palette: a
|
|
113
|
+
* `client({ theme })` override reaches it here, where a hardcoded colour or a
|
|
114
|
+
* Tailwind class cannot see it.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```tsx
|
|
118
|
+
* import { useTheme } from "@alexkroman1/aai-ui";
|
|
119
|
+
*
|
|
120
|
+
* function Total({ amount }: { amount: string }) {
|
|
121
|
+
* const theme = useTheme();
|
|
122
|
+
* return (
|
|
123
|
+
* <strong style={{ color: theme.primary, background: theme.surface }}>
|
|
124
|
+
* {amount}
|
|
125
|
+
* </strong>
|
|
126
|
+
* );
|
|
127
|
+
* }
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* @returns Every {@link ClientTheme} field, filled in.
|
|
131
|
+
*
|
|
96
132
|
* @public
|
|
97
133
|
*/
|
|
98
134
|
export declare function useTheme(): Required<ClientTheme>;
|
package/dist/context.js
CHANGED
|
@@ -83,6 +83,22 @@ function useSession() {
|
|
|
83
83
|
* cheap; when it returns a derived object, pass a custom `isEqual` to avoid
|
|
84
84
|
* re-renders on referentially-new-but-equal results.
|
|
85
85
|
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```tsx
|
|
88
|
+
* import { useSessionSelector } from "@alexkroman1/aai-ui";
|
|
89
|
+
*
|
|
90
|
+
* // Re-renders when `running` flips, and on nothing else — not on every
|
|
91
|
+
* // transcript delta the way `useSession()` would.
|
|
92
|
+
* function MicDot() {
|
|
93
|
+
* const running = useSessionSelector((snapshot) => snapshot.running);
|
|
94
|
+
* return <span>{running ? "●" : "○"}</span>;
|
|
95
|
+
* }
|
|
96
|
+
* ```
|
|
97
|
+
*
|
|
98
|
+
* @param selector - Reads the slice out of the snapshot. Must be pure.
|
|
99
|
+
* @param isEqual - Compares two selected values. Defaults to `Object.is`.
|
|
100
|
+
* @returns The selected slice.
|
|
101
|
+
*
|
|
86
102
|
* @public
|
|
87
103
|
*/
|
|
88
104
|
function useSessionSelector(selector, isEqual = Object.is) {
|
|
@@ -102,40 +118,115 @@ function ThemeProvider({ value, children }) {
|
|
|
102
118
|
...DEFAULT_THEME,
|
|
103
119
|
...value
|
|
104
120
|
} : DEFAULT_THEME, [value]);
|
|
105
|
-
|
|
121
|
+
useThemeStyles(merged);
|
|
106
122
|
return createElement(ThemeCtx.Provider, { value: merged }, children);
|
|
107
123
|
}
|
|
108
124
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
125
|
+
* The custom property each {@link ClientTheme} field is published as.
|
|
126
|
+
*
|
|
127
|
+
* Named after the field, so `theme.surface` and `--aai-surface` are obviously
|
|
128
|
+
* the same thing, and prefixed for the reason `--aai-btn-bg` and
|
|
129
|
+
* `--aai-sidebar-w` already are: these land on `:root`, where an app's own
|
|
130
|
+
* variables live too.
|
|
131
|
+
*
|
|
132
|
+
* @internal
|
|
117
133
|
*/
|
|
118
|
-
|
|
134
|
+
const THEME_VARS = {
|
|
135
|
+
bg: "--aai-bg",
|
|
136
|
+
surface: "--aai-surface",
|
|
137
|
+
text: "--aai-text",
|
|
138
|
+
border: "--aai-border",
|
|
139
|
+
primary: "--aai-primary"
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Publish the theme to CSS, and paint the page with it.
|
|
143
|
+
*
|
|
144
|
+
* Two jobs on one element deliberately — both are about the parts of the page
|
|
145
|
+
* React does not own.
|
|
146
|
+
*
|
|
147
|
+
* **The variables.** {@link useTheme} hands a component a JavaScript object, so
|
|
148
|
+
* everything it styles carries an inline `style={{ }}`; measured across the
|
|
149
|
+
* template tree the ratio of `theme.` reads to inline style objects is
|
|
150
|
+
* essentially one to one. A Tailwind class cannot see a JavaScript object — so
|
|
151
|
+
* the five values are written to `:root` as custom properties, `styles.css`
|
|
152
|
+
* maps them into the `@theme` block's `--color-*` namespace, and
|
|
153
|
+
* `className="bg-aai-surface text-aai-text border-aai-border"` works. This is
|
|
154
|
+
* ADDITIVE: `useTheme()` stays, because the derived tints in
|
|
155
|
+
* `components/_colors.ts` `color-mix` on the resolved values and a page is
|
|
156
|
+
* entitled to read them for a `satisfies`-pinned palette.
|
|
157
|
+
*
|
|
158
|
+
* **The background.** Components paint `theme.bg` on their own containers, but
|
|
159
|
+
* the page behind them keeps whatever the static `<style>` in index.html set.
|
|
160
|
+
* Any viewport wider (or taller) than the app column then shows that color as a
|
|
161
|
+
* border around the UI — which is how a cream theme ended up letterboxed in
|
|
162
|
+
* black. It stays an explicit `background` on `html` AND `body` rather than
|
|
163
|
+
* riding on the new variable: a variable only paints where some rule consumes
|
|
164
|
+
* it, and the two elements this is about are the two nothing in this package
|
|
165
|
+
* renders.
|
|
166
|
+
*/
|
|
167
|
+
function useThemeStyles(theme) {
|
|
168
|
+
const { bg, surface, text, border, primary } = theme;
|
|
119
169
|
useEffect(() => {
|
|
120
170
|
if (typeof document === "undefined") return;
|
|
121
171
|
const { body, documentElement: html } = document;
|
|
122
|
-
const
|
|
172
|
+
const values = {
|
|
173
|
+
bg,
|
|
174
|
+
surface,
|
|
175
|
+
text,
|
|
176
|
+
border,
|
|
177
|
+
primary
|
|
178
|
+
};
|
|
179
|
+
const previousVars = Object.entries(THEME_VARS).map(([field, prop]) => [
|
|
180
|
+
prop,
|
|
181
|
+
html.style.getPropertyValue(prop),
|
|
182
|
+
values[field]
|
|
183
|
+
]);
|
|
184
|
+
for (const [prop, , next] of previousVars) html.style.setProperty(prop, next);
|
|
185
|
+
const previousBg = {
|
|
123
186
|
body: body.style.background,
|
|
124
187
|
html: html.style.background
|
|
125
188
|
};
|
|
126
189
|
body.style.background = bg;
|
|
127
190
|
html.style.background = bg;
|
|
128
191
|
return () => {
|
|
129
|
-
|
|
130
|
-
html.style.
|
|
192
|
+
for (const [prop, before] of previousVars) if (before === "") html.style.removeProperty(prop);
|
|
193
|
+
else html.style.setProperty(prop, before);
|
|
194
|
+
body.style.background = previousBg.body;
|
|
195
|
+
html.style.background = previousBg.html;
|
|
131
196
|
};
|
|
132
|
-
}, [
|
|
197
|
+
}, [
|
|
198
|
+
bg,
|
|
199
|
+
surface,
|
|
200
|
+
text,
|
|
201
|
+
border,
|
|
202
|
+
primary
|
|
203
|
+
]);
|
|
133
204
|
}
|
|
134
205
|
/**
|
|
135
206
|
* Read the resolved theme (every {@link ClientTheme} field filled with its
|
|
136
207
|
* default) from the nearest theme context. Returns the default theme when no
|
|
137
208
|
* provider is present, so components can call it unconditionally.
|
|
138
209
|
*
|
|
210
|
+
* This is how a custom component stays on the agent's palette: a
|
|
211
|
+
* `client({ theme })` override reaches it here, where a hardcoded colour or a
|
|
212
|
+
* Tailwind class cannot see it.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```tsx
|
|
216
|
+
* import { useTheme } from "@alexkroman1/aai-ui";
|
|
217
|
+
*
|
|
218
|
+
* function Total({ amount }: { amount: string }) {
|
|
219
|
+
* const theme = useTheme();
|
|
220
|
+
* return (
|
|
221
|
+
* <strong style={{ color: theme.primary, background: theme.surface }}>
|
|
222
|
+
* {amount}
|
|
223
|
+
* </strong>
|
|
224
|
+
* );
|
|
225
|
+
* }
|
|
226
|
+
* ```
|
|
227
|
+
*
|
|
228
|
+
* @returns Every {@link ClientTheme} field, filled in.
|
|
229
|
+
*
|
|
139
230
|
* @public
|
|
140
231
|
*/
|
|
141
232
|
function useTheme() {
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.3 | 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-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-wide:.025em;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-aai-surface:var(--aai-surface,#fff);--color-aai-text:var(--aai-text,#1b1a18);--color-aai-border:var(--aai-border,#dcd7cc);--font-aai:"Monument Grotesk", "ABC Monument Grotesk", ui-sans-serif, system-ui, -apple-system, sans-serif;--font-aai-serif:"Source Serif 4", "Source Serif Pro", Charter, "Iowan Old Style", Georgia, serif;--font-aai-mono:"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;--radius-aai:4px}}@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,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, 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:where(:not(iframe)){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}html,body{margin:0;padding:0}}@layer components;@layer utilities{.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.order-last{order:9999}.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}}.m-0{margin:0}.mx-auto{margin-inline:auto}.my-0\.5{margin-block:calc(var(--spacing) * .5)}.my-1\.5{margin-block:calc(var(--spacing) * 1.5)}.my-2\.5{margin-block:calc(var(--spacing) * 2.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.box-border{box-sizing:border-box}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-4{height:calc(var(--spacing) * 4)}.h-6{height:calc(var(--spacing) * 6)}.h-9{height:calc(var(--spacing) * 9)}.h-11{height:calc(var(--spacing) * 11)}.h-\[7px\]{height:7px}.h-full{height:100%}.h-screen{height:100vh}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-\[40vh\]{max-height:40vh}.min-h-0{min-height:0}.min-h-5{min-height:calc(var(--spacing) * 5)}.min-h-screen{min-height:100vh}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-4{width:calc(var(--spacing) * 4)}.w-\[7px\]{width:7px}.w-fit{width:fit-content}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-75{max-width:calc(var(--spacing) * 75)}.max-w-105{max-width:calc(var(--spacing) * 105)}.max-w-190{max-width:calc(var(--spacing) * 190)}.max-w-\[82\%\]{max-width:82%}.max-w-\[min\(78\%\,64ch\)\]{max-width:min(78%,64ch)}.min-w-0{min-width:0}.flex-1{flex:1}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.basis-full{flex-basis:100%}.border-collapse{border-collapse:collapse}.rotate-90{rotate:90deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.cursor-pointer{cursor:pointer}.resize{resize:both}.\[scrollbar-width\:none\]{scrollbar-width:none}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.appearance-none{appearance:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-6{gap:calc(var(--spacing) * 6)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded-aai{border-radius:var(--radius-aai)}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.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-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-none{--tw-border-style:none;border-style:none}.border-\(--aai-btn-bd\){border-color:var(--aai-btn-bd)}.border-aai-border{border-color:var(--color-aai-border)}.bg-\(--aai-btn-bg\){background-color:var(--aai-btn-bg)}.bg-aai-surface{background-color:var(--color-aai-surface)}.bg-transparent{background-color:#0000}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-4{padding:calc(var(--spacing) * 4)}.p-7{padding:calc(var(--spacing) * 7)}.p-8{padding:calc(var(--spacing) * 8)}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-7{padding-inline:calc(var(--spacing) * 7)}.px-10{padding-inline:calc(var(--spacing) * 10)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.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-8{padding-block:calc(var(--spacing) * 8)}.py-12{padding-block:calc(var(--spacing) * 12)}.pl-1\.5{padding-left:calc(var(--spacing) * 1.5)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-5{padding-left:calc(var(--spacing) * 5)}.text-center{text-align:center}.text-left{text-align:left}.font-aai{font-family:var(--font-aai)}.font-aai-mono{font-family:var(--font-aai-mono)}.font-aai-serif{font-family:var(--font-aai-serif)}.font-mono{font-family:var(--font-mono)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[0\.625rem\]{font-size:.625rem}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12\.5px\]{font-size:12.5px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.text-\[16px\]{font-size:16px}.text-\[17px\]{font-size:17px}.text-\[22px\]{font-size:22px}.text-\[32px\]{font-size:32px}.leading-4{--tw-leading:calc(var(--spacing) * 4);line-height:calc(var(--spacing) * 4)}.leading-\[1\.2\]{--tw-leading:1.2;line-height:1.2}.leading-\[1\.15\]{--tw-leading:1.15;line-height:1.15}.leading-\[22px\]{--tw-leading:22px;line-height:22px}.leading-\[23px\]{--tw-leading:23px;line-height:23px}.leading-\[130\%\]{--tw-leading:130%;line-height:130%}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[-0\.2px\]{--tw-tracking:-.2px;letter-spacing:-.2px}.tracking-\[1\.2px\]{--tw-tracking:1.2px;letter-spacing:1.2px}.tracking-\[1\.4px\]{--tw-tracking:1.4px;letter-spacing:1.4px}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.text-balance{text-wrap:balance}.wrap-break-word{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\(--aai-btn-fg\){color:var(--aai-btn-fg)}.text-aai-text{color:var(--color-aai-text)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + 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)}.ring-2{--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)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.invert{--tw-invert:invert(100%);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,)}.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-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.file\:mr-3::file-selector-button{margin-right:calc(var(--spacing) * 3)}.file\:cursor-pointer::file-selector-button{cursor:pointer}.file\:rounded-aai::file-selector-button{border-radius:var(--radius-aai)}.file\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\:px-3::file-selector-button{padding-inline:calc(var(--spacing) * 3)}.file\:py-1\.5::file-selector-button{padding-block:calc(var(--spacing) * 1.5)}.file\:font-aai::file-selector-button{font-family:var(--font-aai)}.file\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\:\[color\:var\(--aai-file-button-fg\)\]::file-selector-button{color:var(--aai-file-button-fg)}.file\:\[background\:var\(--aai-file-button-bg\)\]::file-selector-button{background:var(--aai-file-button-bg)}.first\:mt-0:first-child{margin-top:0}.last\:mb-0:last-child{margin-bottom:0}.focus-visible\:\[outline\:2px_solid\]:focus-visible{outline:2px solid}.focus-visible\:\[outline-offset\:2px\]:focus-visible{outline-offset:2px}@media (hover:hover){.enabled\:hover\:border-\(--aai-btn-bd-hover\):enabled:hover{border-color:var(--aai-btn-bd-hover)}.enabled\:hover\:bg-\(--aai-btn-bg-hover\):enabled:hover{background-color:var(--aai-btn-bg-hover)}.enabled\:hover\:text-\(--aai-btn-fg-hover\):enabled:hover{color:var(--aai-btn-fg-hover)}}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}@media (width>=40rem){.sm\:ml-auto{margin-left:auto}.sm\:max-w-\[60\%\]{max-width:60%}.sm\:basis-auto{flex-basis:auto}.sm\:px-16{padding-inline:calc(var(--spacing) * 16)}.sm\:py-14{padding-block:calc(var(--spacing) * 14)}}@media (width>=48rem){.md\:order-none{order:0}.md\:h-screen{height:100vh}.md\:max-h-none{max-height:none}.md\:w-\(--aai-sidebar-w\){width:var(--aai-sidebar-w)}.md\:flex-row{flex-direction:row}.md\:border-t-0{border-top-style:var(--tw-border-style);border-top-width:0}.md\:border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.md\:border-b-0{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.md\:border-l{border-left-style:var(--tw-border-style);border-left-width:1px}}}@keyframes aai-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.82)}}@keyframes aai-bounce{0%,80%,to{opacity:.3;transform:scale(.8)}40%{opacity:1;transform:scale(1)}}@keyframes aai-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.tool-shimmer{-webkit-text-fill-color:transparent;background:linear-gradient(90deg,currentColor 25%,#0000 50%,currentColor 75%) 0 0/200% 100%;-webkit-background-clip:text;background-clip:text;animation:2s infinite aai-shimmer}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-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-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}}
|