vue-wswg-editor 0.0.6 → 0.0.7

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 +1 @@
1
- export declare const blockModules: Record<string, string> | Record<string, () => Promise<any>> | Record<string, any>;
1
+ export declare const blockModules: Record<string, any> | Record<string, string> | Record<string, () => Promise<any>>;
@@ -0,0 +1 @@
1
+ {"root":["../../src/index.ts","../../src/shims.d.ts","../../src/vite-plugin.ts","../../src/components/pagerenderer/blockmodules.ts","../../src/components/wswgjsoneditor/wswgjsoneditor.test.ts","../../src/types/block.d.ts","../../src/types/layout.d.ts","../../src/util/fieldconfig.ts","../../src/util/helpers.ts","../../src/util/registry.ts","../../src/util/validation.ts","../../src/components/addblockitem/addblockitem.vue","../../src/components/blockbrowser/blockbrowser.vue","../../src/components/blockcomponent/blockcomponent.vue","../../src/components/blockeditorfieldnode/blockeditorfieldnode.vue","../../src/components/blockeditorfields/blockeditorfields.vue","../../src/components/blockmarginfieldnode/blockmarginnode.vue","../../src/components/blockrepeaterfieldnode/blockrepeaternode.vue","../../src/components/browsernavigation/browsernavigation.vue","../../src/components/emptystate/emptystate.vue","../../src/components/pageblocklist/pageblocklist.vue","../../src/components/pagebuildersidebar/pagebuildersidebar.vue","../../src/components/pagebuildertoolbar/pagebuildertoolbar.vue","../../src/components/pagerenderer/pagerenderer.vue","../../src/components/pagesettings/pagesettings.vue","../../src/components/resizehandle/resizehandle.vue","../../src/components/wswgjsoneditor/wswgjsoneditor.vue"],"version":"5.8.3"}
@@ -3,8 +3,7 @@ import type { EditorFieldConfig } from "./fieldConfig";
3
3
  import type { Block } from "../types/Block";
4
4
  import type { Layout } from "../types/Layout";
5
5
  /**
6
- * Registry of all page builder blocks
7
- * Automatically populated from the /page-builder/blocks directory of your app
6
+ * Registry of all page builder blocks, layouts & fields
8
7
  */
9
8
  export declare const pageBuilderBlocks: Ref<Record<string, Block>>;
10
9
  export declare const pageBuilderLayouts: Ref<Record<string, Layout>>;
@@ -18,4 +17,4 @@ export declare function getLayouts(): Record<string, Layout>;
18
17
  export declare function getBlockThumbnailUrl(directory: string | undefined): string | undefined;
19
18
  export declare function getBlockComponent(blockType: string): Block | undefined;
20
19
  export declare function getLayoutFields(layoutName: string): Record<string, EditorFieldConfig>;
21
- export declare function initialiseRegistry(): void;
20
+ export declare function initialiseRegistry(): Promise<void>;
@@ -0,0 +1,9 @@
1
+ import type { Plugin } from "vite";
2
+ export interface VueWswgEditorPluginOptions {
3
+ /**
4
+ * Root directory in the host project.
5
+ * Example: "@/features/homepage"
6
+ */
7
+ rootDir: string;
8
+ }
9
+ export declare function vueWswgEditorPlugin(options: VueWswgEditorPluginOptions): Plugin;
@@ -0,0 +1,43 @@
1
+ function s(r) {
2
+ const e = {
3
+ blocks: "\0vue-wswg-editor:blocks",
4
+ fields: "\0vue-wswg-editor:fields",
5
+ layouts: "\0vue-wswg-editor:layouts",
6
+ thumbnails: "\0vue-wswg-editor:thumbnails"
7
+ };
8
+ return {
9
+ name: "vue-wswg-editor-glob-plugin",
10
+ enforce: "pre",
11
+ // Run before other plugins to ensure import.meta.glob is processed correctly
12
+ resolveId(t) {
13
+ if (t.startsWith("vue-wswg-editor:")) {
14
+ const u = t.replace("vue-wswg-editor:", "");
15
+ if (u in e)
16
+ return e[u];
17
+ }
18
+ if (Object.values(e).includes(t))
19
+ return t;
20
+ },
21
+ load(t) {
22
+ switch (t) {
23
+ case e.layouts:
24
+ return `export const modules = import.meta.glob("${r.rootDir}/layout/**/*.vue", { eager: true });`;
25
+ case e.blocks:
26
+ return `export const modules = import.meta.glob("${r.rootDir}/blocks/**/*.vue", { eager: true });`;
27
+ case e.fields:
28
+ return `export const modules = import.meta.glob("${r.rootDir}/blocks/**/fields.ts", { eager: true });`;
29
+ case e.thumbnails:
30
+ return `export const modules = import.meta.glob("${r.rootDir}/blocks/**/thumbnail.png", { eager: true });`;
31
+ default:
32
+ return;
33
+ }
34
+ },
35
+ transform(t, o) {
36
+ if (Object.values(e).includes(o))
37
+ return null;
38
+ }
39
+ };
40
+ }
41
+ export {
42
+ s as vueWswgEditorPlugin
43
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-wswg-editor",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "module": "src/index.ts",
@@ -15,6 +15,11 @@
15
15
  "import": "./src/components/PageRenderer/PageRenderer.vue",
16
16
  "types": "./src/components/PageRenderer/PageRenderer.vue"
17
17
  },
18
+ "./vite-plugin": {
19
+ "import": "./dist/vite-plugin.js",
20
+ "require": "./dist/vite-plugin.js",
21
+ "types": "./src/vite-plugin.ts"
22
+ },
18
23
  "./style.css": "./dist/style.css"
19
24
  },
20
25
  "files": [
@@ -22,8 +27,8 @@
22
27
  "src"
23
28
  ],
24
29
  "scripts": {
25
- "dev": "vite build --watch",
26
- "build": "vite build && vue-tsc --declaration --emitDeclarationOnly",
30
+ "dev": "concurrently \"vite build --watch\" \"vite build --config vite-plugin.config.ts --watch\"",
31
+ "build": "vite build && vite build --config vite-plugin.config.ts && vue-tsc --declaration --emitDeclarationOnly",
27
32
  "preview": "vite preview",
28
33
  "test:unit": "vitest",
29
34
  "test:unit:ui": "vitest --ui",
@@ -59,6 +64,7 @@
59
64
  "@vue/test-utils": "^2.4.6",
60
65
  "@vue/tsconfig": "^0.7.0",
61
66
  "autoprefixer": "^10.4.21",
67
+ "concurrently": "^9.2.1",
62
68
  "eslint": "^9.30.0",
63
69
  "eslint-plugin-tailwindcss": "^3.18.2",
64
70
  "eslint-plugin-vue": "^9.33.0",
@@ -138,12 +138,10 @@ function handleSidebarWidth(width: number) {
138
138
  async function loadLayout(layoutName: string | undefined) {
139
139
  // Use "default" layout if no layout is provided
140
140
  const layout = layoutName || "default";
141
-
142
141
  try {
143
- // Try to import the layout from @page-builder/layout/
144
- // This alias is configured in the consuming app (admin)
145
- const layoutModule = await import(`@page-builder/layout/${layout}.vue`);
146
- pageLayout.value = layoutModule.default;
142
+ const availableLayouts = getLayouts();
143
+ const layoutModule = availableLayouts[layout];
144
+ pageLayout.value = layoutModule;
147
145
  await nextTick();
148
146
  initSortable();
149
147
  } catch (error) {
package/src/shims.d.ts CHANGED
@@ -50,6 +50,23 @@ interface ImportMeta {
50
50
  ): Record<string, () => Promise<T>> | Record<string, T> | Record<string, string>;
51
51
  }
52
52
 
53
+ // Virtual modules created by vue-wswg-editor vite plugin
54
+ declare module "vue-wswg-editor:layouts" {
55
+ export const modules: Record<string, () => Promise<any>>;
56
+ }
57
+
58
+ declare module "vue-wswg-editor:blocks" {
59
+ export const modules: Record<string, () => Promise<any>>;
60
+ }
61
+
62
+ declare module "vue-wswg-editor:fields" {
63
+ export const modules: Record<string, () => Promise<any>>;
64
+ }
65
+
66
+ declare module "vue-wswg-editor:thumbnails" {
67
+ export const modules: Record<string, () => Promise<any>>;
68
+ }
69
+
53
70
  // SortableJS type declaration - reference @types/sortablejs and re-export as ESM default
54
71
  /// <reference types="sortablejs" />
55
72
  declare module "sortablejs" {
@@ -1,28 +1,85 @@
1
- import { ref, shallowRef, type Ref } from "vue";
1
+ import { ref, shallowRef, markRaw, type Ref } from "vue";
2
2
  import type { EditorFieldConfig } from "./fieldConfig";
3
3
  import type { Block } from "../types/Block";
4
4
  import type { Layout } from "../types/Layout";
5
- import { generateNameVariations, generateFilePathPatterns, toCamelCase } from "./helpers";
5
+ import { generateNameVariations, toCamelCase } from "./helpers";
6
6
  // Dynamic imports for all page builder blocks and layouts
7
7
  // IMPORTANT: These globs use the @page-builder alias which must be configured in the CONSUMING APP's vite.config.ts
8
8
  // The globs are evaluated by the consuming app's Vite build, so they resolve relative to the consuming app's project root
9
9
  // The consuming app should have: "@page-builder": fileURLToPath(new URL("../page-builder", import.meta.url))
10
- // Using eager: true to load all modules immediately so we can access component metadata (name, props, icon)
11
- const blockModules = import.meta.glob("@page-builder/blocks/**/*.vue", { eager: true });
12
- const blockFieldsModules = import.meta.glob("@page-builder/blocks/**/fields.ts", { eager: true });
13
- const layoutModules = import.meta.glob("@page-builder/layout/**/*.vue", { eager: true });
10
+ import { modules as layoutModules } from "vue-wswg-editor:layouts";
11
+ import { modules as blockModules } from "vue-wswg-editor:blocks";
12
+ import { modules as fieldModules } from "vue-wswg-editor:fields";
13
+ import { modules as thumbnailModules } from "vue-wswg-editor:thumbnails";
14
+
14
15
  // Load all thumbnail images - Vite will process these as assets and provide URLs
15
16
  // For images, Vite returns the URL as the default export when using eager: true
16
- const thumbnailModules = import.meta.glob("@page-builder/blocks/**/thumbnail.png", { eager: true });
17
+ // const thumbnailModules = import.meta.glob("@page-builder/blocks/**/thumbnail.png", { eager: true });
17
18
 
18
19
  /**
19
- * Registry of all page builder blocks
20
- * Automatically populated from the /page-builder/blocks directory of your app
20
+ * Registry of all page builder blocks, layouts & fields
21
21
  */
22
22
  export const pageBuilderBlocks: Ref<Record<string, Block>> = shallowRef({});
23
23
  export const pageBuilderLayouts: Ref<Record<string, Layout>> = shallowRef({});
24
24
  const pageBuilderBlockFields: Ref<Record<string, any>> = ref({});
25
25
 
26
+ ////////////////////////////////////////////////////////////
27
+ // Helper Functions
28
+ ////////////////////////////////////////////////////////////
29
+
30
+ /**
31
+ * Recursively mark Vue components as raw to prevent reactivity
32
+ * Components are identified by having __name, setup, or render properties
33
+ */
34
+ function markComponentsAsRaw(obj: any): any {
35
+ if (!obj || typeof obj !== "object") return obj;
36
+
37
+ // Check if this is a Vue component
38
+ if (obj.__name || obj.setup || obj.render) {
39
+ return markRaw(obj);
40
+ }
41
+
42
+ // Recursively process objects and arrays
43
+ if (Array.isArray(obj)) {
44
+ return obj.map((item) => markComponentsAsRaw(item));
45
+ }
46
+
47
+ const result: any = {};
48
+ for (const [key, value] of Object.entries(obj)) {
49
+ result[key] = markComponentsAsRaw(value);
50
+ }
51
+ return result;
52
+ }
53
+
54
+ /**
55
+ * Extract the default export from a module, handling different module formats
56
+ * Works with both eager and lazy-loaded modules from import.meta.glob
57
+ */
58
+ function getModuleDefault(module: any): any {
59
+ if (!module) return undefined;
60
+
61
+ // If module is a function (lazy-loaded), we'd need to await it, but with eager: true it should be resolved
62
+ if (typeof module === "function") {
63
+ // This shouldn't happen with eager: true, but handle it just in case
64
+ return undefined;
65
+ }
66
+
67
+ // Try .default first (standard ES module format)
68
+ if (typeof module === "object") {
69
+ // Check if it has .default property
70
+ if ("default" in module && module.default !== undefined) {
71
+ return module.default;
72
+ }
73
+ // If no .default but module has component-like properties (__name, etc.), maybe module itself is the component
74
+ if ("__name" in module || "name" in module || "setup" in module || "render" in module) {
75
+ return module;
76
+ }
77
+ }
78
+
79
+ // Fallback: return the module as-is
80
+ return module;
81
+ }
82
+
26
83
  ////////////////////////////////////////////////////////////
27
84
  // Methods
28
85
  ////////////////////////////////////////////////////////////
@@ -66,20 +123,17 @@ export function getBlockComponent(blockType: string): Block | undefined {
66
123
  return undefined;
67
124
  }
68
125
 
69
- function getBlockFields(blockName: string): any {
126
+ function getBlockFields(directory: string): any {
127
+ const fieldsPath = `${directory}/fields.ts`;
70
128
  try {
71
- // Generate path variations for options.ts file
72
- const pathVariations = generateFilePathPatterns("../page-builder/blocks/", blockName, "fields.ts");
73
- // Find the path that exists in the loaded modules
74
- const path = pathVariations.find((path) => blockFieldsModules[path]);
75
- if (path && blockFieldsModules[path]) {
76
- // Get the block fields
77
- const blockFields = (blockFieldsModules[path] as any).default;
78
- return blockFields || {};
129
+ // Generate path for fields.ts file
130
+ const blockField = pageBuilderBlockFields.value[fieldsPath];
131
+ if (blockField) {
132
+ return blockField;
79
133
  }
80
134
  return {};
81
135
  } catch (error) {
82
- console.error("Error getting block fields for block: ", blockName, error);
136
+ console.error("Error getting block fields for block: ", fieldsPath, error);
83
137
  return {};
84
138
  }
85
139
  }
@@ -92,29 +146,48 @@ export function getLayoutFields(layoutName: string): Record<string, EditorFieldC
92
146
  return layout?.fields || {};
93
147
  }
94
148
 
95
- function initialiseBlockFieldsRegistry(): void {
149
+ async function initialiseBlockFieldsRegistry(): Promise<void> {
150
+ // Clear existing registry
96
151
  Object.keys(pageBuilderBlockFields.value).forEach((key) => {
97
152
  delete pageBuilderBlockFields.value[key];
98
153
  });
99
- Object.entries(blockFieldsModules).forEach(([path, module]) => {
100
- const blockFields = (module as any).default;
101
- pageBuilderBlockFields.value[path] = blockFields;
102
- });
154
+
155
+ for (const [path, module] of Object.entries(fieldModules)) {
156
+ let resolvedModule = module;
157
+ // If module is a function (lazy-loaded), call it to get the actual module
158
+ if (typeof module === "function") {
159
+ resolvedModule = await module();
160
+ }
161
+ const blockFieldModule = getModuleDefault(resolvedModule);
162
+ // Mark as raw to prevent Vue from making it reactive
163
+ pageBuilderBlockFields.value[path] = markRaw(blockFieldModule);
164
+ }
103
165
  }
104
166
 
105
- function initialiseLayoutRegistry(): void {
167
+ async function initialiseLayoutRegistry(): Promise<void> {
106
168
  Object.keys(pageBuilderLayouts.value).forEach((key) => {
107
169
  delete pageBuilderLayouts.value[key];
108
170
  });
109
- Object.entries(layoutModules).forEach(([path, module]) => {
110
- const layout = (module as any).default;
171
+
172
+ // Use layoutModules if available (from vite plugin), otherwise fall back to layoutModules
173
+ const modulesToUse = layoutModules;
174
+
175
+ // Handle both eager-loaded modules and lazy-loaded modules (functions)
176
+ for (const [, module] of Object.entries(modulesToUse)) {
177
+ let resolvedModule = module;
178
+ // If module is a function (lazy-loaded), call it to get the actual module
179
+ if (typeof module === "function") {
180
+ resolvedModule = await module();
181
+ }
182
+ const layout = getModuleDefault(resolvedModule);
111
183
  // exclude modules without name
112
- if (!layout.label) return;
113
- pageBuilderLayouts.value[path] = layout;
114
- });
184
+ if (!layout || !layout.label) return;
185
+ // Mark layout component as raw to prevent Vue from making it reactive
186
+ pageBuilderLayouts.value[layout.__name] = markRaw(layout);
187
+ }
115
188
  }
116
189
 
117
- function initialiseBlockRegistry(): void {
190
+ async function initialiseBlockRegistry(): Promise<void> {
118
191
  // Clear existing registry
119
192
  Object.keys(pageBuilderBlocks.value).forEach((key) => {
120
193
  delete pageBuilderBlocks.value[key];
@@ -122,28 +195,36 @@ function initialiseBlockRegistry(): void {
122
195
 
123
196
  // Load all blocks from the glob pattern
124
197
  // With eager: true, module is the actual module object, not a loader function
125
- Object.entries(blockModules).forEach(([path, module]) => {
126
- const component = (module as any).default;
198
+ for (const [path, module] of Object.entries(blockModules)) {
199
+ let resolvedModule = module;
200
+ // If module is a function (lazy-loaded), call it to get the actual module
201
+ if (typeof module === "function") {
202
+ resolvedModule = await module();
203
+ }
204
+ const component = getModuleDefault(resolvedModule);
127
205
  if (component && component.__name) {
128
206
  const blockType = toCamelCase(component.type || component.__name);
129
207
  // Extract directory path from component path (e.g., "@page-builder/blocks/hero-section/hero-section.vue" -> "@page-builder/blocks/hero-section")
130
208
  const directory = path.replace(/\/[^/]+\.vue$/, "");
209
+ // Mark the component itself as raw before spreading
210
+ const rawComponent = markRaw(component);
131
211
  const block: Block = {
132
- fields: getBlockFields(blockType),
133
- ...component, // Component can override fields
212
+ fields: markComponentsAsRaw(getBlockFields(directory)), // Mark any components in fields as raw
213
+ ...rawComponent, // Component can override fields
134
214
  directory: directory, // directory path where the block component is located (e.g., "@page-builder/blocks/hero-section")
135
215
  type: blockType,
136
216
  };
137
217
  pageBuilderBlocks.value[blockType] = block;
138
218
  }
139
- });
219
+ }
140
220
  }
141
221
 
142
- export function initialiseRegistry(): void {
143
- initialiseLayoutRegistry();
144
- initialiseBlockFieldsRegistry();
145
- initialiseBlockRegistry();
222
+ export async function initialiseRegistry(): Promise<void> {
223
+ await initialiseLayoutRegistry();
224
+ await initialiseBlockFieldsRegistry();
225
+ await initialiseBlockRegistry();
146
226
  }
147
227
 
148
228
  // Initialise the registry when the module is loaded
149
- initialiseRegistry();
229
+ // Use void to handle the promise without blocking
230
+ void initialiseRegistry();
@@ -0,0 +1,65 @@
1
+ // my-lib/src/plugin.ts
2
+ import type { Plugin } from "vite";
3
+
4
+ export interface VueWswgEditorPluginOptions {
5
+ /**
6
+ * Root directory in the host project.
7
+ * Example: "@/features/homepage"
8
+ */
9
+ rootDir: string;
10
+ }
11
+
12
+ export function vueWswgEditorPlugin(options: VueWswgEditorPluginOptions): Plugin {
13
+ const virtualModules = {
14
+ blocks: "\0vue-wswg-editor:blocks",
15
+ fields: "\0vue-wswg-editor:fields",
16
+ layouts: "\0vue-wswg-editor:layouts",
17
+ thumbnails: "\0vue-wswg-editor:thumbnails",
18
+ };
19
+
20
+ return {
21
+ name: "vue-wswg-editor-glob-plugin",
22
+ enforce: "pre", // Run before other plugins to ensure import.meta.glob is processed correctly
23
+
24
+ resolveId(id) {
25
+ // Handle virtual module imports like "vue-wswg-editor:layouts"
26
+ if (id.startsWith("vue-wswg-editor:")) {
27
+ const suffix = id.replace("vue-wswg-editor:", "");
28
+ if (suffix in virtualModules) {
29
+ return virtualModules[suffix as keyof typeof virtualModules];
30
+ }
31
+ }
32
+ // Handle already resolved virtual module IDs (with \0 prefix)
33
+ const virtualModuleValues = Object.values(virtualModules);
34
+ if (virtualModuleValues.includes(id)) {
35
+ return id;
36
+ }
37
+ },
38
+
39
+ load(id) {
40
+ // Generate code that Vite will process - ensure import.meta.glob is at top level
41
+ // Using a more explicit format to ensure Vite processes it correctly
42
+ switch (id) {
43
+ case virtualModules.layouts:
44
+ return `export const modules = import.meta.glob("${options.rootDir}/layout/**/*.vue", { eager: true });`;
45
+ case virtualModules.blocks:
46
+ return `export const modules = import.meta.glob("${options.rootDir}/blocks/**/*.vue", { eager: true });`;
47
+ case virtualModules.fields:
48
+ return `export const modules = import.meta.glob("${options.rootDir}/blocks/**/fields.ts", { eager: true });`;
49
+ case virtualModules.thumbnails:
50
+ return `export const modules = import.meta.glob("${options.rootDir}/blocks/**/thumbnail.png", { eager: true });`;
51
+ default:
52
+ return undefined;
53
+ }
54
+ },
55
+
56
+ transform(_code, id) {
57
+ // Ensure import.meta.glob in virtual modules is processed correctly by Vite
58
+ // This hook ensures the code goes through Vite's transform pipeline
59
+ if (Object.values(virtualModules).includes(id)) {
60
+ // Return null to let Vite process the code normally - this ensures import.meta.glob is transformed
61
+ return null;
62
+ }
63
+ },
64
+ };
65
+ }
package/dist/style.css DELETED
@@ -1 +0,0 @@
1
- .resize-handle[data-v-b9819ded]{position:relative;top:0;right:0;z-index:2;width:3px;height:100%;cursor:col-resize;background-color:var(--grey-20);transition:all .2s ease-in-out}.resize-handle[data-v-b9819ded]:hover{width:3px;background-color:var(--yellow-40)}.resize-handle[data-v-b9819ded]:active{width:3px;background-color:var(--yellow-50)}.resize-handle[data-v-b9819ded]:before{position:absolute;top:50%;left:-6px;z-index:20;width:14px;height:40px;content:"";background-color:var(--yellow-40);border-radius:var(--border-radius-16);opacity:0;transform:translateY(-50%);transition:opacity .2s ease-in-out,background-color .2s ease-in-out}.resize-handle[data-v-b9819ded]:hover:before{opacity:1}.resize-handle[data-v-b9819ded]:active:before{background-color:var(--yellow-50);opacity:1}.repeater-field[data-v-20cd0fde]{width:100%}.empty-state[data-v-20cd0fde]{border:2px dashed #e5e7eb;border-radius:.5rem}.repeater-item .repeater-item-fields[data-v-20cd0fde]{height:0;overflow:hidden}.repeater-item.is-open .repeater-item-fields[data-v-20cd0fde]{height:auto;border-top-width:1px;padding:.75rem}select.form-control[data-v-649db0fa]{padding-right:32px;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center;background-size:20px}.editor-field-node[data-v-664a26d0] .form-control:is(input:not([type=checkbox],[type=radio]),textarea,select){width:100%;padding:8px;font-size:14px;color:#333;outline:none;background-color:#fff;border:1px solid #e0e0e0;border-radius:5px;box-shadow:none;transition:border-color .2s}.editor-field-node[data-v-664a26d0] .form-control label input[type=checkbox],.editor-field-node[data-v-664a26d0] .form-control label input[type=radio]{width:16px;height:16px;padding:8px;font-size:14px;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;border:1px solid #e0e0e0;border-radius:5px}.editor-field-node[data-v-664a26d0] .form-control label input[type=checkbox]:checked,.editor-field-node[data-v-664a26d0] .form-control label input[type=radio]:checked{--tw-border-opacity: 1;border-color:rgb(29 78 216 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.editor-field-node[data-v-664a26d0] .form-control label:has(input[type=checkbox]:checked,input[type=radio]:checked){--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.editor-field-node[data-v-664a26d0] .form-control label:hover input[type=checkbox]:not(:checked),.editor-field-node[data-v-664a26d0] .form-control label:hover input[type=radio]:not(:checked){--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity, 1))}.editor-field-node[data-v-664a26d0] .form-control label:has(input[type=checkbox]:disabled,input[type=radio]:disabled){cursor:not-allowed;opacity:.75}.editor-field-node[data-v-664a26d0] .form-control label:has(input[type=checkbox]:disabled,input[type=radio]:disabled) input{cursor:not-allowed}.editor-field-node[data-v-664a26d0] .form-control:is(select){padding-right:32px;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center;background-size:20px}.editor-field-node[data-v-664a26d0] .form-control:is(input[type=color]){width:auto;aspect-ratio:1/1;padding:3px;cursor:pointer;background-color:#fff;border:none;border:1px solid #e0e0e0;border-radius:5px}.editor-field-node[data-v-664a26d0] .form-control:hover{border-color:#555}.editor-field-node[data-v-664a26d0] .form-control:disabled{cursor:not-allowed;background-color:#fff;opacity:.75}.block-item.hovered-block[data-v-b8a8bb65]{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}select.form-control[data-v-fd08bd6a]{padding-right:32px;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center;background-size:20px}.page-builder-sidebar[data-v-2212ac82]{height:100%;overflow-y:auto;background:#fff}.block-wrapper[data-v-9d8117d8]{position:relative;transition:all .3s ease}.block-wrapper[data-v-9d8117d8]:before,.block-wrapper[data-v-9d8117d8]:after{position:absolute;left:0;display:flex;align-items:center;justify-content:center;width:100%;height:0;font-size:14px;font-weight:500;color:#888017;content:"Spacing";background-color:#f7efac;border:2px dashed #d2c564;border-radius:7px;opacity:0;transform:scaleY(.9) scaleX(.98);transition:all .3s ease}.block-wrapper .block-component[data-v-9d8117d8]{position:relative;cursor:pointer}.block-wrapper .block-component[data-v-9d8117d8]:before{position:absolute;top:0;left:0;z-index:2;width:100%;height:100%;pointer-events:none;outline:2px dashed #638ef1;outline-offset:-2px;content:"";background-color:#9fd0f643;opacity:0}.block-wrapper.active-block .block-component[data-v-9d8117d8]:before{background-color:#9fd0f643;border-color:#638ef1;opacity:1}.block-wrapper.active-block[data-v-9d8117d8]:after,.block-wrapper.active-block[data-v-9d8117d8]:before{opacity:1}.block-wrapper.hovered-block .block-component[data-v-9d8117d8]:before{background-color:#9fd0f643;border-color:#638ef1;opacity:1}.block-wrapper.hovered-block[data-v-9d8117d8]:after,.block-wrapper.hovered-block[data-v-9d8117d8]:before{opacity:1}.block-wrapper.margin-top-sm[data-v-9d8117d8]{padding-top:2rem}.block-wrapper.margin-top-sm[data-v-9d8117d8]:before{top:0;height:2rem}.block-wrapper.margin-top-md[data-v-9d8117d8]{padding-top:4rem}.block-wrapper.margin-top-md[data-v-9d8117d8]:before{top:0;height:4rem}.block-wrapper.margin-top-lg[data-v-9d8117d8]{padding-top:6rem}.block-wrapper.margin-top-lg[data-v-9d8117d8]:before{top:0;height:6rem}.block-wrapper.margin-bottom-sm[data-v-9d8117d8]{padding-bottom:2rem}.block-wrapper.margin-bottom-sm[data-v-9d8117d8]:after{bottom:0;height:2rem}.block-wrapper.margin-bottom-md[data-v-9d8117d8]{padding-bottom:4rem}.block-wrapper.margin-bottom-md[data-v-9d8117d8]:after{bottom:0;height:4rem}.block-wrapper.margin-bottom-lg[data-v-9d8117d8]{padding-bottom:6rem}.block-wrapper.margin-bottom-lg[data-v-9d8117d8]:after{bottom:0;height:6rem}.block-wrapper.margin-top-none[data-v-9d8117d8]:before,.block-wrapper.margin-bottom-none[data-v-9d8117d8]:after{display:none;content:none}.wswg-json-editor{display:flex;flex-direction:column;width:100%;max-width:100%;height:100vh}.wswg-json-editor-header{position:sticky;top:0;z-index:20;background-color:#fff}.wswg-json-editor-loading{display:flex;align-items:center;justify-content:center}.wswg-json-editor-canvas{display:flex;flex:1;flex-grow:1;flex-shrink:0;height:100%;overflow-y:auto;background-color:#6a6a6a}.wswg-json-editor-canvas-preview{flex:1;flex-grow:1;flex-shrink:0;padding:2rem}.wswg-json-editor-canvas-sidebar{min-width:300px;padding:2rem;background:#fff}.block-wrapper.margin-top-sm[data-v-958830a9]{padding-top:2rem}.block-wrapper.margin-top-sm[data-v-958830a9]:before{top:0;height:2rem}.block-wrapper.margin-top-md[data-v-958830a9]{padding-top:4rem}.block-wrapper.margin-top-md[data-v-958830a9]:before{top:0;height:4rem}.block-wrapper.margin-top-lg[data-v-958830a9]{padding-top:6rem}.block-wrapper.margin-top-lg[data-v-958830a9]:before{top:0;height:6rem}.block-wrapper.margin-bottom-sm[data-v-958830a9]{padding-bottom:2rem}.block-wrapper.margin-bottom-sm[data-v-958830a9]:after{bottom:0;height:2rem}.block-wrapper.margin-bottom-md[data-v-958830a9]{padding-bottom:4rem}.block-wrapper.margin-bottom-md[data-v-958830a9]:after{bottom:0;height:4rem}.block-wrapper.margin-bottom-lg[data-v-958830a9]{padding-bottom:6rem}.block-wrapper.margin-bottom-lg[data-v-958830a9]:after{bottom:0;height:6rem}.block-wrapper.margin-top-none[data-v-958830a9]:before,.block-wrapper.margin-bottom-none[data-v-958830a9]:after{display:none;content:none}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.-top-3{top:-.75rem}.left-0{left:0}.right-4{right:1rem}.top-0{top:0}.z-10{z-index:10}.-mx-2\.5{margin-left:-.625rem;margin-right:-.625rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-9{margin-bottom:2.25rem}.ml-0{margin-left:0}.ml-1{margin-left:.25rem}.ml-auto{margin-left:auto}.mr-auto{margin-right:auto}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.\!block{display:block!important}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.size-10{width:2.5rem;height:2.5rem}.size-3{width:.75rem;height:.75rem}.size-4{width:1rem;height:1rem}.size-5{width:1.25rem;height:1.25rem}.size-6{width:1.5rem;height:1.5rem}.size-7{width:1.75rem;height:1.75rem}.h-28{height:7rem}.h-7{height:1.75rem}.h-auto{height:auto}.h-full{height:100%}.w-14{width:3.5rem}.w-96{width:24rem}.w-auto{width:auto}.w-full{width:100%}.max-w-5xl{max-width:64rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-col-resize{cursor:col-resize}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.divide-x>:not([hidden])~:not([hidden]){--tw-divide-x-reverse: 0;border-right-width:calc(1px * var(--tw-divide-x-reverse));border-left-width:calc(1px * calc(1 - var(--tw-divide-x-reverse)))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.125rem}.rounded-t-md{border-top-left-radius:.375rem;border-top-right-radius:.375rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-dashed{border-style:dashed}.\!border-none{border-style:none!important}.border-blue-200{--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1))}.border-blue-500{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.border-blue-800\/20{border-color:#1e40af33}.border-red-500{--tw-border-opacity: 1;border-color:rgb(239 68 68 / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.border-zinc-200{--tw-border-opacity: 1;border-color:rgb(228 228 231 / var(--tw-border-opacity, 1))}.border-b-transparent{border-bottom-color:transparent}.\!bg-white{--tw-bg-opacity: 1 !important;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))!important}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-blue-50\/80{background-color:#eff6ffcc}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.bg-blue-700{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.bg-emerald-700{--tw-bg-opacity: 1;background-color:rgb(4 120 87 / var(--tw-bg-opacity, 1))}.bg-neutral-100{--tw-bg-opacity: 1;background-color:rgb(245 245 245 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-zinc-100{--tw-bg-opacity: 1;background-color:rgb(244 244 245 / var(--tw-bg-opacity, 1))}.bg-zinc-200{--tw-bg-opacity: 1;background-color:rgb(228 228 231 / var(--tw-bg-opacity, 1))}.bg-zinc-300{--tw-bg-opacity: 1;background-color:rgb(212 212 216 / var(--tw-bg-opacity, 1))}.bg-zinc-50{--tw-bg-opacity: 1;background-color:rgb(250 250 250 / var(--tw-bg-opacity, 1))}.bg-zinc-600{--tw-bg-opacity: 1;background-color:rgb(82 82 91 / var(--tw-bg-opacity, 1))}.bg-zinc-700{--tw-bg-opacity: 1;background-color:rgb(63 63 70 / var(--tw-bg-opacity, 1))}.object-contain{-o-object-fit:contain;object-fit:contain}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-5{padding:1.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pt-3{padding-top:.75rem}.text-center{text-align:center}.\!font-sans{font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"!important}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.text-blue-500{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-neutral-500{--tw-text-opacity: 1;color:rgb(115 115 115 / var(--tw-text-opacity, 1))}.text-neutral-900{--tw-text-opacity: 1;color:rgb(23 23 23 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-zinc-300{--tw-text-opacity: 1;color:rgb(212 212 216 / var(--tw-text-opacity, 1))}.text-zinc-400{--tw-text-opacity: 1;color:rgb(161 161 170 / var(--tw-text-opacity, 1))}.text-zinc-500{--tw-text-opacity: 1;color:rgb(113 113 122 / var(--tw-text-opacity, 1))}.text-zinc-600{--tw-text-opacity: 1;color:rgb(82 82 91 / var(--tw-text-opacity, 1))}.text-zinc-900{--tw-text-opacity: 1;color:rgb(24 24 27 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.opacity-50{opacity:.5}.\!outline-none{outline:2px solid transparent!important;outline-offset:2px!important}.outline{outline-style:solid}.\!ring-0{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color) !important;--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color) !important;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)!important}.\!ring-offset-0{--tw-ring-offset-width: 0px !important}.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-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.first-letter\:uppercase:first-letter{text-transform:uppercase}.checked\:ml-7:checked{margin-left:1.75rem}.hover\:border-red-200:hover{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity, 1))}.hover\:border-zinc-300:hover{--tw-border-opacity: 1;border-color:rgb(212 212 216 / var(--tw-border-opacity, 1))}.hover\:border-zinc-400:hover{--tw-border-opacity: 1;border-color:rgb(161 161 170 / var(--tw-border-opacity, 1))}.hover\:bg-blue-100:hover{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.hover\:bg-emerald-800:hover{--tw-bg-opacity: 1;background-color:rgb(6 95 70 / var(--tw-bg-opacity, 1))}.hover\:bg-red-100:hover{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.hover\:bg-zinc-100:hover{--tw-bg-opacity: 1;background-color:rgb(244 244 245 / var(--tw-bg-opacity, 1))}.hover\:bg-zinc-200:hover{--tw-bg-opacity: 1;background-color:rgb(228 228 231 / var(--tw-bg-opacity, 1))}.hover\:bg-zinc-300:hover{--tw-bg-opacity: 1;background-color:rgb(212 212 216 / var(--tw-bg-opacity, 1))}.hover\:bg-zinc-500:hover{--tw-bg-opacity: 1;background-color:rgb(113 113 122 / var(--tw-bg-opacity, 1))}.hover\:text-blue-700:hover{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.hover\:text-blue-800:hover{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity, 1))}.hover\:text-red-600:hover{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.hover\:text-red-700:hover{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.hover\:text-zinc-600:hover{--tw-text-opacity: 1;color:rgb(82 82 91 / var(--tw-text-opacity, 1))}.hover\:text-zinc-700:hover{--tw-text-opacity: 1;color:rgb(63 63 70 / var(--tw-text-opacity, 1))}.hover\:text-zinc-900:hover{--tw-text-opacity: 1;color:rgb(24 24 27 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:shadow-sm:hover{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.active\:border-blue-600:active{--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity, 1))}.active\:bg-blue-50:active{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.active\:text-blue-600:active{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}